diff --git a/lib/git-json-merge.js b/lib/git-json-merge.js index bd4fbef..0d88674 100644 --- a/lib/git-json-merge.js +++ b/lib/git-json-merge.js @@ -4,6 +4,16 @@ var detectIndent = require('detect-indent'); var encoding = 'utf-8'; +function detectTrailingNewline (str) { + if (str.endsWith('\r\n')) { + return '\r\n'; + } else if (str.endsWith('\n')) { + return '\n'; + } else { + return ''; + } +} + function mergeJsonFiles (oursFileName, baseFileName, theirsFileName) { var oursJson = stripBom(fs.readFileSync(oursFileName, encoding)); var baseJson = stripBom(fs.readFileSync(baseFileName, encoding)); @@ -13,15 +23,13 @@ function mergeJsonFiles (oursFileName, baseFileName, theirsFileName) { } function mergeJson (oursJson, baseJson, theirsJson) { - var oursIndent = detectIndent(oursJson).indent; - var baseIndent = detectIndent(baseJson).indent; - var theirsIndent = detectIndent(theirsJson).indent; - var newOursIndent = selectIndent(oursIndent, baseIndent, theirsIndent); + var indent = mapAndSelect((str) => detectIndent(str).indent, oursJson, baseJson, theirsJson); + var trailingNewline = mapAndSelect(detectTrailingNewline, oursJson, baseJson, theirsJson); var ours = JSON.parse(oursJson); var base = JSON.parse(baseJson); var theirs = JSON.parse(theirsJson); var newOurs = merge(ours, base, theirs); - var newOursJson = JSON.stringify(newOurs, null, newOursIndent); + var newOursJson = JSON.stringify(newOurs, null, indent) + trailingNewline; return newOursJson; } @@ -36,8 +44,12 @@ function merge (ours, base, theirs) { return base; } -function selectIndent (oursIndent, baseIndent, theirsIndent) { - return oursIndent !== baseIndent ? oursIndent : theirsIndent !== baseIndent ? theirsIndent : baseIndent; +function selectVersion (ours, base, theirs) { + return ours !== base ? ours : theirs !== base ? theirs : base; +} + +function mapAndSelect (fn, ours, base, theirs) { + return selectVersion(fn(ours), fn(base), fn(theirs)); } function stripBom (str) { @@ -45,9 +57,11 @@ function stripBom (str) { } module.exports = { + detectTrailingNewline: detectTrailingNewline, mergeJsonFiles: mergeJsonFiles, mergeJson: mergeJson, merge: merge, - selectIndent: selectIndent, + selectVersion: selectVersion, + mapAndSelect: mapAndSelect, stripBom: stripBom } diff --git a/test/git-json-merge.spec.js b/test/git-json-merge.spec.js index 260831e..593e7ba 100644 --- a/test/git-json-merge.spec.js +++ b/test/git-json-merge.spec.js @@ -16,13 +16,35 @@ describe('gitJsonMerge', function () { describeMergeJsonTest(bar, fooBar, fooBar, bar); }); - describe('selectIndent', function () { - describeSelectIndentTest(4, 2, 2, 4); - describeSelectIndentTest(4, 4, 2, 2); - describeSelectIndentTest(4, 4, 4, 4); - describeSelectIndentTest(2, 4, 2, 2); - describeSelectIndentTest(2, 2, 4, 4); - describeSelectIndentTest(2, 4, 4, 2); + describe('selectVersion', function () { + describeSelectVersionTest(4, 2, 2, 4); + describeSelectVersionTest(4, 4, 2, 2); + describeSelectVersionTest(4, 4, 4, 4); + describeSelectVersionTest(2, 4, 2, 2); + describeSelectVersionTest(2, 2, 4, 4); + describeSelectVersionTest(2, 4, 4, 2); + }); + + describe('mapAndSelect', function () { + it('calls the function with the arguments and selects the result', function () { + var repeatX = (count) => repeatCharacter('x', count); + + expect(gitJsonMerge.mapAndSelect(repeatX, 4, 2, 2)).to.equal('xxxx'); + }); + }); + + describe('detectTrailingNewline', function () { + it('returns \\r\\n for Windows-style newlines', function () { + expect(gitJsonMerge.detectTrailingNewline('string\r\n')).to.equal('\r\n'); + }); + + it('returns \\n for Unix-style newlines', function () { + expect(gitJsonMerge.detectTrailingNewline('string\n')).to.equal('\n'); + }); + + it('returns an empty string without trailing newline', function () { + expect(gitJsonMerge.detectTrailingNewline('string')).to.equal(''); + }); }); describe('stripBom', function () { @@ -61,7 +83,7 @@ function describeMergeJsonTest (ours, base, theirs, expected) { }); } -function describeSelectIndentTest (ours, base, theirs, expected) { +function describeSelectVersionTest (ours, base, theirs, expected) { var character = ' '; ours = repeatCharacter(character, ours); base = repeatCharacter(character, base); @@ -69,7 +91,7 @@ function describeSelectIndentTest (ours, base, theirs, expected) { expected = repeatCharacter(character, expected); describe('given arguments of ' + ours.length + ' as ours, ' + base.length + ' as base and ' + theirs.length + ' as theirs', function () { - var actual = gitJsonMerge.selectIndent(ours, base, theirs); + var actual = gitJsonMerge.selectVersion(ours, base, theirs); it('should return ' + expected.length, function () { expect(actual).to.equal(expected); })