Skip to content

Commit

Permalink
Add option to ignore line endings and white space differences #10
Browse files Browse the repository at this point in the history
  • Loading branch information
gliviu committed Dec 25, 2018
1 parent 9b04500 commit 191c217
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 73 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Expand Up @@ -3,4 +3,4 @@
/tests/report.txt
/tests/testdir
/coverage/
test.js
test*.js
5 changes: 5 additions & 0 deletions README.md
Expand Up @@ -130,6 +130,7 @@ Included handlers are:
* `dircompare.fileCompareHandlers.defaultFileCompare.compareSync`
* `dircompare.fileCompareHandlers.defaultFileCompare.compareAsync`
* `dircompare.fileCompareHandlers.lineBasedFileCompare.compareSync`
* `dircompare.fileCompareHandlers.lineBasedFileCompare.compareAsync`

The line based comparator can be used to ignore line ending and white space differences. This comparator is not available in [CLI](#command-line) version.
```javascript
Expand All @@ -138,6 +139,7 @@ var dircompare = require('dir-compare');
var options = {
compareContent: true,
compareFileSync: dircompare.fileCompareHandlers.lineBasedFileCompare.compareSync,
compareFileAsync: dircompare.fileCompareHandlers.lineBasedFileCompare.compareAsync,
ignoreLineEnding: true,
ignoreWhiteSpaces: true
};
Expand All @@ -146,6 +148,9 @@ var path1 = '...';
var path2 = '...';
var res = dircompare.compareSync(path1, path2, options);
console.log(res)

dircompare.compare(path1, path2, options)
.then(res => console.log(res))
```

## Command line
Expand Down
35 changes: 35 additions & 0 deletions file_compare_handlers/common.js
@@ -1,3 +1,5 @@
var fs = require('fs');
var Promise = require('bluebird');

var alloc = function(bufSize) {
if(Buffer.alloc){
Expand All @@ -6,6 +8,39 @@ var alloc = function(bufSize) {
return new Buffer(bufSize);
}

var wrapper = function(fdQueue) {
return {
open : Promise.promisify(fdQueue.open),
read : Promise.promisify(fs.read),
}
};

var closeFilesSync = function(fd1, fd2){
if (fd1) {
fs.closeSync(fd1);
}
if (fd2) {
fs.closeSync(fd2);
}
}

var closeFilesAsync = function(fd1, fd2, fdQueue){
if (fd1) {
fdQueue.close(fd1, function(err){
if(err){console.log(err);}
});
}
if (fd2) {
fdQueue.close(fd2, function(err){
if(err){console.log(err);}
});
}
}


module.exports = {
alloc : alloc,
wrapper: wrapper,
closeFilesSync: closeFilesSync,
closeFilesAsync: closeFilesAsync
};
33 changes: 6 additions & 27 deletions file_compare_handlers/defaultFileCompare.js
Expand Up @@ -4,6 +4,10 @@ var Promise = require('bluebird');
var FileDescriptorQueue = require('./fileDescriptorQueue');
var fdQueue = new FileDescriptorQueue(8);
var alloc = require('./common').alloc;
var wrapper = require('./common').wrapper(fdQueue);
var closeFilesSync = require('./common').closeFilesSync;
var closeFilesAsync = require('./common').closeFilesAsync;

/**
* Compares two partial buffers.
*/
Expand Down Expand Up @@ -44,11 +48,6 @@ var compareSync = function (path1, stat1, path2, stat2, options) {
}
};

var wrapper = {
open : Promise.promisify(fdQueue.open),
read : Promise.promisify(fs.read),
};

/**
* Compares two files by content using bufSize as buffer length.
*/
Expand Down Expand Up @@ -80,35 +79,15 @@ var compareAsync = function (path1, stat1, path2, stat2, options) {
});
};
return compareAsyncInternal().then(function (result) {
closeFilesAsync(fd1, fd2);
closeFilesAsync(fd1, fd2, fdQueue);
return result;
});
}).catch(function (error) {
closeFilesAsync(fd1, fd2);
closeFilesAsync(fd1, fd2, fdQueue);
return error;
});
};

