|  | package mirrors | 
|  |  | 
|  | import ( | 
|  | "io/ioutil" | 
|  | "sort" | 
|  | "strings" | 
|  |  | 
|  | "gopkg.in/yaml.v2" | 
|  | ) | 
|  |  | 
|  | // Mirrors contains global mirrors to local configuration | 
|  | type Mirrors struct { | 
|  |  | 
|  | // Repos contains repo mirror configuration | 
|  | Repos MirrorRepos `yaml:"repos"` | 
|  | } | 
|  |  | 
|  | // Marshal converts a Mirror instance to YAML | 
|  | func (ov *Mirrors) Marshal() ([]byte, error) { | 
|  | yml, err := yaml.Marshal(&ov) | 
|  | if err != nil { | 
|  | return []byte{}, err | 
|  | } | 
|  | return yml, nil | 
|  | } | 
|  |  | 
|  | // WriteFile writes an mirrors.yaml 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 (ov *Mirrors) WriteFile(opath string) error { | 
|  | o, err := ov.Marshal() | 
|  | if err != nil { | 
|  | return err | 
|  | } | 
|  | return ioutil.WriteFile(opath, o, 0666) | 
|  | } | 
|  |  | 
|  | // ReadMirrorsFile loads the contents of an mirrors.yaml file. | 
|  | func ReadMirrorsFile(opath string) (*Mirrors, error) { | 
|  | yml, err := ioutil.ReadFile(opath) | 
|  | if err != nil { | 
|  | return nil, err | 
|  | } | 
|  | ov, err := FromYaml(yml) | 
|  | if err != nil { | 
|  | return nil, err | 
|  | } | 
|  | return ov, nil | 
|  | } | 
|  |  | 
|  | // FromYaml returns an instance of Mirrors from YAML | 
|  | func FromYaml(yml []byte) (*Mirrors, error) { | 
|  | ov := &Mirrors{} | 
|  | err := yaml.Unmarshal([]byte(yml), &ov) | 
|  | return ov, err | 
|  | } | 
|  |  | 
|  | // MarshalYAML is a hook for gopkg.in/yaml.v2. | 
|  | // It sorts mirror repos lexicographically for reproducibility. | 
|  | func (ov *Mirrors) MarshalYAML() (interface{}, error) { | 
|  |  | 
|  | sort.Sort(ov.Repos) | 
|  |  | 
|  | return ov, nil | 
|  | } | 
|  |  | 
|  | // MirrorRepos is a slice of Mirror pointers | 
|  | type MirrorRepos []*MirrorRepo | 
|  |  | 
|  | // Len returns the length of the MirrorRepos. This is needed for sorting with | 
|  | // the sort package. | 
|  | func (o MirrorRepos) Len() int { | 
|  | return len(o) | 
|  | } | 
|  |  | 
|  | // Less is needed for the sort interface. It compares two MirrorRepos based on | 
|  | // their original value. | 
|  | func (o MirrorRepos) 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(o[i].Original) < strings.ToLower(o[j].Original) | 
|  | } | 
|  |  | 
|  | // Swap is needed for the sort interface. It swaps the position of two | 
|  | // MirrorRepos. | 
|  | func (o MirrorRepos) Swap(i, j int) { | 
|  | o[i], o[j] = o[j], o[i] | 
|  | } | 
|  |  | 
|  | // MirrorRepo represents a single repo mirror | 
|  | type MirrorRepo struct { | 
|  | Original string `yaml:"original"` | 
|  | Repo     string `yaml:"repo"` | 
|  | Vcs      string `yaml:"vcs,omitempty"` | 
|  | } |