zarro 1.92.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +10 -0
- package/README.md +260 -0
- package/gulp-tasks/.editorconfig +8 -0
- package/gulp-tasks/.git +1 -0
- package/gulp-tasks/.gitignore +9 -0
- package/gulp-tasks/.gitmodules +0 -0
- package/gulp-tasks/LICENSE +24 -0
- package/gulp-tasks/README.md +144 -0
- package/gulp-tasks/build.js +135 -0
- package/gulp-tasks/clean.js +37 -0
- package/gulp-tasks/cover-dotnet.js +56 -0
- package/gulp-tasks/default-report-generator.js +51 -0
- package/gulp-tasks/default-tools-installer.js +33 -0
- package/gulp-tasks/default.js +17 -0
- package/gulp-tasks/dotnet-publish.js +23 -0
- package/gulp-tasks/generate-reports.js +7 -0
- package/gulp-tasks/get-local-nuget.js +16 -0
- package/gulp-tasks/git-submodules.js +83 -0
- package/gulp-tasks/increment-package-json-version.js +12 -0
- package/gulp-tasks/increment-package-json-version.ts +17 -0
- package/gulp-tasks/install-tools.js +24 -0
- package/gulp-tasks/modules/add-stream-on-any-handler.js +31 -0
- package/gulp-tasks/modules/alter-package-json-version.js +64 -0
- package/gulp-tasks/modules/alter-package-json-version.ts +113 -0
- package/gulp-tasks/modules/are-all-dotnet-core.js +96 -0
- package/gulp-tasks/modules/ask.js +31 -0
- package/gulp-tasks/modules/ask.ts +41 -0
- package/gulp-tasks/modules/collect-files.js +15 -0
- package/gulp-tasks/modules/collect-files.ts +16 -0
- package/gulp-tasks/modules/config-generator.js +10 -0
- package/gulp-tasks/modules/defaults.js +9 -0
- package/gulp-tasks/modules/download-nuget.js +104 -0
- package/gulp-tasks/modules/ensure-folder-exists.js +21 -0
- package/gulp-tasks/modules/env-helpers.js +49 -0
- package/gulp-tasks/modules/env-helpers.ts +67 -0
- package/gulp-tasks/modules/env.js +364 -0
- package/gulp-tasks/modules/exec.js +257 -0
- package/gulp-tasks/modules/exec.ts +346 -0
- package/gulp-tasks/modules/fail-after.js +30 -0
- package/gulp-tasks/modules/fail-after.ts +34 -0
- package/gulp-tasks/modules/fallback.js +6 -0
- package/gulp-tasks/modules/find-dirs.js +39 -0
- package/gulp-tasks/modules/find-local-nuget.js +42 -0
- package/gulp-tasks/modules/find-npm-base.js +42 -0
- package/gulp-tasks/modules/fs.js +79 -0
- package/gulp-tasks/modules/gather-paths.js +23 -0
- package/gulp-tasks/modules/gather-paths.ts +29 -0
- package/gulp-tasks/modules/generate-env-help-for.js +30 -0
- package/gulp-tasks/modules/get-tools-folder.js +12 -0
- package/gulp-tasks/modules/git-push-tags.js +33 -0
- package/gulp-tasks/modules/git-push-tags.ts +42 -0
- package/gulp-tasks/modules/git-push.js +51 -0
- package/gulp-tasks/modules/git-tag.js +36 -0
- package/gulp-tasks/modules/gulp-dotnetcover.js +537 -0
- package/gulp-tasks/modules/gulp-git-tag-from-csproj.js +50 -0
- package/gulp-tasks/modules/gulp-git-tag-from-csproj.ts +71 -0
- package/gulp-tasks/modules/gulp-git-tag-from-package-nuspec.js +55 -0
- package/gulp-tasks/modules/gulp-increment-nuget-package-dependency-version.js +40 -0
- package/gulp-tasks/modules/gulp-increment-nuget-package-version.js +87 -0
- package/gulp-tasks/modules/gulp-increment-nuget-package-version.ts +122 -0
- package/gulp-tasks/modules/gulp-msbuild.js +1 -0
- package/gulp-tasks/modules/gulp-npm-run.js +40 -0
- package/gulp-tasks/modules/gulp-npm-run.ts +52 -0
- package/gulp-tasks/modules/gulp-nuget-pack.js +168 -0
- package/gulp-tasks/modules/gulp-nuget-restore.js +106 -0
- package/gulp-tasks/modules/gulp-nunit-runner/.jshintrc +5 -0
- package/gulp-tasks/modules/gulp-nunit-runner/.npmignore +16 -0
- package/gulp-tasks/modules/gulp-nunit-runner/LICENSE +21 -0
- package/gulp-tasks/modules/gulp-nunit-runner/README.md +300 -0
- package/gulp-tasks/modules/gulp-nunit-runner/index.js +1 -0
- package/gulp-tasks/modules/gulp-nunit-runner/lib/index.js +205 -0
- package/gulp-tasks/modules/gulp-nunit-runner/lib/teamcity.js +86 -0
- package/gulp-tasks/modules/gulp-purge.js +88 -0
- package/gulp-tasks/modules/gulp-util.js +5 -0
- package/gulp-tasks/modules/gulp-version.js +8 -0
- package/gulp-tasks/modules/gulp-with-help.js +1 -0
- package/gulp-tasks/modules/gulp-xbuild.js +62 -0
- package/gulp-tasks/modules/gulp.js +92 -0
- package/gulp-tasks/modules/http-downloader.js +113 -0
- package/gulp-tasks/modules/import-npm-tasks.js +33 -0
- package/gulp-tasks/modules/increment-version-string.js +18 -0
- package/gulp-tasks/modules/increment-version.js +30 -0
- package/gulp-tasks/modules/increment-version.ts +41 -0
- package/gulp-tasks/modules/install-local-tools.js +122 -0
- package/gulp-tasks/modules/load-xml-file.js +12 -0
- package/gulp-tasks/modules/load-xml-file.ts +15 -0
- package/gulp-tasks/modules/log-config.js +31 -0
- package/gulp-tasks/modules/log.js +142 -0
- package/gulp-tasks/modules/longest-string-length.js +13 -0
- package/gulp-tasks/modules/looks-like-a-promise.js +11 -0
- package/gulp-tasks/modules/ls-r.js +52 -0
- package/gulp-tasks/modules/multi-split.js +29 -0
- package/gulp-tasks/modules/net-framework-test-assembly-filter.js +45 -0
- package/gulp-tasks/modules/nuget-push.js +66 -0
- package/gulp-tasks/modules/nuget-update-self.js +9 -0
- package/gulp-tasks/modules/nuget.js +8 -0
- package/gulp-tasks/modules/nuget.ts +14 -0
- package/gulp-tasks/modules/pad-left.js +4 -0
- package/gulp-tasks/modules/pad-right.js +4 -0
- package/gulp-tasks/modules/pad.js +25 -0
- package/gulp-tasks/modules/parse-xml-string.js +5 -0
- package/gulp-tasks/modules/parse-xml-string.ts +6 -0
- package/gulp-tasks/modules/parse-xml.js +14 -0
- package/gulp-tasks/modules/parse-xml.ts +15 -0
- package/gulp-tasks/modules/path-unquote.js +6 -0
- package/gulp-tasks/modules/promisify-function.js +19 -0
- package/gulp-tasks/modules/promisify-function.ts +18 -0
- package/gulp-tasks/modules/promisify-stream.js +73 -0
- package/gulp-tasks/modules/promisify.js +1 -0
- package/gulp-tasks/modules/quote-if-required.js +14 -0
- package/gulp-tasks/modules/read-all-git-branches.js +10 -0
- package/gulp-tasks/modules/read-all-git-branches.ts +13 -0
- package/gulp-tasks/modules/read-all-git-remotes.js +36 -0
- package/gulp-tasks/modules/read-all-git-remotes.ts +44 -0
- package/gulp-tasks/modules/read-csproj-package-version.js +16 -0
- package/gulp-tasks/modules/read-csproj-package-version.ts +26 -0
- package/gulp-tasks/modules/read-csproj-version.js +16 -0
- package/gulp-tasks/modules/read-csproj-version.ts +26 -0
- package/gulp-tasks/modules/read-current-git-branch.js +12 -0
- package/gulp-tasks/modules/read-current-git-branch.ts +16 -0
- package/gulp-tasks/modules/read-git-commit-delta-count.js +21 -0
- package/gulp-tasks/modules/read-git-commit-delta-count.ts +33 -0
- package/gulp-tasks/modules/read-git-info.js +28 -0
- package/gulp-tasks/modules/read-git-info.ts +31 -0
- package/gulp-tasks/modules/read-git-remote.js +17 -0
- package/gulp-tasks/modules/read-git-remote.ts +23 -0
- package/gulp-tasks/modules/read-last-fetch-time.js +21 -0
- package/gulp-tasks/modules/read-last-fetch-time.ts +17 -0
- package/gulp-tasks/modules/read-main-branch-name.js +48 -0
- package/gulp-tasks/modules/read-main-branch-name.ts +76 -0
- package/gulp-tasks/modules/read-nuspec-version.js +14 -0
- package/gulp-tasks/modules/read-nuspec-version.ts +22 -0
- package/gulp-tasks/modules/read-package-json.js +16 -0
- package/gulp-tasks/modules/read-package-json.ts +22 -0
- package/gulp-tasks/modules/read-package-version.js +8 -0
- package/gulp-tasks/modules/read-package-version.ts +10 -0
- package/gulp-tasks/modules/read-text-file.js +14 -0
- package/gulp-tasks/modules/read-text-file.ts +14 -0
- package/gulp-tasks/modules/reduce-gulp-noise.js +34 -0
- package/gulp-tasks/modules/register-environment-variables.js +526 -0
- package/gulp-tasks/modules/require-module.js +28 -0
- package/gulp-tasks/modules/resolve-git-branch.js +11 -0
- package/gulp-tasks/modules/resolve-git-branch.ts +13 -0
- package/gulp-tasks/modules/resolve-git-remote.js +11 -0
- package/gulp-tasks/modules/resolve-git-remote.ts +13 -0
- package/gulp-tasks/modules/resolve-masks.js +47 -0
- package/gulp-tasks/modules/resolve-nuget.js +135 -0
- package/gulp-tasks/modules/resolve-test-masks.js +10 -0
- package/gulp-tasks/modules/rewrite-file.js +26 -0
- package/gulp-tasks/modules/rewrite-file.ts +34 -0
- package/gulp-tasks/modules/rimraf.js +21 -0
- package/gulp-tasks/modules/rimraf.ts +31 -0
- package/gulp-tasks/modules/run-sequence.js +16 -0
- package/gulp-tasks/modules/safe-git.js +23 -0
- package/gulp-tasks/modules/safe-git.ts +23 -0
- package/gulp-tasks/modules/seed.js +12 -0
- package/gulp-tasks/modules/set-task-name.js +9 -0
- package/gulp-tasks/modules/sleep.js +5 -0
- package/gulp-tasks/modules/spawn-nuget.js +13 -0
- package/gulp-tasks/modules/spawn.js +103 -0
- package/gulp-tasks/modules/split-path.js +3 -0
- package/gulp-tasks/modules/stat.js +8 -0
- package/gulp-tasks/modules/status.js +57 -0
- package/gulp-tasks/modules/status.ts +71 -0
- package/gulp-tasks/modules/test-path.js +3 -0
- package/gulp-tasks/modules/testutil-finder.js +176 -0
- package/gulp-tasks/modules/throw-if-no-files.js +15 -0
- package/gulp-tasks/modules/uniq.js +6 -0
- package/gulp-tasks/modules/uniq.ts +5 -0
- package/gulp-tasks/modules/verify-exe.js +17 -0
- package/gulp-tasks/modules/version-reading-shared.js +12 -0
- package/gulp-tasks/modules/version-reading-shared.ts +16 -0
- package/gulp-tasks/modules/write-text-file.js +10 -0
- package/gulp-tasks/modules/zarro-error.js +6 -0
- package/gulp-tasks/nuget-restore.js +57 -0
- package/gulp-tasks/pack.js +118 -0
- package/gulp-tasks/purge.js +94 -0
- package/gulp-tasks/release-npm.js +58 -0
- package/gulp-tasks/release-npm.ts +81 -0
- package/gulp-tasks/start/_package.json +39 -0
- package/gulp-tasks/start/gulpfile.js +204 -0
- package/gulp-tasks/start/update-starter-packages.js +63 -0
- package/gulp-tasks/test-dotnet.js +195 -0
- package/gulp-tasks/update-git-submodules.js +11 -0
- package/gulp-tasks/update-git-submodules.ts +29 -0
- package/gulp-tasks/update-self.js +65 -0
- package/gulp-tasks/update-self.ts +88 -0
- package/gulp-tasks/verify-up-to-date.js +77 -0
- package/gulp-tasks/verify-up-to-date.ts +119 -0
- package/index-modules/contains-any.js +31 -0
- package/index-modules/gather-args.js +21 -0
- package/index-modules/handlers/help.js +17 -0
- package/index-modules/handlers/init.js +57 -0
- package/index-modules/handlers/invoke-gulp.js +111 -0
- package/index-modules/handlers/show-env.js +46 -0
- package/index-modules/is-dir.js +6 -0
- package/index-modules/is-file.js +6 -0
- package/index.js +53 -0
- package/package.json +96 -0
- package/tsconfig.json +66 -0
- package/types.d.ts +753 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const
|
|
2
|
+
Git = require("simple-git/promise"),
|
|
3
|
+
resolveGitBranch = requireModule("resolve-git-branch"),
|
|
4
|
+
resolveGitRemote = requireModule("resolve-git-remote"),
|
|
5
|
+
gutil = requireModule("gulp-util");
|
|
6
|
+
|
|
7
|
+
async function gitPush(
|
|
8
|
+
dryRun,
|
|
9
|
+
quiet,
|
|
10
|
+
where
|
|
11
|
+
) {
|
|
12
|
+
if (dryRun === undefined) {
|
|
13
|
+
dryRun = {};
|
|
14
|
+
}
|
|
15
|
+
if (typeof dryRun === "object") {
|
|
16
|
+
quiet = dryRun.quiet || false;
|
|
17
|
+
where = dryRun.where || ".";
|
|
18
|
+
dryRun = dryRun.dryRun || false;
|
|
19
|
+
} else if (quiet !== undefined) {
|
|
20
|
+
gutil.log.warn(
|
|
21
|
+
gutil.colors.red(
|
|
22
|
+
"depreciation warning: options for git-push should be sent via an object"
|
|
23
|
+
)
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
where = where || ".";
|
|
27
|
+
quiet = !!quiet;
|
|
28
|
+
const
|
|
29
|
+
git = new Git(where),
|
|
30
|
+
more = where ? ` (${where})` : "";
|
|
31
|
+
if (dryRun) {
|
|
32
|
+
gutil.log(gutil.colors.green(`dry run: whould push local commits now${more}...`));
|
|
33
|
+
return Promise.resolve();
|
|
34
|
+
}
|
|
35
|
+
if (!quiet) {
|
|
36
|
+
gutil.log(gutil.colors.green(`pushing local commits${more}...`));
|
|
37
|
+
}
|
|
38
|
+
const
|
|
39
|
+
remote = await resolveGitRemote(),
|
|
40
|
+
branch = await resolveGitBranch();
|
|
41
|
+
if (remote && branch) {
|
|
42
|
+
await git.push(
|
|
43
|
+
remote,
|
|
44
|
+
branch, [
|
|
45
|
+
"-u" // we're probably already tracking, but this will help a new branch
|
|
46
|
+
]
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = gitPush;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const
|
|
2
|
+
{ ZarroError } = requireModule("zarro-error"),
|
|
3
|
+
Git = require("simple-git/promise"),
|
|
4
|
+
env = requireModule("env"),
|
|
5
|
+
gutil = requireModule("gulp-util");
|
|
6
|
+
|
|
7
|
+
async function gitTag(tag, comment, where) {
|
|
8
|
+
let dryRun = false;
|
|
9
|
+
if (typeof tag === "object") {
|
|
10
|
+
comment = tag.comment;
|
|
11
|
+
where = tag.where || ".";
|
|
12
|
+
dryRun = tag.dryRun || env.resolveFlag(env.DRY_RUN);
|
|
13
|
+
tag = tag.tag;
|
|
14
|
+
} else if (comment !== undefined) {
|
|
15
|
+
gutil.log.warn(
|
|
16
|
+
gutil.colors.red(
|
|
17
|
+
"depreciation warning: options for git-tag should be sent via an object"
|
|
18
|
+
)
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
if (!(tag || "").trim()) {
|
|
22
|
+
throw new ZarroError("No tag supplied!");
|
|
23
|
+
}
|
|
24
|
+
const more = where === "." ? "" : ` ${where}`
|
|
25
|
+
comment = comment || `:bookmark: tagging${more} at ${tag}`;
|
|
26
|
+
where = where || ".";
|
|
27
|
+
if (dryRun) {
|
|
28
|
+
gutil.log(gutil.colors.green(`dry run: would tag${more} at ${tag} with comment: ${comment}`));
|
|
29
|
+
} else {
|
|
30
|
+
const git = new Git(where);
|
|
31
|
+
gutil.log(gutil.colors.cyan(`Tagging${more} at: "${tag}"`));
|
|
32
|
+
await git.addAnnotatedTag(tag, comment);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = gitTag;
|
|
@@ -0,0 +1,537 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const gutil = requireModule("gulp-util"),
|
|
3
|
+
env = requireModule("env"),
|
|
4
|
+
es = require("event-stream"),
|
|
5
|
+
path = require("path"),
|
|
6
|
+
fs = require("fs"),
|
|
7
|
+
testUtilFinder = require("./testutil-finder"),
|
|
8
|
+
getToolsFolder = require("./get-tools-folder"),
|
|
9
|
+
spawn = require("./spawn"),
|
|
10
|
+
mkdirp = require("mkdirp"),
|
|
11
|
+
coverageTarget = process.env.COVERAGE_TARGET || "Debug",
|
|
12
|
+
debug = require("debug")("gulp-dotnetcover"),
|
|
13
|
+
log = require("./log");
|
|
14
|
+
|
|
15
|
+
const PLUGIN_NAME = "gulp-dotnetcover";
|
|
16
|
+
|
|
17
|
+
function projectPathFor(p) {
|
|
18
|
+
return path.resolve(p);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function dotCover(options) {
|
|
22
|
+
options = options || {};
|
|
23
|
+
options.failOnError = options.failOnError || true;
|
|
24
|
+
options.exec = options.exec || {};
|
|
25
|
+
options.exec.dotCover =
|
|
26
|
+
options.exec.dotCover || testUtilFinder.latestDotCover(options);
|
|
27
|
+
options.exec.openCover =
|
|
28
|
+
options.exec.openCover || testUtilFinder.latestOpenCover(options);
|
|
29
|
+
options.exec.nunit =
|
|
30
|
+
options.exec.nunit || testUtilFinder.latestNUnit(options);
|
|
31
|
+
options.baseFilters =
|
|
32
|
+
options.baseFilters || "+:module=*;class=*;function=*;-:*.Tests";
|
|
33
|
+
options.exclude = options.exclude || [];
|
|
34
|
+
options.nunitOptions = options.nunitOptions || "--labels=Before";
|
|
35
|
+
options.allowProjectAssemblyMismatch = options.allowProjectAssemblyMismatch || false;
|
|
36
|
+
if (Array.isArray(options.nunitOptions)) {
|
|
37
|
+
options.nunitOptions = options.nunitOptions.join(" ");
|
|
38
|
+
}
|
|
39
|
+
options.nunitOutput = projectPathFor(
|
|
40
|
+
options.nunitOutput || "buildreports/nunit-result.xml"
|
|
41
|
+
);
|
|
42
|
+
options.coverageReportBase = projectPathFor(
|
|
43
|
+
options.coverageReportBase || "buildreports/coverage"
|
|
44
|
+
);
|
|
45
|
+
options.coverageOutput = projectPathFor(
|
|
46
|
+
options.coverageOutput || "buildreports/coveragesnapshot"
|
|
47
|
+
);
|
|
48
|
+
options.agents = options.agents || env.resolveNumber("MAX_NUNIT_AGENTS"); // allow setting max agents via environment variable
|
|
49
|
+
mkdirp(options.coverageReportBase); // because open-cover is too lazy to do it itself :/
|
|
50
|
+
if (typeof options.testAssemblyFilter !== "function") {
|
|
51
|
+
const regex = options.testAssemblyFilter;
|
|
52
|
+
options.testAssemblyFilter = function(file) {
|
|
53
|
+
return !!file.match(regex);
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const assemblies = [];
|
|
58
|
+
|
|
59
|
+
const stream = es.through(
|
|
60
|
+
function write(file) {
|
|
61
|
+
if (!file) {
|
|
62
|
+
fail(this, "file may not be empty or undefined");
|
|
63
|
+
}
|
|
64
|
+
const filePath = file.history[0];
|
|
65
|
+
let parts = filePath.split("\\");
|
|
66
|
+
if (parts.length === 1) {
|
|
67
|
+
parts = filePath.split("/");
|
|
68
|
+
}
|
|
69
|
+
// only accept the one which is in the debug project output for itself
|
|
70
|
+
const filePart = parts[parts.length - 1];
|
|
71
|
+
const projectParts = filePart.split(".");
|
|
72
|
+
const projectName = projectParts
|
|
73
|
+
.slice(0, projectParts.length - 1)
|
|
74
|
+
.join(".");
|
|
75
|
+
const isBin = parts.indexOf("bin") > -1;
|
|
76
|
+
const isRelevantForCoverageTarget =
|
|
77
|
+
parts.indexOf(coverageTarget) > -1 ||
|
|
78
|
+
parts.indexOf("bin") === parts.length - 2;
|
|
79
|
+
const isProjectMatch =
|
|
80
|
+
options.allowProjectAssemblyMismatch || parts.indexOf(projectName) > -1;
|
|
81
|
+
const include = isBin && isRelevantForCoverageTarget && isProjectMatch;
|
|
82
|
+
if (include) {
|
|
83
|
+
debug("include: " + filePath);
|
|
84
|
+
assemblies.push(file);
|
|
85
|
+
} else {
|
|
86
|
+
debug("ignore: " + filePath);
|
|
87
|
+
debug("isBin: " + isBin);
|
|
88
|
+
debug("isDebugOrAgnostic: " + isRelevantForCoverageTarget);
|
|
89
|
+
debug("isProjectMatch: " + isProjectMatch);
|
|
90
|
+
}
|
|
91
|
+
stream.emit("data", file);
|
|
92
|
+
},
|
|
93
|
+
function end() {
|
|
94
|
+
runCoverageWith(this, assemblies, options);
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
return stream;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function findLocalExactExecutable(options, what) {
|
|
101
|
+
const toolsFolder = path.join(process.cwd(), getToolsFolder()).toLowerCase();
|
|
102
|
+
return what.reduce((acc, cur) => {
|
|
103
|
+
if (acc || !options.exec[cur]) {
|
|
104
|
+
return acc;
|
|
105
|
+
}
|
|
106
|
+
const exe = trim(options.exec[cur], "\\s", '"', "'");
|
|
107
|
+
if (exe.toLowerCase().indexOf(toolsFolder) === 0) {
|
|
108
|
+
log.info(`preferring local tool: ${exe}`);
|
|
109
|
+
return exe;
|
|
110
|
+
}
|
|
111
|
+
return acc;
|
|
112
|
+
}, undefined);
|
|
113
|
+
}
|
|
114
|
+
function findExactExecutable(stream, options, what, deferLocal) {
|
|
115
|
+
if (!Array.isArray(what)) {
|
|
116
|
+
what = [what];
|
|
117
|
+
}
|
|
118
|
+
if (!deferLocal) {
|
|
119
|
+
const local = findLocalExactExecutable(options, what);
|
|
120
|
+
if (local) {
|
|
121
|
+
return local;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const resolved = what.reduce((acc, cur) => {
|
|
125
|
+
cur = findKeyInsensitive(options.exec, cur);
|
|
126
|
+
if (!options.exec[cur]) {
|
|
127
|
+
return acc;
|
|
128
|
+
}
|
|
129
|
+
const exe = trim(options.exec[cur], "\\s", '"', "'");
|
|
130
|
+
if (!fs.existsSync(exe)) {
|
|
131
|
+
fail(
|
|
132
|
+
stream,
|
|
133
|
+
`Can"t find executable for "${cur}" at provided path: "${
|
|
134
|
+
options.exec[cur]
|
|
135
|
+
}"`
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
return exe;
|
|
139
|
+
}, undefined);
|
|
140
|
+
return (
|
|
141
|
+
resolved ||
|
|
142
|
+
fail(
|
|
143
|
+
stream,
|
|
144
|
+
`Auto-detection of system-wide executables (${what.join(
|
|
145
|
+
","
|
|
146
|
+
)}) not implemented and local version not found. Please specify the exec.{tool} option(s) as required.`
|
|
147
|
+
)
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function findKeyInsensitive(obj, seekKey) {
|
|
152
|
+
return obj
|
|
153
|
+
? Object.keys(obj).filter(
|
|
154
|
+
k => k.toLowerCase() === seekKey.toLowerCase()
|
|
155
|
+
)[0] || seekKey
|
|
156
|
+
: seekKey;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function findCoverageTool(stream, options) {
|
|
160
|
+
return options.coverageTool
|
|
161
|
+
? findExactExecutable(stream, options, [options.coverageTool], true)
|
|
162
|
+
: findExactExecutable(stream, options, ["openCover", "dotCover" ]);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function findNunit(stream, options) {
|
|
166
|
+
return findExactExecutable(stream, options, "nunit");
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function fail(stream, msg) {
|
|
170
|
+
stream.emit("error", new gutil.PluginError(PLUGIN_NAME, msg));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function end(stream) {
|
|
174
|
+
stream.emit("end");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function trim() {
|
|
178
|
+
const args = Array.prototype.slice.call(arguments);
|
|
179
|
+
const source = args[0];
|
|
180
|
+
const replacements = args.slice(1).join(",");
|
|
181
|
+
const regex = new RegExp(
|
|
182
|
+
"^[" + replacements + "]+|[" + replacements + "]+$",
|
|
183
|
+
"g"
|
|
184
|
+
);
|
|
185
|
+
return source.replace(regex, "");
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function isNunit3(nunitRunner) {
|
|
189
|
+
return nunitRunner.indexOf("nunit3-") > -1;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function generateXmlOutputSwitchFor(nunitRunner, options) {
|
|
193
|
+
if ((options.nunitOptions || "").indexOf("/result:") > -1) {
|
|
194
|
+
debug(
|
|
195
|
+
`"/result" option already specified in nunitOptions("${
|
|
196
|
+
options.nunitOptions
|
|
197
|
+
}"), skipping generation`
|
|
198
|
+
);
|
|
199
|
+
return "";
|
|
200
|
+
}
|
|
201
|
+
const outFile = options.nunitOutput;
|
|
202
|
+
return isNunit3(nunitRunner)
|
|
203
|
+
? `/result:${outFile};format=nunit2`
|
|
204
|
+
: `/xml=${outFile}`;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function generateNoShadowFor(nunitRunner) {
|
|
208
|
+
return isNunit3(nunitRunner) ? "" : "/noshadow"; // default to not shadow in nunit3 & /noshadow deprecated
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function generatePlatformSwitchFor(nunitRunner, options) {
|
|
212
|
+
const isX86 =
|
|
213
|
+
options.x86 || (options.platform || options.architecture) === "x86";
|
|
214
|
+
return isNunit3(nunitRunner) && isX86 ? "/x86" : ""; // nunit 2 has separate runners; 3 has a switch
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function updateLabelsOptionFor(nunitOptions) {
|
|
218
|
+
if (nunitOptions.indexOf("labels:") > -1) {
|
|
219
|
+
return nunitOptions; // caller already updated for new labels= syntax
|
|
220
|
+
}
|
|
221
|
+
return nunitOptions.replace(/\/labels/, "/labels:Before");
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function quoted(str) {
|
|
225
|
+
return /[ "]/.test(str) ? `"${str.replace(/"/g, '""')}"` : str;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function generateAgentsLimitFor(nunit, options) {
|
|
229
|
+
const limit = options.agents;
|
|
230
|
+
return `--agents=${limit}`;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function runCoverageWith(stream, allAssemblies, options) {
|
|
234
|
+
const scopeAssemblies = [];
|
|
235
|
+
const testAssemblies = allAssemblies
|
|
236
|
+
.map(function (file) {
|
|
237
|
+
const replace = [
|
|
238
|
+
process.cwd() + "\\",
|
|
239
|
+
process.cwd().replace(/\\\\/g, "/") + "/"
|
|
240
|
+
];
|
|
241
|
+
return replace.reduce((acc, cur) => acc.replace(cur, ""), file.path);
|
|
242
|
+
})
|
|
243
|
+
.filter(function (file) {
|
|
244
|
+
return options.testAssemblyFilter(file) || !scopeAssemblies.push(file);
|
|
245
|
+
})
|
|
246
|
+
.map(function (file) {
|
|
247
|
+
return file.replace(/\\/g, "/");
|
|
248
|
+
});
|
|
249
|
+
if (testAssemblies.length === 0) {
|
|
250
|
+
return fail(
|
|
251
|
+
stream,
|
|
252
|
+
[
|
|
253
|
+
"No test assemblies defined",
|
|
254
|
+
"Hint: coverage will only be run on assemblies which are built as Debug (and reside in that folder)"
|
|
255
|
+
].join("\n")
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
options.testAssemblies = testAssemblies; // so other things can use this
|
|
259
|
+
const coverageToolExe = findCoverageTool(stream, options);
|
|
260
|
+
debug(`selected coverage tool exe: ${coverageToolExe}`);
|
|
261
|
+
const nunit = findNunit(stream, options);
|
|
262
|
+
debug("testAssemblies:", testAssemblies);
|
|
263
|
+
const q = quoteIfSpaced;
|
|
264
|
+
let nunitOptions = [
|
|
265
|
+
q(generateXmlOutputSwitchFor(nunit, options)),
|
|
266
|
+
q(generateNoShadowFor(nunit)),
|
|
267
|
+
q(generatePlatformSwitchFor(nunit, options)),
|
|
268
|
+
q(generateAgentsLimitFor(nunit, options)),
|
|
269
|
+
testAssemblies.map(quoted).join(" ")
|
|
270
|
+
].concat(q(updateLabelsOptionFor(options.nunitOptions).split(" ")));
|
|
271
|
+
debug("nunit options: ", nunitOptions);
|
|
272
|
+
const agents = parseInt(options.agents);
|
|
273
|
+
if (!isNaN(agents)) {
|
|
274
|
+
nunitOptions.push("--agents=" + agents);
|
|
275
|
+
}
|
|
276
|
+
nunitOptions = nunitOptions.join(" ");
|
|
277
|
+
|
|
278
|
+
const coverageToolName = grokCoverageToolNameFrom(options, coverageToolExe);
|
|
279
|
+
debug(`Running tool: ${coverageToolName}`);
|
|
280
|
+
const cliOptions = getCliOptionsFor(
|
|
281
|
+
stream,
|
|
282
|
+
coverageToolName,
|
|
283
|
+
options,
|
|
284
|
+
nunit,
|
|
285
|
+
nunitOptions
|
|
286
|
+
);
|
|
287
|
+
spawnCoverageTool(
|
|
288
|
+
stream,
|
|
289
|
+
coverageToolName,
|
|
290
|
+
coverageToolExe,
|
|
291
|
+
cliOptions,
|
|
292
|
+
options
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const commandLineOptionsGenerators = {
|
|
297
|
+
dotcover: getDotCoverOptionsFor,
|
|
298
|
+
opencover: getOpenCoverOptionsFor
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
const coverageSpawners = {
|
|
302
|
+
dotcover: spawnDotCover,
|
|
303
|
+
opencover: spawnOpenCover
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
function spawnDotCover(stream, coverageToolExe, cliOptions, globalOptions) {
|
|
307
|
+
const reportArgsFor = function(reportType) {
|
|
308
|
+
log.info("creating XML args");
|
|
309
|
+
return [
|
|
310
|
+
"report",
|
|
311
|
+
`/ReportType=${reportType}`,
|
|
312
|
+
`/Source=${quoted(globalOptions.coverageOutput)}`,
|
|
313
|
+
`/Output=${quoted(
|
|
314
|
+
globalOptions.coverageReportBase + "." + reportType.toLowerCase()
|
|
315
|
+
)}`
|
|
316
|
+
];
|
|
317
|
+
},
|
|
318
|
+
xmlArgs = reportArgsFor("XML"),
|
|
319
|
+
htmlArgs = reportArgsFor("HTML");
|
|
320
|
+
|
|
321
|
+
return spawn(coverageToolExe, cliOptions)
|
|
322
|
+
.then(() => {
|
|
323
|
+
log.info("creating XML report");
|
|
324
|
+
return spawn(coverageToolExe, xmlArgs);
|
|
325
|
+
})
|
|
326
|
+
.then(() => {
|
|
327
|
+
log.info("creating HTML report");
|
|
328
|
+
return spawn(coverageToolExe, htmlArgs);
|
|
329
|
+
})
|
|
330
|
+
.then(() => {
|
|
331
|
+
onCoverageComplete(stream);
|
|
332
|
+
})
|
|
333
|
+
.catch(err => handleCoverageFailure(stream, err, globalOptions));
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function stringify(err) {
|
|
337
|
+
if (err === undefined || err === null) {
|
|
338
|
+
return `(${err})`;
|
|
339
|
+
}
|
|
340
|
+
if (typeof err === "string") {
|
|
341
|
+
return err;
|
|
342
|
+
}
|
|
343
|
+
if (typeof err !== "object") {
|
|
344
|
+
return err.toString();
|
|
345
|
+
}
|
|
346
|
+
try {
|
|
347
|
+
return JSON.stringify(err);
|
|
348
|
+
} catch (e) {
|
|
349
|
+
return dumpTopLevel(err);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function dumpTopLevel(obj) {
|
|
354
|
+
const result = [];
|
|
355
|
+
for (let prop in obj) {
|
|
356
|
+
if (obj.hasOwnProperty(prop)) {
|
|
357
|
+
result.push(`${prop}: ${obj[prop]}`);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return `{\n\t${result.join("\n\t")}}`;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function logError(err) {
|
|
364
|
+
log.error(gutil.colors.red(stringify(err)));
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function handleCoverageFailure(stream, err) {
|
|
368
|
+
logError(" --- COVERAGE FAILS ---");
|
|
369
|
+
logError(err);
|
|
370
|
+
fail(stream, "coverage fails");
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function onCoverageComplete(stream) {
|
|
374
|
+
log.info("ending coverage successfully");
|
|
375
|
+
end(stream);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function findCaseInsensitiveUniqueEnvironmentVariables() {
|
|
379
|
+
// naive: last wins
|
|
380
|
+
return Object.keys(process.env).reduce(
|
|
381
|
+
(acc, cur) => {
|
|
382
|
+
const existing = Object.keys(acc).find(k => k.toLowerCase() === cur);
|
|
383
|
+
if (existing) {
|
|
384
|
+
acc[existing] = process.env[cur];
|
|
385
|
+
} else {
|
|
386
|
+
acc[cur] = process.env[cur];
|
|
387
|
+
}
|
|
388
|
+
return acc;
|
|
389
|
+
}, {});
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function spawnOpenCover(stream, exe, cliOptions, globalOptions) {
|
|
393
|
+
debug(`Running opencover:`);
|
|
394
|
+
debug(`${exe} ${cliOptions.join(" ")}`);
|
|
395
|
+
const env = findCaseInsensitiveUniqueEnvironmentVariables();
|
|
396
|
+
debug("setting open-cover env:", {
|
|
397
|
+
env
|
|
398
|
+
});
|
|
399
|
+
return spawn(exe, cliOptions, { env })
|
|
400
|
+
.then(() => onCoverageComplete(stream))
|
|
401
|
+
.catch(err => handleCoverageFailure(stream, err, globalOptions));
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
function generateOpenCoverFilter(prefix, namespaces) {
|
|
405
|
+
return namespaces
|
|
406
|
+
.reduce((acc, cur) => {
|
|
407
|
+
if (cur.indexOf("[") > -1) {
|
|
408
|
+
// this already has a module specification
|
|
409
|
+
acc.push(`${prefix}${cur}`);
|
|
410
|
+
} else {
|
|
411
|
+
acc.push(`${prefix}[*]${cur}`);
|
|
412
|
+
}
|
|
413
|
+
return acc;
|
|
414
|
+
}, [])
|
|
415
|
+
.join(" ");
|
|
416
|
+
}
|
|
417
|
+
function shouldFailOnError(options) {
|
|
418
|
+
return (options || {}).failOnError === undefined
|
|
419
|
+
? true
|
|
420
|
+
: !!options.failOnError;
|
|
421
|
+
}
|
|
422
|
+
function quoteIfSpaced(str, quote) {
|
|
423
|
+
if (str.indexOf(" ") === -1) {
|
|
424
|
+
return str;
|
|
425
|
+
}
|
|
426
|
+
quote = quote || "\"";
|
|
427
|
+
return `${quote}${str}${quote}`;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function getOpenCoverOptionsFor(options, nunit, nunitOptions) {
|
|
431
|
+
const exclude =
|
|
432
|
+
options.exclude && options.exclude.length ? options.exclude : ["*.Tests"],
|
|
433
|
+
failOnError = shouldFailOnError(options),
|
|
434
|
+
excludeFilter = generateOpenCoverFilter("-", exclude);
|
|
435
|
+
|
|
436
|
+
const result = [
|
|
437
|
+
`"-target:${nunit}"`,
|
|
438
|
+
`"-targetargs:${nunitOptions}"`,
|
|
439
|
+
`"-targetdir:${process.cwd()}"`, // TODO: test me please
|
|
440
|
+
`"-output:${options.coverageReportBase + ".xml"}"`,
|
|
441
|
+
`-filter:"+[*]* ${excludeFilter}"`, // TODO: embetterment
|
|
442
|
+
`-register`,
|
|
443
|
+
`-mergebyhash`,
|
|
444
|
+
`"-searchdirs:${getUniqueDirsFrom(options.testAssemblies)}"`
|
|
445
|
+
];
|
|
446
|
+
if (failOnError) {
|
|
447
|
+
result.push("-returntargetcode:0");
|
|
448
|
+
}
|
|
449
|
+
return result;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
function getUniqueDirsFrom(filePaths) {
|
|
453
|
+
return filePaths
|
|
454
|
+
.reduce((acc, cur) => {
|
|
455
|
+
const dirName = path.dirname(cur);
|
|
456
|
+
const required = !acc.filter(p => cur === p)[0];
|
|
457
|
+
if (required) {
|
|
458
|
+
acc.push(quoteIfSpaced(dirName, "\"\""));
|
|
459
|
+
}
|
|
460
|
+
return acc;
|
|
461
|
+
}, [])
|
|
462
|
+
.join(",");
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function spawnCoverageTool(
|
|
466
|
+
stream,
|
|
467
|
+
toolName,
|
|
468
|
+
toolExe,
|
|
469
|
+
cliOptions,
|
|
470
|
+
globalOptions
|
|
471
|
+
) {
|
|
472
|
+
const spawner = coverageSpawners[toolName];
|
|
473
|
+
debug({
|
|
474
|
+
toolName,
|
|
475
|
+
toolExe,
|
|
476
|
+
cliOptions,
|
|
477
|
+
globalOptions
|
|
478
|
+
});
|
|
479
|
+
return spawner
|
|
480
|
+
? spawner(stream, toolExe, cliOptions, globalOptions)
|
|
481
|
+
: unsupportedTool(stream, toolName);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
function unsupportedTool(stream, toolName) {
|
|
485
|
+
fail(stream, `Coverage tool "${toolName}" not supported`);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
function getCliOptionsFor(
|
|
489
|
+
stream,
|
|
490
|
+
coverageToolName,
|
|
491
|
+
options,
|
|
492
|
+
nunit,
|
|
493
|
+
nunitOptions
|
|
494
|
+
) {
|
|
495
|
+
const generator = commandLineOptionsGenerators[coverageToolName];
|
|
496
|
+
return generator
|
|
497
|
+
? generator(options, nunit, nunitOptions)
|
|
498
|
+
: unsupportedTool(stream, coverageToolName);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
function getToolNameForExe(options, toolExe) {
|
|
502
|
+
return (
|
|
503
|
+
Object.keys(options.exec).filter(k => toolExe === options.exec[k])[0] || ""
|
|
504
|
+
).toLowerCase();
|
|
505
|
+
}
|
|
506
|
+
function grokCoverageToolNameFrom(options, toolExe) {
|
|
507
|
+
return getToolNameForExe(options, toolExe) || options.coverageTool;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
function getDotCoverOptionsFor(options, nunit, nunitOptions) {
|
|
511
|
+
const filterJoin = ";-:",
|
|
512
|
+
scopeAssemblies = options.testAssemblies;
|
|
513
|
+
|
|
514
|
+
let filters = options.baseFilters;
|
|
515
|
+
if (options.exclude.length) {
|
|
516
|
+
filters = [filters, options.exclude.join(filterJoin)].join(filterJoin);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
const dotCoverOptions = [
|
|
520
|
+
"cover",
|
|
521
|
+
`/TargetExecutable=${quoted(nunit)}`,
|
|
522
|
+
`/AnalyseTargetArguments=False`,
|
|
523
|
+
`/Output=${quoted(options.coverageOutput)}`,
|
|
524
|
+
`/Filters=${quoted(filters)}`,
|
|
525
|
+
`/ProcessFilters=-:sqlservr.exe`,
|
|
526
|
+
`/TargetWorkingDir=${quoted(process.cwd())}`,
|
|
527
|
+
`/TargetArguments=${quoted(nunitOptions)}`
|
|
528
|
+
];
|
|
529
|
+
if (scopeAssemblies.length) {
|
|
530
|
+
dotCoverOptions.push(`/Scope=${quoted(scopeAssemblies.join(";"))}`);
|
|
531
|
+
}
|
|
532
|
+
log.info("running testing with coverage...");
|
|
533
|
+
log.info("running dotcover with: " + dotCoverOptions.join(" "));
|
|
534
|
+
return dotCoverOptions;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
module.exports = dotCover;
|