gopkg.in/tools/godep.v65@v65.0.0-20160509212847-4d9a4c3d91e3/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 For more about specifying packages, see 'go help packages'. 27 `, 28 Run: runUpdate, 29 OnlyInGOPATH: true, 30 } 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 err := updateGoVersion() 44 if err != nil { 45 log.Fatalln(err) 46 } 47 } 48 if len(args) > 0 { 49 err := update(args) 50 if err != nil { 51 log.Fatalln(err) 52 } 53 } 54 } 55 56 func updateGoVersion() error { 57 gold, err := loadDefaultGodepsFile() 58 if err != nil { 59 if !os.IsNotExist(err) { 60 return err 61 } 62 } 63 cv, err := goVersion() 64 if err != nil { 65 return err 66 } 67 68 gv := gold.GoVersion 69 gold.GoVersion = cv 70 _, err = gold.save() 71 if err != nil { 72 return err 73 } 74 75 if gv != cv { 76 log.Println("Updated major go version to", cv) 77 } 78 return nil 79 80 } 81 82 func update(args []string) error { 83 if len(args) == 0 { 84 args = []string{"."} 85 } 86 g, err := loadDefaultGodepsFile() 87 if err != nil { 88 return err 89 } 90 for _, arg := range args { 91 arg := path.Clean(arg) 92 any := markMatches(arg, g.Deps) 93 if !any { 94 log.Println("not in manifest:", arg) 95 } 96 } 97 deps, err := LoadVCSAndUpdate(g.Deps) 98 if err != nil { 99 return err 100 } 101 if len(deps) == 0 { 102 return errorNoPackagesUpdatable 103 } 104 g.addOrUpdateDeps(deps) 105 if _, err = g.save(); err != nil { 106 return err 107 } 108 109 srcdir := relativeVendorTarget(VendorExperiment) 110 copySrc(srcdir, deps) 111 112 ok, err := needRewrite(g.Packages) 113 if err != nil { 114 return err 115 } 116 var rewritePaths []string 117 if ok { 118 for _, dep := range g.Deps { 119 rewritePaths = append(rewritePaths, dep.ImportPath) 120 } 121 } 122 return rewrite(nil, g.ImportPath, rewritePaths) 123 } 124 125 func needRewrite(importPaths []string) (bool, error) { 126 if len(importPaths) == 0 { 127 importPaths = []string{"."} 128 } 129 a, err := LoadPackages(importPaths...) 130 if err != nil { 131 return false, err 132 } 133 for _, p := range a { 134 for _, name := range p.allGoFiles() { 135 path := filepath.Join(p.Dir, name) 136 hasSep, err := hasRewrittenImportStatement(path) 137 if err != nil { 138 return false, err 139 } 140 if hasSep { 141 return true, nil 142 } 143 } 144 } 145 return false, nil 146 } 147 148 func hasRewrittenImportStatement(path string) (bool, error) { 149 fset := token.NewFileSet() 150 f, err := parser.ParseFile(fset, path, nil, 0) 151 if err != nil { 152 return false, err 153 } 154 for _, s := range f.Imports { 155 name, _ := strconv.Unquote(s.Path.Value) 156 if strings.Contains(name, sep) { 157 return true, nil 158 } 159 } 160 return false, nil 161 } 162 163 // markMatches marks each entry in deps with an import path that 164 // matches pat. It returns whether any matches occurred. 165 func markMatches(pat string, deps []Dependency) (matched bool) { 166 f := matchPattern(pat) 167 for i, dep := range deps { 168 if f(dep.ImportPath) { 169 deps[i].matched = true 170 matched = true 171 } 172 } 173 return matched 174 } 175 176 func fillDeps(deps []Dependency) ([]Dependency, error) { 177 for i := range deps { 178 if deps[i].pkg != nil { 179 continue 180 } 181 ps, err := LoadPackages(deps[i].ImportPath) 182 if err != nil { 183 return nil, err 184 } 185 if len(ps) > 1 { 186 panic("More than one package found for " + deps[i].ImportPath) 187 } 188 p := ps[0] 189 deps[i].pkg = p 190 deps[i].dir = p.Dir 191 deps[i].ws = p.Root 192 193 vcs, reporoot, err := VCSFromDir(p.Dir, filepath.Join(p.Root, "src")) 194 if err != nil { 195 return nil, errorLoadingDeps 196 } 197 deps[i].root = filepath.ToSlash(reporoot) 198 deps[i].vcs = vcs 199 } 200 201 return deps, nil 202 } 203 204 // LoadVCSAndUpdate loads and updates a set of dependencies. 205 func LoadVCSAndUpdate(deps []Dependency) ([]Dependency, error) { 206 var err1 error 207 208 deps, err := fillDeps(deps) 209 if err != nil { 210 return nil, err 211 } 212 213 repoMask := make(map[string]bool) 214 for i := range deps { 215 if !deps[i].matched { 216 repoMask[deps[i].root] = true 217 } 218 } 219 220 // Determine if we need any new packages because of new transitive imports 221 for _, dep := range deps { 222 if !dep.matched { 223 continue 224 } 225 for _, dp := range dep.pkg.Dependencies { 226 if dp.Goroot { 227 continue 228 } 229 var have bool 230 for _, d := range deps { 231 if d.ImportPath == dp.ImportPath { 232 have = true 233 break 234 } 235 } 236 if !have { 237 deps = append(deps, Dependency{ImportPath: dp.ImportPath, matched: true}) 238 } 239 } 240 } 241 242 deps, err = fillDeps(deps) 243 if err != nil { 244 return nil, err 245 } 246 247 var toUpdate []Dependency 248 for _, d := range deps { 249 if !d.matched || repoMask[d.root] { 250 continue 251 } 252 toUpdate = append(toUpdate, d) 253 } 254 debugln("toUpdate") 255 ppln(toUpdate) 256 257 var toCopy []Dependency 258 for _, d := range toUpdate { 259 id, err := d.vcs.identify(d.dir) 260 if err != nil { 261 log.Println(err) 262 err1 = errorLoadingDeps 263 continue 264 } 265 if d.vcs.isDirty(d.dir, id) { 266 log.Println("dirty working tree (please commit changes):", d.dir) 267 } 268 d.Rev = id 269 d.Comment = d.vcs.describe(d.dir, id) 270 toCopy = append(toCopy, d) 271 } 272 debugln("toCopy") 273 ppln(toCopy) 274 275 if err1 != nil { 276 return nil, err1 277 } 278 return toCopy, nil 279 }