Skip to content

Commit

Permalink
fix: excludes the passed path for purposes of matching inclusion/excl…
Browse files Browse the repository at this point in the history
…usion folders

The same folder accessed from a different working directory will include/exclude in the same way
  • Loading branch information
Aeolun committed Jul 7, 2023
1 parent d3df702 commit 6cee01c
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 16 deletions.
37 changes: 21 additions & 16 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ function prep(fs) {

function hashElement(name, dir, options, callback) {
callback = arguments[arguments.length - 1];
const base = name;

return parseParameters(arguments)
.then(({ basename, dir, options }) => {
Expand All @@ -60,7 +61,7 @@ function prep(fs) {
stats.name = basename;
return stats;
})
.then(stats => hashElementPromise(stats, dir, options, true));
.then(stats => hashElementPromise(stats, dir, base, options, true));
})
.then(result => {
if (isFunction(callback)) {
Expand All @@ -82,18 +83,19 @@ function prep(fs) {
/**
* @param {fs.Stats} stats folder element, can also be of type fs.Dirent
* @param {string} dirname
* @param {string} base
* @param {Options} options
* @param {boolean} isRootElement
*/
function hashElementPromise(stats, dirname, options, isRootElement = false) {
function hashElementPromise(stats, dirname, base, options, isRootElement = false) {
const name = stats.name;
let promise = undefined;
if (stats.isDirectory()) {
promise = hashFolderPromise(name, dirname, options, isRootElement);
promise = hashFolderPromise(name, dirname, base, options, isRootElement);
} else if (stats.isFile()) {
promise = hashFilePromise(name, dirname, options, isRootElement);
promise = hashFilePromise(name, dirname, base, options, isRootElement);
} else if (stats.isSymbolicLink()) {
promise = hashSymLinkPromise(name, dirname, options, isRootElement);
promise = hashSymLinkPromise(name, dirname, base, options, isRootElement);
} else {
log.err('hashElementPromise cannot handle ', stats);
return Promise.resolve({ name, hash: 'Error: unknown element type' });
Expand All @@ -106,7 +108,7 @@ function prep(fs) {
const promise = new Promise((resolve, reject) => {
queue.push(() => {
log.queue(`Will processs queued ${dirname}/${name}`);
return hashElementPromise(stats, dirname, options, isRootElement)
return hashElementPromise(stats, dirname, base, options, isRootElement)
.then(ok => resolve(ok))
.catch(err => reject(err));
});
Expand All @@ -129,7 +131,7 @@ function prep(fs) {
runnables.forEach(run => run());
}

async function hashFolderPromise(name, dir, options, isRootElement = false) {
async function hashFolderPromise(name, dir, base, options, isRootElement = false) {
const folderPath = path.join(dir, name);
let ignoreBasenameOnce = options.ignoreBasenameOnce;
delete options.ignoreBasenameOnce;
Expand All @@ -138,30 +140,30 @@ function prep(fs) {
// this is currently only used for the root folder
log.match(`skipped '${folderPath}'`);
delete options.skipMatching;
} else if (ignore(name, folderPath, options.folders)) {
} else if (ignore(name, folderPath, base, options.folders)) {
return undefined;
}

const files = await fs.promises.readdir(folderPath, { withFileTypes: true });
const children = await Promise.all(
files
.sort((a, b) => a.name.localeCompare(b.name))
.map(child => hashElementPromise(child, folderPath, options)),
.map(child => hashElementPromise(child, folderPath, base, options)),
);

if (ignoreBasenameOnce) options.ignoreBasenameOnce = true;
const hash = new HashedFolder(name, children.filter(notUndefined), options, isRootElement);
return hash;
}

function hashFilePromise(name, dir, options, isRootElement = false) {
function hashFilePromise(name, dir, base, options, isRootElement = false) {
const filePath = path.join(dir, name);

if (options.skipMatching) {
// this is currently only used for the root folder
log.match(`skipped '${filePath}'`);
delete options.skipMatching;
} else if (ignore(name, filePath, options.files)) {
} else if (ignore(name, filePath, base, options.files)) {
return Promise.resolve(undefined);
}

Expand Down Expand Up @@ -195,14 +197,14 @@ function prep(fs) {
});
}

async function hashSymLinkPromise(name, dir, options, isRootElement = false) {
async function hashSymLinkPromise(name, dir, base, options, isRootElement = false) {
const target = await fs.promises.readlink(path.join(dir, name));
log.symlink(`handling symbolic link ${name} -> ${target}`);
if (options.symbolicLinks.include) {
if (options.symbolicLinks.ignoreTargetContent) {
return symLinkIgnoreTargetContent(name, target, options, isRootElement);
} else {
return symLinkResolve(name, dir, target, options, isRootElement);
return symLinkResolve(name, dir, base, target, options, isRootElement);
}
} else {
log.symlink('skipping symbolic link');
Expand All @@ -225,7 +227,7 @@ function prep(fs) {
return Promise.resolve(new HashedFile(name, hash, options.encoding));
}

async function symLinkResolve(name, dir, target, options, isRootElement) {
async function symLinkResolve(name, dir, base, target, options, isRootElement) {
delete options.skipMatching; // only used for the root level
if (options.symbolicLinks.ignoreBasename) {
options.ignoreBasenameOnce = true;
Expand All @@ -234,7 +236,7 @@ function prep(fs) {
try {
const stats = await fs.promises.stat(path.join(dir, name));
stats.name = name;
const temp = await hashElementPromise(stats, dir, options, isRootElement);
const temp = await hashElementPromise(stats, dir, base, options, isRootElement);

if (!options.symbolicLinks.ignoreTargetPath) {
const hash = crypto.createHash(options.algo);
Expand Down Expand Up @@ -265,7 +267,10 @@ function prep(fs) {
}
}

function ignore(name, path, rules) {
function ignore(name, path, root, rules) {
path = path.replace(root, '');
if (path.startsWith('/')) path = path.substring(1);

if (rules.exclude) {
if (rules.matchBasename && rules.exclude(name)) {
log.match(`exclude basename '${name}'`);
Expand Down
25 changes: 25 additions & 0 deletions test/folders.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,31 @@ describe('Generating a hash over a folder, it', function () {
return hashElement('abc', options).then(checkChildren);
});

it('ignores base directory for purposes of exclude function', function () {
const hashElement = prep(
Volume.fromJSON({
'abc/def': 'abc/def',
'abc/ghi/jkl/file.js': 'content',
'abc/ghi/jkl/file2.js': 'content',
'abc/ghi/folder/data.json': 'content',
'abc/ghi/folder/subfolder/today.log': 'content',
}),
);

const options = {
folders: {
exclude: ['jkl'],
},
};

const checkChildren = current => {
current.children.length.should.equal(1);
current.children[0].name.should.equal('folder');
};

return hashElement('abc/ghi', options).then(checkChildren);
});

it('generates different hashes if the folders have the same content but different names', function () {
const hashElement = prep(
Volume.fromJSON({
Expand Down

0 comments on commit 6cee01c

Please sign in to comment.