diff --git a/packages/core/src/git.ts b/packages/core/src/git.ts index 500a69ea4d..a574523368 100644 --- a/packages/core/src/git.ts +++ b/packages/core/src/git.ts @@ -79,7 +79,10 @@ export const layer = Layer.effect( }), ) -export const defaultLayer = layer.pipe(Layer.provide(AppFileSystem.defaultLayer), Layer.provide(AppProcess.defaultLayer)) +export const defaultLayer = layer.pipe( + Layer.provide(AppFileSystem.defaultLayer), + Layer.provide(AppProcess.defaultLayer), +) interface Result { readonly exitCode: number @@ -97,7 +100,7 @@ function run(cwd: string, proc: AppProcess.Interface) { }), ) .pipe( - Effect.map((result) => ({ exitCode: result.exitCode, text: result.stdout.toString("utf8") } satisfies Result)), + Effect.map((result) => ({ exitCode: result.exitCode, text: result.stdout.toString("utf8") }) satisfies Result), Effect.catch(() => Effect.succeed({ exitCode: 1, text: "" } satisfies Result)), ) } diff --git a/packages/core/test/project.test.ts b/packages/core/test/project.test.ts index bc457d767c..c5b96b6389 100644 --- a/packages/core/test/project.test.ts +++ b/packages/core/test/project.test.ts @@ -40,7 +40,10 @@ async function rootCommit(dir: string) { describe("ProjectV2.resolve", () => { it.live("returns global for non-git directory", () => Effect.gen(function* () { - const tmp = yield* Effect.acquireRelease(Effect.promise(() => tmpdir()), (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]())) + const tmp = yield* Effect.acquireRelease( + Effect.promise(() => tmpdir()), + (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()), + ) const project = yield* Project.Service const result = yield* project.resolve(abs(tmp.path)) @@ -54,7 +57,10 @@ describe("ProjectV2.resolve", () => { it.live("returns git global for repo with no commits and no remote", () => Effect.gen(function* () { - const tmp = yield* Effect.acquireRelease(Effect.promise(() => tmpdir()), (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]())) + const tmp = yield* Effect.acquireRelease( + Effect.promise(() => tmpdir()), + (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()), + ) yield* Effect.promise(() => initRepo(tmp.path)) const project = yield* Project.Service @@ -69,7 +75,10 @@ describe("ProjectV2.resolve", () => { it.live("falls back to root commit when origin is missing", () => Effect.gen(function* () { - const tmp = yield* Effect.acquireRelease(Effect.promise(() => tmpdir()), (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]())) + const tmp = yield* Effect.acquireRelease( + Effect.promise(() => tmpdir()), + (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()), + ) yield* Effect.promise(() => initRepo(tmp.path, { commit: true })) const project = yield* Project.Service @@ -84,7 +93,10 @@ describe("ProjectV2.resolve", () => { it.live("prefers normalized origin over root commit", () => Effect.gen(function* () { - const tmp = yield* Effect.acquireRelease(Effect.promise(() => tmpdir()), (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]())) + const tmp = yield* Effect.acquireRelease( + Effect.promise(() => tmpdir()), + (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()), + ) yield* Effect.promise(() => initRepo(tmp.path, { commit: true, remote: "git@github.com:Acme/App.git" })) const project = yield* Project.Service @@ -99,8 +111,14 @@ describe("ProjectV2.resolve", () => { it.live("normalizes ssh and https remotes to the same id", () => Effect.gen(function* () { - const ssh = yield* Effect.acquireRelease(Effect.promise(() => tmpdir()), (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]())) - const https = yield* Effect.acquireRelease(Effect.promise(() => tmpdir()), (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]())) + const ssh = yield* Effect.acquireRelease( + Effect.promise(() => tmpdir()), + (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()), + ) + const https = yield* Effect.acquireRelease( + Effect.promise(() => tmpdir()), + (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()), + ) yield* Effect.promise(() => initRepo(ssh.path, { commit: true, remote: "git@github.com:owner/repo.git" })) yield* Effect.promise(() => initRepo(https.path, { commit: true, remote: "https://github.com/owner/repo.git" })) const project = yield* Project.Service @@ -115,7 +133,10 @@ describe("ProjectV2.resolve", () => { it.live("ignores file remotes and falls back to root commit", () => Effect.gen(function* () { - const tmp = yield* Effect.acquireRelease(Effect.promise(() => tmpdir()), (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]())) + const tmp = yield* Effect.acquireRelease( + Effect.promise(() => tmpdir()), + (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()), + ) yield* Effect.promise(() => initRepo(tmp.path, { commit: true, remote: `file://${tmp.path}` })) const project = yield* Project.Service @@ -127,7 +148,10 @@ describe("ProjectV2.resolve", () => { it.live("returns previous cached id from common dir", () => Effect.gen(function* () { - const tmp = yield* Effect.acquireRelease(Effect.promise(() => tmpdir()), (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]())) + const tmp = yield* Effect.acquireRelease( + Effect.promise(() => tmpdir()), + (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()), + ) yield* Effect.promise(() => initRepo(tmp.path, { commit: true, remote: "git@github.com:owner/repo.git" })) yield* Effect.promise(() => Bun.write(path.join(tmp.path, ".git", "opencode"), "old-id")) const project = yield* Project.Service @@ -141,7 +165,10 @@ describe("ProjectV2.resolve", () => { it.live("does not write the cache while resolving", () => Effect.gen(function* () { - const tmp = yield* Effect.acquireRelease(Effect.promise(() => tmpdir()), (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]())) + const tmp = yield* Effect.acquireRelease( + Effect.promise(() => tmpdir()), + (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()), + ) yield* Effect.promise(() => initRepo(tmp.path, { commit: true, remote: "git@github.com:owner/repo.git" })) const project = yield* Project.Service @@ -153,7 +180,10 @@ describe("ProjectV2.resolve", () => { it.live("resolves from nested directories to repo root", () => Effect.gen(function* () { - const tmp = yield* Effect.acquireRelease(Effect.promise(() => tmpdir()), (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]())) + const tmp = yield* Effect.acquireRelease( + Effect.promise(() => tmpdir()), + (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()), + ) yield* Effect.promise(() => initRepo(tmp.path, { commit: true })) yield* Effect.promise(() => fs.mkdir(path.join(tmp.path, "a", "b"), { recursive: true })) const project = yield* Project.Service @@ -166,9 +196,14 @@ describe("ProjectV2.resolve", () => { it.live("linked worktree returns opened worktree directory and previous from common dir", () => Effect.gen(function* () { - const tmp = yield* Effect.acquireRelease(Effect.promise(() => tmpdir()), (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]())) + const tmp = yield* Effect.acquireRelease( + Effect.promise(() => tmpdir()), + (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()), + ) const worktree = `${tmp.path}-worktree` - yield* Effect.addFinalizer(() => Effect.promise(() => $`rm -rf ${worktree}`.quiet().nothrow()).pipe(Effect.ignore)) + yield* Effect.addFinalizer(() => + Effect.promise(() => $`rm -rf ${worktree}`.quiet().nothrow()).pipe(Effect.ignore), + ) yield* Effect.promise(() => initRepo(tmp.path, { commit: true, remote: "git@github.com:owner/repo.git" })) yield* Effect.promise(() => Bun.write(path.join(tmp.path, ".git", "opencode"), "old-id")) yield* Effect.promise(() => $`git worktree add ${worktree} -b test-${Date.now()}`.cwd(tmp.path).quiet()) diff --git a/packages/opencode/src/project/project.ts b/packages/opencode/src/project/project.ts index ce7997765a..a12c2cde1f 100644 --- a/packages/opencode/src/project/project.ts +++ b/packages/opencode/src/project/project.ts @@ -180,7 +180,10 @@ export const layer = Layer.effect( const scope = yield* Scope.Scope - const migrateProjectId = Effect.fn("Project.migrateProjectId")(function* (oldID: ProjectID | undefined, newID: ProjectID) { + const migrateProjectId = Effect.fn("Project.migrateProjectId")(function* ( + oldID: ProjectID | undefined, + newID: ProjectID, + ) { if (!oldID) return if (oldID === ProjectID.global) return if (oldID === newID) return @@ -255,7 +258,11 @@ export const layer = Layer.effect( vcs: data.vcs?.type ?? fakeVcs, time: { ...existing.time, updated: Date.now() }, } - if (projectID !== ProjectID.global && data.directory !== result.worktree && !result.sandboxes.includes(data.directory)) + if ( + projectID !== ProjectID.global && + data.directory !== result.worktree && + !result.sandboxes.includes(data.directory) + ) result.sandboxes.push(data.directory) result.sandboxes = yield* Effect.forEach( result.sandboxes, diff --git a/packages/opencode/test/project/project.test.ts b/packages/opencode/test/project/project.test.ts index ff5478a4d4..869326d87a 100644 --- a/packages/opencode/test/project/project.test.ts +++ b/packages/opencode/test/project/project.test.ts @@ -239,10 +239,19 @@ describe("Project.fromDirectory", () => { const { project } = yield* projects.fromDirectory(tmp) expect(project.id).toBe(remoteID) - expect(Database.use((db) => db.select().from(ProjectTable).where(eq(ProjectTable.id, rootProject.id)).get())).toBeUndefined() - expect(Database.use((db) => db.select().from(SessionTable).where(eq(SessionTable.id, sessionID)).get())?.project_id).toBe(remoteID) - expect(Database.use((db) => db.select().from(PermissionTable).where(eq(PermissionTable.project_id, remoteID)).get())).toBeDefined() - expect(Database.use((db) => db.select().from(WorkspaceTable).where(eq(WorkspaceTable.id, workspaceID)).get())?.project_id).toBe(remoteID) + expect( + Database.use((db) => db.select().from(ProjectTable).where(eq(ProjectTable.id, rootProject.id)).get()), + ).toBeUndefined() + expect( + Database.use((db) => db.select().from(SessionTable).where(eq(SessionTable.id, sessionID)).get())?.project_id, + ).toBe(remoteID) + expect( + Database.use((db) => db.select().from(PermissionTable).where(eq(PermissionTable.project_id, remoteID)).get()), + ).toBeDefined() + expect( + Database.use((db) => db.select().from(WorkspaceTable).where(eq(WorkspaceTable.id, workspaceID)).get()) + ?.project_id, + ).toBe(remoteID) }), ) })