restore,update: look at repository[+vcs] instead of importpath This enables users to manually vendor a fork of a given package by setting the repository to something different from what the importpath Deduces to. Closes #24
diff --git a/README.md b/README.md index 4c6cbe6..f74534a 100644 --- a/README.md +++ b/README.md
@@ -115,6 +115,17 @@ repository goes down or rewrites history, build reproducibility is lost * `go get` won't work on your package +## Vendoring a different fork + +You might have your own version of a repository (i.e. a fork) but still want to +vendor it at the original import path. + +Since this is not a common use-case, there's no support in `gvt fetch` for it, +however, you can manually edit the `vendor/manifest` file, changing `repository` +and `revision`, and then run `gvt restore`. + +`gvt update` will stay on your fork. + ## Troubleshooting ### `fatal: Not a git repository [...]`
diff --git a/fetch.go b/fetch.go index ae43ee9..f78a6cf 100644 --- a/fetch.go +++ b/fetch.go
@@ -117,6 +117,7 @@ dep := vendor.Dependency{ Importpath: path, Repository: repo.URL(), + VCS: repo.Type(), Revision: rev, Branch: b, Path: extra,
diff --git a/gbvendor/manifest.go b/gbvendor/manifest.go index 2282cde..6bb0e27 100644 --- a/gbvendor/manifest.go +++ b/gbvendor/manifest.go
@@ -71,6 +71,9 @@ // dependency was fetched from. Repository string `json:"repository"` + // VCS is the DVCS system found at Repository. + VCS string `json:"vcs"` + // Revision is the revision that describes the dependency's // remote revision. Revision string `json:"revision"`
diff --git a/gbvendor/manifest_test.go b/gbvendor/manifest_test.go index aa486e5..1dc7839 100644 --- a/gbvendor/manifest_test.go +++ b/gbvendor/manifest_test.go
@@ -80,6 +80,7 @@ Dependencies: []Dependency{{ Importpath: "github.com/foo/bar", Repository: "https://github.com/foo/bar", + VCS: "git", Revision: "abcdef", Branch: "master", }}, @@ -94,6 +95,7 @@ { "importpath": "github.com/foo/bar", "repository": "https://github.com/foo/bar", + "vcs": "git", "revision": "abcdef", "branch": "master" }
diff --git a/gbvendor/repo.go b/gbvendor/repo.go index 9b970f3..82f4934 100644 --- a/gbvendor/repo.go +++ b/gbvendor/repo.go
@@ -184,6 +184,34 @@ } } +func NewRemoteRepo(repoURL, vcs string, insecure bool) (RemoteRepo, error) { + u, err := url.Parse(repoURL) + if err != nil { + return nil, fmt.Errorf("%q is not a valid import path", repoURL) + } + switch vcs { + case "git": + return Gitrepo(u, insecure, u.Scheme) + case "hg": + return Hgrepo(u, insecure, u.Scheme) + case "bzr": + return Bzrrepo(repoURL) + case "": + // for backwards compatibility with manifests that miss the VCS entry + if repo, err := Gitrepo(u, insecure, u.Scheme); err == nil { + return repo, nil + } + if repo, err := Hgrepo(u, insecure, u.Scheme); err == nil { + return repo, nil + } + if repo, err := Bzrrepo(repoURL); err == nil { + return repo, nil + } + return nil, fmt.Errorf("can't reach %q", repoURL) + } + return nil, fmt.Errorf("%q is not a valid VCS", vcs) +} + // Gitrepo returns a RemoteRepo representing a remote git repository. func Gitrepo(url *url.URL, insecure bool, schemes ...string) (RemoteRepo, error) { if len(schemes) == 0 {
diff --git a/gbvendor/repo_test.go b/gbvendor/repo_test.go index b42bbc8..7e0c9d1 100644 --- a/gbvendor/repo_test.go +++ b/gbvendor/repo_test.go
@@ -141,5 +141,15 @@ if !reflect.DeepEqual(got, tt.want) || extra != tt.extra { t.Errorf("DeduceRemoteRepo(%q): want %#v, %v, got %#v, %v", tt.path, tt.want, tt.extra, got, extra) } + + if tt.want != nil { + got, err := NewRemoteRepo(tt.want.URL(), tt.want.Type(), tt.insecure) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewRemoteRepo(%s, %s): want %#v, got %#v", tt.want.URL(), tt.want.Type(), tt.want, got) + } + } } }
diff --git a/restore.go b/restore.go index c0756fd..3601291 100644 --- a/restore.go +++ b/restore.go
@@ -104,7 +104,7 @@ log.Printf("fetching %s %s", dep.Importpath, extraMsg) } - repo, _, err := vendor.DeduceRemoteRepo(dep.Importpath, rbInsecure) + repo, err := vendor.NewRemoteRepo(dep.Repository, dep.VCS, rbInsecure) if err != nil { return fmt.Errorf("dependency could not be processed: %s", err) }
diff --git a/update.go b/update.go index ac462fd..8f6c6f1 100644 --- a/update.go +++ b/update.go
@@ -70,7 +70,7 @@ return fmt.Errorf("dependency could not be deleted from manifest: %v", err) } - repo, extra, err := vendor.DeduceRemoteRepo(d.Importpath, insecure) + repo, err := vendor.NewRemoteRepo(d.Repository, d.VCS, insecure) if err != nil { return fmt.Errorf("could not determine repository for import %q", d.Importpath) } @@ -93,9 +93,10 @@ dep := vendor.Dependency{ Importpath: d.Importpath, Repository: repo.URL(), + VCS: repo.Type(), Revision: rev, Branch: branch, - Path: extra, + Path: d.Path, NoTests: d.NoTests, AllFiles: d.AllFiles, }