diff --git a/gitcmds/hook.go b/gitcmds/hook.go index a1fe6db..942c647 100644 --- a/gitcmds/hook.go +++ b/gitcmds/hook.go @@ -57,7 +57,7 @@ func SetLocalPreCommitHook(wd string) error { _ = f.Close() if !largeFileHookExist(PreCommitFilePath) { - return fillPreCommitFile(wd, PreCommitFilePath) + return fillPreCommitFile(dir, PreCommitFilePath) } return nil @@ -84,7 +84,7 @@ func createOrOpenFile(filepath string) (*os.File, error) { return f, nil } -func fillPreCommitFile(wd, myFilePath string) error { +func fillPreCommitFile(rootDir, myFilePath string) error { fPreCommit, err := createOrOpenFile(myFilePath) if err != nil { return err @@ -93,12 +93,7 @@ func fillPreCommitFile(wd, myFilePath string) error { _ = fPreCommit.Close() }() - dir, err := GetRootFolder(wd) - if err != nil { - return err - } - fName := "/.git/hooks/" + LargeFileHookFilename - lfPath := dir + fName + lfPath := rootDir + "/.git/hooks/" + LargeFileHookFilename lf, err := os.Create(lfPath) if err != nil { @@ -123,14 +118,8 @@ func fillPreCommitFile(wd, myFilePath string) error { return new(exec.PipedExec).Command("chmod", "+x", myFilePath).Run(os.Stdout, os.Stdout) } -// isLargeFileHookContentUpToDate checks if the current large-file-hook.sh content matches the expected content -func isLargeFileHookContentUpToDate(wd string) (bool, error) { - dir, err := GetRootFolder(wd) - if err != nil { - return false, err - } - - hookPath := filepath.Join(dir, ".git", "hooks", LargeFileHookFilename) +func isLargeFileHookContentUpToDate(rootDir string) (bool, error) { + hookPath := filepath.Join(rootDir, ".git", "hooks", LargeFileHookFilename) // Check if the file exists if _, err := os.Stat(hookPath); os.IsNotExist(err) { @@ -147,14 +136,8 @@ func isLargeFileHookContentUpToDate(wd string) (bool, error) { return string(currentContent) == largeFileHookContent, nil } -// updateLargeFileHookContent updates the large-file-hook.sh file with the current content -func updateLargeFileHookContent(wd string) error { - dir, err := GetRootFolder(wd) - if err != nil { - return err - } - - hookPath := filepath.Join(dir, ".git", "hooks", LargeFileHookFilename) +func updateLargeFileHookContent(rootDir string) error { + hookPath := filepath.Join(rootDir, ".git", "hooks", LargeFileHookFilename) // Create or overwrite the hook file lf, err := os.Create(hookPath) @@ -172,17 +155,18 @@ func updateLargeFileHookContent(wd string) error { return nil } -// EnsureLargeFileHookUpToDate checks and updates the large file hook if needed func EnsureLargeFileHookUpToDate(wd string) error { - upToDate, err := isLargeFileHookContentUpToDate(wd) + rootDir, err := GetRootFolder(wd) + if err != nil { + return err + } + upToDate, err := isLargeFileHookContentUpToDate(rootDir) if err != nil { return err } - if !upToDate { - return updateLargeFileHookContent(wd) + return updateLargeFileHookContent(rootDir) } - return nil } @@ -196,29 +180,20 @@ func getGlobalHookFolder() string { return strings.TrimSpace(stdout) } -func getLocalHookFolder(wd string) (string, error) { - dir, err := GetRootFolder(wd) - if err != nil { - return "", err - } - filename := "/.git/hooks/pre-commit" - filepath := dir + filename - - return strings.TrimSpace(filepath), nil +func getLocalHookFolder(rootDir string) string { + return rootDir + "/.git/hooks/pre-commit" } -// LocalPreCommitHookExist - s.e. func LocalPreCommitHookExist(wd string) (bool, error) { - filepath, err := getLocalHookFolder(wd) + rootDir, err := GetRootFolder(wd) if err != nil { return false, err } - // Check if the file already exists - if _, err := os.Stat(filepath); os.IsNotExist(err) { + fp := getLocalHookFolder(rootDir) + if _, err := os.Stat(fp); os.IsNotExist(err) { return false, nil } - - return largeFileHookExist(filepath), nil + return largeFileHookExist(fp), nil } func largeFileHookExist(filepath string) bool { @@ -262,13 +237,16 @@ func SetGlobalPreCommitHook(wd string) error { _ = f.Close() if !largeFileHookExist(filepath) { - return fillPreCommitFile(wd, filepath) + rootDir, err := GetRootFolder(wd) + if err != nil { + return err + } + return fillPreCommitFile(rootDir, filepath) } return nil } - func GetRootFolder(wd string) (string, error) { stdout, _, err := new(exec.PipedExec). Command(git, "rev-parse", "--show-toplevel"). @@ -279,4 +257,4 @@ func GetRootFolder(wd string) (string, error) { } return strings.TrimSpace(stdout), nil -} \ No newline at end of file +} diff --git a/gitcmds/status.go b/gitcmds/status.go index 0b180a2..ce38ae1 100644 --- a/gitcmds/status.go +++ b/gitcmds/status.go @@ -158,7 +158,7 @@ func getListOfChangedFiles(wd, statusOutput string) ([]fileInfo, error) { case `M`, `MM`, `RM`: newFileSize, err1 = getFileSize(wd, name) oldSize, err2 = getFileSizeFromHEAD(wd, gitDir, oldName) - case `D`: + case `D`, `MD`: oldSize, err2 = getFileSizeFromHEAD(wd, gitDir, oldName) case `R`: newFileSize, err1 = getFileSize(wd, name) diff --git a/uspecs/changes/archive/2602/2602222051-reduce-getrootfolder-calls/change.md b/uspecs/changes/archive/2602/2602222051-reduce-getrootfolder-calls/change.md new file mode 100644 index 0000000..f5b2645 --- /dev/null +++ b/uspecs/changes/archive/2602/2602222051-reduce-getrootfolder-calls/change.md @@ -0,0 +1,21 @@ +--- +registered_at: 2026-02-22T20:44:12Z +change_id: 2602222044-reduce-getrootfolder-calls +baseline: 54f427c0ff88495738c2b33ea386f73b080bde9d +archived_at: 2026-02-23T02:41:38Z +--- + +# Change request: Reduce redundant GetRootFolder calls in hook.go + +## Why + +`GetRootFolder()` spawns a `git rev-parse --show-toplevel` subprocess each time it is called. In `gitcmds/hook.go` it is called 5 times, but several calls are redundant within the same call chain — the result is already available from a caller up the stack. + +## What + +Eliminate redundant `GetRootFolder()` calls in `gitcmds/hook.go` by passing the already-resolved root dir down the call chain: + +- `fillPreCommitFile`: accept `rootDir` parameter instead of calling `GetRootFolder` (caller `SetLocalPreCommitHook` and `SetGlobalPreCommitHook` already have it or can obtain it once) +- `isLargeFileHookContentUpToDate` and `updateLargeFileHookContent`: accept `rootDir` parameter instead of calling `GetRootFolder`; `EnsureLargeFileHookUpToDate` calls `GetRootFolder` once and passes it to both +- `getLocalHookFolder`: accept `rootDir` parameter instead of calling `GetRootFolder` (caller `LocalPreCommitHookExist` obtains it) +- Net result: 5 calls reduced to 3 (one each in `SetLocalPreCommitHook`, `EnsureLargeFileHookUpToDate`, `LocalPreCommitHookExist`) diff --git a/uspecs/changes/archive/2602/2602222051-reduce-getrootfolder-calls/impl.md b/uspecs/changes/archive/2602/2602222051-reduce-getrootfolder-calls/impl.md new file mode 100644 index 0000000..2ffc511 --- /dev/null +++ b/uspecs/changes/archive/2602/2602222051-reduce-getrootfolder-calls/impl.md @@ -0,0 +1,19 @@ +# Implementation plan: Reduce redundant GetRootFolder calls in hook.go + +## Construction + +- [x] update: [gitcmds/hook.go](../../../../../gitcmds/hook.go) + - refactor: `fillPreCommitFile` — replace `wd` param with `rootDir`, remove internal `GetRootFolder` call + - refactor: `isLargeFileHookContentUpToDate` — replace `wd` param with `rootDir`, remove internal `GetRootFolder` call + - refactor: `updateLargeFileHookContent` — replace `wd` param with `rootDir`, remove internal `GetRootFolder` call + - refactor: `getLocalHookFolder` — replace `wd` param with `rootDir`, remove internal `GetRootFolder` call + - refactor: `EnsureLargeFileHookUpToDate` — call `GetRootFolder` once, pass result to `isLargeFileHookContentUpToDate` and `updateLargeFileHookContent` + - refactor: `SetLocalPreCommitHook` — pass existing `dir` to `fillPreCommitFile` + - refactor: `SetGlobalPreCommitHook` — call `GetRootFolder` once, pass result to `fillPreCommitFile` + - refactor: `LocalPreCommitHookExist` — call `GetRootFolder` once, pass result to `getLocalHookFolder` + +### Tests + +- [x] review: `go build ./...` compiles without errors +- [x] review: `go vet ./...` passes without errors +