@@ -4,7 +4,7 @@ import path from 'node:path';
44import fastGlob from 'fast-glob' ;
55import gitIgnore from 'ignore' ;
66import slash from 'slash' ;
7- import { toPath } from './utilities.js' ;
7+ import { toPath , isNegativePattern } from './utilities.js' ;
88
99const gitignoreGlobOptions = {
1010 ignore : [
@@ -16,85 +16,71 @@ const gitignoreGlobOptions = {
1616 absolute : true ,
1717} ;
1818
19- const mapGitIgnorePatternTo = base => ignore => {
20- if ( ignore . startsWith ( '!' ) ) {
21- return '!' + path . posix . join ( base , ignore . slice ( 1 ) ) ;
22- }
23-
24- return path . posix . join ( base , ignore ) ;
25- } ;
19+ const applyBaseToPattern = ( pattern , base ) => isNegativePattern ( pattern )
20+ ? '!' + path . posix . join ( base , pattern . slice ( 1 ) )
21+ : path . posix . join ( base , pattern ) ;
2622
27- const parseGitIgnore = ( content , options ) => {
28- const base = slash ( path . relative ( options . cwd , path . dirname ( options . fileName ) ) ) ;
23+ const parseGitIgnoreFile = ( file , cwd ) => {
24+ const base = slash ( path . relative ( cwd , path . dirname ( file . filePath ) ) ) ;
2925
30- return content
26+ return file . content
3127 . split ( / \r ? \n / )
32- . filter ( Boolean )
33- . filter ( line => ! line . startsWith ( '#' ) )
34- . map ( mapGitIgnorePatternTo ( base ) ) ;
28+ . filter ( line => line && ! line . startsWith ( '#' ) )
29+ . map ( pattern => applyBaseToPattern ( pattern , base ) ) ;
3530} ;
3631
37- const reduceIgnore = files => {
38- const ignores = gitIgnore ( ) ;
39- for ( const file of files ) {
40- ignores . add ( parseGitIgnore ( file . content , {
41- cwd : file . cwd ,
42- fileName : file . filePath ,
43- } ) ) ;
44- }
45-
46- return ignores ;
47- } ;
48-
49- const ensureAbsolutePathForCwd = ( cwd , p ) => {
32+ const toRelativePath = ( fileOrDirectory , cwd ) => {
5033 cwd = slash ( cwd ) ;
51- if ( path . isAbsolute ( p ) ) {
52- if ( slash ( p ) . startsWith ( cwd ) ) {
53- return p ;
34+ if ( path . isAbsolute ( fileOrDirectory ) ) {
35+ if ( slash ( fileOrDirectory ) . startsWith ( cwd ) ) {
36+ return path . relative ( cwd , fileOrDirectory ) ;
5437 }
5538
56- throw new Error ( `Path ${ p } is not in cwd ${ cwd } ` ) ;
39+ throw new Error ( `Path ${ fileOrDirectory } is not in cwd ${ cwd } ` ) ;
5740 }
5841
59- return path . join ( cwd , p ) ;
42+ return fileOrDirectory ;
6043} ;
6144
62- const getIsIgnoredPredicate = ( ignores , cwd ) => p => ignores . ignores ( slash ( path . relative ( cwd , ensureAbsolutePathForCwd ( cwd , toPath ( p ) ) ) ) ) ;
63-
64- const getFile = async ( filePath , cwd ) => ( {
65- cwd,
66- filePath,
67- content : await fs . promises . readFile ( filePath , 'utf8' ) ,
68- } ) ;
45+ const getIsIgnoredPredicate = ( files , cwd ) => {
46+ const patterns = files . flatMap ( file => parseGitIgnoreFile ( file , cwd ) ) ;
47+ const ignores = gitIgnore ( ) . add ( patterns ) ;
6948
70- const getFileSync = ( filePath , cwd ) => ( {
71- cwd,
72- filePath,
73- content : fs . readFileSync ( filePath , 'utf8' ) ,
74- } ) ;
49+ return fileOrDirectory => {
50+ fileOrDirectory = toPath ( fileOrDirectory ) ;
51+ fileOrDirectory = toRelativePath ( fileOrDirectory , cwd ) ;
52+ return ignores . ignores ( slash ( fileOrDirectory ) ) ;
53+ } ;
54+ } ;
7555
7656const normalizeOptions = ( options = { } ) => ( {
77- cwd : toPath ( options . cwd ) || slash ( process . cwd ( ) ) ,
57+ cwd : toPath ( options . cwd ) || process . cwd ( ) ,
7858} ) ;
7959
8060export const isGitIgnored = async options => {
8161 const { cwd} = normalizeOptions ( options ) ;
8262
8363 const paths = await fastGlob ( '**/.gitignore' , { cwd, ...gitignoreGlobOptions } ) ;
8464
85- const files = await Promise . all ( paths . map ( file => getFile ( file , cwd ) ) ) ;
86- const ignores = reduceIgnore ( files ) ;
65+ const files = await Promise . all (
66+ paths . map ( async filePath => ( {
67+ filePath,
68+ content : await fs . promises . readFile ( filePath , 'utf8' ) ,
69+ } ) ) ,
70+ ) ;
8771
88- return getIsIgnoredPredicate ( ignores , cwd ) ;
72+ return getIsIgnoredPredicate ( files , cwd ) ;
8973} ;
9074
9175export const isGitIgnoredSync = options => {
9276 const { cwd} = normalizeOptions ( options ) ;
9377
9478 const paths = fastGlob . sync ( '**/.gitignore' , { cwd, ...gitignoreGlobOptions } ) ;
9579
96- const files = paths . map ( file => getFileSync ( file , cwd ) ) ;
97- const ignores = reduceIgnore ( files ) ;
80+ const files = paths . map ( filePath => ( {
81+ filePath,
82+ content : fs . readFileSync ( filePath , 'utf8' ) ,
83+ } ) ) ;
9884
99- return getIsIgnoredPredicate ( ignores , cwd ) ;
85+ return getIsIgnoredPredicate ( files , cwd ) ;
10086} ;
0 commit comments