diff --git a/internal/gps/vcs_source.go b/internal/gps/vcs_source.go index 4890da2191..b2eea756af 100644 --- a/internal/gps/vcs_source.go +++ b/internal/gps/vcs_source.go @@ -210,15 +210,18 @@ func (s *gitSource) listVersions(ctx context.Context) (vlist []PairedVersion, er // // If all of those conditions are met, then the user would end up with an // erroneous non-default branch in their lock file. - headrev := Revision(all[0][:40]) + var headrev Revision var onedef, multidef, defmaster bool smap := make(map[string]bool) uniq := 0 - vlist = make([]PairedVersion, len(all)-1) // less 1, because always ignore HEAD + vlist = make([]PairedVersion, len(all)) for _, pair := range all { var v PairedVersion - if string(pair[46:51]) == "heads" { + if string(pair[41:]) == "HEAD" { + // If HEAD is present, it's always first + headrev = Revision(pair[:40]) + } else if string(pair[46:51]) == "heads" { rev := Revision(pair[:40]) isdef := rev == headrev diff --git a/internal/gps/vcs_source_test.go b/internal/gps/vcs_source_test.go index a13a1c6b6d..d7adc844bb 100644 --- a/internal/gps/vcs_source_test.go +++ b/internal/gps/vcs_source_test.go @@ -524,6 +524,63 @@ func testHgSourceInteractions(t *testing.T) { <-donech } +func TestGitSourceListVersionsNoHEAD(t *testing.T) { + t.Parallel() + + requiresBins(t, "git") + + h := test.NewHelper(t) + defer h.Cleanup() + h.TempDir("smcache") + cpath := h.Path("smcache") + h.TempDir("repo") + repoPath := h.Path("repo") + + // Create test repo with a single commit on the master branch + h.RunGit(repoPath, "init") + h.RunGit(repoPath, "config", "--local", "user.email", "test@example.com") + h.RunGit(repoPath, "config", "--local", "user.name", "Test author") + h.RunGit(repoPath, "commit", "--allow-empty", `--message="Initial commit"`) + + // Make HEAD point at a nonexistent branch (deleting it is not allowed) + // The `git ls-remote` that listVersions() calls will not return a HEAD ref + // because it points at a nonexistent branch + h.RunGit(repoPath, "symbolic-ref", "HEAD", "refs/heads/nonexistent") + + un := "file://" + filepath.ToSlash(repoPath) + u, err := url.Parse(un) + if err != nil { + t.Fatalf("Error parsing URL %s: %s", un, err) + } + mb := maybeGitSource{u} + + ctx := context.Background() + superv := newSupervisor(ctx) + isrc, _, err := mb.try(ctx, cpath, newMemoryCache(), superv) + if err != nil { + t.Fatalf("Unexpected error while setting up gitSource for test repo: %s", err) + } + + err = isrc.initLocal(ctx) + if err != nil { + t.Fatalf("Error on cloning git repo: %s", err) + } + + src, ok := isrc.(*gitSource) + if !ok { + t.Fatalf("Expected a gitSource, got a %T", isrc) + } + + pvlist, err := src.listVersions(ctx) + if err != nil { + t.Fatalf("Unexpected error getting version pairs from git repo: %s", err) + } + + if len(pvlist) != 1 { + t.Errorf("Unexpected version pair length:\n\t(GOT): %d\n\t(WNT): %d", len(pvlist), 1) + } +} + func Test_bzrSource_exportRevisionTo_removeVcsFiles(t *testing.T) { t.Parallel()