Skip to content

Commit

Permalink
Sanitize prerelease label, trim branch prefix (#24)
Browse files Browse the repository at this point in the history
* (+semver: feature) Safer sanitized branch names

* (+semver: feature) Trim branch prefix and add tests for cleansing branch name
  • Loading branch information
cuevaskoch authored and annymsMthd committed Apr 30, 2019
1 parent 8675397 commit 1197822
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 22 deletions.
21 changes: 14 additions & 7 deletions cmd/gogitver/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func init() {
for _, cmd := range cmds {
cmd.Flags().String("path", ".", "the path to the git repository")
cmd.Flags().String("settings", "./.gogitver.yaml", "the file that contains the settings")
cmd.Flags().Bool("trim-branch-prefix", false, "Trim branch prefixes feature/ and hotfix/ from prerelease label")
}

rootCmd.Flags().Bool("forbid-behind-master", false, "error if the current branch's calculated version is behind the calculated version of refs/heads/master")
Expand Down Expand Up @@ -74,15 +75,20 @@ func getRepoAndSettings(cmd *cobra.Command) (*gogit.Repository, *git.Settings) {
return r, s
}

func runRoot(cmd *cobra.Command, args []string) {
r, s := getRepoAndSettings(cmd)

fbm, err := strconv.ParseBool(cmd.Flag("forbid-behind-master").Value.String())
func getBoolFromFlag(cmd *cobra.Command, flagName string) bool {
result, err := strconv.ParseBool(cmd.Flag(flagName).Value.String())
if err != nil {
fbm = false
result = false
}
return result
}

func runRoot(cmd *cobra.Command, args []string) {
r, s := getRepoAndSettings(cmd)

version, err := git.GetCurrentVersion(r, s, false, fbm)
fbm := getBoolFromFlag(cmd, "forbid-behind-master")
trimPrefix := getBoolFromFlag(cmd, "trim-branch-prefix")
version, err := git.GetCurrentVersion(r, s, false, fbm, trimPrefix)
if err != nil {
panic(err)
}
Expand All @@ -92,8 +98,9 @@ func runRoot(cmd *cobra.Command, args []string) {

func runPrerelease(cmd *cobra.Command, args[]string) {
r, s := getRepoAndSettings(cmd)
trimPrefix := getBoolFromFlag(cmd, "trim-branch-prefix")

label, err := git.GetPrereleaseLabel(r, s)
label, err := git.GetPrereleaseLabel(r, s, trimPrefix)
if err != nil {
panic(err)
}
Expand Down
59 changes: 46 additions & 13 deletions pkg/git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package git
import (
"fmt"
"os"
"regexp"
"strings"

"github.com/coreos/go-semver/semver"
Expand All @@ -22,7 +23,7 @@ type gitVersion struct {
}

// GetCurrentVersion returns the current version
func GetCurrentVersion(r *git.Repository, settings *Settings, ignoreTravisTag bool, forbidBehindMaster bool) (version string, err error) {
func GetCurrentVersion(r *git.Repository, settings *Settings, ignoreTravisTag bool, forbidBehindMaster bool, trimPrefix bool) (version string, err error) {
tag, ok := os.LookupEnv("TRAVIS_TAG")
if !ignoreTravisTag && ok && tag != "" { // If this is a tagged build in travis shortcircuit here
version, err := semver.NewVersion(tag)
Expand Down Expand Up @@ -70,7 +71,7 @@ func GetCurrentVersion(r *git.Repository, settings *Settings, ignoreTravisTag bo
return "", errors.Wrap(err, "GetCurrentVersion failed")
}

v, err := getVersion(r, h, tagMap, forbidBehindMaster, settings)
v, err := getVersion(r, h, tagMap, forbidBehindMaster, trimPrefix, settings)
if err != nil {
return "", errors.Wrap(err, "GetCurrentVersion failed")
}
Expand All @@ -79,16 +80,16 @@ func GetCurrentVersion(r *git.Repository, settings *Settings, ignoreTravisTag bo
}

// GetPrereleaseLabel returns the prerelease label for the current branch
func GetPrereleaseLabel(r *git.Repository, settings *Settings) (result string, err error) {
func GetPrereleaseLabel(r *git.Repository, settings *Settings, trimPrefix bool) (result string, err error) {
h, err := r.Head()
if err != nil {
return "", errors.Wrap(err, "GetCurrentVersion failed")
}
return getCurrentBranch(r, h)
return getCurrentBranch(r, h, trimPrefix)
}

func getVersion(r *git.Repository, h *plumbing.Reference, tagMap map[string]string, forbidBehindMaster bool, settings *Settings) (version *semver.Version, err error) {
currentBranch, err := getCurrentBranch(r, h)
func getVersion(r *git.Repository, h *plumbing.Reference, tagMap map[string]string, forbidBehindMaster bool, trimPrefix bool, settings *Settings) (version *semver.Version, err error) {
currentBranch, err := getCurrentBranch(r, h, trimPrefix)
if err != nil {
return nil, errors.Wrap(err, "getVersion failed")
}
Expand Down Expand Up @@ -167,22 +168,34 @@ func getVersion(r *git.Repository, h *plumbing.Reference, tagMap map[string]stri
return baseVersion, nil
}

func getCurrentBranch(r *git.Repository, h *plumbing.Reference) (name string, err error) {
func getCurrentBranch(r *git.Repository, h *plumbing.Reference, trimPrefix bool) (name string, err error) {
branchName := ""

name, ok := os.LookupEnv("TRAVIS_PULL_REQUEST_BRANCH") // Travis
if ok {
return cleanseBranchName(name), nil
branchName, err := cleanseBranchName(name, trimPrefix)
if err != nil {
return "", err
}
return branchName, nil
}

name, ok = os.LookupEnv("TRAVIS_BRANCH")
if ok {
return cleanseBranchName(name), nil
branchName, err := cleanseBranchName(name, trimPrefix)
if err != nil {
return "", err
}
return branchName, nil
}

name, ok = os.LookupEnv("CI_COMMIT_REF_NAME") // GitLab
if ok {
return cleanseBranchName(name), nil
branchName, err := cleanseBranchName(name, trimPrefix)
if err != nil {
return "", err
}
return branchName, nil
}

refs, err := r.References()
Expand All @@ -203,9 +216,29 @@ func getCurrentBranch(r *git.Repository, h *plumbing.Reference) (name string, er
return "", fmt.Errorf("Cannot determine branch")
}

return cleanseBranchName(branchName), nil
branch, err := cleanseBranchName(branchName, trimPrefix)
if err != nil {
return "", err
}
return branch, nil
}

func cleanseBranchName(name string) string {
return strings.Replace(name, "/", "-", -1)
func cleanseBranchName(name string, trimPrefix bool) (string, error) {
reg, err := regexp.Compile("[^a-zA-Z0-9]+")
if err != nil {
return "", err
}

branchName := reg.ReplaceAllString(name, "-")
if !trimPrefix {
return branchName, nil
}

reg, err = regexp.Compile("^(feature|master)-")
if err != nil {
return "", err
}

branchName = reg.ReplaceAllString(branchName, "")
return branchName, nil
}
80 changes: 78 additions & 2 deletions pkg/git/git_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package git_test

import (
"fmt"
"path"
"testing"
"time"
Expand Down Expand Up @@ -63,7 +64,7 @@ func TestUseLightweightTagForVersionAnchor(t *testing.T) {
}

s := igit.GetDefaultSettings()
version, err := igit.GetCurrentVersion(r, s, true, false)
version, err := igit.GetCurrentVersion(r, s, true, false, false)
if err != nil {
t.Error(err)
t.FailNow()
Expand Down Expand Up @@ -118,7 +119,7 @@ func TestUseAnnotatedTagForVersionAnchor(t *testing.T) {
}

s := igit.GetDefaultSettings()
version, err := igit.GetCurrentVersion(r, s, true, false)
version, err := igit.GetCurrentVersion(r, s, true, false, false)
if err != nil {
t.Error(err)
t.FailNow()
Expand All @@ -127,6 +128,81 @@ func TestUseAnnotatedTagForVersionAnchor(t *testing.T) {
assert.Equal(t, "1.5.0", version)
}

func TestTrimBranchPrefix(t *testing.T) {
r := getSingleBranchCommit("feature/should-be-trimmed", t)
s := igit.GetDefaultSettings()
label, err := igit.GetPrereleaseLabel(r, s, true)
if err != nil {
t.Error(err)
t.FailNow()
}

assert.Equal(t, "should-be-trimmed", label)
}

func TestCleanseBranchName(t *testing.T) {
r := getSingleBranchCommit("author's-branch", t)
s := igit.GetDefaultSettings()
label, err := igit.GetPrereleaseLabel(r, s, true)
if err != nil {
t.Error(err)
t.FailNow()
}

assert.Equal(t, "author-s-branch", label)
}

func getSingleBranchCommit(branchName string, t *testing.T) *git.Repository {
fs := memfs.New()
storage := memory.NewStorage()

r, err := git.Init(storage, fs)
if err != nil {
t.Error(err)
t.FailNow()
}

w, err := r.Worktree()
if err != nil {
t.Error(err)
t.FailNow()
}

util.WriteFile(fs, "foo", []byte("foo"), 0644)
_, err = w.Add("foo")
if err != nil {
t.Error(err)
t.FailNow()
}
_, err = w.Commit("foo\n", &git.CommitOptions{Author: defaultSignature()})
if err != nil {
t.Error(err)
t.FailNow()
}

ref := fmt.Sprintf("refs/heads/%s", branchName)
b := plumbing.ReferenceName(ref)
w.Checkout(&git.CheckoutOptions{
Create: true,
Force: false,
Branch: b,
})

util.WriteFile(fs, "foo2", []byte("foo"), 0644)
_, err = w.Add("foo2")
if err != nil {
t.Error(err)
t.FailNow()
}
_, err = w.Commit("(+semver: major) This is a major commit\n", &git.CommitOptions{Author: defaultSignature()})
if err != nil {
t.Error(err)
t.FailNow()
}

return r
}

func defaultSignature() *object.Signature {
when, _ := time.Parse(object.DateFormat, "Thu May 04 00:03:43 2017 +0200")
return &object.Signature{
Expand Down

0 comments on commit 1197822

Please sign in to comment.