@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/help.ts
CHANGED
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
import type { Command } from "commander";
|
|
2
|
-
import { newline, text } from "../lib/logger.js";
|
|
3
|
-
import { createTable
|
|
4
|
-
|
|
5
|
-
const commands: { name: string; description: string }[] = [
|
|
6
|
-
{ name: "setup", description: "Interactive setup wizard" },
|
|
7
|
-
{ name: "commit", description: "Create a commit (interactive or quick)" },
|
|
8
|
-
{ name: "push", description: "Push to remote" },
|
|
9
|
-
{ name: "sync", description: "Pull with rebase" },
|
|
10
|
-
{ name: "fetch", description: "Fetch from remote" },
|
|
11
|
-
{ name: "status", description: "Show detailed repository status" },
|
|
12
|
-
{ name: "log", description: "Show commit history" },
|
|
13
|
-
{ name: "diff", description: "Show changes" },
|
|
14
|
-
{ name: "branch", description: "Manage branches" },
|
|
15
|
-
{ name: "stash", description: "Manage stashes" },
|
|
16
|
-
{ name: "tag", description: "Manage tags" },
|
|
17
|
-
{ name: "alias", description: "Manage aliases" },
|
|
18
|
-
{ name: "config", description: "Manage configuration" },
|
|
19
|
-
{ name: "undo", description: "Undo last commit (soft reset)" },
|
|
20
|
-
{ name: "reset", description: "Reset all configuration" },
|
|
21
|
-
{ name: "help", description: "Show this help" },
|
|
22
|
-
{ name: "version", description: "Show version" },
|
|
23
|
-
];
|
|
24
|
-
|
|
25
|
-
export default function register(program: Command): void {
|
|
26
|
-
program
|
|
27
|
-
.command("help")
|
|
28
|
-
.description("Show comprehensive help")
|
|
29
|
-
.action(async () => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const rows = commands.map((c) => [c.name, c.description]);
|
|
33
|
-
text(createTable(["Command", "Description"], rows));
|
|
34
|
-
|
|
35
|
-
newline();
|
|
36
|
-
|
|
37
|
-
text("");
|
|
38
|
-
text(" fg setup Start interactive setup");
|
|
39
|
-
text(' fg commit -m "fix: resolve issue" Quick commit with message');
|
|
40
|
-
text(" fg commit Interactive commit");
|
|
41
|
-
text(" fg push Push current branch");
|
|
42
|
-
text(
|
|
43
|
-
" fg push --force Force push (with confirmation)",
|
|
44
|
-
);
|
|
45
|
-
text(" fg status Show repository status");
|
|
46
|
-
text(" fg log -n 20 Show last 20 commits");
|
|
47
|
-
text(" fg branch -n feature-x Create a new branch");
|
|
48
|
-
text(" fg branch -s feature-x Switch to a branch");
|
|
49
|
-
text(" fg sync Pull with rebase");
|
|
50
|
-
text(" fg diff --staged Show staged changes");
|
|
51
|
-
text(" fg stash Stash changes");
|
|
52
|
-
text(" fg stash --pop Apply latest stash");
|
|
53
|
-
text(" fg alias add co checkout Create an alias");
|
|
54
|
-
text(" fg config --show View configuration");
|
|
55
|
-
text(" fg config --edit Edit configuration");
|
|
56
|
-
newline();
|
|
57
|
-
});
|
|
58
|
-
}
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { newline, text } from "../lib/logger.js";
|
|
3
|
+
import { createTable } from "../lib/ui.js";
|
|
4
|
+
|
|
5
|
+
const commands: { name: string; description: string }[] = [
|
|
6
|
+
{ name: "setup", description: "Interactive setup wizard" },
|
|
7
|
+
{ name: "commit", description: "Create a commit (interactive or quick)" },
|
|
8
|
+
{ name: "push", description: "Push to remote" },
|
|
9
|
+
{ name: "sync", description: "Pull with rebase" },
|
|
10
|
+
{ name: "fetch", description: "Fetch from remote" },
|
|
11
|
+
{ name: "status", description: "Show detailed repository status" },
|
|
12
|
+
{ name: "log", description: "Show commit history" },
|
|
13
|
+
{ name: "diff", description: "Show changes" },
|
|
14
|
+
{ name: "branch", description: "Manage branches" },
|
|
15
|
+
{ name: "stash", description: "Manage stashes" },
|
|
16
|
+
{ name: "tag", description: "Manage tags" },
|
|
17
|
+
{ name: "alias", description: "Manage aliases" },
|
|
18
|
+
{ name: "config", description: "Manage configuration" },
|
|
19
|
+
{ name: "undo", description: "Undo last commit (soft reset)" },
|
|
20
|
+
{ name: "reset", description: "Reset all configuration" },
|
|
21
|
+
{ name: "help", description: "Show this help" },
|
|
22
|
+
{ name: "version", description: "Show version" },
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
export default function register(program: Command): void {
|
|
26
|
+
program
|
|
27
|
+
.command("help")
|
|
28
|
+
.description("Show comprehensive help")
|
|
29
|
+
.action(async () => {
|
|
30
|
+
text("Forge - Git CLI");
|
|
31
|
+
|
|
32
|
+
const rows = commands.map((c) => [c.name, c.description]);
|
|
33
|
+
text(createTable(["Command", "Description"], rows));
|
|
34
|
+
|
|
35
|
+
newline();
|
|
36
|
+
text("Usage Examples");
|
|
37
|
+
text("");
|
|
38
|
+
text(" fg setup Start interactive setup");
|
|
39
|
+
text(' fg commit -m "fix: resolve issue" Quick commit with message');
|
|
40
|
+
text(" fg commit Interactive commit");
|
|
41
|
+
text(" fg push Push current branch");
|
|
42
|
+
text(
|
|
43
|
+
" fg push --force Force push (with confirmation)",
|
|
44
|
+
);
|
|
45
|
+
text(" fg status Show repository status");
|
|
46
|
+
text(" fg log -n 20 Show last 20 commits");
|
|
47
|
+
text(" fg branch -n feature-x Create a new branch");
|
|
48
|
+
text(" fg branch -s feature-x Switch to a branch");
|
|
49
|
+
text(" fg sync Pull with rebase");
|
|
50
|
+
text(" fg diff --staged Show staged changes");
|
|
51
|
+
text(" fg stash Stash changes");
|
|
52
|
+
text(" fg stash --pop Apply latest stash");
|
|
53
|
+
text(" fg alias add co checkout Create an alias");
|
|
54
|
+
text(" fg config --show View configuration");
|
|
55
|
+
text(" fg config --edit Edit configuration");
|
|
56
|
+
newline();
|
|
57
|
+
});
|
|
58
|
+
}
|
package/src/commands/init.ts
CHANGED
|
@@ -1,37 +1,32 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
.
|
|
11
|
-
.
|
|
12
|
-
.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
`Init failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
}
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import * as git from "../lib/git.js";
|
|
3
|
+
import { error, text } from "../lib/logger.js";
|
|
4
|
+
|
|
5
|
+
export default function register(program: Command): void {
|
|
6
|
+
program
|
|
7
|
+
.command("init")
|
|
8
|
+
.description("Initialize a new Git repository")
|
|
9
|
+
.argument("[dir]", "Target directory")
|
|
10
|
+
.option("--initial-commit", "Create an initial commit")
|
|
11
|
+
.option("--branch <name>", "Set initial branch name")
|
|
12
|
+
.action(async (dir, options) => {
|
|
13
|
+
try {
|
|
14
|
+
const targetDir = dir || ".";
|
|
15
|
+
|
|
16
|
+
await git.init(dir, { initialBranch: options.branch });
|
|
17
|
+
|
|
18
|
+
if (options.initialCommit) {
|
|
19
|
+
await git.commit("Initial commit");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const content = [`Path: ${targetDir}`].join("\n");
|
|
23
|
+
text(content);
|
|
24
|
+
|
|
25
|
+
text(`Git repository initialized at ${targetDir}.`);
|
|
26
|
+
} catch (err) {
|
|
27
|
+
error(
|
|
28
|
+
`Init failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { createIssue, listIssues } from "../lib/github.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
|
+
const issue = program.command("issue").description("Manage issues");
|
|
8
|
+
|
|
9
|
+
issue
|
|
10
|
+
.command("create")
|
|
11
|
+
.description("Create an issue")
|
|
12
|
+
.option("-t, --title <title>", "Issue title")
|
|
13
|
+
.action(async (options) => {
|
|
14
|
+
try {
|
|
15
|
+
const title = options.title || (await input("Issue title"));
|
|
16
|
+
if (!title) {
|
|
17
|
+
error("Title is required.");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const body = await input("Description (optional)");
|
|
21
|
+
const result = await withSpinner("Creating issue...", () =>
|
|
22
|
+
createIssue(title, body),
|
|
23
|
+
);
|
|
24
|
+
text(`Issue #${result.number} created: ${result.url}`);
|
|
25
|
+
} catch (err) {
|
|
26
|
+
error(
|
|
27
|
+
`Issue creation failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
issue
|
|
33
|
+
.command("list")
|
|
34
|
+
.description("List issues")
|
|
35
|
+
.option(
|
|
36
|
+
"-s, --state <state>",
|
|
37
|
+
"Filter by state (open, closed, all)",
|
|
38
|
+
"open",
|
|
39
|
+
)
|
|
40
|
+
.action(async (options) => {
|
|
41
|
+
try {
|
|
42
|
+
const issues = await withSpinner("Fetching issues...", () =>
|
|
43
|
+
listIssues(options.state),
|
|
44
|
+
);
|
|
45
|
+
if (issues.length === 0) {
|
|
46
|
+
text("No issues found.");
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const rows = issues.map((i) => [
|
|
50
|
+
`#${i.number}`,
|
|
51
|
+
i.title.substring(0, 60),
|
|
52
|
+
i.state,
|
|
53
|
+
i.author,
|
|
54
|
+
]);
|
|
55
|
+
text("Issues:");
|
|
56
|
+
text(createTable(["#", "Title", "State", "Author"], rows));
|
|
57
|
+
} catch (err) {
|
|
58
|
+
error(
|
|
59
|
+
`Failed to list issues: ${err instanceof Error ? err.message : String(err)}`,
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
package/src/commands/log.ts
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import type { Command } from "commander";
|
|
2
|
-
import * as git from "../lib/git.js";
|
|
3
|
-
import {
|
|
4
|
-
import { createTable } from "../lib/ui.js";
|
|
5
|
-
|
|
6
|
-
export default function register(program: Command): void {
|
|
7
|
-
program
|
|
8
|
-
.command("log")
|
|
9
|
-
.description("Show commit history")
|
|
10
|
-
.option("-n, --number <count>", "Number of commits", "10")
|
|
11
|
-
.action(async (options) => {
|
|
12
|
-
try {
|
|
13
|
-
const count = parseInt(options.number, 10) || 10;
|
|
14
|
-
const commits = await git.log(count);
|
|
15
|
-
|
|
16
|
-
const rows = commits.map((c) => [
|
|
17
|
-
c.hash.substring(0, 7),
|
|
18
|
-
c.date.substring(0, 10),
|
|
19
|
-
c.author,
|
|
20
|
-
c.message.substring(0, 60),
|
|
21
|
-
]);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
} catch (err) {
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
}
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import * as git from "../lib/git.js";
|
|
3
|
+
import { text } from "../lib/logger.js";
|
|
4
|
+
import { createTable } from "../lib/ui.js";
|
|
5
|
+
|
|
6
|
+
export default function register(program: Command): void {
|
|
7
|
+
program
|
|
8
|
+
.command("log")
|
|
9
|
+
.description("Show commit history")
|
|
10
|
+
.option("-n, --number <count>", "Number of commits", "10")
|
|
11
|
+
.action(async (options) => {
|
|
12
|
+
try {
|
|
13
|
+
const count = parseInt(options.number, 10) || 10;
|
|
14
|
+
const commits = await git.log(count);
|
|
15
|
+
|
|
16
|
+
const rows = commits.map((c) => [
|
|
17
|
+
c.hash.substring(0, 7),
|
|
18
|
+
c.date.substring(0, 10),
|
|
19
|
+
c.author,
|
|
20
|
+
c.message.substring(0, 60),
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
text(`Last ${commits.length} commits:`);
|
|
24
|
+
text(createTable(["Hash", "Date", "Author", "Message"], rows));
|
|
25
|
+
} catch (err) {
|
|
26
|
+
text(`Log: ${err instanceof Error ? err.message : String(err)}`);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
package/src/commands/merge.ts
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
import type { Command } from "commander";
|
|
2
|
-
import * as git from "../lib/git.js";
|
|
3
|
-
import { error,
|
|
4
|
-
|
|
5
|
-
export default function register(program: Command): void {
|
|
6
|
-
program
|
|
7
|
-
.command("merge")
|
|
8
|
-
.description("Merge branches")
|
|
9
|
-
.argument("<branch>", "Branch to merge into current")
|
|
10
|
-
.option(
|
|
11
|
-
"--no-ff",
|
|
12
|
-
"Create a merge commit even when fast-forward is possible",
|
|
13
|
-
)
|
|
14
|
-
.option("--squash", "Squash commits into one")
|
|
15
|
-
.option("--no-commit", "Perform merge but do not commit")
|
|
16
|
-
.action(
|
|
17
|
-
async (
|
|
18
|
-
branch: string,
|
|
19
|
-
options: { noFF?: boolean; squash?: boolean; noCommit?: boolean },
|
|
20
|
-
) => {
|
|
21
|
-
try {
|
|
22
|
-
const currentBranch = await git.getCurrentBranch();
|
|
23
|
-
|
|
24
|
-
const result = await git.merge(branch, {
|
|
25
|
-
noFF: options.noFF ?? undefined,
|
|
26
|
-
squash: options.squash ?? undefined,
|
|
27
|
-
noCommit: options.noCommit ?? undefined,
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
} catch (err) {
|
|
31
|
-
error(
|
|
32
|
-
`Merge failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
);
|
|
37
|
-
}
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import * as git from "../lib/git.js";
|
|
3
|
+
import { error, text } from "../lib/logger.js";
|
|
4
|
+
|
|
5
|
+
export default function register(program: Command): void {
|
|
6
|
+
program
|
|
7
|
+
.command("merge")
|
|
8
|
+
.description("Merge branches")
|
|
9
|
+
.argument("<branch>", "Branch to merge into current")
|
|
10
|
+
.option(
|
|
11
|
+
"--no-ff",
|
|
12
|
+
"Create a merge commit even when fast-forward is possible",
|
|
13
|
+
)
|
|
14
|
+
.option("--squash", "Squash commits into one")
|
|
15
|
+
.option("--no-commit", "Perform merge but do not commit")
|
|
16
|
+
.action(
|
|
17
|
+
async (
|
|
18
|
+
branch: string,
|
|
19
|
+
options: { noFF?: boolean; squash?: boolean; noCommit?: boolean },
|
|
20
|
+
) => {
|
|
21
|
+
try {
|
|
22
|
+
const currentBranch = await git.getCurrentBranch();
|
|
23
|
+
text(`Merging '${branch}' into '${currentBranch}'...`);
|
|
24
|
+
const result = await git.merge(branch, {
|
|
25
|
+
noFF: options.noFF ?? undefined,
|
|
26
|
+
squash: options.squash ?? undefined,
|
|
27
|
+
noCommit: options.noCommit ?? undefined,
|
|
28
|
+
});
|
|
29
|
+
text(`Merge completed: ${result}`);
|
|
30
|
+
} catch (err) {
|
|
31
|
+
error(
|
|
32
|
+
`Merge failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { createPR, listPRs } from "../lib/github.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
|
+
const pr = program.command("pr").description("Manage pull requests");
|
|
8
|
+
|
|
9
|
+
pr.command("create")
|
|
10
|
+
.description("Create a pull request")
|
|
11
|
+
.option("-t, --title <title>", "PR title")
|
|
12
|
+
.option("-H, --head <branch>", "Source branch (default: current branch)")
|
|
13
|
+
.option("-B, --base <branch>", "Target branch (default: main)")
|
|
14
|
+
.action(async (options) => {
|
|
15
|
+
try {
|
|
16
|
+
const title = options.title || (await input("PR title"));
|
|
17
|
+
if (!title) {
|
|
18
|
+
error("Title is required.");
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const head = options.head || (await input("Source branch"));
|
|
22
|
+
const base = options.base || (await input("Target branch", "main"));
|
|
23
|
+
const body = await input("Description (optional)");
|
|
24
|
+
const result = await withSpinner("Creating PR...", () =>
|
|
25
|
+
createPR(title, body, head, base),
|
|
26
|
+
);
|
|
27
|
+
text(`PR #${result.number} created: ${result.url}`);
|
|
28
|
+
} catch (err) {
|
|
29
|
+
error(
|
|
30
|
+
`PR creation failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
pr.command("list")
|
|
36
|
+
.description("List pull requests")
|
|
37
|
+
.option(
|
|
38
|
+
"-s, --state <state>",
|
|
39
|
+
"Filter by state (open, closed, all)",
|
|
40
|
+
"open",
|
|
41
|
+
)
|
|
42
|
+
.action(async (options) => {
|
|
43
|
+
try {
|
|
44
|
+
const prs = await withSpinner("Fetching PRs...", () =>
|
|
45
|
+
listPRs(options.state),
|
|
46
|
+
);
|
|
47
|
+
if (prs.length === 0) {
|
|
48
|
+
text("No pull requests found.");
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const rows = prs.map((p) => [
|
|
52
|
+
`#${p.number}`,
|
|
53
|
+
p.title.substring(0, 60),
|
|
54
|
+
p.state,
|
|
55
|
+
p.author,
|
|
56
|
+
]);
|
|
57
|
+
text("Pull Requests:");
|
|
58
|
+
text(createTable(["#", "Title", "State", "Author"], rows));
|
|
59
|
+
} catch (err) {
|
|
60
|
+
error(
|
|
61
|
+
`Failed to list PRs: ${err instanceof Error ? err.message : String(err)}`,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
package/src/commands/push.ts
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
import type { Command } from "commander";
|
|
2
|
-
import * as git from "../lib/git.js";
|
|
3
|
-
import { error,
|
|
4
|
-
import { confirm, withSpinner } from "../lib/ui.js";
|
|
5
|
-
|
|
6
|
-
export default function register(program: Command): void {
|
|
7
|
-
program
|
|
8
|
-
.command("push")
|
|
9
|
-
.description("Push to remote")
|
|
10
|
-
.option("--force", "Force push (with warning)")
|
|
11
|
-
.action(async (options) => {
|
|
12
|
-
try {
|
|
13
|
-
const branch = await git.getCurrentBranch();
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (options.force) {
|
|
17
|
-
warning("Force push will overwrite remote history.");
|
|
18
|
-
const proceed = await confirm("Are you sure you want to force push?");
|
|
19
|
-
if (!proceed) {
|
|
20
|
-
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const result = await withSpinner("Pushing...", () =>
|
|
26
|
-
git.push(!!options.force),
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
} catch (err) {
|
|
30
|
-
error(
|
|
31
|
-
`Push failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
}
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import * as git from "../lib/git.js";
|
|
3
|
+
import { error, text, warning } from "../lib/logger.js";
|
|
4
|
+
import { confirm, withSpinner } from "../lib/ui.js";
|
|
5
|
+
|
|
6
|
+
export default function register(program: Command): void {
|
|
7
|
+
program
|
|
8
|
+
.command("push")
|
|
9
|
+
.description("Push to remote")
|
|
10
|
+
.option("--force", "Force push (with warning)")
|
|
11
|
+
.action(async (options) => {
|
|
12
|
+
try {
|
|
13
|
+
const branch = await git.getCurrentBranch();
|
|
14
|
+
text(`Pushing to origin/${branch}`);
|
|
15
|
+
|
|
16
|
+
if (options.force) {
|
|
17
|
+
warning("Force push will overwrite remote history.");
|
|
18
|
+
const proceed = await confirm("Are you sure you want to force push?");
|
|
19
|
+
if (!proceed) {
|
|
20
|
+
text("Push cancelled.");
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const result = await withSpinner("Pushing...", () =>
|
|
26
|
+
git.push(!!options.force),
|
|
27
|
+
);
|
|
28
|
+
text(`Push complete: ${result}`);
|
|
29
|
+
} catch (err) {
|
|
30
|
+
error(
|
|
31
|
+
`Push failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { createRelease } from "../lib/github.js";
|
|
3
|
+
import { error, text } from "../lib/logger.js";
|
|
4
|
+
import { input, withSpinner } from "../lib/ui.js";
|
|
5
|
+
|
|
6
|
+
export default function register(program: Command): void {
|
|
7
|
+
program
|
|
8
|
+
.command("release")
|
|
9
|
+
.description("Create a GitHub release")
|
|
10
|
+
.argument("<tag>", "Git tag name")
|
|
11
|
+
.option("-n, --name <name>", "Release name")
|
|
12
|
+
.action(async (tag, options) => {
|
|
13
|
+
try {
|
|
14
|
+
const name = options.name || (await input("Release name", tag));
|
|
15
|
+
const body = await input("Release description (optional)");
|
|
16
|
+
const result = await withSpinner("Creating release...", () =>
|
|
17
|
+
createRelease(tag, name, body),
|
|
18
|
+
);
|
|
19
|
+
text(`Release created: ${result.url}`);
|
|
20
|
+
} catch (err) {
|
|
21
|
+
error(
|
|
22
|
+
`Release creation failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|