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.3.0 to 4.0.0

build/src/Entry/EntryBuilder.d.ts

12

build/src/compareAsync.d.ts

@@ -1,6 +0,14 @@

export = compare;
import { ExtOptions } from './ExtOptions';
import { Difference, InitialStatistics } from '.';
import { SymlinkCache } from './Symlink/LoopDetector';
import { OptionalEntry } from './Entry/EntryType';
/**
* List of differences occurred during comparison.
* Async DiffSets are kept into recursive structures.
*/
export declare type AsyncDiffSet = Array<Difference | AsyncDiffSet>;
/**
* Compares two directories asynchronously.
*/
declare function compare(rootEntry1: any, rootEntry2: any, level: any, relativePath: any, options: any, statistics: any, diffSet: any, symlinkCache: any): any;
export declare function compareAsync(rootEntry1: OptionalEntry, rootEntry2: OptionalEntry, level: number, relativePath: string, options: ExtOptions, statistics: InitialStatistics, asyncDiffSet: AsyncDiffSet, symlinkCache: SymlinkCache): Promise<void>;
//# sourceMappingURL=compareAsync.d.ts.map

134

build/src/compareAsync.js

@@ -1,11 +0,22 @@

const entryBuilder = require('./entry/entryBuilder');
const entryEquality = require('./entry/entryEquality');
const stats = require('./statistics/statisticsUpdate');
const pathUtils = require('path');
const fsPromise = require('./fs/fsPromise');
const loopDetector = require('./symlink/loopDetector');
const entryComparator = require('./entry/entryComparator');
const entryType = require('./entry/entryType');
const { getPrmissionDenieStateWhenLeftMissing, getPrmissionDenieStateWhenRightMissing, getPermissionDeniedState } = require('./permissions/permissionDeniedState');
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.compareAsync = void 0;
const path_1 = __importDefault(require("path"));
const EntryEquality_1 = require("./Entry/EntryEquality");
const FsPromise_1 = require("./FileSystem/FsPromise");
const EntryBuilder_1 = require("./Entry/EntryBuilder");
const LoopDetector_1 = require("./Symlink/LoopDetector");
const EntryComparator_1 = require("./Entry/EntryComparator");
const EntryType_1 = require("./Entry/EntryType");
const Permission_1 = require("./Permission/Permission");
const StatisticsUpdate_1 = require("./Statistics/StatisticsUpdate");
const p_limit_1 = __importDefault(require("p-limit"));
/**
* Limits concurrent promises.
*/
const CONCURRENCY = 2;
/**
* Returns the sorted list of entries in a directory.

@@ -19,6 +30,6 @@ */

if (rootEntry.isPermissionDenied) {
return [];
return Promise.resolve([]);
}
return fsPromise.readdir(rootEntry.absolutePath)
.then(entries => entryBuilder.buildDirEntries(rootEntry, entries, relativePath, options));
return FsPromise_1.FsPromise.readdir(rootEntry.absolutePath)
.then(entries => EntryBuilder_1.EntryBuilder.buildDirEntries(rootEntry, entries, relativePath, options));
}

@@ -30,6 +41,7 @@ return Promise.resolve([rootEntry]);

*/
function compare(rootEntry1, rootEntry2, level, relativePath, options, statistics, diffSet, symlinkCache) {
const loopDetected1 = loopDetector.detectLoop(rootEntry1, symlinkCache.dir1);
const loopDetected2 = loopDetector.detectLoop(rootEntry2, symlinkCache.dir2);
loopDetector.updateSymlinkCache(symlinkCache, rootEntry1, rootEntry2, loopDetected1, loopDetected2);
function compareAsync(rootEntry1, rootEntry2, level, relativePath, options, statistics, asyncDiffSet, symlinkCache) {
const limit = (0, p_limit_1.default)(CONCURRENCY);
const loopDetected1 = LoopDetector_1.LoopDetector.detectLoop(rootEntry1, symlinkCache.dir1);
const loopDetected2 = LoopDetector_1.LoopDetector.detectLoop(rootEntry2, symlinkCache.dir2);
LoopDetector_1.LoopDetector.updateSymlinkCache(symlinkCache, rootEntry1, rootEntry2, loopDetected1, loopDetected2);
return Promise.all([getEntries(rootEntry1, relativePath, loopDetected1, options), getEntries(rootEntry2, relativePath, loopDetected2, options)])

@@ -41,4 +53,3 @@ .then(entriesResult => {

const comparePromises = [];
const compareFilePromises = [];
let subDiffSet;
const fileEqualityAsyncPromises = [];
while (i1 < entries1.length || i2 < entries2.length) {

@@ -51,14 +62,14 @@ const entry1 = entries1[i1];

if (i1 < entries1.length && i2 < entries2.length) {
cmp = entryComparator.compareEntry(entry1, entry2, options);
type1 = entryType.getType(entry1);
type2 = entryType.getType(entry2);
cmp = EntryComparator_1.EntryComparator.compareEntry(entry1, entry2, options);
type1 = EntryType_1.EntryType.getType(entry1);
type2 = EntryType_1.EntryType.getType(entry2);
}
else if (i1 < entries1.length) {
type1 = entryType.getType(entry1);
type2 = entryType.getType(undefined);
type1 = EntryType_1.EntryType.getType(entry1);
type2 = EntryType_1.EntryType.getType(undefined);
cmp = -1;
}
else {
type1 = entryType.getType(undefined);
type2 = entryType.getType(entry2);
type1 = EntryType_1.EntryType.getType(undefined);
type2 = EntryType_1.EntryType.getType(entry2);
cmp = 1;

@@ -69,13 +80,11 @@ }

// Both left/right exist and have the same name and type
const permissionDeniedState = getPermissionDeniedState(entry1, entry2);
const permissionDeniedState = Permission_1.Permission.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);
const compareEntryRes = EntryEquality_1.EntryEquality.isEntryEqualAsync(entry1, entry2, type1, asyncDiffSet, options);
if (compareEntryRes.isSync) {
options.resultBuilder(entry1, entry2, compareEntryRes.same ? 'equal' : 'distinct', level, relativePath, options, statistics, asyncDiffSet, compareEntryRes.reason, permissionDeniedState);
StatisticsUpdate_1.StatisticsUpdate.updateStatisticsBoth(entry1, entry2, compareEntryRes.same, compareEntryRes.reason, type1, permissionDeniedState, statistics, options);
}
else {
compareFilePromises.push(samePromise);
fileEqualityAsyncPromises.push(compareEntryRes.fileEqualityAsyncPromise);
}

@@ -87,4 +96,4 @@ }

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);
options.resultBuilder(entry1, entry2, state, level, relativePath, options, statistics, asyncDiffSet, reason, permissionDeniedState);
StatisticsUpdate_1.StatisticsUpdate.updateStatisticsBoth(entry1, entry2, same, reason, type1, permissionDeniedState, statistics, options);
}

@@ -94,7 +103,8 @@ i1++;

if (!options.skipSubdirs && type1 === 'directory') {
const subDiffSet = [];
if (!options.noDiffSet) {
subDiffSet = [];
diffSet.push(subDiffSet);
asyncDiffSet.push(subDiffSet);
}
comparePromises.push(compare(entry1, entry2, level + 1, pathUtils.join(relativePath, entry1.name), options, statistics, subDiffSet, loopDetector.cloneSymlinkCache(symlinkCache)));
const comparePromise = limit(() => compareAsync(entry1, entry2, level + 1, path_1.default.join(relativePath, entry1.name), options, statistics, subDiffSet, LoopDetector_1.LoopDetector.cloneSymlinkCache(symlinkCache)));
comparePromises.push(comparePromise);
}

@@ -104,12 +114,13 @@ }

