Support packed-refs in GitRepository
Description
In Git, refs can be packed with git pack-refs which creates a single .git/packed-refs file with all the refs. According to documentation:
This command is used to solve the storage and performance problem by storing the refs in a single file, $GIT_DIR/packed-refs. When a ref is missing from the traditional $GIT_DIR/refs directory hierarchy, it is looked up in this file and used if found.
Currently, Nuke only looks for refs in refs directory
https://github.com/nuke-build/nuke/blob/217b8080c3011c4b06dbe6953b837ce5ce663d7a/source/Nuke.Common/Git/GitRepository.cs#L98-L106
Would be cool to have it also look into packed-refs
Usage Example
No response
Alternative
No response
This became a blocker today, as git decided to pack refs for some reason, resulting in
Repeating warnings and errors:
Assertion failed: File.Exists(D:\dev\***\.git\refs/heads/master)
StackTrace:
at Nuke.Common.ControlFlow.Fail(String text)
at Nuke.Common.ControlFlow.Assert(Boolean condition, String text)
at Nuke.Common.Git.GitRepository.GetCommitFromHead(String gitDirectory, String head)
at Nuke.Common.Git.GitRepository.FromLocalDirectory(String directory, String branch, String remote)
at Nuke.Common.Git.GitRepositoryAttribute.GetValue(MemberInfo member, Object instance)
at Nuke.Common.ValueInjection.ValueInjectionAttributeBase.<>c__DisplayClass0_0.<TryGetValue>b__0()
Folder refs/heads doesn't contain master, as it was moved into packed-refs. I'm searching for the workaround for the time being.
I'll be occupied for a little longer. If you have something, feel free to post here or open a pull-request.
Turns out packed-refs file is basically a list of refs which has the following structure
# pack-refs with: peeled fully-peeled sorted
373f5554d5d3248e2feb640513c01f1f515b7eb4 refs/heads/master
0b6bc59e6555ae020480225922a37b8434a13f39 refs/remotes/origin/master
...
Given that refs/ files have precedence over packed-refs in reading the refs, I just created a new refs/heads/master file with 373f5554d5d3248e2feb640513c01f1f515b7eb4 contents to band-aid this problem. This approach of restoring refs from packed-refs works without issues so far.
I've run into this recently. Turned out git gc deleted refs/heads/main file. Probably more robust aproach is to get data for GitRepository via git cli
Here's a workaround I'm using
public static int Main()
{
UnpackRefs();
return Execute<Build>();
}
static void UnpackRefs()
{
var gitPath = RootDirectory / ".git";
var refs = ReadAllLines(gitPath / "packed-refs").Skip(1);
foreach (var line in refs)
{
var parts = line.Split(" ");
var hash = parts[0];
var path = parts[1];
WriteAllText(gitPath / path, hash);
}
}