var closeFilesSync = function(fd1, fd2){
if (fd1) {
fs.closeSync(fd1);
}
if (fd2) {
fs.closeSync(fd2);
}
}
var closeFilesAsync = function(fd1, fd2){
if (fd1) {
fdQueue.close(fd1, function(err){
if(err){console.log(err);}
});
}
if (fd2) {
fdQueue.close(fd2, function(err){
if(err){console.log(err);}
});
}
}
module.exports = {
compareSync : compareSync,
compareAsync : compareAsync
Expand Down
105 changes: 77 additions & 28 deletions file_compare_handlers/lineBasedFileCompare.js
@@ -1,11 +1,17 @@
// Compare files line by line with options to ignore line endings and white space differencies.
'use strict'
var fs = require('fs')
var fs = require('fs');
var bufferEqual = require('buffer-equal');
var Promise = require('bluebird');
var FileDescriptorQueue = require('./fileDescriptorQueue');
var fdQueue = new FileDescriptorQueue(8);
var alloc = require('./common').alloc;
var wrapper = require('./common').wrapper(fdQueue);
var closeFilesSync = require('./common').closeFilesSync;
var closeFilesAsync = require('./common').closeFilesAsync;

var BUF_SIZE = 4096
var compareSync = function (path1, stat1, path2, stat2, options) {
var BUF_SIZE = 4096;
var fd1, fd2;
try {
fd1 = fs.openSync(path1, 'r');
Expand All @@ -28,34 +34,65 @@ var compareSync = function (path1, stat1, path2, stat2, options) {
else if(lines1.length !== lines2.length) {
return false;
} else {
var i
for(i = 0; i < lines1.length - 1; i++) {
var line1 = lines1[i]
var line2 = lines2[i]
if(options.ignoreLineEnding){
line1 = removeLineEnding(line1)
line2 = removeLineEnding(line2)
}
if(options.ignoreWhiteSpaces){
line1 = removeWhiteSpaces(line1)
line2 = removeWhiteSpaces(line2)
}
if(line1!==line2) {
return false
}
if(!compareLines(lines1, lines2, options)){
return false
}
last1 = lines1[i]
last2 = lines2[i]
last1 = lines1[lines1.length-1]
last2 = lines2[lines2.length-1]
}
}
} finally {
closeFilesSync(fd1, fd2);
}
};

var compareAsync = function (filePath1, fileStat1, filePath2, fileStat2, options) {
throw 'not implemented'
};
var compareAsync = function(path1, stat1, path2, stat2, options) {
var fd1, fd2;
return Promise.all([wrapper.open(path1, 'r'), wrapper.open(path2, 'r')])
.then(function(fds){
fd1 = fds[0]
fd2 = fds[1]
var buf1 = alloc(BUF_SIZE);
var buf2 = alloc(BUF_SIZE);
var progress = 0;
var last1='', last2=''
var compareAsyncInternal = function () {
return Promise.all([
wrapper.read(fd1, buf1, 0, BUF_SIZE, null),
wrapper.read(fd2, buf2, 0, BUF_SIZE, null)
]).then(function(sizes){
var size1 = sizes[0]
var size2 = sizes[1]
var chunk1 = buf1.toString('utf8', 0, size1)
var chunk2 = buf2.toString('utf8', 0, size2)
var lines1 = (last1+chunk1).split(/\n/)
var lines2 = (last2+chunk2).split(/\n/)
if(size1===0 && size2===0){
// End of file reached
return true
}
else if(lines1.length !== lines2.length) {
return false;
} else {
if(!compareLines(lines1, lines2, options)){
return false
}
last1 = lines1[lines1.length-1]
last2 = lines2[lines2.length-1]
return compareAsyncInternal()
}
})
}
return compareAsyncInternal().then(function (result) {
closeFilesAsync(fd1, fd2, fdQueue);
return result;
});
})
.catch(function (error) {
closeFilesAsync(fd1, fd2, fdQueue);
return error;
});
}

var removeLineEnding = function (s) {
return s.replace(/[\r]+$/g, '');
Expand All @@ -66,13 +103,25 @@ var removeWhiteSpaces = function (s) {
return s.replace(/^[ \f\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+|[ \f\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+$/g, '');
};

var closeFilesSync = function(fd1, fd2){
if (fd1) {
fs.closeSync(fd1);
}
if (fd2) {
fs.closeSync(fd2);

function compareLines(lines1, lines2, options){
var i
for(i = 0; i < lines1.length - 1; i++) {
var line1 = lines1[i]
var line2 = lines2[i]
if(options.ignoreLineEnding){
line1 = removeLineEnding(line1)
line2 = removeLineEnding(line2)
}
if(options.ignoreWhiteSpaces){
line1 = removeWhiteSpaces(line1)
line2 = removeWhiteSpaces(line2)
}
if(line1!==line2) {
return false
}
}
return true
}

module.exports = {
Expand Down
5 changes: 3 additions & 2 deletions package.json
Expand Up @@ -19,8 +19,9 @@
"shelljs": "0.3.0",
"tar-fs": "1.13.0",
"temp": "0.8.1",
"istanbul": "0.4.4",
"memory-streams": "0.1.0"
"istanbul": "0.4.5",
"memory-streams": "0.1.0",
"semver": "5.6.0"
},
"bin": {
"dircompare": "dircompare.js"
Expand Down

0 comments on commit 191c217

Please sign in to comment.