From e2605999d9d1fa4e98bcf850ed007cfd98f27383 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Thu, 15 Oct 2020 09:47:17 +0200 Subject: pkg/vcs: add ReleaseTag Add ReleaseTag method that returns last release tag for the given commit. Update #2171 --- pkg/vcs/fuchsia.go | 4 ++++ pkg/vcs/git.go | 31 +++++++++++++++++++++---------- pkg/vcs/git_test.go | 5 +---- pkg/vcs/git_test_util.go | 2 +- pkg/vcs/linux.go | 8 ++++---- pkg/vcs/testos.go | 2 +- pkg/vcs/vcs.go | 4 ++++ 7 files changed, 36 insertions(+), 20 deletions(-) (limited to 'pkg/vcs') diff --git a/pkg/vcs/fuchsia.go b/pkg/vcs/fuchsia.go index 9b052e0de..97e5f8b47 100644 --- a/pkg/vcs/fuchsia.go +++ b/pkg/vcs/fuchsia.go @@ -89,3 +89,7 @@ func (ctx *fuchsia) ListRecentCommits(baseCommit string) ([]string, error) { func (ctx *fuchsia) ExtractFixTagsFromCommits(baseCommit, email string) ([]*Commit, error) { return ctx.repo.ExtractFixTagsFromCommits(baseCommit, email) } + +func (ctx *fuchsia) ReleaseTag(commit string) (string, error) { + return "", fmt.Errorf("not implemented for fuchsia") +} diff --git a/pkg/vcs/git.go b/pkg/vcs/git.go index 025fab69e..f487b60c2 100644 --- a/pkg/vcs/git.go +++ b/pkg/vcs/git.go @@ -482,36 +482,47 @@ func (git *git) bisectInconclusive(output []byte) ([]*Commit, error) { return commits, nil } -func (git *git) previousReleaseTags(commit string, self bool) ([]string, error) { +func (git *git) ReleaseTag(commit string) (string, error) { + tags, err := git.previousReleaseTags(commit, true, true) + if err != nil { + return "", err + } + if len(tags) == 0 { + return "", fmt.Errorf("no release tags found for commit %v", commit) + } + return tags[0], nil +} + +func (git *git) previousReleaseTags(commit string, self, onlyTop bool) ([]string, error) { var tags []string if self { output, err := git.git("tag", "--list", "--points-at", commit, "--merged", commit, "v*.*") if err != nil { return nil, err } - tags, err = gitParseReleaseTags(output) - if err != nil { - return nil, err + tags = gitParseReleaseTags(output) + if onlyTop && len(tags) != 0 { + return tags, nil } } output, err := git.git("tag", "--no-contains", commit, "--merged", commit, "v*.*") if err != nil { return nil, err } - tags1, err := gitParseReleaseTags(output) - if err != nil { - return nil, err - } + tags1 := gitParseReleaseTags(output) tags = append(tags, tags1...) + if len(tags) == 0 { + return nil, fmt.Errorf("no release tags found for commit %v", commit) + } return tags, nil } func (git *git) IsRelease(commit string) (bool, error) { - tags1, err := git.previousReleaseTags(commit, true) + tags1, err := git.previousReleaseTags(commit, true, false) if err != nil { return false, err } - tags2, err := git.previousReleaseTags(commit, false) + tags2, err := git.previousReleaseTags(commit, false, false) if err != nil { return false, err } diff --git a/pkg/vcs/git_test.go b/pkg/vcs/git_test.go index 053dc6d33..4648f04f1 100644 --- a/pkg/vcs/git_test.go +++ b/pkg/vcs/git_test.go @@ -121,10 +121,7 @@ v1. "v2.6.13", "v2.6.12", } - got, err := gitParseReleaseTags([]byte(input)) - if err != nil { - t.Fatal(err) - } + got := gitParseReleaseTags([]byte(input)) if !reflect.DeepEqual(got, want) { t.Fatalf("got bad tags\ngot: %+v\nwant: %+v", got, want) } diff --git a/pkg/vcs/git_test_util.go b/pkg/vcs/git_test_util.go index 09f5a6af6..5ef6c50c3 100644 --- a/pkg/vcs/git_test_util.go +++ b/pkg/vcs/git_test_util.go @@ -90,7 +90,7 @@ func (repo *TestRepo) SetTag(tag string) { func (repo *TestRepo) SupportsBisection() bool { // Detect too old git binary. --no-contains appeared in git 2.13. - _, err := repo.repo.previousReleaseTags("HEAD", true) + _, err := repo.repo.previousReleaseTags("HEAD", true, false) return err == nil || !strings.Contains(err.Error(), "usage: git tag") && !strings.Contains(err.Error(), "error: unknown option") diff --git a/pkg/vcs/linux.go b/pkg/vcs/linux.go index 8e4f17d4a..c4e2a90a5 100644 --- a/pkg/vcs/linux.go +++ b/pkg/vcs/linux.go @@ -39,7 +39,7 @@ func newLinux(dir string) *linux { } func (ctx *linux) PreviousReleaseTags(commit string) ([]string, error) { - tags, err := ctx.git.previousReleaseTags(commit, false) + tags, err := ctx.git.previousReleaseTags(commit, false, false) if err != nil { return nil, err } @@ -71,7 +71,7 @@ func (ctx *linux) PreviousReleaseTags(commit string) ([]string, error) { return tags, nil } -func gitParseReleaseTags(output []byte) ([]string, error) { +func gitParseReleaseTags(output []byte) []string { var tags []string for _, tag := range bytes.Split(output, []byte{'\n'}) { if releaseTagRe.Match(tag) && gitReleaseTagToInt(string(tag)) != 0 { @@ -81,7 +81,7 @@ func gitParseReleaseTags(output []byte) ([]string, error) { sort.Slice(tags, func(i, j int) bool { return gitReleaseTagToInt(tags[i]) > gitReleaseTagToInt(tags[j]) }) - return tags, nil + return tags } func gitReleaseTagToInt(tag string) uint64 { @@ -105,7 +105,7 @@ func gitReleaseTagToInt(tag string) uint64 { } func (ctx *linux) EnvForCommit(binDir, commit string, kernelConfig []byte) (*BisectEnv, error) { - tagList, err := ctx.previousReleaseTags(commit, true) + tagList, err := ctx.previousReleaseTags(commit, true, false) if err != nil { return nil, err } diff --git a/pkg/vcs/testos.go b/pkg/vcs/testos.go index ea369f529..ad6df6b1e 100644 --- a/pkg/vcs/testos.go +++ b/pkg/vcs/testos.go @@ -21,7 +21,7 @@ func newTestos(dir string) *testos { } func (ctx *testos) PreviousReleaseTags(commit string) ([]string, error) { - return ctx.git.previousReleaseTags(commit, false) + return ctx.git.previousReleaseTags(commit, false, false) } func (ctx *testos) EnvForCommit(binDir, commit string, kernelConfig []byte) (*BisectEnv, error) { diff --git a/pkg/vcs/vcs.go b/pkg/vcs/vcs.go index 72484203d..1f12fa85a 100644 --- a/pkg/vcs/vcs.go +++ b/pkg/vcs/vcs.go @@ -102,6 +102,9 @@ type Repo interface { // Given email = "user@domain.com", it searches for tags of the form "user+tag@domain.com" // and returns commits with these tags. ExtractFixTagsFromCommits(baseCommit, email string) ([]*Commit, error) + + // ReleaseTag returns the latest release tag that is reachable from the given commit. + ReleaseTag(commit string) (string, error) } // Bisecter may be optionally implemented by Repo. @@ -115,6 +118,7 @@ type Bisecter interface { Bisect(bad, good string, trace io.Writer, pred func() (BisectResult, error)) ([]*Commit, error) // PreviousReleaseTags returns list of preceding release tags that are reachable from the given commit. + // If the commit itself has a release tag, this tag is not included. PreviousReleaseTags(commit string) ([]string, error) IsRelease(commit string) (bool, error) -- cgit mrf-deployment