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