Skip to content

Commit 90880bd

Browse files
authored
Merge branch 'dev' into fix/remote-workspace-proxy-body
2 parents 966bf77 + 00a6f22 commit 90880bd

3 files changed

Lines changed: 12 additions & 116 deletions

File tree

packages/core/src/project.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export const layer = Layer.effect(
108108
if (!repo) return { id: ID.global, directory: input, vcs: undefined }
109109

110110
const previous = yield* cached(repo.store)
111-
const id = (yield* remote(repo)) ?? previous ?? (yield* root(repo))
111+
const id = previous ?? (yield* root(repo))
112112

113113
return {
114114
previous,

packages/core/test/project.test.ts

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,11 @@ import path from "path"
55
import { Effect } from "effect"
66
import { Project } from "@opencode-ai/core/project"
77
import { AbsolutePath } from "@opencode-ai/core/schema"
8-
import { Hash } from "@opencode-ai/core/util/hash"
98
import { tmpdir } from "./fixture/tmpdir"
109
import { testEffect } from "./lib/effect"
1110

1211
const it = testEffect(Project.defaultLayer)
1312

14-
function remoteID(remote: string) {
15-
return Project.ID.make(Hash.fast(`git-remote:${remote}`))
16-
}
17-
1813
function abs(value: string) {
1914
return AbsolutePath.make(value)
2015
}
@@ -91,7 +86,7 @@ describe("ProjectV2.resolve", () => {
9186
}),
9287
)
9388

94-
it.live("prefers normalized origin over root commit", () =>
89+
it.live("uses root commit when origin exists", () =>
9590
Effect.gen(function* () {
9691
const tmp = yield* Effect.acquireRelease(
9792
Effect.promise(() => tmpdir()),
@@ -102,36 +97,13 @@ describe("ProjectV2.resolve", () => {
10297

10398
const result = yield* project.resolve(abs(tmp.path))
10499

105-
expect(result.id).toBe(remoteID("github.com/Acme/App"))
106-
expect(result.id).not.toBe(Project.ID.make(yield* Effect.promise(() => rootCommit(tmp.path))))
100+
expect(result.id).toBe(Project.ID.make(yield* Effect.promise(() => rootCommit(tmp.path))))
107101
expect(result.directory).toBe(yield* real(tmp.path))
108102
expect(result.vcs?.type).toBe("git")
109103
}),
110104
)
111105

112-
it.live("normalizes ssh and https remotes to the same id", () =>
113-
Effect.gen(function* () {
114-
const ssh = yield* Effect.acquireRelease(
115-
Effect.promise(() => tmpdir()),
116-
(tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()),
117-
)
118-
const https = yield* Effect.acquireRelease(
119-
Effect.promise(() => tmpdir()),
120-
(tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()),
121-
)
122-
yield* Effect.promise(() => initRepo(ssh.path, { commit: true, remote: "git@github.com:owner/repo.git" }))
123-
yield* Effect.promise(() => initRepo(https.path, { commit: true, remote: "https://github.com/owner/repo.git" }))
124-
const project = yield* Project.Service
125-
126-
const a = yield* project.resolve(abs(ssh.path))
127-
const b = yield* project.resolve(abs(https.path))
128-
129-
expect(a.id).toBe(remoteID("github.com/owner/repo"))
130-
expect(b.id).toBe(a.id)
131-
}),
132-
)
133-
134-
it.live("ignores file remotes and falls back to root commit", () =>
106+
it.live("uses root commit when local remote exists", () =>
135107
Effect.gen(function* () {
136108
const tmp = yield* Effect.acquireRelease(
137109
Effect.promise(() => tmpdir()),
@@ -146,7 +118,7 @@ describe("ProjectV2.resolve", () => {
146118
}),
147119
)
148120

149-
it.live("returns previous cached id from common dir", () =>
121+
it.live("prefers previous cached id over origin", () =>
150122
Effect.gen(function* () {
151123
const tmp = yield* Effect.acquireRelease(
152124
Effect.promise(() => tmpdir()),
@@ -159,7 +131,7 @@ describe("ProjectV2.resolve", () => {
159131
const result = yield* project.resolve(abs(tmp.path))
160132

161133
expect(result.previous).toBe(Project.ID.make("old-id"))
162-
expect(result.id).toBe(remoteID("github.com/owner/repo"))
134+
expect(result.id).toBe(Project.ID.make("old-id"))
163135
}),
164136
)
165137

@@ -213,7 +185,7 @@ describe("ProjectV2.resolve", () => {
213185

214186
expect(result.directory).toBe(yield* real(worktree))
215187
expect(result.previous).toBe(Project.ID.make("old-id"))
216-
expect(result.id).toBe(remoteID("github.com/owner/repo"))
188+
expect(result.id).toBe(Project.ID.make("old-id"))
217189
expect(result.vcs?.type).toBe("git")
218190
}),
219191
)

packages/opencode/test/project/project.test.ts

Lines changed: 5 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,6 @@ import path from "path"
77
import { tmpdirScoped } from "../fixture/fixture"
88
import { GlobalBus } from "../../src/bus/global"
99
import { ProjectID } from "../../src/project/schema"
10-
import { Database } from "@/storage/db"
11-
import { ProjectTable } from "@/project/project.sql"
12-
import { SessionTable } from "@/session/session.sql"
13-
import { PermissionTable } from "@/session/session.sql"
14-
import { WorkspaceTable } from "@/control-plane/workspace.sql"
15-
import { eq } from "drizzle-orm"
16-
import { Hash } from "@opencode-ai/core/util/hash"
17-
import { SessionID } from "@/session/schema"
18-
import { WorkspaceID } from "@/control-plane/schema"
1910
import { Cause, Effect, Exit, Layer, Stream } from "effect"
2011
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
2112
import { NodePath } from "@effect/platform-node"
@@ -40,10 +31,6 @@ function run<A, E>(fn: (svc: Project.Interface) => Effect.Effect<A, E>) {
4031
})
4132
}
4233

43-
function remoteProjectID(remote: string) {
44-
return ProjectID.make(Hash.fast(`git-remote:${remote}`))
45-
}
46-
4734
/**
4835
* Creates a mock ChildProcessSpawner layer that intercepts git subcommands
4936
* matching `failArg` and returns exit code 128, while delegating everything
@@ -167,91 +154,28 @@ describe("Project.fromDirectory", () => {
167154
}),
168155
)
169156

170-
it.live("prefers normalized origin remote over root commit", () =>
157+
it.live("keeps root commit identity when origin exists", () =>
171158
Effect.gen(function* () {
172159
const tmp = yield* tmpdirScoped({ git: true })
173160
yield* Effect.promise(() => $`git remote add origin git@github.com:Test-Org/Test-Repo.git`.cwd(tmp).quiet())
174161

175162
const { project } = yield* run((svc) => svc.fromDirectory(tmp))
163+
const root = (yield* Effect.promise(() => $`git rev-list --max-parents=0 HEAD`.cwd(tmp).text())).trim()
176164

177-
expect(project.id).toBe(remoteProjectID("github.com/Test-Org/Test-Repo"))
178-
}),
179-
)
180-
181-
it.live("normalizes equivalent origin URL forms to the same project ID", () =>
182-
Effect.gen(function* () {
183-
const ssh = yield* tmpdirScoped({ git: true })
184-
const https = yield* tmpdirScoped({ git: true })
185-
yield* Effect.promise(() => $`git remote add origin git@github.com:owner/repo.git`.cwd(ssh).quiet())
186-
yield* Effect.promise(() => $`git remote add origin https://github.com/owner/repo.git`.cwd(https).quiet())
187-
188-
const { project: a } = yield* run((svc) => svc.fromDirectory(ssh))
189-
const { project: b } = yield* run((svc) => svc.fromDirectory(https))
190-
191-
expect(a.id).toBe(remoteProjectID("github.com/owner/repo"))
192-
expect(b.id).toBe(a.id)
165+
expect(project.id).toBe(ProjectID.make(root))
193166
}),
194167
)
195168

196-
it.live("migrates cached root project data when origin becomes available", () =>
169+
it.live("keeps cached project identity when origin becomes available", () =>
197170
Effect.gen(function* () {
198171
const tmp = yield* tmpdirScoped({ git: true })
199172
const projects = yield* Project.Service
200173
const { project: rootProject } = yield* projects.fromDirectory(tmp)
201-
const remoteID = remoteProjectID("github.com/acme/app")
202-
const sessionID = crypto.randomUUID() as SessionID
203-
const workspaceID = WorkspaceID.ascending()
204-
205-
yield* Effect.sync(() => {
206-
Database.use((db) => {
207-
db.insert(SessionTable)
208-
.values({
209-
id: sessionID,
210-
project_id: rootProject.id,
211-
slug: sessionID,
212-
directory: tmp,
213-
title: "test",
214-
version: "0.0.0-test",
215-
time_created: Date.now(),
216-
time_updated: Date.now(),
217-
})
218-
.run()
219-
db.insert(PermissionTable)
220-
.values({
221-
project_id: rootProject.id,
222-
data: [{ permission: "edit", pattern: "*", action: "allow" }],
223-
time_created: Date.now(),
224-
time_updated: Date.now(),
225-
})
226-
.run()
227-
db.insert(WorkspaceTable)
228-
.values({
229-
id: workspaceID,
230-
type: "local",
231-
name: "test",
232-
project_id: rootProject.id,
233-
})
234-
.run()
235-
})
236-
})
237174
yield* Effect.promise(() => $`git remote add origin git@github.com:acme/app.git`.cwd(tmp).quiet())
238175

239176
const { project } = yield* projects.fromDirectory(tmp)
240177

241-
expect(project.id).toBe(remoteID)
242-
expect(
243-
Database.use((db) => db.select().from(ProjectTable).where(eq(ProjectTable.id, rootProject.id)).get()),
244-
).toBeUndefined()
245-
expect(
246-
Database.use((db) => db.select().from(SessionTable).where(eq(SessionTable.id, sessionID)).get())?.project_id,
247-
).toBe(remoteID)
248-
expect(
249-
Database.use((db) => db.select().from(PermissionTable).where(eq(PermissionTable.project_id, remoteID)).get()),
250-
).toBeDefined()
251-
expect(
252-
Database.use((db) => db.select().from(WorkspaceTable).where(eq(WorkspaceTable.id, workspaceID)).get())
253-
?.project_id,
254-
).toBe(remoteID)
178+
expect(project.id).toBe(rootProject.id)
255179
}),
256180
)
257181
})

0 commit comments

Comments
 (0)