You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
4.1 KiB
170 lines
4.1 KiB
/* |
|
MIT License http://www.opensource.org/licenses/mit-license.php |
|
Author Tobias Koppers @sokra |
|
*/ |
|
|
|
"use strict"; |
|
|
|
const forEachBail = require("./forEachBail"); |
|
|
|
/** @typedef {import("./Resolver")} Resolver */ |
|
/** @typedef {import("./Resolver").ResolveContext} ResolveContext */ |
|
|
|
/** |
|
* @typedef {Object} DescriptionFileInfo |
|
* @property {any=} content |
|
* @property {string} path |
|
* @property {string} directory |
|
*/ |
|
|
|
/** |
|
* @callback ErrorFirstCallback |
|
* @param {Error|null=} error |
|
* @param {DescriptionFileInfo=} result |
|
*/ |
|
|
|
/** |
|
* @param {Resolver} resolver resolver |
|
* @param {string} directory directory |
|
* @param {string[]} filenames filenames |
|
* @param {DescriptionFileInfo|undefined} oldInfo oldInfo |
|
* @param {ResolveContext} resolveContext resolveContext |
|
* @param {ErrorFirstCallback} callback callback |
|
*/ |
|
function loadDescriptionFile( |
|
resolver, |
|
directory, |
|
filenames, |
|
oldInfo, |
|
resolveContext, |
|
callback |
|
) { |
|
(function findDescriptionFile() { |
|
if (oldInfo && oldInfo.directory === directory) { |
|
// We already have info for this directory and can reuse it |
|
return callback(null, oldInfo); |
|
} |
|
forEachBail( |
|
filenames, |
|
(filename, callback) => { |
|
const descriptionFilePath = resolver.join(directory, filename); |
|
if (resolver.fileSystem.readJson) { |
|
resolver.fileSystem.readJson(descriptionFilePath, (err, content) => { |
|
if (err) { |
|
if (typeof err.code !== "undefined") { |
|
if (resolveContext.missingDependencies) { |
|
resolveContext.missingDependencies.add(descriptionFilePath); |
|
} |
|
return callback(); |
|
} |
|
if (resolveContext.fileDependencies) { |
|
resolveContext.fileDependencies.add(descriptionFilePath); |
|
} |
|
return onJson(err); |
|
} |
|
if (resolveContext.fileDependencies) { |
|
resolveContext.fileDependencies.add(descriptionFilePath); |
|
} |
|
onJson(null, content); |
|
}); |
|
} else { |
|
resolver.fileSystem.readFile(descriptionFilePath, (err, content) => { |
|
if (err) { |
|
if (resolveContext.missingDependencies) { |
|
resolveContext.missingDependencies.add(descriptionFilePath); |
|
} |
|
return callback(); |
|
} |
|
if (resolveContext.fileDependencies) { |
|
resolveContext.fileDependencies.add(descriptionFilePath); |
|
} |
|
let json; |
|
|
|
if (content) { |
|
try { |
|
json = JSON.parse(content.toString()); |
|
} catch (e) { |
|
return onJson(e); |
|
} |
|
} else { |
|
return onJson(new Error("No content in file")); |
|
} |
|
|
|
onJson(null, json); |
|
}); |
|
} |
|
|
|
function onJson(err, content) { |
|
if (err) { |
|
if (resolveContext.log) |
|
resolveContext.log( |
|
descriptionFilePath + " (directory description file): " + err |
|
); |
|
else |
|
err.message = |
|
descriptionFilePath + " (directory description file): " + err; |
|
return callback(err); |
|
} |
|
callback(null, { |
|
content, |
|
directory, |
|
path: descriptionFilePath |
|
}); |
|
} |
|
}, |
|
(err, result) => { |
|
if (err) return callback(err); |
|
if (result) { |
|
return callback(null, result); |
|
} else { |
|
const dir = cdUp(directory); |
|
if (!dir) { |
|
return callback(); |
|
} else { |
|
directory = dir; |
|
return findDescriptionFile(); |
|
} |
|
} |
|
} |
|
); |
|
})(); |
|
} |
|
|
|
/** |
|
* @param {any} content content |
|
* @param {string|string[]} field field |
|
* @returns {object|string|number|boolean|undefined} field data |
|
*/ |
|
function getField(content, field) { |
|
if (!content) return undefined; |
|
if (Array.isArray(field)) { |
|
let current = content; |
|
for (let j = 0; j < field.length; j++) { |
|
if (current === null || typeof current !== "object") { |
|
current = null; |
|
break; |
|
} |
|
current = current[field[j]]; |
|
} |
|
return current; |
|
} else { |
|
return content[field]; |
|
} |
|
} |
|
|
|
/** |
|
* @param {string} directory directory |
|
* @returns {string|null} parent directory or null |
|
*/ |
|
function cdUp(directory) { |
|
if (directory === "/") return null; |
|
const i = directory.lastIndexOf("/"), |
|
j = directory.lastIndexOf("\\"); |
|
const p = i < 0 ? j : j < 0 ? i : i < j ? j : i; |
|
if (p < 0) return null; |
|
return directory.substr(0, p || 1); |
|
} |
|
|
|
exports.loadDescriptionFile = loadDescriptionFile; |
|
exports.getField = getField; |
|
exports.cdUp = cdUp;
|
|
|