Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] AbstractAdapter: GLOB match virtual dir fragments #28

Merged
merged 4 commits into from
Jan 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 42 additions & 12 deletions lib/adapters/AbstractAdapter.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const log = require("@ui5/logger").getLogger("resources:adapters:AbstractAdapter");
const minimatch = require("minimatch");
const AbstractReaderWriter = require("../AbstractReaderWriter");
const Resource = require("../Resource");

/**
* Abstract Resource Adapter
Expand Down Expand Up @@ -49,6 +50,25 @@ class AbstractAdapter extends AbstractReaderWriter {
return [];
}
patterns = Array.prototype.concat.apply([], patterns);
if (!options.nodir) {
for (let i = patterns.length - 1; i >= 0; i--) {
const idx = this._virBaseDir.indexOf(patterns[i]);
if (patterns[i] && idx !== -1 && idx < this._virBaseDir.length) {
const subPath = patterns[i];
return Promise.resolve([
new Resource({
project: this.project,
statInfo: { // TODO: make closer to fs stat info
isDirectory: function() {
return true;
}
},
path: subPath
})
]);
}
}
}
return this._runGlob(patterns, options, trace);
});
}
Expand All @@ -62,6 +82,7 @@ class AbstractAdapter extends AbstractReaderWriter {
*/
_normalizePattern(virPattern) {
return Promise.resolve().then(() => {
const that = this;
const mm = new minimatch.Minimatch(virPattern);

const basePathParts = this._virBaseDir.split("/");
Expand All @@ -71,41 +92,50 @@ class AbstractAdapter extends AbstractReaderWriter {
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;
log.verbose("Ran out of glob parts to match (this should not happen):");
if (that._project) { // project is optional
log.verbose(`Project: ${that._project.metadata.name}`);
}
log.verbose(`Virtual base path: ${that._virBaseDir}`);
log.verbose(`Pattern to match: ${virPattern}`);
log.verbose(`Current subset (tried index ${i}):`);
log.verbose(subset);
return {idx: i, virtualMatch: true};
}
const basePathPart = basePathParts[i];
if (typeof globPart === "string") {
if (globPart !== basePathPart) {
return -42;
return null;
} else {
continue;
}
} else if (globPart === minimatch.GLOBSTAR) {
return i;
return {idx: i};
} else { // Regex
if (!globPart.test(basePathPart)) {
return -42;
return null;
} else {
continue;
}
}
}
if (subset.length === basePathParts.length) {
return -1;
return {rootMatch: true};
}
return i;
return {idx: 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
const match = matchSubset(mm.set[i]);
if (match) {
let resultPattern;
if (match.virtualMatch) {
resultPattern = basePathParts.slice(0, match.idx).join("/");
} else if (match.rootMatch) { // matched one up
resultPattern = ""; // root "/"
} else { // matched at some part of the glob
resultPattern = mm.globParts[i].slice(matchIdx).join("/");
resultPattern = mm.globParts[i].slice(match.idx).join("/");
if (resultPattern.startsWith("/")) {
resultPattern = resultPattern.substr(1);
}
Expand Down
21 changes: 11 additions & 10 deletions lib/adapters/Memory.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,24 @@ class Memory extends AbstractAdapter {
}

const filePaths = Object.keys(this._virFiles);
let matchedResources = micromatch(filePaths, patterns, {
const matchedFilePaths = micromatch(filePaths, patterns, {
dot: true
});
let matchedResources = matchedFilePaths.map((virPath) => {
return this._virFiles[virPath];
});

if (!options.nodir) {
// TODO: Add tests for all this
const dirPaths = Object.keys(this._virDirs);
const matchedDirs = micromatch(dirPaths, patterns, {
dot: true
});
matchedResources = matchedResources.concat(matchedDirs);
matchedResources = matchedResources.concat(matchedDirs.map((virPath) => {
return this._virDirs[virPath];
}));
}

return Promise.resolve(matchedResources.map((virPath) => {
return this._virFiles[virPath];
}));
return Promise.resolve(matchedResources);
}

/**
Expand Down Expand Up @@ -117,9 +119,8 @@ class Memory extends AbstractAdapter {
pathSegments.pop(); // Remove last segment representing the resource itself

pathSegments.forEach((segment, i) => {
segment = "/" + segment;
if (i > 1) {
segment = pathSegments[i - 1] + segment;
if (i >= 1) {
segment = pathSegments[i - 1] + "/" + segment;
}
pathSegments[i] = segment;
});
Expand All @@ -134,7 +135,7 @@ class Memory extends AbstractAdapter {
return true;
}
},
path: segment
path: this._virBasePath + segment
});
}
}
Expand Down
63 changes: 63 additions & 0 deletions test/lib/adapters/FileSystem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const {test} = require("ava");
const {resourceFactory} = require("../../../");

test("GLOB resources from application.a w/ virtual base path prefix", async (t) => {
const readerWriter = resourceFactory.createAdapter({
fsBasePath: "./test/fixtures/application.a/webapp",
virBasePath: "/app/"
});

const resources = await readerWriter.byGlob("/app/**/*.html");
t.deepEqual(resources.length, 1, "Found exactly one resource");
});

test("GLOB resources from application.a w/o virtual base path prefix", async (t) => {
const readerWriter = resourceFactory.createAdapter({
fsBasePath: "./test/fixtures/application.a/webapp",
virBasePath: "/app/"
});

const resources = await readerWriter.byGlob("/**/*.html");
t.deepEqual(resources.length, 1, "Found exactly one resource");
});


test("GLOB virtual directory w/o virtual base path prefix", async (t) => {
const readerWriter = resourceFactory.createAdapter({
fsBasePath: "./test/fixtures/application.a/webapp",
virBasePath: "/app/"
});

const resources = await readerWriter.byGlob("/*", {nodir: false});
t.deepEqual(resources.length, 1, "Found exactly one resource");
});

test("GLOB virtual directory w/ virtual base path prefix", async (t) => {
const readerWriter = resourceFactory.createAdapter({
fsBasePath: "./test/fixtures/application.a/webapp",
virBasePath: "/app/one/two/"
});

const resources = await readerWriter.byGlob("/app/*", {nodir: false});
t.deepEqual(resources.length, 1, "Found exactly one resource");
});

test("GLOB virtual directory w/o virtual base path prefix and nodir: true", async (t) => {
const readerWriter = resourceFactory.createAdapter({
fsBasePath: "./test/fixtures/application.a/webapp",
virBasePath: "/app/"
});

const resources = await readerWriter.byGlob("/*", {nodir: true});
t.deepEqual(resources.length, 0, "Found no resources");
});

test("GLOB virtual directory w/ virtual base path prefix and nodir: true", async (t) => {
const readerWriter = resourceFactory.createAdapter({
fsBasePath: "./test/fixtures/application.a/webapp",
virBasePath: "/app/one/two/"
});

const resources = await readerWriter.byGlob("/app/*", {nodir: true});
t.deepEqual(resources.length, 0, "Found no resources");
});
Loading