// Right missing
const permissionDeniedState = getPrmissionDenieStateWhenRightMissing(entry1);
options.resultBuilder(entry1, undefined, 'left', level, relativePath, options, statistics, diffSet, undefined, permissionDeniedState);
stats.updateStatisticsLeft(entry1, type1, permissionDeniedState, statistics, options);
const permissionDeniedState = Permission_1.Permission.getPermissionDeniedStateWhenRightMissing(entry1);
options.resultBuilder(entry1, undefined, 'left', level, relativePath, options, statistics, asyncDiffSet, undefined, permissionDeniedState);
StatisticsUpdate_1.StatisticsUpdate.updateStatisticsLeft(entry1, type1, permissionDeniedState, statistics, options);
i1++;
if (type1 === 'directory' && !options.skipSubdirs) {
const subDiffSet = [];
if (!options.noDiffSet) {
subDiffSet = [];
diffSet.push(subDiffSet);
asyncDiffSet.push(subDiffSet);
}
comparePromises.push(compare(entry1, undefined, level + 1, pathUtils.join(relativePath, entry1.name), options, statistics, subDiffSet, loopDetector.cloneSymlinkCache(symlinkCache)));
const comparePromise = limit(() => compareAsync(entry1, undefined, level + 1, path_1.default.join(relativePath, entry1.name), options, statistics, subDiffSet, LoopDetector_1.LoopDetector.cloneSymlinkCache(symlinkCache)));
comparePromises.push(comparePromise);
}

@@ -119,12 +130,13 @@ }

// Left missing
let permissionDeniedState = getPrmissionDenieStateWhenLeftMissing(entry2);
options.resultBuilder(undefined, entry2, 'right', level, relativePath, options, statistics, diffSet, undefined, permissionDeniedState);
stats.updateStatisticsRight(entry2, type2, permissionDeniedState, statistics, options);
const permissionDeniedState = Permission_1.Permission.getPermissionDeniedStateWhenLeftMissing(entry2);
options.resultBuilder(undefined, entry2, 'right', level, relativePath, options, statistics, asyncDiffSet, undefined, permissionDeniedState);
StatisticsUpdate_1.StatisticsUpdate.updateStatisticsRight(entry2, type2, permissionDeniedState, statistics, options);
i2++;
if (type2 === 'directory' && !options.skipSubdirs) {
const subDiffSet = [];
if (!options.noDiffSet) {
subDiffSet = [];
diffSet.push(subDiffSet);
asyncDiffSet.push(subDiffSet);
}
comparePromises.push(compare(undefined, entry2, level + 1, pathUtils.join(relativePath, entry2.name), options, statistics, subDiffSet, loopDetector.cloneSymlinkCache(symlinkCache)));
const comparePromise = limit(() => compareAsync(undefined, entry2, level + 1, path_1.default.join(relativePath, entry2.name), options, statistics, subDiffSet, LoopDetector_1.LoopDetector.cloneSymlinkCache(symlinkCache)));
comparePromises.push(comparePromise);
}

@@ -134,14 +146,12 @@ }

