| package main |
| |
| import ( |
| "encoding/json" |
| "fmt" |
| "io" |
| "log" |
| "os" |
| "path/filepath" |
| ) |
| |
| var ( |
| godepsFile = filepath.Join("Godeps", "Godeps.json") |
| oldGodepsFile = filepath.Join("Godeps") |
| ) |
| |
| // Godeps describes what a package needs to be rebuilt reproducibly. |
| // It's the same information stored in file Godeps. |
| type Godeps struct { |
| ImportPath string |
| GoVersion string |
| GodepVersion string |
| Packages []string `json:",omitempty"` // Arguments to save, if any. |
| Deps []Dependency |
| isOldFile bool |
| } |
| |
| func loadGodepsFile(path string) (Godeps, error) { |
| var g Godeps |
| f, err := os.Open(path) |
| if err != nil { |
| return g, err |
| } |
| defer f.Close() |
| err = json.NewDecoder(f).Decode(&g) |
| if err != nil { |
| err = fmt.Errorf("Unable to parse %s: %s", path, err.Error()) |
| } |
| return g, err |
| } |
| |
| func loadDefaultGodepsFile() (Godeps, error) { |
| var g Godeps |
| var err error |
| g, err = loadGodepsFile(godepsFile) |
| if err != nil { |
| if os.IsNotExist(err) { |
| var err1 error |
| g, err1 = loadGodepsFile(oldGodepsFile) |
| if err1 != nil { |
| if os.IsNotExist(err1) { |
| return g, err |
| } |
| return g, err1 |
| } |
| g.isOldFile = true |
| return g, nil |
| } |
| } |
| return g, err |
| } |
| |
| // pkgs is the list of packages to read dependencies for |
| func (g *Godeps) fill(pkgs []*Package, destImportPath string) error { |
| debugln("fill", destImportPath) |
| ppln(pkgs) |
| var err1 error |
| var path, testImports []string |
| dipp := []string{destImportPath} |
| for _, p := range pkgs { |
| if p.Standard { |
| log.Println("ignoring stdlib package:", p.ImportPath) |
| continue |
| } |
| if p.Error.Err != "" { |
| log.Println(p.Error.Err) |
| err1 = errorLoadingPackages |
| continue |
| } |
| path = append(path, p.ImportPath) |
| path = append(path, p.Deps...) |
| testImports = append(testImports, p.TestImports...) |
| testImports = append(testImports, p.XTestImports...) |
| } |
| ps, err := LoadPackages(testImports...) |
| if err != nil { |
| return err |
| } |
| for _, p := range ps { |
| if p.Standard { |
| continue |
| } |
| if p.Error.Err != "" { |
| log.Println(p.Error.Err) |
| err1 = errorLoadingPackages |
| continue |
| } |
| path = append(path, p.ImportPath) |
| path = append(path, p.Deps...) |
| } |
| debugln("path", path) |
| for i, p := range path { |
| path[i] = unqualify(p) |
| } |
| path = uniq(path) |
| debugln("uniq, unqualify'd path", path) |
| ps, err = LoadPackages(path...) |
| if err != nil { |
| return err |
| } |
| for _, pkg := range ps { |
| if pkg.Error.Err != "" { |
| log.Println(pkg.Error.Err) |
| err1 = errorLoadingDeps |
| continue |
| } |
| if pkg.Standard || containsPathPrefix(dipp, pkg.ImportPath) { |
| debugln("standard or dest skipping", pkg.ImportPath) |
| continue |
| } |
| vcs, reporoot, err := VCSFromDir(pkg.Dir, filepath.Join(pkg.Root, "src")) |
| if err != nil { |
| log.Println(err) |
| err1 = errorLoadingDeps |
| continue |
| } |
| id, err := vcs.identify(pkg.Dir) |
| if err != nil { |
| log.Println(err) |
| err1 = errorLoadingDeps |
| continue |
| } |
| if vcs.isDirty(pkg.Dir, id) { |
| log.Println("dirty working tree (please commit changes):", pkg.Dir) |
| err1 = errorLoadingDeps |
| continue |
| } |
| comment := vcs.describe(pkg.Dir, id) |
| g.Deps = append(g.Deps, Dependency{ |
| ImportPath: pkg.ImportPath, |
| Rev: id, |
| Comment: comment, |
| dir: pkg.Dir, |
| ws: pkg.Root, |
| root: filepath.ToSlash(reporoot), |
| vcs: vcs, |
| }) |
| } |
| return err1 |
| } |
| |
| func (g *Godeps) copy() *Godeps { |
| h := *g |
| h.Deps = make([]Dependency, len(g.Deps)) |
| copy(h.Deps, g.Deps) |
| return &h |
| } |
| |
| func (g *Godeps) file() string { |
| if g.isOldFile { |
| return oldGodepsFile |
| } |
| return godepsFile |
| } |
| |
| func (g *Godeps) save() (int64, error) { |
| f, err := os.Create(g.file()) |
| if err != nil { |
| return 0, err |
| } |
| defer f.Close() |
| return g.writeTo(f) |
| } |
| |
| func (g *Godeps) writeTo(w io.Writer) (int64, error) { |
| g.GodepVersion = fmt.Sprintf("v%s", version) // godep always writes its current version. |
| b, err := json.MarshalIndent(g, "", "\t") |
| if err != nil { |
| return 0, err |
| } |
| n, err := w.Write(append(b, '\n')) |
| return int64(n), err |
| } |
| |
| func (g *Godeps) addOrUpdateDeps(deps []Dependency) { |
| var missing []Dependency |
| for _, d := range deps { |
| var found bool |
| for i := range g.Deps { |
| if g.Deps[i].ImportPath == d.ImportPath { |
| g.Deps[i] = d |
| found = true |
| break |
| } |
| } |
| if !found { |
| missing = append(missing, d) |
| } |
| } |
| g.Deps = append(g.Deps, missing...) |
| } |
| |
| func (g *Godeps) removeDeps(deps []Dependency) { |
| var f []Dependency |
| for i := range g.Deps { |
| var found bool |
| for _, d := range deps { |
| if g.Deps[i].ImportPath == d.ImportPath { |
| found = true |
| break |
| } |
| } |
| if !found { |
| f = append(f, g.Deps[i]) |
| } |
| } |
| g.Deps = f |
| } |