Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/opencode/src/file/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ export class FileService extends ServiceMap.Service<FileService, FileService.Ser
}

const init = Effect.fn("FileService.init")(function* () {
void kick()
yield* Effect.promise(() => kick())
})

const status = Effect.fn("FileService.status")(function* () {
Expand Down
22 changes: 7 additions & 15 deletions packages/opencode/test/file/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -681,9 +681,7 @@ describe("file/index Filesystem patterns", () => {
await Instance.provide({
directory: tmp.path,
fn: async () => {
File.init()
// Give the background scan time to populate
await new Promise((r) => setTimeout(r, 500))
await File.init()

const result = await File.search({ query: "", type: "file" })
expect(result.length).toBeGreaterThan(0)
Expand All @@ -697,8 +695,7 @@ describe("file/index Filesystem patterns", () => {
await Instance.provide({
directory: tmp.path,
fn: async () => {
File.init()
await new Promise((r) => setTimeout(r, 500))
await File.init()

const result = await File.search({ query: "", type: "directory" })
expect(result.length).toBeGreaterThan(0)
Expand All @@ -718,8 +715,7 @@ describe("file/index Filesystem patterns", () => {
await Instance.provide({
directory: tmp.path,
fn: async () => {
File.init()
await new Promise((r) => setTimeout(r, 500))
await File.init()

const result = await File.search({ query: "main", type: "file" })
expect(result.some((f) => f.includes("main"))).toBe(true)
Expand All @@ -733,8 +729,7 @@ describe("file/index Filesystem patterns", () => {
await Instance.provide({
directory: tmp.path,
fn: async () => {
File.init()
await new Promise((r) => setTimeout(r, 500))
await File.init()

const result = await File.search({ query: "", type: "file" })
// Files don't end with /
Expand All @@ -751,8 +746,7 @@ describe("file/index Filesystem patterns", () => {
await Instance.provide({
directory: tmp.path,
fn: async () => {
File.init()
await new Promise((r) => setTimeout(r, 500))
await File.init()

const result = await File.search({ query: "", type: "directory" })
// Directories end with /
Expand All @@ -769,8 +763,7 @@ describe("file/index Filesystem patterns", () => {
await Instance.provide({
directory: tmp.path,
fn: async () => {
File.init()
await new Promise((r) => setTimeout(r, 500))
await File.init()

const result = await File.search({ query: "", type: "file", limit: 2 })
expect(result.length).toBeLessThanOrEqual(2)
Expand All @@ -784,8 +777,7 @@ describe("file/index Filesystem patterns", () => {
await Instance.provide({
directory: tmp.path,
fn: async () => {
File.init()
await new Promise((r) => setTimeout(r, 500))
await File.init()

const result = await File.search({ query: ".hidden", type: "directory" })
expect(result.length).toBeGreaterThan(0)
Expand Down
62 changes: 42 additions & 20 deletions packages/opencode/test/file/time.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ import { tmpdir } from "../fixture/fixture"

afterEach(() => Instance.disposeAll())

async function touch(file: string, time: number) {
const date = new Date(time)
await fs.utimes(file, date, date)
}

function gate() {
let open!: () => void
const wait = new Promise<void>((resolve) => {
open = resolve
})
return { open, wait }
}

describe("file/time", () => {
const sessionID = SessionID.make("ses_00000000000000000000000001")

Expand All @@ -25,7 +38,6 @@ describe("file/time", () => {
expect(before).toBeUndefined()

await FileTime.read(sessionID, filepath)
await Bun.sleep(10)

const after = await FileTime.get(sessionID, filepath)
expect(after).toBeInstanceOf(Date)
Expand All @@ -44,7 +56,6 @@ describe("file/time", () => {
fn: async () => {
await FileTime.read(SessionID.make("ses_00000000000000000000000002"), filepath)
await FileTime.read(SessionID.make("ses_00000000000000000000000003"), filepath)
await Bun.sleep(10)

const time1 = await FileTime.get(SessionID.make("ses_00000000000000000000000002"), filepath)
const time2 = await FileTime.get(SessionID.make("ses_00000000000000000000000003"), filepath)
Expand All @@ -63,14 +74,10 @@ describe("file/time", () => {
await Instance.provide({
directory: tmp.path,
fn: async () => {
FileTime.read(sessionID, filepath)
await Bun.sleep(10)
await FileTime.read(sessionID, filepath)
const first = await FileTime.get(sessionID, filepath)

await Bun.sleep(10)

FileTime.read(sessionID, filepath)
await Bun.sleep(10)
await FileTime.read(sessionID, filepath)
const second = await FileTime.get(sessionID, filepath)

expect(second!.getTime()).toBeGreaterThanOrEqual(first!.getTime())
Expand All @@ -84,12 +91,12 @@ describe("file/time", () => {
await using tmp = await tmpdir()
const filepath = path.join(tmp.path, "file.txt")
await fs.writeFile(filepath, "content", "utf-8")
await touch(filepath, 1_000)

await Instance.provide({
directory: tmp.path,
fn: async () => {
FileTime.read(sessionID, filepath)
await Bun.sleep(10)
await FileTime.read(sessionID, filepath)
await FileTime.assert(sessionID, filepath)
},
})
Expand All @@ -112,13 +119,14 @@ describe("file/time", () => {
await using tmp = await tmpdir()
const filepath = path.join(tmp.path, "file.txt")
await fs.writeFile(filepath, "content", "utf-8")
await touch(filepath, 1_000)

await Instance.provide({
directory: tmp.path,
fn: async () => {
FileTime.read(sessionID, filepath)
await Bun.sleep(100)
await FileTime.read(sessionID, filepath)
await fs.writeFile(filepath, "modified content", "utf-8")
await touch(filepath, 2_000)
await expect(FileTime.assert(sessionID, filepath)).rejects.toThrow("modified since it was last read")
},
})
Expand All @@ -128,13 +136,14 @@ describe("file/time", () => {
await using tmp = await tmpdir()
const filepath = path.join(tmp.path, "file.txt")
await fs.writeFile(filepath, "content", "utf-8")
await touch(filepath, 1_000)

await Instance.provide({
directory: tmp.path,
fn: async () => {
await FileTime.read(sessionID, filepath)
await Bun.sleep(100)
await fs.writeFile(filepath, "modified", "utf-8")
await touch(filepath, 2_000)

let error: Error | undefined
try {
Expand Down Expand Up @@ -191,18 +200,25 @@ describe("file/time", () => {
directory: tmp.path,
fn: async () => {
const order: number[] = []
const hold = gate()
const ready = gate()

const op1 = FileTime.withLock(filepath, async () => {
order.push(1)
await Bun.sleep(50)
ready.open()
await hold.wait
order.push(2)
})

await ready.wait

const op2 = FileTime.withLock(filepath, async () => {
order.push(3)
order.push(4)
})

hold.open()

await Promise.all([op1, op2])
expect(order).toEqual([1, 2, 3, 4])
},
Expand All @@ -219,15 +235,21 @@ describe("file/time", () => {
fn: async () => {
let started1 = false
let started2 = false
const hold = gate()
const ready = gate()

const op1 = FileTime.withLock(filepath1, async () => {
started1 = true
await Bun.sleep(50)
ready.open()
await hold.wait
expect(started2).toBe(true)
})

await ready.wait

const op2 = FileTime.withLock(filepath2, async () => {
started2 = true
hold.open()
})

await Promise.all([op1, op2])
Expand Down Expand Up @@ -265,12 +287,12 @@ describe("file/time", () => {
await using tmp = await tmpdir()
const filepath = path.join(tmp.path, "file.txt")
await fs.writeFile(filepath, "content", "utf-8")
await touch(filepath, 1_000)

await Instance.provide({
directory: tmp.path,
fn: async () => {
FileTime.read(sessionID, filepath)
await Bun.sleep(10)
await FileTime.read(sessionID, filepath)

const stats = Filesystem.stat(filepath)
expect(stats?.mtime).toBeInstanceOf(Date)
Expand All @@ -285,17 +307,17 @@ describe("file/time", () => {
await using tmp = await tmpdir()
const filepath = path.join(tmp.path, "file.txt")
await fs.writeFile(filepath, "original", "utf-8")
await touch(filepath, 1_000)

await Instance.provide({
directory: tmp.path,
fn: async () => {
FileTime.read(sessionID, filepath)
await Bun.sleep(10)
await FileTime.read(sessionID, filepath)

const originalStat = Filesystem.stat(filepath)

await Bun.sleep(100)
await fs.writeFile(filepath, "modified", "utf-8")
await touch(filepath, 2_000)

const newStat = Filesystem.stat(filepath)
expect(newStat!.mtime.getTime()).toBeGreaterThan(originalStat!.mtime.getTime())
Expand Down
1 change: 1 addition & 0 deletions packages/opencode/test/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ process.env["OPENCODE_TEST_HOME"] = testHome
// Set test managed config directory to isolate tests from system managed settings
const testManagedConfigDir = path.join(dir, "managed")
process.env["OPENCODE_TEST_MANAGED_CONFIG_DIR"] = testManagedConfigDir
process.env["OPENCODE_DISABLE_DEFAULT_PLUGINS"] = "true"

// Write the cache version file to prevent global/index.ts from clearing the cache
const cacheDir = path.join(dir, "cache", "opencode")
Expand Down
Loading
Loading