Skip to content

Commit

Permalink
perf: reduce path.join invocations
Browse files Browse the repository at this point in the history
  • Loading branch information
jbedard committed Aug 22, 2024
1 parent 4d93f01 commit a3d1b7c
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 29 deletions.
32 changes: 13 additions & 19 deletions walk/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"os"
"path"
"strings"
"sync"

"github.com/bazelbuild/bazel-gazelle/config"
"github.com/bazelbuild/bazel-gazelle/rule"
Expand All @@ -42,7 +41,6 @@ type walkConfig struct {
excludes []string
ignore bool
follow []string
loadOnce *sync.Once
}

const walkName = "_walk"
Expand All @@ -51,23 +49,23 @@ func getWalkConfig(c *config.Config) *walkConfig {
return c.Exts[walkName].(*walkConfig)
}

func (wc *walkConfig) isExcluded(rel, base string) bool {
if base == ".git" {
func (wc *walkConfig) isExcluded(p string) bool {
if strings.HasPrefix(p, ".git") && (len(p) < 5 || p[4] == '/') {
return true
}
return matchAnyGlob(wc.excludes, path.Join(rel, base))
return matchAnyGlob(wc.excludes, p)
}

func (wc *walkConfig) shouldFollow(rel, base string) bool {
return matchAnyGlob(wc.follow, path.Join(rel, base))
func (wc *walkConfig) shouldFollow(p string) bool {
return matchAnyGlob(wc.follow, p)
}

var _ config.Configurer = (*Configurer)(nil)

type Configurer struct{}

func (*Configurer) RegisterFlags(fs *flag.FlagSet, cmd string, c *config.Config) {
wc := &walkConfig{loadOnce: &sync.Once{}}
wc := &walkConfig{}
c.Exts[walkName] = wc
fs.Var(&gzflag.MultiFlag{Values: &wc.excludes}, "exclude", "pattern that should be ignored (may be repeated)")
}
Expand All @@ -84,12 +82,6 @@ func (cr *Configurer) Configure(c *config.Config, rel string, f *rule.File) {
*wcCopy = *wc
wcCopy.ignore = false

wc.loadOnce.Do(func() {
if err := cr.loadBazelIgnore(c.RepoRoot, wcCopy); err != nil {
log.Printf("error loading .bazelignore: %v", err)
}
})

if f != nil {
for _, d := range f.Directives {
switch d.Key {
Expand All @@ -114,17 +106,19 @@ func (cr *Configurer) Configure(c *config.Config, rel string, f *rule.File) {
c.Exts[walkName] = wcCopy
}

func (c *Configurer) loadBazelIgnore(repoRoot string, wc *walkConfig) error {
func loadBazelIgnore(repoRoot string) (map[string]struct{}, error) {
ignorePath := path.Join(repoRoot, ".bazelignore")
file, err := os.Open(ignorePath)
if errors.Is(err, fs.ErrNotExist) {
return nil
return nil, nil
}
if err != nil {
return fmt.Errorf(".bazelignore exists but couldn't be read: %v", err)
return nil, fmt.Errorf(".bazelignore exists but couldn't be read: %v", err)
}
defer file.Close()

excludes := make(map[string]struct{})

scanner := bufio.NewScanner(file)
for scanner.Scan() {
ignore := strings.TrimSpace(scanner.Text())
Expand All @@ -142,9 +136,9 @@ func (c *Configurer) loadBazelIgnore(repoRoot string, wc *walkConfig) error {
// the exclude matching won't work correctly.
ignore = path.Clean(ignore)

wc.excludes = append(wc.excludes, ignore)
excludes[ignore] = struct{}{}
}
return nil
return excludes, nil
}

func checkPathMatchPattern(pattern string) error {
Expand Down
36 changes: 26 additions & 10 deletions walk/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ func Walk(c *config.Config, cexts []config.Configurer, dirs []string, mode Mode,

updateRels := NewUpdateFilter(c.RepoRoot, dirs, mode)

bazelExcludes, bazelExcludesErr := loadBazelIgnore(c.RepoRoot)
if bazelExcludesErr != nil {
log.Printf("error loading .bazelignore: %v", bazelExcludesErr)
}

var visit func(*config.Config, string, string, bool)
visit = func(c *config.Config, dir, rel string, updateParent bool) {
haveError := false
Expand All @@ -142,16 +147,31 @@ func Walk(c *config.Config, cexts []config.Configurer, dirs []string, mode Mode,
}

c = configure(cexts, knownDirectives, c, rel, f)

if _, bazelExcluded := bazelExcludes[rel]; bazelExcluded {
return
}

wc := getWalkConfig(c)

if wc.isExcluded(rel, ".") {
if wc.isExcluded(rel) {
return
}

var subdirs, regularFiles []string
for _, ent := range ents {
base := ent.Name()
ent := resolveFileInfo(wc, dir, rel, ent)
relBase := path.Join(rel, base)

if _, bazelExcluded := bazelExcludes[relBase]; bazelExcluded {
continue
}

if wc.isExcluded(relBase) {
continue
}

ent := resolveFileInfo(wc, c.RepoRoot, relBase, ent)
switch {
case ent == nil:
continue
Expand Down Expand Up @@ -317,27 +337,23 @@ func findGenFiles(wc *walkConfig, f *rule.File) []string {

var genFiles []string
for _, s := range strs {
if !wc.isExcluded(f.Pkg, s) {
if !wc.isExcluded(path.Join(f.Pkg, s)) {
genFiles = append(genFiles, s)
}
}
return genFiles
}

func resolveFileInfo(wc *walkConfig, dir, rel string, ent fs.DirEntry) fs.DirEntry {
base := ent.Name()
if base == "" || wc.isExcluded(rel, base) {
return nil
}
func resolveFileInfo(wc *walkConfig, dir, repoRel string, ent fs.DirEntry) fs.DirEntry {
if ent.Type()&os.ModeSymlink == 0 {
// Not a symlink, use the original FileInfo.
return ent
}
if !wc.shouldFollow(rel, ent.Name()) {
if !wc.shouldFollow(repoRel) {
// A symlink, but not one we should follow.
return nil
}
fi, err := os.Stat(path.Join(dir, base))
fi, err := os.Stat(path.Join(dir, repoRel))
if err != nil {
// A symlink, but not one we could resolve.
return nil
Expand Down

0 comments on commit a3d1b7c

Please sign in to comment.