return Promise.all(comparePromises)
.then(() => Promise.all(compareFilePromises)
.then(sameResults => {
for (let i = 0; i < sameResults.length; i++) {
const sameResult = sameResults[i];
if (sameResult.error) {
return Promise.reject(sameResult.error);
.then(() => Promise.all(fileEqualityAsyncPromises)
.then(fileEqualityAsyncResults => {
for (let i = 0; i < fileEqualityAsyncResults.length; i++) {
const fileEqualityAsync = fileEqualityAsyncResults[i];
if (fileEqualityAsync.hasErrors) {
return Promise.reject(fileEqualityAsync.error);
}
else {
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);
}
const permissionDeniedState = "access-ok";
options.resultBuilder(fileEqualityAsync.context.entry1, fileEqualityAsync.context.entry2, fileEqualityAsync.same ? 'equal' : 'distinct', level, relativePath, options, statistics, fileEqualityAsync.context.asyncDiffSet, fileEqualityAsync.reason, permissionDeniedState);
StatisticsUpdate_1.StatisticsUpdate.updateStatisticsBoth(fileEqualityAsync.context.entry1, fileEqualityAsync.context.entry2, fileEqualityAsync.same, fileEqualityAsync.reason, fileEqualityAsync.context.type1, permissionDeniedState, statistics, options);
}

@@ -151,3 +161,3 @@ }));

}
module.exports = compare;
exports.compareAsync = compareAsync;
//# sourceMappingURL=compareAsync.js.map

@@ -1,6 +0,9 @@

export = compare;
import { InitialStatistics, OptionalDiffSet } from '.';
import { ExtOptions } from './ExtOptions';
import { SymlinkCache } from './Symlink/LoopDetector';
import { OptionalEntry } from './Entry/EntryType';
/**
* Compares two directories synchronously.
*/
declare function compare(rootEntry1: any, rootEntry2: any, level: any, relativePath: any, options: any, statistics: any, diffSet: any, symlinkCache: any): void;
export declare function compareSync(rootEntry1: OptionalEntry, rootEntry2: OptionalEntry, level: number, relativePath: string, options: ExtOptions, statistics: InitialStatistics, diffSet: OptionalDiffSet, symlinkCache: SymlinkCache): void;
//# sourceMappingURL=compareSync.d.ts.map

@@ -1,10 +0,16 @@

const fs = require('fs');
const pathUtils = require('path');
const entryBuilder = require('./entry/entryBuilder');
const entryEquality = require('./entry/entryEquality');
const stats = require('./statistics/statisticsUpdate');
const loopDetector = require('./symlink/loopDetector');
const entryComparator = require('./entry/entryComparator');
const entryType = require('./entry/entryType');
const { getPrmissionDenieStateWhenLeftMissing, getPrmissionDenieStateWhenRightMissing, getPermissionDeniedState } = require('./permissions/permissionDeniedState');
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.compareSync = void 0;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const EntryEquality_1 = require("./Entry/EntryEquality");
const EntryBuilder_1 = require("./Entry/EntryBuilder");
const LoopDetector_1 = require("./Symlink/LoopDetector");
const EntryComparator_1 = require("./Entry/EntryComparator");
const EntryType_1 = require("./Entry/EntryType");
const Permission_1 = require("./Permission/Permission");
const StatisticsUpdate_1 = require("./Statistics/StatisticsUpdate");
/**

@@ -21,4 +27,4 @@ * Returns the sorted list of entries in a directory.

}
const entries = fs.readdirSync(rootEntry.absolutePath);
return entryBuilder.buildDirEntries(rootEntry, entries, relativePath, options);
const entries = fs_1.default.readdirSync(rootEntry.absolutePath);
return EntryBuilder_1.EntryBuilder.buildDirEntries(rootEntry, entries, relativePath, options);
}

@@ -30,6 +36,6 @@ return [rootEntry];

*/
function compare(rootEntry1, rootEntry2, level, relativePath, options, statistics, diffSet, symlinkCache) {
const loopDetected1 = loopDetector.detectLoop(rootEntry1, symlinkCache.dir1);
const loopDetected2 = loopDetector.detectLoop(rootEntry2, symlinkCache.dir2);
loopDetector.updateSymlinkCache(symlinkCache, rootEntry1, rootEntry2, loopDetected1, loopDetected2);
function compareSync(rootEntry1, rootEntry2, level, relativePath, options, statistics, diffSet, symlinkCache) {
const loopDetected1 = LoopDetector_1.LoopDetector.detectLoop(rootEntry1, symlinkCache.dir1);
const loopDetected2 = LoopDetector_1.LoopDetector.detectLoop(rootEntry2, symlinkCache.dir2);
LoopDetector_1.LoopDetector.updateSymlinkCache(symlinkCache, rootEntry1, rootEntry2, loopDetected1, loopDetected2);
const entries1 = getEntries(rootEntry1, relativePath, loopDetected1, options);

@@ -45,14 +51,14 @@ const entries2 = getEntries(rootEntry2, relativePath, loopDetected2, options);

if (i1 < entries1.length && i2 < entries2.length) {
cmp = entryComparator.compareEntry(entry1, entry2, options);
type1 = entryType.getType(entry1);
type2 = entryType.getType(entry2);
cmp = EntryComparator_1.EntryComparator.compareEntry(entry1, entry2, options);
type1 = EntryType_1.EntryType.getType(entry1);
type2 = EntryType_1.EntryType.getType(entry2);
}
else if (i1 < entries1.length) {
type1 = entryType.getType(entry1);
type2 = entryType.getType(undefined);
type1 = EntryType_1.EntryType.getType(entry1);
type2 = EntryType_1.EntryType.getType(undefined);
cmp = -1;
}
else {
type1 = entryType.getType(undefined);
type2 = entryType.getType(entry2);
type1 = EntryType_1.EntryType.getType(undefined);
type2 = EntryType_1.EntryType.getType(entry2);
cmp = 1;

@@ -64,5 +70,5 @@ }

let same, reason, state;
const permissionDeniedState = getPermissionDeniedState(entry1, entry2);
const permissionDeniedState = Permission_1.Permission.getPermissionDeniedState(entry1, entry2);
if (permissionDeniedState === "access-ok") {
const compareEntryRes = entryEquality.isEntryEqualSync(entry1, entry2, type1, options);
const compareEntryRes = EntryEquality_1.EntryEquality.isEntryEqualSync(entry1, entry2, type1, options);
state = compareEntryRes.same ? 'equal' : 'distinct';

@@ -78,7 +84,7 @@ same = compareEntryRes.same;

options.resultBuilder(entry1, entry2, state, level, relativePath, options, statistics, diffSet, reason, permissionDeniedState);
stats.updateStatisticsBoth(entry1, entry2, same, reason, type1, permissionDeniedState, statistics, options);
StatisticsUpdate_1.StatisticsUpdate.updateStatisticsBoth(entry1, entry2, same, reason, type1, permissionDeniedState, statistics, options);
i1++;
i2++;
if (!options.skipSubdirs && type1 === 'directory') {
compare(entry1, entry2, level + 1, pathUtils.join(relativePath, entry1.name), options, statistics, diffSet, loopDetector.cloneSymlinkCache(symlinkCache));
compareSync(entry1, entry2, level + 1, path_1.default.join(relativePath, entry1.name), options, statistics, diffSet, LoopDetector_1.LoopDetector.cloneSymlinkCache(symlinkCache));
}

@@ -88,8 +94,8 @@ }

// Right missing
const permissionDeniedState = getPrmissionDenieStateWhenRightMissing(entry1);
const permissionDeniedState = Permission_1.Permission.getPermissionDeniedStateWhenRightMissing(entry1);
options.resultBuilder(entry1, undefined, 'left', level, relativePath, options, statistics, diffSet, undefined, permissionDeniedState);
stats.updateStatisticsLeft(entry1, type1, permissionDeniedState, statistics, options);
StatisticsUpdate_1.StatisticsUpdate.updateStatisticsLeft(entry1, type1, permissionDeniedState, statistics, options);
i1++;
if (type1 === 'directory' && !options.skipSubdirs) {
compare(entry1, undefined, level + 1, pathUtils.join(relativePath, entry1.name), options, statistics, diffSet, loopDetector.cloneSymlinkCache(symlinkCache));
compareSync(entry1, undefined, level + 1, path_1.default.join(relativePath, entry1.name), options, statistics, diffSet, LoopDetector_1.LoopDetector.cloneSymlinkCache(symlinkCache));
}

@@ -99,8 +105,8 @@ }

// Left missing
let permissionDeniedState = getPrmissionDenieStateWhenLeftMissing(entry2);
const permissionDeniedState = Permission_1.Permission.getPermissionDeniedStateWhenLeftMissing(entry2);
options.resultBuilder(undefined, entry2, "right", level, relativePath, options, statistics, diffSet, undefined, permissionDeniedState);
stats.updateStatisticsRight(entry2, type2, permissionDeniedState, statistics, options);
StatisticsUpdate_1.StatisticsUpdate.updateStatisticsRight(entry2, type2, permissionDeniedState, statistics, options);
i2++;
if (type2 === 'directory' && !options.skipSubdirs) {
compare(undefined, entry2, level + 1, pathUtils.join(relativePath, entry2.name), options, statistics, diffSet, loopDetector.cloneSymlinkCache(symlinkCache));
compareSync(undefined, entry2, level + 1, path_1.default.join(relativePath, entry2.name), options, statistics, diffSet, LoopDetector_1.LoopDetector.cloneSymlinkCache(symlinkCache));
}

@@ -110,3 +116,3 @@ }

}
module.exports = compare;
exports.compareSync = compareSync;
//# sourceMappingURL=compareSync.js.map

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

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

@@ -16,10 +14,15 @@ * Synchronously compares given paths.

* @param path2 Right file or directory to be compared.
* @param options Comparison options.
* @param extOptions Comparison options.
*/
export declare function compare(path1: string, path2: string, options?: Options): Promise<Result>;
/**
* File comparison handlers.
* These handlers are used when [[Options.compareContent]] is set.
* File content comparison handlers.
* These comparators are included with dir-compare.
*
* The `defaultFileCompare` is used when {@link Options.compareContent} is enabled
* and {@link Options.compareFileSync} or {@link Options.compareFileAsync} are sent as `undefined`.
*
* See [Custom file content comparators](https://github.com/gliviu/dir-compare#custom-file-content-comparators) for details.
*/
export declare const fileCompareHandlers: FileCompareHandlers;
//# sourceMappingURL=index.d.ts.map

@@ -19,11 +19,12 @@ "use strict";

const fs_1 = __importDefault(require("fs"));
const compareSync_1 = __importDefault(require("./compareSync"));
const compareAsync_1 = __importDefault(require("./compareAsync"));
const defaultResultBuilderCallback_1 = __importDefault(require("./resultBuilder/defaultResultBuilderCallback"));
const defaultFileCompare_1 = require("./fileCompareHandler/default/defaultFileCompare");
const lineBasedFileCompare_1 = require("./fileCompareHandler/lines/lineBasedFileCompare");
const defaultNameCompare_1 = __importDefault(require("./nameCompare/defaultNameCompare"));
const entryBuilder_1 = __importDefault(require("./entry/entryBuilder"));
const statisticsLifecycle_1 = __importDefault(require("./statistics/statisticsLifecycle"));
const loopDetector_1 = __importDefault(require("./symlink/loopDetector"));
const compareSync_1 = require("./compareSync");
const compareAsync_1 = require("./compareAsync");
const defaultFileCompare_1 = require("./FileCompareHandler/default/defaultFileCompare");
const lineBasedFileCompare_1 = require("./FileCompareHandler/lines/lineBasedFileCompare");
const defaultNameCompare_1 = require("./NameCompare/defaultNameCompare");
const EntryBuilder_1 = require("./Entry/EntryBuilder");
const StatisticsLifecycle_1 = require("./Statistics/StatisticsLifecycle");
const LoopDetector_1 = require("./Symlink/LoopDetector");
const defaultResultBuilderCallback_1 = require("./ResultBuilder/defaultResultBuilderCallback");
const fileBasedNameCompare_1 = require("./NameCompare/fileBasedNameCompare");
const ROOT_PATH = path_1.default.sep;

@@ -41,12 +42,18 @@ __exportStar(require("./types"), exports);

const absolutePath2 = path_1.default.normalize(path_1.default.resolve(fs_1.default.realpathSync(path2)));
const compareInfo = getCompareInfo(absolutePath1, absolutePath2);
const extOptions = prepareOptions(compareInfo, options);
let diffSet;
options = prepareOptions(options);
if (!options.noDiffSet) {
if (!extOptions.noDiffSet) {
diffSet = [];
}
const statistics = statisticsLifecycle_1.default.initStats(options);
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);
statistics.diffSet = diffSet;
return statistics;
const initialStatistics = StatisticsLifecycle_1.StatisticsLifecycle.initStats(extOptions);
if (compareInfo.mode === 'mixed') {
compareMixedEntries(absolutePath1, absolutePath2, diffSet, initialStatistics, compareInfo);
}
else {
(0, compareSync_1.compareSync)(EntryBuilder_1.EntryBuilder.buildEntry(absolutePath1, path1, path_1.default.basename(absolutePath1), extOptions), EntryBuilder_1.EntryBuilder.buildEntry(absolutePath2, path2, path_1.default.basename(absolutePath2), extOptions), 0, ROOT_PATH, extOptions, initialStatistics, diffSet, LoopDetector_1.LoopDetector.initSymlinkCache());
}
const result = StatisticsLifecycle_1.StatisticsLifecycle.completeStatistics(initialStatistics, extOptions);
result.diffSet = diffSet;
return result;
}

@@ -58,3 +65,3 @@ exports.compareSync = compareSync;

* @param path2 Right file or directory to be compared.
* @param options Comparison options.
* @param extOptions Comparison options.
*/

@@ -73,17 +80,25 @@ function compare(path1, path2, options) {

.then(() => {
options = prepareOptions(options);
let asyncDiffSet;
if (!options.noDiffSet) {
asyncDiffSet = [];
const compareInfo = getCompareInfo(absolutePath1, absolutePath2);
const extOptions = prepareOptions(compareInfo, options);
const asyncDiffSet = [];
const initialStatistics = StatisticsLifecycle_1.StatisticsLifecycle.initStats(extOptions);
if (compareInfo.mode === 'mixed') {
let diffSet;
if (!extOptions.noDiffSet) {
diffSet = [];
}
compareMixedEntries(absolutePath1, absolutePath2, diffSet, initialStatistics, compareInfo);
const result = StatisticsLifecycle_1.StatisticsLifecycle.completeStatistics(initialStatistics, extOptions);
result.diffSet = diffSet;
return result;
}
const statistics = statisticsLifecycle_1.default.initStats(options);
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())
return (0, compareAsync_1.compareAsync)(EntryBuilder_1.EntryBuilder.buildEntry(absolutePath1, path1, path_1.default.basename(absolutePath1), extOptions), EntryBuilder_1.EntryBuilder.buildEntry(absolutePath2, path2, path_1.default.basename(absolutePath2), extOptions), 0, ROOT_PATH, extOptions, initialStatistics, asyncDiffSet, LoopDetector_1.LoopDetector.initSymlinkCache())
.then(() => {
statisticsLifecycle_1.default.completeStatistics(statistics, options);
if (!(options === null || options === void 0 ? void 0 : options.noDiffSet)) {
const result = StatisticsLifecycle_1.StatisticsLifecycle.completeStatistics(initialStatistics, extOptions);
if (!extOptions.noDiffSet) {
const diffSet = [];
rebuildAsyncDiffSet(statistics, asyncDiffSet, diffSet);
statistics.diffSet = diffSet;
rebuildAsyncDiffSet(result, asyncDiffSet, diffSet);
result.diffSet = diffSet;
}
return statistics;
return result;
});

@@ -94,4 +109,9 @@ });

/**
* File comparison handlers.
* These handlers are used when [[Options.compareContent]] is set.
* File content comparison handlers.
* These comparators are included with dir-compare.
*
* The `defaultFileCompare` is used when {@link Options.compareContent} is enabled
* and {@link Options.compareFileSync} or {@link Options.compareFileAsync} are sent as `undefined`.
*
* See [Custom file content comparators](https://github.com/gliviu/dir-compare#custom-file-content-comparators) for details.
*/

@@ -116,3 +136,3 @@ exports.fileCompareHandlers = {

};
function prepareOptions(options) {
function prepareOptions(compareInfo, options) {
options = options || {};

@@ -125,3 +145,3 @@ const clone = JSON.parse(JSON.stringify(options));

if (!clone.resultBuilder) {
clone.resultBuilder = defaultResultBuilderCallback_1.default;
clone.resultBuilder = defaultResultBuilderCallback_1.defaultResultBuilderCallback;
}

@@ -135,3 +155,4 @@ if (!clone.compareFileSync) {

if (!clone.compareNameHandler) {
clone.compareNameHandler = defaultNameCompare_1.default;
const isFileBasedCompare = compareInfo.mode === 'files';
clone.compareNameHandler = isFileBasedCompare ? fileBasedNameCompare_1.fileBasedNameCompare : defaultNameCompare_1.defaultNameCompare;
}

@@ -145,3 +166,3 @@ clone.dateTolerance = clone.dateTolerance || 1000;

}
// Async diffsets are kept into recursive structures.
// Async DiffSets are kept into recursive structures.
// This method transforms them into one dimensional arrays.

@@ -158,2 +179,65 @@ function rebuildAsyncDiffSet(statistics, asyncDiffSet, diffSet) {

}
function getCompareInfo(path1, path2) {
const stat1 = fs_1.default.lstatSync(path1);
const stat2 = fs_1.default.lstatSync(path2);
if (stat1.isDirectory() && stat2.isDirectory()) {
return {
mode: 'directories',
type1: 'directory',
type2: 'directory',
size1: stat1.size,
size2: stat2.size,
date1: stat1.mtime,
date2: stat2.mtime,
};
}
if (stat1.isFile() && stat2.isFile()) {
return {
mode: 'files',
type1: 'file',
type2: 'file',
size1: stat1.size,
size2: stat2.size,
date1: stat1.mtime,
date2: stat2.mtime,
};
}
return {
mode: 'mixed',
type1: stat1.isFile() ? 'file' : 'directory',
type2: stat2.isFile() ? 'file' : 'directory',
size1: stat1.size,
size2: stat2.size,
date1: stat1.mtime,
date2: stat2.mtime,
};
}
/**
* Normally dir-compare is used to compare either two directories or two files.
* This method is used when one directory needs to be compared to a file.
*/
function compareMixedEntries(path1, path2, diffSet, initialStatistics, compareInfo) {
initialStatistics.distinct = 2;
initialStatistics.distinctDirs = 1;
initialStatistics.distinctFiles = 1;
if (diffSet) {
diffSet.push({
path1,
path2,
relativePath: '',
name1: path_1.default.basename(path1),
name2: path_1.default.basename(path2),
state: 'distinct',
permissionDeniedState: 'access-ok',
type1: compareInfo.type1,
type2: compareInfo.type2,
level: 0,
size1: compareInfo.size1,
size2: compareInfo.size2,
date1: compareInfo.date1,
date2: compareInfo.date2,
reason: 'different-content',
});
}
}
//# sourceMappingURL=index.js.map

@@ -100,4 +100,11 @@ /// <reference types="node" />

*
* And [[Result.permissionDenied]] statistics look like - left: 0, right: 1, distinct: 0, total: 1
*
* And [[Result.permissionDenied]] statistics look like
* ```json
* {
* leftPermissionDenied: 0,
* rightPermissionDenied: 1,
* distinctPermissionDenied: 0,
* totalPermissionDenied: 1
* }
* ```
*/

@@ -114,7 +121,7 @@ handlePermissionDenied?: boolean;

/**
* File comparison handler. See [Custom file comparators](https://github.com/gliviu/dir-compare#custom-file-content-comparators).
* File content comparison handler. See [Custom file comparators](https://github.com/gliviu/dir-compare#custom-file-content-comparators).
*/
compareFileSync?: CompareFileSync;
/**
* File comparison handler. See [Custom file comparators](https://github.com/gliviu/dir-compare#custom-file-content-comparators).
* File content comparison handler. See [Custom file comparators](https://github.com/gliviu/dir-compare#custom-file-content-comparators).
*/

@@ -128,2 +135,10 @@ compareFileAsync?: CompareFileAsync;

/**
* List of differences occurred during comparison.
*/
export declare type DiffSet = Array<Difference>;
/**
* @internal
*/
export declare type OptionalDiffSet = DiffSet | undefined;
/**
* Callback for constructing result. Called for each compared entry pair.

@@ -145,3 +160,3 @@ *

*/
(entry1: Entry | undefined, entry2: Entry | undefined, state: DifferenceState, level: number, relativePath: string, options: Options, statistics: Statistics, diffSet: Array<Difference> | undefined, reason: Reason | undefined) => void;
(entry1: Entry | undefined, entry2: Entry | undefined, state: DifferenceState, level: number, relativePath: string, options: Options, statistics: InitialStatistics, diffSet: DiffSet | undefined, reason: Reason | undefined, permissionDeniedState: PermissionDeniedState) => void;
export interface Entry {

@@ -153,3 +168,5 @@ name: string;

lstat: fs.Stats;
symlink: boolean;
isDirectory: boolean;
isSymlink: boolean;
isBrokenLink: boolean;
/**

@@ -166,7 +183,11 @@ * True when this entry is not readable.

/**
* List of changes (present if [[Options.noDiffSet]] is false).
* Detailed list of comparison results.
* Present if [[Options.noDiffSet]] is false.
*/
diffSet?: Array<Difference>;
diffSet?: DiffSet;
}
export interface Statistics {
/**
* Basic statistics information. Does not have any computed fields.
*/
export interface InitialStatistics {
/**

@@ -177,6 +198,2 @@ * Any property is allowed if default result builder is not used.

/**
* True if directories are identical.
*/
same: boolean;
/**
* Number of distinct entries.

@@ -198,10 +215,2 @@ */

/**
* Total number of differences (distinct+left+right).
*/
differences: number;
/**
* Total number of entries (differences+equal).
*/
total: number;
/**
* Number of distinct files.

@@ -223,10 +232,2 @@ */

/**
* Total number of different files (distinctFiles+leftFiles+rightFiles).
*/
differencesFiles: number;
/**
* Total number of files (differencesFiles+equalFiles).
*/
totalFiles: number;
/**
* Number of distinct directories.

@@ -248,10 +249,2 @@ */

/**
* Total number of different directories (distinctDirs+leftDirs+rightDirs).
*/
differencesDirs: number;
/**
* Total number of directories (differencesDirs+equalDirs).
*/
totalDirs: number;
/**
* Stats about broken links.

@@ -269,2 +262,36 @@ */

}
/**
* In addition to fields inherited from {@link InitialStatistics} this class
* adds fields computed at the final stage of the comparison.
*/
export interface Statistics extends InitialStatistics {
/**
* True if directories are identical.
*/
same: boolean;
/**
* Total number of differences (distinct+left+right).
*/
differences: number;
/**
* Total number of entries (differences+equal).
*/
total: number;
/**
* Total number of different files (distinctFiles+leftFiles+rightFiles).
*/
differencesFiles: number;
/**
* Total number of files (differencesFiles+equalFiles).
*/
totalFiles: number;
/**
* Total number of different directories (distinctDirs+leftDirs+rightDirs).
*/
differencesDirs: number;
/**
* Total number of directories (differencesDirs+equalDirs).
*/
totalDirs: number;
}
export interface BrokenLinksStatistics {

@@ -426,3 +453,3 @@ /**

*/
date1?: number;
date1?: Date;
/**

@@ -432,3 +459,3 @@ * Right entry modification date (stat.mtime).

*/
date2?: number;
date2?: Date;
/**

@@ -461,2 +488,20 @@ * Depth level relative to root dir.

export declare type CompareNameHandler = (name1: string, name2: string, options: Options) => 0 | 1 | -1;
export interface FileCompareHandlers {
/**
* Default file content comparison handlers, used if [[Options.compareFileAsync]] or [[Options.compareFileSync]] are not specified.
*
* Performs binary comparison.
*/
defaultFileCompare: CompareFileHandler;
/**
* Compares files line by line.
*
* Options:
* * ignoreLineEnding - true/false (default: false) - Ignore cr/lf line endings
* * ignoreWhiteSpaces - true/false (default: false) - Ignore white spaces at the beginning and ending of a line (similar to 'diff -b')
* * ignoreAllWhiteSpaces - true/false (default: false) - Ignore all white space differences (similar to 'diff -w')
* * ignoreEmptyLines - true/false (default: false) - Ignores differences caused by empty lines (similar to 'diff -B')
*/
lineBasedFileCompare: CompareFileHandler;
}
//# sourceMappingURL=types.d.ts.map
{
"name": "dir-compare",
"version": "3.3.0",
"version": "4.0.0",
"description": "Node JS directory compare",

@@ -31,23 +31,23 @@ "main": "build/src/index.js",

"toc": "npx markdown-toc README.md; echo \n",
"docs": "typedoc --includeVersion --excludeExternals --theme minimal --readme none --gitRevision master --toc compare,compareSync,fileCompareHandlers,Options,Result --out docs ./src/index.ts"
"docs": "typedoc --includeVersion --excludeExternals --excludeInternal --readme none --gitRevision master --out docs ./src/index.ts"
},
"dependencies": {
"buffer-equal": "^1.0.0",
"minimatch": "^3.0.4"
"minimatch": "^3.0.4",
"p-limit": "^3.1.0 "
},
"devDependencies": {
"@types/node": "^12.11.7",
"@typescript-eslint/eslint-plugin": "^4.14.0",
"@typescript-eslint/parser": "^4.14.0",
"colors": "^1.4.0",
"copyfiles": "^1.2.0",
"eslint": "^7.18.0",
"@types/node": "16.11.12",
"@typescript-eslint/eslint-plugin": "5.6.0",
"@typescript-eslint/parser": "5.6.0",
"colors": "1.4.0",
"copyfiles": "2.4.1",
"eslint": "7.32.0",
"memory-streams": "0.1.0",
"semver": "5.6.0",
"semver": "7.3.5",
"tar-fs": "2.1.1",
"temp": "0.9.0",
"ts-node": "9.1.1",
"tsc-watch": "^4.2.9",
"typedoc": "0.20.16",
"typescript": "^4.1.3"
"temp": "0.9.4",
"ts-node": "10.4.0",
"tsc-watch": "4.5.0",
"typedoc": "v0.22.10",
"typescript": "4.5.4"
},

@@ -54,0 +54,0 @@ "author": "Liviu Grigorescu",

@@ -85,15 +85,15 @@ dir-compare

* [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)
* [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)
Common options:
* [compareSize](https://gliviu.github.io/dc-api/interfaces/options.html#comparesize)
* [compareContent](https://gliviu.github.io/dc-api/interfaces/options.html#comparecontent)
* [compareDate](https://gliviu.github.io/dc-api/interfaces/options.html#comparedate)
* [excludeFilter](https://gliviu.github.io/dc-api/interfaces/options.html#excludefilter)
* [includeFilter](https://gliviu.github.io/dc-api/interfaces/options.html#includefilter)
* [ignoreCase](https://gliviu.github.io/dc-api/interfaces/options.html#ignorecase)
* [skipSubdirs](https://gliviu.github.io/dc-api/interfaces/options.html#skipsubdirs)
* [skipEmptyDirs](https://gliviu.github.io/dc-api/interfaces/options.html#skipemptydirs)
* [compareSize](https://gliviu.github.io/dc-api/interfaces/Options.html#compareSize)
* [compareContent](https://gliviu.github.io/dc-api/interfaces/Options.html#compareContent)
* [compareDate](https://gliviu.github.io/dc-api/interfaces/Options.html#compareDate)
* [excludeFilter](https://gliviu.github.io/dc-api/interfaces/Options.html#excludeFilter)
* [includeFilter](https://gliviu.github.io/dc-api/interfaces/Options.html#includeFilter)
* [ignoreCase](https://gliviu.github.io/dc-api/interfaces/Options.html#ignoreCase)
* [skipSubdirs](https://gliviu.github.io/dc-api/interfaces/Options.html#skipSubdirs)
* [skipEmptyDirs](https://gliviu.github.io/dc-api/interfaces/Options.html#skipEmptyDirs)

@@ -133,3 +133,3 @@ ## Glob patterns

Use [defaultFileCompare.js](https://github.com/gliviu/dir-compare/blob/master/src/fileCompareHandler/defaultFileCompare.js) as an example to create your own.
Use [defaultFileCompare.js](https://github.com/gliviu/dir-compare/blob/master/src/FileCompareHandler/default/defaultFileCompare.ts) as an example to create your own.

@@ -160,3 +160,3 @@ ### Ignore line endings and white spaces

## Custom name comparators
If [default](https://github.com/gliviu/dir-compare/blob/master/src/nameCompare/defaultNameCompare.js) name comparison is not enough, custom behavior can be specified with [compareNameHandler](https://gliviu.github.io/dc-api/index.html#comparenamehandler) option.
If [default](https://github.com/gliviu/dir-compare/blob/master/src/NameCompare/defaultNameCompare.ts) name comparison is not enough, custom behavior can be specified with [compareNameHandler](https://gliviu.github.io/dc-api/interfaces/Options.html#compareNameHandler) option.
Following example adds the possibility to ignore file extensions.

@@ -203,3 +203,3 @@ ```typescript

## Custom result builder
[Result builder](https://gliviu.github.io/dc-api/index.html#resultbuilder) is called for each pair of entries encountered during comparison. Its purpose is to append entries in `diffSet` and eventually update `statistics` object with new stats.
[Result builder](https://gliviu.github.io/dc-api/interfaces/Options.html#resultBuilder) is called for each pair of entries encountered during comparison. Its purpose is to append entries in `diffSet` and eventually update `statistics` object with new stats.

@@ -223,3 +223,3 @@ If needed it can be replaced with custom implementation.

The [default](https://github.com/gliviu/dir-compare/blob/master/src/resultBuilder/defaultResultBuilderCallback.js) builder can be used as an example.
The [default](https://github.com/gliviu/dir-compare/blob/master/src/ResultBuilder/defaultResultBuilderCallback.ts) builder can be used as an example.

@@ -245,3 +245,3 @@ ## Symbolic links

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).
This behavior can be altered with [Options.handlePermissionDenied](https://gliviu.github.io/dc-api/interfaces/Options.html#handlePermissionDenied).

@@ -253,2 +253,12 @@ # UI tools

# Changelog
* v4.0.0
* Switched project to typescript
* [Async comparator](https://gliviu.github.io/dc-api/index.html#compare) improvements when comparing large directory structures
* Heap usage has decreased 3x compared to previous version
* Works 2x faster when comparing by content
* Better concurrency. UI apps will be more responsive while comparison is ongoing
Breaking changes:
* Using this library to compare two files will ignore the name of the files. More details in [#48](https://github.com/gliviu/dir-compare/issues/48)
* Removed support for node 8, 9
* v3.3.0 Added `skipEmptyDirs` option

@@ -258,5 +268,5 @@ * v3.2.0 [Handle permission denied errors](#handling-permission-denied-errors)

* v3.0.0 Moved CLI component into separate project [dir-compare-cli](https://github.com/gliviu/dir-compare-cli)
* v2.4.0 New option to customize file/folder name comparison
* v2.4.0 [New option](https://gliviu.github.io/dc-api/interfaces/Options.html#compareNameHandler) to customize file/folder name comparison
* v2.3.0 Fixes
* v2.1.0 Removed [bluebird](https://github.com/petkaantonov/bluebird/#note) dependency
* v2.1.0 Removed [bluebird](https://github.com/petkaantonov/bluebird/#%EF%B8%8Fnote%EF%B8%8F) dependency
* v2.0.0

@@ -267,3 +277,3 @@ * New option to compare symlinks.

* Tests are no longer part of published package.
* Generated [Api](#api) documentation.
* Generated [Api](https://gliviu.github.io/dc-api/index.html) documentation.

@@ -287,3 +297,3 @@ Breaking changes:

* v1.0.0
* asynchronous processing
* asynchronous comparison
* new library options: noDiffSet, resultBuilder

@@ -290,0 +300,0 @@ * new statistics: distinctFiles, equalFiles, leftFiles, rightFiles, distinctDirs, equalDirs, leftDirs, rightDirs

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