Skip to content

Commit 37dcf7e

Browse files
committed
fix: Ignore path conflicts and use spawn instead of exec
1 parent 19dc12b commit 37dcf7e

File tree

4 files changed

+87
-14
lines changed

4 files changed

+87
-14
lines changed

src/__tests__/cli-tests.ts

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,69 @@ describe('cli', () => {
2424
expect(readStdinSpy).toHaveBeenCalledWith();
2525
});
2626

27-
test('should readStdin when inputType is `command`', async () => {
28-
const executeSpy = jest.spyOn(utils, 'execute').mockImplementationOnce(() => '');
27+
describe('should execute command when inputType is `command`', () => {
28+
test('should pass args to git command and add `--no-color` flag', async () => {
29+
const executeSpy = jest.spyOn(utils, 'execute').mockImplementationOnce(() => '');
2930

30-
await cli.getInput('command', ['lol', 'foo'], []);
31+
await cli.getInput('command', ['foo'], []);
3132

32-
expect(executeSpy).toHaveBeenCalledTimes(1);
33-
expect(executeSpy).toHaveBeenCalledWith('git diff "lol" "foo" --no-color ');
33+
expect(executeSpy).toHaveBeenCalledTimes(1);
34+
expect(executeSpy).toHaveBeenCalledWith('git', ['diff', '--no-color', 'foo']);
35+
});
36+
37+
test('should not add `--no-color` flag if already in args', async () => {
38+
const executeSpy = jest.spyOn(utils, 'execute').mockImplementationOnce(() => '');
39+
40+
await cli.getInput('command', ['--no-color'], []);
41+
42+
expect(executeSpy).toHaveBeenCalledTimes(1);
43+
expect(executeSpy).toHaveBeenCalledWith('git', ['diff', '--no-color']);
44+
});
45+
46+
test('should add default flags if no args are provided', async () => {
47+
const executeSpy = jest.spyOn(utils, 'execute').mockImplementationOnce(() => '');
48+
49+
await cli.getInput('command', [], []);
50+
51+
expect(executeSpy).toHaveBeenCalledTimes(1);
52+
expect(executeSpy).toHaveBeenCalledWith('git', ['diff', '--no-color', '-M', '-C', 'HEAD']);
53+
});
54+
55+
describe('when receiving paths to ignore', () => {
56+
test('should add the `--` separator if it is not already in args', async () => {
57+
const executeSpy = jest.spyOn(utils, 'execute').mockImplementationOnce(() => '');
58+
59+
await cli.getInput('command', ['foo'], ['some/path']);
60+
61+
expect(executeSpy).toHaveBeenCalledTimes(1);
62+
expect(executeSpy).toHaveBeenCalledWith('git', ['diff', '--no-color', 'foo', '--', ':(exclude)some/path']);
63+
});
64+
65+
test('should not add `--` flag if it is already in args', async () => {
66+
const executeSpy = jest.spyOn(utils, 'execute').mockImplementationOnce(() => '');
67+
68+
await cli.getInput('command', ['foo', '--', 'other/path'], ['some/path']);
69+
70+
expect(executeSpy).toHaveBeenCalledTimes(1);
71+
expect(executeSpy).toHaveBeenCalledWith('git', [
72+
'diff',
73+
'--no-color',
74+
'foo',
75+
'--',
76+
'other/path',
77+
':(exclude)some/path',
78+
]);
79+
});
80+
});
81+
82+
test('should not add `--` flag when there are no paths to ignore', async () => {
83+
const executeSpy = jest.spyOn(utils, 'execute').mockImplementationOnce(() => '');
84+
85+
await cli.getInput('command', ['bar'], []);
86+
87+
expect(executeSpy).toHaveBeenCalledTimes(1);
88+
expect(executeSpy).toHaveBeenCalledWith('git', ['diff', '--no-color', 'bar']);
89+
});
3490
});
3591
});
3692

src/__tests__/utils-tests.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ describe('utils', () => {
1313

1414
test('should execute command in shell', () => {
1515
const echoedValue = 'echoed string';
16-
const result = utils.execute(`echo "${echoedValue}"`);
16+
const result = utils.execute('echo', [echoedValue]);
1717

1818
expect(result).toBe(`${echoedValue}\n`);
1919
});

src/cli.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,31 @@ import * as log from './logger';
1111
import { Configuration, InputType, DiffyType } from './types';
1212
import * as utils from './utils';
1313

14-
function runGitDiff(gitArgsArr: string[], ignore: string[]): string {
15-
const baseArgs = gitArgsArr.length > 0 ? gitArgsArr.map(arg => `"${arg}"`) : ['-M', '-C', 'HEAD'];
16-
const colorArgs = gitArgsArr.indexOf('--no-color') < 0 ? ['--no-color'] : [];
17-
const ignoreArgs = ignore.map(file => `":(exclude)${file}"`);
14+
const defaultArgs = ['-M', '-C', 'HEAD'];
15+
16+
function generateGitDiffArgs(gitArgsArr: string[], ignore: string[]): string[] {
17+
const gitDiffArgs: string[] = ['diff'];
18+
19+
if (!gitArgsArr.includes('--no-color')) gitDiffArgs.push('--no-color');
1820

19-
const diffCommand = `git diff ${baseArgs.join(' ')} ${colorArgs.join(' ')} ${ignoreArgs.join(' ')}`;
21+
if (gitArgsArr.length === 0) Array.prototype.push.apply(gitDiffArgs, defaultArgs);
2022

21-
return utils.execute(diffCommand);
23+
Array.prototype.push.apply(gitDiffArgs, gitArgsArr);
24+
25+
if (ignore.length > 0) {
26+
if (!gitArgsArr.includes('--')) gitDiffArgs.push('--');
27+
Array.prototype.push.apply(
28+
gitDiffArgs,
29+
ignore.map(path => `:(exclude)${path}`),
30+
);
31+
}
32+
33+
return gitDiffArgs;
34+
}
35+
36+
function runGitDiff(gitArgsArr: string[], ignore: string[]): string {
37+
const gitDiffArgs = generateGitDiffArgs(gitArgsArr, ignore);
38+
return utils.execute('git', gitDiffArgs);
2239
}
2340

2441
function prepareHTML(diffHTMLContent: string, config: Configuration): string {

src/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ export function writeFile(filePath: string, content: string): void {
2828
return fs.writeFileSync(filePath, content);
2929
}
3030

31-
export function execute(cmd: string): string {
32-
return childProcess.execSync(cmd).toString('utf8');
31+
export function execute(executable: string, args: string[]): string {
32+
return childProcess.spawnSync(executable, args, { encoding: 'utf8' }).stdout;
3333
}
3434

3535
export function replaceExactly(value: string, searchValue: string, replaceValue: string): string {

0 commit comments

Comments
 (0)