workon 3.4.0 → 3.5.1
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 +87 -43
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +13 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +13 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -269,10 +269,11 @@ var init_project = __esm({
|
|
|
269
269
|
return this._events;
|
|
270
270
|
}
|
|
271
271
|
set path(path8) {
|
|
272
|
-
|
|
272
|
+
const pathFile = File.from(path8);
|
|
273
|
+
if (this._base && !pathFile.isAbsolute()) {
|
|
273
274
|
this._path = this._base.join(path8);
|
|
274
275
|
} else {
|
|
275
|
-
this._path =
|
|
276
|
+
this._path = pathFile;
|
|
276
277
|
}
|
|
277
278
|
this._path = this._path.absolutify();
|
|
278
279
|
}
|
|
@@ -365,17 +366,17 @@ var init_environment = __esm({
|
|
|
365
366
|
return this.projects;
|
|
366
367
|
}
|
|
367
368
|
const defaults = this.config.getDefaults();
|
|
368
|
-
|
|
369
|
-
this.projects = [];
|
|
370
|
-
return this.projects;
|
|
371
|
-
}
|
|
372
|
-
const baseDir = File2.from(defaults.base);
|
|
369
|
+
const baseDir = defaults?.base ? File2.from(defaults.base).absolutify() : null;
|
|
373
370
|
const projectsMap = this.config.getProjects();
|
|
374
|
-
this.projects = Object.entries(projectsMap).map(([name, project]) =>
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
371
|
+
this.projects = Object.entries(projectsMap).map(([name, project]) => {
|
|
372
|
+
const projectPath = File2.from(project.path);
|
|
373
|
+
const resolvedPath = baseDir && !projectPath.isAbsolute() ? baseDir.join(project.path) : projectPath;
|
|
374
|
+
return {
|
|
375
|
+
...project,
|
|
376
|
+
name,
|
|
377
|
+
path: resolvedPath
|
|
378
|
+
};
|
|
379
|
+
});
|
|
379
380
|
return this.projects;
|
|
380
381
|
}
|
|
381
382
|
static getProjectEnvironment(base, _matching) {
|
|
@@ -1443,20 +1444,36 @@ import { exec as execCallback2 } from "child_process";
|
|
|
1443
1444
|
import { promisify as promisify2 } from "util";
|
|
1444
1445
|
import { existsSync as existsSync2, chmodSync } from "fs";
|
|
1445
1446
|
import { join, basename } from "path";
|
|
1447
|
+
import { createHash } from "crypto";
|
|
1448
|
+
import { homedir } from "os";
|
|
1446
1449
|
import { simpleGit as simpleGit2 } from "simple-git";
|
|
1447
|
-
|
|
1450
|
+
function shortHash(input7) {
|
|
1451
|
+
return createHash("sha256").update(input7).digest("hex").substring(0, 8);
|
|
1452
|
+
}
|
|
1453
|
+
function deriveProjectIdentifier(projectPath) {
|
|
1454
|
+
const name = basename(projectPath);
|
|
1455
|
+
const hash = shortHash(projectPath);
|
|
1456
|
+
return `${name}-${hash}`;
|
|
1457
|
+
}
|
|
1458
|
+
function getWorktreesDirForProject(projectIdentifier) {
|
|
1459
|
+
return join(homedir(), WORKON_DIR, WORKTREES_SUBDIR, projectIdentifier);
|
|
1460
|
+
}
|
|
1461
|
+
var exec2, WORKON_DIR, WORKTREES_SUBDIR, HOOK_DIR, SETUP_HOOK, WorktreeManager;
|
|
1448
1462
|
var init_worktree = __esm({
|
|
1449
1463
|
"src/lib/worktree.ts"() {
|
|
1450
1464
|
"use strict";
|
|
1451
1465
|
exec2 = promisify2(execCallback2);
|
|
1452
|
-
|
|
1466
|
+
WORKON_DIR = ".workon";
|
|
1467
|
+
WORKTREES_SUBDIR = "worktrees";
|
|
1453
1468
|
HOOK_DIR = ".workon";
|
|
1454
1469
|
SETUP_HOOK = "worktree-setup.sh";
|
|
1455
1470
|
WorktreeManager = class {
|
|
1456
1471
|
projectPath;
|
|
1472
|
+
projectIdentifier;
|
|
1457
1473
|
git;
|
|
1458
|
-
constructor(projectPath) {
|
|
1474
|
+
constructor(projectPath, _projectName) {
|
|
1459
1475
|
this.projectPath = projectPath;
|
|
1476
|
+
this.projectIdentifier = deriveProjectIdentifier(projectPath);
|
|
1460
1477
|
this.git = simpleGit2(projectPath);
|
|
1461
1478
|
}
|
|
1462
1479
|
/**
|
|
@@ -1472,9 +1489,10 @@ var init_worktree = __esm({
|
|
|
1472
1489
|
}
|
|
1473
1490
|
/**
|
|
1474
1491
|
* Get the worktrees directory path
|
|
1492
|
+
* Stored at ~/.workon/worktrees/{project-identifier}/
|
|
1475
1493
|
*/
|
|
1476
1494
|
getWorktreesDir() {
|
|
1477
|
-
return join(this.
|
|
1495
|
+
return join(homedir(), WORKON_DIR, WORKTREES_SUBDIR, this.projectIdentifier);
|
|
1478
1496
|
}
|
|
1479
1497
|
/**
|
|
1480
1498
|
* Convert branch name to directory name (replace slashes with dashes)
|
|
@@ -1765,7 +1783,8 @@ async function findWorktreeNameByPath(mainRepoPath, worktreePath) {
|
|
|
1765
1783
|
const git = simpleGit3(mainRepoPath);
|
|
1766
1784
|
const result = await git.raw(["worktree", "list", "--porcelain"]);
|
|
1767
1785
|
const blocks = result.trim().split("\n\n");
|
|
1768
|
-
const
|
|
1786
|
+
const projectIdentifier = deriveProjectIdentifier(mainRepoPath);
|
|
1787
|
+
const projectWorktreesDir = getWorktreesDirForProject(projectIdentifier);
|
|
1769
1788
|
for (const block of blocks) {
|
|
1770
1789
|
if (!block.trim()) continue;
|
|
1771
1790
|
const lines = block.split("\n");
|
|
@@ -1781,7 +1800,7 @@ async function findWorktreeNameByPath(mainRepoPath, worktreePath) {
|
|
|
1781
1800
|
}
|
|
1782
1801
|
}
|
|
1783
1802
|
if (wtPath === worktreePath) {
|
|
1784
|
-
if (wtPath.startsWith(
|
|
1803
|
+
if (wtPath.startsWith(projectWorktreesDir)) {
|
|
1785
1804
|
return path.basename(wtPath);
|
|
1786
1805
|
} else {
|
|
1787
1806
|
return branch && branch !== "(detached)" ? branch.replace(/\//g, "-") : path.basename(wtPath);
|
|
@@ -1904,6 +1923,7 @@ async function promptToRegisterProject(projectPath, config, log) {
|
|
|
1904
1923
|
var init_utils = __esm({
|
|
1905
1924
|
"src/commands/worktrees/utils.ts"() {
|
|
1906
1925
|
"use strict";
|
|
1926
|
+
init_worktree();
|
|
1907
1927
|
init_registry();
|
|
1908
1928
|
init_constants();
|
|
1909
1929
|
}
|
|
@@ -1926,7 +1946,7 @@ function createListCommand(ctx) {
|
|
|
1926
1946
|
}
|
|
1927
1947
|
const { projectPath, projectName } = projectCtx;
|
|
1928
1948
|
const displayName = projectName || path2.basename(projectPath);
|
|
1929
|
-
const manager = new WorktreeManager(projectPath);
|
|
1949
|
+
const manager = new WorktreeManager(projectPath, projectName ?? void 0);
|
|
1930
1950
|
const allWorktrees = await manager.list();
|
|
1931
1951
|
const managedWorktrees = await manager.listManagedWorktrees();
|
|
1932
1952
|
const managedPaths = new Set(managedWorktrees.map((wt) => wt.path));
|
|
@@ -1990,7 +2010,7 @@ function createAddCommand(ctx) {
|
|
|
1990
2010
|
}
|
|
1991
2011
|
}
|
|
1992
2012
|
const { projectPath, projectName } = projectCtx;
|
|
1993
|
-
const manager = new WorktreeManager(projectPath);
|
|
2013
|
+
const manager = new WorktreeManager(projectPath, projectName ?? void 0);
|
|
1994
2014
|
const branchExists = await manager.branchExists(branch);
|
|
1995
2015
|
let baseBranch = options.base;
|
|
1996
2016
|
if (!branchExists && !baseBranch) {
|
|
@@ -2099,7 +2119,7 @@ function createRemoveCommand(ctx) {
|
|
|
2099
2119
|
}
|
|
2100
2120
|
const { projectPath, projectName } = projectCtx;
|
|
2101
2121
|
const displayName = projectName || path3.basename(projectPath);
|
|
2102
|
-
const manager = new WorktreeManager(projectPath);
|
|
2122
|
+
const manager = new WorktreeManager(projectPath, projectName ?? void 0);
|
|
2103
2123
|
const worktree = await manager.get(name);
|
|
2104
2124
|
if (!worktree) {
|
|
2105
2125
|
log.error(`Worktree '${name}' not found for '${displayName}'`);
|
|
@@ -2193,7 +2213,7 @@ function createMergeCommand(ctx) {
|
|
|
2193
2213
|
}
|
|
2194
2214
|
const { projectPath, projectName } = projectCtx;
|
|
2195
2215
|
const displayName = projectName || path4.basename(projectPath);
|
|
2196
|
-
const manager = new WorktreeManager(projectPath);
|
|
2216
|
+
const manager = new WorktreeManager(projectPath, projectName ?? void 0);
|
|
2197
2217
|
const worktree = await manager.get(name);
|
|
2198
2218
|
if (!worktree) {
|
|
2199
2219
|
log.error(`Worktree '${name}' not found for '${displayName}'`);
|
|
@@ -2339,7 +2359,7 @@ function createBranchCommand(ctx) {
|
|
|
2339
2359
|
}
|
|
2340
2360
|
const { projectPath, projectName } = projectCtx;
|
|
2341
2361
|
const displayName = projectName || path5.basename(projectPath);
|
|
2342
|
-
const manager = new WorktreeManager(projectPath);
|
|
2362
|
+
const manager = new WorktreeManager(projectPath, projectName ?? void 0);
|
|
2343
2363
|
const worktree = await manager.get(worktreeName);
|
|
2344
2364
|
if (!worktree) {
|
|
2345
2365
|
log.error(`Worktree '${worktreeName}' not found for '${displayName}'`);
|
|
@@ -2527,7 +2547,7 @@ async function runWorktreeOpen(projectCtx, worktreeName, options, ctx) {
|
|
|
2527
2547
|
const { config, log } = ctx;
|
|
2528
2548
|
const { projectPath, projectName, projectConfig, isRegistered } = projectCtx;
|
|
2529
2549
|
const displayName = projectName || path6.basename(projectPath);
|
|
2530
|
-
const manager = new WorktreeManager(projectPath);
|
|
2550
|
+
const manager = new WorktreeManager(projectPath, projectName ?? void 0);
|
|
2531
2551
|
const worktree = await manager.get(worktreeName);
|
|
2532
2552
|
if (!worktree) {
|
|
2533
2553
|
log.error(`Worktree '${worktreeName}' not found for '${displayName}'`);
|
|
@@ -2555,6 +2575,7 @@ async function runWorktreeOpen(projectCtx, worktreeName, options, ctx) {
|
|
|
2555
2575
|
hasClaudeEvent = !!events.claude;
|
|
2556
2576
|
hasNpmEvent = !!events.npm;
|
|
2557
2577
|
}
|
|
2578
|
+
const shouldAttach = options.attach !== false;
|
|
2558
2579
|
if (isShellMode) {
|
|
2559
2580
|
const shellCommands = await buildWorktreeShellCommands(
|
|
2560
2581
|
project,
|
|
@@ -2571,10 +2592,20 @@ async function runWorktreeOpen(projectCtx, worktreeName, options, ctx) {
|
|
|
2571
2592
|
hasClaudeEvent,
|
|
2572
2593
|
hasNpmEvent
|
|
2573
2594
|
});
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2595
|
+
if (shouldAttach) {
|
|
2596
|
+
await tmux.attachToSession(sessionName);
|
|
2597
|
+
console.log(
|
|
2598
|
+
chalk6.green(`Opened worktree '${worktreeName}' in tmux session '${sessionName}'`)
|
|
2599
|
+
);
|
|
2600
|
+
} else {
|
|
2601
|
+
console.log(
|
|
2602
|
+
chalk6.green(`
|
|
2603
|
+
Created tmux session '${sessionName}' for worktree '${worktreeName}'`)
|
|
2604
|
+
);
|
|
2605
|
+
console.log(`
|
|
2606
|
+
To attach to this session, run:`);
|
|
2607
|
+
console.log(chalk6.cyan(` tmux attach -t '${sessionName}'`));
|
|
2608
|
+
}
|
|
2578
2609
|
} catch (error) {
|
|
2579
2610
|
log.error(`Failed to create tmux session: ${error.message}`);
|
|
2580
2611
|
process.exit(1);
|
|
@@ -2874,7 +2905,7 @@ async function initProject(defaultName, fromUser, ctx) {
|
|
|
2874
2905
|
default: defaults?.base ? File5.from(defaults.base).join(name).path : name
|
|
2875
2906
|
});
|
|
2876
2907
|
let answerFile = File5.from(pathAnswer);
|
|
2877
|
-
const defaultBase = defaults?.base ? File5.from(defaults.base) : File5.cwd();
|
|
2908
|
+
const defaultBase = defaults?.base ? File5.from(defaults.base).absolutify() : File5.cwd();
|
|
2878
2909
|
if (!answerFile.isAbsolute()) {
|
|
2879
2910
|
answerFile = defaultBase.join(answerFile.path);
|
|
2880
2911
|
}
|
|
@@ -2888,7 +2919,8 @@ async function initProject(defaultName, fromUser, ctx) {
|
|
|
2888
2919
|
} catch {
|
|
2889
2920
|
answerFile = answerFile.absolutify();
|
|
2890
2921
|
}
|
|
2891
|
-
|
|
2922
|
+
const relPath = answerFile.relativize(defaultBase.path);
|
|
2923
|
+
basePath = relPath && !relPath.path.startsWith("..") ? relPath.path : answerFile.path;
|
|
2892
2924
|
}
|
|
2893
2925
|
const ide = await select4({
|
|
2894
2926
|
message: "What is the IDE?",
|
|
@@ -3081,18 +3113,21 @@ async function createProjectManage(ctx) {
|
|
|
3081
3113
|
return true;
|
|
3082
3114
|
}
|
|
3083
3115
|
});
|
|
3084
|
-
const defaultPath = defaults?.base ? File5.from(defaults.base).join(name).path : name;
|
|
3116
|
+
const defaultPath = defaults?.base ? File5.from(defaults.base).absolutify().join(name).path : name;
|
|
3085
3117
|
const pathInput = await input5({
|
|
3086
3118
|
message: "Project path:",
|
|
3087
3119
|
default: defaultPath
|
|
3088
3120
|
});
|
|
3089
3121
|
let relativePath = pathInput;
|
|
3090
3122
|
if (defaults?.base) {
|
|
3091
|
-
const baseDir = File5.from(defaults.base);
|
|
3123
|
+
const baseDir = File5.from(defaults.base).absolutify();
|
|
3092
3124
|
const pathFile = File5.from(pathInput);
|
|
3093
3125
|
try {
|
|
3094
3126
|
if (pathFile.isAbsolute()) {
|
|
3095
|
-
|
|
3127
|
+
const relPath = pathFile.relativize(baseDir.path);
|
|
3128
|
+
if (relPath && !relPath.path.startsWith("..")) {
|
|
3129
|
+
relativePath = relPath.path;
|
|
3130
|
+
}
|
|
3096
3131
|
}
|
|
3097
3132
|
} catch {
|
|
3098
3133
|
relativePath = pathInput;
|
|
@@ -3153,11 +3188,14 @@ async function editProjectManage(ctx) {
|
|
|
3153
3188
|
});
|
|
3154
3189
|
let relativePath = pathInput;
|
|
3155
3190
|
if (defaults?.base) {
|
|
3156
|
-
const baseDir = File5.from(defaults.base);
|
|
3191
|
+
const baseDir = File5.from(defaults.base).absolutify();
|
|
3157
3192
|
const pathFile = File5.from(pathInput);
|
|
3158
3193
|
try {
|
|
3159
3194
|
if (pathFile.isAbsolute()) {
|
|
3160
|
-
|
|
3195
|
+
const relPath = pathFile.relativize(baseDir.path);
|
|
3196
|
+
if (relPath && !relPath.path.startsWith("..")) {
|
|
3197
|
+
relativePath = relPath.path;
|
|
3198
|
+
}
|
|
3161
3199
|
}
|
|
3162
3200
|
} catch {
|
|
3163
3201
|
relativePath = pathInput;
|
|
@@ -3386,7 +3424,7 @@ async function manageWorktrees(projectName, ctx) {
|
|
|
3386
3424
|
} else {
|
|
3387
3425
|
projectPath = configPath.absolutify().path;
|
|
3388
3426
|
}
|
|
3389
|
-
const manager = new WorktreeManager(projectPath);
|
|
3427
|
+
const manager = new WorktreeManager(projectPath, projectName);
|
|
3390
3428
|
if (!await manager.isGitRepository()) {
|
|
3391
3429
|
log.error(`'${projectName}' is not a git repository`);
|
|
3392
3430
|
return;
|
|
@@ -3535,7 +3573,7 @@ async function openWorktreeManage(projectName, manager, config, log) {
|
|
|
3535
3573
|
}
|
|
3536
3574
|
};
|
|
3537
3575
|
const { runWorktreeOpen: runWorktreeOpen2 } = await Promise.resolve().then(() => (init_open(), open_exports));
|
|
3538
|
-
await runWorktreeOpen2(projectCtx, worktreeName, {}, { config, log });
|
|
3576
|
+
await runWorktreeOpen2(projectCtx, worktreeName, { attach: false }, { config, log });
|
|
3539
3577
|
}
|
|
3540
3578
|
async function removeWorktreeManage(projectName, manager, log) {
|
|
3541
3579
|
const worktrees = await manager.list();
|
|
@@ -3670,7 +3708,7 @@ async function manageWorktreesInteractive(projectCtx, ctx) {
|
|
|
3670
3708
|
const { config, log } = ctx;
|
|
3671
3709
|
const { projectPath, projectName } = projectCtx;
|
|
3672
3710
|
const displayName = projectName || path7.basename(projectPath);
|
|
3673
|
-
const manager = new WorktreeManager(projectPath);
|
|
3711
|
+
const manager = new WorktreeManager(projectPath, projectName ?? void 0);
|
|
3674
3712
|
if (!await manager.isGitRepository()) {
|
|
3675
3713
|
log.error(`'${displayName}' is not a git repository`);
|
|
3676
3714
|
return;
|
|
@@ -4247,10 +4285,13 @@ async function createProject(ctx) {
|
|
|
4247
4285
|
});
|
|
4248
4286
|
let relativePath = pathInput;
|
|
4249
4287
|
if (defaults?.base) {
|
|
4250
|
-
const baseDir = File7.from(defaults.base);
|
|
4288
|
+
const baseDir = File7.from(defaults.base).absolutify();
|
|
4251
4289
|
const pathFile = File7.from(pathInput);
|
|
4252
4290
|
try {
|
|
4253
|
-
|
|
4291
|
+
const relPath = pathFile.relativize(baseDir.path);
|
|
4292
|
+
if (relPath && !relPath.path.startsWith("..")) {
|
|
4293
|
+
relativePath = relPath.path;
|
|
4294
|
+
}
|
|
4254
4295
|
} catch {
|
|
4255
4296
|
relativePath = pathInput;
|
|
4256
4297
|
}
|
|
@@ -4322,11 +4363,14 @@ async function editProject(ctx) {
|
|
|
4322
4363
|
});
|
|
4323
4364
|
let relativePath = pathInput;
|
|
4324
4365
|
if (defaults?.base) {
|
|
4325
|
-
const baseDir = File7.from(defaults.base);
|
|
4366
|
+
const baseDir = File7.from(defaults.base).absolutify();
|
|
4326
4367
|
const pathFile = File7.from(pathInput);
|
|
4327
4368
|
try {
|
|
4328
4369
|
if (pathFile.isAbsolute()) {
|
|
4329
|
-
|
|
4370
|
+
const relPath = pathFile.relativize(baseDir.path);
|
|
4371
|
+
if (relPath && !relPath.path.startsWith("..")) {
|
|
4372
|
+
relativePath = relPath.path;
|
|
4373
|
+
}
|
|
4330
4374
|
}
|
|
4331
4375
|
} catch {
|
|
4332
4376
|
relativePath = pathInput;
|
|
@@ -4494,7 +4538,7 @@ async function addProject(pathArg, options, ctx) {
|
|
|
4494
4538
|
log.debug(`IDE: ${ide}`);
|
|
4495
4539
|
let relativePath = targetPath;
|
|
4496
4540
|
if (defaults?.base) {
|
|
4497
|
-
const baseDir = File8.from(defaults.base);
|
|
4541
|
+
const baseDir = File8.from(defaults.base).absolutify();
|
|
4498
4542
|
try {
|
|
4499
4543
|
const relPath = pathFile.relativize(baseDir.path);
|
|
4500
4544
|
if (relPath && !relPath.path.startsWith("..")) {
|