Skip to content

Commit bc4c1f2

Browse files
authored
Merge pull request #4 from keith/ks/respect-gitignore-files-from-more-places
Respect gitignore files from more places
2 parents 708d649 + 8f642b1 commit bc4c1f2

2 files changed

Lines changed: 88 additions & 11 deletions

File tree

‎internal/godemon/godemon.go‎

Lines changed: 61 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,24 @@ func addGitignorePatterns(cfg *Config, path string) error {
357357
}
358358
repoPath := *optRepoPath
359359
debugf("git repo path for %q: %q", path, repoPath)
360+
361+
globalExcludesPath, err := gitConfigPath(repoPath, "core.excludesFile")
362+
if err != nil {
363+
debugf("Could not determine global Git excludes file: %s", err)
364+
} else if globalExcludesPath != "" {
365+
if err := addGitignoreFilePatterns(cfg, globalExcludesPath, repoPath); err != nil {
366+
return err
367+
}
368+
}
369+
infoExcludesPath, err := gitPath(repoPath, "info/exclude")
370+
if err != nil {
371+
debugf("Could not determine repository Git excludes file: %s", err)
372+
} else {
373+
if err := addGitignoreFilePatterns(cfg, infoExcludesPath, repoPath); err != nil {
374+
return err
375+
}
376+
}
377+
360378
ls := exec.Command("git", "ls-files", "--cached", "--modified", "--others")
361379
ls.Dir = repoPath
362380
stdout := bytes.NewBuffer(nil)
@@ -375,24 +393,56 @@ func addGitignorePatterns(cfg *Config, path string) error {
375393
}
376394
}
377395
for _, gitignoreRelPath := range gitignorePaths {
378-
// TODO: Use `git ls-files` to find all .gitignore paths in the repo, and
379-
// incorporate those too.
380396
gitignorePath := filepath.Join(repoPath, gitignoreRelPath)
381-
b, err := os.ReadFile(gitignorePath)
382-
if err != nil {
383-
if os.IsNotExist(err) {
384-
return nil
385-
}
397+
if err := addGitignoreFilePatterns(cfg, gitignorePath, filepath.Dir(gitignorePath)); err != nil {
386398
return err
387399
}
388-
debugf("Reading .gitignore patterns from %s", gitignorePath)
389-
debugf("Raw .gitignore contents: %s", string(b))
390-
patterns := parseGitignore(b, filepath.Dir(gitignorePath))
391-
cfg.ignorePatterns = append(cfg.ignorePatterns, patterns...)
392400
}
393401
return nil
394402
}
395403

404+
func gitConfigPath(repoPath, key string) (string, error) {
405+
cmd := exec.Command("git", "config", "--path", "--get", key)
406+
cmd.Dir = repoPath
407+
out, err := cmd.Output()
408+
if err != nil {
409+
if exitErr, ok := err.(*exec.ExitError); ok && exitErr.ExitCode() == 1 {
410+
return "", nil
411+
}
412+
return "", fmt.Errorf("git config --get %s failed: %w", key, err)
413+
}
414+
return strings.TrimSpace(string(out)), nil
415+
}
416+
417+
func gitPath(repoPath, path string) (string, error) {
418+
cmd := exec.Command("git", "rev-parse", "--git-path", path)
419+
cmd.Dir = repoPath
420+
out, err := cmd.Output()
421+
if err != nil {
422+
return "", fmt.Errorf("git rev-parse --git-path %s failed: %w", path, err)
423+
}
424+
gitPath := strings.TrimSpace(string(out))
425+
if !filepath.IsAbs(gitPath) {
426+
gitPath = filepath.Join(repoPath, gitPath)
427+
}
428+
return gitPath, nil
429+
}
430+
431+
func addGitignoreFilePatterns(cfg *Config, path, parentDirPath string) error {
432+
b, err := os.ReadFile(path)
433+
if err != nil {
434+
if os.IsNotExist(err) {
435+
return nil
436+
}
437+
return err
438+
}
439+
debugf("Reading git ignore patterns from %s", path)
440+
debugf("Raw git ignore contents: %s", string(b))
441+
patterns := parseGitignore(b, parentDirPath)
442+
cfg.ignorePatterns = append(cfg.ignorePatterns, patterns...)
443+
return nil
444+
}
445+
396446
func parseGitignore(b []byte, parentDirPath string) []*pattern {
397447
var patterns []*pattern
398448
lines := strings.Split(string(b), "\n")

‎internal/godemon/godemon_test.go‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,33 @@ func TestGitignoreInChildDirectory(t *testing.T) {
699699
expectRunCount(t, ctx, ws, 1)
700700
}
701701

702+
func TestGlobalGitignore(t *testing.T) {
703+
root := t.TempDir()
704+
globalIgnorePath := filepath.Join(root, "global-ignore")
705+
writeFile(t, root, "global-ignore", "tags\n")
706+
707+
globalConfigPath := filepath.Join(root, "global-gitconfig")
708+
config := exec.Command("git", "config", "--file", globalConfigPath, "core.excludesFile", globalIgnorePath)
709+
if out, err := config.CombinedOutput(); err != nil {
710+
t.Fatalf("configure global excludes file: %s: %s", err, out)
711+
}
712+
t.Setenv("GIT_CONFIG_GLOBAL", globalConfigPath)
713+
t.Setenv("GIT_CONFIG_NOSYSTEM", "1")
714+
715+
ws := newTestWorkspace(t)
716+
cfg, err := parseConfig([]string{"godemon", "--watch", ws, "true"})
717+
if err != nil {
718+
t.Fatal(err)
719+
}
720+
g := &godemon{cfg: cfg}
721+
if !g.shouldIgnore(filepath.Join(ws, "tags")) {
722+
t.Fatal("global core.excludesFile pattern did not ignore tags")
723+
}
724+
if g.shouldIgnore(filepath.Join(ws, "watched.go")) {
725+
t.Fatal("global core.excludesFile ignored an unrelated path")
726+
}
727+
}
728+
702729
func TestSendSIGINTToSleepCommandTerminates(t *testing.T) {
703730
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
704731
defer cancel()

0 commit comments

Comments
 (0)