1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167 | 1×
1×
1×
1×
1×
1×
1×
26×
26×
26×
26×
26×
26×
26×
26×
26×
1×
26×
26×
26×
26×
26×
26×
26×
26×
26×
26×
26×
26×
26×
1×
52×
52×
52×
52×
52×
52×
48×
52×
52×
52×
52×
52×
1×
52×
52×
52×
52×
52×
52×
52×
1×
274×
587×
339×
248×
1×
| var util = require('util');
var Promise = require('bluebird');
var compareSyncInternal = require('./compareSync');
var compareAsyncInternal = require('./compareAsync');
var defaultResultBuilderCallback = require('./defaultResultBuilderCallback');
var defaultCompareFileCallback = require('./defaultCompareFileCallback');
var compareSync = function (path1, path2, options) {
'use strict';
var statistics = {
distinct : 0,
equal : 0,
left : 0,
right : 0,
distinctFiles : 0,
equalFiles : 0,
leftFiles : 0,
rightFiles : 0,
distinctDirs : 0,
equalDirs : 0,
leftDirs : 0,
rightDirs : 0,
same : undefined
};
var diffSet;
options = prepareOptions(options);
Eif(!options.noDiffSet){
diffSet = [];
}
compareSyncInternal(path1, path2, 0, '', options, statistics, diffSet);
completeStatistics(statistics);
statistics.diffSet = diffSet;
return statistics;
};
// TODO: provide async file comparison
// TODO: remove all 'debugger', 'console.', 'throw'
// TODO: see if npm test requires root: do 'npm install ./dir-compare -g', npm test, sudo npm test.
// TODO: test adding exceptions and delays in compareAsync.js -> wrapper.
var compareAsync = function (path1, path2, options) {
'use strict';
return Promise.resolve().then(function(xx){
var statistics = {
distinct : 0,
equal : 0,
left : 0,
right : 0,
distinctFiles : 0,
equalFiles : 0,
leftFiles : 0,
rightFiles : 0,
distinctDirs : 0,
equalDirs : 0,
leftDirs : 0,
rightDirs : 0,
same : undefined
};
options = prepareOptions(options);
var asyncDiffSet;
Eif(!options.noDiffSet){
asyncDiffSet = [];
}
return compareAsyncInternal(path1, path2, 0, '', options, statistics, asyncDiffSet).then(
function(){
completeStatistics(statistics);
Eif(!options.noDiffSet){
var diffSet = [];
rebuildAsyncDiffSet(statistics, asyncDiffSet, diffSet);
statistics.diffSet = diffSet;
}
return statistics;
});
});
};
var prepareOptions = function(options){
options = options || {};
var clone = JSON.parse(JSON.stringify(options))
clone.resultBuilder = options.resultBuilder;
clone.compareFileSync = options.compareFileSync;
clone.compareFileAsync = options.compareFileAsync;
if (!clone.resultBuilder) {
clone.resultBuilder = defaultResultBuilderCallback;
}
Eif (!clone.compareFileSync) {
clone.compareFileSync = defaultCompareFileCallback.compareSync;
}
Eif (!clone.compareFileAsync) {
clone.compareFileAsync = defaultCompareFileCallback.compareAsync;
}
return clone;
}
var completeStatistics = function(statistics){
statistics.differences = statistics.distinct + statistics.left + statistics.right;
statistics.differencesFiles = statistics.distinctFiles + statistics.leftFiles + statistics.rightFiles;
statistics.differencesDirs = statistics.distinctDirs + statistics.leftDirs + statistics.rightDirs;
statistics.total = statistics.equal+statistics.differences;
statistics.totalFiles = statistics.equalFiles+statistics.differencesFiles;
statistics.totalDirs = statistics.equalDirs+statistics.differencesDirs;
statistics.same = statistics.differences ? false : true;
}
// Async diffsets are kept into recursive structures.
// This method transforms them into one dimensional arrays.
var rebuildAsyncDiffSet = function(statistics, asyncDiffSet, diffSet){
asyncDiffSet.forEach(function(rawDiff){
if(!Array.isArray(rawDiff)){
diffSet.push(rawDiff);
} else{
rebuildAsyncDiffSet(statistics, rawDiff, diffSet);
}
});
}
/**
* Options:
* compareSize: true/false - Compares files by size. Defaults to 'false'.
* compareContent: true/false - Compares files by content. Defaults to 'false'.
* skipSubdirs: true/false - Skips sub directories. Defaults to 'false'.
* skipSymlinks: true/false - Skips symbolic links. 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.
* excludeFilter: File/directory name exclude filter. Comma separated [minimatch](https://www.npmjs.com/package/minimatch) patterns.
* resultBuilder: Callback for constructing result.
* function (entry1, entry2, state, level, relativePath, options, statistics, diffSet). Called for each compared entry pair. Updates 'statistics' and 'diffSet'.
*
* Output format:
* 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)
* 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)
* 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)
* same: true if directories are identical
* diffSet - List of changes (present if Options.noDiffSet is false)
* path1: absolute path not including file/directory name,
* path2: absolute path not including file/directory name,
* relativePath: common 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
* type2: one of missing, file, directory
* size1: file size
* size2: file size
* date1: modification date (stat.mdate)
* date2: modification date (stat.mdate)
* level: depth
*/
module.exports = {
compareSync : compareSync,
compare : compareAsync
};
|