mirror of
https://github.com/stablyai/orca.git
synced 2026-09-29 16:02:50 +00:00
* Split speech session lifecycle * Split terminal output scheduler pipeline * Split mobile browser pane modules * Prune resolved max-lines suppressions * Split pane tree equalization logic * Extract mobile troubleshoot screen styles * Split external automation manager * Split main window service attachments * Split hosted review creation checks * Split automation dispatch event handling * Split settings navigation metadata * Split daemon initialization lifecycle * Split GitLab item dialog * Split relay dispatcher layers * Split mobile host screen * Retarget mobile view settings source test * Split runtime file client layers * Split ports panel layers * Split runtime environments pane layers * Split local PTY provider responsibilities * Split CDP bridge responsibilities * Split relay Git handler responsibilities * Track moved relay Git fetch audit * Fix F3-speech for #17123 * Fix F1-cycle for #17131 * Fix F4-navtest for #17157 * Fix F2-allowlist for #17161
135 lines
4.4 KiB
TypeScript
135 lines
4.4 KiB
TypeScript
import { GitHandlerOperationContext, GIT_BULK_CHUNK_SIZE } from './git-handler-operation-context'
|
|
import { commitChangesRelay } from './git-handler-worktree-ops'
|
|
|
|
const BULK_CHUNK_SIZE = GIT_BULK_CHUNK_SIZE
|
|
|
|
export class GitHandlerWorktreeChangeOperations extends GitHandlerOperationContext {
|
|
async stage(params: Record<string, unknown>) {
|
|
this.clearGitMutationReadCaches()
|
|
const worktreePath = params.worktreePath as string
|
|
const filePath = params.filePath as string
|
|
try {
|
|
await this.git(['add', '--', this.literalPathspec(filePath)], worktreePath)
|
|
} finally {
|
|
this.clearGitMutationReadCaches()
|
|
}
|
|
}
|
|
|
|
async commit(params: Record<string, unknown>): Promise<{ success: boolean; error?: string }> {
|
|
this.clearGitMutationReadCaches()
|
|
const worktreePath = params.worktreePath as string
|
|
const message = params.message as string
|
|
try {
|
|
return await commitChangesRelay(this.git.bind(this), worktreePath, message)
|
|
} finally {
|
|
this.clearGitMutationReadCaches()
|
|
}
|
|
}
|
|
|
|
async unstage(params: Record<string, unknown>) {
|
|
this.clearGitMutationReadCaches()
|
|
const worktreePath = params.worktreePath as string
|
|
const filePath = params.filePath as string
|
|
try {
|
|
await this.git(['restore', '--staged', '--', this.literalPathspec(filePath)], worktreePath)
|
|
} finally {
|
|
this.clearGitMutationReadCaches()
|
|
}
|
|
}
|
|
|
|
async bulkStage(params: Record<string, unknown>) {
|
|
this.clearGitMutationReadCaches()
|
|
const worktreePath = params.worktreePath as string
|
|
const filePaths = params.filePaths as string[]
|
|
try {
|
|
for (let i = 0; i < filePaths.length; i += BULK_CHUNK_SIZE) {
|
|
const chunk = filePaths.slice(i, i + BULK_CHUNK_SIZE)
|
|
await this.git(
|
|
['add', '--', ...chunk.map((filePath) => this.literalPathspec(filePath))],
|
|
worktreePath
|
|
)
|
|
}
|
|
} finally {
|
|
this.clearGitMutationReadCaches()
|
|
}
|
|
}
|
|
|
|
async bulkUnstage(params: Record<string, unknown>) {
|
|
this.clearGitMutationReadCaches()
|
|
const worktreePath = params.worktreePath as string
|
|
const filePaths = params.filePaths as string[]
|
|
try {
|
|
for (let i = 0; i < filePaths.length; i += BULK_CHUNK_SIZE) {
|
|
const chunk = filePaths.slice(i, i + BULK_CHUNK_SIZE)
|
|
await this.git(
|
|
['restore', '--staged', '--', ...chunk.map((filePath) => this.literalPathspec(filePath))],
|
|
worktreePath
|
|
)
|
|
}
|
|
} finally {
|
|
this.clearGitMutationReadCaches()
|
|
}
|
|
}
|
|
|
|
async abortMerge(params: Record<string, unknown>) {
|
|
this.clearGitMutationReadCaches()
|
|
const worktreePath = params.worktreePath as string
|
|
try {
|
|
await this.git(['merge', '--abort'], worktreePath)
|
|
} finally {
|
|
this.clearGitMutationReadCaches()
|
|
}
|
|
}
|
|
|
|
async abortRebase(params: Record<string, unknown>) {
|
|
this.clearGitMutationReadCaches()
|
|
const worktreePath = params.worktreePath as string
|
|
try {
|
|
await this.git(['rebase', '--abort'], worktreePath)
|
|
} finally {
|
|
this.clearGitMutationReadCaches()
|
|
}
|
|
}
|
|
|
|
async checkout(params: Record<string, unknown>) {
|
|
this.clearGitMutationReadCaches()
|
|
const worktreePath = params.worktreePath as string
|
|
const branch = params.branch as string
|
|
// Defense-in-depth: reject `-`-prefixed branch tokens to block flag injection (this relay entrypoint is reachable independently of the RPC schema).
|
|
if (typeof branch !== 'string' || branch.length === 0 || branch.startsWith('-')) {
|
|
throw new Error('invalid_branch_name')
|
|
}
|
|
try {
|
|
await this.git(['checkout', branch, '--'], worktreePath)
|
|
return { ok: true as const, branch }
|
|
} finally {
|
|
this.clearGitMutationReadCaches()
|
|
}
|
|
}
|
|
|
|
async localBranches(params: Record<string, unknown>) {
|
|
const worktreePath = params.worktreePath as string
|
|
const { stdout } = await this.git(
|
|
['for-each-ref', '--format=%(HEAD)%09%(refname:short)', 'refs/heads/'],
|
|
worktreePath
|
|
)
|
|
let current: string | null = null
|
|
const branches: string[] = []
|
|
for (const line of stdout.split('\n')) {
|
|
if (line.length === 0) {
|
|
continue
|
|
}
|
|
const [marker, name] = line.split('\t')
|
|
if (!name) {
|
|
continue
|
|
}
|
|
if (marker === '*') {
|
|
current = name
|
|
}
|
|
branches.push(name)
|
|
}
|
|
branches.sort((a, b) => (a === current ? -1 : b === current ? 1 : 0))
|
|
return { current, branches }
|
|
}
|
|
}
|