Skip to content
This repository was archived by the owner on Sep 9, 2020. It is now read-only.

Commit a42708e

Browse files
authored
Merge pull request #641 from ibrasho-forks/symlink-project-roots-changes
Handling symlinks as project root
2 parents 708b53d + 13f512f commit a42708e

File tree

11 files changed

+336
-284
lines changed

11 files changed

+336
-284
lines changed

FAQ.md

+9-6
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ Overrides are also discussed with some visuals in [the gps docs](https://github.
167167
Sometimes the revision specified in the lock file is no longer valid. There are a few
168168
ways this can occur:
169169

170-
* When you generated the lock file, you had an unpushed commit in your local copy of package X's repository in your GOPATH. (This case will be going away soon)
170+
* When you generated the lock file, you had an unpushed commit in your local copy of package X's repository in your `GOPATH`. (This case will be going away soon)
171171
* After generating the lock file, new commits were force pushed to package X's repository, causing the commit revision in your lock file to no longer exist.
172172

173173
To troubleshoot, you can revert dep's changes to your lock, and then run `dep ensure -v -n`.
@@ -255,14 +255,17 @@ There's another major performance issue that's much harder - the process of pick
255255

256256
## How does `dep` handle symbolic links?
257257

258-
> because we're not crazy people who delight in inviting chaos into our lives, we need to work within one GOPATH at a time.
258+
> because we're not crazy people who delight in inviting chaos into our lives, we need to work within one `GOPATH` at a time.
259259
-[@sdboyer in #247](https://github.com/golang/dep/pull/247#issuecomment-284181879)
260260

261-
Out of convenience, one might create a symlink to a directory within their `GOPATH`, e.g. `ln -s ~/go/src/github.com/golang/dep dep`. When `dep` is invoked it will resolve the current working directory accordingly:
261+
Out of convenience, one might create a symlink to a directory within their `GOPATH/src`, e.g. `ln -s ~/go/src/github.com/user/awesome-project ~/Code/awesome-project`.
262262

263-
- If the cwd is a symlink outside a `GOPATH` and links to directory within a `GOPATH`, or vice versa, `dep` chooses whichever path is within the `GOPATH`. If neither path is within a `GOPATH`, `dep` produces an error.
264-
- If both the cwd and resolved path are in the same `GOPATH`, an error is thrown since the users intentions and expectations can't be accurately deduced.
265-
- If the symlink is within a `GOPATH` and the real path is within a *different* `GOPATH` - an error is thrown.
263+
When `dep` is invoked with a project root that is a symlink, it will be resolved according to the following rules:
264+
265+
- If the symlink is outside `GOPATH` and links to a directory within a `GOPATH`, or vice versa, then `dep` will choose whichever path is within `GOPATH`.
266+
- If the symlink is within a `GOPATH` and the resolved path is within a *different* `GOPATH`, then an error is thrown.
267+
- If both the symlink and the resolved path are in the same `GOPATH`, then an error is thrown.
268+
- If neither the symlink nor the resolved path are in a `GOPATH`, then an error is thrown.
266269

267270
This is the only symbolic link support that `dep` really intends to provide. In keeping with the general practices of the `go` tool, `dep` tends to either ignore symlinks (when walking) or copy the symlink itself, depending on the filesystem operation being performed.
268271

cmd/dep/ensure.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ func (cmd *ensureCommand) Run(ctx *dep.Ctx, args []string) error {
124124
if ctx.Verbose {
125125
params.TraceLogger = ctx.Err
126126
}
127-
params.RootPackageTree, err = pkgtree.ListPackages(p.AbsRoot, string(p.ImportRoot))
127+
128+
params.RootPackageTree, err = pkgtree.ListPackages(p.ResolvedAbsRoot, string(p.ImportRoot))
128129
if err != nil {
129130
return errors.Wrap(err, "ensure ListPackage for project")
130131
}

cmd/dep/hash_in.go

+1-6
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,7 @@ func (hashinCommand) Run(ctx *dep.Ctx, args []string) error {
3737
defer sm.Release()
3838

3939
params := p.MakeParams()
40-
cpr, err := ctx.SplitAbsoluteProjectRoot(p.AbsRoot)
41-
if err != nil {
42-
return errors.Wrap(err, "determineProjectRoot")
43-
}
44-
45-
params.RootPackageTree, err = pkgtree.ListPackages(p.AbsRoot, cpr)
40+
params.RootPackageTree, err = pkgtree.ListPackages(p.ResolvedAbsRoot, string(p.ImportRoot))
4641
if err != nil {
4742
return errors.Wrap(err, "gps.ListPackages")
4843
}

cmd/dep/init.go

+26-13
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,17 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
7777
}
7878
}
7979

80+
var err error
81+
p := new(dep.Project)
82+
if err = p.SetRoot(root); err != nil {
83+
return errors.Wrap(err, "NewProject")
84+
}
85+
86+
ctx.GOPATH, err = ctx.DetectProjectGOPATH(p)
87+
if err != nil {
88+
return errors.Wrapf(err, "ctx.DetectProjectGOPATH")
89+
}
90+
8091
mf := filepath.Join(root, dep.ManifestName)
8192
lf := filepath.Join(root, dep.LockName)
8293
vpath := filepath.Join(root, "vendor")
@@ -98,11 +109,13 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
98109
return errors.Errorf("invalid state: manifest %q does not exist, but lock %q does", mf, lf)
99110
}
100111

101-
cpr, err := ctx.SplitAbsoluteProjectRoot(root)
112+
ip, err := ctx.SplitAbsoluteProjectRoot(root)
102113
if err != nil {
103114
return errors.Wrap(err, "determineProjectRoot")
104115
}
105-
pkgT, directDeps, err := getDirectDependencies(root, cpr)
116+
p.ImportRoot = gps.ProjectRoot(ip)
117+
118+
pkgT, directDeps, err := getDirectDependencies(p)
106119
if err != nil {
107120
return err
108121
}
@@ -115,12 +128,12 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
115128

116129
// Initialize with imported data, then fill in the gaps using the GOPATH
117130
rootAnalyzer := newRootAnalyzer(cmd.skipTools, ctx, directDeps, sm)
118-
m, l, err := rootAnalyzer.InitializeRootManifestAndLock(root, gps.ProjectRoot(cpr))
131+
p.Manifest, p.Lock, err = rootAnalyzer.InitializeRootManifestAndLock(root, p.ImportRoot)
119132
if err != nil {
120133
return err
121134
}
122135
gs := newGopathScanner(ctx, directDeps, sm)
123-
err = gs.InitializeRootManifestAndLock(m, l)
136+
err = gs.InitializeRootManifestAndLock(p.Manifest, p.Lock)
124137
if err != nil {
125138
return err
126139
}
@@ -130,8 +143,8 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
130143
params := gps.SolveParameters{
131144
RootDir: root,
132145
RootPackageTree: pkgT,
133-
Manifest: m,
134-
Lock: l,
146+
Manifest: p.Manifest,
147+
Lock: p.Lock,
135148
ProjectAnalyzer: rootAnalyzer,
136149
}
137150

@@ -149,10 +162,10 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
149162
handleAllTheFailuresOfTheWorld(err)
150163
return err
151164
}
152-
l = dep.LockFromSolution(soln)
165+
p.Lock = dep.LockFromSolution(soln)
153166

