Add semver range parsing support

This commit is contained in:
Ron Buckton
2018-08-28 14:11:01 -07:00
parent 37ec065d93
commit 04a524511e
10 changed files with 483 additions and 19 deletions

View File

@@ -0,0 +1,62 @@
// @ts-check
const { CancelToken } = require("./cancellation");
class Countdown {
constructor(initialCount = 0) {
if (initialCount < 0) throw new Error();
this._remainingCount = initialCount;
this._promise = undefined;
this._resolve = undefined;
}
get remainingCount() {
return this._remainingCount;
}
add(count = 1) {
if (count < 1 || !isFinite(count) || Math.trunc(count) !== count) throw new Error();
if (this._remainingCount === 0) {
this._promise = undefined;
this._resolve = undefined;
}
this._remainingCount += count;
}
signal(count = 1) {
if (count < 1 || !isFinite(count) || Math.trunc(count) !== count) throw new Error();
if (this._remainingCount - count < 0) throw new Error();
this._remainingCount -= count;
if (this._remainingCount == 0) {
if (this._resolve) {
this._resolve();
}
return true;
}
return false;
}
/** @param {CancelToken} [token] */
wait(token) {
if (!this._promise) {
this._promise = new Promise(resolve => { this._resolve = resolve; });
}
if (this._remainingCount === 0) {
this._resolve();
}
if (!token) return this._promise;
return new Promise((resolve, reject) => {
const subscription = token.subscribe(reject);
this._promise.then(
value => {
subscription.unsubscribe();
resolve(value);
},
error => {
subscription.unsubscribe();
reject(error);
});
});
}
}
exports.Countdown = Countdown;

View File

@@ -25,8 +25,10 @@ function exec(cmd, args, options = {}) {
const command = isWin ? [possiblyQuote(cmd), ...args] : [`${cmd} ${args.join(" ")}`];
const ex = cp.spawn(isWin ? "cmd" : "/bin/sh", [subshellFlag, ...command], { stdio: "inherit", windowsVerbatimArguments: true });
const subscription = options.cancelToken && options.cancelToken.subscribe(() => {
log(`${chalk.red("killing")} '${chalk.green(cmd)} ${args.join(" ")}'...`);
ex.kill("SIGINT");
ex.kill("SIGTERM");
ex.kill();
reject(new CancelError());
});
ex.on("exit", exitCode => {

View File

@@ -13,8 +13,27 @@ const del = require("del");
const needsUpdate = require("./needsUpdate");
const mkdirp = require("./mkdirp");
const { reportDiagnostics } = require("./diagnostics");
const { Countdown } = require("./countdown");
const { CancelToken } = require("./cancellation");
const countdown = new Countdown();
class CompilationGulp extends gulp.Gulp {
constructor() {
super();
this.on("start", () => {
const onDone = () => {
this.removeListener("stop", onDone);
this.removeListener("err", onDone);
countdown.signal();
};
this.on("stop", onDone);
this.on("err", onDone);
countdown.add();
});
}
/**
* @param {boolean} [verbose]
*/
@@ -38,6 +57,17 @@ class ForkedGulp extends gulp.Gulp {
constructor(tasks) {
super();
this.tasks = tasks;
this.on("start", () => {
const onDone = () => {
this.removeListener("stop", onDone);
this.removeListener("err", onDone);
countdown.signal();
};
this.on("stop", onDone);
this.on("err", onDone);
countdown.add();
});
}
// Do not reset tasks
@@ -211,22 +241,10 @@ exports.flatten = flatten;
/**
* Returns a Promise that resolves when all pending build tasks have completed
* @param {CancelToken} [token]
*/
function wait() {
return new Promise(resolve => {
if (compilationGulp.allDone()) {
resolve();
}
else {
const onDone = () => {
compilationGulp.removeListener("onDone", onDone);
compilationGulp.removeListener("err", onDone);
resolve();
};
compilationGulp.on("stop", onDone);
compilationGulp.on("err", onDone);
}
});
function wait(token) {
return countdown.wait(token);
}
exports.wait = wait;