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