writeShims method
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;
}