@g-abhishek/gitx 0.1.1 β†’ 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.
Files changed (161) hide show
  1. package/README.md +374 -3
  2. package/dist/ai/claudeAi.d.ts +35 -0
  3. package/dist/ai/claudeAi.d.ts.map +1 -0
  4. package/dist/ai/claudeAi.js +396 -0
  5. package/dist/ai/claudeAi.js.map +1 -0
  6. package/dist/ai/claudeCliAi.d.ts +27 -0
  7. package/dist/ai/claudeCliAi.d.ts.map +1 -0
  8. package/dist/ai/claudeCliAi.js +312 -0
  9. package/dist/ai/claudeCliAi.js.map +1 -0
  10. package/dist/ai/localClaudeAi.d.ts +2 -0
  11. package/dist/ai/localClaudeAi.d.ts.map +1 -0
  12. package/dist/ai/localClaudeAi.js +4 -0
  13. package/dist/ai/localClaudeAi.js.map +1 -0
  14. package/dist/ai/mockAi.d.ts +8 -1
  15. package/dist/ai/mockAi.d.ts.map +1 -1
  16. package/dist/ai/mockAi.js +57 -0
  17. package/dist/ai/mockAi.js.map +1 -1
  18. package/dist/ai/openAiAi.d.ts +33 -0
  19. package/dist/ai/openAiAi.d.ts.map +1 -0
  20. package/dist/ai/openAiAi.js +388 -0
  21. package/dist/ai/openAiAi.js.map +1 -0
  22. package/dist/ai/reviewHelpers.d.ts +66 -0
  23. package/dist/ai/reviewHelpers.d.ts.map +1 -0
  24. package/dist/ai/reviewHelpers.js +559 -0
  25. package/dist/ai/reviewHelpers.js.map +1 -0
  26. package/dist/ai/types.d.ts +247 -0
  27. package/dist/ai/types.d.ts.map +1 -1
  28. package/dist/ai/types.js.map +1 -1
  29. package/dist/cli/commands/ask.d.ts +27 -0
  30. package/dist/cli/commands/ask.d.ts.map +1 -0
  31. package/dist/cli/commands/ask.js +230 -0
  32. package/dist/cli/commands/ask.js.map +1 -0
  33. package/dist/cli/commands/commit.d.ts +16 -0
  34. package/dist/cli/commands/commit.d.ts.map +1 -0
  35. package/dist/cli/commands/commit.js +163 -0
  36. package/dist/cli/commands/commit.js.map +1 -0
  37. package/dist/cli/commands/config.d.ts +4 -0
  38. package/dist/cli/commands/config.d.ts.map +1 -0
  39. package/dist/cli/commands/config.js +666 -0
  40. package/dist/cli/commands/config.js.map +1 -0
  41. package/dist/cli/commands/implement.d.ts.map +1 -1
  42. package/dist/cli/commands/implement.js +149 -28
  43. package/dist/cli/commands/implement.js.map +1 -1
  44. package/dist/cli/commands/init.d.ts +4 -0
  45. package/dist/cli/commands/init.d.ts.map +1 -1
  46. package/dist/cli/commands/init.js +7 -54
  47. package/dist/cli/commands/init.js.map +1 -1
  48. package/dist/cli/commands/port.d.ts +32 -0
  49. package/dist/cli/commands/port.d.ts.map +1 -0
  50. package/dist/cli/commands/port.js +554 -0
  51. package/dist/cli/commands/port.js.map +1 -0
  52. package/dist/cli/commands/pr/close.d.ts +15 -0
  53. package/dist/cli/commands/pr/close.d.ts.map +1 -0
  54. package/dist/cli/commands/pr/close.js +71 -0
  55. package/dist/cli/commands/pr/close.js.map +1 -0
  56. package/dist/cli/commands/pr/create.d.ts +17 -0
  57. package/dist/cli/commands/pr/create.d.ts.map +1 -1
  58. package/dist/cli/commands/pr/create.js +209 -5
  59. package/dist/cli/commands/pr/create.js.map +1 -1
  60. package/dist/cli/commands/pr/fixComments.d.ts.map +1 -1
  61. package/dist/cli/commands/pr/fixComments.js +77 -5
  62. package/dist/cli/commands/pr/fixComments.js.map +1 -1
  63. package/dist/cli/commands/pr/index.d.ts.map +1 -1
  64. package/dist/cli/commands/pr/index.js +4 -0
  65. package/dist/cli/commands/pr/index.js.map +1 -1
  66. package/dist/cli/commands/pr/list.d.ts.map +1 -1
  67. package/dist/cli/commands/pr/list.js +26 -3
  68. package/dist/cli/commands/pr/list.js.map +1 -1
  69. package/dist/cli/commands/pr/merge.d.ts +23 -0
  70. package/dist/cli/commands/pr/merge.d.ts.map +1 -0
  71. package/dist/cli/commands/pr/merge.js +191 -0
  72. package/dist/cli/commands/pr/merge.js.map +1 -0
  73. package/dist/cli/commands/pr/review.d.ts.map +1 -1
  74. package/dist/cli/commands/pr/review.js +123 -5
  75. package/dist/cli/commands/pr/review.js.map +1 -1
  76. package/dist/cli/commands/push.d.ts +16 -0
  77. package/dist/cli/commands/push.d.ts.map +1 -0
  78. package/dist/cli/commands/push.js +166 -0
  79. package/dist/cli/commands/push.js.map +1 -0
  80. package/dist/cli/commands/sync.d.ts +24 -0
  81. package/dist/cli/commands/sync.d.ts.map +1 -0
  82. package/dist/cli/commands/sync.js +414 -0
  83. package/dist/cli/commands/sync.js.map +1 -0
  84. package/dist/cli/index.d.ts.map +1 -1
  85. package/dist/cli/index.js +34 -6
  86. package/dist/cli/index.js.map +1 -1
  87. package/dist/config/config.d.ts +20 -3
  88. package/dist/config/config.d.ts.map +1 -1
  89. package/dist/config/config.js +103 -24
  90. package/dist/config/config.js.map +1 -1
  91. package/dist/config/schema.d.ts.map +1 -1
  92. package/dist/config/schema.js +70 -9
  93. package/dist/config/schema.js.map +1 -1
  94. package/dist/core/context.d.ts +13 -0
  95. package/dist/core/context.d.ts.map +1 -0
  96. package/dist/core/context.js +2 -0
  97. package/dist/core/context.js.map +1 -0
  98. package/dist/core/gitx.d.ts +47 -0
  99. package/dist/core/gitx.d.ts.map +1 -1
  100. package/dist/core/gitx.js +204 -9
  101. package/dist/core/gitx.js.map +1 -1
  102. package/dist/index.d.ts +1 -5
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.js +4 -1
  105. package/dist/index.js.map +1 -1
  106. package/dist/providers/azure.d.ts +26 -0
  107. package/dist/providers/azure.d.ts.map +1 -0
  108. package/dist/providers/azure.js +256 -0
  109. package/dist/providers/azure.js.map +1 -0
  110. package/dist/providers/base.d.ts +104 -0
  111. package/dist/providers/base.d.ts.map +1 -0
  112. package/dist/providers/base.js +5 -0
  113. package/dist/providers/base.js.map +1 -0
  114. package/dist/providers/factory.d.ts +8 -0
  115. package/dist/providers/factory.d.ts.map +1 -0
  116. package/dist/providers/factory.js +25 -0
  117. package/dist/providers/factory.js.map +1 -0
  118. package/dist/providers/github.d.ts +19 -0
  119. package/dist/providers/github.d.ts.map +1 -0
  120. package/dist/providers/github.js +291 -0
  121. package/dist/providers/github.js.map +1 -0
  122. package/dist/providers/gitlab.d.ts +19 -0
  123. package/dist/providers/gitlab.d.ts.map +1 -0
  124. package/dist/providers/gitlab.js +186 -0
  125. package/dist/providers/gitlab.js.map +1 -0
  126. package/dist/types/config.d.ts +53 -9
  127. package/dist/types/config.d.ts.map +1 -1
  128. package/dist/types/config.js.map +1 -1
  129. package/dist/utils/azureAuth.d.ts +51 -0
  130. package/dist/utils/azureAuth.d.ts.map +1 -0
  131. package/dist/utils/azureAuth.js +172 -0
  132. package/dist/utils/azureAuth.js.map +1 -0
  133. package/dist/utils/git.d.ts +22 -0
  134. package/dist/utils/git.d.ts.map +1 -1
  135. package/dist/utils/git.js +63 -7
  136. package/dist/utils/git.js.map +1 -1
  137. package/dist/utils/gitOps.d.ts +118 -0
  138. package/dist/utils/gitOps.d.ts.map +1 -0
  139. package/dist/utils/gitOps.js +380 -0
  140. package/dist/utils/gitOps.js.map +1 -0
  141. package/dist/utils/lockFile.d.ts +13 -0
  142. package/dist/utils/lockFile.d.ts.map +1 -0
  143. package/dist/utils/lockFile.js +54 -0
  144. package/dist/utils/lockFile.js.map +1 -0
  145. package/dist/utils/retry.d.ts +10 -0
  146. package/dist/utils/retry.d.ts.map +1 -0
  147. package/dist/utils/retry.js +31 -0
  148. package/dist/utils/retry.js.map +1 -0
  149. package/dist/workflows/implement.d.ts +41 -0
  150. package/dist/workflows/implement.d.ts.map +1 -0
  151. package/dist/workflows/implement.js +219 -0
  152. package/dist/workflows/implement.js.map +1 -0
  153. package/dist/workflows/pr.d.ts +41 -0
  154. package/dist/workflows/pr.d.ts.map +1 -0
  155. package/dist/workflows/pr.js +285 -0
  156. package/dist/workflows/pr.js.map +1 -0
  157. package/dist/workflows/prAddress.d.ts +55 -0
  158. package/dist/workflows/prAddress.d.ts.map +1 -0
  159. package/dist/workflows/prAddress.js +349 -0
  160. package/dist/workflows/prAddress.js.map +1 -0
  161. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port.js","sourceRoot":"","sources":["../../../src/cli/commands/port.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * gitx port <target1> [target2...]\n *\n * Cherry-pick all commits from the current branch onto one or more target\n * branches, with AI-assisted conflict resolution, then push and open PRs.\n *\n * Smart incremental detection via `git cherry`:\n * - First run β†’ creates port/<source>-to-<target>, ports all commits\n * - Re-run β†’ detects which commits are NEW since the last port, ports only those\n * - Up to date β†’ tells you nothing to do\n *\n * Flow (per target branch):\n * 1. Detect base branch β†’ collect commits on current branch (base..HEAD)\n * 2. If port branch exists β†’ run `git cherry` to find unported commits only\n * 3. Create (or checkout) port/<source>-to-<target> from origin/<target>\n * 4. Cherry-pick commits oldestβ†’newest with -x flag (records source SHA)\n * 5. On conflict β†’ AI resolves β†’ stage β†’ cherry-pick --continue\n * 6. On unresolvable β†’ pause, print manual instructions, `gitx port --continue`\n * 7. Push β†’ create PR\n *\n * Usage:\n * gitx port release/v2 # port to one branch\n * gitx port release/v2 hotfix/v1 # port to multiple branches\n * gitx port release/v2 --base develop # override base branch\n * gitx port release/v2 --no-pr # skip PR creation\n * gitx port release/v2 --draft # create draft PRs\n * gitx port --continue # after manually resolving conflicts\n * gitx port --abort # abort a stuck cherry-pick\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, writeFile as fsWriteFile } from \"node:fs/promises\";\nimport { resolve as resolvePath, join as pathJoin } from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { confirm } from \"@inquirer/prompts\";\nimport { logger } from \"../../logger/logger.js\";\nimport { isInsideGitRepo } from \"../../utils/git.js\";\nimport { getCurrentBranch, detectBaseBranch, getBranchCommits, getBranchDiff, getBranchStat } from \"../../utils/gitOps.js\";\nimport { GitxError } from \"../../utils/errors.js\";\nimport { Gitx } from \"../../core/gitx.js\";\nimport { createProvider } from \"../../providers/factory.js\";\n\nconst execFileAsync = promisify(execFile);\n\n// ─── Git helper ───────────────────────────────────────────────────────────────\n\nasync function git(\n args: string[],\n cwd: string\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n try {\n const result = await execFileAsync(\"git\", args, { cwd });\n return { stdout: result.stdout.trim(), stderr: \"\", exitCode: 0 };\n } catch (err: unknown) {\n const e = err as { stdout?: string; stderr?: string; code?: number };\n return {\n stdout: e.stdout?.trim() ?? \"\",\n stderr: e.stderr?.trim() ?? \"\",\n exitCode: e.code ?? 1,\n };\n }\n}\n\n// ─── Port state file ──────────────────────────────────────────────────────────\n// Saved to .git/GITX_PORT so --continue knows where to resume.\n\ninterface PortState {\n sourceBranch: string;\n portBranch: string;\n targetBranch: string;\n remainingCommits: string[]; // SHAs oldestβ†’newest still to cherry-pick\n noPr: boolean;\n draft: boolean;\n}\n\nasync function loadPortState(cwd: string): Promise<PortState | null> {\n const { stdout: gitDir } = await git([\"rev-parse\", \"--git-dir\"], cwd);\n const statePath = pathJoin(cwd, gitDir || \".git\", \"GITX_PORT\");\n try {\n const raw = await readFile(statePath, \"utf8\");\n return JSON.parse(raw) as PortState;\n } catch {\n return null;\n }\n}\n\nasync function savePortState(cwd: string, state: PortState): Promise<void> {\n const { stdout: gitDir } = await git([\"rev-parse\", \"--git-dir\"], cwd);\n const statePath = pathJoin(cwd, gitDir || \".git\", \"GITX_PORT\");\n await fsWriteFile(statePath, JSON.stringify(state, null, 2), \"utf8\");\n}\n\nasync function clearPortState(cwd: string): Promise<void> {\n const { stdout: gitDir } = await git([\"rev-parse\", \"--git-dir\"], cwd);\n const statePath = pathJoin(cwd, gitDir || \".git\", \"GITX_PORT\");\n try {\n const { unlink } = await import(\"node:fs/promises\");\n await unlink(statePath);\n } catch { /* already gone */ }\n}\n\n// ─── Conflict detection ───────────────────────────────────────────────────────\n\nasync function getConflictingFiles(cwd: string): Promise<string[]> {\n const { stdout } = await git([\"diff\", \"--name-only\", \"--diff-filter=U\"], cwd);\n return stdout.split(\"\\n\").map((l) => l.trim()).filter(Boolean);\n}\n\nasync function isCherryPickInProgress(cwd: string): Promise<boolean> {\n const { stdout: gitDir } = await git([\"rev-parse\", \"--git-dir\"], cwd);\n const cherryPickHead = pathJoin(cwd, gitDir || \".git\", \"CHERRY_PICK_HEAD\");\n return existsSync(cherryPickHead);\n}\n\n// ─── Incremental commit detection ────────────────────────────────────────────\n\n/**\n * Use `git cherry <upstreamBranch> <headBranch>` to find commits in headBranch\n * that are NOT yet present in upstreamBranch (by patch-id comparison).\n *\n * Returns SHAs of unported commits, oldest-first.\n * Lines prefixed with '+' are not yet ported; '-' are already present.\n */\nasync function getUnportedCommits(\n cwd: string,\n portBranch: string,\n sourceBranch: string\n): Promise<string[]> {\n // git cherry compares patch IDs β€” works even when SHAs differ after cherry-pick\n const { stdout } = await git(\n [\"cherry\", portBranch, sourceBranch],\n cwd\n );\n const lines = stdout.split(\"\\n\").filter(Boolean);\n // '+' = not on portBranch (needs porting), '-' = already there\n const unported = lines\n .filter((l) => l.startsWith(\"+ \"))\n .map((l) => l.slice(2).trim());\n // git cherry returns newest-first; reverse to get oldest-first for cherry-pick\n return unported.reverse();\n}\n\n/**\n * Get ALL commits on the current branch (base..HEAD), oldest-first.\n * These are the SHAs we'll cherry-pick on a first run.\n */\nasync function getAllBranchCommitShas(\n cwd: string,\n baseBranch: string\n): Promise<string[]> {\n const { stdout } = await git(\n [\"log\", \"--format=%H\", \"--no-decorate\", `${baseBranch}..HEAD`],\n cwd\n );\n const shas = stdout.split(\"\\n\").map((l) => l.trim()).filter(Boolean);\n // git log returns newest-first; reverse to oldest-first\n return shas.reverse();\n}\n\n// ─── AI conflict resolution ───────────────────────────────────────────────────\n\nasync function resolveConflictsWithAi(\n conflictFiles: string[],\n cwd: string,\n gitx: Gitx\n): Promise<{ resolved: string[]; needsManual: string[] }> {\n const resolved: string[] = [];\n const needsManual: string[] = [];\n\n for (const filePath of conflictFiles) {\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 if (!content.includes(\"<<<<<<<\")) {\n needsManual.push(filePath);\n continue;\n }\n\n const spinner = 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 spinner.succeed(` βœ… Auto-resolved: ${filePath} β€” ${result.explanation}`);\n resolved.push(filePath);\n } else {\n spinner.warn(` ⚠️ Low confidence: ${filePath} β€” ${result.explanation}`);\n const preview = result.resolved.split(\"\\n\").slice(0, 30).join(\"\\n\");\n logger.info(`\\n${preview}\\n`);\n\n let apply = false;\n try {\n apply = await confirm({ message: `Apply AI resolution for ${filePath}?`, default: true });\n } catch { apply = false; }\n\n if (apply) {\n await writeFile(absPath, result.resolved, \"utf8\");\n logger.success(` βœ… Applied: ${filePath}`);\n resolved.push(filePath);\n } else {\n needsManual.push(filePath);\n }\n }\n } catch {\n spinner.fail(` ❌ AI resolution failed: ${filePath} β€” resolve manually`);\n needsManual.push(filePath);\n }\n }\n\n return { resolved, needsManual };\n}\n\n// ─── Cherry-pick a list of commits ───────────────────────────────────────────\n\ninterface CherryPickResult {\n status: \"success\" | \"paused\";\n remainingCommits: string[]; // only set when status is \"paused\"\n}\n\nasync function cherryPickCommits(\n commits: string[],\n cwd: string,\n gitx: Gitx\n): Promise<CherryPickResult> {\n for (let i = 0; i < commits.length; i++) {\n const sha = commits[i]!;\n const shortSha = sha.slice(0, 7);\n\n // Get the commit subject for display\n const { stdout: subject } = await git(\n [\"log\", \"--format=%s\", \"-1\", sha],\n cwd\n );\n\n logger.info(`\\n πŸ’ [${i + 1}/${commits.length}] ${shortSha} β€” ${subject}`);\n\n // -x appends \"(cherry picked from commit <sha>)\" to the commit message\n const result = await git([\"cherry-pick\", \"-x\", sha], cwd);\n\n if (result.exitCode === 0) {\n logger.success(` βœ“ Applied cleanly`);\n continue;\n }\n\n // Cherry-pick failed β€” check for conflicts\n const conflictFiles = await getConflictingFiles(cwd);\n\n if (conflictFiles.length === 0) {\n // Some other error (e.g. empty commit)\n logger.warn(` ⚠️ Skipping (empty or already applied): ${shortSha}`);\n await git([\"cherry-pick\", \"--skip\"], cwd);\n continue;\n }\n\n logger.warn(`\\n ⚑ Conflicts in ${conflictFiles.length} file(s):`);\n conflictFiles.forEach((f) => logger.info(` β€’ ${f}`));\n\n const { resolved, needsManual } = await resolveConflictsWithAi(conflictFiles, cwd, gitx);\n\n if (needsManual.length > 0) {\n // Can't auto-resolve everything β€” pause and let user fix manually\n logger.warn(`\\n β›” ${needsManual.length} file(s) need manual resolution:`);\n needsManual.forEach((f) => logger.warn(` β€’ ${f}`));\n\n // Stage the auto-resolved files so user only needs to fix the rest\n if (resolved.length > 0) {\n await git([\"add\", ...resolved], cwd);\n logger.info(`\\n βœ… Auto-resolved files have been staged.`);\n }\n\n return {\n status: \"paused\",\n remainingCommits: commits.slice(i), // include current commit (still in progress)\n };\n }\n\n // All conflicts resolved β€” stage and continue\n await git([\"add\", ...resolved], cwd);\n const continueResult = await git(\n [\"cherry-pick\", \"--continue\", \"--no-edit\"],\n cwd\n );\n\n if (continueResult.exitCode !== 0) {\n // Still failing β€” pause\n return {\n status: \"paused\",\n remainingCommits: commits.slice(i),\n };\n }\n\n logger.success(` βœ… Conflict resolved and applied`);\n }\n\n return { status: \"success\", remainingCommits: [] };\n}\n\n// ─── Port a single target branch ─────────────────────────────────────────────\n\nasync function portToTarget(opts: {\n sourceBranch: string;\n targetBranch: string;\n baseBranch: string;\n cwd: string;\n gitx: Gitx;\n noPr: boolean;\n draft: boolean;\n}): Promise<void> {\n const { sourceBranch, targetBranch, baseBranch, cwd, gitx, noPr, draft } = opts;\n const portBranch = `port/${sourceBranch.replace(/\\//g, \"-\")}-to-${targetBranch.replace(/\\//g, \"-\")}`;\n\n logger.info(`\\n${\"─\".repeat(60)}`);\n logger.info(`🎯 Target: ${targetBranch}`);\n logger.info(` Port branch: ${portBranch}`);\n\n // ── 1. Fetch origin ────────────────────────────────────────────────────────\n const fetchSpinner = ora(\"Fetching origin…\").start();\n const fetchResult = await git([\"fetch\", \"origin\"], cwd);\n if (fetchResult.exitCode !== 0) {\n fetchSpinner.fail(`fetch failed: ${fetchResult.stderr}`);\n return;\n }\n fetchSpinner.succeed(\"Fetched origin\");\n\n // ── 2. Check if target branch exists on origin ────────────────────────────\n const { stdout: remoteRefs } = await git(\n [\"ls-remote\", \"--heads\", \"origin\", targetBranch],\n cwd\n );\n if (!remoteRefs.trim()) {\n logger.error(` ❌ Branch \"${targetBranch}\" does not exist on origin. Skipping.`);\n return;\n }\n\n // ── 3. Determine which commits to port ────────────────────────────────────\n const portBranchExistsRemote = (await git(\n [\"ls-remote\", \"--heads\", \"origin\", portBranch],\n cwd\n )).stdout.trim().length > 0;\n\n const portBranchExistsLocal = (await git(\n [\"rev-parse\", \"--verify\", portBranch],\n cwd\n )).exitCode === 0;\n\n const portBranchExists = portBranchExistsLocal || portBranchExistsRemote;\n\n let commitShas: string[];\n\n if (portBranchExists) {\n // Incremental run β€” use git cherry to find only NEW commits\n const localRef = portBranchExistsLocal\n ? portBranch\n : `origin/${portBranch}`;\n\n const unported = await getUnportedCommits(cwd, localRef, sourceBranch);\n\n if (unported.length === 0) {\n logger.success(` βœ… Already up to date β€” nothing new to port to ${targetBranch}`);\n return;\n }\n\n logger.info(` πŸ“‹ ${unported.length} new commit(s) to port (incremental):`);\n for (const sha of unported) {\n const { stdout: subject } = await git([\"log\", \"--format=%s\", \"-1\", sha], cwd);\n logger.info(` + ${sha.slice(0, 7)} β€” ${subject}`);\n }\n\n commitShas = unported;\n } else {\n // First run β€” port all commits on this branch\n commitShas = await getAllBranchCommitShas(cwd, baseBranch);\n\n if (commitShas.length === 0) {\n logger.warn(` ⚠️ No commits found on \"${sourceBranch}\" since \"${baseBranch}\". Nothing to port.`);\n return;\n }\n\n logger.info(` πŸ“‹ ${commitShas.length} commit(s) to port:`);\n for (const sha of commitShas) {\n const { stdout: subject } = await git([\"log\", \"--format=%s\", \"-1\", sha], cwd);\n logger.info(` + ${sha.slice(0, 7)} β€” ${subject}`);\n }\n }\n\n const proceed = await confirm({\n message: `Port ${commitShas.length} commit(s) to ${targetBranch}?`,\n default: true,\n });\n if (!proceed) {\n logger.info(\" Skipped.\");\n return;\n }\n\n // ── 4. Create or checkout the port branch ─────────────────────────────────\n if (portBranchExists) {\n // Checkout and update from origin if it exists remotely\n if (portBranchExistsLocal) {\n await git([\"checkout\", portBranch], cwd);\n } else {\n await git([\"checkout\", \"-b\", portBranch, `origin/${portBranch}`], cwd);\n }\n // Pull latest from origin if it's there\n if (portBranchExistsRemote) {\n await git([\"pull\", \"--ff-only\", \"origin\", portBranch], cwd);\n }\n } else {\n // Create fresh from origin/<target>\n const checkoutResult = await git(\n [\"checkout\", \"-b\", portBranch, `origin/${targetBranch}`],\n cwd\n );\n if (checkoutResult.exitCode !== 0) {\n logger.error(` ❌ Could not create port branch: ${checkoutResult.stderr}`);\n return;\n }\n }\n\n // ── 5. Cherry-pick ─────────────────────────────────────────────────────────\n const pickResult = await cherryPickCommits(commitShas, cwd, gitx);\n\n if (pickResult.status === \"paused\") {\n // Save state and bail β€” user needs to fix conflicts manually\n await savePortState(cwd, {\n sourceBranch,\n portBranch,\n targetBranch,\n remainingCommits: pickResult.remainingCommits,\n noPr,\n draft,\n });\n\n logger.warn(`\\n β›” Port paused β€” manual conflict resolution needed.`);\n logger.info(`\\n Fix the conflicts above, then run:`);\n logger.info(` git add <resolved-files>`);\n logger.info(` gitx port --continue`);\n logger.info(`\\n Or to abandon this port:`);\n logger.info(` gitx port --abort`);\n return;\n }\n\n // ── 6. Push port branch ────────────────────────────────────────────────────\n const pushSpinner = ora(`Pushing ${portBranch}…`).start();\n const pushResult = await git(\n [\"push\", \"--force-with-lease\", \"--set-upstream\", \"origin\", portBranch],\n cwd\n );\n if (pushResult.exitCode !== 0) {\n pushSpinner.fail(`Push failed: ${pushResult.stderr}`);\n return;\n }\n pushSpinner.succeed(`Pushed ${portBranch}`);\n\n // ── 7. Create PR ───────────────────────────────────────────────────────────\n if (noPr) {\n logger.success(`\\n βœ… Port branch pushed: ${portBranch}`);\n logger.info(` Create PR manually: ${portBranch} β†’ ${targetBranch}`);\n return;\n }\n\n let ctx;\n try {\n ctx = await gitx.getRepoContext();\n } catch {\n logger.warn(` ⚠️ Could not get repo context for PR creation β€” create PR manually.`);\n logger.success(` βœ… Port branch pushed: ${portBranch}`);\n return;\n }\n\n const provider = createProvider(ctx);\n\n // Check if a PR already exists for this port branch\n let existingPrUrl: string | undefined;\n try {\n const allPrs = await provider.listPRs(ctx.repoSlug);\n const existing = allPrs.find(\n (pr) => pr.head === portBranch && pr.base === targetBranch && pr.state === \"open\"\n );\n if (existing) {\n existingPrUrl = existing.url;\n }\n } catch { /* non-fatal */ }\n\n if (existingPrUrl) {\n logger.success(` βœ… PR already open β€” updated with new commits: ${existingPrUrl}`);\n return;\n }\n\n // Generate PR content with AI\n const prSpinner = ora(\"Generating PR description…\").start();\n let prTitle = `[Port β†’ ${targetBranch}] ${sourceBranch}`;\n let prBody = `Ported from \\`${sourceBranch}\\` β†’ \\`${targetBranch}\\`.\\n\\n`;\n prBody += `Cherry-picked ${commitShas.length} commit(s):\\n`;\n for (const sha of commitShas) {\n const { stdout: subject } = await git([\"log\", \"--format=%s\", \"-1\", sha], cwd);\n prBody += `- ${sha.slice(0, 7)} ${subject}\\n`;\n }\n\n try {\n const commits = await getBranchCommits(cwd, targetBranch);\n const diff = await getBranchDiff(cwd, `origin/${targetBranch}`);\n const stat = await getBranchStat(cwd, `origin/${targetBranch}`);\n const aiContent = await gitx.ai.generatePrContent(commits, diff, stat || undefined);\n // Prepend port context to AI-generated body\n prTitle = `[Port β†’ ${targetBranch}] ${aiContent.title}`;\n prBody = `> πŸ’ Ported from \\`${sourceBranch}\\` β†’ \\`${targetBranch}\\` (${commitShas.length} commit(s))\\n\\n${aiContent.body}`;\n prSpinner.succeed(\"PR description generated\");\n } catch {\n prSpinner.warn(\"Could not generate AI description β€” using commit list\");\n }\n\n try {\n const createdPr = await provider.createPR(ctx.repoSlug, {\n title: prTitle,\n body: prBody,\n head: portBranch,\n base: targetBranch,\n draft,\n });\n logger.success(`\\n βœ… PR created: ${createdPr.url}`);\n logger.info(` #${createdPr.number} β€” ${createdPr.title}`);\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.warn(` ⚠️ PR creation failed: ${msg}`);\n logger.info(` Create manually: ${portBranch} β†’ ${targetBranch}`);\n }\n}\n\n// ─── Register command ─────────────────────────────────────────────────────────\n\nexport function registerPortCommand(program: Command): void {\n program\n .command(\"port\")\n .description(\n \"πŸ’ Port commits from the current branch to one or more other branches\\n\" +\n \" Smart incremental: only ports NEW commits on re-runs\\n\" +\n \" Example: gitx port release/v2 hotfix/v1\"\n )\n .argument(\"[targets...]\", \"Target branch(es) to port commits onto\")\n .option(\"--base <branch>\", \"Base branch to calculate commits from (auto-detected if omitted)\")\n .option(\"--no-pr\", \"Push the port branch but skip PR creation\")\n .option(\"--draft\", \"Create PRs as drafts\")\n .option(\"--continue\", \"Continue after manually resolving cherry-pick conflicts\")\n .option(\"--abort\", \"Abort a paused port and clean up\")\n .action(async (\n targets: string[],\n opts: { base?: string; pr: boolean; draft: boolean; continue?: boolean; 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 gitx = await Gitx.fromCwd(cwd);\n\n // ── --abort ─────────────────────────────────────────────────────────────\n if (opts.abort) {\n const inProgress = await isCherryPickInProgress(cwd);\n if (inProgress) {\n await git([\"cherry-pick\", \"--abort\"], cwd);\n }\n const state = await loadPortState(cwd);\n if (state) {\n // Return to source branch\n await git([\"checkout\", state.sourceBranch], cwd);\n await clearPortState(cwd);\n logger.success(`βœ… Port aborted. Back on ${state.sourceBranch}.`);\n } else {\n logger.info(\"No port in progress to abort.\");\n }\n return;\n }\n\n // ── --continue ──────────────────────────────────────────────────────────\n if (opts.continue) {\n const state = await loadPortState(cwd);\n if (!state) {\n throw new GitxError(\n \"No port in progress. Run `gitx port <target>` to start one.\",\n { exitCode: 2 }\n );\n }\n\n // Make sure cherry-pick is no longer paused (user staged their fixes)\n const cherryInProgress = await isCherryPickInProgress(cwd);\n if (cherryInProgress) {\n // Complete the current cherry-pick\n const continueResult = await git(\n [\"cherry-pick\", \"--continue\", \"--no-edit\"],\n cwd\n );\n if (continueResult.exitCode !== 0) {\n const remaining = await getConflictingFiles(cwd);\n if (remaining.length > 0) {\n logger.warn(\"Still has conflicts β€” resolve them and stage before running --continue again.\");\n remaining.forEach((f) => logger.warn(` β€’ ${f}`));\n return;\n }\n }\n }\n\n // Resume remaining commits (skip the first β€” it was the one in conflict)\n const toResume = state.remainingCommits.slice(1);\n\n if (toResume.length > 0) {\n logger.info(`\\nβ–Ά Resuming port β€” ${toResume.length} commit(s) remaining…`);\n const pickResult = await cherryPickCommits(toResume, cwd, gitx);\n\n if (pickResult.status === \"paused\") {\n await savePortState(cwd, { ...state, remainingCommits: pickResult.remainingCommits });\n logger.warn(\"Port paused again β€” fix conflicts and run `gitx port --continue`.\");\n return;\n }\n }\n\n // All done β€” push and create PR\n await clearPortState(cwd);\n\n const pushSpinner = ora(`Pushing ${state.portBranch}…`).start();\n const pushResult = await git(\n [\"push\", \"--force-with-lease\", \"--set-upstream\", \"origin\", state.portBranch],\n cwd\n );\n if (pushResult.exitCode !== 0) {\n pushSpinner.fail(`Push failed: ${pushResult.stderr}`);\n return;\n }\n pushSpinner.succeed(`Pushed ${state.portBranch}`);\n\n if (!state.noPr) {\n let ctx;\n try {\n ctx = await gitx.getRepoContext();\n const provider = createProvider(ctx);\n const createdPr = await provider.createPR(ctx.repoSlug, {\n title: `[Port β†’ ${state.targetBranch}] ${state.sourceBranch}`,\n body: `Ported from \\`${state.sourceBranch}\\` β†’ \\`${state.targetBranch}\\` (manual conflict resolution).`,\n head: state.portBranch,\n base: state.targetBranch,\n draft: state.draft,\n });\n logger.success(`βœ… PR created: ${createdPr.url}`);\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.warn(`PR creation failed: ${msg} β€” create manually.`);\n }\n } else {\n logger.success(`βœ… Port complete. Branch: ${state.portBranch}`);\n }\n\n // Return to source branch\n await git([\"checkout\", state.sourceBranch], cwd);\n return;\n }\n\n // ── Normal port run ─────────────────────────────────────────────────────\n if (targets.length === 0) {\n throw new GitxError(\n \"Specify at least one target branch.\\n Example: gitx port release/v2 hotfix/v1\",\n { exitCode: 2 }\n );\n }\n\n const sourceBranch = await getCurrentBranch(cwd);\n if (!sourceBranch) {\n throw new GitxError(\"Could not determine current branch.\", { exitCode: 2 });\n }\n\n // Prevent porting to the same branch\n const invalidTargets = targets.filter((t) => t === sourceBranch);\n if (invalidTargets.length > 0) {\n throw new GitxError(\n `Cannot port a branch onto itself: ${invalidTargets.join(\", \")}`,\n { exitCode: 2 }\n );\n }\n\n const baseBranch = opts.base ?? (await detectBaseBranch(cwd));\n\n logger.info(`\\nπŸ’ gitx port`);\n logger.info(` Source: ${sourceBranch}`);\n logger.info(` Base: ${baseBranch}`);\n logger.info(` Targets: ${targets.join(\", \")}`);\n\n const originalBranch = sourceBranch;\n\n for (const targetBranch of targets) {\n await portToTarget({\n sourceBranch,\n targetBranch,\n baseBranch,\n cwd,\n gitx,\n noPr: opts.pr === false,\n draft: opts.draft,\n });\n\n // Return to source branch between targets\n const { stdout: currentBranch } = await git(\n [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"],\n cwd\n );\n if (currentBranch !== originalBranch) {\n await git([\"checkout\", originalBranch], cwd);\n }\n }\n\n logger.info(`\\n${\"─\".repeat(60)}`);\n logger.success(`\\nβœ… gitx port complete.`);\n });\n}\n"]}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * gitx pr close <number>
