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

Commit 60e5c84

Browse files
committed
fix(status): concurrent BasicStatus creation
This change adds concurrent BasicStatus creation, maintaining the order of status output.
1 parent 062d2d0 commit 60e5c84

File tree

1 file changed

+99
-59
lines changed

1 file changed

+99
-59
lines changed

cmd/dep/status.go

+99-59
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"io/ioutil"
1414
"log"
1515
"sort"
16+
"sync"
1617
"text/tabwriter"
1718

1819
"github.com/golang/dep"
@@ -362,82 +363,121 @@ func runStatusAll(ctx *dep.Ctx, out outputter, p *dep.Project, sm gps.SourceMana
362363

363364
logger.Println("Checking upstream projects:")
364365

366+
// BasicStatus channel to collect all the BasicStatus
367+
bsCh := make(chan *BasicStatus, len(slp))
368+
369+
// Error channel to collect all the errors
370+
errorCh := make(chan error, len(slp))
371+
372+
var wg sync.WaitGroup
373+
365374
for i, proj := range slp {
375+
wg.Add(1)
366376
logger.Printf("(%d/%d) %s\n", i+1, len(slp), proj.Ident().ProjectRoot)
367377

368-
bs := BasicStatus{
369-
ProjectRoot: string(proj.Ident().ProjectRoot),
370-
PackageCount: len(proj.Packages()),
371-
}
378+
go func(proj gps.LockedProject) {
379+
defer wg.Done()
372380

373-
// Get children only for specific outputers
374-
// in order to avoid slower status process
375-
switch out.(type) {
376-
case *dotOutput:
377-
ptr, err := sm.ListPackages(proj.Ident(), proj.Version())
378-
379-
if err != nil {
380-
return digestMismatch, hasMissingPkgs, errors.Wrapf(err, "analysis of %s package failed", proj.Ident().ProjectRoot)
381+
bs := BasicStatus{
382+
ProjectRoot: string(proj.Ident().ProjectRoot),
383+
PackageCount: len(proj.Packages()),
381384
}
382385

383-
prm, _ := ptr.ToReachMap(true, false, false, nil)
384-
bs.Children = prm.FlattenFn(paths.IsStandardImportPath)
385-
}
386+
// Get children only for specific outputers
387+
// in order to avoid slower status process
388+
switch out.(type) {
389+
case *dotOutput:
390+
ptr, err := sm.ListPackages(proj.Ident(), proj.Version())
386391

387-
// Split apart the version from the lock into its constituent parts
388-
switch tv := proj.Version().(type) {
389-
case gps.UnpairedVersion:
390-
bs.Version = tv
391-
case gps.Revision:
392-
bs.Revision = tv
393-
case gps.PairedVersion:
394-
bs.Version = tv.Unpair()
395-
bs.Revision = tv.Revision()
396-
}
392+
if err != nil {
393+
errorCh <- err
394+
}
397395

398-
// Check if the manifest has an override for this project. If so,
399-
// set that as the constraint.
400-
if pp, has := p.Manifest.Ovr[proj.Ident().ProjectRoot]; has && pp.Constraint != nil {
401-
bs.hasOverride = true
402-
bs.Constraint = pp.Constraint
403-
} else {
404-
bs.Constraint = gps.Any()
405-
for _, c := range cm[bs.ProjectRoot] {
406-
bs.Constraint = c.Intersect(bs.Constraint)
396+
prm, _ := ptr.ToReachMap(true, false, false, nil)
397+
bs.Children = prm.FlattenFn(paths.IsStandardImportPath)
398+
}
399+
400+
// Split apart the version from the lock into its constituent parts
401+
switch tv := proj.Version().(type) {
402+
case gps.UnpairedVersion:
403+
bs.Version = tv
404+
case gps.Revision:
405+
bs.Revision = tv
406+
case gps.PairedVersion:
407+
bs.Version = tv.Unpair()
408+
bs.Revision = tv.Revision()
407409
}
408-
}
409410

410-
// Only if we have a non-rev and non-plain version do/can we display
411-
// anything wrt the version's updateability.
412-
if bs.Version != nil && bs.Version.Type() != gps.IsVersion {
413-
c, has := p.Manifest.Constraints[proj.Ident().ProjectRoot]
414-
if !has {
415-
c.Constraint = gps.Any()
411+
// Check if the manifest has an override for this project. If so,
412+
// set that as the constraint.
413+
if pp, has := p.Manifest.Ovr[proj.Ident().ProjectRoot]; has && pp.Constraint != nil {
414+
bs.hasOverride = true
415+
bs.Constraint = pp.Constraint
416+
} else {
417+
bs.Constraint = gps.Any()
418+
for _, c := range cm[bs.ProjectRoot] {
419+
bs.Constraint = c.Intersect(bs.Constraint)
420+
}
416421
}
417-
// TODO: This constraint is only the constraint imposed by the
418-
// current project, not by any transitive deps. As a result,
419-
// transitive project deps will always show "any" here.
420-
bs.Constraint = c.Constraint
421-
422-
vl, err := sm.ListVersions(proj.Ident())
423-
if err == nil {
424-
gps.SortPairedForUpgrade(vl)
425-
426-
for _, v := range vl {
427-
// Because we've sorted the version list for
428-
// upgrade, the first version we encounter that
429-
// matches our constraint will be what we want.
430-
if c.Constraint.Matches(v) {
431-
bs.Latest = v.Revision()
432-
break
422+
423+
// Only if we have a non-rev and non-plain version do/can we display
424+
// anything wrt the version's updateability.
425+
if bs.Version != nil && bs.Version.Type() != gps.IsVersion {
426+
c, has := p.Manifest.Constraints[proj.Ident().ProjectRoot]
427+
if !has {
428+
c.Constraint = gps.Any()
429+
}
430+
// TODO: This constraint is only the constraint imposed by the
431+
// current project, not by any transitive deps. As a result,
432+
// transitive project deps will always show "any" here.
433+
bs.Constraint = c.Constraint
434+
435+
vl, err := sm.ListVersions(proj.Ident())
436+
if err == nil {
437+
gps.SortPairedForUpgrade(vl)
438+
439+
for _, v := range vl {
440+
// Because we've sorted the version list for
441+
// upgrade, the first version we encounter that
442+
// matches our constraint will be what we want.
443+
if c.Constraint.Matches(v) {
444+
bs.Latest = v.Revision()
445+
break
446+
}
433447
}
434448
}
435449
}
436-
}
437450

438-
out.BasicLine(&bs)
451+
bsCh <- &bs
452+
453+
}(proj)
439454
}
455+
456+
wg.Wait()
457+
close(bsCh)
458+
close(errorCh)
440459
logger.Println()
460+
461+
if len(errorCh) > 0 {
462+
for err := range errorCh {
463+
ctx.Err.Println(err.Error())
464+
}
465+
ctx.Err.Println()
466+
}
467+
468+
// A map of ProjectRoot and *BasicStatus. This is used in maintain the
469+
// order of BasicStatus in output by collecting all the BasicStatus and
470+
// then using them in order.
471+
bsMap := make(map[string]*BasicStatus)
472+
for bs := range bsCh {
473+
bsMap[bs.ProjectRoot] = bs
474+
}
475+
476+
// Use the collected BasicStatus in outputter
477+
for _, proj := range slp {
478+
out.BasicLine(bsMap[string(proj.Ident().ProjectRoot)])
479+
}
480+
441481
out.BasicFooter()
442482

443483
return digestMismatch, hasMissingPkgs, nil

0 commit comments

Comments
 (0)