Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fix ENAMETOOLONG for too big commit messages #263

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 17 additions & 1 deletion 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.
*
Expand Down Expand Up @@ -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);
}

/**
Expand Down
8 changes: 6 additions & 2 deletions test/git.test.js
Expand Up @@ -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);
});
Expand Down