aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/git
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/git')
-rw-r--r--pkg/git/git.go52
-rw-r--r--pkg/git/git_test.go45
2 files changed, 94 insertions, 3 deletions
diff --git a/pkg/git/git.go b/pkg/git/git.go
index 6464dc5eb..f7e93825f 100644
--- a/pkg/git/git.go
+++ b/pkg/git/git.go
@@ -13,6 +13,8 @@ import (
"os"
"os/exec"
"regexp"
+ "sort"
+ "strconv"
"strings"
"time"
@@ -316,6 +318,49 @@ func Patch(dir string, patch []byte) error {
return nil
}
+// PreviousReleaseTags returns list of preceding release tags that are reachable from the given commit.
+// Note: linux-specific.
+func PreviousReleaseTags(dir, commit string) ([]string, error) {
+ output, err := runSandboxed(dir, "git", "tag", "--no-contains", commit, "--merged", commit, "v*.*")
+ if err != nil {
+ return nil, err
+ }
+ return parseReleaseTags(output)
+}
+
+func parseReleaseTags(output []byte) ([]string, error) {
+ var tags []string
+ for _, tag := range bytes.Split(output, []byte{'\n'}) {
+ if releaseTagRe.Match(tag) && releaseTagToInt(string(tag)) != 0 {
+ tags = append(tags, string(tag))
+ }
+ }
+ sort.Slice(tags, func(i, j int) bool {
+ return releaseTagToInt(tags[i]) > releaseTagToInt(tags[j])
+ })
+ return tags, nil
+}
+
+func releaseTagToInt(tag string) uint64 {
+ matches := releaseTagRe.FindStringSubmatchIndex(tag)
+ v1, err := strconv.ParseUint(tag[matches[2]:matches[3]], 10, 64)
+ if err != nil {
+ return 0
+ }
+ v2, err := strconv.ParseUint(tag[matches[4]:matches[5]], 10, 64)
+ if err != nil {
+ return 0
+ }
+ var v3 uint64
+ if matches[6] != -1 {
+ v3, err = strconv.ParseUint(tag[matches[6]:matches[7]], 10, 64)
+ if err != nil {
+ return 0
+ }
+ }
+ return v1*1e6 + v2*1e3 + v3
+}
+
func runSandboxed(dir, command string, args ...string) ([]byte, error) {
cmd := osutil.Command(command, args...)
cmd.Dir = dir
@@ -345,7 +390,8 @@ func CheckCommitHash(hash string) bool {
var (
// nolint: lll
- gitRepoRe = regexp.MustCompile(`^(git|ssh|http|https|ftp|ftps)://[a-zA-Z0-9-_]+(\.[a-zA-Z0-9-_]+)+(:[0-9]+)?/[a-zA-Z0-9-_./]+\.git(/)?$`)
- gitBranchRe = regexp.MustCompile("^[a-zA-Z0-9-_/.]{2,200}$")
- gitHashRe = regexp.MustCompile("^[a-f0-9]+$")
+ gitRepoRe = regexp.MustCompile(`^(git|ssh|http|https|ftp|ftps)://[a-zA-Z0-9-_]+(\.[a-zA-Z0-9-_]+)+(:[0-9]+)?/[a-zA-Z0-9-_./]+\.git(/)?$`)
+ gitBranchRe = regexp.MustCompile("^[a-zA-Z0-9-_/.]{2,200}$")
+ gitHashRe = regexp.MustCompile("^[a-f0-9]+$")
+ releaseTagRe = regexp.MustCompile(`^v([0-9]+).([0-9]+)(?:\.([0-9]+))?$`)
)
diff --git a/pkg/git/git_test.go b/pkg/git/git_test.go
index 18ba03d6e..66159107f 100644
--- a/pkg/git/git_test.go
+++ b/pkg/git/git_test.go
@@ -82,6 +82,51 @@ func testPredicate(t *testing.T, fn func(string) bool, tests map[string]bool) {
}
}
+func TestParseReleaseTags(t *testing.T) {
+ input := `
+v3.1
+v2.6.12
+v2.6.39
+v3.0
+v3.10
+v2.6.13
+v3.11
+v3.19
+v3.9
+v3.2
+v4.9
+v2.6.32
+v4.0
+voo
+v1.foo
+v10.2.foo
+v1.2.
+v1.
+`
+ want := []string{
+ "v4.9",
+ "v4.0",
+ "v3.19",
+ "v3.11",
+ "v3.10",
+ "v3.9",
+ "v3.2",
+ "v3.1",
+ "v3.0",
+ "v2.6.39",
+ "v2.6.32",
+ "v2.6.13",
+ "v2.6.12",
+ }
+ got, err := parseReleaseTags([]byte(input))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Fatalf("got bad tags\ngot: %+v\nwant: %+v", got, want)
+ }
+}
+
func TestExtractFixTags(t *testing.T) {
commits, err := extractFixTags(strings.NewReader(extractFixTagsInput), extractFixTagsEmail)
if err != nil {