takt/src/infra/task/branchGitResolver.ts

103 lines
2.5 KiB
TypeScript

import { existsSync } from 'node:fs';
import { runGit } from './branchGitCommands.js';
import {
type BranchBaseResolutionCache,
createBranchBaseResolutionCache,
} from './branchBaseRefCache.js';
import {
resolveBranchBaseCommitFromRefs,
resolveMergeBase,
} from './branchBaseCandidateResolver.js';
import {
readCommitSubject,
resolveBranchEntryPointFromReflog,
} from './branchEntryPointResolver.js';
type FirstTaktCommit = {
subject: string;
};
type FindFirstTaktCommitOptions = {
baseCommit?: string;
cache?: BranchBaseResolutionCache;
};
function parseFirstCommitLine(output: string): FirstTaktCommit | null {
if (!output) {
return null;
}
const firstLine = output.split('\n')[0];
if (!firstLine) {
return null;
}
const tabIndex = firstLine.indexOf('\t');
if (tabIndex === -1) {
return null;
}
return {
subject: firstLine.slice(tabIndex + 1),
};
}
export function resolveGitCwd(cwd: string, worktreePath?: string): string {
return worktreePath && existsSync(worktreePath) ? worktreePath : cwd;
}
export { createBranchBaseResolutionCache, resolveMergeBase };
export type { BranchBaseResolutionCache };
export function findFirstTaktCommit(
gitCwd: string,
defaultBranch: string,
branch: string,
options?: FindFirstTaktCommitOptions,
): FirstTaktCommit | null {
let baseCommit: string;
if (options?.baseCommit) {
baseCommit = options.baseCommit;
} else {
const entryPoint = resolveBranchEntryPointFromReflog(gitCwd, branch);
if (entryPoint) {
const subject = readCommitSubject(gitCwd, entryPoint.firstCommit);
return {
subject,
};
}
const resolvedFromRefs = resolveBranchBaseCommitFromRefs(gitCwd, defaultBranch, branch, options?.cache);
baseCommit = resolvedFromRefs ? resolvedFromRefs : resolveMergeBase(gitCwd, defaultBranch, branch);
}
const output = runGit(gitCwd, [
'log',
'--format=%H\t%s',
'--reverse',
'--first-parent',
'--grep=^takt:',
`${baseCommit}..${branch}`,
]);
return parseFirstCommitLine(output);
}
export function resolveBranchBaseCommit(
gitCwd: string,
defaultBranch: string,
branch: string,
cache?: BranchBaseResolutionCache,
): string {
const entryPoint = resolveBranchEntryPointFromReflog(gitCwd, branch);
if (entryPoint) {
return entryPoint.baseCommit;
}
const baseCommitFromRefs = resolveBranchBaseCommitFromRefs(gitCwd, defaultBranch, branch, cache);
if (baseCommitFromRefs) {
return baseCommitFromRefs;
}
return resolveMergeBase(gitCwd, defaultBranch, branch);
}