154-
rootAnalyzer.FinalizeRootManifestAndLock(m, l)
155-
gs.FinalizeRootManifestAndLock(m, l)
167+
rootAnalyzer.FinalizeRootManifestAndLock(p.Manifest, p.Lock)
168+
gs.FinalizeRootManifestAndLock(p.Manifest, p.Lock)
156169

157170
// Run gps.Prepare with appropriate constraint solutions from solve run
158171
// to generate the final lock memo.
@@ -161,7 +174,7 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
161174
return errors.Wrap(err, "prepare solver")
162175
}
163176

164-
l.SolveMeta.InputsDigest = s.HashInputs()
177+
p.Lock.SolveMeta.InputsDigest = s.HashInputs()
165178

166179
// Pass timestamp (yyyyMMddHHmmss format) as suffix to backup name.
167180
vendorbak, err := dep.BackupVendor(vpath, time.Now().Format("20060102150405"))
@@ -172,7 +185,7 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
172185
ctx.Err.Printf("Old vendor backed up to %v", vendorbak)
173186
}
174187

175-
sw, err := dep.NewSafeWriter(m, nil, l, dep.VendorAlways)
188+
sw, err := dep.NewSafeWriter(p.Manifest, nil, p.Lock, dep.VendorAlways)
176189
if err != nil {
177190
return err
178191
}
@@ -184,8 +197,8 @@ func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error {
184197
return nil
185198
}
186199

