mirror of
https://gitee.com/zhangsken/opencode.git
synced 2026-10-16 10:30:01 +08:00
fix(vcs): accept explicit Git init provider
This commit is contained in:
@@ -63,5 +63,6 @@ for (const view of ["desktop", "mobile"] as const) {
|
||||
await test.info().attach("review-after-git", { body: await panel.screenshot(), contentType: "image/png" })
|
||||
expect(requests).toHaveLength(1)
|
||||
expect(new URL(requests[0]!).searchParams.get("location[directory]")).toBe(directory)
|
||||
expect(new URL(requests[0]!).searchParams.get("provider")).toBe("git")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ export function createSessionReview(input: {
|
||||
if (!sessionID) return
|
||||
setState("initializingGit", true)
|
||||
void server.api.vcs
|
||||
.init({ location: { directory } })
|
||||
.init({ location: { directory }, provider: "git" })
|
||||
.then(async () => {
|
||||
data.project.invalidate()
|
||||
data.session.invalidate(sessionID)
|
||||
|
||||
@@ -2223,7 +2223,10 @@ export interface WorktreeApi<E = never> {
|
||||
readonly refresh: WorktreeRefreshOperation<E>
|
||||
}
|
||||
|
||||
export type VcsInitInput = { readonly location?: { readonly directory?: string | undefined } | undefined }
|
||||
export type VcsInitInput = {
|
||||
readonly location?: { readonly directory?: string | undefined } | undefined
|
||||
readonly provider?: "git" | undefined
|
||||
}
|
||||
export type VcsInitOutput = void
|
||||
export type VcsInitOperation<E = never> = (input?: VcsInitInput) => Effect.Effect<VcsInitOutput, E>
|
||||
|
||||
|
||||
@@ -1454,7 +1454,9 @@ const adaptGroupWorktree = (raw: RawClient["server.worktree"]) => ({
|
||||
|
||||
const EndpointVcsInit = (raw: RawClient["server.vcs"]) => (input?: VcsInitInput) =>
|
||||
preserveEffect<VcsInitOutput>()(
|
||||
raw["vcs.init"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)),
|
||||
raw["vcs.init"]({ query: { location: input?.["location"], provider: input?.["provider"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
),
|
||||
)
|
||||
|
||||
const EndpointVcsGet = (raw: RawClient["server.vcs"]) => (input?: VcsGetInput) =>
|
||||
|
||||
@@ -2019,7 +2019,7 @@ export function make(options: ClientOptions) {
|
||||
{
|
||||
method: "POST",
|
||||
path: `/api/vcs/init`,
|
||||
query: { location: input?.["location"] },
|
||||
query: { location: input?.["location"], provider: input?.["provider"] },
|
||||
successStatus: 204,
|
||||
declaredStatuses: [400, 401, 409, 503],
|
||||
empty: true,
|
||||
|
||||
@@ -6250,7 +6250,14 @@ export type WorktreeRefreshInput = { readonly projectID: { readonly projectID: s
|
||||
export type WorktreeRefreshOutput = void
|
||||
|
||||
export type VcsInitInput = {
|
||||
readonly location?: { readonly location?: { readonly directory?: string | undefined } | undefined }["location"]
|
||||
readonly location?: {
|
||||
readonly location?: { readonly directory?: string | undefined } | undefined
|
||||
readonly provider?: "git" | undefined
|
||||
}["location"]
|
||||
readonly provider?: {
|
||||
readonly location?: { readonly directory?: string | undefined } | undefined
|
||||
readonly provider?: "git" | undefined
|
||||
}["provider"]
|
||||
}
|
||||
|
||||
export type VcsInitOutput = void
|
||||
|
||||
@@ -7,6 +7,11 @@ import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/un
|
||||
import { LocationQuery, locationQueryOpenApi } from "./location.js"
|
||||
import { ConflictError, InvalidRequestError, ServiceUnavailableError } from "../errors.js"
|
||||
|
||||
const InitQuery = Schema.Struct({
|
||||
...LocationQuery.fields,
|
||||
provider: Schema.optional(Schema.Literal("git")),
|
||||
})
|
||||
|
||||
const BranchesQuery = Schema.Struct({
|
||||
...LocationQuery.fields,
|
||||
search: Schema.optional(Schema.String),
|
||||
@@ -23,7 +28,7 @@ const DiffQuery = Schema.Struct({
|
||||
export const VcsGroup = HttpApiGroup.make("server.vcs")
|
||||
.add(
|
||||
HttpApiEndpoint.post("vcs.init", "/api/vcs/init", {
|
||||
query: LocationQuery,
|
||||
query: InitQuery,
|
||||
success: HttpApiSchema.NoContent,
|
||||
error: [ConflictError, InvalidRequestError, ServiceUnavailableError],
|
||||
})
|
||||
@@ -32,7 +37,8 @@ export const VcsGroup = HttpApiGroup.make("server.vcs")
|
||||
OpenApi.annotations({
|
||||
identifier: "vcs.init",
|
||||
summary: "Initialize Git repository",
|
||||
description: "Initialize Git in a markerless project's directory and refresh its location services.",
|
||||
description:
|
||||
"Initialize the selected repository type in a markerless project's directory and refresh its location services. Only git is supported; omitting provider defaults to git.",
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -80,6 +80,26 @@ it.live(
|
||||
15_000,
|
||||
)
|
||||
|
||||
it.live(
|
||||
"accepts an explicit Git provider and rejects unsupported providers without initializing",
|
||||
() =>
|
||||
Effect.gen(function* () {
|
||||
const tmp = yield* Effect.acquireDisposable(Effect.promise(() => tmpdir("opencode-vcs-provider-")))
|
||||
const server = yield* startServer(path.join(tmp.path, "config"))
|
||||
const url = new URL("/api/vcs/init", server.base)
|
||||
url.searchParams.set("location[directory]", tmp.path)
|
||||
url.searchParams.set("provider", "hg")
|
||||
const unsupported = yield* Effect.promise(() => fetch(url, { method: "POST", headers: server.headers }))
|
||||
expect(unsupported.status).toBe(400)
|
||||
expect(yield* Effect.promise(() => Bun.file(path.join(tmp.path, ".git", "HEAD")).exists())).toBe(false)
|
||||
url.searchParams.set("provider", "git")
|
||||
const initialized = yield* Effect.promise(() => fetch(url, { method: "POST", headers: server.headers }))
|
||||
expect(initialized.status).toBe(204)
|
||||
expect(yield* Effect.promise(() => Bun.file(path.join(tmp.path, ".git", "HEAD")).exists())).toBe(true)
|
||||
}),
|
||||
15_000,
|
||||
)
|
||||
|
||||
it.live(
|
||||
"serves lazy review bases, committed diffs, and unavailable-base errors",
|
||||
() =>
|
||||
|
||||
Reference in New Issue
Block a user