fetchGitDiff function
Fetch git diff stats comparing working tree to HEAD. Returns null if not in a git repo or during transient git states.
Implementation
Future<GitDiffResult?> fetchGitDiff({String? cwd}) async {
if (!await getIsGit(cwd: cwd)) return null;
if (await _isInTransientGitState(cwd: cwd)) return null;
// Quick probe with --shortstat
final shortstat = await _runGit([
'--no-optional-locks',
'diff',
'HEAD',
'--shortstat',
], cwd: cwd);
if (shortstat.code == 0) {
final quickStats = parseShortstat(shortstat.stdout);
if (quickStats != null && quickStats.filesCount > _maxFilesForDetails) {
return GitDiffResult(stats: quickStats, perFileStats: {}, hunks: {});
}
}
// Get stats via --numstat
final numstat = await _runGit([
'--no-optional-locks',
'diff',
'HEAD',
'--numstat',
], cwd: cwd);
if (numstat.code != 0) return null;
final result = parseGitNumstat(numstat.stdout);
final stats = GitDiffStats(
filesCount: result.stats.filesCount,
linesAdded: result.stats.linesAdded,
linesRemoved: result.stats.linesRemoved,
);
final perFileStats = Map<String, PerFileStats>.from(result.perFileStats);
// Include untracked files
final remainingSlots = _maxFiles - perFileStats.length;
if (remainingSlots > 0) {
final untrackedStats = await _fetchUntrackedFiles(remainingSlots, cwd: cwd);
if (untrackedStats != null) {
perFileStats.addAll(untrackedStats);
}
}
return GitDiffResult(
stats: GitDiffStats(
filesCount:
stats.filesCount + (perFileStats.length - result.perFileStats.length),
linesAdded: stats.linesAdded,
linesRemoved: stats.linesRemoved,
),
perFileStats: perFileStats,
hunks: {},
);
}