There is an `exec()` helper provided by `utils/shelljs.ts`, which is a
wrapper around ShellJS' `exec()` with some default options (currently
`silent: true`). The intention is to avoid having to pass these options
to every invocation of the `exec()` function.
This commit updates all code inside `dev-infra/` to use this helper
whenever possible).
NOTE: For simplicity, the `utils/shelljs` helper does not support some
      of the less common call signatures of the original `exec()`
      helper, so in some cases we still need to use the original.
PR Close #37444
		
	
			
		
			
				
	
	
		
			58 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			58 lines
		
	
	
		
			2.2 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
 | 
						|
 */
 | 
						|
import {info} from '../utils/console';
 | 
						|
import {exec} from '../utils/shelljs';
 | 
						|
 | 
						|
import {parseCommitMessage, validateCommitMessage, ValidateCommitMessageOptions} from './validate';
 | 
						|
 | 
						|
// Whether the provided commit is a fixup commit.
 | 
						|
const isNonFixup = (m: string) => !parseCommitMessage(m).isFixup;
 | 
						|
 | 
						|
// Extracts commit header (first line of commit message).
 | 
						|
const extractCommitHeader = (m: string) => parseCommitMessage(m).header;
 | 
						|
 | 
						|
/** Validate all commits in a provided git commit range. */
 | 
						|
export function validateCommitRange(range: string) {
 | 
						|
  // A random value is used as a string to allow for a definite split point in the git log result.
 | 
						|
  const randomValueSeparator = `${Math.random()}`;
 | 
						|
  // Custom git log format that provides the commit header and body, separated as expected with
 | 
						|
  // the custom separator as the trailing value.
 | 
						|
  const gitLogFormat = `%s%n%n%b${randomValueSeparator}`;
 | 
						|
 | 
						|
  // Retrieve the commits in the provided range.
 | 
						|
  const result = exec(`git log --reverse --format=${gitLogFormat} ${range}`);
 | 
						|
  if (result.code) {
 | 
						|
    throw new Error(`Failed to get all commits in the range: \n  ${result.stderr}`);
 | 
						|
  }
 | 
						|
 | 
						|
  // Separate the commits from a single string into individual commits
 | 
						|
  const commits = result.split(randomValueSeparator).map(l => l.trim()).filter(line => !!line);
 | 
						|
 | 
						|
  info(`Examining ${commits.length} commit(s) in the provided range: ${range}`);
 | 
						|
 | 
						|
  // Check each commit in the commit range.  Commits are allowed to be fixup commits for other
 | 
						|
  // commits in the provided commit range.
 | 
						|
  const allCommitsInRangeValid = commits.every((m, i) => {
 | 
						|
    const options: ValidateCommitMessageOptions = {
 | 
						|
      disallowSquash: true,
 | 
						|
      nonFixupCommitHeaders: isNonFixup(m) ?
 | 
						|
          undefined :
 | 
						|
          commits.slice(0, i).filter(isNonFixup).map(extractCommitHeader)
 | 
						|
    };
 | 
						|
    return validateCommitMessage(m, options);
 | 
						|
  });
 | 
						|
 | 
						|
  if (allCommitsInRangeValid) {
 | 
						|
    info('√  All commit messages in range valid.');
 | 
						|
  } else {
 | 
						|
    // Exit with a non-zero exit code if invalid commit messages have
 | 
						|
    // been discovered.
 | 
						|
    process.exit(1);
 | 
						|
  }
 | 
						|
}
 |