Skip to content

Commit d4a568d

Browse files
committed
Entend pkgVersionFromGit() to prefer @latest version
even if @master is ahead of @latest tagged release because Go modules are becoming commonplace. Also add -force-prerelease flag to revert to old behaviour of always hoosing @master over @latest tagged version.
1 parent 89e799f commit d4a568d

File tree

3 files changed

+81
-31
lines changed

3 files changed

+81
-31
lines changed

make.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ type upstream struct {
109109
vendorDirs []string // all vendor sub directories, relative to the repo directory
110110
repoDeps []string // the repository paths of all dependencies (e.g. github.com/zyedidia/glob)
111111
hasGodeps bool // whether the Godeps/_workspace directory exists
112+
hasRelease bool // whether any release tags exist, for debian/watch
113+
isRelease bool // whether we are packaging a tagged version or not
112114
}
113115

114116
func (u *upstream) get(gopath, repo, rev string) error {
@@ -278,7 +280,7 @@ func (u *upstream) findDependencies(gopath, repo string) error {
278280
return nil
279281
}
280282

281-
func makeUpstreamSourceTarball(repo, revision string) (*upstream, error) {
283+
func makeUpstreamSourceTarball(repo, revision string, forcePrerelease bool) (*upstream, error) {
282284
gopath, err := ioutil.TempDir("", "dh-make-golang")
283285
if err != nil {
284286
return nil, err
@@ -322,7 +324,7 @@ func makeUpstreamSourceTarball(repo, revision string) (*upstream, error) {
322324

323325
log.Printf("Determining upstream version number\n")
324326

325-
u.version, err = pkgVersionFromGit(repoDir)
327+
u.version, u.hasRelease, u.isRelease, err = pkgVersionFromGit(repoDir, forcePrerelease)
326328
if err != nil {
327329
return nil, err
328330
}
@@ -671,6 +673,12 @@ func execMake(args []string, usage func()) {
671673
"and the \"Drop pristine-tar branches\" section at\n"+
672674
"https://go-team.pages.debian.net/workflow-changes.html")
673675

676+
var forcePrerelease bool
677+
fs.BoolVar(&forcePrerelease,
678+
"force-prerelease",
679+
false,
680+
"Package @master or @tip instead of the latest tagged version")
681+
674682
var pkgTypeString string
675683
fs.StringVar(&pkgTypeString,
676684
"type",
@@ -781,7 +789,8 @@ func execMake(args []string, usage func()) {
781789
golangBinaries, err = getGolangBinaries()
782790
return err
783791
})
784-
u, err := makeUpstreamSourceTarball(gopkg, gitRevision)
792+
793+
u, err := makeUpstreamSourceTarball(gopkg, gitRevision, forcePrerelease)
785794
if err != nil {
786795
log.Fatalf("Could not create a tarball of the upstream source: %v\n", err)
787796
}

version.go

Lines changed: 65 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"fmt"
5+
"log"
56
"os"
67
"os/exec"
78
"regexp"
@@ -13,39 +14,79 @@ import (
1314
var (
1415
// describeRegexp parses the count and revision part of the “git describe --long” output.
1516
describeRegexp = regexp.MustCompile(`-\d+-g([0-9a-f]+)\s*$`)
17+
18+
// semverRegexp checks if a string is a valid Go semver,
19+
// from https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
20+
// with leading "v" added.
21+
semverRegexp = regexp.MustCompile(`^v(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`)
1622
)
1723

1824
// TODO: also support other VCS
19-
func pkgVersionFromGit(gitdir string) (string, error) {
20-
cmd := exec.Command("git", "describe", "--exact-match", "--tags")
25+
func pkgVersionFromGit(gitdir string, forcePrerelease bool) (version string, hasRelease, isRelease bool, err error) {
26+
var latestTag string
27+
var commitsAhead int
28+
29+
// Find @latest version tag (whether annotated or not)
30+
cmd := exec.Command("git", "describe", "--abbrev=0", "--tags")
2131
cmd.Dir = gitdir
22-
if tag, err := cmd.Output(); err == nil {
23-
version := strings.TrimSpace(string(tag))
24-
if strings.HasPrefix(version, "v") {
25-
version = version[1:]
32+
if out, err := cmd.Output(); err == nil {
33+
latestTag = strings.TrimSpace(string(out))
34+
hasRelease = true
35+
log.Printf("Found latest tag %q", latestTag)
36+
37+
if !semverRegexp.MatchString(latestTag) {
38+
log.Printf("WARNING: Latest tag %q is not a valid SemVer version\n", latestTag)
39+
// TODO: Enforce strict sementic versioning with leading "v"?
40+
}
41+
42+
// Count number of commits since @latest version
43+
cmd = exec.Command("git", "rev-list", "--count", latestTag+"..HEAD")
44+
cmd.Dir = gitdir
45+
out, err := cmd.Output()
46+
if err != nil {
47+
return "", true, false, err
48+
}
49+
commitsAhead, err = strconv.Atoi(strings.TrimSpace(string(out)))
50+
if err != nil {
51+
return "", true, false, err
52+
}
53+
54+
if commitsAhead == 0 {
55+
// Equivalent to "git describe --exact-match --tags"
56+
log.Printf("Latest tag %q matches master", latestTag)
57+
} else {
58+
log.Printf("INFO: master is ahead of %q by %v commits", latestTag, commitsAhead)
59+
}
60+
61+
version = strings.TrimPrefix(latestTag, "v")
62+
isRelease = true
63+
64+
if forcePrerelease {
65+
log.Printf("INFO: Force packaging master (prerelease) as requested by user")
66+
} else {
67+
return version, hasRelease, isRelease, nil
2668
}
27-
return version, nil
2869
}
2970

71+
// Packaging @master (prerelease)
72+
73+
// 1.0~rc1 < 1.0 < 1.0+b1, as per
74+
// https://www.debian.org/doc/manuals/maint-guide/first.en.html#namever
75+
mainVer := "0.0~"
76+
if hasRelease {
77+
mainVer = version + "+"
78+
}
79+
80+
// Find committer date, UNIX timestamp
3081
cmd = exec.Command("git", "log", "--pretty=format:%ct", "-n1")
3182
cmd.Dir = gitdir
3283
lastCommitUnixBytes, err := cmd.Output()
3384
if err != nil {
34-
return "", err
85+
return "", hasRelease, isRelease, err
3586
}
3687
lastCommitUnix, err := strconv.ParseInt(strings.TrimSpace(string(lastCommitUnixBytes)), 0, 64)
3788
if err != nil {
38-
return "", err
39-
}
40-
41-
// Find the most recent tag (whether annotated or not)
42-
cmd = exec.Command("git", "describe", "--abbrev=0", "--tags")
43-
cmd.Dir = gitdir
44-
// 1.0~rc1 < 1.0 < 1.0+b1, as per
45-
// https://www.debian.org/doc/manuals/maint-guide/first.en.html#namever
46-
lastTag := "0.0~"
47-
if lastTagBytes, err := cmd.Output(); err == nil {
48-
lastTag = strings.TrimPrefix(strings.TrimSpace(string(lastTagBytes)), "v") + "+"
89+
return "", hasRelease, isRelease, err
4990
}
5091

5192
// This results in an output like 4.10.2-232-g9f107c8
@@ -60,19 +101,19 @@ func pkgVersionFromGit(gitdir string) (string, error) {
60101
cmd.Stderr = os.Stderr
61102
revparseBytes, err := cmd.Output()
62103
if err != nil {
63-
return "", err
104+
return "", hasRelease, isRelease, err
64105
}
65106
lastCommitSha = strings.TrimSpace(string(revparseBytes))
66107
} else {
67108
submatches := describeRegexp.FindSubmatch(describeBytes)
68109
if submatches == nil {
69-
return "", fmt.Errorf("git describe output %q does not match expected format", string(describeBytes))
110+
return "", hasRelease, isRelease, fmt.Errorf("git describe output %q does not match expected format", string(describeBytes))
70111
}
71112
lastCommitSha = string(submatches[1])
72113
}
73-
version := fmt.Sprintf("%sgit%s.%s",
74-
lastTag,
114+
version = fmt.Sprintf("%sgit%s.%s",
115+
mainVer,
75116
time.Unix(lastCommitUnix, 0).UTC().Format("20060102"),
76117
lastCommitSha)
77-
return version, nil
118+
return version, hasRelease, isRelease, nil
78119
}

version_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func TestSnapshotVersion(t *testing.T) {
4242
t.Fatalf("Could not run %v: %v", cmd.Args, err)
4343
}
4444

45-
got, err := pkgVersionFromGit(tempdir)
45+
got, _, _, err := pkgVersionFromGit(tempdir, false)
4646
if err != nil {
4747
t.Fatalf("Determining package version from git failed: %v", err)
4848
}
@@ -52,7 +52,7 @@ func TestSnapshotVersion(t *testing.T) {
5252

5353
gitCmdOrFatal(t, tempdir, "tag", "-a", "v1", "-m", "release v1")
5454

55-
got, err = pkgVersionFromGit(tempdir)
55+
got, _, _, err = pkgVersionFromGit(tempdir, false)
5656
if err != nil {
5757
t.Fatalf("Determining package version from git failed: %v", err)
5858
}
@@ -72,7 +72,7 @@ func TestSnapshotVersion(t *testing.T) {
7272
t.Fatalf("Could not run %v: %v", cmd.Args, err)
7373
}
7474

75-
got, err = pkgVersionFromGit(tempdir)
75+
got, _, _, err = pkgVersionFromGit(tempdir, false)
7676
if err != nil {
7777
t.Fatalf("Determining package version from git failed: %v", err)
7878
}
@@ -92,7 +92,7 @@ func TestSnapshotVersion(t *testing.T) {
9292
t.Fatalf("Could not run %v: %v", cmd.Args, err)
9393
}
9494

95-
got, err = pkgVersionFromGit(tempdir)
95+
got, _, _, err = pkgVersionFromGit(tempdir, false)
9696
if err != nil {
9797
t.Fatalf("Determining package version from git failed: %v", err)
9898
}

0 commit comments

Comments
 (0)