diff options
Diffstat (limited to 'src/cmd/go/vcs.go')
| -rw-r--r-- | src/cmd/go/vcs.go | 45 |
1 files changed, 40 insertions, 5 deletions
diff --git a/src/cmd/go/vcs.go b/src/cmd/go/vcs.go index 39881a6dc..22d5ebc24 100644 --- a/src/cmd/go/vcs.go +++ b/src/cmd/go/vcs.go @@ -91,7 +91,7 @@ var vcsGit = &vcsCmd{ cmd: "git", createCmd: "clone {repo} {dir}", - downloadCmd: "fetch", + downloadCmd: "pull --ff-only", tagCmd: []tagCmd{ // tags/xxx matches a git tag named xxx @@ -102,7 +102,7 @@ var vcsGit = &vcsCmd{ {"show-ref tags/{tag} origin/{tag}", `((?:tags|origin)/\S+)$`}, }, tagSyncCmd: "checkout {tag}", - tagSyncDefault: "checkout origin/master", + tagSyncDefault: "checkout master", scheme: []string{"git", "https", "http", "git+ssh"}, pingCmd: "ls-remote {scheme}://{repo}", @@ -223,9 +223,36 @@ func (v *vcsCmd) create(dir, repo string) error { // download downloads any new changes for the repo in dir. func (v *vcsCmd) download(dir string) error { + if err := v.fixDetachedHead(dir); err != nil { + return err + } return v.run(dir, v.downloadCmd) } +// fixDetachedHead switches a Git repository in dir from a detached head to the master branch. +// Go versions before 1.2 downloaded Git repositories in an unfortunate way +// that resulted in the working tree state being on a detached head. +// That meant the repository was not usable for normal Git operations. +// Go 1.2 fixed that, but we can't pull into a detached head, so if this is +// a Git repository we check for being on a detached head and switch to the +// real branch, almost always called "master". +// TODO(dsymonds): Consider removing this for Go 1.3. +func (v *vcsCmd) fixDetachedHead(dir string) error { + if v != vcsGit { + return nil + } + + // "git symbolic-ref HEAD" succeeds iff we are not on a detached head. + if err := v.runVerboseOnly(dir, "symbolic-ref HEAD"); err == nil { + // not on a detached head + return nil + } + if buildV { + log.Printf("%s on detached head; repairing", dir) + } + return v.run(dir, "checkout master") +} + // tags returns the list of available tags for the repo in dir. func (v *vcsCmd) tags(dir string) ([]string, error) { var tags []string @@ -294,6 +321,7 @@ func vcsForDir(p *Package) (vcs *vcsCmd, root string, err error) { return nil, "", fmt.Errorf("directory %q is outside source root %q", dir, srcRoot) } + origDir := dir for len(dir) > len(srcRoot) { for _, vcs := range vcsList { if fi, err := os.Stat(filepath.Join(dir, "."+vcs.cmd)); err == nil && fi.IsDir() { @@ -310,7 +338,7 @@ func vcsForDir(p *Package) (vcs *vcsCmd, root string, err error) { dir = ndir } - return nil, "", fmt.Errorf("directory %q is not using a known version control system", dir) + return nil, "", fmt.Errorf("directory %q is not using a known version control system", origDir) } // repoRoot represents a version control system, a repo, and a root of @@ -442,7 +470,11 @@ func repoRootForImportDynamic(importPath string) (*repoRoot, error) { return nil, fmt.Errorf("http/https fetch: %v", err) } defer body.Close() - metaImport, err := matchGoImport(parseMetaGoImports(body), importPath) + imports, err := parseMetaGoImports(body) + if err != nil { + return nil, fmt.Errorf("parsing %s: %v", importPath, err) + } + metaImport, err := matchGoImport(imports, importPath) if err != nil { if err != errNoMatch { return nil, fmt.Errorf("parse %s: %v", urlStr, err) @@ -467,7 +499,10 @@ func repoRootForImportDynamic(importPath string) (*repoRoot, error) { if err != nil { return nil, fmt.Errorf("fetch %s: %v", urlStr, err) } - imports := parseMetaGoImports(body) + imports, err := parseMetaGoImports(body) + if err != nil { + return nil, fmt.Errorf("parsing %s: %v", importPath, err) + } if len(imports) == 0 { return nil, fmt.Errorf("fetch %s: no go-import meta tag", urlStr) } |
