diff --git a/CHANGELOG.md b/CHANGELOG.md
index 682c9f3..31d6720 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
# Changelog
+## 4.0.3 (2023-01-10)
+- Fix #146 and remove `graceful-fs`
+- Update dependencies
+
## 4.0.2 (2022-02-15)
- Update dependencies
- Minor changes to README
diff --git a/README.md b/README.md
index 44032d4..8bf80b7 100644
--- a/README.md
+++ b/README.md
@@ -138,7 +138,7 @@ const options = {
```js
{
algo: 'sha1', // see crypto.getHashes() for options in your node.js REPL
- encoding: 'base64', // 'base64', 'hex' or 'binary'
+ encoding: 'base64', // 'base64', 'base64url', 'hex' or 'binary'
files: {
exclude: [],
include: [],
@@ -199,7 +199,7 @@ const options = {
'base64'
|
- encoding of the resulting hash. One of 'base64', 'hex' or 'binary' |
+ encoding of the resulting hash. One of 'base64', 'base64url', 'hex' or 'binary' |
files |
diff --git a/index.js b/index.js
index 96e55f7..59d9e0c 100644
--- a/index.js
+++ b/index.js
@@ -5,7 +5,7 @@
const defaultOptions = {
algo: 'sha1', // see crypto.getHashes() for options
- encoding: 'base64', // 'base64', 'hex' or 'binary'
+ encoding: 'base64', // 'base64', 'base64url', 'hex' or 'binary'
files: {
exclude: [],
include: [],
@@ -40,9 +40,13 @@ const log = {
},
err: debug('fhash:err'),
symlink: debug('fhash:symlink'),
+ queue: debug('fhash:queue'),
};
function prep(fs) {
+ let queue = [];
+ let queueTimer = undefined;
+
function hashElement(name, dir, options, callback) {
callback = arguments[arguments.length - 1];
@@ -83,19 +87,49 @@ function prep(fs) {
*/
function hashElementPromise(stats, dirname, options, isRootElement = false) {
const name = stats.name;
+ let promise = undefined;
if (stats.isDirectory()) {
- return hashFolderPromise(name, dirname, options, isRootElement);
+ promise = hashFolderPromise(name, dirname, options, isRootElement);
} else if (stats.isFile()) {
- return hashFilePromise(name, dirname, options, isRootElement);
+ promise = hashFilePromise(name, dirname, options, isRootElement);
} else if (stats.isSymbolicLink()) {
- return hashSymLinkPromise(name, dirname, options, isRootElement);
+ promise = hashSymLinkPromise(name, dirname, options, isRootElement);
} else {
log.err('hashElementPromise cannot handle ', stats);
- return { name, hash: 'Error: unknown element type' };
+ return Promise.resolve({ name, hash: 'Error: unknown element type' });
}
+
+ return promise.catch(err => {
+ if (err.code && (err.code === 'EMFILE' || err.code === 'ENFILE')) {
+ log.queue(`queued ${dirname}/${name} because of ${err.code}`);
+
+ const promise = new Promise((resolve, reject) => {
+ queue.push(() => {
+ log.queue(`Will processs queued ${dirname}/${name}`);
+ return hashElementPromise(stats, dirname, options, isRootElement)
+ .then(ok => resolve(ok))
+ .catch(err => reject(err));
+ });
+ });
+
+ if (queueTimer === undefined) {
+ queueTimer = setTimeout(processQueue, 0);
+ }
+ return promise;
+ }
+
+ throw err;
+ });
}
- function hashFolderPromise(name, dir, options, isRootElement = false) {
+ function processQueue() {
+ queueTimer = undefined;
+ const runnables = queue;
+ queue = [];
+ runnables.forEach(run => run());
+ }
+
+ async function hashFolderPromise(name, dir, options, isRootElement = false) {
const folderPath = path.join(dir, name);
let ignoreBasenameOnce = options.ignoreBasenameOnce;
delete options.ignoreBasenameOnce;
@@ -108,19 +142,16 @@ function prep(fs) {
return undefined;
}
- return fs.promises.readdir(folderPath, { withFileTypes: true }).then(files => {
- const children = files
+ 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 => {
- return hashElementPromise(child, folderPath, options);
- });
+ .map(child => hashElementPromise(child, folderPath, options)),
+ );
- return Promise.all(children).then(children => {
- if (ignoreBasenameOnce) options.ignoreBasenameOnce = true;
- const hash = new HashedFolder(name, children.filter(notUndefined), options, isRootElement);
- return hash;
- });
- });
+ if (ignoreBasenameOnce) options.ignoreBasenameOnce = true;
+ const hash = new HashedFolder(name, children.filter(notUndefined), options, isRootElement);
+ return hash;
}
function hashFilePromise(name, dir, options, isRootElement = false) {
@@ -131,7 +162,7 @@ function prep(fs) {
log.match(`skipped '${filePath}'`);
delete options.skipMatching;
} else if (ignore(name, filePath, options.files)) {
- return undefined;
+ return Promise.resolve(undefined);
}
return new Promise((resolve, reject) => {
@@ -149,6 +180,9 @@ function prep(fs) {
}
const f = fs.createReadStream(filePath);
+ f.on('error', err => {
+ reject(err);
+ });
f.pipe(hash, { end: false });
f.on('end', () => {
@@ -382,7 +416,7 @@ function reduceGlobPatterns(globs) {
module.exports = {
defaults: defaultOptions,
- hashElement: prep(require('graceful-fs')),
+ hashElement: prep(require('fs')),
// exposed for testing
prep,
parseParameters,
diff --git a/package-lock.json b/package-lock.json
index a17c10d..5eab945 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,17 +1,16 @@
{
"name": "folder-hash",
- "version": "4.0.2",
+ "version": "4.0.3",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "folder-hash",
- "version": "4.0.2",
+ "version": "4.0.3",
"license": "MIT",
"dependencies": {
"debug": "^4.3.3",
- "graceful-fs": "~4.2.9",
- "minimatch": "~5.0.0"
+ "minimatch": "~5.1.2"
},
"bin": {
"folder-hash": "bin/folder-hash"
@@ -21,11 +20,11 @@
"chai-as-promised": "^7.1.1",
"clone": "^2.1.2",
"ignore": "^5.2.0",
- "jsdoc": "3.6.10",
+ "jsdoc": "4.0.0",
"memfs": "^3.4.1",
"mocha": "^9.2.0",
"nyc": "^15.1.0",
- "prettier": "~2.5.1"
+ "prettier": "~2.8.2"
},
"engines": {
"node": ">=10.10.0"
@@ -358,6 +357,18 @@
"node": ">=8"
}
},
+ "node_modules/@jsdoc/salty": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.1.tgz",
+ "integrity": "sha512-JXwylDNSHa549N9uceDYu8D4GMXwSo3H8CCPYEQqxhhHpxD28+lRl2b3bS/caaPj5w1YD3SWtrficJNTnUjGpg==",
+ "dev": true,
+ "dependencies": {
+ "lodash": "^4.17.21"
+ },
+ "engines": {
+ "node": ">=v12.0.0"
+ }
+ },
"node_modules/@types/color-name": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
@@ -567,14 +578,14 @@
}
},
"node_modules/chai": {
- "version": "4.3.6",
- "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
- "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz",
+ "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==",
"dev": true,
"dependencies": {
"assertion-error": "^1.1.0",
"check-error": "^1.0.2",
- "deep-eql": "^3.0.1",
+ "deep-eql": "^4.1.2",
"get-func-name": "^2.0.0",
"loupe": "^2.3.1",
"pathval": "^1.1.1",
@@ -800,9 +811,9 @@
}
},
"node_modules/debug": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
- "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dependencies": {
"ms": "2.1.2"
},
@@ -825,15 +836,15 @@
}
},
"node_modules/deep-eql": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
- "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
+ "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==",
"dev": true,
"dependencies": {
"type-detect": "^4.0.0"
},
"engines": {
- "node": ">=0.12"
+ "node": ">=6"
}
},
"node_modules/default-require-extensions": {
@@ -1104,7 +1115,8 @@
"node_modules/graceful-fs": {
"version": "4.2.9",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
+ "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
+ "dev": true
},
"node_modules/growl": {
"version": "1.10.5",
@@ -1153,9 +1165,9 @@
"dev": true
},
"node_modules/ignore": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
- "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
"dev": true,
"engines": {
"node": ">= 4"
@@ -1451,32 +1463,32 @@
}
},
"node_modules/jsdoc": {
- "version": "3.6.10",
- "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.10.tgz",
- "integrity": "sha512-IdQ8ppSo5LKZ9o3M+LKIIK8i00DIe5msDvG3G81Km+1dhy0XrOWD0Ji8H61ElgyEj/O9KRLokgKbAM9XX9CJAg==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.0.tgz",
+ "integrity": "sha512-tzTgkklbWKrlaQL2+e3NNgLcZu3NaK2vsHRx7tyHQ+H5jcB9Gx0txSd2eJWlMC/xU1+7LQu4s58Ry0RkuaEQVg==",
"dev": true,
"dependencies": {
"@babel/parser": "^7.9.4",
+ "@jsdoc/salty": "^0.2.1",
"@types/markdown-it": "^12.2.3",
"bluebird": "^3.7.2",
"catharsis": "^0.9.0",
"escape-string-regexp": "^2.0.0",
"js2xmlparser": "^4.0.2",
- "klaw": "^4.0.1",
+ "klaw": "^3.0.0",
"markdown-it": "^12.3.2",
"markdown-it-anchor": "^8.4.1",
"marked": "^4.0.10",
"mkdirp": "^1.0.4",
"requizzle": "^0.2.3",
"strip-json-comments": "^3.1.0",
- "taffydb": "2.6.2",
"underscore": "~1.13.2"
},
"bin": {
"jsdoc": "jsdoc.js"
},
"engines": {
- "node": ">=8.15.0"
+ "node": ">=12.0.0"
}
},
"node_modules/jsesc": {
@@ -1492,13 +1504,10 @@
}
},
"node_modules/json5": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
- "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true,
- "dependencies": {
- "minimist": "^1.2.5"
- },
"bin": {
"json5": "lib/cli.js"
},
@@ -1507,12 +1516,12 @@
}
},
"node_modules/klaw": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/klaw/-/klaw-4.0.1.tgz",
- "integrity": "sha512-pgsE40/SvC7st04AHiISNewaIMUbY5V/K8b21ekiPiFoYs/EYSdsGa+FJArB1d441uq4Q8zZyIxvAzkGNlBdRw==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz",
+ "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==",
"dev": true,
- "engines": {
- "node": ">=14.14.0"
+ "dependencies": {
+ "graceful-fs": "^4.1.9"
}
},
"node_modules/linkify-it": {
@@ -1715,21 +1724,21 @@
"dev": true
},
"node_modules/memfs": {
- "version": "3.4.1",
- "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz",
- "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==",
+ "version": "3.4.13",
+ "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.13.tgz",
+ "integrity": "sha512-omTM41g3Skpvx5dSYeZIbXKcXoAVc/AoMNwn9TKx++L/gaen/+4TTttmu8ZSch5vfVJ8uJvGbroTsIlslRg6lg==",
"dev": true,
"dependencies": {
- "fs-monkey": "1.0.3"
+ "fs-monkey": "^1.0.3"
},
"engines": {
"node": ">= 4.0.0"
}
},
"node_modules/minimatch": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.0.tgz",
- "integrity": "sha512-EU+GCVjXD00yOUf1TwAHVP7v3fBD3A8RkkPYsWWKGWesxM/572sL53wJQnHxquHlRhYUV36wHkqrN8cdikKc2g==",
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.2.tgz",
+ "integrity": "sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg==",
"dependencies": {
"brace-expansion": "^2.0.1"
},
@@ -1737,12 +1746,6 @@
"node": ">=10"
}
},
- "node_modules/minimist": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
- "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
- "dev": true
- },
"node_modules/mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
@@ -1855,6 +1858,29 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
+ "node_modules/mocha/node_modules/debug": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
+ "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/mocha/node_modules/debug/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
"node_modules/mocha/node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -2292,15 +2318,18 @@
}
},
"node_modules/prettier": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
- "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
+ "version": "2.8.2",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.2.tgz",
+ "integrity": "sha512-BtRV9BcncDyI2tsuS19zzhzoxD8Dh8LiCx7j7tHzrkz8GFXAexeWFdi22mjE1d16dftH2qNaytVxqiRTGlMfpw==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/process-on-spawn": {
@@ -2545,12 +2574,6 @@
"node": ">=8"
}
},
- "node_modules/taffydb": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz",
- "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=",
- "dev": true
- },
"node_modules/test-exclude": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
@@ -3255,6 +3278,15 @@
"integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==",
"dev": true
},
+ "@jsdoc/salty": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.1.tgz",
+ "integrity": "sha512-JXwylDNSHa549N9uceDYu8D4GMXwSo3H8CCPYEQqxhhHpxD28+lRl2b3bS/caaPj5w1YD3SWtrficJNTnUjGpg==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.21"
+ }
+ },
"@types/color-name": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
@@ -3428,14 +3460,14 @@
}
},
"chai": {
- "version": "4.3.6",
- "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
- "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz",
+ "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==",
"dev": true,
"requires": {
"assertion-error": "^1.1.0",
"check-error": "^1.0.2",
- "deep-eql": "^3.0.1",
+ "deep-eql": "^4.1.2",
"get-func-name": "^2.0.0",
"loupe": "^2.3.1",
"pathval": "^1.1.1",
@@ -3617,9 +3649,9 @@
}
},
"debug": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
- "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"requires": {
"ms": "2.1.2"
}
@@ -3631,9 +3663,9 @@
"dev": true
},
"deep-eql": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
- "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
+ "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==",
"dev": true,
"requires": {
"type-detect": "^4.0.0"
@@ -3838,7 +3870,8 @@
"graceful-fs": {
"version": "4.2.9",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
- "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
+ "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
+ "dev": true
},
"growl": {
"version": "1.10.5",
@@ -3875,9 +3908,9 @@
"dev": true
},
"ignore": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
- "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
"dev": true
},
"imurmurhash": {
@@ -4107,25 +4140,25 @@
}
},
"jsdoc": {
- "version": "3.6.10",
- "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.10.tgz",
- "integrity": "sha512-IdQ8ppSo5LKZ9o3M+LKIIK8i00DIe5msDvG3G81Km+1dhy0XrOWD0Ji8H61ElgyEj/O9KRLokgKbAM9XX9CJAg==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.0.tgz",
+ "integrity": "sha512-tzTgkklbWKrlaQL2+e3NNgLcZu3NaK2vsHRx7tyHQ+H5jcB9Gx0txSd2eJWlMC/xU1+7LQu4s58Ry0RkuaEQVg==",
"dev": true,
"requires": {
"@babel/parser": "^7.9.4",
+ "@jsdoc/salty": "^0.2.1",
"@types/markdown-it": "^12.2.3",
"bluebird": "^3.7.2",
"catharsis": "^0.9.0",
"escape-string-regexp": "^2.0.0",
"js2xmlparser": "^4.0.2",
- "klaw": "^4.0.1",
+ "klaw": "^3.0.0",
"markdown-it": "^12.3.2",
"markdown-it-anchor": "^8.4.1",
"marked": "^4.0.10",
"mkdirp": "^1.0.4",
"requizzle": "^0.2.3",
"strip-json-comments": "^3.1.0",
- "taffydb": "2.6.2",
"underscore": "~1.13.2"
}
},
@@ -4136,20 +4169,20 @@
"dev": true
},
"json5": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
- "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true
+ },
+ "klaw": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz",
+ "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==",
"dev": true,
"requires": {
- "minimist": "^1.2.5"
+ "graceful-fs": "^4.1.9"
}
},
- "klaw": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/klaw/-/klaw-4.0.1.tgz",
- "integrity": "sha512-pgsE40/SvC7st04AHiISNewaIMUbY5V/K8b21ekiPiFoYs/EYSdsGa+FJArB1d441uq4Q8zZyIxvAzkGNlBdRw==",
- "dev": true
- },
"linkify-it": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
@@ -4308,28 +4341,22 @@
"dev": true
},
"memfs": {
- "version": "3.4.1",
- "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz",
- "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==",
+ "version": "3.4.13",
+ "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.13.tgz",
+ "integrity": "sha512-omTM41g3Skpvx5dSYeZIbXKcXoAVc/AoMNwn9TKx++L/gaen/+4TTttmu8ZSch5vfVJ8uJvGbroTsIlslRg6lg==",
"dev": true,
"requires": {
- "fs-monkey": "1.0.3"
+ "fs-monkey": "^1.0.3"
}
},
"minimatch": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.0.tgz",
- "integrity": "sha512-EU+GCVjXD00yOUf1TwAHVP7v3fBD3A8RkkPYsWWKGWesxM/572sL53wJQnHxquHlRhYUV36wHkqrN8cdikKc2g==",
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.2.tgz",
+ "integrity": "sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg==",
"requires": {
"brace-expansion": "^2.0.1"
}
},
- "minimist": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
- "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
- "dev": true
- },
"mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
@@ -4419,6 +4446,23 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
+ "debug": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
+ "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
"escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -4759,9 +4803,9 @@
}
},
"prettier": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
- "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
+ "version": "2.8.2",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.2.tgz",
+ "integrity": "sha512-BtRV9BcncDyI2tsuS19zzhzoxD8Dh8LiCx7j7tHzrkz8GFXAexeWFdi22mjE1d16dftH2qNaytVxqiRTGlMfpw==",
"dev": true
},
"process-on-spawn": {
@@ -4959,12 +5003,6 @@
}
}
},
- "taffydb": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz",
- "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=",
- "dev": true
- },
"test-exclude": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
diff --git a/package.json b/package.json
index af9c1c2..d1c95e0 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "folder-hash",
- "version": "4.0.2",
+ "version": "4.0.3",
"description": "Create a hash checksum over a folder and its content - its children and their content",
"main": "index.js",
"bin": {
@@ -36,19 +36,18 @@
},
"dependencies": {
"debug": "^4.3.3",
- "graceful-fs": "~4.2.9",
- "minimatch": "~5.0.0"
+ "minimatch": "~5.1.2"
},
"devDependencies": {
"chai": "^4.3.6",
"chai-as-promised": "^7.1.1",
"clone": "^2.1.2",
"ignore": "^5.2.0",
- "jsdoc": "3.6.10",
+ "jsdoc": "4.0.0",
"memfs": "^3.4.1",
"mocha": "^9.2.0",
"nyc": "^15.1.0",
- "prettier": "~2.5.1"
+ "prettier": "~2.8.2"
},
"engines": {
"node": ">=10.10.0"
diff --git a/test/issue-146.js b/test/issue-146.js
new file mode 100644
index 0000000..b42aad4
--- /dev/null
+++ b/test/issue-146.js
@@ -0,0 +1,33 @@
+const { folderHash, should, inspect } = require('./_common');
+const { Volume } = require('memfs');
+
+it('Issue 146: Handle `EMFILE` and `ENFILE` errors gracefully', async function () {
+ const expected = 'BA8G/XdAkkeNRQd09bowxdp4rMg=';
+ const fs = Volume.fromJSON({
+ 'folder/file.txt': 'content',
+ 'folder/file1.txt': 'content',
+ 'folder/file2.txt': 'content',
+ 'folder/b/file1.txt': 'content',
+ 'folder/b/file2.txt': 'content',
+ 'folder/b/file3.txt': 'content',
+ });
+ let counter = 0;
+ const readdir = fs.promises.readdir;
+ fs.promises.readdir = (path, options) => {
+ counter++;
+ if (counter > 1 && counter < 5) {
+ throw { code: 'EMFILE', message: 'fake readdir error' };
+ } else if (counter < 10) {
+ throw { code: 'ENFILE', message: 'fake readdir error' };
+ } else {
+ return readdir(path, options);
+ }
+ };
+ const hashElement = folderHash.prep(fs, Promise);
+ const folder = 'folder';
+ const options = {};
+ const result = await hashElement(folder, options);
+ // ensure that the errors were raised
+ counter.should.be.greaterThanOrEqual(7);
+ result.hash.should.equal('rGaf5+7Q5VwsunfiBL9XobKDio4=');
+});