Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

dir-compare

Package Overview
Dependencies
Maintainers
1
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dir-compare - npm Package Compare versions

Comparing version 3.1.5 to 3.2.0

build/src/permissions/permissionDeniedState.d.ts

43

build/src/compareAsync.js

@@ -9,2 +9,3 @@ const entryBuilder = require('./entry/entryBuilder');

const entryType = require('./entry/entryType');
const { getPrmissionDenieStateWhenLeftMissing, getPrmissionDenieStateWhenRightMissing, getPermissionDeniedState } = require('./permissions/permissionDeniedState');
/**

@@ -18,2 +19,5 @@ * Returns the sorted list of entries in a directory.

if (rootEntry.isDirectory) {
if (rootEntry.isPermissionDenied) {
return [];
}
return fsPromise.readdir(rootEntry.absolutePath)

@@ -63,11 +67,21 @@ .then(entries => entryBuilder.buildDirEntries(rootEntry, entries, relativePath, options));

// Both left/right exist and have the same name and type
const compareAsyncRes = entryEquality.isEntryEqualAsync(entry1, entry2, type1, diffSet, options);
const samePromise = compareAsyncRes.samePromise;
const same = compareAsyncRes.same;
if (same !== undefined) {
options.resultBuilder(entry1, entry2, same ? 'equal' : 'distinct', level, relativePath, options, statistics, diffSet, compareAsyncRes.reason);
stats.updateStatisticsBoth(entry1, entry2, compareAsyncRes.same, compareAsyncRes.reason, type1, statistics, options);
const permissionDeniedState = getPermissionDeniedState(entry1, entry2);
if (permissionDeniedState === "access-ok") {
const compareEntryRes = entryEquality.isEntryEqualAsync(entry1, entry2, type1, diffSet, options);
const samePromise = compareEntryRes.samePromise;
const same = compareEntryRes.same;
if (same !== undefined) {
options.resultBuilder(entry1, entry2, same ? 'equal' : 'distinct', level, relativePath, options, statistics, diffSet, compareEntryRes.reason, permissionDeniedState);
stats.updateStatisticsBoth(entry1, entry2, compareEntryRes.same, compareEntryRes.reason, type1, permissionDeniedState, statistics, options);
}
else {
compareFilePromises.push(samePromise);
}
}
else {
compareFilePromises.push(samePromise);
const state = 'distinct';
const reason = "permission-denied";
const same = false;
options.resultBuilder(entry1, entry2, state, level, relativePath, options, statistics, diffSet, reason, permissionDeniedState);
stats.updateStatisticsBoth(entry1, entry2, same, reason, type1, permissionDeniedState, statistics, options);
}

@@ -86,4 +100,5 @@ i1++;

// Right missing
options.resultBuilder(entry1, undefined, 'left', level, relativePath, options, statistics, diffSet);
stats.updateStatisticsLeft(entry1, type1, statistics, options);
const permissionDeniedState = getPrmissionDenieStateWhenRightMissing(entry1);
options.resultBuilder(entry1, undefined, 'left', level, relativePath, options, statistics, diffSet, undefined, permissionDeniedState);
stats.updateStatisticsLeft(entry1, type1, permissionDeniedState, statistics, options);
i1++;

@@ -100,4 +115,5 @@ if (type1 === 'directory' && !options.skipSubdirs) {

// Left missing
options.resultBuilder(undefined, entry2, 'right', level, relativePath, options, statistics, diffSet);
stats.updateStatisticsRight(entry2, type2, statistics, options);
let permissionDeniedState = getPrmissionDenieStateWhenLeftMissing(entry2);
options.resultBuilder(undefined, entry2, 'right', level, relativePath, options, statistics, diffSet, undefined, permissionDeniedState);
stats.updateStatisticsRight(entry2, type2, permissionDeniedState, statistics, options);
i2++;

@@ -122,4 +138,5 @@ if (type2 === 'directory' && !options.skipSubdirs) {

else {
options.resultBuilder(sameResult.entry1, sameResult.entry2, sameResult.same ? 'equal' : 'distinct', level, relativePath, options, statistics, sameResult.diffSet, sameResult.reason);
stats.updateStatisticsBoth(sameResult.entries1, sameResult.entries2, sameResult.same, sameResult.reason, sameResult.type1, statistics, options);
const permissionDeniedState = "access-ok";
options.resultBuilder(sameResult.entry1, sameResult.entry2, sameResult.same ? 'equal' : 'distinct', level, relativePath, options, statistics, sameResult.diffSet, sameResult.reason, permissionDeniedState);
stats.updateStatisticsBoth(sameResult.entries1, sameResult.entries2, sameResult.same, sameResult.reason, sameResult.type1, permissionDeniedState, statistics, options);
}

@@ -126,0 +143,0 @@ }

@@ -9,2 +9,3 @@ const fs = require('fs');

const entryType = require('./entry/entryType');
const { getPrmissionDenieStateWhenLeftMissing, getPrmissionDenieStateWhenRightMissing, getPermissionDeniedState } = require('./permissions/permissionDeniedState');
/**

@@ -18,2 +19,5 @@ * Returns the sorted list of entries in a directory.

if (rootEntry.isDirectory) {
if (rootEntry.isPermissionDenied) {
return [];
}
const entries = fs.readdirSync(rootEntry.absolutePath);

@@ -58,5 +62,17 @@ return entryBuilder.buildDirEntries(rootEntry, entries, relativePath, options);

// Both left/right exist and have the same name and type
let compareEntryRes = entryEquality.isEntryEqualSync(entry1, entry2, type1, options);
options.resultBuilder(entry1, entry2, compareEntryRes.same ? 'equal' : 'distinct', level, relativePath, options, statistics, diffSet, compareEntryRes.reason);
stats.updateStatisticsBoth(entry1, entry2, compareEntryRes.same, compareEntryRes.reason, type1, statistics, options);
let same, reason, state;
const permissionDeniedState = getPermissionDeniedState(entry1, entry2);
if (permissionDeniedState === "access-ok") {
const compareEntryRes = entryEquality.isEntryEqualSync(entry1, entry2, type1, options);
state = compareEntryRes.same ? 'equal' : 'distinct';
same = compareEntryRes.same;
reason = compareEntryRes.reason;
}
else {
state = 'distinct';
same = false;
reason = "permission-denied";
}
options.resultBuilder(entry1, entry2, state, level, relativePath, options, statistics, diffSet, reason, permissionDeniedState);
stats.updateStatisticsBoth(entry1, entry2, same, reason, type1, permissionDeniedState, statistics, options);
i1++;

@@ -70,4 +86,5 @@ i2++;

// Right missing
options.resultBuilder(entry1, undefined, 'left', level, relativePath, options, statistics, diffSet);
stats.updateStatisticsLeft(entry1, type1, statistics, options);
const permissionDeniedState = getPrmissionDenieStateWhenRightMissing(entry1);
options.resultBuilder(entry1, undefined, 'left', level, relativePath, options, statistics, diffSet, undefined, permissionDeniedState);
stats.updateStatisticsLeft(entry1, type1, permissionDeniedState, statistics, options);
i1++;

@@ -80,4 +97,5 @@ if (type1 === 'directory' && !options.skipSubdirs) {

// Left missing
options.resultBuilder(undefined, entry2, 'right', level, relativePath, options, statistics, diffSet);
stats.updateStatisticsRight(entry2, type2, statistics, options);
let permissionDeniedState = getPrmissionDenieStateWhenLeftMissing(entry2);
options.resultBuilder(undefined, entry2, "right", level, relativePath, options, statistics, diffSet, undefined, permissionDeniedState);
stats.updateStatisticsRight(entry2, type2, permissionDeniedState, statistics, options);
i2++;

@@ -84,0 +102,0 @@ if (type2 === 'directory' && !options.skipSubdirs) {

@@ -15,2 +15,3 @@ /// <reference types="node" />

isDirectory: boolean;
isPermissionDenied: boolean;
}[];

@@ -29,4 +30,5 @@ /**

isDirectory: boolean;
isPermissionDenied: boolean;
}[];
export function buildEntry(absolutePath: any, path: any, name: any): {
export function buildEntry(absolutePath: any, path: any, name: any, options: any): {
name: any;

@@ -40,4 +42,5 @@ absolutePath: any;

isDirectory: boolean;
isPermissionDenied: boolean;
};
export function buildEntry(absolutePath: any, path: any, name: any): {
export function buildEntry(absolutePath: any, path: any, name: any, options: any): {
name: any;

@@ -51,3 +54,4 @@ absolutePath: any;

isDirectory: boolean;
isPermissionDenied: boolean;
};
//# sourceMappingURL=entryBuilder.d.ts.map

@@ -16,3 +16,3 @@ const fs = require('fs');

const entryPath = rootEntry.path + PATH_SEP + entryName;
const entry = this.buildEntry(entryAbsolutePath, entryPath, entryName);
const entry = this.buildEntry(entryAbsolutePath, entryPath, entryName, options);
if (options.skipSymlinks && entry.isSymlink) {

@@ -27,4 +27,10 @@ entry.stat = undefined;

},
buildEntry(absolutePath, path, name) {
buildEntry(absolutePath, path, name, options) {
const stats = getStatIgnoreBrokenLink(absolutePath);
const isDirectory = stats.stat.isDirectory();
let isPermissionDenied = false;
if (options.handlePermissionDenied) {
const isFile = !isDirectory;
isPermissionDenied = hasPermissionDenied(absolutePath, isFile, options);
}
return {

@@ -38,6 +44,19 @@ name: name,

isBrokenLink: stats.isBrokenLink,
isDirectory: stats.stat.isDirectory()
isDirectory,
isPermissionDenied
};
},
};
function hasPermissionDenied(absolutePath, isFile, options) {
if (isFile && !options.compareContent) {
return false;
}
try {
fs.accessSync(absolutePath, fs.constants.R_OK);
return false;
}
catch (_a) {
return true;
}
}
function getStatIgnoreBrokenLink(absolutePath) {

@@ -44,0 +63,0 @@ const lstat = fs.lstatSync(absolutePath);

import { Options, Result } from './types';
import { FileCompareHandlers } from './FileCompareHandlers';
export * from './types';
export { FileCompareHandlers };
/**

@@ -5,0 +6,0 @@ * Synchronously compares given paths.

@@ -46,3 +46,3 @@ "use strict";

const statistics = statisticsLifecycle_1.default.initStats(options);
compareSync_1.default(entryBuilder_1.default.buildEntry(absolutePath1, path1, path_1.default.basename(absolutePath1)), entryBuilder_1.default.buildEntry(absolutePath2, path2, path_1.default.basename(absolutePath2)), 0, ROOT_PATH, options, statistics, diffSet, loopDetector_1.default.initSymlinkCache());
compareSync_1.default(entryBuilder_1.default.buildEntry(absolutePath1, path1, path_1.default.basename(absolutePath1), options), entryBuilder_1.default.buildEntry(absolutePath2, path2, path_1.default.basename(absolutePath2), options), 0, ROOT_PATH, options, statistics, diffSet, loopDetector_1.default.initSymlinkCache());
statisticsLifecycle_1.default.completeStatistics(statistics, options);

@@ -77,3 +77,3 @@ statistics.diffSet = diffSet;

const statistics = statisticsLifecycle_1.default.initStats(options);
return compareAsync_1.default(entryBuilder_1.default.buildEntry(absolutePath1, path1, path_1.default.basename(path1)), entryBuilder_1.default.buildEntry(absolutePath2, path2, path_1.default.basename(path2)), 0, ROOT_PATH, options, statistics, asyncDiffSet, loopDetector_1.default.initSymlinkCache())
return compareAsync_1.default(entryBuilder_1.default.buildEntry(absolutePath1, path1, path_1.default.basename(path1), options), entryBuilder_1.default.buildEntry(absolutePath2, path2, path_1.default.basename(path2), options), 0, ROOT_PATH, options, statistics, asyncDiffSet, loopDetector_1.default.initSymlinkCache())
.then(() => {

@@ -80,0 +80,0 @@ statisticsLifecycle_1.default.completeStatistics(statistics, options);

@@ -1,3 +0,3 @@

declare function _exports(entry1: any, entry2: any, state: any, level: any, relativePath: any, options: any, statistics: any, diffSet: any, reason: any): void;
declare function _exports(entry1: any, entry2: any, state: any, level: any, relativePath: any, options: any, statistics: any, diffSet: any, reason: any, permissionDeniedState: any): void;
export = _exports;
//# sourceMappingURL=defaultResultBuilderCallback.d.ts.map
const pathUtils = require('path');
const entryType = require('../entry/entryType');
module.exports = function (entry1, entry2, state, level, relativePath, options, statistics, diffSet, reason) {
module.exports = function (entry1, entry2, state, level, relativePath, options, statistics, diffSet, reason, permissionDeniedState) {
if (options.noDiffSet) {

@@ -14,2 +14,3 @@ return;

state: state,
permissionDeniedState,
type1: entryType.getType(entry1),

@@ -16,0 +17,0 @@ type2: entryType.getType(entry2),

@@ -27,2 +27,7 @@ export function initStats(options: any): {

} | undefined;
permissionDenied: {
leftPermissionDenied: number;
rightPermissionDenied: number;
distinctPermissionDenied: number;
};
same: undefined;

@@ -56,2 +61,7 @@ };

} | undefined;
permissionDenied: {
leftPermissionDenied: number;
rightPermissionDenied: number;
distinctPermissionDenied: number;
};
same: undefined;

@@ -58,0 +68,0 @@ };

@@ -22,2 +22,7 @@ /**

};
const permissionDeniedStatistics = {
leftPermissionDenied: 0,
rightPermissionDenied: 0,
distinctPermissionDenied: 0,
};
return {

@@ -38,2 +43,3 @@ distinct: 0,

symlinks: symlinkStatistics,
permissionDenied: permissionDeniedStatistics,
same: undefined

@@ -51,2 +57,4 @@ };

brokenLInksStats.totalBrokenLinks = brokenLInksStats.leftBrokenLinks + brokenLInksStats.rightBrokenLinks + brokenLInksStats.distinctBrokenLinks;
const permissionDeniedStats = statistics.permissionDenied;
permissionDeniedStats.totalPermissionDenied = permissionDeniedStats.leftPermissionDenied + permissionDeniedStats.rightPermissionDenied + permissionDeniedStats.distinctPermissionDenied;
statistics.same = statistics.differences ? false : true;

@@ -53,0 +61,0 @@ if (options.compareSymlink) {

@@ -1,7 +0,7 @@

export function updateStatisticsBoth(entry1: any, entry2: any, same: any, reason: any, type: any, statistics: any, options: any): void;
export function updateStatisticsBoth(entry1: any, entry2: any, same: any, reason: any, type: any, statistics: any, options: any): void;
export function updateStatisticsLeft(entry1: any, type: any, statistics: any, options: any): void;
export function updateStatisticsLeft(entry1: any, type: any, statistics: any, options: any): void;
export function updateStatisticsRight(entry2: any, type: any, statistics: any, options: any): void;
export function updateStatisticsRight(entry2: any, type: any, statistics: any, options: any): void;
export function updateStatisticsBoth(entry1: any, entry2: any, same: any, reason: any, type: any, permissionDeniedState: any, statistics: any, options: any): void;
export function updateStatisticsBoth(entry1: any, entry2: any, same: any, reason: any, type: any, permissionDeniedState: any, statistics: any, options: any): void;
export function updateStatisticsLeft(entry1: any, type: any, permissionDeniedState: any, statistics: any, options: any): void;
export function updateStatisticsLeft(entry1: any, type: any, permissionDeniedState: any, statistics: any, options: any): void;
export function updateStatisticsRight(entry2: any, type: any, permissionDeniedState: any, statistics: any, options: any): void;
export function updateStatisticsRight(entry2: any, type: any, permissionDeniedState: any, statistics: any, options: any): void;
//# sourceMappingURL=statisticsUpdate.d.ts.map

@@ -5,3 +5,3 @@ /**

module.exports = {
updateStatisticsBoth(entry1, entry2, same, reason, type, statistics, options) {
updateStatisticsBoth(entry1, entry2, same, reason, type, permissionDeniedState, statistics, options) {
same ? statistics.equal++ : statistics.distinct++;

@@ -32,4 +32,13 @@ if (type === 'file') {

}
if (permissionDeniedState === "access-error-left") {
statistics.permissionDenied.leftPermissionDenied++;
}
else if (permissionDeniedState === "access-error-right") {
statistics.permissionDenied.rightPermissionDenied++;
}
else if (permissionDeniedState === "access-error-both") {
statistics.permissionDenied.distinctPermissionDenied++;
}
},
updateStatisticsLeft(entry1, type, statistics, options) {
updateStatisticsLeft(entry1, type, permissionDeniedState, statistics, options) {
statistics.left++;

@@ -51,4 +60,7 @@ if (type === 'file') {

}
if (permissionDeniedState === "access-error-left") {
statistics.permissionDenied.leftPermissionDenied++;
}
},
updateStatisticsRight(entry2, type, statistics, options) {
updateStatisticsRight(entry2, type, permissionDeniedState, statistics, options) {
statistics.right++;

@@ -70,4 +82,7 @@ if (type === 'file') {

}
if (permissionDeniedState === "access-error-right") {
statistics.permissionDenied.rightPermissionDenied++;
}
},
};
//# sourceMappingURL=statisticsUpdate.js.map

@@ -29,2 +29,9 @@ /// <reference types="node" />

* Compares entries by symlink. Defaults to 'false'.
* If this option is enabled two entries must have the same type in order to be considered equal.
* They have to be either two fies, two directories or two symlinks.
*
* If left entry is a file and right entry is a symlink, they are considered distinct disregarding the content of the file.
*
* Further if both entries are symlinks they need to have the same link value. For example if one symlink points to '/x/b.txt' and the other to '/x/../x/b.txt' the symlinks are considered distinct even if they point to the same file.
*/

