-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathutils.js
More file actions
46 lines (40 loc) · 1.55 KB
/
utils.js
File metadata and controls
46 lines (40 loc) · 1.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
"use strict";
const path = require("path");
const fs = require("fs");
/**
* Walk up the directory tree from `parent/directory` looking for any file
* whose name matches one of the entries in `name`. Stops at `parent`.
*
* @param {string} parent - Root of the workspace (walk stops here).
* @param {string} directory - Relative directory to start from (must be within parent).
* @param {string|string[]} name - File name(s) to look for.
* @returns {string|null} Absolute path to the first matching file, or null.
*/
function findFiles(parent, directory, name) {
const names = [].concat(name);
const resolvedParent = path.resolve(parent);
const resolvedStart = path.resolve(parent, directory);
// Guard: if the resolved start path is outside parent (e.g. cross-drive path
// on Windows produced by path.relative between different drives), there is
// nothing to find within the workspace boundary — return null immediately.
if (resolvedStart !== resolvedParent &&
!resolvedStart.startsWith(resolvedParent + path.sep)) {
return null;
}
const chunks = resolvedStart.split(path.sep);
while (chunks.length) {
let currentDir = chunks.join(path.sep);
for (const fileName of names) {
const filePath = path.join(currentDir, fileName);
if (fs.existsSync(filePath)) {
return filePath;
}
}
if (resolvedParent === currentDir) {
break;
}
chunks.pop();
}
return null;
}
module.exports = { findFiles };