Files
orca/src/shared/worktree-lineage-placement.ts
T
Brennan Benson ef98eff38b Allow worktree parents across projects on the same machine (#28942)
* Allow worktree parentage across projects on one host

* Keep sidebar placement and project ownership consistent

* Keep project labels on phone rows outside their own section

* Derive sidebar placement and reveal from shared occurrences

* Preserve project text across workspace card styles

* Resolve saved lineage peers without rebuilding host projects

* fix: preserve independent project deletion progress

* fix: satisfy mobile formatting and test lint checks

* test: declare project fixture arrays without assertions

* Align reveal fixtures with rendered workspace occurrences

* fix: reuse project name for cross-repo child cards

* fix: satisfy mobile section lint after main merge

* fix: retain project label for nested mobile rows

* test: keep nested card owner assertion resilient

* test: assert project badge visibility across card styles

* test: drop lineage tests already covered by the whole-flow suites

The host-peer projection is exercised by the runtime and SSH listing
integration tests, and the simple phone nesting case is covered by the
deep-chain, Pinned and hidden-project flow test.
2026-10-15 16:47:44 -07:00

64 lines
1.9 KiB
TypeScript

export function getVisibleLineagePlacement<Row>(
visibleRows: readonly Row[],
roots: readonly Row[],
childrenByParentIdentity: ReadonlyMap<string, readonly Row[]>,
identityOf: (row: Row) => string,
bridgeHidden = false
): Map<string, Row> {
const visible = new Set(visibleRows.map(identityOf))
const placement = new Map<string, Row>()
const seen = new Set<string>()
for (const root of roots) {
const pending = [root]
while (pending.length > 0) {
const current = pending.pop()
if (current === undefined) {
continue
}
const identity = identityOf(current)
if (seen.has(identity)) {
continue
}
seen.add(identity)
const isVisible = visible.has(identity)
if (isVisible) {
placement.set(identity, root)
}
if (isVisible || bridgeHidden) {
for (const child of childrenByParentIdentity.get(identity) ?? []) {
pending.push(child)
}
}
}
}
return placement
}
/** A hidden parent breaks placement; a visible child starts its own section. */
export function getTopVisibleLineageRoots<Row>(
visibleRows: readonly Row[],
childrenByParentIdentity: ReadonlyMap<string, readonly Row[]>,
identityOf: (row: Row) => string
): Map<string, Row> {
const childrenOfVisibleParents = new Set<string>()
for (const row of visibleRows) {
for (const child of childrenByParentIdentity.get(identityOf(row)) ?? []) {
childrenOfVisibleParents.add(identityOf(child))
}
}
const roots = visibleRows.filter((row) => !childrenOfVisibleParents.has(identityOf(row)))
const placement = getVisibleLineagePlacement(
visibleRows,
roots,
childrenByParentIdentity,
identityOf
)
for (const row of visibleRows) {
const identity = identityOf(row)
if (!placement.has(identity)) {
placement.set(identity, row)
}
}
return placement
}