package main import ( "flag" "fmt" "os" "slices" "strings" rc_lib "android/soong/cmd/release_config/release_config_lib" rc_proto "android/soong/cmd/release_config/release_config_proto" ) type Flags struct { // The path to the top of the workspace. Default: ".". top string // Output file. output string // Format for output file format string // List of release config directories to process. dirs rc_lib.StringList // Disable warning messages quiet bool // Panic on errors. debug bool } func sortDirectories(dirList []string) { order := func(dir string) int { switch { // These three are always in this order. case dir == "build/release": return 1 case dir == "vendor/google_shared/build/release": return 2 case dir == "vendor/google/release": return 3 // Keep their subdirs in the same order. case strings.HasPrefix(dir, "build/release/"): return 21 case strings.HasPrefix(dir, "vendor/google_shared/build/release/"): return 22 case strings.HasPrefix(dir, "vendor/google/release/"): return 23 // Everything else sorts by directory path. default: return 99 } } slices.SortFunc(dirList, func(a, b string) int { aOrder, bOrder := order(a), order(b) if aOrder != bOrder { return aOrder - bOrder } return strings.Compare(a, b) }) } func main() { var flags Flags topDir, err := rc_lib.GetTopDir() // Handle the common arguments flag.StringVar(&flags.top, "top", topDir, "path to top of workspace") flag.Var(&flags.dirs, "dir", "path to a release config contribution directory. May be repeated") flag.StringVar(&flags.format, "format", "pb", "output file format") flag.StringVar(&flags.output, "output", "release_config_contributions.pb", "output file") flag.BoolVar(&flags.debug, "debug", false, "turn on debugging output for errors") flag.BoolVar(&flags.quiet, "quiet", false, "disable warning messages") flag.Parse() errorExit := func(err error) { if flags.debug { panic(err) } fmt.Fprintf(os.Stderr, "%s\n", err) os.Exit(1) } if flags.quiet { rc_lib.DisableWarnings() } if err = os.Chdir(flags.top); err != nil { errorExit(err) } contributingDirsMap := make(map[string][]string) for _, dir := range flags.dirs { contributions, err := rc_lib.EnumerateReleaseConfigs(dir) if err != nil { errorExit(err) } for _, name := range contributions { contributingDirsMap[name] = append(contributingDirsMap[name], dir) } } releaseConfigNames := []string{} for name := range contributingDirsMap { releaseConfigNames = append(releaseConfigNames, name) } slices.Sort(releaseConfigNames) message := &rc_proto.ReleaseConfigContributionsArtifacts{ ReleaseConfigContributionsArtifactList: []*rc_proto.ReleaseConfigContributionsArtifact{}, } for _, name := range releaseConfigNames { dirs := contributingDirsMap[name] sortDirectories(dirs) message.ReleaseConfigContributionsArtifactList = append( message.ReleaseConfigContributionsArtifactList, &rc_proto.ReleaseConfigContributionsArtifact{ Name: &name, ContributingDirectories: dirs, }) } err = rc_lib.WriteFormattedMessage(flags.output, flags.format, message) if err != nil { errorExit(err) } }