3
+ *
4
+ * Close (or abandon on Azure DevOps) a pull request.
5
+ *
6
+ * Note: no provider's public API supports hard-deleting a PR.
7
+ * GitHub/GitLab mark it "closed"; Azure DevOps marks it "abandoned".
8
+ *
9
+ * Usage:
10
+ * gitx pr close 42 # close PR #42 (prompts for confirmation)
11
+ * gitx pr close 42 --force # skip confirmation prompt
12
+ */
13
+ import type { Command } from "commander";
14
+ export declare function registerPrCloseCommand(pr: Command): void;
15
+ //# sourceMappingURL=close.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"close.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/pr/close.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQzC,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CA0DxD"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * gitx pr close <number>
3
+ *
4
+ * Close (or abandon on Azure DevOps) a pull request.
5
+ *
6
+ * Note: no provider's public API supports hard-deleting a PR.
7
+ * GitHub/GitLab mark it "closed"; Azure DevOps marks it "abandoned".
8
+ *
9
+ * Usage:
10
+ * gitx pr close 42 # close PR #42 (prompts for confirmation)
11
+ * gitx pr close 42 --force # skip confirmation prompt
12
+ */
13
+ import inquirer from "inquirer";
14
+ import ora from "ora";
15
+ import { logger } from "../../../logger/logger.js";
16
+ import { Gitx } from "../../../core/gitx.js";
17
+ import { createProvider } from "../../../providers/factory.js";
18
+ import { GitxError } from "../../../utils/errors.js";
19
+ export function registerPrCloseCommand(pr) {
20
+ pr.command("close <number>")
21
+ .description("🚫 Close (or abandon) a pull request")
22
+ .option("-f, --force", "Skip confirmation prompt")
23
+ .action(async (numberArg, opts) => {
24
+ const prNumber = parseInt(numberArg, 10);
25
+ if (isNaN(prNumber) || prNumber <= 0) {
26
+ throw new GitxError(`Invalid PR number: "${numberArg}"`, { exitCode: 2 });
27
+ }
28
+ const gitx = await Gitx.fromCwd();
29
+ const ctx = await gitx.getRepoContext();
30
+ const provider = createProvider(ctx);
31
+ // Fetch PR to show details before confirming
32
+ const fetchSpinner = ora(`Fetching PR #${prNumber}…`).start();
33
+ let pr_;
34
+ try {
35
+ pr_ = await provider.getPR(ctx.repoSlug, prNumber);
36
+ fetchSpinner.stop();
37
+ }
38
+ catch (err) {
39
+ fetchSpinner.fail();
40
+ throw err;
41
+ }
42
+ if (pr_.state !== "open") {
43
+ logger.warn(`PR #${prNumber} is already ${pr_.state} β€” nothing to do.`);
44
+ return;
45
+ }
46
+ // Show PR summary
47
+ logger.info(`\n #${pr_.number} ${pr_.title}`);
48
+ logger.info(` Branch: ${pr_.head} β†’ ${pr_.base}`);
49
+ logger.info(` Author: ${pr_.author} | ${pr_.url}\n`);
50
+ // Determine provider-specific label for UX messaging
51
+ const actionLabel = ctx.provider === "azure" ? "abandon" : "close";
52
+ if (!opts.force) {
53
+ const { confirmed } = await inquirer.prompt([
54
+ {
55
+ type: "confirm",
56
+ name: "confirmed",
57
+ message: `${actionLabel.charAt(0).toUpperCase() + actionLabel.slice(1)} PR #${prNumber}?`,
58
+ default: false,
59
+ },
60
+ ]);
61
+ if (!confirmed) {
62
+ logger.info("Aborted β€” PR left open.");
63
+ return;
64
+ }
65
+ }
66
+ const closeSpinner = ora(`Closing PR #${prNumber}…`).start();
67
+ await provider.closePR(ctx.repoSlug, prNumber);
68
+ closeSpinner.succeed(`PR #${prNumber} "${pr_.title}" has been ${actionLabel}d βœ“`);
69
+ });
70
+ }
71
+ //# sourceMappingURL=close.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"close.js","sourceRoot":"","sources":["../../../../src/cli/commands/pr/close.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * gitx pr close <number>\n *\n * Close (or abandon on Azure DevOps) a pull request.\n *\n * Note: no provider's public API supports hard-deleting a PR.\n * GitHub/GitLab mark it \"closed\"; Azure DevOps marks it \"abandoned\".\n *\n * Usage:\n * gitx pr close 42 # close PR #42 (prompts for confirmation)\n * gitx pr close 42 --force # skip confirmation prompt\n */\n\nimport type { Command } from \"commander\";\nimport inquirer from \"inquirer\";\nimport ora from \"ora\";\nimport { logger } from \"../../../logger/logger.js\";\nimport { Gitx } from \"../../../core/gitx.js\";\nimport { createProvider } from \"../../../providers/factory.js\";\nimport { GitxError } from \"../../../utils/errors.js\";\n\nexport function registerPrCloseCommand(pr: Command): void {\n pr.command(\"close <number>\")\n .description(\"🚫 Close (or abandon) a pull request\")\n .option(\"-f, --force\", \"Skip confirmation prompt\")\n .action(async (numberArg: string, opts: { force?: boolean }) => {\n const prNumber = parseInt(numberArg, 10);\n if (isNaN(prNumber) || prNumber <= 0) {\n throw new GitxError(`Invalid PR number: \"${numberArg}\"`, { exitCode: 2 });\n }\n\n const gitx = await Gitx.fromCwd();\n const ctx = await gitx.getRepoContext();\n const provider = createProvider(ctx);\n\n // Fetch PR to show details before confirming\n const fetchSpinner = ora(`Fetching PR #${prNumber}…`).start();\n let pr_: Awaited<ReturnType<typeof provider.getPR>>;\n try {\n pr_ = await provider.getPR(ctx.repoSlug, prNumber);\n fetchSpinner.stop();\n } catch (err) {\n fetchSpinner.fail();\n throw err;\n }\n\n if (pr_.state !== \"open\") {\n logger.warn(`PR #${prNumber} is already ${pr_.state} β€” nothing to do.`);\n return;\n }\n\n // Show PR summary\n logger.info(`\\n #${pr_.number} ${pr_.title}`);\n logger.info(` Branch: ${pr_.head} β†’ ${pr_.base}`);\n logger.info(` Author: ${pr_.author} | ${pr_.url}\\n`);\n\n // Determine provider-specific label for UX messaging\n const actionLabel = ctx.provider === \"azure\" ? \"abandon\" : \"close\";\n\n if (!opts.force) {\n const { confirmed } = await inquirer.prompt<{ confirmed: boolean }>([\n {\n type: \"confirm\",\n name: \"confirmed\",\n message: `${actionLabel.charAt(0).toUpperCase() + actionLabel.slice(1)} PR #${prNumber}?`,\n default: false,\n },\n ]);\n\n if (!confirmed) {\n logger.info(\"Aborted β€” PR left open.\");\n return;\n }\n }\n\n const closeSpinner = ora(`Closing PR #${prNumber}…`).start();\n await provider.closePR(ctx.repoSlug, prNumber);\n closeSpinner.succeed(`PR #${prNumber} \"${pr_.title}\" has been ${actionLabel}d βœ“`);\n });\n}\n"]}
@@ -1,3 +1,20 @@
1
+ /**
2
+ * gitx pr create
3
+ *
4
+ * Fully automated PR creation workflow:
5
+ * 1. If there are uncommitted changes β†’ AI commit message β†’ commit
6
+ * 2. Push branch to origin
7
+ * 3. If PR already exists β†’ print its URL and exit
8
+ * 4. Auto-detect base branch (upstream, remote HEAD, or closest ancestor)
9
+ * 5. AI-generate PR title and body from branch commits + diff
10
+ * 6. Show preview β†’ confirm β†’ create PR
11
+ *
12
+ * Usage:
13
+ * gitx pr create # full auto
14
+ * gitx pr create --base main # override base branch
15
+ * gitx pr create --draft # open as draft
16
+ * gitx pr create --dry-run # preview without creating
17
+ */
1
18
  import type { Command } from "commander";
