diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2022-03-24 16:30:24 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2022-03-24 17:33:35 +0300 |
commit | eddec48155c974fbc14aed9122a44a7e0e5bdab2 (patch) | |
tree | a50eff01af9ea3a8817126c1b276c5edd93cd0b6 | |
parent | be1bd6724f67a83fb9d4588c8bb613e261684529 (diff) |
housekeeping: Avoid stat calls when searching for broken refs
We use `filepath.Walk()` to search for broken refs, which will stat
every single directory entry we're finding. While this cannot be avoided
for normal files, we also needlessly stat directories.
Convert the function to instead use `filepath.WalkDir()` so that we can
avoid statting directories.
Changelog: performance
-rw-r--r-- | internal/git/housekeeping/clean_stale_data.go | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/internal/git/housekeeping/clean_stale_data.go b/internal/git/housekeeping/clean_stale_data.go index aa48f0e28..39135a5cb 100644 --- a/internal/git/housekeeping/clean_stale_data.go +++ b/internal/git/housekeeping/clean_stale_data.go @@ -309,32 +309,41 @@ func isStaleTemporaryObject(dirEntry fs.DirEntry) (bool, error) { } func findBrokenLooseReferences(ctx context.Context, repoPath string) ([]string, error) { - logger := myLogger(ctx) - var brokenRefs []string - err := filepath.Walk(filepath.Join(repoPath, "refs"), func(path string, info os.FileInfo, err error) error { - if info == nil { - logger.WithFields(log.Fields{ - "path": path, - }).WithError(err).Error("nil FileInfo in housekeeping.Perform") + if err := filepath.WalkDir(filepath.Join(repoPath, "refs"), func(path string, dirEntry fs.DirEntry, err error) error { + if err != nil { + if errors.Is(err, fs.ErrPermission) || errors.Is(err, fs.ErrNotExist) { + return nil + } + return err + } + if dirEntry.IsDir() { return nil } + fi, err := dirEntry.Info() + if err != nil { + if errors.Is(err, fs.ErrNotExist) { + return nil + } + + return fmt.Errorf("statting loose ref: %w", err) + } + // When git crashes or a node reboots, it may happen that it leaves behind empty // references. These references break various assumptions made by git and cause it // to error in various circumstances. We thus clean them up to work around the // issue. - if info.IsDir() || info.Size() > 0 || time.Since(info.ModTime()) < brokenRefsGracePeriod { + if fi.Size() > 0 || time.Since(fi.ModTime()) < brokenRefsGracePeriod { return nil } brokenRefs = append(brokenRefs, path) return nil - }) - if err != nil { - return nil, err + }); err != nil { + return nil, fmt.Errorf("walking references: %w", err) } return brokenRefs, nil |