addons/isl/src/repositoryData.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 {CommitInfo, RepoInfo, RepoRelativePath} from './types';
b69ab319
b69ab3110import {atom, useAtomValue} from 'jotai';
b69ab3111import {atomResetOnDepChange, localStorageBackedAtom} from './jotaiUtils';
b69ab3112import platform from './platform';
b69ab3113
b69ab3114export const repositoryData = atom<{info?: RepoInfo; cwd?: string}>({});
b69ab3115
b69ab3116/** "cwd" is not always the repo root. It can be a path inside the repo. */
b69ab3117export const serverCwd = atom<string>(get => {
b69ab3118 const data = get(repositoryData);
b69ab3119 if (data.info?.type === 'cwdNotARepository') {
b69ab3120 return data.info.cwd;
b69ab3121 }
b69ab3122 return data?.cwd ?? platform.initialUrlParams?.get('cwd') ?? '';
b69ab3123});
b69ab3124
b69ab3125export const repoRootAtom = atom(get => {
b69ab3126 const data = get(repositoryData);
b69ab3127 return data.info?.type === 'success' ? data.info.repoRoot : '';
b69ab3128});
b69ab3129
b69ab3130export const repoRelativeCwd = atom<RepoRelativePath>(get => {
b69ab3131 const cwd = get(serverCwd);
b69ab3132 const root = get(repoRootAtom);
b69ab3133 return cwd.startsWith(root) ? cwd.slice(root.length + 1) + '/' : cwd;
b69ab3134});
b69ab3135
b69ab3136/**
b69ab3137 * Returns true if the commit is irrelevant to the current cwd,
b69ab3138 * due to it modifying only files in folders that are not under the cwd.
b69ab3139 * If the max prefix is "inside" the cwd, it is NOT irrelevant.
b69ab3140 * > if the max prefix is `addons/isl` and the cwd is `addons`, it is NOT irrelevant.
b69ab3141 * If the max prefix is "above" the cwd, it is NOT irrelevant.
b69ab3142 * > if the max prefix is `addons` and the cwd is `addons/isl`, it is NOT irrelevant.
b69ab3143 * Only if the max prefix contains portions that do not match the cwd is it irrelevant.
b69ab3144 * > if the max prefix is `addons/isl` and the cwd is `www`, it IS irrelevant.
b69ab3145 * Thus, if the cwd is the repo root, it is never irrelevant.
b69ab3146 *
b69ab3147 * If a commit has only irrelevant files, but then a relevant file is added, the commit
b69ab3148 * is guaranteed to become relevant, since the common portion of the paths will
b69ab3149 * be a prefix of the relevant file.
b69ab3150 */
b69ab3151export const useIsIrrelevantToCwd = (commit: CommitInfo) => {
b69ab3152 const isEnabled = useAtomValue(irrelevantCwdDeemphasisEnabled);
b69ab3153 const cwd = useAtomValue(repoRelativeCwd);
b69ab3154 if (!isEnabled) {
b69ab3155 return false;
b69ab3156 }
b69ab3157 return isIrrelevantToCwd(commit, cwd);
b69ab3158};
b69ab3159
b69ab3160export function isIrrelevantToCwd(commit: CommitInfo, repoRelativeCwd: RepoRelativePath): boolean {
b69ab3161 return (
b69ab3162 repoRelativeCwd !== '/' &&
b69ab3163 !commit.maxCommonPathPrefix.startsWith(repoRelativeCwd) &&
b69ab3164 !repoRelativeCwd.startsWith(commit.maxCommonPathPrefix)
b69ab3165 );
b69ab3166}
b69ab3167export const __TEST__ = {isIrrelevantToCwd};
b69ab3168
b69ab3169export const irrelevantCwdDeemphasisEnabled = localStorageBackedAtom<boolean>(
b69ab3170 'isl.deemphasize-cwd-irrelevant-commits',
b69ab3171 true,
b69ab3172);
b69ab3173
b69ab3174export const hideIrrelevantCwdStacks = localStorageBackedAtom<boolean>(
b69ab3175 'isl.hide-cwd-irrelevant-stacks',
b69ab3176 false,
b69ab3177);
b69ab3178
b69ab3179/**
b69ab3180 * Derived atom that combines the irrelevant CWD display settings into a single value.
b69ab3181 * - 'show': Show irrelevant commits normally (deemphasis disabled)
b69ab3182 * - 'deemphasize': Show irrelevant commits but with reduced visual prominence
b69ab3183 * - 'hide': Don't show irrelevant commits at all
b69ab3184 */
b69ab3185export const irrelevantCwdDisplayModeAtom = atom(
b69ab3186 get => {
b69ab3187 const deemphasizeEnabled = get(irrelevantCwdDeemphasisEnabled);
b69ab3188 const hideEnabled = get(hideIrrelevantCwdStacks);
b69ab3189
b69ab3190 if (hideEnabled) {
b69ab3191 return 'hide';
b69ab3192 }
b69ab3193 if (deemphasizeEnabled) {
b69ab3194 return 'deemphasize';
b69ab3195 }
b69ab3196 return 'show';
b69ab3197 },
b69ab3198 (_get, set, newValue: 'show' | 'deemphasize' | 'hide') => {
b69ab3199 switch (newValue) {
b69ab31100 case 'show':
b69ab31101 set(irrelevantCwdDeemphasisEnabled, false);
b69ab31102 set(hideIrrelevantCwdStacks, false);
b69ab31103 break;
b69ab31104 case 'deemphasize':
b69ab31105 set(irrelevantCwdDeemphasisEnabled, true);
b69ab31106 set(hideIrrelevantCwdStacks, false);
b69ab31107 break;
b69ab31108 case 'hide':
b69ab31109 set(irrelevantCwdDeemphasisEnabled, true);
b69ab31110 set(hideIrrelevantCwdStacks, true);
b69ab31111 break;
b69ab31112 }
b69ab31113 },
b69ab31114);
b69ab31115
b69ab31116/**
b69ab31117 * A string of repo root and the "cwd". Note a same "cwd" does not infer the same repo,
b69ab31118 * when there are nested (ex. submodule) repos.
b69ab31119 */
b69ab31120export const repoRootAndCwd = atom<string>(get => `${get(serverCwd)}\n${get(repoRootAtom)}`);
b69ab31121
b69ab31122/** A specific version of `atomResetOnDepChange`. */
b69ab31123export function atomResetOnCwdChange<T>(defaultValue: T) {
b69ab31124 return atomResetOnDepChange(defaultValue, repoRootAndCwd);
b69ab31125}