Skip to content

Commit

Permalink
Support annotated tags for push git metadata (#3013)
Browse files Browse the repository at this point in the history
Fix resolving of annotated tags on push with `--git-metadata` flag by
fetching from the remote and then using `--points-at` to discover each
ref and tag. Currently only lightweight tags are resolved as the commit
sha for annotated tags doesn't directly point to the commit.
  • Loading branch information
emcfarlane committed May 28, 2024
1 parent 0ebe2de commit 2dfac93
Showing 1 changed file with 86 additions and 21 deletions.
107 changes: 86 additions & 21 deletions private/pkg/git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import (
"errors"
"fmt"
"os/exec"
"path"
"regexp"
"sort"
"strings"

"github.com/bufbuild/buf/private/pkg/app"
Expand All @@ -33,10 +35,7 @@ import (
)

const (
gitCommand = "git"
gitOriginRemote = "origin"
tagsPrefix = "refs/tags/"
headsPrefix = "refs/heads/"
gitCommand = "git"
)

var (
Expand Down Expand Up @@ -233,7 +232,7 @@ func CheckDirectoryIsValidGitCheckout(
); err != nil {
var exitErr *exec.ExitError
if errors.As(err, &exitErr) {
if exitErr.ProcessState.ExitCode() == 128 {
if exitErr.ExitCode() == 128 {
return fmt.Errorf("dir %s: %w", dir, ErrInvalidGitCheckout)
}
}
Expand Down Expand Up @@ -314,36 +313,102 @@ func GetRefsForGitCommitAndRemote(
dir string,
remote string,
gitCommitSha string,
) ([]string, error) {
if err := fetchRemoteRefs(ctx, runner, envContainer, dir, remote); err != nil {
return nil, err
}
refs, err := getRefsPointsAt(ctx, runner, envContainer, dir, remote, gitCommitSha)
if err != nil {
return nil, err
}
tags, err := getTagsPointsAt(ctx, runner, envContainer, dir, gitCommitSha)
if err != nil {
return nil, err
}
values := append(refs, tags...)
sort.Strings(values)
return values, nil
}

func fetchRemoteRefs(
ctx context.Context,
runner command.Runner,
envContainer app.EnvContainer,
dir string,
remote string,
) error {
if err := runner.Run(
ctx,
gitCommand,
command.RunWithArgs("fetch", "--tags", remote),
command.RunWithDir(dir),
command.RunWithEnv(app.EnvironMap(envContainer)),
); err != nil {
return err
}
return nil
}

func getRefsPointsAt(
ctx context.Context,
runner command.Runner,
envContainer app.EnvContainer,
dir string,
remote string,
gitCommitSha string,
) ([]string, error) {
stdout := bytes.NewBuffer(nil)
stderr := bytes.NewBuffer(nil)
if err := runner.Run(
ctx,
gitCommand,
command.RunWithArgs("ls-remote", "--heads", "--tags", "--refs", remote),
command.RunWithArgs(
"for-each-ref",
"--points-at", gitCommitSha,
"--format", "%(refname:short)",
path.Join("refs/remotes", remote),
),
command.RunWithStdout(stdout),
command.RunWithStderr(stderr),
command.RunWithDir(dir),
command.RunWithEnv(app.EnvironMap(envContainer)),
); err != nil {
return nil, err
}
scanner := bufio.NewScanner(stdout)
var refs []string
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if ref, found := strings.CutPrefix(line, gitCommitSha); found {
ref = strings.TrimSpace(ref)
if tag, isTag := strings.CutPrefix(ref, tagsPrefix); isTag {
refs = append(refs, tag)
continue
}
if branch, isBranchHead := strings.CutPrefix(ref, headsPrefix); isBranchHead {
refs = append(refs, branch)
}
}
lines := getAllTrimmedLinesFromBuffer(stdout)
originPrefix := fmt.Sprintf("%s/", remote)
for i, line := range lines {
lines[i] = strings.TrimPrefix(line, originPrefix)
}
return lines, nil
}

func getTagsPointsAt(
ctx context.Context,
runner command.Runner,
envContainer app.EnvContainer,
dir string,
gitCommitSha string,
) ([]string, error) {
stdout := bytes.NewBuffer(nil)
stderr := bytes.NewBuffer(nil)
if err := runner.Run(
ctx,
gitCommand,
command.RunWithArgs(
"for-each-ref",
"--points-at", gitCommitSha,
"--format", "%(refname:short)",
"refs/tags",
),
command.RunWithStdout(stdout),
command.RunWithStderr(stderr),
command.RunWithDir(dir),
command.RunWithEnv(app.EnvironMap(envContainer)),
); err != nil {
return nil, err
}
return refs, nil
return getAllTrimmedLinesFromBuffer(stdout), nil
}

func getAllTrimmedLinesFromBuffer(buffer *bytes.Buffer) []string {
Expand Down

0 comments on commit 2dfac93

Please sign in to comment.