git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v3 2/2] builtin/pack-objects.c: introduce `pack.recentObjectsHook`

From
Taylor Blau <me@ttaylorr.com>
Date
May 15, 2023, 20:38 UTC
Message-ID
<ZGKYOeMGs4fGO5bz@nand.local>
In-Reply-To
<20230512212456.GA2495860@coredump.intra.peff.net>
On Fri, May 12, 2023 at 05:24:56PM -0400, Jeff King wrote:
Show 6 quoted lines
> I think this description suffers a bit from being adapted from the
> original patch which was targeting cruft packs. It's not clear to me
> what "the caller" means here. And really, I think this is getting into
> the details before giving an overview and motivation.
>
> I'd expect something the rationale to be something like:

Re-reading it myself, I tend to agree with you. I modified it quite a bit, and I'm much happier with the result. Thanks for mentioning it.

Show 11 quoted lines
> One option I don't see here is: update the mtime on the objects you want
> to salvage.
>
> Why would we want this patch instead of just having the caller update
> the mtimes of objects (or in a cruft-pack world, call a command that
> rewrites the .mtimes file with new values)?
>
> I can think of some possible arguments against it (you might want to
> retain the old mtimes, or you might find it a hassle to have to
> continually update them before gc kills them). But I think the commit
> message should probably make those arguments.
I agree with everything you wrote here.
Show 8 quoted lines
> > We then add those as tips to another reachability traversal (along with
> > any recent objects, if pruning), marking every object along the way
> > (either adding it to the cruft pack, or writing it out as a loose
> > object).
>
> I didn't understand this "if pruning" comment. If we are not pruning at
> all, wouldn't we skip the extra traversal entirely, since we know we are
> saving everything?

I was talking about the rescuing traversal for generating a cruft pack. But I ended up dropping this whole paragraph anyway, since I don't think it's adding anything in the context of the new patch message.

Show 26 quoted lines
> > @@ -126,8 +198,14 @@ static int want_recent_object(struct recent_data *data,
> >  			      const struct object_id *oid)
> >  {
> >  	if (data->ignore_in_core_kept_packs &&
> > -	    has_object_kept_pack(oid, IN_CORE_KEEP_PACKS))
> > +	    has_object_kept_pack(oid, IN_CORE_KEEP_PACKS)) {
> > +		if (!data->extra_recent_oids_loaded)
> > +			load_pack_recent_objects(data);
> > +		if (oidset_contains(&data->extra_recent_oids, oid))
> > +			return 1;
> > +
> >  		return 0;
> > +	}
> >  	return 1;
> >  }
>
> This hunk I'm less sure about. The purpose of this function is that the
> caller has told us about some packs which are "special", and we avoid
> adding their objects to the traversal.
>
> This kicks in for cruft packs, when the git-repack caller says "I just
> made pack xyz.pack; do not bother saving anything in it to the cruft
> pack, since xyz.pack is here to stay". So if a hook says "you should
> keep object X", why would we want to override that check? It is already
> a reachable object that has been packed into xyz.pack, so we know there
> is no point in even considering its recency.
Yup, you're absolutely right here. Thanks for catching it.
Show 9 quoted lines
> > --- a/t/t5329-pack-objects-cruft.sh
> > +++ b/t/t5329-pack-objects-cruft.sh
> > @@ -739,4 +739,175 @@ test_expect_success 'cruft objects are freshend via loose' '
> >  	)
> >  '
> >
> > +test_expect_success 'additional cruft tips may be specified via pack.extraCruftTips' '
>
> This title (and others below) seems out of date. :)
Thanks for noticing, fixed.
Show 47 quoted lines
> > diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
> > index ebb267855f..d2eea6e754 100755
> > --- a/t/t7701-repack-unpack-unreachable.sh
> > +++ b/t/t7701-repack-unpack-unreachable.sh
> > @@ -113,6 +113,28 @@ test_expect_success 'do not bother loosening old objects' '
> >  	test_must_fail git cat-file -p $obj2
> >  '
> >
> > +test_expect_success 'extra recent tips are kept regardless of age' '
> > +	obj1=$(echo one | git hash-object -w --stdin) &&
> > +	obj2=$(echo two | git hash-object -w --stdin) &&
> > +	pack1=$(echo $obj1 | git pack-objects .git/objects/pack/pack) &&
> > +	pack2=$(echo $obj2 | git pack-objects .git/objects/pack/pack) &&
> > +	git prune-packed &&
> > +
> > +	git cat-file -p $obj1 &&
> > +	git cat-file -p $obj2 &&
> > +
> > +	write_script extra-tips <<-EOF &&
> > +	echo $obj2
> > +	EOF
> > +	git config pack.recentObjectsHook ./extra-tips &&
> > +
> > +	test-tool chmtime =-86400 .git/objects/pack/pack-$pack2.pack &&
> > +	git repack -A -d --unpack-unreachable=1.hour.ago &&
> > +
> > +	git cat-file -p $obj1 &&
> > +	git cat-file -p $obj2
> > +'
>
> And this is the new test in this iteration covering the "repack -A"
> case.
>
> It is checking that $obj2, which our hook mentions, is saved. It also
> checks that $obj1 is saved because it is still recent. But there are two
> other possibly interesting cases:
>
>   - an object that is too old and is _not_ saved. It seems useful to
>     confirm that the new patch does not simply break the ability to drop
>     objects. ;)
>
>   - an object that is reachable from $obj2 is also saved. From a
>     white-box perspective this is less interesting, because we should
>     already test elsewhere that this works for recent objects, and we
>     know the new feature is implemented by faking recency. But it might
>     be worth it for completeness, and because it's easy to do (making
>     $obj2 a tag pointing to a blob should work).

