spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

claude-code / mods / diff / hooks / git / probes / branch-base-of / branch-base-of.ts
75 lines · 2.1 KBRaw
1import Argv from '../../argv'
2import type Types from '../../types'
3import { currentBranchOf } from '../current-branch-of'
4import { defaultBranchOf } from '../default-branch-of'
5import { mergeBaseCandidatesOf } from '../merge-base-candidates-of'
6import { missingBaseOf } from '../missing-base-of'
7
8/**
9 * What branch mode compares against, resolved as the built-in panel does:
10 * the merge-base of HEAD and the default branch, HEAD itself, or none.
11 *
12 * `origin/<default>` wins unless the local ref's base descends from it; a
13 * detached HEAD, a `-`-led default name or no common ancestor is `none`;
14 * a failure that may pass (a ref still there, a failed rev-parse) `error`.
15 *
16 * @param run runs git
17 * @returns the base
18 */
19export async function branchBaseOf(
20 run: Types.GitRun,
21): Promise<Types.BranchBase> {
22 const [branch, defaultBranch] = await Promise.all([
23 currentBranchOf(run),
24 defaultBranchOf(run),
25 ])
26
27 const isUnrelated = branch === 'HEAD' || defaultBranch.startsWith('-')
28
29 if (isUnrelated) {
30 return { kind: 'none' }
31 }
32
33 if (branch === defaultBranch) {
34 return { kind: 'head-is-base', baseBranch: defaultBranch }
35 }
36
37 const { candidates, hasNoCommonAncestor } = await mergeBaseCandidatesOf(
38 run,
39 defaultBranch,
40 )
41
42 const [first, second] = candidates
43
44 if (first === undefined) {
45 return hasNoCommonAncestor
46 ? { kind: 'none' }
47 : missingBaseOf(run, defaultBranch)
48 }
49
50 const isLocalBaseNewer =
51 second !== undefined &&
52 second !== first &&
53 (
54 await run([
55 Argv.NO_OPTIONAL_LOCKS,
56 'merge-base',
57 '--is-ancestor',
58 first,
59 second,
60 ])
61 ).exitCode === 0
62
63 const mergeBase = isLocalBaseNewer ? second : first
64 const head = await run([Argv.NO_OPTIONAL_LOCKS, 'rev-parse', 'HEAD'])
65
66 if (head.exitCode !== 0) {
67 return { kind: 'error', reason: 'head_rev_parse_failed' }
68 }
69
70 const isHeadTheBase = head.stdout.trim() === mergeBase
71
72 return isHeadTheBase
73 ? { kind: 'head-is-base', baseBranch: defaultBranch }
74 : { kind: 'merge-base', mergeBase, baseBranch: defaultBranch }
75}