fetchSingleFileGitDiff function
Fetch a structured diff for a single file against the merge base.
Implementation
Future<ToolUseDiff?> fetchSingleFileGitDiff(String absoluteFilePath) async {
final gitRoot = findGitRoot(p.dirname(absoluteFilePath));
if (gitRoot == null) return null;
final gitPath = p
.relative(absoluteFilePath, from: gitRoot)
.replaceAll(p.separator, '/');
final repository = getCachedRepository();
// Check if tracked
final lsFiles = await _runGit(
['--no-optional-locks', 'ls-files', '--error-unmatch', gitPath],
cwd: gitRoot,
timeoutMs: _singleFileDiffTimeoutMs,
);
if (lsFiles.code == 0) {
final diffRef = await _getDiffRef(gitRoot);
final diff = await _runGit(
['--no-optional-locks', 'diff', diffRef, '--', gitPath],
cwd: gitRoot,
timeoutMs: _singleFileDiffTimeoutMs,
);
if (diff.code != 0 || diff.stdout.isEmpty) return null;
final parsed = _parseRawDiffToToolUseDiff(gitPath, diff.stdout, 'modified');
return ToolUseDiff(
filename: parsed.filename,
status: parsed.status,
additions: parsed.additions,
deletions: parsed.deletions,
changes: parsed.changes,
patch: parsed.patch,
repository: repository,
);
}
// Untracked - synthetic diff
final synthetic = await _generateSyntheticDiff(gitPath, absoluteFilePath);
if (synthetic == null) return null;
return ToolUseDiff(
filename: synthetic.filename,
status: synthetic.status,
additions: synthetic.additions,
deletions: synthetic.deletions,
changes: synthetic.changes,
patch: synthetic.patch,
repository: repository,
);
}