workshell 0.0.7 → 0.2.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/index.js +139 -36
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7098,37 +7098,78 @@ function newCommand(branchName, fromBranch) {
|
|
|
7098
7098
|
}
|
|
7099
7099
|
|
|
7100
7100
|
// commands/open.ts
|
|
7101
|
+
import { execSync as execSync3 } from "child_process";
|
|
7101
7102
|
import { mkdirSync as mkdirSync4 } from "fs";
|
|
7102
7103
|
import { basename as basename4, dirname as dirname4, join as join4 } from "path";
|
|
7103
|
-
function
|
|
7104
|
-
|
|
7105
|
-
|
|
7106
|
-
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7111
|
-
|
|
7104
|
+
function isGhInstalled() {
|
|
7105
|
+
try {
|
|
7106
|
+
execSync3("gh --version", { stdio: "pipe", encoding: "utf-8" });
|
|
7107
|
+
return true;
|
|
7108
|
+
} catch {
|
|
7109
|
+
return false;
|
|
7110
|
+
}
|
|
7111
|
+
}
|
|
7112
|
+
function isGhAuthenticated() {
|
|
7113
|
+
try {
|
|
7114
|
+
execSync3("gh auth status", { stdio: "pipe", encoding: "utf-8" });
|
|
7115
|
+
return true;
|
|
7116
|
+
} catch {
|
|
7117
|
+
return false;
|
|
7118
|
+
}
|
|
7119
|
+
}
|
|
7120
|
+
function getPRInfo(prRef) {
|
|
7121
|
+
try {
|
|
7122
|
+
const output = execSync3(
|
|
7123
|
+
`gh pr view ${prRef} --json number,headRefName`,
|
|
7124
|
+
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
7125
|
+
);
|
|
7126
|
+
return JSON.parse(output);
|
|
7127
|
+
} catch {
|
|
7128
|
+
return null;
|
|
7129
|
+
}
|
|
7130
|
+
}
|
|
7131
|
+
function fetchPRBranch(prRef, prInfo) {
|
|
7132
|
+
try {
|
|
7133
|
+
execSync3(`git fetch origin ${prInfo.headRefName}:${prInfo.headRefName}`, { stdio: "pipe" });
|
|
7134
|
+
return true;
|
|
7135
|
+
} catch {
|
|
7136
|
+
}
|
|
7137
|
+
const currentBranch = getCurrentBranch();
|
|
7138
|
+
try {
|
|
7139
|
+
execSync3(`gh pr checkout ${prRef}`, { stdio: "pipe" });
|
|
7140
|
+
execSync3(`git checkout "${currentBranch}"`, { stdio: "pipe" });
|
|
7141
|
+
return true;
|
|
7142
|
+
} catch {
|
|
7143
|
+
try {
|
|
7144
|
+
execSync3(`git checkout "${currentBranch}"`, { stdio: "pipe" });
|
|
7145
|
+
} catch {
|
|
7112
7146
|
}
|
|
7113
|
-
console.log();
|
|
7114
7147
|
}
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7148
|
+
try {
|
|
7149
|
+
execSync3(`git fetch origin pull/${prInfo.number}/head:${prInfo.headRefName}`, { stdio: "pipe" });
|
|
7150
|
+
return true;
|
|
7151
|
+
} catch {
|
|
7152
|
+
return false;
|
|
7118
7153
|
}
|
|
7154
|
+
}
|
|
7155
|
+
function openBranch(branch, prNumber) {
|
|
7119
7156
|
const parentBranch = getCurrentBranch();
|
|
7157
|
+
const mainWorktree = getMainWorktree();
|
|
7120
7158
|
const existingWorktreePath = getWorktreeForBranch(branch);
|
|
7121
7159
|
if (existingWorktreePath) {
|
|
7122
7160
|
const worktreeId2 = getWorktreeId(existingWorktreePath);
|
|
7123
|
-
const mainWorktree2 = getMainWorktree();
|
|
7124
7161
|
console.log();
|
|
7125
|
-
|
|
7162
|
+
if (prNumber) {
|
|
7163
|
+
console.log(success(bold(`PR #${prNumber}`)), dim(`branch: ${cyan(branch)} (existing worktree)`));
|
|
7164
|
+
} else {
|
|
7165
|
+
console.log(success(bold(branch)), dim(`(existing worktree)`));
|
|
7166
|
+
}
|
|
7126
7167
|
console.log(dim("Type 'wk close' to return."));
|
|
7127
7168
|
console.log();
|
|
7128
7169
|
spawnShell(existingWorktreePath, {
|
|
7129
7170
|
branch,
|
|
7130
7171
|
worktreePath: existingWorktreePath,
|
|
7131
|
-
repoPath:
|
|
7172
|
+
repoPath: mainWorktree
|
|
7132
7173
|
});
|
|
7133
7174
|
console.log();
|
|
7134
7175
|
console.log(success(`Back in ${bold(parentBranch)}`));
|
|
@@ -7138,7 +7179,6 @@ function openCommand(branch) {
|
|
|
7138
7179
|
return;
|
|
7139
7180
|
}
|
|
7140
7181
|
const store = loadStore();
|
|
7141
|
-
const mainWorktree = getMainWorktree();
|
|
7142
7182
|
const repoName = basename4(mainWorktree);
|
|
7143
7183
|
const worktreeId = `${repoName}@${slugify(branch)}`;
|
|
7144
7184
|
const worktreePath = join4(getWorktreesDir(), worktreeId);
|
|
@@ -7150,8 +7190,13 @@ function openCommand(branch) {
|
|
|
7150
7190
|
});
|
|
7151
7191
|
saveStore(store);
|
|
7152
7192
|
console.log();
|
|
7153
|
-
|
|
7154
|
-
|
|
7193
|
+
if (prNumber) {
|
|
7194
|
+
console.log(success(bold(`PR #${prNumber}`)), dim(`branch: ${cyan(branch)}`));
|
|
7195
|
+
console.log(dim(`Opened PR in ephemeral subshell`));
|
|
7196
|
+
} else {
|
|
7197
|
+
console.log(success(bold(branch)));
|
|
7198
|
+
console.log(dim(`Opened branch in ephemeral subshell`));
|
|
7199
|
+
}
|
|
7155
7200
|
console.log(dim("Type 'exit' or 'wk close' to return."));
|
|
7156
7201
|
console.log();
|
|
7157
7202
|
spawnShell(worktreePath, {
|
|
@@ -7165,6 +7210,55 @@ function openCommand(branch) {
|
|
|
7165
7210
|
autoCleanupWorktree(worktreeId, worktreePath, currentStore, saveStore);
|
|
7166
7211
|
console.log();
|
|
7167
7212
|
}
|
|
7213
|
+
function openCommand(ref) {
|
|
7214
|
+
if (isInsideWorktree()) {
|
|
7215
|
+
const currentBranch = getCurrentBranch();
|
|
7216
|
+
console.log();
|
|
7217
|
+
console.log(warn(`You're inside a worktree (branch: ${cyan(currentBranch)})`));
|
|
7218
|
+
console.log(` This will nest subshells (subshell inside subshell).`);
|
|
7219
|
+
console.log();
|
|
7220
|
+
if (!confirm("Continue?")) {
|
|
7221
|
+
process.exit(0);
|
|
7222
|
+
}
|
|
7223
|
+
console.log();
|
|
7224
|
+
}
|
|
7225
|
+
if (branchExists(ref)) {
|
|
7226
|
+
openBranch(ref);
|
|
7227
|
+
return;
|
|
7228
|
+
}
|
|
7229
|
+
if (!isGhInstalled()) {
|
|
7230
|
+
console.error(fail(`Branch '${ref}' not found.`));
|
|
7231
|
+
console.error(dim(" Install GitHub CLI (gh) to open PRs: https://cli.github.com/"));
|
|
7232
|
+
process.exit(1);
|
|
7233
|
+
}
|
|
7234
|
+
if (!isGhAuthenticated()) {
|
|
7235
|
+
console.error(fail(`Branch '${ref}' not found.`));
|
|
7236
|
+
console.error(dim(" Run 'gh auth login' to open PRs from GitHub."));
|
|
7237
|
+
process.exit(1);
|
|
7238
|
+
}
|
|
7239
|
+
const prInfo = getPRInfo(ref);
|
|
7240
|
+
if (!prInfo) {
|
|
7241
|
+
console.error(fail(`'${ref}' is not a local branch or GitHub PR.`));
|
|
7242
|
+
process.exit(1);
|
|
7243
|
+
}
|
|
7244
|
+
const branch = prInfo.headRefName;
|
|
7245
|
+
const prNumber = prInfo.number;
|
|
7246
|
+
if (branchExists(branch)) {
|
|
7247
|
+
console.log(dim(`PR #${prNumber} \u2192 ${branch}`));
|
|
7248
|
+
openBranch(branch, prNumber);
|
|
7249
|
+
return;
|
|
7250
|
+
}
|
|
7251
|
+
console.log(dim(`Fetching PR #${prNumber}...`));
|
|
7252
|
+
if (!fetchPRBranch(ref, prInfo)) {
|
|
7253
|
+
console.error(fail(`Failed to fetch branch '${branch}' for PR #${prNumber}`));
|
|
7254
|
+
process.exit(1);
|
|
7255
|
+
}
|
|
7256
|
+
if (!branchExists(branch)) {
|
|
7257
|
+
console.error(fail(`Failed to fetch branch '${branch}' for PR #${prNumber}`));
|
|
7258
|
+
process.exit(1);
|
|
7259
|
+
}
|
|
7260
|
+
openBranch(branch, prNumber);
|
|
7261
|
+
}
|
|
7168
7262
|
|
|
7169
7263
|
// commands/ls.ts
|
|
7170
7264
|
var import_table = __toESM(require_src(), 1);
|
|
@@ -8015,7 +8109,7 @@ function lsCommand(plain = false) {
|
|
|
8015
8109
|
}
|
|
8016
8110
|
|
|
8017
8111
|
// commands/rm.ts
|
|
8018
|
-
import { execSync as
|
|
8112
|
+
import { execSync as execSync4 } from "child_process";
|
|
8019
8113
|
import { resolve as resolve2 } from "path";
|
|
8020
8114
|
function rmCommand(branch, force = false) {
|
|
8021
8115
|
const mainWorktree = getMainWorktree();
|
|
@@ -8046,8 +8140,8 @@ function rmCommand(branch, force = false) {
|
|
|
8046
8140
|
}
|
|
8047
8141
|
if (isDirty && force) {
|
|
8048
8142
|
try {
|
|
8049
|
-
|
|
8050
|
-
|
|
8143
|
+
execSync4(`git -C "${worktreePath}" reset --hard HEAD`, { stdio: "ignore" });
|
|
8144
|
+
execSync4(`git -C "${worktreePath}" clean -fd`, { stdio: "ignore" });
|
|
8051
8145
|
} catch {
|
|
8052
8146
|
}
|
|
8053
8147
|
}
|
|
@@ -8065,7 +8159,7 @@ function rmCommand(branch, force = false) {
|
|
|
8065
8159
|
}
|
|
8066
8160
|
|
|
8067
8161
|
// commands/status.ts
|
|
8068
|
-
import { execSync as
|
|
8162
|
+
import { execSync as execSync5 } from "child_process";
|
|
8069
8163
|
import { existsSync as existsSync4, readdirSync as readdirSync3 } from "fs";
|
|
8070
8164
|
import { resolve as resolve3 } from "path";
|
|
8071
8165
|
function getDetailedStatus(path) {
|
|
@@ -8073,7 +8167,7 @@ function getDetailedStatus(path) {
|
|
|
8073
8167
|
return [];
|
|
8074
8168
|
}
|
|
8075
8169
|
try {
|
|
8076
|
-
const status =
|
|
8170
|
+
const status = execSync5(`git -C "${path}" status --short`, { encoding: "utf-8" }).trim();
|
|
8077
8171
|
if (!status) {
|
|
8078
8172
|
return [];
|
|
8079
8173
|
}
|
|
@@ -8139,17 +8233,17 @@ function statusCommand() {
|
|
|
8139
8233
|
}
|
|
8140
8234
|
|
|
8141
8235
|
// commands/preclose.ts
|
|
8142
|
-
import { execSync as
|
|
8236
|
+
import { execSync as execSync6 } from "child_process";
|
|
8143
8237
|
function precloseCommand(force) {
|
|
8144
8238
|
if (!hasUncommittedChanges()) {
|
|
8145
8239
|
process.exit(0);
|
|
8146
8240
|
}
|
|
8147
8241
|
if (force) {
|
|
8148
8242
|
try {
|
|
8149
|
-
|
|
8150
|
-
|
|
8151
|
-
|
|
8152
|
-
|
|
8243
|
+
execSync6("git reset --hard HEAD", { stdio: "ignore" });
|
|
8244
|
+
execSync6("git clean -ffd", { stdio: "ignore" });
|
|
8245
|
+
execSync6("git submodule foreach --recursive 'git reset --hard HEAD; git clean -ffd'", { stdio: "ignore" });
|
|
8246
|
+
execSync6("git submodule update --init --recursive --force", { stdio: "ignore" });
|
|
8153
8247
|
} catch {
|
|
8154
8248
|
}
|
|
8155
8249
|
process.exit(0);
|
|
@@ -8222,7 +8316,7 @@ function promptChoice() {
|
|
|
8222
8316
|
}
|
|
8223
8317
|
|
|
8224
8318
|
// index.ts
|
|
8225
|
-
var VERSION = "0.0
|
|
8319
|
+
var VERSION = "0.2.0";
|
|
8226
8320
|
function printHelp() {
|
|
8227
8321
|
const dim2 = import_picocolors4.default.dim;
|
|
8228
8322
|
const cyan2 = import_picocolors4.default.cyan;
|
|
@@ -8233,7 +8327,7 @@ ${import_picocolors4.default.bold("Usage:")} ${cyan2("wk")} ${dim2("<command>")}
|
|
|
8233
8327
|
|
|
8234
8328
|
${import_picocolors4.default.bold("Commands:")}
|
|
8235
8329
|
${green2("new")} ${dim2("[branch]")} Create a branch and open it ${dim2("[--from <branch>]")}
|
|
8236
|
-
${green2("open")} ${dim2("<
|
|
8330
|
+
${green2("open")} ${dim2("<ref>")} Open a branch or PR in an ephemeral subshell
|
|
8237
8331
|
${green2("close")} Exit current subshell
|
|
8238
8332
|
${green2("ls")} List open branches
|
|
8239
8333
|
${green2("status")} Show current branch
|
|
@@ -8298,15 +8392,24 @@ ${import_picocolors4.default.bold("Description:")}
|
|
|
8298
8392
|
function printOpenHelp() {
|
|
8299
8393
|
const dim2 = import_picocolors4.default.dim;
|
|
8300
8394
|
const cyan2 = import_picocolors4.default.cyan;
|
|
8301
|
-
console.log(`${import_picocolors4.default.bold("wk open")} - Open a branch in an ephemeral subshell
|
|
8395
|
+
console.log(`${import_picocolors4.default.bold("wk open")} - Open a branch or PR in an ephemeral subshell
|
|
8302
8396
|
|
|
8303
|
-
${import_picocolors4.default.bold("Usage:")} ${cyan2("wk open")} ${dim2("<
|
|
8397
|
+
${import_picocolors4.default.bold("Usage:")} ${cyan2("wk open")} ${dim2("<ref>")}
|
|
8304
8398
|
|
|
8305
8399
|
${import_picocolors4.default.bold("Arguments:")}
|
|
8306
|
-
${dim2("<
|
|
8400
|
+
${dim2("<ref>")} Branch name, PR number, or PR URL ${dim2("(required)")}
|
|
8401
|
+
|
|
8402
|
+
${import_picocolors4.default.bold("Examples:")}
|
|
8403
|
+
${dim2("$")} ${cyan2("wk open feature-branch")} ${dim2("# Open local branch")}
|
|
8404
|
+
${dim2("$")} ${cyan2("wk open 123")} ${dim2("# Open PR #123")}
|
|
8405
|
+
${dim2("$")} ${cyan2("wk open https://github.com/o/r/pull/123")}
|
|
8307
8406
|
|
|
8308
8407
|
${import_picocolors4.default.bold("Description:")}
|
|
8309
|
-
Opens the specified
|
|
8408
|
+
Opens the specified ref in an ephemeral subshell.
|
|
8409
|
+
|
|
8410
|
+
First tries to open as a local branch. If not found, tries to fetch
|
|
8411
|
+
as a GitHub PR (requires gh CLI to be installed and authenticated).
|
|
8412
|
+
|
|
8310
8413
|
If a worktree already exists for the branch, uses that.
|
|
8311
8414
|
Otherwise, creates a new worktree automatically.
|
|
8312
8415
|
Type 'wk close' to return.`);
|
|
@@ -8430,7 +8533,7 @@ switch (cmd) {
|
|
|
8430
8533
|
process.exit(0);
|
|
8431
8534
|
}
|
|
8432
8535
|
if (!args[1]) {
|
|
8433
|
-
console.error("Usage: wk open <branch>");
|
|
8536
|
+
console.error("Usage: wk open <branch|pr-number|pr-url>");
|
|
8434
8537
|
process.exit(1);
|
|
8435
8538
|
}
|
|
8436
8539
|
openCommand(args[1]);
|