Files
react-native/packages/core-cli-utils/src/private/clean.js
T
Tim Yung 84de8a075e RN: Delete @oncall Annotations (#51416)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51416

Deletes `oncall` annotations from the `facebook/react-native` repository.

Changelog:
[Internal]

Reviewed By: javache

Differential Revision: D74902524

fbshipit-source-id: 32a6a5b2ff27281792d572f151e2b094d9a79029
2025-05-17 16:18:05 -07:00

203 lines
5.2 KiB
JavaScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import type {Task} from './types';
import type {ExecaPromise, Options as ExecaOptions} from 'execa';
import {assertDependencies, isMacOS, isOnPath, isWindows, task} from './utils';
import execa from 'execa';
import {existsSync, readdirSync, rm} from 'fs';
import os from 'os';
import path from 'path';
const FIRST = 1,
SECOND = 2;
const rmrf = (pathname: string) => {
if (!existsSync(pathname)) {
return;
}
rm(pathname, {force: true, maxRetries: 3, recursive: true});
};
/**
* Removes the contents of a directory matching a given pattern, but keeps the directory.
* @private
*/
export function deleteDirectoryContents(
directory: string,
filePattern: RegExp,
): () => Promise<void> {
return async function deleteDirectoryContentsAction() {
const base = path.dirname(directory);
const files = readdirSync(base).filter((filename: string) =>
filePattern.test(filename),
);
for (const filename of files) {
rmrf(path.join(base, filename));
}
};
}
/**
* Removes a directory recursively.
* @private
*/
export function deleteDirectory(directory: string): () => Promise<void> {
return async function cleanDirectoryAction() {
rmrf(directory);
};
}
/**
* Deletes the contents of the tmp directory matching a given pattern.
* @private
*/
export function deleteTmpDirectoryContents(
filepattern: RegExp,
): () => Promise<void> {
return deleteDirectoryContents(os.tmpdir(), filepattern);
}
const platformGradlew = isWindows ? 'gradlew.bat' : 'gradlew';
type CocoaPodsClean = {
clean: Task<ExecaPromise>,
};
type AndroidClean = {
validate: Task<void>,
run: Task<ExecaPromise>,
};
type MetroClean = {
metro: Task<Promise<void>>,
haste: Task<Promise<void>>,
react_native: Task<Promise<void>>,
};
type NpmClean = {
node_modules: Task<Promise<void>>,
verify_cache: Task<ExecaPromise>,
};
type WatchmanClean = {
stop: Task<ExecaPromise>,
cache: Task<ExecaPromise>,
};
type YarnClean = {
clean: Task<ExecaPromise>,
};
type CleanTasks = {
android: (andoirdSrcDir: ?string, opts?: ExecaOptions) => AndroidClean,
cocoapods: CocoaPodsClean,
metro: () => MetroClean,
npm: (projectRootDir: string) => NpmClean,
watchman: (projectRootDir: string) => WatchmanClean,
yarn: (projectRootDir: string) => YarnClean,
cocoapods?: (projectRootDir: string) => CocoaPodsClean,
};
// The tasks that cleanup various build artefacts.
/* eslint sort-keys: "off" */
export const tasks: CleanTasks = {
/**
* Cleans up the Android Gradle cache
*/
android: (androidSrcDir: ?string, opts?: ExecaOptions) => ({
validate: task(FIRST, 'Check gradlew is available', () => {
assertDependencies(isOnPath(platformGradlew, 'Gradle wrapper'));
}),
run: task(SECOND, '🧹 Clean Gradle cache', () => {
const gradlew = path.join(androidSrcDir ?? 'android', platformGradlew);
const script = path.basename(gradlew);
const cwd = path.dirname(gradlew);
return execa(isWindows ? script : './' + script, ['clean'], {
cwd,
...opts,
});
}),
}),
/**
* Aggressively cleans up all Metro caches.
*/
metro: () => ({
metro: task(
FIRST,
'🧹 Clean Metro cache',
deleteTmpDirectoryContents(/^metro-.+/),
),
haste: task(
FIRST,
'🧹 Clean Haste cache',
deleteTmpDirectoryContents(/^haste-map-.+/),
),
react_native: task(
FIRST,
'🧹 Clean React Native cache',
deleteTmpDirectoryContents(/^react-.+/),
),
}),
/**
* Cleans up the `node_modules` folder and optionally garbage collects the npm cache.
*/
npm: (projectRootDir: string) => ({
node_modules: task(
FIRST,
'🧹 Clean node_modules',
deleteDirectory(path.join(projectRootDir, 'node_modules')),
),
verify_cache: task(SECOND, '🔬 Verify npm cache', (opts?: ExecaOptions) =>
execa('npm', ['cache', 'verify'], {cwd: projectRootDir, ...opts}),
),
}),
/**
* Stops Watchman and clears its cache
*/
watchman: (projectRootDir: string) => ({
stop: task(FIRST, '✋ Stop Watchman', (opts?: ExecaOptions) =>
execa(isWindows ? 'tskill' : 'killall', ['watchman'], {
cwd: projectRootDir,
...opts,
}),
),
cache: task(SECOND, '🧹 Delete Watchman cache', (opts?: ExecaOptions) =>
execa('watchman', ['watch-del-all'], {cwd: projectRootDir, ...opts}),
),
}),
/**
* Cleans up the Yarn cache
*/
yarn: (projectRootDir: string) => ({
clean: task(FIRST, '🧹 Clean Yarn cache', (opts?: ExecaOptions) =>
execa('yarn', ['cache', 'clean'], {cwd: projectRootDir, ...opts}),
),
}),
};
if (isMacOS) {
/**
* Cleans up the local and global CocoaPods cache
*/
tasks.cocoapods = (projectRootDir: string) => ({
// TODO: add project root
clean: task(FIRST, '🧹 Clean CocoaPods pod cache', (opts?: ExecaOptions) =>
execa('bundle', ['exec', 'pod', 'deintegrate'], {
cwd: projectRootDir,
...opts,
}),
),
});
}