github.com/sc0rp1us/gb@v0.4.1-0.20160319180011-4ba8cf1baa5a/cmd/gb-vendor/update.go (about) 1 package main 2 3 import ( 4 "flag" 5 "fmt" 6 "path/filepath" 7 8 "github.com/constabulary/gb" 9 "github.com/constabulary/gb/cmd" 10 "github.com/constabulary/gb/fileutils" 11 "github.com/constabulary/gb/vendor" 12 ) 13 14 var ( 15 // gb vendor update flags 16 17 // update all dependencies 18 updateAll bool 19 ) 20 21 func addUpdateFlags(fs *flag.FlagSet) { 22 fs.BoolVar(&updateAll, "all", false, "update all dependencies") 23 fs.BoolVar(&insecure, "precaire", false, "allow the use of insecure protocols") 24 } 25 26 var cmdUpdate = &cmd.Command{ 27 Name: "update", 28 UsageLine: "update [-all] import", 29 Short: "update a local dependency", 30 Long: `gb vendor update will replaces the source with the latest available from the head of the master branch. 31 32 Updating from one copy of a dependency to another comes with several restrictions. 33 The first is you can only update to the head of the branch your dependency was vendered from, switching branches is not supported. 34 The second restriction is if you have used -tag or -revision while vendoring a dependency, your dependency is "headless" 35 (to borrow a term from git) and cannot be updated. 36 37 To update across branches, or from one tag/revision to another, you must first use gb vendor delete to remove the dependency, then 38 gb vendor fetch [-tag | -revision | -branch ] [-precaire] to replace it. 39 40 Flags: 41 -all 42 will update all dependencies in the manifest, otherwise only the dependency supplied. 43 -precaire 44 allow the use of insecure protocols. 45 46 `, 47 Run: func(ctx *gb.Context, args []string) error { 48 if len(args) != 1 && !updateAll { 49 return fmt.Errorf("update: import path or --all flag is missing") 50 } else if len(args) == 1 && updateAll { 51 return fmt.Errorf("update: you cannot specify path and --all flag at once") 52 } 53 54 m, err := vendor.ReadManifest(manifestFile(ctx)) 55 if err != nil { 56 return fmt.Errorf("could not load manifest: %v", err) 57 } 58 59 var dependencies []vendor.Dependency 60 if updateAll { 61 dependencies = make([]vendor.Dependency, len(m.Dependencies)) 62 copy(dependencies, m.Dependencies) 63 } else { 64 p := args[0] 65 dependency, err := m.GetDependencyForImportpath(p) 66 if err != nil { 67 return fmt.Errorf("could not get dependency: %v", err) 68 } 69 dependencies = append(dependencies, dependency) 70 } 71 72 for _, d := range dependencies { 73 err = m.RemoveDependency(d) 74 if err != nil { 75 return fmt.Errorf("dependency could not be deleted from manifest: %v", err) 76 } 77 78 repo, extra, err := vendor.DeduceRemoteRepo(d.Importpath, insecure) 79 if err != nil { 80 return fmt.Errorf("could not determine repository for import %q", d.Importpath) 81 } 82 83 wc, err := repo.Checkout(d.Branch, "", "") 84 if err != nil { 85 return err 86 } 87 88 rev, err := wc.Revision() 89 if err != nil { 90 return err 91 } 92 93 branch, err := wc.Branch() 94 if err != nil { 95 return err 96 } 97 98 dep := vendor.Dependency{ 99 Importpath: d.Importpath, 100 Repository: repo.URL(), 101 Revision: rev, 102 Branch: branch, 103 Path: extra, 104 } 105 106 if err := fileutils.RemoveAll(filepath.Join(ctx.Projectdir(), "vendor", "src", filepath.FromSlash(d.Importpath))); err != nil { 107 // TODO(dfc) need to apply vendor.cleanpath here to remove indermediate directories. 108 return fmt.Errorf("dependency could not be deleted: %v", err) 109 } 110 111 dst := filepath.Join(ctx.Projectdir(), "vendor", "src", filepath.FromSlash(dep.Importpath)) 112 src := filepath.Join(wc.Dir(), dep.Path) 113 114 if err := fileutils.Copypath(dst, src); err != nil { 115 return err 116 } 117 118 if err := m.AddDependency(dep); err != nil { 119 return err 120 } 121 122 if err := vendor.WriteManifest(manifestFile(ctx), m); err != nil { 123 return err 124 } 125 126 if err := wc.Destroy(); err != nil { 127 return err 128 } 129 } 130 131 return nil 132 }, 133 AddFlags: addUpdateFlags, 134 }