diff --git a/lib/changes.js b/lib/changes.js index 4449b1a..ee3cf7e 100644 --- a/lib/changes.js +++ b/lib/changes.js @@ -9,10 +9,12 @@ const fs = require('fs'); const $ = require('child_process'); const CHANGES_FILE = 'CHANGES.md'; -const CHANGES_HEADING = '# Changes\n\n'; +const CHANGES_HEADING = '# Changes'; function exists(changes, version) { - return changes.indexOf(`\n## ${version}\n`) !== -1; + const escaped_version = version.replace(/([\.\-])/g, '\\$1'); + const regexp = new RegExp(`\r?\n## ${escaped_version}\r?\n`); + return regexp.test(changes); } // Write the commit history to the changes file @@ -22,15 +24,21 @@ exports.write = function () { // Get previous file content let previous; + let heading; + let newline; try { previous = fs.readFileSync(CHANGES_FILE, 'utf8'); - if (previous.indexOf(CHANGES_HEADING) !== 0) { + const match = previous.match(new RegExp(`^${CHANGES_HEADING}(\r?\n){2}`)); + if (!match) { console.error(`Unexpected ${CHANGES_FILE} file header`); process.exit(1); return null; } + heading = match[0]; + newline = match[1]; } catch (e) { - previous = CHANGES_HEADING; + previous = heading = `${CHANGES_HEADING}\n\n`; + newline = '\n'; } // Do not allow version to be added twice @@ -57,7 +65,8 @@ exports.write = function () { // Remove blanks (if no body) and indent body changes = changes.replace(/\n{3,}/g, '\n') .replace(/^([^\»\s])/gm, ' $1') - .replace(/^»/gm, '-'); + .replace(/^»/gm, '-') + .replace(/\n/gm, newline); // Only mention contributors if (author) { @@ -66,10 +75,10 @@ exports.write = function () { } // Generate new changes - let next = `${CHANGES_HEADING}## ${version}\n\n${changes}`; - const remain = previous.substring(CHANGES_HEADING.length); + let next = `${heading}## ${version}${newline}${newline}${changes}`; + const remain = previous.substring(heading.length); if (remain) { - next += `\n${remain}`; + next += `${newline}${remain}`; } fs.writeFileSync(CHANGES_FILE, next); return previous; diff --git a/test/changes-test.js b/test/changes-test.js index 6393adb..56bbf6b 100644 --- a/test/changes-test.js +++ b/test/changes-test.js @@ -137,4 +137,32 @@ describe('changes', () => { sinon.assert.calledWith(process.exit, 1); }); + it('works if changes file was checked out with CRLF', () => { + const initial = '# Changes\r\n\r\n## 0.0.1\r\n\r\n- Inception\r\n'; + setChanges(initial); + setLog('» JavaScript (Studio)\n\nWhat else?\n\n\n\n'); + + const previous = changes.write(); + + sinon.assert.calledOnce(fs.writeFileSync); + sinon.assert.calledWith(fs.writeFileSync, 'CHANGES.md', '# Changes\r\n\r\n' + + '## 1.0.0\r\n\r\n- JavaScript\r\n\r\n What else?\r\n\r\n' + + '## 0.0.1\r\n\r\n- Inception\r\n'); + sinon.assert.calledOnce($.execSync); + sinon.assert.calledWithMatch($.execSync, 'git log v0.0.1..HEAD'); + assert.equal(previous, initial); + }); + + it('fails if version is already in changes file with CRLF', () => { + setChanges('# Changes\r\n\r\n## 1.0.0\r\n\r\nFoo'); + + changes.write(); + + sinon.assert.calledOnce(console.error); + sinon.assert.calledWith(console.error, + 'Version 1.0.0 is already in CHANGES.md'); + sinon.assert.calledOnce(process.exit); + sinon.assert.calledWith(process.exit, 1); + }); + });