(files: string[], message: string)
| 69 | * - rev-parse 失败时仍返回 ok,但 commit 字段填 "?" + warning。 |
| 70 | */ |
| 71 | export async function gitAddAndCommit(files: string[], message: string): Promise<CommitResult> { |
| 72 | if (files.length === 0) return { ok: false, error: "没有要提交的文件" }; |
| 73 | |
| 74 | const safeMsg = sanitizeCommitMessage(message); |
| 75 | if (!safeMsg) return { ok: false, error: "commit message 为空" }; |
| 76 | |
| 77 | const addResult = await runGit(["add", "--", ...files]); |
| 78 | if (!addResult.ok) return { ok: false, error: `git add 失败: ${addResult.stderr}` }; |
| 79 | |
| 80 | // 用 git diff --cached -- ...files 限定到本批文件,避免别处 staged 改动干扰判断 |
| 81 | const diffResult = await runGit(["diff", "--cached", "--quiet", "--", ...files]); |
| 82 | if (diffResult.ok) { |
| 83 | // exit 0 表示这批文件无变更 |
| 84 | return { ok: true, noop: true, message: "无实际变更,跳过 commit" }; |
| 85 | } |
| 86 | |
| 87 | // -- ...files 限定本次 commit 仅这些文件,不带走预先 staged 的别的内容 |
| 88 | const commitResult = await runGit(["commit", "-m", safeMsg, "--", ...files]); |
| 89 | if (!commitResult.ok) { |
| 90 | return { ok: false, error: `git commit 失败: ${commitResult.stderr}` }; |
| 91 | } |
| 92 | |
| 93 | // 取最新 commit hash;rev-parse 失败时降级为 "?" + warning,仍视为 ok |
| 94 | const revResult = await runGit(["rev-parse", "HEAD"]); |
| 95 | const commit = revResult.ok ? revResult.stdout.trim().slice(0, 7) : "?"; |
| 96 | const out: CommitResult = { |
| 97 | ok: true, |
| 98 | commit, |
| 99 | message: safeMsg, |
| 100 | }; |
| 101 | if (!revResult.ok) { |
| 102 | out.warning = `rev-parse HEAD 失败: ${revResult.stderr.trim() || "unknown"}`; |
| 103 | } |
| 104 | return out; |
| 105 | } |
no test coverage detected