addons/isl/src/operations/RevertOperation.tsblame
View source
b69ab311/**
b69ab312 * Copyright (c) Meta Platforms, Inc. and affiliates.
b69ab313 *
b69ab314 * This source code is licensed under the MIT license found in the
b69ab315 * LICENSE file in the root directory of this source tree.
b69ab316 */
b69ab317
b69ab318import type {
b69ab319 ApplyUncommittedChangesPreviewsFuncType,
b69ab3110 UncommittedChangesPreviewContext,
b69ab3111} from '../previews';
b69ab3112import type {
b69ab3113 CommandArg,
b69ab3114 ExactRevset,
b69ab3115 OptimisticRevset,
b69ab3116 RepoRelativePath,
b69ab3117 SucceedableRevset,
b69ab3118 UncommittedChanges,
b69ab3119} from '../types';
b69ab3120
b69ab3121import {Operation} from './Operation';
b69ab3122
b69ab3123export class RevertOperation extends Operation {
b69ab3124 static opName = 'Revert';
b69ab3125
b69ab3126 constructor(
b69ab3127 private files: Array<RepoRelativePath>,
b69ab3128 private revset?: SucceedableRevset | ExactRevset | OptimisticRevset,
b69ab3129 ) {
b69ab3130 super('RevertOperation');
b69ab3131 }
b69ab3132
b69ab3133 getArgs() {
b69ab3134 const args: Array<CommandArg> = ['revert'];
b69ab3135 if (this.revset != null) {
b69ab3136 args.push('--rev', this.revset);
b69ab3137 }
b69ab3138 if (this.files.length > 0) {
b69ab3139 // Tag file arguments specially so the remote repo can convert them to the proper cwd-relative format.
b69ab3140 args.push({
b69ab3141 type: 'repo-relative-file-list' as const,
b69ab3142 paths: this.files,
b69ab3143 });
b69ab3144 }
b69ab3145 return args;
b69ab3146 }
b69ab3147
b69ab3148 makeOptimisticUncommittedChangesApplier?(
b69ab3149 context: UncommittedChangesPreviewContext,
b69ab3150 ): ApplyUncommittedChangesPreviewsFuncType | undefined {
b69ab3151 if (this.revset == null) {
b69ab3152 const filesToHide = new Set(this.files);
b69ab3153 if (context.uncommittedChanges.every(change => !filesToHide.has(change.path))) {
b69ab3154 return undefined;
b69ab3155 }
b69ab3156
b69ab3157 const func: ApplyUncommittedChangesPreviewsFuncType = (changes: UncommittedChanges) => {
b69ab3158 return changes.filter(change => !filesToHide.has(change.path));
b69ab3159 };
b69ab3160 return func;
b69ab3161 } else {
b69ab3162 // If reverting back to a specific commit, the file will probably become 'M', not disappear.
b69ab3163 // Note: this is just a guess, in reality the file could do any number of things.
b69ab3164
b69ab3165 const filesToMarkChanged = new Set(this.files);
b69ab3166 if (context.uncommittedChanges.find(change => filesToMarkChanged.has(change.path)) != null) {
b69ab3167 return undefined;
b69ab3168 }
b69ab3169 const func: ApplyUncommittedChangesPreviewsFuncType = (changes: UncommittedChanges) => {
b69ab3170 const existingChanges = new Set(changes.map(change => change.path));
b69ab3171 const revertedChangesToInsert = this.files.filter(file => !existingChanges.has(file));
b69ab3172 return [
b69ab3173 ...changes.map(change =>
b69ab3174 filesToMarkChanged.has(change.path) ? {...change, status: 'M' as const} : change,
b69ab3175 ),
b69ab3176 ...revertedChangesToInsert.map(path => ({path, status: 'M' as const})),
b69ab3177 ];
b69ab3178 };
b69ab3179 return func;
b69ab3180 }
b69ab3181 }
b69ab3182}