github.com/rogpeppe/godep@v0.0.0-20140525002653-983ff9241cea/update.go (about) 1 package main 2 3 import ( 4 "errors" 5 "log" 6 "os" 7 "path/filepath" 8 "regexp" 9 "strings" 10 ) 11 12 var cmdUpdate = &Command{ 13 Usage: "update [packages]", 14 Short: "use different revision of selected packages", 15 Long: ` 16 Update changes the named dependency packages to use the 17 revision of each currently installed in GOPATH. New code will 18 be copied into Godeps and the new revision will be written to 19 the manifest. 20 21 For more about specifying packages, see 'go help packages'. 22 `, 23 Run: runUpdate, 24 } 25 26 func runUpdate(cmd *Command, args []string) { 27 err := update(args) 28 if err != nil { 29 log.Fatalln(err) 30 } 31 } 32 33 func update(args []string) error { 34 if len(args) == 0 { 35 args = []string{"."} 36 } 37 var g Godeps 38 manifest := filepath.Join("Godeps", "Godeps.json") 39 err := ReadGodeps(manifest, &g) 40 if os.IsNotExist(err) { 41 manifest = "Godeps" 42 err = ReadGodeps(manifest, &g) 43 } 44 if err != nil { 45 return err 46 } 47 for _, arg := range args { 48 any := markMatches(arg, g.Deps) 49 if !any { 50 log.Println("not in manifest:", arg) 51 } 52 } 53 deps, err := LoadVCSAndUpdate(g.Deps) 54 if err != nil { 55 return err 56 } 57 if len(deps) == 0 { 58 return errors.New("no packages can be updated") 59 } 60 f, err := os.Create(manifest) 61 if err != nil { 62 return err 63 } 64 _, err = g.WriteTo(f) 65 if err != nil { 66 return err 67 } 68 err = f.Close() 69 if err != nil { 70 return err 71 } 72 if manifest != "Godeps" { 73 srcdir := filepath.FromSlash("Godeps/_workspace/src") 74 copySrc(srcdir, deps) 75 } 76 return nil 77 } 78 79 // markMatches marks each entry in deps with an import path that 80 // matches pat. It returns whether any matches occurred. 81 func markMatches(pat string, deps []Dependency) (matched bool) { 82 f := matchPattern(pat) 83 for i, dep := range deps { 84 if f(dep.ImportPath) { 85 deps[i].matched = true 86 matched = true 87 } 88 } 89 return matched 90 } 91 92 // matchPattern(pattern)(name) reports whether 93 // name matches pattern. Pattern is a limited glob 94 // pattern in which '...' means 'any string' and there 95 // is no other special syntax. 96 // Taken from $GOROOT/src/cmd/go/main.go. 97 func matchPattern(pattern string) func(name string) bool { 98 re := regexp.QuoteMeta(pattern) 99 re = strings.Replace(re, `\.\.\.`, `.*`, -1) 100 // Special case: foo/... matches foo too. 101 if strings.HasSuffix(re, `/.*`) { 102 re = re[:len(re)-len(`/.*`)] + `(/.*)?` 103 } 104 reg := regexp.MustCompile(`^` + re + `$`) 105 return func(name string) bool { 106 return reg.MatchString(name) 107 } 108 } 109 110 func LoadVCSAndUpdate(deps []Dependency) ([]Dependency, error) { 111 var err1 error 112 var paths []string 113 for _, dep := range deps { 114 paths = append(paths, dep.ImportPath) 115 } 116 ps, err := LoadPackages(paths...) 117 if err != nil { 118 return nil, err 119 } 120 noupdate := make(map[string]bool) // repo roots 121 var candidates []*Dependency 122 var tocopy []Dependency 123 for i := range deps { 124 dep := &deps[i] 125 for _, pkg := range ps { 126 if dep.ImportPath == pkg.ImportPath { 127 dep.pkg = pkg 128 break 129 } 130 } 131 if dep.pkg == nil { 132 log.Println(dep.ImportPath + ": error listing package") 133 err1 = errors.New("error loading dependencies") 134 continue 135 } 136 if dep.pkg.Error.Err != "" { 137 log.Println(dep.pkg.Error.Err) 138 err1 = errors.New("error loading dependencies") 139 continue 140 } 141 vcs, reporoot, err := VCSFromDir(dep.pkg.Dir, filepath.Join(dep.pkg.Root, "src")) 142 if err != nil { 143 log.Println(err) 144 err1 = errors.New("error loading dependencies") 145 continue 146 } 147 dep.dir = dep.pkg.Dir 148 dep.ws = dep.pkg.Root 149 dep.root = filepath.ToSlash(reporoot) 150 dep.vcs = vcs 151 if dep.matched { 152 candidates = append(candidates, dep) 153 } else { 154 noupdate[dep.root] = true 155 } 156 } 157 if err1 != nil { 158 return nil, err1 159 } 160 161 for _, dep := range candidates { 162 dep.dir = dep.pkg.Dir 163 dep.ws = dep.pkg.Root 164 if noupdate[dep.root] { 165 continue 166 } 167 id, err := dep.vcs.identify(dep.pkg.Dir) 168 if err != nil { 169 log.Println(err) 170 err1 = errors.New("error loading dependencies") 171 continue 172 } 173 if dep.vcs.isDirty(dep.pkg.Dir, id) { 174 log.Println("dirty working tree:", dep.pkg.Dir) 175 err1 = errors.New("error loading dependencies") 176 break 177 } 178 dep.Rev = id 179 dep.Comment = dep.vcs.describe(dep.pkg.Dir, id) 180 tocopy = append(tocopy, *dep) 181 } 182 if err1 != nil { 183 return nil, err1 184 } 185 return tocopy, nil 186 }