Use pure child_process.exec instead of execa

master
Jason Park 7 years ago
parent 08fa1c6dd7
commit 01cb894b9b

111
package-lock.json generated

@ -393,18 +393,6 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
"integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
"requires": {
"nice-try": "^1.0.4",
"path-key": "^2.0.1",
"semver": "^5.5.0",
"shebang-command": "^1.2.0",
"which": "^1.2.9"
}
},
"currently-unhandled": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
@ -491,14 +479,6 @@
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
},
"end-of-stream": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
"integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
"requires": {
"once": "^1.4.0"
}
},
"error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@ -536,20 +516,6 @@
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
},
"execa": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
"integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
"requires": {
"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"
}
},
"express": {
"version": "4.17.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
@ -688,14 +654,6 @@
"integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
"dev": true
},
"get-stream": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
"integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
"requires": {
"pump": "^3.0.0"
}
},
"glob": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
@ -802,11 +760,6 @@
"number-is-nan": "^1.0.0"
}
},
"is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
},
"is-utf8": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
@ -822,7 +775,8 @@
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true
},
"js-tokens": {
"version": "4.0.0",
@ -997,11 +951,6 @@
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
},
"node-notifier": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.0.tgz",
@ -1027,14 +976,6 @@
"validate-npm-package-license": "^3.0.1"
}
},
"npm-run-path": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
"integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
"requires": {
"path-key": "^2.0.0"
}
},
"number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
@ -1064,15 +1005,11 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1"
}
},
"p-finally": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
},
"parse-json": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
@ -1102,11 +1039,6 @@
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
},
"path-key": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
},
"path-parse": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
@ -1159,15 +1091,6 @@
"ipaddr.js": "1.9.0"
}
},
"pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
"requires": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"qs": {
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
@ -1265,7 +1188,8 @@
"semver": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA=="
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
"dev": true
},
"send": {
"version": "0.17.1",
@ -1325,19 +1249,6 @@
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
},
"shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
"integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
"requires": {
"shebang-regex": "^1.0.0"
}
},
"shebang-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
},
"shellwords": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
@ -1347,7 +1258,8 @@
"signal-exit": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
"dev": true
},
"source-map": {
"version": "0.6.1",
@ -1415,11 +1327,6 @@
"is-utf8": "^0.2.0"
}
},
"strip-eof": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
},
"strip-indent": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
@ -1616,6 +1523,7 @@
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"dev": true,
"requires": {
"isexe": "^2.0.0"
}
@ -1623,7 +1531,8 @@
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
"xtend": {
"version": "4.0.1",

@ -30,7 +30,6 @@
"compression": "^1.7.3",
"dotenv": "^8.0.0",
"dotenv-flow": "^2.0.0",
"execa": "^1.0.0",
"express": "^4.16.4",
"express-github-webhook": "^1.0.6",
"fs-extra": "^6.0.1",

@ -8,10 +8,9 @@ import { __PROD__, credentials, httpPort, httpsPort, webhookOptions } from 'conf
import http from 'http';
import https from 'https';
import { Hierarchy } from 'models';
import execa from 'execa';
import * as Tracers from 'tracers';
import { errorHandlerMiddleware, frontendMiddleware, redirectMiddleware } from 'middlewares';
import { pull } from 'utils/misc';
import { execute, pull } from 'utils/misc';
import { frontendBuildDir, frontendBuiltDir, frontendDir, rootDir } from 'config/paths';
const Webhook = require('express-github-webhook');
@ -76,13 +75,13 @@ export default class Server {
async update(commit?: string) {
await pull(rootDir, 'server', commit);
await execa.shell('npm install', {cwd: rootDir});
await execute('npm install', {cwd: rootDir});
process.exit(0);
};
async updateFrontend(commit?: string) {
await pull(frontendDir, 'algorithm-visualizer', commit);
await execa.shell([
await execute([
'npm install',
'npm run build',
`rm -rf ${frontendBuiltDir}`,

@ -4,8 +4,7 @@ import { GitHubApi } from 'utils/apis';
import { Algorithm, Category, File } from 'models';
import { Author } from 'models/File';
import { algorithmsDir } from 'config/paths';
import { pull } from 'utils/misc';
import execa from 'execa';
import { execute, pull } from 'utils/misc';
type CommitAuthors = {
[sha: string]: Author,
@ -52,7 +51,7 @@ export class Hierarchy {
async cacheContributors(files: File[], commitAuthors: CommitAuthors) {
for (const file of files) {
const stdout = await execa('git', ['--no-pager', 'log', '--follow', '--no-merges', '--format="%H"', '--', `"${file.path}"`], {
const stdout = await execute(`git --no-pager log --follow --no-merges --format="%H" -- "${path.relative(this.path, file.path)}"`, {
cwd: this.path,
});
const output = stdout.toString().replace(/\n$/, '');

@ -5,7 +5,7 @@ import uuid from 'uuid';
import fs from 'fs-extra';
import { memoryLimit, timeLimit } from 'config/constants';
import { codesDir } from 'config/paths';
import execa = require('execa');
import { execute } from 'utils/misc';
export class DockerTracer extends Tracer {
private readonly directory: string;
@ -21,7 +21,7 @@ export class DockerTracer extends Tracer {
build(release: Release) {
const {tag_name} = release;
return execa('docker', ['build', '-t', this.imageName, '.', '--build-arg', `tag_name=${tag_name}`], {cwd: this.directory});
return execute(`docker build -t ${this.imageName} . --build-arg tag_name=${tag_name}`, {cwd: this.directory});
}
route(router: express.Router) {
@ -33,19 +33,19 @@ export class DockerTracer extends Tracer {
const containerName = uuid.v4();
let killed = false;
const timer = setTimeout(() => {
execa('docker', ['kill', containerName]).then(() => {
execute(`docker kill ${containerName}`).then(() => {
killed = true;
});
}, timeLimit);
return execa('docker', [
'run', '--rm',
return execute([
'docker run --rm',
`--name=${containerName}`,
'-w=/usr/visualization',
`-v=${tempPath}:/usr/visualization:rw`,
`-m=${memoryLimit}m`,
'-e', 'ALGORITHM_VISUALIZER=1',
'-e ALGORITHM_VISUALIZER=1',
this.imageName,
]).catch(error => {
].join(' ')).catch(error => {
if (killed) throw new Error('Time Limit Exceeded');
throw error;
}).finally(() => clearTimeout(timer));

@ -1,8 +1,9 @@
import axios from 'axios';
import fs from 'fs-extra';
import execa from 'execa';
import { File } from 'models';
import removeMarkdown from 'remove-markdown';
import * as child_process from 'child_process';
import { ExecOptions } from 'child_process';
export function download(url: string, localPath: string) {
return axios({url, method: 'GET', responseType: 'stream'})
@ -16,11 +17,11 @@ export function download(url: string, localPath: string) {
export async function pull(dir: string, repo: string, commit = 'origin/master') {
if (fs.pathExistsSync(dir)) {
await execa.shell(`git fetch`, {cwd: dir});
await execute(`git fetch`, {cwd: dir});
} else {
await execa.shell(`git clone https://github.com/algorithm-visualizer/${repo}.git ${dir}`);
await execute(`git clone https://github.com/algorithm-visualizer/${repo}.git ${dir}`);
}
await execa.shell(`git reset --hard ${commit}`, {cwd: dir});
await execute(`git reset --hard ${commit}`, {cwd: dir});
}
export function getDescription(files: File[]) {
@ -34,6 +35,18 @@ export function getDescription(files: File[]) {
return removeMarkdown(descriptionLines.join(' '));
}
export function rethrow(err: any) {
throw err;
type ExecuteOptions = ExecOptions & {
stdout?: NodeJS.WriteStream;
stderr?: NodeJS.WriteStream;
}
export function execute(command: string, {stdout, stderr, ...options}: ExecuteOptions = {}): Promise<string> {
return new Promise((resolve, reject) => {
const child = child_process.exec(command, options, (error, stdout, stderr) => {
if (error) return reject(error.code ? new Error(stderr) : error);
resolve(stdout);
});
if (child.stdout && stdout) child.stdout.pipe(stdout);
if (child.stderr && stderr) child.stderr.pipe(stderr);
});
}

@ -18,5 +18,6 @@
},
"exclude": [
"node_modules",
"public"
]
}

Loading…
Cancel
Save