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,
}