You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
82 lines
2.0 KiB
JavaScript
82 lines
2.0 KiB
JavaScript
'use strict';
|
|
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const defaultValue = require("default-value");
|
|
|
|
let defaultCheckers = {
|
|
"package.json": function(directory) {
|
|
let parentPackageFile = path.join(directory, `..${path.sep}..${path.sep}package.json`);
|
|
|
|
try {
|
|
fs.accessSync(parentPackageFile);
|
|
return false;
|
|
} catch (err) {
|
|
return true;
|
|
}
|
|
},
|
|
"vcs": function(directory) {
|
|
let files = fs.readdirSync(directory);
|
|
|
|
return [".git", ".hg"].some((target) => {
|
|
return (files.indexOf(target) !== -1);
|
|
});
|
|
}
|
|
}
|
|
|
|
function reachedRoot(candidatePath) {
|
|
/* Returns true if we hit the root of the filesystem; like / or C:\ */
|
|
return /^(?:\/|a-z:\\)$/i.test(candidatePath);
|
|
}
|
|
|
|
module.exports = function(options) {
|
|
let currentPath = defaultValue(options.basePath, __dirname);
|
|
let checker = defaultValue(options.checker, "package.json");
|
|
|
|
if (typeof checker === "string") {
|
|
if (defaultCheckers[checker] != null) {
|
|
checker = defaultCheckers[checker];
|
|
} else {
|
|
throw new Error("No such checker exists.");
|
|
}
|
|
}
|
|
|
|
/* Locate the first thing that has a package.json, in case we're in a
|
|
* subdirectory within a module. Only after we've found the nearest
|
|
* package.json, we will start using the checker.
|
|
*/
|
|
|
|
let baseFound = false;
|
|
|
|
while (baseFound === false) {
|
|
baseFound = (fs.readdirSync(currentPath).indexOf("package.json") !== -1);
|
|
|
|
if (reachedRoot(currentPath)) {
|
|
throw new Error("Reached filesystem root without encountering a module");
|
|
}
|
|
|
|
if (baseFound === false) {
|
|
currentPath = path.join(currentPath, "..");
|
|
}
|
|
}
|
|
|
|
let rootFound = false;
|
|
|
|
while (rootFound === false) {
|
|
rootFound = checker(currentPath);
|
|
|
|
if (rootFound !== true && rootFound !== false) {
|
|
throw new Error("Checker must always return either true or false");
|
|
}
|
|
|
|
if (reachedRoot(currentPath)) {
|
|
throw new Error("Reached filesystem root without encountering the project root");
|
|
}
|
|
|
|
if (rootFound === false) {
|
|
currentPath = path.join(currentPath, `..${path.sep}..`);
|
|
}
|
|
}
|
|
|
|
return currentPath;
|
|
} |