mirror of
https://github.com/stablyai/orca.git
synced 2026-11-04 11:07:42 +00:00
* [comment audit] Shorten daemon, hook, and emulator comments [skip ci] * [comment audit] Shorten VM, conversation, SQLite, and theme-import comments [skip ci] * [comment audit] Tighten Git execution and source-control comment contracts [skip ci] * [comment audit] Clarify repository probes and maintenance comments [skip ci] * [comment audit] Shorten status, diff-cache, and checkout comments [skip ci] * [comment audit] Clarify worktree lifecycle and WSL routing comments [skip ci] * [comment audit] Shorten forge identity and review-refresh comments [skip ci] * [comment audit] Tighten hosted-review client comment contracts [skip ci] * [comment audit] Clarify GitLab compatibility and review comments [skip ci] * [comment audit] Tighten hook ownership and watchdog rationale [skip ci] * [comment audit] Condense host and integration compatibility comments [skip ci] * [comment audit] Clarify IPC authority and remote-routing rationale [skip ci] * [comment audit] Finalize file-import and containment comment cleanup * [comment audit] Fix stale Jira type imports blocking full CI --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
92 lines
2.4 KiB
TypeScript
92 lines
2.4 KiB
TypeScript
import { execFile } from 'node:child_process'
|
|
import { promisify } from 'node:util'
|
|
import { gitExecFileAsync, ghExecFileAsync } from '../git/runner'
|
|
// Import pure parsing outside runner so runner-mocked tests retain the real implementation.
|
|
import { extractExecError, parseRetryAfterMs } from '../git/exec-error'
|
|
|
|
// Repo-scoped operations need the WSL-aware runner; this legacy wrapper serves generic commands.
|
|
export const execFileAsync = promisify(execFile)
|
|
export { ghExecFileAsync, gitExecFileAsync, extractExecError, parseRetryAfterMs }
|
|
export {
|
|
classifyGhError,
|
|
classifyListIssuesError,
|
|
classifyListPrsError,
|
|
classifyPullRequestUpdateError
|
|
} from './gh-error-classification'
|
|
export {
|
|
_getOwnerRepoCacheSize,
|
|
_resetOwnerRepoCache,
|
|
getOwnerRepoForRemote,
|
|
getRemoteUrlForRepo,
|
|
ghRepoExecOptions,
|
|
githubRepoContext,
|
|
parseGitHubOwnerRepo,
|
|
parseGitHubRemoteIdentity
|
|
} from './github-repository-identity'
|
|
export type {
|
|
GitHubRemoteIdentity,
|
|
GitHubRemoteIdentityProbeOptions,
|
|
GitHubRepoContext,
|
|
LocalGitExecOptions,
|
|
OwnerRepo
|
|
} from './github-repository-identity'
|
|
export {
|
|
getIssueOwnerRepo,
|
|
getOwnerRepo,
|
|
resolveIssueSource,
|
|
resolvePRRepositoryCandidates
|
|
} from './github-owner-repo-selection'
|
|
export type { PRRepositoryCandidates, ResolvedIssueSource } from './github-owner-repo-selection'
|
|
|
|
const MAX_CONCURRENT = 4
|
|
let running = 0
|
|
type QueueEntry = {
|
|
signal?: AbortSignal
|
|
start: () => void
|
|
reject: (error: Error) => void
|
|
}
|
|
const queue: QueueEntry[] = []
|
|
|
|
function githubOperationAbortError(): Error {
|
|
const error = new Error('GitHub operation aborted')
|
|
error.name = 'AbortError'
|
|
return error
|
|
}
|
|
|
|
export function acquire(signal?: AbortSignal): Promise<void> {
|
|
if (signal?.aborted) {
|
|
return Promise.reject(githubOperationAbortError())
|
|
}
|
|
if (running < MAX_CONCURRENT) {
|
|
running += 1
|
|
return Promise.resolve()
|
|
}
|
|
return new Promise((resolve, reject) => {
|
|
const entry: QueueEntry = {
|
|
signal,
|
|
reject,
|
|
start: () => {
|
|
signal?.removeEventListener('abort', onAbort)
|
|
running += 1
|
|
resolve()
|
|
}
|
|
}
|
|
const onAbort = (): void => {
|
|
const index = queue.indexOf(entry)
|
|
if (index === -1) {
|
|
return
|
|
}
|
|
queue.splice(index, 1)
|
|
reject(githubOperationAbortError())
|
|
}
|
|
signal?.addEventListener('abort', onAbort, { once: true })
|
|
queue.push(entry)
|
|
})
|
|
}
|
|
|
|
export function release(): void {
|
|
running -= 1
|
|
const next = queue.shift()
|
|
next?.start()
|
|
}
|