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 +86 -12
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
|
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 (!
|
|
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 (
|
|
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 (
|
|
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 (
|
|
4698
|
+
if (existsSync6(cursorDir)) {
|
|
4625
4699
|
discovery.detectedIde = "cursor";
|
|
4626
4700
|
log.debug("Detected Cursor (.cursor directory found)");
|
|
4627
|
-
} else if (
|
|
4701
|
+
} else if (existsSync6(vscodeDir)) {
|
|
4628
4702
|
discovery.detectedIde = "code";
|
|
4629
4703
|
log.debug("Detected VS Code (.vscode directory found)");
|
|
4630
|
-
} else if (
|
|
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 (
|
|
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 (
|
|
5005
|
+
if (existsSync7(p)) {
|
|
4932
5006
|
return p;
|
|
4933
5007
|
}
|
|
4934
5008
|
}
|