dep: Allow explicitly setting the project root

This is potentially useful when working on projects that aren't compiled
by the standard toolchain (e.g., by Bazel), and thus don't need to live
within a GOPATH.

It also comports with the upcoming changes to do away with GOPATH.
This commit is contained in:
sam boyer 2018-06-04 16:55:40 -04:00
Родитель a6b1e89bb0
Коммит e7525a43b4
2 изменённых файлов: 82 добавлений и 7 удалений

Просмотреть файл

@ -38,6 +38,7 @@ type Ctx struct {
WorkingDir string // Where to execute.
GOPATH string // Selected Go path, containing WorkingDir.
GOPATHs []string // Other Go paths.
ExplicitRoot string // An explicitly-set path to use as the project root.
Out, Err *log.Logger // Required loggers.
Verbose bool // Enables more verbose logging.
DisableLocking bool // When set, no lock file will be created to protect against simultaneous dep processes.
@ -63,6 +64,8 @@ func (c *Ctx) SetPaths(wd string, GOPATHs ...string) error {
c.GOPATHs = append(c.GOPATHs, GOPATHs...)
c.ExplicitRoot = os.Getenv("DEP_PROJECT_ROOT")
return nil
}
@ -137,11 +140,15 @@ func (c *Ctx) LoadProject() (*Project, error) {
return nil, err
}
ip, err := c.ImportForAbs(p.AbsRoot)
if err != nil {
return nil, errors.Wrap(err, "root project import")
if c.ExplicitRoot != "" {
p.ImportRoot = gps.ProjectRoot(c.ExplicitRoot)
} else {
ip, err := c.ImportForAbs(p.AbsRoot)
if err != nil {
return nil, errors.Wrap(err, "root project import")
}
p.ImportRoot = gps.ProjectRoot(ip)
}
p.ImportRoot = gps.ProjectRoot(ip)
mp := filepath.Join(p.AbsRoot, ManifestName)
mf, err := os.Open(mp)
@ -202,9 +209,14 @@ func (c *Ctx) DetectProjectGOPATH(p *Project) (string, error) {
return "", errors.New("project AbsRoot and ResolvedAbsRoot must be set to detect GOPATH")
}
if c.ExplicitRoot != "" {
// If an explicit root is set, just use the first GOPATH in the list.
return c.GOPATHs[0], nil
}
pGOPATH, perr := c.detectGOPATH(p.AbsRoot)
// If p.AbsRoot is a not symlink, attempt to detect GOPATH for p.AbsRoot only.
// If p.AbsRoot is a not a symlink, attempt to detect GOPATH for p.AbsRoot only.
if equal, _ := fs.EquivalentPaths(p.AbsRoot, p.ResolvedAbsRoot); equal {
return pGOPATH, perr
}

Просмотреть файл

@ -152,6 +152,69 @@ func TestLoadProject(t *testing.T) {
}
}
func TestExplicitRootProject(t *testing.T) {
h := test.NewHelper(t)
defer h.Cleanup()
h.TempDir(filepath.Join("src", "test1", "sub"))
h.TempFile(filepath.Join("src", "test1", ManifestName), "")
h.TempFile(filepath.Join("src", "test1", LockName), `memo = "cdafe8641b28cd16fe025df278b0a49b9416859345d8b6ba0ace0272b74925ee"`)
h.TempDir(filepath.Join("src", "test2", "sub"))
h.TempFile(filepath.Join("src", "test2", ManifestName), "")
h.Setenv("DEP_PROJECT_ROOT", "github.com/user/module")
type tcase struct {
name string
lock bool
wd string
}
var testcases = []tcase{
{"direct", true, filepath.Join("src", "test1")},
{"ascending", true, filepath.Join("src", "test1", "sub")},
{"without lock", false, filepath.Join("src", "test2")},
{"ascending without lock", false, filepath.Join("src", "test2", "sub")},
}
tf := func(withGOPATH bool, tc tcase, t *testing.T) func(t *testing.T) {
return func(t *testing.T) {
ctx := &Ctx{
Out: discardLogger(),
Err: discardLogger(),
}
var err error
if withGOPATH {
err = ctx.SetPaths(h.Path(tc.wd), h.Path("."))
} else {
err = ctx.SetPaths(h.Path(tc.wd))
}
if err != nil {
t.Fatalf("%+v", err)
}
ctx.ExplicitRoot = "github.com/user/module"
p, err := ctx.LoadProject()
switch {
case err != nil:
t.Fatalf("%s: LoadProject failed: %+v", tc.wd, err)
case p.Manifest == nil:
t.Fatalf("%s: Manifest file didn't load", tc.wd)
case tc.lock && p.Lock == nil:
t.Fatalf("%s: Lock file didn't load", tc.wd)
case !tc.lock && p.Lock != nil:
t.Fatalf("%s: Non-existent Lock file loaded", tc.wd)
}
}
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
t.Run("within-GOPATH", tf(true, tc, t))
t.Run("outside-GOPATH", tf(false, tc, t))
})
}
}
func TestLoadProjectNotFoundErrors(t *testing.T) {
tg := test.NewHelper(t)
defer tg.Cleanup()
@ -313,9 +376,9 @@ func TestLoadProjectGopkgFilenames(t *testing.T) {
}
}
// TestCaseInsentitive is test for Windows. This should work even though set
// TestCaseInsensitive is test for Windows. This should work even though set
// difference letter cases in GOPATH.
func TestCaseInsentitiveGOPATH(t *testing.T) {
func TestCaseInsensitiveGOPATH(t *testing.T) {
if runtime.GOOS != "windows" {
t.Skip("skip this test on non-Windows")
}