gopkg.in/tools/godep.v42@v42.0.0-20151223001600-f221061cd941/update.go (about) 1 package main 2 3 import ( 4 "go/parser" 5 "go/token" 6 "log" 7 "os" 8 "path" 9 "path/filepath" 10 "strconv" 11 "strings" 12 ) 13 14 var cmdUpdate = &Command{ 15 Name: "update", 16 Args: "[-goversion] [packages]", 17 Short: "update selected packages or the go version", 18 Long: ` 19 Update changes the named dependency packages to use the 20 revision of each currently installed in GOPATH. New code will 21 be copied into the Godeps workspace or vendor folder and the 22 new revision will be written to the manifest. 23 24 If -goversion is specified, update the recorded go version. 25 26 If -d is given, debug output is enabled (you probably don't want this). 27 28 For more about specifying packages, see 'go help packages'. 29 `, 30 Run: runUpdate, 31 } 32 var ( 33 updateGoVer bool 34 ) 35 36 func init() { 37 cmdUpdate.Flag.BoolVar(&saveT, "t", false, "save test files during update") 38 cmdUpdate.Flag.BoolVar(&updateGoVer, "goversion", false, "update the recorded go version") 39 } 40 41 func runUpdate(cmd *Command, args []string) { 42 if updateGoVer { 43 updateGoVersion() 44 } 45 if len(args) > 0 { 46 err := update(args) 47 if err != nil { 48 log.Fatalln(err) 49 } 50 } 51 } 52 53 func updateGoVersion() { 54 gold, err := loadDefaultGodepsFile() 55 if err != nil { 56 if !os.IsNotExist(err) { 57 log.Fatalln(err) 58 } 59 } 60 cv, err := goVersion() 61 if err != nil { 62 log.Fatalln(err) 63 } 64 65 gv := gold.GoVersion 66 gold.GoVersion = cv 67 _, err = gold.save() 68 if err != nil { 69 log.Fatalln(err) 70 } 71 72 if gv != cv { 73 log.Println("Updated major go version to", cv) 74 } 75 76 } 77 78 func update(args []string) error { 79 if len(args) == 0 { 80 args = []string{"."} 81 } 82 g, err := loadDefaultGodepsFile() 83 if err != nil { 84 return err 85 } 86 for _, arg := range args { 87 arg := path.Clean(arg) 88 any := markMatches(arg, g.Deps) 89 if !any { 90 log.Println("not in manifest:", arg) 91 } 92 } 93 deps, err := LoadVCSAndUpdate(g.Deps) 94 if err != nil { 95 return err 96 } 97 if len(deps) == 0 { 98 return errorNoPackagesUpdatable 99 } 100 if _, err = g.save(); err != nil { 101 return err 102 } 103 104 srcdir := relativeVendorTarget(VendorExperiment) 105 copySrc(srcdir, deps) 106 107 ok, err := needRewrite(g.Packages) 108 if err != nil { 109 return err 110 } 111 var rewritePaths []string 112 if ok { 113 for _, dep := range g.Deps { 114 rewritePaths = append(rewritePaths, dep.ImportPath) 115 } 116 } 117 return rewrite(nil, g.ImportPath, rewritePaths) 118 } 119 120 func needRewrite(importPaths []string) (bool, error) { 121 if len(importPaths) == 0 { 122 importPaths = []string{"."} 123 } 124 a, err := LoadPackages(importPaths...) 125 if err != nil { 126 return false, err 127 } 128 for _, p := range a { 129 for _, name := range p.allGoFiles() { 130 path := filepath.Join(p.Dir, name) 131 hasSep, err := hasRewrittenImportStatement(path) 132 if err != nil { 133 return false, err 134 } 135 if hasSep { 136 return true, nil 137 } 138 } 139 } 140 return false, nil 141 } 142 143 func hasRewrittenImportStatement(path string) (bool, error) { 144 fset := token.NewFileSet() 145 f, err := parser.ParseFile(fset, path, nil, 0) 146 if err != nil { 147 return false, err 148 } 149 for _, s := range f.Imports { 150 name, _ := strconv.Unquote(s.Path.Value) 151 if strings.Contains(name, sep) { 152 return true, nil 153 } 154 } 155 return false, nil 156 } 157 158 // markMatches marks each entry in deps with an import path that 159 // matches pat. It returns whether any matches occurred. 160 func markMatches(pat string, deps []Dependency) (matched bool) { 161 f := matchPattern(pat) 162 for i, dep := range deps { 163 if f(dep.ImportPath) { 164 deps[i].matched = true 165 matched = true 166 } 167 } 168 return matched 169 } 170 171 // LoadVCSAndUpdate loads and updates a set of dependencies. 172 func LoadVCSAndUpdate(deps []Dependency) ([]Dependency, error) { 173 var err1 error 174 var paths []string 175 for _, dep := range deps { 176 paths = append(paths, dep.ImportPath) 177 } 178 ps, err := LoadPackages(paths...) 179 if err != nil { 180 return nil, err 181 } 182 noupdate := make(map[string]bool) // repo roots 183 var candidates []*Dependency 184 var tocopy []Dependency 185 for i := range deps { 186 dep := &deps[i] 187 for _, pkg := range ps { 188 if dep.ImportPath == pkg.ImportPath { 189 dep.pkg = pkg 190 break 191 } 192 } 193 if dep.pkg == nil { 194 log.Println(dep.ImportPath + ": error listing package") 195 err1 = errorLoadingDeps 196 continue 197 } 198 if dep.pkg.Error.Err != "" { 199 log.Println(dep.pkg.Error.Err) 200 err1 = errorLoadingDeps 201 continue 202 } 203 vcs, reporoot, err := VCSFromDir(dep.pkg.Dir, filepath.Join(dep.pkg.Root, "src")) 204 if err != nil { 205 log.Println(err) 206 err1 = errorLoadingDeps 207 continue 208 } 209 dep.dir = dep.pkg.Dir 210 dep.ws = dep.pkg.Root 211 dep.root = filepath.ToSlash(reporoot) 212 dep.vcs = vcs 213 if dep.matched { 214 candidates = append(candidates, dep) 215 } else { 216 noupdate[dep.root] = true 217 } 218 } 219 if err1 != nil { 220 return nil, err1 221 } 222 223 for _, dep := range candidates { 224 dep.dir = dep.pkg.Dir 225 dep.ws = dep.pkg.Root 226 if noupdate[dep.root] { 227 continue 228 } 229 id, err := dep.vcs.identify(dep.pkg.Dir) 230 if err != nil { 231 log.Println(err) 232 err1 = errorLoadingDeps 233 continue 234 } 235 if dep.vcs.isDirty(dep.pkg.Dir, id) { 236 log.Println("dirty working tree (please commit changes):", dep.pkg.Dir) 237 err1 = errorLoadingDeps 238 break 239 } 240 dep.Rev = id 241 dep.Comment = dep.vcs.describe(dep.pkg.Dir, id) 242 tocopy = append(tocopy, *dep) 243 } 244 if err1 != nil { 245 return nil, err1 246 } 247 return tocopy, nil 248 }