Skip to content

Commit e5fee05

Browse files
authored
fix(cli): use core.commentChar from git config with --edit flag (#3191)
* 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.) * fix(cli): tweaks for core.commentChar handling (#3190) - Remove useless change to test git repository setup - Add comment on git config error handling * fix(cli): make tests independent of global git config (#3190) - Don't apply global changes - Set $HOME to ensure default global settings aren't picked up * ci: try fixing HOME setting on Windows * test: use cross-env for setting $HOME
1 parent afbb11f commit e5fee05

File tree

6 files changed

+75
-14
lines changed

6 files changed

+75
-14
lines changed

@commitlint/cli/fixtures/comment-char/commitlint.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module.exports = {
22
rules: {
3-
'subject-empty': [2, 'never']
3+
'body-empty': [2, 'never']
44
},
55
parserPreset: {
66
parserOpts: {

@commitlint/cli/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
"@commitlint/utils": "^17.0.0",
4242
"@types/node": "12.20.52",
4343
"@types/yargs": "^17.0.0",
44-
"execa": "^5.0.0",
4544
"fs-extra": "^10.0.0"
4645
},
4746
"dependencies": {
@@ -50,6 +49,7 @@
5049
"@commitlint/load": "^17.0.0",
5150
"@commitlint/read": "^17.0.0",
5251
"@commitlint/types": "^17.0.0",
52+
"execa": "^5.0.0",
5353
"lodash": "^4.17.19",
5454
"resolve-from": "5.0.0",
5555
"resolve-global": "1.0.0",

@commitlint/cli/src/cli.test.ts

+40-3
Original file line numberDiff line numberDiff line change
@@ -329,13 +329,50 @@ test('should handle --amend with signoff', async () => {
329329
expect(commit).toBeTruthy();
330330
}, 10000);
331331

332-
test('should fail with an empty message and a commentChar is set', async () => {
332+
test('it uses parserOpts.commentChar when not using edit mode', async () => {
333+
const cwd = await gitBootstrap('fixtures/comment-char');
334+
const input = 'header: foo\n$body\n';
335+
336+
const actual = await cli([], {cwd})(input);
337+
expect(actual.stdout).toContain('[body-empty]');
338+
expect(actual.exitCode).toBe(1);
339+
});
340+
341+
test("it doesn't use parserOpts.commentChar when using edit mode", async () => {
342+
const cwd = await gitBootstrap('fixtures/comment-char');
343+
await fs.writeFile(
344+
path.join(cwd, '.git', 'COMMIT_EDITMSG'),
345+
'header: foo\n\n$body\n'
346+
);
347+
348+
const actual = await cli(['--edit', '.git/COMMIT_EDITMSG'], {cwd})();
349+
expect(actual.stdout).not.toContain('[body-empty]');
350+
expect(actual.exitCode).toBe(0);
351+
});
352+
353+
test('it uses core.commentChar git config when using edit mode', async () => {
333354
const cwd = await gitBootstrap('fixtures/comment-char');
334355
await execa('git', ['config', '--local', 'core.commentChar', '$'], {cwd});
335-
await fs.writeFile(path.join(cwd, '.git', 'COMMIT_EDITMSG'), '#1234');
356+
await fs.writeFile(
357+
path.join(cwd, '.git', 'COMMIT_EDITMSG'),
358+
'header: foo\n\n$body\n'
359+
);
360+
361+
const actual = await cli(['--edit', '.git/COMMIT_EDITMSG'], {cwd})();
362+
expect(actual.stdout).toContain('[body-empty]');
363+
expect(actual.exitCode).toBe(1);
364+
});
365+
366+
test('it falls back to # for core.commentChar when using edit mode', async () => {
367+
const cwd = await gitBootstrap('fixtures/comment-char');
368+
await fs.writeFile(
369+
path.join(cwd, '.git', 'COMMIT_EDITMSG'),
370+
'header: foo\n\n#body\n'
371+
);
336372

337373
const actual = await cli(['--edit', '.git/COMMIT_EDITMSG'], {cwd})();
338-
expect(actual.stdout).toContain('[subject-empty]');
374+
expect(actual.stdout).toContain('[body-empty]');
375+
expect(actual.stderr).toEqual('');
339376
expect(actual.exitCode).toBe(1);
340377
});
341378

@commitlint/cli/src/cli.ts

+21-5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import execa, {ExecaError} from 'execa';
12
import load from '@commitlint/load';
23
import lint from '@commitlint/lint';
34
import read from '@commitlint/read';
@@ -21,6 +22,8 @@ import {CliError} from './cli-error';
2122

2223
const pkg = require('../package');
2324

25+
const gitDefaultCommentChar = '#';
26+
2427
const cli = yargs
2528
.options({
2629
color: {
@@ -221,11 +224,24 @@ async function main(args: MainArgs) {
221224
}
222225
const format = loadFormatter(loaded, flags);
223226

224-
// Strip comments if reading from `.git/COMMIT_EDIT_MSG` using the
225-
// commentChar from the parser preset falling back to a `#` if that is not
226-
// set
227-
if (flags.edit && typeof opts.parserOpts.commentChar !== 'string') {
228-
opts.parserOpts.commentChar = '#';
227+
// If reading from `.git/COMMIT_EDIT_MSG`, strip comments using
228+
// core.commentChar from git configuration, falling back to '#'.
229+
if (flags.edit) {
230+
try {
231+
const {stdout} = await execa('git', ['config', 'core.commentChar']);
232+
opts.parserOpts.commentChar = stdout.trim() || gitDefaultCommentChar;
233+
} catch (e) {
234+
const execaError = e as ExecaError;
235+
// git config returns exit code 1 when the setting is unset,
236+
// don't warn in this case.
237+
if (!execaError.failed || execaError.exitCode !== 1) {
238+
console.warn(
239+
'Could not determine core.commentChar git configuration',
240+
e
241+
);
242+
}
243+
opts.parserOpts.commentChar = gitDefaultCommentChar;
244+
}
229245
}
230246

231247
const results = await Promise.all(

package.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
"publish": "lerna publish --conventional-commits",
2020
"reinstall": "yarn clean && yarn install",
2121
"start": "yarn watch",
22-
"test": "jest",
23-
"test-ci": "jest --runInBand",
22+
"test": "cross-env HOME=$PWD jest",
23+
"test-ci": "cross-env HOME=$PWD jest --runInBand",
2424
"postinstall": "yarn husky install"
2525
},
2626
"commitlint": {
@@ -90,6 +90,7 @@
9090
"@types/node": "^12.20.27",
9191
"@typescript-eslint/eslint-plugin": "^5.0.0",
9292
"@typescript-eslint/parser": "^5.0.0",
93+
"cross-env": "^7.0.3",
9394
"docsify-cli": "^4.4.3",
9495
"eslint": "^8.0.0",
9596
"eslint-config-prettier": "^8.0.0",
@@ -106,4 +107,4 @@
106107
"resolutions": {
107108
"**/lodash": "^4.17.19"
108109
}
109-
}
110+
}

yarn.lock

+8-1
Original file line numberDiff line numberDiff line change
@@ -3915,7 +3915,14 @@ create-require@^1.1.0:
39153915
resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
39163916
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
39173917

3918-
cross-spawn@^7.0.2, cross-spawn@^7.0.3:
3918+
cross-env@^7.0.3:
3919+
version "7.0.3"
3920+
resolved "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf"
3921+
integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==
3922+
dependencies:
3923+
cross-spawn "^7.0.1"
3924+
3925+
cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
39193926
version "7.0.3"
39203927
resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
39213928
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==

0 commit comments

Comments
 (0)