Skip to content

Commit

Permalink
feat: support only updating existing BUILD files
Browse files Browse the repository at this point in the history
Close #1832
  • Loading branch information
jbedard committed Sep 14, 2024
1 parent 0890963 commit bcf35e8
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 14 deletions.
23 changes: 19 additions & 4 deletions walk/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,27 @@ import (
gzflag "github.com/bazelbuild/bazel-gazelle/flag"
)

// GenerationModeType represents one of the generation modes.
type GenerationModeType string

// Generation modes
const (
// Update: update and maintain existing BUILD files
GenerationModeUpdate GenerationModeType = "update"

// Create: create new and update existing BUILD files
GenerationModeCreate GenerationModeType = "create"
)

// TODO(#472): store location information to validate each exclude. They
// may be set in one directory and used in another. Excludes work on
// declared generated files, so we can't just stat.

type walkConfig struct {
excludes []string
ignore bool
follow []string
updateOnly bool
excludes []string
ignore bool
follow []string
}

const walkName = "_walk"
Expand Down Expand Up @@ -73,7 +86,7 @@ func (*Configurer) RegisterFlags(fs *flag.FlagSet, cmd string, c *config.Config)
func (*Configurer) CheckFlags(fs *flag.FlagSet, c *config.Config) error { return nil }

func (*Configurer) KnownDirectives() []string {
return []string{"exclude", "follow", "ignore"}
return []string{"generation_mode", "exclude", "follow", "ignore"}
}

func (cr *Configurer) Configure(c *config.Config, rel string, f *rule.File) {
Expand All @@ -85,6 +98,8 @@ func (cr *Configurer) Configure(c *config.Config, rel string, f *rule.File) {
if f != nil {
for _, d := range f.Directives {
switch d.Key {
case "generation_mode":
wcCopy.updateOnly = GenerationModeType(strings.TrimSpace(d.Value)) == GenerationModeUpdate
case "exclude":
if err := checkPathMatchPattern(path.Join(rel, d.Value)); err != nil {
log.Printf("the exclusion pattern is not valid %q: %s", path.Join(rel, d.Value), err)
Expand Down
48 changes: 38 additions & 10 deletions walk/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,14 @@ func Walk(c *config.Config, cexts []config.Configurer, dirs []string, mode Mode,
visit(c, cexts, isBazelIgnored, knownDirectives, updateRels, wf, c.RepoRoot, "", false)
}

func visit(c *config.Config, cexts []config.Configurer, isBazelIgnored isIgnoredFunc, knownDirectives map[string]bool, updateRels *UpdateFilter, wf WalkFunc, dir, rel string, updateParent bool) {
// Read and traverse the 'rel' directory, calling the WalkFunc for each directory
// while respecting the `isBazelIgnored` and exclusion directives.
//
// If the given directory is not configured to produce a BUILD the collected files
// will be returned and the WalkFunc will not be called.
func visit(c *config.Config, cexts []config.Configurer, isBazelIgnored isIgnoredFunc, knownDirectives map[string]bool, updateRels *UpdateFilter, wf WalkFunc, dir, rel string, updateParent bool) ([]string, bool) {
if isBazelIgnored(rel) {
return
return nil, false
}

haveError := false
Expand All @@ -138,7 +143,7 @@ func visit(c *config.Config, cexts []config.Configurer, isBazelIgnored isIgnored
ents, err := os.ReadDir(dir)
if err != nil {
log.Print(err)
return
return nil, false
}

f, err := loadBuildFile(c, rel, dir, ents)
Expand All @@ -152,14 +157,22 @@ func visit(c *config.Config, cexts []config.Configurer, isBazelIgnored isIgnored
haveError = true
}

c = configure(cexts, knownDirectives, c, rel, f)
wc := getWalkConfig(c)
collectionOnly := f == nil && wc.updateOnly

// Configure the current directory if not only collecting files
if !collectionOnly {
c = configure(cexts, knownDirectives, c, rel, f)
wc = getWalkConfig(c)

if wc.isExcluded(rel, ".") {
return
// If the config of this directory has excluded itself
if wc.isExcluded(rel, ".") {
return nil, false
}
}

var subdirs, regularFiles []string
// Divide the directory entries while filtering out ignored/excluded.
var dirs, regularFiles []string
for _, ent := range ents {
base := ent.Name()
if isBazelIgnored(path.Join(rel, base)) || wc.isExcluded(rel, base) {
Expand All @@ -170,24 +183,39 @@ func visit(c *config.Config, cexts []config.Configurer, isBazelIgnored isIgnored
case ent == nil:
continue
case ent.IsDir():
subdirs = append(subdirs, base)
dirs = append(dirs, base)
default:
regularFiles = append(regularFiles, base)
}
}

var subdirs []string

// Visit subdirectories dividing them into `regularFiles` and `subdirs``
shouldUpdate := updateRels.shouldUpdate(rel, updateParent)
for _, sub := range subdirs {
for _, sub := range dirs {
if subRel := path.Join(rel, sub); updateRels.shouldVisit(subRel, shouldUpdate) {
visit(c, cexts, isBazelIgnored, knownDirectives, updateRels, wf, filepath.Join(dir, sub), subRel, shouldUpdate)
subFiles, shouldMerge := visit(c, cexts, isBazelIgnored, knownDirectives, updateRels, wf, filepath.Join(dir, sub), subRel, shouldUpdate)
if shouldMerge {
for _, f := range subFiles {
regularFiles = append(regularFiles, path.Join(sub, f))
}
} else {
subdirs = append(subdirs, sub)
}
}
}

if collectionOnly {
return regularFiles, true
}

update := !haveError && !wc.ignore && shouldUpdate
if updateRels.shouldCall(rel, updateParent) {
genFiles := findGenFiles(wc, f)
wf(dir, rel, c, update, f, subdirs, regularFiles, genFiles)
}
return nil, false
}

// An UpdateFilter tracks which directories need to be updated
Expand Down

0 comments on commit bcf35e8

Please sign in to comment.