fix(core): ensure ANSI escape codes are stripped in git-hasher process outputs
This commit is contained in:
parent
a5ba9bc0c3
commit
4956ebea9f
@ -1,6 +1,6 @@
|
|||||||
import { spawnSync } from 'child_process';
|
|
||||||
import { join } from 'path';
|
|
||||||
import { statSync } from 'fs';
|
import { statSync } from 'fs';
|
||||||
|
import { join } from 'path';
|
||||||
|
import { spawnProcess } from './spawn-process';
|
||||||
|
|
||||||
function parseGitLsTree(output: string): Map<string, string> {
|
function parseGitLsTree(output: string): Map<string, string> {
|
||||||
const changes: Map<string, string> = new Map<string, string>();
|
const changes: Map<string, string> = new Map<string, string>();
|
||||||
@ -33,7 +33,7 @@ function parseGitStatus(path: string): Map<string, string> {
|
|||||||
// we need to manually strip the root path from the filenames.
|
// we need to manually strip the root path from the filenames.
|
||||||
const prefix = spawnProcess('git', ['rev-parse', '--show-prefix'], path);
|
const prefix = spawnProcess('git', ['rev-parse', '--show-prefix'], path);
|
||||||
|
|
||||||
var chunks = output.split('\0');
|
const chunks = output.split('\0');
|
||||||
for (let i = 0; i < chunks.length; i++) {
|
for (let i = 0; i < chunks.length; i++) {
|
||||||
const chunk = chunks[i];
|
const chunk = chunks[i];
|
||||||
if (chunk.length) {
|
if (chunk.length) {
|
||||||
@ -52,16 +52,6 @@ function parseGitStatus(path: string): Map<string, string> {
|
|||||||
return changes;
|
return changes;
|
||||||
}
|
}
|
||||||
|
|
||||||
function spawnProcess(command: string, args: string[], cwd: string): string {
|
|
||||||
const r = spawnSync(command, args, { cwd, maxBuffer: 50 * 1024 * 1024 });
|
|
||||||
if (r.status !== 0) {
|
|
||||||
throw new Error(
|
|
||||||
`Failed to run ${command} ${args.join(' ')}.\n${r.stdout}\n${r.stderr}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return r.stdout.toString().trimEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getGitHashForFiles(
|
function getGitHashForFiles(
|
||||||
filesToHash: string[],
|
filesToHash: string[],
|
||||||
path: string
|
path: string
|
||||||
|
|||||||
57
packages/workspace/src/core/hasher/spawn-process.spec.ts
Normal file
57
packages/workspace/src/core/hasher/spawn-process.spec.ts
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import * as childProcess from 'child_process';
|
||||||
|
import { spawnProcess } from './spawn-process';
|
||||||
|
|
||||||
|
describe('spawnProcess()', () => {
|
||||||
|
let spy: jest.SpyInstance<
|
||||||
|
childProcess.SpawnSyncReturns<Buffer>,
|
||||||
|
[
|
||||||
|
command: string,
|
||||||
|
args?: readonly string[],
|
||||||
|
options?: childProcess.SpawnSyncOptions
|
||||||
|
]
|
||||||
|
>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
spy = jest.spyOn(childProcess, 'spawnSync');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
spy.mockReset();
|
||||||
|
spy.mockRestore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call spawnSync and return the stdout', () => {
|
||||||
|
const mockedStdout = 'stdout';
|
||||||
|
spy.mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
status: 0,
|
||||||
|
stdout: mockedStdout,
|
||||||
|
} as any;
|
||||||
|
});
|
||||||
|
const output = spawnProcess('git', ['status', '-s', '-u', '-z', '.'], '');
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(output).toEqual(mockedStdout);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work even when ANSI escape characters are present in the child process output - https://github.com/nrwl/nx/issues/7022', () => {
|
||||||
|
spy.mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
status: 0,
|
||||||
|
// ANSI escaped characters can come through in the child process output, as reported here: https://github.com/nrwl/nx/issues/7022
|
||||||
|
stdout:
|
||||||
|
' \x1B[7;33mM\x1B[m packages/semver/src/generators/install/index.spec.ts\x00',
|
||||||
|
} as any;
|
||||||
|
});
|
||||||
|
|
||||||
|
const output = spawnProcess('git', ['status', '-s', '-u', '-z', '.'], '');
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure the ANSI escaped characters have been stripped
|
||||||
|
* (the remaining trailing \0 is expected as part of the real-world git output)
|
||||||
|
*/
|
||||||
|
expect(output).toEqual(
|
||||||
|
' M packages/semver/src/generators/install/index.spec.ts\0'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
26
packages/workspace/src/core/hasher/spawn-process.ts
Normal file
26
packages/workspace/src/core/hasher/spawn-process.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { spawnSync } from 'child_process';
|
||||||
|
|
||||||
|
// We can't use an import for this package because of how it is published
|
||||||
|
const stripAnsi = require('strip-ansi');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We separated this out into its own file to make it much easier to unit test
|
||||||
|
* and ensure that ANSI escape codes are appropriately stripped so that utilities
|
||||||
|
* in git-hasher work as intended in all cases.
|
||||||
|
*/
|
||||||
|
export function spawnProcess(
|
||||||
|
command: string,
|
||||||
|
args: string[],
|
||||||
|
cwd: string
|
||||||
|
): string {
|
||||||
|
const r = spawnSync(command, args, { cwd, maxBuffer: 50 * 1024 * 1024 });
|
||||||
|
if (r.status !== 0) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to run ${command} ${args.join(' ')}.\n${r.stdout}\n${r.stderr}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const output = r.stdout.toString().trimEnd();
|
||||||
|
|
||||||
|
// We use strip-ansi to prevent issues such as https://github.com/nrwl/nx/issues/7022
|
||||||
|
return stripAnsi(output);
|
||||||
|
}
|
||||||
@ -85,6 +85,7 @@ const IGNORE_MATCHES = {
|
|||||||
'karma-coverage-istanbul-reporter',
|
'karma-coverage-istanbul-reporter',
|
||||||
'karma-jasmine',
|
'karma-jasmine',
|
||||||
'karma-jasmine-html-reporter',
|
'karma-jasmine-html-reporter',
|
||||||
|
'strip-ansi',
|
||||||
'webpack',
|
'webpack',
|
||||||
'webpack-dev-server',
|
'webpack-dev-server',
|
||||||
],
|
],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user