Skip to content

Commit 2a74e0b

Browse files
manual gc
1 parent d6692a4 commit 2a74e0b

2 files changed

Lines changed: 42 additions & 0 deletions

File tree

git-sensor/internals/Configuration.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type Configuration struct {
2929
CliCmdTimeoutGlobal int `env:"CLI_CMD_TIMEOUT_GLOBAL_SECONDS" envDefault:"900"`
3030
CliCmdTimeoutJson string `env:"CLI_CMD_TIMEOUT_JSON" envDefault:""`
3131
GoGitTimeout int `env:"GOGIT_TIMEOUT_SECONDS" envDefault:"10" `
32+
EnableManualGitGc bool `env:"ENABLE_MANUAL_GIT_GC" envDefault:"false"`
3233
}
3334

3435
func ParseConfiguration() (*Configuration, error) {

git-sensor/pkg/git/GitBaseManager.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,9 @@ func (impl *GitManagerBaseImpl) createCmdWithContext(ctx GitContext, name string
387387
//TODO: how to make it generic, currently works because the
388388
// git command is placed at index 2 for current implementations
389389
timeout := 0
390+
command := ""
390391
if len(arg) > 2 {
392+
command = arg[2]
391393
timeout = impl.getCommandTimeout(arg[2])
392394
}
393395
if timeout > 0 {
@@ -406,6 +408,13 @@ func (impl *GitManagerBaseImpl) createCmdWithContext(ctx GitContext, name string
406408
} else {
407409
impl.logger.Infow("sucess cancel command", "name", name, "arg", arg)
408410
}
411+
412+
// Run git gc --prune=now to clean up temp.pack files left by killed git commands
413+
if impl.conf.EnableManualGitGc && name == "git" && command == "fetch" {
414+
if rootDir := impl.extractRootDirFromArgs(arg); rootDir != "" {
415+
impl.runGitGcWithTimeout(rootDir, 5*time.Minute)
416+
}
417+
}
409418
return err
410419
}
411420
return cmd, newCtx, cancel
@@ -431,3 +440,35 @@ func (impl *GitManagerBaseImpl) ExecuteCustomCommand(gitContext GitContext, name
431440
output, errMsg, err := impl.runCommandWithCred(cmd, newGitCtx, gitContext.Username, gitContext.Password, tlsPathInfo)
432441
return output, errMsg, err
433442
}
443+
444+
// extractRootDirFromArgs extracts the root directory from git command arguments.
445+
// It looks for the -C flag which specifies the directory to run git commands in.
446+
func (impl *GitManagerBaseImpl) extractRootDirFromArgs(args []string) string {
447+
for i, arg := range args {
448+
if arg == "-C" && i+1 < len(args) {
449+
return args[i+1]
450+
}
451+
}
452+
return ""
453+
}
454+
455+
// runGitGcWithTimeout runs git gc --prune=now with a timeout to clean up
456+
// temporary pack files left behind when git commands are killed/cancelled.
457+
func (impl *GitManagerBaseImpl) runGitGcWithTimeout(rootDir string, timeout time.Duration) {
458+
ctx, cancel := context.WithTimeout(context.Background(), timeout)
459+
defer cancel()
460+
461+
impl.logger.Infow("running git gc --prune=now", "rootDir", rootDir, "timeout", timeout)
462+
cmd := exec.CommandContext(ctx, "git", "-C", rootDir, "gc", "--prune=now")
463+
cmd.Env = append(os.Environ(), "HOME=/dev/null")
464+
output, err := cmd.CombinedOutput()
465+
if err != nil {
466+
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
467+
impl.logger.Warnw("git gc timed out", "rootDir", rootDir, "timeout", timeout)
468+
} else {
469+
impl.logger.Errorw("error running git gc", "rootDir", rootDir, "err", err, "output", string(output))
470+
}
471+
} else {
472+
impl.logger.Infow("git gc completed successfully", "rootDir", rootDir)
473+
}
474+
}

0 commit comments

Comments
 (0)