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

Commit 1b8edb3

Browse files
committed
First bits of -add path
1 parent 8b6ac9a commit 1b8edb3

File tree

2 files changed

+86
-15
lines changed

2 files changed

+86
-15
lines changed

cmd/dep/ensure.go

+73-15
Original file line numberDiff line numberDiff line change
@@ -138,17 +138,17 @@ func (cmd *ensureCommand) Run(ctx *dep.Ctx, args []string) error {
138138
return errors.New("cannot pass both -add and -update")
139139
}
140140

141-
if cmd.update && cmd.vendorOnly {
142-
return errors.New("-vendor-only makes -update a no-op; cannot pass them together")
143-
}
144-
145-
if cmd.add && cmd.vendorOnly {
146-
return errors.New("-vendor-only makes -add a no-op; cannot pass them together")
147-
}
148-
149-
if cmd.vendorOnly && cmd.noVendor {
150-
// TODO(sdboyer) can't think of anything not snarky right now
151-
return errors.New("really?")
141+
if cmd.vendorOnly {
142+
if cmd.update {
143+
return errors.New("-vendor-only makes -update a no-op; cannot pass them together")
144+
}
145+
if cmd.add {
146+
return errors.New("-vendor-only makes -add a no-op; cannot pass them together")
147+
}
148+
if cmd.noVendor {
149+
// TODO(sdboyer) can't think of anything not snarky right now
150+
return errors.New("really?")
151+
}
152152
}
153153

154154
p, err := ctx.LoadProject("")
@@ -263,7 +263,6 @@ func (cmd *ensureCommand) runDefault(ctx *dep.Ctx, args []string, p *dep.Project
263263
// that "verification" is supposed to look like (#121); in the meantime,
264264
// we unconditionally write out vendor/ so that `dep ensure`'s behavior
265265
// is maximally compatible with what it will eventually become.
266-
// vendor doesn't exist at all; be helpful and write it.
267266
err := sw.Prepare(nil, p.Lock, p.Lock, dep.VendorAlways)
268267
if err != nil {
269268
return err
@@ -308,7 +307,8 @@ func (cmd *ensureCommand) runUpdate(ctx *dep.Ctx, args []string, p *dep.Project,
308307
// run a straight `dep ensure` before updating. This is handholding the
309308
// user a bit, but the extra effort required is minimal, and it ensures the
310309
// user is isolating variables in the event of solve problems (was it the
311-
// existing changes, or the -update that caused the problem?).
310+
// "pending" changes, or the -update that caused the problem?).
311+
// TODO(sdboyer) reduce this to a warning?
312312
if bytes.Equal(p.Lock.InputHash(), solver.HashInputs()) {
313313
return errors.Errorf("%s and %s are out of sync. run a plain `dep ensure` to resync them before attempting an -update.", dep.ManifestName, dep.LockName)
314314
}
@@ -328,15 +328,18 @@ func (cmd *ensureCommand) runUpdate(ctx *dep.Ctx, args []string, p *dep.Project,
328328
pc, err := getProjectConstraint(arg, sm)
329329
if err != nil {
330330
// TODO(sdboyer) return all errors, not just the first one we encounter
331-
// TODO(sdboyer) ensure these errors are contextualized in a
332-
// sensible way for -update
331+
// TODO(sdboyer) ensure these errors are contextualized in a sensible way for -update
333332
return err
334333
}
335334

336335
if !p.Lock.HasProjectWithRoot(pc.Ident.ProjectRoot) {
337336
return errors.Errorf("%s is not present in %s, cannot -update it", pc.Ident.ProjectRoot, dep.LockName)
338337
}
339338

339+
if p.Ident.Source != "" {
340+
return errors.Errorf("cannot specify alternate sources on -update (%s)")
341+
}
342+
340343
if !gps.IsAny(pc.Constraint) {
341344
// TODO(sdboyer) constraints should be allowed to allow solves that
342345
// target particular versions while remaining within declared constraints
@@ -370,6 +373,61 @@ func (cmd *ensureCommand) runUpdate(ctx *dep.Ctx, args []string, p *dep.Project,
370373
}
371374

372375
func (cmd *ensureCommand) runAdd(ctx *dep.Ctx, args []string, p *dep.Project, sm gps.SourceManager, params gps.SolveParameters) error {
376+
if len(args) == 0 {
377+
return errors.New("must specify at least one project or package to add")
378+
}
379+
380+
// Compare the hashes. If they're not equal, bail out and ask the user to
381+
// run a straight `dep ensure` before updating. This is handholding the
382+
// user a bit, but the extra effort required is minimal, and it ensures the
383+
// user is isolating variables in the event of solve problems (was it the
384+
// "pending" changes, or the -add that caused the problem?).
385+
// TODO(sdboyer) reduce this to a warning?
386+
if bytes.Equal(p.Lock.InputHash(), solver.HashInputs()) {
387+
return errors.Errorf("%s and %s are out of sync. run a plain `dep ensure` to resync them before attempting an -add.", dep.ManifestName, dep.LockName)
388+
}
389+
390+
rm, errmap := params.RootPackageTree.ToReachMap(true, true, false, p.Manifest.IgnoredPackages())
391+
// Having some problematic internal packages isn't cause for termination,
392+
// but the user needs to be warned.
393+
for fail := range errmap {
394+
internal.Logf("Warning: %s", fail)
395+
}
396+
397+
exmap := make(map[string]bool)
398+
exrmap := make(map[gps.ProjectRoot]bool)
399+
for _, ex := range append(rm.Flatten(false), p.Manifest.RequiredPackages()...) {
400+
exmap[ex] = true
401+
root, err := sm.DeduceProjectRoot(ex)
402+
if err != nil {
403+
// This should be essentially impossible to hit, as it entails that
404+
// we couldn't deduce the root for an import, but that some previous
405+
// solve run WAS able to deduce the root.
406+
return errors.Wrap(err, "could not deduce project root")
407+
}
408+
exrmap[root] = true
409+
}
410+
411+
for _, arg := range args {
412+
// TODO(sdboyer) return all errors, not just the first one we encounter
413+
// TODO(sdboyer) do these concurrently
414+
pc, err := getProjectConstraint(arg, sm)
415+
if err != nil {
416+
// TODO(sdboyer) ensure these errors are contextualized in a sensible way for -add
417+
return err
418+
}
419+
420+
inManifest := p.Manifest.HasConstraintsOn(pc.Ident.ProjectRoot)
421+
inImports := exrmap[pc.Ident.ProjectRoot]
422+
if inManifest && inImports {
423+
return errors.Errorf("%s is already in %s and the project's direct imports, nothing to add", pc.Ident.ProjectRoot, dep.ManifestName)
424+
}
425+
426+
err = sm.SyncSourceFor(pc.Ident)
427+
if err != nil {
428+
return errors.Wrap(err, "failed to fetch source for %s", pc.Ident.ProjectRoot)
429+
}
430+
}
373431
}
374432

375433
func applyEnsureArgs(args []string, overrides stringSlice, p *dep.Project, sm *gps.SourceMgr, params *gps.SolveParameters) error {

manifest.go

+13
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,19 @@ func (m *Manifest) IgnoredPackages() map[string]bool {
227227
return mp
228228
}
229229

230+
// HasConstraintsOn checks if the manifest contains either constraints or
231+
// overrides on the provided ProjectRoot.
232+
func (m *Manifest) HasConstraintsOn(root gps.ProjectRoot) bool {
233+
if _, has := m.Dependencies[root]; has {
234+
return true
235+
}
236+
if _, has := m.Ovr[root]; has {
237+
return true
238+
}
239+
240+
return false
241+
}
242+
230243
func (m *Manifest) RequiredPackages() map[string]bool {
231244
if len(m.Required) == 0 {
232245
return nil

0 commit comments

Comments
 (0)