Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: force clean #41

Merged
merged 5 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion integration/index.2.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('test/index.v2.test.js', () => {
let cwd;

afterEach(async () => {
await clean(cwd);
await clean({ cwd });
if (process.platform === 'darwin') {
try {
await forceExitDaemon();
Expand Down
4 changes: 3 additions & 1 deletion integration/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ const {
describe('test/tnpm-install-rapid.test.js', () => {
let fixture;
afterEach(async () => {
await clean(fixture);
await clean({
cwd: fixture,
});
if (process.platform === 'darwin') {
await forceExitDaemon();
} else {
Expand Down
11 changes: 9 additions & 2 deletions integration/workspaces.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ describe('test/workspaces.test.js', () => {

it('should install lodash successfully', async () => {
cwd = path.join(__dirname, './fixtures/workspaces');
await clean(cwd);
await clean({
cwd,
force: true,
});
await install({
nydusMode: 'FUSE',
cwd,
pkg: require(path.join(cwd, 'package.json')),
depsTreePath: path.join(cwd, 'package-lock.json'),
Expand All @@ -34,7 +38,10 @@ describe('test/workspaces.test.js', () => {
assert(lodash1.version.startsWith('1.'));
assert(lodash2.version.startsWith('2.'));
} finally {
await clean(cwd);
await clean({
cwd,
force: true,
});
if (process.platform === 'darwin') {
await forceExitDaemon();
} else {
Expand Down
20 changes: 14 additions & 6 deletions packages/cli/bin/rapid.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@

const { clean, install, list } = require('../lib/index.js');
const yargs = require('yargs');
const { NpmFsMode } = require('../lib/constants.js');
const { NpmFsMode, NYDUS_TYPE } = require('../lib/constants.js');
const util = require('../lib/util');
const path = require('node:path');

yargs
.command({
command: 'install',
aliases: [ 'i', 'ii' ],
describe: 'Install dependencies',
builder: yargs => {
return yargs
Expand All @@ -30,10 +32,12 @@ yargs
const pkgRes = await util.readPkgJSON();
const pkg = pkgRes?.pkg || {};

await util.shouldFuseSupport();
await install({
cwd,
pkg,
mode,
nydusMode: NYDUS_TYPE.FUSE,
ignoreScripts,
});

Expand All @@ -43,17 +47,21 @@ yargs
},
})
.command({
command: 'clean',
command: 'clean [path]',
aliases: [ 'c', 'unmount', 'uninstall' ],
describe: 'Clean up the project',
handler: async () => {
const cwd = process.cwd();
await clean(cwd);

handler: async argv => {
let cwd = argv.path || process.cwd();
if (cwd.endsWith('node_modules') || cwd.endsWith('node_modules/')) {
cwd = path.dirname(cwd);
}
await clean({ nydusMode: NYDUS_TYPE.FUSE, cwd, force: false });
console.log('[rapid] clean finished');
},
})
.command({
command: 'list',
aliases: 'l',
describe: 'List rapid mount info',
handler: async () => {
const cwd = process.cwd();
Expand Down
30 changes: 15 additions & 15 deletions packages/cli/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ const { MirrorConfig } = require('binary-mirror-config');
// 有依赖树(package-lock.json)走 npm / npminstall 极速安装
exports.install = async options => {
options.env = util.getEnv(options.env, options.args);
const nydusMode = await nydusd.getNydusMode();
if (!nydusMode || nydusMode === NYDUS_TYPE.NATIVE) {
await util.shouldFuseSupport();
}

const { packageLock } = options.packageLock || (await util.readPackageLock(options.cwd));

const currentMountInfo = await util.listMountInfo();
Expand All @@ -35,8 +30,13 @@ exports.install = async options => {
const mountedInfo = currentMountInfo.find(item => item.mountPoint === nodeModulesDir);

if (mountedInfo) {
console.log(`[rapid] ${nodeModulesDir} already mounted, try to clean`);
await exports.clean(path.join(options.cwd, pkgPath), true);
console.time(`[rapid] ${nodeModulesDir} already mounted, try to clean`);
await exports.clean({
nydusMode: options.nydusMode,
cwd: options.cwd,
force: true,
});
console.timeEnd(`[rapid] ${nodeModulesDir} already mounted, try to clean`);
}

await fs.mkdir(baseDir, { recursive: true });
Expand All @@ -56,7 +56,7 @@ exports.install = async options => {
await downloadDependency.download(options);

assert(Object.keys(packageLock).length, '[rapid] depsJSON invalid.');
await nydusd.startNydusFs(nydusMode, options.cwd, options.pkg);
await nydusd.startNydusFs(options.nydusMode, options.cwd, options.pkg);

console.time('[rapid] wait for access');
await util.ensureAccess(options.cwd, packageLock);
Expand All @@ -67,20 +67,20 @@ exports.install = async options => {
console.timeEnd('[rapid] run lifecycle scripts');
};

exports.clean = async function clean(cwd) {
const mode = await nydusd.getNydusInstallMode(cwd);
if (!mode) {
console.log(`[rapid] invalid mode ${mode} ignore`);
exports.clean = async function clean({ nydusMode = NYDUS_TYPE.FUSE, cwd, force }) {
const listInfo = await util.listMountInfo();
if (!listInfo.length) {
console.log('[rapid] no mount info found.');
return;
}
const { pkg } = await util.readPkgJSON(cwd);
await nydusd.endNydusFs(mode, cwd, pkg);
await nydusd.endNydusFs(nydusMode, cwd, pkg, force);
};

exports.list = async () => {
const running = await nydusdApi.isDaemonRunning();
if (!running) {
console.error('[rapid] nydusd is not running, please run `rapid install` first.');
return;
console.warn('[rapid] nydusd is not running, please run `rapid install` first.');
}
const listInfo = await util.listMountInfo();
if (!listInfo.length) {
Expand Down
25 changes: 12 additions & 13 deletions packages/cli/lib/nydusd/fuse_mode.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const {
wrapSudo,
getWorkdir,
getAllPkgPaths,
safeExeca,
} = require('../util');
const nydusdApi = require('./nydusd_api');

Expand Down Expand Up @@ -98,23 +99,21 @@ ${nodeModulesDir}`;
}
}

async function endNydusFs(cwd, pkg) {
async function endNydusFs(cwd, pkg, force = false) {
const allPkgs = await getAllPkgPaths(cwd, pkg);
const umountCmd = force ? 'umount -f' : 'umount';
for (const pkgPath of allPkgs) {
const {
dirname,
overlay,
baseDir,
nodeModulesDir,
} = await getWorkdir(cwd, pkgPath);
const { dirname, overlay, baseDir, nodeModulesDir } = await getWorkdir(
cwd,
pkgPath
);
if (os.type() === 'Darwin') {
console.log(`[rapid] umount ${nodeModulesDir}`);
await execa.command(`umount ${nodeModulesDir}`);
// hdiutil detach
await execa.command(`hdiutil detach ${overlay}`);
killagu marked this conversation as resolved.
Show resolved Hide resolved
console.log(`[rapid] ${umountCmd} ${nodeModulesDir}`);
await safeExeca(`umount ${nodeModulesDir}`, force ? `umount -f ${nodeModulesDir}` : '');
await safeExeca(`hdiutil detach ${overlay}`, force ? `hdiutil detach -force ${overlay}` : '');
} else {
await execa.command(wrapSudo(`umount ${nodeModulesDir}`));
await execa.command(wrapSudo(`umount ${overlay}`));
await execa.command(wrapSudo(`${umountCmd} ${nodeModulesDir}`));
await execa.command(wrapSudo(`${umountCmd} ${overlay}`));
}
await nydusdApi.umount(`/${dirname}`);
// 清除 nydus 相关目录
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/lib/nydusd/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ exports.startNydusFs = async function(mode, cwd, pkg) {
await impl.start(cwd, pkg);
};

exports.endNydusFs = async function(mode, cwd, pkg) {
exports.endNydusFs = async function(mode, cwd, pkg, force) {
if (!mode || mode === NYDUS_TYPE.NATIVE) {
console.log('[rapid] nydusd is not running, skip clean');
return;
}
const impl = fsImplMap[mode];
assert(impl, `can not find fs impl for mode: ${mode}`);
await impl.end(cwd, pkg);
await impl.end(cwd, pkg, force);
};

exports.getNydusMode = async function(cwd) {
Expand Down
10 changes: 9 additions & 1 deletion packages/cli/lib/nydusd/nydusd_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,15 @@ async function forceExitDaemon() {
await execa.command('killall -9 nydusd');
} catch (e) {
// ignore, nydusd quits with error, but it's ok
e.message = 'exit nydusd faield: ' + e.message;
e.message = 'umount nydusd mnt failed: ' + e.message;
console.warn(e);
}

try {
await execa.command('killall -9 nydusd');
} catch (e) {
// ignore, nydusd quits with error, but it's ok
e.message = 'exit nydusd failed: ' + e.message;
console.warn(e);
}
}
Expand Down
14 changes: 14 additions & 0 deletions packages/cli/lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,19 @@ function wrapSudo(shScript) {
return `sudo ${shScript}`;
}

async function safeExeca(command, fallback) {
try {
await execa.command(command);
} catch (e) {
console.warn(`[rapid] ${command} error: `, e);
try {
fallback && (await execa.command(fallback));
} catch (e) {
// ignore
}
}
}

// 需要手动写入,保证 path 路径符合预期
async function createNydusdConfigFile(path) {
await fs.writeFile(path, JSON.stringify({
Expand Down Expand Up @@ -617,3 +630,4 @@ exports.isFlattenPackage = isFlattenPackage;
exports.resolveBinMap = resolveBinMap;
exports.getFileEntryMode = getFileEntryMode;
exports.getEnv = getEnv;
exports.safeExeca = safeExeca;
Loading