mergeable
uses tcmts.cli.merge.silently, which uses process
Whether a contribution merges into its target, settled as the merge settles it: a name both sides edited where the edits are apart is merged as text, not a conflict.
import type { Codebase } from "#codebase/tcmts/cli/codebase"; import type { Mergeable } from "#codebase/tcmts/cli/contributions"; import { keyPath } from "#codebase/tcmts/cli/diff"; import { isBytes } from "#codebase/tcmts/cli/files"; import { mergeShown, planMerge, silently } from "#codebase/tcmts/cli/merge"; import type { Contribution } from "#codebase/tcmts/store"; export function mergeable(cb: Codebase, c: Contribution): Mergeable { const plan = planMerge(cb, c.target, c.source); if (plan.kind !== "merge") return { kind: plan.kind }; const one = (s: Set<string> | undefined) => s?.size === 1 ? cb.store.getDef([...s][0]!) : undefined; const asText: string[] = []; const names: string[] = []; for (const key of plan.result.conflicts) { const [b, o, t] = [plan.base, plan.before, plan.theirs].map((s) => one(s.get(key))); const apart = !!b && !!o && !!t && o.kind === b.kind && t.kind === b.kind && !(b.kind === "file" && [b, o, t].some((r) => isBytes(r))) && silently(() => { try { return !mergeShown(cb, keyPath(key), b, o, t).conflicts; } catch { return false; } }); (apart ? asText : names).push(key); } return names.length ? { kind: "conflicts", names } : { kind: "clean", ...(asText.length ? { asText } : {}) }; }
uses
- tcmts.cli.codebase.Codebase
- tcmts.cli.contributions.Mergeable
- tcmts.cli.diff.keyPath
- tcmts.cli.files.isBytes
- tcmts.cli.merge.mergeShown
- tcmts.cli.merge.planMerge
- tcmts.cli.merge.silently
- tcmts.store.Contribution