check for dirty tree without update-index, which is not parallel-safe (#4133)

Signed-off-by: Avi Deitcher <avi@deitcher.net>
This commit is contained in:
Avi Deitcher 2025-06-26 19:53:13 +03:00 committed by GitHub
parent 4df360d62d
commit 254aefc953
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -12,7 +12,6 @@ import (
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings" "strings"
"sync"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@ -28,8 +27,6 @@ type git struct {
dir string dir string
} }
var gitMutex sync.Mutex
// Returns git==nil and no error if the path is not within a git repository // Returns git==nil and no error if the path is not within a git repository
func newGit(dir string) (*git, error) { func newGit(dir string) (*git, error) {
g := &git{dir} g := &git{dir}
@ -183,40 +180,37 @@ func (g git) commitTag(commit string) (string, error) {
} }
func (g git) isDirty(pkg, commit string) (bool, error) { func (g git) isDirty(pkg, commit string) (bool, error) {
// If it isn't HEAD it can't be dirty // Only makes sense to check for HEAD
if commit != "HEAD" { if commit != "HEAD" {
return false, nil return false, nil
} }
// Update cache, otherwise files which have an updated // 1. Check for changes in tracked files (without using update-index)
// timestamp but no actual changes are marked as changes // --no-ext-diff disables any external diff tool
// because `git diff-index` only uses the `lstat` result and // --exit-code makes it return 1 if differences are found
// not the actual file contents. Running `git update-index err := g.command("diff", "--no-ext-diff", "--exit-code", "--quiet", commit, "--", pkg)
// --refresh` updates the cache. if err != nil {
gitMutex.Lock() if _, ok := err.(*exec.ExitError); ok {
if err := g.command("update-index", "-q", "--refresh"); err != nil { // Changes found in tracked files
gitMutex.Unlock() return true, nil
}
// Some actual failure
return false, err return false, err
} }
gitMutex.Unlock()
// diff-index works pretty well, except that // 2. Check for untracked files
err := g.command("diff-index", "--quiet", commit, "--", pkg) _, err = g.commandStdout(nil, "ls-files", "--exclude-standard", "--others", "--error-unmatch", "--", pkg)
if err == nil { if err == nil {
// this returns an error if there are *no* untracked files, which is strange, but we can work with it // Untracked files found
if _, err := g.commandStdout(nil, "ls-files", "--exclude-standard", "--others", "--error-unmatch", "--", pkg); err != nil { return true, nil
}
if _, ok := err.(*exec.ExitError); ok {
// No untracked files — clean
return false, nil return false, nil
} }
return true, nil // Unexpected error
}
switch err.(type) {
case *exec.ExitError:
// diff-index exits with an error if there are differences
return true, nil
default:
return false, err return false, err
} }
}
// goPkgVersion return a version that is compliant with go package versioning. // goPkgVersion return a version that is compliant with go package versioning.
// This would either be: // This would either be: