1.8 KB57 lines
Blame
1/**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8import type {Dag} from './dag/dag';
9import type {ExactRevset, OptimisticRevset} from './types';
10
11import {
12 exactRevset,
13 optimisticRevset,
14 succeedableRevset,
15 type CommitInfo,
16 type SucceedableRevset,
17} from './types';
18
19/**
20 * Get the latest successor hash of the given hash,
21 * traversing multiple successions if necessary.
22 * Returns original hash if no successors were found.
23 *
24 * Useful for previews to ensure they're working with the latest version of a commit,
25 * given that they may have been queued up while another operation ran and eventually caused succession.
26 *
27 * Note: if an ExactRevset is passed, don't look up the successor.
28 */
29export function latestSuccessor(
30 ctx: Dag,
31 oldRevset: SucceedableRevset | ExactRevset | OptimisticRevset,
32): string {
33 let hash = oldRevset.type === 'optimistic-revset' ? oldRevset.fake : oldRevset.revset;
34 if (oldRevset.type === 'exact-revset') {
35 return hash;
36 }
37 hash = ctx.followSuccessors(hash).toHashes().first() ?? hash;
38 return hash;
39}
40
41/**
42 * Typically we want to use succeedable revsets everywhere, to maximize support for queued commands.
43 * But if you see and act on a visibly obsolete commit in the UI, we should use its exact hash,
44 * so that you don't suddenly act on a seemingly unrelated commit.
45 */
46export function latestSuccessorUnlessExplicitlyObsolete(
47 commit: Readonly<CommitInfo>,
48): SucceedableRevset | ExactRevset | OptimisticRevset {
49 if (commit.optimisticRevset != null) {
50 return optimisticRevset(commit.optimisticRevset, commit.hash);
51 }
52 if (commit.successorInfo?.type != null) {
53 return exactRevset(commit.hash);
54 }
55 return succeedableRevset(commit.hash);
56}
57