Skip to content

Commit 6aee6a3

Browse files
authored
perf: improve isSubdirectoryOrEqual performance (#152)
1 parent 5f707b6 commit 6aee6a3

File tree

3 files changed

+51
-7
lines changed

3 files changed

+51
-7
lines changed

.changeset/poor-sites-buy.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'vite-plugin-static-copy': patch
3+
---
4+
5+
improve performance of internal `isSubdirectoryOrEqual` function

src/utils.test.ts

+38-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,43 @@
11
import { describe, expect, test } from 'vitest'
2-
import { groupTargetsByDirectoryTree } from './utils'
2+
import { isSubdirectoryOrEqual, groupTargetsByDirectoryTree } from './utils'
33
import path from 'node:path'
4+
import { fileURLToPath } from 'node:url'
5+
import os from 'node:os'
6+
7+
const _dirname = path.dirname(fileURLToPath(import.meta.url))
8+
const isWindows = os.platform() === 'win32'
9+
10+
describe('isSubdirectoryOrEqual', () => {
11+
const cases: readonly [a: string, b: string, expected: boolean][] = [
12+
['./', '.', true],
13+
['./', './', true],
14+
['.', './', true],
15+
['./index.ts', './', true],
16+
['./foo/', './', true],
17+
['./foo/bar', './', true],
18+
['./foo/bar.js', './', true],
19+
['..', './', false],
20+
['../', './', false],
21+
['../test', './', false],
22+
['../test/', './', false],
23+
...(isWindows
24+
? ([
25+
['C:/', 'C:/', true],
26+
['C:\\', 'C:/', true],
27+
['C:/', 'D:/', false],
28+
['C:\\', 'D:/', false]
29+
] satisfies readonly [string, string, boolean][])
30+
: [])
31+
]
32+
33+
const resolve = (p: string) => path.resolve(_dirname, p)
34+
35+
for (const [a, b, expected] of cases) {
36+
test(`isSubdirectoryOrEqual(${a}, ${b})`, () => {
37+
expect(isSubdirectoryOrEqual(resolve(a), resolve(b))).toBe(expected)
38+
})
39+
}
40+
})
441

542
describe('groupTargetsByDirectoryTree', () => {
643
const defineCase = (input: string[], expected: string[][]) => ({

src/utils.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,14 @@ type ResolvedTarget = SimpleTarget & {
2727
resolvedSrc: string
2828
}
2929

30-
const isSubdirectoryOrEqual = (a: string, b: string) => {
31-
const relative = path.relative(b, a)
32-
return (
33-
!relative ||
34-
(!relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative))
35-
)
30+
/**
31+
* Whether a is a subdirectory of b or equal to b
32+
*
33+
* @param a absolute path
34+
* @param b absolute path
35+
*/
36+
export const isSubdirectoryOrEqual = (a: string, b: string) => {
37+
return a.startsWith(b + path.sep) || a === b
3638
}
3739

3840
export const groupTargetsByDirectoryTree = <T extends { resolvedDest: string }>(

0 commit comments

Comments
 (0)