forked from anomalyco/opencode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfilesystem.ts
More file actions
93 lines (87 loc) · 2.55 KB
/
Copy pathfilesystem.ts
File metadata and controls
93 lines (87 loc) · 2.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import { realpathSync } from "fs"
import { dirname, join, relative } from "path"
export namespace Filesystem {
export const exists = (p: string) =>
Bun.file(p)
.stat()
.then(() => true)
.catch(() => false)
export const isDir = (p: string) =>
Bun.file(p)
.stat()
.then((s) => s.isDirectory())
.catch(() => false)
/**
* On Windows, normalize a path to its canonical casing using the filesystem.
* This is needed because Windows paths are case-insensitive but LSP servers
* may return paths with different casing than what we send them.
*/
export function normalizePath(p: string): string {
if (process.platform !== "win32") return p
try {
return realpathSync.native(p)
} catch {
return p
}
}
export function overlaps(a: string, b: string) {
const relA = relative(a, b)
const relB = relative(b, a)
return !relA || !relA.startsWith("..") || !relB || !relB.startsWith("..")
}
export function contains(parent: string, child: string) {
return !relative(parent, child).startsWith("..")
}
export async function findUp(target: string, start: string, stop?: string) {
let current = start
const result = []
while (true) {
const search = join(current, target)
if (await exists(search)) result.push(search)
if (stop === current) break
const parent = dirname(current)
if (parent === current) break
current = parent
}
return result
}
export async function* up(options: { targets: string[]; start: string; stop?: string }) {
const { targets, start, stop } = options
let current = start
while (true) {
for (const target of targets) {
const search = join(current, target)
if (await exists(search)) yield search
}
if (stop === current) break
const parent = dirname(current)
if (parent === current) break
current = parent
}
}
export async function globUp(pattern: string, start: string, stop?: string) {
let current = start
const result = []
while (true) {
try {
const glob = new Bun.Glob(pattern)
for await (const match of glob.scan({
cwd: current,
absolute: true,
onlyFiles: true,
followSymlinks: true,
dot: true,
})) {
result.push(match)
}
} catch {
// Skip invalid glob patterns
}
if (stop === current) break
const parent = dirname(current)
if (parent === current) break
current = parent
}
return result
}
}