diffFiles method

Future<List<String>> diffFiles({
  1. required List<String> diffArgs,
  2. required String diffFilters,
})

Implementation

Future<List<String>> diffFiles({
  required List<String> diffArgs,
  required String diffFilters,
}) async {
  final result = await process.run('git', [
    'diff',
    ...diffArgs,
    if (diffFilters.isNotEmpty) '--diff-filter=$diffFilters',
    '--name-only',
    '-z',
  ]);

  if (result.exitCode != 0) {
    // Missing upstream / failed `@{u}` should not fail the hook — treat as
    // no files (e.g. first push of a branch with no remote tracking ref).
    if (diffArgs.contains('@{u}')) {
      if (remoteName case final String remoteName) {
        final currentBranch = await getCurrentBranch();
        final upstream = '$remoteName/$currentBranch';

        logger.detail('git diff with @{u} failed; retrying with $upstream');

        return diffFiles(
          diffArgs: [
            for (final arg in diffArgs)
              if (arg == '@{u}') upstream else arg,
          ],
          diffFilters: diffFilters,
        );
      }

      logger.detail(
        'git diff with @{u} failed and no remote was provided; '
        'treating as empty file list',
      );
      return [];
    }

    logger.detail(
      'git diff failed (exit ${result.exitCode}); treating as empty. '
      'stderr: ${result.stderr}',
    );
    return [];
  }

  final out = switch (result.stdout) {
    final String out => out.trim(),
    final Future<String> out => (await out).trim(),
  };

  return out.split('\x00').where((element) => element.isNotEmpty).toList();
}