All very good cases to check for. Here's a patch on top (which I'll obviously squash into my new version, but figured I'd send it as a response to you directly, too):

--- 8< --- S

diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
index d2eea6e754..fa2df6016b 100755
--- a/t/t7701-repack-unpack-unreachable.sh
+++ b/t/t7701-repack-unpack-unreachable.sh
@@ -116,23 +116,33 @@ test_expect_success 'do not bother loosening old objects' '
 test_expect_success 'extra recent tips are kept regardless of age' '
 	obj1=$(echo one | git hash-object -w --stdin) &&
 	obj2=$(echo two | git hash-object -w --stdin) &&
+	obj3=$(echo three | git hash-object -w --stdin) &&
 	pack1=$(echo $obj1 | git pack-objects .git/objects/pack/pack) &&
 	pack2=$(echo $obj2 | git pack-objects .git/objects/pack/pack) &&
+	pack3=$(echo $obj3 | git pack-objects .git/objects/pack/pack) &&
 	git prune-packed &&

 	git cat-file -p $obj1 &&
 	git cat-file -p $obj2 &&
+	git cat-file -p $obj3 &&

-	write_script extra-tips <<-EOF &&
-	echo $obj2
+	git tag -a -m tag obj2-tag $obj2 &&
+	obj2_tag="$(git rev-parse obj2-tag)" &&
+
+
+	write_script precious-objects <<-EOF &&
+	echo $obj2_tag
 	EOF
-	git config pack.recentObjectsHook ./extra-tips &&
+	git config pack.recentObjectsHook ./precious-objects &&

 	test-tool chmtime =-86400 .git/objects/pack/pack-$pack2.pack &&
+	test-tool chmtime =-86400 .git/objects/pack/pack-$pack3.pack &&
 	git repack -A -d --unpack-unreachable=1.hour.ago &&

 	git cat-file -p $obj1 &&
-	git cat-file -p $obj2
+	git cat-file -p $obj2 &&
+	git cat-file -p $obj2_tag &&
+	test_must_fail git cat-file -p $obj3
 '

 test_expect_success 'keep packed objects found only in index' '
--- >8 ---

Thanks,
Taylor
Previous: Taylor BlauNext: Taylor Blau
Message 15 of 28 in “pack-objects: introduce `pack.extraRecentObjectsHook`”
  1. 0/2 pack-objects: introduce `pack.extraRecentObjectsHook`Taylor Blau, May 11, 2023
  2. 1/2 reachable.c: extract `obj_is_recent()`Taylor Blau, May 11, 2023
  3. 2/2 builtin/pack-objects.c: introduce `pack.recentObjectsHook`Taylor Blau, May 11, 2023
  4. Jeff KingMay 12, 2023
  5. Taylor BlauMay 15, 2023
  6. Jeff KingMay 12, 2023
  7. Taylor BlauMay 12, 2023
  8. Jeff KingMay 12, 2023
  9. Jeff KingMay 12, 2023
  10. Jeff KingMay 12, 2023
  11. Junio C HamanoMay 12, 2023
  12. Jeff KingMay 13, 2023
  13. Jeff KingMay 13, 2023
  14. Taylor BlauMay 15, 2023
  15. Taylor BlauMay 15, 2023
  16. Taylor BlauMay 11, 2023
  17. Junio C HamanoMay 11, 2023
  18. Taylor BlauMay 11, 2023
  19. 0/2 gc: introduce `gc.recentObjectsHook`Taylor Blau, May 16, 2023
  20. 1/2 reachable.c: extract `obj_is_recent()`Taylor Blau, May 16, 2023
  21. 2/2 gc: introduce `gc.recentObjectsHook`Taylor Blau, May 16, 2023
  22. Glen ChooMay 24, 2023
  23. Taylor BlauJun 7, 2023
  24. 0/2 gc: introduce `gc.recentObjectsHook`Taylor Blau, Jun 7, 2023
  25. 1/2 reachable.c: extract `obj_is_recent()`Taylor Blau, Jun 7, 2023
  26. 2/2 gc: introduce `gc.recentObjectsHook`Taylor Blau, Jun 7, 2023
  27. Glen ChooJun 9, 2023
  28. Junio C HamanoJun 12, 2023

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.