| b69ab31 | | | 1 | /** |
| b69ab31 | | | 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. |
| b69ab31 | | | 3 | * |
| b69ab31 | | | 4 | * This source code is licensed under the MIT license found in the |
| b69ab31 | | | 5 | * LICENSE file in the root directory of this source tree. |
| b69ab31 | | | 6 | */ |
| b69ab31 | | | 7 | |
| b69ab31 | | | 8 | import type {CommitStackState} from './commitStackState'; |
| b69ab31 | | | 9 | |
| b69ab31 | | | 10 | import {cached} from 'shared/LRU'; |
| b69ab31 | | | 11 | import {firstLine, nullthrows} from 'shared/utils'; |
| b69ab31 | | | 12 | import {Dag, DagCommitInfo} from '../dag/dag'; |
| b69ab31 | | | 13 | import {WDIR_NODE, YOU_ARE_HERE_VIRTUAL_COMMIT} from '../dag/virtualCommit'; |
| b69ab31 | | | 14 | |
| b69ab31 | | | 15 | /** |
| b69ab31 | | | 16 | * Calculate a virtual "Dag" purely from "stack". |
| b69ab31 | | | 17 | * The virtual "Dag" does not have to be a subset of the main dag being displayed. |
| b69ab31 | | | 18 | * This avoids race conditions and various issues when the "stack" does not |
| b69ab31 | | | 19 | * match the main dag. |
| b69ab31 | | | 20 | * The nodes (commit hashes) of the returned dag is the "key" of commits in |
| b69ab31 | | | 21 | * the "stack", not real commit hashes. This is to support various stack edit |
| b69ab31 | | | 22 | * operations like splitting, inserting new commits, etc. |
| b69ab31 | | | 23 | */ |
| b69ab31 | | | 24 | function calculateDagFromStackImpl(stack: CommitStackState): Dag { |
| b69ab31 | | | 25 | let dag = new Dag(); |
| b69ab31 | | | 26 | |
| b69ab31 | | | 27 | // Figure out the "dot" from the initial exported stack. |
| b69ab31 | | | 28 | // "dot" is the parent of "wdir()". |
| b69ab31 | | | 29 | // The exported stack might not have "wdir()" if not requested. |
| b69ab31 | | | 30 | // Run `sl debugexportstack -r '.+wdir()' | python3 -m json.tool` to get a sense of the output. |
| b69ab31 | | | 31 | let dotNode: string | undefined = undefined; |
| b69ab31 | | | 32 | let dotKey: string | undefined = undefined; |
| b69ab31 | | | 33 | for (const exportedCommit of stack.originalStack) { |
| b69ab31 | | | 34 | if (exportedCommit.node === WDIR_NODE) { |
| b69ab31 | | | 35 | dotNode = exportedCommit.parents?.at(0); |
| b69ab31 | | | 36 | break; |
| b69ab31 | | | 37 | } |
| b69ab31 | | | 38 | } |
| b69ab31 | | | 39 | |
| b69ab31 | | | 40 | if (dotNode != null) { |
| b69ab31 | | | 41 | const maybeDotCommit = stack.stack.findLast(commit => commit.originalNodes.contains(dotNode)); |
| b69ab31 | | | 42 | if (maybeDotCommit != null) { |
| b69ab31 | | | 43 | dotKey = maybeDotCommit.key; |
| b69ab31 | | | 44 | const wdirRev = stack.findLastRev(commit => commit.originalNodes.contains(WDIR_NODE)); |
| b69ab31 | | | 45 | dag = dag.add([YOU_ARE_HERE_VIRTUAL_COMMIT.merge({parents: [dotKey], stackRev: wdirRev})]); |
| b69ab31 | | | 46 | } |
| b69ab31 | | | 47 | } |
| b69ab31 | | | 48 | |
| b69ab31 | | | 49 | // Insert commits from the stack. |
| b69ab31 | | | 50 | // Since we've already inserted the "wdir()" commit, skip it from the stack. |
| b69ab31 | | | 51 | dag = dag.add( |
| b69ab31 | | | 52 | stack |
| b69ab31 | | | 53 | .revs() |
| b69ab31 | | | 54 | .filter(rev => !stack.get(rev)?.originalNodes?.contains(WDIR_NODE)) |
| b69ab31 | | | 55 | .map(rev => { |
| b69ab31 | | | 56 | const commit = nullthrows(stack.get(rev)); |
| b69ab31 | | | 57 | return DagCommitInfo.fromCommitInfo({ |
| b69ab31 | | | 58 | title: firstLine(commit.text), |
| b69ab31 | | | 59 | hash: commit.key, |
| b69ab31 | | | 60 | parents: commit.parents |
| b69ab31 | | | 61 | .flatMap(parentRev => { |
| b69ab31 | | | 62 | const parent = stack.get(parentRev); |
| b69ab31 | | | 63 | return parent == null ? [] : [parent.key]; |
| b69ab31 | | | 64 | }) |
| b69ab31 | | | 65 | .toArray(), |
| b69ab31 | | | 66 | phase: commit.immutableKind === 'hash' ? 'public' : 'draft', |
| b69ab31 | | | 67 | author: commit.author, |
| b69ab31 | | | 68 | date: new Date(commit.date.unix), |
| b69ab31 | | | 69 | isDot: commit.key === dotKey, |
| b69ab31 | | | 70 | stackRev: rev, |
| b69ab31 | | | 71 | // Other fields are omitted for now, since nobody uses them yet. |
| b69ab31 | | | 72 | }); |
| b69ab31 | | | 73 | }), |
| b69ab31 | | | 74 | ); |
| b69ab31 | | | 75 | |
| b69ab31 | | | 76 | return dag; |
| b69ab31 | | | 77 | } |
| b69ab31 | | | 78 | |
| b69ab31 | | | 79 | /** |
| b69ab31 | | | 80 | * Provides a `Dag` that just contains the `stack`. |
| b69ab31 | | | 81 | * If `dotRev` is set, add a "YouAreHere" virtual commit as a child of the rev. |
| b69ab31 | | | 82 | */ |
| b69ab31 | | | 83 | export const calculateDagFromStack = cached(calculateDagFromStackImpl); |