refactor: remove makeRuntime facades from File and Ripgrep (#22513)

This commit is contained in:
Kit Langton
2026-04-15 21:22:18 -04:00
committed by GitHub
parent 02f2cf439e
commit 0fb0135e51
5 changed files with 130 additions and 213 deletions
+99 -142
View File
@@ -6,20 +6,8 @@ import path from "path"
import { tmpdir } from "../fixture/fixture"
import { Ripgrep } from "../../src/file/ripgrep"
async function seed(dir: string, count: number, size = 16) {
const txt = "a".repeat(size)
await Promise.all(Array.from({ length: count }, (_, i) => Bun.write(path.join(dir, `file-${i}.txt`), `${txt}${i}\n`)))
}
function env(name: string, value: string | undefined) {
const prev = process.env[name]
if (value === undefined) delete process.env[name]
else process.env[name] = value
return () => {
if (prev === undefined) delete process.env[name]
else process.env[name] = prev
}
}
const run = <A>(effect: Effect.Effect<A, unknown, Ripgrep.Service>) =>
effect.pipe(Effect.provide(Ripgrep.defaultLayer), Effect.runPromise)
describe("file.ripgrep", () => {
test("defaults to include hidden", async () => {
@@ -31,7 +19,14 @@ describe("file.ripgrep", () => {
},
})
const files = await Array.fromAsync(await Ripgrep.files({ cwd: tmp.path }))
const files = await run(
Ripgrep.Service.use((rg) =>
rg.files({ cwd: tmp.path }).pipe(
Stream.runCollect,
Effect.map((c) => [...c]),
),
),
)
expect(files.includes("visible.txt")).toBe(true)
expect(files.includes(path.join(".opencode", "thing.json"))).toBe(true)
})
@@ -45,7 +40,14 @@ describe("file.ripgrep", () => {
},
})
const files = await Array.fromAsync(await Ripgrep.files({ cwd: tmp.path, hidden: false }))
const files = await run(
Ripgrep.Service.use((rg) =>
rg.files({ cwd: tmp.path, hidden: false }).pipe(
Stream.runCollect,
Effect.map((c) => [...c]),
),
),
)
expect(files.includes("visible.txt")).toBe(true)
expect(files.includes(path.join(".opencode", "thing.json"))).toBe(false)
})
@@ -57,7 +59,7 @@ describe("file.ripgrep", () => {
},
})
const result = await Ripgrep.search({ cwd: tmp.path, pattern: "needle" })
const result = await run(Ripgrep.Service.use((rg) => rg.search({ cwd: tmp.path, pattern: "needle" })))
expect(result.partial).toBe(false)
expect(result.items).toEqual([])
})
@@ -70,7 +72,7 @@ describe("file.ripgrep", () => {
},
})
const result = await Ripgrep.search({ cwd: tmp.path, pattern: "needle" })
const result = await run(Ripgrep.Service.use((rg) => rg.search({ cwd: tmp.path, pattern: "needle" })))
expect(result.partial).toBe(false)
expect(result.items).toHaveLength(1)
expect(result.items[0]?.path.text).toBe(path.join("src", "match.ts"))
@@ -78,99 +80,7 @@ describe("file.ripgrep", () => {
expect(result.items[0]?.lines.text).toContain("needle")
})
test("files returns empty when glob matches no files in worker mode", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await fs.mkdir(path.join(dir, "packages", "console"), { recursive: true })
await Bun.write(path.join(dir, "packages", "console", "package.json"), "{}")
},
})
const ctl = new AbortController()
const files = await Array.fromAsync(
await Ripgrep.files({
cwd: tmp.path,
glob: ["packages/*"],
signal: ctl.signal,
}),
)
expect(files).toEqual([])
})
test("ignores RIPGREP_CONFIG_PATH in direct mode", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(path.join(dir, "match.ts"), "const needle = 1\n")
},
})
const restore = env("RIPGREP_CONFIG_PATH", path.join(tmp.path, "missing-ripgreprc"))
try {
const result = await Ripgrep.search({ cwd: tmp.path, pattern: "needle" })
expect(result.items).toHaveLength(1)
} finally {
restore()
}
})
test("ignores RIPGREP_CONFIG_PATH in worker mode", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(path.join(dir, "match.ts"), "const needle = 1\n")
},
})
const restore = env("RIPGREP_CONFIG_PATH", path.join(tmp.path, "missing-ripgreprc"))
try {
const ctl = new AbortController()
const result = await Ripgrep.search({
cwd: tmp.path,
pattern: "needle",
signal: ctl.signal,
})
expect(result.items).toHaveLength(1)
} finally {
restore()
}
})
test("aborts files scan in worker mode", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await seed(dir, 4000)
},
})
const ctl = new AbortController()
const iter = await Ripgrep.files({ cwd: tmp.path, signal: ctl.signal })
const pending = Array.fromAsync(iter)
setTimeout(() => ctl.abort(), 0)
const err = await pending.catch((err) => err)
expect(err).toBeInstanceOf(Error)
expect(err.name).toBe("AbortError")
}, 15_000)
test("aborts search in worker mode", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await seed(dir, 512, 64 * 1024)
},
})
const ctl = new AbortController()
const pending = Ripgrep.search({ cwd: tmp.path, pattern: "needle", signal: ctl.signal })
setTimeout(() => ctl.abort(), 0)
const err = await pending.catch((err) => err)
expect(err).toBeInstanceOf(Error)
expect(err.name).toBe("AbortError")
}, 15_000)
})
describe("Ripgrep.Service", () => {
test("search returns matched rows", async () => {
test("search returns matched rows with glob filter", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(path.join(dir, "match.ts"), "const value = 'needle'\n")
@@ -178,11 +88,9 @@ describe("Ripgrep.Service", () => {
},
})
const result = await Effect.gen(function* () {
const rg = yield* Ripgrep.Service
return yield* rg.search({ cwd: tmp.path, pattern: "needle", glob: ["*.ts"] })
}).pipe(Effect.provide(Ripgrep.defaultLayer), Effect.runPromise)
const result = await run(
Ripgrep.Service.use((rg) => rg.search({ cwd: tmp.path, pattern: "needle", glob: ["*.ts"] })),
)
expect(result.partial).toBe(false)
expect(result.items).toHaveLength(1)
expect(result.items[0]?.path.text).toContain("match.ts")
@@ -198,16 +106,31 @@ describe("Ripgrep.Service", () => {
})
const file = path.join(tmp.path, "match.ts")
const result = await Effect.gen(function* () {
const rg = yield* Ripgrep.Service
return yield* rg.search({ cwd: tmp.path, pattern: "needle", file: [file] })
}).pipe(Effect.provide(Ripgrep.defaultLayer), Effect.runPromise)
const result = await run(Ripgrep.Service.use((rg) => rg.search({ cwd: tmp.path, pattern: "needle", file: [file] })))
expect(result.partial).toBe(false)
expect(result.items).toHaveLength(1)
expect(result.items[0]?.path.text).toBe(file)
})
test("files returns empty when glob matches no files", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await fs.mkdir(path.join(dir, "packages", "console"), { recursive: true })
await Bun.write(path.join(dir, "packages", "console", "package.json"), "{}")
},
})
const files = await run(
Ripgrep.Service.use((rg) =>
rg.files({ cwd: tmp.path, glob: ["packages/*"] }).pipe(
Stream.runCollect,
Effect.map((c) => [...c]),
),
),
)
expect(files).toEqual([])
})
test("files returns stream of filenames", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
@@ -216,14 +139,14 @@ describe("Ripgrep.Service", () => {
},
})
const files = await Effect.gen(function* () {
const rg = yield* Ripgrep.Service
return yield* rg.files({ cwd: tmp.path }).pipe(
Stream.runCollect,
Effect.map((chunk) => [...chunk].sort()),
)
}).pipe(Effect.provide(Ripgrep.defaultLayer), Effect.runPromise)
const files = await run(
Ripgrep.Service.use((rg) =>
rg.files({ cwd: tmp.path }).pipe(
Stream.runCollect,
Effect.map((c) => [...c].sort()),
),
),
)
expect(files).toEqual(["a.txt", "b.txt"])
})
@@ -235,23 +158,57 @@ describe("Ripgrep.Service", () => {
},
})
const files = await Effect.gen(function* () {
const rg = yield* Ripgrep.Service
return yield* rg.files({ cwd: tmp.path, glob: ["*.ts"] }).pipe(
Stream.runCollect,
Effect.map((chunk) => [...chunk]),
)
}).pipe(Effect.provide(Ripgrep.defaultLayer), Effect.runPromise)
const files = await run(
Ripgrep.Service.use((rg) =>
rg.files({ cwd: tmp.path, glob: ["*.ts"] }).pipe(
Stream.runCollect,
Effect.map((c) => [...c]),
),
),
)
expect(files).toEqual(["keep.ts"])
})
test("files dies on nonexistent directory", async () => {
const exit = await Effect.gen(function* () {
const rg = yield* Ripgrep.Service
return yield* rg.files({ cwd: "/tmp/nonexistent-dir-12345" }).pipe(Stream.runCollect)
}).pipe(Effect.provide(Ripgrep.defaultLayer), Effect.runPromiseExit)
const exit = await Ripgrep.Service.use((rg) =>
rg.files({ cwd: "/tmp/nonexistent-dir-12345" }).pipe(Stream.runCollect),
).pipe(Effect.provide(Ripgrep.defaultLayer), Effect.runPromiseExit)
expect(exit._tag).toBe("Failure")
})
test("ignores RIPGREP_CONFIG_PATH in direct mode", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(path.join(dir, "match.ts"), "const needle = 1\n")
},
})
const prev = process.env["RIPGREP_CONFIG_PATH"]
process.env["RIPGREP_CONFIG_PATH"] = path.join(tmp.path, "missing-ripgreprc")
try {
const result = await run(Ripgrep.Service.use((rg) => rg.search({ cwd: tmp.path, pattern: "needle" })))
expect(result.items).toHaveLength(1)
} finally {
if (prev === undefined) delete process.env["RIPGREP_CONFIG_PATH"]
else process.env["RIPGREP_CONFIG_PATH"] = prev
}
})
test("ignores RIPGREP_CONFIG_PATH in worker mode", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(path.join(dir, "match.ts"), "const needle = 1\n")
},
})
const prev = process.env["RIPGREP_CONFIG_PATH"]
process.env["RIPGREP_CONFIG_PATH"] = path.join(tmp.path, "missing-ripgreprc")
try {
const result = await run(Ripgrep.Service.use((rg) => rg.search({ cwd: tmp.path, pattern: "needle" })))
expect(result.items).toHaveLength(1)
} finally {
if (prev === undefined) delete process.env["RIPGREP_CONFIG_PATH"]
else process.env["RIPGREP_CONFIG_PATH"] = prev
}
})
})