workon 3.4.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1443,20 +1443,36 @@ import { exec as execCallback2 } from "child_process";
1443
1443
  import { promisify as promisify2 } from "util";
1444
1444
  import { existsSync as existsSync2, chmodSync } from "fs";
1445
1445
  import { join, basename } from "path";
1446
+ import { createHash } from "crypto";
1447
+ import { homedir } from "os";
1446
1448
  import { simpleGit as simpleGit2 } from "simple-git";
1447
- var exec2, WORKTREES_DIR, HOOK_DIR, SETUP_HOOK, WorktreeManager;
1449
+ function shortHash(input7) {
1450
+ return createHash("sha256").update(input7).digest("hex").substring(0, 8);
1451
+ }
1452
+ function deriveProjectIdentifier(projectPath) {
1453
+ const name = basename(projectPath);
1454
+ const hash = shortHash(projectPath);
1455
+ return `${name}-${hash}`;
1456
+ }
1457
+ function getWorktreesDirForProject(projectIdentifier) {
1458
+ return join(homedir(), WORKON_DIR, WORKTREES_SUBDIR, projectIdentifier);
1459
+ }
1460
+ var exec2, WORKON_DIR, WORKTREES_SUBDIR, HOOK_DIR, SETUP_HOOK, WorktreeManager;
1448
1461
  var init_worktree = __esm({
1449
1462
  "src/lib/worktree.ts"() {
1450
1463
  "use strict";
1451
1464
  exec2 = promisify2(execCallback2);
1452
- WORKTREES_DIR = ".worktrees";
1465
+ WORKON_DIR = ".workon";
1466
+ WORKTREES_SUBDIR = "worktrees";
1453
1467
  HOOK_DIR = ".workon";
1454
1468
  SETUP_HOOK = "worktree-setup.sh";
1455
1469
  WorktreeManager = class {
1456
1470
  projectPath;
1471
+ projectIdentifier;
1457
1472
  git;
1458
- constructor(projectPath) {
1473
+ constructor(projectPath, _projectName) {
1459
1474
  this.projectPath = projectPath;
1475
+ this.projectIdentifier = deriveProjectIdentifier(projectPath);
1460
1476
  this.git = simpleGit2(projectPath);
1461
1477
  }
1462
1478
  /**
@@ -1472,9 +1488,10 @@ var init_worktree = __esm({
1472
1488
  }
1473
1489
  /**
1474
1490
  * Get the worktrees directory path
1491
+ * Stored at ~/.workon/worktrees/{project-identifier}/
1475
1492
  */
1476
1493
  getWorktreesDir() {
1477
- return join(this.projectPath, WORKTREES_DIR);
1494
+ return join(homedir(), WORKON_DIR, WORKTREES_SUBDIR, this.projectIdentifier);
1478
1495
  }
1479
1496
  /**
1480
1497
  * Convert branch name to directory name (replace slashes with dashes)
@@ -1765,7 +1782,8 @@ async function findWorktreeNameByPath(mainRepoPath, worktreePath) {
1765
1782
  const git = simpleGit3(mainRepoPath);
1766
1783
  const result = await git.raw(["worktree", "list", "--porcelain"]);
1767
1784
  const blocks = result.trim().split("\n\n");
1768
- const worktreesDir = path.join(mainRepoPath, ".worktrees");
1785
+ const projectIdentifier = deriveProjectIdentifier(mainRepoPath);
1786
+ const projectWorktreesDir = getWorktreesDirForProject(projectIdentifier);
1769
1787
  for (const block of blocks) {
1770
1788
  if (!block.trim()) continue;
1771
1789
  const lines = block.split("\n");
@@ -1781,7 +1799,7 @@ async function findWorktreeNameByPath(mainRepoPath, worktreePath) {
1781
1799
  }
1782
1800
  }
1783
1801
  if (wtPath === worktreePath) {
1784
- if (wtPath.startsWith(worktreesDir)) {
1802
+ if (wtPath.startsWith(projectWorktreesDir)) {
1785
1803
  return path.basename(wtPath);
1786
1804
  } else {
1787
1805
  return branch && branch !== "(detached)" ? branch.replace(/\//g, "-") : path.basename(wtPath);
@@ -1904,6 +1922,7 @@ async function promptToRegisterProject(projectPath, config, log) {
1904
1922
  var init_utils = __esm({
1905
1923
  "src/commands/worktrees/utils.ts"() {
1906
1924
  "use strict";
1925
+ init_worktree();
1907
1926
  init_registry();
1908
1927
  init_constants();
1909
1928
  }
@@ -1926,7 +1945,7 @@ function createListCommand(ctx) {
1926
1945
  }
1927
1946
  const { projectPath, projectName } = projectCtx;
1928
1947
  const displayName = projectName || path2.basename(projectPath);
1929
- const manager = new WorktreeManager(projectPath);
1948
+ const manager = new WorktreeManager(projectPath, projectName ?? void 0);
1930
1949
  const allWorktrees = await manager.list();
1931
1950
  const managedWorktrees = await manager.listManagedWorktrees();
1932
1951
  const managedPaths = new Set(managedWorktrees.map((wt) => wt.path));
@@ -1990,7 +2009,7 @@ function createAddCommand(ctx) {
1990
2009
  }
1991
2010
  }
1992
2011
  const { projectPath, projectName } = projectCtx;
1993
- const manager = new WorktreeManager(projectPath);
2012
+ const manager = new WorktreeManager(projectPath, projectName ?? void 0);
1994
2013
  const branchExists = await manager.branchExists(branch);
1995
2014
  let baseBranch = options.base;
1996
2015
  if (!branchExists && !baseBranch) {
@@ -2099,7 +2118,7 @@ function createRemoveCommand(ctx) {
2099
2118
  }
2100
2119
  const { projectPath, projectName } = projectCtx;
2101
2120
  const displayName = projectName || path3.basename(projectPath);
2102
- const manager = new WorktreeManager(projectPath);
2121
+ const manager = new WorktreeManager(projectPath, projectName ?? void 0);
2103
2122
  const worktree = await manager.get(name);
2104
2123
  if (!worktree) {
2105
2124
  log.error(`Worktree '${name}' not found for '${displayName}'`);
@@ -2193,7 +2212,7 @@ function createMergeCommand(ctx) {
2193
2212
  }
2194
2213
  const { projectPath, projectName } = projectCtx;
2195
2214
  const displayName = projectName || path4.basename(projectPath);
2196
- const manager = new WorktreeManager(projectPath);
2215
+ const manager = new WorktreeManager(projectPath, projectName ?? void 0);
2197
2216
  const worktree = await manager.get(name);
2198
2217
  if (!worktree) {
2199
2218
  log.error(`Worktree '${name}' not found for '${displayName}'`);
@@ -2339,7 +2358,7 @@ function createBranchCommand(ctx) {
2339
2358
  }
2340
2359
  const { projectPath, projectName } = projectCtx;
2341
2360
  const displayName = projectName || path5.basename(projectPath);
2342
- const manager = new WorktreeManager(projectPath);
2361
+ const manager = new WorktreeManager(projectPath, projectName ?? void 0);
2343
2362
  const worktree = await manager.get(worktreeName);
2344
2363
  if (!worktree) {
2345
2364
  log.error(`Worktree '${worktreeName}' not found for '${displayName}'`);
@@ -2527,7 +2546,7 @@ async function runWorktreeOpen(projectCtx, worktreeName, options, ctx) {
2527
2546
  const { config, log } = ctx;
2528
2547
  const { projectPath, projectName, projectConfig, isRegistered } = projectCtx;
2529
2548
  const displayName = projectName || path6.basename(projectPath);
2530
- const manager = new WorktreeManager(projectPath);
2549
+ const manager = new WorktreeManager(projectPath, projectName ?? void 0);
2531
2550
  const worktree = await manager.get(worktreeName);
2532
2551
  if (!worktree) {
2533
2552
  log.error(`Worktree '${worktreeName}' not found for '${displayName}'`);
@@ -2555,6 +2574,7 @@ async function runWorktreeOpen(projectCtx, worktreeName, options, ctx) {
2555
2574
  hasClaudeEvent = !!events.claude;
2556
2575
  hasNpmEvent = !!events.npm;
2557
2576
  }
2577
+ const shouldAttach = options.attach !== false;
2558
2578
  if (isShellMode) {
2559
2579
  const shellCommands = await buildWorktreeShellCommands(
2560
2580
  project,
@@ -2571,10 +2591,20 @@ async function runWorktreeOpen(projectCtx, worktreeName, options, ctx) {
2571
2591
  hasClaudeEvent,
2572
2592
  hasNpmEvent
2573
2593
  });
2574
- await tmux.attachToSession(sessionName);
2575
- console.log(
2576
- chalk6.green(`Opened worktree '${worktreeName}' in tmux session '${sessionName}'`)
2577
- );
2594
+ if (shouldAttach) {
2595
+ await tmux.attachToSession(sessionName);
2596
+ console.log(
2597
+ chalk6.green(`Opened worktree '${worktreeName}' in tmux session '${sessionName}'`)
2598
+ );
2599
+ } else {
2600
+ console.log(
2601
+ chalk6.green(`
2602
+ Created tmux session '${sessionName}' for worktree '${worktreeName}'`)
2603
+ );
2604
+ console.log(`
2605
+ To attach to this session, run:`);
2606
+ console.log(chalk6.cyan(` tmux attach -t '${sessionName}'`));
2607
+ }
2578
2608
  } catch (error) {
2579
2609
  log.error(`Failed to create tmux session: ${error.message}`);
2580
2610
  process.exit(1);
@@ -3386,7 +3416,7 @@ async function manageWorktrees(projectName, ctx) {
3386
3416
  } else {
3387
3417
  projectPath = configPath.absolutify().path;
3388
3418
  }
3389
- const manager = new WorktreeManager(projectPath);
3419
+ const manager = new WorktreeManager(projectPath, projectName);
3390
3420
  if (!await manager.isGitRepository()) {
3391
3421
  log.error(`'${projectName}' is not a git repository`);
3392
3422
  return;
@@ -3535,7 +3565,7 @@ async function openWorktreeManage(projectName, manager, config, log) {
3535
3565
  }
3536
3566
  };
3537
3567
  const { runWorktreeOpen: runWorktreeOpen2 } = await Promise.resolve().then(() => (init_open(), open_exports));
3538
- await runWorktreeOpen2(projectCtx, worktreeName, {}, { config, log });
3568
+ await runWorktreeOpen2(projectCtx, worktreeName, { attach: false }, { config, log });
3539
3569
  }
3540
3570
  async function removeWorktreeManage(projectName, manager, log) {
3541
3571
  const worktrees = await manager.list();
@@ -3670,7 +3700,7 @@ async function manageWorktreesInteractive(projectCtx, ctx) {
3670
3700
  const { config, log } = ctx;
3671
3701
  const { projectPath, projectName } = projectCtx;
3672
3702
  const displayName = projectName || path7.basename(projectPath);
3673
- const manager = new WorktreeManager(projectPath);
3703
+ const manager = new WorktreeManager(projectPath, projectName ?? void 0);
3674
3704
  if (!await manager.isGitRepository()) {
3675
3705
  log.error(`'${displayName}' is not a git repository`);
3676
3706
  return;