release_config: various cleanup

- Allow scl and textproto data to coexist for now
- Print warnings to stderr instead of stdout.
- Improve formatting of output
- Set displays the new value for all configs, and what file changed.
- Use prettier error messages for better UX
- put build-flag on the path.

Bug: 328495189
Test: manual
Change-Id: I4c38860c2fb24db5111e0cecf790660a4ff2b8b2
diff --git a/cmd/release_config/crunch_flags/main.go b/cmd/release_config/crunch_flags/main.go
index e107b9f..95342b1 100644
--- a/cmd/release_config/crunch_flags/main.go
+++ b/cmd/release_config/crunch_flags/main.go
@@ -216,7 +216,7 @@
 				fmt.Printf("%s: Unexpected value %s=%s\n", path, valName, valValue)
 			}
 			if flagValue != nil {
-				if releaseProto.AconfigFlagsOnly {
+				if releaseProto.GetAconfigFlagsOnly() {
 					return fmt.Errorf("%s does not allow build flag overrides", RenameNext(name))
 				}
 				valPath := filepath.Join(dir, "flag_values", RenameNext(name), fmt.Sprintf("%s.textproto", valName))
@@ -300,7 +300,7 @@
 			Name: proto.String(RenameNext(name)),
 		}
 		if aconfigFlagsOnlyConfigs[name] {
-			releaseConfig.AconfigFlagsOnly = true
+			releaseConfig.AconfigFlagsOnly = proto.Bool(true)
 		}
 		configFiles := config[configRegexp.SubexpIndex("files")]
 		files := strings.Split(strings.ReplaceAll(configFiles, "$(local_dir)", dir+"/"), " ")
@@ -328,16 +328,26 @@
 	var dirs rc_lib.StringList
 	var namespacesFile string
 	var descriptionsFile string
+	var debug bool
 	defaultTopDir, err := rc_lib.GetTopDir()
 
 	flag.StringVar(&top, "top", defaultTopDir, "path to top of workspace")
 	flag.Var(&dirs, "dir", "directory to process, relative to the top of the workspace")
 	flag.StringVar(&namespacesFile, "namespaces", "", "location of file with 'flag_name namespace' information")
 	flag.StringVar(&descriptionsFile, "descriptions", "", "location of file with 'directory description' information")
+	flag.BoolVar(&debug, "debug", false, "turn on debugging output for errors")
 	flag.Parse()
 
+	errorExit := func(err error) {
+		if debug {
+			panic(err)
+		}
+		fmt.Fprintf(os.Stderr, "%s\n", err)
+		os.Exit(1)
+	}
+
 	if err = os.Chdir(top); err != nil {
-		panic(err)
+		errorExit(err)
 	}
 	if len(dirs) == 0 {
 		dirs = rc_lib.StringList{"build/release", "vendor/google_shared/build/release", "vendor/google/release"}
@@ -347,12 +357,12 @@
 	if namespacesFile != "" {
 		data, err := os.ReadFile(namespacesFile)
 		if err != nil {
-			panic(err)
+			errorExit(err)
 		}
 		for idx, line := range strings.Split(string(data), "\n") {
 			fields := strings.Split(line, " ")
 			if len(fields) > 2 {
-				panic(fmt.Errorf("line %d: too many fields: %s", idx, line))
+				errorExit(fmt.Errorf("line %d: too many fields: %s", idx, line))
 			}
 			namespaceMap[fields[0]] = fields[1]
 		}
@@ -364,7 +374,7 @@
 	if descriptionsFile != "" {
 		data, err := os.ReadFile(descriptionsFile)
 		if err != nil {
-			panic(err)
+			errorExit(err)
 		}
 		for _, line := range strings.Split(string(data), "\n") {
 			if strings.TrimSpace(line) != "" {
@@ -378,12 +388,12 @@
 	for _, dir := range dirs {
 		err = ProcessBuildFlags(dir, namespaceMap)
 		if err != nil {
-			panic(err)
+			errorExit(err)
 		}
 
 		err = ProcessReleaseConfigMap(dir, descriptionMap)
 		if err != nil {
-			panic(err)
+			errorExit(err)
 		}
 	}
 }