UNPKG

worktree-tool

Version:

A command-line tool for managing Git worktrees with integrated tmux/shell session management

90 lines 3.79 kB
import { execSync } from "child_process"; import { createTmuxSessionWithWindow, createTmuxWindowWithCommand, isTmuxAvailable, sanitizeTmuxName, sanitizeTmuxWindowName, tmuxSessionExists, } from "../../platform/tmux.js"; import { getErrorMessage } from "../../utils/error-handler.js"; import { ExecutionMode } from "./base.js"; export class ExitMode extends ExecutionMode { config; logger; constructor(config, logger) { super(); this.config = config; this.logger = logger; } async execute(contexts) { this.logger.info(`Executing command in ${String(contexts.length)} worktree(s) (exit mode)...`); const hasTmux = await isTmuxAvailable(); const sessionName = sanitizeTmuxName(this.config.projectName); const sessionExists = this.config.tmux && hasTmux ? await tmuxSessionExists(sessionName) : false; let failureCount = 0; for (let i = 0; i < contexts.length; i++) { const context = contexts[i]; if (!context) { continue; } const windowName = sanitizeTmuxWindowName(`${context.worktreeName}::tmp`); try { if (this.config.tmux && hasTmux) { await this.executeTmux(context, windowName, sessionName, i === 0 && !sessionExists); } else { this.executeSync(context); } this.logger.success(`Completed in ${context.worktreeName}: ${context.command}`); } catch (error) { this.logger.error(`Failed in ${context.worktreeName}: ${getErrorMessage(error)}`); failureCount++; } } if (failureCount > 0) { throw new Error(`${String(failureCount)} command(s) failed`); } } async executeTmux(context, windowName, sessionName, isFirstWindow) { const fullCommand = this.buildFullCommand(context); if (isFirstWindow) { await createTmuxSessionWithWindow(sessionName, windowName, context.worktreePath, fullCommand); } else { await createTmuxWindowWithCommand(sessionName, windowName, context.worktreePath, fullCommand); } } executeSync(context) { const command = this.buildCommand(context); try { // For exit mode without tmux, we run synchronously in the current terminal execSync(command, { cwd: context.worktreePath, env: this.getEnvironment(context), stdio: "inherit", }); } catch { // execSync throws on non-zero exit codes throw new Error("Command failed with exit code"); } } buildCommand(context) { const args = context.args.map((arg) => { // Quote args that contain spaces if (arg.includes(" ")) { return `"${arg}"`; } return arg; }); return [context.command, ...args].join(" "); } buildFullCommand(context) { // Build environment variable exports const env = this.getEnvironment(context); const envCommands = Object.entries(env) .filter(([key]) => key.startsWith("WTT_")) .map(([key, value]) => `export ${key}="${value}"`) .join("; "); const command = this.buildCommand(context); // Create the full command to run in the shell // For exit mode, we add 'exit' at the end to close the window after completion return `${envCommands}; clear; echo "Running: ${command}"; echo; ${command}; echo; echo "Command completed. Window will close..."; sleep 2; exit`; } } //# sourceMappingURL=exit.js.map