2.6 KB83 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 {
9 ApplyUncommittedChangesPreviewsFuncType,
10 UncommittedChangesPreviewContext,
11} from '../previews';
12import type {
13 CommandArg,
14 ExactRevset,
15 OptimisticRevset,
16 RepoRelativePath,
17 SucceedableRevset,
18 UncommittedChanges,
19} from '../types';
20
21import {Operation} from './Operation';
22
23export class RevertOperation extends Operation {
24 static opName = 'Revert';
25
26 constructor(
27 private files: Array<RepoRelativePath>,
28 private revset?: SucceedableRevset | ExactRevset | OptimisticRevset,
29 ) {
30 super('RevertOperation');
31 }
32
33 getArgs() {
34 const args: Array<CommandArg> = ['revert'];
35 if (this.revset != null) {
36 args.push('--rev', this.revset);
37 }
38 if (this.files.length > 0) {
39 // Tag file arguments specially so the remote repo can convert them to the proper cwd-relative format.
40 args.push({
41 type: 'repo-relative-file-list' as const,
42 paths: this.files,
43 });
44 }
45 return args;
46 }
47
48 makeOptimisticUncommittedChangesApplier?(
49 context: UncommittedChangesPreviewContext,
50 ): ApplyUncommittedChangesPreviewsFuncType | undefined {
51 if (this.revset == null) {
52 const filesToHide = new Set(this.files);
53 if (context.uncommittedChanges.every(change => !filesToHide.has(change.path))) {
54 return undefined;
55 }
56
57 const func: ApplyUncommittedChangesPreviewsFuncType = (changes: UncommittedChanges) => {
58 return changes.filter(change => !filesToHide.has(change.path));
59 };
60 return func;
61 } else {
62 // If reverting back to a specific commit, the file will probably become 'M', not disappear.
63 // Note: this is just a guess, in reality the file could do any number of things.
64
65 const filesToMarkChanged = new Set(this.files);
66 if (context.uncommittedChanges.find(change => filesToMarkChanged.has(change.path)) != null) {
67 return undefined;
68 }
69 const func: ApplyUncommittedChangesPreviewsFuncType = (changes: UncommittedChanges) => {
70 const existingChanges = new Set(changes.map(change => change.path));
71 const revertedChangesToInsert = this.files.filter(file => !existingChanges.has(file));
72 return [
73 ...changes.map(change =>
74 filesToMarkChanged.has(change.path) ? {...change, status: 'M' as const} : change,
75 ),
76 ...revertedChangesToInsert.map(path => ({path, status: 'M' as const})),
77 ];
78 };
79 return func;
80 }
81 }
82}
83