///
import * as fs from "fs";
/**
* Comparison options.
*/
export interface Options {
/**
* Properties to be used in various extension points ie. result builder.
*/
[key: string]: any;
/**
* Compares files by size. Defaults to 'false'.
*
* Usually one of `compareSize` or `compareContent` options has to be activated. Otherwise files are compared by name disregarding size or content.
*/
compareSize?: boolean;
/**
* Compares files by content. Defaults to 'false'.
*
* Usually one of `compareSize` or `compareContent` options has to be activated. Otherwise files are compared by name disregarding size or content.
*/
compareContent?: boolean;
/**
* Compares files by date of modification (stat.mtime). Defaults to 'false'.
*
* Also see {@link Options.dateTolerance}.
*/
compareDate?: boolean;
/**
* Two files are considered to have the same date if the difference between their modification dates fits within date tolerance. Defaults to 1000 ms.
*/
dateTolerance?: number;
/**
* 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.
*/
compareSymlink?: boolean;
/**
* Skips sub directories. Defaults to 'false'.
*/
skipSubdirs?: boolean;
/**
* Ignore empty directories. Defaults to 'false'.
*/
skipEmptyDirs?: boolean;
/**
* Ignore symbolic links. Defaults to 'false'.
*/
skipSymlinks?: boolean;
/**
* Ignores case when comparing names. Defaults to 'false'.
*/
ignoreCase?: boolean;
/**
* 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'.
*/
noDiffSet?: boolean;
/**
* File name filter. Comma separated minimatch patterns. See [Glob patterns](https://github.com/gliviu/dir-compare#glob-patterns).
*/
includeFilter?: string;
/**
* File/directory name exclude filter. Comma separated minimatch patterns. See [Glob patterns](https://github.com/gliviu/dir-compare#glob-patterns).
*/
excludeFilter?: string;
/**
* 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 {@link Difference.permissionDeniedState}, {@link Difference.reason} and {@link Result.permissionDenied}.
*
* Lets consider we want to compare two identical folders `A` and `B` with `B/dir2` being unreadable for the current user.
* ```
* A B
* ├── dir1 ├── dir1
* ├──── file1 ├──── file1
* ├── dir2 ├── dir2 (permission denied)
* └─────file2 └─────file2
* ```
*
* {@link 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 {@link Result.permissionDenied} statistics look like
* ```json
* {
* leftPermissionDenied: 0,
* rightPermissionDenied: 1,
* distinctPermissionDenied: 0,
* totalPermissionDenied: 1
* }
* ```
*/
handlePermissionDenied?: boolean;
/**
* Extension point used for constructing the {@link Result} object.
*
* See [Result builder](https://github.com/gliviu/dir-compare#result-builder).
*/
resultBuilder?: ResultBuilder;
/**
* Extension point used to perform sync file content comparison.
*
* See [File comparators](https://github.com/gliviu/dir-compare#file-content-comparators).
*/
compareFileSync?: CompareFileSync;
/**
* Extension point used to perform async file content comparison.
*
* See [File comparators](https://github.com/gliviu/dir-compare#file-content-comparators).
*/
compareFileAsync?: CompareFileAsync;
/**
* Extension point used to compare files or directories names.
*
* See [Name comparators](https://github.com/gliviu/dir-compare#name-comparators).
*/
compareNameHandler?: CompareNameHandler;
/**
* Extension point used to control which files or directories should be included in the comparison.
*
* See [Glob filter](https://github.com/gliviu/dir-compare#glob-filter).
*/
filterHandler?: FilterHandler;
}
/**
* List of differences occurred during comparison.
*/
export type DiffSet = Array;
/**
* @internal
*/
export type OptionalDiffSet = DiffSet | undefined;
export type EntryOrigin = 'left' | 'right';
export interface Entry {
name: string;
absolutePath: string;
path: string;
/**
* Whether this entry originated from the left or the right dir.
*/
origin: EntryOrigin;
stat: fs.Stats;
lstat: fs.Stats;
isDirectory: boolean;
isSymlink: boolean;
isBrokenLink: boolean;
/**
* True when this entry is not readable.
* This value is set only when {@link Options.handlePermissionDenied} is enabled.
*/
isPermissionDenied: boolean;
}
/**
* Comparison result.
*/
export interface Result extends Statistics {
/**
* Detailed list of comparison results.
* Present if {@link Options.noDiffSet} is false.
*/
diffSet?: DiffSet;
}
/**
* Basic statistics information. Does not have any computed fields.
*/
export interface InitialStatistics {
/**
* Any property is allowed if default result builder is not used.
*/
[key: string]: any;
/**
* Number of distinct entries.
*/
distinct: number;
/**
* Number of equal entries.
*/
equal: number;
/**
* Number of entries only in path1.
*/
left: number;
/**
* Number of entries only in path2.
*/
right: number;
/**
* Number of distinct files.
*/
distinctFiles: number;
/**
* Number of equal files.
*/
equalFiles: number;
/**
* Number of files only in path1.
*/
leftFiles: number;
/**
* Number of files only in path2
*/
rightFiles: number;
/**
* Number of distinct directories.
*/
distinctDirs: number;
/**
* Number of equal directories.
*/
equalDirs: number;
/**
* Number of directories only in path1.
*/
leftDirs: number;
/**
* Number of directories only in path2.
*/
rightDirs: number;
/**
* Stats about broken links.
*/
brokenLinks: BrokenLinksStatistics;
/**
* Statistics available if 'compareSymlink' options is used.
*/
symlinks?: SymlinkStatistics;
/**
* Stats about entries that could not be accessed.
*/
permissionDenied: PermissionDeniedStatistics;
}
/**
* 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 {
/**
* Number of broken links only in path1
*/
leftBrokenLinks: number;
/**
* Number of broken links only in path2
*/
rightBrokenLinks: number;
/**
* Number of broken links with same name appearing in both path1 and path2 (leftBrokenLinks + rightBrokenLinks + distinctBrokenLinks)
*/
distinctBrokenLinks: number;
/**
* Total number of broken links
*/
totalBrokenLinks: 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 {
/**
* Number of distinct links.
*/
distinctSymlinks: number;
/**
* Number of equal links.
*/
equalSymlinks: number;
/**
* Number of links only in path1.
*/
leftSymlinks: number;
/**
* Number of links only in path2
*/
rightSymlinks: number;
/**
* Total number of different links (distinctSymlinks+leftSymlinks+rightSymlinks).
*/
differencesSymlinks: number;
/**
* Total number of links (differencesSymlinks+equalSymlinks).
*/
totalSymlinks: number;
}
/**
* 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 {@link Difference.reason} to understan why entries are considered distinct.
*/
export type DifferenceState = "equal" | "left" | "right" | "distinct";
/**
* Permission related state of left/right entries. Available only when {@link 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 type PermissionDeniedState = "access-ok" | "access-error-both" | "access-error-left" | "access-error-right";
/**
* Type of entry.
*/
export type DifferenceType = "missing" | "file" | "directory" | "broken-link";
/**
* 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 {@link Options.compareDate} is `true`.
* * `different-content` - File contents are different. Used when {@link Options.compareContent} is `true`.
* * `broken-link` - Both left/right entries are broken links.
* * `different-symlink` - Symlinks are different. See {@link Options.compareSymlink} for details.
* * `permission-denied` - One or both left/right entries are not accessible. See {@link Options.handlePermissionDenied} for details.
*/
export type Reason = undefined | "different-size" | "different-date" | "different-content" | "broken-link" | 'different-symlink' | 'permission-denied';
export interface Difference {
/**
* Any property is allowed if default result builder is not used.
*/
[key: string]: any;
/**
* Path not including file/directory name; can be relative or absolute depending on call to compare().
* Is undefined if missing on the left side.
*/
path1?: string;
/**
* Path not including file/directory name; can be relative or absolute depending on call to compare().
* Is undefined if missing on the right side.
*/
path2?: string;
/**
* Path relative to the root directory of the comparison.
*/
relativePath: string;
/**
* Left file/directory name.
* Is undefined if missing on the left side.
*/
name1?: string;
/**
* Right file/directory name.
* Is undefined if missing on the right side.
*/
name2?: string;
/**
* See {@link DifferenceState}
*/
state: DifferenceState;
/**
* Permission related state of left/right entries.
*/
permissionDeniedState: PermissionDeniedState;
/**
* Type of left entry.
* Is undefined if missing on the left side.
*/
type1: DifferenceType;
/**
* Type of right entry.
* Is undefined if missing on the right side.
*/
type2: DifferenceType;
/**
* Left file size.
* Is undefined if missing on the left side.
*/
size1?: number;
/**
* Right file size.
* Is undefined if missing on the right side.
*/
size2?: number;
/**
* Left entry modification date (stat.mtime).
* Is undefined if missing on the left side.
*/
date1?: Date;
/**
* Right entry modification date (stat.mtime).
* Is undefined if missing on the right side.
*/
date2?: Date;
/**
* Depth level relative to root dir.
*/
level: number;
/**
* Provides reason when two identically named entries are distinct.
*/
reason: Reason;
}
/**
* Extension point used for constructing the {@link Result} object.
* Called for each compared entry pair.
* Updates 'statistics' and 'diffSet'.
* @param entry1 Left entry.
* @param entry2 Right entry.
* @param state See {@link DifferenceState}.
* @param level Depth level relative to root dir.
* @param relativePath Path relative to the root directory of the comparison.
* @param statistics Statistics to be updated.
* @param diffSet Status per each entry to be appended.
* Do not append if {@link Options.noDiffSet} is false.
* @param reason See {@link Reason}. Not available if entries are equal.
*/
export type ResultBuilder = (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;
/**
* Extension point used to perform sync file content comparison.
*/
export type CompareFileSync = (path1: string, stat1: fs.Stats, path2: string, stat2: fs.Stats, options: Options) => boolean;
/**
* Extension point used to perform async file content comparison.
*/
export type CompareFileAsync = (path1: string, stat1: fs.Stats, path2: string, stat2: fs.Stats, options: Options) => Promise;
export interface CompareFileHandler {
compareSync: CompareFileSync;
compareAsync: CompareFileAsync;
}
/**
* Extension point used to compare files or directories names.
* The comparison should be dependent on received options (ie. case sensitive, ...).
* Returns 0 if names are identical, -1 if name1name2.
*/
export type CompareNameHandler = (name1: string, name2: string, options: Options) => 0 | 1 | -1;
/**
* Extension point used to control which files or directories should be included in the comparison.
*
* @param entry Filesystem entry to include or ignore.
* @param relativePath Path relative to the root directory of the comparison. It depends on {@link Entry.origin}.
* @param option Comparison options.
* @returns Returns true if the entry is to be processed or false to ignore it.
*/
export type FilterHandler = (entry: Entry, relativePath: string, options: Options) => boolean;
export interface FileCompareHandlers {
/**
* Compares files based on their binary content.
*
* This is the default file content comparator.
* It is used when {@link Options.compareContent} is true and custom file comparator
* is not specified (ie. {@link Options.compareFileSync} or {@link Options.compareFileAsync} are 'undefined').
*/
defaultFileCompare: CompareFileHandler;
/**
* Compares files line by line.
*
* These additional options are available:
* * 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;
}
export interface CompareNameHandlers {
/**
* Compares file or directory names using the 'strcmp' function.
* It is used if {@link Options.compareNameHandler} is not specified.
*/
defaultNameCompare: CompareNameHandler;
}
export interface FilterHandlers {
/**
* Uses minimatch to include/ignore files based on {@link Options.includeFilter} and {@link Options.excludeFilter}.
* It is used if {@link Options.filterHandler} is not specified.
*/
defaultFilterHandler: FilterHandler;
}
//# sourceMappingURL=types.d.ts.map