nuke icon indicating copy to clipboard operation
nuke copied to clipboard

Support packed-refs in GitRepository

Open Razenpok opened this issue 4 years ago • 5 comments

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

Razenpok avatar Sep 16 '21 09:09 Razenpok

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.

Razenpok avatar Feb 08 '22 15:02 Razenpok

I'll be occupied for a little longer. If you have something, feel free to post here or open a pull-request.

matkoch avatar Feb 10 '22 00:02 matkoch

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.

Razenpok avatar Feb 13 '22 10:02 Razenpok

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

harrhp avatar Apr 19 '22 01:04 harrhp

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);
        }
    }

Razenpok avatar Apr 27 '22 20:04 Razenpok