Skip to content

Commit 11dd2df

Browse files
committed
Fix parent directory patterns with gitignore option
Fixes #133
1 parent e4d0918 commit 11dd2df

File tree

3 files changed

+61
-9
lines changed

3 files changed

+61
-9
lines changed

ignore.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,9 @@ const toRelativePath = (fileOrDirectory, cwd) => {
8282
// isPathInside returns false for equal paths, so check this case first
8383
const relativePath = path.relative(cwd, fileOrDirectory);
8484
if (relativePath && !isPathInside(fileOrDirectory, cwd)) {
85-
throw new Error(`Path ${fileOrDirectory} is not in cwd ${cwd}`);
85+
// Path is outside cwd - it cannot be ignored by patterns in cwd
86+
// Return undefined to indicate this path is outside scope
87+
return undefined;
8688
}
8789

8890
return relativePath;

tests/globby.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,58 @@ test('nested gitignore with negation applies recursively to globby results (issu
638638
t.false(result.includes('y/z/a1.txt'));
639639
});
640640

641+
test.serial('parent directory patterns work with gitignore option (issue #133)', async t => {
642+
const temporaryParent = temporaryDirectory();
643+
const temporarySrc = path.join(temporaryParent, 'src');
644+
const temporaryChild = path.join(temporaryParent, 'child');
645+
646+
fs.mkdirSync(temporarySrc, {recursive: true});
647+
fs.mkdirSync(temporaryChild, {recursive: true});
648+
649+
const srcFile1 = path.join(temporarySrc, 'test1.ts');
650+
const srcFile2 = path.join(temporarySrc, 'test2.ts');
651+
652+
fs.writeFileSync(srcFile1, 'content1', 'utf8');
653+
fs.writeFileSync(srcFile2, 'content2', 'utf8');
654+
655+
// Add a .gitignore to ensure gitignore processing is active
656+
fs.writeFileSync(path.join(temporaryParent, '.gitignore'), 'node_modules\n', 'utf8');
657+
658+
try {
659+
// Test relative parent directory pattern with gitignore:true
660+
const relativeResult = await runGlobby(t, '../src/*.ts', {
661+
cwd: temporaryChild,
662+
gitignore: true,
663+
absolute: false,
664+
});
665+
666+
t.deepEqual(relativeResult.sort(), ['../src/test1.ts', '../src/test2.ts']);
667+
668+
// Test absolute paths with gitignore:true
669+
const absoluteResult = await runGlobby(t, '../src/*.ts', {
670+
cwd: temporaryChild,
671+
gitignore: true,
672+
absolute: true,
673+
});
674+
675+
t.is(absoluteResult.length, 2);
676+
t.true(absoluteResult.every(p => path.isAbsolute(p)));
677+
t.true(absoluteResult.some(p => p.endsWith('test1.ts')));
678+
t.true(absoluteResult.some(p => p.endsWith('test2.ts')));
679+
680+
// Verify it still works with gitignore:false for consistency
681+
const withoutGitignoreResult = await runGlobby(t, '../src/*.ts', {
682+
cwd: temporaryChild,
683+
gitignore: false,
684+
absolute: false,
685+
});
686+
687+
t.deepEqual(withoutGitignoreResult.sort(), ['../src/test1.ts', '../src/test2.ts']);
688+
} finally {
689+
fs.rmSync(temporaryParent, {recursive: true, force: true});
690+
}
691+
});
692+
641693
test.serial('gitignore directory patterns stop fast-glob traversal', async t => {
642694
const temporaryCwd = temporaryDirectory();
643695
const gitignorePath = path.join(temporaryCwd, '.gitignore');

tests/ignore.js

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -655,17 +655,15 @@ test('fs option preserves context for ignore file readers', async t => {
655655
t.false(syncPredicate('not-ignored.js'));
656656
});
657657

658-
test('path prefix edge case - reject paths with similar prefix outside cwd', async t => {
658+
test('path prefix edge case - paths with similar prefix outside cwd return false', async t => {
659659
const cwd = path.join(PROJECT_ROOT, 'fixtures/gitignore');
660660
const isIgnored = await isGitIgnored({cwd});
661661

662-
// Test that paths outside the cwd but with similar prefix are rejected
663-
// e.g., if cwd is /foo/bar, then /foo/barbaz should throw an error
662+
// Test that paths outside the cwd but with similar prefix return false (not ignored)
663+
// e.g., if cwd is /foo/bar, then /foo/barextra should not be ignored
664+
// because it's outside cwd and gitignore patterns from cwd don't apply to it
664665
const outsidePath = cwd + 'extra/file.js'; // Creates path like /foo/gitignoreextra/file.js
665666

666-
const error = t.throws(() => {
667-
isIgnored(outsidePath);
668-
});
669-
670-
t.regex(error.message, /Path .+ is not in cwd/);
667+
// Should return false (not ignored) rather than throwing error
668+
t.false(isIgnored(outsidePath));
671669
});

0 commit comments

Comments
 (0)