workshell 0.2.0 → 0.4.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/README.md +47 -5
- package/dist/index.js +151 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -68,6 +68,7 @@ This approach has some nice properties.
|
|
|
68
68
|
|
|
69
69
|
- 🖥️ **Tab-local workspaces** — Normally a `git checkout`/`git switch` changes your active branch for all terminals. With workshells, you can functionality open branches *in the current tab only*.
|
|
70
70
|
- 🌳 **Full isolation** — Each workshell is isolated on disk, so the changes you make don't interfere anything else you're doing.
|
|
71
|
+
- 📦 **Instant setup** — Untracked files (`.env.*`, etc) are automatically copied using [copy-on-write](https://notes.billmill.org/blog/2024/03/How_I_use_git_worktrees.html). For JS projects, the package manager is auto-detected and `npm/yarn/pnpm/bun install` runs automatically.
|
|
71
72
|
- 🙅♂️ **Never stash again** — You can `wk open` a branch even with uncommitted changes. When you exit the subshell, things will be exactly the same as they were. ☕️
|
|
72
73
|
- **Consistent with branch semantics** — As with regular `git switch`, `wk close` won't let you close the subshell if you have unstaged/uncommitted changes. This is a feature, not a bug! Regular worktrees make it easy to lose your work in a forgotten corner of your file system.
|
|
73
74
|
- 🤖 **Agent-ready** — Spin up parallel workshells so multiple agents can work simultaneously without conflicts.
|
|
@@ -310,9 +311,48 @@ Choice (1/2): 1
|
|
|
310
311
|
|
|
311
312
|
<br />
|
|
312
313
|
|
|
314
|
+
## Automatic file copying
|
|
315
|
+
|
|
316
|
+
When you create a workshell, `wk` automatically copies all gitignored files from your repo root to the new worktree using **copy-on-write**. This means:
|
|
317
|
+
|
|
318
|
+
- `.env`, `.venv`, etc. are instantly available
|
|
319
|
+
- Copy-on-write is near-instant and uses zero extra disk space (until files are modified)
|
|
320
|
+
|
|
321
|
+
This works automatically on macOS (APFS) and Linux (Btrfs/XFS). On other filesystems, files are copied normally.
|
|
322
|
+
|
|
323
|
+
### JS package manager detection
|
|
324
|
+
|
|
325
|
+
For JavaScript projects, `wk` auto-detects your package manager from lockfiles:
|
|
326
|
+
|
|
327
|
+
| Lockfile | Package Manager |
|
|
328
|
+
|----------|-----------------|
|
|
329
|
+
| `pnpm-lock.yaml` | pnpm |
|
|
330
|
+
| `yarn.lock` | yarn |
|
|
331
|
+
| `bun.lockb` / `bun.lock` | bun |
|
|
332
|
+
| `package-lock.json` | npm |
|
|
333
|
+
|
|
334
|
+
When detected, `node_modules` is skipped during copying and `<pm> install` runs automatically. This is faster than copying large `node_modules` directories.
|
|
335
|
+
|
|
336
|
+
### Python package manager detection
|
|
337
|
+
|
|
338
|
+
For Python projects, `wk` auto-detects your package manager from lockfiles:
|
|
339
|
+
|
|
340
|
+
| Lockfile | Package Manager | Install Command |
|
|
341
|
+
|----------|-----------------|-----------------|
|
|
342
|
+
| `uv.lock` | uv | `uv sync` |
|
|
343
|
+
| `poetry.lock` | poetry | `poetry install` |
|
|
344
|
+
| `Pipfile.lock` | pipenv | `pipenv install` |
|
|
345
|
+
| `pdm.lock` | pdm | `pdm install` |
|
|
346
|
+
|
|
347
|
+
When detected, `.venv` and `venv` are skipped during copying and the install command runs automatically. Mixed JS+Python projects are supported: both ecosystems are detected and their installs run in sequence.
|
|
348
|
+
|
|
349
|
+
To disable auto-detection, add a custom `setup` script in `workshell.toml`.
|
|
350
|
+
|
|
351
|
+
<br />
|
|
352
|
+
|
|
313
353
|
## `workshell.toml`
|
|
314
354
|
|
|
315
|
-
You can configure `wk` with a `workshell.toml` file.
|
|
355
|
+
You can optionally configure `wk` with a `workshell.toml` file.
|
|
316
356
|
|
|
317
357
|
`wk` looks for config files in the following order:
|
|
318
358
|
|
|
@@ -323,13 +363,15 @@ You can configure `wk` with a `workshell.toml` file. This is useful for running
|
|
|
323
363
|
|
|
324
364
|
<br />
|
|
325
365
|
|
|
326
|
-
|
|
366
|
+
### Options
|
|
327
367
|
|
|
328
368
|
```toml
|
|
329
|
-
# setup script executed in subshell after initialization
|
|
330
|
-
#
|
|
369
|
+
# Optional: setup script executed in subshell after initialization
|
|
370
|
+
# Variable substitutions:
|
|
331
371
|
# `{{ branch }}` — The name of the opened branch, e.g. `feature/auth`
|
|
332
372
|
# `{{ repo_path }}` — The absolute path to main repo, e.g. `/path/to/repo`
|
|
333
373
|
# `{{ worktree_path }}` — The absolute path to worktree, e.g. `~/.workshell/worktrees/.../repo@feat`
|
|
334
|
-
setup = "
|
|
374
|
+
setup = "nvm use"
|
|
335
375
|
```
|
|
376
|
+
|
|
377
|
+
Note: Setting `setup` disables automatic package manager detection. If you want both, include the install command in your setup script.
|
package/dist/index.js
CHANGED
|
@@ -5783,6 +5783,7 @@ var require_src = __commonJS({
|
|
|
5783
5783
|
|
|
5784
5784
|
// index.ts
|
|
5785
5785
|
var import_picocolors4 = __toESM(require_picocolors(), 1);
|
|
5786
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
5786
5787
|
|
|
5787
5788
|
// commands/new.ts
|
|
5788
5789
|
import { basename as basename3, dirname as dirname3, join as join3 } from "path";
|
|
@@ -6604,7 +6605,7 @@ function loadConfig() {
|
|
|
6604
6605
|
|
|
6605
6606
|
// utils.ts
|
|
6606
6607
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
6607
|
-
import { execSync as execSync2, spawnSync } from "child_process";
|
|
6608
|
+
import { execSync as execSync2, execFileSync, spawnSync } from "child_process";
|
|
6608
6609
|
import { existsSync as existsSync2, readSync, openSync, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, rmSync, lstatSync, readdirSync, readlinkSync } from "fs";
|
|
6609
6610
|
import { basename as basename2, dirname as dirname2, join as join2 } from "path";
|
|
6610
6611
|
import { tmpdir } from "os";
|
|
@@ -6749,6 +6750,9 @@ function isInsideWorktree() {
|
|
|
6749
6750
|
return false;
|
|
6750
6751
|
}
|
|
6751
6752
|
}
|
|
6753
|
+
function isInsideWorkshell() {
|
|
6754
|
+
return process.env.WK_WORKSHELL === "1";
|
|
6755
|
+
}
|
|
6752
6756
|
function hasUncommittedChanges() {
|
|
6753
6757
|
try {
|
|
6754
6758
|
const status = execSync2("git status --porcelain", { encoding: "utf-8" }).trim();
|
|
@@ -6942,13 +6946,14 @@ end
|
|
|
6942
6946
|
# wk setup script
|
|
6943
6947
|
${setupCommand}
|
|
6944
6948
|
` : "";
|
|
6949
|
+
const workshellEnv = { ...process.env, WK_WORKSHELL: "1" };
|
|
6945
6950
|
if (shell.endsWith("zsh")) {
|
|
6946
6951
|
const tmpDir = join2(tmpdir(), `wk-${process.pid}`);
|
|
6947
6952
|
mkdirSync2(tmpDir, { recursive: true });
|
|
6948
6953
|
try {
|
|
6949
6954
|
writeFileSync2(join2(tmpDir, ".zshrc"), `[[ -f "$HOME/.zshrc" ]] && source "$HOME/.zshrc"
|
|
6950
6955
|
${zshScript}${setupSection}`);
|
|
6951
|
-
spawnSync(shell, ["-l"], { cwd, stdio: "inherit", env: { ...
|
|
6956
|
+
spawnSync(shell, ["-l"], { cwd, stdio: "inherit", env: { ...workshellEnv, ZDOTDIR: tmpDir } });
|
|
6952
6957
|
} finally {
|
|
6953
6958
|
rmSync(tmpDir, { recursive: true, force: true });
|
|
6954
6959
|
}
|
|
@@ -6959,7 +6964,7 @@ ${zshScript}${setupSection}`);
|
|
|
6959
6964
|
const rcFile = join2(tmpDir, ".bashrc");
|
|
6960
6965
|
writeFileSync2(rcFile, `[[ -f "$HOME/.bashrc" ]] && source "$HOME/.bashrc"
|
|
6961
6966
|
${bashScript}${setupSection}`);
|
|
6962
|
-
spawnSync(shell, ["--rcfile", rcFile, "-il"], { cwd, stdio: "inherit" });
|
|
6967
|
+
spawnSync(shell, ["--rcfile", rcFile, "-il"], { cwd, stdio: "inherit", env: workshellEnv });
|
|
6963
6968
|
} finally {
|
|
6964
6969
|
rmSync(tmpDir, { recursive: true, force: true });
|
|
6965
6970
|
}
|
|
@@ -6967,7 +6972,7 @@ ${bashScript}${setupSection}`);
|
|
|
6967
6972
|
const fishInit = setupCommand ? `${fishScript}
|
|
6968
6973
|
# wk setup script
|
|
6969
6974
|
${setupCommand}` : fishScript;
|
|
6970
|
-
spawnSync(shell, ["--init-command", fishInit], { cwd, stdio: "inherit" });
|
|
6975
|
+
spawnSync(shell, ["--init-command", fishInit], { cwd, stdio: "inherit", env: workshellEnv });
|
|
6971
6976
|
} else {
|
|
6972
6977
|
console.error(`Error: Unsupported shell '${shell}'`);
|
|
6973
6978
|
console.error("wk requires bash, zsh, or fish.");
|
|
@@ -6976,6 +6981,47 @@ ${setupCommand}` : fishScript;
|
|
|
6976
6981
|
}
|
|
6977
6982
|
var success = (text) => import_picocolors.default.green(import_picocolors.default.bold("\u2713")) + " " + text;
|
|
6978
6983
|
var warn = (text) => import_picocolors.default.yellow(import_picocolors.default.bold("\u26A0")) + " " + text;
|
|
6984
|
+
function hasBinary(name) {
|
|
6985
|
+
try {
|
|
6986
|
+
execSync2(`command -v ${name}`, { stdio: "ignore" });
|
|
6987
|
+
return true;
|
|
6988
|
+
} catch {
|
|
6989
|
+
return false;
|
|
6990
|
+
}
|
|
6991
|
+
}
|
|
6992
|
+
function detectJsPackageManager(cwd) {
|
|
6993
|
+
if (existsSync2(join2(cwd, "pnpm-lock.yaml")) && hasBinary("pnpm")) return "pnpm";
|
|
6994
|
+
if (existsSync2(join2(cwd, "yarn.lock")) && hasBinary("yarn")) return "yarn";
|
|
6995
|
+
if ((existsSync2(join2(cwd, "bun.lockb")) || existsSync2(join2(cwd, "bun.lock"))) && hasBinary("bun")) return "bun";
|
|
6996
|
+
if (existsSync2(join2(cwd, "package-lock.json")) && hasBinary("npm")) return "npm";
|
|
6997
|
+
return null;
|
|
6998
|
+
}
|
|
6999
|
+
function detectPythonPackageManager(cwd) {
|
|
7000
|
+
if (existsSync2(join2(cwd, "uv.lock")) && hasBinary("uv")) return "uv";
|
|
7001
|
+
if (existsSync2(join2(cwd, "poetry.lock")) && hasBinary("poetry")) return "poetry";
|
|
7002
|
+
if (existsSync2(join2(cwd, "Pipfile.lock")) && hasBinary("pipenv")) return "pipenv";
|
|
7003
|
+
if (existsSync2(join2(cwd, "pdm.lock")) && hasBinary("pdm")) return "pdm";
|
|
7004
|
+
return null;
|
|
7005
|
+
}
|
|
7006
|
+
var installCmds = {
|
|
7007
|
+
npm: "npm install",
|
|
7008
|
+
yarn: "yarn install",
|
|
7009
|
+
pnpm: "pnpm install",
|
|
7010
|
+
bun: "bun install",
|
|
7011
|
+
uv: "uv sync",
|
|
7012
|
+
poetry: "poetry install",
|
|
7013
|
+
pipenv: "pipenv install",
|
|
7014
|
+
pdm: "pdm install"
|
|
7015
|
+
};
|
|
7016
|
+
function runPackageManagerInstall(pm, cwd) {
|
|
7017
|
+
const cmd2 = installCmds[pm];
|
|
7018
|
+
console.log(dim(`Running ${cmd2}...`));
|
|
7019
|
+
try {
|
|
7020
|
+
execSync2(cmd2, { cwd, stdio: "inherit" });
|
|
7021
|
+
} catch {
|
|
7022
|
+
console.error(warn(`${cmd2} failed \u2014 you may need to run it manually`));
|
|
7023
|
+
}
|
|
7024
|
+
}
|
|
6979
7025
|
var fail = (text) => import_picocolors.default.red(import_picocolors.default.bold("\u2717")) + " " + text;
|
|
6980
7026
|
var dim = (text) => import_picocolors.default.dim(text);
|
|
6981
7027
|
var bold = (text) => import_picocolors.default.bold(text);
|
|
@@ -6983,6 +7029,71 @@ var green = (text) => import_picocolors.default.green(text);
|
|
|
6983
7029
|
var cyan = (text) => import_picocolors.default.cyan(text);
|
|
6984
7030
|
var yellow = (text) => import_picocolors.default.yellow(text);
|
|
6985
7031
|
var red = (text) => import_picocolors.default.red(text);
|
|
7032
|
+
function cpCow(src, dest) {
|
|
7033
|
+
try {
|
|
7034
|
+
if (process.platform === "darwin") {
|
|
7035
|
+
execFileSync("cp", ["-RPc", src, dest], { stdio: "ignore" });
|
|
7036
|
+
} else if (process.platform === "linux") {
|
|
7037
|
+
execFileSync("cp", ["-RP", "--reflink=auto", src, dest], { stdio: "ignore" });
|
|
7038
|
+
} else {
|
|
7039
|
+
execFileSync("cp", ["-RP", src, dest], { stdio: "ignore" });
|
|
7040
|
+
}
|
|
7041
|
+
} catch (err) {
|
|
7042
|
+
if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") {
|
|
7043
|
+
return;
|
|
7044
|
+
}
|
|
7045
|
+
if (process.platform === "darwin") {
|
|
7046
|
+
try {
|
|
7047
|
+
execFileSync("cp", ["-RP", src, dest], { stdio: "ignore" });
|
|
7048
|
+
return;
|
|
7049
|
+
} catch {
|
|
7050
|
+
}
|
|
7051
|
+
}
|
|
7052
|
+
console.error(warn(`Failed to copy ${src}: ${err instanceof Error ? err.message : String(err)}`));
|
|
7053
|
+
}
|
|
7054
|
+
}
|
|
7055
|
+
function getIgnoredPaths(repoPath) {
|
|
7056
|
+
try {
|
|
7057
|
+
const output = execFileSync(
|
|
7058
|
+
"git",
|
|
7059
|
+
["ls-files", "--others", "--ignored", "--exclude-standard", "--directory"],
|
|
7060
|
+
{ cwd: repoPath, encoding: "utf-8" }
|
|
7061
|
+
);
|
|
7062
|
+
const paths = output.split("\n").map((p) => p.replace(/\/$/, "")).filter((p) => p.length > 0 && p !== ".git").sort();
|
|
7063
|
+
const minimal = [];
|
|
7064
|
+
let prev = "";
|
|
7065
|
+
for (const path of paths) {
|
|
7066
|
+
if (prev && path.startsWith(prev + "/")) continue;
|
|
7067
|
+
minimal.push(path);
|
|
7068
|
+
prev = path;
|
|
7069
|
+
}
|
|
7070
|
+
return minimal;
|
|
7071
|
+
} catch {
|
|
7072
|
+
return [];
|
|
7073
|
+
}
|
|
7074
|
+
}
|
|
7075
|
+
var JUNK_FILES = /* @__PURE__ */ new Set([".DS_Store", "Thumbs.db", "desktop.ini"]);
|
|
7076
|
+
function isJunkFile(item) {
|
|
7077
|
+
const base = item.includes("/") ? item.slice(item.lastIndexOf("/") + 1) : item;
|
|
7078
|
+
return JUNK_FILES.has(base);
|
|
7079
|
+
}
|
|
7080
|
+
function copyIgnoredFiles(repoPath, worktreePath, skipDirs) {
|
|
7081
|
+
let items = getIgnoredPaths(repoPath);
|
|
7082
|
+
items = items.filter((item) => !isJunkFile(item));
|
|
7083
|
+
if (skipDirs && skipDirs.length > 0) {
|
|
7084
|
+
items = items.filter(
|
|
7085
|
+
(item) => !skipDirs.some((dir) => item.split("/").includes(dir))
|
|
7086
|
+
);
|
|
7087
|
+
}
|
|
7088
|
+
if (items.length === 0) return;
|
|
7089
|
+
console.log(dim(`Copying untracked files:`));
|
|
7090
|
+
for (const item of items) {
|
|
7091
|
+
console.log(dim(` ${item}`));
|
|
7092
|
+
const dest = join2(worktreePath, item);
|
|
7093
|
+
mkdirSync2(dirname2(dest), { recursive: true });
|
|
7094
|
+
cpCow(join2(repoPath, item), dest);
|
|
7095
|
+
}
|
|
7096
|
+
}
|
|
6986
7097
|
function autoCleanupWorktree(worktreeId, path, store, saveStore2) {
|
|
6987
7098
|
const branch = getWorktreeBranch(path);
|
|
6988
7099
|
const status = getWorktreeStatus(path);
|
|
@@ -7075,6 +7186,15 @@ function newCommand(branchName, fromBranch) {
|
|
|
7075
7186
|
mkdirSync3(dirname3(worktreePath), { recursive: true });
|
|
7076
7187
|
createWorktree(branch, worktreePath, fromBranch);
|
|
7077
7188
|
initSubmodules(worktreePath);
|
|
7189
|
+
const config = loadConfig();
|
|
7190
|
+
const jsPm = config?.setup ? null : detectJsPackageManager(mainWorktree);
|
|
7191
|
+
const pyPm = config?.setup ? null : detectPythonPackageManager(mainWorktree);
|
|
7192
|
+
const skipDirs = [];
|
|
7193
|
+
if (jsPm) skipDirs.push("node_modules");
|
|
7194
|
+
if (pyPm) skipDirs.push(".venv", "venv");
|
|
7195
|
+
copyIgnoredFiles(mainWorktree, worktreePath, skipDirs);
|
|
7196
|
+
if (jsPm) runPackageManagerInstall(jsPm, worktreePath);
|
|
7197
|
+
if (pyPm) runPackageManagerInstall(pyPm, worktreePath);
|
|
7078
7198
|
setWorktreeMeta(store, worktreeId, {
|
|
7079
7199
|
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
7080
7200
|
});
|
|
@@ -7185,6 +7305,15 @@ function openBranch(branch, prNumber) {
|
|
|
7185
7305
|
mkdirSync4(dirname4(worktreePath), { recursive: true });
|
|
7186
7306
|
createWorktreeForExistingBranch(branch, worktreePath);
|
|
7187
7307
|
initSubmodules(worktreePath);
|
|
7308
|
+
const config = loadConfig();
|
|
7309
|
+
const jsPm = config?.setup ? null : detectJsPackageManager(mainWorktree);
|
|
7310
|
+
const pyPm = config?.setup ? null : detectPythonPackageManager(mainWorktree);
|
|
7311
|
+
const skipDirs = [];
|
|
7312
|
+
if (jsPm) skipDirs.push("node_modules");
|
|
7313
|
+
if (pyPm) skipDirs.push(".venv", "venv");
|
|
7314
|
+
copyIgnoredFiles(mainWorktree, worktreePath, skipDirs);
|
|
7315
|
+
if (jsPm) runPackageManagerInstall(jsPm, worktreePath);
|
|
7316
|
+
if (pyPm) runPackageManagerInstall(pyPm, worktreePath);
|
|
7188
7317
|
setWorktreeMeta(store, worktreeId, {
|
|
7189
7318
|
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
7190
7319
|
});
|
|
@@ -7211,10 +7340,10 @@ function openBranch(branch, prNumber) {
|
|
|
7211
7340
|
console.log();
|
|
7212
7341
|
}
|
|
7213
7342
|
function openCommand(ref) {
|
|
7214
|
-
if (
|
|
7343
|
+
if (isInsideWorkshell()) {
|
|
7215
7344
|
const currentBranch = getCurrentBranch();
|
|
7216
7345
|
console.log();
|
|
7217
|
-
console.log(warn(`You're inside a
|
|
7346
|
+
console.log(warn(`You're inside a workshell (branch: ${cyan(currentBranch)})`));
|
|
7218
7347
|
console.log(` This will nest subshells (subshell inside subshell).`);
|
|
7219
7348
|
console.log();
|
|
7220
7349
|
if (!confirm("Continue?")) {
|
|
@@ -8316,7 +8445,7 @@ function promptChoice() {
|
|
|
8316
8445
|
}
|
|
8317
8446
|
|
|
8318
8447
|
// index.ts
|
|
8319
|
-
var VERSION = "0.
|
|
8448
|
+
var VERSION = "0.4.0";
|
|
8320
8449
|
function printHelp() {
|
|
8321
8450
|
const dim2 = import_picocolors4.default.dim;
|
|
8322
8451
|
const cyan2 = import_picocolors4.default.cyan;
|
|
@@ -8328,7 +8457,7 @@ ${import_picocolors4.default.bold("Usage:")} ${cyan2("wk")} ${dim2("<command>")}
|
|
|
8328
8457
|
${import_picocolors4.default.bold("Commands:")}
|
|
8329
8458
|
${green2("new")} ${dim2("[branch]")} Create a branch and open it ${dim2("[--from <branch>]")}
|
|
8330
8459
|
${green2("open")} ${dim2("<ref>")} Open a branch or PR in an ephemeral subshell
|
|
8331
|
-
${green2("close")} Exit current
|
|
8460
|
+
${green2("close")} Exit current workshell
|
|
8332
8461
|
${green2("ls")} List open branches
|
|
8333
8462
|
${green2("status")} Show current branch
|
|
8334
8463
|
${green2("rm")} ${dim2("<branch>")} Remove a branch's worktree
|
|
@@ -8459,7 +8588,7 @@ ${import_picocolors4.default.bold("Description:")}
|
|
|
8459
8588
|
function printCloseHelp() {
|
|
8460
8589
|
const dim2 = import_picocolors4.default.dim;
|
|
8461
8590
|
const cyan2 = import_picocolors4.default.cyan;
|
|
8462
|
-
console.log(`${import_picocolors4.default.bold("wk close")} - Exit current
|
|
8591
|
+
console.log(`${import_picocolors4.default.bold("wk close")} - Exit current workshell
|
|
8463
8592
|
|
|
8464
8593
|
${import_picocolors4.default.bold("Usage:")} ${cyan2("wk close")} ${dim2("[options]")}
|
|
8465
8594
|
|
|
@@ -8467,7 +8596,7 @@ ${import_picocolors4.default.bold("Options:")}
|
|
|
8467
8596
|
${cyan2("-f")}, ${cyan2("--force")} Discard uncommitted changes and exit
|
|
8468
8597
|
|
|
8469
8598
|
${import_picocolors4.default.bold("Description:")}
|
|
8470
|
-
Exits the current
|
|
8599
|
+
Exits the current workshell and returns to the parent.
|
|
8471
8600
|
|
|
8472
8601
|
On exit, if the branch is clean:
|
|
8473
8602
|
- Worktree is pruned (branch is kept)
|
|
@@ -8575,7 +8704,18 @@ switch (cmd) {
|
|
|
8575
8704
|
printCloseHelp();
|
|
8576
8705
|
process.exit(0);
|
|
8577
8706
|
}
|
|
8578
|
-
|
|
8707
|
+
if (!isInsideWorkshell() && isInsideWorktree()) {
|
|
8708
|
+
const currentBranch = getCurrentBranch();
|
|
8709
|
+
const mainWorktree = getMainWorktree();
|
|
8710
|
+
const shell = process.env.SHELL || "/bin/bash";
|
|
8711
|
+
console.log();
|
|
8712
|
+
console.log(dim(`You're in a worktree (branch: ${cyan(currentBranch)}) but not a workshell.`));
|
|
8713
|
+
console.log(dim(`Opening repo root in a fresh shell...`));
|
|
8714
|
+
console.log();
|
|
8715
|
+
spawnSync2(shell, [], { cwd: mainWorktree, stdio: "inherit" });
|
|
8716
|
+
process.exit(0);
|
|
8717
|
+
}
|
|
8718
|
+
console.error(fail("'wk close' only works inside a workshell."));
|
|
8579
8719
|
process.exit(1);
|
|
8580
8720
|
break;
|
|
8581
8721
|
case "__preclose":
|