From 6e1fedeb0791cd925d0a0aa12a91fcb14dcbcd95 Mon Sep 17 00:00:00 2001 From: Tim Waugh Date: Fri, 14 Sep 2018 12:19:46 +0100 Subject: [PATCH] Add support for identifying source vendored by godep Fixes #31. Signed-off-by: Tim Waugh --- backvendor/vendored.go | 92 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 4 deletions(-) diff --git a/backvendor/vendored.go b/backvendor/vendored.go index c1b68a96..7c0ffd71 100644 --- a/backvendor/vendored.go +++ b/backvendor/vendored.go @@ -16,10 +16,13 @@ package backvendor import ( + "bytes" + "io/ioutil" "os" "path/filepath" "strings" + "github.com/pkg/errors" "golang.org/x/tools/go/vcs" ) @@ -98,15 +101,89 @@ func (src GoSource) VendoredProjects() (map[string]*vcs.RepoRoot, error) { return search.vendored, nil } -func matchFromRefs(hashes *FileHashes, wt *WorkingTree, refs []string) (string, error) { +func updateHashesAfterStrip(hashes *FileHashes, wt *WorkingTree, ref string, paths []string) (bool, error) { + // Update working tree to match the ref + err := wt.RevSync(ref) + if err != nil { + return false, errors.Wrapf(err, "RevSync to %s", ref) + } + + anyChanged := false + for _, path := range paths { + w := bytes.NewBuffer(nil) + changed, err := wt.StripImportComment(path, w) + if err != nil { + return false, err + } + if !changed { + continue + } + + anyChanged = true + + // Write the altered content out to a file + f, err := ioutil.TempFile("", "backvendor-strip.") + if err != nil { + return true, errors.Wrap(err, "updating hash") + } + defer f.Close() + defer os.Remove(f.Name()) + _, err = w.WriteTo(f) + if err != nil { + return true, errors.Wrap(err, "updating hash") + } + if err := f.Close(); err != nil { + return true, errors.Wrap(err, "updating hash") + } + + // Re-hash the altered file + h, err := hashFile(hashes.vcsCmd, path, f.Name()) + if err != nil { + return false, err + } + hashes.hashes[path] = h + } + + return anyChanged, nil +} + +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: for _, ref := range refs { tagHashes, err := wt.FileHashesFromRef(ref) if err != nil { + if err == ErrorInvalidRef { + continue + } return "", err } if hashes.IsSubsetOf(tagHashes) { return ref, nil } + 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 + } + } } return "", ErrorVersionNotFound @@ -157,8 +234,15 @@ func (src GoSource) DescribeProject(project *vcs.RepoRoot, root string) (*Refere return nil, err } - match, err := matchFromRefs(hashes, wt, tags) - if (err != nil && err != ErrorVersionNotFound) || match != "" { + // If godep is in use, strip import comments from the + // 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) + if err != nil && err != ErrorVersionNotFound { + return nil, err + } + if err != ErrorVersionNotFound { rev, err := wt.RevisionFromTag(match) if err != nil { return nil, err @@ -177,7 +261,7 @@ func (src GoSource) DescribeProject(project *vcs.RepoRoot, root string) (*Refere return nil, err } - rev, err := matchFromRefs(hashes, wt, revs) + rev, err := matchFromRefs(strip, hashes, wt, revs) if err != nil { return nil, err }