addons/isl/src/Cleanup.tsxblame
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 {UICodeReviewProvider} from './codeReview/UICodeReviewProvider';
b69ab319import type {CommitInfo, DiffSummary, Hash} from './types';
b69ab3110
b69ab3111import {Button} from 'isl-components/Button';
b69ab3112import {Icon} from 'isl-components/Icon';
b69ab3113import {Tooltip} from 'isl-components/Tooltip';
b69ab3114import {useAtomValue} from 'jotai';
b69ab3115import {nullthrows} from 'shared/utils';
b69ab3116import {OperationDisabledButton} from './OperationDisabledButton';
b69ab3117import {allDiffSummaries, codeReviewProvider} from './codeReview/CodeReviewInfo';
b69ab3118import {t, T} from './i18n';
b69ab3119import {HideOperation} from './operations/HideOperation';
b69ab3120import {useRunOperation} from './operationsState';
b69ab3121import {type Dag, dagWithPreviews} from './previews';
b69ab3122import {latestSuccessorUnlessExplicitlyObsolete} from './successionUtils';
b69ab3123
b69ab3124export function isStackEligibleForCleanup(
b69ab3125 hash: Hash,
b69ab3126 dag: Dag,
b69ab3127 diffMap: Map<string, DiffSummary>,
b69ab3128 provider: UICodeReviewProvider,
b69ab3129): boolean {
b69ab3130 return dag
b69ab3131 .descendants(hash)
b69ab3132 .toSeq()
b69ab3133 .every(h => {
b69ab3134 const info = dag.get(h);
b69ab3135 // don't allow hiding a stack you're checked out on
b69ab3136 if (info == null || info.isDot) {
b69ab3137 return false;
b69ab3138 }
b69ab3139 // allow clean up obsoleted commits regardless of review state
b69ab3140 if (info.successorInfo != null) {
b69ab3141 return true;
b69ab3142 }
b69ab3143 // if not obsoleted, still allow cleanup for "Closed" diffs
b69ab3144 if (info.diffId != null) {
b69ab3145 const diffInfo = diffMap.get(info.diffId);
b69ab3146 if (diffInfo != null && provider.isDiffEligibleForCleanup(diffInfo)) {
b69ab3147 return true;
b69ab3148 }
b69ab3149 }
b69ab3150 // no cleanup otherwise
b69ab3151 return false;
b69ab3152 });
b69ab3153}
b69ab3154
b69ab3155export function CleanupButton({commit, hasChildren}: {commit: CommitInfo; hasChildren: boolean}) {
b69ab3156 const runOperation = useRunOperation();
b69ab3157 return (
b69ab3158 <Tooltip
b69ab3159 title={
b69ab3160 hasChildren
b69ab3161 ? t('You can safely "clean up" by hiding this stack of commits.')
b69ab3162 : t('You can safely "clean up" by hiding this commit.')
b69ab3163 }
b69ab3164 placement="bottom">
b69ab3165 <Button
b69ab3166 icon
b69ab3167 onClick={() => {
b69ab3168 runOperation(new HideOperation(latestSuccessorUnlessExplicitlyObsolete(commit)));
b69ab3169 }}>
b69ab3170 <Icon icon="eye-closed" slot="start" />
b69ab3171 {hasChildren ? <T>Clean up stack</T> : <T>Clean up</T>}
b69ab3172 </Button>
b69ab3173 </Tooltip>
b69ab3174 );
b69ab3175}
b69ab3176
b69ab3177export function CleanupAllButton() {
b69ab3178 const dag = useAtomValue(dagWithPreviews);
b69ab3179 const reviewProvider = useAtomValue(codeReviewProvider);
b69ab3180 const diffMap = useAtomValue(allDiffSummaries)?.value;
b69ab3181 if (diffMap == null || reviewProvider == null) {
b69ab3182 return null;
b69ab3183 }
b69ab3184
b69ab3185 const stackBases = dag.roots(dag.draft()).toArray();
b69ab3186 const cleanableStacks = stackBases.filter(hash =>
b69ab3187 isStackEligibleForCleanup(hash, dag, diffMap, reviewProvider),
b69ab3188 );
b69ab3189
b69ab3190 const disabled = cleanableStacks.length === 0;
b69ab3191 return (
b69ab3192 <Tooltip
b69ab3193 title={
b69ab3194 disabled
b69ab3195 ? t('No landed or closed commits to hide')
b69ab3196 : t('Hide all commits for landed or closed Diffs')
b69ab3197 }>
b69ab3198 <OperationDisabledButton
b69ab3199 contextKey="cleanup-all"
b69ab31100 runOperation={() => {
b69ab31101 return cleanableStacks.map(hash => {
b69ab31102 const info = nullthrows(dag.get(hash));
b69ab31103 return new HideOperation(latestSuccessorUnlessExplicitlyObsolete(info));
b69ab31104 });
b69ab31105 }}
b69ab31106 icon={<Icon icon="eye-closed" slot="start" />}
b69ab31107 disabled={disabled}>
b69ab31108 <T>Clean up all</T>
b69ab31109 </OperationDisabledButton>
b69ab31110 </Tooltip>
b69ab31111 );
b69ab31112}