Skip to content

Commit

Permalink
cmd/go: allow nested VCS repositories when preparing build stamp
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jay Conrod committed Oct 15, 2021
1 parent 22951fb commit a17b2e8
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 17 deletions.
3 changes: 2 additions & 1 deletion src/cmd/go/internal/get/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,8 @@ func downloadPackage(p *load.Package) error {

if p.Internal.Build.SrcRoot != "" {
// 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 {
return err
}
Expand Down
7 changes: 4 additions & 3 deletions src/cmd/go/internal/load/pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -2318,8 +2318,9 @@ func (p *Package) setBuildInfo() {
var repoDir string
var vcsCmd *vcs.Cmd
var err error
const allowNesting = true
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) {
setVCSError(err)
return
Expand All @@ -2338,7 +2339,7 @@ func (p *Package) setBuildInfo() {
// repository. vcs.FromDir allows nested Git repositories, but nesting
// is not allowed for other VCS tools. The current directory may be outside
// p.Module.Dir when a workspace is used.
pkgRepoDir, _, err := vcs.FromDir(p.Dir, "")
pkgRepoDir, _, err := vcs.FromDir(p.Dir, "", allowNesting)
if err != nil {
setVCSError(err)
return
Expand All @@ -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))
return
}
modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "")
modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "", allowNesting)
if err != nil {
setVCSError(err)
return
Expand Down
11 changes: 8 additions & 3 deletions src/cmd/go/internal/vcs/vcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ type vcsPath struct {
// version control system and code repository to use.
// If no repository is found, FromDir returns an error
// 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.
dir = filepath.Clean(dir)
if srcRoot != "" {
Expand All @@ -617,11 +617,16 @@ func FromDir(dir, srcRoot string) (repoDir string, vcsCmd *Cmd, err error) {
for len(dir) > len(srcRoot) {
for _, vcs := range vcsList {
if _, err := os.Stat(filepath.Join(dir, "."+vcs.Cmd)); err == nil {
// Record first VCS we find, but keep looking,
// to detect mistakes like one kind of VCS inside another.
// Record first VCS we find.
// 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 {
vcsCmd = vcs
repoDir = dir
if allowNesting {
return repoDir, vcsCmd, nil
}
continue
}
// Allow .git inside .git, which can arise due to submodules.
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/go/internal/vcs/vcs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ func TestFromDir(t *testing.T) {
}

wantRepoDir := filepath.Dir(dir)
gotRepoDir, gotVCS, err := FromDir(dir, tempDir)
gotRepoDir, gotVCS, err := FromDir(dir, tempDir, false)
if err != nil {
t.Errorf("FromDir(%q, %q): %v", dir, tempDir, err)
continue
Expand Down
19 changes: 10 additions & 9 deletions src/cmd/go/testdata/script/version_buildvcs_nested.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[!exec:git] skip
[!exec:hg] skip
[short] skip
env GOFLAGS=-n

# Create a root module in a root Git repository.
Expand All @@ -8,25 +9,25 @@ cd root
go mod init example.com/root
exec git init

# It's an error to build a package from a nested Mercurial repository
# without -buildvcs=false, even if the package is in a separate module.
# Nesting repositories in parent directories are ignored, as the current
# 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
cd hgsub
exec hg init
cp ../../main.go main.go
! go build
stderr '^error obtaining VCS status: directory ".*hgsub" uses hg, but parent ".*root" uses git$'
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$'
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.$'
go build -buildvcs=false
go mod init example.com/root/hgsub
go build
cd ..

# 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
# root directory. However, unlike with other VCS, it's okay for a Git repository
# to be nested within another Git repository. This happens with submodules.
# root directory.
mkdir gitsub
cd gitsub
exec git init
Expand Down

0 comments on commit a17b2e8

Please sign in to comment.