all files / dir-compare/ index.js

100% Statements 57/57
72.22% Branches 13/18
100% Functions 8/8
100% Lines 57/57
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     26×                             26× 26× 26× 26×   26× 26× 26×   26×               26× 26×                             26× 26× 26× 26×   26×   26× 26× 26× 26× 26×   26×         52× 52× 52× 52× 52× 52× 48×   52× 52×   52× 52×   52×     52× 52× 52× 52× 52× 52× 52×         274× 587× 339×   248×                                                                                                            
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
};