@hallaxius/forge 0.1.2 → 0.1.4
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 +160 -158
- package/bin/forge.js +2 -2
- package/dist/cli.js +31602 -9895
- package/package.json +75 -72
- package/src/cli.ts +80 -78
- package/src/commands/account.ts +80 -0
- package/src/commands/alias.ts +66 -66
- package/src/commands/branch.ts +46 -46
- package/src/commands/ci.ts +28 -0
- package/src/commands/clone.ts +100 -100
- package/src/commands/commit.ts +88 -93
- package/src/commands/config.ts +47 -48
- package/src/commands/diff.ts +26 -26
- package/src/commands/fetch.ts +20 -20
- package/src/commands/help.ts +58 -58
- package/src/commands/init.ts +32 -37
- package/src/commands/issue.ts +63 -0
- package/src/commands/log.ts +29 -29
- package/src/commands/merge.ts +37 -37
- package/src/commands/pr.ts +65 -0
- package/src/commands/push.ts +35 -35
- package/src/commands/release.ts +26 -0
- package/src/commands/remote.ts +107 -107
- package/src/commands/reset.ts +30 -30
- package/src/commands/setup.ts +93 -95
- package/src/commands/stash.ts +44 -44
- package/src/commands/status.ts +74 -74
- package/src/commands/sync.ts +20 -20
- package/src/commands/tag.ts +41 -41
- package/src/commands/undo.ts +27 -27
- package/src/commands/version.ts +12 -12
- package/src/constants/colors.ts +7 -7
- package/src/constants/commit-types.ts +24 -24
- package/src/constants/messages.ts +13 -23
- package/src/lib/auth.ts +172 -95
- package/src/lib/config.ts +108 -99
- package/src/lib/git.ts +543 -382
- package/src/lib/github.ts +202 -0
- package/src/lib/logger.ts +18 -31
- package/src/lib/ui.ts +122 -156
- package/src/lib/validators.ts +16 -27
- package/src/templates/commit-types.json +9 -9
- package/src/utils/files.ts +21 -21
- package/src/utils/strings.ts +19 -19
- package/src/version.const.ts +1 -1
- package/src/commands/archive.ts +0 -35
- package/src/commands/bisect.ts +0 -102
- package/src/commands/cherry-pick.ts +0 -57
- package/src/commands/clean.ts +0 -76
- package/src/commands/worktree.ts +0 -92
package/src/commands/remote.ts
CHANGED
|
@@ -1,107 +1,107 @@
|
|
|
1
|
-
import type { Command } from "commander";
|
|
2
|
-
import * as git from "../lib/git.js";
|
|
3
|
-
import { error,
|
|
4
|
-
import { confirm, createTable } from "../lib/ui.js";
|
|
5
|
-
|
|
6
|
-
export default function register(program: Command): void {
|
|
7
|
-
const remote = program.command("remote").description("Manage remotes");
|
|
8
|
-
|
|
9
|
-
remote
|
|
10
|
-
.command("add <name> <url>")
|
|
11
|
-
.description("Add a new remote")
|
|
12
|
-
.action(async (name, url) => {
|
|
13
|
-
try {
|
|
14
|
-
await git.remoteAdd(name, url);
|
|
15
|
-
|
|
16
|
-
} catch (err) {
|
|
17
|
-
error(
|
|
18
|
-
`Failed to add remote: ${err instanceof Error ? err.message : String(err)}`,
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
remote
|
|
24
|
-
.command("remove <name>")
|
|
25
|
-
.description("Remove a remote")
|
|
26
|
-
.action(async (name) => {
|
|
27
|
-
try {
|
|
28
|
-
const confirmed = await confirm(
|
|
29
|
-
`Are you sure you want to remove remote '${name}'?`,
|
|
30
|
-
false,
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
if (!confirmed) {
|
|
34
|
-
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
await git.remoteRemove(name);
|
|
39
|
-
|
|
40
|
-
} catch (err) {
|
|
41
|
-
error(
|
|
42
|
-
`Failed to remove remote: ${err instanceof Error ? err.message : String(err)}`,
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
remote
|
|
48
|
-
.command("set-url <name> <new-url>")
|
|
49
|
-
.description("Change a remote URL")
|
|
50
|
-
.action(async (name, newUrl) => {
|
|
51
|
-
try {
|
|
52
|
-
await git.remoteSetUrl(name, newUrl);
|
|
53
|
-
|
|
54
|
-
} catch (err) {
|
|
55
|
-
error(
|
|
56
|
-
`Failed to update remote URL: ${err instanceof Error ? err.message : String(err)}`,
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
remote
|
|
62
|
-
.command("rename <old-name> <new-name>")
|
|
63
|
-
.description("Rename a remote")
|
|
64
|
-
.action(async (oldName, newName) => {
|
|
65
|
-
try {
|
|
66
|
-
await git.remoteRename(oldName, newName);
|
|
67
|
-
|
|
68
|
-
} catch (err) {
|
|
69
|
-
error(
|
|
70
|
-
`Failed to rename remote: ${err instanceof Error ? err.message : String(err)}`,
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
remote
|
|
76
|
-
.command("get-url <name>")
|
|
77
|
-
.description("Get the URL of a remote")
|
|
78
|
-
.action(async (name) => {
|
|
79
|
-
try {
|
|
80
|
-
const url = await git.remoteGetUrl(name);
|
|
81
|
-
|
|
82
|
-
} catch (err) {
|
|
83
|
-
error(
|
|
84
|
-
`Failed to get remote URL: ${err instanceof Error ? err.message : String(err)}`,
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
remote.action(async () => {
|
|
90
|
-
try {
|
|
91
|
-
const remotes = await git.remoteList();
|
|
92
|
-
|
|
93
|
-
if (remotes.length === 0) {
|
|
94
|
-
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const rows = remotes.map((r) => [r.name, r.url]);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
} catch (err) {
|
|
102
|
-
error(
|
|
103
|
-
`Failed to list remotes: ${err instanceof Error ? err.message : String(err)}`,
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
}
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import * as git from "../lib/git.js";
|
|
3
|
+
import { error, text } from "../lib/logger.js";
|
|
4
|
+
import { confirm, createTable } from "../lib/ui.js";
|
|
5
|
+
|
|
6
|
+
export default function register(program: Command): void {
|
|
7
|
+
const remote = program.command("remote").description("Manage remotes");
|
|
8
|
+
|
|
9
|
+
remote
|
|
10
|
+
.command("add <name> <url>")
|
|
11
|
+
.description("Add a new remote")
|
|
12
|
+
.action(async (name, url) => {
|
|
13
|
+
try {
|
|
14
|
+
await git.remoteAdd(name, url);
|
|
15
|
+
text(`Remote '${name}' added (${url}).`);
|
|
16
|
+
} catch (err) {
|
|
17
|
+
error(
|
|
18
|
+
`Failed to add remote: ${err instanceof Error ? err.message : String(err)}`,
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
remote
|
|
24
|
+
.command("remove <name>")
|
|
25
|
+
.description("Remove a remote")
|
|
26
|
+
.action(async (name) => {
|
|
27
|
+
try {
|
|
28
|
+
const confirmed = await confirm(
|
|
29
|
+
`Are you sure you want to remove remote '${name}'?`,
|
|
30
|
+
false,
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
if (!confirmed) {
|
|
34
|
+
text("Canceled.");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
await git.remoteRemove(name);
|
|
39
|
+
text(`Remote '${name}' removed.`);
|
|
40
|
+
} catch (err) {
|
|
41
|
+
error(
|
|
42
|
+
`Failed to remove remote: ${err instanceof Error ? err.message : String(err)}`,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
remote
|
|
48
|
+
.command("set-url <name> <new-url>")
|
|
49
|
+
.description("Change a remote URL")
|
|
50
|
+
.action(async (name, newUrl) => {
|
|
51
|
+
try {
|
|
52
|
+
await git.remoteSetUrl(name, newUrl);
|
|
53
|
+
text(`Remote '${name}' URL updated to ${newUrl}.`);
|
|
54
|
+
} catch (err) {
|
|
55
|
+
error(
|
|
56
|
+
`Failed to update remote URL: ${err instanceof Error ? err.message : String(err)}`,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
remote
|
|
62
|
+
.command("rename <old-name> <new-name>")
|
|
63
|
+
.description("Rename a remote")
|
|
64
|
+
.action(async (oldName, newName) => {
|
|
65
|
+
try {
|
|
66
|
+
await git.remoteRename(oldName, newName);
|
|
67
|
+
text(`Remote '${oldName}' renamed to '${newName}'.`);
|
|
68
|
+
} catch (err) {
|
|
69
|
+
error(
|
|
70
|
+
`Failed to rename remote: ${err instanceof Error ? err.message : String(err)}`,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
remote
|
|
76
|
+
.command("get-url <name>")
|
|
77
|
+
.description("Get the URL of a remote")
|
|
78
|
+
.action(async (name) => {
|
|
79
|
+
try {
|
|
80
|
+
const url = await git.remoteGetUrl(name);
|
|
81
|
+
text(`Remote '${name}': ${url}`);
|
|
82
|
+
} catch (err) {
|
|
83
|
+
error(
|
|
84
|
+
`Failed to get remote URL: ${err instanceof Error ? err.message : String(err)}`,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
remote.action(async () => {
|
|
90
|
+
try {
|
|
91
|
+
const remotes = await git.remoteList();
|
|
92
|
+
|
|
93
|
+
if (remotes.length === 0) {
|
|
94
|
+
text("No remotes configured.");
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const rows = remotes.map((r) => [r.name, r.url]);
|
|
99
|
+
text("Remotes:");
|
|
100
|
+
text(createTable(["Name", "URL"], rows));
|
|
101
|
+
} catch (err) {
|
|
102
|
+
error(
|
|
103
|
+
`Failed to list remotes: ${err instanceof Error ? err.message : String(err)}`,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
package/src/commands/reset.ts
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import type { Command } from "commander";
|
|
2
|
-
import { ConfigManager } from "../lib/config.js";
|
|
3
|
-
import { error,
|
|
4
|
-
import { confirm } from "../lib/ui.js";
|
|
5
|
-
|
|
6
|
-
export default function register(program: Command): void {
|
|
7
|
-
program
|
|
8
|
-
.command("reset")
|
|
9
|
-
.description("Reset all configuration")
|
|
10
|
-
.action(async () => {
|
|
11
|
-
try {
|
|
12
|
-
warning("This will delete all Forge configuration.");
|
|
13
|
-
const proceed = await confirm(
|
|
14
|
-
"Are you sure? This will delete all configuration",
|
|
15
|
-
);
|
|
16
|
-
if (!proceed) {
|
|
17
|
-
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const config = new ConfigManager();
|
|
22
|
-
config.clear();
|
|
23
|
-
|
|
24
|
-
} catch (err) {
|
|
25
|
-
error(
|
|
26
|
-
`Reset failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
}
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { ConfigManager } from "../lib/config.js";
|
|
3
|
+
import { error, text, warning } from "../lib/logger.js";
|
|
4
|
+
import { confirm } from "../lib/ui.js";
|
|
5
|
+
|
|
6
|
+
export default function register(program: Command): void {
|
|
7
|
+
program
|
|
8
|
+
.command("reset")
|
|
9
|
+
.description("Reset all configuration")
|
|
10
|
+
.action(async () => {
|
|
11
|
+
try {
|
|
12
|
+
warning("This will delete all Forge configuration.");
|
|
13
|
+
const proceed = await confirm(
|
|
14
|
+
"Are you sure? This will delete all configuration",
|
|
15
|
+
);
|
|
16
|
+
if (!proceed) {
|
|
17
|
+
text("Reset cancelled.");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const config = new ConfigManager();
|
|
22
|
+
config.clear();
|
|
23
|
+
text("Configuration reset successfully.");
|
|
24
|
+
} catch (err) {
|
|
25
|
+
error(
|
|
26
|
+
`Reset failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
package/src/commands/setup.ts
CHANGED
|
@@ -1,95 +1,93 @@
|
|
|
1
|
-
import type { Command } from "commander";
|
|
2
|
-
import { encryptToken } from "../lib/auth.js";
|
|
3
|
-
import { ConfigManager } from "../lib/config.js";
|
|
4
|
-
import { error,
|
|
5
|
-
import { confirm, input, password
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
`
|
|
82
|
-
`
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
});
|
|
95
|
-
}
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { encryptToken, generateMachineKey } from "../lib/auth.js";
|
|
3
|
+
import { ConfigManager } from "../lib/config.js";
|
|
4
|
+
import { error, newline, text, warning } from "../lib/logger.js";
|
|
5
|
+
import { confirm, input, password } from "../lib/ui.js";
|
|
6
|
+
import { validateEmail } from "../lib/validators.js";
|
|
7
|
+
|
|
8
|
+
export default function register(program: Command): void {
|
|
9
|
+
program
|
|
10
|
+
.command("setup")
|
|
11
|
+
.description("Interactive setup wizard")
|
|
12
|
+
.action(async () => {
|
|
13
|
+
try {
|
|
14
|
+
const config = new ConfigManager();
|
|
15
|
+
|
|
16
|
+
if (config.isConfigured()) {
|
|
17
|
+
warning("Forge is already configured. You are about to reconfigure.");
|
|
18
|
+
const proceed = await confirm("Continue with reconfiguration?");
|
|
19
|
+
if (!proceed) {
|
|
20
|
+
text("Setup cancelled.");
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
newline();
|
|
26
|
+
text("Starting setup...");
|
|
27
|
+
newline();
|
|
28
|
+
|
|
29
|
+
const name = await input("Your name");
|
|
30
|
+
|
|
31
|
+
let email = await input("Your email");
|
|
32
|
+
while (!validateEmail(email)) {
|
|
33
|
+
error("Invalid email format.");
|
|
34
|
+
email = await input("Your email");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const rawToken = await input(
|
|
38
|
+
"GitHub token (required for remote operations)",
|
|
39
|
+
);
|
|
40
|
+
if (!rawToken) {
|
|
41
|
+
error(
|
|
42
|
+
"GitHub token is required. Get one at https://github.com/settings/tokens",
|
|
43
|
+
);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const useMasterPassword = await confirm(
|
|
48
|
+
"Protect token with a master password? (recommended)",
|
|
49
|
+
true,
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const machineKey = generateMachineKey();
|
|
53
|
+
let hasMasterPassword = false;
|
|
54
|
+
|
|
55
|
+
if (useMasterPassword) {
|
|
56
|
+
const mp = await password("Master password:");
|
|
57
|
+
const encryptedKey = await encryptToken(machineKey, mp);
|
|
58
|
+
config.set("auth.machineKey", encryptedKey);
|
|
59
|
+
config.set("auth.hasMasterPassword", true);
|
|
60
|
+
hasMasterPassword = true;
|
|
61
|
+
} else {
|
|
62
|
+
config.set("auth.machineKey", machineKey);
|
|
63
|
+
config.set("auth.hasMasterPassword", false);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const encryptedToken = await encryptToken(rawToken, machineKey);
|
|
67
|
+
config.set("github.encryptedToken", encryptedToken);
|
|
68
|
+
|
|
69
|
+
config.set("user", { name, email });
|
|
70
|
+
config.set("preferences", {
|
|
71
|
+
autoPush: false,
|
|
72
|
+
commitTemplate: "",
|
|
73
|
+
editor: process.env.EDITOR || "vim",
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
newline();
|
|
77
|
+
text(
|
|
78
|
+
[
|
|
79
|
+
`User: ${name} <${email}>`,
|
|
80
|
+
`Token: Set (encrypted)`,
|
|
81
|
+
`Security: ${hasMasterPassword ? "Master password protected" : "Machine key"}`,
|
|
82
|
+
`Config: ${config.getPath()}`,
|
|
83
|
+
].join("\n"),
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
text("Forge is ready to use!");
|
|
87
|
+
} catch (err) {
|
|
88
|
+
error(
|
|
89
|
+
`Setup failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
package/src/commands/stash.ts
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
import type { Command } from "commander";
|
|
2
|
-
import * as git from "../lib/git.js";
|
|
3
|
-
import { error,
|
|
4
|
-
import { createTable, input, withSpinner } from "../lib/ui.js";
|
|
5
|
-
|
|
6
|
-
export default function register(program: Command): void {
|
|
7
|
-
program
|
|
8
|
-
.command("stash")
|
|
9
|
-
.description("Manage stashes")
|
|
10
|
-
.option("--pop", "Apply and remove latest stash")
|
|
11
|
-
.option("--list", "List all stashes")
|
|
12
|
-
.action(async (options) => {
|
|
13
|
-
try {
|
|
14
|
-
if (options.pop) {
|
|
15
|
-
const result = await withSpinner("Applying stash...", () =>
|
|
16
|
-
git.stashPop(),
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (options.list) {
|
|
23
|
-
const stashes = await git.stashList();
|
|
24
|
-
if (stashes.length === 0) {
|
|
25
|
-
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const rows = stashes.map((s) => [String(s.index), s.description]);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const _message = await input("Stash message (optional)");
|
|
36
|
-
const result = await withSpinner("Stashing...", () => git.stash());
|
|
37
|
-
|
|
38
|
-
} catch (err) {
|
|
39
|
-
error(
|
|
40
|
-
`Stash operation failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
}
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import * as git from "../lib/git.js";
|
|
3
|
+
import { error, text } from "../lib/logger.js";
|
|
4
|
+
import { createTable, input, withSpinner } from "../lib/ui.js";
|
|
5
|
+
|
|
6
|
+
export default function register(program: Command): void {
|
|
7
|
+
program
|
|
8
|
+
.command("stash")
|
|
9
|
+
.description("Manage stashes")
|
|
10
|
+
.option("--pop", "Apply and remove latest stash")
|
|
11
|
+
.option("--list", "List all stashes")
|
|
12
|
+
.action(async (options) => {
|
|
13
|
+
try {
|
|
14
|
+
if (options.pop) {
|
|
15
|
+
const result = await withSpinner("Applying stash...", () =>
|
|
16
|
+
git.stashPop(),
|
|
17
|
+
);
|
|
18
|
+
text(`Stash popped: ${result}`);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (options.list) {
|
|
23
|
+
const stashes = await git.stashList();
|
|
24
|
+
if (stashes.length === 0) {
|
|
25
|
+
text("No stashes found.");
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const rows = stashes.map((s) => [String(s.index), s.description]);
|
|
30
|
+
text("Stashes:");
|
|
31
|
+
text(createTable(["#", "Description"], rows));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const _message = await input("Stash message (optional)");
|
|
36
|
+
const result = await withSpinner("Stashing...", () => git.stash());
|
|
37
|
+
text(`Stash saved: ${result}`);
|
|
38
|
+
} catch (err) {
|
|
39
|
+
error(
|
|
40
|
+
`Stash operation failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|