All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ted Nyman <tnyman@openai.com>
To: git@vger.kernel.org
Cc: gitster@pobox.com, me@ttaylorr.com, peff@peff.net, ps@pks.im,
	karthik.188@gmail.com, sandals@crustytoothpaste.net,
	avarab@gmail.com
Subject: [PATCH v5 0/3] packfile URIs: support concurrent downloads
Date: Sat, 25 Jul 2026 23:44:45 -0700	[thread overview]
Message-ID: <cover.1785047139.git.tnyman@openai.com> (raw)
In-Reply-To: <cover.1784874850.git.tnyman@openai.com>

Packfile URI and dumb HTTP downloads stage packs at
objects/pack/pack-<hash>.pack.temp so an interrupted transfer can
resume. Opening that file in append mode forces every write to its
current end. Two Git processes fetching the same pack into one object
database can therefore append duplicate data and corrupt the pack.

The first patch separates the unrelated --index-pack-arg documentation
and error-message correction requested during review.

The second patch keeps the predictable staging name but removes append
mode. Each downloader seeks once to the current end, requests the
corresponding Range, and writes using its own descriptor offset. Since
the staging key must identify immutable pack contents, overlapping
responses write identical bytes at identical offsets. There is no need
for pwrite(2) or cross-process coordination, and resumption continues to
work for both packfile URI and ordinary dumb HTTP downloads.

A downloader can also find that the partial pack has completed and
request a range starting at EOF. Servers may respond with HTTP 416 in
that case. Treat the response as a completed download and let
index-pack validate the pack.

On MinGW, the non-append O_RDWR open grants FILE_SHARE_DELETE only for an
existing file. Create a missing staging file exclusively, close it, and
reopen it without O_CREAT so every retained descriptor permits another
downloader to unlink the path. Keep the open descriptor for index-pack;
it installs its own pack, so the shared staging file is only unlinked,
never renamed.

The third patch handles the related .keep race. When another process has
already created the keep file, index-pack reports "pack<TAB><hash>"
instead of "keep<TAB><hash>". Accept both successful forms and remove
only keep files created by the current process. Read only the prefix and
hash so any following fsck output remains available to fetch-pack.

The tests cover resumption, a completed partial returning 416,
overlapping downloads, unlinking the staging path while index-pack holds
its descriptor, and a pre-existing .keep file. The unlink test does not
require FIFOs, so it can exercise MinGW's sharing behavior even though
the concurrent-download tests are skipped there.

Changes since v4:

  * Clarify that the first --index-pack-arg specifies the command and
    subsequent instances specify its arguments.
  * Drop assumptions about which concurrent response reaches the
    staging file first. Either write order exercises the same
    overlapping-download behavior.
  * No production code changes.

The overlapping-download test passes 240 runs with 12 parallel stress
jobs.

The v4 discussion is at:

  https://lore.kernel.org/git/cover.1784874850.git.tnyman@openai.com/

Ted Nyman (3):
  http-fetch: correct --index-pack-arg documentation
  http: avoid concurrent appends to partial packs
  fetch-pack: accept "pack" output for packfile URIs

 Documentation/git-http-fetch.adoc |  14 +-
 fetch-pack.c                      |  33 ++--
 http-fetch.c                      |   7 +-
 http-push.c                       |   3 +-
 http-walker.c                     |   3 +-
 http.c                            |  56 ++++---
 t/t5550-http-fetch-dumb.sh        | 246 ++++++++++++++++++++++++++++++
 t/t5702-protocol-v2.sh            |  31 ++++
 8 files changed, 347 insertions(+), 46 deletions(-)

Range-diff against v4:
1:  a6a40b8046 ! 1:  a79af009ea http-fetch: correct --index-pack-arg documentation
    @@ Documentation/git-http-fetch.adoc: commit-id::
     -	For internal use only. The command to run on the contents of the
     -	downloaded pack. Arguments are URL-encoded separated by spaces.
     +--index-pack-arg=<arg>::
    -+	For internal use only. An argument to the command run on the contents
    -+	of the downloaded pack. This option can be specified multiple times.
    ++	For internal use only. The first instance specifies the command run on
    ++	the contents of the downloaded pack. Subsequent instances specify its
    ++	arguments.
      
      --recover::
      	Verify that everything reachable from target is fetched.  Used after
