Skip to content

Commit

Permalink
Skipping the file if it was not found (the CI is fixed) (microsoft#779)
Browse files Browse the repository at this point in the history
A part of the code was taken out from the `find` function to the new `_getStats` function. A new field `skipMissingFiles` was added into the `findOptions` parameter. When it is true, the `find` function skips files that were not found during the `_getStats` function execution. Also, the `mocktests` timeout increased from 15 to 30 seconds.
  • Loading branch information
DenisRumyantsev authored Jul 23, 2021
1 parent ce5aefa commit a2b5414
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 45 deletions.
2 changes: 1 addition & 1 deletion node/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion node/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "azure-pipelines-task-lib",
"version": "3.1.5",
"version": "3.1.6",
"description": "Azure Pipelines Task SDK",
"main": "./task.js",
"typings": "./task.d.ts",
Expand Down
97 changes: 57 additions & 40 deletions node/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,11 @@ export interface FindOptions {
* symbolic link directories.
*/
followSymbolicLinks: boolean;

/**
* When true, missing files will not cause an error and will be skipped.
*/
skipMissingFiles?: boolean;
}

/**
Expand Down Expand Up @@ -858,6 +863,40 @@ export function retry(func: Function, args: any[], retryOptions: RetryOptions =
}
}

/**
* Gets info about item stats.
*
* @param path a path to the item to be processed.
* @param followSymbolicLinks indicates whether to traverse descendants of symbolic link directories.
* @param allowBrokenSymbolicLinks when true, broken symbolic link will not cause an error.
* @returns fs.Stats
*/
function _getStats (path: string, followSymbolicLinks: boolean, allowBrokenSymbolicLinks: boolean): fs.Stats {
// stat returns info about the target of a symlink (or symlink chain),
// lstat returns info about a symlink itself
let stats: fs.Stats;

if (followSymbolicLinks) {
try {
// use stat (following symlinks)
stats = fs.statSync(path);
} catch (err) {
if (err.code == 'ENOENT' && allowBrokenSymbolicLinks) {
// fallback to lstat (broken symlinks allowed)
stats = fs.lstatSync(path);
debug(` ${path} (broken symlink)`);
} else {
throw err;
}
}
} else {
// use lstat (not following symlinks)
stats = fs.lstatSync(path);
}

return stats;
}

/**
* Recursively finds all paths a given path. Returns an array of paths.
*
Expand Down Expand Up @@ -903,49 +942,25 @@ export function find(findPath: string, options?: FindOptions): string[] {
while (stack.length) {
// pop the next item and push to the result array
let item = stack.pop()!; // non-null because `stack.length` was truthy
result.push(item.path);

// stat the item. the stat info is used further below to determine whether to traverse deeper
//
// stat returns info about the target of a symlink (or symlink chain),
// lstat returns info about a symlink itself
let stats: fs.Stats;
if (options.followSymbolicLinks) {
try {
// use stat (following all symlinks)
stats = fs.statSync(item.path);
}
catch (err) {
if (err.code == 'ENOENT' && options.allowBrokenSymbolicLinks) {
// fallback to lstat (broken symlinks allowed)
stats = fs.lstatSync(item.path);
debug(` ${item.path} (broken symlink)`);
}
else {
throw err;
}
}
}
else if (options.followSpecifiedSymbolicLink && result.length == 1) {
try {
// use stat (following symlinks for the specified path and this is the specified path)
stats = fs.statSync(item.path);
}
catch (err) {
if (err.code == 'ENOENT' && options.allowBrokenSymbolicLinks) {
// fallback to lstat (broken symlinks allowed)
stats = fs.lstatSync(item.path);
debug(` ${item.path} (broken symlink)`);
}
else {
throw err;
}
try {
// `item.path` equals `findPath` for the first item to be processed, when the `result` array is empty
const isPathToSearch = !result.length;

// following all symlinks OR following symlinks for the specified path AND this is the specified path
const followSymbolicLinks = options.followSymbolicLinks || options.followSpecifiedSymbolicLink && isPathToSearch;

// stat the item. The stat info is used further below to determine whether to traverse deeper
stats = _getStats(item.path, followSymbolicLinks, options.allowBrokenSymbolicLinks);
} catch (err) {
if (err.code == 'ENOENT' && options.skipMissingFiles) {
warning(`"${item.path}" seems to be a removed file or directory / broken symlink - so skipping it.`);
continue;
}
throw err;
}
else {
// use lstat (not following symlinks)
stats = fs.lstatSync(item.path);
}
result.push(item.path);

// note, isDirectory() returns false for the lstat of a symlink
if (stats.isDirectory()) {
Expand Down Expand Up @@ -1012,13 +1027,15 @@ function _debugFindOptions(options: FindOptions): void {
debug(`findOptions.allowBrokenSymbolicLinks: '${options.allowBrokenSymbolicLinks}'`);
debug(`findOptions.followSpecifiedSymbolicLink: '${options.followSpecifiedSymbolicLink}'`);
debug(`findOptions.followSymbolicLinks: '${options.followSymbolicLinks}'`);
debug(`findOptions.skipMissingFiles: '${options.skipMissingFiles}'`);
}

function _getDefaultFindOptions(): FindOptions {
return <FindOptions>{
allowBrokenSymbolicLinks: false,
followSpecifiedSymbolicLink: true,
followSymbolicLinks: true
followSymbolicLinks: true,
skipMissingFiles: false
};
}

Expand Down
6 changes: 3 additions & 3 deletions node/test/mocktests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ describe('Mock Tests', function () {
})

it('MockTest handles node 6 tasks correctly', function (done) {
this.timeout(15000);
this.timeout(30000);
const runner = new mtm.MockTestRunner(path.join(__dirname, 'fakeTasks', 'node6task', 'entry.js'));
const nodePath = runner.nodePath;
assert(nodePath, 'node path should have been correctly set');
Expand All @@ -309,7 +309,7 @@ describe('Mock Tests', function () {
})

it('MockTest handles node 10 tasks correctly', function (done) {
this.timeout(15000);
this.timeout(30000);
const runner = new mtm.MockTestRunner(path.join(__dirname, 'fakeTasks', 'node10task', 'entry.js'));
const nodePath = runner.nodePath;
assert(nodePath, 'node path should have been correctly set');
Expand All @@ -319,7 +319,7 @@ describe('Mock Tests', function () {
})

it('MockTest handles node 14 tasks correctly', function (done) {
this.timeout(15000);
this.timeout(30000);
const runner = new mtm.MockTestRunner(path.join(__dirname, 'fakeTasks', 'node14task', 'entry.js'));
const nodePath = runner.nodePath;
assert(nodePath, 'node path should have been correctly set');
Expand Down

0 comments on commit a2b5414

Please sign in to comment.