When creating a commit with the git cli, git pre-populates the editor used to enter the commit message with some comments (i.e. lines starting with `#`). These comments contain helpful instructions or information regarding the changes that are part of the commit. As happens with all commit message comments, they are removed by git and do not end up in the final commit message. However, the file that is passed to the `commit-msg` to be validated still contains these comments. This may affect the outcome of the commit message validation. In such cases, the author will not realize that the commit message is not in the desired format until the linting checks fail on CI (which validates the final commit messages and is not affected by this issue), usually several minutes later. Possible ways in which the commit message validation outcome can be affected: - The minimum body length check may pass incorrectly, even if there is no actual body, because the comments are counted as part of the body. - The maximum line length check may fail incorrectly due to a very long line in the comments. This commit fixes the problem by removing comment lines before validating a commit message. Fixes #37865 PR Close #38438
78 lines
2.4 KiB
TypeScript
78 lines
2.4 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google LLC All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*/
|
|
|
|
/** A parsed commit message. */
|
|
export interface ParsedCommitMessage {
|
|
header: string;
|
|
body: string;
|
|
bodyWithoutLinking: string;
|
|
type: string;
|
|
scope: string;
|
|
subject: string;
|
|
isFixup: boolean;
|
|
isSquash: boolean;
|
|
isRevert: boolean;
|
|
}
|
|
|
|
/** Regex determining if a commit is a fixup. */
|
|
const FIXUP_PREFIX_RE = /^fixup! /i;
|
|
/** Regex finding all github keyword links. */
|
|
const GITHUB_LINKING_RE = /((closed?s?)|(fix(es)?(ed)?)|(resolved?s?))\s\#(\d+)/ig;
|
|
/** Regex determining if a commit is a squash. */
|
|
const SQUASH_PREFIX_RE = /^squash! /i;
|
|
/** Regex determining if a commit is a revert. */
|
|
const REVERT_PREFIX_RE = /^revert:? /i;
|
|
/** Regex determining the scope of a commit if provided. */
|
|
const TYPE_SCOPE_RE = /^(\w+)(?:\(([^)]+)\))?\:\s(.+)$/;
|
|
/** Regex determining the entire header line of the commit. */
|
|
const COMMIT_HEADER_RE = /^(.*)/i;
|
|
/** Regex determining the body of the commit. */
|
|
const COMMIT_BODY_RE = /^.*\n\n([\s\S]*)$/;
|
|
|
|
/** Parse a full commit message into its composite parts. */
|
|
export function parseCommitMessage(commitMsg: string): ParsedCommitMessage {
|
|
// Ignore comments (i.e. lines starting with `#`). Comments are automatically removed by git and
|
|
// should not be considered part of the final commit message.
|
|
commitMsg = commitMsg.split('\n').filter(line => !line.startsWith('#')).join('\n');
|
|
|
|
let header = '';
|
|
let body = '';
|
|
let bodyWithoutLinking = '';
|
|
let type = '';
|
|
let scope = '';
|
|
let subject = '';
|
|
|
|
if (COMMIT_HEADER_RE.test(commitMsg)) {
|
|
header = COMMIT_HEADER_RE.exec(commitMsg)![1]
|
|
.replace(FIXUP_PREFIX_RE, '')
|
|
.replace(SQUASH_PREFIX_RE, '');
|
|
}
|
|
if (COMMIT_BODY_RE.test(commitMsg)) {
|
|
body = COMMIT_BODY_RE.exec(commitMsg)![1];
|
|
bodyWithoutLinking = body.replace(GITHUB_LINKING_RE, '');
|
|
}
|
|
|
|
if (TYPE_SCOPE_RE.test(header)) {
|
|
const parsedCommitHeader = TYPE_SCOPE_RE.exec(header)!;
|
|
type = parsedCommitHeader[1];
|
|
scope = parsedCommitHeader[2];
|
|
subject = parsedCommitHeader[3];
|
|
}
|
|
return {
|
|
header,
|
|
body,
|
|
bodyWithoutLinking,
|
|
type,
|
|
scope,
|
|
subject,
|
|
isFixup: FIXUP_PREFIX_RE.test(commitMsg),
|
|
isSquash: SQUASH_PREFIX_RE.test(commitMsg),
|
|
isRevert: REVERT_PREFIX_RE.test(commitMsg),
|
|
};
|
|
}
|