@@ -57,2 +64,34 @@ compareSymlink?: boolean;

/**
* Handle permission denied errors. Defaults to 'false'.
*
* By default when some entry cannot be read due to `EACCES` error the comparison will
* stop immediately with an exception.
*
* If `handlePermissionDenied` is set to true the comparison will continue when unreadable entries are encountered.
*
* Offending entries will be reported within [[Difference.permissionDeniedState]], [[Difference.reason]] and [[Result.permissionDenied]].
*
* Lets consider we want to compare two identical folders `A` and `B` with `B/dir2` being unreadable for current user.
* ```
* A B
* dir1 dir1
* file1 file1
* dir2 dir2 (permission denied)
* file2 file2
* ```
*
* [[Result.diffSet]] will look like:
*
* |relativePath |path1 |path2 | state |reason |permissionDeniedState|
* |--------------|---------|---------|------------|------------------------|---------------------|
* |[/] |dir1 |dir1 |`equal` | | |
* |[/dir1] |file1 |file1 |`equal` | | |
* |[/] |dir2 |dir2 |`distinct` | `permission-denied` |`access-error-right` |
* |[/dir2] |file2 |missing |`left` | | |
*
* And [[Result.permissionDenied]] statistics look like - left: 0, right: 1, distinct: 0, total: 1
*
*/
handlePermissionDenied?: boolean;
/**
* Callback for constructing result. Called for each compared entry pair.

@@ -103,2 +142,7 @@ *

symlink: boolean;
/**
* True when this entry is not readable.
* This value is set only when [[Options.handlePermissionDenied]] is enabled.
*/
isPermissionDenied: boolean;
}

