| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- import { realpathSync } from "fs"
- import { exists } from "fs/promises"
- import { dirname, join, relative } from "path"
- export namespace Filesystem {
- /**
- * 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).catch(() => false)) 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).catch(() => false)) 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
- }
- }
|