Files
orca/src/main/git/source-control/compare-ref-oids.ts
T
Jinjing 933345d347 Clarify upstream divergence stats for rebased branches (#16358)
* Clarify upstream divergence stats for rebased branches

When a branch is rebased, it still tracks the pre-rebase upstream
while comparing against the new base. Move upstream arrows to the
head line to prevent them being confused with compare-base counts.

* Show upstream divergence stats independent of compare base

Measure HEAD against upstream regardless of compare-base state,
so divergence indicators stay visible even when comparison is
missing, loading, or failed. Also use cross-platform temp paths
in tests.

* Show commit counts against compare base, not upstream

Upstream divergence (↑/↓ against tracking branch) was confusing for
rebased branches — the counts appeared beside the base ref but measured
against the upstream branch. Show only the compare base count instead,
on the line that names it.

* Report branch divergence in both directions

Rebased branches are typically ahead AND behind their base; a single count
hides this case. Use symmetric range with --left-right --count to capture
both directions efficiently, then expose commitsBehind in the UI alongside
commitsAhead.

* Use semantic names for i18n keys and template variables

Rename hash-based translation keys to descriptive identifiers and replace generic value0/value1 placeholders with semantic variable names like `count` and `ref`. Improves code maintainability and makes translation strings self-documenting.
2026-08-25 22:19:04 -07:00

61 lines
1.8 KiB
TypeScript

import type { GitRuntimeOptions } from '../git-runtime-options'
import { gitOptionsForWorktree } from '../git-runtime-options'
import { gitExecFileAsync } from '../runner'
export async function resolveCompareRef(
worktreePath: string,
options: GitRuntimeOptions = {}
): Promise<string> {
try {
const { stdout } = await gitExecFileAsync(['branch', '--show-current'], {
...gitOptionsForWorktree(worktreePath, options)
})
const branch = stdout.trim()
return branch || 'HEAD'
} catch {
return 'HEAD'
}
}
export async function resolveRefOid(
worktreePath: string,
ref: string,
options: GitRuntimeOptions = {}
): Promise<string> {
const { stdout } = await gitExecFileAsync(['rev-parse', '--verify', '--end-of-options', ref], {
...gitOptionsForWorktree(worktreePath, options)
})
return stdout.trim()
}
export async function resolveMergeBase(
worktreePath: string,
baseOid: string,
headOid: string,
options: GitRuntimeOptions = {}
): Promise<string> {
const { stdout } = await gitExecFileAsync(['merge-base', baseOid, headOid], {
...gitOptionsForWorktree(worktreePath, options)
})
return stdout.trim()
}
// Why: `--left-right --count` on the symmetric range answers both directions in one
// rev-list walk; a rebased branch is usually ahead AND behind its base.
export async function countCompareDivergence(
worktreePath: string,
baseOid: string,
headOid: string,
options: GitRuntimeOptions = {}
): Promise<{ ahead: number; behind: number }> {
const { stdout } = await gitExecFileAsync(
['rev-list', '--left-right', '--count', `${baseOid}...${headOid}`],
{ ...gitOptionsForWorktree(worktreePath, options) }
)
const [behind = '', ahead = ''] = stdout.trim().split(/\s+/)
return {
ahead: Number.parseInt(ahead, 10) || 0,
behind: Number.parseInt(behind, 10) || 0
}
}