From 4018e0076486112d6015f044d3363d40eded257d Mon Sep 17 00:00:00 2001 From: Julian Scheid Date: Mon, 23 May 2022 01:31:56 +1200 Subject: [PATCH] fix(cli): use core.commentChar from git config with --edit flag (#3190) When parsing `.git/COMMIT_EDITMSG` use the `core.commentChar` git setting if present, falling back to the default comment char `#` otherwise. Use the `parserOpts.commentChar` setting only when parsing other messages (e.g. from stdin.) --- .../comment-char/commitlint.config.js | 2 +- @commitlint/cli/package.json | 2 +- @commitlint/cli/src/cli.test.ts | 45 +++++++++++++++++-- @commitlint/cli/src/cli.ts | 18 +++++--- @packages/test/src/git.ts | 1 + 5 files changed, 57 insertions(+), 11 deletions(-) diff --git a/@commitlint/cli/fixtures/comment-char/commitlint.config.js b/@commitlint/cli/fixtures/comment-char/commitlint.config.js index 2292580640..98ea1686e0 100644 --- a/@commitlint/cli/fixtures/comment-char/commitlint.config.js +++ b/@commitlint/cli/fixtures/comment-char/commitlint.config.js @@ -1,6 +1,6 @@ module.exports = { rules: { - 'subject-empty': [2, 'never'] + 'body-empty': [2, 'never'] }, parserPreset: { parserOpts: { diff --git a/@commitlint/cli/package.json b/@commitlint/cli/package.json index a7d95c50b6..ddc77537bc 100644 --- a/@commitlint/cli/package.json +++ b/@commitlint/cli/package.json @@ -41,7 +41,6 @@ "@commitlint/utils": "^17.0.0", "@types/node": "12.20.52", "@types/yargs": "^17.0.0", - "execa": "^5.0.0", "fs-extra": "^10.0.0" }, "dependencies": { @@ -50,6 +49,7 @@ "@commitlint/load": "^17.0.0", "@commitlint/read": "^17.0.0", "@commitlint/types": "^17.0.0", + "execa": "^5.0.0", "lodash": "^4.17.19", "resolve-from": "5.0.0", "resolve-global": "1.0.0", diff --git a/@commitlint/cli/src/cli.test.ts b/@commitlint/cli/src/cli.test.ts index 324c55e409..8ce9838fcb 100644 --- a/@commitlint/cli/src/cli.test.ts +++ b/@commitlint/cli/src/cli.test.ts @@ -329,13 +329,50 @@ test('should handle --amend with signoff', async () => { expect(commit).toBeTruthy(); }, 10000); -test('should fail with an empty message and a commentChar is set', async () => { +test('it uses parserOpts.commentChar when not using edit mode', async () => { const cwd = await gitBootstrap('fixtures/comment-char'); - await execa('git', ['config', '--local', 'core.commentChar', '$'], {cwd}); - await fs.writeFile(path.join(cwd, '.git', 'COMMIT_EDITMSG'), '#1234'); + const input = 'header: foo\n$body\n'; + + const actual = await cli([], {cwd})(input); + expect(actual.stdout).toContain('[body-empty]'); + expect(actual.exitCode).toBe(1); +}); + +test("it doesn't use parserOpts.commentChar when using edit mode", async () => { + const cwd = await gitBootstrap('fixtures/comment-char'); + await fs.writeFile( + path.join(cwd, '.git', 'COMMIT_EDITMSG'), + 'header: foo\n\n$body\n' + ); + + const actual = await cli(['--edit', '.git/COMMIT_EDITMSG'], {cwd})(); + expect(actual.stdout).not.toContain('[body-empty]'); + expect(actual.exitCode).toBe(0); +}); + +test('it uses core.commentChar git config when using edit mode', async () => { + const cwd = await gitBootstrap('fixtures/comment-char'); + await execa('git', ['config', 'core.commentChar', '$'], {cwd}); + await fs.writeFile( + path.join(cwd, '.git', 'COMMIT_EDITMSG'), + 'header: foo\n\n$body\n' + ); + + const actual = await cli(['--edit', '.git/COMMIT_EDITMSG'], {cwd})(); + expect(actual.stdout).toContain('[body-empty]'); + expect(actual.exitCode).toBe(1); +}); + +test('it falls back to # for core.commentChar when using edit mode', async () => { + const cwd = await gitBootstrap('fixtures/comment-char'); + await execa('git', ['config', 'core.commentChar', ''], {cwd}); + await fs.writeFile( + path.join(cwd, '.git', 'COMMIT_EDITMSG'), + 'header: foo\n\n#body\n' + ); const actual = await cli(['--edit', '.git/COMMIT_EDITMSG'], {cwd})(); - expect(actual.stdout).toContain('[subject-empty]'); + expect(actual.stdout).toContain('[body-empty]'); expect(actual.exitCode).toBe(1); }); diff --git a/@commitlint/cli/src/cli.ts b/@commitlint/cli/src/cli.ts index e95d31536a..4f232f8048 100644 --- a/@commitlint/cli/src/cli.ts +++ b/@commitlint/cli/src/cli.ts @@ -1,3 +1,4 @@ +import execa from 'execa'; import load from '@commitlint/load'; import lint from '@commitlint/lint'; import read from '@commitlint/read'; @@ -21,6 +22,8 @@ import {CliError} from './cli-error'; const pkg = require('../package'); +const gitDefaultCommentChar = '#'; + const cli = yargs .options({ color: { @@ -221,11 +224,16 @@ async function main(args: MainArgs) { } const format = loadFormatter(loaded, flags); - // Strip comments if reading from `.git/COMMIT_EDIT_MSG` using the - // commentChar from the parser preset falling back to a `#` if that is not - // set - if (flags.edit && typeof opts.parserOpts.commentChar !== 'string') { - opts.parserOpts.commentChar = '#'; + // If reading from `.git/COMMIT_EDIT_MSG`, strip comments using + // core.commentChar from git configuration, falling back to '#'. + if (flags.edit) { + try { + const {stdout} = await execa('git', ['config', 'core.commentChar']); + opts.parserOpts.commentChar = stdout.trim() || gitDefaultCommentChar; + } catch (e) { + console.warn('Could not determine core.commentChar git configuration', e); + opts.parserOpts.commentChar = gitDefaultCommentChar; + } } const results = await Promise.all( diff --git a/@packages/test/src/git.ts b/@packages/test/src/git.ts index e0ba9f7dbd..d0acb9d86f 100644 --- a/@packages/test/src/git.ts +++ b/@packages/test/src/git.ts @@ -35,6 +35,7 @@ async function setup(cwd: string, gitCommand = 'git') { cwd, }); await execa(gitCommand, ['config', 'commit.gpgsign', 'false'], {cwd}); + await execa(gitCommand, ['config', 'core.commentChar', '#'], {cwd}); } catch (err: any) { if (typeof err === 'object' && typeof err.message === 'object') { console.warn(`git config in ${cwd} failed`, err.message);