workon 3.5.2 → 3.6.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
@@ -1458,7 +1458,7 @@ function deriveProjectIdentifier(projectPath) {
1458
1458
  function getWorktreesDirForProject(projectIdentifier) {
1459
1459
  return join(homedir(), WORKON_DIR, WORKTREES_SUBDIR, projectIdentifier);
1460
1460
  }
1461
- var exec2, WORKON_DIR, WORKTREES_SUBDIR, HOOK_DIR, SETUP_HOOK, WorktreeManager;
1461
+ var exec2, WORKON_DIR, WORKTREES_SUBDIR, HOOK_DIR, SETUP_HOOK, TEARDOWN_HOOK, WorktreeManager;
1462
1462
  var init_worktree = __esm({
1463
1463
  "src/lib/worktree.ts"() {
1464
1464
  "use strict";
@@ -1467,6 +1467,7 @@ var init_worktree = __esm({
1467
1467
  WORKTREES_SUBDIR = "worktrees";
1468
1468
  HOOK_DIR = ".workon";
1469
1469
  SETUP_HOOK = "worktree-setup.sh";
1470
+ TEARDOWN_HOOK = "worktree-teardown.sh";
1470
1471
  WorktreeManager = class {
1471
1472
  projectPath;
1472
1473
  projectIdentifier;
@@ -1684,6 +1685,42 @@ var init_worktree = __esm({
1684
1685
  });
1685
1686
  return { stdout, stderr };
1686
1687
  }
1688
+ /**
1689
+ * Check if a pre-teardown hook exists
1690
+ */
1691
+ hasTeardownHook() {
1692
+ const hookPath = this.getTeardownHookPath();
1693
+ return existsSync2(hookPath);
1694
+ }
1695
+ /**
1696
+ * Get the path to the teardown hook
1697
+ */
1698
+ getTeardownHookPath() {
1699
+ return join(this.projectPath, HOOK_DIR, TEARDOWN_HOOK);
1700
+ }
1701
+ /**
1702
+ * Run the pre-teardown hook for a worktree
1703
+ */
1704
+ async runPreTeardownHook(worktreePath) {
1705
+ const hookPath = this.getTeardownHookPath();
1706
+ if (!existsSync2(hookPath)) {
1707
+ throw new Error("Teardown hook not found");
1708
+ }
1709
+ try {
1710
+ chmodSync(hookPath, "755");
1711
+ } catch {
1712
+ }
1713
+ const env = {
1714
+ ...process.env,
1715
+ WORKTREE_PATH: worktreePath,
1716
+ PROJECT_PATH: this.projectPath
1717
+ };
1718
+ const { stdout, stderr } = await exec2(hookPath, {
1719
+ cwd: worktreePath,
1720
+ env
1721
+ });
1722
+ return { stdout, stderr };
1723
+ }
1687
1724
  /**
1688
1725
  * Parse the porcelain output of git worktree list
1689
1726
  */
@@ -2115,7 +2152,7 @@ import { existsSync as existsSync4 } from "fs";
2115
2152
  import { confirm as confirm5 } from "@inquirer/prompts";
2116
2153
  function createRemoveCommand(ctx) {
2117
2154
  const { config, log } = ctx;
2118
- return new Command3("remove").description("Remove a worktree").argument("<name>", "Worktree name").option("-f, --force", "Force removal even with uncommitted changes").option("-y, --yes", "Skip confirmation prompt").action(async (name, options) => {
2155
+ return new Command3("remove").description("Remove a worktree").argument("<name>", "Worktree name").option("-f, --force", "Force removal even with uncommitted changes").option("-y, --yes", "Skip confirmation prompt").option("--no-hook", "Skip running the pre-teardown hook").action(async (name, options) => {
2119
2156
  const projectCtx = await resolveProjectFromCwd(config, log);
2120
2157
  if (!projectCtx) {
2121
2158
  log.error("Not in a git repository. Run this command from within a git project.");
@@ -2188,6 +2225,21 @@ ${chalk3.bold("Worktree to remove:")}`);
2188
2225
  log.debug(`Killing tmux session: ${sessionName}`);
2189
2226
  await tmux.killSession(sessionName);
2190
2227
  }
2228
+ if (options.hook !== false && !pathMissing && manager.hasTeardownHook()) {
2229
+ const hookSpinner = ora2("Running pre-teardown hook...").start();
2230
+ try {
2231
+ const { stdout, stderr } = await manager.runPreTeardownHook(worktree.path);
2232
+ hookSpinner.succeed("Pre-teardown hook completed");
2233
+ if (stdout.trim()) {
2234
+ console.log(chalk3.gray(stdout.trim()));
2235
+ }
2236
+ if (stderr.trim()) {
2237
+ console.log(chalk3.yellow(stderr.trim()));
2238
+ }
2239
+ } catch (error) {
2240
+ hookSpinner.warn(`Pre-teardown hook failed: ${error.message}`);
2241
+ }
2242
+ }
2191
2243
  const spinner = ora2(`Removing worktree '${name}'...`).start();
2192
2244
  try {
2193
2245
  await manager.remove(name, options.force);
@@ -2802,6 +2854,7 @@ __export(interactive_exports, {
2802
2854
  runInteractive: () => runInteractive
2803
2855
  });
2804
2856
  import { select as select4, input as input5, checkbox as checkbox2, confirm as confirm8 } from "@inquirer/prompts";
2857
+ import { existsSync as existsSync5 } from "fs";
2805
2858
  import File5 from "phylo";
2806
2859
  import path7 from "path";
2807
2860
  import deepAssign2 from "deep-assign";
@@ -3621,6 +3674,18 @@ async function removeWorktreeManage(projectName, manager, log) {
3621
3674
  });
3622
3675
  if (confirmed) {
3623
3676
  try {
3677
+ if (manager.hasTeardownHook()) {
3678
+ const worktree = await manager.get(worktreeName);
3679
+ if (worktree && existsSync5(worktree.path)) {
3680
+ log.info("Running pre-teardown hook...");
3681
+ try {
3682
+ await manager.runPreTeardownHook(worktree.path);
3683
+ log.info("Pre-teardown hook completed.");
3684
+ } catch (error) {
3685
+ log.warn(`Pre-teardown hook failed: ${error.message}`);
3686
+ }
3687
+ }
3688
+ }
3624
3689
  await manager.remove(worktreeName, true);
3625
3690
  log.info(`Worktree '${worktreeName}' removed.`);
3626
3691
  } catch (error) {
@@ -3670,6 +3735,15 @@ async function mergeWorktreeManage(projectName, manager, log) {
3670
3735
  await manager.merge(worktreeName, { targetBranch, squash });
3671
3736
  log.info(`Merged '${worktree.branch}' into '${targetBranch}'`);
3672
3737
  if (removeAfter) {
3738
+ if (manager.hasTeardownHook() && existsSync5(worktree.path)) {
3739
+ log.info("Running pre-teardown hook...");
3740
+ try {
3741
+ await manager.runPreTeardownHook(worktree.path);
3742
+ log.info("Pre-teardown hook completed.");
3743
+ } catch (error) {
3744
+ log.warn(`Pre-teardown hook failed: ${error.message}`);
3745
+ }
3746
+ }
3673
3747
  await manager.remove(worktreeName, true);
3674
3748
  log.info(`Worktree '${worktreeName}' removed.`);
3675
3749
  }
@@ -4119,7 +4193,7 @@ init_environment();
4119
4193
  init_registry();
4120
4194
  init_open2();
4121
4195
  import { Command as Command16 } from "commander";
4122
- import { readFileSync as readFileSync2, existsSync as existsSync6 } from "fs";
4196
+ import { readFileSync as readFileSync2, existsSync as existsSync7 } from "fs";
4123
4197
  import { join as join2, dirname as dirname2 } from "path";
4124
4198
  import { fileURLToPath } from "url";
4125
4199
  import loog from "loog";
@@ -4492,7 +4566,7 @@ async function listProjects(ctx) {
4492
4566
 
4493
4567
  // src/commands/add.ts
4494
4568
  import { Command as Command14 } from "commander";
4495
- import { existsSync as existsSync5, readFileSync } from "fs";
4569
+ import { existsSync as existsSync6, readFileSync } from "fs";
4496
4570
  import { basename as basename2, resolve } from "path";
4497
4571
  import File8 from "phylo";
4498
4572
  import { confirm as confirm10 } from "@inquirer/prompts";
@@ -4514,7 +4588,7 @@ async function addProject(pathArg, options, ctx) {
4514
4588
  const projects = config.getProjects();
4515
4589
  const targetPath = resolve(pathArg);
4516
4590
  log.debug(`Resolved path: ${targetPath}`);
4517
- if (!existsSync5(targetPath)) {
4591
+ if (!existsSync6(targetPath)) {
4518
4592
  log.error(`Path does not exist: ${targetPath}`);
4519
4593
  process.exit(1);
4520
4594
  }
@@ -4598,7 +4672,7 @@ function discoverProject(targetPath, log) {
4598
4672
  packageJson: null
4599
4673
  };
4600
4674
  const packageJsonPath = resolve(targetPath, "package.json");
4601
- if (existsSync5(packageJsonPath)) {
4675
+ if (existsSync6(packageJsonPath)) {
4602
4676
  discovery.isNode = true;
4603
4677
  log.debug("Detected Node project (package.json found)");
4604
4678
  try {
@@ -4614,25 +4688,25 @@ function discoverProject(targetPath, log) {
4614
4688
  }
4615
4689
  }
4616
4690
  const bunLockPath = resolve(targetPath, "bun.lockb");
4617
- if (existsSync5(bunLockPath)) {
4691
+ if (existsSync6(bunLockPath)) {
4618
4692
  discovery.isBun = true;
4619
4693
  log.debug("Detected Bun project (bun.lockb found)");
4620
4694
  }
4621
4695
  const vscodeDir = resolve(targetPath, ".vscode");
4622
4696
  const cursorDir = resolve(targetPath, ".cursor");
4623
4697
  const ideaDir = resolve(targetPath, ".idea");
4624
- if (existsSync5(cursorDir)) {
4698
+ if (existsSync6(cursorDir)) {
4625
4699
  discovery.detectedIde = "cursor";
4626
4700
  log.debug("Detected Cursor (.cursor directory found)");
4627
- } else if (existsSync5(vscodeDir)) {
4701
+ } else if (existsSync6(vscodeDir)) {
4628
4702
  discovery.detectedIde = "code";
4629
4703
  log.debug("Detected VS Code (.vscode directory found)");
4630
- } else if (existsSync5(ideaDir)) {
4704
+ } else if (existsSync6(ideaDir)) {
4631
4705
  discovery.detectedIde = "idea";
4632
4706
  log.debug("Detected IntelliJ IDEA (.idea directory found)");
4633
4707
  }
4634
4708
  const claudeMdPath = resolve(targetPath, "CLAUDE.md");
4635
- if (existsSync5(claudeMdPath)) {
4709
+ if (existsSync6(claudeMdPath)) {
4636
4710
  discovery.hasClaude = true;
4637
4711
  log.debug("Detected Claude Code project (CLAUDE.md found)");
4638
4712
  }
@@ -4928,7 +5002,7 @@ function findPackageJson() {
4928
5002
  join2(process.cwd(), "package.json")
4929
5003
  ];
4930
5004
  for (const p of paths) {
4931
- if (existsSync6(p)) {
5005
+ if (existsSync7(p)) {
4932
5006
  return p;
4933
5007
  }
4934
5008
  }