Commit f3a98dee authored by Russ Cox's avatar Russ Cox

cmd/go: re-resolve and check vcs roots during go get -u

If you do 'go get -u rsc.io/pdf' and then rsc.io/pdf's redirect
changes to point somewhere else, after this CL a later
'go get -u rsc.io/pdf' will tell you that.

Fixes #8548.

LGTM=iant
R=golang-codereviews, iant
CC=adg, golang-codereviews, n13m3y3r, r
https://golang.org/cl/147170043
parent 7fa96f08
...@@ -266,6 +266,18 @@ func downloadPackage(p *Package) error { ...@@ -266,6 +266,18 @@ func downloadPackage(p *Package) error {
return err return err
} }
repo = "<local>" // should be unused; make distinctive repo = "<local>" // should be unused; make distinctive
// Double-check where it came from.
if *getU && vcs.remoteRepo != nil {
dir := filepath.Join(p.build.SrcRoot, rootPath)
if remote, err := vcs.remoteRepo(vcs, dir); err == nil {
if rr, err := repoRootForImportPath(p.ImportPath); err == nil {
if remote != rr.repo {
return fmt.Errorf("%s is from %s, should be from %s", dir, remote, rr.repo)
}
}
}
}
} else { } else {
// Analyze the import path to determine the version control system, // Analyze the import path to determine the version control system,
// repository, and the import path for the root of the repository. // repository, and the import path for the root of the repository.
......
...@@ -126,6 +126,56 @@ if ! ./testgo build -v ./testdata/testinternal2; then ...@@ -126,6 +126,56 @@ if ! ./testgo build -v ./testdata/testinternal2; then
ok=false ok=false
fi fi
# Test that 'go get -u' reports moved packages.
testmove() {
vcs=$1
url=$2
base=$3
config=$4
TEST go get -u notices $vcs package that moved
d=$(mktemp -d -t testgoXXX)
mkdir -p $d/src
if ! GOPATH=$d ./testgo get -d $url; then
echo 'go get -d $url failed'
ok=false
elif ! GOPATH=$d ./testgo get -d -u $url; then
echo 'go get -d -u $url failed'
ok=false
else
set +e
case "$vcs" in
svn)
# SVN doesn't believe in text files so we can't just edit the config.
# Check out a different repo into the wrong place.
rm -rf $d/src/code.google.com/p/rsc-svn
GOPATH=$d ./testgo get -d -u code.google.com/p/rsc-svn2/trunk
mv $d/src/code.google.com/p/rsc-svn2 $d/src/code.google.com/p/rsc-svn
;;
*)
echo '1,$s;'"$base"';'"$base"'XXX;
w
q' | ed $d/src/$config >/dev/null 2>&1
esac
set -e
if GOPATH=$d ./testgo get -d -u $url 2>$d/err; then
echo "go get -d -u $url succeeded with wrong remote repo"
cat $d/err
ok=false
elif ! grep 'should be from' $d/err >/dev/null; then
echo "go get -d -u $url failed for wrong reason"
cat $d/err
ok=false
fi
fi
rm -rf $d
}
testmove hg rsc.io/x86/x86asm x86 rsc.io/x86/.hg/hgrc
testmove git rsc.io/pdf pdf rsc.io/pdf/.git/config
testmove svn code.google.com/p/rsc-svn/trunk - -
export GOPATH=$(pwd)/testdata/importcom export GOPATH=$(pwd)/testdata/importcom
TEST 'import comment - match' TEST 'import comment - match'
if ! ./testgo build ./testdata/importcom/works.go; then if ! ./testgo build ./testdata/importcom/works.go; then
......
...@@ -33,6 +33,8 @@ type vcsCmd struct { ...@@ -33,6 +33,8 @@ type vcsCmd struct {
scheme []string scheme []string
pingCmd string pingCmd string
remoteRepo func(v *vcsCmd, rootDir string) (remoteRepo string, err error)
} }
// A tagCmd describes a command to list available tags // A tagCmd describes a command to list available tags
...@@ -81,8 +83,17 @@ var vcsHg = &vcsCmd{ ...@@ -81,8 +83,17 @@ var vcsHg = &vcsCmd{
tagSyncCmd: "update -r {tag}", tagSyncCmd: "update -r {tag}",
tagSyncDefault: "update default", tagSyncDefault: "update default",
scheme: []string{"https", "http", "ssh"}, scheme: []string{"https", "http", "ssh"},
pingCmd: "identify {scheme}://{repo}", pingCmd: "identify {scheme}://{repo}",
remoteRepo: hgRemoteRepo,
}
func hgRemoteRepo(vcsHg *vcsCmd, rootDir string) (remoteRepo string, err error) {
out, err := vcsHg.runOutput(rootDir, "paths default")
if err != nil {
return "", err
}
return strings.TrimSpace(string(out)), nil
} }
// vcsGit describes how to use Git. // vcsGit describes how to use Git.
...@@ -104,8 +115,38 @@ var vcsGit = &vcsCmd{ ...@@ -104,8 +115,38 @@ var vcsGit = &vcsCmd{
tagSyncCmd: "checkout {tag}", tagSyncCmd: "checkout {tag}",
tagSyncDefault: "checkout master", tagSyncDefault: "checkout master",
scheme: []string{"git", "https", "http", "git+ssh"}, scheme: []string{"git", "https", "http", "git+ssh"},
pingCmd: "ls-remote {scheme}://{repo}", pingCmd: "ls-remote {scheme}://{repo}",
remoteRepo: gitRemoteRepo,
}
func gitRemoteRepo(vcsGit *vcsCmd, rootDir string) (remoteRepo string, err error) {
outb, err := vcsGit.runOutput(rootDir, "remote -v")
if err != nil {
return "", err
}
out := string(outb)
// Expect:
// origin https://github.com/rsc/pdf (fetch)
// origin https://github.com/rsc/pdf (push)
// use first line only.
if !strings.HasPrefix(out, "origin\t") {
return "", fmt.Errorf("unable to parse output of git remote -v")
}
out = strings.TrimPrefix(out, "origin\t")
i := strings.Index(out, "\n")
if i < 0 {
return "", fmt.Errorf("unable to parse output of git remote -v")
}
out = out[:i]
i = strings.LastIndex(out, " ")
if i < 0 {
return "", fmt.Errorf("unable to parse output of git remote -v")
}
out = out[:i]
return strings.TrimSpace(string(out)), nil
} }
// vcsBzr describes how to use Bazaar. // vcsBzr describes how to use Bazaar.
...@@ -138,8 +179,34 @@ var vcsSvn = &vcsCmd{ ...@@ -138,8 +179,34 @@ var vcsSvn = &vcsCmd{
// There is no tag command in subversion. // There is no tag command in subversion.
// The branch information is all in the path names. // The branch information is all in the path names.
scheme: []string{"https", "http", "svn", "svn+ssh"}, scheme: []string{"https", "http", "svn", "svn+ssh"},
pingCmd: "info {scheme}://{repo}", pingCmd: "info {scheme}://{repo}",
remoteRepo: svnRemoteRepo,
}
func svnRemoteRepo(vcsSvn *vcsCmd, rootDir string) (remoteRepo string, err error) {
outb, err := vcsSvn.runOutput(rootDir, "info")
if err != nil {
return "", err
}
out := string(outb)
// Expect:
// ...
// Repository Root: <URL>
// ...
i := strings.Index(out, "\nRepository Root: ")
if i < 0 {
return "", fmt.Errorf("unable to parse output of svn info")
}
out = out[i+len("\nRepository Root: "):]
i = strings.Index(out, "\n")
if i < 0 {
return "", fmt.Errorf("unable to parse output of svn info")
}
out = out[:i]
return strings.TrimSpace(string(out)), nil
} }
func (v *vcsCmd) String() string { func (v *vcsCmd) String() string {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment