Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1cd929181f | ||
|
|
f4d818c7a2 | ||
|
|
9de8f6f5c3 | ||
|
|
a60e6db920 | ||
|
|
c050f7bc2e | ||
|
|
0483fce47e | ||
|
|
92cb8ef23c | ||
|
|
5d702dc7bd |
@@ -5,3 +5,4 @@ packages/*/__tests__/_temp/
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
*.xar
|
*.xar
|
||||||
packages/*/audit.json
|
packages/*/audit.json
|
||||||
|
.nx/
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* Test to validate that glob works correctly on Windows with backslash paths
|
||||||
|
* This test validates the fix for glob not working on GitHub's Windows runners
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {MatchKind} from '../src/internal-match-kind'
|
||||||
|
import {Pattern} from '../src/internal-pattern'
|
||||||
|
|
||||||
|
const IS_WINDOWS = process.platform === 'win32'
|
||||||
|
|
||||||
|
describe('Windows path matching', () => {
|
||||||
|
it('matches paths with backslashes on Windows', () => {
|
||||||
|
if (!IS_WINDOWS) {
|
||||||
|
// This test is only relevant on Windows
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test basic pattern matching with Windows paths
|
||||||
|
const pattern = new Pattern('C:\\Users\\test\\*')
|
||||||
|
|
||||||
|
// The itemPath would come from fs.readdir with backslashes on Windows
|
||||||
|
const itemPath = 'C:\\Users\\test\\file.txt'
|
||||||
|
|
||||||
|
// This should match because the pattern and path both refer to the same file
|
||||||
|
expect(pattern.match(itemPath)).toBe(MatchKind.All)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('partial matches work with backslashes on Windows', () => {
|
||||||
|
if (!IS_WINDOWS) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test partial matching with Windows paths
|
||||||
|
const pattern = new Pattern('C:\\Users\\test\\**')
|
||||||
|
|
||||||
|
// Should partially match parent directory
|
||||||
|
expect(pattern.partialMatch('C:\\Users')).toBe(true)
|
||||||
|
expect(pattern.partialMatch('C:\\Users\\test')).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('matches globstar patterns with backslashes on Windows', () => {
|
||||||
|
if (!IS_WINDOWS) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const pattern = new Pattern('C:\\foo\\**')
|
||||||
|
|
||||||
|
// Should match the directory itself and descendants
|
||||||
|
expect(pattern.match('C:\\foo')).toBe(MatchKind.All)
|
||||||
|
expect(pattern.match('C:\\foo\\bar')).toBe(MatchKind.All)
|
||||||
|
expect(pattern.match('C:\\foo\\bar\\baz.txt')).toBe(MatchKind.All)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('matches wildcard patterns with mixed separators on Windows', () => {
|
||||||
|
if (!IS_WINDOWS) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pattern might be specified with forward slashes by user
|
||||||
|
const pattern = new Pattern('C:/Users/*/file.txt')
|
||||||
|
|
||||||
|
// But the actual path from filesystem will have backslashes
|
||||||
|
expect(pattern.match('C:\\Users\\test\\file.txt')).toBe(MatchKind.All)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('handles complex patterns with backslashes on Windows', () => {
|
||||||
|
if (!IS_WINDOWS) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentDrive = process.cwd().substring(0, 2)
|
||||||
|
const pattern = new Pattern(`${currentDrive}\\**\\*.txt`)
|
||||||
|
|
||||||
|
// Should match .txt files at any depth
|
||||||
|
expect(pattern.match(`${currentDrive}\\file.txt`)).toBe(MatchKind.All)
|
||||||
|
expect(pattern.match(`${currentDrive}\\foo\\bar\\test.txt`)).toBe(
|
||||||
|
MatchKind.All
|
||||||
|
)
|
||||||
|
expect(pattern.match(`${currentDrive}\\foo\\bar\\test.js`)).toBe(
|
||||||
|
MatchKind.None
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -156,6 +156,10 @@ export class Pattern {
|
|||||||
itemPath = pathHelper.safeTrimTrailingSeparator(itemPath)
|
itemPath = pathHelper.safeTrimTrailingSeparator(itemPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert to forward slashes on Windows before matching with minimatch
|
||||||
|
// since the pattern was converted to forward slashes in the constructor
|
||||||
|
itemPath = Pattern.convertToMinimatchPath(itemPath)
|
||||||
|
|
||||||
// Match
|
// Match
|
||||||
if (this.minimatch.match(itemPath)) {
|
if (this.minimatch.match(itemPath)) {
|
||||||
return this.trailingSeparator ? MatchKind.Directory : MatchKind.All
|
return this.trailingSeparator ? MatchKind.Directory : MatchKind.All
|
||||||
@@ -176,8 +180,11 @@ export class Pattern {
|
|||||||
return this.rootRegExp.test(itemPath)
|
return this.rootRegExp.test(itemPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert to forward slashes on Windows to match the pattern format used by minimatch
|
||||||
|
itemPath = Pattern.convertToMinimatchPath(itemPath)
|
||||||
|
|
||||||
return this.minimatch.matchOne(
|
return this.minimatch.matchOne(
|
||||||
itemPath.split(IS_WINDOWS ? /\\+/ : /\/+/),
|
itemPath.split(/\/+/),
|
||||||
this.minimatch.set[0],
|
this.minimatch.set[0],
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@@ -193,6 +200,18 @@ export class Pattern {
|
|||||||
.replace(/\*/g, '[*]') // escape '*'
|
.replace(/\*/g, '[*]') // escape '*'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts path to forward slashes on Windows for compatibility with minimatch.
|
||||||
|
* On Windows, minimatch patterns use forward slashes, so paths must be converted
|
||||||
|
* to match the same format.
|
||||||
|
*/
|
||||||
|
private static convertToMinimatchPath(itemPath: string): string {
|
||||||
|
if (IS_WINDOWS) {
|
||||||
|
return itemPath.replace(/\\/g, '/')
|
||||||
|
}
|
||||||
|
return itemPath
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalizes slashes and ensures absolute root
|
* Normalizes slashes and ensures absolute root
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user