Skip to content

Commit

Permalink
[BREAKING] resourceFactory: Remove #createCollectionsForTree
Browse files Browse the repository at this point in the history
Resource readers are now created during project graph creation in the
corresponding specification implementation
  • Loading branch information
RandomByte committed Jun 13, 2022
1 parent 6d1f411 commit a4d15f6
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 472 deletions.
217 changes: 6 additions & 211 deletions lib/resourceFactory.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,3 @@
const log = require("@ui5/logger").getLogger("resources:resourceFactory");
const path = require("path");
const FsAdapter = require("./adapters/FileSystem");
const MemAdapter = require("./adapters/Memory");
const ReaderCollection = require("./ReaderCollection");
const ReaderCollectionPrioritized = require("./ReaderCollectionPrioritized");
const DuplexCollection = require("./DuplexCollection");
const Resource = require("./Resource");
const hasOwnProperty = Object.prototype.hasOwnProperty;

/**
* Resource Factory
*
Expand All @@ -16,207 +6,6 @@ const hasOwnProperty = Object.prototype.hasOwnProperty;
* @alias module:@ui5/fs.resourceFactory
*/
const resourceFactory = {
/**
* Callback to retrieve excludes for a given project
*
* @public
* @callback module:@ui5/fs.resourceFactory~getProjectExcludes
* @param {object} Project
* @returns {string[]} List of glob patterns to exclude
*/

/**
* Callback to retrieve a prefix to use for a given virtual base path of a project
*
* @public
* @callback module:@ui5/fs.resourceFactory~getVirtualBasePathPrefix
* @param {object} parameters Parameters
* @param {object} parameters.project Project
* @param {object} parameters.virBasePath virtual base path to prefix
* @returns {string} Prefix for the virtual base path
*/

/**
* Creates resource reader collections for a (sub-)tree. Returns an object of resource readers:
* <pre>
* {
* source: Resource reader for source resources
* dependencies: Resource readers for dependency resources
* }
* </pre>
*
* @public
* @param {object} tree A (sub-)tree
* @param {object} [parameters] Parameters
* @param {module:@ui5/fs.resourceFactory~getProjectExcludes} [parameters.getProjectExcludes]
* Callback to retrieve the exclude globs of a project
* @param {module:@ui5/fs.resourceFactory~getVirtualBasePathPrefix} [parameters.getVirtualBasePathPrefix]
* Callback to retrieve a prefix for a given virtual base path of a project if required
* @param {object} [parameters.virtualReaders] Experimental, internal parameter. Do not use
* @returns {object} Object containing <code>source</code> and <code>dependencies</code> resource readers
*/
createCollectionsForTree(tree, {
getProjectExcludes, getVirtualBasePathPrefix, virtualReaders={}
} = {}) {
// TODO 3.0: virtualReaders is private API. The virtual reader of a project should be stored on the
// project itself. This requires projects to become objects independent from the dependency tree.
// Also see: https://github.com/SAP/ui5-project/issues/122

const dependencyCollection = [];
const dependencyPathIndex = {};
const virtualReaderIndex = {};
const sourceResourceLocators = [];

function processDependencies(project) {
if (project.resources && project.resources.pathMappings) {
const fsAdapters = [];
for (const virBasePath in project.resources.pathMappings) {
if (hasOwnProperty.call(project.resources.pathMappings, virBasePath)) {
// Prevent duplicate dependency resource locators
const fsPath = project.resources.pathMappings[virBasePath];
const fsBasePath = path.join(project.path, fsPath);
const key = virBasePath + fsBasePath;
if (dependencyPathIndex[key]) {
continue;
}
dependencyPathIndex[key] = true;

// Create an fs adapter for every path mapping
const fsAdapter = resourceFactory._createFsAdapterForVirtualBasePath({
project,
virBasePath,
getProjectExcludes,
getVirtualBasePathPrefix
});
fsAdapters.push(fsAdapter);
}
}

if (!virtualReaderIndex[project.metadata.name] && virtualReaders[project.metadata.name]) {
// Mix-in virtual reader of dependency if available and not already added
virtualReaderIndex[project.metadata.name] = true;
const virtualReader = virtualReaders[project.metadata.name];
const readerCollection = new ReaderCollectionPrioritized({
name: `fs & vir reader collection for project ${project.metadata.name}`,
readers: [virtualReader, ...fsAdapters]
});
dependencyCollection.push(readerCollection);
} else {
dependencyCollection.push(...fsAdapters);
}
}

project.dependencies.forEach(function(depProject) {
processDependencies(depProject);
});
}

if (tree.resources && tree.resources.pathMappings) {
for (const virBasePath in tree.resources.pathMappings) {
if (hasOwnProperty.call(tree.resources.pathMappings, virBasePath)) {
// Create an fs adapter for every path mapping
const fsAdapter = resourceFactory._createFsAdapterForVirtualBasePath({
project: tree,
virBasePath,
getProjectExcludes,
getVirtualBasePathPrefix
});
sourceResourceLocators.push(fsAdapter);
}
}
}

tree.dependencies.forEach(function(project) {
processDependencies(project);
});

const source = new ReaderCollection({
name: "source of " + tree.metadata.name,
readers: sourceResourceLocators
});
const dependencies = new ReaderCollection({
name: "dependencies of " + tree.metadata.name,
readers: dependencyCollection
});
return {
source,
dependencies
};
},

/**
* Creates a FileSystem adapter mapping to the given virtual base path based on the given projects
* configuration.
*
* @param {object} parameters Parameters
* @param {Project} parameters.project A project
* @param {string} parameters.virBasePath Virtual base path to create the adapter for
* @param {module:@ui5/fs.resourceFactory~getProjectExcludes} [parameters.getProjectExcludes]
* Callback to retrieve the exclude glob of a project
* @param {module:@ui5/fs.resourceFactory~getVirtualBasePathPrefix} [parameters.getVirtualBasePathPrefix]
* Callback to retrieve the exclude glob of a project
* @returns {Promise<string[]>} Promise resolving to list of normalized glob patterns
*/
_createFsAdapterForVirtualBasePath({
project, virBasePath, getProjectExcludes, getVirtualBasePathPrefix
}) {
const fsPath = project.resources.pathMappings[virBasePath];
const fsBasePath = path.join(project.path, fsPath);

let pathExcludes;
if (getProjectExcludes) {
pathExcludes = getProjectExcludes(project);
}

if (getVirtualBasePathPrefix) {
const virBasePathPrefix = getVirtualBasePathPrefix({project, virBasePath});
if (virBasePathPrefix) {
log.verbose(`Prefixing virtual base path ${virBasePath} of project ${project.metadata.name} ` +
`${virBasePathPrefix}...`);
virBasePath = virBasePathPrefix + virBasePath;
log.verbose(`New virtual base path: ${virBasePath}`);

if (pathExcludes) {
const normalizedPatterns = pathExcludes.map((pattern) => {
return resourceFactory._prefixGlobPattern(pattern, virBasePathPrefix);
});
pathExcludes = Array.prototype.concat.apply([], normalizedPatterns);
}
}
}

return resourceFactory.createAdapter({
fsBasePath,
virBasePath,
excludes: pathExcludes,
project
});
},

/**
* Normalizes virtual glob patterns by prefixing them with
* a given virtual base directory path
*
* @param {string} virPattern glob pattern for virtual directory structure
* @param {string} virBaseDir virtual base directory path to prefix the given patterns with
* @returns {Promise<string[]>} Promise resolving to list of normalized glob patterns
*/
_prefixGlobPattern(virPattern, virBaseDir) {
const minimatch = require("minimatch");
const mm = new minimatch.Minimatch(virPattern);

const resultGlobs = [];
for (let i = 0; i < mm.globSet.length; i++) {
let resultPattern = path.posix.join(virBaseDir, mm.globSet[i]);

if (mm.negate) {
resultPattern = "!" + resultPattern;
}
resultGlobs.push(resultPattern);
}
return resultGlobs;
},

/**
* Creates a resource <code>ReaderWriter</code>.
*
Expand All @@ -233,8 +22,10 @@ const resourceFactory = {
*/
createAdapter({fsBasePath, virBasePath, project, excludes}) {
if (fsBasePath) {
const FsAdapter = require("./adapters/FileSystem");
return new FsAdapter({fsBasePath, virBasePath, project, excludes});
} else {
const MemAdapter = require("./adapters/Memory");
return new MemAdapter({virBasePath, project, excludes});
}
},
Expand Down Expand Up @@ -299,6 +90,7 @@ const resourceFactory = {
* @returns {module:@ui5/fs.Resource} Resource
*/
createResource(parameters) {
const Resource = require("./Resource");
return new Resource(parameters);
},

Expand All @@ -319,7 +111,10 @@ const resourceFactory = {
* @returns {module:@ui5/fs.DuplexCollection} DuplexCollection which wraps the provided resource locators
*/
createWorkspace({reader, writer, virBasePath = "/", name = "vir & fs source"}) {
const DuplexCollection = require("./DuplexCollection");

if (!writer) {
const MemAdapter = require("./adapters/Memory");
writer = new MemAdapter({
virBasePath
});
Expand Down
Loading

0 comments on commit a4d15f6

Please sign in to comment.