npmci/dist/npmci.build.docker.js
2016-06-07 12:36:00 +02:00

257 lines
35 KiB
JavaScript

"use strict";
var plugins = require("./npmci.plugins");
var paths = require("./npmci.paths");
var NpmciEnv = require("./npmci.env");
var npmci_bash_1 = require("./npmci.bash");
exports.build = function () {
var done = plugins.q.defer();
exports.readDockerfiles()
.then(exports.sortDockerfiles)
.then(exports.mapDockerfiles)
.then(exports.buildDockerfiles)
.then(exports.pushDockerfiles)
.then(function () {
done.resolve();
});
return done.promise;
};
exports.readDockerfiles = function () {
var done = plugins.q.defer();
var readDockerfilesArray = [];
plugins.gulp.src("./Dockerfile*")
.pipe(plugins.through2.obj(function (file, enc, cb) {
var myDockerfile = new Dockerfile({
filePath: file.path,
read: true
});
readDockerfilesArray.push(myDockerfile);
cb(null, file);
}, function () {
done.resolve(readDockerfilesArray);
}));
return done.promise;
};
exports.sortDockerfiles = function (sortableArrayArg) {
var done = plugins.q.defer();
var sortedArray = [];
var cleanTagsOriginal = exports.cleanTagsArrayFunction(sortableArrayArg, sortedArray);
var sorterFunctionCounter = 0;
var sorterFunction = function () {
sortableArrayArg.forEach(function (dockerfileArg) {
var cleanTags = exports.cleanTagsArrayFunction(sortableArrayArg, sortedArray);
if (cleanTags.indexOf(dockerfileArg.baseImage) == -1 && sortedArray.indexOf(dockerfileArg) == -1) {
sortedArray.push(dockerfileArg);
}
;
if (cleanTagsOriginal.indexOf(dockerfileArg.baseImage) != -1) {
dockerfileArg.localBaseImageDependent = true;
}
;
});
if (sortableArrayArg.length == sortedArray.length) {
done.resolve(sortedArray);
}
else if (sorterFunctionCounter < 10) {
sorterFunctionCounter++;
sorterFunction();
}
;
};
sorterFunction();
return done.promise;
};
exports.mapDockerfiles = function (sortedArray) {
var done = plugins.q.defer();
sortedArray.forEach(function (dockerfileArg) {
if (dockerfileArg.localBaseImageDependent) {
sortedArray.forEach(function (dockfile2) {
if (dockfile2.cleanTag == dockerfileArg.baseImage) {
dockerfileArg.localBaseDockerfile = dockfile2;
}
});
}
;
});
done.resolve(sortedArray);
return done.promise;
};
exports.buildDockerfiles = function (sortedArrayArg) {
var done = plugins.q.defer();
sortedArrayArg.forEach(function (dockerfileArg) {
dockerfileArg.build();
});
done.resolve(sortedArrayArg);
return done.promise;
};
exports.pushDockerfiles = function (sortedArrayArg) {
var done = plugins.q.defer();
sortedArrayArg.forEach(function (dockerfileArg) {
dockerfileArg.push();
});
done.resolve(sortedArrayArg);
return done.promise;
};
exports.pullDockerfileImages = function (sortableArrayArg) {
var done = plugins.q.defer();
sortableArrayArg.forEach(function (dockerfileArg) {
dockerfileArg.pull();
});
done.resolve(sortableArrayArg);
return done.promise;
};
exports.testDockerfiles = function (sortedArrayArg) {
var done = plugins.q.defer();
sortedArrayArg.forEach(function (dockerfileArg) {
dockerfileArg.test();
});
done.resolve(sortedArrayArg);
return done.promise;
};
exports.releaseDockerfiles = function (sortedArrayArg) {
var done = plugins.q.defer();
sortedArrayArg.forEach(function (dockerfileArg) {
dockerfileArg.release();
});
done.resolve(sortedArrayArg);
return done.promise;
};
var Dockerfile = (function () {
function Dockerfile(options) {
this.filePath = options.filePath;
this.repo = NpmciEnv.repo.user + "/" + NpmciEnv.repo.repo;
this.version = exports.dockerFileVersion(plugins.path.parse(options.filePath).base);
this.cleanTag = this.repo + ":" + this.version;
this.buildTag = exports.dockerTag(this.repo, this.version, "build");
this.releaseTag = exports.dockerTag(this.repo, this.version, "release");
this.containerName = "dockerfile-" + this.version;
if (options.filePath && options.read) {
this.content = plugins.smartfile.local.toStringSync(plugins.path.resolve(options.filePath));
}
;
this.baseImage = exports.dockerBaseImage(this.content);
this.localBaseImageDependent = false;
}
;
Dockerfile.prototype.build = function () {
plugins.beautylog.info("now building Dockerfile for " + this.cleanTag);
var done = plugins.q.defer();
this.patchContents();
npmci_bash_1.bashBare("docker build -t " + this.buildTag + " -f " + this.filePath + " .");
NpmciEnv.dockerFilesBuilt.push(this);
this.restoreContents();
done.resolve();
return done.promise;
};
;
Dockerfile.prototype.push = function () {
var done = plugins.q.defer();
if (this.buildTag) {
npmci_bash_1.bashBare("docker push " + this.buildTag);
}
else {
plugins.beautylog.error("Dockerfile hasn't been built yet!");
}
done.resolve();
return done.promise;
};
Dockerfile.prototype.pull = function () {
npmci_bash_1.bashBare("docker pull " + this.buildTag);
};
;
Dockerfile.prototype.test = function () {
var testFile = plugins.path.join(paths.NpmciTestDir, "test_" + this.version + ".sh");
var testFileExists = plugins.smartfile.checks.fileExistsSync(testFile);
if (testFileExists) {
npmci_bash_1.bashBare("docker run --name npmci_test_container " + this.buildTag + " mkdir /npmci_test");
npmci_bash_1.bashBare("docker cp " + testFile + " npmci_test_container:/npmci_test/test.sh");
npmci_bash_1.bashBare("docker commit npmci_test_container npmci_test_image");
npmci_bash_1.bashBare("docker run npmci_test_image sh /npmci_test/test.sh");
npmci_bash_1.bashBare("docker rm npmci_test_container");
npmci_bash_1.bashBare("docker rmi --force npmci_test_image");
}
else {
plugins.beautylog.warn("skipping tests for " + this.cleanTag + " because no testfile was found!");
}
};
;
Dockerfile.prototype.release = function () {
npmci_bash_1.bashBare("docker tag " + this.getId() + " " + this.releaseTag);
npmci_bash_1.bashBare("docker push " + this.releaseTag);
};
Dockerfile.prototype.getId = function () {
var containerId = npmci_bash_1.bashBare("docker inspect --type=image --format=\"{{.Id}}\" " + this.buildTag);
return containerId;
};
;
Dockerfile.prototype.patchContents = function () {
var done = plugins.q.defer();
if (this.localBaseImageDependent == true) {
plugins.beautylog.info("patching Dockerfile due to local build dependency!");
this.patchedContent = this.content.replace(/FROM\s[a-zA-Z0-9\/\-\:]*/, 'FROM ' + this.localBaseDockerfile.buildTag);
plugins.smartfile.memory.toFsSync(this.patchedContent, {
fileName: plugins.path.parse(this.filePath).name,
filePath: plugins.path.parse(this.filePath).dir
});
}
done.resolve();
return done.promise;
};
;
Dockerfile.prototype.restoreContents = function () {
var done = plugins.q.defer();
if (this.localBaseImageDependent == true) {
plugins.smartfile.memory.toFsSync(this.content, {
fileName: plugins.path.parse(this.filePath).name,
filePath: plugins.path.parse(this.filePath).dir
});
}
done.resolve();
return done.promise;
};
;
return Dockerfile;
}());
exports.Dockerfile = Dockerfile;
exports.dockerFileVersion = function (dockerfileNameArg) {
var versionString;
var versionRegex = /Dockerfile_([a-zA-Z0-9\.]*)$/;
var regexResultArray = versionRegex.exec(dockerfileNameArg);
if (regexResultArray && regexResultArray.length == 2) {
versionString = regexResultArray[1];
}
else {
versionString = "latest";
}
return versionString;
};
exports.dockerBaseImage = function (dockerfileContentArg) {
var baseImageRegex = /FROM\s([a-zA-z0-9\/\-\:]*)\n?/;
var regexResultArray = baseImageRegex.exec(dockerfileContentArg);
return regexResultArray[1];
};
exports.dockerTag = function (repoArg, versionArg, stageArg) {
var tagString;
var registry = NpmciEnv.dockerRegistry;
if (stageArg == "build" || stageArg == "test") {
registry = "registry.gitlab.com";
}
var repo = repoArg;
var version = versionArg;
if (stageArg == "build" || stageArg == "test") {
version = version + "_test";
}
tagString = registry + "/" + repo + ":" + version;
return tagString;
};
exports.cleanTagsArrayFunction = function (dockerfileArrayArg, trackingArrayArg) {
var cleanTagsArray = [];
dockerfileArrayArg.forEach(function (dockerfileArg) {
if (trackingArrayArg.indexOf(dockerfileArg) == -1) {
cleanTagsArray.push(dockerfileArg.cleanTag);
}
});
return cleanTagsArray;
};
//# sourceMappingURL=data:application/json;charset=utf8;base64,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Q0FBQSxDQUFDO1lBQzlDLGNBQWMsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2hELENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUNILE1BQU0sQ0FBQyxjQUFjLENBQUM7QUFDMUIsQ0FBQyxDQUFBIiwiZmlsZSI6Im5wbWNpLmJ1aWxkLmRvY2tlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBsdWdpbnMgZnJvbSBcIi4vbnBtY2kucGx1Z2luc1wiO1xyXG5pbXBvcnQgKiBhcyBwYXRocyBmcm9tIFwiLi9ucG1jaS5wYXRoc1wiO1xyXG5pbXBvcnQgKiBhcyBOcG1jaUVudiBmcm9tIFwiLi9ucG1jaS5lbnZcIjtcclxuaW1wb3J0IHtiYXNoQmFyZX0gZnJvbSBcIi4vbnBtY2kuYmFzaFwiO1xyXG5cclxuZXhwb3J0IGxldCBidWlsZCA9IGZ1bmN0aW9uKCl7XHJcbiAgICBsZXQgZG9uZSA9IHBsdWdpbnMucS5kZWZlcigpO1xyXG4gICAgcmVhZERvY2tlcmZpbGVzKClcclxuICAgICAgICAudGhlbihzb3J0RG9ja2VyZmlsZXMpXHJcbiAgICAgICAgLnRoZW4obWFwRG9ja2VyZmlsZXMpXHJcbiAgICAgICAgLnRoZW4oYnVpbGREb2NrZXJmaWxlcylcclxuICAgICAgICAudGhlbihwdXNoRG9ja2VyZmlsZXMpXHJcbiAgICAgICAgLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgICBkb25lLnJlc29sdmUoKTtcclxuICAgICAgICB9KTtcclxuICAgIHJldHVybiBkb25lLnByb21pc2U7XHJcbn1cclxuXHJcbmV4cG9ydCBsZXQgcmVhZERvY2tlcmZpbGVzID0gZnVuY3Rpb24oKXtcclxuICAgIGxldCBkb25lID0gcGx1Z2lucy5xLmRlZmVyKCk7XHJcbiAgICBsZXQgcmVhZERvY2tlcmZpbGVzQXJyYXk6RG9ja2VyZmlsZVtdID0gW11cclxuICAgIHBsdWdpbnMuZ3VscC5zcmMoXCIuL0RvY2tlcmZpbGUqXCIpXHJcbiAgICAgICAgLnBpcGUocGx1Z2lucy50aHJvdWdoMi5vYmooZnVuY3Rpb24oZmlsZSxlbmMsY2Ipe1xyXG4gICAgICAgICAgICBsZXQgbXlEb2NrZXJmaWxlID0gbmV3IERvY2tlcmZpbGUoe1xyXG4gICAgICAgICAgICAgICAgZmlsZVBhdGg6ZmlsZS5wYXRoLFxyXG4gICAgICAgICAgICAgICAgcmVhZDp0cnVlXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICByZWFkRG9ja2VyZmlsZXNBcnJheS5wdXNoKG15RG9ja2VyZmlsZSk7XHJcbiAgICAgICAgICAgIGNiKG51bGwsZmlsZSk7XHJcbiAgICAgICAgIH0sZnVuY3Rpb24oKXtcclxuICAgICAgICAgICAgIGRvbmUucmVzb2x2ZShyZWFkRG9ja2VyZmlsZXNBcnJheSk7XHJcbiAgICAgICAgIH0pKTtcclxuICAgIHJldHVybiBkb25lLnByb21pc2U7XHJcbn1cclxuXHJcbmV4cG9ydCBsZXQgc29ydERvY2tlcmZpbGVzID0gZnVuY3Rpb24oc29ydGFibGVBcnJheUFyZzpEb2NrZXJmaWxlW10pe1xyXG4gICAgbGV0IGRvbmUgPSBwbHVnaW5zLnEuZGVmZXIoKTtcclxuICAgIGxldCBzb3J0ZWRBcnJheTpEb2NrZXJmaWxlW10gPSBbXTtcclxuICAgIGxldCBjbGVhblRhZ3NPcmlnaW5hbCA9IGNsZWFuVGFnc0FycmF5RnVuY3Rpb24oc29ydGFibGVBcnJheUFyZyxzb3J0ZWRBcnJheSk7XHJcbiAgICBsZXQgc29ydGVyRnVuY3Rpb25Db3VudGVyOm51bWJlciA9IDA7XHJcbiAgICBsZXQgc29ydGVyRnVuY3Rpb24gPSBmdW5jdGlvbigpe1xyXG4gICAgICAgIHNvcnRhYmxlQXJyYXlBcmcuZm9yRWFjaCgoZG9ja2VyZmlsZUFyZyk9PntcclxuICAgICAgICAgICAgbGV0IGNsZWFuVGFncyA9IGNsZWFuVGFnc0FycmF5RnVuY3Rpb24oc29ydGFibGVBcnJheUFyZyxzb3J0ZWRBcnJheSk7XHJcbiAgICAgICAgICAgIGlmKGNsZWFuVGFncy5pbmRleE9mKGRvY2tlcmZpbGVBcmcuYmFzZUltYWdlKSA9PSAtMSAmJiBzb3J0ZWRBcnJheS5pbmRleE9mKGRvY2tlcmZpbGVBcmcpID09IC0xKXtcclxuICAgICAgICAgICAgICAgIHNvcnRlZEFycmF5LnB1c2goZG9ja2VyZmlsZUFyZyk7XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIGlmKGNsZWFuVGFnc09yaWdpbmFsLmluZGV4T2YoZG9ja2VyZmlsZUFyZy5iYXNlSW1hZ2UpICE9IC0xKXtcclxuICAgICAgICAgICAgICAgIGRvY2tlcmZpbGVBcmcubG9jYWxCYXNlSW1hZ2VEZXBlbmRlbnQgPSB0cnVlO1xyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGlmKHNvcnRhYmxlQXJyYXlBcmcubGVuZ3RoID09IHNvcnRlZEFycmF5Lmxlbmd0aCl7XHJcbiAgICAgICAgICAgIGRvbmUucmVzb2x2ZShzb3J0ZWRBcnJheSk7XHJcbiAgICAgICAgfSBlbHNlIGlmIChzb3J0ZXJGdW5jdGlvbkNvdW50ZXIgPCAxMCkge1xyXG4gICAgICAgICAgICBzb3J0ZXJGdW5jdGlvbkNvdW50ZXIrKztcclxuICAgICAgICAgICAgc29ydGVyRnVuY3Rpb24oKTtcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG4gICAgc29ydGVyRnVuY3Rpb24oKTtcclxuICAgIHJldHVybiBkb25lLnByb21pc2U7XHJcbn07XHJcblxyXG5leHBvcnQgbGV0IG1hcERvY2tlcmZpbGVzID0gZnVuY3Rpb24oc29ydGVkQXJyYXk6RG9ja2VyZmlsZVtdKXtcclxuICAgIGxldCBkb25lID0gcGx1Z2lucy5xLmRlZmVyKCk7XHJcbiAgICBzb3J0ZWRBcnJheS5mb3JFYWNoKChkb2NrZXJmaWxlQXJnKSA9PiB7XHJcbiAgICAgICAgaWYoZG9ja2VyZmlsZUFyZy5sb2NhbEJhc2VJbWFnZURlcGVuZGVudCl7XHJcbiAgICAgICAgICAgIHNvcnRlZEFycmF5LmZvckVhY2goKGRvY2tmaWxlMjpEb2NrZXJmaWxlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBpZihkb2NrZmlsZTIuY2xlYW5UYWcgPT0gZG9ja2VyZmlsZUFyZy5iYXNlSW1hZ2Upe1xyXG4gICAgICAgICAgICAgICAgICAgIGRvY2tlcmZpbGVBcmcubG9jYWxCYXNlRG9ja2VyZmlsZSA9IGRvY2tmaWxlMjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSlcclxuICAgICAgICB9O1xyXG4gICAgfSk7XHJcbiAgICBkb25lLnJlc29sdmUoc29ydGVkQXJyYXkpO1xyXG4gICAgcmV0dXJuIGRvbmUucHJvbWlzZTtcclxufVxyXG5cclxuZXhwb3J0IGxldCBidWlsZERvY2tlcmZpbGVzID0gKHNvcnRlZEFycmF5QXJnOkRvY2tlcmZpbGVbXSkgPT4ge1xyXG4gICAgbGV0IGRvbmUgPSBwbHVnaW5zLnEuZGVmZXIoKTtcclxuICAgIHNvcnRlZEFycmF5QXJnLmZvckVhY2goZnVuY3Rpb24oZG9ja2VyZmlsZUFyZyl7XHJcbiAgICAgICAgZG9ja2VyZmlsZUFyZy5idWlsZCgpO1xyXG4gICAgfSlcclxuICAgIGRvbmUucmVzb2x2ZShzb3J0ZWRBcnJheUFyZyk7XHJcbiAgICByZXR1cm4gZG9uZS5wcm9taXNlO1xyXG59XHJcblxyXG5leHBvcnQgbGV0IHB1c2hEb2NrZXJmaWxlcyA9IGZ1bmN0aW9uKHNvcnRlZEFycmF5QXJnOkRvY2tlcmZpbGVbXSl7XHJcbiAgICBsZXQgZG9uZSA9IHBsdWdpbnMucS5kZWZlcigpO1xyXG4gICAgc29ydGVkQXJyYXlBcmcuZm9yRWFjaChmdW5jdGlvbihkb2NrZXJmaWxlQXJnKXtcclxuICAgICAgICBkb2NrZXJmaWxlQXJnLnB1c2goKTtcclxuICAgIH0pO1xyXG4gICAgZG9uZS5yZXNvbHZlKHNvcnRlZEFycmF5QXJnKTtcclxuICAgIHJldHVybiBkb25lLnByb21pc2U7XHJcbn1cclxuXHJcbmV4cG9ydCBsZXQgcHVsbERvY2tlcmZpbGVJbWFnZXMgPSAoc29ydGFibGVBcnJheUFyZzpEb2NrZXJmaWxlW10pID0+IHtcclxuICAgIGxldCBkb25lID0gcGx1Z2lucy5xLmRlZmVyKCk7XHJcbiAgICBzb3J0YWJsZUFycmF5QXJnLmZvckVhY2goKGRvY2tlcmZpbGVBcmcpID0+IHtcclxuICAgICAgICBkb2NrZXJmaWxlQXJnLnB1bGwoKTtcclxuICAgIH0pO1xyXG4gICAgZG9uZS5yZXNvbHZlKHNvcnRhYmxlQXJyYXlBcmcpO1xyXG4gICAgcmV0dXJuIGRvbmUucHJvbWlzZTtcclxufVxyXG5cclxuZXhwb3J0IGxldCB0ZXN0RG9ja2VyZmlsZXMgPSAoc29ydGVkQXJyYXlBcmc6RG9ja2VyZmlsZVtdKSA9PiB7XHJcbiAgICBsZXQgZG9uZSA9IHBsdWdpbnMucS5kZWZlcigpO1xyXG4gICAgc29ydGVkQXJyYXlBcmcuZm9yRWFjaChmdW5jdGlvbihkb2NrZXJmaWxlQXJnKXtcclxuICAgICAgICBkb2NrZXJmaWxlQXJnLnRlc3QoKTtcclxuICAgIH0pO1xyXG4gICAgZG9uZS5yZXNvbHZlKHNvcnRlZEFycmF5QXJnKTtcclxuICAgIHJldHVybiBkb25lLnByb21pc2U7XHJcbn07XHJcblxyXG5leHBvcnQgbGV0IHJlbGVhc2VEb2NrZXJmaWxlcyA9IChzb3J0ZWRBcnJheUFyZzpEb2NrZXJmaWxlW10pID0+IHtcclxuICAgICBsZXQgZG9uZSA9IHBsdWdpbnMucS5kZWZlcigpO1xyXG4gICAgc29ydGVkQXJyYXlBcmcuZm9yRWFjaChmdW5jdGlvbihkb2NrZXJmaWxlQXJnKXtcclxuICAgICAgICBkb2NrZXJmaWxlQXJnLnJlbGVhc2UoKTtcclxuICAgIH0pO1xyXG4gICAgZG9uZS5yZXNvbHZlKHNvcnRlZEFycmF5QXJnKTtcclxuICAgIHJldHVybiBkb25lLnByb21pc2U7XHJcbn1cclxuXHJcbmV4cG9ydCBjbGFzcyBEb2NrZXJmaWxlIHtcclxuICAgIGZpbGVQYXRoOnN0cmluZztcclxuICAgIHJlcG86c3RyaW5nO1xyXG4gICAgdmVyc2lvbjpzdHJpbmc7XHJcbiAgICBjbGVhblRhZzpzdHJpbmc7XHJcbiAgICBidWlsZFRhZzpzdHJpbmc7XHJcbiAgICByZWxlYXNlVGFnOnN0cmluZztcclxuICAgIGNvbnRhaW5lck5hbWU6c3RyaW5nXHJcbiAgICBjb250ZW50OnN0cmluZztcclxuICAgIHBhdGNoZWRDb250ZW50OnN0cmluZztcclxuICAgIGJhc2VJbWFnZTpzdHJpbmc7XHJcbiAgICBsb2NhbEJhc2VJbWFnZURlcGVuZGVudDpib29sZWFuO1xyXG4gICAgbG9jYWxCYXNlRG9ja2VyZmlsZTpEb2NrZXJmaWxlO1xyXG4gICAgY29uc3RydWN0b3Iob3B0aW9uczp7ZmlsZVBhdGg/OnN0cmluZyxmaWxlQ29udGVudHM/OnN0cmluZ3xCdWZmZXIscmVhZD86Ym9vbGVhbn0pe1xyXG4gICAgICAgIHRoaXMuZmlsZVBhdGggPSBvcHRpb25zLmZpbGVQYXRoO1xyXG4gICAgICAgIHRoaXMucmVwbyA9IE5wbWNpRW52LnJlcG8udXNlciArIFwiL1wiICsgTnBtY2lFbnYucmVwby5yZXBvO1xyXG4gICAgICAgIHRoaXMudmVyc2lvbiA9IGRvY2tlckZpbGVWZXJzaW9uKHBsdWdpbnMucGF0aC5wYXJzZShvcHRpb25zLmZpbGVQYXRoKS5iYXNlKTtcclxuICAgICAgICB0aGlzLmNsZWFuVGFnID0gdGhpcy5yZXBvICsgXCI6XCIgKyB0aGlzLnZlcnNpb247XHJcbiAgICAgICAgdGhpcy5idWlsZFRhZyA9IGRvY2tlclRhZyh0aGlzLnJlcG8sdGhpcy52ZXJzaW9uLFwiYnVpbGRcIik7XHJcbiAgICAgICAgdGhpcy5yZWxlYXNlVGFnID0gZG9ja2VyVGFnKHRoaXMucmVwbyx0aGlzLnZlcnNpb24sXCJyZWxlYXNlXCIpO1xyXG4gICAgICAgIHRoaXMuY29udGFpbmVyTmFtZSA9IFwiZG9ja2VyZmlsZS1cIiArIHRoaXMudmVyc2lvbjtcclxuICAgICAgICBpZihvcHRpb25zLmZpbGVQYXRoICYmIG9wdGlvbnMucmVhZCl7XHJcbiAgICAgICAgICAgIHRoaXMuY29udGVudCA9IHBsdWdpbnMuc21hcnRmaWxlLmxvY2FsLnRvU3RyaW5nU3luYyhwbHVnaW5zLnBhdGgucmVzb2x2ZShvcHRpb25zLmZpbGVQYXRoKSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICB0aGlzLmJhc2VJbWFnZSA9IGRvY2tlckJhc2VJbWFnZSh0aGlzLmNvbnRlbnQpO1xyXG4gICAgICAgIHRoaXMubG9jYWxCYXNlSW1hZ2VEZXBlbmRlbnQgPSBmYWxzZTtcclxuICAgIH07XHJcbiAgICBidWlsZCgpe1xyXG4gICAgICAgIHBsdWdpbnMuYmVhdXR5bG9nLmluZm8oXCJub3cgYnVpbGRpbmcgRG9ja2VyZmlsZSBmb3IgXCIgKyB0aGlzLmNsZWFuVGFnKTtcclxuICAgICAgICBsZXQgZG9uZSA9IHBsdWdpbnMucS5kZWZlcigpO1xyXG4gICAgICAgIHRoaXMucGF0Y2hDb250ZW50cygpO1xyXG4gICAgICAgIGJhc2hCYXJlKFwiZG9ja2VyIGJ1aWxkIC10IFwiICsgdGhpcy5idWlsZFRhZyArIFwiIC1mIFwiICsgdGhpcy5maWxlUGF0aCArIFwiIC5cIik7XHJcbiAgICAgICAgTnBtY2lFbnYuZG9ja2VyRmlsZXNCdWlsdC5wdXNoKHRoaXMpO1xyXG4gICAgICAgIHRoaXMucmVzdG9yZUNvbnRlbnRzKCk7XHJcbiAgICAgICAgZG9uZS5yZXNvbHZlKCk7XHJcbiAgICAgICAgcmV0dXJuIGRvbmUucHJvbWlzZTtcclxuICAgIH07XHJcbiAgICBwdXNoKCl7XHJcbiAgICAgICAgbGV0IGRvbmUgPSBwbHVnaW5zLnEuZGVmZXIoKTtcclxuICAgICAgICBpZih0aGlzLmJ1aWxkVGFnKXtcclxuICAgICAgICAgICAgYmFzaEJhcmUoXCJkb2NrZXIgcHVzaCBcIiArIHRoaXMuYnVpbGRUYWcpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHBsdWdpbnMuYmVhdXR5bG9nLmVycm9yKFwiRG9ja2VyZmlsZSBoYXNuJ3QgYmVlbiBidWlsdCB5ZXQhXCIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBkb25lLnJlc29sdmUoKTtcclxuICAgICAgICByZXR1cm4gZG9uZS5wcm9taXNlO1xyXG4gICAgfVxyXG4gICAgcHVsbCgpe1xyXG4gICAgICAgIGJhc2hCYXJlKFwiZG9ja2VyIHB1bGwgXCIgKyB0aGlzLmJ1aWxkVGFnKTtcclxuICAgIH07XHJcbiAgICB0ZXN0KCl7XHJcbiAgICAgICAgbGV0IHRlc3RGaWxlOnN0cmluZyA9IHBsdWdpbnMucGF0aC5qb2luKHBhdGhzLk5wbWNpVGVzdERpcixcInRlc3RfXCIgKyB0aGlzLnZlcnNpb24gKyBcIi5zaFwiKTtcclxuICAgICAgICBsZXQgdGVzdEZpbGVFeGlzdHM6Ym9vbGVhbiA9IHBsdWdpbnMuc21hcnRmaWxlLmNoZWNrcy5maWxlRXhpc3RzU3luYyh0ZXN0RmlsZSk7XHJcbiAgICAgICAgaWYodGVzdEZpbGVFeGlzdHMpe1xyXG4gICAgICAgICAgICBiYXNoQmFyZShcImRvY2tlciBydW4gLS1uYW1lIG5wbWNpX3Rlc3RfY29udGFpbmVyIFwiICsgdGhpcy5idWlsZFRhZyArIFwiIG1rZGlyIC9ucG1jaV90ZXN0XCIpO1xyXG4gICAgICAgICAgICBiYXNoQmFyZShcImRvY2tlciBjcCBcIiArIHRlc3RGaWxlICsgXCIgbnBtY2lfdGVzdF9jb250YWluZXI6L25wbWNpX3Rlc3QvdGVzdC5zaFwiKTtcclxuICAgICAgICAgICAgYmFzaEJhcmUoXCJkb2NrZXIgY29tbWl0IG5wbWNpX3Rlc3RfY29udGFpbmVyIG5wbWNpX3Rlc3RfaW1hZ2VcIik7XHJcbiAgICAgICAgICAgIGJhc2hCYXJlKFwiZG9ja2VyIHJ1biBucG1jaV90ZXN0X2ltYWdlIHNoIC9ucG1jaV90ZXN0L3Rlc3Quc2hcIik7XHJcbiAgICAgICAgICAgIGJhc2hCYXJlKFwiZG9ja2VyIHJtIG5wbWNpX3Rlc3RfY29udGFpbmVyXCIpO1xyXG4gICAgICAgICAgICBiYXNoQmFyZShcImRvY2tlciBybWkgLS1mb3JjZSBucG1jaV90ZXN0X2ltYWdlXCIpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHBsdWdpbnMuYmVhdXR5bG9nLndhcm4oXCJza2lwcGluZyB0ZXN0cyBmb3IgXCIgKyB0aGlzLmNsZWFuVGFnICsgXCIgYmVjYXVzZSBubyB0ZXN0ZmlsZSB3YXMgZm91bmQhXCIpO1xyXG4gICAgICAgIH1cclxuICAgIH07XHJcbiAgICByZWxlYXNlKCl7XHJcbiAgICAgICAgYmFzaEJhcmUoXCJkb2NrZXIgdGFnIFwiICsgdGhpcy5nZXRJZCgpICsgXCIgXCIgKyB0aGlzLnJlbGVhc2VUYWcpO1xyXG4gICAgICAgIGJhc2hCYXJlKFwiZG9ja2VyIHB1c2ggXCIgKyB0aGlzLnJlbGVhc2VUYWcpO1xyXG4gICAgfVxyXG4gICAgZ2V0SWQoKXtcclxuICAgICAgICBsZXQgY29udGFpbmVySWQgPSBiYXNoQmFyZShcImRvY2tlciBpbnNwZWN0IC0tdHlwZT1pbWFnZSAtLWZvcm1hdD1cXFwie3suSWR9fVxcXCIgXCIgKyB0aGlzLmJ1aWxkVGFnKTtcclxuICAgICAgICByZXR1cm4gY29udGFpbmVySWQ7XHJcbiAgICB9O1xyXG4gICAgcGF0Y2hDb250ZW50cygpe1xyXG4gICAgICAgIGxldCBkb25lID0gcGx1Z2lucy5xLmRlZmVyKCk7XHJcbiAgICAgICAgaWYodGhpcy5sb2NhbEJhc2VJbWFnZURlcGVuZGVudCA9PSB0cnVlKXtcclxuICAgICAgICAgICAgcGx1Z2lucy5iZWF1dHlsb2cuaW5mbyhcInBhdGNoaW5nIERvY2tlcmZpbGUgZHVlIHRvIGxvY2FsIGJ1aWxkIGRlcGVuZGVuY3khXCIpO1xyXG4gICAgICAgICAgICB0aGlzLnBhdGNoZWRDb250ZW50ID0gdGhpcy5jb250ZW50LnJlcGxhY2UoL0ZST01cXHNbYS16QS1aMC05XFwvXFwtXFw6XSovLCAnRlJPTSAnICsgdGhpcy5sb2NhbEJhc2VEb2NrZXJmaWxlLmJ1aWxkVGFnKTtcclxuICAgICAgICAgICAgcGx1Z2lucy5zbWFydGZpbGUubWVtb3J5LnRvRnNTeW5jKFxyXG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaGVkQ29udGVudCxcclxuICAgICAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgICAgICBmaWxlTmFtZTpwbHVnaW5zLnBhdGgucGFyc2UodGhpcy5maWxlUGF0aCkubmFtZSxcclxuICAgICAgICAgICAgICAgICAgICBmaWxlUGF0aDpwbHVnaW5zLnBhdGgucGFyc2UodGhpcy5maWxlUGF0aCkuZGlyXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGRvbmUucmVzb2x2ZSgpO1xyXG4gICAgICAgIHJldHVybiBkb25lLnByb21pc2U7XHJcbiAgICB9O1xyXG4gICAgcmVzdG9yZUNvbnRlbnRzKCl7XHJcbiAgICAgICAgbGV0IGRvbmUgPSBwbHVnaW5zLnEuZGVmZXIoKTtcclxuICAgICAgICBpZih0aGlzLmxvY2FsQmFzZUltYWdlRGVwZW5kZW50ID09IHRydWUpe1xyXG4gICAgICAgICAgICBwbHVnaW5zLnNtYXJ0ZmlsZS5tZW1vcnkudG9Gc1N5bmMoXHJcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRlbnQsXHJcbiAgICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAgICAgZmlsZU5hbWU6cGx1Z2lucy5wYXRoLnBhcnNlKHRoaXMuZmlsZVBhdGgpLm5hbWUsXHJcbiAgICAgICAgICAgICAgICAgICAgZmlsZVBhdGg6cGx1Z2lucy5wYXRoLnBhcnNlKHRoaXMuZmlsZVBhdGgpLmRpclxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH1cclxuICAgICAgICBkb25lLnJlc29sdmUoKTtcclxuICAgICAgICByZXR1cm4gZG9uZS5wcm9taXNlO1xyXG4gICAgfTtcclxufVxyXG5cclxuZXhwb3J0IGxldCBkb2NrZXJGaWxlVmVyc2lvbiA9IGZ1bmN0aW9uKGRvY2tlcmZpbGVOYW1lQXJnOnN0cmluZyk6c3RyaW5ne1xyXG4gICAgbGV0IHZlcnNpb25TdHJpbmc6c3RyaW5nO1xyXG4gICAgbGV0IHZlcnNpb25SZWdleCA9IC9Eb2NrZXJmaWxlXyhbYS16QS1aMC05XFwuXSopJC87XHJcbiAgICBsZXQgcmVnZXhSZXN1bHRBcnJheSA9IHZlcnNpb25SZWdleC5leGVjKGRvY2tlcmZpbGVOYW1lQXJnKTtcclxuICAgIGlmKHJlZ2V4UmVzdWx0QXJyYXkgJiYgcmVnZXhSZXN1bHRBcnJheS5sZW5ndGggPT0gMil7XHJcbiAgICAgICAgdmVyc2lvblN0cmluZyA9IHJlZ2V4UmVzdWx0QXJyYXlbMV07ICAgICAgICBcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdmVyc2lvblN0cmluZyA9IFwibGF0ZXN0XCI7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdmVyc2lvblN0cmluZztcclxufVxyXG5cclxuZXhwb3J0IGxldCBkb2NrZXJCYXNlSW1hZ2UgPSBmdW5jdGlvbihkb2NrZXJmaWxlQ29udGVudEFyZzpzdHJpbmcpe1xyXG4gICAgbGV0IGJhc2VJbWFnZVJlZ2V4ID0gL0ZST01cXHMoW2EtekEtejAtOVxcL1xcLVxcOl0qKVxcbj8vXHJcbiAgICBsZXQgcmVnZXhSZXN1bHRBcnJheSA9IGJhc2VJbWFnZVJlZ2V4LmV4ZWMoZG9ja2VyZmlsZUNvbnRlbnRBcmcpXHJcbiAgICByZXR1cm4gcmVnZXhSZXN1bHRBcnJheVsxXTtcclxufVxyXG5cclxuZXhwb3J0IGxldCBkb2NrZXJUYWcgPSBmdW5jdGlvbihyZXBvQXJnOnN0cmluZyx2ZXJzaW9uQXJnOnN0cmluZyxzdGFnZUFyZzpzdHJpbmcpOnN0cmluZ3tcclxuICAgIGxldCB0YWdTdHJpbmc6c3RyaW5nO1xyXG4gICAgbGV0IHJlZ2lzdHJ5ID0gTnBtY2lFbnYuZG9ja2VyUmVnaXN0cnk7XHJcbiAgICBpZihzdGFnZUFyZyA9PSBcImJ1aWxkXCIgIHx8IHN0YWdlQXJnID09IFwidGVzdFwiKXtcclxuICAgICAgICByZWdpc3RyeSA9IFwicmVnaXN0cnkuZ2l0bGFiLmNvbVwiO1xyXG4gICAgfSBcclxuICAgIGxldCByZXBvID0gcmVwb0FyZztcclxuICAgIGxldCB2ZXJzaW9uID0gdmVyc2lvbkFyZztcclxuICAgIGlmKHN0YWdlQXJnID09IFwiYnVpbGRcIiAgfHwgc3RhZ2VBcmcgPT0gXCJ0ZXN0XCIpe1xyXG4gICAgICAgIHZlcnNpb24gPSB2ZXJzaW9uICsgXCJfdGVzdFwiO1xyXG4gICAgfVxyXG4gICAgdGFnU3RyaW5nID0gcmVnaXN0cnkgKyBcIi9cIiArIHJlcG8gKyBcIjpcIiArIHZlcnNpb247XHJcbiAgICByZXR1cm4gdGFnU3RyaW5nO1xyXG59O1xyXG5cclxuZXhwb3J0IGxldCBjbGVhblRhZ3NBcnJheUZ1bmN0aW9uID0gZnVuY3Rpb24oZG9ja2VyZmlsZUFycmF5QXJnOkRvY2tlcmZpbGVbXSx0cmFja2luZ0FycmF5QXJnOkRvY2tlcmZpbGVbXSk6c3RyaW5nW117XHJcbiAgICBsZXQgY2xlYW5UYWdzQXJyYXk6c3RyaW5nW10gPSBbXTtcclxuICAgIGRvY2tlcmZpbGVBcnJheUFyZy5mb3JFYWNoKGZ1bmN0aW9uKGRvY2tlcmZpbGVBcmcpe1xyXG4gICAgICAgIGlmKHRyYWNraW5nQXJyYXlBcmcuaW5kZXhPZihkb2NrZXJmaWxlQXJnKSA9PSAtMSl7XHJcbiAgICAgICAgICAgIGNsZWFuVGFnc0FycmF5LnB1c2goZG9ja2VyZmlsZUFyZy5jbGVhblRhZyk7XHJcbiAgICAgICAgfVxyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gY2xlYW5UYWdzQXJyYXk7XHJcbn0iXX0=