feat: add --uninstall support to install script
- Add --uninstall flag to remove installed components - List items to be removed before confirmation - Remove pass_mgr binary, skills modules, and env config - Preserve admin key directory (warns user to remove manually) - Update PROJECT_PLAN.md with uninstall usage
This commit is contained in:
@@ -286,6 +286,12 @@ node install.mjs --build-only
|
|||||||
|
|
||||||
# 跳过依赖检测
|
# 跳过依赖检测
|
||||||
node install.mjs --skip-check
|
node install.mjs --skip-check
|
||||||
|
|
||||||
|
# 卸载
|
||||||
|
node install.mjs --uninstall
|
||||||
|
|
||||||
|
# 从指定路径卸载
|
||||||
|
node install.mjs --uninstall --prefix /usr/local
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
87
install.mjs
87
install.mjs
@@ -8,6 +8,8 @@
|
|||||||
* node install.mjs --prefix /usr/local
|
* node install.mjs --prefix /usr/local
|
||||||
* node install.mjs --build-only
|
* node install.mjs --build-only
|
||||||
* node install.mjs --skip-check
|
* node install.mjs --skip-check
|
||||||
|
* node install.mjs --uninstall
|
||||||
|
* node install.mjs --uninstall --prefix /usr/local
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { execSync, spawn } from 'child_process';
|
import { execSync, spawn } from 'child_process';
|
||||||
@@ -27,6 +29,7 @@ const options = {
|
|||||||
buildOnly: args.includes('--build-only'),
|
buildOnly: args.includes('--build-only'),
|
||||||
skipCheck: args.includes('--skip-check'),
|
skipCheck: args.includes('--skip-check'),
|
||||||
verbose: args.includes('--verbose') || args.includes('-v'),
|
verbose: args.includes('--verbose') || args.includes('-v'),
|
||||||
|
uninstall: args.includes('--uninstall'),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parse --prefix value
|
// Parse --prefix value
|
||||||
@@ -589,9 +592,84 @@ function printSummary(env) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Main
|
// Uninstall Function
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
|
async function uninstall(env) {
|
||||||
|
logStep(1, 'Uninstalling PaddedCell...');
|
||||||
|
|
||||||
|
const installDir = options.prefix || env.openclawDir;
|
||||||
|
const binDir = join(installDir, 'bin');
|
||||||
|
const skillsDir = join(installDir, 'skills', 'paddedcell');
|
||||||
|
const envFile = join(installDir, 'paddedcell.env');
|
||||||
|
|
||||||
|
const itemsToRemove = [];
|
||||||
|
|
||||||
|
// Check what exists
|
||||||
|
const passMgrBinary = join(binDir, 'pass_mgr');
|
||||||
|
if (existsSync(passMgrBinary)) {
|
||||||
|
itemsToRemove.push(passMgrBinary);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existsSync(skillsDir)) {
|
||||||
|
itemsToRemove.push(skillsDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existsSync(envFile)) {
|
||||||
|
itemsToRemove.push(envFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemsToRemove.length === 0) {
|
||||||
|
log('No installed components found.', 'yellow');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log('The following items will be removed:', 'yellow');
|
||||||
|
for (const item of itemsToRemove) {
|
||||||
|
log(` • ${item}`, 'reset');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ask for confirmation
|
||||||
|
const confirm = await prompt('\nAre you sure you want to uninstall? (y/N): ');
|
||||||
|
if (confirm.toLowerCase() !== 'y') {
|
||||||
|
log('Uninstall cancelled.', 'yellow');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform uninstall
|
||||||
|
for (const item of itemsToRemove) {
|
||||||
|
try {
|
||||||
|
if (item === passMgrBinary || item === envFile) {
|
||||||
|
execSync(`rm -f "${item}"`, { silent: true });
|
||||||
|
logSuccess(`Removed: ${item}`);
|
||||||
|
} else {
|
||||||
|
execSync(`rm -rf "${item}"`, { silent: true });
|
||||||
|
logSuccess(`Removed: ${item}`);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
logError(`Failed to remove: ${item}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for admin key directory
|
||||||
|
const adminKeyDir = join(homedir(), '.pass_mgr');
|
||||||
|
if (existsSync(adminKeyDir)) {
|
||||||
|
log('\n⚠️ Admin key directory found:', 'yellow');
|
||||||
|
log(` ${adminKeyDir}`, 'cyan');
|
||||||
|
log(' This contains your encryption keys. Remove manually if desired.', 'yellow');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('');
|
||||||
|
log('╔════════════════════════════════════════════════════════╗', 'cyan');
|
||||||
|
log('║ PaddedCell Uninstall Complete ║', 'cyan');
|
||||||
|
log('╚════════════════════════════════════════════════════════╝', 'cyan');
|
||||||
|
console.log('');
|
||||||
|
|
||||||
|
log('Remember to remove the following from your shell profile:', 'yellow');
|
||||||
|
log(` source ${envFile}`, 'cyan');
|
||||||
|
console.log('');
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
console.log('');
|
console.log('');
|
||||||
log('╔════════════════════════════════════════════════════════╗', 'cyan');
|
log('╔════════════════════════════════════════════════════════╗', 'cyan');
|
||||||
@@ -601,6 +679,13 @@ async function main() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const env = detectEnvironment();
|
const env = detectEnvironment();
|
||||||
|
|
||||||
|
// Handle uninstall
|
||||||
|
if (options.uninstall) {
|
||||||
|
await uninstall(env);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
checkDependencies(env);
|
checkDependencies(env);
|
||||||
await buildComponents(env);
|
await buildComponents(env);
|
||||||
await installComponents(env);
|
await installComponents(env);
|
||||||
|
|||||||
Reference in New Issue
Block a user