diff --git a/.circleci/config.yml b/.circleci/config.yml
index abdfb35..0220c36 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -4,11 +4,11 @@ workflows:
run_tests_with_coverage:
jobs:
- cover:
- version: "10"
+ version: '10'
- cover:
- version: "lts"
+ version: 'lts'
- cover:
- version: "current"
+ version: 'current'
jobs:
cover:
@@ -26,9 +26,9 @@ jobs:
# Download and cache dependencies
- restore_cache:
keys:
- - v1-dependencies-{{ checksum "package.json" }}
- # fallback to using the latest cache if no exact match is found
- - v1-dependencies-
+ - v1-dependencies-{{ checksum "package.json" }}
+ # fallback to using the latest cache if no exact match is found
+ - v1-dependencies-
- run: npm install
diff --git a/README.md b/README.md
index 8bf80b7..a86f1a7 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-Create a hash checksum over a folder or a file.
-The hashes are propagated upwards, the hash that is returned for a folder is generated over all the hashes of its children.
+Create a hash checksum over a folder or a file.
+The hashes are propagated upwards, the hash that is returned for a folder is generated over all the hashes of its children.
The hashes are generated with the _sha1_ algorithm and returned in _base64_ encoding by default.
Each file returns a name and a hash, and each folder returns additionally an array of children (file or folder elements).
@@ -10,7 +10,7 @@ First, install folder-hash with `npm install --save folder-hash` or `yarn add fo
### Simple example
-To see differences to the last version of this package, I would create hashes over all _.js_ and _.json_ files. But ignore everything inside folders starting with a dot, and also from the folders _node_modules_, _test_coverage_. The structure of the options object is documented below.
+To see differences to the last version of this package, I would create hashes over all _.js_ and _.json_ files. But ignore everything inside folders starting with a dot, and also from the folders _node_modules_, _test_coverage_. The structure of the options object is documented below.
This example is also stored in [./examples/readme-example1.js](/examples/readme-example1.js).
```js
@@ -56,7 +56,7 @@ Creating a hash over the current folder:
And the structure may be traversed to e.g. create incremental backups.
-It is also possible to only match the full path and not the basename. The same configuration could look like this:
+It is also possible to only match the full path and not the basename. The same configuration could look like this:
_You should be aware that \*nix and Windows behave differently, so please use caution._
```js
@@ -138,6 +138,7 @@ const options = {
```js
{
algo: 'sha1', // see crypto.getHashes() for options in your node.js REPL
+ algoOptions: {}, // see https://nodejs.org/api/crypto.html#cryptocreatehashalgorithm-options -- only valid in node v12.8 and higher
encoding: 'base64', // 'base64', 'base64url', 'hex' or 'binary'
files: {
exclude: [],
@@ -336,7 +337,7 @@ const options = {
### Symlink options
-Configure, how symbolic links should be hashed.
+Configure, how symbolic links should be hashed.
To understand how the options can be combined to create a specific behavior, look into [test/symbolic-links.js](https://github.com/marc136/node-folder-hash/blob/master/test/symbolic-links.js).
@@ -509,11 +510,23 @@ hashElement(__dirname, options, (error, hash) => {
console.log(hash.toString());
}
});
+
+// pass algoOptions (example: shake256)
+// see https://nodejs.org/api/crypto.html#cryptocreatehashalgorithm-options -- only valid in node v12.8 and higher
+const options = { algo: 'shake256', algoOptions:{ outputLength: 5 }, files: { exclude: ['.*'], matchBasename: true } };
+hashElement(__dirname, options, (error, hash) => {
+ if (error) {
+ return console.error('hashing failed:', error);
+ } else {
+ console.log('Result for folder "' + __dirname + '":');
+ console.log(hash.toString());
+ }
+});
```
## Behavior
-The behavior is documented and verified in the unit tests. Execute `npm test` or `mocha test`, and have a look at the _test_ subfolder.
+The behavior is documented and verified in the unit tests. Execute `npm test` or `mocha test`, and have a look at the _test_ subfolder.
You can also have a look at the [CircleCI report. ](https://circleci.com/gh/marc136/node-folder-hash/tree/master)
### Creating hashes over files (with default options)
diff --git a/index.js b/index.js
index 59d9e0c..2a81b53 100644
--- a/index.js
+++ b/index.js
@@ -5,6 +5,7 @@
const defaultOptions = {
algo: 'sha1', // see crypto.getHashes() for options
+ algoOptions: {},
encoding: 'base64', // 'base64', 'base64url', 'hex' or 'binary'
files: {
exclude: [],
@@ -167,7 +168,7 @@ function prep(fs) {
return new Promise((resolve, reject) => {
try {
- const hash = crypto.createHash(options.algo);
+ const hash = crypto.createHash(options.algo, options.algoOptions);
if (
options.files.ignoreBasename ||
options.ignoreBasenameOnce ||
@@ -213,7 +214,7 @@ function prep(fs) {
function symLinkIgnoreTargetContent(name, target, options, isRootElement) {
delete options.skipMatching; // only used for the root level
log.symlink('ignoring symbolic link target content');
- const hash = crypto.createHash(options.algo);
+ const hash = crypto.createHash(options.algo, options.algoOptions);
if (!options.symbolicLinks.ignoreBasename && !(isRootElement && options.files.ignoreRootName)) {
log.symlink('hash basename');
hash.update(name);
@@ -237,7 +238,7 @@ function prep(fs) {
const temp = await hashElementPromise(stats, dir, options, isRootElement);
if (!options.symbolicLinks.ignoreTargetPath) {
- const hash = crypto.createHash(options.algo);
+ const hash = crypto.createHash(options.algo, options.algoOptions);
hash.update(temp.hash);
log.symlink('hash targetpath');
hash.update(target);
@@ -247,7 +248,7 @@ function prep(fs) {
} catch (err) {
if (options.symbolicLinks.ignoreTargetContentAfterError) {
log.symlink(`Ignoring error "${err.code}" when hashing symbolic link ${name}`, err);
- const hash = crypto.createHash(options.algo);
+ const hash = crypto.createHash(options.algo, options.algoOptions);
if (
!options.symbolicLinks.ignoreBasename &&
!(isRootElement && options.files.ignoreRootName)
@@ -314,6 +315,7 @@ function parseParameters(args) {
if (!isObject(options_)) options_ = {};
const options = {
algo: options_.algo || defaultOptions.algo,
+ algoOptions: options_.algoOptions || defaultOptions.algoOptions,
encoding: options_.encoding || defaultOptions.encoding,
files: Object.assign({}, defaultOptions.files, options_.files),
folders: Object.assign({}, defaultOptions.folders, options_.folders),
@@ -334,7 +336,7 @@ const HashedFolder = function HashedFolder(name, children, options, isRootElemen
this.name = name;
this.children = children;
- const hash = crypto.createHash(options.algo);
+ const hash = crypto.createHash(options.algo, options.algoOptions);
if (
options.folders.ignoreBasename ||
options.ignoreBasenameOnce ||
diff --git a/package.json b/package.json
index e656e9e..0c58559 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "folder-hash",
- "version": "4.0.4",
+ "version": "4.0.5",
"description": "Create a hash checksum over a folder and its content - its children and their content",
"main": "index.js",
"bin": {
diff --git a/test/base.js b/test/base.js
index ceaccb6..21322aa 100644
--- a/test/base.js
+++ b/test/base.js
@@ -35,6 +35,36 @@ describe('Should generate hashes', function () {
};
return hashElement(basename, dir, options).then(checkHash);
});
+
+ it('with algoOptions passed', function () {
+ // base our expected hash on node version behavior
+ // algo options were not available until v12.8
+ var v = process.version.split('.');
+ var major = parseInt(v[0].replace('v', ''));
+ var minor = parseInt(v[1]);
+ var expectedHash =
+ major > 12 || (major === 12 && minor >= 8)
+ ? 'd89f885449'
+ : 'd89f8854493c06a3bea8deffaee1c43d7e29e8b140122f17829bb8ad73950cbc';
+
+ const checkAlgoOptionHash = result => {
+ should.exist(result);
+ should.exist(result.hash);
+ result.hash.should.equal(expectedHash);
+ };
+
+ var options = {
+ algo: 'shake256',
+ algoOptions: { outputLength: 5 },
+ encoding: 'hex',
+ excludes: [],
+ match: {
+ basename: false,
+ path: false,
+ },
+ };
+ return hashElement(basename, dir, options).then(checkAlgoOptionHash);
+ });
});
describe('when executed with an error-first callback', function () {