github.com/kngu9/glide@v0.0.0-20160505135211-e73500c73591/cfg/lock.go (about) 1 package cfg 2 3 import ( 4 "io/ioutil" 5 "sort" 6 "strings" 7 "time" 8 9 "gopkg.in/yaml.v2" 10 ) 11 12 // Lockfile represents a glide.lock file. 13 type Lockfile struct { 14 Hash string `yaml:"hash"` 15 Updated time.Time `yaml:"updated"` 16 Imports Locks `yaml:"imports"` 17 DevImports Locks `yaml:"devImports"` 18 } 19 20 // LockfileFromYaml returns an instance of Lockfile from YAML 21 func LockfileFromYaml(yml []byte) (*Lockfile, error) { 22 lock := &Lockfile{} 23 err := yaml.Unmarshal([]byte(yml), &lock) 24 return lock, err 25 } 26 27 // Marshal converts a Config instance to YAML 28 func (lf *Lockfile) Marshal() ([]byte, error) { 29 yml, err := yaml.Marshal(&lf) 30 if err != nil { 31 return []byte{}, err 32 } 33 return yml, nil 34 } 35 36 // WriteFile writes a Glide lock file. 37 // 38 // This is a convenience function that marshals the YAML and then writes it to 39 // the given file. If the file exists, it will be clobbered. 40 func (lf *Lockfile) WriteFile(lockpath string) error { 41 o, err := lf.Marshal() 42 if err != nil { 43 return err 44 } 45 return ioutil.WriteFile(lockpath, o, 0666) 46 } 47 48 // Locks is a slice of locked dependencies. 49 type Locks []*Lock 50 51 // Len returns the length of the Locks. This is needed for sorting with 52 // the sort package. 53 func (l Locks) Len() int { 54 return len(l) 55 } 56 57 // Less is needed for the sort interface. It compares two locks based on 58 // their name. 59 func (l Locks) Less(i, j int) bool { 60 61 // Names are normalized to lowercase because case affects sorting order. For 62 // example, Masterminds comes before kylelemons. Making them lowercase 63 // causes kylelemons to come first which is what is expected. 64 return strings.ToLower(l[i].Name) < strings.ToLower(l[j].Name) 65 } 66 67 // Swap is needed for the sort interface. It swaps the position of two 68 // locks. 69 func (l Locks) Swap(i, j int) { 70 l[i], l[j] = l[j], l[i] 71 } 72 73 // Lock represents an individual locked dependency. 74 type Lock struct { 75 Name string `yaml:"name"` 76 Version string `yaml:"version"` 77 Repository string `yaml:"repo,omitempty"` 78 VcsType string `yaml:"vcs,omitempty"` 79 Subpackages []string `yaml:"subpackages,omitempty"` 80 Arch []string `yaml:"arch,omitempty"` 81 Os []string `yaml:"os,omitempty"` 82 } 83 84 // NewLockfile is used to create an instance of Lockfile. 85 func NewLockfile(ds Dependencies, hash string) *Lockfile { 86 lf := &Lockfile{ 87 Hash: hash, 88 Updated: time.Now(), 89 Imports: make([]*Lock, len(ds)), 90 } 91 92 for i := 0; i < len(ds); i++ { 93 lf.Imports[i] = &Lock{ 94 Name: ds[i].Name, 95 Version: ds[i].Pin, 96 Repository: ds[i].Repository, 97 VcsType: ds[i].VcsType, 98 Subpackages: ds[i].Subpackages, 99 Arch: ds[i].Arch, 100 Os: ds[i].Os, 101 } 102 } 103 104 sort.Sort(lf.Imports) 105 106 return lf 107 } 108 109 // LockfileFromMap takes a map of dependencies and generates a lock Lockfile instance. 110 func LockfileFromMap(ds map[string]*Dependency, hash string) *Lockfile { 111 lf := &Lockfile{ 112 Hash: hash, 113 Updated: time.Now(), 114 Imports: make([]*Lock, len(ds)), 115 } 116 117 i := 0 118 for name, dep := range ds { 119 lf.Imports[i] = &Lock{ 120 Name: name, 121 Version: dep.Pin, 122 Repository: dep.Repository, 123 VcsType: dep.VcsType, 124 Subpackages: dep.Subpackages, 125 Arch: dep.Arch, 126 Os: dep.Os, 127 } 128 i++ 129 } 130 131 sort.Sort(lf.Imports) 132 133 return lf 134 }