Skip to content

Commit

Permalink
feat: add support for .gitignore
Browse files Browse the repository at this point in the history
  • Loading branch information
jbedard committed Sep 6, 2024
1 parent bbcd2f9 commit cacc420
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 4 deletions.
1 change: 1 addition & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ use_repo(
"com_github_bazelbuild_buildtools",
"com_github_bmatcuk_doublestar_v4",
"com_github_fsnotify_fsnotify",
"com_github_go_git_go_git_v5",
"com_github_google_go_cmp",
"com_github_pmezard_go_difflib",
"org_golang_x_mod",
Expand Down
1 change: 1 addition & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ register_unittest_toolchains()
# gazelle:repository go_repository name=com_github_client9_misspell importpath=github.com/client9/misspell
# gazelle:repository go_repository name=com_github_envoyproxy_go_control_plane importpath=github.com/envoyproxy/go-control-plane
# gazelle:repository go_repository name=com_github_envoyproxy_protoc_gen_validate importpath=github.com/envoyproxy/protoc-gen-validate
# gazelle:repository go_repository name=com_github_go_git_go_git_v5 importpath=github.com/go-git/go-git/v5
# gazelle:repository go_repository name=com_github_fsnotify_fsnotify importpath=github.com/fsnotify/fsnotify
# gazelle:repository go_repository name=com_github_gogo_protobuf importpath=github.com/gogo/protobuf
# gazelle:repository go_repository name=com_github_golang_glog importpath=github.com/golang/glog
Expand Down
7 changes: 7 additions & 0 deletions deps.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,13 @@ def gazelle_dependencies(
sum = "h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=",
version = "v0.1.0",
)
_maybe(
go_repository,
name = "com_github_go_git_go_git_v5",
importpath = "github.com/go-git/go-git/v5",
sum = "h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=",
version = "v5.12.0",
)
_maybe(
go_repository,
name = "com_github_fsnotify_fsnotify",
Expand Down
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
module github.com/bazelbuild/bazel-gazelle

go 1.21
go 1.21.1

toolchain go1.22.4

require (
github.com/bazelbuild/buildtools v0.0.0-20240313121412-66c605173954
github.com/bazelbuild/rules_go v0.46.0
github.com/bmatcuk/doublestar/v4 v4.6.1
github.com/fsnotify/fsnotify v1.7.0
github.com/go-git/go-git/v5 v5.12.0
github.com/google/go-cmp v0.6.0
github.com/pmezard/go-difflib v1.0.0
golang.org/x/mod v0.16.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
Expand Down
3 changes: 3 additions & 0 deletions vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ github.com/bazelbuild/buildtools/build
github.com/bazelbuild/buildtools/tables
# github.com/bazelbuild/rules_go v0.46.0
## explicit; go 1.21.1
github.com/bazelbuild/rules_go/go/runfiles
github.com/bazelbuild/rules_go/go/tools/bazel
github.com/bazelbuild/rules_go/go/tools/bazel_testing
github.com/bazelbuild/rules_go/go/tools/internal/txtar
Expand All @@ -13,6 +14,8 @@ github.com/bmatcuk/doublestar/v4
# github.com/fsnotify/fsnotify v1.7.0
## explicit; go 1.17
github.com/fsnotify/fsnotify
# github.com/go-git/go-git/v5 v5.12.0
## explicit; go 1.19
# github.com/google/go-cmp v0.6.0
## explicit; go 1.13
github.com/google/go-cmp/cmp
Expand Down
1 change: 1 addition & 0 deletions walk/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ go_library(
"//flag",
"//rule",
"@com_github_bmatcuk_doublestar_v4//:doublestar",
"@com_github_go_git_go_git_v5//plumbing/format/gitignore",
],
)

Expand Down
74 changes: 73 additions & 1 deletion walk/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"errors"
"flag"
"fmt"
"io"
"io/fs"
"log"
"os"
Expand All @@ -29,6 +30,7 @@ import (
"github.com/bazelbuild/bazel-gazelle/config"
"github.com/bazelbuild/bazel-gazelle/rule"
"github.com/bmatcuk/doublestar/v4"
"github.com/go-git/go-git/v5/plumbing/format/gitignore"

gzflag "github.com/bazelbuild/bazel-gazelle/flag"
)
Expand All @@ -41,6 +43,9 @@ type walkConfig struct {
excludes []string
ignore bool
follow []string

gitignoreEnabled bool
gitignore *gitignoreEntry
}

const walkName = "_walk"
Expand All @@ -56,6 +61,17 @@ func (wc *walkConfig) isExcluded(rel, base string) bool {
return matchAnyGlob(wc.excludes, path.Join(rel, base))
}

func (wc *walkConfig) isGitIgnored(rel, base string) bool {
// .gitignore
if wc.gitignoreEnabled && wc.gitignore != nil {
if wc.gitignore.isIgnored(strings.Split(path.Join(rel, base), "/")) {
return true
}
}

return false
}

func (wc *walkConfig) shouldFollow(rel, base string) bool {
return matchAnyGlob(wc.follow, path.Join(rel, base))
}
Expand All @@ -73,7 +89,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{"gitignore", "exclude", "follow", "ignore"}
}

func (cr *Configurer) Configure(c *config.Config, rel string, f *rule.File) {
Expand All @@ -99,11 +115,26 @@ func (cr *Configurer) Configure(c *config.Config, rel string, f *rule.File) {
wcCopy.follow = append(wcCopy.follow, path.Join(rel, d.Value))
case "ignore":
wcCopy.ignore = true
case "gitignore":
wcCopy.gitignoreEnabled = d.Value == "on"
}
}
}

