gc.sh: accumulate more friends
commitd072721712354878508c945a1087aef2e6b30285
authorKyle J. McKay <mackyle@gmail.com>
Sun, 27 Jan 2019 01:24:39 +0000 (26 18:24 -0700)
committerKyle J. McKay <mackyle@gmail.com>
Sun, 27 Jan 2019 01:24:39 +0000 (26 18:24 -0700)
tree457c688afcebb5ba72842e9be2c3842c55acd1f8
parent0e5eefbb06eafe7d79856742caafc3099bf00d85
gc.sh: accumulate more friends

When working in non-bare mode such as may be the case with either
a non-bare repository OR a linked working tree to *any* kind of
repository, normal Git processing may save commit hashes in top-level
refs (AKA "one-level refnames").  Examples are things such as
"FETCH_HEAD", "ORIG_HEAD", "MERGE_HEAD" etc.

It can be most unfortunate if the commits these top-level refs refer
to are not referenced any other way and are gratuitiously garbage
collected, but are then subsequently needed to complete a merge
check-in or perhaps recover from some kind of "accident" (cf.  PEBCAK).

Since the garbage collection process already identifies "friends"
to be preserved during Phase II, address this issue by adding any
existing "one-level refnames" to the list of friends.

Since Git does not have a mechanism to provide these we use an
heuristic based on the name and length of the file name used to
store the "one-level refname".

Currently the heuristic is that the name must match the regex
"^[A-Za-z][A-Za-z0-9_-]*[A-Za-z0-9]$" and be 31 or fewer characters
in length.  In addition, the file size must be at least 40 characters
but no more than 1000 and finally, every line in the file (after
trimming off any trailing "\t.*$" part to permit "FETCH_HEAD" style
files) must be all hex digits of at least 40 characters in length.

This should catch all likely candidates at very minimal cost while
avoiding false positives (Girocco does create some files with
contents that would match during mirror update processing except
that they are named starting with a "." so they will therefore be
correctly excluded).  Since this is part of the standard "friends"
processing, any hashes found this way end up being validated and
silently discarded if they do not refer to existing objects in the
repository (as well as having duplicate hashes eliminated).

Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
jobd/gc.sh