mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 08:37:49 +00:00
The GitLab, GitHub, Jira and Linear integration modules, their two IPC registrars, and the shared GitHub project types each carried a file-level `eslint-disable max-lines` and ran 351-614 counted lines against a 300-line budget. AGENTS.md calls for splitting rather than suppressing, and config/max-lines-baseline.txt is a shrink-only ratchet, so this removes all eight suppressions and prunes their entries (341 -> 333). Pure move, no behavior change. Each client is cut along the seam it already had: per-operation modules for the issue APIs (create / update / comment / field options), and for Jira the request queue, site credential store, authenticated request, and site identity. The two IPC registrars keep their own handlers and delegate the rest to per-domain sub-registrars, so they remain real entry points rather than re-export shims. The IPC surface is proved intact rather than assumed: comparing (method, channel) multisets between HEAD and the split gives 52 registrations across 52 distinct channels on both sides. Provider-neutrality is preserved -- GitLab and GitHub keep separate, parallel module layouts rather than being merged behind a shared abstraction. Verified: oxlint clean, ratchet passes, typecheck clean, full unit suite green (the one remaining failure is a pre-existing load flake in an untouched file, green when re-run serially), no new runtime import cycles among 744 modules, and no lint suppression added anywhere.
95 lines
2.9 KiB
TypeScript
95 lines
2.9 KiB
TypeScript
import type { GitLabMRFile } from '../../shared/gitlab-types'
|
|
import { encodedProject } from './project-path-encoding'
|
|
import {
|
|
glabHostnameArgs,
|
|
glabRepoExecOptions,
|
|
glabExecFileAsync,
|
|
type LocalGitExecOptions,
|
|
type ProjectRef
|
|
} from './gl-utils'
|
|
|
|
/**
|
|
* Counts the added/removed lines in a single GitLab MR file's unified diff,
|
|
* feeding the +N/-N shown in the MR file list. `---`/`+++` are file headers
|
|
* only before the first `@@` hunk; every `+`/`-` line inside a hunk is content.
|
|
* Requires hunk headers: a diff with no `@@` counts zero, so do not reuse this
|
|
* for header-less agent-tool diffs (see `diffFromText` in shared/native-chat-diff).
|
|
*
|
|
* @internal - exposed for tests only.
|
|
*/
|
|
export function countDiffLines(diff: string): { additions: number; deletions: number } {
|
|
let additions = 0
|
|
let deletions = 0
|
|
// Why: `---`/`+++` are file headers only before the first hunk. A removed line
|
|
// whose original text began with `--` (SQL/Lua/Haskell `-- comment`) becomes a
|
|
// diff line `---<content>`, colliding with the `--- a/file` header — so it must
|
|
// be counted once inside a hunk, not skipped.
|
|
let inHunk = false
|
|
for (const line of diff.split('\n')) {
|
|
if (line.startsWith('@@')) {
|
|
inHunk = true
|
|
continue
|
|
}
|
|
if (!inHunk) {
|
|
continue
|
|
}
|
|
if (line.startsWith('+')) {
|
|
additions += 1
|
|
} else if (line.startsWith('-')) {
|
|
deletions += 1
|
|
}
|
|
}
|
|
return { additions, deletions }
|
|
}
|
|
|
|
function mapMRFile(raw: {
|
|
new_path?: string
|
|
old_path?: string
|
|
diff?: string
|
|
new_file?: boolean
|
|
deleted_file?: boolean
|
|
renamed_file?: boolean
|
|
binary?: boolean
|
|
too_large?: boolean
|
|
}): GitLabMRFile {
|
|
const diff = raw.diff ?? ''
|
|
const counts = countDiffLines(diff)
|
|
const status = raw.new_file
|
|
? 'added'
|
|
: raw.deleted_file
|
|
? 'removed'
|
|
: raw.renamed_file
|
|
? 'renamed'
|
|
: 'modified'
|
|
return {
|
|
path: raw.new_path ?? raw.old_path ?? '',
|
|
...(raw.old_path && raw.old_path !== raw.new_path ? { oldPath: raw.old_path } : {}),
|
|
status,
|
|
additions: counts.additions,
|
|
deletions: counts.deletions,
|
|
isBinary: Boolean(raw.binary || raw.too_large || !diff),
|
|
...(diff ? { diff } : {})
|
|
}
|
|
}
|
|
|
|
export async function fetchMRFiles(
|
|
repoPath: string,
|
|
projectRef: ProjectRef,
|
|
iid: number,
|
|
connectionId?: string | null,
|
|
localGitOptions: LocalGitExecOptions = {}
|
|
): Promise<GitLabMRFile[]> {
|
|
const { stdout } = await glabExecFileAsync(
|
|
[
|
|
'api',
|
|
...glabHostnameArgs(projectRef, connectionId),
|
|
// Why: GitLab deprecated the all-in-one `changes` endpoint in favor of
|
|
// the paginated diffs endpoint; cap the file snapshot at one visible page.
|
|
`projects/${encodedProject(projectRef.path)}/merge_requests/${iid}/diffs?per_page=100`
|
|
],
|
|
glabRepoExecOptions(repoPath, connectionId, localGitOptions)
|
|
)
|
|
const data = JSON.parse(stdout) as Parameters<typeof mapMRFile>[0][]
|
|
return data.map(mapMRFile).filter((file) => file.path)
|
|
}
|