diff --git a/lib/git.js b/lib/git.js index 267ef1d7..c25f3f9a 100644 --- a/lib/git.js +++ b/lib/git.js @@ -1,6 +1,15 @@ +const os = require('os'); +const path = require('path'); +const fs = require('fs'); +const crypto = require('crypto'); const execa = require('execa'); const debug = require('debug')('semantic-release:git'); +function _generateUniqueFilename() { + // -> https://stackoverflow.com/questions/23327010/how-to-generate-unique-id-with-node-js + return crypto.randomBytes(16).toString('hex'); +} + /** * Retrieve the list of files modified on the local repository. * @@ -35,7 +44,14 @@ async function add(files, execaOptions) { * @throws {Error} if the commit failed. */ async function commit(message, execaOptions) { - await execa('git', ['commit', '-m', message], execaOptions); + /* As messages can be arbitrarily long, we have to + write it to a tempfile to avoid ENAMETOOLONG on + poor systems not supporting "long" arguments */ + const temporaryDir = os.tmpdir(); + const temporaryMessageFileName = path.resolve(temporaryDir, _generateUniqueFilename()); + fs.writeFileSync(temporaryMessageFileName, message); + await execa('git', ['commit', '-F', temporaryMessageFileName], execaOptions); + fs.unlinkSync(temporaryMessageFileName); } /** diff --git a/test/git.test.js b/test/git.test.js index ada4e6d8..1aec411e 100644 --- a/test/git.test.js +++ b/test/git.test.js @@ -47,14 +47,18 @@ test('Returns [] if there is no modified files', async t => { await t.deepEqual(await getModifiedFiles({cwd}), []); }); -test('Commit added files', async t => { +test('Commit added files with a huge message', async t => { // Create a git repository, set the current working directory at the root of the repo const {cwd} = await gitRepo(); // Create files await outputFile(path.resolve(cwd, 'file1.js'), ''); // Add files and commit await add(['.'], {cwd}); - await commit('Test commit', {cwd}); + // 1 MB message should break everything, ... + const hugeMessage = Array.from({length: 1024 * 1024}) + .map((_, index) => (index % 72 ? 'z' : '\n')) + .join(''); + await commit(hugeMessage, {cwd}); await t.true((await gitGetCommits(undefined, {cwd})).length === 1); });