Skip to content
This repository has been archived by the owner on Mar 6, 2020. It is now read-only.

Commit

Permalink
gb-vendor: parallelize dependencies download in rebuild
Browse files Browse the repository at this point in the history
  • Loading branch information
FiloSottile committed Jan 18, 2016
1 parent fd27784 commit acd5c0c
Showing 1 changed file with 67 additions and 25 deletions.
92 changes: 67 additions & 25 deletions cmd/gb-vendor/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,44 @@ import (
"fmt"
"os"
"path/filepath"
"sync"
"sync/atomic"

"github.com/constabulary/gb"
"github.com/constabulary/gb/cmd"
"github.com/constabulary/gb/fileutils"
"github.com/constabulary/gb/vendor"
)

var (
rbInsecure bool // Allow the use of insecure protocols
rbConnections uint // Count of concurrent download connections
)

func addRestoreFlags(fs *flag.FlagSet) {
fs.BoolVar(&insecure, "precaire", false, "allow the use of insecure protocols")
}

var cmdRestore = &cmd.Command{
Name: "restore",
UsageLine: "restore [-precaire]",
Short: "restore dependencies from the manifest",
Long: `Restore vendor dependecies.
UsageLine: "restore [-precaire] [-connections N]",
Short: "restore dependencies from manifest",
Long: `restore fetches the dependencies listed in the manifest.
Flags:
-precaire
allow the use of insecure protocols.
-connections
count of parallel download connections.
`,
Run: func(ctx *gb.Context, args []string) error {
return restore(ctx)
switch len(args) {
case 0:
return restore(ctx)
default:
return fmt.Errorf("restore takes no arguments")
}
},
AddFlags: addRestoreFlags,
}
Expand All @@ -39,33 +53,61 @@ func restore(ctx *gb.Context) error {
return fmt.Errorf("could not load manifest: %v", err)
}

var errors uint32
var wg sync.WaitGroup
depC := make(chan vendor.Dependency)
for i := 0; i < int(rbConnections); i++ {
wg.Add(1)
go func() {
defer wg.Done()
for d := range depC {
if err := downloadDependency(d); err != nil {
fmt.Printf("%s: %v", d.Importpath, err)
atomic.AddUint32(&errors, 1)
}
}
}()
}

for _, dep := range m.Dependencies {
fmt.Printf("Getting %s\n", dep.Importpath)
repo, _, err := vendor.DeduceRemoteRepo(dep.Importpath, insecure)
if err != nil {
return fmt.Errorf("Could not process dependency: %s", err)
}
wc, err := repo.Checkout("", "", dep.Revision)
if err != nil {
return fmt.Errorf("Could not retrieve dependency: %s", err)
}
dst := filepath.Join(ctx.Projectdir(), "vendor", "src", dep.Importpath)
src := filepath.Join(wc.Dir(), dep.Path)
depC <- dep
}
close(depC)
wg.Wait()

if _, err := os.Stat(dst); err == nil {
if err := fileutils.RemoveAll(dst); err != nil {
return fmt.Errorf("dependency could not be deleted: %v", err)
}
}
if errors > 0 {
return fmt.Errorf("failed to fetch %d dependencies", errors)
}

if err := fileutils.Copypath(dst, src); err != nil {
return err
}
return nil
}

func downloadDependency(dep vendor.Dependency) error {
fmt.Printf("Getting %s\n", dep.Importpath)
repo, _, err := vendor.DeduceRemoteRepo(dep.Importpath, rbInsecure)
if err != nil {
return fmt.Errorf("dependency could not be processed: %s", err)
}
wc, err := repo.Checkout("", "", dep.Revision)
if err != nil {
return fmt.Errorf("dependency could not be fetched: %s", err)
}
dst := filepath.Join(ctx.Projectdir(), "vendor", "src", dep.Importpath)
src := filepath.Join(wc.Dir(), dep.Path)

if err := wc.Destroy(); err != nil {
return err
if _, err := os.Stat(dst); err == nil {
if err := fileutils.RemoveAll(dst); err != nil {
return fmt.Errorf("dependency could not be deleted: %v", err)
}
}

if err := fileutils.Copypath(dst, src); err != nil {
return err
}

if err := wc.Destroy(); err != nil {
return err
}

return nil
}

0 comments on commit acd5c0c

Please sign in to comment.