2:  144c98cdfa ! 2:  d9667c93b0 http: avoid concurrent appends to partial packs
    @@ t/t5550-http-fetch-dumb.sh: test_expect_success 'http-fetch --packfile' '
     +	read ready <&8 &&
     +	test "$ready" = ready &&
     +	test_path_is_file "$tmpfile" &&
    -+	test -s "$tmpfile" &&
     +	{
     +		GIT_TRACE_CURL="$TRASH_DIRECTORY/overlap-second.trace" \
     +		GIT_TRACE_CURL_NO_DATA=1 \
    @@ t/t5550-http-fetch-dumb.sh: test_expect_success 'http-fetch --packfile' '
     +	wait "$second_pid" &&
     +	wait "$first_pid" &&
     +	wait "$server_pid" &&
    -+	test_grep "HTTP/[0-9.]* 200" overlap-first.trace &&
    -+	test_grep "Range: bytes=[1-9][0-9]*-" overlap-second.trace &&
    -+	test_grep "HTTP/[0-9.]* 206" overlap-second.trace &&
     +	printf "keep\t%s\npack\t%s\n" "$packhash" "$packhash" | sort >expect &&
     +	sort first.out second.out >actual &&
     +	test_cmp expect actual &&
3:  d9063deb60 = 3:  fee6f292cb fetch-pack: accept "pack" output for packfile URIs

base-commit: 5d2e7709234afea1b6ddb25cd4f60d3d5fb3c200
-- 
2.55.0.openai.131.g83a728de1eb6

  parent reply	other threads:[~2026-07-26  6:44 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-13 22:37 [PATCH 0/2] packfile URIs: support concurrent downloads Ted Nyman
2026-07-13 22:34 ` [PATCH 1/2] http: use unique tempfiles for packfile URI downloads Ted Nyman
2026-07-14  1:00   ` Junio C Hamano
2026-07-14  1:58     ` Ted Nyman
2026-07-14  4:07       ` Taylor Blau
2026-07-14  5:28       ` Jeff King
2026-07-14 18:10         ` Junio C Hamano
2026-07-14 18:31           ` Ted Nyman
2026-07-14  4:06   ` Taylor Blau
2026-07-14  5:44     ` Jeff King
2026-07-14  6:46   ` Jeff King
2026-07-13 22:34 ` [PATCH 2/2] fetch-pack: accept "pack" output for packfile URIs Ted Nyman
2026-07-14  7:12   ` Jeff King
2026-07-14  7:13     ` Jeff King
2026-07-14 18:38     ` Ted Nyman
2026-07-14 21:47       ` Jeff King
2026-07-14  4:13 ` [PATCH 0/2] packfile URIs: support concurrent downloads Taylor Blau
2026-07-20 22:33 ` [PATCH v2 " Ted Nyman
2026-07-20 22:33   ` [PATCH v2 1/2] http: avoid concurrent appends to partial packs Ted Nyman
2026-07-21 19:56     ` Junio C Hamano
2026-07-20 22:34   ` [PATCH v2 2/2] fetch-pack: accept "pack" output for packfile URIs Ted Nyman
2026-07-21 23:29 ` [PATCH v3 0/3] packfile URIs: support concurrent downloads Ted Nyman
2026-07-21 23:29   ` [PATCH v3 1/3] http-fetch: correct --index-pack-arg documentation Ted Nyman
2026-07-21 23:29   ` [PATCH v3 2/3] http: avoid concurrent appends to partial packs Ted Nyman
2026-07-21 23:29   ` [PATCH v3 3/3] fetch-pack: accept "pack" output for packfile URIs Ted Nyman
2026-07-24  4:43   ` [PATCH v3 0/3] packfile URIs: support concurrent downloads Junio C Hamano
2026-07-25  9:09     ` Jeff King
2026-07-25  9:21       ` Jeff King
2026-07-25 10:02         ` Jeff King
2026-07-25 10:10           ` Jeff King
2026-07-25 16:20           ` Junio C Hamano
2026-07-24  8:14   ` [PATCH v4 " Ted Nyman
2026-07-24  8:14     ` [PATCH v4 1/3] http-fetch: correct --index-pack-arg documentation Ted Nyman
2026-07-24 21:38       ` Taylor Blau
2026-07-24  8:14     ` [PATCH v4 2/3] http: avoid concurrent appends to partial packs Ted Nyman
2026-07-24  8:14     ` [PATCH v4 3/3] fetch-pack: accept "pack" output for packfile URIs Ted Nyman
2026-07-24 21:46       ` Taylor Blau
2026-07-26  6:44     ` Ted Nyman [this message]
2026-07-26  6:44       ` [PATCH v5 1/3] http-fetch: correct --index-pack-arg documentation Ted Nyman
2026-07-26  6:44       ` [PATCH v5 2/3] http: avoid concurrent appends to partial packs Ted Nyman
2026-07-26  9:20         ` Jeff King
2026-07-26 10:04           ` Ted Nyman
2026-07-26 10:27             ` Jeff King
2026-07-26  6:44       ` [PATCH v5 3/3] fetch-pack: accept "pack" output for packfile URIs Ted Nyman
2026-07-26  9:21       ` [PATCH v5 0/3] packfile URIs: support concurrent downloads Jeff King

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cover.1785047139.git.tnyman@openai.com \
    --to=tnyman@openai.com \
    --cc=avarab@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=karthik.188@gmail.com \
    --cc=me@ttaylorr.com \
    --cc=peff@peff.net \
    --cc=ps@pks.im \
    --cc=sandals@crustytoothpaste.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.