mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
Merge pull request #1174 from QwenLM/fix/glob-windows-casing
fix: handle case-insensitive path comparison in glob tool on Windows
This commit is contained in:
@@ -198,6 +198,52 @@ describe('GlobTool', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should find files even if workspace path casing differs from glob results (Windows/macOS)', async () => {
|
||||||
|
// Only relevant for Windows and macOS
|
||||||
|
if (process.platform !== 'win32' && process.platform !== 'darwin') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mismatchedRootDir = tempRootDir;
|
||||||
|
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
// 1. Create a path with mismatched casing for the workspace root
|
||||||
|
// e.g., if tempRootDir is "C:\Users\...", make it "c:\Users\..."
|
||||||
|
const drive = path.parse(tempRootDir).root;
|
||||||
|
if (!drive || !drive.match(/^[A-Z]:\\/)) {
|
||||||
|
// Skip if we can't determine/manipulate the drive letter easily
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lowerDrive = drive.toLowerCase();
|
||||||
|
mismatchedRootDir = lowerDrive + tempRootDir.substring(drive.length);
|
||||||
|
} else {
|
||||||
|
// macOS: change the casing of the path
|
||||||
|
if (tempRootDir === tempRootDir.toLowerCase()) {
|
||||||
|
mismatchedRootDir = tempRootDir.toUpperCase();
|
||||||
|
} else {
|
||||||
|
mismatchedRootDir = tempRootDir.toLowerCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Create a new GlobTool instance with this mismatched root
|
||||||
|
const mismatchedConfig = {
|
||||||
|
...mockConfig,
|
||||||
|
getTargetDir: () => mismatchedRootDir,
|
||||||
|
getWorkspaceContext: () =>
|
||||||
|
createMockWorkspaceContext(mismatchedRootDir),
|
||||||
|
} as unknown as Config;
|
||||||
|
|
||||||
|
const mismatchedGlobTool = new GlobTool(mismatchedConfig);
|
||||||
|
|
||||||
|
// 3. Execute search
|
||||||
|
const params: GlobToolParams = { pattern: '*.txt' };
|
||||||
|
const invocation = mismatchedGlobTool.build(params);
|
||||||
|
const result = await invocation.execute(abortSignal);
|
||||||
|
|
||||||
|
expect(result.llmContent).toContain('Found 2 file(s)');
|
||||||
|
});
|
||||||
|
|
||||||
it('should return error if path is outside workspace', async () => {
|
it('should return error if path is outside workspace', async () => {
|
||||||
// Bypassing validation to test execute method directly
|
// Bypassing validation to test execute method directly
|
||||||
vi.spyOn(globTool, 'validateToolParams').mockReturnValue(null);
|
vi.spyOn(globTool, 'validateToolParams').mockReturnValue(null);
|
||||||
|
|||||||
@@ -134,12 +134,21 @@ class GlobToolInvocation extends BaseToolInvocation<
|
|||||||
this.getFileFilteringOptions(),
|
this.getFileFilteringOptions(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const normalizePathForComparison = (p: string) =>
|
||||||
|
process.platform === 'win32' || process.platform === 'darwin'
|
||||||
|
? p.toLowerCase()
|
||||||
|
: p;
|
||||||
|
|
||||||
const filteredAbsolutePaths = new Set(
|
const filteredAbsolutePaths = new Set(
|
||||||
filteredPaths.map((p) => path.resolve(this.config.getTargetDir(), p)),
|
filteredPaths.map((p) =>
|
||||||
|
normalizePathForComparison(
|
||||||
|
path.resolve(this.config.getTargetDir(), p),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const filteredEntries = allEntries.filter((entry) =>
|
const filteredEntries = allEntries.filter((entry) =>
|
||||||
filteredAbsolutePaths.has(entry.fullpath()),
|
filteredAbsolutePaths.has(normalizePathForComparison(entry.fullpath())),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!filteredEntries || filteredEntries.length === 0) {
|
if (!filteredEntries || filteredEntries.length === 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user