11#!/usr/bin/env node
22
3- import { readFile , readdir , stat } from 'node:fs/promises' ;
3+ import { lstat , readFile , readdir , readlink } from 'node:fs/promises' ;
44import { basename , join } from 'node:path' ;
55
66const roots = process . argv . slice ( 2 ) ;
@@ -37,9 +37,15 @@ const forbiddenPatterns = [
3737] ;
3838
3939const files = [ ] ;
40+ const symlinks = [ ] ;
4041
4142async function collect ( path ) {
42- const metadata = await stat ( path ) ;
43+ const metadata = await lstat ( path ) ;
44+ if ( metadata . isSymbolicLink ( ) ) {
45+ symlinks . push ( { path, target : await readlink ( path ) } ) ;
46+ return ;
47+ }
48+
4349 if ( ! metadata . isDirectory ( ) ) {
4450 files . push ( path ) ;
4551 return ;
@@ -53,25 +59,37 @@ async function collect(path) {
5359for ( const root of roots ) await collect ( root ) ;
5460
5561const failures = [ ] ;
62+ function scanContent ( path , content ) {
63+ for ( const [ needle , label ] of forbiddenContent ) {
64+ if ( content . includes ( Buffer . from ( needle ) ) ) failures . push ( `${ path } : contains ${ label } ` ) ;
65+ }
66+ const text = content . toString ( 'latin1' ) ;
67+ for ( const [ pattern , label ] of forbiddenPatterns ) {
68+ if ( pattern . test ( text ) ) failures . push ( `${ path } : contains ${ label } ` ) ;
69+ }
70+ }
71+
5672for ( const file of files ) {
5773 if ( forbiddenNames . some ( ( pattern ) => pattern . test ( basename ( file ) ) ) ) {
5874 failures . push ( `${ file } : forbidden release filename` ) ;
5975 continue ;
6076 }
6177
62- const content = await readFile ( file ) ;
63- for ( const [ needle , label ] of forbiddenContent ) {
64- if ( content . includes ( Buffer . from ( needle ) ) ) failures . push ( ` ${ file } : contains ${ label } ` ) ;
65- }
66- const text = content . toString ( 'latin1' ) ;
67- for ( const [ pattern , label ] of forbiddenPatterns ) {
68- if ( pattern . test ( text ) ) failures . push ( ` ${ file } : contains ${ label } ` ) ;
78+ scanContent ( file , await readFile ( file ) ) ;
79+ }
80+
81+ for ( const { path , target } of symlinks ) {
82+ if ( forbiddenNames . some ( ( pattern ) => pattern . test ( basename ( path ) ) ) ) {
83+ failures . push ( ` ${ path } : forbidden release filename` ) ;
84+ continue ;
6985 }
86+
87+ scanContent ( `${ path } -> ${ target } ` , Buffer . from ( target ) ) ;
7088}
7189
7290if ( failures . length > 0 ) {
7391 console . error ( `Release privacy check failed:\n${ failures . join ( '\n' ) } ` ) ;
7492 process . exit ( 1 ) ;
7593}
7694
77- console . log ( `Release privacy check passed (${ files . length } files)` ) ;
95+ console . log ( `Release privacy check passed (${ files . length } files, ${ symlinks . length } symlinks )` ) ;
0 commit comments