MCPcopy Index your code
hub / github.com/coder/coder / computeGitDiff

Function computeGitDiff

agent/agentgit/agentgit.go:399–453  ·  view source on GitHub ↗

computeGitDiff produces a unified diff string for the repository by combining `git diff HEAD` (staged + unstaged changes) with diffs for untracked files.

(ctx context.Context, logger slog.Logger, gitBin string, repoRoot string)

Source from the content-addressed store, hash-verified

397// combining `git diff HEAD` (staged + unstaged changes) with diffs
398// for untracked files.
399func computeGitDiff(ctx context.Context, logger slog.Logger, gitBin string, repoRoot string) (string, error) {
400 var diffParts []string
401
402 // Check if the repo has any commits.
403 hasCommits := true
404 checkCmd := exec.CommandContext(ctx, gitBin, "-C", repoRoot, "rev-parse", "HEAD")
405 if err := checkCmd.Run(); err != nil {
406 hasCommits = false
407 }
408
409 if hasCommits {
410 // `git diff HEAD` captures both staged and unstaged changes
411 // relative to HEAD in a single unified diff.
412 cmd := exec.CommandContext(ctx, gitBin, "-C", repoRoot, "diff", "HEAD")
413 out, err := cmd.Output()
414 if err != nil {
415 return "", xerrors.Errorf("git diff HEAD: %w", err)
416 }
417 if len(out) > 0 {
418 diffParts = append(diffParts, string(out))
419 }
420 }
421
422 // Show untracked files as diffs too.
423 // `git ls-files --others --exclude-standard` lists untracked,
424 // non-ignored files.
425 lsCmd := exec.CommandContext(ctx, gitBin, "-C", repoRoot, "ls-files", "--others", "--exclude-standard")
426 lsOut, err := lsCmd.Output()
427 if err != nil {
428 logger.Debug(ctx, "failed to list untracked files", slog.F("root", repoRoot), slog.Error(err))
429 return strings.Join(diffParts, ""), nil
430 }
431
432 untrackedFiles := strings.Split(strings.TrimSpace(string(lsOut)), "\n")
433 for _, f := range untrackedFiles {
434 f = strings.TrimSpace(f)
435 if f == "" {
436 continue
437 }
438 // Use `git diff --no-index /dev/null <file>` to generate
439 // a unified diff for untracked files.
440 var stdout bytes.Buffer
441 untrackedCmd := exec.CommandContext(ctx, gitBin, "-C", repoRoot, "diff", "--no-index", "--", "/dev/null", f)
442 untrackedCmd.Stdout = &stdout
443 // git diff --no-index exits with 1 when files differ,
444 // which is expected. We ignore the error and check for
445 // output instead.
446 _ = untrackedCmd.Run()
447 if stdout.Len() > 0 {
448 diffParts = append(diffParts, stdout.String())
449 }
450 }
451
452 return strings.Join(diffParts, ""), nil
453}

Callers 1

getRepoChangesFunction · 0.85

Calls 7

CommandContextMethod · 0.65
RunMethod · 0.65
OutputMethod · 0.65
ErrorfMethod · 0.45
ErrorMethod · 0.45
LenMethod · 0.45
StringMethod · 0.45

Tested by

no test coverage detected