1
0
mirror of https://github.com/golang/go synced 2024-11-23 06:40:05 -07:00

cmd/go: allow nested VCS repositories when preparing build stamp

The go command no longer reports an error when invoked in a repository
nested inside another. This check is still used by 'go get' in GOPATH
mode when locating a repository, but it's not needed when preparing
the build stamp.

Fixes #49004

Change-Id: I4ed4dcc04174d2d42da8651d47e52ab1d7d66e35
Reviewed-on: https://go-review.googlesource.com/c/go/+/356309
Trust: Jay Conrod <jayconrod@google.com>
Run-TryBot: Jay Conrod <jayconrod@google.com>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
This commit is contained in:
Jay Conrod 2021-10-15 11:57:58 -07:00
parent 22951fbc89
commit a17b2e8655
5 changed files with 25 additions and 17 deletions

View File

@ -446,7 +446,8 @@ func downloadPackage(p *load.Package) error {
if p.Internal.Build.SrcRoot != "" { if p.Internal.Build.SrcRoot != "" {
// Directory exists. Look for checkout along path to src. // Directory exists. Look for checkout along path to src.
repoDir, vcsCmd, err = vcs.FromDir(p.Dir, p.Internal.Build.SrcRoot) const allowNesting = false
repoDir, vcsCmd, err = vcs.FromDir(p.Dir, p.Internal.Build.SrcRoot, allowNesting)
if err != nil { if err != nil {
return err return err
} }

View File

@ -2318,8 +2318,9 @@ func (p *Package) setBuildInfo() {
var repoDir string var repoDir string
var vcsCmd *vcs.Cmd var vcsCmd *vcs.Cmd
var err error var err error
const allowNesting = true
if cfg.BuildBuildvcs && p.Module != nil && p.Module.Version == "" && !p.Standard { if cfg.BuildBuildvcs && p.Module != nil && p.Module.Version == "" && !p.Standard {
repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "") repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "", allowNesting)
if err != nil && !errors.Is(err, os.ErrNotExist) { if err != nil && !errors.Is(err, os.ErrNotExist) {
setVCSError(err) setVCSError(err)
return return
@ -2338,7 +2339,7 @@ func (p *Package) setBuildInfo() {
// repository. vcs.FromDir allows nested Git repositories, but nesting // repository. vcs.FromDir allows nested Git repositories, but nesting
// is not allowed for other VCS tools. The current directory may be outside // is not allowed for other VCS tools. The current directory may be outside
// p.Module.Dir when a workspace is used. // p.Module.Dir when a workspace is used.
pkgRepoDir, _, err := vcs.FromDir(p.Dir, "") pkgRepoDir, _, err := vcs.FromDir(p.Dir, "", allowNesting)
if err != nil { if err != nil {
setVCSError(err) setVCSError(err)
return return
@ -2347,7 +2348,7 @@ func (p *Package) setBuildInfo() {
setVCSError(fmt.Errorf("main package is in repository %q but current directory is in repository %q", pkgRepoDir, repoDir)) setVCSError(fmt.Errorf("main package is in repository %q but current directory is in repository %q", pkgRepoDir, repoDir))
return return
} }
modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "") modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "", allowNesting)
if err != nil { if err != nil {
setVCSError(err) setVCSError(err)
return return

View File

@ -603,7 +603,7 @@ type vcsPath struct {
// version control system and code repository to use. // version control system and code repository to use.
// If no repository is found, FromDir returns an error // If no repository is found, FromDir returns an error
// equivalent to os.ErrNotExist. // equivalent to os.ErrNotExist.
func FromDir(dir, srcRoot string) (repoDir string, vcsCmd *Cmd, err error) { func FromDir(dir, srcRoot string, allowNesting bool) (repoDir string, vcsCmd *Cmd, err error) {
// Clean and double-check that dir is in (a subdirectory of) srcRoot. // Clean and double-check that dir is in (a subdirectory of) srcRoot.
dir = filepath.Clean(dir) dir = filepath.Clean(dir)
if srcRoot != "" { if srcRoot != "" {
@ -617,11 +617,16 @@ func FromDir(dir, srcRoot string) (repoDir string, vcsCmd *Cmd, err error) {
for len(dir) > len(srcRoot) { for len(dir) > len(srcRoot) {
for _, vcs := range vcsList { for _, vcs := range vcsList {
if _, err := os.Stat(filepath.Join(dir, "."+vcs.Cmd)); err == nil { if _, err := os.Stat(filepath.Join(dir, "."+vcs.Cmd)); err == nil {
// Record first VCS we find, but keep looking, // Record first VCS we find.
// to detect mistakes like one kind of VCS inside another. // If allowNesting is false (as it is in GOPATH), keep looking for
// repositories in parent directories and report an error if one is
// found to mitigate VCS injection attacks.
if vcsCmd == nil { if vcsCmd == nil {
vcsCmd = vcs vcsCmd = vcs
repoDir = dir repoDir = dir
if allowNesting {
return repoDir, vcsCmd, nil
}
continue continue
} }
// Allow .git inside .git, which can arise due to submodules. // Allow .git inside .git, which can arise due to submodules.

View File

@ -233,7 +233,7 @@ func TestFromDir(t *testing.T) {
} }
wantRepoDir := filepath.Dir(dir) wantRepoDir := filepath.Dir(dir)
gotRepoDir, gotVCS, err := FromDir(dir, tempDir) gotRepoDir, gotVCS, err := FromDir(dir, tempDir, false)
if err != nil { if err != nil {
t.Errorf("FromDir(%q, %q): %v", dir, tempDir, err) t.Errorf("FromDir(%q, %q): %v", dir, tempDir, err)
continue continue

View File

@ -1,5 +1,6 @@
[!exec:git] skip [!exec:git] skip
[!exec:hg] skip [!exec:hg] skip
[short] skip
env GOFLAGS=-n env GOFLAGS=-n
# Create a root module in a root Git repository. # Create a root module in a root Git repository.
@ -8,25 +9,25 @@ cd root
go mod init example.com/root go mod init example.com/root
exec git init exec git init
# It's an error to build a package from a nested Mercurial repository # Nesting repositories in parent directories are ignored, as the current
# without -buildvcs=false, even if the package is in a separate module. # directory main package, and containing main module are in the same repository.
# This is an error in GOPATH mode (to prevent VCS injection), but for modules,
# we assume users have control over repositories they've checked out.
mkdir hgsub mkdir hgsub
cd hgsub cd hgsub
exec hg init exec hg init
cp ../../main.go main.go cp ../../main.go main.go
! go build ! go build
stderr '^error obtaining VCS status: directory ".*hgsub" uses hg, but parent ".*root" uses git$' stderr '^error obtaining VCS status: main module is in repository ".*root" but current directory is in repository ".*hgsub"$'
stderr '\tUse -buildvcs=false to disable VCS stamping.$' stderr '^\tUse -buildvcs=false to disable VCS stamping.$'
go mod init example.com/root/hgsub
! go build
stderr '^error obtaining VCS status: directory ".*hgsub" uses hg, but parent ".*root" uses git$'
go build -buildvcs=false go build -buildvcs=false
go mod init example.com/root/hgsub
go build
cd .. cd ..
# It's an error to build a package from a nested Git repository if the package # It's an error to build a package from a nested Git repository if the package
# is in a separate repository from the current directory or from the module # is in a separate repository from the current directory or from the module
# root directory. However, unlike with other VCS, it's okay for a Git repository # root directory.
# to be nested within another Git repository. This happens with submodules.
mkdir gitsub mkdir gitsub
cd gitsub cd gitsub
exec git init exec git init