Files
orca/src/main/runtime/runtime-git-sync-commands.ts
T
Neil d456549c22 refactor runtime Git bridges (#16189)
* refactor runtime git bridges

* fix(test): avoid computed namespace import access in runtime Git client contract test
2026-08-25 00:54:43 -07:00

186 lines
7.1 KiB
TypeScript

import type { GitForkSyncExpectedUpstream, GitForkSyncResult } from '../../shared/git-fork-sync'
import type { GitUpstreamStatus } from '../../shared/git-status-types'
import type { GitPushTarget } from '../../shared/worktree/types'
import { gitSyncForkDefaultBranch } from '../git/fork-sync'
import { gitFastForward, gitFetch, gitPull, gitPullRebaseFromBase, gitPush } from '../git/remote'
import { abortMerge, abortRebase, commitChanges } from '../git/status'
import { getUpstreamStatus } from '../git/upstream'
import {
getSshGitProvider,
SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE
} from '../providers/ssh-git-dispatch'
import { localGitOptionsForTarget, type RuntimeGitCommandHost } from './runtime-git-command-target'
export class RuntimeGitSyncCommands {
constructor(private readonly host: RuntimeGitCommandHost) {}
async abortRuntimeGitMerge(worktreeSelector: string): Promise<{ ok: true }> {
const target = await this.host.resolveRuntimeGitTarget(worktreeSelector)
const provider = target.connectionId ? getSshGitProvider(target.connectionId) : null
if (target.connectionId) {
if (!provider) {
throw new Error(SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE)
}
await provider.abortMerge(target.worktree.path)
return { ok: true }
}
await abortMerge(target.worktree.path, localGitOptionsForTarget(target))
return { ok: true }
}
async abortRuntimeGitRebase(worktreeSelector: string): Promise<{ ok: true }> {
const target = await this.host.resolveRuntimeGitTarget(worktreeSelector)
const provider = target.connectionId ? getSshGitProvider(target.connectionId) : null
if (target.connectionId) {
if (!provider) {
throw new Error(SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE)
}
await provider.abortRebase(target.worktree.path)
return { ok: true }
}
await abortRebase(target.worktree.path, localGitOptionsForTarget(target))
return { ok: true }
}
async getRuntimeGitUpstreamStatus(
worktreeSelector: string,
pushTarget?: GitPushTarget
): Promise<GitUpstreamStatus> {
const target = await this.host.resolveRuntimeGitTarget(worktreeSelector)
const provider = target.connectionId ? getSshGitProvider(target.connectionId) : null
if (target.connectionId) {
if (!provider) {
throw new Error(SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE)
}
return provider.getUpstreamStatus(target.worktree.path, pushTarget)
}
return getUpstreamStatus(target.worktree.path, pushTarget, localGitOptionsForTarget(target))
}
async fetchRuntimeGit(
worktreeSelector: string,
pushTarget?: GitPushTarget
): Promise<{ ok: true }> {
const target = await this.host.resolveRuntimeGitTarget(worktreeSelector)
const provider = target.connectionId ? getSshGitProvider(target.connectionId) : null
if (target.connectionId) {
if (!provider) {
throw new Error(SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE)
}
await provider.fetchRemote(target.worktree.path, pushTarget)
return { ok: true }
}
await gitFetch(target.worktree.path, pushTarget, localGitOptionsForTarget(target))
return { ok: true }
}
async syncRuntimeGitForkDefaultBranch(
worktreeSelector: string,
expectedUpstream: GitForkSyncExpectedUpstream
): Promise<GitForkSyncResult> {
const target = await this.host.resolveRuntimeGitTarget(worktreeSelector)
const provider = target.connectionId ? getSshGitProvider(target.connectionId) : null
if (target.connectionId) {
if (!provider) {
throw new Error(SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE)
}
return provider.syncForkDefaultBranch(target.worktree.path, expectedUpstream)
}
return gitSyncForkDefaultBranch(
target.worktree.path,
expectedUpstream,
localGitOptionsForTarget(target)
)
}
async pullRuntimeGit(
worktreeSelector: string,
pushTarget?: GitPushTarget
): Promise<{ ok: true }> {
const target = await this.host.resolveRuntimeGitTarget(worktreeSelector)
const provider = target.connectionId ? getSshGitProvider(target.connectionId) : null
if (target.connectionId) {
if (!provider) {
throw new Error(SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE)
}
await provider.pullBranch(target.worktree.path, pushTarget)
return { ok: true }
}
await gitPull(target.worktree.path, pushTarget, localGitOptionsForTarget(target))
return { ok: true }
}
async fastForwardRuntimeGit(
worktreeSelector: string,
pushTarget?: GitPushTarget
): Promise<{ ok: true }> {
const target = await this.host.resolveRuntimeGitTarget(worktreeSelector)
const provider = target.connectionId ? getSshGitProvider(target.connectionId) : null
if (target.connectionId) {
if (!provider) {
throw new Error(SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE)
}
await provider.fastForwardBranch(target.worktree.path, pushTarget)
return { ok: true }
}
await gitFastForward(target.worktree.path, pushTarget, localGitOptionsForTarget(target))
return { ok: true }
}
async rebaseRuntimeGitFromBase(worktreeSelector: string, baseRef: string): Promise<{ ok: true }> {
const target = await this.host.resolveRuntimeGitTarget(worktreeSelector)
const provider = target.connectionId ? getSshGitProvider(target.connectionId) : null
if (target.connectionId) {
if (!provider) {
throw new Error(SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE)
}
await provider.rebaseFromBase(target.worktree.path, baseRef)
return { ok: true }
}
await gitPullRebaseFromBase(target.worktree.path, baseRef, localGitOptionsForTarget(target))
return { ok: true }
}
async pushRuntimeGit(
worktreeSelector: string,
publish?: boolean,
pushTarget?: GitPushTarget,
forceWithLease?: boolean
): Promise<{ ok: true }> {
const target = await this.host.resolveRuntimeGitTarget(worktreeSelector)
const provider = target.connectionId ? getSshGitProvider(target.connectionId) : null
if (target.connectionId) {
if (!provider) {
throw new Error(SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE)
}
await provider.pushBranch(target.worktree.path, publish === true, pushTarget, {
forceWithLease: forceWithLease === true
})
return { ok: true }
}
await gitPush(target.worktree.path, publish === true, pushTarget, {
forceWithLease: forceWithLease === true,
...localGitOptionsForTarget(target)
})
return { ok: true }
}
async commitRuntimeGit(
worktreeSelector: string,
message: string
): Promise<{ success: boolean; error?: string }> {
if (message.trim().length === 0) {
throw new Error('Commit message is required')
}
const target = await this.host.resolveRuntimeGitTarget(worktreeSelector)
const provider = target.connectionId ? getSshGitProvider(target.connectionId) : null
if (target.connectionId) {
if (!provider) {
throw new Error(SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE)
}
return provider.commit(target.worktree.path, message)
}
return commitChanges(target.worktree.path, message, localGitOptionsForTarget(target))
}
}