Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

worktree.Status() not respecting .gitignore #500

Closed
acumino opened this issue Mar 24, 2022 · 8 comments
Closed

worktree.Status() not respecting .gitignore #500

acumino opened this issue Mar 24, 2022 · 8 comments

Comments

@acumino
Copy link

acumino commented Mar 24, 2022

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.

@acumino
Copy link
Author

acumino commented Mar 24, 2022

cc - @mcuadros

@sourcec0de
Copy link

sourcec0de commented Apr 5, 2022

I was trying to follow along here because I had a similar theory.
https://go.dev/play/p/pjtX_coRiQ8

package main

import "fmt"

func recurse(a []string) []string {
	if len(a) == 3 {
		return a
	}

	return recurse(append(a, "test"))
}

func main() {
	a := []string{"a"}
	b := recurse(a)
	fmt.Println(a, b)
}

My assumption was that because Go slices are pass-by-value that a and b would have the same contents.
They do not in this case. This program evaluated to.

[a] [a test test]

Program exited.

The return value of append will be a slice that points to the newly allocated array.
I could be widely misunderstanding the issue though.

@acumino
Copy link
Author

acumino commented Apr 5, 2022

Please check this issue golang/go#52152 for examples.

@acumino
Copy link
Author

acumino commented Apr 5, 2022

As suggested in the issue golang/go#52152 there is nothing that can be done from the go side.
If needed I can open a PR with a possible workaround.

@TopherIsSwell
Copy link

@acumino , I have no association with this repo, but I think a PR would be welcome. Do you have a fork with your copy-based workaround?

I've run into the issue where there's a large directory (~300M of contents) that is in the .gitignore file. The worktree.Status() call takes anywhere from 1.6s (with repeated calls so that the kernel is caching the directory contents I'm guessing), to 15s,
whereas if I delete that directory, the call takes ~300ms (with repeated calls).

For comparison, the git status command returns in <20ms

I'm guessing respecting the .gitignore would be a non-trivial performance improvement.

@tisonkun
Copy link

tisonkun commented Sep 4, 2022

@acumino another issue I spot on .gitignore is that a global .gitignore doesn't take effect.

@jghal
Copy link

jghal commented Oct 20, 2022

I think I'm seeing the same as @tisonkun, with my attempts at debugging reported here. Copying my gitignore file into the directory that I've specified as the Path in my Add/AddOptions doesn't seem to have any impact though.

@mieubrisse
Copy link

as @tisonkun mentioned, we're seeing the same issue in #597

@pjbgf pjbgf closed this as completed in 80d5f72 May 29, 2023
pjbgf added a commit that referenced this issue May 29, 2023
plumbing: gitignore, fix incorrect parsing. Fixes #500
durandj pushed a commit to durandj/go-git that referenced this issue Jul 1, 2023
Signed-off-by: Arieh Schneier <15041913+AriehSchneier@users.noreply.github.com>
acumino added a commit to acumino/gardener that referenced this issue Sep 7, 2023
gardener-prow bot pushed a commit to gardener/gardener that referenced this issue Sep 7, 2023
* Remove deprecated `AnalyzerPlugin`

* Update go-apidiff

Fix of - go-git/go-git#500

* Update skaffold
nickytd pushed a commit to nickytd/gardener that referenced this issue Sep 11, 2023
* Remove deprecated `AnalyzerPlugin`

* Update go-apidiff

Fix of - go-git/go-git#500

* Update skaffold
acumino added a commit to acumino/controller-runtime that referenced this issue Sep 27, 2023
It brings the fix for go-git/go-git#500
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants