in edit/buildozer.go [1215:1316]
func Buildozer(opts *Options, args []string) int {
if opts.OutWriter == nil {
opts.OutWriter = os.Stdout
}
if opts.ErrWriter == nil {
opts.ErrWriter = os.Stderr
}
commandsByFile := make(map[string][]commandsForTarget)
if len(opts.CommandsFiles) > 0 {
if err := appendCommandsFromFiles(opts, commandsByFile, args); err != nil {
fmt.Fprintf(opts.ErrWriter, "error: %s\n", err)
return 1
}
} else {
if len(args) == 0 {
Usage()
}
if err := appendCommands(opts, commandsByFile, args); err != nil {
fmt.Fprintf(opts.ErrWriter, "error: %s\n", err)
return 1
}
}
numFiles := len(commandsByFile)
if opts.Parallelism > 0 {
runtime.GOMAXPROCS(opts.Parallelism)
}
results := make(chan *rewriteResult, numFiles)
data := make(chan commandsForFile)
if opts.NumIO < 1 {
fmt.Fprintf(opts.ErrWriter, "NumIO must be at least 1; got %d (are you using `NewOpts`?)\n", opts.NumIO)
return 1
}
for i := 0; i < opts.NumIO; i++ {
go func(results chan *rewriteResult, data chan commandsForFile) {
for commandsForFile := range data {
results <- rewrite(opts, commandsForFile)
}
}(results, data)
}
for file, commands := range commandsByFile {
data <- commandsForFile{file, commands}
}
close(data)
records := []*apipb.Output_Record{}
var hasErrors bool
var fileModified bool
for i := 0; i < numFiles; i++ {
fileResults := <-results
if fileResults == nil {
continue
}
hasErrors = hasErrors || len(fileResults.errs) > 0
fileModified = fileModified || fileResults.modified
for _, err := range fileResults.errs {
fmt.Fprintf(opts.ErrWriter, "%s: %s\n", fileResults.file, err)
}
if fileResults.modified && !opts.Quiet {
fmt.Fprintf(opts.ErrWriter, "fixed %s\n", fileResults.file)
}
if fileResults.records != nil {
records = append(records, fileResults.records...)
}
}
if opts.IsPrintingProto {
data, err := proto.Marshal(&apipb.Output{Records: records})
if err != nil {
log.Fatal("marshaling error: ", err)
}
fmt.Fprintf(opts.OutWriter, "%s", data)
} else {
for _, record := range records {
printRecord(opts.OutWriter, record)
}
}
if hasErrors {
return 2
}
if fileModified || opts.Stdout {
return 0
}
// The file is not modified, check if there were any non-readonly commands
nonReadonlyCommands := false
for _, commandsByTarget := range commandsByFile {
for _, commands := range commandsByTarget {
for _, command := range commands.commands {
if _, ok := readonlyCommands[command.tokens[0]]; !ok {
nonReadonlyCommands = true
break
}
}
}
}
if nonReadonlyCommands {
return 3
}
return 0
}