mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-11 02:33:51 +08:00
feat(uninstall): 增强卸载命令以支持全局安装保护和文件跳过逻辑
This commit is contained in:
@@ -1,10 +1,14 @@
|
|||||||
import { existsSync, unlinkSync, rmdirSync, readdirSync, statSync } from 'fs';
|
import { existsSync, unlinkSync, rmdirSync, readdirSync, statSync } from 'fs';
|
||||||
import { join, dirname, basename } from 'path';
|
import { join, dirname, basename } from 'path';
|
||||||
|
import { homedir } from 'os';
|
||||||
import inquirer from 'inquirer';
|
import inquirer from 'inquirer';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import { showBanner, createSpinner, success, info, warning, error, summaryBox, divider } from '../utils/ui.js';
|
import { showBanner, createSpinner, success, info, warning, error, summaryBox, divider } from '../utils/ui.js';
|
||||||
import { getAllManifests, deleteManifest } from '../core/manifest.js';
|
import { getAllManifests, deleteManifest } from '../core/manifest.js';
|
||||||
|
|
||||||
|
// Global subdirectories that should be protected when Global installation exists
|
||||||
|
const GLOBAL_SUBDIRS = ['workflows', 'scripts', 'templates'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uninstall command handler
|
* Uninstall command handler
|
||||||
* @param {Object} options - Command options
|
* @param {Object} options - Command options
|
||||||
@@ -92,6 +96,22 @@ export async function uninstallCommand(options) {
|
|||||||
|
|
||||||
console.log('');
|
console.log('');
|
||||||
|
|
||||||
|
// Check if this is a Path mode uninstallation and if Global installation exists
|
||||||
|
const isPathMode = selectedManifest.installation_mode === 'Path';
|
||||||
|
const globalClaudeDir = join(homedir(), '.claude');
|
||||||
|
let hasGlobalInstallation = false;
|
||||||
|
let skippedFiles = 0;
|
||||||
|
|
||||||
|
if (isPathMode) {
|
||||||
|
// Check if any Global installation manifest exists
|
||||||
|
const globalManifest = manifests.find(m => m.installation_mode === 'Global');
|
||||||
|
if (globalManifest) {
|
||||||
|
hasGlobalInstallation = true;
|
||||||
|
info('Global installation detected - global files will be preserved');
|
||||||
|
console.log('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Perform uninstallation
|
// Perform uninstallation
|
||||||
const spinner = createSpinner('Removing files...').start();
|
const spinner = createSpinner('Removing files...').start();
|
||||||
|
|
||||||
@@ -105,6 +125,25 @@ export async function uninstallCommand(options) {
|
|||||||
|
|
||||||
for (const fileEntry of files) {
|
for (const fileEntry of files) {
|
||||||
const filePath = fileEntry.path;
|
const filePath = fileEntry.path;
|
||||||
|
|
||||||
|
// For Path mode uninstallation, skip global files if Global installation exists
|
||||||
|
if (isPathMode && hasGlobalInstallation) {
|
||||||
|
const normalizedPath = filePath.toLowerCase().replace(/\\/g, '/');
|
||||||
|
const normalizedGlobalDir = globalClaudeDir.toLowerCase().replace(/\\/g, '/');
|
||||||
|
|
||||||
|
// Check if file is under global .claude directory
|
||||||
|
if (normalizedPath.startsWith(normalizedGlobalDir)) {
|
||||||
|
// Check if it's in one of the global subdirectories
|
||||||
|
const relativePath = normalizedPath.substring(normalizedGlobalDir.length + 1);
|
||||||
|
const topDir = relativePath.split('/')[0];
|
||||||
|
|
||||||
|
if (GLOBAL_SUBDIRS.includes(topDir)) {
|
||||||
|
skippedFiles++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
spinner.text = `Removing: ${basename(filePath)}`;
|
spinner.text = `Removing: ${basename(filePath)}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -168,41 +207,43 @@ export async function uninstallCommand(options) {
|
|||||||
// Show summary
|
// Show summary
|
||||||
console.log('');
|
console.log('');
|
||||||
|
|
||||||
if (failedFiles.length > 0) {
|
const summaryLines = [];
|
||||||
summaryBox({
|
|
||||||
title: ' Uninstall Summary ',
|
|
||||||
lines: [
|
|
||||||
chalk.yellow.bold('⚠ Partially Completed'),
|
|
||||||
'',
|
|
||||||
chalk.white(`Files removed: ${chalk.green(removedFiles)}`),
|
|
||||||
chalk.white(`Directories removed: ${chalk.green(removedDirs)}`),
|
|
||||||
chalk.white(`Failed: ${chalk.red(failedFiles.length)}`),
|
|
||||||
'',
|
|
||||||
chalk.gray('Some files could not be removed.'),
|
|
||||||
chalk.gray('They may be in use or require elevated permissions.'),
|
|
||||||
],
|
|
||||||
borderColor: 'yellow'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (process.env.DEBUG) {
|
if (failedFiles.length > 0) {
|
||||||
console.log('');
|
summaryLines.push(chalk.yellow.bold('⚠ Partially Completed'));
|
||||||
console.log(chalk.gray('Failed files:'));
|
|
||||||
failedFiles.forEach(f => {
|
|
||||||
console.log(chalk.red(` ${f.path}: ${f.error}`));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
summaryBox({
|
summaryLines.push(chalk.green.bold('✓ Successfully Uninstalled'));
|
||||||
title: ' Uninstall Summary ',
|
}
|
||||||
lines: [
|
|
||||||
chalk.green.bold('✓ Successfully Uninstalled'),
|
summaryLines.push('');
|
||||||
'',
|
summaryLines.push(chalk.white(`Files removed: ${chalk.green(removedFiles)}`));
|
||||||
chalk.white(`Files removed: ${chalk.green(removedFiles)}`),
|
summaryLines.push(chalk.white(`Directories removed: ${chalk.green(removedDirs)}`));
|
||||||
chalk.white(`Directories removed: ${chalk.green(removedDirs)}`),
|
|
||||||
'',
|
if (skippedFiles > 0) {
|
||||||
chalk.gray('Manifest removed'),
|
summaryLines.push(chalk.white(`Global files preserved: ${chalk.cyan(skippedFiles)}`));
|
||||||
],
|
}
|
||||||
borderColor: 'green'
|
|
||||||
|
if (failedFiles.length > 0) {
|
||||||
|
summaryLines.push(chalk.white(`Failed: ${chalk.red(failedFiles.length)}`));
|
||||||
|
summaryLines.push('');
|
||||||
|
summaryLines.push(chalk.gray('Some files could not be removed.'));
|
||||||
|
summaryLines.push(chalk.gray('They may be in use or require elevated permissions.'));
|
||||||
|
} else {
|
||||||
|
summaryLines.push('');
|
||||||
|
summaryLines.push(chalk.gray('Manifest removed'));
|
||||||
|
}
|
||||||
|
|
||||||
|
summaryBox({
|
||||||
|
title: ' Uninstall Summary ',
|
||||||
|
lines: summaryLines,
|
||||||
|
borderColor: failedFiles.length > 0 ? 'yellow' : 'green'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (process.env.DEBUG && failedFiles.length > 0) {
|
||||||
|
console.log('');
|
||||||
|
console.log(chalk.gray('Failed files:'));
|
||||||
|
failedFiles.forEach(f => {
|
||||||
|
console.log(chalk.red(` ${f.path}: ${f.error}`));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user