diff options
author | Sami Hiltunen <shiltunen@gitlab.com> | 2021-07-21 17:25:40 +0300 |
---|---|---|
committer | Sami Hiltunen <shiltunen@gitlab.com> | 2021-07-23 11:57:42 +0300 |
commit | 4f2cb9fbe04b3a94c96cb14271539b3b55cd2e5f (patch) | |
tree | c60d8659718f91f087e88407b6638f921f8fe10d | |
parent | dd160399735126da6a1757bf9ff3818059848c35 (diff) |
localrepo: differentiate symbolic refs in GetRemoteReferences
GetRemoteReferences currently doesn't differentiate symbolic refs from
normal references. This makes it difficult for calling code to handle
symbolic references separately. UpdateRemoteMirror should ignore symbolic
references. This commit extends GetRemoteReferences to return whether or
not a reference is a symbolic ref.
-rw-r--r-- | internal/git/localrepo/refs.go | 38 | ||||
-rw-r--r-- | internal/git/localrepo/refs_test.go | 4 |
2 files changed, 36 insertions, 6 deletions
diff --git a/internal/git/localrepo/refs.go b/internal/git/localrepo/refs.go index 12f4c7ef7..ac9c69fd1 100644 --- a/internal/git/localrepo/refs.go +++ b/internal/git/localrepo/refs.go @@ -192,8 +192,7 @@ func WithConfig(config ...git.ConfigPair) GetRemoteReferencesOption { } } -// GetRemoteReferences lists references of the remote. Symbolic references are dereferenced. Peeled -// tags are not returned. +// GetRemoteReferences lists references of the remote. Peeled tags are not returned. func (repo *Repo) GetRemoteReferences(ctx context.Context, remote string, opts ...GetRemoteReferencesOption) ([]git.Reference, error) { var cfg getRemoteReferenceConfig for _, opt := range opts { @@ -212,6 +211,7 @@ func (repo *Repo) GetRemoteReferences(ctx context.Context, remote string, opts . Name: "ls-remote", Flags: []git.Option{ git.Flag{Name: "--refs"}, + git.Flag{Name: "--symref"}, }, Args: append([]string{remote}, cfg.patterns...), }, @@ -226,13 +226,43 @@ func (repo *Repo) GetRemoteReferences(ctx context.Context, remote string, opts . var refs []git.Reference scanner := bufio.NewScanner(stdout) for scanner.Scan() { - split := strings.SplitN(string(scanner.Bytes()), "\t", 2) + split := strings.SplitN(scanner.Text(), "\t", 2) if len(split) != 2 { - return nil, fmt.Errorf("invalid ls-remote output line: %q", scanner.Bytes()) + return nil, fmt.Errorf("invalid ls-remote output line: %q", scanner.Text()) + } + + // Symbolic references are outputted as: + // ref: refs/heads/master refs/heads/symbolic-ref + // 0c9cf732b5774fa948348bbd6f273009bd66e04c refs/heads/symbolic-ref + if strings.HasPrefix(split[0], "ref: ") { + symRef := split[1] + if !scanner.Scan() { + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("scan dereferenced symbolic ref: %w", err) + } + + return nil, fmt.Errorf("missing dereferenced symbolic ref line for %q", symRef) + } + + split = strings.SplitN(scanner.Text(), "\t", 2) + if len(split) != 2 { + return nil, fmt.Errorf("invalid dereferenced symbolic ref line: %q", scanner.Text()) + } + + if split[1] != symRef { + return nil, fmt.Errorf("expected dereferenced symbolic ref %q but got reference %q", symRef, split[1]) + } + + refs = append(refs, git.NewSymbolicReference(git.ReferenceName(symRef), split[0])) + continue } refs = append(refs, git.NewReference(git.ReferenceName(split[1]), split[0])) } + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("scan: %w", err) + } + return refs, nil } diff --git a/internal/git/localrepo/refs_test.go b/internal/git/localrepo/refs_test.go index b4a7c449b..4e9e911ba 100644 --- a/internal/git/localrepo/refs_test.go +++ b/internal/git/localrepo/refs_test.go @@ -268,7 +268,7 @@ func TestRepo_GetRemoteReferences(t *testing.T) { remote: repoPath, expected: []git.Reference{ {Name: "refs/heads/master", Target: commit}, - {Name: "refs/heads/symbolic", Target: commit}, + {Name: "refs/heads/symbolic", Target: commit, IsSymbolic: true}, {Name: "refs/remote/remote-name/remote-branch", Target: commit}, {Name: "refs/tags/annotated-tag", Target: annotatedTagOID}, {Name: "refs/tags/lightweight-tag", Target: commit}, @@ -282,7 +282,7 @@ func TestRepo_GetRemoteReferences(t *testing.T) { }, expected: []git.Reference{ {Name: "refs/heads/master", Target: commit}, - {Name: "refs/heads/symbolic", Target: commit}, + {Name: "refs/heads/symbolic", Target: commit, IsSymbolic: true}, {Name: "refs/tags/annotated-tag", Target: annotatedTagOID}, {Name: "refs/tags/lightweight-tag", Target: commit}, }, |