getRepoChanges reads the current state of a git repository using the git CLI. It returns branch, remote origin, and a unified diff.
(ctx context.Context, logger slog.Logger, gitBin string, repoRoot string)
| 351 | // getRepoChanges reads the current state of a git repository using |
| 352 | // the git CLI. It returns branch, remote origin, and a unified diff. |
| 353 | func getRepoChanges(ctx context.Context, logger slog.Logger, gitBin string, repoRoot string) (codersdk.WorkspaceAgentRepoChanges, error) { |
| 354 | result := codersdk.WorkspaceAgentRepoChanges{ |
| 355 | RepoRoot: repoRoot, |
| 356 | } |
| 357 | |
| 358 | // Verify this is still a valid git repository before doing |
| 359 | // anything else. This catches deleted repos early. |
| 360 | verifyCmd := exec.CommandContext(ctx, gitBin, "-C", repoRoot, "rev-parse", "--git-dir") |
| 361 | if err := verifyCmd.Run(); err != nil { |
| 362 | return result, xerrors.Errorf("not a git repository: %w", err) |
| 363 | } |
| 364 | |
| 365 | // Read branch name. |
| 366 | branchCmd := exec.CommandContext(ctx, gitBin, "-C", repoRoot, "symbolic-ref", "--short", "HEAD") |
| 367 | if out, err := branchCmd.Output(); err == nil { |
| 368 | result.Branch = strings.TrimSpace(string(out)) |
| 369 | } else { |
| 370 | logger.Debug(ctx, "failed to read HEAD", slog.F("root", repoRoot), slog.Error(err)) |
| 371 | } |
| 372 | |
| 373 | // Read remote origin URL. |
| 374 | remoteCmd := exec.CommandContext(ctx, gitBin, "-C", repoRoot, "config", "--get", "remote.origin.url") |
| 375 | if out, err := remoteCmd.Output(); err == nil { |
| 376 | result.RemoteOrigin = strings.TrimSpace(string(out)) |
| 377 | } |
| 378 | |
| 379 | // Compute unified diff. |
| 380 | // `git diff HEAD` shows both staged and unstaged changes vs HEAD. |
| 381 | // For repos with no commits yet, fall back to showing untracked |
| 382 | // files only. |
| 383 | diff, err := computeGitDiff(ctx, logger, gitBin, repoRoot) |
| 384 | if err != nil { |
| 385 | return result, xerrors.Errorf("compute diff: %w", err) |
| 386 | } |
| 387 | |
| 388 | result.UnifiedDiff = diff |
| 389 | if len(result.UnifiedDiff) > maxTotalDiffSize { |
| 390 | result.UnifiedDiff = "Total diff too large to show. Size: " + humanize.IBytes(uint64(len(result.UnifiedDiff))) + ". Showing branch and remote only." |
| 391 | } |
| 392 | |
| 393 | return result, nil |
| 394 | } |
| 395 | |
| 396 | // computeGitDiff produces a unified diff string for the repository by |
| 397 | // combining `git diff HEAD` (staged + unstaged changes) with diffs |
no test coverage detected