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.
Files changed (201) hide show
  1. package/LICENSE +10 -0
  2. package/README.md +260 -0
  3. package/gulp-tasks/.editorconfig +8 -0
  4. package/gulp-tasks/.git +1 -0
  5. package/gulp-tasks/.gitignore +9 -0
  6. package/gulp-tasks/.gitmodules +0 -0
  7. package/gulp-tasks/LICENSE +24 -0
  8. package/gulp-tasks/README.md +144 -0
  9. package/gulp-tasks/build.js +135 -0
  10. package/gulp-tasks/clean.js +37 -0
  11. package/gulp-tasks/cover-dotnet.js +56 -0
  12. package/gulp-tasks/default-report-generator.js +51 -0
  13. package/gulp-tasks/default-tools-installer.js +33 -0
  14. package/gulp-tasks/default.js +17 -0
  15. package/gulp-tasks/dotnet-publish.js +23 -0
  16. package/gulp-tasks/generate-reports.js +7 -0
  17. package/gulp-tasks/get-local-nuget.js +16 -0
  18. package/gulp-tasks/git-submodules.js +83 -0
  19. package/gulp-tasks/increment-package-json-version.js +12 -0
  20. package/gulp-tasks/increment-package-json-version.ts +17 -0
  21. package/gulp-tasks/install-tools.js +24 -0
  22. package/gulp-tasks/modules/add-stream-on-any-handler.js +31 -0
  23. package/gulp-tasks/modules/alter-package-json-version.js +64 -0
  24. package/gulp-tasks/modules/alter-package-json-version.ts +113 -0
  25. package/gulp-tasks/modules/are-all-dotnet-core.js +96 -0
  26. package/gulp-tasks/modules/ask.js +31 -0
  27. package/gulp-tasks/modules/ask.ts +41 -0
  28. package/gulp-tasks/modules/collect-files.js +15 -0
  29. package/gulp-tasks/modules/collect-files.ts +16 -0
  30. package/gulp-tasks/modules/config-generator.js +10 -0
  31. package/gulp-tasks/modules/defaults.js +9 -0
  32. package/gulp-tasks/modules/download-nuget.js +104 -0
  33. package/gulp-tasks/modules/ensure-folder-exists.js +21 -0
  34. package/gulp-tasks/modules/env-helpers.js +49 -0
  35. package/gulp-tasks/modules/env-helpers.ts +67 -0
  36. package/gulp-tasks/modules/env.js +364 -0
  37. package/gulp-tasks/modules/exec.js +257 -0
  38. package/gulp-tasks/modules/exec.ts +346 -0
  39. package/gulp-tasks/modules/fail-after.js +30 -0
  40. package/gulp-tasks/modules/fail-after.ts +34 -0
  41. package/gulp-tasks/modules/fallback.js +6 -0
  42. package/gulp-tasks/modules/find-dirs.js +39 -0
  43. package/gulp-tasks/modules/find-local-nuget.js +42 -0
  44. package/gulp-tasks/modules/find-npm-base.js +42 -0
  45. package/gulp-tasks/modules/fs.js +79 -0
  46. package/gulp-tasks/modules/gather-paths.js +23 -0
  47. package/gulp-tasks/modules/gather-paths.ts +29 -0
  48. package/gulp-tasks/modules/generate-env-help-for.js +30 -0
  49. package/gulp-tasks/modules/get-tools-folder.js +12 -0
  50. package/gulp-tasks/modules/git-push-tags.js +33 -0
  51. package/gulp-tasks/modules/git-push-tags.ts +42 -0
  52. package/gulp-tasks/modules/git-push.js +51 -0
  53. package/gulp-tasks/modules/git-tag.js +36 -0
  54. package/gulp-tasks/modules/gulp-dotnetcover.js +537 -0
  55. package/gulp-tasks/modules/gulp-git-tag-from-csproj.js +50 -0
  56. package/gulp-tasks/modules/gulp-git-tag-from-csproj.ts +71 -0
  57. package/gulp-tasks/modules/gulp-git-tag-from-package-nuspec.js +55 -0
  58. package/gulp-tasks/modules/gulp-increment-nuget-package-dependency-version.js +40 -0
  59. package/gulp-tasks/modules/gulp-increment-nuget-package-version.js +87 -0
  60. package/gulp-tasks/modules/gulp-increment-nuget-package-version.ts +122 -0
  61. package/gulp-tasks/modules/gulp-msbuild.js +1 -0
  62. package/gulp-tasks/modules/gulp-npm-run.js +40 -0
  63. package/gulp-tasks/modules/gulp-npm-run.ts +52 -0
  64. package/gulp-tasks/modules/gulp-nuget-pack.js +168 -0
  65. package/gulp-tasks/modules/gulp-nuget-restore.js +106 -0
  66. package/gulp-tasks/modules/gulp-nunit-runner/.jshintrc +5 -0
  67. package/gulp-tasks/modules/gulp-nunit-runner/.npmignore +16 -0
  68. package/gulp-tasks/modules/gulp-nunit-runner/LICENSE +21 -0
  69. package/gulp-tasks/modules/gulp-nunit-runner/README.md +300 -0
  70. package/gulp-tasks/modules/gulp-nunit-runner/index.js +1 -0
  71. package/gulp-tasks/modules/gulp-nunit-runner/lib/index.js +205 -0
  72. package/gulp-tasks/modules/gulp-nunit-runner/lib/teamcity.js +86 -0
  73. package/gulp-tasks/modules/gulp-purge.js +88 -0
  74. package/gulp-tasks/modules/gulp-util.js +5 -0
  75. package/gulp-tasks/modules/gulp-version.js +8 -0
  76. package/gulp-tasks/modules/gulp-with-help.js +1 -0
  77. package/gulp-tasks/modules/gulp-xbuild.js +62 -0
  78. package/gulp-tasks/modules/gulp.js +92 -0
  79. package/gulp-tasks/modules/http-downloader.js +113 -0
  80. package/gulp-tasks/modules/import-npm-tasks.js +33 -0
  81. package/gulp-tasks/modules/increment-version-string.js +18 -0
  82. package/gulp-tasks/modules/increment-version.js +30 -0
  83. package/gulp-tasks/modules/increment-version.ts +41 -0
  84. package/gulp-tasks/modules/install-local-tools.js +122 -0
  85. package/gulp-tasks/modules/load-xml-file.js +12 -0
  86. package/gulp-tasks/modules/load-xml-file.ts +15 -0
  87. package/gulp-tasks/modules/log-config.js +31 -0
  88. package/gulp-tasks/modules/log.js +142 -0
  89. package/gulp-tasks/modules/longest-string-length.js +13 -0
  90. package/gulp-tasks/modules/looks-like-a-promise.js +11 -0
  91. package/gulp-tasks/modules/ls-r.js +52 -0
  92. package/gulp-tasks/modules/multi-split.js +29 -0
  93. package/gulp-tasks/modules/net-framework-test-assembly-filter.js +45 -0
  94. package/gulp-tasks/modules/nuget-push.js +66 -0
  95. package/gulp-tasks/modules/nuget-update-self.js +9 -0
  96. package/gulp-tasks/modules/nuget.js +8 -0
  97. package/gulp-tasks/modules/nuget.ts +14 -0
  98. package/gulp-tasks/modules/pad-left.js +4 -0
  99. package/gulp-tasks/modules/pad-right.js +4 -0
  100. package/gulp-tasks/modules/pad.js +25 -0
  101. package/gulp-tasks/modules/parse-xml-string.js +5 -0
  102. package/gulp-tasks/modules/parse-xml-string.ts +6 -0
  103. package/gulp-tasks/modules/parse-xml.js +14 -0
  104. package/gulp-tasks/modules/parse-xml.ts +15 -0
  105. package/gulp-tasks/modules/path-unquote.js +6 -0
  106. package/gulp-tasks/modules/promisify-function.js +19 -0
  107. package/gulp-tasks/modules/promisify-function.ts +18 -0
  108. package/gulp-tasks/modules/promisify-stream.js +73 -0
  109. package/gulp-tasks/modules/promisify.js +1 -0
  110. package/gulp-tasks/modules/quote-if-required.js +14 -0
  111. package/gulp-tasks/modules/read-all-git-branches.js +10 -0
  112. package/gulp-tasks/modules/read-all-git-branches.ts +13 -0
  113. package/gulp-tasks/modules/read-all-git-remotes.js +36 -0
  114. package/gulp-tasks/modules/read-all-git-remotes.ts +44 -0
  115. package/gulp-tasks/modules/read-csproj-package-version.js +16 -0
  116. package/gulp-tasks/modules/read-csproj-package-version.ts +26 -0
  117. package/gulp-tasks/modules/read-csproj-version.js +16 -0
  118. package/gulp-tasks/modules/read-csproj-version.ts +26 -0
  119. package/gulp-tasks/modules/read-current-git-branch.js +12 -0
  120. package/gulp-tasks/modules/read-current-git-branch.ts +16 -0
  121. package/gulp-tasks/modules/read-git-commit-delta-count.js +21 -0
  122. package/gulp-tasks/modules/read-git-commit-delta-count.ts +33 -0
  123. package/gulp-tasks/modules/read-git-info.js +28 -0
  124. package/gulp-tasks/modules/read-git-info.ts +31 -0
  125. package/gulp-tasks/modules/read-git-remote.js +17 -0
  126. package/gulp-tasks/modules/read-git-remote.ts +23 -0
  127. package/gulp-tasks/modules/read-last-fetch-time.js +21 -0
  128. package/gulp-tasks/modules/read-last-fetch-time.ts +17 -0
  129. package/gulp-tasks/modules/read-main-branch-name.js +48 -0
  130. package/gulp-tasks/modules/read-main-branch-name.ts +76 -0
  131. package/gulp-tasks/modules/read-nuspec-version.js +14 -0
  132. package/gulp-tasks/modules/read-nuspec-version.ts +22 -0
  133. package/gulp-tasks/modules/read-package-json.js +16 -0
  134. package/gulp-tasks/modules/read-package-json.ts +22 -0
  135. package/gulp-tasks/modules/read-package-version.js +8 -0
  136. package/gulp-tasks/modules/read-package-version.ts +10 -0
  137. package/gulp-tasks/modules/read-text-file.js +14 -0
  138. package/gulp-tasks/modules/read-text-file.ts +14 -0
  139. package/gulp-tasks/modules/reduce-gulp-noise.js +34 -0
  140. package/gulp-tasks/modules/register-environment-variables.js +526 -0
  141. package/gulp-tasks/modules/require-module.js +28 -0
  142. package/gulp-tasks/modules/resolve-git-branch.js +11 -0
  143. package/gulp-tasks/modules/resolve-git-branch.ts +13 -0
  144. package/gulp-tasks/modules/resolve-git-remote.js +11 -0
  145. package/gulp-tasks/modules/resolve-git-remote.ts +13 -0
  146. package/gulp-tasks/modules/resolve-masks.js +47 -0
  147. package/gulp-tasks/modules/resolve-nuget.js +135 -0
  148. package/gulp-tasks/modules/resolve-test-masks.js +10 -0
  149. package/gulp-tasks/modules/rewrite-file.js +26 -0
  150. package/gulp-tasks/modules/rewrite-file.ts +34 -0
  151. package/gulp-tasks/modules/rimraf.js +21 -0
  152. package/gulp-tasks/modules/rimraf.ts +31 -0
  153. package/gulp-tasks/modules/run-sequence.js +16 -0
  154. package/gulp-tasks/modules/safe-git.js +23 -0
  155. package/gulp-tasks/modules/safe-git.ts +23 -0
  156. package/gulp-tasks/modules/seed.js +12 -0
  157. package/gulp-tasks/modules/set-task-name.js +9 -0
  158. package/gulp-tasks/modules/sleep.js +5 -0
  159. package/gulp-tasks/modules/spawn-nuget.js +13 -0
  160. package/gulp-tasks/modules/spawn.js +103 -0
  161. package/gulp-tasks/modules/split-path.js +3 -0
  162. package/gulp-tasks/modules/stat.js +8 -0
  163. package/gulp-tasks/modules/status.js +57 -0
  164. package/gulp-tasks/modules/status.ts +71 -0
  165. package/gulp-tasks/modules/test-path.js +3 -0
  166. package/gulp-tasks/modules/testutil-finder.js +176 -0
  167. package/gulp-tasks/modules/throw-if-no-files.js +15 -0
  168. package/gulp-tasks/modules/uniq.js +6 -0
  169. package/gulp-tasks/modules/uniq.ts +5 -0
  170. package/gulp-tasks/modules/verify-exe.js +17 -0
  171. package/gulp-tasks/modules/version-reading-shared.js +12 -0
  172. package/gulp-tasks/modules/version-reading-shared.ts +16 -0
  173. package/gulp-tasks/modules/write-text-file.js +10 -0
  174. package/gulp-tasks/modules/zarro-error.js +6 -0
  175. package/gulp-tasks/nuget-restore.js +57 -0
  176. package/gulp-tasks/pack.js +118 -0
  177. package/gulp-tasks/purge.js +94 -0
  178. package/gulp-tasks/release-npm.js +58 -0
  179. package/gulp-tasks/release-npm.ts +81 -0
  180. package/gulp-tasks/start/_package.json +39 -0
  181. package/gulp-tasks/start/gulpfile.js +204 -0
  182. package/gulp-tasks/start/update-starter-packages.js +63 -0
  183. package/gulp-tasks/test-dotnet.js +195 -0
  184. package/gulp-tasks/update-git-submodules.js +11 -0
  185. package/gulp-tasks/update-git-submodules.ts +29 -0
  186. package/gulp-tasks/update-self.js +65 -0
  187. package/gulp-tasks/update-self.ts +88 -0
  188. package/gulp-tasks/verify-up-to-date.js +77 -0
  189. package/gulp-tasks/verify-up-to-date.ts +119 -0
  190. package/index-modules/contains-any.js +31 -0
  191. package/index-modules/gather-args.js +21 -0
  192. package/index-modules/handlers/help.js +17 -0
  193. package/index-modules/handlers/init.js +57 -0
  194. package/index-modules/handlers/invoke-gulp.js +111 -0
  195. package/index-modules/handlers/show-env.js +46 -0
  196. package/index-modules/is-dir.js +6 -0
  197. package/index-modules/is-file.js +6 -0
  198. package/index.js +53 -0
  199. package/package.json +96 -0
  200. package/tsconfig.json +66 -0
  201. 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;