@ui5/fs
Version:
UI5 Build and Development Tooling - File System Abstraction
125 lines (117 loc) • 3.48 kB
JavaScript
const log = require("@ui5/logger").getLogger("resources:adapters:AbstractAdapter");
const minimatch = require("minimatch");
const AbstractReaderWriter = require("../AbstractReaderWriter");
/**
* Abstract Resource Adapter
*
* @abstract
* @public
* @memberof module:@ui5/fs.adapters
* @augments module:@ui5/fs.AbstractReaderWriter
*/
class AbstractAdapter extends AbstractReaderWriter {
/**
* The constructor
*
* @public
* @param {Object} parameters Parameters
* @param {string} parameters.virBasePath Virtual base path
*/
constructor({virBasePath, project}) {
if (new.target === AbstractAdapter) {
throw new TypeError("Class 'AbstractAdapter' is abstract");
}
super();
this._virBasePath = virBasePath;
this._virBaseDir = virBasePath.slice(0, -1);
this._project = project;
}
/**
* Locates resources by GLOB.
*
* @abstract
* @private
* @param {string|Array} virPattern GLOB pattern as string or an array of
* glob patterns for virtual directory structure
* @param {Object} [options={}] GLOB options
* @param {boolean} [options.nodir=true] Do not match directories
* @param {module:@ui5/fs.tracing.Trace} trace Trace instance
* @returns {Promise<module:@ui5/fs.Resource[]>} Promise resolving to list of resources
*/
_byGlob(virPattern, options = {nodir: true}, trace) {
if (!(virPattern instanceof Array)) {
virPattern = [virPattern];
}
return Promise.all(virPattern.map(this._normalizePattern, this)).then((patterns) => {
if (patterns.length === 0) {
return [];
}
patterns = Array.prototype.concat.apply([], patterns);
return this._runGlob(patterns, options, trace);
});
}
/**
* Normalizes virtual GLOB patterns.
*
* @private
* @param {string} virPattern GLOB pattern for virtual directory structure
* @returns {Promise<string[]>} Promise resolving to list of normalized GLOB patterns
*/
_normalizePattern(virPattern) {
return Promise.resolve().then(() => {
const mm = new minimatch.Minimatch(virPattern);
const basePathParts = this._virBaseDir.split("/");
function matchSubset(subset) {
let i;
for (i = 0; i < basePathParts.length; i++) {
const globPart = subset[i];
if (globPart === undefined) {
log.verbose("Ran out of glob parts to match. This should not happen.");
return -42;
}
const basePathPart = basePathParts[i];
if (typeof globPart === "string") {
if (globPart !== basePathPart) {
return -42;
} else {
continue;
}
} else if (globPart === minimatch.GLOBSTAR) {
return i;
} else { // Regex
if (!globPart.test(basePathPart)) {
return -42;
} else {
continue;
}
}
}
if (subset.length === basePathParts.length) {
return -1;
}
return i;
}
const resultGlobs = [];
for (let i = 0; i < mm.set.length; i++) {
const matchIdx = matchSubset(mm.set[i]);
let resultPattern;
if (matchIdx !== -42) {
if (matchIdx === -1) { // matched one up
resultPattern = ""; // root "/"
} else { // matched at some part of the glob
resultPattern = mm.globParts[i].slice(matchIdx).join("/");
if (resultPattern.startsWith("/")) {
resultPattern = resultPattern.substr(1);
}
}
if (mm.negate) {
resultPattern = "!" + resultPattern;
}
resultGlobs.push(resultPattern);
}
}
return resultGlobs;
});
}
}
module.exports = AbstractAdapter;