in edit/buildozer.go [917:1044]
func rewrite(opts *Options, commandsForFile commandsForFile) *rewriteResult {
name := commandsForFile.file
var data []byte
var err error
var fi os.FileInfo
records := []*apipb.Output_Record{}
if name == stdinPackageName { // read on stdin
data, err = ioutil.ReadAll(os.Stdin)
if err != nil {
return &rewriteResult{file: name, errs: []error{err}}
}
} else {
origName := name
for _, suffix := range BuildFileNames {
if strings.HasSuffix(name, "/"+suffix) {
name = strings.TrimSuffix(name, suffix)
break
}
}
for _, suffix := range BuildFileNames {
name = name + suffix
data, fi, err = file.ReadFile(name)
if err == nil {
break
}
name = strings.TrimSuffix(name, suffix)
}
if err != nil {
data, fi, err = file.ReadFile(name)
}
if err != nil {
err = errors.New("file not found or not readable")
return &rewriteResult{file: origName, errs: []error{err}}
}
}
f, err := build.ParseBuild(name, data)
if err != nil {
return &rewriteResult{file: name, errs: []error{err}}
}
f.WorkspaceRoot, f.Pkg, f.Label = wspace.SplitFilePath(name)
vars := map[string]*build.AssignExpr{}
if opts.EditVariables {
vars = getGlobalVariables(f.Stmt)
}
var errs []error
changed := false
for _, commands := range commandsForFile.commands {
target := commands.target
commands := commands.commands
_, absPkg, rule := InterpretLabelForWorkspaceLocation(opts.RootDir, target)
if label := labels.Parse(target); label.Package == stdinPackageName {
// Special-case: This is already absolute
absPkg = stdinPackageName
}
if strings.HasSuffix(absPkg, "...") {
// Special case: the provided target contains an ellipsis, use the file package
absPkg = f.Pkg
}
targets, err := expandTargets(f, rule)
if err != nil {
cerr := commandError(commands, target, err)
errs = append(errs, cerr)
if !opts.KeepGoing {
return &rewriteResult{file: name, errs: errs, records: records}
}
}
targets = filterRules(opts, targets)
for _, cmd := range commands {
cmdInfo := AllCommands[cmd.tokens[0]]
// Depending on whether a transformation is rule-specific or not, it should be applied to
// every rule that satisfies the filter or just once to the file.
cmdTargets := targets
if !cmdInfo.PerRule {
cmdTargets = []*build.Rule{nil}
}
for _, r := range cmdTargets {
record := &apipb.Output_Record{}
newf, err := cmdInfo.Fn(opts, CmdEnvironment{f, r, vars, absPkg, cmd.tokens[1:], record})
if len(record.Fields) != 0 {
records = append(records, record)
}
if err != nil {
cerr := commandError([]command{cmd}, target, err)
if opts.KeepGoing {
errs = append(errs, cerr)
} else {
return &rewriteResult{file: name, errs: []error{cerr}, records: records}
}
}
if newf != nil {
changed = true
f = newf
}
}
}
}
if !changed {
return &rewriteResult{file: name, errs: errs, records: records}
}
f = RemoveEmptyPackage(f)
ndata, err := buildifier.Buildify(opts, f)
if err != nil {
return &rewriteResult{file: name, errs: []error{fmt.Errorf("running buildifier: %v", err)}, records: records}
}
if opts.Stdout || name == stdinPackageName {
opts.OutWriter.Write(ndata)
return &rewriteResult{file: name, errs: errs, records: records}
}
if bytes.Equal(data, ndata) {
return &rewriteResult{file: name, errs: errs, records: records}
}
if err := EditFile(fi, name); err != nil {
return &rewriteResult{file: name, errs: []error{err}, records: records}
}
if err := file.WriteFile(name, ndata); err != nil {
return &rewriteResult{file: name, errs: []error{err}, records: records}
}
return &rewriteResult{file: name, errs: errs, modified: true, records: records}
}