@g-abhishek/gitx 0.1.4 โ 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/README.md +82 -13
- package/dist/ai/claudeAi.d.ts.map +1 -1
- package/dist/ai/claudeAi.js +4 -30
- package/dist/ai/claudeAi.js.map +1 -1
- package/dist/ai/claudeCliAi.d.ts.map +1 -1
- package/dist/ai/claudeCliAi.js +4 -21
- package/dist/ai/claudeCliAi.js.map +1 -1
- package/dist/ai/openAiAi.d.ts.map +1 -1
- package/dist/ai/openAiAi.js +4 -30
- package/dist/ai/openAiAi.js.map +1 -1
- package/dist/ai/reviewHelpers.d.ts +24 -0
- package/dist/ai/reviewHelpers.d.ts.map +1 -1
- package/dist/ai/reviewHelpers.js +123 -39
- package/dist/ai/reviewHelpers.js.map +1 -1
- package/dist/cli/commands/pr/cherryPick.d.ts +25 -0
- package/dist/cli/commands/pr/cherryPick.d.ts.map +1 -0
- package/dist/cli/commands/pr/cherryPick.js +317 -0
- package/dist/cli/commands/pr/cherryPick.js.map +1 -0
- package/dist/cli/commands/pr/fixComments.d.ts +5 -2
- package/dist/cli/commands/pr/fixComments.d.ts.map +1 -1
- package/dist/cli/commands/pr/fixComments.js +5 -82
- package/dist/cli/commands/pr/fixComments.js.map +1 -1
- package/dist/cli/commands/pr/index.d.ts.map +1 -1
- package/dist/cli/commands/pr/index.js +6 -2
- package/dist/cli/commands/pr/index.js.map +1 -1
- package/dist/cli/commands/pr/port.d.ts +34 -0
- package/dist/cli/commands/pr/port.d.ts.map +1 -0
- package/dist/cli/commands/pr/port.js +453 -0
- package/dist/cli/commands/pr/port.js.map +1 -0
- package/dist/cli/commands/pr/resolve.d.ts +3 -0
- package/dist/cli/commands/pr/resolve.d.ts.map +1 -0
- package/dist/cli/commands/pr/resolve.js +92 -0
- package/dist/cli/commands/pr/resolve.js.map +1 -0
- package/dist/cli/commands/pr/review.js +1 -1
- package/dist/cli/commands/pr/review.js.map +1 -1
- package/dist/cli/commands/sync.d.ts +12 -11
- package/dist/cli/commands/sync.d.ts.map +1 -1
- package/dist/cli/commands/sync.js +13 -101
- package/dist/cli/commands/sync.js.map +1 -1
- package/dist/utils/gitOps.d.ts +11 -4
- package/dist/utils/gitOps.d.ts.map +1 -1
- package/dist/utils/gitOps.js +53 -37
- package/dist/utils/gitOps.js.map +1 -1
- package/dist/workflows/pr.d.ts +1 -1
- package/dist/workflows/pr.d.ts.map +1 -1
- package/dist/workflows/pr.js +82 -19
- package/dist/workflows/pr.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../../src/cli/commands/pr/resolve.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport inquirer from \"inquirer\";\nimport { logger } from \"../../../logger/logger.js\";\nimport { Gitx } from \"../../../core/gitx.js\";\nimport { runFixCommentsWorkflow } from \"../../../workflows/pr.js\";\nimport { pushBranch, getCurrentBranch, isWorkingTreeDirty } from \"../../../utils/gitOps.js\";\n\nexport function registerPrResolveCommand(pr: Command): void {\n pr.command(\"resolve\")\n .description(\"๐ง AI-resolve review comments: applies code fixes, commits, and pushes\")\n .argument(\"<id>\", \"Pull request number\")\n .option(\"--dry-run\", \"Preview fixes without applying or committing\", false)\n .option(\"--no-commit\", \"Apply fixes to working tree only โ skip commit and push\", false)\n .option(\"--no-push\", \"Apply & commit locally but skip push\", false)\n .action(async (id: string, options: { dryRun: boolean; commit: boolean; push: boolean }) => {\n const prNumber = parseInt(id, 10);\n if (isNaN(prNumber) || prNumber <= 0) {\n logger.error(`Invalid PR number: ${id}`);\n process.exit(1);\n }\n\n // Commander sets options.commit = false when --no-commit is passed\n const noCommit = options.commit === false;\n\n const gitx = await Gitx.fromCwd();\n const ctx = await gitx.getRepoContext();\n logger.info(`๐ง Resolving review comments on PR #${prNumber} (${ctx.repoSlug})โฆ\\n`);\n\n // โโ AI availability check โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (!await Gitx.isAiAvailable(gitx.config)) {\n logger.warn(\n \"โ ๏ธ No AI provider configured โ cannot generate fixes.\\n\" +\n \" Run `gitx config` to set up an AI provider (Claude, OpenAI, or claude-cli).\"\n );\n return;\n }\n\n // โโ Confirmation prompt โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (!options.dryRun) {\n const modeDesc = noCommit\n ? \"apply fixes to your working tree only (no commit or push)\"\n : options.push === false\n ? \"apply fixes and commit locally (no push)\"\n : \"apply fixes, commit, and push\";\n\n const { proceed } = await inquirer.prompt<{ proceed: boolean }>([\n {\n type: \"confirm\",\n name: \"proceed\",\n message: `This will ${modeDesc}. Continue?`,\n default: false,\n },\n ]);\n if (!proceed) {\n logger.warn(\"Cancelled.\");\n return;\n }\n }\n\n // โโ Guard: warn about uncommitted changes โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (!options.dryRun) {\n const dirty = await isWorkingTreeDirty(gitx.cwd);\n if (dirty) {\n logger.warn(\"โ ๏ธ You have uncommitted changes. They may conflict with applied fixes.\");\n const { cont } = await inquirer.prompt<{ cont: boolean }>([\n { type: \"confirm\", name: \"cont\", message: \"Continue anyway?\", default: false },\n ]);\n if (!cont) { logger.warn(\"Cancelled.\"); return; }\n }\n }\n\n const result = await runFixCommentsWorkflow(gitx, prNumber, options.dryRun, noCommit);\n\n logger.info(`\\n๐ PR: ${result.pr.title}`);\n\n if (result.appliedFixes.length === 0 && result.skippedFixes.length === 0) {\n logger.info(\"No actionable review comments found.\");\n return;\n }\n\n if (result.appliedFixes.length > 0) {\n logger.success(`\\nโ
Applied ${result.appliedFixes.length} fix(es):`);\n result.appliedFixes.forEach((f) => logger.info(` โข ${f.path} โ ${f.rationale}`));\n }\n\n if (result.skippedFixes.length > 0) {\n logger.warn(`\\nโ ๏ธ Skipped ${result.skippedFixes.length} fix(es):`);\n result.skippedFixes.forEach((f) => logger.warn(` โข ${f.path}: ${f.reason}`));\n }\n\n // โโ Push if applicable โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (!options.dryRun && !noCommit && options.push !== false && result.appliedFixes.length > 0) {\n const branch = await getCurrentBranch(gitx.cwd);\n logger.info(`\\n๐ Pushing ${branch}โฆ`);\n try {\n await pushBranch(branch, gitx.cwd);\n logger.success(\"Branch pushed.\");\n } catch (err) {\n logger.warn(`Push failed: ${String((err as Error).message ?? err)}`);\n }\n }\n });\n}\n"]}
|
|
@@ -123,7 +123,7 @@ export function registerPrReviewCommand(pr) {
|
|
|
123
123
|
logger.warn("โ ๏ธ Review could not be posted to the PR (see error above).\n" +
|
|
124
124
|
" The full review is shown above โ you can copy it manually.");
|
|
125
125
|
}
|
|
126
|
-
// To
|
|
126
|
+
// To resolve the review comments, run: gitx pr resolve <PR_number>
|
|
127
127
|
});
|
|
128
128
|
}
|
|
129
129
|
//# sourceMappingURL=review.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review.js","sourceRoot":"","sources":["../../../../src/cli/commands/pr/review.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,UAAU,uBAAuB,CAAC,EAAW;IACjD,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,8DAA8D,CAAC;SAC3E,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;SACvC,MAAM,CAAC,cAAc,EAAE,8CAA8C,CAAC;SACtE,MAAM,CAAC,aAAa,EAAE,mDAAmD,CAAC;SAC1E,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,OAA8C,EAAE,EAAE;QAC3E,MAAM,QAAQ,GAAG,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAClC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;YACrC,MAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAElC,IAAI,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3C,MAAM,CAAC,IAAI,CACT,kEAAkE;gBAClE,8DAA8D,CAC/D,CAAC;YACF,OAAO;QACT,CAAC;QAED,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,KAAK,KAAK,CAAC;QAE9C,MAAM,CAAC,IAAI,CAAC,mCAAmC,QAAQ,IAAI,CAAC,CAAC;QAE7D,IAAI,MAAqD,CAAC;QAC1D,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;QAChE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,kBAAkB,MAAM,CAAE,GAAa,CAAC,OAAO,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC;YACxE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QAED,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC;QAEjD,yEAAyE;QACzE,MAAM,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACtC,MAAM,CAAC,IAAI,CAAC,OAAO,OAAO,CAAC,IAAI,MAAM,OAAO,CAAC,IAAI,WAAW,OAAO,CAAC,MAAM,QAAQ,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACnG,MAAM,CAAC,IAAI,CAAC,OAAO,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QAEpC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;YAC/C,OAAO;QACT,CAAC;QAED,yEAAyE;QACzE,MAAM,WAAW,GACf,MAAM,CAAC,OAAO,KAAK,SAAS;YAC1B,CAAC,CAAC,YAAY;YACd,CAAC,CAAC,MAAM,CAAC,OAAO,KAAK,iBAAiB;gBACtC,CAAC,CAAC,qBAAqB;gBACvB,CAAC,CAAC,aAAa,CAAC;QAEpB,MAAM,CAAC,IAAI,CAAC,eAAe,WAAW,IAAI,CAAC,CAAC;QAE5C,yEAAyE;QACzE,MAAM,CAAC,IAAI,CAAC,mBAAmB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAE3E,yEAAyE;QACzE,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;YACnC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;gBACpC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;gBACjF,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAClE,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;QAED,yEAAyE;QACzE,MAAM,SAAS,GAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC;QAC5E,MAAM,QAAQ,GAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC;QAC3E,MAAM,WAAW,GAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC;QAE9E,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,cAAc,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;YACpD,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,EAAE,GAAG,QAAQ,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC;gBAChE,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC/F,MAAM,GAAG,GAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxF,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,KAAK,CAAC,WAAW,GAAG,GAAG,EAAE,CAAC,CAAC;YACvD,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;QAED,yEAAyE;QACzE,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrC,MAAM,CAAC,IAAI,CAAC,uBAAuB,MAAM,CAAC,cAAc,CAAC,MAAM,IAAI,CAAC,CAAC;YACrE,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;gBACtC,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;gBACvF,MAAM,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBAChD,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC;gBAC1D,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;oBACjB,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBACtE,CAAC;YACH,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;QAED,yEAAyE;QACzE,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAC7B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,SAAS;gBAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YAC5D,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;QAED,yEAAyE;QACzE,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,uBAAuB,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACtF,CAAC;QAED,yEAAyE;QACzE,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,+BAA+B,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;YAChE,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;gBACrC,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtE,MAAM,CAAC,IAAI,CACT,OAAO,CAAC,CAAC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACnF,CAAC;YACJ,CAAC;YACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAM,CAAC,IAAI,CAAC,YAAY,QAAQ,CAAC,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC9E,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;QAED,yEAAyE;QACzE,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;QAC/D,CAAC;aAAM,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YAC/B,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC;YACjD,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;gBACpB,MAAM,CAAC,OAAO,CACZ,0BAA0B,WAAW,2DAA2D,CACjG,CAAC;gBACF,MAAM,CAAC,IAAI,CACT,yFAAyF,CAC1F,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CACT,+DAA+D;gBAC/D,+DAA+D,CAChE,CAAC;QACJ,CAAC;QAED,wEAAwE;IAC1E,CAAC,CAAC,CAAC;AACP,CAAC","sourcesContent":["import type { Command } from \"commander\";\nimport { logger } from \"../../../logger/logger.js\";\nimport { Gitx } from \"../../../core/gitx.js\";\nimport { runReviewWorkflow } from \"../../../workflows/pr.js\";\n\nexport function registerPrReviewCommand(pr: Command): void {\n pr.command(\"review\")\n .description(\"๐ง Senior-dev AI review: inline comments, checklist, verdict\")\n .argument(\"<id>\", \"Pull request number\")\n .option(\"--no-comment\", \"Show review locally only โ do not post to PR\")\n .option(\"--no-inline\", \"Post overall review but skip inline file comments\")\n .action(async (id: string, options: { comment: boolean; inline: boolean }) => {\n const prNumber = parseInt(id, 10);\n if (isNaN(prNumber) || prNumber <= 0) {\n logger.error(`Invalid PR number: ${id}`);\n process.exit(1);\n }\n\n const gitx = await Gitx.fromCwd();\n\n if (!await Gitx.isAiAvailable(gitx.config)) {\n logger.warn(\n \"โ ๏ธ No AI provider configured โ review will not be meaningful.\\n\" +\n \" Run: gitx config set anthropic (or openai / claude-cli)\"\n );\n return;\n }\n\n const postComment = options.comment !== false;\n\n logger.info(`\\n๐ง Senior-dev AI review โ PR #${prNumber}\\n`);\n\n let result: Awaited<ReturnType<typeof runReviewWorkflow>>;\n try {\n result = await runReviewWorkflow(gitx, prNumber, postComment);\n } catch (err) {\n logger.error(`Review failed: ${String((err as Error).message ?? err)}`);\n process.exitCode = 1;\n return;\n }\n\n const { pr: pullReq, review, comments } = result;\n\n // โโ PR header โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n logger.info(`\\n๐ ${pullReq.title}`);\n logger.info(` ${pullReq.head} โ ${pullReq.base} ยท by ${pullReq.author} ยท ${pullReq.state}`);\n logger.info(` ${pullReq.url}\\n`);\n\n if (!review) {\n logger.info(`๐ค Review:\\n${result.aiSummary}`);\n return;\n }\n\n // โโ Verdict โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n const verdictIcon =\n review.verdict === \"approve\"\n ? \"โ
APPROVE\"\n : review.verdict === \"request_changes\"\n ? \"๐ด REQUEST CHANGES\"\n : \"๐ฌ COMMENT\";\n\n logger.info(`๐ค Verdict: ${verdictIcon}\\n`);\n\n // โโ Summary โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n logger.info(`๐ Summary:\\n ${review.summary.replace(/\\n/g, \"\\n \")}\\n`);\n\n // โโ Checklist โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (review.checklist.length > 0) {\n logger.info(\"โ
Review Checklist:\");\n for (const item of review.checklist) {\n const icon = item.status === \"pass\" ? \"โ
\" : item.status === \"warn\" ? \"โ ๏ธ \" : \"โ\";\n logger.info(` ${icon} ${item.area.padEnd(20)} ${item.note}`);\n }\n logger.info(\"\");\n }\n\n // โโ Issues โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n const criticals = review.issues.filter((i) => i.severity === \"critical\");\n const warnings = review.issues.filter((i) => i.severity === \"warning\");\n const suggestions = review.issues.filter((i) => i.severity === \"suggestion\");\n\n if (review.issues.length > 0) {\n logger.info(`๐ Issues (${review.issues.length}):`);\n for (const issue of [...criticals, ...warnings, ...suggestions]) {\n const icon = issue.severity === \"critical\" ? \"๐ด\" : issue.severity === \"warning\" ? \"๐ก\" : \"๐ก\";\n const loc = issue.file ? ` [${issue.file}${issue.line ? `:${issue.line}` : \"\"}]` : \"\";\n logger.info(` ${icon} ${issue.description}${loc}`);\n }\n logger.info(\"\");\n }\n\n // โโ Inline comments โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (review.inlineComments.length > 0) {\n logger.info(`๐ฌ Inline Comments (${review.inlineComments.length}):`);\n for (const c of review.inlineComments) {\n const icon = c.severity === \"critical\" ? \"๐ด\" : c.severity === \"warning\" ? \"๐ก\" : \"๐ก\";\n logger.info(`\\n ${icon} ${c.path}:${c.line}`);\n logger.info(` ${c.body.replace(/\\n/g, \"\\n \")}`);\n if (c.suggestion) {\n logger.info(` ๐ Suggestion: ${c.suggestion.split(\"\\n\")[0]}โฆ`);\n }\n }\n logger.info(\"\");\n }\n\n // โโ Positives โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (review.positives.length > 0) {\n logger.info(\"๐ Positives:\");\n for (const p of review.positives) logger.info(` โ ${p}`);\n logger.info(\"\");\n }\n\n // โโ Testing notes โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (review.testingNotes) {\n logger.info(`๐งช How to test:\\n ${review.testingNotes.replace(/\\n/g, \"\\n \")}\\n`);\n }\n\n // โโ Existing PR comments โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (comments.length > 0) {\n logger.info(`๐ฌ Existing comments on PR (${comments.length}):`);\n for (const c of comments.slice(0, 4)) {\n const loc = c.path ? ` @ ${c.path}${c.line ? `:${c.line}` : \"\"}` : \"\";\n logger.info(\n ` [${c.author}${loc}]: ${c.body.slice(0, 120)}${c.body.length > 120 ? \"โฆ\" : \"\"}`\n );\n }\n if (comments.length > 4) logger.info(` โฆ and ${comments.length - 4} more.`);\n logger.info(\"\");\n }\n\n // โโ Status โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (!postComment) {\n logger.info(\"โน๏ธ Review shown locally only (--no-comment).\");\n } else if (result.reviewPosted) {\n const inlineCount = review.inlineComments.length;\n if (inlineCount > 0) {\n logger.success(\n `โ
Review posted to PR. ${inlineCount} inline comment(s) โ check the PR to see delivery method.`\n );\n logger.info(\n ` (If lines were outside the diff, comments were posted as plain PR comments instead.)`\n );\n } else {\n logger.success(\"โ
Review posted to PR.\");\n }\n } else {\n logger.warn(\n \"โ ๏ธ Review could not be posted to the PR (see error above).\\n\" +\n \" The full review is shown above โ you can copy it manually.\"\n );\n }\n\n // To address the review comments, run: gitx pr fix-comments <PR_number>\n });\n}\n\n"]}
|
|
1
|
+
{"version":3,"file":"review.js","sourceRoot":"","sources":["../../../../src/cli/commands/pr/review.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { logger } from \"../../../logger/logger.js\";\nimport { Gitx } from \"../../../core/gitx.js\";\nimport { runReviewWorkflow } from \"../../../workflows/pr.js\";\n\nexport function registerPrReviewCommand(pr: Command): void {\n pr.command(\"review\")\n .description(\"๐ง Senior-dev AI review: inline comments, checklist, verdict\")\n .argument(\"<id>\", \"Pull request number\")\n .option(\"--no-comment\", \"Show review locally only โ do not post to PR\")\n .option(\"--no-inline\", \"Post overall review but skip inline file comments\")\n .action(async (id: string, options: { comment: boolean; inline: boolean }) => {\n const prNumber = parseInt(id, 10);\n if (isNaN(prNumber) || prNumber <= 0) {\n logger.error(`Invalid PR number: ${id}`);\n process.exit(1);\n }\n\n const gitx = await Gitx.fromCwd();\n\n if (!await Gitx.isAiAvailable(gitx.config)) {\n logger.warn(\n \"โ ๏ธ No AI provider configured โ review will not be meaningful.\\n\" +\n \" Run: gitx config set anthropic (or openai / claude-cli)\"\n );\n return;\n }\n\n const postComment = options.comment !== false;\n\n logger.info(`\\n๐ง Senior-dev AI review โ PR #${prNumber}\\n`);\n\n let result: Awaited<ReturnType<typeof runReviewWorkflow>>;\n try {\n result = await runReviewWorkflow(gitx, prNumber, postComment);\n } catch (err) {\n logger.error(`Review failed: ${String((err as Error).message ?? err)}`);\n process.exitCode = 1;\n return;\n }\n\n const { pr: pullReq, review, comments } = result;\n\n // โโ PR header โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n logger.info(`\\n๐ ${pullReq.title}`);\n logger.info(` ${pullReq.head} โ ${pullReq.base} ยท by ${pullReq.author} ยท ${pullReq.state}`);\n logger.info(` ${pullReq.url}\\n`);\n\n if (!review) {\n logger.info(`๐ค Review:\\n${result.aiSummary}`);\n return;\n }\n\n // โโ Verdict โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n const verdictIcon =\n review.verdict === \"approve\"\n ? \"โ
APPROVE\"\n : review.verdict === \"request_changes\"\n ? \"๐ด REQUEST CHANGES\"\n : \"๐ฌ COMMENT\";\n\n logger.info(`๐ค Verdict: ${verdictIcon}\\n`);\n\n // โโ Summary โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n logger.info(`๐ Summary:\\n ${review.summary.replace(/\\n/g, \"\\n \")}\\n`);\n\n // โโ Checklist โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (review.checklist.length > 0) {\n logger.info(\"โ
Review Checklist:\");\n for (const item of review.checklist) {\n const icon = item.status === \"pass\" ? \"โ
\" : item.status === \"warn\" ? \"โ ๏ธ \" : \"โ\";\n logger.info(` ${icon} ${item.area.padEnd(20)} ${item.note}`);\n }\n logger.info(\"\");\n }\n\n // โโ Issues โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n const criticals = review.issues.filter((i) => i.severity === \"critical\");\n const warnings = review.issues.filter((i) => i.severity === \"warning\");\n const suggestions = review.issues.filter((i) => i.severity === \"suggestion\");\n\n if (review.issues.length > 0) {\n logger.info(`๐ Issues (${review.issues.length}):`);\n for (const issue of [...criticals, ...warnings, ...suggestions]) {\n const icon = issue.severity === \"critical\" ? \"๐ด\" : issue.severity === \"warning\" ? \"๐ก\" : \"๐ก\";\n const loc = issue.file ? ` [${issue.file}${issue.line ? `:${issue.line}` : \"\"}]` : \"\";\n logger.info(` ${icon} ${issue.description}${loc}`);\n }\n logger.info(\"\");\n }\n\n // โโ Inline comments โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (review.inlineComments.length > 0) {\n logger.info(`๐ฌ Inline Comments (${review.inlineComments.length}):`);\n for (const c of review.inlineComments) {\n const icon = c.severity === \"critical\" ? \"๐ด\" : c.severity === \"warning\" ? \"๐ก\" : \"๐ก\";\n logger.info(`\\n ${icon} ${c.path}:${c.line}`);\n logger.info(` ${c.body.replace(/\\n/g, \"\\n \")}`);\n if (c.suggestion) {\n logger.info(` ๐ Suggestion: ${c.suggestion.split(\"\\n\")[0]}โฆ`);\n }\n }\n logger.info(\"\");\n }\n\n // โโ Positives โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (review.positives.length > 0) {\n logger.info(\"๐ Positives:\");\n for (const p of review.positives) logger.info(` โ ${p}`);\n logger.info(\"\");\n }\n\n // โโ Testing notes โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (review.testingNotes) {\n logger.info(`๐งช How to test:\\n ${review.testingNotes.replace(/\\n/g, \"\\n \")}\\n`);\n }\n\n // โโ Existing PR comments โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (comments.length > 0) {\n logger.info(`๐ฌ Existing comments on PR (${comments.length}):`);\n for (const c of comments.slice(0, 4)) {\n const loc = c.path ? ` @ ${c.path}${c.line ? `:${c.line}` : \"\"}` : \"\";\n logger.info(\n ` [${c.author}${loc}]: ${c.body.slice(0, 120)}${c.body.length > 120 ? \"โฆ\" : \"\"}`\n );\n }\n if (comments.length > 4) logger.info(` โฆ and ${comments.length - 4} more.`);\n logger.info(\"\");\n }\n\n // โโ Status โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (!postComment) {\n logger.info(\"โน๏ธ Review shown locally only (--no-comment).\");\n } else if (result.reviewPosted) {\n const inlineCount = review.inlineComments.length;\n if (inlineCount > 0) {\n logger.success(\n `โ
Review posted to PR. ${inlineCount} inline comment(s) โ check the PR to see delivery method.`\n );\n logger.info(\n ` (If lines were outside the diff, comments were posted as plain PR comments instead.)`\n );\n } else {\n logger.success(\"โ
Review posted to PR.\");\n }\n } else {\n logger.warn(\n \"โ ๏ธ Review could not be posted to the PR (see error above).\\n\" +\n \" The full review is shown above โ you can copy it manually.\"\n );\n }\n\n // To resolve the review comments, run: gitx pr resolve <PR_number>\n });\n}\n\n"]}
|
|
@@ -2,22 +2,23 @@
|
|
|
2
2
|
* gitx sync
|
|
3
3
|
*
|
|
4
4
|
* Bring the current branch up to date with its base branch so a PR can be
|
|
5
|
-
* merged cleanly.
|
|
5
|
+
* merged cleanly.
|
|
6
6
|
*
|
|
7
7
|
* Flow:
|
|
8
|
-
* 1.
|
|
8
|
+
* 1. Auto-detect base branch (same logic as `gitx pr create`)
|
|
9
9
|
* 2. git fetch origin
|
|
10
|
-
* 3. git
|
|
11
|
-
* 4a. No conflicts โ
|
|
12
|
-
* 4b. Conflicts
|
|
13
|
-
* then run `gitx sync --continue` to finish
|
|
10
|
+
* 3. git merge origin/<base> (default) or git rebase origin/<base>
|
|
11
|
+
* 4a. No conflicts โ push โ "ready to merge"
|
|
12
|
+
* 4b. Conflicts โ AI attempts resolution; unresolvable ones pause for manual fix
|
|
14
13
|
*
|
|
15
14
|
* Usage:
|
|
16
|
-
* gitx sync
|
|
17
|
-
* gitx sync --base main
|
|
18
|
-
* gitx sync --strategy
|
|
19
|
-
* gitx sync --continue
|
|
20
|
-
* gitx sync --abort
|
|
15
|
+
* gitx sync # auto-detect base, merge (default)
|
|
16
|
+
* gitx sync --base main # target a specific base branch
|
|
17
|
+
* gitx sync --strategy rebase # rebase instead of merge
|
|
18
|
+
* gitx sync --continue # after manually resolving conflicts
|
|
19
|
+
* gitx sync --abort # abort an in-progress rebase/merge
|
|
20
|
+
*
|
|
21
|
+
* To resolve PR review comments before syncing, run `gitx pr resolve <number>` first.
|
|
21
22
|
*/
|
|
22
23
|
import type { Command } from "commander";
|
|
23
24
|
export declare function registerSyncCommand(program: Command): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/sync.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmEzC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoS1D"}
|
|
@@ -2,36 +2,35 @@
|
|
|
2
2
|
* gitx sync
|
|
3
3
|
*
|
|
4
4
|
* Bring the current branch up to date with its base branch so a PR can be
|
|
5
|
-
* merged cleanly.
|
|
5
|
+
* merged cleanly.
|
|
6
6
|
*
|
|
7
7
|
* Flow:
|
|
8
|
-
* 1.
|
|
8
|
+
* 1. Auto-detect base branch (same logic as `gitx pr create`)
|
|
9
9
|
* 2. git fetch origin
|
|
10
|
-
* 3. git
|
|
11
|
-
* 4a. No conflicts โ
|
|
12
|
-
* 4b. Conflicts
|
|
13
|
-
* then run `gitx sync --continue` to finish
|
|
10
|
+
* 3. git merge origin/<base> (default) or git rebase origin/<base>
|
|
11
|
+
* 4a. No conflicts โ push โ "ready to merge"
|
|
12
|
+
* 4b. Conflicts โ AI attempts resolution; unresolvable ones pause for manual fix
|
|
14
13
|
*
|
|
15
14
|
* Usage:
|
|
16
|
-
* gitx sync
|
|
17
|
-
* gitx sync --base main
|
|
18
|
-
* gitx sync --strategy
|
|
19
|
-
* gitx sync --continue
|
|
20
|
-
* gitx sync --abort
|
|
15
|
+
* gitx sync # auto-detect base, merge (default)
|
|
16
|
+
* gitx sync --base main # target a specific base branch
|
|
17
|
+
* gitx sync --strategy rebase # rebase instead of merge
|
|
18
|
+
* gitx sync --continue # after manually resolving conflicts
|
|
19
|
+
* gitx sync --abort # abort an in-progress rebase/merge
|
|
20
|
+
*
|
|
21
|
+
* To resolve PR review comments before syncing, run `gitx pr resolve <number>` first.
|
|
21
22
|
*/
|
|
22
23
|
import ora from "ora";
|
|
23
24
|
import { execFile } from "node:child_process";
|
|
24
25
|
import { promisify } from "node:util";
|
|
25
26
|
import { readFile, writeFile } from "node:fs/promises";
|
|
26
27
|
import { resolve as resolvePath } from "node:path";
|
|
27
|
-
import { confirm
|
|
28
|
+
import { confirm } from "@inquirer/prompts";
|
|
28
29
|
import { logger } from "../../logger/logger.js";
|
|
29
30
|
import { getCurrentBranch, detectBaseBranch } from "../../utils/gitOps.js";
|
|
30
31
|
import { isInsideGitRepo } from "../../utils/git.js";
|
|
31
32
|
import { GitxError } from "../../utils/errors.js";
|
|
32
33
|
import { Gitx } from "../../core/gitx.js";
|
|
33
|
-
import { createProvider } from "../../providers/factory.js";
|
|
34
|
-
import { runAddressWorkflow, filterUnresolvedInlineComments } from "../../workflows/prAddress.js";
|
|
35
34
|
const execFileAsync = promisify(execFile);
|
|
36
35
|
async function git(args, cwd) {
|
|
37
36
|
try {
|
|
@@ -151,11 +150,6 @@ export function registerSyncCommand(program) {
|
|
|
151
150
|
logger.info(`โจ Already on the base branch "${base}" โ nothing to sync.`);
|
|
152
151
|
return;
|
|
153
152
|
}
|
|
154
|
-
// โโ Check for unresolved PR review comments BEFORE syncing โโโโโโโโโโโโ
|
|
155
|
-
// If the current branch has an open PR with unresolved inline comments,
|
|
156
|
-
// offer to resolve them now. Fixes are committed onto the branch; the
|
|
157
|
-
// sync then rebases/merges and pushes everything together.
|
|
158
|
-
await checkAndOfferAddressComments(cwd, head);
|
|
159
153
|
logger.info(`\n๐ Syncing ${head} onto origin/${base}\n`);
|
|
160
154
|
// Fetch latest
|
|
161
155
|
const fetchSpinner = ora("Fetching latest from originโฆ").start();
|
|
@@ -310,88 +304,6 @@ export function registerSyncCommand(program) {
|
|
|
310
304
|
await pushAfterSync(cwd, strategy === "rebase");
|
|
311
305
|
});
|
|
312
306
|
}
|
|
313
|
-
/**
|
|
314
|
-
* Before syncing, look up any open PR for the current branch.
|
|
315
|
-
* If it has unresolved inline review comments, ask the user:
|
|
316
|
-
* - "Resolve comments first, then sync" โ address + commit, sync continues
|
|
317
|
-
* - "Sync normally" โ proceed immediately
|
|
318
|
-
*
|
|
319
|
-
* Fixes are committed using "commit-no-push" mode so the sync rebase/merge
|
|
320
|
-
* picks them up and pushes everything together in a single push.
|
|
321
|
-
*/
|
|
322
|
-
async function checkAndOfferAddressComments(cwd, currentBranch) {
|
|
323
|
-
let gitx = null;
|
|
324
|
-
try {
|
|
325
|
-
gitx = await Gitx.fromCwd(cwd);
|
|
326
|
-
if (!await Gitx.isAiAvailable(gitx.config))
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
catch {
|
|
330
|
-
return; // no gitx config โ skip silently
|
|
331
|
-
}
|
|
332
|
-
let prNumber = null;
|
|
333
|
-
let unresolvedCount = 0;
|
|
334
|
-
try {
|
|
335
|
-
const ctx = await gitx.getRepoContext();
|
|
336
|
-
const provider = createProvider(ctx);
|
|
337
|
-
// Find the open PR for the current branch
|
|
338
|
-
const prs = await provider.listPRs(ctx.repoSlug);
|
|
339
|
-
const openPr = prs.find((p) => p.head === currentBranch && p.state === "open");
|
|
340
|
-
if (!openPr)
|
|
341
|
-
return;
|
|
342
|
-
prNumber = openPr.number;
|
|
343
|
-
// Use the shared helper: root inline comments with no "โ
Addressed" reply yet
|
|
344
|
-
const allComments = await provider.getPRComments(ctx.repoSlug, prNumber);
|
|
345
|
-
unresolvedCount = filterUnresolvedInlineComments(allComments).length;
|
|
346
|
-
if (unresolvedCount === 0)
|
|
347
|
-
return;
|
|
348
|
-
}
|
|
349
|
-
catch {
|
|
350
|
-
return; // provider error โ don't block the sync
|
|
351
|
-
}
|
|
352
|
-
// โโ Surface the choice โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
353
|
-
logger.info(`\n๐ฌ PR #${prNumber} has ${unresolvedCount} unresolved review comment(s).\n`);
|
|
354
|
-
let choice;
|
|
355
|
-
try {
|
|
356
|
-
choice = await select({
|
|
357
|
-
message: "How would you like to proceed?",
|
|
358
|
-
choices: [
|
|
359
|
-
{
|
|
360
|
-
name: `Resolve comments first, then sync (AI generates fixes โ you approve โ commit โ sync)`,
|
|
361
|
-
value: "resolve",
|
|
362
|
-
},
|
|
363
|
-
{
|
|
364
|
-
name: `Sync normally (skip comment resolution, proceed with merge)`,
|
|
365
|
-
value: "skip",
|
|
366
|
-
},
|
|
367
|
-
],
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
catch {
|
|
371
|
-
return; // Ctrl-C โ skip
|
|
372
|
-
}
|
|
373
|
-
if (choice === "skip") {
|
|
374
|
-
logger.info("โญ๏ธ Skipping comment resolution โ proceeding with sync.\n");
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
// โโ Resolve comments (commit but don't push โ sync handles the push) โโโโโโโ
|
|
378
|
-
logger.info(`\n๐ง Resolving ${unresolvedCount} review comment(s) on PR #${prNumber}โฆ\n`);
|
|
379
|
-
try {
|
|
380
|
-
const result = await runAddressWorkflow(gitx, prNumber, { mode: "commit-no-push" });
|
|
381
|
-
const applied = result.addressed.filter((a) => a.applied).length;
|
|
382
|
-
const skipped = result.addressed.filter((a) => a.skipped).length;
|
|
383
|
-
if (applied > 0) {
|
|
384
|
-
logger.success(`โ
${applied} fix(es) committed.${skipped > 0 ? ` (${skipped} skipped)` : ""}`);
|
|
385
|
-
logger.info(" Sync will rebase these commits and push everything together.\n");
|
|
386
|
-
}
|
|
387
|
-
else {
|
|
388
|
-
logger.info(" No fixes applied โ continuing with normal sync.\n");
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
catch (err) {
|
|
392
|
-
logger.warn(`โ ๏ธ Comment resolution error: ${err.message}\n Continuing with sync.\n`);
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
307
|
async function pushAfterSync(cwd, forceWithLease = false) {
|
|
396
308
|
// Rebase rewrites history โ requires --force-with-lease.
|
|
397
309
|
// Merge does not rewrite history โ plain push is fine.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../src/cli/commands/sync.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * gitx sync\n *\n * Bring the current branch up to date with its base branch so a PR can be\n * merged cleanly. Uses rebase by default (keeps a linear history).\n *\n * Flow:\n * 1. Detect base branch (same logic as `gitx pr create`)\n * 2. git fetch origin\n * 3. git rebase origin/<base> (or --merge: git merge origin/<base>)\n * 4a. No conflicts โ git push --force-with-lease โ \"ready to merge\"\n * 4b. Conflicts โ list conflicting files, instruct user how to resolve,\n * then run `gitx sync --continue` to finish\n *\n * Usage:\n * gitx sync # rebase onto auto-detected base\n * gitx sync --base main # rebase onto a specific base\n * gitx sync --strategy merge # merge base into branch instead of rebase\n * gitx sync --continue # after manually resolving conflicts\n * gitx sync --abort # abort an in-progress rebase/merge\n */\n\nimport type { Command } from \"commander\";\nimport ora from \"ora\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { resolve as resolvePath } from \"node:path\";\nimport { confirm, select } from \"@inquirer/prompts\";\nimport { logger } from \"../../logger/logger.js\";\nimport { getCurrentBranch, detectBaseBranch } from \"../../utils/gitOps.js\";\nimport { isInsideGitRepo } from \"../../utils/git.js\";\nimport { GitxError } from \"../../utils/errors.js\";\nimport { Gitx } from \"../../core/gitx.js\";\nimport { createProvider } from \"../../providers/factory.js\";\nimport { runAddressWorkflow, filterUnresolvedInlineComments } from \"../../workflows/prAddress.js\";\n\nconst execFileAsync = promisify(execFile);\n\nasync function git(\n args: string[],\n cwd: string\n): Promise<{ stdout: string; stderr: string }> {\n try {\n const result = await execFileAsync(\"git\", args, { cwd });\n return { stdout: result.stdout.trim(), stderr: \"\" };\n } catch (err: unknown) {\n const e = err as { stdout?: string; stderr?: string; message?: string };\n return {\n stdout: e.stdout?.trim() ?? \"\",\n stderr: (e.stderr ?? e.message ?? String(err)).trim(),\n };\n }\n}\n\n/** Returns list of files that currently have conflict markers. */\nasync function getConflictingFiles(cwd: string): Promise<string[]> {\n const { stdout } = await git(\n [\"diff\", \"--name-only\", \"--diff-filter=U\"],\n cwd\n );\n return stdout.split(\"\\n\").map((l) => l.trim()).filter(Boolean);\n}\n\n/** Check whether a rebase or merge is currently in progress. */\nasync function getInProgressOperation(\n cwd: string\n): Promise<\"rebase\" | \"merge\" | null> {\n const { stdout: gitDir } = await git([\"rev-parse\", \"--git-dir\"], cwd);\n const base = gitDir || \".git\";\n\n const { stdout: rebaseDir } = await git(\n [\"rev-parse\", \"--git-path\", \"rebase-merge\"],\n cwd\n );\n const { stdout: rebaseApply } = await git(\n [\"rev-parse\", \"--git-path\", \"rebase-apply\"],\n cwd\n );\n const { stdout: mergeHead } = await git(\n [\"rev-parse\", \"--git-path\", \"MERGE_HEAD\"],\n cwd\n );\n\n // Check if the paths actually exist on disk\n const { existsSync } = await import(\"node:fs\");\n if (existsSync(rebaseDir) || existsSync(rebaseApply)) return \"rebase\";\n if (existsSync(mergeHead) || existsSync(`${base}/MERGE_HEAD`)) return \"merge\";\n return null;\n}\n\nexport function registerSyncCommand(program: Command): void {\n program\n .command(\"sync\")\n .description(\"๐ Sync current branch with its base branch (merge by default, or --strategy rebase)\")\n .option(\"--base <branch>\", \"Base branch to sync with (auto-detected if omitted)\")\n .option(\n \"--strategy <strategy>\",\n \"Sync strategy: merge (default) | rebase\",\n \"merge\"\n )\n .option(\"--continue\", \"Continue after manually resolving conflicts\")\n .option(\"--abort\", \"Abort an in-progress rebase or merge\")\n .action(async (opts: {\n base?: string;\n strategy: string;\n continue?: boolean;\n abort?: boolean;\n }) => {\n const cwd = process.cwd();\n\n if (!(await isInsideGitRepo(cwd))) {\n throw new GitxError(\"Not inside a git repository. cd into your project folder first.\", { exitCode: 2 });\n }\n\n const strategy = opts.strategy === \"rebase\" ? \"rebase\" : \"merge\";\n\n // โโ Handle --abort โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (opts.abort) {\n const op = await getInProgressOperation(cwd);\n if (!op) {\n logger.info(\"No rebase or merge in progress.\");\n return;\n }\n const abortSpinner = ora(`Aborting ${op}โฆ`).start();\n const { stderr } = await git([op, \"--abort\"], cwd);\n if (stderr) {\n abortSpinner.fail(`Abort failed: ${stderr}`);\n process.exitCode = 1;\n return;\n }\n abortSpinner.succeed(`${op.charAt(0).toUpperCase() + op.slice(1)} aborted. Branch restored to its previous state.`);\n return;\n }\n\n // โโ Handle --continue โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (opts.continue) {\n const op = await getInProgressOperation(cwd);\n if (!op) {\n logger.info(\"No rebase or merge in progress โ nothing to continue.\");\n return;\n }\n\n // Check if all conflicts are resolved\n const conflicts = await getConflictingFiles(cwd);\n if (conflicts.length > 0) {\n logger.error(`\\nโ There are still unresolved conflicts:\\n`);\n for (const f of conflicts) logger.info(` โข ${f}`);\n logger.info(`\\n Fix the conflicts above, then:\\n`);\n logger.info(` git add <file> # mark each file as resolved`);\n logger.info(` gitx sync --continue # resume\\n`);\n process.exitCode = 1;\n return;\n }\n\n // Stage all resolved files and continue\n await git([\"add\", \"-A\"], cwd);\n const continueSpinner = ora(`Continuing ${op}โฆ`).start();\n\n const env = { ...process.env, GIT_EDITOR: \"true\" }; // skip editor for commit msg\n const { stderr } = await execFileAsync(\n \"git\",\n [op, \"--continue\"],\n { cwd, env }\n ).then(\n (r) => ({ stdout: r.stdout, stderr: \"\" }),\n (e: { stderr?: string; message?: string }) => ({\n stdout: \"\",\n stderr: (e.stderr ?? e.message ?? \"\").trim(),\n })\n );\n\n if (stderr && !stderr.includes(\"Successfully\")) {\n continueSpinner.fail(`Could not continue ${op}: ${stderr}`);\n process.exitCode = 1;\n return;\n }\n continueSpinner.succeed(`${op.charAt(0).toUpperCase() + op.slice(1)} completed โ`);\n\n // Rebase rewrites history; merge does not\n await pushAfterSync(cwd, op === \"rebase\");\n return;\n }\n\n // โโ Normal sync flow โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n const head = await getCurrentBranch(cwd);\n\n // Resolve base\n let base: string;\n if (opts.base) {\n base = opts.base;\n logger.info(`๐ Base branch (provided): ${base}`);\n } else {\n const detectSpinner = ora(\"Detecting base branchโฆ\").start();\n base = await detectBaseBranch(cwd);\n detectSpinner.succeed(`Base branch: ${base}`);\n }\n\n if (head === base) {\n logger.info(`โจ Already on the base branch \"${base}\" โ nothing to sync.`);\n return;\n }\n\n // โโ Check for unresolved PR review comments BEFORE syncing โโโโโโโโโโโโ\n // If the current branch has an open PR with unresolved inline comments,\n // offer to resolve them now. Fixes are committed onto the branch; the\n // sync then rebases/merges and pushes everything together.\n await checkAndOfferAddressComments(cwd, head);\n\n logger.info(`\\n๐ Syncing ${head} onto origin/${base}\\n`);\n\n // Fetch latest\n const fetchSpinner = ora(\"Fetching latest from originโฆ\").start();\n const { stderr: fetchErr } = await git([\"fetch\", \"origin\"], cwd);\n if (fetchErr && !fetchErr.includes(\"->\")) {\n fetchSpinner.fail(`Fetch failed: ${fetchErr}`);\n process.exitCode = 1;\n return;\n }\n fetchSpinner.succeed(\"Fetched latest.\");\n\n // Check if we're already up to date\n const { stdout: behindCount } = await git(\n [\"rev-list\", \"--count\", `HEAD..origin/${base}`],\n cwd\n );\n if (behindCount === \"0\") {\n logger.success(`โ
\"${head}\" is already up to date with origin/${base}. Ready to merge!`);\n return;\n }\n\n // Run rebase or merge\n const syncSpinner = ora(\n strategy === \"rebase\"\n ? `Rebasing ${head} onto origin/${base}โฆ`\n : `Merging origin/${base} into ${head}โฆ`\n ).start();\n\n const syncArgs =\n strategy === \"rebase\"\n ? [\"rebase\", `origin/${base}`]\n : [\"merge\", `origin/${base}`, \"--no-edit\"];\n\n const { stderr: syncErr } = await git(syncArgs, cwd);\n\n // Detect conflict โ try AI resolution first\n const conflicts = await getConflictingFiles(cwd);\n if (conflicts.length > 0) {\n syncSpinner.fail(`Conflicts detected in ${conflicts.length} file(s) โ attempting AI resolutionโฆ`);\n\n // Try to load an AI client\n let gitx: Gitx | null = null;\n try {\n gitx = await Gitx.fromCwd(cwd);\n } catch {\n // No AI available; fall through to manual instructions\n }\n\n if (gitx && await Gitx.isAiAvailable(gitx.config)) {\n const resolved: string[] = [];\n const needsManual: string[] = [];\n\n for (const filePath of conflicts) {\n const absPath = resolvePath(cwd, filePath);\n let content: string;\n try {\n content = await readFile(absPath, \"utf8\");\n } catch {\n needsManual.push(filePath);\n continue;\n }\n\n // Skip binary files (no conflict markers)\n if (!content.includes(\"<<<<<<<\")) {\n needsManual.push(filePath);\n continue;\n }\n\n const resolveSpinner = ora(` ๐ค AI resolving: ${filePath}`).start();\n try {\n const result = await gitx.ai.resolveConflict(filePath, content);\n\n if (result.confidence === \"high\") {\n await writeFile(absPath, result.resolved, \"utf8\");\n resolveSpinner.succeed(` โ
Auto-resolved: ${filePath} โ ${result.explanation}`);\n resolved.push(filePath);\n } else {\n resolveSpinner.warn(` โ ๏ธ Low confidence: ${filePath} โ ${result.explanation}`);\n logger.info(`\\n AI proposed resolution (low confidence). Preview:\\n`);\n // Show first 40 lines of the resolved content as a preview\n const preview = result.resolved.split(\"\\n\").slice(0, 40).join(\"\\n\");\n logger.info(preview);\n if (result.resolved.split(\"\\n\").length > 40) {\n logger.info(` โฆ (${result.resolved.split(\"\\n\").length - 40} more lines)`);\n }\n logger.info(\"\");\n\n let apply = false;\n try {\n apply = await confirm({\n message: `Apply AI resolution for ${filePath}?`,\n default: true,\n });\n } catch {\n apply = false;\n }\n\n if (apply) {\n await writeFile(absPath, result.resolved, \"utf8\");\n logger.success(` โ
Applied: ${filePath}`);\n resolved.push(filePath);\n } else {\n logger.info(` โญ๏ธ Skipped: ${filePath} โ resolve manually`);\n needsManual.push(filePath);\n }\n }\n } catch {\n resolveSpinner.fail(` โ AI resolution failed for: ${filePath}`);\n needsManual.push(filePath);\n }\n }\n\n if (needsManual.length > 0) {\n logger.error(`\\nโ ๏ธ ${needsManual.length} file(s) still need manual resolution:\\n`);\n for (const f of needsManual) logger.info(` โข ${f}`);\n logger.info(`\\n Steps to finish:\\n`);\n logger.info(` 1. Open each file and fix the conflict markers (<<<<, ====, >>>>)`);\n logger.info(` 2. Mark resolved: git add <file>`);\n logger.info(` 3. Finish sync: gitx sync --continue`);\n logger.info(` 4. Retry merge: gitx pr merge <number>\\n`);\n logger.info(` To give up and go back: gitx sync --abort\\n`);\n process.exitCode = 1;\n return;\n }\n\n // All resolved โ stage and continue\n if (resolved.length > 0) {\n logger.success(`\\nโ
AI resolved all ${resolved.length} conflict(s). Staging and continuingโฆ\\n`);\n await git([\"add\", \"-A\"], cwd);\n\n const env = { ...process.env, GIT_EDITOR: \"true\" };\n const { stderr: contErr } = await execFileAsync(\n \"git\",\n [strategy === \"rebase\" ? \"rebase\" : \"merge\", \"--continue\"],\n { cwd, env }\n ).then(\n (r) => ({ stdout: r.stdout, stderr: \"\" }),\n (e: { stderr?: string; message?: string }) => ({\n stdout: \"\",\n stderr: (e.stderr ?? e.message ?? \"\").trim(),\n })\n );\n\n if (contErr && !contErr.toLowerCase().includes(\"successfully\")) {\n logger.error(`Could not continue ${strategy}: ${contErr}`);\n process.exitCode = 1;\n return;\n }\n }\n } else {\n // No AI โ fall back to manual instructions\n logger.error(`\\nโ ๏ธ Merge conflicts in ${conflicts.length} file(s):\\n`);\n for (const f of conflicts) logger.info(` โข ${f}`);\n logger.info(`\\n Steps to resolve:\\n`);\n logger.info(` 1. Open each file and fix the conflict markers (<<<<, ====, >>>>)`);\n logger.info(` 2. Mark resolved: git add <file>`);\n logger.info(` 3. Finish sync: gitx sync --continue`);\n logger.info(` 4. Retry merge: gitx pr merge <number>\\n`);\n logger.info(` To give up and go back: gitx sync --abort\\n`);\n process.exitCode = 1;\n return;\n }\n }\n\n if (syncErr && !syncErr.toLowerCase().includes(\"successfully\")) {\n syncSpinner.fail(`Sync failed: ${syncErr}`);\n process.exitCode = 1;\n return;\n }\n\n syncSpinner.succeed(\n strategy === \"rebase\"\n ? `Rebased ${head} onto origin/${base} โ`\n : `Merged origin/${base} into ${head} โ`\n );\n\n // Rebase rewrites history โ force-with-lease; merge โ plain push\n await pushAfterSync(cwd, strategy === \"rebase\");\n });\n}\n\n/**\n * Before syncing, look up any open PR for the current branch.\n * If it has unresolved inline review comments, ask the user:\n * - \"Resolve comments first, then sync\" โ address + commit, sync continues\n * - \"Sync normally\" โ proceed immediately\n *\n * Fixes are committed using \"commit-no-push\" mode so the sync rebase/merge\n * picks them up and pushes everything together in a single push.\n */\nasync function checkAndOfferAddressComments(cwd: string, currentBranch: string): Promise<void> {\n let gitx: Gitx | null = null;\n try {\n gitx = await Gitx.fromCwd(cwd);\n if (!await Gitx.isAiAvailable(gitx.config)) return;\n } catch {\n return; // no gitx config โ skip silently\n }\n\n let prNumber: number | null = null;\n let unresolvedCount = 0;\n\n try {\n const ctx = await gitx.getRepoContext();\n const provider = createProvider(ctx);\n\n // Find the open PR for the current branch\n const prs = await provider.listPRs(ctx.repoSlug);\n const openPr = prs.find((p) => p.head === currentBranch && p.state === \"open\");\n if (!openPr) return;\n\n prNumber = openPr.number;\n\n // Use the shared helper: root inline comments with no \"โ
Addressed\" reply yet\n const allComments = await provider.getPRComments(ctx.repoSlug, prNumber);\n unresolvedCount = filterUnresolvedInlineComments(allComments).length;\n\n if (unresolvedCount === 0) return;\n } catch {\n return; // provider error โ don't block the sync\n }\n\n // โโ Surface the choice โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n logger.info(`\\n๐ฌ PR #${prNumber} has ${unresolvedCount} unresolved review comment(s).\\n`);\n\n let choice: string;\n try {\n choice = await select({\n message: \"How would you like to proceed?\",\n choices: [\n {\n name: `Resolve comments first, then sync (AI generates fixes โ you approve โ commit โ sync)`,\n value: \"resolve\",\n },\n {\n name: `Sync normally (skip comment resolution, proceed with merge)`,\n value: \"skip\",\n },\n ],\n });\n } catch {\n return; // Ctrl-C โ skip\n }\n\n if (choice === \"skip\") {\n logger.info(\"โญ๏ธ Skipping comment resolution โ proceeding with sync.\\n\");\n return;\n }\n\n // โโ Resolve comments (commit but don't push โ sync handles the push) โโโโโโโ\n logger.info(`\\n๐ง Resolving ${unresolvedCount} review comment(s) on PR #${prNumber}โฆ\\n`);\n try {\n const result = await runAddressWorkflow(gitx!, prNumber, { mode: \"commit-no-push\" });\n const applied = result.addressed.filter((a) => a.applied).length;\n const skipped = result.addressed.filter((a) => a.skipped).length;\n\n if (applied > 0) {\n logger.success(`โ
${applied} fix(es) committed.${skipped > 0 ? ` (${skipped} skipped)` : \"\"}`);\n logger.info(\" Sync will rebase these commits and push everything together.\\n\");\n } else {\n logger.info(\" No fixes applied โ continuing with normal sync.\\n\");\n }\n } catch (err) {\n logger.warn(`โ ๏ธ Comment resolution error: ${(err as Error).message}\\n Continuing with sync.\\n`);\n }\n}\n\nasync function pushAfterSync(cwd: string, forceWithLease = false): Promise<void> {\n // Rebase rewrites history โ requires --force-with-lease.\n // Merge does not rewrite history โ plain push is fine.\n const pushArgs = forceWithLease\n ? [\"push\", \"--force-with-lease\"]\n : [\"push\"];\n\n const label = forceWithLease ? \"Pushing (force-with-lease)โฆ\" : \"Pushingโฆ\";\n const pushSpinner = ora(label).start();\n const { stderr } = await git(pushArgs, cwd);\n if (stderr && stderr.includes(\"error\")) {\n pushSpinner.fail(`Push failed: ${stderr}`);\n const hint = forceWithLease ? \"git push --force-with-lease\" : \"git push\";\n logger.info(` Try: ${hint}`);\n process.exitCode = 1;\n return;\n }\n pushSpinner.succeed(\"Pushed โ\");\n logger.success(`\\nโ
Branch is now up to date. Run \\`gitx pr merge <number>\\` to merge.\\n`);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../src/cli/commands/sync.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * gitx sync\n *\n * Bring the current branch up to date with its base branch so a PR can be\n * merged cleanly.\n *\n * Flow:\n * 1. Auto-detect base branch (same logic as `gitx pr create`)\n * 2. git fetch origin\n * 3. git merge origin/<base> (default) or git rebase origin/<base>\n * 4a. No conflicts โ push โ \"ready to merge\"\n * 4b. Conflicts โ AI attempts resolution; unresolvable ones pause for manual fix\n *\n * Usage:\n * gitx sync # auto-detect base, merge (default)\n * gitx sync --base main # target a specific base branch\n * gitx sync --strategy rebase # rebase instead of merge\n * gitx sync --continue # after manually resolving conflicts\n * gitx sync --abort # abort an in-progress rebase/merge\n *\n * To resolve PR review comments before syncing, run `gitx pr resolve <number>` first.\n */\n\nimport type { Command } from \"commander\";\nimport ora from \"ora\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { resolve as resolvePath } from \"node:path\";\nimport { confirm } from \"@inquirer/prompts\";\nimport { logger } from \"../../logger/logger.js\";\nimport { getCurrentBranch, detectBaseBranch } from \"../../utils/gitOps.js\";\nimport { isInsideGitRepo } from \"../../utils/git.js\";\nimport { GitxError } from \"../../utils/errors.js\";\nimport { Gitx } from \"../../core/gitx.js\";\n\nconst execFileAsync = promisify(execFile);\n\nasync function git(\n args: string[],\n cwd: string\n): Promise<{ stdout: string; stderr: string }> {\n try {\n const result = await execFileAsync(\"git\", args, { cwd });\n return { stdout: result.stdout.trim(), stderr: \"\" };\n } catch (err: unknown) {\n const e = err as { stdout?: string; stderr?: string; message?: string };\n return {\n stdout: e.stdout?.trim() ?? \"\",\n stderr: (e.stderr ?? e.message ?? String(err)).trim(),\n };\n }\n}\n\n/** Returns list of files that currently have conflict markers. */\nasync function getConflictingFiles(cwd: string): Promise<string[]> {\n const { stdout } = await git(\n [\"diff\", \"--name-only\", \"--diff-filter=U\"],\n cwd\n );\n return stdout.split(\"\\n\").map((l) => l.trim()).filter(Boolean);\n}\n\n/** Check whether a rebase or merge is currently in progress. */\nasync function getInProgressOperation(\n cwd: string\n): Promise<\"rebase\" | \"merge\" | null> {\n const { stdout: gitDir } = await git([\"rev-parse\", \"--git-dir\"], cwd);\n const base = gitDir || \".git\";\n\n const { stdout: rebaseDir } = await git(\n [\"rev-parse\", \"--git-path\", \"rebase-merge\"],\n cwd\n );\n const { stdout: rebaseApply } = await git(\n [\"rev-parse\", \"--git-path\", \"rebase-apply\"],\n cwd\n );\n const { stdout: mergeHead } = await git(\n [\"rev-parse\", \"--git-path\", \"MERGE_HEAD\"],\n cwd\n );\n\n // Check if the paths actually exist on disk\n const { existsSync } = await import(\"node:fs\");\n if (existsSync(rebaseDir) || existsSync(rebaseApply)) return \"rebase\";\n if (existsSync(mergeHead) || existsSync(`${base}/MERGE_HEAD`)) return \"merge\";\n return null;\n}\n\nexport function registerSyncCommand(program: Command): void {\n program\n .command(\"sync\")\n .description(\"๐ Sync current branch with its base branch (merge by default, or --strategy rebase)\")\n .option(\"--base <branch>\", \"Base branch to sync with (auto-detected if omitted)\")\n .option(\n \"--strategy <strategy>\",\n \"Sync strategy: merge (default) | rebase\",\n \"merge\"\n )\n .option(\"--continue\", \"Continue after manually resolving conflicts\")\n .option(\"--abort\", \"Abort an in-progress rebase or merge\")\n .action(async (opts: {\n base?: string;\n strategy: string;\n continue?: boolean;\n abort?: boolean;\n }) => {\n const cwd = process.cwd();\n\n if (!(await isInsideGitRepo(cwd))) {\n throw new GitxError(\"Not inside a git repository. cd into your project folder first.\", { exitCode: 2 });\n }\n\n const strategy = opts.strategy === \"rebase\" ? \"rebase\" : \"merge\";\n\n // โโ Handle --abort โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (opts.abort) {\n const op = await getInProgressOperation(cwd);\n if (!op) {\n logger.info(\"No rebase or merge in progress.\");\n return;\n }\n const abortSpinner = ora(`Aborting ${op}โฆ`).start();\n const { stderr } = await git([op, \"--abort\"], cwd);\n if (stderr) {\n abortSpinner.fail(`Abort failed: ${stderr}`);\n process.exitCode = 1;\n return;\n }\n abortSpinner.succeed(`${op.charAt(0).toUpperCase() + op.slice(1)} aborted. Branch restored to its previous state.`);\n return;\n }\n\n // โโ Handle --continue โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n if (opts.continue) {\n const op = await getInProgressOperation(cwd);\n if (!op) {\n logger.info(\"No rebase or merge in progress โ nothing to continue.\");\n return;\n }\n\n // Check if all conflicts are resolved\n const conflicts = await getConflictingFiles(cwd);\n if (conflicts.length > 0) {\n logger.error(`\\nโ There are still unresolved conflicts:\\n`);\n for (const f of conflicts) logger.info(` โข ${f}`);\n logger.info(`\\n Fix the conflicts above, then:\\n`);\n logger.info(` git add <file> # mark each file as resolved`);\n logger.info(` gitx sync --continue # resume\\n`);\n process.exitCode = 1;\n return;\n }\n\n // Stage all resolved files and continue\n await git([\"add\", \"-A\"], cwd);\n const continueSpinner = ora(`Continuing ${op}โฆ`).start();\n\n const env = { ...process.env, GIT_EDITOR: \"true\" }; // skip editor for commit msg\n const { stderr } = await execFileAsync(\n \"git\",\n [op, \"--continue\"],\n { cwd, env }\n ).then(\n (r) => ({ stdout: r.stdout, stderr: \"\" }),\n (e: { stderr?: string; message?: string }) => ({\n stdout: \"\",\n stderr: (e.stderr ?? e.message ?? \"\").trim(),\n })\n );\n\n if (stderr && !stderr.includes(\"Successfully\")) {\n continueSpinner.fail(`Could not continue ${op}: ${stderr}`);\n process.exitCode = 1;\n return;\n }\n continueSpinner.succeed(`${op.charAt(0).toUpperCase() + op.slice(1)} completed โ`);\n\n // Rebase rewrites history; merge does not\n await pushAfterSync(cwd, op === \"rebase\");\n return;\n }\n\n // โโ Normal sync flow โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n const head = await getCurrentBranch(cwd);\n\n // Resolve base\n let base: string;\n if (opts.base) {\n base = opts.base;\n logger.info(`๐ Base branch (provided): ${base}`);\n } else {\n const detectSpinner = ora(\"Detecting base branchโฆ\").start();\n base = await detectBaseBranch(cwd);\n detectSpinner.succeed(`Base branch: ${base}`);\n }\n\n if (head === base) {\n logger.info(`โจ Already on the base branch \"${base}\" โ nothing to sync.`);\n return;\n }\n\n logger.info(`\\n๐ Syncing ${head} onto origin/${base}\\n`);\n\n // Fetch latest\n const fetchSpinner = ora(\"Fetching latest from originโฆ\").start();\n const { stderr: fetchErr } = await git([\"fetch\", \"origin\"], cwd);\n if (fetchErr && !fetchErr.includes(\"->\")) {\n fetchSpinner.fail(`Fetch failed: ${fetchErr}`);\n process.exitCode = 1;\n return;\n }\n fetchSpinner.succeed(\"Fetched latest.\");\n\n // Check if we're already up to date\n const { stdout: behindCount } = await git(\n [\"rev-list\", \"--count\", `HEAD..origin/${base}`],\n cwd\n );\n if (behindCount === \"0\") {\n logger.success(`โ
\"${head}\" is already up to date with origin/${base}. Ready to merge!`);\n return;\n }\n\n // Run rebase or merge\n const syncSpinner = ora(\n strategy === \"rebase\"\n ? `Rebasing ${head} onto origin/${base}โฆ`\n : `Merging origin/${base} into ${head}โฆ`\n ).start();\n\n const syncArgs =\n strategy === \"rebase\"\n ? [\"rebase\", `origin/${base}`]\n : [\"merge\", `origin/${base}`, \"--no-edit\"];\n\n const { stderr: syncErr } = await git(syncArgs, cwd);\n\n // Detect conflict โ try AI resolution first\n const conflicts = await getConflictingFiles(cwd);\n if (conflicts.length > 0) {\n syncSpinner.fail(`Conflicts detected in ${conflicts.length} file(s) โ attempting AI resolutionโฆ`);\n\n // Try to load an AI client\n let gitx: Gitx | null = null;\n try {\n gitx = await Gitx.fromCwd(cwd);\n } catch {\n // No AI available; fall through to manual instructions\n }\n\n if (gitx && await Gitx.isAiAvailable(gitx.config)) {\n const resolved: string[] = [];\n const needsManual: string[] = [];\n\n for (const filePath of conflicts) {\n const absPath = resolvePath(cwd, filePath);\n let content: string;\n try {\n content = await readFile(absPath, \"utf8\");\n } catch {\n needsManual.push(filePath);\n continue;\n }\n\n // Skip binary files (no conflict markers)\n if (!content.includes(\"<<<<<<<\")) {\n needsManual.push(filePath);\n continue;\n }\n\n const resolveSpinner = ora(` ๐ค AI resolving: ${filePath}`).start();\n try {\n const result = await gitx.ai.resolveConflict(filePath, content);\n\n if (result.confidence === \"high\") {\n await writeFile(absPath, result.resolved, \"utf8\");\n resolveSpinner.succeed(` โ
Auto-resolved: ${filePath} โ ${result.explanation}`);\n resolved.push(filePath);\n } else {\n resolveSpinner.warn(` โ ๏ธ Low confidence: ${filePath} โ ${result.explanation}`);\n logger.info(`\\n AI proposed resolution (low confidence). Preview:\\n`);\n // Show first 40 lines of the resolved content as a preview\n const preview = result.resolved.split(\"\\n\").slice(0, 40).join(\"\\n\");\n logger.info(preview);\n if (result.resolved.split(\"\\n\").length > 40) {\n logger.info(` โฆ (${result.resolved.split(\"\\n\").length - 40} more lines)`);\n }\n logger.info(\"\");\n\n let apply = false;\n try {\n apply = await confirm({\n message: `Apply AI resolution for ${filePath}?`,\n default: true,\n });\n } catch {\n apply = false;\n }\n\n if (apply) {\n await writeFile(absPath, result.resolved, \"utf8\");\n logger.success(` โ
Applied: ${filePath}`);\n resolved.push(filePath);\n } else {\n logger.info(` โญ๏ธ Skipped: ${filePath} โ resolve manually`);\n needsManual.push(filePath);\n }\n }\n } catch {\n resolveSpinner.fail(` โ AI resolution failed for: ${filePath}`);\n needsManual.push(filePath);\n }\n }\n\n if (needsManual.length > 0) {\n logger.error(`\\nโ ๏ธ ${needsManual.length} file(s) still need manual resolution:\\n`);\n for (const f of needsManual) logger.info(` โข ${f}`);\n logger.info(`\\n Steps to finish:\\n`);\n logger.info(` 1. Open each file and fix the conflict markers (<<<<, ====, >>>>)`);\n logger.info(` 2. Mark resolved: git add <file>`);\n logger.info(` 3. Finish sync: gitx sync --continue`);\n logger.info(` 4. Retry merge: gitx pr merge <number>\\n`);\n logger.info(` To give up and go back: gitx sync --abort\\n`);\n process.exitCode = 1;\n return;\n }\n\n // All resolved โ stage and continue\n if (resolved.length > 0) {\n logger.success(`\\nโ
AI resolved all ${resolved.length} conflict(s). Staging and continuingโฆ\\n`);\n await git([\"add\", \"-A\"], cwd);\n\n const env = { ...process.env, GIT_EDITOR: \"true\" };\n const { stderr: contErr } = await execFileAsync(\n \"git\",\n [strategy === \"rebase\" ? \"rebase\" : \"merge\", \"--continue\"],\n { cwd, env }\n ).then(\n (r) => ({ stdout: r.stdout, stderr: \"\" }),\n (e: { stderr?: string; message?: string }) => ({\n stdout: \"\",\n stderr: (e.stderr ?? e.message ?? \"\").trim(),\n })\n );\n\n if (contErr && !contErr.toLowerCase().includes(\"successfully\")) {\n logger.error(`Could not continue ${strategy}: ${contErr}`);\n process.exitCode = 1;\n return;\n }\n }\n } else {\n // No AI โ fall back to manual instructions\n logger.error(`\\nโ ๏ธ Merge conflicts in ${conflicts.length} file(s):\\n`);\n for (const f of conflicts) logger.info(` โข ${f}`);\n logger.info(`\\n Steps to resolve:\\n`);\n logger.info(` 1. Open each file and fix the conflict markers (<<<<, ====, >>>>)`);\n logger.info(` 2. Mark resolved: git add <file>`);\n logger.info(` 3. Finish sync: gitx sync --continue`);\n logger.info(` 4. Retry merge: gitx pr merge <number>\\n`);\n logger.info(` To give up and go back: gitx sync --abort\\n`);\n process.exitCode = 1;\n return;\n }\n }\n\n if (syncErr && !syncErr.toLowerCase().includes(\"successfully\")) {\n syncSpinner.fail(`Sync failed: ${syncErr}`);\n process.exitCode = 1;\n return;\n }\n\n syncSpinner.succeed(\n strategy === \"rebase\"\n ? `Rebased ${head} onto origin/${base} โ`\n : `Merged origin/${base} into ${head} โ`\n );\n\n // Rebase rewrites history โ force-with-lease; merge โ plain push\n await pushAfterSync(cwd, strategy === \"rebase\");\n });\n}\n\n\nasync function pushAfterSync(cwd: string, forceWithLease = false): Promise<void> {\n // Rebase rewrites history โ requires --force-with-lease.\n // Merge does not rewrite history โ plain push is fine.\n const pushArgs = forceWithLease\n ? [\"push\", \"--force-with-lease\"]\n : [\"push\"];\n\n const label = forceWithLease ? \"Pushing (force-with-lease)โฆ\" : \"Pushingโฆ\";\n const pushSpinner = ora(label).start();\n const { stderr } = await git(pushArgs, cwd);\n if (stderr && stderr.includes(\"error\")) {\n pushSpinner.fail(`Push failed: ${stderr}`);\n const hint = forceWithLease ? \"git push --force-with-lease\" : \"git push\";\n logger.info(` Try: ${hint}`);\n process.exitCode = 1;\n return;\n }\n pushSpinner.succeed(\"Pushed โ\");\n logger.success(`\\nโ
Branch is now up to date. Run \\`gitx pr merge <number>\\` to merge.\\n`);\n}\n"]}
|
package/dist/utils/gitOps.d.ts
CHANGED
|
@@ -62,10 +62,17 @@ export declare function getWorkingDiffStat(cwd?: string): Promise<string>;
|
|
|
62
62
|
* Auto-detect the most likely base branch for the current feature branch.
|
|
63
63
|
*
|
|
64
64
|
* Strategy:
|
|
65
|
-
* 1.
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
65
|
+
* 1. Upstream tracking branch set via `git push -u` โ strongest signal.
|
|
66
|
+
* Ignored if it points to the branch's own remote ref (origin/current).
|
|
67
|
+
* 2. Scan ALL remote tracking branches and count how many commits HEAD has
|
|
68
|
+
* that each candidate doesn't (`git rev-list --count <ref>..HEAD`).
|
|
69
|
+
* The branch with the FEWEST such commits is the closest ancestor โ
|
|
70
|
+
* i.e. the branch this one was forked from.
|
|
71
|
+
*
|
|
72
|
+
* Example: main โ feature1 (3 commits) โ feature2 (2 commits)
|
|
73
|
+
* - origin/main..HEAD = 5 (feature1's 3 + feature2's 2)
|
|
74
|
+
* - origin/feature1..HEAD = 2 (just feature2's commits)
|
|
75
|
+
* โ feature1 wins โ
|
|
69
76
|
*
|
|
70
77
|
* Falls back to "main" if nothing can be determined.
|
|
71
78
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitOps.d.ts","sourceRoot":"","sources":["../../src/utils/gitOps.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA+BH,wBAAsB,gBAAgB,CAAC,GAAG,SAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAE3E;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,SAAgB,EACnB,iBAAiB,CAAC,EAAE,MAAM,GACzB,OAAO,CAAC,MAAM,CAAC,CA6BjB;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAClB,GAAG,SAAgB,GAClB,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,SAAS,GAAG,MAAM,CAQvE;AAID;;;GAGG;AACH,wBAAsB,aAAa,CACjC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,GAAG,SAAgB,GAClB,OAAO,CAAC,IAAI,CAAC,CAIf;AAID;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,GAAG,SAAgB,GAClB,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAe1C;AAID,wBAAsB,QAAQ,CAAC,GAAG,SAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAEjE;AAED,wBAAsB,gBAAgB,CAAC,GAAG,SAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAO5E;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,GAAG,SAAgB,GAClB,OAAO,CAAC,MAAM,CAAC,CAGjB;AAID,wBAAsB,UAAU,CAC9B,UAAU,EAAE,MAAM,EAClB,GAAG,SAAgB,GAClB,OAAO,CAAC,IAAI,CAAC,CAEf;AAID;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,SAAgB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAU7E;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,GAAG,SAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAMxE;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,SAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAM5E;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,GAAG,SAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAQzE;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,SAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ7E;AAED
|
|
1
|
+
{"version":3,"file":"gitOps.d.ts","sourceRoot":"","sources":["../../src/utils/gitOps.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/gitOps.js
CHANGED
|
@@ -205,20 +205,24 @@ export async function getWorkingDiffStat(cwd = process.cwd()) {
|
|
|
205
205
|
* Auto-detect the most likely base branch for the current feature branch.
|
|
206
206
|
*
|
|
207
207
|
* Strategy:
|
|
208
|
-
* 1.
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
208
|
+
* 1. Upstream tracking branch set via `git push -u` โ strongest signal.
|
|
209
|
+
* Ignored if it points to the branch's own remote ref (origin/current).
|
|
210
|
+
* 2. Scan ALL remote tracking branches and count how many commits HEAD has
|
|
211
|
+
* that each candidate doesn't (`git rev-list --count <ref>..HEAD`).
|
|
212
|
+
* The branch with the FEWEST such commits is the closest ancestor โ
|
|
213
|
+
* i.e. the branch this one was forked from.
|
|
214
|
+
*
|
|
215
|
+
* Example: main โ feature1 (3 commits) โ feature2 (2 commits)
|
|
216
|
+
* - origin/main..HEAD = 5 (feature1's 3 + feature2's 2)
|
|
217
|
+
* - origin/feature1..HEAD = 2 (just feature2's commits)
|
|
218
|
+
* โ feature1 wins โ
|
|
212
219
|
*
|
|
213
220
|
* Falls back to "main" if nothing can be determined.
|
|
214
221
|
*/
|
|
215
222
|
export async function detectBaseBranch(cwd = process.cwd()) {
|
|
216
|
-
// Get current branch name upfront โ used for all checks below
|
|
217
223
|
const current = await git(["rev-parse", "--abbrev-ref", "HEAD"], cwd).catch(() => "");
|
|
218
|
-
// 1.
|
|
219
|
-
// branch (
|
|
220
|
-
// e.g. "origin/gitx/test" โ "gitx/test" == current โ skip
|
|
221
|
-
// "origin/main" โ "main" != current โ use it
|
|
224
|
+
// 1. Explicit upstream tracking branch โ only trust it if it differs from
|
|
225
|
+
// the current branch (guards against "origin/feature2" โ "feature2").
|
|
222
226
|
try {
|
|
223
227
|
const upstream = await git(["rev-parse", "--abbrev-ref", "@{upstream}"], cwd);
|
|
224
228
|
const branch = upstream.replace(/^[^/]+\//, "").trim();
|
|
@@ -226,39 +230,51 @@ export async function detectBaseBranch(cwd = process.cwd()) {
|
|
|
226
230
|
return branch;
|
|
227
231
|
}
|
|
228
232
|
catch {
|
|
229
|
-
// No upstream
|
|
233
|
+
// No upstream set โ fall through
|
|
230
234
|
}
|
|
231
|
-
// 2.
|
|
235
|
+
// 2. Scan all remote tracking branches (origin/*), compute how many commits
|
|
236
|
+
// HEAD has that each remote ref doesn't. Closest ancestor wins.
|
|
232
237
|
try {
|
|
233
|
-
const
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
238
|
+
const remoteOut = await git(["branch", "-r", "--format=%(refname:short)"], cwd);
|
|
239
|
+
const remoteRefs = remoteOut
|
|
240
|
+
.split("\n")
|
|
241
|
+
.map((b) => b.trim())
|
|
242
|
+
.filter((b) => b && !b.endsWith("/HEAD")); // skip "origin/HEAD" pointer
|
|
243
|
+
if (remoteRefs.length === 0)
|
|
244
|
+
return "main";
|
|
245
|
+
// Count commits ahead of every remote ref in parallel for speed
|
|
246
|
+
const results = await Promise.all(remoteRefs.map(async (ref) => {
|
|
247
|
+
const name = ref.replace(/^[^/]+\//, ""); // "origin/feature1" โ "feature1"
|
|
248
|
+
if (name === current)
|
|
249
|
+
return null; // skip own remote tracking ref
|
|
250
|
+
try {
|
|
251
|
+
const out = await git(["rev-list", "--count", `${ref}..HEAD`], cwd);
|
|
252
|
+
return { branch: name, ahead: parseInt(out.trim(), 10) || 0 };
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
}));
|
|
258
|
+
const counts = results.filter((r) => r !== null);
|
|
259
|
+
if (counts.length === 0)
|
|
260
|
+
return "main";
|
|
261
|
+
// Sort by fewest commits ahead โ that's the closest ancestor.
|
|
262
|
+
// Tiebreak: prefer default branch names so "main" beats an equally-close
|
|
263
|
+
// unrelated branch that happens to have 0 commits.
|
|
264
|
+
const defaults = new Set(["main", "master", "develop", "dev", "staging"]);
|
|
265
|
+
counts.sort((a, b) => {
|
|
266
|
+
if (a.ahead !== b.ahead)
|
|
267
|
+
return a.ahead - b.ahead;
|
|
268
|
+
// Same distance โ prefer default branches
|
|
269
|
+
const aDefault = defaults.has(a.branch) ? 0 : 1;
|
|
270
|
+
const bDefault = defaults.has(b.branch) ? 0 : 1;
|
|
271
|
+
return aDefault - bDefault;
|
|
272
|
+
});
|
|
273
|
+
return counts[0].branch;
|
|
237
274
|
}
|
|
238
275
|
catch {
|
|
239
|
-
|
|
240
|
-
}
|
|
241
|
-
// 3. Count commits ahead of each common default branch name
|
|
242
|
-
const candidates = ["main", "master", "develop", "dev", "staging"];
|
|
243
|
-
const counts = [];
|
|
244
|
-
for (const candidate of candidates) {
|
|
245
|
-
if (candidate === current)
|
|
246
|
-
continue;
|
|
247
|
-
try {
|
|
248
|
-
// Count commits on HEAD not in candidate
|
|
249
|
-
const out = await git(["rev-list", "--count", `${candidate}..HEAD`], cwd);
|
|
250
|
-
counts.push({ branch: candidate, ahead: parseInt(out.trim(), 10) || 0 });
|
|
251
|
-
}
|
|
252
|
-
catch {
|
|
253
|
-
// Branch doesn't exist locally โ skip
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
if (counts.length > 0) {
|
|
257
|
-
// Pick the branch with the fewest commits ahead (closest ancestor)
|
|
258
|
-
counts.sort((a, b) => a.ahead - b.ahead);
|
|
259
|
-
return counts[0].branch;
|
|
276
|
+
return "main";
|
|
260
277
|
}
|
|
261
|
-
return "main";
|
|
262
278
|
}
|
|
263
279
|
/**
|
|
264
280
|
* Get the one-line commit log for commits on HEAD that are not in baseBranch.
|