azure-pipelines-task-lib 3.2.0 → 4.0.0-preview

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/task.js CHANGED
@@ -1,1915 +1,2003 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.updateReleaseName = exports.addBuildTag = exports.updateBuildNumber = exports.uploadBuildLog = exports.associateArtifact = exports.uploadArtifact = exports.logIssue = exports.logDetail = exports.setProgress = exports.setEndpoint = exports.addAttachment = exports.uploadSummary = exports.prependPath = exports.uploadFile = exports.CodeCoverageEnabler = exports.CodeCoveragePublisher = exports.TestPublisher = exports.getHttpCertConfiguration = exports.getHttpProxyConfiguration = exports.findMatch = exports.filter = exports.match = exports.tool = exports.execSync = exports.exec = exports.rmRF = exports.legacyFindFiles = exports.find = exports.retry = exports.mv = exports.cp = exports.ls = exports.which = exports.resolve = exports.mkdirP = exports.popd = exports.pushd = exports.cd = exports.checkPath = exports.cwd = exports.getPlatform = exports.osType = exports.writeFile = exports.exist = exports.stats = exports.debug = exports.error = exports.warning = exports.command = exports.setTaskVariable = exports.getTaskVariable = exports.getSecureFileTicket = exports.getSecureFileName = exports.getEndpointAuthorization = exports.getEndpointAuthorizationParameter = exports.getEndpointAuthorizationScheme = exports.getEndpointDataParameter = exports.getEndpointUrl = exports.getPathInput = exports.filePathSupplied = exports.getDelimitedInput = exports.getBoolInput = exports.getInput = exports.setSecret = exports.setVariable = exports.getVariables = exports.assertAgent = exports.getVariable = exports.loc = exports.setResourcePath = exports.setResult = exports.setErrStream = exports.setStdStream = exports.Platform = exports.FieldType = exports.ArtifactType = exports.IssueType = exports.TaskState = exports.TaskResult = void 0;
4
- var shell = require("shelljs");
5
- var childProcess = require("child_process");
6
- var fs = require("fs");
7
- var path = require("path");
8
- var os = require("os");
9
- var minimatch = require("minimatch");
10
- var im = require("./internal");
11
- var tcm = require("./taskcommand");
12
- var trm = require("./toolrunner");
13
- var semver = require("semver");
14
- var TaskResult;
15
- (function (TaskResult) {
16
- TaskResult[TaskResult["Succeeded"] = 0] = "Succeeded";
17
- TaskResult[TaskResult["SucceededWithIssues"] = 1] = "SucceededWithIssues";
18
- TaskResult[TaskResult["Failed"] = 2] = "Failed";
19
- TaskResult[TaskResult["Cancelled"] = 3] = "Cancelled";
20
- TaskResult[TaskResult["Skipped"] = 4] = "Skipped";
21
- })(TaskResult = exports.TaskResult || (exports.TaskResult = {}));
22
- var TaskState;
23
- (function (TaskState) {
24
- TaskState[TaskState["Unknown"] = 0] = "Unknown";
25
- TaskState[TaskState["Initialized"] = 1] = "Initialized";
26
- TaskState[TaskState["InProgress"] = 2] = "InProgress";
27
- TaskState[TaskState["Completed"] = 3] = "Completed";
28
- })(TaskState = exports.TaskState || (exports.TaskState = {}));
29
- var IssueType;
30
- (function (IssueType) {
31
- IssueType[IssueType["Error"] = 0] = "Error";
32
- IssueType[IssueType["Warning"] = 1] = "Warning";
33
- })(IssueType = exports.IssueType || (exports.IssueType = {}));
34
- var ArtifactType;
35
- (function (ArtifactType) {
36
- ArtifactType[ArtifactType["Container"] = 0] = "Container";
37
- ArtifactType[ArtifactType["FilePath"] = 1] = "FilePath";
38
- ArtifactType[ArtifactType["VersionControl"] = 2] = "VersionControl";
39
- ArtifactType[ArtifactType["GitRef"] = 3] = "GitRef";
40
- ArtifactType[ArtifactType["TfvcLabel"] = 4] = "TfvcLabel";
41
- })(ArtifactType = exports.ArtifactType || (exports.ArtifactType = {}));
42
- var FieldType;
43
- (function (FieldType) {
44
- FieldType[FieldType["AuthParameter"] = 0] = "AuthParameter";
45
- FieldType[FieldType["DataParameter"] = 1] = "DataParameter";
46
- FieldType[FieldType["Url"] = 2] = "Url";
47
- })(FieldType = exports.FieldType || (exports.FieldType = {}));
48
- /** Platforms supported by our build agent */
49
- var Platform;
50
- (function (Platform) {
51
- Platform[Platform["Windows"] = 0] = "Windows";
52
- Platform[Platform["MacOS"] = 1] = "MacOS";
53
- Platform[Platform["Linux"] = 2] = "Linux";
54
- })(Platform = exports.Platform || (exports.Platform = {}));
55
- //-----------------------------------------------------
56
- // General Helpers
57
- //-----------------------------------------------------
58
- exports.setStdStream = im._setStdStream;
59
- exports.setErrStream = im._setErrStream;
60
- //-----------------------------------------------------
61
- // Results
62
- //-----------------------------------------------------
63
- /**
64
- * Sets the result of the task.
65
- * Execution will continue.
66
- * If not set, task will be Succeeded.
67
- * If multiple calls are made to setResult the most pessimistic call wins (Failed) regardless of the order of calls.
68
- *
69
- * @param result TaskResult enum of Succeeded, SucceededWithIssues, Failed, Cancelled or Skipped.
70
- * @param message A message which will be logged as an error issue if the result is Failed.
71
- * @param done Optional. Instructs the agent the task is done. This is helpful when child processes
72
- * may still be running and prevent node from fully exiting. This argument is supported
73
- * from agent version 2.142.0 or higher (otherwise will no-op).
74
- * @returns void
75
- */
76
- function setResult(result, message, done) {
77
- exports.debug('task result: ' + TaskResult[result]);
78
- // add an error issue
79
- if (result == TaskResult.Failed && message) {
80
- exports.error(message);
81
- }
82
- else if (result == TaskResult.SucceededWithIssues && message) {
83
- exports.warning(message);
84
- }
85
- // task.complete
86
- var properties = { 'result': TaskResult[result] };
87
- if (done) {
88
- properties['done'] = 'true';
89
- }
90
- exports.command('task.complete', properties, message);
91
- }
92
- exports.setResult = setResult;
93
- //
94
- // Catching all exceptions
95
- //
96
- process.on('uncaughtException', function (err) {
97
- setResult(TaskResult.Failed, exports.loc('LIB_UnhandledEx', err.message));
98
- });
99
- //-----------------------------------------------------
100
- // Loc Helpers
101
- //-----------------------------------------------------
102
- exports.setResourcePath = im._setResourcePath;
103
- exports.loc = im._loc;
104
- //-----------------------------------------------------
105
- // Input Helpers
106
- //-----------------------------------------------------
107
- exports.getVariable = im._getVariable;
108
- /**
109
- * Asserts the agent version is at least the specified minimum.
110
- *
111
- * @param minimum minimum version version - must be 2.104.1 or higher
112
- */
113
- function assertAgent(minimum) {
114
- if (semver.lt(minimum, '2.104.1')) {
115
- throw new Error('assertAgent() requires the parameter to be 2.104.1 or higher');
116
- }
117
- var agent = exports.getVariable('Agent.Version');
118
- if (agent && semver.lt(agent, minimum)) {
119
- throw new Error("Agent version " + minimum + " or higher is required");
120
- }
121
- }
122
- exports.assertAgent = assertAgent;
123
- /**
124
- * Gets a snapshot of the current state of all job variables available to the task.
125
- * Requires a 2.104.1 agent or higher for full functionality.
126
- *
127
- * Limitations on an agent prior to 2.104.1:
128
- * 1) The return value does not include all public variables. Only public variables
129
- * that have been added using setVariable are returned.
130
- * 2) The name returned for each secret variable is the formatted environment variable
131
- * name, not the actual variable name (unless it was set explicitly at runtime using
132
- * setVariable).
133
- *
134
- * @returns VariableInfo[]
135
- */
136
- function getVariables() {
137
- return Object.keys(im._knownVariableMap)
138
- .map(function (key) {
139
- var info = im._knownVariableMap[key];
140
- return { name: info.name, value: exports.getVariable(info.name), secret: info.secret };
141
- });
142
- }
143
- exports.getVariables = getVariables;
144
- /**
145
- * Sets a variable which will be available to subsequent tasks as well.
146
- *
147
- * @param name name of the variable to set
148
- * @param val value to set
149
- * @param secret whether variable is secret. Multi-line secrets are not allowed. Optional, defaults to false
150
- * @param isOutput whether variable is an output variable. Optional, defaults to false
151
- * @returns void
152
- */
153
- function setVariable(name, val, secret, isOutput) {
154
- if (secret === void 0) { secret = false; }
155
- if (isOutput === void 0) { isOutput = false; }
156
- // once a secret always a secret
157
- var key = im._getVariableKey(name);
158
- if (im._knownVariableMap.hasOwnProperty(key)) {
159
- secret = secret || im._knownVariableMap[key].secret;
160
- }
161
- // store the value
162
- var varValue = val || '';
163
- exports.debug('set ' + name + '=' + (secret && varValue ? '********' : varValue));
164
- if (secret) {
165
- if (varValue && varValue.match(/\r|\n/) && ("" + process.env['SYSTEM_UNSAFEALLOWMULTILINESECRET']).toUpperCase() != 'TRUE') {
166
- throw new Error(exports.loc('LIB_MultilineSecret'));
167
- }
168
- im._vault.storeSecret('SECRET_' + key, varValue);
169
- delete process.env[key];
170
- }
171
- else {
172
- process.env[key] = varValue;
173
- }
174
- // store the metadata
175
- im._knownVariableMap[key] = { name: name, secret: secret };
176
- // write the setvariable command
177
- exports.command('task.setvariable', { 'variable': name || '', isOutput: (isOutput || false).toString(), 'issecret': (secret || false).toString() }, varValue);
178
- }
179
- exports.setVariable = setVariable;
180
- /**
181
- * Registers a value with the logger, so the value will be masked from the logs. Multi-line secrets are not allowed.
182
- *
183
- * @param val value to register
184
- */
185
- function setSecret(val) {
186
- if (val) {
187
- if (val.match(/\r|\n/) && ("" + process.env['SYSTEM_UNSAFEALLOWMULTILINESECRET']).toUpperCase() !== 'TRUE') {
188
- throw new Error(exports.loc('LIB_MultilineSecret'));
189
- }
190
- exports.command('task.setsecret', {}, val);
191
- }
192
- }
193
- exports.setSecret = setSecret;
194
- /**
195
- * Gets the value of an input.
196
- * If required is true and the value is not set, it will throw.
197
- *
198
- * @param name name of the input to get
199
- * @param required whether input is required. optional, defaults to false
200
- * @returns string
201
- */
202
- function getInput(name, required) {
203
- var inval = im._vault.retrieveSecret('INPUT_' + im._getVariableKey(name));
204
- if (required && !inval) {
205
- throw new Error(exports.loc('LIB_InputRequired', name));
206
- }
207
- exports.debug(name + '=' + inval);
208
- return inval;
209
- }
210
- exports.getInput = getInput;
211
- /**
212
- * Gets the value of an input and converts to a bool. Convenience.
213
- * If required is true and the value is not set, it will throw.
214
- * If required is false and the value is not set, returns false.
215
- *
216
- * @param name name of the bool input to get
217
- * @param required whether input is required. optional, defaults to false
218
- * @returns boolean
219
- */
220
- function getBoolInput(name, required) {
221
- return (getInput(name, required) || '').toUpperCase() == "TRUE";
222
- }
223
- exports.getBoolInput = getBoolInput;
224
- /**
225
- * Gets the value of an input and splits the value using a delimiter (space, comma, etc).
226
- * Empty values are removed. This function is useful for splitting an input containing a simple
227
- * list of items - such as build targets.
228
- * IMPORTANT: Do not use this function for splitting additional args! Instead use argString(), which
229
- * follows normal argument splitting rules and handles values encapsulated by quotes.
230
- * If required is true and the value is not set, it will throw.
231
- *
232
- * @param name name of the input to get
233
- * @param delim delimiter to split on
234
- * @param required whether input is required. optional, defaults to false
235
- * @returns string[]
236
- */
237
- function getDelimitedInput(name, delim, required) {
238
- var inputVal = getInput(name, required);
239
- if (!inputVal) {
240
- return [];
241
- }
242
- var result = [];
243
- inputVal.split(delim).forEach(function (x) {
244
- if (x) {
245
- result.push(x);
246
- }
247
- });
248
- return result;
249
- }
250
- exports.getDelimitedInput = getDelimitedInput;
251
- /**
252
- * Checks whether a path inputs value was supplied by the user
253
- * File paths are relative with a picker, so an empty path is the root of the repo.
254
- * Useful if you need to condition work (like append an arg) if a value was supplied
255
- *
256
- * @param name name of the path input to check
257
- * @returns boolean
258
- */
259
- function filePathSupplied(name) {
260
- // normalize paths
261
- var pathValue = this.resolve(this.getPathInput(name) || '');
262
- var repoRoot = this.resolve(exports.getVariable('build.sourcesDirectory') || exports.getVariable('system.defaultWorkingDirectory') || '');
263
- var supplied = pathValue !== repoRoot;
264
- exports.debug(name + 'path supplied :' + supplied);
265
- return supplied;
266
- }
267
- exports.filePathSupplied = filePathSupplied;
268
- /**
269
- * Gets the value of a path input
270
- * It will be quoted for you if it isn't already and contains spaces
271
- * If required is true and the value is not set, it will throw.
272
- * If check is true and the path does not exist, it will throw.
273
- *
274
- * @param name name of the input to get
275
- * @param required whether input is required. optional, defaults to false
276
- * @param check whether path is checked. optional, defaults to false
277
- * @returns string
278
- */
279
- function getPathInput(name, required, check) {
280
- var inval = getInput(name, required);
281
- if (inval) {
282
- if (check) {
283
- exports.checkPath(inval, name);
284
- }
285
- }
286
- return inval;
287
- }
288
- exports.getPathInput = getPathInput;
289
- //-----------------------------------------------------
290
- // Endpoint Helpers
291
- //-----------------------------------------------------
292
- /**
293
- * Gets the url for a service endpoint
294
- * If the url was not set and is not optional, it will throw.
295
- *
296
- * @param id name of the service endpoint
297
- * @param optional whether the url is optional
298
- * @returns string
299
- */
300
- function getEndpointUrl(id, optional) {
301
- var urlval = process.env['ENDPOINT_URL_' + id];
302
- if (!optional && !urlval) {
303
- throw new Error(exports.loc('LIB_EndpointNotExist', id));
304
- }
305
- exports.debug(id + '=' + urlval);
306
- return urlval;
307
- }
308
- exports.getEndpointUrl = getEndpointUrl;
309
- /*
310
- * Gets the endpoint data parameter value with specified key for a service endpoint
311
- * If the endpoint data parameter was not set and is not optional, it will throw.
312
- *
313
- * @param id name of the service endpoint
314
- * @param key of the parameter
315
- * @param optional whether the endpoint data is optional
316
- * @returns {string} value of the endpoint data parameter
317
- */
318
- function getEndpointDataParameter(id, key, optional) {
319
- var dataParamVal = process.env['ENDPOINT_DATA_' + id + '_' + key.toUpperCase()];
320
- if (!optional && !dataParamVal) {
321
- throw new Error(exports.loc('LIB_EndpointDataNotExist', id, key));
322
- }
323
- exports.debug(id + ' data ' + key + ' = ' + dataParamVal);
324
- return dataParamVal;
325
- }
326
- exports.getEndpointDataParameter = getEndpointDataParameter;
327
- /**
328
- * Gets the endpoint authorization scheme for a service endpoint
329
- * If the endpoint authorization scheme is not set and is not optional, it will throw.
330
- *
331
- * @param id name of the service endpoint
332
- * @param optional whether the endpoint authorization scheme is optional
333
- * @returns {string} value of the endpoint authorization scheme
334
- */
335
- function getEndpointAuthorizationScheme(id, optional) {
336
- var authScheme = im._vault.retrieveSecret('ENDPOINT_AUTH_SCHEME_' + id);
337
- if (!optional && !authScheme) {
338
- throw new Error(exports.loc('LIB_EndpointAuthNotExist', id));
339
- }
340
- exports.debug(id + ' auth scheme = ' + authScheme);
341
- return authScheme;
342
- }
343
- exports.getEndpointAuthorizationScheme = getEndpointAuthorizationScheme;
344
- /**
345
- * Gets the endpoint authorization parameter value for a service endpoint with specified key
346
- * If the endpoint authorization parameter is not set and is not optional, it will throw.
347
- *
348
- * @param id name of the service endpoint
349
- * @param key key to find the endpoint authorization parameter
350
- * @param optional optional whether the endpoint authorization scheme is optional
351
- * @returns {string} value of the endpoint authorization parameter value
352
- */
353
- function getEndpointAuthorizationParameter(id, key, optional) {
354
- var authParam = im._vault.retrieveSecret('ENDPOINT_AUTH_PARAMETER_' + id + '_' + key.toUpperCase());
355
- if (!optional && !authParam) {
356
- throw new Error(exports.loc('LIB_EndpointAuthNotExist', id));
357
- }
358
- exports.debug(id + ' auth param ' + key + ' = ' + authParam);
359
- return authParam;
360
- }
361
- exports.getEndpointAuthorizationParameter = getEndpointAuthorizationParameter;
362
- /**
363
- * Gets the authorization details for a service endpoint
364
- * If the authorization was not set and is not optional, it will set the task result to Failed.
365
- *
366
- * @param id name of the service endpoint
367
- * @param optional whether the url is optional
368
- * @returns string
369
- */
370
- function getEndpointAuthorization(id, optional) {
371
- var aval = im._vault.retrieveSecret('ENDPOINT_AUTH_' + id);
372
- if (!optional && !aval) {
373
- setResult(TaskResult.Failed, exports.loc('LIB_EndpointAuthNotExist', id));
374
- }
375
- exports.debug(id + ' exists ' + (!!aval));
376
- var auth;
377
- try {
378
- if (aval) {
379
- auth = JSON.parse(aval);
380
- }
381
- }
382
- catch (err) {
383
- throw new Error(exports.loc('LIB_InvalidEndpointAuth', aval));
384
- }
385
- return auth;
386
- }
387
- exports.getEndpointAuthorization = getEndpointAuthorization;
388
- //-----------------------------------------------------
389
- // SecureFile Helpers
390
- //-----------------------------------------------------
391
- /**
392
- * Gets the name for a secure file
393
- *
394
- * @param id secure file id
395
- * @returns string
396
- */
397
- function getSecureFileName(id) {
398
- var name = process.env['SECUREFILE_NAME_' + id];
399
- exports.debug('secure file name for id ' + id + ' = ' + name);
400
- return name;
401
- }
402
- exports.getSecureFileName = getSecureFileName;
403
- /**
404
- * Gets the secure file ticket that can be used to download the secure file contents
405
- *
406
- * @param id name of the secure file
407
- * @returns {string} secure file ticket
408
- */
409
- function getSecureFileTicket(id) {
410
- var ticket = im._vault.retrieveSecret('SECUREFILE_TICKET_' + id);
411
- exports.debug('secure file ticket for id ' + id + ' = ' + ticket);
412
- return ticket;
413
- }
414
- exports.getSecureFileTicket = getSecureFileTicket;
415
- //-----------------------------------------------------
416
- // Task Variable Helpers
417
- //-----------------------------------------------------
418
- /**
419
- * Gets a variable value that is set by previous step from the same wrapper task.
420
- * Requires a 2.115.0 agent or higher.
421
- *
422
- * @param name name of the variable to get
423
- * @returns string
424
- */
425
- function getTaskVariable(name) {
426
- assertAgent('2.115.0');
427
- var inval = im._vault.retrieveSecret('VSTS_TASKVARIABLE_' + im._getVariableKey(name));
428
- if (inval) {
429
- inval = inval.trim();
430
- }
431
- exports.debug('task variable: ' + name + '=' + inval);
432
- return inval;
433
- }
434
- exports.getTaskVariable = getTaskVariable;
435
- /**
436
- * Sets a task variable which will only be available to subsequent steps belong to the same wrapper task.
437
- * Requires a 2.115.0 agent or higher.
438
- *
439
- * @param name name of the variable to set
440
- * @param val value to set
441
- * @param secret whether variable is secret. optional, defaults to false
442
- * @returns void
443
- */
444
- function setTaskVariable(name, val, secret) {
445
- if (secret === void 0) { secret = false; }
446
- assertAgent('2.115.0');
447
- var key = im._getVariableKey(name);
448
- // store the value
449
- var varValue = val || '';
450
- exports.debug('set task variable: ' + name + '=' + (secret && varValue ? '********' : varValue));
451
- im._vault.storeSecret('VSTS_TASKVARIABLE_' + key, varValue);
452
- delete process.env[key];
453
- // write the command
454
- exports.command('task.settaskvariable', { 'variable': name || '', 'issecret': (secret || false).toString() }, varValue);
455
- }
456
- exports.setTaskVariable = setTaskVariable;
457
- //-----------------------------------------------------
458
- // Cmd Helpers
459
- //-----------------------------------------------------
460
- exports.command = im._command;
461
- exports.warning = im._warning;
462
- exports.error = im._error;
463
- exports.debug = im._debug;
464
- //-----------------------------------------------------
465
- // Disk Functions
466
- //-----------------------------------------------------
467
- function _checkShell(cmd, continueOnError) {
468
- var se = shell.error();
469
- if (se) {
470
- exports.debug(cmd + ' failed');
471
- var errMsg = exports.loc('LIB_OperationFailed', cmd, se);
472
- exports.debug(errMsg);
473
- if (!continueOnError) {
474
- throw new Error(errMsg);
475
- }
476
- }
477
- }
478
- /**
479
- * Get's stat on a path.
480
- * Useful for checking whether a file or directory. Also getting created, modified and accessed time.
481
- * see [fs.stat](https://nodejs.org/api/fs.html#fs_class_fs_stats)
482
- *
483
- * @param path path to check
484
- * @returns fsStat
485
- */
486
- function stats(path) {
487
- return fs.statSync(path);
488
- }
489
- exports.stats = stats;
490
- exports.exist = im._exist;
491
- function writeFile(file, data, options) {
492
- if (typeof (options) === 'string') {
493
- fs.writeFileSync(file, data, { encoding: options });
494
- }
495
- else {
496
- fs.writeFileSync(file, data, options);
497
- }
498
- }
499
- exports.writeFile = writeFile;
500
- /**
501
- * @deprecated Use `getPlatform`
502
- * Useful for determining the host operating system.
503
- * see [os.type](https://nodejs.org/api/os.html#os_os_type)
504
- *
505
- * @return the name of the operating system
506
- */
507
- function osType() {
508
- return os.type();
509
- }
510
- exports.osType = osType;
511
- /**
512
- * Determine the operating system the build agent is running on.
513
- * @returns {Platform}
514
- * @throws {Error} Platform is not supported by our agent
515
- */
516
- function getPlatform() {
517
- switch (process.platform) {
518
- case 'win32': return Platform.Windows;
519
- case 'darwin': return Platform.MacOS;
520
- case 'linux': return Platform.Linux;
521
- default: throw Error(exports.loc('LIB_PlatformNotSupported', process.platform));
522
- }
523
- }
524
- exports.getPlatform = getPlatform;
525
- /**
526
- * Returns the process's current working directory.
527
- * see [process.cwd](https://nodejs.org/api/process.html#process_process_cwd)
528
- *
529
- * @return the path to the current working directory of the process
530
- */
531
- function cwd() {
532
- return process.cwd();
533
- }
534
- exports.cwd = cwd;
535
- exports.checkPath = im._checkPath;
536
- /**
537
- * Change working directory.
538
- *
539
- * @param path new working directory path
540
- * @returns void
541
- */
542
- function cd(path) {
543
- if (path) {
544
- shell.cd(path);
545
- _checkShell('cd');
546
- }
547
- }
548
- exports.cd = cd;
549
- /**
550
- * Change working directory and push it on the stack
551
- *
552
- * @param path new working directory path
553
- * @returns void
554
- */
555
- function pushd(path) {
556
- shell.pushd(path);
557
- _checkShell('pushd');
558
- }
559
- exports.pushd = pushd;
560
- /**
561
- * Change working directory back to previously pushed directory
562
- *
563
- * @returns void
564
- */
565
- function popd() {
566
- shell.popd();
567
- _checkShell('popd');
568
- }
569
- exports.popd = popd;
570
- /**
571
- * Make a directory. Creates the full path with folders in between
572
- * Will throw if it fails
573
- *
574
- * @param p path to create
575
- * @returns void
576
- */
577
- function mkdirP(p) {
578
- if (!p) {
579
- throw new Error(exports.loc('LIB_ParameterIsRequired', 'p'));
580
- }
581
- // build a stack of directories to create
582
- var stack = [];
583
- var testDir = p;
584
- while (true) {
585
- // validate the loop is not out of control
586
- if (stack.length >= (process.env['TASKLIB_TEST_MKDIRP_FAILSAFE'] || 1000)) {
587
- // let the framework throw
588
- exports.debug('loop is out of control');
589
- fs.mkdirSync(p);
590
- return;
591
- }
592
- exports.debug("testing directory '" + testDir + "'");
593
- var stats_1 = void 0;
594
- try {
595
- stats_1 = fs.statSync(testDir);
596
- }
597
- catch (err) {
598
- if (err.code == 'ENOENT') {
599
- // validate the directory is not the drive root
600
- var parentDir = path.dirname(testDir);
601
- if (testDir == parentDir) {
602
- throw new Error(exports.loc('LIB_MkdirFailedInvalidDriveRoot', p, testDir)); // Unable to create directory '{p}'. Root directory does not exist: '{testDir}'
603
- }
604
- // push the dir and test the parent
605
- stack.push(testDir);
606
- testDir = parentDir;
607
- continue;
608
- }
609
- else if (err.code == 'UNKNOWN') {
610
- throw new Error(exports.loc('LIB_MkdirFailedInvalidShare', p, testDir)); // Unable to create directory '{p}'. Unable to verify the directory exists: '{testDir}'. If directory is a file share, please verify the share name is correct, the share is online, and the current process has permission to access the share.
611
- }
612
- else {
613
- throw err;
614
- }
615
- }
616
- if (!stats_1.isDirectory()) {
617
- throw new Error(exports.loc('LIB_MkdirFailedFileExists', p, testDir)); // Unable to create directory '{p}'. Conflicting file exists: '{testDir}'
618
- }
619
- // testDir exists
620
- break;
621
- }
622
- // create each directory
623
- while (stack.length) {
624
- var dir = stack.pop(); // non-null because `stack.length` was truthy
625
- exports.debug("mkdir '" + dir + "'");
626
- try {
627
- fs.mkdirSync(dir);
628
- }
629
- catch (err) {
630
- throw new Error(exports.loc('LIB_MkdirFailed', p, err.message)); // Unable to create directory '{p}'. {err.message}
631
- }
632
- }
633
- }
634
- exports.mkdirP = mkdirP;
635
- /**
636
- * Resolves a sequence of paths or path segments into an absolute path.
637
- * Calls node.js path.resolve()
638
- * Allows L0 testing with consistent path formats on Mac/Linux and Windows in the mock implementation
639
- * @param pathSegments
640
- * @returns {string}
641
- */
642
- function resolve() {
643
- var pathSegments = [];
644
- for (var _i = 0; _i < arguments.length; _i++) {
645
- pathSegments[_i] = arguments[_i];
646
- }
647
- var absolutePath = path.resolve.apply(this, pathSegments);
648
- exports.debug('Absolute path for pathSegments: ' + pathSegments + ' = ' + absolutePath);
649
- return absolutePath;
650
- }
651
- exports.resolve = resolve;
652
- exports.which = im._which;
653
- /**
654
- * Returns array of files in the given path, or in current directory if no path provided. See shelljs.ls
655
- * @param {string} options Available options: -R (recursive), -A (all files, include files beginning with ., except for . and ..)
656
- * @param {string[]} paths Paths to search.
657
- * @return {string[]} An array of files in the given path(s).
658
- */
659
- function ls(options, paths) {
660
- if (options) {
661
- return shell.ls(options, paths);
662
- }
663
- else {
664
- return shell.ls(paths);
665
- }
666
- }
667
- exports.ls = ls;
668
- /**
669
- * Copies a file or folder.
670
- *
671
- * @param source source path
672
- * @param dest destination path
673
- * @param options string -r, -f or -rf for recursive and force
674
- * @param continueOnError optional. whether to continue on error
675
- * @param retryCount optional. Retry count to copy the file. It might help to resolve intermittent issues e.g. with UNC target paths on a remote host.
676
- */
677
- function cp(source, dest, options, continueOnError, retryCount) {
678
- if (retryCount === void 0) { retryCount = 0; }
679
- while (retryCount >= 0) {
680
- try {
681
- if (options) {
682
- shell.cp(options, source, dest);
683
- }
684
- else {
685
- shell.cp(source, dest);
686
- }
687
- _checkShell('cp', false);
688
- break;
689
- }
690
- catch (e) {
691
- if (retryCount <= 0) {
692
- if (continueOnError) {
693
- exports.warning(e);
694
- break;
695
- }
696
- else {
697
- throw e;
698
- }
699
- }
700
- else {
701
- console.log(exports.loc('LIB_CopyFileFailed', retryCount));
702
- retryCount--;
703
- }
704
- }
705
- }
706
- }
707
- exports.cp = cp;
708
- /**
709
- * Moves a path.
710
- *
711
- * @param source source path
712
- * @param dest destination path
713
- * @param options string -f or -n for force and no clobber
714
- * @param continueOnError optional. whether to continue on error
715
- */
716
- function mv(source, dest, options, continueOnError) {
717
- if (options) {
718
- shell.mv(options, source, dest);
719
- }
720
- else {
721
- shell.mv(source, dest);
722
- }
723
- _checkShell('mv', continueOnError);
724
- }
725
- exports.mv = mv;
726
- /**
727
- * Tries to execute a function a specified number of times.
728
- *
729
- * @param func a function to be executed.
730
- * @param args executed function arguments array.
731
- * @param retryOptions optional. Defaults to { continueOnError: false, retryCount: 0 }.
732
- * @returns the same as the usual function.
733
- */
734
- function retry(func, args, retryOptions) {
735
- if (retryOptions === void 0) { retryOptions = { continueOnError: false, retryCount: 0 }; }
736
- while (retryOptions.retryCount >= 0) {
737
- try {
738
- return func.apply(void 0, args);
739
- }
740
- catch (e) {
741
- if (retryOptions.retryCount <= 0) {
742
- if (retryOptions.continueOnError) {
743
- exports.warning(e);
744
- break;
745
- }
746
- else {
747
- throw e;
748
- }
749
- }
750
- else {
751
- exports.debug("Attempt to execute function \"" + (func === null || func === void 0 ? void 0 : func.name) + "\" failed, retries left: " + retryOptions.retryCount);
752
- retryOptions.retryCount--;
753
- }
754
- }
755
- }
756
- }
757
- exports.retry = retry;
758
- /**
759
- * Gets info about item stats.
760
- *
761
- * @param path a path to the item to be processed.
762
- * @param followSymbolicLink indicates whether to traverse descendants of symbolic link directories.
763
- * @param allowBrokenSymbolicLinks when true, broken symbolic link will not cause an error.
764
- * @returns fs.Stats
765
- */
766
- function _getStats(path, followSymbolicLink, allowBrokenSymbolicLinks) {
767
- // stat returns info about the target of a symlink (or symlink chain),
768
- // lstat returns info about a symlink itself
769
- var stats;
770
- if (followSymbolicLink) {
771
- try {
772
- // use stat (following symlinks)
773
- stats = fs.statSync(path);
774
- }
775
- catch (err) {
776
- if (err.code == 'ENOENT' && allowBrokenSymbolicLinks) {
777
- // fallback to lstat (broken symlinks allowed)
778
- stats = fs.lstatSync(path);
779
- exports.debug(" " + path + " (broken symlink)");
780
- }
781
- else {
782
- throw err;
783
- }
784
- }
785
- }
786
- else {
787
- // use lstat (not following symlinks)
788
- stats = fs.lstatSync(path);
789
- }
790
- return stats;
791
- }
792
- /**
793
- * Recursively finds all paths a given path. Returns an array of paths.
794
- *
795
- * @param findPath path to search
796
- * @param options optional. defaults to { followSymbolicLinks: true }. following soft links is generally appropriate unless deleting files.
797
- * @returns string[]
798
- */
799
- function find(findPath, options) {
800
- if (!findPath) {
801
- exports.debug('no path specified');
802
- return [];
803
- }
804
- // normalize the path, otherwise the first result is inconsistently formatted from the rest of the results
805
- // because path.join() performs normalization.
806
- findPath = path.normalize(findPath);
807
- // debug trace the parameters
808
- exports.debug("findPath: '" + findPath + "'");
809
- options = options || _getDefaultFindOptions();
810
- _debugFindOptions(options);
811
- // return empty if not exists
812
- try {
813
- fs.lstatSync(findPath);
814
- }
815
- catch (err) {
816
- if (err.code == 'ENOENT') {
817
- exports.debug('0 results');
818
- return [];
819
- }
820
- throw err;
821
- }
822
- try {
823
- var result = [];
824
- // push the first item
825
- var stack = [new _FindItem(findPath, 1)];
826
- var traversalChain = []; // used to detect cycles
827
- var _loop_1 = function () {
828
- // pop the next item and push to the result array
829
- var item = stack.pop(); // non-null because `stack.length` was truthy
830
- var stats_2 = void 0;
831
- try {
832
- // `item.path` equals `findPath` for the first item to be processed, when the `result` array is empty
833
- var isPathToSearch = !result.length;
834
- // following specified symlinks only if current path equals specified path
835
- var followSpecifiedSymbolicLink = options.followSpecifiedSymbolicLink && isPathToSearch;
836
- // following all symlinks or following symlink for the specified path
837
- var followSymbolicLink = options.followSymbolicLinks || followSpecifiedSymbolicLink;
838
- // stat the item. The stat info is used further below to determine whether to traverse deeper
839
- stats_2 = _getStats(item.path, followSymbolicLink, options.allowBrokenSymbolicLinks);
840
- }
841
- catch (err) {
842
- if (err.code == 'ENOENT' && options.skipMissingFiles) {
843
- exports.warning("No such file or directory: \"" + item.path + "\" - skipping.");
844
- return "continue";
845
- }
846
- throw err;
847
- }
848
- result.push(item.path);
849
- // note, isDirectory() returns false for the lstat of a symlink
850
- if (stats_2.isDirectory()) {
851
- exports.debug(" " + item.path + " (directory)");
852
- if (options.followSymbolicLinks) {
853
- // get the realpath
854
- var realPath_1;
855
- if (im._isUncPath(item.path)) {
856
- // Sometimes there are spontaneous issues when working with unc-paths, so retries have been added for them.
857
- realPath_1 = retry(fs.realpathSync, [item.path], { continueOnError: false, retryCount: 5 });
858
- }
859
- else {
860
- realPath_1 = fs.realpathSync(item.path);
861
- }
862
- // fixup the traversal chain to match the item level
863
- while (traversalChain.length >= item.level) {
864
- traversalChain.pop();
865
- }
866
- // test for a cycle
867
- if (traversalChain.some(function (x) { return x == realPath_1; })) {
868
- exports.debug(' cycle detected');
869
- return "continue";
870
- }
871
- // update the traversal chain
872
- traversalChain.push(realPath_1);
873
- }
874
- // push the child items in reverse onto the stack
875
- var childLevel_1 = item.level + 1;
876
- var childItems = fs.readdirSync(item.path)
877
- .map(function (childName) { return new _FindItem(path.join(item.path, childName), childLevel_1); });
878
- for (var i = childItems.length - 1; i >= 0; i--) {
879
- stack.push(childItems[i]);
880
- }
881
- }
882
- else {
883
- exports.debug(" " + item.path + " (file)");
884
- }
885
- };
886
- while (stack.length) {
887
- _loop_1();
888
- }
889
- exports.debug(result.length + " results");
890
- return result;
891
- }
892
- catch (err) {
893
- throw new Error(exports.loc('LIB_OperationFailed', 'find', err.message));
894
- }
895
- }
896
- exports.find = find;
897
- var _FindItem = /** @class */ (function () {
898
- function _FindItem(path, level) {
899
- this.path = path;
900
- this.level = level;
901
- }
902
- return _FindItem;
903
- }());
904
- function _debugFindOptions(options) {
905
- exports.debug("findOptions.allowBrokenSymbolicLinks: '" + options.allowBrokenSymbolicLinks + "'");
906
- exports.debug("findOptions.followSpecifiedSymbolicLink: '" + options.followSpecifiedSymbolicLink + "'");
907
- exports.debug("findOptions.followSymbolicLinks: '" + options.followSymbolicLinks + "'");
908
- exports.debug("findOptions.skipMissingFiles: '" + options.skipMissingFiles + "'");
909
- }
910
- function _getDefaultFindOptions() {
911
- return {
912
- allowBrokenSymbolicLinks: false,
913
- followSpecifiedSymbolicLink: true,
914
- followSymbolicLinks: true,
915
- skipMissingFiles: false
916
- };
917
- }
918
- /**
919
- * Prefer tl.find() and tl.match() instead. This function is for backward compatibility
920
- * when porting tasks to Node from the PowerShell or PowerShell3 execution handler.
921
- *
922
- * @param rootDirectory path to root unrooted patterns with
923
- * @param pattern include and exclude patterns
924
- * @param includeFiles whether to include files in the result. defaults to true when includeFiles and includeDirectories are both false
925
- * @param includeDirectories whether to include directories in the result
926
- * @returns string[]
927
- */
928
- function legacyFindFiles(rootDirectory, pattern, includeFiles, includeDirectories) {
929
- if (!pattern) {
930
- throw new Error('pattern parameter cannot be empty');
931
- }
932
- exports.debug("legacyFindFiles rootDirectory: '" + rootDirectory + "'");
933
- exports.debug("pattern: '" + pattern + "'");
934
- exports.debug("includeFiles: '" + includeFiles + "'");
935
- exports.debug("includeDirectories: '" + includeDirectories + "'");
936
- if (!includeFiles && !includeDirectories) {
937
- includeFiles = true;
938
- }
939
- // organize the patterns into include patterns and exclude patterns
940
- var includePatterns = [];
941
- var excludePatterns = [];
942
- pattern = pattern.replace(/;;/g, '\0');
943
- for (var _i = 0, _a = pattern.split(';'); _i < _a.length; _i++) {
944
- var pat = _a[_i];
945
- if (!pat) {
946
- continue;
947
- }
948
- pat = pat.replace(/\0/g, ';');
949
- // determine whether include pattern and remove any include/exclude prefix.
950
- // include patterns start with +: or anything other than -:
951
- // exclude patterns start with -:
952
- var isIncludePattern = void 0;
953
- if (im._startsWith(pat, '+:')) {
954
- pat = pat.substring(2);
955
- isIncludePattern = true;
956
- }
957
- else if (im._startsWith(pat, '-:')) {
958
- pat = pat.substring(2);
959
- isIncludePattern = false;
960
- }
961
- else {
962
- isIncludePattern = true;
963
- }
964
- // validate pattern does not end with a slash
965
- if (im._endsWith(pat, '/') || (process.platform == 'win32' && im._endsWith(pat, '\\'))) {
966
- throw new Error(exports.loc('LIB_InvalidPattern', pat));
967
- }
968
- // root the pattern
969
- if (rootDirectory && !path.isAbsolute(pat)) {
970
- pat = path.join(rootDirectory, pat);
971
- // remove trailing slash sometimes added by path.join() on Windows, e.g.
972
- // path.join('\\\\hello', 'world') => '\\\\hello\\world\\'
973
- // path.join('//hello', 'world') => '\\\\hello\\world\\'
974
- if (im._endsWith(pat, '\\')) {
975
- pat = pat.substring(0, pat.length - 1);
976
- }
977
- }
978
- if (isIncludePattern) {
979
- includePatterns.push(pat);
980
- }
981
- else {
982
- excludePatterns.push(im._legacyFindFiles_convertPatternToRegExp(pat));
983
- }
984
- }
985
- // find and apply patterns
986
- var count = 0;
987
- var result = _legacyFindFiles_getMatchingItems(includePatterns, excludePatterns, !!includeFiles, !!includeDirectories);
988
- exports.debug('all matches:');
989
- for (var _b = 0, result_1 = result; _b < result_1.length; _b++) {
990
- var resultItem = result_1[_b];
991
- exports.debug(' ' + resultItem);
992
- }
993
- exports.debug('total matched: ' + result.length);
994
- return result;
995
- }
996
- exports.legacyFindFiles = legacyFindFiles;
997
- function _legacyFindFiles_getMatchingItems(includePatterns, excludePatterns, includeFiles, includeDirectories) {
998
- exports.debug('getMatchingItems()');
999
- for (var _i = 0, includePatterns_1 = includePatterns; _i < includePatterns_1.length; _i++) {
1000
- var pattern = includePatterns_1[_i];
1001
- exports.debug("includePattern: '" + pattern + "'");
1002
- }
1003
- for (var _a = 0, excludePatterns_1 = excludePatterns; _a < excludePatterns_1.length; _a++) {
1004
- var pattern = excludePatterns_1[_a];
1005
- exports.debug("excludePattern: " + pattern);
1006
- }
1007
- exports.debug('includeFiles: ' + includeFiles);
1008
- exports.debug('includeDirectories: ' + includeDirectories);
1009
- var allFiles = {};
1010
- var _loop_2 = function (pattern) {
1011
- // determine the directory to search
1012
- //
1013
- // note, getDirectoryName removes redundant path separators
1014
- var findPath = void 0;
1015
- var starIndex = pattern.indexOf('*');
1016
- var questionIndex = pattern.indexOf('?');
1017
- if (starIndex < 0 && questionIndex < 0) {
1018
- // if no wildcards are found, use the directory name portion of the path.
1019
- // if there is no directory name (file name only in pattern or drive root),
1020
- // this will return empty string.
1021
- findPath = im._getDirectoryName(pattern);
1022
- }
1023
- else {
1024
- // extract the directory prior to the first wildcard
1025
- var index = Math.min(starIndex >= 0 ? starIndex : questionIndex, questionIndex >= 0 ? questionIndex : starIndex);
1026
- findPath = im._getDirectoryName(pattern.substring(0, index));
1027
- }
1028
- // note, due to this short-circuit and the above usage of getDirectoryName, this
1029
- // function has the same limitations regarding drive roots as the powershell
1030
- // implementation.
1031
- //
1032
- // also note, since getDirectoryName eliminates slash redundancies, some additional
1033
- // work may be required if removal of this limitation is attempted.
1034
- if (!findPath) {
1035
- return "continue";
1036
- }
1037
- var patternRegex = im._legacyFindFiles_convertPatternToRegExp(pattern);
1038
- // find files/directories
1039
- var items = find(findPath, { followSymbolicLinks: true })
1040
- .filter(function (item) {
1041
- if (includeFiles && includeDirectories) {
1042
- return true;
1043
- }
1044
- var isDir = fs.statSync(item).isDirectory();
1045
- return (includeFiles && !isDir) || (includeDirectories && isDir);
1046
- })
1047
- .forEach(function (item) {
1048
- var normalizedPath = process.platform == 'win32' ? item.replace(/\\/g, '/') : item; // normalize separators
1049
- // **/times/** will not match C:/fun/times because there isn't a trailing slash
1050
- // so try both if including directories
1051
- var alternatePath = normalizedPath + "/"; // potential bug: it looks like this will result in a false
1052
- // positive if the item is a regular file and not a directory
1053
- var isMatch = false;
1054
- if (patternRegex.test(normalizedPath) || (includeDirectories && patternRegex.test(alternatePath))) {
1055
- isMatch = true;
1056
- // test whether the path should be excluded
1057
- for (var _i = 0, excludePatterns_2 = excludePatterns; _i < excludePatterns_2.length; _i++) {
1058
- var regex = excludePatterns_2[_i];
1059
- if (regex.test(normalizedPath) || (includeDirectories && regex.test(alternatePath))) {
1060
- isMatch = false;
1061
- break;
1062
- }
1063
- }
1064
- }
1065
- if (isMatch) {
1066
- allFiles[item] = item;
1067
- }
1068
- });
1069
- };
1070
- for (var _b = 0, includePatterns_2 = includePatterns; _b < includePatterns_2.length; _b++) {
1071
- var pattern = includePatterns_2[_b];
1072
- _loop_2(pattern);
1073
- }
1074
- return Object.keys(allFiles).sort();
1075
- }
1076
- /**
1077
- * Remove a path recursively with force
1078
- *
1079
- * @param inputPath path to remove
1080
- * @throws when the file or directory exists but could not be deleted.
1081
- */
1082
- function rmRF(inputPath) {
1083
- exports.debug('rm -rf ' + inputPath);
1084
- if (getPlatform() == Platform.Windows) {
1085
- // Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another
1086
- // program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del.
1087
- try {
1088
- if (fs.statSync(inputPath).isDirectory()) {
1089
- exports.debug('removing directory ' + inputPath);
1090
- childProcess.execSync("rd /s /q \"" + inputPath + "\"");
1091
- }
1092
- else {
1093
- exports.debug('removing file ' + inputPath);
1094
- childProcess.execSync("del /f /a \"" + inputPath + "\"");
1095
- }
1096
- }
1097
- catch (err) {
1098
- // if you try to delete a file that doesn't exist, desired result is achieved
1099
- // other errors are valid
1100
- if (err.code != 'ENOENT') {
1101
- throw new Error(exports.loc('LIB_OperationFailed', 'rmRF', err.message));
1102
- }
1103
- }
1104
- // Shelling out fails to remove a symlink folder with missing source, this unlink catches that
1105
- try {
1106
- fs.unlinkSync(inputPath);
1107
- }
1108
- catch (err) {
1109
- // if you try to delete a file that doesn't exist, desired result is achieved
1110
- // other errors are valid
1111
- if (err.code != 'ENOENT') {
1112
- throw new Error(exports.loc('LIB_OperationFailed', 'rmRF', err.message));
1113
- }
1114
- }
1115
- }
1116
- else {
1117
- // get the lstats in order to workaround a bug in shelljs@0.3.0 where symlinks
1118
- // with missing targets are not handled correctly by "rm('-rf', path)"
1119
- var lstats = void 0;
1120
- try {
1121
- lstats = fs.lstatSync(inputPath);
1122
- }
1123
- catch (err) {
1124
- // if you try to delete a file that doesn't exist, desired result is achieved
1125
- // other errors are valid
1126
- if (err.code == 'ENOENT') {
1127
- return;
1128
- }
1129
- throw new Error(exports.loc('LIB_OperationFailed', 'rmRF', err.message));
1130
- }
1131
- if (lstats.isDirectory()) {
1132
- exports.debug('removing directory');
1133
- shell.rm('-rf', inputPath);
1134
- var errMsg = shell.error();
1135
- if (errMsg) {
1136
- throw new Error(exports.loc('LIB_OperationFailed', 'rmRF', errMsg));
1137
- }
1138
- return;
1139
- }
1140
- exports.debug('removing file');
1141
- try {
1142
- fs.unlinkSync(inputPath);
1143
- }
1144
- catch (err) {
1145
- throw new Error(exports.loc('LIB_OperationFailed', 'rmRF', err.message));
1146
- }
1147
- }
1148
- }
1149
- exports.rmRF = rmRF;
1150
- /**
1151
- * Exec a tool. Convenience wrapper over ToolRunner to exec with args in one call.
1152
- * Output will be streamed to the live console.
1153
- * Returns promise with return code
1154
- *
1155
- * @param tool path to tool to exec
1156
- * @param args an arg string or array of args
1157
- * @param options optional exec options. See IExecOptions
1158
- * @returns number
1159
- */
1160
- function exec(tool, args, options) {
1161
- var tr = this.tool(tool);
1162
- tr.on('debug', function (data) {
1163
- exports.debug(data);
1164
- });
1165
- if (args) {
1166
- if (args instanceof Array) {
1167
- tr.arg(args);
1168
- }
1169
- else if (typeof (args) === 'string') {
1170
- tr.line(args);
1171
- }
1172
- }
1173
- return tr.exec(options);
1174
- }
1175
- exports.exec = exec;
1176
- /**
1177
- * Exec a tool synchronously. Convenience wrapper over ToolRunner to execSync with args in one call.
1178
- * Output will be *not* be streamed to the live console. It will be returned after execution is complete.
1179
- * Appropriate for short running tools
1180
- * Returns IExecResult with output and return code
1181
- *
1182
- * @param tool path to tool to exec
1183
- * @param args an arg string or array of args
1184
- * @param options optional exec options. See IExecSyncOptions
1185
- * @returns IExecSyncResult
1186
- */
1187
- function execSync(tool, args, options) {
1188
- var tr = this.tool(tool);
1189
- tr.on('debug', function (data) {
1190
- exports.debug(data);
1191
- });
1192
- if (args) {
1193
- if (args instanceof Array) {
1194
- tr.arg(args);
1195
- }
1196
- else if (typeof (args) === 'string') {
1197
- tr.line(args);
1198
- }
1199
- }
1200
- return tr.execSync(options);
1201
- }
1202
- exports.execSync = execSync;
1203
- /**
1204
- * Convenience factory to create a ToolRunner.
1205
- *
1206
- * @param tool path to tool to exec
1207
- * @returns ToolRunner
1208
- */
1209
- function tool(tool) {
1210
- var tr = new trm.ToolRunner(tool);
1211
- tr.on('debug', function (message) {
1212
- exports.debug(message);
1213
- });
1214
- return tr;
1215
- }
1216
- exports.tool = tool;
1217
- /**
1218
- * Applies glob patterns to a list of paths. Supports interleaved exclude patterns.
1219
- *
1220
- * @param list array of paths
1221
- * @param patterns patterns to apply. supports interleaved exclude patterns.
1222
- * @param patternRoot optional. default root to apply to unrooted patterns. not applied to basename-only patterns when matchBase:true.
1223
- * @param options optional. defaults to { dot: true, nobrace: true, nocase: process.platform == 'win32' }.
1224
- */
1225
- function match(list, patterns, patternRoot, options) {
1226
- // trace parameters
1227
- exports.debug("patternRoot: '" + patternRoot + "'");
1228
- options = options || _getDefaultMatchOptions(); // default match options
1229
- _debugMatchOptions(options);
1230
- // convert pattern to an array
1231
- if (typeof patterns == 'string') {
1232
- patterns = [patterns];
1233
- }
1234
- // hashtable to keep track of matches
1235
- var map = {};
1236
- var originalOptions = options;
1237
- for (var _i = 0, patterns_1 = patterns; _i < patterns_1.length; _i++) {
1238
- var pattern = patterns_1[_i];
1239
- exports.debug("pattern: '" + pattern + "'");
1240
- // trim and skip empty
1241
- pattern = (pattern || '').trim();
1242
- if (!pattern) {
1243
- exports.debug('skipping empty pattern');
1244
- continue;
1245
- }
1246
- // clone match options
1247
- var options_1 = im._cloneMatchOptions(originalOptions);
1248
- // skip comments
1249
- if (!options_1.nocomment && im._startsWith(pattern, '#')) {
1250
- exports.debug('skipping comment');
1251
- continue;
1252
- }
1253
- // set nocomment - brace expansion could result in a leading '#'
1254
- options_1.nocomment = true;
1255
- // determine whether pattern is include or exclude
1256
- var negateCount = 0;
1257
- if (!options_1.nonegate) {
1258
- while (pattern.charAt(negateCount) == '!') {
1259
- negateCount++;
1260
- }
1261
- pattern = pattern.substring(negateCount); // trim leading '!'
1262
- if (negateCount) {
1263
- exports.debug("trimmed leading '!'. pattern: '" + pattern + "'");
1264
- }
1265
- }
1266
- var isIncludePattern = negateCount == 0 ||
1267
- (negateCount % 2 == 0 && !options_1.flipNegate) ||
1268
- (negateCount % 2 == 1 && options_1.flipNegate);
1269
- // set nonegate - brace expansion could result in a leading '!'
1270
- options_1.nonegate = true;
1271
- options_1.flipNegate = false;
1272
- // expand braces - required to accurately root patterns
1273
- var expanded = void 0;
1274
- var preExpanded = pattern;
1275
- if (options_1.nobrace) {
1276
- expanded = [pattern];
1277
- }
1278
- else {
1279
- // convert slashes on Windows before calling braceExpand(). unfortunately this means braces cannot
1280
- // be escaped on Windows, this limitation is consistent with current limitations of minimatch (3.0.3).
1281
- exports.debug('expanding braces');
1282
- var convertedPattern = process.platform == 'win32' ? pattern.replace(/\\/g, '/') : pattern;
1283
- expanded = minimatch.braceExpand(convertedPattern);
1284
- }
1285
- // set nobrace
1286
- options_1.nobrace = true;
1287
- for (var _a = 0, expanded_1 = expanded; _a < expanded_1.length; _a++) {
1288
- var pattern_1 = expanded_1[_a];
1289
- if (expanded.length != 1 || pattern_1 != preExpanded) {
1290
- exports.debug("pattern: '" + pattern_1 + "'");
1291
- }
1292
- // trim and skip empty
1293
- pattern_1 = (pattern_1 || '').trim();
1294
- if (!pattern_1) {
1295
- exports.debug('skipping empty pattern');
1296
- continue;
1297
- }
1298
- // root the pattern when all of the following conditions are true:
1299
- if (patternRoot && // patternRoot supplied
1300
- !im._isRooted(pattern_1) && // AND pattern not rooted
1301
- // AND matchBase:false or not basename only
1302
- (!options_1.matchBase || (process.platform == 'win32' ? pattern_1.replace(/\\/g, '/') : pattern_1).indexOf('/') >= 0)) {
1303
- pattern_1 = im._ensureRooted(patternRoot, pattern_1);
1304
- exports.debug("rooted pattern: '" + pattern_1 + "'");
1305
- }
1306
- if (isIncludePattern) {
1307
- // apply the pattern
1308
- exports.debug('applying include pattern against original list');
1309
- var matchResults = minimatch.match(list, pattern_1, options_1);
1310
- exports.debug(matchResults.length + ' matches');
1311
- // union the results
1312
- for (var _b = 0, matchResults_1 = matchResults; _b < matchResults_1.length; _b++) {
1313
- var matchResult = matchResults_1[_b];
1314
- map[matchResult] = true;
1315
- }
1316
- }
1317
- else {
1318
- // apply the pattern
1319
- exports.debug('applying exclude pattern against original list');
1320
- var matchResults = minimatch.match(list, pattern_1, options_1);
1321
- exports.debug(matchResults.length + ' matches');
1322
- // substract the results
1323
- for (var _c = 0, matchResults_2 = matchResults; _c < matchResults_2.length; _c++) {
1324
- var matchResult = matchResults_2[_c];
1325
- delete map[matchResult];
1326
- }
1327
- }
1328
- }
1329
- }
1330
- // return a filtered version of the original list (preserves order and prevents duplication)
1331
- var result = list.filter(function (item) { return map.hasOwnProperty(item); });
1332
- exports.debug(result.length + ' final results');
1333
- return result;
1334
- }
1335
- exports.match = match;
1336
- /**
1337
- * Filter to apply glob patterns
1338
- *
1339
- * @param pattern pattern to apply
1340
- * @param options optional. defaults to { dot: true, nobrace: true, nocase: process.platform == 'win32' }.
1341
- */
1342
- function filter(pattern, options) {
1343
- options = options || _getDefaultMatchOptions();
1344
- return minimatch.filter(pattern, options);
1345
- }
1346
- exports.filter = filter;
1347
- function _debugMatchOptions(options) {
1348
- exports.debug("matchOptions.debug: '" + options.debug + "'");
1349
- exports.debug("matchOptions.nobrace: '" + options.nobrace + "'");
1350
- exports.debug("matchOptions.noglobstar: '" + options.noglobstar + "'");
1351
- exports.debug("matchOptions.dot: '" + options.dot + "'");
1352
- exports.debug("matchOptions.noext: '" + options.noext + "'");
1353
- exports.debug("matchOptions.nocase: '" + options.nocase + "'");
1354
- exports.debug("matchOptions.nonull: '" + options.nonull + "'");
1355
- exports.debug("matchOptions.matchBase: '" + options.matchBase + "'");
1356
- exports.debug("matchOptions.nocomment: '" + options.nocomment + "'");
1357
- exports.debug("matchOptions.nonegate: '" + options.nonegate + "'");
1358
- exports.debug("matchOptions.flipNegate: '" + options.flipNegate + "'");
1359
- }
1360
- function _getDefaultMatchOptions() {
1361
- return {
1362
- debug: false,
1363
- nobrace: true,
1364
- noglobstar: false,
1365
- dot: true,
1366
- noext: false,
1367
- nocase: process.platform == 'win32',
1368
- nonull: false,
1369
- matchBase: false,
1370
- nocomment: false,
1371
- nonegate: false,
1372
- flipNegate: false
1373
- };
1374
- }
1375
- /**
1376
- * Determines the find root from a list of patterns. Performs the find and then applies the glob patterns.
1377
- * Supports interleaved exclude patterns. Unrooted patterns are rooted using defaultRoot, unless
1378
- * matchOptions.matchBase is specified and the pattern is a basename only. For matchBase cases, the
1379
- * defaultRoot is used as the find root.
1380
- *
1381
- * @param defaultRoot default path to root unrooted patterns. falls back to System.DefaultWorkingDirectory or process.cwd().
1382
- * @param patterns pattern or array of patterns to apply
1383
- * @param findOptions defaults to { followSymbolicLinks: true }. following soft links is generally appropriate unless deleting files.
1384
- * @param matchOptions defaults to { dot: true, nobrace: true, nocase: process.platform == 'win32' }
1385
- */
1386
- function findMatch(defaultRoot, patterns, findOptions, matchOptions) {
1387
- // apply defaults for parameters and trace
1388
- defaultRoot = defaultRoot || this.getVariable('system.defaultWorkingDirectory') || process.cwd();
1389
- exports.debug("defaultRoot: '" + defaultRoot + "'");
1390
- patterns = patterns || [];
1391
- patterns = typeof patterns == 'string' ? [patterns] : patterns;
1392
- findOptions = findOptions || _getDefaultFindOptions();
1393
- _debugFindOptions(findOptions);
1394
- matchOptions = matchOptions || _getDefaultMatchOptions();
1395
- _debugMatchOptions(matchOptions);
1396
- // normalize slashes for root dir
1397
- defaultRoot = im._normalizeSeparators(defaultRoot);
1398
- var results = {};
1399
- var originalMatchOptions = matchOptions;
1400
- for (var _i = 0, _a = (patterns || []); _i < _a.length; _i++) {
1401
- var pattern = _a[_i];
1402
- exports.debug("pattern: '" + pattern + "'");
1403
- // trim and skip empty
1404
- pattern = (pattern || '').trim();
1405
- if (!pattern) {
1406
- exports.debug('skipping empty pattern');
1407
- continue;
1408
- }
1409
- // clone match options
1410
- var matchOptions_1 = im._cloneMatchOptions(originalMatchOptions);
1411
- // skip comments
1412
- if (!matchOptions_1.nocomment && im._startsWith(pattern, '#')) {
1413
- exports.debug('skipping comment');
1414
- continue;
1415
- }
1416
- // set nocomment - brace expansion could result in a leading '#'
1417
- matchOptions_1.nocomment = true;
1418
- // determine whether pattern is include or exclude
1419
- var negateCount = 0;
1420
- if (!matchOptions_1.nonegate) {
1421
- while (pattern.charAt(negateCount) == '!') {
1422
- negateCount++;
1423
- }
1424
- pattern = pattern.substring(negateCount); // trim leading '!'
1425
- if (negateCount) {
1426
- exports.debug("trimmed leading '!'. pattern: '" + pattern + "'");
1427
- }
1428
- }
1429
- var isIncludePattern = negateCount == 0 ||
1430
- (negateCount % 2 == 0 && !matchOptions_1.flipNegate) ||
1431
- (negateCount % 2 == 1 && matchOptions_1.flipNegate);
1432
- // set nonegate - brace expansion could result in a leading '!'
1433
- matchOptions_1.nonegate = true;
1434
- matchOptions_1.flipNegate = false;
1435
- // expand braces - required to accurately interpret findPath
1436
- var expanded = void 0;
1437
- var preExpanded = pattern;
1438
- if (matchOptions_1.nobrace) {
1439
- expanded = [pattern];
1440
- }
1441
- else {
1442
- // convert slashes on Windows before calling braceExpand(). unfortunately this means braces cannot
1443
- // be escaped on Windows, this limitation is consistent with current limitations of minimatch (3.0.3).
1444
- exports.debug('expanding braces');
1445
- var convertedPattern = process.platform == 'win32' ? pattern.replace(/\\/g, '/') : pattern;
1446
- expanded = minimatch.braceExpand(convertedPattern);
1447
- }
1448
- // set nobrace
1449
- matchOptions_1.nobrace = true;
1450
- for (var _b = 0, expanded_2 = expanded; _b < expanded_2.length; _b++) {
1451
- var pattern_2 = expanded_2[_b];
1452
- if (expanded.length != 1 || pattern_2 != preExpanded) {
1453
- exports.debug("pattern: '" + pattern_2 + "'");
1454
- }
1455
- // trim and skip empty
1456
- pattern_2 = (pattern_2 || '').trim();
1457
- if (!pattern_2) {
1458
- exports.debug('skipping empty pattern');
1459
- continue;
1460
- }
1461
- if (isIncludePattern) {
1462
- // determine the findPath
1463
- var findInfo = im._getFindInfoFromPattern(defaultRoot, pattern_2, matchOptions_1);
1464
- var findPath = findInfo.findPath;
1465
- exports.debug("findPath: '" + findPath + "'");
1466
- if (!findPath) {
1467
- exports.debug('skipping empty path');
1468
- continue;
1469
- }
1470
- // perform the find
1471
- exports.debug("statOnly: '" + findInfo.statOnly + "'");
1472
- var findResults = [];
1473
- if (findInfo.statOnly) {
1474
- // simply stat the path - all path segments were used to build the path
1475
- try {
1476
- fs.statSync(findPath);
1477
- findResults.push(findPath);
1478
- }
1479
- catch (err) {
1480
- if (err.code != 'ENOENT') {
1481
- throw err;
1482
- }
1483
- exports.debug('ENOENT');
1484
- }
1485
- }
1486
- else {
1487
- findResults = find(findPath, findOptions);
1488
- }
1489
- exports.debug("found " + findResults.length + " paths");
1490
- // apply the pattern
1491
- exports.debug('applying include pattern');
1492
- if (findInfo.adjustedPattern != pattern_2) {
1493
- exports.debug("adjustedPattern: '" + findInfo.adjustedPattern + "'");
1494
- pattern_2 = findInfo.adjustedPattern;
1495
- }
1496
- var matchResults = minimatch.match(findResults, pattern_2, matchOptions_1);
1497
- exports.debug(matchResults.length + ' matches');
1498
- // union the results
1499
- for (var _c = 0, matchResults_3 = matchResults; _c < matchResults_3.length; _c++) {
1500
- var matchResult = matchResults_3[_c];
1501
- var key = process.platform == 'win32' ? matchResult.toUpperCase() : matchResult;
1502
- results[key] = matchResult;
1503
- }
1504
- }
1505
- else {
1506
- // check if basename only and matchBase=true
1507
- if (matchOptions_1.matchBase &&
1508
- !im._isRooted(pattern_2) &&
1509
- (process.platform == 'win32' ? pattern_2.replace(/\\/g, '/') : pattern_2).indexOf('/') < 0) {
1510
- // do not root the pattern
1511
- exports.debug('matchBase and basename only');
1512
- }
1513
- else {
1514
- // root the exclude pattern
1515
- pattern_2 = im._ensurePatternRooted(defaultRoot, pattern_2);
1516
- exports.debug("after ensurePatternRooted, pattern: '" + pattern_2 + "'");
1517
- }
1518
- // apply the pattern
1519
- exports.debug('applying exclude pattern');
1520
- var matchResults = minimatch.match(Object.keys(results).map(function (key) { return results[key]; }), pattern_2, matchOptions_1);
1521
- exports.debug(matchResults.length + ' matches');
1522
- // substract the results
1523
- for (var _d = 0, matchResults_4 = matchResults; _d < matchResults_4.length; _d++) {
1524
- var matchResult = matchResults_4[_d];
1525
- var key = process.platform == 'win32' ? matchResult.toUpperCase() : matchResult;
1526
- delete results[key];
1527
- }
1528
- }
1529
- }
1530
- }
1531
- var finalResult = Object.keys(results)
1532
- .map(function (key) { return results[key]; })
1533
- .sort();
1534
- exports.debug(finalResult.length + ' final results');
1535
- return finalResult;
1536
- }
1537
- exports.findMatch = findMatch;
1538
- /**
1539
- * Gets http proxy configuration used by Build/Release agent
1540
- *
1541
- * @return ProxyConfiguration
1542
- */
1543
- function getHttpProxyConfiguration(requestUrl) {
1544
- var proxyUrl = exports.getVariable('Agent.ProxyUrl');
1545
- if (proxyUrl && proxyUrl.length > 0) {
1546
- var proxyUsername = exports.getVariable('Agent.ProxyUsername');
1547
- var proxyPassword = exports.getVariable('Agent.ProxyPassword');
1548
- var proxyBypassHosts = JSON.parse(exports.getVariable('Agent.ProxyBypassList') || '[]');
1549
- var bypass_1 = false;
1550
- if (requestUrl) {
1551
- proxyBypassHosts.forEach(function (bypassHost) {
1552
- if (new RegExp(bypassHost, 'i').test(requestUrl)) {
1553
- bypass_1 = true;
1554
- }
1555
- });
1556
- }
1557
- if (bypass_1) {
1558
- return null;
1559
- }
1560
- else {
1561
- return {
1562
- proxyUrl: proxyUrl,
1563
- proxyUsername: proxyUsername,
1564
- proxyPassword: proxyPassword,
1565
- proxyBypassHosts: proxyBypassHosts
1566
- };
1567
- }
1568
- }
1569
- else {
1570
- return null;
1571
- }
1572
- }
1573
- exports.getHttpProxyConfiguration = getHttpProxyConfiguration;
1574
- /**
1575
- * Gets http certificate configuration used by Build/Release agent
1576
- *
1577
- * @return CertConfiguration
1578
- */
1579
- function getHttpCertConfiguration() {
1580
- var ca = exports.getVariable('Agent.CAInfo');
1581
- var clientCert = exports.getVariable('Agent.ClientCert');
1582
- if (ca || clientCert) {
1583
- var certConfig = {};
1584
- certConfig.caFile = ca;
1585
- certConfig.certFile = clientCert;
1586
- if (clientCert) {
1587
- var clientCertKey = exports.getVariable('Agent.ClientCertKey');
1588
- var clientCertArchive = exports.getVariable('Agent.ClientCertArchive');
1589
- var clientCertPassword = exports.getVariable('Agent.ClientCertPassword');
1590
- certConfig.keyFile = clientCertKey;
1591
- certConfig.certArchiveFile = clientCertArchive;
1592
- certConfig.passphrase = clientCertPassword;
1593
- }
1594
- return certConfig;
1595
- }
1596
- else {
1597
- return null;
1598
- }
1599
- }
1600
- exports.getHttpCertConfiguration = getHttpCertConfiguration;
1601
- //-----------------------------------------------------
1602
- // Test Publisher
1603
- //-----------------------------------------------------
1604
- var TestPublisher = /** @class */ (function () {
1605
- function TestPublisher(testRunner) {
1606
- this.testRunner = testRunner;
1607
- }
1608
- TestPublisher.prototype.publish = function (resultFiles, mergeResults, platform, config, runTitle, publishRunAttachments, testRunSystem) {
1609
- // Could have used an initializer, but wanted to avoid reordering parameters when converting to strict null checks
1610
- // (A parameter cannot both be optional and have an initializer)
1611
- testRunSystem = testRunSystem || "VSTSTask";
1612
- var properties = {};
1613
- properties['type'] = this.testRunner;
1614
- if (mergeResults) {
1615
- properties['mergeResults'] = mergeResults;
1616
- }
1617
- if (platform) {
1618
- properties['platform'] = platform;
1619
- }
1620
- if (config) {
1621
- properties['config'] = config;
1622
- }
1623
- if (runTitle) {
1624
- properties['runTitle'] = runTitle;
1625
- }
1626
- if (publishRunAttachments) {
1627
- properties['publishRunAttachments'] = publishRunAttachments;
1628
- }
1629
- if (resultFiles) {
1630
- properties['resultFiles'] = Array.isArray(resultFiles) ? resultFiles.join() : resultFiles;
1631
- }
1632
- properties['testRunSystem'] = testRunSystem;
1633
- exports.command('results.publish', properties, '');
1634
- };
1635
- return TestPublisher;
1636
- }());
1637
- exports.TestPublisher = TestPublisher;
1638
- //-----------------------------------------------------
1639
- // Code coverage Publisher
1640
- //-----------------------------------------------------
1641
- var CodeCoveragePublisher = /** @class */ (function () {
1642
- function CodeCoveragePublisher() {
1643
- }
1644
- CodeCoveragePublisher.prototype.publish = function (codeCoverageTool, summaryFileLocation, reportDirectory, additionalCodeCoverageFiles) {
1645
- var properties = {};
1646
- if (codeCoverageTool) {
1647
- properties['codecoveragetool'] = codeCoverageTool;
1648
- }
1649
- if (summaryFileLocation) {
1650
- properties['summaryfile'] = summaryFileLocation;
1651
- }
1652
- if (reportDirectory) {
1653
- properties['reportdirectory'] = reportDirectory;
1654
- }
1655
- if (additionalCodeCoverageFiles) {
1656
- properties['additionalcodecoveragefiles'] = Array.isArray(additionalCodeCoverageFiles) ? additionalCodeCoverageFiles.join() : additionalCodeCoverageFiles;
1657
- }
1658
- exports.command('codecoverage.publish', properties, "");
1659
- };
1660
- return CodeCoveragePublisher;
1661
- }());
1662
- exports.CodeCoveragePublisher = CodeCoveragePublisher;
1663
- //-----------------------------------------------------
1664
- // Code coverage Publisher
1665
- //-----------------------------------------------------
1666
- var CodeCoverageEnabler = /** @class */ (function () {
1667
- function CodeCoverageEnabler(buildTool, ccTool) {
1668
- this.buildTool = buildTool;
1669
- this.ccTool = ccTool;
1670
- }
1671
- CodeCoverageEnabler.prototype.enableCodeCoverage = function (buildProps) {
1672
- buildProps['buildtool'] = this.buildTool;
1673
- buildProps['codecoveragetool'] = this.ccTool;
1674
- exports.command('codecoverage.enable', buildProps, "");
1675
- };
1676
- return CodeCoverageEnabler;
1677
- }());
1678
- exports.CodeCoverageEnabler = CodeCoverageEnabler;
1679
- //-----------------------------------------------------
1680
- // Task Logging Commands
1681
- //-----------------------------------------------------
1682
- /**
1683
- * Upload user interested file as additional log information
1684
- * to the current timeline record.
1685
- *
1686
- * The file shall be available for download along with task logs.
1687
- *
1688
- * @param path Path to the file that should be uploaded.
1689
- * @returns void
1690
- */
1691
- function uploadFile(path) {
1692
- exports.command("task.uploadfile", null, path);
1693
- }
1694
- exports.uploadFile = uploadFile;
1695
- /**
1696
- * Instruction for the agent to update the PATH environment variable.
1697
- * The specified directory is prepended to the PATH.
1698
- * The updated environment variable will be reflected in subsequent tasks.
1699
- *
1700
- * @param path Local directory path.
1701
- * @returns void
1702
- */
1703
- function prependPath(path) {
1704
- assertAgent("2.115.0");
1705
- exports.command("task.prependpath", null, path);
1706
- }
1707
- exports.prependPath = prependPath;
1708
- /**
1709
- * Upload and attach summary markdown to current timeline record.
1710
- * This summary shall be added to the build/release summary and
1711
- * not available for download with logs.
1712
- *
1713
- * @param path Local directory path.
1714
- * @returns void
1715
- */
1716
- function uploadSummary(path) {
1717
- exports.command("task.uploadsummary", null, path);
1718
- }
1719
- exports.uploadSummary = uploadSummary;
1720
- /**
1721
- * Upload and attach attachment to current timeline record.
1722
- * These files are not available for download with logs.
1723
- * These can only be referred to by extensions using the type or name values.
1724
- *
1725
- * @param type Attachment type.
1726
- * @param name Attachment name.
1727
- * @param path Attachment path.
1728
- * @returns void
1729
- */
1730
- function addAttachment(type, name, path) {
1731
- exports.command("task.addattachment", { "type": type, "name": name }, path);
1732
- }
1733
- exports.addAttachment = addAttachment;
1734
- /**
1735
- * Set an endpoint field with given value.
1736
- * Value updated will be retained in the endpoint for
1737
- * the subsequent tasks that execute within the same job.
1738
- *
1739
- * @param id Endpoint id.
1740
- * @param field FieldType enum of AuthParameter, DataParameter or Url.
1741
- * @param key Key.
1742
- * @param value Value for key or url.
1743
- * @returns void
1744
- */
1745
- function setEndpoint(id, field, key, value) {
1746
- exports.command("task.setendpoint", { "id": id, "field": FieldType[field].toLowerCase(), "key": key }, value);
1747
- }
1748
- exports.setEndpoint = setEndpoint;
1749
- /**
1750
- * Set progress and current operation for current task.
1751
- *
1752
- * @param percent Percentage of completion.
1753
- * @param currentOperation Current pperation.
1754
- * @returns void
1755
- */
1756
- function setProgress(percent, currentOperation) {
1757
- exports.command("task.setprogress", { "value": "" + percent }, currentOperation);
1758
- }
1759
- exports.setProgress = setProgress;
1760
- /**
1761
- * Indicates whether to write the logging command directly to the host or to the output pipeline.
1762
- *
1763
- * @param id Timeline record Guid.
1764
- * @param parentId Parent timeline record Guid.
1765
- * @param recordType Record type.
1766
- * @param recordName Record name.
1767
- * @param order Order of timeline record.
1768
- * @param startTime Start time.
1769
- * @param finishTime End time.
1770
- * @param progress Percentage of completion.
1771
- * @param state TaskState enum of Unknown, Initialized, InProgress or Completed.
1772
- * @param result TaskResult enum of Succeeded, SucceededWithIssues, Failed, Cancelled or Skipped.
1773
- * @param message current operation
1774
- * @returns void
1775
- */
1776
- function logDetail(id, message, parentId, recordType, recordName, order, startTime, finishTime, progress, state, result) {
1777
- var properties = {
1778
- "id": id,
1779
- "parentid": parentId,
1780
- "type": recordType,
1781
- "name": recordName,
1782
- "order": order ? order.toString() : undefined,
1783
- "starttime": startTime,
1784
- "finishtime": finishTime,
1785
- "progress": progress ? progress.toString() : undefined,
1786
- "state": state ? TaskState[state] : undefined,
1787
- "result": result ? TaskResult[result] : undefined
1788
- };
1789
- exports.command("task.logdetail", properties, message);
1790
- }
1791
- exports.logDetail = logDetail;
1792
- /**
1793
- * Log error or warning issue to timeline record of current task.
1794
- *
1795
- * @param type IssueType enum of Error or Warning.
1796
- * @param sourcePath Source file location.
1797
- * @param lineNumber Line number.
1798
- * @param columnNumber Column number.
1799
- * @param code Error or warning code.
1800
- * @param message Error or warning message.
1801
- * @returns void
1802
- */
1803
- function logIssue(type, message, sourcePath, lineNumber, columnNumber, errorCode) {
1804
- var properties = {
1805
- "type": IssueType[type].toLowerCase(),
1806
- "code": errorCode,
1807
- "sourcepath": sourcePath,
1808
- "linenumber": lineNumber ? lineNumber.toString() : undefined,
1809
- "columnnumber": columnNumber ? columnNumber.toString() : undefined,
1810
- };
1811
- exports.command("task.logissue", properties, message);
1812
- }
1813
- exports.logIssue = logIssue;
1814
- //-----------------------------------------------------
1815
- // Artifact Logging Commands
1816
- //-----------------------------------------------------
1817
- /**
1818
- * Upload user interested file as additional log information
1819
- * to the current timeline record.
1820
- *
1821
- * The file shall be available for download along with task logs.
1822
- *
1823
- * @param containerFolder Folder that the file will upload to, folder will be created if needed.
1824
- * @param path Path to the file that should be uploaded.
1825
- * @param name Artifact name.
1826
- * @returns void
1827
- */
1828
- function uploadArtifact(containerFolder, path, name) {
1829
- exports.command("artifact.upload", { "containerfolder": containerFolder, "artifactname": name }, path);
1830
- }
1831
- exports.uploadArtifact = uploadArtifact;
1832
- /**
1833
- * Create an artifact link, artifact location is required to be
1834
- * a file container path, VC path or UNC share path.
1835
- *
1836
- * The file shall be available for download along with task logs.
1837
- *
1838
- * @param name Artifact name.
1839
- * @param path Path to the file that should be associated.
1840
- * @param artifactType ArtifactType enum of Container, FilePath, VersionControl, GitRef or TfvcLabel.
1841
- * @returns void
1842
- */
1843
- function associateArtifact(name, path, artifactType) {
1844
- exports.command("artifact.associate", { "type": ArtifactType[artifactType].toLowerCase(), "artifactname": name }, path);
1845
- }
1846
- exports.associateArtifact = associateArtifact;
1847
- //-----------------------------------------------------
1848
- // Build Logging Commands
1849
- //-----------------------------------------------------
1850
- /**
1851
- * Upload user interested log to build’s container “logs\tool” folder.
1852
- *
1853
- * @param path Path to the file that should be uploaded.
1854
- * @returns void
1855
- */
1856
- function uploadBuildLog(path) {
1857
- exports.command("build.uploadlog", null, path);
1858
- }
1859
- exports.uploadBuildLog = uploadBuildLog;
1860
- /**
1861
- * Update build number for current build.
1862
- *
1863
- * @param value Value to be assigned as the build number.
1864
- * @returns void
1865
- */
1866
- function updateBuildNumber(value) {
1867
- exports.command("build.updatebuildnumber", null, value);
1868
- }
1869
- exports.updateBuildNumber = updateBuildNumber;
1870
- /**
1871
- * Add a tag for current build.
1872
- *
1873
- * @param value Tag value.
1874
- * @returns void
1875
- */
1876
- function addBuildTag(value) {
1877
- exports.command("build.addbuildtag", null, value);
1878
- }
1879
- exports.addBuildTag = addBuildTag;
1880
- //-----------------------------------------------------
1881
- // Release Logging Commands
1882
- //-----------------------------------------------------
1883
- /**
1884
- * Update release name for current release.
1885
- *
1886
- * @param value Value to be assigned as the release name.
1887
- * @returns void
1888
- */
1889
- function updateReleaseName(name) {
1890
- assertAgent("2.132.0");
1891
- exports.command("release.updatereleasename", null, name);
1892
- }
1893
- exports.updateReleaseName = updateReleaseName;
1894
- //-----------------------------------------------------
1895
- // Tools
1896
- //-----------------------------------------------------
1897
- exports.TaskCommand = tcm.TaskCommand;
1898
- exports.commandFromString = tcm.commandFromString;
1899
- exports.ToolRunner = trm.ToolRunner;
1900
- //-----------------------------------------------------
1901
- // Validation Checks
1902
- //-----------------------------------------------------
1903
- // async await needs generators in node 4.x+
1904
- if (semver.lt(process.versions.node, '4.2.0')) {
1905
- exports.warning('Tasks require a new agent. Upgrade your agent or node to 4.2.0 or later');
1906
- }
1907
- //-------------------------------------------------------------------
1908
- // Populate the vault with sensitive data. Inputs and Endpoints
1909
- //-------------------------------------------------------------------
1910
- // avoid loading twice (overwrites .taskkey)
1911
- if (!global['_vsts_task_lib_loaded']) {
1912
- im._loadData();
1913
- im._exposeProxySettings();
1914
- im._exposeCertSettings();
1915
- }
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.updateReleaseName = exports.addBuildTag = exports.updateBuildNumber = exports.uploadBuildLog = exports.associateArtifact = exports.uploadArtifact = exports.logIssue = exports.logDetail = exports.setProgress = exports.setEndpoint = exports.addAttachment = exports.uploadSummary = exports.prependPath = exports.uploadFile = exports.CodeCoverageEnabler = exports.CodeCoveragePublisher = exports.TestPublisher = exports.getHttpCertConfiguration = exports.getHttpProxyConfiguration = exports.findMatch = exports.filter = exports.match = exports.tool = exports.execSync = exports.exec = exports.rmRF = exports.legacyFindFiles = exports.find = exports.retry = exports.mv = exports.cp = exports.ls = exports.which = exports.resolve = exports.mkdirP = exports.popd = exports.pushd = exports.cd = exports.checkPath = exports.cwd = exports.getPlatform = exports.osType = exports.writeFile = exports.exist = exports.stats = exports.debug = exports.error = exports.warning = exports.command = exports.setTaskVariable = exports.getTaskVariable = exports.getSecureFileTicket = exports.getSecureFileName = exports.getEndpointAuthorization = exports.getEndpointAuthorizationParameterRequired = exports.getEndpointAuthorizationParameter = exports.getEndpointAuthorizationSchemeRequired = exports.getEndpointAuthorizationScheme = exports.getEndpointDataParameterRequired = exports.getEndpointDataParameter = exports.getEndpointUrlRequired = exports.getEndpointUrl = exports.getPathInputRequired = exports.getPathInput = exports.filePathSupplied = exports.getDelimitedInput = exports.getBoolInput = exports.getInputRequired = exports.getInput = exports.setSecret = exports.setVariable = exports.getVariables = exports.assertAgent = exports.getVariable = exports.loc = exports.setResourcePath = exports.setResult = exports.setErrStream = exports.setStdStream = exports.Platform = exports.FieldType = exports.ArtifactType = exports.IssueType = exports.TaskState = exports.TaskResult = void 0;
4
+ var shell = require("shelljs");
5
+ var childProcess = require("child_process");
6
+ var fs = require("fs");
7
+ var path = require("path");
8
+ var os = require("os");
9
+ var minimatch = require("minimatch");
10
+ var im = require("./internal");
11
+ var tcm = require("./taskcommand");
12
+ var trm = require("./toolrunner");
13
+ var semver = require("semver");
14
+ var TaskResult;
15
+ (function (TaskResult) {
16
+ TaskResult[TaskResult["Succeeded"] = 0] = "Succeeded";
17
+ TaskResult[TaskResult["SucceededWithIssues"] = 1] = "SucceededWithIssues";
18
+ TaskResult[TaskResult["Failed"] = 2] = "Failed";
19
+ TaskResult[TaskResult["Cancelled"] = 3] = "Cancelled";
20
+ TaskResult[TaskResult["Skipped"] = 4] = "Skipped";
21
+ })(TaskResult = exports.TaskResult || (exports.TaskResult = {}));
22
+ var TaskState;
23
+ (function (TaskState) {
24
+ TaskState[TaskState["Unknown"] = 0] = "Unknown";
25
+ TaskState[TaskState["Initialized"] = 1] = "Initialized";
26
+ TaskState[TaskState["InProgress"] = 2] = "InProgress";
27
+ TaskState[TaskState["Completed"] = 3] = "Completed";
28
+ })(TaskState = exports.TaskState || (exports.TaskState = {}));
29
+ var IssueType;
30
+ (function (IssueType) {
31
+ IssueType[IssueType["Error"] = 0] = "Error";
32
+ IssueType[IssueType["Warning"] = 1] = "Warning";
33
+ })(IssueType = exports.IssueType || (exports.IssueType = {}));
34
+ var ArtifactType;
35
+ (function (ArtifactType) {
36
+ ArtifactType[ArtifactType["Container"] = 0] = "Container";
37
+ ArtifactType[ArtifactType["FilePath"] = 1] = "FilePath";
38
+ ArtifactType[ArtifactType["VersionControl"] = 2] = "VersionControl";
39
+ ArtifactType[ArtifactType["GitRef"] = 3] = "GitRef";
40
+ ArtifactType[ArtifactType["TfvcLabel"] = 4] = "TfvcLabel";
41
+ })(ArtifactType = exports.ArtifactType || (exports.ArtifactType = {}));
42
+ var FieldType;
43
+ (function (FieldType) {
44
+ FieldType[FieldType["AuthParameter"] = 0] = "AuthParameter";
45
+ FieldType[FieldType["DataParameter"] = 1] = "DataParameter";
46
+ FieldType[FieldType["Url"] = 2] = "Url";
47
+ })(FieldType = exports.FieldType || (exports.FieldType = {}));
48
+ /** Platforms supported by our build agent */
49
+ var Platform;
50
+ (function (Platform) {
51
+ Platform[Platform["Windows"] = 0] = "Windows";
52
+ Platform[Platform["MacOS"] = 1] = "MacOS";
53
+ Platform[Platform["Linux"] = 2] = "Linux";
54
+ })(Platform = exports.Platform || (exports.Platform = {}));
55
+ //-----------------------------------------------------
56
+ // General Helpers
57
+ //-----------------------------------------------------
58
+ exports.setStdStream = im._setStdStream;
59
+ exports.setErrStream = im._setErrStream;
60
+ //-----------------------------------------------------
61
+ // Results
62
+ //-----------------------------------------------------
63
+ /**
64
+ * Sets the result of the task.
65
+ * Execution will continue.
66
+ * If not set, task will be Succeeded.
67
+ * If multiple calls are made to setResult the most pessimistic call wins (Failed) regardless of the order of calls.
68
+ *
69
+ * @param result TaskResult enum of Succeeded, SucceededWithIssues, Failed, Cancelled or Skipped.
70
+ * @param message A message which will be logged as an error issue if the result is Failed.
71
+ * @param done Optional. Instructs the agent the task is done. This is helpful when child processes
72
+ * may still be running and prevent node from fully exiting. This argument is supported
73
+ * from agent version 2.142.0 or higher (otherwise will no-op).
74
+ * @returns void
75
+ */
76
+ function setResult(result, message, done) {
77
+ exports.debug('task result: ' + TaskResult[result]);
78
+ // add an error issue
79
+ if (result == TaskResult.Failed && message) {
80
+ exports.error(message);
81
+ }
82
+ else if (result == TaskResult.SucceededWithIssues && message) {
83
+ exports.warning(message);
84
+ }
85
+ // task.complete
86
+ var properties = { 'result': TaskResult[result] };
87
+ if (done) {
88
+ properties['done'] = 'true';
89
+ }
90
+ exports.command('task.complete', properties, message);
91
+ }
92
+ exports.setResult = setResult;
93
+ //
94
+ // Catching all exceptions
95
+ //
96
+ process.on('uncaughtException', function (err) {
97
+ setResult(TaskResult.Failed, exports.loc('LIB_UnhandledEx', err.message));
98
+ });
99
+ //-----------------------------------------------------
100
+ // Loc Helpers
101
+ //-----------------------------------------------------
102
+ exports.setResourcePath = im._setResourcePath;
103
+ exports.loc = im._loc;
104
+ //-----------------------------------------------------
105
+ // Input Helpers
106
+ //-----------------------------------------------------
107
+ exports.getVariable = im._getVariable;
108
+ /**
109
+ * Asserts the agent version is at least the specified minimum.
110
+ *
111
+ * @param minimum minimum version version - must be 2.104.1 or higher
112
+ */
113
+ function assertAgent(minimum) {
114
+ if (semver.lt(minimum, '2.104.1')) {
115
+ throw new Error('assertAgent() requires the parameter to be 2.104.1 or higher');
116
+ }
117
+ var agent = exports.getVariable('Agent.Version');
118
+ if (agent && semver.lt(agent, minimum)) {
119
+ throw new Error("Agent version " + minimum + " or higher is required");
120
+ }
121
+ }
122
+ exports.assertAgent = assertAgent;
123
+ /**
124
+ * Gets a snapshot of the current state of all job variables available to the task.
125
+ * Requires a 2.104.1 agent or higher for full functionality.
126
+ *
127
+ * Limitations on an agent prior to 2.104.1:
128
+ * 1) The return value does not include all public variables. Only public variables
129
+ * that have been added using setVariable are returned.
130
+ * 2) The name returned for each secret variable is the formatted environment variable
131
+ * name, not the actual variable name (unless it was set explicitly at runtime using
132
+ * setVariable).
133
+ *
134
+ * @returns VariableInfo[]
135
+ */
136
+ function getVariables() {
137
+ return Object.keys(im._knownVariableMap)
138
+ .map(function (key) {
139
+ var info = im._knownVariableMap[key];
140
+ return { name: info.name, value: exports.getVariable(info.name), secret: info.secret };
141
+ });
142
+ }
143
+ exports.getVariables = getVariables;
144
+ /**
145
+ * Sets a variable which will be available to subsequent tasks as well.
146
+ *
147
+ * @param name name of the variable to set
148
+ * @param val value to set
149
+ * @param secret whether variable is secret. Multi-line secrets are not allowed. Optional, defaults to false
150
+ * @param isOutput whether variable is an output variable. Optional, defaults to false
151
+ * @returns void
152
+ */
153
+ function setVariable(name, val, secret, isOutput) {
154
+ if (secret === void 0) { secret = false; }
155
+ if (isOutput === void 0) { isOutput = false; }
156
+ // once a secret always a secret
157
+ var key = im._getVariableKey(name);
158
+ if (im._knownVariableMap.hasOwnProperty(key)) {
159
+ secret = secret || im._knownVariableMap[key].secret;
160
+ }
161
+ // store the value
162
+ var varValue = val || '';
163
+ exports.debug('set ' + name + '=' + (secret && varValue ? '********' : varValue));
164
+ if (secret) {
165
+ if (varValue && varValue.match(/\r|\n/) && ("" + process.env['SYSTEM_UNSAFEALLOWMULTILINESECRET']).toUpperCase() != 'TRUE') {
166
+ throw new Error(exports.loc('LIB_MultilineSecret'));
167
+ }
168
+ im._vault.storeSecret('SECRET_' + key, varValue);
169
+ delete process.env[key];
170
+ }
171
+ else {
172
+ process.env[key] = varValue;
173
+ }
174
+ // store the metadata
175
+ im._knownVariableMap[key] = { name: name, secret: secret };
176
+ // write the setvariable command
177
+ exports.command('task.setvariable', { 'variable': name || '', isOutput: (isOutput || false).toString(), 'issecret': (secret || false).toString() }, varValue);
178
+ }
179
+ exports.setVariable = setVariable;
180
+ /**
181
+ * Registers a value with the logger, so the value will be masked from the logs. Multi-line secrets are not allowed.
182
+ *
183
+ * @param val value to register
184
+ */
185
+ function setSecret(val) {
186
+ if (val) {
187
+ if (val.match(/\r|\n/) && ("" + process.env['SYSTEM_UNSAFEALLOWMULTILINESECRET']).toUpperCase() !== 'TRUE') {
188
+ throw new Error(exports.loc('LIB_MultilineSecret'));
189
+ }
190
+ exports.command('task.setsecret', {}, val);
191
+ }
192
+ }
193
+ exports.setSecret = setSecret;
194
+ /**
195
+ * Gets the value of an input.
196
+ * If required is true and the value is not set, it will throw.
197
+ *
198
+ * @param name name of the input to get
199
+ * @param required whether input is required. optional, defaults to false
200
+ * @returns string
201
+ */
202
+ function getInput(name, required) {
203
+ var inval = im._vault.retrieveSecret('INPUT_' + im._getVariableKey(name));
204
+ if (required && !inval) {
205
+ throw new Error(exports.loc('LIB_InputRequired', name));
206
+ }
207
+ exports.debug(name + '=' + inval);
208
+ return inval;
209
+ }
210
+ exports.getInput = getInput;
211
+ /**
212
+ * Gets the value of an input.
213
+ * If the value is not set, it will throw.
214
+ *
215
+ * @param name name of the input to get
216
+ * @returns string
217
+ */
218
+ function getInputRequired(name) {
219
+ return getInput(name, true);
220
+ }
221
+ exports.getInputRequired = getInputRequired;
222
+ /**
223
+ * Gets the value of an input and converts to a bool. Convenience.
224
+ * If required is true and the value is not set, it will throw.
225
+ * If required is false and the value is not set, returns false.
226
+ *
227
+ * @param name name of the bool input to get
228
+ * @param required whether input is required. optional, defaults to false
229
+ * @returns boolean
230
+ */
231
+ function getBoolInput(name, required) {
232
+ return (getInput(name, required) || '').toUpperCase() == "TRUE";
233
+ }
234
+ exports.getBoolInput = getBoolInput;
235
+ /**
236
+ * Gets the value of an input and splits the value using a delimiter (space, comma, etc).
237
+ * Empty values are removed. This function is useful for splitting an input containing a simple
238
+ * list of items - such as build targets.
239
+ * IMPORTANT: Do not use this function for splitting additional args! Instead use argString(), which
240
+ * follows normal argument splitting rules and handles values encapsulated by quotes.
241
+ * If required is true and the value is not set, it will throw.
242
+ *
243
+ * @param name name of the input to get
244
+ * @param delim delimiter to split on
245
+ * @param required whether input is required. optional, defaults to false
246
+ * @returns string[]
247
+ */
248
+ function getDelimitedInput(name, delim, required) {
249
+ var inputVal = getInput(name, required);
250
+ if (!inputVal) {
251
+ return [];
252
+ }
253
+ var result = [];
254
+ inputVal.split(delim).forEach(function (x) {
255
+ if (x) {
256
+ result.push(x);
257
+ }
258
+ });
259
+ return result;
260
+ }
261
+ exports.getDelimitedInput = getDelimitedInput;
262
+ /**
263
+ * Checks whether a path inputs value was supplied by the user
264
+ * File paths are relative with a picker, so an empty path is the root of the repo.
265
+ * Useful if you need to condition work (like append an arg) if a value was supplied
266
+ *
267
+ * @param name name of the path input to check
268
+ * @returns boolean
269
+ */
270
+ function filePathSupplied(name) {
271
+ // normalize paths
272
+ var pathValue = this.resolve(this.getPathInput(name) || '');
273
+ var repoRoot = this.resolve(exports.getVariable('build.sourcesDirectory') || exports.getVariable('system.defaultWorkingDirectory') || '');
274
+ var supplied = pathValue !== repoRoot;
275
+ exports.debug(name + 'path supplied :' + supplied);
276
+ return supplied;
277
+ }
278
+ exports.filePathSupplied = filePathSupplied;
279
+ /**
280
+ * Gets the value of a path input
281
+ * It will be quoted for you if it isn't already and contains spaces
282
+ * If required is true and the value is not set, it will throw.
283
+ * If check is true and the path does not exist, it will throw.
284
+ *
285
+ * @param name name of the input to get
286
+ * @param required whether input is required. optional, defaults to false
287
+ * @param check whether path is checked. optional, defaults to false
288
+ * @returns string
289
+ */
290
+ function getPathInput(name, required, check) {
291
+ var inval = getInput(name, required);
292
+ if (inval) {
293
+ if (check) {
294
+ exports.checkPath(inval, name);
295
+ }
296
+ }
297
+ return inval;
298
+ }
299
+ exports.getPathInput = getPathInput;
300
+ /**
301
+ * Gets the value of a path input
302
+ * It will be quoted for you if it isn't already and contains spaces
303
+ * If the value is not set, it will throw.
304
+ * If check is true and the path does not exist, it will throw.
305
+ *
306
+ * @param name name of the input to get
307
+ * @param check whether path is checked. optional, defaults to false
308
+ * @returns string
309
+ */
310
+ function getPathInputRequired(name, check) {
311
+ return getPathInput(name, true, check);
312
+ }
313
+ exports.getPathInputRequired = getPathInputRequired;
314
+ //-----------------------------------------------------
315
+ // Endpoint Helpers
316
+ //-----------------------------------------------------
317
+ /**
318
+ * Gets the url for a service endpoint
319
+ * If the url was not set and is not optional, it will throw.
320
+ *
321
+ * @param id name of the service endpoint
322
+ * @param optional whether the url is optional
323
+ * @returns string
324
+ */
325
+ function getEndpointUrl(id, optional) {
326
+ var urlval = process.env['ENDPOINT_URL_' + id];
327
+ if (!optional && !urlval) {
328
+ throw new Error(exports.loc('LIB_EndpointNotExist', id));
329
+ }
330
+ exports.debug(id + '=' + urlval);
331
+ return urlval;
332
+ }
333
+ exports.getEndpointUrl = getEndpointUrl;
334
+ /**
335
+ * Gets the url for a service endpoint
336
+ * If the url was not set, it will throw.
337
+ *
338
+ * @param id name of the service endpoint
339
+ * @returns string
340
+ */
341
+ function getEndpointUrlRequired(id) {
342
+ return getEndpointUrl(id, false);
343
+ }
344
+ exports.getEndpointUrlRequired = getEndpointUrlRequired;
345
+ /*
346
+ * Gets the endpoint data parameter value with specified key for a service endpoint
347
+ * If the endpoint data parameter was not set and is not optional, it will throw.
348
+ *
349
+ * @param id name of the service endpoint
350
+ * @param key of the parameter
351
+ * @param optional whether the endpoint data is optional
352
+ * @returns {string} value of the endpoint data parameter
353
+ */
354
+ function getEndpointDataParameter(id, key, optional) {
355
+ var dataParamVal = process.env['ENDPOINT_DATA_' + id + '_' + key.toUpperCase()];
356
+ if (!optional && !dataParamVal) {
357
+ throw new Error(exports.loc('LIB_EndpointDataNotExist', id, key));
358
+ }
359
+ exports.debug(id + ' data ' + key + ' = ' + dataParamVal);
360
+ return dataParamVal;
361
+ }
362
+ exports.getEndpointDataParameter = getEndpointDataParameter;
363
+ /*
364
+ * Gets the endpoint data parameter value with specified key for a service endpoint
365
+ * If the endpoint data parameter was not set, it will throw.
366
+ *
367
+ * @param id name of the service endpoint
368
+ * @param key of the parameter
369
+ * @returns {string} value of the endpoint data parameter
370
+ */
371
+ function getEndpointDataParameterRequired(id, key) {
372
+ return getEndpointDataParameter(id, key, false);
373
+ }
374
+ exports.getEndpointDataParameterRequired = getEndpointDataParameterRequired;
375
+ /**
376
+ * Gets the endpoint authorization scheme for a service endpoint
377
+ * If the endpoint authorization scheme is not set and is not optional, it will throw.
378
+ *
379
+ * @param id name of the service endpoint
380
+ * @param optional whether the endpoint authorization scheme is optional
381
+ * @returns {string} value of the endpoint authorization scheme
382
+ */
383
+ function getEndpointAuthorizationScheme(id, optional) {
384
+ var authScheme = im._vault.retrieveSecret('ENDPOINT_AUTH_SCHEME_' + id);
385
+ if (!optional && !authScheme) {
386
+ throw new Error(exports.loc('LIB_EndpointAuthNotExist', id));
387
+ }
388
+ exports.debug(id + ' auth scheme = ' + authScheme);
389
+ return authScheme;
390
+ }
391
+ exports.getEndpointAuthorizationScheme = getEndpointAuthorizationScheme;
392
+ /**
393
+ * Gets the endpoint authorization scheme for a service endpoint
394
+ * If the endpoint authorization scheme is not set, it will throw.
395
+ *
396
+ * @param id name of the service endpoint
397
+ * @returns {string} value of the endpoint authorization scheme
398
+ */
399
+ function getEndpointAuthorizationSchemeRequired(id) {
400
+ return getEndpointAuthorizationScheme(id, false);
401
+ }
402
+ exports.getEndpointAuthorizationSchemeRequired = getEndpointAuthorizationSchemeRequired;
403
+ /**
404
+ * Gets the endpoint authorization parameter value for a service endpoint with specified key
405
+ * If the endpoint authorization parameter is not set and is not optional, it will throw.
406
+ *
407
+ * @param id name of the service endpoint
408
+ * @param key key to find the endpoint authorization parameter
409
+ * @param optional optional whether the endpoint authorization scheme is optional
410
+ * @returns {string} value of the endpoint authorization parameter value
411
+ */
412
+ function getEndpointAuthorizationParameter(id, key, optional) {
413
+ var authParam = im._vault.retrieveSecret('ENDPOINT_AUTH_PARAMETER_' + id + '_' + key.toUpperCase());
414
+ if (!optional && !authParam) {
415
+ throw new Error(exports.loc('LIB_EndpointAuthNotExist', id));
416
+ }
417
+ exports.debug(id + ' auth param ' + key + ' = ' + authParam);
418
+ return authParam;
419
+ }
420
+ exports.getEndpointAuthorizationParameter = getEndpointAuthorizationParameter;
421
+ /**
422
+ * Gets the endpoint authorization parameter value for a service endpoint with specified key
423
+ * If the endpoint authorization parameter is not set, it will throw.
424
+ *
425
+ * @param id name of the service endpoint
426
+ * @param key key to find the endpoint authorization parameter
427
+ * @returns {string} value of the endpoint authorization parameter value
428
+ */
429
+ function getEndpointAuthorizationParameterRequired(id, key) {
430
+ return getEndpointAuthorizationParameter(id, key, false);
431
+ }
432
+ exports.getEndpointAuthorizationParameterRequired = getEndpointAuthorizationParameterRequired;
433
+ /**
434
+ * Gets the authorization details for a service endpoint
435
+ * If the authorization was not set and is not optional, it will set the task result to Failed.
436
+ *
437
+ * @param id name of the service endpoint
438
+ * @param optional whether the url is optional
439
+ * @returns string
440
+ */
441
+ function getEndpointAuthorization(id, optional) {
442
+ var aval = im._vault.retrieveSecret('ENDPOINT_AUTH_' + id);
443
+ if (!optional && !aval) {
444
+ setResult(TaskResult.Failed, exports.loc('LIB_EndpointAuthNotExist', id));
445
+ }
446
+ exports.debug(id + ' exists ' + (!!aval));
447
+ var auth;
448
+ try {
449
+ if (aval) {
450
+ auth = JSON.parse(aval);
451
+ }
452
+ }
453
+ catch (err) {
454
+ throw new Error(exports.loc('LIB_InvalidEndpointAuth', aval));
455
+ }
456
+ return auth;
457
+ }
458
+ exports.getEndpointAuthorization = getEndpointAuthorization;
459
+ //-----------------------------------------------------
460
+ // SecureFile Helpers
461
+ //-----------------------------------------------------
462
+ /**
463
+ * Gets the name for a secure file
464
+ *
465
+ * @param id secure file id
466
+ * @returns string
467
+ */
468
+ function getSecureFileName(id) {
469
+ var name = process.env['SECUREFILE_NAME_' + id];
470
+ exports.debug('secure file name for id ' + id + ' = ' + name);
471
+ return name;
472
+ }
473
+ exports.getSecureFileName = getSecureFileName;
474
+ /**
475
+ * Gets the secure file ticket that can be used to download the secure file contents
476
+ *
477
+ * @param id name of the secure file
478
+ * @returns {string} secure file ticket
479
+ */
480
+ function getSecureFileTicket(id) {
481
+ var ticket = im._vault.retrieveSecret('SECUREFILE_TICKET_' + id);
482
+ exports.debug('secure file ticket for id ' + id + ' = ' + ticket);
483
+ return ticket;
484
+ }
485
+ exports.getSecureFileTicket = getSecureFileTicket;
486
+ //-----------------------------------------------------
487
+ // Task Variable Helpers
488
+ //-----------------------------------------------------
489
+ /**
490
+ * Gets a variable value that is set by previous step from the same wrapper task.
491
+ * Requires a 2.115.0 agent or higher.
492
+ *
493
+ * @param name name of the variable to get
494
+ * @returns string
495
+ */
496
+ function getTaskVariable(name) {
497
+ assertAgent('2.115.0');
498
+ var inval = im._vault.retrieveSecret('VSTS_TASKVARIABLE_' + im._getVariableKey(name));
499
+ if (inval) {
500
+ inval = inval.trim();
501
+ }
502
+ exports.debug('task variable: ' + name + '=' + inval);
503
+ return inval;
504
+ }
505
+ exports.getTaskVariable = getTaskVariable;
506
+ /**
507
+ * Sets a task variable which will only be available to subsequent steps belong to the same wrapper task.
508
+ * Requires a 2.115.0 agent or higher.
509
+ *
510
+ * @param name name of the variable to set
511
+ * @param val value to set
512
+ * @param secret whether variable is secret. optional, defaults to false
513
+ * @returns void
514
+ */
515
+ function setTaskVariable(name, val, secret) {
516
+ if (secret === void 0) { secret = false; }
517
+ assertAgent('2.115.0');
518
+ var key = im._getVariableKey(name);
519
+ // store the value
520
+ var varValue = val || '';
521
+ exports.debug('set task variable: ' + name + '=' + (secret && varValue ? '********' : varValue));
522
+ im._vault.storeSecret('VSTS_TASKVARIABLE_' + key, varValue);
523
+ delete process.env[key];
524
+ // write the command
525
+ exports.command('task.settaskvariable', { 'variable': name || '', 'issecret': (secret || false).toString() }, varValue);
526
+ }
527
+ exports.setTaskVariable = setTaskVariable;
528
+ //-----------------------------------------------------
529
+ // Cmd Helpers
530
+ //-----------------------------------------------------
531
+ exports.command = im._command;
532
+ exports.warning = im._warning;
533
+ exports.error = im._error;
534
+ exports.debug = im._debug;
535
+ //-----------------------------------------------------
536
+ // Disk Functions
537
+ //-----------------------------------------------------
538
+ function _checkShell(cmd, continueOnError) {
539
+ var se = shell.error();
540
+ if (se) {
541
+ exports.debug(cmd + ' failed');
542
+ var errMsg = exports.loc('LIB_OperationFailed', cmd, se);
543
+ exports.debug(errMsg);
544
+ if (!continueOnError) {
545
+ throw new Error(errMsg);
546
+ }
547
+ }
548
+ }
549
+ /**
550
+ * Get's stat on a path.
551
+ * Useful for checking whether a file or directory. Also getting created, modified and accessed time.
552
+ * see [fs.stat](https://nodejs.org/api/fs.html#fs_class_fs_stats)
553
+ *
554
+ * @param path path to check
555
+ * @returns fsStat
556
+ */
557
+ function stats(path) {
558
+ return fs.statSync(path);
559
+ }
560
+ exports.stats = stats;
561
+ exports.exist = im._exist;
562
+ function writeFile(file, data, options) {
563
+ if (typeof (options) === 'string') {
564
+ fs.writeFileSync(file, data, { encoding: options });
565
+ }
566
+ else {
567
+ fs.writeFileSync(file, data, options);
568
+ }
569
+ }
570
+ exports.writeFile = writeFile;
571
+ /**
572
+ * @deprecated Use `getPlatform`
573
+ * Useful for determining the host operating system.
574
+ * see [os.type](https://nodejs.org/api/os.html#os_os_type)
575
+ *
576
+ * @return the name of the operating system
577
+ */
578
+ function osType() {
579
+ return os.type();
580
+ }
581
+ exports.osType = osType;
582
+ /**
583
+ * Determine the operating system the build agent is running on.
584
+ * @returns {Platform}
585
+ * @throws {Error} Platform is not supported by our agent
586
+ */
587
+ function getPlatform() {
588
+ switch (process.platform) {
589
+ case 'win32': return Platform.Windows;
590
+ case 'darwin': return Platform.MacOS;
591
+ case 'linux': return Platform.Linux;
592
+ default: throw Error(exports.loc('LIB_PlatformNotSupported', process.platform));
593
+ }
594
+ }
595
+ exports.getPlatform = getPlatform;
596
+ /**
597
+ * Returns the process's current working directory.
598
+ * see [process.cwd](https://nodejs.org/api/process.html#process_process_cwd)
599
+ *
600
+ * @return the path to the current working directory of the process
601
+ */
602
+ function cwd() {
603
+ return process.cwd();
604
+ }
605
+ exports.cwd = cwd;
606
+ exports.checkPath = im._checkPath;
607
+ /**
608
+ * Change working directory.
609
+ *
610
+ * @param path new working directory path
611
+ * @returns void
612
+ */
613
+ function cd(path) {
614
+ if (path) {
615
+ shell.cd(path);
616
+ _checkShell('cd');
617
+ }
618
+ }
619
+ exports.cd = cd;
620
+ /**
621
+ * Change working directory and push it on the stack
622
+ *
623
+ * @param path new working directory path
624
+ * @returns void
625
+ */
626
+ function pushd(path) {
627
+ shell.pushd(path);
628
+ _checkShell('pushd');
629
+ }
630
+ exports.pushd = pushd;
631
+ /**
632
+ * Change working directory back to previously pushed directory
633
+ *
634
+ * @returns void
635
+ */
636
+ function popd() {
637
+ shell.popd();
638
+ _checkShell('popd');
639
+ }
640
+ exports.popd = popd;
641
+ /**
642
+ * Make a directory. Creates the full path with folders in between
643
+ * Will throw if it fails
644
+ *
645
+ * @param p path to create
646
+ * @returns void
647
+ */
648
+ function mkdirP(p) {
649
+ if (!p) {
650
+ throw new Error(exports.loc('LIB_ParameterIsRequired', 'p'));
651
+ }
652
+ // build a stack of directories to create
653
+ var stack = [];
654
+ var testDir = p;
655
+ while (true) {
656
+ // validate the loop is not out of control
657
+ if (stack.length >= (process.env['TASKLIB_TEST_MKDIRP_FAILSAFE'] || 1000)) {
658
+ // let the framework throw
659
+ exports.debug('loop is out of control');
660
+ fs.mkdirSync(p);
661
+ return;
662
+ }
663
+ exports.debug("testing directory '" + testDir + "'");
664
+ var stats_1 = void 0;
665
+ try {
666
+ stats_1 = fs.statSync(testDir);
667
+ }
668
+ catch (err) {
669
+ if (err.code == 'ENOENT') {
670
+ // validate the directory is not the drive root
671
+ var parentDir = path.dirname(testDir);
672
+ if (testDir == parentDir) {
673
+ throw new Error(exports.loc('LIB_MkdirFailedInvalidDriveRoot', p, testDir)); // Unable to create directory '{p}'. Root directory does not exist: '{testDir}'
674
+ }
675
+ // push the dir and test the parent
676
+ stack.push(testDir);
677
+ testDir = parentDir;
678
+ continue;
679
+ }
680
+ else if (err.code == 'UNKNOWN') {
681
+ throw new Error(exports.loc('LIB_MkdirFailedInvalidShare', p, testDir)); // Unable to create directory '{p}'. Unable to verify the directory exists: '{testDir}'. If directory is a file share, please verify the share name is correct, the share is online, and the current process has permission to access the share.
682
+ }
683
+ else {
684
+ throw err;
685
+ }
686
+ }
687
+ if (!stats_1.isDirectory()) {
688
+ throw new Error(exports.loc('LIB_MkdirFailedFileExists', p, testDir)); // Unable to create directory '{p}'. Conflicting file exists: '{testDir}'
689
+ }
690
+ // testDir exists
691
+ break;
692
+ }
693
+ // create each directory
694
+ while (stack.length) {
695
+ var dir = stack.pop(); // non-null because `stack.length` was truthy
696
+ exports.debug("mkdir '" + dir + "'");
697
+ try {
698
+ fs.mkdirSync(dir);
699
+ }
700
+ catch (err) {
701
+ throw new Error(exports.loc('LIB_MkdirFailed', p, err.message)); // Unable to create directory '{p}'. {err.message}
702
+ }
703
+ }
704
+ }
705
+ exports.mkdirP = mkdirP;
706
+ /**
707
+ * Resolves a sequence of paths or path segments into an absolute path.
708
+ * Calls node.js path.resolve()
709
+ * Allows L0 testing with consistent path formats on Mac/Linux and Windows in the mock implementation
710
+ * @param pathSegments
711
+ * @returns {string}
712
+ */
713
+ function resolve() {
714
+ var pathSegments = [];
715
+ for (var _i = 0; _i < arguments.length; _i++) {
716
+ pathSegments[_i] = arguments[_i];
717
+ }
718
+ var absolutePath = path.resolve.apply(this, pathSegments);
719
+ exports.debug('Absolute path for pathSegments: ' + pathSegments + ' = ' + absolutePath);
720
+ return absolutePath;
721
+ }
722
+ exports.resolve = resolve;
723
+ exports.which = im._which;
724
+ /**
725
+ * Returns array of files in the given path, or in current directory if no path provided. See shelljs.ls
726
+ * @param {string} options Available options: -R (recursive), -A (all files, include files beginning with ., except for . and ..)
727
+ * @param {string[]} paths Paths to search.
728
+ * @return {string[]} An array of files in the given path(s).
729
+ */
730
+ function ls(options, paths) {
731
+ if (options) {
732
+ return shell.ls(options, paths);
733
+ }
734
+ else {
735
+ return shell.ls(paths);
736
+ }
737
+ }
738
+ exports.ls = ls;
739
+ /**
740
+ * Copies a file or folder.
741
+ *
742
+ * @param source source path
743
+ * @param dest destination path
744
+ * @param options string -r, -f or -rf for recursive and force
745
+ * @param continueOnError optional. whether to continue on error
746
+ * @param retryCount optional. Retry count to copy the file. It might help to resolve intermittent issues e.g. with UNC target paths on a remote host.
747
+ */
748
+ function cp(source, dest, options, continueOnError, retryCount) {
749
+ if (retryCount === void 0) { retryCount = 0; }
750
+ while (retryCount >= 0) {
751
+ try {
752
+ if (options) {
753
+ shell.cp(options, source, dest);
754
+ }
755
+ else {
756
+ shell.cp(source, dest);
757
+ }
758
+ _checkShell('cp', false);
759
+ break;
760
+ }
761
+ catch (e) {
762
+ if (retryCount <= 0) {
763
+ if (continueOnError) {
764
+ exports.warning(e);
765
+ break;
766
+ }
767
+ else {
768
+ throw e;
769
+ }
770
+ }
771
+ else {
772
+ console.log(exports.loc('LIB_CopyFileFailed', retryCount));
773
+ retryCount--;
774
+ }
775
+ }
776
+ }
777
+ }
778
+ exports.cp = cp;
779
+ /**
780
+ * Moves a path.
781
+ *
782
+ * @param source source path
783
+ * @param dest destination path
784
+ * @param options string -f or -n for force and no clobber
785
+ * @param continueOnError optional. whether to continue on error
786
+ */
787
+ function mv(source, dest, options, continueOnError) {
788
+ if (options) {
789
+ shell.mv(options, source, dest);
790
+ }
791
+ else {
792
+ shell.mv(source, dest);
793
+ }
794
+ _checkShell('mv', continueOnError);
795
+ }
796
+ exports.mv = mv;
797
+ /**
798
+ * Tries to execute a function a specified number of times.
799
+ *
800
+ * @param func a function to be executed.
801
+ * @param args executed function arguments array.
802
+ * @param retryOptions optional. Defaults to { continueOnError: false, retryCount: 0 }.
803
+ * @returns the same as the usual function.
804
+ */
805
+ function retry(func, args, retryOptions) {
806
+ if (retryOptions === void 0) { retryOptions = { continueOnError: false, retryCount: 0 }; }
807
+ while (retryOptions.retryCount >= 0) {
808
+ try {
809
+ return func.apply(void 0, args);
810
+ }
811
+ catch (e) {
812
+ if (retryOptions.retryCount <= 0) {
813
+ if (retryOptions.continueOnError) {
814
+ exports.warning(e);
815
+ break;
816
+ }
817
+ else {
818
+ throw e;
819
+ }
820
+ }
821
+ else {
822
+ exports.debug("Attempt to execute function \"" + (func === null || func === void 0 ? void 0 : func.name) + "\" failed, retries left: " + retryOptions.retryCount);
823
+ retryOptions.retryCount--;
824
+ }
825
+ }
826
+ }
827
+ }
828
+ exports.retry = retry;
829
+ /**
830
+ * Gets info about item stats.
831
+ *
832
+ * @param path a path to the item to be processed.
833
+ * @param followSymbolicLink indicates whether to traverse descendants of symbolic link directories.
834
+ * @param allowBrokenSymbolicLinks when true, broken symbolic link will not cause an error.
835
+ * @returns fs.Stats
836
+ */
837
+ function _getStats(path, followSymbolicLink, allowBrokenSymbolicLinks) {
838
+ // stat returns info about the target of a symlink (or symlink chain),
839
+ // lstat returns info about a symlink itself
840
+ var stats;
841
+ if (followSymbolicLink) {
842
+ try {
843
+ // use stat (following symlinks)
844
+ stats = fs.statSync(path);
845
+ }
846
+ catch (err) {
847
+ if (err.code == 'ENOENT' && allowBrokenSymbolicLinks) {
848
+ // fallback to lstat (broken symlinks allowed)
849
+ stats = fs.lstatSync(path);
850
+ exports.debug(" " + path + " (broken symlink)");
851
+ }
852
+ else {
853
+ throw err;
854
+ }
855
+ }
856
+ }
857
+ else {
858
+ // use lstat (not following symlinks)
859
+ stats = fs.lstatSync(path);
860
+ }
861
+ return stats;
862
+ }
863
+ /**
864
+ * Recursively finds all paths a given path. Returns an array of paths.
865
+ *
866
+ * @param findPath path to search
867
+ * @param options optional. defaults to { followSymbolicLinks: true }. following soft links is generally appropriate unless deleting files.
868
+ * @returns string[]
869
+ */
870
+ function find(findPath, options) {
871
+ if (!findPath) {
872
+ exports.debug('no path specified');
873
+ return [];
874
+ }
875
+ // normalize the path, otherwise the first result is inconsistently formatted from the rest of the results
876
+ // because path.join() performs normalization.
877
+ findPath = path.normalize(findPath);
878
+ // debug trace the parameters
879
+ exports.debug("findPath: '" + findPath + "'");
880
+ options = options || _getDefaultFindOptions();
881
+ _debugFindOptions(options);
882
+ // return empty if not exists
883
+ try {
884
+ fs.lstatSync(findPath);
885
+ }
886
+ catch (err) {
887
+ if (err.code == 'ENOENT') {
888
+ exports.debug('0 results');
889
+ return [];
890
+ }
891
+ throw err;
892
+ }
893
+ try {
894
+ var result = [];
895
+ // push the first item
896
+ var stack = [new _FindItem(findPath, 1)];
897
+ var traversalChain = []; // used to detect cycles
898
+ var _loop_1 = function () {
899
+ // pop the next item and push to the result array
900
+ var item = stack.pop(); // non-null because `stack.length` was truthy
901
+ var stats_2 = void 0;
902
+ try {
903
+ // `item.path` equals `findPath` for the first item to be processed, when the `result` array is empty
904
+ var isPathToSearch = !result.length;
905
+ // following specified symlinks only if current path equals specified path
906
+ var followSpecifiedSymbolicLink = options.followSpecifiedSymbolicLink && isPathToSearch;
907
+ // following all symlinks or following symlink for the specified path
908
+ var followSymbolicLink = options.followSymbolicLinks || followSpecifiedSymbolicLink;
909
+ // stat the item. The stat info is used further below to determine whether to traverse deeper
910
+ stats_2 = _getStats(item.path, followSymbolicLink, options.allowBrokenSymbolicLinks);
911
+ }
912
+ catch (err) {
913
+ if (err.code == 'ENOENT' && options.skipMissingFiles) {
914
+ exports.warning("No such file or directory: \"" + item.path + "\" - skipping.");
915
+ return "continue";
916
+ }
917
+ throw err;
918
+ }
919
+ result.push(item.path);
920
+ // note, isDirectory() returns false for the lstat of a symlink
921
+ if (stats_2.isDirectory()) {
922
+ exports.debug(" " + item.path + " (directory)");
923
+ if (options.followSymbolicLinks) {
924
+ // get the realpath
925
+ var realPath_1;
926
+ if (im._isUncPath(item.path)) {
927
+ // Sometimes there are spontaneous issues when working with unc-paths, so retries have been added for them.
928
+ realPath_1 = retry(fs.realpathSync, [item.path], { continueOnError: false, retryCount: 5 });
929
+ }
930
+ else {
931
+ realPath_1 = fs.realpathSync(item.path);
932
+ }
933
+ // fixup the traversal chain to match the item level
934
+ while (traversalChain.length >= item.level) {
935
+ traversalChain.pop();
936
+ }
937
+ // test for a cycle
938
+ if (traversalChain.some(function (x) { return x == realPath_1; })) {
939
+ exports.debug(' cycle detected');
940
+ return "continue";
941
+ }
942
+ // update the traversal chain
943
+ traversalChain.push(realPath_1);
944
+ }
945
+ // push the child items in reverse onto the stack
946
+ var childLevel_1 = item.level + 1;
947
+ var childItems = fs.readdirSync(item.path)
948
+ .map(function (childName) { return new _FindItem(path.join(item.path, childName), childLevel_1); });
949
+ for (var i = childItems.length - 1; i >= 0; i--) {
950
+ stack.push(childItems[i]);
951
+ }
952
+ }
953
+ else {
954
+ exports.debug(" " + item.path + " (file)");
955
+ }
956
+ };
957
+ while (stack.length) {
958
+ _loop_1();
959
+ }
960
+ exports.debug(result.length + " results");
961
+ return result;
962
+ }
963
+ catch (err) {
964
+ throw new Error(exports.loc('LIB_OperationFailed', 'find', err.message));
965
+ }
966
+ }
967
+ exports.find = find;
968
+ var _FindItem = /** @class */ (function () {
969
+ function _FindItem(path, level) {
970
+ this.path = path;
971
+ this.level = level;
972
+ }
973
+ return _FindItem;
974
+ }());
975
+ function _debugFindOptions(options) {
976
+ exports.debug("findOptions.allowBrokenSymbolicLinks: '" + options.allowBrokenSymbolicLinks + "'");
977
+ exports.debug("findOptions.followSpecifiedSymbolicLink: '" + options.followSpecifiedSymbolicLink + "'");
978
+ exports.debug("findOptions.followSymbolicLinks: '" + options.followSymbolicLinks + "'");
979
+ exports.debug("findOptions.skipMissingFiles: '" + options.skipMissingFiles + "'");
980
+ }
981
+ function _getDefaultFindOptions() {
982
+ return {
983
+ allowBrokenSymbolicLinks: false,
984
+ followSpecifiedSymbolicLink: true,
985
+ followSymbolicLinks: true,
986
+ skipMissingFiles: false
987
+ };
988
+ }
989
+ /**
990
+ * Prefer tl.find() and tl.match() instead. This function is for backward compatibility
991
+ * when porting tasks to Node from the PowerShell or PowerShell3 execution handler.
992
+ *
993
+ * @param rootDirectory path to root unrooted patterns with
994
+ * @param pattern include and exclude patterns
995
+ * @param includeFiles whether to include files in the result. defaults to true when includeFiles and includeDirectories are both false
996
+ * @param includeDirectories whether to include directories in the result
997
+ * @returns string[]
998
+ */
999
+ function legacyFindFiles(rootDirectory, pattern, includeFiles, includeDirectories) {
1000
+ if (!pattern) {
1001
+ throw new Error('pattern parameter cannot be empty');
1002
+ }
1003
+ exports.debug("legacyFindFiles rootDirectory: '" + rootDirectory + "'");
1004
+ exports.debug("pattern: '" + pattern + "'");
1005
+ exports.debug("includeFiles: '" + includeFiles + "'");
1006
+ exports.debug("includeDirectories: '" + includeDirectories + "'");
1007
+ if (!includeFiles && !includeDirectories) {
1008
+ includeFiles = true;
1009
+ }
1010
+ // organize the patterns into include patterns and exclude patterns
1011
+ var includePatterns = [];
1012
+ var excludePatterns = [];
1013
+ pattern = pattern.replace(/;;/g, '\0');
1014
+ for (var _i = 0, _a = pattern.split(';'); _i < _a.length; _i++) {
1015
+ var pat = _a[_i];
1016
+ if (!pat) {
1017
+ continue;
1018
+ }
1019
+ pat = pat.replace(/\0/g, ';');
1020
+ // determine whether include pattern and remove any include/exclude prefix.
1021
+ // include patterns start with +: or anything other than -:
1022
+ // exclude patterns start with -:
1023
+ var isIncludePattern = void 0;
1024
+ if (im._startsWith(pat, '+:')) {
1025
+ pat = pat.substring(2);
1026
+ isIncludePattern = true;
1027
+ }
1028
+ else if (im._startsWith(pat, '-:')) {
1029
+ pat = pat.substring(2);
1030
+ isIncludePattern = false;
1031
+ }
1032
+ else {
1033
+ isIncludePattern = true;
1034
+ }
1035
+ // validate pattern does not end with a slash
1036
+ if (im._endsWith(pat, '/') || (process.platform == 'win32' && im._endsWith(pat, '\\'))) {
1037
+ throw new Error(exports.loc('LIB_InvalidPattern', pat));
1038
+ }
1039
+ // root the pattern
1040
+ if (rootDirectory && !path.isAbsolute(pat)) {
1041
+ pat = path.join(rootDirectory, pat);
1042
+ // remove trailing slash sometimes added by path.join() on Windows, e.g.
1043
+ // path.join('\\\\hello', 'world') => '\\\\hello\\world\\'
1044
+ // path.join('//hello', 'world') => '\\\\hello\\world\\'
1045
+ if (im._endsWith(pat, '\\')) {
1046
+ pat = pat.substring(0, pat.length - 1);
1047
+ }
1048
+ }
1049
+ if (isIncludePattern) {
1050
+ includePatterns.push(pat);
1051
+ }
1052
+ else {
1053
+ excludePatterns.push(im._legacyFindFiles_convertPatternToRegExp(pat));
1054
+ }
1055
+ }
1056
+ // find and apply patterns
1057
+ var count = 0;
1058
+ var result = _legacyFindFiles_getMatchingItems(includePatterns, excludePatterns, !!includeFiles, !!includeDirectories);
1059
+ exports.debug('all matches:');
1060
+ for (var _b = 0, result_1 = result; _b < result_1.length; _b++) {
1061
+ var resultItem = result_1[_b];
1062
+ exports.debug(' ' + resultItem);
1063
+ }
1064
+ exports.debug('total matched: ' + result.length);
1065
+ return result;
1066
+ }
1067
+ exports.legacyFindFiles = legacyFindFiles;
1068
+ function _legacyFindFiles_getMatchingItems(includePatterns, excludePatterns, includeFiles, includeDirectories) {
1069
+ exports.debug('getMatchingItems()');
1070
+ for (var _i = 0, includePatterns_1 = includePatterns; _i < includePatterns_1.length; _i++) {
1071
+ var pattern = includePatterns_1[_i];
1072
+ exports.debug("includePattern: '" + pattern + "'");
1073
+ }
1074
+ for (var _a = 0, excludePatterns_1 = excludePatterns; _a < excludePatterns_1.length; _a++) {
1075
+ var pattern = excludePatterns_1[_a];
1076
+ exports.debug("excludePattern: " + pattern);
1077
+ }
1078
+ exports.debug('includeFiles: ' + includeFiles);
1079
+ exports.debug('includeDirectories: ' + includeDirectories);
1080
+ var allFiles = {};
1081
+ var _loop_2 = function (pattern) {
1082
+ // determine the directory to search
1083
+ //
1084
+ // note, getDirectoryName removes redundant path separators
1085
+ var findPath = void 0;
1086
+ var starIndex = pattern.indexOf('*');
1087
+ var questionIndex = pattern.indexOf('?');
1088
+ if (starIndex < 0 && questionIndex < 0) {
1089
+ // if no wildcards are found, use the directory name portion of the path.
1090
+ // if there is no directory name (file name only in pattern or drive root),
1091
+ // this will return empty string.
1092
+ findPath = im._getDirectoryName(pattern);
1093
+ }
1094
+ else {
1095
+ // extract the directory prior to the first wildcard
1096
+ var index = Math.min(starIndex >= 0 ? starIndex : questionIndex, questionIndex >= 0 ? questionIndex : starIndex);
1097
+ findPath = im._getDirectoryName(pattern.substring(0, index));
1098
+ }
1099
+ // note, due to this short-circuit and the above usage of getDirectoryName, this
1100
+ // function has the same limitations regarding drive roots as the powershell
1101
+ // implementation.
1102
+ //
1103
+ // also note, since getDirectoryName eliminates slash redundancies, some additional
1104
+ // work may be required if removal of this limitation is attempted.
1105
+ if (!findPath) {
1106
+ return "continue";
1107
+ }
1108
+ var patternRegex = im._legacyFindFiles_convertPatternToRegExp(pattern);
1109
+ // find files/directories
1110
+ var items = find(findPath, { followSymbolicLinks: true })
1111
+ .filter(function (item) {
1112
+ if (includeFiles && includeDirectories) {
1113
+ return true;
1114
+ }
1115
+ var isDir = fs.statSync(item).isDirectory();
1116
+ return (includeFiles && !isDir) || (includeDirectories && isDir);
1117
+ })
1118
+ .forEach(function (item) {
1119
+ var normalizedPath = process.platform == 'win32' ? item.replace(/\\/g, '/') : item; // normalize separators
1120
+ // **/times/** will not match C:/fun/times because there isn't a trailing slash
1121
+ // so try both if including directories
1122
+ var alternatePath = normalizedPath + "/"; // potential bug: it looks like this will result in a false
1123
+ // positive if the item is a regular file and not a directory
1124
+ var isMatch = false;
1125
+ if (patternRegex.test(normalizedPath) || (includeDirectories && patternRegex.test(alternatePath))) {
1126
+ isMatch = true;
1127
+ // test whether the path should be excluded
1128
+ for (var _i = 0, excludePatterns_2 = excludePatterns; _i < excludePatterns_2.length; _i++) {
1129
+ var regex = excludePatterns_2[_i];
1130
+ if (regex.test(normalizedPath) || (includeDirectories && regex.test(alternatePath))) {
1131
+ isMatch = false;
1132
+ break;
1133
+ }
1134
+ }
1135
+ }
1136
+ if (isMatch) {
1137
+ allFiles[item] = item;
1138
+ }
1139
+ });
1140
+ };
1141
+ for (var _b = 0, includePatterns_2 = includePatterns; _b < includePatterns_2.length; _b++) {
1142
+ var pattern = includePatterns_2[_b];
1143
+ _loop_2(pattern);
1144
+ }
1145
+ return Object.keys(allFiles).sort();
1146
+ }
1147
+ /**
1148
+ * Remove a path recursively with force
1149
+ *
1150
+ * @param inputPath path to remove
1151
+ * @throws when the file or directory exists but could not be deleted.
1152
+ */
1153
+ function rmRF(inputPath) {
1154
+ exports.debug('rm -rf ' + inputPath);
1155
+ if (getPlatform() == Platform.Windows) {
1156
+ // Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another
1157
+ // program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del.
1158
+ try {
1159
+ if (fs.statSync(inputPath).isDirectory()) {
1160
+ exports.debug('removing directory ' + inputPath);
1161
+ childProcess.execSync("rd /s /q \"" + inputPath + "\"");
1162
+ }
1163
+ else {
1164
+ exports.debug('removing file ' + inputPath);
1165
+ childProcess.execSync("del /f /a \"" + inputPath + "\"");
1166
+ }
1167
+ }
1168
+ catch (err) {
1169
+ // if you try to delete a file that doesn't exist, desired result is achieved
1170
+ // other errors are valid
1171
+ if (err.code != 'ENOENT') {
1172
+ throw new Error(exports.loc('LIB_OperationFailed', 'rmRF', err.message));
1173
+ }
1174
+ }
1175
+ // Shelling out fails to remove a symlink folder with missing source, this unlink catches that
1176
+ try {
1177
+ fs.unlinkSync(inputPath);
1178
+ }
1179
+ catch (err) {
1180
+ // if you try to delete a file that doesn't exist, desired result is achieved
1181
+ // other errors are valid
1182
+ if (err.code != 'ENOENT') {
1183
+ throw new Error(exports.loc('LIB_OperationFailed', 'rmRF', err.message));
1184
+ }
1185
+ }
1186
+ }
1187
+ else {
1188
+ // get the lstats in order to workaround a bug in shelljs@0.3.0 where symlinks
1189
+ // with missing targets are not handled correctly by "rm('-rf', path)"
1190
+ var lstats = void 0;
1191
+ try {
1192
+ lstats = fs.lstatSync(inputPath);
1193
+ }
1194
+ catch (err) {
1195
+ // if you try to delete a file that doesn't exist, desired result is achieved
1196
+ // other errors are valid
1197
+ if (err.code == 'ENOENT') {
1198
+ return;
1199
+ }
1200
+ throw new Error(exports.loc('LIB_OperationFailed', 'rmRF', err.message));
1201
+ }
1202
+ if (lstats.isDirectory()) {
1203
+ exports.debug('removing directory');
1204
+ shell.rm('-rf', inputPath);
1205
+ var errMsg = shell.error();
1206
+ if (errMsg) {
1207
+ throw new Error(exports.loc('LIB_OperationFailed', 'rmRF', errMsg));
1208
+ }
1209
+ return;
1210
+ }
1211
+ exports.debug('removing file');
1212
+ try {
1213
+ fs.unlinkSync(inputPath);
1214
+ }
1215
+ catch (err) {
1216
+ throw new Error(exports.loc('LIB_OperationFailed', 'rmRF', err.message));
1217
+ }
1218
+ }
1219
+ }
1220
+ exports.rmRF = rmRF;
1221
+ /**
1222
+ * Exec a tool. Convenience wrapper over ToolRunner to exec with args in one call.
1223
+ * Output will be streamed to the live console.
1224
+ * Returns promise with return code
1225
+ *
1226
+ * @param tool path to tool to exec
1227
+ * @param args an arg string or array of args
1228
+ * @param options optional exec options. See IExecOptions
1229
+ * @returns number
1230
+ */
1231
+ function exec(tool, args, options) {
1232
+ var tr = this.tool(tool);
1233
+ tr.on('debug', function (data) {
1234
+ exports.debug(data);
1235
+ });
1236
+ if (args) {
1237
+ if (args instanceof Array) {
1238
+ tr.arg(args);
1239
+ }
1240
+ else if (typeof (args) === 'string') {
1241
+ tr.line(args);
1242
+ }
1243
+ }
1244
+ return tr.exec(options);
1245
+ }
1246
+ exports.exec = exec;
1247
+ /**
1248
+ * Exec a tool synchronously. Convenience wrapper over ToolRunner to execSync with args in one call.
1249
+ * Output will be *not* be streamed to the live console. It will be returned after execution is complete.
1250
+ * Appropriate for short running tools
1251
+ * Returns IExecResult with output and return code
1252
+ *
1253
+ * @param tool path to tool to exec
1254
+ * @param args an arg string or array of args
1255
+ * @param options optional exec options. See IExecSyncOptions
1256
+ * @returns IExecSyncResult
1257
+ */
1258
+ function execSync(tool, args, options) {
1259
+ var tr = this.tool(tool);
1260
+ tr.on('debug', function (data) {
1261
+ exports.debug(data);
1262
+ });
1263
+ if (args) {
1264
+ if (args instanceof Array) {
1265
+ tr.arg(args);
1266
+ }
1267
+ else if (typeof (args) === 'string') {
1268
+ tr.line(args);
1269
+ }
1270
+ }
1271
+ return tr.execSync(options);
1272
+ }
1273
+ exports.execSync = execSync;
1274
+ /**
1275
+ * Convenience factory to create a ToolRunner.
1276
+ *
1277
+ * @param tool path to tool to exec
1278
+ * @returns ToolRunner
1279
+ */
1280
+ function tool(tool) {
1281
+ var tr = new trm.ToolRunner(tool);
1282
+ tr.on('debug', function (message) {
1283
+ exports.debug(message);
1284
+ });
1285
+ return tr;
1286
+ }
1287
+ exports.tool = tool;
1288
+ /**
1289
+ * Applies glob patterns to a list of paths. Supports interleaved exclude patterns.
1290
+ *
1291
+ * @param list array of paths
1292
+ * @param patterns patterns to apply. supports interleaved exclude patterns.
1293
+ * @param patternRoot optional. default root to apply to unrooted patterns. not applied to basename-only patterns when matchBase:true.
1294
+ * @param options optional. defaults to { dot: true, nobrace: true, nocase: process.platform == 'win32' }.
1295
+ */
1296
+ function match(list, patterns, patternRoot, options) {
1297
+ // trace parameters
1298
+ exports.debug("patternRoot: '" + patternRoot + "'");
1299
+ options = options || _getDefaultMatchOptions(); // default match options
1300
+ _debugMatchOptions(options);
1301
+ // convert pattern to an array
1302
+ if (typeof patterns == 'string') {
1303
+ patterns = [patterns];
1304
+ }
1305
+ // hashtable to keep track of matches
1306
+ var map = {};
1307
+ var originalOptions = options;
1308
+ for (var _i = 0, patterns_1 = patterns; _i < patterns_1.length; _i++) {
1309
+ var pattern = patterns_1[_i];
1310
+ exports.debug("pattern: '" + pattern + "'");
1311
+ // trim and skip empty
1312
+ pattern = (pattern || '').trim();
1313
+ if (!pattern) {
1314
+ exports.debug('skipping empty pattern');
1315
+ continue;
1316
+ }
1317
+ // clone match options
1318
+ var options_1 = im._cloneMatchOptions(originalOptions);
1319
+ // skip comments
1320
+ if (!options_1.nocomment && im._startsWith(pattern, '#')) {
1321
+ exports.debug('skipping comment');
1322
+ continue;
1323
+ }
1324
+ // set nocomment - brace expansion could result in a leading '#'
1325
+ options_1.nocomment = true;
1326
+ // determine whether pattern is include or exclude
1327
+ var negateCount = 0;
1328
+ if (!options_1.nonegate) {
1329
+ while (pattern.charAt(negateCount) == '!') {
1330
+ negateCount++;
1331
+ }
1332
+ pattern = pattern.substring(negateCount); // trim leading '!'
1333
+ if (negateCount) {
1334
+ exports.debug("trimmed leading '!'. pattern: '" + pattern + "'");
1335
+ }
1336
+ }
1337
+ var isIncludePattern = negateCount == 0 ||
1338
+ (negateCount % 2 == 0 && !options_1.flipNegate) ||
1339
+ (negateCount % 2 == 1 && options_1.flipNegate);
1340
+ // set nonegate - brace expansion could result in a leading '!'
1341
+ options_1.nonegate = true;
1342
+ options_1.flipNegate = false;
1343
+ // expand braces - required to accurately root patterns
1344
+ var expanded = void 0;
1345
+ var preExpanded = pattern;
1346
+ if (options_1.nobrace) {
1347
+ expanded = [pattern];
1348
+ }
1349
+ else {
1350
+ // convert slashes on Windows before calling braceExpand(). unfortunately this means braces cannot
1351
+ // be escaped on Windows, this limitation is consistent with current limitations of minimatch (3.0.3).
1352
+ exports.debug('expanding braces');
1353
+ var convertedPattern = process.platform == 'win32' ? pattern.replace(/\\/g, '/') : pattern;
1354
+ expanded = minimatch.braceExpand(convertedPattern);
1355
+ }
1356
+ // set nobrace
1357
+ options_1.nobrace = true;
1358
+ for (var _a = 0, expanded_1 = expanded; _a < expanded_1.length; _a++) {
1359
+ var pattern_1 = expanded_1[_a];
1360
+ if (expanded.length != 1 || pattern_1 != preExpanded) {
1361
+ exports.debug("pattern: '" + pattern_1 + "'");
1362
+ }
1363
+ // trim and skip empty
1364
+ pattern_1 = (pattern_1 || '').trim();
1365
+ if (!pattern_1) {
1366
+ exports.debug('skipping empty pattern');
1367
+ continue;
1368
+ }
1369
+ // root the pattern when all of the following conditions are true:
1370
+ if (patternRoot && // patternRoot supplied
1371
+ !im._isRooted(pattern_1) && // AND pattern not rooted
1372
+ // AND matchBase:false or not basename only
1373
+ (!options_1.matchBase || (process.platform == 'win32' ? pattern_1.replace(/\\/g, '/') : pattern_1).indexOf('/') >= 0)) {
1374
+ pattern_1 = im._ensureRooted(patternRoot, pattern_1);
1375
+ exports.debug("rooted pattern: '" + pattern_1 + "'");
1376
+ }
1377
+ if (isIncludePattern) {
1378
+ // apply the pattern
1379
+ exports.debug('applying include pattern against original list');
1380
+ var matchResults = minimatch.match(list, pattern_1, options_1);
1381
+ exports.debug(matchResults.length + ' matches');
1382
+ // union the results
1383
+ for (var _b = 0, matchResults_1 = matchResults; _b < matchResults_1.length; _b++) {
1384
+ var matchResult = matchResults_1[_b];
1385
+ map[matchResult] = true;
1386
+ }
1387
+ }
1388
+ else {
1389
+ // apply the pattern
1390
+ exports.debug('applying exclude pattern against original list');
1391
+ var matchResults = minimatch.match(list, pattern_1, options_1);
1392
+ exports.debug(matchResults.length + ' matches');
1393
+ // substract the results
1394
+ for (var _c = 0, matchResults_2 = matchResults; _c < matchResults_2.length; _c++) {
1395
+ var matchResult = matchResults_2[_c];
1396
+ delete map[matchResult];
1397
+ }
1398
+ }
1399
+ }
1400
+ }
1401
+ // return a filtered version of the original list (preserves order and prevents duplication)
1402
+ var result = list.filter(function (item) { return map.hasOwnProperty(item); });
1403
+ exports.debug(result.length + ' final results');
1404
+ return result;
1405
+ }
1406
+ exports.match = match;
1407
+ /**
1408
+ * Filter to apply glob patterns
1409
+ *
1410
+ * @param pattern pattern to apply
1411
+ * @param options optional. defaults to { dot: true, nobrace: true, nocase: process.platform == 'win32' }.
1412
+ */
1413
+ function filter(pattern, options) {
1414
+ options = options || _getDefaultMatchOptions();
1415
+ return minimatch.filter(pattern, options);
1416
+ }
1417
+ exports.filter = filter;
1418
+ function _debugMatchOptions(options) {
1419
+ exports.debug("matchOptions.debug: '" + options.debug + "'");
1420
+ exports.debug("matchOptions.nobrace: '" + options.nobrace + "'");
1421
+ exports.debug("matchOptions.noglobstar: '" + options.noglobstar + "'");
1422
+ exports.debug("matchOptions.dot: '" + options.dot + "'");
1423
+ exports.debug("matchOptions.noext: '" + options.noext + "'");
1424
+ exports.debug("matchOptions.nocase: '" + options.nocase + "'");
1425
+ exports.debug("matchOptions.nonull: '" + options.nonull + "'");
1426
+ exports.debug("matchOptions.matchBase: '" + options.matchBase + "'");
1427
+ exports.debug("matchOptions.nocomment: '" + options.nocomment + "'");
1428
+ exports.debug("matchOptions.nonegate: '" + options.nonegate + "'");
1429
+ exports.debug("matchOptions.flipNegate: '" + options.flipNegate + "'");
1430
+ }
1431
+ function _getDefaultMatchOptions() {
1432
+ return {
1433
+ debug: false,
1434
+ nobrace: true,
1435
+ noglobstar: false,
1436
+ dot: true,
1437
+ noext: false,
1438
+ nocase: process.platform == 'win32',
1439
+ nonull: false,
1440
+ matchBase: false,
1441
+ nocomment: false,
1442
+ nonegate: false,
1443
+ flipNegate: false
1444
+ };
1445
+ }
1446
+ /**
1447
+ * Determines the find root from a list of patterns. Performs the find and then applies the glob patterns.
1448
+ * Supports interleaved exclude patterns. Unrooted patterns are rooted using defaultRoot, unless
1449
+ * matchOptions.matchBase is specified and the pattern is a basename only. For matchBase cases, the
1450
+ * defaultRoot is used as the find root.
1451
+ *
1452
+ * @param defaultRoot default path to root unrooted patterns. falls back to System.DefaultWorkingDirectory or process.cwd().
1453
+ * @param patterns pattern or array of patterns to apply
1454
+ * @param findOptions defaults to { followSymbolicLinks: true }. following soft links is generally appropriate unless deleting files.
1455
+ * @param matchOptions defaults to { dot: true, nobrace: true, nocase: process.platform == 'win32' }
1456
+ */
1457
+ function findMatch(defaultRoot, patterns, findOptions, matchOptions) {
1458
+ // apply defaults for parameters and trace
1459
+ defaultRoot = defaultRoot || this.getVariable('system.defaultWorkingDirectory') || process.cwd();
1460
+ exports.debug("defaultRoot: '" + defaultRoot + "'");
1461
+ patterns = patterns || [];
1462
+ patterns = typeof patterns == 'string' ? [patterns] : patterns;
1463
+ findOptions = findOptions || _getDefaultFindOptions();
1464
+ _debugFindOptions(findOptions);
1465
+ matchOptions = matchOptions || _getDefaultMatchOptions();
1466
+ _debugMatchOptions(matchOptions);
1467
+ // normalize slashes for root dir
1468
+ defaultRoot = im._normalizeSeparators(defaultRoot);
1469
+ var results = {};
1470
+ var originalMatchOptions = matchOptions;
1471
+ for (var _i = 0, _a = (patterns || []); _i < _a.length; _i++) {
1472
+ var pattern = _a[_i];
1473
+ exports.debug("pattern: '" + pattern + "'");
1474
+ // trim and skip empty
1475
+ pattern = (pattern || '').trim();
1476
+ if (!pattern) {
1477
+ exports.debug('skipping empty pattern');
1478
+ continue;
1479
+ }
1480
+ // clone match options
1481
+ var matchOptions_1 = im._cloneMatchOptions(originalMatchOptions);
1482
+ // skip comments
1483
+ if (!matchOptions_1.nocomment && im._startsWith(pattern, '#')) {
1484
+ exports.debug('skipping comment');
1485
+ continue;
1486
+ }
1487
+ // set nocomment - brace expansion could result in a leading '#'
1488
+ matchOptions_1.nocomment = true;
1489
+ // determine whether pattern is include or exclude
1490
+ var negateCount = 0;
1491
+ if (!matchOptions_1.nonegate) {
1492
+ while (pattern.charAt(negateCount) == '!') {
1493
+ negateCount++;
1494
+ }
1495
+ pattern = pattern.substring(negateCount); // trim leading '!'
1496
+ if (negateCount) {
1497
+ exports.debug("trimmed leading '!'. pattern: '" + pattern + "'");
1498
+ }
1499
+ }
1500
+ var isIncludePattern = negateCount == 0 ||
1501
+ (negateCount % 2 == 0 && !matchOptions_1.flipNegate) ||
1502
+ (negateCount % 2 == 1 && matchOptions_1.flipNegate);
1503
+ // set nonegate - brace expansion could result in a leading '!'
1504
+ matchOptions_1.nonegate = true;
1505
+ matchOptions_1.flipNegate = false;
1506
+ // expand braces - required to accurately interpret findPath
1507
+ var expanded = void 0;
1508
+ var preExpanded = pattern;
1509
+ if (matchOptions_1.nobrace) {
1510
+ expanded = [pattern];
1511
+ }
1512
+ else {
1513
+ // convert slashes on Windows before calling braceExpand(). unfortunately this means braces cannot
1514
+ // be escaped on Windows, this limitation is consistent with current limitations of minimatch (3.0.3).
1515
+ exports.debug('expanding braces');
1516
+ var convertedPattern = process.platform == 'win32' ? pattern.replace(/\\/g, '/') : pattern;
1517
+ expanded = minimatch.braceExpand(convertedPattern);
1518
+ }
1519
+ // set nobrace
1520
+ matchOptions_1.nobrace = true;
1521
+ for (var _b = 0, expanded_2 = expanded; _b < expanded_2.length; _b++) {
1522
+ var pattern_2 = expanded_2[_b];
1523
+ if (expanded.length != 1 || pattern_2 != preExpanded) {
1524
+ exports.debug("pattern: '" + pattern_2 + "'");
1525
+ }
1526
+ // trim and skip empty
1527
+ pattern_2 = (pattern_2 || '').trim();
1528
+ if (!pattern_2) {
1529
+ exports.debug('skipping empty pattern');
1530
+ continue;
1531
+ }
1532
+ if (isIncludePattern) {
1533
+ // determine the findPath
1534
+ var findInfo = im._getFindInfoFromPattern(defaultRoot, pattern_2, matchOptions_1);
1535
+ var findPath = findInfo.findPath;
1536
+ exports.debug("findPath: '" + findPath + "'");
1537
+ if (!findPath) {
1538
+ exports.debug('skipping empty path');
1539
+ continue;
1540
+ }
1541
+ // perform the find
1542
+ exports.debug("statOnly: '" + findInfo.statOnly + "'");
1543
+ var findResults = [];
1544
+ if (findInfo.statOnly) {
1545
+ // simply stat the path - all path segments were used to build the path
1546
+ try {
1547
+ fs.statSync(findPath);
1548
+ findResults.push(findPath);
1549
+ }
1550
+ catch (err) {
1551
+ if (err.code != 'ENOENT') {
1552
+ throw err;
1553
+ }
1554
+ exports.debug('ENOENT');
1555
+ }
1556
+ }
1557
+ else {
1558
+ findResults = find(findPath, findOptions);
1559
+ }
1560
+ exports.debug("found " + findResults.length + " paths");
1561
+ // apply the pattern
1562
+ exports.debug('applying include pattern');
1563
+ if (findInfo.adjustedPattern != pattern_2) {
1564
+ exports.debug("adjustedPattern: '" + findInfo.adjustedPattern + "'");
1565
+ pattern_2 = findInfo.adjustedPattern;
1566
+ }
1567
+ var matchResults = minimatch.match(findResults, pattern_2, matchOptions_1);
1568
+ exports.debug(matchResults.length + ' matches');
1569
+ // union the results
1570
+ for (var _c = 0, matchResults_3 = matchResults; _c < matchResults_3.length; _c++) {
1571
+ var matchResult = matchResults_3[_c];
1572
+ var key = process.platform == 'win32' ? matchResult.toUpperCase() : matchResult;
1573
+ results[key] = matchResult;
1574
+ }
1575
+ }
1576
+ else {
1577
+ // check if basename only and matchBase=true
1578
+ if (matchOptions_1.matchBase &&
1579
+ !im._isRooted(pattern_2) &&
1580
+ (process.platform == 'win32' ? pattern_2.replace(/\\/g, '/') : pattern_2).indexOf('/') < 0) {
1581
+ // do not root the pattern
1582
+ exports.debug('matchBase and basename only');
1583
+ }
1584
+ else {
1585
+ // root the exclude pattern
1586
+ pattern_2 = im._ensurePatternRooted(defaultRoot, pattern_2);
1587
+ exports.debug("after ensurePatternRooted, pattern: '" + pattern_2 + "'");
1588
+ }
1589
+ // apply the pattern
1590
+ exports.debug('applying exclude pattern');
1591
+ var matchResults = minimatch.match(Object.keys(results).map(function (key) { return results[key]; }), pattern_2, matchOptions_1);
1592
+ exports.debug(matchResults.length + ' matches');
1593
+ // substract the results
1594
+ for (var _d = 0, matchResults_4 = matchResults; _d < matchResults_4.length; _d++) {
1595
+ var matchResult = matchResults_4[_d];
1596
+ var key = process.platform == 'win32' ? matchResult.toUpperCase() : matchResult;
1597
+ delete results[key];
1598
+ }
1599
+ }
1600
+ }
1601
+ }
1602
+ var finalResult = Object.keys(results)
1603
+ .map(function (key) { return results[key]; })
1604
+ .sort();
1605
+ exports.debug(finalResult.length + ' final results');
1606
+ return finalResult;
1607
+ }
1608
+ exports.findMatch = findMatch;
1609
+ /**
1610
+ * Build Proxy URL in the following format: protocol://username:password@hostname:port
1611
+ * @param proxyUrl Url address of the proxy server (eg: http://example.com)
1612
+ * @param proxyUsername Proxy username (optional)
1613
+ * @param proxyPassword Proxy password (optional)
1614
+ * @returns string
1615
+ */
1616
+ function getProxyFormattedUrl(proxyUrl, proxyUsername, proxyPassword) {
1617
+ var parsedUrl = new URL(proxyUrl);
1618
+ var proxyAddress = parsedUrl.protocol + "//" + parsedUrl.host;
1619
+ if (proxyUsername) {
1620
+ proxyAddress = parsedUrl.protocol + "//" + proxyUsername + ":" + proxyPassword + "@" + parsedUrl.host;
1621
+ }
1622
+ return proxyAddress;
1623
+ }
1624
+ /**
1625
+ * Gets http proxy configuration used by Build/Release agent
1626
+ *
1627
+ * @return ProxyConfiguration
1628
+ */
1629
+ function getHttpProxyConfiguration(requestUrl) {
1630
+ var proxyUrl = exports.getVariable('Agent.ProxyUrl');
1631
+ if (proxyUrl && proxyUrl.length > 0) {
1632
+ var proxyUsername = exports.getVariable('Agent.ProxyUsername');
1633
+ var proxyPassword = exports.getVariable('Agent.ProxyPassword');
1634
+ var proxyBypassHosts = JSON.parse(exports.getVariable('Agent.ProxyBypassList') || '[]');
1635
+ var bypass_1 = false;
1636
+ if (requestUrl) {
1637
+ proxyBypassHosts.forEach(function (bypassHost) {
1638
+ if (new RegExp(bypassHost, 'i').test(requestUrl)) {
1639
+ bypass_1 = true;
1640
+ }
1641
+ });
1642
+ }
1643
+ if (bypass_1) {
1644
+ return null;
1645
+ }
1646
+ else {
1647
+ var proxyAddress = getProxyFormattedUrl(proxyUrl, proxyUsername, proxyPassword);
1648
+ return {
1649
+ proxyUrl: proxyUrl,
1650
+ proxyUsername: proxyUsername,
1651
+ proxyPassword: proxyPassword,
1652
+ proxyBypassHosts: proxyBypassHosts,
1653
+ proxyFormattedUrl: proxyAddress
1654
+ };
1655
+ }
1656
+ }
1657
+ else {
1658
+ return null;
1659
+ }
1660
+ }
1661
+ exports.getHttpProxyConfiguration = getHttpProxyConfiguration;
1662
+ /**
1663
+ * Gets http certificate configuration used by Build/Release agent
1664
+ *
1665
+ * @return CertConfiguration
1666
+ */
1667
+ function getHttpCertConfiguration() {
1668
+ var ca = exports.getVariable('Agent.CAInfo');
1669
+ var clientCert = exports.getVariable('Agent.ClientCert');
1670
+ if (ca || clientCert) {
1671
+ var certConfig = {};
1672
+ certConfig.caFile = ca;
1673
+ certConfig.certFile = clientCert;
1674
+ if (clientCert) {
1675
+ var clientCertKey = exports.getVariable('Agent.ClientCertKey');
1676
+ var clientCertArchive = exports.getVariable('Agent.ClientCertArchive');
1677
+ var clientCertPassword = exports.getVariable('Agent.ClientCertPassword');
1678
+ certConfig.keyFile = clientCertKey;
1679
+ certConfig.certArchiveFile = clientCertArchive;
1680
+ certConfig.passphrase = clientCertPassword;
1681
+ }
1682
+ return certConfig;
1683
+ }
1684
+ else {
1685
+ return null;
1686
+ }
1687
+ }
1688
+ exports.getHttpCertConfiguration = getHttpCertConfiguration;
1689
+ //-----------------------------------------------------
1690
+ // Test Publisher
1691
+ //-----------------------------------------------------
1692
+ var TestPublisher = /** @class */ (function () {
1693
+ function TestPublisher(testRunner) {
1694
+ this.testRunner = testRunner;
1695
+ }
1696
+ TestPublisher.prototype.publish = function (resultFiles, mergeResults, platform, config, runTitle, publishRunAttachments, testRunSystem) {
1697
+ // Could have used an initializer, but wanted to avoid reordering parameters when converting to strict null checks
1698
+ // (A parameter cannot both be optional and have an initializer)
1699
+ testRunSystem = testRunSystem || "VSTSTask";
1700
+ var properties = {};
1701
+ properties['type'] = this.testRunner;
1702
+ if (mergeResults) {
1703
+ properties['mergeResults'] = mergeResults;
1704
+ }
1705
+ if (platform) {
1706
+ properties['platform'] = platform;
1707
+ }
1708
+ if (config) {
1709
+ properties['config'] = config;
1710
+ }
1711
+ if (runTitle) {
1712
+ properties['runTitle'] = runTitle;
1713
+ }
1714
+ if (publishRunAttachments) {
1715
+ properties['publishRunAttachments'] = publishRunAttachments;
1716
+ }
1717
+ if (resultFiles) {
1718
+ properties['resultFiles'] = Array.isArray(resultFiles) ? resultFiles.join() : resultFiles;
1719
+ }
1720
+ properties['testRunSystem'] = testRunSystem;
1721
+ exports.command('results.publish', properties, '');
1722
+ };
1723
+ return TestPublisher;
1724
+ }());
1725
+ exports.TestPublisher = TestPublisher;
1726
+ //-----------------------------------------------------
1727
+ // Code coverage Publisher
1728
+ //-----------------------------------------------------
1729
+ var CodeCoveragePublisher = /** @class */ (function () {
1730
+ function CodeCoveragePublisher() {
1731
+ }
1732
+ CodeCoveragePublisher.prototype.publish = function (codeCoverageTool, summaryFileLocation, reportDirectory, additionalCodeCoverageFiles) {
1733
+ var properties = {};
1734
+ if (codeCoverageTool) {
1735
+ properties['codecoveragetool'] = codeCoverageTool;
1736
+ }
1737
+ if (summaryFileLocation) {
1738
+ properties['summaryfile'] = summaryFileLocation;
1739
+ }
1740
+ if (reportDirectory) {
1741
+ properties['reportdirectory'] = reportDirectory;
1742
+ }
1743
+ if (additionalCodeCoverageFiles) {
1744
+ properties['additionalcodecoveragefiles'] = Array.isArray(additionalCodeCoverageFiles) ? additionalCodeCoverageFiles.join() : additionalCodeCoverageFiles;
1745
+ }
1746
+ exports.command('codecoverage.publish', properties, "");
1747
+ };
1748
+ return CodeCoveragePublisher;
1749
+ }());
1750
+ exports.CodeCoveragePublisher = CodeCoveragePublisher;
1751
+ //-----------------------------------------------------
1752
+ // Code coverage Publisher
1753
+ //-----------------------------------------------------
1754
+ var CodeCoverageEnabler = /** @class */ (function () {
1755
+ function CodeCoverageEnabler(buildTool, ccTool) {
1756
+ this.buildTool = buildTool;
1757
+ this.ccTool = ccTool;
1758
+ }
1759
+ CodeCoverageEnabler.prototype.enableCodeCoverage = function (buildProps) {
1760
+ buildProps['buildtool'] = this.buildTool;
1761
+ buildProps['codecoveragetool'] = this.ccTool;
1762
+ exports.command('codecoverage.enable', buildProps, "");
1763
+ };
1764
+ return CodeCoverageEnabler;
1765
+ }());
1766
+ exports.CodeCoverageEnabler = CodeCoverageEnabler;
1767
+ //-----------------------------------------------------
1768
+ // Task Logging Commands
1769
+ //-----------------------------------------------------
1770
+ /**
1771
+ * Upload user interested file as additional log information
1772
+ * to the current timeline record.
1773
+ *
1774
+ * The file shall be available for download along with task logs.
1775
+ *
1776
+ * @param path Path to the file that should be uploaded.
1777
+ * @returns void
1778
+ */
1779
+ function uploadFile(path) {
1780
+ exports.command("task.uploadfile", null, path);
1781
+ }
1782
+ exports.uploadFile = uploadFile;
1783
+ /**
1784
+ * Instruction for the agent to update the PATH environment variable.
1785
+ * The specified directory is prepended to the PATH.
1786
+ * The updated environment variable will be reflected in subsequent tasks.
1787
+ *
1788
+ * @param path Local directory path.
1789
+ * @returns void
1790
+ */
1791
+ function prependPath(path) {
1792
+ assertAgent("2.115.0");
1793
+ exports.command("task.prependpath", null, path);
1794
+ }
1795
+ exports.prependPath = prependPath;
1796
+ /**
1797
+ * Upload and attach summary markdown to current timeline record.
1798
+ * This summary shall be added to the build/release summary and
1799
+ * not available for download with logs.
1800
+ *
1801
+ * @param path Local directory path.
1802
+ * @returns void
1803
+ */
1804
+ function uploadSummary(path) {
1805
+ exports.command("task.uploadsummary", null, path);
1806
+ }
1807
+ exports.uploadSummary = uploadSummary;
1808
+ /**
1809
+ * Upload and attach attachment to current timeline record.
1810
+ * These files are not available for download with logs.
1811
+ * These can only be referred to by extensions using the type or name values.
1812
+ *
1813
+ * @param type Attachment type.
1814
+ * @param name Attachment name.
1815
+ * @param path Attachment path.
1816
+ * @returns void
1817
+ */
1818
+ function addAttachment(type, name, path) {
1819
+ exports.command("task.addattachment", { "type": type, "name": name }, path);
1820
+ }
1821
+ exports.addAttachment = addAttachment;
1822
+ /**
1823
+ * Set an endpoint field with given value.
1824
+ * Value updated will be retained in the endpoint for
1825
+ * the subsequent tasks that execute within the same job.
1826
+ *
1827
+ * @param id Endpoint id.
1828
+ * @param field FieldType enum of AuthParameter, DataParameter or Url.
1829
+ * @param key Key.
1830
+ * @param value Value for key or url.
1831
+ * @returns void
1832
+ */
1833
+ function setEndpoint(id, field, key, value) {
1834
+ exports.command("task.setendpoint", { "id": id, "field": FieldType[field].toLowerCase(), "key": key }, value);
1835
+ }
1836
+ exports.setEndpoint = setEndpoint;
1837
+ /**
1838
+ * Set progress and current operation for current task.
1839
+ *
1840
+ * @param percent Percentage of completion.
1841
+ * @param currentOperation Current pperation.
1842
+ * @returns void
1843
+ */
1844
+ function setProgress(percent, currentOperation) {
1845
+ exports.command("task.setprogress", { "value": "" + percent }, currentOperation);
1846
+ }
1847
+ exports.setProgress = setProgress;
1848
+ /**
1849
+ * Indicates whether to write the logging command directly to the host or to the output pipeline.
1850
+ *
1851
+ * @param id Timeline record Guid.
1852
+ * @param parentId Parent timeline record Guid.
1853
+ * @param recordType Record type.
1854
+ * @param recordName Record name.
1855
+ * @param order Order of timeline record.
1856
+ * @param startTime Start time.
1857
+ * @param finishTime End time.
1858
+ * @param progress Percentage of completion.
1859
+ * @param state TaskState enum of Unknown, Initialized, InProgress or Completed.
1860
+ * @param result TaskResult enum of Succeeded, SucceededWithIssues, Failed, Cancelled or Skipped.
1861
+ * @param message current operation
1862
+ * @returns void
1863
+ */
1864
+ function logDetail(id, message, parentId, recordType, recordName, order, startTime, finishTime, progress, state, result) {
1865
+ var properties = {
1866
+ "id": id,
1867
+ "parentid": parentId,
1868
+ "type": recordType,
1869
+ "name": recordName,
1870
+ "order": order ? order.toString() : undefined,
1871
+ "starttime": startTime,
1872
+ "finishtime": finishTime,
1873
+ "progress": progress ? progress.toString() : undefined,
1874
+ "state": state ? TaskState[state] : undefined,
1875
+ "result": result ? TaskResult[result] : undefined
1876
+ };
1877
+ exports.command("task.logdetail", properties, message);
1878
+ }
1879
+ exports.logDetail = logDetail;
1880
+ /**
1881
+ * Log error or warning issue to timeline record of current task.
1882
+ *
1883
+ * @param type IssueType enum of Error or Warning.
1884
+ * @param sourcePath Source file location.
1885
+ * @param lineNumber Line number.
1886
+ * @param columnNumber Column number.
1887
+ * @param code Error or warning code.
1888
+ * @param message Error or warning message.
1889
+ * @returns void
1890
+ */
1891
+ function logIssue(type, message, sourcePath, lineNumber, columnNumber, errorCode) {
1892
+ var properties = {
1893
+ "type": IssueType[type].toLowerCase(),
1894
+ "code": errorCode,
1895
+ "sourcepath": sourcePath,
1896
+ "linenumber": lineNumber ? lineNumber.toString() : undefined,
1897
+ "columnnumber": columnNumber ? columnNumber.toString() : undefined,
1898
+ };
1899
+ exports.command("task.logissue", properties, message);
1900
+ }
1901
+ exports.logIssue = logIssue;
1902
+ //-----------------------------------------------------
1903
+ // Artifact Logging Commands
1904
+ //-----------------------------------------------------
1905
+ /**
1906
+ * Upload user interested file as additional log information
1907
+ * to the current timeline record.
1908
+ *
1909
+ * The file shall be available for download along with task logs.
1910
+ *
1911
+ * @param containerFolder Folder that the file will upload to, folder will be created if needed.
1912
+ * @param path Path to the file that should be uploaded.
1913
+ * @param name Artifact name.
1914
+ * @returns void
1915
+ */
1916
+ function uploadArtifact(containerFolder, path, name) {
1917
+ exports.command("artifact.upload", { "containerfolder": containerFolder, "artifactname": name }, path);
1918
+ }
1919
+ exports.uploadArtifact = uploadArtifact;
1920
+ /**
1921
+ * Create an artifact link, artifact location is required to be
1922
+ * a file container path, VC path or UNC share path.
1923
+ *
1924
+ * The file shall be available for download along with task logs.
1925
+ *
1926
+ * @param name Artifact name.
1927
+ * @param path Path to the file that should be associated.
1928
+ * @param artifactType ArtifactType enum of Container, FilePath, VersionControl, GitRef or TfvcLabel.
1929
+ * @returns void
1930
+ */
1931
+ function associateArtifact(name, path, artifactType) {
1932
+ exports.command("artifact.associate", { "type": ArtifactType[artifactType].toLowerCase(), "artifactname": name }, path);
1933
+ }
1934
+ exports.associateArtifact = associateArtifact;
1935
+ //-----------------------------------------------------
1936
+ // Build Logging Commands
1937
+ //-----------------------------------------------------
1938
+ /**
1939
+ * Upload user interested log to build’s container “logs\tool” folder.
1940
+ *
1941
+ * @param path Path to the file that should be uploaded.
1942
+ * @returns void
1943
+ */
1944
+ function uploadBuildLog(path) {
1945
+ exports.command("build.uploadlog", null, path);
1946
+ }
1947
+ exports.uploadBuildLog = uploadBuildLog;
1948
+ /**
1949
+ * Update build number for current build.
1950
+ *
1951
+ * @param value Value to be assigned as the build number.
1952
+ * @returns void
1953
+ */
1954
+ function updateBuildNumber(value) {
1955
+ exports.command("build.updatebuildnumber", null, value);
1956
+ }
1957
+ exports.updateBuildNumber = updateBuildNumber;
1958
+ /**
1959
+ * Add a tag for current build.
1960
+ *
1961
+ * @param value Tag value.
1962
+ * @returns void
1963
+ */
1964
+ function addBuildTag(value) {
1965
+ exports.command("build.addbuildtag", null, value);
1966
+ }
1967
+ exports.addBuildTag = addBuildTag;
1968
+ //-----------------------------------------------------
1969
+ // Release Logging Commands
1970
+ //-----------------------------------------------------
1971
+ /**
1972
+ * Update release name for current release.
1973
+ *
1974
+ * @param value Value to be assigned as the release name.
1975
+ * @returns void
1976
+ */
1977
+ function updateReleaseName(name) {
1978
+ assertAgent("2.132.0");
1979
+ exports.command("release.updatereleasename", null, name);
1980
+ }
1981
+ exports.updateReleaseName = updateReleaseName;
1982
+ //-----------------------------------------------------
1983
+ // Tools
1984
+ //-----------------------------------------------------
1985
+ exports.TaskCommand = tcm.TaskCommand;
1986
+ exports.commandFromString = tcm.commandFromString;
1987
+ exports.ToolRunner = trm.ToolRunner;
1988
+ //-----------------------------------------------------
1989
+ // Validation Checks
1990
+ //-----------------------------------------------------
1991
+ // async await needs generators in node 4.x+
1992
+ if (semver.lt(process.versions.node, '4.2.0')) {
1993
+ exports.warning('Tasks require a new agent. Upgrade your agent or node to 4.2.0 or later');
1994
+ }
1995
+ //-------------------------------------------------------------------
1996
+ // Populate the vault with sensitive data. Inputs and Endpoints
1997
+ //-------------------------------------------------------------------
1998
+ // avoid loading twice (overwrites .taskkey)
1999
+ if (!global['_vsts_task_lib_loaded']) {
2000
+ im._loadData();
2001
+ im._exposeProxySettings();
2002
+ im._exposeCertSettings();
2003
+ }