2
19
  export declare function registerPrCreateCommand(pr: Command): void;
3
20
  //# sourceMappingURL=create.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/pr/create.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAQzD"}
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/pr/create.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwBzC,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAyNzD"}
@@ -1,12 +1,216 @@
1
+ /**
2
+ * gitx pr create
3
+ *
4
+ * Fully automated PR creation workflow:
5
+ * 1. If there are uncommitted changes β†’ AI commit message β†’ commit
6
+ * 2. Push branch to origin
7
+ * 3. If PR already exists β†’ print its URL and exit
8
+ * 4. Auto-detect base branch (upstream, remote HEAD, or closest ancestor)
9
+ * 5. AI-generate PR title and body from branch commits + diff
10
+ * 6. Show preview β†’ confirm β†’ create PR
11
+ *
12
+ * Usage:
13
+ * gitx pr create # full auto
14
+ * gitx pr create --base main # override base branch
15
+ * gitx pr create --draft # open as draft
16
+ * gitx pr create --dry-run # preview without creating
17
+ */
18
+ import inquirer from "inquirer";
19
+ import ora from "ora";
1
20
  import { logger } from "../../../logger/logger.js";
21
+ import { Gitx } from "../../../core/gitx.js";
22
+ import { createProvider } from "../../../providers/factory.js";
23
+ import { GitHubProvider } from "../../../providers/github.js";
24
+ import { getCurrentBranch, isWorkingTreeDirty, hasStagedChanges, stageAll, commitChanges, pushBranch, getWorkingDiff, getWorkingDiffStat, detectBaseBranch, getBranchCommits, getBranchDiff, getBranchStat, } from "../../../utils/gitOps.js";
25
+ import { withLockRetry } from "../../../utils/lockFile.js";
26
+ import { GitxError } from "../../../utils/errors.js";
2
27
  export function registerPrCreateCommand(pr) {
3
28
  pr.command("create")
4
- .description("πŸ†• Create a pull request")
5
- .option("--branches <branches>", "Comma-separated branches (e.g. dev,staging,prod)")
29
+ .description("πŸ†• Stage β†’ commit β†’ push β†’ open a pull request in one step")
30
+ .option("--base <base>", "Target / base branch (auto-detected if omitted)")
31
+ .option("--draft", "Open as draft PR", false)
32
+ .option("--dry-run", "Preview PR content without creating")
33
+ .option("-m, --message <msg>", "Override the AI commit message")
34
+ .option("--title <title>", "Override the AI-generated PR title")
35
+ .option("--body <body>", "Override the AI-generated PR body")
6
36
  .action(async (options) => {
7
- logger.warn("Not implemented yet (provider system next).");
8
- if (options.branches)
9
- logger.info(`Branches: ${options.branches}`);
37
+ const cwd = process.cwd();
38
+ const gitx = await Gitx.fromCwd(cwd);
39
+ const ctx = await gitx.getRepoContext();
40
+ const provider = createProvider(ctx);
41
+ // ── 1. Stage & AI-commit any uncommitted changes ───────────────────────
42
+ const dirty = await isWorkingTreeDirty(cwd);
43
+ const alreadyStaged = await hasStagedChanges(cwd);
44
+ if (dirty || alreadyStaged) {
45
+ logger.info("πŸ“‚ Uncommitted changes detected β€” committing first.\n");
46
+ if (dirty) {
47
+ const stageSpinner = ora("Staging all changes…").start();
48
+ await withLockRetry(() => stageAll(cwd), cwd);
49
+ stageSpinner.succeed("All changes staged.");
50
+ }
51
+ // Get diff for AI commit message
52
+ const [stat, workingDiff] = await Promise.all([
53
+ getWorkingDiffStat(cwd),
54
+ getWorkingDiff(cwd),
55
+ ]);
56
+ let commitMsg;
57
+ if (options.message) {
58
+ commitMsg = options.message;
59
+ logger.info(`πŸ“ Using provided commit message: ${commitMsg}`);
60
+ }
61
+ else {
62
+ const aiCommitSpinner = ora("πŸ€– Generating commit message…").start();
63
+ try {
64
+ const aiInput = stat
65
+ ? `=== Changed files (complete list) ===\n${stat}\n\n=== Detailed diff ===\n${workingDiff}`
66
+ : workingDiff;
67
+ const result = await gitx.ai.generateCommitMessage(aiInput);
68
+ commitMsg = result.body
69
+ ? `${result.subject}\n\n${result.body}`
70
+ : result.subject;
71
+ aiCommitSpinner.succeed(`Commit: ${result.subject}`);
72
+ }
73
+ catch (err) {
74
+ aiCommitSpinner.fail("AI commit message generation failed.");
75
+ logger.warn(` ${err instanceof Error ? err.message : String(err)}`);
76
+ const { manualMsg } = await inquirer.prompt([
77
+ {
78
+ type: "input",
79
+ name: "manualMsg",
80
+ message: "Commit message:",
81
+ validate: (v) => v.trim().length > 0 || "Cannot be empty",
82
+ },
83
+ ]);
84
+ commitMsg = manualMsg.trim();
85
+ }
86
+ }
87
+ const commitSpinner = ora("Committing…").start();
88
+ await withLockRetry(() => commitChanges(commitMsg, cwd), cwd);
89
+ commitSpinner.succeed("Committed βœ“");
90
+ }
91
+ else {
92
+ logger.info("✨ Working tree is clean β€” skipping commit step.");
93
+ }
94
+ // ── 2. Determine current branch ────────────────────────────────────────
95
+ const head = await getCurrentBranch(cwd);
96
+ // ── 3. Detect / resolve base branch ───────────────────────────────────
97
+ let base;
98
+ if (options.base) {
99
+ base = options.base;
100
+ logger.info(`πŸ“Œ Base branch (provided): ${base}`);
101
+ }
102
+ else {
103
+ const detectSpinner = ora("Detecting base branch…").start();
104
+ base = await detectBaseBranch(cwd);
105
+ detectSpinner.succeed(`Base branch: ${base}`);
106
+ }
107
+ if (head === base) {
108
+ throw new GitxError(`You are on "${head}" which is also the base branch.\n` +
109
+ ` Create a feature branch first: git checkout -b my-feature`, { exitCode: 1 });
110
+ }
111
+ logger.info(`\nπŸ”€ ${ctx.repoSlug} Β· ${head} β†’ ${base}\n`);
112
+ // ── 4. Push branch ─────────────────────────────────────────────────────
113
+ const pushSpinner = ora(`Pushing ${head} to origin…`).start();
114
+ await pushBranch(head, cwd);
115
+ pushSpinner.succeed("Pushed βœ“");
116
+ // ── 5. Check for existing open PR ──────────────────────────────────────
117
+ if (provider instanceof GitHubProvider) {
118
+ const existing = await provider.findExistingPR(ctx.repoSlug, head, base);
119
+ if (existing) {
120
+ logger.warn(`\n⚠️ A PR already exists for ${head} β†’ ${base}:`);
121
+ logger.info(` #${existing.number} β€” ${existing.title}`);
122
+ logger.success(` ${existing.url}`);
123
+ return;
124
+ }
125
+ }
126
+ else {
127
+ // GitLab / Azure: scan open PR list for matching head branch
128
+ try {
129
+ const openPrs = await provider.listPRs(ctx.repoSlug);
130
+ const existing = openPrs.find((p) => p.head === head && p.base === base && p.state === "open");
131
+ if (existing) {
132
+ logger.warn(`\n⚠️ A PR already exists for ${head} β†’ ${base}:`);
133
+ logger.info(` #${existing.number} β€” ${existing.title}`);
134
+ logger.success(` ${existing.url}`);
135
+ return;
136
+ }
137
+ }
138
+ catch {
139
+ // Non-fatal β€” proceed to create
140
+ }
141
+ }
142
+ // ── 6. AI-generate PR title & body ─────────────────────────────────────
143
+ let prTitle = options.title ?? "";
144
+ let prBody = options.body ?? "";
145
+ if (!prTitle || !prBody) {
146
+ const prSpinner = ora("πŸ€– Generating PR title and description…").start();
147
+ try {
148
+ const [commits, branchDiff, branchStat] = await Promise.all([
149
+ getBranchCommits(cwd, base),
150
+ getBranchDiff(cwd, base),
151
+ getBranchStat(cwd, base),
152
+ ]);
153
+ const aiResult = await gitx.ai.generatePrContent(commits, branchDiff, branchStat || undefined);
154
+ if (!prTitle)
155
+ prTitle = aiResult.title;
156
+ if (!prBody)
157
+ prBody = aiResult.body;
158
+ prSpinner.succeed("PR content generated.");
159
+ }
160
+ catch (err) {
161
+ prSpinner.fail("AI PR generation failed β€” falling back to manual entry.");
162
+ logger.warn(` ${err instanceof Error ? err.message : String(err)}`);
163
+ }
164
+ }
165
+ // Fallback: prompt for any still-missing values
166
+ if (!prTitle) {
167
+ const ans = await inquirer.prompt([
168
+ {
169
+ type: "input",
170
+ name: "title",
171
+ message: "PR title:",
172
+ validate: (v) => v.trim().length > 0 || "Title cannot be empty",
173
+ },
174
+ ]);
175
+ prTitle = ans.title.trim();
176
+ }
177
+ // ── 7. Preview & confirm ───────────────────────────────────────────────
178
+ logger.info("\nπŸ“‹ Pull Request preview:\n");
179
+ logger.info("─".repeat(60));
180
+ logger.info(` Title: ${prTitle}`);
181
+ logger.info(` Branch: ${head} β†’ ${base}`);
182
+ if (prBody) {
183
+ logger.info(`\n${prBody}`);
184
+ }
185
+ logger.info("─".repeat(60));
186
+ if (options.dryRun) {
187
+ logger.info("\nπŸ” Dry run β€” PR not created.");
188
+ return;
189
+ }
190
+ const { confirmed } = await inquirer.prompt([
191
+ {
192
+ type: "confirm",
193
+ name: "confirmed",
194
+ message: `Create${options.draft ? " draft" : ""} PR?`,
195
+ default: true,
196
+ },
197
+ ]);
198
+ if (!confirmed) {
199
+ logger.info("Aborted β€” PR not created.");
200
+ return;
201
+ }
202
+ // ── 8. Create PR ───────────────────────────────────────────────────────
203
+ const createSpinner = ora("Creating pull request…").start();
204
+ const createdPr = await provider.createPR(ctx.repoSlug, {
205
+ title: prTitle,
206
+ body: prBody,
207
+ head,
208
+ base,
209
+ draft: options.draft,
210
+ });
211
+ createSpinner.stop();
212
+ logger.success(`\nβœ… PR created: ${createdPr.url}`);
213
+ logger.info(` #${createdPr.number} β€” ${createdPr.title}`);
10
214
  });
11
215
  }
