writeShims method

int writeShims(
  1. List<String> executables, {
  2. required String managedHooksDir,
})

Writes thin shims into managedHooksDir that exec compiled binaries.

Does not touch .git/hooks. Clears previous managed shims while preserving .gitignore / README.md.

Implementation

int writeShims(List<String> executables, {required String managedHooksDir}) {
  final hooksDir = fs.directory(managedHooksDir);

  if (hooksDir.existsSync()) {
    for (final entity in hooksDir.listSync()) {
      final name = fs.path.basename(entity.path);
      if (name == '.gitignore' || name == 'README.md') continue;
      entity.deleteSync(recursive: true);
    }
  } else {
    hooksDir.createSync(recursive: true);
  }

  final gitignore = hooksDir.childFile('.gitignore');
  if (!gitignore.existsSync()) {
    gitignore.writeAsStringSync('*\n!.gitignore\n!README.md\n');
  }

  final readme = hooksDir.childFile('README.md');
  if (!readme.existsSync()) {
    readme.writeAsStringSync(
      '# Managed by hooksman\n\n'
      'Do not edit files in this directory. Shims are regenerated by '
      '`dart run hooksman register`.\n\n'
      'After cloning, run register so `.dart_tool/hooksman/executables/` '
      'exists; these shims invoke those binaries.\n',
    );
  }

  for (final exe in executables) {
    final name = fs.path.basename(exe).toParamCase();
    final shimPath = fs.path.join(hooksDir.path, name);
    // Relative from hooks/_/<name> → .dart_tool/hooksman/executables/<name>
    final relativeBin = '../../.dart_tool/hooksman/executables/$name'
        .replaceAll(r'\', '/');

    final shim =
        '''
#!/usr/bin/env sh
# Generated by hooksman — do not edit
[ "\${HOOKSMAN-}" = "0" ] && exit 0
[ "\${SKIP-}" = "1" ] && exit 0
[ "\${SKIP-}" = "true" ] && exit 0

DIR="\$(CDPATH= cd -- "\$(dirname "\$0")" && pwd)"
exec "\$DIR/$relativeBin" "\$@"
''';

    fs.file(shimPath)
      ..createSync(recursive: true)
      ..writeAsStringSync(shim);

    if (!Platform.isWindows) {
      Process.runSync('chmod', ['+x', shimPath]);
    }
  }

  return 0;
}