187-
func getDirectDependencies(root, cpr string) (pkgtree.PackageTree, map[string]bool, error) {
188-
pkgT, err := pkgtree.ListPackages(root, cpr)
200+
func getDirectDependencies(p *dep.Project) (pkgtree.PackageTree, map[string]bool, error) {
201+
pkgT, err := pkgtree.ListPackages(p.ResolvedAbsRoot, string(p.ImportRoot))
189202
if err != nil {
190203
return pkgtree.PackageTree{}, nil, errors.Wrap(err, "gps.ListPackages")
191204
}

cmd/dep/main.go

+22-21
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ func (c *Config) Run() (exitCode int) {
8383
},
8484
}
8585

86+
outLogger := log.New(c.Stdout, "", 0)
8687
errLogger := log.New(c.Stderr, "", 0)
88+
8789
usage := func() {
8890
errLogger.Println("dep is a tool for managing dependencies for Go projects")
8991
errLogger.Println()
@@ -142,19 +144,15 @@ func (c *Config) Run() (exitCode int) {
142144
return
143145
}
144146

145-
// Set up the dep context.
147+
// Set up dep context.
146148
ctx := &dep.Ctx{
147-
Out: log.New(c.Stdout, "", 0),
149+
Out: outLogger,
148150
Err: errLogger,
149151
Verbose: *verbose,
150152
}
151-
gopaths := filepath.SplitList(getEnv(c.Env, "GOPATH"))
152-
err := ctx.SetPaths(c.WorkingDir, gopaths...)
153-
if err != nil {
154-
errLogger.Printf("%q not in any GOPATH: %s\n", c.WorkingDir, err)
155-
exitCode = 1
156-
return
157-
}
153+
154+
GOPATHS := filepath.SplitList(getEnv(c.Env, "GOPATH"))
155+
ctx.SetPaths(c.WorkingDir, GOPATHS...)
158156

159157
// Run the command with the post-flag-processing args.
160158
if err := cmd.Run(ctx, fs.Args()); err != nil {
@@ -174,18 +172,6 @@ func (c *Config) Run() (exitCode int) {
174172
return
175173
}
176174

177-
// getEnv returns the last instance of the environment variable.
178-
func getEnv(env []string, key string) string {
179-
pre := key + "="
180-
for i := len(env) - 1; i >= 0; i-- {
181-
v := env[i]
182-
if strings.HasPrefix(v, pre) {
183-
return strings.TrimPrefix(v, pre)
184-
}
185-
}
186-
return ""
187-
}
188-
189175
func resetUsage(logger *log.Logger, fs *flag.FlagSet, name, args, longHelp string) {
190176
var (
191177
hasFlags bool
@@ -241,3 +227,18 @@ func parseArgs(args []string) (cmdName string, printCmdUsage bool, exit bool) {
241227
}
242228
return cmdName, printCmdUsage, exit
243229
}
230+
231+
// getEnv returns the last instance of an environment variable.
232+
func getEnv(env []string, key string) string {
233+
for i := len(env) - 1; i >= 0; i-- {
234+
v := env[i]
235+
kv := strings.SplitN(v, "=", 2)
236+
if kv[0] == key {
237+
if len(kv) > 1 {
238+
return kv[1]
239+
}
240+
return ""
241+
}
242+
}
243+
return ""
244+
}

cmd/dep/prune.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func (cmd *pruneCommand) Run(ctx *dep.Ctx, args []string) error {
5050

5151
// While the network churns on ListVersions() requests, statically analyze
5252
// code from the current project.
53-
ptree, err := pkgtree.ListPackages(p.AbsRoot, string(p.ImportRoot))
53+
ptree, err := pkgtree.ListPackages(p.ResolvedAbsRoot, string(p.ImportRoot))
5454
if err != nil {
5555
return errors.Wrap(err, "analysis of local packages failed: %v")
5656
}

cmd/dep/status.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ type dotOutput struct {
162162
func (out *dotOutput) BasicHeader() {
163163
out.g = new(graphviz).New()
164164

165-
ptree, _ := pkgtree.ListPackages(out.p.AbsRoot, string(out.p.ImportRoot))
165+
ptree, _ := pkgtree.ListPackages(out.p.ResolvedAbsRoot, string(out.p.ImportRoot))
166166
prm, _ := ptree.ToReachMap(true, false, false, nil)
167167

168168
out.g.createNode(string(out.p.ImportRoot), "", prm.FlattenFn(paths.IsStandardImportPath))
@@ -263,7 +263,7 @@ func runStatusAll(ctx *dep.Ctx, out outputter, p *dep.Project, sm gps.SourceMana
263263

264264
// While the network churns on ListVersions() requests, statically analyze
265265
// code from the current project.
266-
ptree, err := pkgtree.ListPackages(p.AbsRoot, string(p.ImportRoot))
266+
ptree, err := pkgtree.ListPackages(p.ResolvedAbsRoot, string(p.ImportRoot))
267267
if err != nil {
268268
return digestMismatch, hasMissingPkgs, errors.Errorf("analysis of local packages failed: %v", err)
269269
}

cmd/dep/testdata/harness_tests/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ for example, it can be completely left out.
6969

7070
The test procedure is as follows:
7171

72-
1. Create a unique temporary directory (TMPDIR) as the test run's GOPATH
72+
1. Create a unique temporary directory (TMPDIR) as the test run's `GOPATH`
7373
2. Create `$TMPDIR/src/github.com/golang/notexist` as the current project
7474
3. Copy the contents of `initial` input directory to the project
7575
4. Fetch the repos and versions in `gopath-initial` into `$TMPDIR/src` directory

0 commit comments

Comments
 (0)