12
216
  //# sourceMappingURL=create.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"create.js","sourceRoot":"","sources":["../../../../src/cli/commands/pr/create.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAEnD,MAAM,UAAU,uBAAuB,CAAC,EAAW;IACjD,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,0BAA0B,CAAC;SACvC,MAAM,CAAC,uBAAuB,EAAE,kDAAkD,CAAC;SACnF,MAAM,CAAC,KAAK,EAAE,OAA8B,EAAE,EAAE;QAC/C,MAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;QAC3D,IAAI,OAAO,CAAC,QAAQ;YAAE,MAAM,CAAC,IAAI,CAAC,aAAa,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;AACP,CAAC","sourcesContent":["import type { Command } from \"commander\";\nimport { logger } from \"../../../logger/logger.js\";\n\nexport function registerPrCreateCommand(pr: Command): void {\n pr.command(\"create\")\n .description(\"πŸ†• Create a pull request\")\n .option(\"--branches <branches>\", \"Comma-separated branches (e.g. dev,staging,prod)\")\n .action(async (options: { branches?: string }) => {\n logger.warn(\"Not implemented yet (provider system next).\");\n if (options.branches) logger.info(`Branches: ${options.branches}`);\n });\n}\n\n"]}
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../../../../src/cli/commands/pr/create.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * gitx pr create\n *\n * Fully automated PR creation workflow:\n * 1. If there are uncommitted changes β†’ AI commit message β†’ commit\n * 2. Push branch to origin\n * 3. If PR already exists β†’ print its URL and exit\n * 4. Auto-detect base branch (upstream, remote HEAD, or closest ancestor)\n * 5. AI-generate PR title and body from branch commits + diff\n * 6. Show preview β†’ confirm β†’ create PR\n *\n * Usage:\n * gitx pr create # full auto\n * gitx pr create --base main # override base branch\n * gitx pr create --draft # open as draft\n * gitx pr create --dry-run # preview without creating\n */\n\nimport type { Command } from \"commander\";\nimport inquirer from \"inquirer\";\nimport ora from \"ora\";\nimport { logger } from \"../../../logger/logger.js\";\nimport { Gitx } from \"../../../core/gitx.js\";\nimport { createProvider } from \"../../../providers/factory.js\";\nimport { GitHubProvider } from \"../../../providers/github.js\";\nimport {\n getCurrentBranch,\n isWorkingTreeDirty,\n hasStagedChanges,\n stageAll,\n commitChanges,\n pushBranch,\n getWorkingDiff,\n getWorkingDiffStat,\n detectBaseBranch,\n getBranchCommits,\n getBranchDiff,\n getBranchStat,\n} from \"../../../utils/gitOps.js\";\nimport { withLockRetry } from \"../../../utils/lockFile.js\";\nimport { GitxError } from \"../../../utils/errors.js\";\n\nexport function registerPrCreateCommand(pr: Command): void {\n pr.command(\"create\")\n .description(\"πŸ†• Stage β†’ commit β†’ push β†’ open a pull request in one step\")\n .option(\"--base <base>\", \"Target / base branch (auto-detected if omitted)\")\n .option(\"--draft\", \"Open as draft PR\", false)\n .option(\"--dry-run\", \"Preview PR content without creating\")\n .option(\"-m, --message <msg>\", \"Override the AI commit message\")\n .option(\"--title <title>\", \"Override the AI-generated PR title\")\n .option(\"--body <body>\", \"Override the AI-generated PR body\")\n .action(\n async (options: {\n base?: string;\n draft: boolean;\n dryRun?: boolean;\n message?: string;\n title?: string;\n body?: string;\n }) => {\n const cwd = process.cwd();\n const gitx = await Gitx.fromCwd(cwd);\n const ctx = await gitx.getRepoContext();\n const provider = createProvider(ctx);\n\n // ── 1. Stage & AI-commit any uncommitted changes ───────────────────────\n const dirty = await isWorkingTreeDirty(cwd);\n const alreadyStaged = await hasStagedChanges(cwd);\n\n if (dirty || alreadyStaged) {\n logger.info(\"πŸ“‚ Uncommitted changes detected β€” committing first.\\n\");\n\n if (dirty) {\n const stageSpinner = ora(\"Staging all changes…\").start();\n await withLockRetry(() => stageAll(cwd), cwd);\n stageSpinner.succeed(\"All changes staged.\");\n }\n\n // Get diff for AI commit message\n const [stat, workingDiff] = await Promise.all([\n getWorkingDiffStat(cwd),\n getWorkingDiff(cwd),\n ]);\n\n let commitMsg: string;\n\n if (options.message) {\n commitMsg = options.message;\n logger.info(`πŸ“ Using provided commit message: ${commitMsg}`);\n } else {\n const aiCommitSpinner = ora(\"πŸ€– Generating commit message…\").start();\n try {\n const aiInput = stat\n ? `=== Changed files (complete list) ===\\n${stat}\\n\\n=== Detailed diff ===\\n${workingDiff}`\n : workingDiff;\n const result = await gitx.ai.generateCommitMessage(aiInput);\n commitMsg = result.body\n ? `${result.subject}\\n\\n${result.body}`\n : result.subject;\n aiCommitSpinner.succeed(`Commit: ${result.subject}`);\n } catch (err) {\n aiCommitSpinner.fail(\"AI commit message generation failed.\");\n logger.warn(` ${err instanceof Error ? err.message : String(err)}`);\n\n const { manualMsg } = await inquirer.prompt<{ manualMsg: string }>([\n {\n type: \"input\",\n name: \"manualMsg\",\n message: \"Commit message:\",\n validate: (v: string) => v.trim().length > 0 || \"Cannot be empty\",\n },\n ]);\n commitMsg = manualMsg.trim();\n }\n }\n\n const commitSpinner = ora(\"Committing…\").start();\n await withLockRetry(() => commitChanges(commitMsg, cwd), cwd);\n commitSpinner.succeed(\"Committed βœ“\");\n } else {\n logger.info(\"✨ Working tree is clean β€” skipping commit step.\");\n }\n\n // ── 2. Determine current branch ────────────────────────────────────────\n const head = await getCurrentBranch(cwd);\n\n // ── 3. Detect / resolve base branch ───────────────────────────────────\n let base: string;\n if (options.base) {\n base = options.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 throw new GitxError(\n `You are on \"${head}\" which is also the base branch.\\n` +\n ` Create a feature branch first: git checkout -b my-feature`,\n { exitCode: 1 }\n );\n }\n\n logger.info(`\\nπŸ”€ ${ctx.repoSlug} Β· ${head} β†’ ${base}\\n`);\n\n // ── 4. Push branch ─────────────────────────────────────────────────────\n const pushSpinner = ora(`Pushing ${head} to origin…`).start();\n await pushBranch(head, cwd);\n pushSpinner.succeed(\"Pushed βœ“\");\n\n // ── 5. Check for existing open PR ──────────────────────────────────────\n if (provider instanceof GitHubProvider) {\n const existing = await provider.findExistingPR(ctx.repoSlug, head, base);\n if (existing) {\n logger.warn(`\\n⚠️ A PR already exists for ${head} β†’ ${base}:`);\n logger.info(` #${existing.number} β€” ${existing.title}`);\n logger.success(` ${existing.url}`);\n return;\n }\n } else {\n // GitLab / Azure: scan open PR list for matching head branch\n try {\n const openPrs = await provider.listPRs(ctx.repoSlug);\n const existing = openPrs.find(\n (p) => p.head === head && p.base === base && p.state === \"open\"\n );\n if (existing) {\n logger.warn(`\\n⚠️ A PR already exists for ${head} β†’ ${base}:`);\n logger.info(` #${existing.number} β€” ${existing.title}`);\n logger.success(` ${existing.url}`);\n return;\n }\n } catch {\n // Non-fatal β€” proceed to create\n }\n }\n\n // ── 6. AI-generate PR title & body ─────────────────────────────────────\n let prTitle = options.title ?? \"\";\n let prBody = options.body ?? \"\";\n\n if (!prTitle || !prBody) {\n const prSpinner = ora(\"πŸ€– Generating PR title and description…\").start();\n try {\n const [commits, branchDiff, branchStat] = await Promise.all([\n getBranchCommits(cwd, base),\n getBranchDiff(cwd, base),\n getBranchStat(cwd, base),\n ]);\n\n const aiResult = await gitx.ai.generatePrContent(commits, branchDiff, branchStat || undefined);\n if (!prTitle) prTitle = aiResult.title;\n if (!prBody) prBody = aiResult.body;\n prSpinner.succeed(\"PR content generated.\");\n } catch (err) {\n prSpinner.fail(\"AI PR generation failed β€” falling back to manual entry.\");\n logger.warn(` ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n // Fallback: prompt for any still-missing values\n if (!prTitle) {\n const ans = await inquirer.prompt<{ title: string }>([\n {\n type: \"input\",\n name: \"title\",\n message: \"PR title:\",\n validate: (v: string) => v.trim().length > 0 || \"Title cannot be empty\",\n },\n ]);\n prTitle = ans.title.trim();\n }\n\n // ── 7. Preview & confirm ───────────────────────────────────────────────\n logger.info(\"\\nπŸ“‹ Pull Request preview:\\n\");\n logger.info(\"─\".repeat(60));\n logger.info(` Title: ${prTitle}`);\n logger.info(` Branch: ${head} β†’ ${base}`);\n if (prBody) {\n logger.info(`\\n${prBody}`);\n }\n logger.info(\"─\".repeat(60));\n\n if (options.dryRun) {\n logger.info(\"\\nπŸ” Dry run β€” PR not created.\");\n return;\n }\n\n const { confirmed } = await inquirer.prompt<{ confirmed: boolean }>([\n {\n type: \"confirm\",\n name: \"confirmed\",\n message: `Create${options.draft ? \" draft\" : \"\"} PR?`,\n default: true,\n },\n ]);\n\n if (!confirmed) {\n logger.info(\"Aborted β€” PR not created.\");\n return;\n }\n\n // ── 8. Create PR ───────────────────────────────────────────────────────\n const createSpinner = ora(\"Creating pull request…\").start();\n const createdPr = await provider.createPR(ctx.repoSlug, {\n title: prTitle,\n body: prBody,\n head,\n base,\n draft: options.draft,\n });\n createSpinner.stop();\n\n logger.success(`\\nβœ… PR created: ${createdPr.url}`);\n logger.info(` #${createdPr.number} β€” ${createdPr.title}`);\n }\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"fixComments.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/pr/fixComments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAQ9D"}
1
+ {"version":3,"file":"fixComments.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/pr/fixComments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAsF9D"}
@@ -1,11 +1,83 @@
1
+ import inquirer from "inquirer";
1
2
  import { logger } from "../../../logger/logger.js";
