Skip to content

Commit

Permalink
fix: include deleted files in release commit
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Require Git 2.7.1 or higher
  • Loading branch information
pvdlg committed Nov 5, 2019
1 parent e6af5b4 commit f59d20c
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 224 deletions.
17 changes: 7 additions & 10 deletions lib/git.js
Expand Up @@ -2,20 +2,17 @@ const execa = require('execa');
const debug = require('debug')('semantic-release:git');

/**
* Filter files modified on the local repository.
* Retrieve the list of files modified on the local repository.
*
* @param {Array<String>} files List of file paths to filter.
* @param {Object} [execaOpts] Options to pass to `execa`.
*
* @return {Array<String>} Array of modified files path.
*/
async function filterModifiedFiles(files, execaOpts) {
return files.length > 0
? (await execa('git', ['ls-files', '-m', '-o', ...files], execaOpts)).stdout
.split('\n')
.map(file => file.trim())
.filter(file => Boolean(file))
: [];
async function getModifiedFiles(execaOpts) {
return (await execa('git', ['ls-files', '-m', '-o'], execaOpts)).stdout
.split('\n')
.map(file => file.trim())
.filter(file => Boolean(file));
}

/**
Expand Down Expand Up @@ -65,4 +62,4 @@ async function gitHead(execaOpts) {
return (await execa('git', ['rev-parse', 'HEAD'], execaOpts)).stdout;
}

module.exports = {filterModifiedFiles, add, gitHead, commit, push};
module.exports = {getModifiedFiles, add, gitHead, commit, push};
37 changes: 0 additions & 37 deletions lib/glob-assets.js

This file was deleted.

56 changes: 38 additions & 18 deletions lib/prepare.js
@@ -1,8 +1,10 @@
const {template} = require('lodash');
const {isPlainObject, isArray, template, castArray, uniq} = require('lodash');
const micromatch = require('micromatch');
const dirGlob = require('dir-glob');
const pReduce = require('p-reduce');
const debug = require('debug')('semantic-release:git');
const resolveConfig = require('./resolve-config');
const globAssets = require('./glob-assets.js');
const {filterModifiedFiles, add, commit, push} = require('./git');
const {getModifiedFiles, add, commit, push} = require('./git');

/**
* Prepare a release commit including configurable files.
Expand All @@ -28,24 +30,42 @@ module.exports = async (pluginConfig, context) => {
} = context;
const {message, assets} = resolveConfig(pluginConfig, logger);

if (assets && assets.length > 0) {
const globbedAssets = await globAssets(context, assets);
debug('globed assets: %o', globbedAssets);
const modifiedFiles = await getModifiedFiles({env, cwd});

const filesToCommit = await filterModifiedFiles(globbedAssets, {cwd, env});
const filesToCommit = uniq(
await pReduce(
assets.map(asset => (!isArray(asset) && isPlainObject(asset) ? asset.path : asset)),
async (result, asset) => {
const glob = castArray(asset);
let nonegate;
// Skip solo negated pattern (avoid to include every non js file with `!**/*.js`)
if (glob.length <= 1 && glob[0].startsWith('!')) {
nonegate = true;
debug(
'skipping the negated glob %o as its alone in its group and would retrieve a large amount of files ',
glob[0]
);
}

if (filesToCommit.length > 0) {
logger.log('Found %d file(s) to commit', filesToCommit.length);
await add(filesToCommit, {env, cwd});
debug('commited files: %o', filesToCommit);
await commit(
message
? template(message)({branch: branch.name, lastRelease, nextRelease})
: `chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}`,
{env, cwd}
);
}
return [
...result,
...micromatch(modifiedFiles, await dirGlob(glob, {cwd}), {dot: true, nonegate, cwd, expand: true}),
];
},
[]
)
);

if (filesToCommit.length > 0) {
logger.log('Found %d file(s) to commit', filesToCommit.length);
await add(filesToCommit, {env, cwd});
debug('commited files: %o', filesToCommit);
await commit(
message
? template(message)({branch: branch.name, lastRelease, nextRelease})
: `chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}`,
{env, cwd}
);
await push(repositoryUrl, branch.name, {env, cwd});
logger.log('Prepared Git release: %s', nextRelease.gitTag);
}
Expand Down
3 changes: 1 addition & 2 deletions package.json
Expand Up @@ -24,8 +24,6 @@
"debug": "^4.0.0",
"dir-glob": "^3.0.0",
"execa": "^3.0.0",
"fs-extra": "^8.0.0",
"globby": "^10.0.0",
"lodash": "^4.17.4",
"micromatch": "^4.0.0",
"p-reduce": "^2.0.0"
Expand All @@ -35,6 +33,7 @@
"clear-module": "^4.0.0",
"codecov": "^3.0.0",
"file-url": "^3.0.0",
"fs-extra": "^8.0.0",
"get-stream": "^5.0.0",
"git-log-parser": "^1.2.0",
"nyc": "^14.0.0",
Expand Down
1 change: 0 additions & 1 deletion test/fixtures/files/.dotfile

This file was deleted.

1 change: 0 additions & 1 deletion test/fixtures/files/upload.txt

This file was deleted.

1 change: 0 additions & 1 deletion test/fixtures/files/upload_other.txt

This file was deleted.

18 changes: 4 additions & 14 deletions test/git.test.js
@@ -1,7 +1,7 @@
import path from 'path';
import test from 'ava';
import {outputFile, appendFile} from 'fs-extra';
import {add, filterModifiedFiles, commit, gitHead, push} from '../lib/git';
import {add, getModifiedFiles, commit, gitHead, push} from '../lib/git';
import {gitRepo, gitCommits, gitGetCommits, gitStaged, gitRemoteHead} from './helpers/git-utils';

test('Add file to index', async t => {
Expand All @@ -15,7 +15,7 @@ test('Add file to index', async t => {
await t.deepEqual(await gitStaged({cwd}), ['file1.js']);
});

test('Filter modified files, including files in .gitignore and untracked ones', async t => {
test('Get the modified files, including files in .gitignore but including untracked ones', async t => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
// Create files
Expand All @@ -35,7 +35,7 @@ test('Filter modified files, including files in .gitignore and untracked ones',
await outputFile(path.resolve(cwd, 'file4.js'), 'Test content');

await t.deepEqual(
(await filterModifiedFiles(['file1.js', 'dir/file2.js', 'file3.js', 'file4.js'], {cwd})).sort(),
(await getModifiedFiles({cwd})).sort(),
['file1.js', 'dir/file2.js', 'file3.js', 'file4.js'].sort()
);
});
Expand All @@ -44,17 +44,7 @@ test('Returns [] if there is no modified files', async t => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();

await t.deepEqual(await filterModifiedFiles(['file1.js', 'file2.js'], {cwd}), []);
});

test('Returns [] if there is no files for which to check modification', 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'), '');
await outputFile(path.resolve(cwd, 'dir/file2.js'), '');

await t.deepEqual(await filterModifiedFiles([], {cwd}), []);
await t.deepEqual(await getModifiedFiles({cwd}), []);
});

test('Commit added files', async t => {
Expand Down
138 changes: 0 additions & 138 deletions test/glob-assets.test.js

This file was deleted.

21 changes: 21 additions & 0 deletions test/helpers/git-utils.js
Expand Up @@ -186,3 +186,24 @@ export async function gitCommitedFiles(ref, execaOpts) {
.split('\n')
.filter(file => Boolean(file));
}

/**
* Add a list of file to the Git index.
*
* @param {Array<String>} files Array of files path to add to the index.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
export async function gitAdd(files, execaOpts) {
await execa('git', ['add', '--force', '--ignore-errors', ...files], {...execaOpts});
}

/**
* Push to the remote repository.
*
* @param {String} repositoryUrl The remote repository URL.
* @param {String} branch The branch to push.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
export async function gitPush(repositoryUrl, branch, execaOpts) {
await execa('git', ['push', '--tags', repositoryUrl, `HEAD:${branch}`], execaOpts);
}

0 comments on commit f59d20c

Please sign in to comment.