11#!/usr/bin/env node
22
33import { exec } from "child_process" ;
4- import { readFile , writeFile } from "fs" ;
4+ import { createReadStream , readFile , writeFile } from "fs" ;
5+ import { createInterface } from "readline" ;
56
67/**
78 * Path to an empty file that we can provide to linters/formatters as a config
@@ -39,6 +40,9 @@ const run = (...args: string[]) =>
3940 ) ;
4041 } ) ;
4142
43+ /** Type guard that returns true iff the given value is truthy */
44+ export const isTruthy = < T > (value: T): value is NonNullable< T > => ! ! value ;
45+
4246/** Reads a file, transforms its contents, and writes the result if different */
4347const transformFile = ( path : string , transform : ( before : string ) => string ) =>
4448 new Promise < void > ( ( resolve , reject ) => {
@@ -346,8 +350,32 @@ const HOOKS: Record<HookName, LockableHook> = {
346350 [ HookName . Shfmt ] : createLockableHook ( {
347351 action : async sources => {
348352 // Find source files that are Shell files
349- const shellSources = ( await run ( "/shfmt" , "-f" , ...sources ) ) . trim ( ) ;
350- if ( ! shellSources ) {
353+ const shellSources = (
354+ await Promise . all (
355+ sources . map ( async source => {
356+ // Check file extension
357+ if ( / \. ( b a s h | s h | z s h ) $ / . test ( source ) ) {
358+ return source ;
359+ }
360+
361+ // Check shebang
362+ const firstLine = await new Promise < string > ( resolve => {
363+ // https://stackoverflow.com/a/45556848
364+ const reader = createInterface ( {
365+ input : createReadStream ( source ) ,
366+ } ) ;
367+ reader . on ( "line" , line => {
368+ reader . close ( ) ;
369+ resolve ( line ) ;
370+ } ) ;
371+ } ) ;
372+ if ( / ^ # ! .* \b ( b a s h | s h | z s h ) \b / . test ( firstLine ) ) {
373+ return source ;
374+ }
375+ } ) ,
376+ )
377+ ) . filter ( isTruthy ) ;
378+ if ( ! shellSources . length ) {
351379 return ;
352380 }
353381
@@ -360,7 +388,7 @@ const HOOKS: Record<HookName, LockableHook> = {
360388 "-s" , // Simplify code
361389 "-sr" , // Add space after redirect operators
362390 "-w" , // Write
363- ...shellSources . split ( "\n" ) ,
391+ ...shellSources ,
364392 ) ;
365393 } ,
366394 // pre-commit's `types: [text]` config option sometimes has false positives,
0 commit comments