3
+ import { Gitx } from "../../../core/gitx.js";
4
+ import { runFixCommentsWorkflow } from "../../../workflows/pr.js";
5
+ import { pushBranch, getCurrentBranch, isWorkingTreeDirty } from "../../../utils/gitOps.js";
2
6
  export function registerPrFixCommentsCommand(pr) {
3
7
  pr.command("fix-comments")
4
- .description("🩹 Attempt to fix PR review comments")
5
- .argument("<id>", "Pull request id/number")
6
- .action(async (id) => {
7
- logger.warn("Not implemented yet (AI + provider wiring next).");
8
- logger.info(`PR: ${id}`);
8
+ .description("🩹 AI-fix review comments and push changes")
9
+ .argument("<id>", "Pull request number")
10
+ .option("--dry-run", "Preview fixes without applying or committing", false)
11
+ .option("--no-push", "Apply & commit locally but skip push", false)
12
+ .action(async (id, options) => {
13
+ const prNumber = parseInt(id, 10);
14
+ if (isNaN(prNumber) || prNumber <= 0) {
15
+ logger.error(`Invalid PR number: ${id}`);
16
+ process.exit(1);
17
+ }
18
+ const gitx = await Gitx.fromCwd();
19
+ const ctx = await gitx.getRepoContext();
20
+ logger.info(`🩹 Fixing review comments on PR #${prNumber} (${ctx.repoSlug})…\n`);
21
+ // ── AI availability warning ────────────────────────────────────────────
22
+ if (!await Gitx.isAiAvailable(gitx.config)) {
23
+ logger.warn("⚠️ No AI provider configured β€” AI fix suggestions will be empty.\n" +
24
+ " Run `gitx config` to set up an AI provider (Claude, OpenAI, or claude-cli).");
25
+ return;
26
+ }
27
+ if (!options.dryRun) {
28
+ const { proceed } = await inquirer.prompt([
29
+ {
30
+ type: "confirm",
31
+ name: "proceed",
32
+ message: "This will apply AI-suggested fixes, commit, and push. Continue?",
33
+ default: false,
34
+ },
35
+ ]);
36
+ if (!proceed) {
37
+ logger.warn("Cancelled.");
38
+ return;
39
+ }
40
+ }
41
+ // ── Guard: warn about uncommitted changes ────────────────────────────
42
+ if (!options.dryRun) {
43
+ const dirty = await isWorkingTreeDirty(gitx.cwd);
44
+ if (dirty) {
45
+ logger.warn("⚠️ You have uncommitted changes. They may conflict with applied fixes.");
46
+ const { cont } = await inquirer.prompt([
47
+ { type: "confirm", name: "cont", message: "Continue anyway?", default: false },
48
+ ]);
49
+ if (!cont) {
50
+ logger.warn("Cancelled.");
51
+ return;
52
+ }
53
+ }
54
+ }
55
+ const result = await runFixCommentsWorkflow(gitx, prNumber, options.dryRun);
56
+ logger.info(`\nπŸ“‹ PR: ${result.pr.title}`);
57
+ if (result.appliedFixes.length === 0 && result.skippedFixes.length === 0) {
58
+ logger.info("No actionable review comments found.");
59
+ return;
60
+ }
61
+ if (result.appliedFixes.length > 0) {
62
+ logger.success(`\nβœ… Applied ${result.appliedFixes.length} fix(es):`);
63
+ result.appliedFixes.forEach((f) => logger.info(` β€’ ${f.path} β€” ${f.rationale}`));
64
+ }
65
+ if (result.skippedFixes.length > 0) {
66
+ logger.warn(`\n⚠️ Skipped ${result.skippedFixes.length} fix(es):`);
67
+ result.skippedFixes.forEach((f) => logger.warn(` β€’ ${f.path}: ${f.reason}`));
68
+ }
69
+ // Push if not dry-run and push not disabled
70
+ if (!options.dryRun && options.push !== false && result.appliedFixes.length > 0) {
71
+ const branch = await getCurrentBranch(gitx.cwd);
72
+ logger.info(`\nπŸš€ Pushing ${branch}…`);
73
+ try {
74
+ await pushBranch(branch, gitx.cwd);
75
+ logger.success("Branch pushed.");
76
+ }
77
+ catch (err) {
78
+ logger.warn(`Push failed: ${String(err.message ?? err)}`);
79
+ }
80
+ }
9
81
  });
10
82
  }
11
83
  //# sourceMappingURL=fixComments.js.map