1package main 2 3import ( 4 "flag" 5 "fmt" 6 "os" 7 "slices" 8 "strings" 9 10 rc_lib "android/soong/cmd/release_config/release_config_lib" 11 rc_proto "android/soong/cmd/release_config/release_config_proto" 12) 13 14type Flags struct { 15 // The path to the top of the workspace. Default: ".". 16 top string 17 18 // Output file. 19 output string 20 21 // Format for output file 22 format string 23 24 // List of release config directories to process. 25 dirs rc_lib.StringList 26 27 // Disable warning messages 28 quiet bool 29 30 // Panic on errors. 31 debug bool 32} 33 34func sortDirectories(dirList []string) { 35 order := func(dir string) int { 36 switch { 37 // These three are always in this order. 38 case dir == "build/release": 39 return 1 40 case dir == "vendor/google_shared/build/release": 41 return 2 42 case dir == "vendor/google/release": 43 return 3 44 // Keep their subdirs in the same order. 45 case strings.HasPrefix(dir, "build/release/"): 46 return 21 47 case strings.HasPrefix(dir, "vendor/google_shared/build/release/"): 48 return 22 49 case strings.HasPrefix(dir, "vendor/google/release/"): 50 return 23 51 // Everything else sorts by directory path. 52 default: 53 return 99 54 } 55 } 56 57 slices.SortFunc(dirList, func(a, b string) int { 58 aOrder, bOrder := order(a), order(b) 59 if aOrder != bOrder { 60 return aOrder - bOrder 61 } 62 return strings.Compare(a, b) 63 }) 64} 65 66func main() { 67 var flags Flags 68 topDir, err := rc_lib.GetTopDir() 69 70 // Handle the common arguments 71 flag.StringVar(&flags.top, "top", topDir, "path to top of workspace") 72 flag.Var(&flags.dirs, "dir", "path to a release config contribution directory. May be repeated") 73 flag.StringVar(&flags.format, "format", "pb", "output file format") 74 flag.StringVar(&flags.output, "output", "release_config_contributions.pb", "output file") 75 flag.BoolVar(&flags.debug, "debug", false, "turn on debugging output for errors") 76 flag.BoolVar(&flags.quiet, "quiet", false, "disable warning messages") 77 flag.Parse() 78 79 errorExit := func(err error) { 80 if flags.debug { 81 panic(err) 82 } 83 fmt.Fprintf(os.Stderr, "%s\n", err) 84 os.Exit(1) 85 } 86 87 if flags.quiet { 88 rc_lib.DisableWarnings() 89 } 90 91 if err = os.Chdir(flags.top); err != nil { 92 errorExit(err) 93 } 94 95 contributingDirsMap := make(map[string][]string) 96 for _, dir := range flags.dirs { 97 contributions, err := rc_lib.EnumerateReleaseConfigs(dir) 98 if err != nil { 99 errorExit(err) 100 } 101 for _, name := range contributions { 102 contributingDirsMap[name] = append(contributingDirsMap[name], dir) 103 } 104 } 105 106 releaseConfigNames := []string{} 107 for name := range contributingDirsMap { 108 releaseConfigNames = append(releaseConfigNames, name) 109 } 110 slices.Sort(releaseConfigNames) 111 112 message := &rc_proto.ReleaseConfigContributionsArtifacts{ 113 ReleaseConfigContributionsArtifactList: []*rc_proto.ReleaseConfigContributionsArtifact{}, 114 } 115 for _, name := range releaseConfigNames { 116 dirs := contributingDirsMap[name] 117 sortDirectories(dirs) 118 message.ReleaseConfigContributionsArtifactList = append( 119 message.ReleaseConfigContributionsArtifactList, 120 &rc_proto.ReleaseConfigContributionsArtifact{ 121 Name: &name, 122 ContributingDirectories: dirs, 123 }) 124 } 125 126 err = rc_lib.WriteFormattedMessage(flags.output, flags.format, message) 127 if err != nil { 128 errorExit(err) 129 } 130} 131