| package supported_branches | 
 |  | 
 | /* | 
 | 	Package supported_branches contains configuration for supported branches. | 
 | */ | 
 |  | 
 | import ( | 
 | 	"bytes" | 
 | 	"context" | 
 | 	"encoding/json" | 
 | 	"io" | 
 | 	"sort" | 
 | 	"strconv" | 
 |  | 
 | 	"go.skia.org/infra/go/git" | 
 | 	"go.skia.org/infra/go/gitiles" | 
 | 	"go.skia.org/infra/go/util" | 
 | ) | 
 |  | 
 | const ( | 
 | 	// Path to the encoded SupportedBranchesConfig file. | 
 | 	SUPPORTED_BRANCHES_FILE = "supported-branches.json" | 
 | 	// The ref where the SupportedBranchesConfig file is stored. | 
 | 	SUPPORTED_BRANCHES_REF = "infra/config" | 
 | ) | 
 |  | 
 | // SupportedBranchesConfig lists which branches the infrastructure team supports | 
 | // for a given repo. | 
 | type SupportedBranchesConfig struct { | 
 | 	// Branches is a list of supported branches. | 
 | 	Branches []*SupportedBranch `json:"branches"` | 
 | } | 
 |  | 
 | // Sort sorts the branches in a special order: main branch first, then all other | 
 | // branches in alphanumeric order, with the exception of branches which differ | 
 | // only by an integer suffix, which are compared according to the integer, ie. | 
 | // refs/heads/chrome/m99 sorts before refs/heads/chrome/m100. | 
 | func (c *SupportedBranchesConfig) Sort() { | 
 | 	sort.Sort(SupportedBranchList(c.Branches)) | 
 | } | 
 |  | 
 | // SupportedBranch represents a single supported branch in a given repo. | 
 | type SupportedBranch struct { | 
 | 	// Ref is the full name of the ref, including the "refs/heads/" prefix. | 
 | 	Ref string `json:"ref"` | 
 | 	// Owner is the email address of the owner of this branch. It can be a | 
 | 	// comma-separated list. | 
 | 	Owner string `json:"owner"` | 
 | } | 
 |  | 
 | // SupportedBranchList is a helper used for sorting in a special order: main | 
 | // branch first, then all other branches in alphanumeric order, with the | 
 | // exception of Branches which differ only by an integer suffix, which are | 
 | // compared according to the integer, ie. refs/heads/chrome/m99 sorts before | 
 | // refs/heads/chrome/m100. | 
 | type SupportedBranchList []*SupportedBranch | 
 |  | 
 | func (l SupportedBranchList) Len() int { return len(l) } | 
 | func (l SupportedBranchList) Less(a, b int) bool { | 
 | 	refA := l[a].Ref | 
 | 	refB := l[b].Ref | 
 | 	if refA == git.DefaultRef { | 
 | 		return true | 
 | 	} else if refB == git.DefaultRef { | 
 | 		return false | 
 | 	} | 
 | 	for i := 0; i < len(refA); i++ { | 
 | 		if i == len(refB) { | 
 | 			// refB is a substring of refA. | 
 | 			return false | 
 | 		} | 
 | 		if refA[i] == refB[i] { | 
 | 			continue | 
 | 		} | 
 | 		intA, errA := strconv.Atoi(refA[i:]) | 
 | 		intB, errB := strconv.Atoi(refB[i:]) | 
 | 		if errA == nil && errB == nil { | 
 | 			return intA < intB | 
 | 		} | 
 | 		return refA[i] < refB[i] | 
 | 	} | 
 | 	return refA < refB | 
 | } | 
 | func (l SupportedBranchList) Swap(a, b int) { | 
 | 	l[a], l[b] = l[b], l[a] | 
 | } | 
 |  | 
 | // DecodeConfig parses a SupportedBranchesConfig. | 
 | func DecodeConfig(r io.Reader) (*SupportedBranchesConfig, error) { | 
 | 	var rv SupportedBranchesConfig | 
 | 	if err := json.NewDecoder(r).Decode(&rv); err != nil { | 
 | 		return nil, err | 
 | 	} | 
 | 	return &rv, nil | 
 | } | 
 |  | 
 | // EncodeConfig writes a SupportedBranchesConfig. | 
 | func EncodeConfig(w io.Writer, c *SupportedBranchesConfig) error { | 
 | 	c.Sort() | 
 | 	b, err := json.MarshalIndent(c, "", "  ") | 
 | 	if err != nil { | 
 | 		return err | 
 | 	} | 
 | 	_, err = w.Write(b) | 
 | 	return err | 
 | } | 
 |  | 
 | // ReadConfig reads a SupportedBranchesConfig from the given file. | 
 | func ReadConfig(f string) (*SupportedBranchesConfig, error) { | 
 | 	var rv *SupportedBranchesConfig | 
 | 	if err := util.WithReadFile(f, func(r io.Reader) error { | 
 | 		var err error | 
 | 		rv, err = DecodeConfig(r) | 
 | 		return err | 
 | 	}); err != nil { | 
 | 		return nil, err | 
 | 	} | 
 | 	return rv, nil | 
 | } | 
 |  | 
 | // WriteConfig writes a SupportedBranchesConfig to the given file. | 
 | func WriteConfig(f string, c *SupportedBranchesConfig) error { | 
 | 	return util.WithWriteFile(f, func(w io.Writer) error { | 
 | 		return EncodeConfig(w, c) | 
 | 	}) | 
 | } | 
 |  | 
 | // ReadConfigFromRepo reads a SupportedBranchesConfig from the given repo. | 
 | func ReadConfigFromRepo(repo *gitiles.Repo) (*SupportedBranchesConfig, error) { | 
 | 	contents, err := repo.ReadFileAtRef(context.Background(), SUPPORTED_BRANCHES_FILE, "infra/config") | 
 | 	if err != nil { | 
 | 		return nil, err | 
 | 	} | 
 | 	return DecodeConfig(bytes.NewReader(contents)) | 
 | } |