From 532a2f0cfa81f64f4c423ab53aad3c2486e23c56 Mon Sep 17 00:00:00 2001 From: Marc Walter Date: Wed, 17 Jun 2020 09:00:28 +0200 Subject: [PATCH 1/3] Extract HashedFile and HashedFolder from closure --- index.js | 108 +++++++++++++++++++++++++++---------------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/index.js b/index.js index 5faf0ee..0e53e72 100644 --- a/index.js +++ b/index.js @@ -165,10 +165,10 @@ function prep(fs) { case 'ignore-target-content': return symLinkIgnoreTargetContent(name, target, options, isRootElement); - + case 'resolve': return symLinkResolve(name, dir, target, options, isRootElement); - + default: throw `Invalid option: symbolicLinks.follow = "${options.symbolicLinks.follow}"`; } @@ -178,7 +178,7 @@ function prep(fs) { delete options.skipMatching // only used for the root level log.symlink('ignoring symbolic link target content'); const hash = crypto.createHash(options.algo); - if (!options.symbolicLinks.ignoreBasename && + if (!options.symbolicLinks.ignoreBasename && !(isRootElement && options.files.ignoreRootName)) { log.symlink('hash basename'); hash.update(name); @@ -255,57 +255,6 @@ function prep(fs) { return false; } - const HashedFolder = function HashedFolder(name, children, options, isRootElement = false) { - this.name = name; - this.children = children; - - const hash = crypto.createHash(options.algo); - if (options.folders.ignoreBasename || - options.ignoreBasenameOnce || - (isRootElement && options.folders.ignoreRootName)) - { - delete options.ignoreBasenameOnce; - log.match(`omitted name of folder ${name} from hash`) - } else { - hash.update(name); - } - children.forEach(child => { - if (child.hash) { - hash.update(child.hash); - } - }); - - this.hash = hash.digest(options.encoding); - }; - - HashedFolder.prototype.toString = function (padding = '') { - const first = `${padding}{ name: '${this.name}', hash: '${this.hash},'\n`; - padding += ' '; - - return `${first}${padding}children: ${this.childrenToString(padding)}}`; - }; - - HashedFolder.prototype.childrenToString = function (padding = '') { - if (this.children.length === 0) { - return '[]'; - } else { - const nextPadding = padding + ' '; - const children = this.children - .map(child => child.toString(nextPadding)) - .join('\n'); - return `[\n${children}\n${padding}]`; - } - }; - - const HashedFile = function HashedFile(name, hash, encoding) { - this.name = name; - this.hash = hash.digest(encoding); - }; - - HashedFile.prototype.toString = function (padding = '') { - return padding + '{ name: \'' + this.name + '\', hash: \'' + this.hash + '\' }'; - }; - return hashElement; } @@ -344,6 +293,57 @@ function parseParameters(args) { return Promise.resolve(log.params({ basename, dir, options })); } +const HashedFolder = function HashedFolder(name, children, options, isRootElement = false) { + this.name = name; + this.children = children; + + const hash = crypto.createHash(options.algo); + if (options.folders.ignoreBasename || + options.ignoreBasenameOnce || + (isRootElement && options.folders.ignoreRootName)) + { + delete options.ignoreBasenameOnce; + log.match(`omitted name of folder ${name} from hash`) + } else { + hash.update(name); + } + children.forEach(child => { + if (child.hash) { + hash.update(child.hash); + } + }); + + this.hash = hash.digest(options.encoding); +}; + +HashedFolder.prototype.toString = function (padding = '') { + const first = `${padding}{ name: '${this.name}', hash: '${this.hash},'\n`; + padding += ' '; + + return `${first}${padding}children: ${this.childrenToString(padding)}}`; +}; + +HashedFolder.prototype.childrenToString = function (padding = '') { + if (this.children.length === 0) { + return '[]'; + } else { + const nextPadding = padding + ' '; + const children = this.children + .map(child => child.toString(nextPadding)) + .join('\n'); + return `[\n${children}\n${padding}]`; + } +}; + +const HashedFile = function HashedFile(name, hash, encoding) { + this.name = name; + this.hash = hash.digest(encoding); +}; + +HashedFile.prototype.toString = function (padding = '') { + return padding + '{ name: \'' + this.name + '\', hash: \'' + this.hash + '\' }'; +}; + function isFunction(any) { return typeof any === 'function'; } From f90b78400a4aeb406d9bfe48b5f728e0b4b93797 Mon Sep 17 00:00:00 2001 From: Marc Walter Date: Wed, 17 Jun 2020 09:24:52 +0200 Subject: [PATCH 2/3] Improve logs of matching rules --- index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 0e53e72..e98eb36 100644 --- a/index.js +++ b/index.js @@ -233,7 +233,7 @@ function prep(fs) { function ignore(name, path, rules) { if (rules.exclude) { if (rules.matchBasename && rules.exclude(name)) { - log.match(`exclude basename '${path}'`); + log.match(`exclude basename '${name}'`); return true; } else if (rules.matchPath && rules.exclude(path)) { log.match(`exclude path '${path}'`); @@ -241,12 +241,13 @@ function prep(fs) { } } else if (rules.include) { if (rules.matchBasename && rules.include(name)) { - log.match(`include basename '${path}'`); + log.match(`include basename '${name}'`); return false; } else if (rules.matchPath && rules.include(path)) { log.match(`include path '${path}'`); return false; } else { + log.match(`include rule failed for path '${path}'`); return true; } } From 39ae165c9293659c4e96d2e8a512130283cf3a9c Mon Sep 17 00:00:00 2001 From: Marc Walter Date: Wed, 17 Jun 2020 09:25:30 +0200 Subject: [PATCH 3/3] Breaking change: Allow users to combine include and exclude rules Exclude rules beat include rules: If a file/folder matches both include and exclude rules, it is excluded. Fixes #25 --- index.js | 3 ++- test/folders.js | 45 ++++++++++++++++++++++++++++----------------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/index.js b/index.js index e98eb36..7e0ff17 100644 --- a/index.js +++ b/index.js @@ -239,7 +239,8 @@ function prep(fs) { log.match(`exclude path '${path}'`); return true; } - } else if (rules.include) { + } + if (rules.include) { if (rules.matchBasename && rules.include(name)) { log.match(`include basename '${name}'`); return false; diff --git a/test/folders.js b/test/folders.js index 9bfe770..c129af5 100644 --- a/test/folders.js +++ b/test/folders.js @@ -195,26 +195,37 @@ describe('Generating a hash over a folder, it', function () { }); }); - it('ignores a folder it is both included and excluded', function () { + it('ignores a folder it is both included and excluded', async function () { const hashElement = prep(Volume.fromJSON({ 'base/file1': 'content', 'base/folder/file2': '2', 'base/folder2/file3': '3' })); - return hashElement('base', { + async function verify(options) { + const result = await hashElement('base', options); + should.exist(result.hash); + should.exist(result.children); + result.children.length.should.equal(2); + result.children[0].name.should.equal('file1'); + result.children[1].name.should.equal('folder2'); + } + + await verify({ folders: { - exclude: ['**/folder', '**folder'], include: ['*'], + exclude: ['**/folder'], + include: ['**/*'], matchBasename: false, matchPath: true } - }) - .then(result => { - should.exist(result.hash); - should.exist(result.children); - result.children.length.should.equal(2); - result.children[0].name.should.equal('file1'); - result.children[1].name.should.equal('folder2'); - }); + }); + + await verify({ + folders: { + exclude: ['folder'], + include: ['*'], + matchBasename: true, matchPath: false + } + }); }); it('only includes the wanted folders', function () { @@ -280,15 +291,15 @@ describe('Generating a hash over a folder, it', function () { 'def/file1.js': '//just a comment', 'def/def/.ignored': 'ignored' })); - const options = { + const options = { folders: { ignoreRootName: true }, - files: { exclude: ['.*'] } + files: { exclude: ['.*'] } }; return Promise.all([ hashElement('abc', options), hashElement('def', options) - ]).then(function (hashes) { + ]).then(function (hashes) { return hashes[0].hash.should.equal(hashes[1].hash); }); }); @@ -301,15 +312,15 @@ describe('Generating a hash over a folder, it', function () { 'def/file1.js': '//just a comment', 'def/def/.ignored': 'ignored' })); - const options = { + const options = { folders: { ignoreBasename: true }, - files: { exclude: ['.*'] } + files: { exclude: ['.*'] } }; return Promise.all([ hashElement('abc', options), hashElement('def', options) - ]).then(function (hashes) { + ]).then(function (hashes) { return hashes[1].hash.should.equal(hashes[0].hash); }); });