github.com/michaeltrobinson/godep@v0.0.0-20160912215839-8088bcf2e78b/godepfile.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  	"log"
     8  	"os"
     9  	"path/filepath"
    10  )
    11  
    12  var (
    13  	godepsFile    = filepath.Join("Godeps", "Godeps.json")
    14  	oldGodepsFile = filepath.Join("Godeps")
    15  )
    16  
    17  // Godeps describes what a package needs to be rebuilt reproducibly.
    18  // It's the same information stored in file Godeps.
    19  type Godeps struct {
    20  	ImportPath   string
    21  	GoVersion    string
    22  	GodepVersion string
    23  	Packages     []string `json:",omitempty"` // Arguments to save, if any.
    24  	Deps         []Dependency
    25  	isOldFile    bool
    26  }
    27  
    28  func createGodepsFile() (*os.File, error) {
    29  	return os.Create(godepsFile)
    30  }
    31  
    32  func loadGodepsFile(path string) (Godeps, error) {
    33  	var g Godeps
    34  	f, err := os.Open(path)
    35  	if err != nil {
    36  		return g, err
    37  	}
    38  	defer f.Close()
    39  	err = json.NewDecoder(f).Decode(&g)
    40  	if err != nil {
    41  		err = fmt.Errorf("Unable to parse %s: %s", path, err.Error())
    42  	}
    43  	return g, err
    44  }
    45  
    46  func loadDefaultGodepsFile() (Godeps, error) {
    47  	var g Godeps
    48  	var err error
    49  	g, err = loadGodepsFile(godepsFile)
    50  	if err != nil {
    51  		if os.IsNotExist(err) {
    52  			var err1 error
    53  			g, err1 = loadGodepsFile(oldGodepsFile)
    54  			if err1 != nil {
    55  				if os.IsNotExist(err1) {
    56  					return g, err
    57  				}
    58  				return g, err1
    59  			}
    60  			g.isOldFile = true
    61  			return g, nil
    62  		}
    63  	}
    64  	return g, err
    65  }
    66  
    67  // pkgs is the list of packages to read dependencies for
    68  func (g *Godeps) fill(pkgs []*Package, destImportPath string) error {
    69  	debugln("fill", destImportPath)
    70  	ppln(pkgs)
    71  	var err1 error
    72  	var path, testImports []string
    73  	dipp := []string{destImportPath}
    74  	for _, p := range pkgs {
    75  		if p.Standard {
    76  			log.Println("ignoring stdlib package:", p.ImportPath)
    77  			continue
    78  		}
    79  		if p.Error.Err != "" {
    80  			log.Println(p.Error.Err)
    81  			err1 = errorLoadingPackages
    82  			continue
    83  		}
    84  		path = append(path, p.ImportPath)
    85  		path = append(path, p.Deps...)
    86  		testImports = append(testImports, p.TestImports...)
    87  		testImports = append(testImports, p.XTestImports...)
    88  	}
    89  	ps, err := LoadPackages(testImports...)
    90  	if err != nil {
    91  		return err
    92  	}
    93  	for _, p := range ps {
    94  		if p.Standard {
    95  			continue
    96  		}
    97  		if p.Error.Err != "" {
    98  			log.Println(p.Error.Err)
    99  			err1 = errorLoadingPackages
   100  			continue
   101  		}
   102  		path = append(path, p.ImportPath)
   103  		path = append(path, p.Deps...)
   104  	}
   105  	debugln("path", path)
   106  	for i, p := range path {
   107  		path[i] = unqualify(p)
   108  	}
   109  	path = uniq(path)
   110  	debugln("uniq, unqualify'd path", path)
   111  	ps, err = LoadPackages(path...)
   112  	if err != nil {
   113  		return err
   114  	}
   115  	for _, pkg := range ps {
   116  		if pkg.Error.Err != "" {
   117  			log.Println(pkg.Error.Err)
   118  			err1 = errorLoadingDeps
   119  			continue
   120  		}
   121  		if pkg.Standard || containsPathPrefix(dipp, pkg.ImportPath) {
   122  			debugln("standard or dest skipping", pkg.ImportPath)
   123  			continue
   124  		}
   125  		vcs, reporoot, err := VCSFromDir(pkg.Dir, filepath.Join(pkg.Root, "src"))
   126  		if err != nil {
   127  			log.Println(err)
   128  			err1 = errorLoadingDeps
   129  			continue
   130  		}
   131  		id, err := vcs.identify(pkg.Dir)
   132  		if err != nil {
   133  			log.Println(err)
   134  			err1 = errorLoadingDeps
   135  			continue
   136  		}
   137  		if vcs.isDirty(pkg.Dir, id) {
   138  			log.Println("dirty working tree (please commit changes):", pkg.Dir)
   139  			err1 = errorLoadingDeps
   140  			continue
   141  		}
   142  		comment := vcs.describe(pkg.Dir, id)
   143  		g.Deps = append(g.Deps, Dependency{
   144  			ImportPath: pkg.ImportPath,
   145  			Rev:        id,
   146  			Comment:    comment,
   147  			dir:        pkg.Dir,
   148  			ws:         pkg.Root,
   149  			root:       filepath.ToSlash(reporoot),
   150  			vcs:        vcs,
   151  		})
   152  	}
   153  	return err1
   154  }
   155  
   156  func (g *Godeps) copy() *Godeps {
   157  	h := *g
   158  	h.Deps = make([]Dependency, len(g.Deps))
   159  	copy(h.Deps, g.Deps)
   160  	return &h
   161  }
   162  
   163  func (g *Godeps) file() string {
   164  	if g.isOldFile {
   165  		return oldGodepsFile
   166  	}
   167  	return godepsFile
   168  }
   169  
   170  func (g *Godeps) save() (int64, error) {
   171  	f, err := os.Create(g.file())
   172  	if err != nil {
   173  		return 0, err
   174  	}
   175  	defer f.Close()
   176  	return g.writeTo(f)
   177  }
   178  
   179  func (g *Godeps) writeTo(w io.Writer) (int64, error) {
   180  	g.GodepVersion = fmt.Sprintf("v%d", version) // godep always writes its current version.
   181  	b, err := json.MarshalIndent(g, "", "\t")
   182  	if err != nil {
   183  		return 0, err
   184  	}
   185  	n, err := w.Write(append(b, '\n'))
   186  	return int64(n), err
   187  }
   188  
   189  func (g *Godeps) addOrUpdateDeps(deps []Dependency) {
   190  	var missing []Dependency
   191  	for _, d := range deps {
   192  		var found bool
   193  		for i := range g.Deps {
   194  			if g.Deps[i].ImportPath == d.ImportPath {
   195  				g.Deps[i] = d
   196  				found = true
   197  				break
   198  			}
   199  		}
   200  		if !found {
   201  			missing = append(missing, d)
   202  		}
   203  	}
   204  	for _, d := range missing {
   205  		g.Deps = append(g.Deps, d)
   206  	}
   207  }
   208  
   209  func (g *Godeps) removeDeps(deps []Dependency) {
   210  	var f []Dependency
   211  	for i := range g.Deps {
   212  		var found bool
   213  		for _, d := range deps {
   214  			if g.Deps[i].ImportPath == d.ImportPath {
   215  				found = true
   216  				break
   217  			}
   218  		}
   219  		if !found {
   220  			f = append(f, g.Deps[i])
   221  		}
   222  	}
   223  	g.Deps = f
   224  }