|
7 | 7 | */ |
8 | 8 |
|
9 | 9 | import { type PathLike, constants, promises as fs } from 'node:fs'; |
| 10 | +import os from 'node:os'; |
10 | 11 | import { basename, dirname, extname, isAbsolute, join, relative } from 'node:path'; |
11 | 12 | import { glob, isDynamicPattern } from 'tinyglobby'; |
12 | 13 | import { toPosixPath } from '../../utils/path'; |
@@ -157,15 +158,32 @@ function generateNameFromPath( |
157 | 158 | return result; |
158 | 159 | } |
159 | 160 |
|
160 | | -/** Removes a leading slash from a path. */ |
161 | | -const removeLeadingSlash = (path: string): string => { |
162 | | - return path.startsWith('/') ? path.substring(1) : path; |
163 | | -}; |
| 161 | +/** |
| 162 | + * Whether the current operating system's filesystem is case-insensitive. |
| 163 | + */ |
| 164 | +const isCaseInsensitiveFilesystem = os.platform() === 'win32' || os.platform() === 'darwin'; |
164 | 165 |
|
165 | | -/** Removes a prefix from the beginning of a string. */ |
166 | | -const removePrefix = (str: string, prefix: string): string => { |
167 | | - return str.startsWith(prefix) ? str.substring(prefix.length) : str; |
168 | | -}; |
| 166 | +/** |
| 167 | + * Removes a prefix from the beginning of a string, with conditional case-insensitivity |
| 168 | + * based on the operating system's filesystem characteristics. |
| 169 | + * |
| 170 | + * @param text The string to remove the prefix from. |
| 171 | + * @param prefix The prefix to remove. |
| 172 | + * @returns The string with the prefix removed, or the original string if the prefix was not found. |
| 173 | + */ |
| 174 | +function removePrefix(text: string, prefix: string): string { |
| 175 | + if (isCaseInsensitiveFilesystem) { |
| 176 | + if (text.toLowerCase().startsWith(prefix.toLowerCase())) { |
| 177 | + return text.substring(prefix.length); |
| 178 | + } |
| 179 | + } else { |
| 180 | + if (text.startsWith(prefix)) { |
| 181 | + return text.substring(prefix.length); |
| 182 | + } |
| 183 | + } |
| 184 | + |
| 185 | + return text; |
| 186 | +} |
169 | 187 |
|
170 | 188 | /** |
171 | 189 | * Removes potential root paths from a file path, returning a relative path. |
@@ -194,15 +212,18 @@ function removeRoots(path: string, roots: string[]): string { |
194 | 212 | * @returns A normalized glob pattern. |
195 | 213 | */ |
196 | 214 | function normalizePattern(pattern: string, projectRootPrefix: string): string { |
197 | | - let normalizedPattern = toPosixPath(pattern); |
198 | | - normalizedPattern = removeLeadingSlash(normalizedPattern); |
| 215 | + const posixPattern = toPosixPath(pattern); |
| 216 | + |
| 217 | + // Do not modify absolute paths. The globber will handle them correctly. |
| 218 | + if (isAbsolute(posixPattern)) { |
| 219 | + return posixPattern; |
| 220 | + } |
199 | 221 |
|
200 | | - // Some IDEs and tools may provide patterns relative to the workspace root. |
201 | | - // To ensure the glob operates correctly within the project's source root, |
202 | | - // we remove the project's relative path from the front of the pattern. |
203 | | - normalizedPattern = removePrefix(normalizedPattern, projectRootPrefix); |
| 222 | + // For relative paths, ensure they are correctly relative to the project source root. |
| 223 | + // This involves removing the project root prefix if the user provided a workspace-relative path. |
| 224 | + const normalizedRelative = removePrefix(posixPattern, projectRootPrefix); |
204 | 225 |
|
205 | | - return normalizedPattern; |
| 226 | + return normalizedRelative; |
206 | 227 | } |
207 | 228 |
|
208 | 229 | /** |
|
0 commit comments