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