Skip to content

Commit

Permalink
resourceFactory: Do namespace normalization on exclude patterns
Browse files Browse the repository at this point in the history
  • Loading branch information
RandomByte committed May 24, 2019
1 parent 9d85762 commit c81e2c5
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 28 deletions.
98 changes: 71 additions & 27 deletions lib/resourceFactory.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const path = require("path");
const minimatch = require("minimatch");
const FsAdapter = require("./adapters/FileSystem");
const MemAdapter = require("./adapters/Memory");
const ReaderCollection = require("./ReaderCollection");
Expand Down Expand Up @@ -52,31 +53,26 @@ const resourceFactory = {

function processDependencies(project) {
if (project.resources && project.resources.pathMappings) {
const fsReaders = [];
for (let virBasePath in project.resources.pathMappings) {
// Create an fs reader for every path mapping
const fsAdapters = [];
for (const virBasePath in project.resources.pathMappings) {
if (project.resources.pathMappings.hasOwnProperty(virBasePath)) {
// Prevent duplicate dependency resource locators
const fsPath = project.resources.pathMappings[virBasePath];
const fsBasePath = path.join(project.path, fsPath);

if (useNamespaces && project.metadata.namespace) { // Prefix resource paths with namespace
virBasePath = "/resources/" + project.metadata.namespace + virBasePath;
}

// Prevent duplicate dependency resource locators
const key = virBasePath + fsBasePath;
if (dependencyPathIndex[key]) {
continue;
}
dependencyPathIndex[key] = true;

const fsReader = resourceFactory.createAdapter({
fsBasePath,
// Create an fs adapter for every path mapping
const fsAdapter = resourceFactory.createFsAdapterForVirtualBasePath({
project,
virBasePath,
excludes: getProjectExcludes ? getProjectExcludes(project) : [],
project
useNamespace: useNamespaces,
getProjectExcludes
});
fsReaders.push(fsReader);
fsAdapters.push(fsAdapter);
}
}

Expand All @@ -86,11 +82,11 @@ const resourceFactory = {
const virtualReader = virtualReaders[project.metadata.name];
const readerCollection = new ReaderCollectionPrioritized({
name: `fs & vir reader collection for project ${project.metadata.name}`,
readers: [virtualReader, ...fsReaders]
readers: [virtualReader, ...fsAdapters]
});
dependencyCollection.push(readerCollection);
} else {
dependencyCollection.push(...fsReaders);
dependencyCollection.push(...fsAdapters);
}
}

Expand All @@ -100,19 +96,16 @@ const resourceFactory = {
}

if (tree.resources && tree.resources.pathMappings) {
for (let virBasePath in tree.resources.pathMappings) {
for (const virBasePath in tree.resources.pathMappings) {
if (tree.resources.pathMappings.hasOwnProperty(virBasePath)) {
const fsBasePath = path.join(tree.path, tree.resources.pathMappings[virBasePath]);

if (useNamespaces && tree.metadata.namespace) { // Prefix resource paths with namespace
virBasePath = "/resources/" + tree.metadata.namespace + virBasePath;
}
sourceResourceLocators.push(resourceFactory.createAdapter({
fsBasePath,
// Create an fs adapter for every path mapping
const fsAdapter = resourceFactory.createFsAdapterForVirtualBasePath({
project: tree,
virBasePath,
excludes: getProjectExcludes ? getProjectExcludes(tree) : [],
project: tree
}));
useNamespace: useNamespaces,
getProjectExcludes
});
sourceResourceLocators.push(fsAdapter);
}
}
}
Expand All @@ -135,6 +128,57 @@ const resourceFactory = {
};
},

createFsAdapterForVirtualBasePath({project, virBasePath, useNamespace, getProjectExcludes}) {
const fsPath = project.resources.pathMappings[virBasePath];
const fsBasePath = path.join(project.path, fsPath);

let pathExcludes;
if (getProjectExcludes) {
pathExcludes = getProjectExcludes(project);
}
if (useNamespace && project.metadata.namespace) { // Prefix resource paths with namespace
const namespacedBasePath = "/resources/" + project.metadata.namespace;
virBasePath = namespacedBasePath + virBasePath;

if (pathExcludes) {
const normalizedPatterns = pathExcludes.map((pattern) => {
return resourceFactory._normalizePattern(pattern, namespacedBasePath);
});
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
*/
_normalizePattern(virPattern, virBaseDir) {
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 Down
36 changes: 35 additions & 1 deletion test/lib/resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ test("Get resource from application.a (/index.html) and write it to /dest/ using
}));
});

test("createCollectionsForTree", (t) => {
test("createCollectionsForTree: high level test", (t) => {
// Creates resource reader collections for a given tree
const resourceReaders = ui5Fs.resourceFactory.createCollectionsForTree(applicationBTree);

Expand Down Expand Up @@ -114,6 +114,40 @@ test.serial("createCollectionsForTree with excludes", (t) => {
"Fifth createAdapter call: Correct exclude patterns supplied");
});

test.serial("createFsAdapterForVirtualBasePath", (t) => {
const createAdapterSpy = sinon.spy(ui5Fs.resourceFactory, "createAdapter");

const fsAdapter = ui5Fs.resourceFactory.createFsAdapterForVirtualBasePath({
project: applicationBTreeWithExcludes,
virBasePath: "/",
useNamespace: true,
getProjectExcludes: () => {
return [
"{/sub-directory-1/,/sub-directory-2/}**",
"/pony-path/**",
"!/duck*path/**",
"!**.json"
];
}
});

t.deepEqual(createAdapterSpy.callCount, 1, "createAdapter got called one time");
const firstCall = createAdapterSpy.getCall(0).args[0];
t.deepEqual(firstCall.fsBasePath, path.join(applicationBPath, "webapp"),
"First createAdapter call: Correct base path supplied");
t.deepEqual(firstCall.excludes, [
"/resources/id1/sub-directory-1/**",
"/resources/id1/sub-directory-2/**",
"/resources/id1/pony-path/**",
"!/resources/id1/duck*path/**",
"!/resources/id1/**.json"
],
"First createAdapter call: Correct exclude patterns supplied");

t.deepEqual(fsAdapter._fsBasePath, path.join(applicationBPath, "webapp"), "Returned an FS adapter");
// t.deepEqual(fsAdapter);
});

/* Test data */
const applicationBTree = {
"id": "application.b",
Expand Down

0 comments on commit c81e2c5

Please sign in to comment.