Re: [PATCH] setlocalversion: Add workaround for "git describe" performance issue
- From
- Rasmus Villemoes <ravi@prevas.dk>
- Date
- Nov 1, 2024, 10:23 UTC
- Message-ID
- <8734kbjlrq.fsf@prevas.dk>
- In-Reply-To
- <20241031122456.GB593548@coredump.intra.peff.net>
On Thu, Oct 31 2024, Jeff King <peff@peff.net> wrote:
Show 19 quoted lines
> On Thu, Oct 31, 2024 at 07:42:10AM -0400, Jeff King wrote: > >> That works, but I have a feeling that figured out what the heck is going >> on with gave_up_on might produce a more elegant solution. > > OK, I think I might have made some sense of this. > > In finish_depth_computation(), we traverse down "list" forever, passing > flags up to our parents, until we find a commit that is marked with the > same "within" flag as our candidate. And then if everything left has > that same "within" flag set, we can bail. > > So I _think_ the point is to basically count up what we'd get from this > traversal: > > $tag..$commit > > where "$tag" is the candidate tag we found, and "$commit" is what we're > trying to describe (so imagine "git describe --match=$tag $commit").
Yeah, so this is really just what the setlocalversion script wants to know. For a few diffent possible values of $tag (in most cases just 1), we ask: Is $tag an annotated tag? Is it an ancestor of HEAD? And if so, how many commits are in $tag..HEAD.
Perhaps we could on the kernel side replace the "git describe --match" calls with a helper, something like this (needs a lot of polishing):
===
# Produce output similar to what "git describe --match=$tag 2>
# /dev/null" would. It doesn't have to match exactly as the caller is
# only interested in whether $tag == HEAD, and if not, the number
# between the tag and the short sha1.
describe()
{
# Is $tag an annotated tag? Could/should probably be written using
# some plumbing instead of git describe, but with --exact-match,
# we avoid the walk-to-the-start-of-history behaviour, so fine for
# this demo.
git describe --exact-match --match=$tag $tag >/dev/null 2>/dev/null || return 1 # Can it be used to describe HEAD, i.e. is it an ancestor of HEAD?
git merge-base --is-ancestor $tag HEAD || return 1 # Find the number that "git describe" would append.
count=$(git rev-list --count $tag..HEAD)
if [ $count -eq 0 ] ; then
echo "$tag"
else
echo "$tag-$count-$head"
fi
}
===But if we go this route, we should probably rework the logic somewhat. There's no point getting the count ourselves, stuffing that into a string, and then splitting that string with awk to %05d format the count.
I also don't know if either the --is-ancestor or the rev-list count could end up doing the same walk-all-commits we're trying to avoid.
Rasmus