Subject: [PATCH v5 0/2] gc: introduce `gc.recentObjectsHook`

From: Taylor Blau <[email-masked]>
Date: Wed, 7 Jun 2023 18:58:07 -0400

Here is a version of my series to implement the mutli-valued
"gc.recentObjectHook" configuration, which allows users to define custom
programs whose output determines an additional set of objects to retain
(along with their descendants) when GCing, regardless of their true age.

It is largely the same as the previous round, with the following
changes:

  - a small handful of wordsmithing changes in the second patch's
    message thanks to a very helpful review from the Google team's
    "Review Club" meeting.

  - removed a pair of stray references to "cruft tips" in favor of
    "recent objects".

  - rebased onto v2.41.0

Based on previous rounds of review, I think that this version should be
pretty much ready to go. But I'd appreciate some extra eyes on it just
to make sure.

Thanks in advance for your (hopefully final!) review.

Taylor Blau (2):
  reachable.c: extract `obj_is_recent()`
  gc: introduce `gc.recentObjectsHook`

 Documentation/config/gc.txt          |  15 +++
 reachable.c                          |  85 ++++++++++++-
 t/t5304-prune.sh                     |  14 +++
 t/t5329-pack-objects-cruft.sh        | 171 +++++++++++++++++++++++++++
 t/t7701-repack-unpack-unreachable.sh |  31 +++++
 5 files changed, 313 insertions(+), 3 deletions(-)

Range-diff against v4:
1:  9c1b59c8cf = 1:  38c4c4a17f reachable.c: extract `obj_is_recent()`
2:  18e50d2517 ! 2:  f661b54941 gc: introduce `gc.recentObjectsHook`
    @@ Commit message
         be pruned. Our options today consist of:
     
           - Point references at the reachability tips of any objects you
    -        consider precious, which may be undesirable or infeasible.
    +        consider precious, which may be undesirable or infeasible if there
    +        are many such objects.
     
           - Track them via the reflog, which may be undesirable since the
             reflog's lifetime is limited to that of the reference it's tracking
    @@ Documentation/config/gc.txt: or rebase occurring.  Since these changes are not p
      default is more aggressive than `gc.reflogExpire`.
      
     +gc.recentObjectsHook::
    -+	When considering the recency of an object (e.g., when generating
    -+	a cruft pack or storing unreachable objects as loose), use the
    -+	shell to execute the specified command(s). Interpret their
    -+	output as object IDs which Git will consider as "recent",
    -+	regardless of their age.
    ++	When considering whether or not to remove an object (either when
    ++	generating a cruft pack or storing unreachable objects as
    ++	loose), use the shell to execute the specified command(s).
    ++	Interpret their output as object IDs which Git will consider as
    ++	"recent", regardless of their age. By treating their mtimes as
    ++	"now", any objects (and their descendants) mentioned in the
    ++	output will be kept regardless of their true age.
     ++
     +Output must contain exactly one hex object ID per line, and nothing
     +else. Objects which cannot be found in the repository are ignored.
    @@ reachable.c: struct recent_data {
     +		ret = run_one_gc_recent_objects_hook(&data->extra_recent_oids,
     +						       programs->items[i].string);
     +		if (ret)
    -+			die(_("unable to enumerate additional cruft tips"));
    ++			die(_("unable to enumerate additional recent objects"));
     +	}
     +}
     +
    @@ t/t5329-pack-objects-cruft.sh: test_expect_success 'cruft objects are freshend v
     +		# ensure that a dirty exit halts cruft pack generation
     +		git config --add gc.recentObjectsHook ./extra-tips.c &&
     +		test_must_fail git repack --cruft --cruft-expiration=now -d 2>err &&
    -+		grep "unable to enumerate additional cruft tips" err &&
    ++		grep "unable to enumerate additional recent objects" err &&
     +
     +		# and that the existing cruft pack is left alone
     +		test_path_is_file "$mtimes"
-- 
2.41.0.2.gaaae24b3a6.dirty