Skip to content
This repository has been archived by the owner on Jun 6, 2022. It is now read-only.

Commit

Permalink
Merge pull request #42 from release-engineering/multiple-versions
Browse files Browse the repository at this point in the history
 Look for a run of matching refs and choose the best one
  • Loading branch information
mprahl authored Sep 21, 2018
2 parents 3a3d719 + d775043 commit 8591a88
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 25 deletions.
92 changes: 67 additions & 25 deletions backvendor/vendored.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"path/filepath"
"strings"

"github.com/Masterminds/semver"
"github.com/pkg/errors"
"golang.org/x/tools/go/vcs"
)
Expand Down Expand Up @@ -157,47 +158,65 @@ func updateHashesAfterStrip(hashes *FileHashes, wt WorkingTree, ref string, path
return anyChanged, nil
}

func matchFromRefs(strip bool, hashes *FileHashes, wt WorkingTree, refs []string) (string, error) {
func matchFromRefs(strip bool, hashes *FileHashes, wt WorkingTree, refs []string) ([]string, error) {
var paths []string
if strip {
for hash, _ := range hashes.hashes {
paths = append(paths, hash)
}
}

Refs:
matchFromRef := func(th *FileHashes, ref string) (bool, error) {
if hashes.IsSubsetOf(th) {
return true, nil
}

if !strip {
return false, nil
}

for _, path := range paths {
if _, ok := th.hashes[path]; !ok {
// File missing from revision
return false, nil
}
}

changed, err := updateHashesAfterStrip(th, wt, ref, paths)
if err != nil {
return false, err
}

return changed && hashes.IsSubsetOf(th), nil
}

matches := make([]string, 0)
for _, ref := range refs {
log.Debugf("%s: trying match", ref)
tagHashes, err := wt.FileHashesFromRef(ref)
refHashes, err := wt.FileHashesFromRef(ref)
if err != nil {
if err == ErrorInvalidRef {
continue
}
return "", err
return nil, err
}
if hashes.IsSubsetOf(tagHashes) {
return ref, nil
ok, err := matchFromRef(refHashes, ref)
if err != nil {
return nil, err
}
if strip {
for _, path := range paths {
if _, ok := tagHashes.hashes[path]; !ok {
// File missing from revision
continue Refs
}
}

changed, err := updateHashesAfterStrip(tagHashes, wt, ref, paths)
if err != nil {
return "", err
}

if changed && hashes.IsSubsetOf(tagHashes) {
return ref, nil
}
if ok {
matches = append(matches, ref)
} else if len(matches) > 0 {
// This is the end of a matching run of refs
break
}
}

return "", ErrorVersionNotFound
if len(matches) == 0 {
return nil, ErrorVersionNotFound
}

return matches, nil
}

// Reference describes the origin of a vendored project.
Expand All @@ -216,6 +235,26 @@ type Reference struct {
Ver string
}

// chooseBestTag takes a sorted list of tags and returns the oldest
// semver tag which is not a prerelease, or else the oldest tag.
func chooseBestTag(tags []string) string {
for i := len(tags) - 1; i >= 0; i-- {
tag := tags[i]
v, err := semver.NewVersion(tag)
if err != nil {
continue
}
if v.Prerelease() == "" {
log.Debugf("best from %v: %v (no prerelease)", tags, tag)
return tag
}
}

tag := tags[len(tags)-1]
log.Debugf("best from %v: %v (earliest)", tags, tag)
return tag
}

// DescribeProject attempts to identify the tag in the version control
// system which corresponds to the project. Vendored files and files
// whose names begin with "." are ignored.
Expand Down Expand Up @@ -262,10 +301,11 @@ func (src GoSource) DescribeProject(project *vcs.RepoRoot, root string) (*Refere
// project's vendored files (but not files from the top-level
// project).
strip := src.usesGodep && root != src.Path
match, err := matchFromRefs(strip, hashes, wt, tags)
matches, err := matchFromRefs(strip, hashes, wt, tags)
switch err {
case nil:
// Found a match
match := chooseBestTag(matches)
rev, err := wt.RevisionFromTag(match)
if err != nil {
return nil, err
Expand All @@ -289,11 +329,13 @@ func (src GoSource) DescribeProject(project *vcs.RepoRoot, root string) (*Refere
return nil, err
}

rev, err := matchFromRefs(strip, hashes, wt, revs)
matches, err = matchFromRefs(strip, hashes, wt, revs)
if err != nil {
return nil, err
}

// Use newest matching revision
rev := matches[0]
ver, err := PseudoVersion(wt, rev)
if err != nil {
return nil, err
Expand Down
12 changes: 12 additions & 0 deletions backvendor/vendored_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,15 @@ func TestVendoredProjects(t *testing.T) {
t.Errorf("%v != %v", got, expected)
}
}

func TestChooseBestTag(t *testing.T) {
tags := []string{
"1.2.3-beta1",
"1.2.2",
"1.2.2-beta2",
}
best := chooseBestTag(tags)
if best != "1.2.2" {
t.Errorf("wrong best tag (%s)", best)
}
}

0 comments on commit 8591a88

Please sign in to comment.