Skip to content

Commit

Permalink
git: allow cloning commit shas not referenced by branch/tag
Browse files Browse the repository at this point in the history
Signed-off-by: Justin Chadwell <[email protected]>
  • Loading branch information
jedevc committed Oct 21, 2024
1 parent ac3eb58 commit 57b4c9a
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 6 deletions.
4 changes: 3 additions & 1 deletion source/git/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,9 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out
}
}
args = append(args, "origin")
if !gitutil.IsCommitSHA(ref) {
if gitutil.IsCommitSHA(ref) {
args = append(args, ref)
} else {
// local refs are needed so they would be advertised on next fetches. Force is used
// in case the ref is a branch and it now points to a different commit sha
// TODO: is there a better way to do this?
Expand Down
33 changes: 28 additions & 5 deletions source/git/source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,15 +218,23 @@ func testFetchBySHA(t *testing.T, keepGitDir bool) {
}

func TestFetchUnreferencedTagSha(t *testing.T) {
testFetchUnreferencedTagSha(t, false)
testFetchUnreferencedRefSha(t, "v1.2.3-special", false)
}

func TestFetchUnreferencedTagShaKeepGitDir(t *testing.T) {
testFetchUnreferencedTagSha(t, true)
testFetchUnreferencedRefSha(t, "v1.2.3-special", true)
}

// testFetchUnreferencedTagSha tests fetching a SHA that points to a tag that is not reachable from any branch.
func testFetchUnreferencedTagSha(t *testing.T, keepGitDir bool) {
func TestFetchUnreferencedRefSha(t *testing.T) {
testFetchUnreferencedRefSha(t, "refs/special", false)
}

func TestFetchUnreferencedRefShaKeepGitDir(t *testing.T) {
testFetchUnreferencedRefSha(t, "refs/special", true)
}

// testFetchUnreferencedRefSha tests fetching a SHA that points to a ref that is not reachable from any branch.
func testFetchUnreferencedRefSha(t *testing.T, ref string, keepGitDir bool) {
if runtime.GOOS == "windows" {
t.Skip("Depends on unimplemented containerd bind-mount support on Windows")
}
Expand All @@ -239,7 +247,7 @@ func testFetchUnreferencedTagSha(t *testing.T, keepGitDir bool) {

repo := setupGitRepo(t)

cmd := exec.Command("git", "rev-parse", "v1.2.3-special")
cmd := exec.Command("git", "rev-parse", ref)
cmd.Dir = repo.mainPath

out, err := cmd.Output()
Expand Down Expand Up @@ -699,35 +707,50 @@ func setupGitRepo(t *testing.T) gitRepoFixture {
"git -c init.defaultBranch=master init",
"git config --local user.email test",
"git config --local user.name test",

"echo foo > abc",
"git add abc",
"git commit -m initial",
"git tag --no-sign a/v1.2.3",

"echo bar > def",
"mkdir subdir",
"echo subcontents > subdir/subfile",
"git add def subdir",
"git commit -m second",
"git tag -a -m \"this is an annotated tag\" v1.2.3",

"echo foo > bar",
"git add bar",
"git commit -m tagonly-leaf",
"git tag --no-sign v1.2.3-special",

"echo foo2 > bar2",
"git add bar2",
"git commit -m more",
"git update-ref refs/special $(git rev-parse HEAD)",

// switch master back to v1.2.3
"git checkout -B master v1.2.3",

"echo sbb > foo13",
"git add foo13",
"git commit -m third",
"git tag --no-sign lightweight-tag",

"git checkout -B feature",

"echo baz > ghi",
"git add ghi",
"git commit -m feature",
"git update-ref refs/test $(git rev-parse HEAD)",

"git submodule add "+fixture.subURL+" sub",
"git add -A",
"git commit -m withsub",

"git checkout master",

// "git log --oneline --graph --decorate=full --all",
)
return fixture
Expand Down
23 changes: 23 additions & 0 deletions util/gitutil/git_cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,13 @@ func (cli *GitCLI) Run(ctx context.Context, args ...string) (_ []byte, err error
continue
}
}
if strings.Contains(errbuf.String(), "upload-pack: not our ref") {
// https://github.com/git/git/blob/34b6ce9b30747131b6e781ff718a45328aa887d0/upload-pack.c
if newArgs := argsNoCommitRefspec(args); len(args) > len(newArgs) {
args = newArgs
continue
}
}

return buf.Bytes(), errors.Wrapf(err, "git stderr:\n%s", errbuf.String())
}
Expand All @@ -244,3 +251,19 @@ func argsNoDepth(args []string) []string {
}
return out
}

func argsNoCommitRefspec(args []string) []string {
if len(args) <= 2 {
return args
}
if args[0] != "fetch" {
return args
}

// assume the refspec is the last arg
if IsCommitSHA(args[len(args)-1]) {
return args[:len(args)-1]
}

return args
}

0 comments on commit 57b4c9a

Please sign in to comment.