When we have multi nested directory and the .gitignore file is inside that. The wroktree.Status() is not respecting patterns inside .gitignore that can cause the git status to dirty.
How to reproduce
Check this repo https://github.com/acumino/git-status. When we run $ go run ./test.go which is basically checking the status and returning an error if status is not clean.
wt, err := repo.Worktree()
if err != nil {
fmt.Printf("failed to get git worktree: %v", err)
}
if stat, err := wt.Status(); err != nil {
fmt.Printf("failed to get git status: %v", err)
} else if !stat.IsClean() {
fmt.Printf("%v\n%v", err, stat)
}
It throws an error and ideally it should not.
?? pp/hh/hack1/configs/authwebhook.yaml
Explanation
The issue is happening because append() is being used for the slice in recursion at line 64.
|
func ReadPatterns(fs billy.Filesystem, path []string) (ps []Pattern, err error) { |
|
ps, _ = readIgnoreFile(fs, path, infoExcludeFile) |
|
|
|
subps, _ := readIgnoreFile(fs, path, gitignoreFile) |
|
ps = append(ps, subps...) |
|
|
|
var fis []os.FileInfo |
|
fis, err = fs.ReadDir(fs.Join(path...)) |
|
if err != nil { |
|
return |
|
} |
|
|
|
for _, fi := range fis { |
|
if fi.IsDir() && fi.Name() != gitDir { |
|
var subps []Pattern |
|
subps, err = ReadPatterns(fs, append(path, fi.Name())) |
|
if err != nil { |
|
return |
|
} |
|
|
|
if len(subps) > 0 { |
|
ps = append(ps, subps...) |
|
} |
|
} |
|
} |
|
|
|
return |
|
} |
The passed value of fs is being changed with appends and is being used as domain here
|
res := pattern{domain: domain} |
So when this fs is updated next time with append it is causing overwrite to previously written domain values leading to previously added pattern's domain to overwritten. So git status basically at the end store wrong pattern to ignore, leading to dirty git status.
An explanation of how slices are passed in function and are used internally golang https://stackoverflow.com/questions/39993688/are-slices-passed-by-value.
Solution
Instead to passing append(path, fi.Name()) in ReadPatterns() every times a new copy of slice should be passed.
When we have multi nested directory and the
.gitignorefile is inside that. Thewroktree.Status()is not respectingpatternsinside.gitignorethat can cause the git status to dirty.How to reproduce
Check this repo https://github.com/acumino/git-status. When we run
$ go run ./test.gowhich is basically checking the status and returning an error ifstatusis not clean.It throws an error and ideally it should not.
Explanation
The issue is happening because
append()is being used for theslicein recursion at line64.go-git/plumbing/format/gitignore/dir.go
Lines 49 to 76 in c785af3
The passed value of
fsis being changed with appends and is being used asdomainherego-git/plumbing/format/gitignore/pattern.go
Line 42 in c785af3
So when this
fsis updated next time with append it is causing overwrite to previously writtendomainvalues leading to previously addedpattern's domain to overwritten. So git status basically at the end store wrong pattern to ignore, leading to dirty git status.An explanation of how slices are passed in function and are used internally
golanghttps://stackoverflow.com/questions/39993688/are-slices-passed-by-value.Solution
Instead to passing
append(path, fi.Name())inReadPatterns()every times a new copy of slice should be passed.