UNPKG

stryker

Version:
205 lines 10.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var path = require("path"); var util_1 = require("@stryker-mutator/util"); var util_2 = require("@stryker-mutator/util"); var core_1 = require("stryker-api/core"); var fileUtils_1 = require("../utils/fileUtils"); var util_3 = require("@stryker-mutator/util"); var InputFileCollection_1 = require("./InputFileCollection"); var objectUtils_1 = require("../utils/objectUtils"); var config_1 = require("stryker-api/config"); var plugin_1 = require("stryker-api/plugin"); var di_1 = require("../di"); function toReportSourceFile(file) { return { content: file.textContent, path: file.name }; } var IGNORE_PATTERN_CHARACTER = '!'; var InputFileResolver = /** @class */ (function () { function InputFileResolver(log, _a, reporter) { var mutate = _a.mutate, files = _a.files; this.log = log; this.reporter = reporter; this.mutatePatterns = this.normalize(mutate || []); if (files) { this.filePatterns = this.normalize(files); } } InputFileResolver.prototype.resolve = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var _a, inputFileNames, mutateFiles, files, inputFileCollection; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: return [4 /*yield*/, Promise.all([ this.resolveInputFiles(), this.resolveMutateFiles() ])]; case 1: _a = _b.sent(), inputFileNames = _a[0], mutateFiles = _a[1]; return [4 /*yield*/, this.readFiles(inputFileNames)]; case 2: files = _b.sent(); inputFileCollection = new InputFileCollection_1.default(files, mutateFiles); this.reportAllSourceFilesRead(files); inputFileCollection.logFiles(this.log); return [2 /*return*/, inputFileCollection]; } }); }); }; InputFileResolver.prototype.resolveInputFiles = function () { if (this.filePatterns) { return this.expand(this.filePatterns); } else { return this.resolveFilesUsingGit(); } }; InputFileResolver.prototype.resolveMutateFiles = function () { return this.expand(this.mutatePatterns, !shallowEquals(this.mutatePatterns, new config_1.Config().mutate)); function shallowEquals(arr1, arr2) { if (arr1.length !== arr2.length) { return false; } else { for (var i = 0; i < arr1.length; i++) { if (arr1[i] !== arr2[i]) { return false; } } return true; } } }; /** * Takes a list of globbing patterns and expands them into files. * If a patterns starts with a `!`, it negates the pattern. * @param patterns The patterns to expand into files */ InputFileResolver.prototype.expand = function (patterns, logAboutUselessPatterns) { if (logAboutUselessPatterns === void 0) { logAboutUselessPatterns = true; } return tslib_1.__awaiter(this, void 0, void 0, function () { var fileSet, _i, patterns_1, pattern, files, files; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: fileSet = new Set(); _i = 0, patterns_1 = patterns; _a.label = 1; case 1: if (!(_i < patterns_1.length)) return [3 /*break*/, 6]; pattern = patterns_1[_i]; if (!pattern.startsWith(IGNORE_PATTERN_CHARACTER)) return [3 /*break*/, 3]; return [4 /*yield*/, this.expandPattern(pattern.substr(1), logAboutUselessPatterns)]; case 2: files = _a.sent(); files.forEach(function (fileName) { return fileSet.delete(fileName); }); return [3 /*break*/, 5]; case 3: return [4 /*yield*/, this.expandPattern(pattern, logAboutUselessPatterns)]; case 4: files = _a.sent(); files.forEach(function (fileName) { return fileSet.add(fileName); }); _a.label = 5; case 5: _i++; return [3 /*break*/, 1]; case 6: return [2 /*return*/, Array.from(fileSet)]; } }); }); }; InputFileResolver.prototype.expandPattern = function (globbingExpression, logAboutUselessPatterns) { return tslib_1.__awaiter(this, void 0, void 0, function () { var fileNames; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, fileUtils_1.glob(globbingExpression)]; case 1: fileNames = (_a.sent()).map(function (relativeFile) { return path.resolve(relativeFile); }); if (!fileNames.length && logAboutUselessPatterns) { this.log.warn("Globbing expression \"" + globbingExpression + "\" did not result in any files."); } return [2 /*return*/, fileNames]; } }); }); }; InputFileResolver.prototype.resolveFilesUsingGit = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var stdout, fileNames, error_1; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); return [4 /*yield*/, util_2.childProcessAsPromised.exec('git ls-files --others --exclude-standard --cached --exclude .stryker-tmp', { maxBuffer: 10 * 1000 * 1024 })]; case 1: stdout = (_a.sent()).stdout; fileNames = stdout.toString() .split('\n') .map(function (line) { return line.trim(); }) .filter(function (line) { return line; }) // remove empty lines .map(function (relativeFileName) { return path.resolve(relativeFileName); }); return [2 /*return*/, fileNames]; case 2: error_1 = _a.sent(); throw new util_3.StrykerError(objectUtils_1.normalizeWhiteSpaces("Cannot determine input files. Either specify a `files`\n array in your stryker configuration, or make sure \"" + process.cwd() + "\"\n is located inside a git repository"), error_1); case 3: return [2 /*return*/]; } }); }); }; InputFileResolver.prototype.reportAllSourceFilesRead = function (allFiles) { this.reporter.onAllSourceFilesRead(allFiles.map(toReportSourceFile)); }; InputFileResolver.prototype.reportSourceFilesRead = function (textFile) { this.reporter.onSourceFileRead(toReportSourceFile(textFile)); }; InputFileResolver.prototype.readFiles = function (files) { var _this = this; return Promise.all(files.map(function (fileName) { return _this.readFile(fileName); })).then(objectUtils_1.filterEmpty); }; InputFileResolver.prototype.normalize = function (inputFileExpressions) { var inputFileDescriptorObjects = []; var globExpressions = inputFileExpressions.map(function (expression) { if (typeof expression === 'string') { return expression; } else { inputFileDescriptorObjects.push(expression); return expression.pattern; } }); if (inputFileDescriptorObjects.length) { this.log.warn(objectUtils_1.normalizeWhiteSpaces("\n DEPRECATED: Using the `InputFileDescriptor` syntax to\n select files is no longer supported. We'll assume: " + JSON.stringify(inputFileDescriptorObjects) + "\n can be migrated to " + JSON.stringify(inputFileDescriptorObjects.map(function (_) { return _.pattern; })) + " for this\n mutation run. Please move any files to mutate into the `mutate` array (top level stryker option).\n You can fix this warning in 2 ways:\n 1) If your project is under git version control, you can remove the \"files\" patterns all together.\n Stryker can figure it out for you.\n 2) If your project is not under git version control or you need ignored files in your sandbox, you can replace the\n `InputFileDescriptor` syntax with strings (as done for this test run).")); } return globExpressions; }; InputFileResolver.prototype.readFile = function (fileName) { var _this = this; return util_1.fsAsPromised .readFile(fileName) .then(function (content) { return new core_1.File(fileName, content); }) .then(function (file) { _this.reportSourceFilesRead(file); return file; }) .catch(function (error) { if ((util_1.isErrnoException(error) && error.code === 'ENOENT') || error.code === 'EISDIR') { return null; // file is deleted or a directory. This can be a valid result of the git command } else { // Rethrow throw error; } }); }; InputFileResolver.inject = plugin_1.tokens(plugin_1.commonTokens.logger, plugin_1.commonTokens.options, di_1.coreTokens.reporter); return InputFileResolver; }()); exports.default = InputFileResolver; //# sourceMappingURL=InputFileResolver.js.map