getCommits method

Future<List<GitCommit>> getCommits(
  1. String projectPath, {
  2. String? fromRef,
  3. String? toRef,
  4. int? maxCount,
})

Fetches a list of structured GitCommit objects.

Implementation

Future<List<GitCommit>> getCommits(
  String projectPath, {
  String? fromRef,
  String? toRef,
  int? maxCount,
}) async {
  final args = <String>[
    'log',
    '--format=%H%x1f%h%x1f%an%x1f%aI%x1f%s%x1f%b%x1e',
  ];

  if (maxCount != null && maxCount > 0) {
    args.add('-n');
    args.add(maxCount.toString());
  }

  final targetTo = toRef ?? 'HEAD';
  if (fromRef != null && fromRef.isNotEmpty) {
    args.add('$fromRef..$targetTo');
  } else {
    args.add(targetTo);
  }

  final result = await _runner.run(
    'git',
    args,
    workingDirectory: projectPath,
  );

  if (result.exitCode != 0) {
    // Fallback if ref range fails
    if (fromRef != null) {
      return getCommits(projectPath, toRef: toRef, maxCount: maxCount ?? 50);
    }
    return [];
  }

  final raw = result.stdout.toString().trim();
  if (raw.isEmpty) return [];

  final records = raw.split('\x1e');
  final commits = <GitCommit>[];

  for (final record in records) {
    final trimmed = record.trim();
    if (trimmed.isEmpty) continue;
    final parts = trimmed.split('\x1f');
    if (parts.length < 5) continue;

    final sha = parts[0].trim();
    final shortSha = parts[1].trim();
    final author = parts[2].trim();
    final dateStr = parts[3].trim();
    final subject = parts[4].trim();
    final body = parts.length > 5 ? parts[5].trim() : '';

    DateTime timestamp;
    try {
      timestamp = DateTime.parse(dateStr);
    } catch (_) {
      timestamp = DateTime.now().toUtc();
    }

    commits.add(
      GitCommit(
        sha: sha,
        shortSha: shortSha,
        subject: subject,
        body: body,
        author: author,
        timestamp: timestamp,
      ),
    );
  }

  return commits;
}