execIntoTmuxWorktree method
Fast-path handler for --worktree --tmux. Creates the worktree and execs into tmux running Neomage inside.
Implementation
Future<({bool handled, String? error})> execIntoTmuxWorktree(
List<String> args,
) async {
// Check platform
if (Platform.isWindows) {
return (
handled: false,
error: 'Error: --tmux is not supported on Windows',
);
}
// Check tmux
final tmuxAvailable = await isTmuxAvailable();
if (!tmuxAvailable) {
return (
handled: false,
error: 'Error: tmux is not installed. ${getTmuxInstallInstructions()}',
);
}
// Parse worktree name from args
String? worktreeName;
bool forceClassicTmux = false;
for (int i = 0; i < args.length; i++) {
final arg = args[i];
if (arg == '-w' || arg == '--worktree') {
if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
worktreeName = args[i + 1];
}
} else if (arg.startsWith('--worktree=')) {
worktreeName = arg.substring('--worktree='.length);
} else if (arg == '--tmux=classic') {
forceClassicTmux = true;
}
}
// Check for PR reference
int? prNumber;
if (worktreeName != null) {
prNumber = parsePRReference(worktreeName);
if (prNumber != null) {
worktreeName = 'pr-$prNumber';
}
}
// Generate a slug if no name provided
if (worktreeName == null) {
const adjectives = ['swift', 'bright', 'calm', 'keen', 'bold'];
const nouns = ['fox', 'owl', 'elm', 'oak', 'ray'];
final rng = Random();
final adj = adjectives[rng.nextInt(adjectives.length)];
final noun = nouns[rng.nextInt(nouns.length)];
final suffix = rng.nextInt(0xFFFF).toRadixString(36).padLeft(4, '0');
worktreeName = '$adj-$noun-$suffix';
}
try {
validateWorktreeSlug(worktreeName);
} catch (e) {
return (handled: false, error: 'Error: $e');
}
// Create or resume worktree
final gitRoot = _findCanonicalGitRoot(_getCwd());
if (gitRoot == null && !_hasWorktreeCreateHook()) {
return (
handled: false,
error: 'Error: --worktree requires a git repository',
);
}
String worktreeDir;
String repoName;
if (_hasWorktreeCreateHook() && onExecuteWorktreeCreateHook != null) {
try {
final hookResult = await onExecuteWorktreeCreateHook!(worktreeName);
worktreeDir = hookResult.worktreePath;
} catch (e) {
return (handled: false, error: 'Error: $e');
}
repoName = (gitRoot ?? _getCwd()).split('/').last;
} else {
repoName = gitRoot!.split('/').last;
worktreeDir = _worktreePathFor(gitRoot, worktreeName);
try {
final result = await _getOrCreateWorktree(
gitRoot,
worktreeName,
options: prNumber != null
? WorktreeCreateOptions(prNumber: prNumber)
: null,
);
if (result is WorktreeCreated) {
await _performPostCreationSetup(gitRoot, worktreeDir);
}
} catch (e) {
return (handled: false, error: 'Error: $e');
}
}
// Build tmux session name
final tmuxSessionNameFinal =
'${repoName}_${worktreeBranchName(worktreeName)}'.replaceAll(
RegExp(r'[/.]'),
'_',
);
// Build new args without --tmux and --worktree
final newArgs = <String>[];
for (int i = 0; i < args.length; i++) {
final arg = args[i];
if (arg == '--tmux' || arg == '--tmux=classic') continue;
if (arg == '-w' || arg == '--worktree') {
if (i + 1 < args.length && !args[i + 1].startsWith('-')) i++;
continue;
}
if (arg.startsWith('--worktree=')) continue;
newArgs.add(arg);
}
// Create tmux session
final tmuxArgs = [
'new-session',
'-A',
'-s',
tmuxSessionNameFinal,
'-c',
worktreeDir,
'--',
Platform.resolvedExecutable,
...newArgs,
];
final tmuxResult = Process.runSync(
'tmux',
tmuxArgs,
workingDirectory: worktreeDir,
);
return (handled: true, error: null);
}