Skip to content

Commit

Permalink
feat: PreviousTag
Browse files Browse the repository at this point in the history
- PreviousTag finds the tag that preceded the current one
  • Loading branch information
fallion committed Sep 3, 2019
1 parent 005b770 commit ca2b543
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 0 deletions.
93 changes: 93 additions & 0 deletions pkg/history/previous_tag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package history

import (
"errors"
"log"
"sort"
"time"

"gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/plumbing"
)

var (
// ErrPrevTagNotAvailable is returned when no previous tag is found.
ErrPrevTagNotAvailable = errors.New("previous tag is not available")
)

type tag struct {
hash plumbing.Hash
time time.Time
}

// PreviousTag sorts tags based on when their commit happened and returns the one previous
// to the current.
func (g *Git) PreviousTag(currentHash plumbing.Hash) (plumbing.Hash, error) {
tagrefs, err := g.repo.Tags()

if err != nil {
return currentHash, err
}

defer tagrefs.Close()

var tagHashes []tag

err = tagrefs.ForEach(func(t *plumbing.Reference) error {
commitDate, err := g.commitDate(t.Hash())

if err != nil {
return err
}

tagHashes = append(tagHashes, tag{time: commitDate, hash: t.Hash()})
return nil
})

if err != nil {
if g.Debug {
log.Printf("[ERR] getting previous tag failed: %v", err)
}
return currentHash, err
}

// Tags are alphabetically ordered. We need to sort them by date.
sortedTags := sortTags(g.repo, tagHashes)

if g.Debug {
log.Println("Sorted tag output: ")
for _, taginstance := range sortedTags {
log.Printf("hash: %v time: %v", taginstance.hash, taginstance.time.UTC())
}
}

// If there are fewer than two tags assume that the currentCommit is the newest tag
if len(sortedTags) < 2 {
if g.Debug {
log.Println("[ERR] previous tag not available")
}
return currentHash, ErrPrevTagNotAvailable
}

if sortedTags[0].hash != currentHash {
if g.Debug {
log.Println("[ERR] current commit does not have a tag attached, building from this commit")
}
return sortedTags[0].hash, nil
}

if g.Debug {
log.Printf("success: previous tag found at %v", sortedTags[1].hash)
}

return sortedTags[1].hash, nil
}

// sortTags sorts the tags according to when their parent commit happened.
func sortTags(repo *git.Repository, tags []tag) []tag {
sort.Slice(tags, func(i, j int) bool {
return tags[i].time.After(tags[j].time)
})

return tags
}
29 changes: 29 additions & 0 deletions pkg/history/previous_tag_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package history

import (
"log"
"testing"

"github.com/stretchr/testify/assert"
"gopkg.in/src-d/go-git.v4"
)

func TestPreviousTag(t *testing.T) {
repo, _ := git.PlainOpen("../../testdata/git_tags")
testGit := &Git{repo: repo, Debug: true}

head, err := repo.Head()

assert.NoError(t, err)

tagHash, err := testGit.PreviousTag(head.Hash())

assert.NoError(t, err)

log.Print(tagHash)

commit, err := repo.CommitObject(tagHash)
assert.NoError(t, err)
assert.Equal(t, "chore: first commit on master\n", commit.Message)

}

0 comments on commit ca2b543

Please sign in to comment.