c.Exts[walkName] = wcCopy

// TODO: read the gitignore file even if gitignoring is not enabled in this dir
// because it might be enabled in a subdir.
if wcCopy.gitignoreEnabled {
// Collect gitignore style ignore files in this directory.
ignoreFilePath := path.Join(c.RepoRoot, rel, ".gitignore")

// TODO: reuse the fs entry already created by gazelle to avoid os.Open,
// see https://github.com/bazelbuild/bazel-gazelle/pull/1737.
if ignoreReader, ignoreErr := os.Open(ignoreFilePath); ignoreErr == nil {
wcCopy.gitignore = createGitIgnorer(wcCopy.gitignore, rel, ignoreReader)
}
}
}

type isIgnoredFunc = func(string) bool
Expand Down Expand Up @@ -151,6 +182,47 @@ func loadBazelIgnore(repoRoot string) (isIgnoredFunc, error) {
return isIgnored, nil
}

type gitignoreEntry struct {
i *gitignore.Matcher
base string
parent *gitignoreEntry
}

func createGitIgnorer(parent *gitignoreEntry, rel string, ignoreReader io.Reader) *gitignoreEntry {
domain := []string{}
if rel != "" {
domain = strings.Split(rel, "/")
}

matcherPatterns := make([]gitignore.Pattern, 0)

reader := bufio.NewScanner(ignoreReader)
for reader.Scan() {
p := gitignore.ParsePattern(reader.Text(), domain)
matcherPatterns = append(matcherPatterns, p)
}

ignore := gitignore.NewMatcher(matcherPatterns)

return &gitignoreEntry{
i: ignore,
base: rel,
parent: parent,
}
}

func (g *gitignoreEntry) isIgnored(p []string) bool {
if g.i.Match(p) {
return true
}

if g.parent == nil {
return false
}

return g.parent.isIgnored(p)
}

func checkPathMatchPattern(pattern string) error {
_, err := doublestar.Match(pattern, "x")
return err
Expand Down
4 changes: 2 additions & 2 deletions walk/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,14 @@ func visit(c *config.Config, cexts []config.Configurer, isBazelIgnored isIgnored
c = configure(cexts, knownDirectives, c, rel, f)
wc := getWalkConfig(c)

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

var subdirs, regularFiles []string
for _, ent := range ents {
base := ent.Name()
if isBazelIgnored(path.Join(rel, base)) || wc.isExcluded(rel, base) {
if isBazelIgnored(path.Join(rel, base)) || wc.isExcluded(rel, base) || wc.isGitIgnored(rel, base) {
continue
}
ent := resolveFileInfo(wc, dir, rel, ent)
Expand Down

0 comments on commit cacc420

Please sign in to comment.