( settings: GetCommitMessageOptions, )
| 17 | |
| 18 | // Get commit messages |
| 19 | export default async function getCommitMessages( |
| 20 | settings: GetCommitMessageOptions, |
| 21 | ): Promise<string[]> { |
| 22 | const { cwd, fromLastTag, to, last, edit, gitLogArgs } = settings; |
| 23 | let from = settings.from; |
| 24 | |
| 25 | if (edit) { |
| 26 | return getEditCommit(cwd, edit); |
| 27 | } |
| 28 | |
| 29 | if (last) { |
| 30 | const gitCommandResult = await x("git", ["log", "-1", "--pretty=format:%B"], { |
| 31 | nodeOptions: { cwd }, |
| 32 | }); |
| 33 | let output = gitCommandResult.stdout.trim(); |
| 34 | // strip output of extra quotation marks ("") |
| 35 | if (output[0] == '"' && output[output.length - 1] == '"') output = output.slice(1, -1); |
| 36 | return [output]; |
| 37 | } |
| 38 | |
| 39 | if (!from && fromLastTag) { |
| 40 | const output = await x( |
| 41 | "git", |
| 42 | ["describe", "--abbrev=40", "--always", "--first-parent", "--long", "--tags"], |
| 43 | { nodeOptions: { cwd } }, |
| 44 | ); |
| 45 | const stdout = output.stdout.trim(); |
| 46 | |
| 47 | if (stdout.length === 40) { |
| 48 | // Hash only means no last tag. Use that as the from ref which |
| 49 | // results in a no-op. |
| 50 | from = stdout; |
| 51 | } else { |
| 52 | // Description will be in the format: <tag>-<count>-g<hash> |
| 53 | // Example: v3.2.0-11-g9057371a52adaae5180d93fe4d0bb808d874b9fb |
| 54 | // Minus zero based (1), dash (1), "g" prefix (1), hash (40) = -43 |
| 55 | const tagSlice = stdout.lastIndexOf("-", stdout.length - 43); |
| 56 | |
| 57 | from = stdout.slice(0, tagSlice); |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | // Verify the two refs share a merge-base before handing off the range |
| 62 | // walk to the git client. In a shallow clone the common ancestor may |
| 63 | // be missing, in which case `git log from..to` silently returns only |
| 64 | // the commits that happen to be present, hiding invalid commits in the |
| 65 | // unfetched portion of history. |
| 66 | if (from) { |
| 67 | // `to` is left undefined here when no --to was given; the git client |
| 68 | // defaults it to HEAD, so we mirror that for the merge-base check. |
| 69 | const effectiveTo = to ?? "HEAD"; |
| 70 | const mergeBase = await x("git", ["merge-base", from, effectiveTo], { |
| 71 | nodeOptions: { cwd }, |
| 72 | }); |
| 73 | if (mergeBase.exitCode === 1) { |
| 74 | throw new Error( |
| 75 | `Cannot find merge-base between '${from}' and '${effectiveTo}'. ` + |
| 76 | `This typically indicates incomplete git history (e.g., a shallow clone). ` + |
nothing calls this directly
no test coverage detected