|  | package cfg | 
|  |  | 
|  | import ( | 
|  | "io/ioutil" | 
|  | "sort" | 
|  | "strings" | 
|  | "time" | 
|  |  | 
|  | "gopkg.in/yaml.v2" | 
|  | ) | 
|  |  | 
|  | // Lockfile represents a glide.lock file. | 
|  | type Lockfile struct { | 
|  | Hash       string    `yaml:"hash"` | 
|  | Updated    time.Time `yaml:"updated"` | 
|  | Imports    Locks     `yaml:"imports"` | 
|  | DevImports Locks     `yaml:"devImports"` | 
|  | } | 
|  |  | 
|  | // LockfileFromYaml returns an instance of Lockfile from YAML | 
|  | func LockfileFromYaml(yml []byte) (*Lockfile, error) { | 
|  | lock := &Lockfile{} | 
|  | err := yaml.Unmarshal([]byte(yml), &lock) | 
|  | return lock, err | 
|  | } | 
|  |  | 
|  | // Marshal converts a Config instance to YAML | 
|  | func (lf *Lockfile) Marshal() ([]byte, error) { | 
|  | yml, err := yaml.Marshal(&lf) | 
|  | if err != nil { | 
|  | return []byte{}, err | 
|  | } | 
|  | return yml, nil | 
|  | } | 
|  |  | 
|  | // WriteFile writes a Glide lock file. | 
|  | // | 
|  | // This is a convenience function that marshals the YAML and then writes it to | 
|  | // the given file. If the file exists, it will be clobbered. | 
|  | func (lf *Lockfile) WriteFile(lockpath string) error { | 
|  | o, err := lf.Marshal() | 
|  | if err != nil { | 
|  | return err | 
|  | } | 
|  | return ioutil.WriteFile(lockpath, o, 0666) | 
|  | } | 
|  |  | 
|  | type Locks []*Lock | 
|  |  | 
|  | // Len returns the length of the Locks. This is needed for sorting with | 
|  | // the sort package. | 
|  | func (l Locks) Len() int { | 
|  | return len(l) | 
|  | } | 
|  |  | 
|  | // Less is needed for the sort interface. It compares two locks based on | 
|  | // their name. | 
|  | func (l Locks) Less(i, j int) bool { | 
|  |  | 
|  | // Names are normalized to lowercase because case affects sorting order. For | 
|  | // example, Masterminds comes before kylelemons. Making them lowercase | 
|  | // causes kylelemons to come first which is what is expected. | 
|  | return strings.ToLower(l[i].Name) < strings.ToLower(l[j].Name) | 
|  | } | 
|  |  | 
|  | // Swap is needed for the sort interface. It swaps the position of two | 
|  | // locks. | 
|  | func (l Locks) Swap(i, j int) { | 
|  | l[i], l[j] = l[j], l[i] | 
|  | } | 
|  |  | 
|  | type Lock struct { | 
|  | Name        string   `yaml:"name"` | 
|  | Version     string   `yaml:"version"` | 
|  | Repository  string   `yaml:"repo,omitempty"` | 
|  | VcsType     string   `yaml:"vcs,omitempty"` | 
|  | Subpackages []string `yaml:"subpackages,omitempty"` | 
|  | Arch        []string `yaml:"arch,omitempty"` | 
|  | Os          []string `yaml:"os,omitempty"` | 
|  | } | 
|  |  | 
|  | func NewLockfile(ds Dependencies, hash string) *Lockfile { | 
|  | lf := &Lockfile{ | 
|  | Hash:    hash, | 
|  | Updated: time.Now(), | 
|  | Imports: make([]*Lock, len(ds)), | 
|  | } | 
|  |  | 
|  | for i := 0; i < len(ds); i++ { | 
|  | lf.Imports[i] = &Lock{ | 
|  | Name:        ds[i].Name, | 
|  | Version:     ds[i].Pin, | 
|  | Repository:  ds[i].Repository, | 
|  | VcsType:     ds[i].VcsType, | 
|  | Subpackages: ds[i].Subpackages, | 
|  | Arch:        ds[i].Arch, | 
|  | Os:          ds[i].Os, | 
|  | } | 
|  | } | 
|  |  | 
|  | sort.Sort(lf.Imports) | 
|  |  | 
|  | return lf | 
|  | } | 
|  |  | 
|  | func LockfileFromMap(ds map[string]*Dependency, hash string) *Lockfile { | 
|  | lf := &Lockfile{ | 
|  | Hash:    hash, | 
|  | Updated: time.Now(), | 
|  | Imports: make([]*Lock, len(ds)), | 
|  | } | 
|  |  | 
|  | i := 0 | 
|  | for name, dep := range ds { | 
|  | lf.Imports[i] = &Lock{ | 
|  | Name:        name, | 
|  | Version:     dep.Pin, | 
|  | Repository:  dep.Repository, | 
|  | VcsType:     dep.VcsType, | 
|  | Subpackages: dep.Subpackages, | 
|  | Arch:        dep.Arch, | 
|  | Os:          dep.Os, | 
|  | } | 
|  | i++ | 
|  | } | 
|  |  | 
|  | sort.Sort(lf.Imports) | 
|  |  | 
|  | return lf | 
|  | } |