Work on adding ignorefiles support to choose-files

This commit is contained in:
Kovid Goyal
2025-07-09 11:54:43 +05:30
parent a341f8b56f
commit 351275cb8c
5 changed files with 200 additions and 19 deletions

View File

@@ -4,6 +4,7 @@ import (
"fmt"
"io"
"io/fs"
"sync"
)
var _ = fmt.Print
@@ -16,10 +17,15 @@ type IgnoreFile interface {
LoadPath(string) error
// relpath is the path relative to the directory containing the ignorefile.
// When is_ignored is true, linenum_of_matching_rule will be the line
// number of the rule causing relpath to be ignored and pattern is the
// textual representation of the matching pattern.
// When the result is due to a rule matching, linenum_of_matching_rule is
// >=0 and pattern is the textual representation of the rule. Otherwise
// linenum_of_matching_rule is -1 and pattern is the empty string.
IsIgnored(relpath string, ftype fs.FileMode) (is_ignored bool, linenum_of_matching_rule int, pattern string)
}
func NewGitignore() IgnoreFile { return &Gitignore{index_of_last_negated_rule: -1} }
// The global gitignore from ~/.config/git/ignore
var GlobalGitignore = sync.OnceValue(func() IgnoreFile {
return get_global_gitignore()
})

View File

@@ -41,8 +41,8 @@ func (g Gitignore) IsIgnored(relpath string, ftype os.FileMode) (is_ignored bool
}
if pat.negated && pat.Match(relpath, ftype) {
is_ignored = false
linenum_of_matching_rule = -1
pattern = ""
linenum_of_matching_rule = pat.line_number
pattern = pat.pattern
}
} else {
if !pat.negated && pat.Match(relpath, ftype) {
@@ -257,3 +257,45 @@ func CompileGitIgnoreLine(line string) (ans GitPattern, skipped_line bool) {
}
return
}
func get_global_gitconfig_excludesfile() (ans string) {
cfhome := os.Getenv("XDG_CONFIG_HOME")
if cfhome == "" {
cfhome = utils.Expanduser("~/.config")
}
for _, candidate := range []string{"/etc/gitconfig", filepath.Join(cfhome, "git", "config"), utils.Expanduser("~/.gitconfig")} {
if data, err := os.ReadFile(candidate); err == nil {
s := utils.NewLineScanner(utils.UnsafeBytesToString(data))
in_core := false
for s.Scan() {
line := strings.TrimSpace(s.Text())
if in_core {
if strings.HasPrefix(line, "[") {
in_core = false
continue
}
if k, rest, found := strings.Cut(line, "="); found && strings.ToLower(strings.TrimSpace(k)) == `excludesfile` {
ans = strings.TrimSpace(rest)
}
} else if strings.ToLower(line) == "[core]" {
in_core = true
}
}
}
}
if ans == "" {
ans = filepath.Join(cfhome, "git", "ignore")
}
return
}
func get_global_gitignore() (ans IgnoreFile) {
excludesfile := get_global_gitconfig_excludesfile()
if data, err := os.ReadFile(excludesfile); err == nil {
q := NewGitignore()
if q.LoadString(utils.UnsafeBytesToString(data)) == nil {
ans = q
}
}
return
}