mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-11 02:33:51 +08:00
feat(install): 添加 Git Bash 多行提示修复功能并在卸载时询问移除
refactor(cli): 删除不再使用的 CLI 脚本和测试文件 fix(cli): 移除多行参数提示的输出
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { existsSync, mkdirSync, readdirSync, statSync, copyFileSync, readFileSync, writeFileSync, unlinkSync, rmdirSync } from 'fs';
|
||||
import { existsSync, mkdirSync, readdirSync, statSync, copyFileSync, readFileSync, writeFileSync, unlinkSync, rmdirSync, appendFileSync } from 'fs';
|
||||
import { join, dirname, basename } from 'path';
|
||||
import { homedir } from 'os';
|
||||
import { homedir, platform } from 'os';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { execSync } from 'child_process';
|
||||
import inquirer from 'inquirer';
|
||||
import chalk from 'chalk';
|
||||
import { showHeader, createSpinner, info, warning, error, summaryBox, divider } from '../utils/ui.js';
|
||||
@@ -9,6 +10,10 @@ import { createManifest, addFileEntry, addDirectoryEntry, saveManifest, findMani
|
||||
import { validatePath } from '../utils/path-resolver.js';
|
||||
import type { Ora } from 'ora';
|
||||
|
||||
// Git Bash fix markers
|
||||
const GITBASH_FIX_START = '# >>> ccw gitbash fix';
|
||||
const GITBASH_FIX_END = '# <<< ccw gitbash fix';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
@@ -272,6 +277,27 @@ export async function installCommand(options: InstallOptions): Promise<void> {
|
||||
borderColor: 'green'
|
||||
});
|
||||
|
||||
// Install Git Bash fix on Windows
|
||||
if (platform() === 'win32') {
|
||||
console.log('');
|
||||
const { installFix } = await inquirer.prompt([{
|
||||
type: 'confirm',
|
||||
name: 'installFix',
|
||||
message: 'Install Git Bash multi-line prompt fix? (recommended for Git Bash users)',
|
||||
default: true
|
||||
}]);
|
||||
|
||||
if (installFix) {
|
||||
const fixResult = await installGitBashFix();
|
||||
if (fixResult.installed) {
|
||||
info(`Git Bash fix: ${fixResult.message}`);
|
||||
info(' Run: source ~/.bashrc (to apply immediately)');
|
||||
} else {
|
||||
warning(`Git Bash fix skipped: ${fixResult.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Show next steps
|
||||
console.log('');
|
||||
info('Next steps:');
|
||||
@@ -497,6 +523,153 @@ async function copyDirectory(
|
||||
return { files, directories };
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if running in Git Bash on Windows
|
||||
*/
|
||||
function isGitBashOnWindows(): boolean {
|
||||
if (platform() !== 'win32') return false;
|
||||
|
||||
// Check for MSYSTEM env var (set by Git Bash)
|
||||
const msystem = process.env.MSYSTEM;
|
||||
if (msystem && ['MINGW64', 'MINGW32', 'MSYS'].includes(msystem)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for typical Git Bash shell path
|
||||
const shell = process.env.SHELL || '';
|
||||
if (shell.includes('bash') || shell.includes('sh')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ccw.js path for Git Bash fix
|
||||
*/
|
||||
function getCcwJsPath(): string | null {
|
||||
try {
|
||||
const npmPrefix = execSync('npm config get prefix', { encoding: 'utf8' }).trim();
|
||||
const ccwJsPath = join(npmPrefix, 'node_modules', 'claude-code-workflow', 'ccw', 'bin', 'ccw.js');
|
||||
|
||||
if (existsSync(ccwJsPath)) {
|
||||
return ccwJsPath;
|
||||
}
|
||||
return null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Git Bash fix content for .bashrc
|
||||
*/
|
||||
function generateGitBashFix(ccwJsPath: string): string {
|
||||
// Use Windows path format for node (works in Git Bash)
|
||||
const windowsPath = ccwJsPath.replace(/\//g, '/');
|
||||
|
||||
return `
|
||||
${GITBASH_FIX_START}
|
||||
# Fix for multi-line prompt arguments in Git Bash + Windows
|
||||
# npm's shell wrapper cannot handle multi-line quoted strings correctly
|
||||
ccw() {
|
||||
node "${windowsPath}" "$@"
|
||||
}
|
||||
${GITBASH_FIX_END}
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install Git Bash fix to user's shell config
|
||||
* @returns true if fix was installed, false otherwise
|
||||
*/
|
||||
export async function installGitBashFix(): Promise<{ installed: boolean; message: string }> {
|
||||
// Only applicable on Windows
|
||||
if (platform() !== 'win32') {
|
||||
return { installed: false, message: 'Not Windows platform' };
|
||||
}
|
||||
|
||||
const ccwJsPath = getCcwJsPath();
|
||||
if (!ccwJsPath) {
|
||||
return { installed: false, message: 'ccw not found in npm global modules' };
|
||||
}
|
||||
|
||||
// Find shell config file
|
||||
const home = homedir();
|
||||
const configFiles = [
|
||||
join(home, '.bashrc'),
|
||||
join(home, '.bash_profile'),
|
||||
join(home, '.profile')
|
||||
];
|
||||
|
||||
let targetConfig: string | null = null;
|
||||
for (const configFile of configFiles) {
|
||||
if (existsSync(configFile)) {
|
||||
targetConfig = configFile;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no config exists, create .bashrc
|
||||
if (!targetConfig) {
|
||||
targetConfig = join(home, '.bashrc');
|
||||
}
|
||||
|
||||
// Check if fix already exists
|
||||
if (existsSync(targetConfig)) {
|
||||
const content = readFileSync(targetConfig, 'utf8');
|
||||
if (content.includes(GITBASH_FIX_START)) {
|
||||
// Update existing fix
|
||||
const fixContent = generateGitBashFix(ccwJsPath);
|
||||
const regex = new RegExp(`${GITBASH_FIX_START}[\\s\\S]*?${GITBASH_FIX_END}`, 'g');
|
||||
const newContent = content.replace(regex, fixContent.trim());
|
||||
writeFileSync(targetConfig, newContent, 'utf8');
|
||||
return { installed: true, message: `Updated in ${basename(targetConfig)}` };
|
||||
}
|
||||
}
|
||||
|
||||
// Append fix to config file
|
||||
const fixContent = generateGitBashFix(ccwJsPath);
|
||||
appendFileSync(targetConfig, fixContent, 'utf8');
|
||||
|
||||
return { installed: true, message: `Added to ${basename(targetConfig)}` };
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Git Bash fix from user's shell config
|
||||
* @returns true if fix was removed, false otherwise
|
||||
*/
|
||||
export function removeGitBashFix(): { removed: boolean; message: string } {
|
||||
const home = homedir();
|
||||
const configFiles = [
|
||||
join(home, '.bashrc'),
|
||||
join(home, '.bash_profile'),
|
||||
join(home, '.profile')
|
||||
];
|
||||
|
||||
let removed = false;
|
||||
let targetFile = '';
|
||||
|
||||
for (const configFile of configFiles) {
|
||||
if (!existsSync(configFile)) continue;
|
||||
|
||||
const content = readFileSync(configFile, 'utf8');
|
||||
if (content.includes(GITBASH_FIX_START)) {
|
||||
// Remove the fix block
|
||||
const regex = new RegExp(`\\n?${GITBASH_FIX_START}[\\s\\S]*?${GITBASH_FIX_END}\\n?`, 'g');
|
||||
const newContent = content.replace(regex, '\n');
|
||||
writeFileSync(configFile, newContent, 'utf8');
|
||||
removed = true;
|
||||
targetFile = basename(configFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (removed) {
|
||||
return { removed: true, message: `Removed from ${targetFile}` };
|
||||
}
|
||||
return { removed: false, message: 'No fix found to remove' };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get package version
|
||||
* @returns {string} - Version string
|
||||
|
||||
Reference in New Issue
Block a user