From: Patrick Steinhardt <ps@pks.im>
To: Justin Tobler <jltobler@gmail.com>
Cc: git@vger.kernel.org, gitster@pobox.com
Subject: Re: [PATCH v3 1/9] builtin/receive-pack: properly clean up keep files
Date: Fri, 14 Aug 2026 09:46:32 +0200 [thread overview]
Message-ID: <an7H2C3JKqEdbGXQ@pks.im> (raw)
In-Reply-To: <an41gSCa7EFGkB1r@denethor>
On Thu, Aug 13, 2026 at 04:45:16PM -0500, Justin Tobler wrote:
> On 26/08/12 08:07AM, Patrick Steinhardt wrote:
> > On Tue, Aug 11, 2026 at 12:54:07PM -0500, Justin Tobler wrote:
> > > When git-receive-pack(1) stores an incoming packfile with
> > > git-index-pack(1), a ".keep" file is written alongside it to hold the
> > > pack in place until the references have been updated, and is removed
> > > afterwards. The path used to remove it is derived via
> > > `index_pack_lockfile()` from the repository's primary object directory.
> > >
> > > In bdee7b3013 (builtin/receive-pack: stage incoming objects via ODB
> > > transactions, 2026-07-10), git-receive-pack(1) started using the ODB
> > > transaction interfaces instead of managing a temporary directory
> > > directly. When starting an ODB transaction, the sources list is
> > > reordered to insert the newly created transaction source first as the
> > > primary to ensure writes are routed to it accordingly.
> > >
> > > Prior to using ODB transactions, git-receive-pack(1) would only set the
> > > temporary directory as the primary source for the child
> > > git-index-pack(1) and git-unpack-objects(1) processes it spawned and the
> > > parent process would set the temporary directory set as an alternate
> > > only. By using ODB transactions, the ODB source list is also reordered
> > > for the parent process which results in `index_pack_lockfile()` deriving
> > > the ".keep" path relative to the temporary directory instead the actual
> >
> > Nit: s/instead/& of/
>
> Will fix.
>
> > > main ODB source path. Consequently, this prevents the ".keep" file from
> > > being properly removed after being migrated into the main ODB source
> > > post-commit.
> >
> > Hm. Are the temporary packs written into the transaction-managed tempdir
> > now, or do they still end up in the main object directory?
>
> The packfile and associated ".keep" lockfiles are both initially written
> into the temporary directory managed by the ODB transaction. On
> transaction commit, they are then both migrated to the main ODB.
>
> When registering the keep tempfile, we need to record the future
> post-commit location of the keep file that way it can be removed when
> `odb_transaction_finalize()` is invoked. This matches the original
> behavior prior to ODB transaction being introduced in
> git-receive-pack(1).
>
> > > diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
> > > index 86933d8d7e..d74b787148 100644
> > > --- a/builtin/receive-pack.c
> > > +++ b/builtin/receive-pack.c
> > > @@ -2412,7 +2412,13 @@ static const char *unpack(int err_fd, struct shallow_info *si,
> > > if (status)
> > > return "index-pack fork failed";
> > >
> > > - lockfile = index_pack_lockfile(the_repository, child.out, NULL);
> > > + /*
> > > + * The lockfile filepath is expected to be the final location of
> > > + * the ".keep" file after being migrated to the main ODB source.
> > > + * This ensures the lockfile can be found and removed later
> > > + * after the ODB transaction has been committed.
> > > + */
> > > + lockfile = index_pack_lockfile(transaction->source, child.out, NULL);
> > > if (lockfile) {
> > > pack_lockfile = register_tempfile(lockfile);
> > > free(lockfile);
> >
> > Okay. So previously, we wrote the ".keep" file into the main repository,
> > whereas now we write it into the temporary object directory? Is the
> > packfile itself also written in there?
>
> Not quite, both the packfile and keep file were written to the temporary
> directory and continue to do so.
>
> Prior to bdee7b3013 (builtin/receive-pack: stage incoming objects via
> ODB transactions, 2026-07-10), the ".keep" files were also being written
> to the quarantine directory and migrated alongside the packfiles. The
> main git-receive-pack(1) process always kept the primary ODB as the
> first entry in the source list though ensuring that the "filename"
> registered for keep tempfile was the final location. With ODB
> transactions though, the source list order _does_ get changed and
> resulted in the keep tempfile not knowing about its final location.
> Consequently, it is no longer cleaned up.
>
> > What I'm wondering is why we even need a ".keep" file at all anymore if
> > we're not storing it in the main object directory. It wouldn't help us
> > to avoid the race, because after committing the transaction the ".keep"
> > file would remain in the temporary directory, whereas the packfile would
> > have been migrated to the main object directory. So it doesn't have a
> > ".keep" file at that point, and neither have references been updated to
> > point to the new objects yet.
>
> The ".keep" file does end up in the main ODB alongside the packfile when
> the transaction is committed. The main problem here is that it is not
> being cleaned up because the post-migration path does not match what the
> registered tempfile tracks.
>
> > So I wonder whether instead, we'd have to:
> >
> > 1. Start the transaction, creating the temporary object directory.
> >
> > 2. Write the packfile into the temporary object directory, but don't
> > create a ".keep" file.
> >
> > 3. At commit time, first write a ".keep" file in the main object
> > directory and then migrate the packfile over.
> >
> > 4. At finalization time, prune the ".keep" file from the main object
> > directory.
> >
> > That would retain the current properties of the system, but as far as I
> > can see this is not what we're doing here.
>
> With this patch, this is effectly what we are doing already. The main
> difference is that we are creating the ".keep" file alongside the
> packfile via git-index-pack(1) and migrating both when
> `odb_transaction_commit()` is invoked.
>
> We could stop relying on git-index-pack(1) to generate the ".keep" file
> and instead generate it ourselves during the commit phase as you
> suggested, but I'm not sure that would really buy us anything right now.
> For now, I think it would be fine to keep the changes more minimal.
>
> I'll try to clarify the commit message a bit in the next version to
> better explain what is happening.
Thanks for the explanation, this helped a lot!
Patrick
next prev parent reply other threads:[~2026-08-14 7:46 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-06 21:38 [PATCH 0/6] builtin/receive-pack: support pluggable packfile writes Justin Tobler
2026-08-06 21:38 ` [PATCH 1/6] odb/transaction: add transaction release interface Justin Tobler
2026-08-07 7:03 ` Patrick Steinhardt
2026-08-07 15:11 ` Justin Tobler
2026-08-06 21:38 ` [PATCH 2/6] builtin/receive-pack: pass shallow file explicitly Justin Tobler
2026-08-07 7:03 ` Patrick Steinhardt
2026-08-06 21:38 ` [PATCH 3/6] builtin/receive-pack: lift global state out of unpack() Justin Tobler
2026-08-07 7:03 ` Patrick Steinhardt
2026-08-07 15:33 ` Justin Tobler
2026-08-06 21:38 ` [PATCH 4/6] builtin/receive-pack: report unpack errors via strbuf Justin Tobler
2026-08-07 7:03 ` Patrick Steinhardt
2026-08-07 15:36 ` Justin Tobler
2026-08-09 19:00 ` Justin Tobler
2026-08-10 5:15 ` Patrick Steinhardt
2026-08-06 21:38 ` [PATCH 5/6] builtin/receive-pack: explicitly pass packfile fd Justin Tobler
2026-08-06 21:38 ` [PATCH 6/6] odb/transaction: add transaction interface to write packfiles Justin Tobler
2026-08-07 7:03 ` Patrick Steinhardt
2026-08-07 16:01 ` Justin Tobler
2026-08-09 19:00 ` [PATCH v2 0/7] builtin/receive-pack: support pluggable packfile writes Justin Tobler
2026-08-09 19:01 ` [PATCH v2 1/7] odb/transaction: add transaction finalize interface Justin Tobler
2026-08-10 3:38 ` Junio C Hamano
2026-08-10 19:10 ` Justin Tobler
2026-08-09 19:01 ` [PATCH v2 2/7] builtin/receive-pack: pass shallow file explicitly Justin Tobler
2026-08-09 19:01 ` [PATCH v2 3/7] builtin/receive-pack: read unpack limit config lazily Justin Tobler
2026-08-10 5:15 ` Patrick Steinhardt
2026-08-10 15:42 ` Justin Tobler
2026-08-10 17:54 ` Junio C Hamano
2026-08-10 19:16 ` Justin Tobler
2026-08-09 19:01 ` [PATCH v2 4/7] builtin/receive-pack: lift global state out of unpack() Justin Tobler
2026-08-09 19:01 ` [PATCH v2 5/7] builtin/receive-pack: report unpack errors via strbuf Justin Tobler
2026-08-09 19:01 ` [PATCH v2 6/7] builtin/receive-pack: explicitly pass packfile fd Justin Tobler
2026-08-09 19:01 ` [PATCH v2 7/7] odb/transaction: add transaction interface to write packfiles Justin Tobler
2026-08-10 1:54 ` Junio C Hamano
2026-08-10 19:29 ` Justin Tobler
2026-08-10 4:02 ` Junio C Hamano
2026-08-10 19:54 ` Justin Tobler
2026-08-11 17:54 ` [PATCH v3 0/9] builtin/receive-pack: support pluggable packfile writes Justin Tobler
2026-08-11 17:54 ` [PATCH v3 1/9] builtin/receive-pack: properly clean up keep files Justin Tobler
2026-08-12 6:07 ` Patrick Steinhardt
2026-08-13 21:45 ` Justin Tobler
2026-08-14 7:46 ` Patrick Steinhardt [this message]
2026-08-11 17:54 ` [PATCH v3 2/9] odb/transaction: add transaction finalize interface Justin Tobler
2026-08-12 6:07 ` Patrick Steinhardt
2026-08-11 17:54 ` [PATCH v3 3/9] builtin/receive-pack: pass shallow file explicitly Justin Tobler
2026-08-11 17:54 ` [PATCH v3 4/9] builtin/receive-pack: read unpack limit config lazily Justin Tobler
2026-08-11 17:54 ` [PATCH v3 5/9] builtin/receive-pack: lift global state out of unpack() Justin Tobler
2026-08-11 17:54 ` [PATCH v3 6/9] builtin/receive-pack: report unpack errors via strbuf Justin Tobler
2026-08-11 17:54 ` [PATCH v3 7/9] builtin/receive-pack: explicitly pass packfile fd Justin Tobler
2026-08-11 17:54 ` [PATCH v3 8/9] odb: return temporary ODB source when set Justin Tobler
2026-08-12 6:07 ` Patrick Steinhardt
2026-08-11 17:54 ` [PATCH v3 9/9] odb/transaction: add transaction interface to write packfiles Justin Tobler
2026-08-14 8:51 ` Patrick Steinhardt
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=an7H2C3JKqEdbGXQ@pks.im \
--to=ps@pks.im \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=jltobler@gmail.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox