Skip to content

Commit

Permalink
refactor: use execa instead of child_process for VCS commands (#6987)
Browse files Browse the repository at this point in the history
  • Loading branch information
SimenB committed Sep 19, 2018
1 parent 86fc23d commit c3dc90f
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 92 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
- `[docs]` Explain how to rewrite assertions to avoid large irrelevant diff ([#6971](https://github.com/facebook/jest/pull/6971))
- `[examples]` add example using Babel 7 ([#6983](https://github.com/facebook/jest/pull/6983))
- `[docs]` Replace shallow equality with referential identity in `ExpectAPI.md` ([#6991](https://github.com/facebook/jest/pull/6991))
- `[jest-changed-files]` Refactor to use `execa` over `child_process` ([#6987](https://github.com/facebook/jest/pull/6987))

## 23.6.0

Expand Down
1 change: 1 addition & 0 deletions packages/jest-changed-files/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"license": "MIT",
"main": "build/index.js",
"dependencies": {
"execa": "^1.0.0",
"throat": "^4.0.0"
}
}
64 changes: 22 additions & 42 deletions packages/jest-changed-files/src/git.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,19 @@ import type {Path} from 'types/Config';
import type {Options, SCMAdapter} from 'types/ChangedFiles';

import path from 'path';
import childProcess from 'child_process';
import execa from 'execa';

const findChangedFilesUsingCommand = async (
args: Array<string>,
cwd: Path,
): Promise<Array<Path>> =>
new Promise((resolve, reject) => {
const child = childProcess.spawn('git', args, {cwd});
let stdout = '';
let stderr = '';
child.stdout.on('data', data => (stdout += data));
child.stderr.on('data', data => (stderr += data));
child.on('error', e => reject(e));
child.on('close', code => {
if (code === 0) {
stdout = stdout.trim();
if (stdout === '') {
resolve([]);
} else {
resolve(
stdout
.split('\n')
.filter(s => s !== '')
.map(changedPath => path.resolve(cwd, changedPath)),
);
}
} else {
reject(code + ': ' + stderr);
}
});
});
): Promise<Array<Path>> => {
const result = await execa('git', args, {cwd});

return result.stdout
.split('\n')
.filter(s => s !== '')
.map(changedPath => path.resolve(cwd, changedPath));
};

const adapter: SCMAdapter = {
findChangedFiles: async (
Expand All @@ -54,7 +36,7 @@ const adapter: SCMAdapter = {
const includePaths: Array<Path> = (options && options.includePaths) || [];

if (options && options.lastCommit) {
return await findChangedFilesUsingCommand(
return findChangedFilesUsingCommand(
['show', '--name-only', '--pretty=%b', 'HEAD'].concat(includePaths),
cwd,
);
Expand All @@ -81,7 +63,7 @@ const adapter: SCMAdapter = {
);
return [...committed, ...staged, ...unstaged];
} else {
return await findChangedFilesUsingCommand(
return findChangedFilesUsingCommand(
['ls-files', '--other', '--modified', '--exclude-standard'].concat(
includePaths,
),
Expand All @@ -90,19 +72,17 @@ const adapter: SCMAdapter = {
}
},

getRoot: async (cwd: string): Promise<?string> =>
new Promise(resolve => {
try {
let stdout = '';
const options = ['rev-parse', '--show-toplevel'];
const child = childProcess.spawn('git', options, {cwd});
child.stdout.on('data', data => (stdout += data));
child.on('error', () => resolve(null));
child.on('close', code => resolve(code === 0 ? stdout.trim() : null));
} catch (e) {
resolve(null);
}
}),
getRoot: async (cwd: string): Promise<?string> => {
const options = ['rev-parse', '--show-toplevel'];

try {
const result = await execa('git', options, {cwd});

return result.stdout;
} catch (e) {
return null;
}
},
};

export default adapter;
77 changes: 29 additions & 48 deletions packages/jest-changed-files/src/hg.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type {Path} from 'types/Config';
import type {Options, SCMAdapter} from 'types/ChangedFiles';

import path from 'path';
import childProcess from 'child_process';
import execa from 'execa';

const env = Object.assign({}, process.env, {
HGPLAIN: 1,
Expand All @@ -32,55 +32,36 @@ const adapter: SCMAdapter = {
findChangedFiles: async (
cwd: string,
options: Options,
): Promise<Array<Path>> =>
new Promise((resolve, reject) => {
const includePaths: Array<Path> = (options && options.includePaths) || [];
): Promise<Array<Path>> => {
const includePaths: Array<Path> = (options && options.includePaths) || [];

const args = ['status', '-amnu'];
if (options && options.withAncestor) {
args.push('--rev', `ancestor(${ANCESTORS.join(', ')})`);
} else if (options && options.changedSince) {
args.push('--rev', `ancestor(., ${options.changedSince})`);
} else if (options && options.lastCommit === true) {
args.push('-A');
}
args.push(...includePaths);
const child = childProcess.spawn('hg', args, {cwd, env});
let stdout = '';
let stderr = '';
child.stdout.on('data', data => (stdout += data));
child.stderr.on('data', data => (stderr += data));
child.on('error', (error: Error) => reject(error));
child.on('close', code => {
if (code === 0) {
stdout = stdout.trim();
if (stdout === '') {
resolve([]);
} else {
resolve(
stdout
.split('\n')
.map(changedPath => path.resolve(cwd, changedPath)),
);
}
} else {
reject(new Error(code + ': ' + stderr));
}
});
}),
const args = ['status', '-amnu'];
if (options && options.withAncestor) {
args.push('--rev', `ancestor(${ANCESTORS.join(', ')})`);
} else if (options && options.changedSince) {
args.push('--rev', `ancestor(., ${options.changedSince})`);
} else if (options && options.lastCommit === true) {
args.push('-A');
}
args.push(...includePaths);

getRoot: async (cwd: Path): Promise<?Path> =>
new Promise(resolve => {
try {
let stdout = '';
const child = childProcess.spawn('hg', ['root'], {cwd, env});
child.stdout.on('data', data => (stdout += data));
child.on('error', () => resolve(null));
child.on('close', code => resolve(code === 0 ? stdout.trim() : null));
} catch (e) {
resolve(null);
}
}),
const result = await execa('hg', args, {cwd, env});

return result.stdout
.split('\n')
.filter(s => s !== '')
.map(changedPath => path.resolve(cwd, changedPath));
},

getRoot: async (cwd: Path): Promise<?Path> => {
try {
const result = await execa('hg', ['root'], {cwd, env});

return result.stdout;
} catch (e) {
return null;
}
},
};

export default adapter;
29 changes: 27 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3929,7 +3929,7 @@ encoding@^0.1.11:
dependencies:
iconv-lite "~0.4.13"

end-of-stream@^1.0.0:
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
dependencies:
Expand Down Expand Up @@ -4404,6 +4404,18 @@ execa@^0.8.0:
signal-exit "^3.0.0"
strip-eof "^1.0.0"

execa@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
dependencies:
cross-spawn "^6.0.0"
get-stream "^4.0.0"
is-stream "^1.1.0"
npm-run-path "^2.0.0"
p-finally "^1.0.0"
signal-exit "^3.0.0"
strip-eof "^1.0.0"

executable@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/executable/-/executable-1.1.0.tgz#877980e9112f3391066da37265de7ad8434ab4d9"
Expand Down Expand Up @@ -5040,6 +5052,12 @@ get-stream@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"

get-stream@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.0.0.tgz#9e074cb898bd2b9ebabb445a1766d7f43576d977"
dependencies:
pump "^3.0.0"

get-uri@2:
version "2.0.1"
resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-2.0.1.tgz#dbdcacacd8c608a38316869368117697a1631c59"
Expand Down Expand Up @@ -8119,7 +8137,7 @@ on-headers@~1.0.0, on-headers@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"

once@^1.3.0, once@^1.4.0:
once@^1.3.0, once@^1.3.1, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
dependencies:
Expand Down Expand Up @@ -8909,6 +8927,13 @@ public-encrypt@^4.0.0:
parse-asn1 "^5.0.0"
randombytes "^2.0.1"

pump@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
dependencies:
end-of-stream "^1.1.0"
once "^1.3.1"

punycode@1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
Expand Down

0 comments on commit c3dc90f

Please sign in to comment.