@devchangjun/ctm 0.1.5 → 0.1.6
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 +87 -38
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -876,8 +876,56 @@ async function cleanCommand(keyArg) {
|
|
|
876
876
|
console.log();
|
|
877
877
|
}
|
|
878
878
|
|
|
879
|
-
// src/commands/
|
|
879
|
+
// src/commands/checkout.ts
|
|
880
880
|
import chalk8 from "chalk";
|
|
881
|
+
import { select as select3, confirm as confirm4 } from "@inquirer/prompts";
|
|
882
|
+
async function checkoutCommand(keyArg) {
|
|
883
|
+
if (!keyArg) {
|
|
884
|
+
console.error(chalk8.red("Usage: ctm co <ticket-key>"));
|
|
885
|
+
process.exit(1);
|
|
886
|
+
}
|
|
887
|
+
const config = ensureConfig();
|
|
888
|
+
const issueKey = resolveIssueKey(keyArg, config.jiraProjectKey);
|
|
889
|
+
const allBranches = await getLocalBranches();
|
|
890
|
+
const matching = allBranches.filter((b) => b.toUpperCase().includes(issueKey));
|
|
891
|
+
if (matching.length === 0) {
|
|
892
|
+
console.error(chalk8.red(`No local branch found for ${issueKey}`));
|
|
893
|
+
process.exit(1);
|
|
894
|
+
}
|
|
895
|
+
let target;
|
|
896
|
+
if (matching.length === 1) {
|
|
897
|
+
target = matching[0];
|
|
898
|
+
} else {
|
|
899
|
+
target = await select3({
|
|
900
|
+
message: `Multiple branches found for ${chalk8.cyan(issueKey)}:`,
|
|
901
|
+
choices: matching.map((b) => ({ value: b, name: b }))
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
const currentBranch = await getCurrentBranch();
|
|
905
|
+
if (currentBranch === target) {
|
|
906
|
+
printWarn(`Already on ${chalk8.cyan(target)}`);
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
if (await hasUncommittedChanges()) {
|
|
910
|
+
printWarn(`Uncommitted changes on "${currentBranch}".`);
|
|
911
|
+
const shouldStash = await confirm4({
|
|
912
|
+
message: "Stash them before switching?",
|
|
913
|
+
default: true
|
|
914
|
+
});
|
|
915
|
+
if (shouldStash) {
|
|
916
|
+
await stashChanges(`ctm: stash before ${target}`);
|
|
917
|
+
printSuccess("Changes stashed.");
|
|
918
|
+
} else {
|
|
919
|
+
printWarn("Checkout aborted to preserve uncommitted changes.");
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
await checkoutBranch(target);
|
|
924
|
+
printSuccess(`Switched to ${chalk8.cyan(target)}`);
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
// src/commands/help.ts
|
|
928
|
+
import chalk9 from "chalk";
|
|
881
929
|
var COMMANDS = [
|
|
882
930
|
{
|
|
883
931
|
name: "init",
|
|
@@ -961,50 +1009,50 @@ var COMMANDS = [
|
|
|
961
1009
|
]
|
|
962
1010
|
}
|
|
963
1011
|
];
|
|
964
|
-
var DIM_RULE =
|
|
1012
|
+
var DIM_RULE = chalk9.dim("\u2500".repeat(56));
|
|
965
1013
|
function renderHeader() {
|
|
966
1014
|
console.log();
|
|
967
|
-
console.log(` ${
|
|
968
|
-
console.log(` ${
|
|
1015
|
+
console.log(` ${chalk9.bold.cyan("ctm")} ${chalk9.dim("\u2014 Colo Ticket Manager")}`);
|
|
1016
|
+
console.log(` ${chalk9.dim("Jira \uD2F0\uCF13 \uAE30\uBC18 Git \uBE0C\uB79C\uCE58 \uAD00\uB9AC CLI")}`);
|
|
969
1017
|
console.log();
|
|
970
1018
|
}
|
|
971
1019
|
function renderUsageLine() {
|
|
972
|
-
console.log(` ${
|
|
1020
|
+
console.log(` ${chalk9.bold("\uC0AC\uC6A9\uBC95")} ${chalk9.cyan("ctm")} ${chalk9.dim("<command>")} ${chalk9.dim("[options]")}`);
|
|
973
1021
|
console.log();
|
|
974
1022
|
}
|
|
975
1023
|
function renderCommandRow(cmd) {
|
|
976
|
-
const aliases = cmd.aliases?.length ?
|
|
977
|
-
const name =
|
|
1024
|
+
const aliases = cmd.aliases?.length ? chalk9.dim(` (${cmd.aliases.join(", ")})`) : "";
|
|
1025
|
+
const name = chalk9.cyan(cmd.name.padEnd(10)) + aliases;
|
|
978
1026
|
const shortDesc = cmd.description.split("\n")[0];
|
|
979
1027
|
console.log(` ${name} ${shortDesc}`);
|
|
980
1028
|
}
|
|
981
1029
|
function renderCommandDetail(cmd) {
|
|
982
|
-
const aliases = cmd.aliases?.length ? " " +
|
|
1030
|
+
const aliases = cmd.aliases?.length ? " " + chalk9.dim(`alias: ${cmd.aliases.join(", ")}`) : "";
|
|
983
1031
|
console.log();
|
|
984
1032
|
console.log(DIM_RULE);
|
|
985
|
-
console.log(` ${
|
|
1033
|
+
console.log(` ${chalk9.bold.cyan(cmd.name)}${aliases}`);
|
|
986
1034
|
console.log();
|
|
987
|
-
console.log(` ${
|
|
1035
|
+
console.log(` ${chalk9.bold("\uC0AC\uC6A9\uBC95")} ${chalk9.cyan(cmd.usage)}`);
|
|
988
1036
|
console.log();
|
|
989
1037
|
for (const line of cmd.description.split("\n")) {
|
|
990
1038
|
console.log(` ${line}`);
|
|
991
1039
|
}
|
|
992
1040
|
console.log();
|
|
993
1041
|
if (cmd.options?.length) {
|
|
994
|
-
console.log(` ${
|
|
1042
|
+
console.log(` ${chalk9.bold("\uC635\uC158")}`);
|
|
995
1043
|
for (const opt of cmd.options) {
|
|
996
|
-
console.log(` ${
|
|
1044
|
+
console.log(` ${chalk9.green(opt.flag.padEnd(26))} ${opt.desc}`);
|
|
997
1045
|
}
|
|
998
1046
|
console.log();
|
|
999
1047
|
}
|
|
1000
|
-
console.log(` ${
|
|
1048
|
+
console.log(` ${chalk9.bold("\uC608\uC2DC")}`);
|
|
1001
1049
|
for (const ex of cmd.examples) {
|
|
1002
|
-
console.log(` ${
|
|
1050
|
+
console.log(` ${chalk9.cyan(ex.cmd.padEnd(38))} ${chalk9.dim(ex.comment)}`);
|
|
1003
1051
|
}
|
|
1004
1052
|
}
|
|
1005
1053
|
function renderWorkflow() {
|
|
1006
1054
|
console.log();
|
|
1007
|
-
console.log(` ${
|
|
1055
|
+
console.log(` ${chalk9.bold("\uC77C\uBC18\uC801\uC778 \uC6CC\uD06C\uD50C\uB85C\uC6B0")}`);
|
|
1008
1056
|
console.log();
|
|
1009
1057
|
const steps = [
|
|
1010
1058
|
["ctm init", "\uCD5C\uCD08 1\uD68C \u2014 Jira \uC5F0\uACB0 \uC124\uC815"],
|
|
@@ -1015,7 +1063,7 @@ function renderWorkflow() {
|
|
|
1015
1063
|
["ctm clean", "\uBA38\uC9C0 \uD6C4 \uBE0C\uB79C\uCE58 \uC815\uB9AC"]
|
|
1016
1064
|
];
|
|
1017
1065
|
for (const [cmd, comment] of steps) {
|
|
1018
|
-
console.log(` ${
|
|
1066
|
+
console.log(` ${chalk9.cyan(cmd.padEnd(24))} ${chalk9.dim(comment)}`);
|
|
1019
1067
|
}
|
|
1020
1068
|
console.log();
|
|
1021
1069
|
}
|
|
@@ -1026,10 +1074,10 @@ function helpCommand(commandName) {
|
|
|
1026
1074
|
);
|
|
1027
1075
|
if (!target) {
|
|
1028
1076
|
console.error(
|
|
1029
|
-
`${
|
|
1077
|
+
`${chalk9.red("\u2717")} \uC54C \uC218 \uC5C6\uB294 \uBA85\uB839\uC5B4: ${chalk9.bold(commandName)}
|
|
1030
1078
|
`
|
|
1031
1079
|
);
|
|
1032
|
-
console.log(` \uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uBA85\uB839\uC5B4: ${COMMANDS.map((c) =>
|
|
1080
|
+
console.log(` \uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uBA85\uB839\uC5B4: ${COMMANDS.map((c) => chalk9.cyan(c.name)).join(", ")}`);
|
|
1033
1081
|
console.log();
|
|
1034
1082
|
process.exit(1);
|
|
1035
1083
|
}
|
|
@@ -1042,21 +1090,21 @@ function helpCommand(commandName) {
|
|
|
1042
1090
|
}
|
|
1043
1091
|
renderHeader();
|
|
1044
1092
|
renderUsageLine();
|
|
1045
|
-
console.log(` ${
|
|
1093
|
+
console.log(` ${chalk9.bold("\uBA85\uB839\uC5B4")}`);
|
|
1046
1094
|
console.log();
|
|
1047
1095
|
for (const cmd of COMMANDS) {
|
|
1048
1096
|
renderCommandRow(cmd);
|
|
1049
1097
|
}
|
|
1050
1098
|
renderWorkflow();
|
|
1051
1099
|
console.log(
|
|
1052
|
-
` ${
|
|
1100
|
+
` ${chalk9.dim(`\uC790\uC138\uD55C \uB3C4\uC6C0\uB9D0: ${chalk9.cyan("ctm help <command>")}`)}`
|
|
1053
1101
|
);
|
|
1054
1102
|
console.log();
|
|
1055
1103
|
}
|
|
1056
1104
|
|
|
1057
1105
|
// src/commands/worktree.ts
|
|
1058
|
-
import
|
|
1059
|
-
import { confirm as
|
|
1106
|
+
import chalk10 from "chalk";
|
|
1107
|
+
import { confirm as confirm5 } from "@inquirer/prompts";
|
|
1060
1108
|
import ora7 from "ora";
|
|
1061
1109
|
async function worktreeListCommand() {
|
|
1062
1110
|
let trees;
|
|
@@ -1068,23 +1116,23 @@ async function worktreeListCommand() {
|
|
|
1068
1116
|
}
|
|
1069
1117
|
console.log();
|
|
1070
1118
|
if (trees.length === 0) {
|
|
1071
|
-
console.log(
|
|
1119
|
+
console.log(chalk10.dim(" No worktrees found.\n"));
|
|
1072
1120
|
return;
|
|
1073
1121
|
}
|
|
1074
1122
|
console.log(
|
|
1075
1123
|
` ${"PATH".padEnd(52)} ${"BRANCH".padEnd(30)} HEAD`
|
|
1076
1124
|
);
|
|
1077
|
-
console.log(
|
|
1125
|
+
console.log(chalk10.dim(` ${"\u2500".repeat(52)} ${"\u2500".repeat(30)} ${"\u2500".repeat(7)}`));
|
|
1078
1126
|
for (const t of trees) {
|
|
1079
|
-
const pathLabel = t.isMain ? `${t.path} ${
|
|
1127
|
+
const pathLabel = t.isMain ? `${t.path} ${chalk10.dim("(main)")}` : t.path;
|
|
1080
1128
|
const branchDisplay = t.branch.replace("refs/heads/", "");
|
|
1081
1129
|
const shortHead = t.head.slice(0, 7);
|
|
1082
|
-
const pathCol =
|
|
1083
|
-
const branchCol = t.isMain ?
|
|
1084
|
-
console.log(` ${pathCol.padEnd(52)} ${branchCol.padEnd(30)} ${
|
|
1130
|
+
const pathCol = chalk10.cyan(pathLabel.length > 50 ? "\u2026" + pathLabel.slice(-49) : pathLabel);
|
|
1131
|
+
const branchCol = t.isMain ? chalk10.dim(branchDisplay) : chalk10.white(branchDisplay);
|
|
1132
|
+
console.log(` ${pathCol.padEnd(52)} ${branchCol.padEnd(30)} ${chalk10.dim(shortHead)}`);
|
|
1085
1133
|
}
|
|
1086
1134
|
console.log();
|
|
1087
|
-
console.log(
|
|
1135
|
+
console.log(chalk10.dim(` ${trees.length} worktree(s) \xB7 ctm wt rm [key] to remove`));
|
|
1088
1136
|
console.log();
|
|
1089
1137
|
}
|
|
1090
1138
|
async function worktreeRemoveCommand(keyArg, options) {
|
|
@@ -1101,7 +1149,7 @@ async function worktreeRemoveCommand(keyArg, options) {
|
|
|
1101
1149
|
branchName = match;
|
|
1102
1150
|
} else {
|
|
1103
1151
|
printError("Please specify an issue key: ctm wt rm <key>");
|
|
1104
|
-
console.log(
|
|
1152
|
+
console.log(chalk10.dim(" Example: ctm wt rm CGKR-1423 or ctm wt rm 1423"));
|
|
1105
1153
|
process.exit(1);
|
|
1106
1154
|
}
|
|
1107
1155
|
const tree = await findWorktreeForBranch(branchName);
|
|
@@ -1113,7 +1161,7 @@ async function worktreeRemoveCommand(keyArg, options) {
|
|
|
1113
1161
|
);
|
|
1114
1162
|
if (!fuzzy) {
|
|
1115
1163
|
printWarn(`No worktree found for branch "${branchName}".`);
|
|
1116
|
-
console.log(
|
|
1164
|
+
console.log(chalk10.dim(" Use ctm wt to see existing worktrees."));
|
|
1117
1165
|
process.exit(0);
|
|
1118
1166
|
}
|
|
1119
1167
|
return doRemove(fuzzy, branchName, options);
|
|
@@ -1123,10 +1171,10 @@ async function worktreeRemoveCommand(keyArg, options) {
|
|
|
1123
1171
|
async function doRemove(tree, branchName, options) {
|
|
1124
1172
|
const branchDisplay = tree.branch.replace("refs/heads/", "");
|
|
1125
1173
|
console.log();
|
|
1126
|
-
console.log(` ${
|
|
1127
|
-
console.log(` ${
|
|
1174
|
+
console.log(` ${chalk10.bold("Worktree:")} ${chalk10.cyan(tree.path)}`);
|
|
1175
|
+
console.log(` ${chalk10.bold("Branch:")} ${chalk10.cyan(branchDisplay)}`);
|
|
1128
1176
|
console.log();
|
|
1129
|
-
const confirmed = await
|
|
1177
|
+
const confirmed = await confirm5({
|
|
1130
1178
|
message: `Remove worktree at "${tree.path}"?`,
|
|
1131
1179
|
default: false
|
|
1132
1180
|
});
|
|
@@ -1134,13 +1182,13 @@ async function doRemove(tree, branchName, options) {
|
|
|
1134
1182
|
const spinner = ora7("Removing worktree\u2026").start();
|
|
1135
1183
|
try {
|
|
1136
1184
|
await removeWorktree(tree.path, options.force);
|
|
1137
|
-
spinner.succeed(`Worktree removed: ${
|
|
1185
|
+
spinner.succeed(`Worktree removed: ${chalk10.cyan(tree.path)}`);
|
|
1138
1186
|
} catch (err) {
|
|
1139
1187
|
spinner.fail(`Failed to remove worktree: ${String(err)}`);
|
|
1140
|
-
console.log(
|
|
1188
|
+
console.log(chalk10.dim(" Try: ctm wt rm <key> --force"));
|
|
1141
1189
|
process.exit(1);
|
|
1142
1190
|
}
|
|
1143
|
-
const deleteBranch = options.branch ?? await
|
|
1191
|
+
const deleteBranch = options.branch ?? await confirm5({
|
|
1144
1192
|
message: `Also delete branch "${branchDisplay}"?`,
|
|
1145
1193
|
default: false
|
|
1146
1194
|
});
|
|
@@ -1151,7 +1199,7 @@ async function doRemove(tree, branchName, options) {
|
|
|
1151
1199
|
} catch (err) {
|
|
1152
1200
|
printWarn(`Could not delete local branch: ${String(err)}`);
|
|
1153
1201
|
}
|
|
1154
|
-
const deleteRemote = await
|
|
1202
|
+
const deleteRemote = await confirm5({
|
|
1155
1203
|
message: `Also delete remote branch origin/${branchDisplay}?`,
|
|
1156
1204
|
default: false
|
|
1157
1205
|
});
|
|
@@ -1177,6 +1225,7 @@ program.command("issues").alias("ls").description("List Jira issues assigned to
|
|
|
1177
1225
|
program.command("start [key]").description("Create and checkout a branch for a Jira issue (e.g. CTM-123 or just 123)").option("-w, --worktree", "Create a linked worktree instead of switching branches").action(startCommand);
|
|
1178
1226
|
program.command("done [key]").description("Push branch, create PR, and mark the Jira issue as Done").action(doneCommand);
|
|
1179
1227
|
program.command("status").alias("st").description("Show current branch status and linked Jira issue").action(statusCommand);
|
|
1228
|
+
program.command("checkout [key]").alias("co").description("Checkout a branch by Jira issue key (e.g. CTM-123 or just 123)").action(checkoutCommand);
|
|
1180
1229
|
program.command("clean [key]").description("Delete local (and optionally remote) branch for a Jira issue").action(cleanCommand);
|
|
1181
1230
|
program.command("help [command]").description("\uBA85\uB839\uC5B4 \uB3C4\uC6C0\uB9D0 \uCD9C\uB825").action(helpCommand);
|
|
1182
1231
|
var wt = program.command("worktree").alias("wt").description("Manage git worktrees created by ctm start --worktree");
|