@@ -203,2 +247,6 @@ /**

symlinks?: SymlinkStatistics;
/**
* Stats about entries that could not be accessed.
*/
permissionDenied: PermissionDeniedStatistics;
}

@@ -215,3 +263,3 @@ export interface BrokenLinksStatistics {

/**
* Number of broken links with same name appearing in both path1 and path2 (leftBrokenLinks+rightBrokenLinks+distinctBrokenLinks)
* Number of broken links with same name appearing in both path1 and path2 (leftBrokenLinks + rightBrokenLinks + distinctBrokenLinks)
*/

@@ -224,2 +272,20 @@ distinctBrokenLinks: number;

}
export interface PermissionDeniedStatistics {
/**
* Number of forbidden entries found only in path1
*/
leftPermissionDenied: number;
/**
* Number of forbidden entries found only in path2
*/
rightPermissionDenied: number;
/**
* Number of forbidden entries with same name appearing in both path1 and path2 (leftPermissionDenied + rightPermissionDenied + distinctPermissionDenied)
*/
distinctPermissionDenied: number;
/**
* Total number of forbidden entries
*/
totalPermissionDenied: number;
}
export interface SymlinkStatistics {

@@ -253,5 +319,17 @@ /**

* State of left/right entries relative to each other.
* * `equal` - Identical entries are found in both left/right dirs.
* * `left` - Entry is found only in left dir.
* * `right` - Entry is found only in right dir.
* * `distinct` - Entries exist in both left/right dir but have different content. See [[Difference.reason]] to understan why entries are considered distinct.
*/
export declare type DifferenceState = "equal" | "left" | "right" | "distinct";
/**
* Permission related state of left/right entries. Available only when [[Options.handlePermissionDenied]] is enabled.
* * `access-ok` - Both entries are accessible.
* * `access-error-both` - Neither entry can be accessed.
* * `access-error-left` - Left entry cannot be accessed.
* * `access-error-right` - Right entry cannot be accessed.
*/
export declare type PermissionDeniedState = "access-ok" | "access-error-both" | "access-error-left" | "access-error-right";
/**
* Type of entry.

@@ -262,4 +340,13 @@ */

* Provides reason when two identically named entries are distinct.
*
* Not available if entries are equal.
*
* * `different-size` - Files differ in size.
* * `different-date - Entry dates are different. Used when [[Options.compareDate]] is `true`.
* * `different-content` - File contents are different. Used when [[Options.compareContent]] is `true`.
* * `broken-link` - Both left/right entries are broken links.
* * `different-symlink` - Symlinks are different. See [[Options.compareSymlink]] for details.
* * `permission-denied` - One or both left/right entries are not accessible. See [[Options.handlePermissionDenied]] for details.
*/
export declare type Reason = "different-size" | "different-date" | "different-content" | "broken-link" | 'different-symlink';
export declare type Reason = undefined | "different-size" | "different-date" | "different-content" | "broken-link" | 'different-symlink' | 'permission-denied';
export interface Difference {

@@ -299,2 +386,6 @@ /**

/**
* Permission related state of left/right entries.
*/
permissionDeniedState: PermissionDeniedState;
/**
* Type of left entry.

@@ -334,6 +425,5 @@ * Is undefined if missing on the left side.

/**
* See [[Reason]].
* Not available if entries are equal.
* Provides reason when two identically named entries are distinct.
*/
reason?: Reason;
reason: Reason;
}

@@ -340,0 +430,0 @@ /**

{
"name": "dir-compare",
"version": "3.1.5",
"version": "3.2.0",
"description": "Node JS directory compare",

@@ -25,2 +25,3 @@ "main": "build/src/index.js",

"lint": "eslint ./src ./test --ext .ts,.js",
"watch": "tsc-watch --onSuccess 'npm run copydeps --silent'",
"pretest": "npm install && npm run build",

@@ -49,2 +50,3 @@ "test": "node build/test/runTests.js",

"ts-node": "9.1.1",
"tsc-watch": "^4.2.9",
"typedoc": "0.20.16",

@@ -51,0 +53,0 @@ "typescript": "^4.1.3"

@@ -20,3 +20,4 @@ dir-compare

* [Symbolic links](#symbolic-links)
- [Command line](#command-line)
* [Handling permission denied errors](#handling-permission-denied-errors)
- [UI tools](#ui-tools)
- [Changelog](#changelog)

@@ -80,3 +81,2 @@

Below is a quick recap of the api. For more details check the [reference documentation](https://gliviu.github.io/dc-api/).
```typescript

@@ -86,69 +86,9 @@ compare(path1: string, path2: string, options?: Options): Promise<Result>

```
More details can be found in the reference documentation:
* [compare](https://gliviu.github.io/dc-api/index.html#compare)
* [compareSync](https://gliviu.github.io/dc-api/index.html#comparesync)
* [Options](https://gliviu.github.io/dc-api/interfaces/options.html)
* [Result](https://gliviu.github.io/dc-api/interfaces/result.html)
```Options```
* **compareSize**: true/false - Compares files by size. Defaults to 'false'.
* **compareContent**: true/false - Compares files by content. Defaults to 'false'.
* **compareFileSync**, **compareFileAsync**: Callbacks for file comparison. See [Custom file content comparators](#custom-file-content-comparators).
* **compareDate**: true/false - Compares files by date of modification (stat.mtime). Defaults to 'false'.
* **compareNameHandler**: Callback for name comparison. See [Custom name comparators](#custom-name-comparators).
* **dateTolerance**: milliseconds - Two files are considered to have the same date if the difference between their modification dates fits within date tolerance. Defaults to 1000 ms.
* **compareSymlink**: true/false - Compares entries by symlink. Defaults to 'false'.
* **skipSymlinks**: true/false - Ignore symbolic links. Defaults to 'false'.
* **skipSubdirs**: true/false - Skips sub directories. Defaults to 'false'.
* **ignoreCase**: true/false - Ignores case when comparing names. Defaults to 'false'.
* **noDiffSet**: true/false - Toggles presence of diffSet in output. If true, only statistics are provided. Use this when comparing large number of files to avoid out of memory situations. Defaults to 'false'.
* **includeFilter**: File name filter. Comma separated [minimatch](https://www.npmjs.com/package/minimatch) patterns. See [Glob patterns](#glob-patterns) below.
* **excludeFilter**: File/directory name exclude filter. Comma separated [minimatch](https://www.npmjs.com/package/minimatch) patterns. See [Glob patterns](#glob-patterns) below.
* **resultBuilder**: Callback for constructing result. Called for each compared entry pair. Updates `statistics` and `diffSet`. More details in [Custom result builder](#custom-result-builder).
```Result```
* **same**: true if directories are identical
* **distinct**: number of distinct entries
* **equal**: number of equal entries
* **left**: number of entries only in path1
* **right**: number of entries only in path2
* **differences**: total number of differences (distinct+left+right)
* **total**: total number of entries (differences+equal)
* **distinctFiles**: number of distinct files
* **equalFiles**: number of equal files
* **leftFiles**: number of files only in path1
* **rightFiles**: number of files only in path2
* **differencesFiles**: total number of different files (distinctFiles+leftFiles+rightFiles)
* **totalFiles**: total number of files (differencesFiles+equalFiles)
* **distinctDirs**: number of distinct directories
* **equalDirs**: number of equal directories
* **leftDirs**: number of directories only in path1
* **rightDirs**: number of directories only in path2
* **differencesDirs**: total number of different directories (distinctDirs+leftDirs+rightDirs)
* **totalDirs**: total number of directories (differencesDirs+equalDirs)
* **brokenLinks**:
* **leftBrokenLinks**: number of broken links only in path1
* **rightBrokenLinks**: number of broken links only in path2
* **distinctBrokenLinks**: number of broken links with same name appearing in both path1 and path2
* **totalBrokenLinks**: total number of broken links (leftBrokenLinks+rightBrokenLinks+distinctBrokenLinks)
* **symlinks**: Statistics available if `compareSymlink` options is used
* **distinctSymlinks**: number of distinct links
* **equalSymlinks**: number of equal links
* **leftSymlinks**: number of links only in path1
* **rightSymlinks**: number of links only in path2
* **differencesSymlinks**: total number of different links (distinctSymlinks+leftSymlinks+rightSymlinks)
* **totalSymlinks**: total number of links (differencesSymlinks+equalSymlinks)
* **diffSet** - List of changes (present if `options.noDiffSet` is false)
* **path1**: path not including file/directory name; can be relative or absolute depending on call to compare(),
* **path2**: path not including file/directory name; can be relative or absolute depending on call to compare(),
* **relativePath**: path relative to root,
* **name1**: file/directory name
* **name2**: file/directory name
* **state**: one of equal, left, right, distinct,
* **type1**: one of missing, file, directory, broken-link
* **type2**: one of missing, file, directory, broken-link
* **size1**: file size
* **size2**: file size
* **date1**: modification date (stat.mtime)
* **date2**: modification date (stat.mtime)
* **level**: depth
* **reason**: Provides reason when two identically named entries are distinct.
Not available if entries are equal.
One of "different-size", "different-date", "different-content", "broken-link", "different-symlink".
## Glob patterns

@@ -187,3 +127,3 @@ [Minimatch](https://www.npmjs.com/package/minimatch) patterns are used to include/exclude files to be compared.

### Ignore line endings and white spaces
Line based comparator can be used to ignore line ending and white space differences. This comparator is not available in [CLI](#command-line) mode.
Line based comparator can be used to ignore line ending and white space differences.
```javascript

@@ -291,6 +231,12 @@ const dircompare = require('dir-compare');

# Command line
See [dir-compare-cli](https://github.com/gliviu/dir-compare-cli).
## Handling permission denied errors
Unreadable files or directories are normally reported as errors. The comparison will be intrerrupted with an `EACCES` exception.
This behavior can be altered with [Options.handlePermissionDenied](https://gliviu.github.io/dc-api/interfaces/options.html#handlepermissiondenied).
# UI tools
* [dir-compare-cli](https://github.com/gliviu/dir-compare-cli)
* [Visual Studio Code - Compare Folders](https://marketplace.visualstudio.com/items?itemName=moshfeu.compare-folders)
# Changelog
* v3.2.0 [Handle permission denied errors](#handling-permission-denied-errors)
* v3.1.0 Added ignoreAllWhiteSpaces and ignoreEmptyLines options

@@ -331,1 +277,2 @@ * v3.0.0 Moved CLI component into separate project [dir-compare-cli](https://github.com/gliviu/dir-compare-cli)

* v0.0.3 Fix fille ordering issue for newer node versions

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc