Skip to content

Commit

Permalink
Remove merge commits in co-author collection (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisdothtml authored Jan 13, 2020
1 parent 023a7a0 commit 36b090a
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 121 deletions.
255 changes: 134 additions & 121 deletions lib/USync.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,143 +69,156 @@ test('USync.validateConfig()', () => {
});

describe('usync.import()', () => {
test.concurrent('imports file changes into new branch', async () => {
const parentName = 'foo/import-parent';
const childName = 'foo/import-child';
const subdir = 'sub-dir';
const changeBranch = 'my-test-change';
const commitAuthor = 'Test User <[email protected]>';
const contribAuthor = 'Other Test User <[email protected]>';

// prepare repos
{
const parent = await createFixture(CLONES_DIR, parentName);
const child = await createFixture(CLONES_DIR, childName);
test.concurrent(
'imports file changes into new branch',
async () => {
const parentName = 'foo/import-parent';
const childName = 'foo/import-child';
const subdir = 'sub-dir';
const changeBranch = 'my-test-change';
const commitAuthor = 'Test User <[email protected]>';
const contribAuthor = 'Other Test User <[email protected]>';

// setup initial states (before change is authored)
// prepare repos
{
await parent.editor.write(
'.usyncrc.json',
JSON.stringify({
mapping: {
[childName]: {
[subdir]: '/',
const parent = await createFixture(CLONES_DIR, parentName);
const child = await createFixture(CLONES_DIR, childName);

// setup initial states (before change is authored)
{
await parent.editor.write(
'.usyncrc.json',
JSON.stringify({
mapping: {
[childName]: {
[subdir]: '/',
},
},
},
}),
);
}),
);

parent.editor.cd(subdir);
// copy change from child's init commit
await parent.editor.write(`foo.txt`, 'foo');
for (const repo of [parent, child]) {
parent.editor.cd(subdir);
// copy change from child's init commit
await parent.editor.write(`foo.txt`, 'foo');
for (const repo of [parent, child]) {
await Promise.all([
repo.editor.write(
'file-to-delete.txt',
generateParagraphs('foo'),
),
repo.editor.write(
'some/dir/file-to-delete.txt',
generateParagraphs('bar'),
),
repo.editor.write(
'file-to-rename.txt',
generateParagraphs('baz'),
),
repo.editor.write(
'foo/file-to-move.txt',
generateParagraphs('qux'),
),
repo.editor.write(
'file-to-modify.txt',
generateParagraphs('quux'),
),
repo.editor.write(
'foo/file-to-modify.txt',
generateParagraphs('blah'),
),
repo.editor.write(
'file-to-rename-and-modify.txt',
generateParagraphs('blahh'),
),
]);
await repo.git.raw(['add', '--all']);
await repo.git.raw(['commit', '-m', 'setup pre-import state']);
}
}

// author the changes that will be imported
{
await child.git.raw(['checkout', '-b', changeBranch]);
await Promise.all([
repo.editor.write('file-to-delete.txt', generateParagraphs('foo')),
repo.editor.write(
'some/dir/file-to-delete.txt',
generateParagraphs('bar'),
),
repo.editor.write('file-to-rename.txt', generateParagraphs('baz')),
repo.editor.write(
'foo/file-to-move.txt',
generateParagraphs('qux'),
),
repo.editor.write('file-to-modify.txt', generateParagraphs('quux')),
repo.editor.write(
'foo/file-to-modify.txt',
generateParagraphs('blah'),
),
repo.editor.write(
'file-to-rename-and-modify.txt',
generateParagraphs('blahh'),
child.editor.remove('file-to-delete.txt'),
child.editor.remove('some/dir/file-to-delete.txt'),
child.editor.move('file-to-rename.txt', 'file-renamed.txt'),
child.editor.move('foo/file-to-move.txt', 'file-moved.txt'),
]);
await child.git.raw(['add', '--all']);
await child.git.raw([
'commit',
'-m',
'do some changes',
'--author',
commitAuthor,
]);
await Promise.all([
child.editor.write('file-added.txt', generateParagraphs('blahhh')),
child.editor.write(
'foo/file-added.txt',
generateParagraphs('blahhhh'),
),
child.editor.removeLine('file-to-modify.txt', 0),
child.editor.removeLine('foo/file-to-modify.txt', 0),
child.editor.removeLine('file-to-rename-and-modify.txt', 0),
]);
await repo.git.raw(['add', '--all']);
await repo.git.raw(['commit', '-m', 'setup pre-import state']);
await child.editor.move(
'file-to-rename-and-modify.txt',
'file-renamed-and-modified.txt',
);
await child.git.raw(['add', '--all']);
await child.git.raw([
'commit',
'-m',
'do more changes',
'--author',
contribAuthor,
]);
await child.git.raw(['checkout', 'master']);
}
}

// author the changes that will be imported
{
await child.git.raw(['checkout', '-b', changeBranch]);
await Promise.all([
child.editor.remove('file-to-delete.txt'),
child.editor.remove('some/dir/file-to-delete.txt'),
child.editor.move('file-to-rename.txt', 'file-renamed.txt'),
child.editor.move('foo/file-to-move.txt', 'file-moved.txt'),
]);
await child.git.raw(['add', '--all']);
await child.git.raw([
'commit',
'-m',
'do some changes',
'--author',
commitAuthor,
]);
await Promise.all([
child.editor.write('file-added.txt', generateParagraphs('blahhh')),
child.editor.write(
'foo/file-added.txt',
generateParagraphs('blahhhh'),
),
child.editor.removeLine('file-to-modify.txt', 0),
child.editor.removeLine('foo/file-to-modify.txt', 0),
child.editor.removeLine('file-to-rename-and-modify.txt', 0),
]);
await child.editor.move(
'file-to-rename-and-modify.txt',
'file-renamed-and-modified.txt',
);
await child.git.raw(['add', '--all']);
await child.git.raw([
'commit',
'-m',
'do more changes',
'--author',
contribAuthor,
convertToRemote(parent.git.repoPath),
convertToRemote(child.git.repoPath),
]);
await child.git.raw(['checkout', 'master']);
}

await Promise.all([
convertToRemote(parent.git.repoPath),
convertToRemote(child.git.repoPath),
]);
}

// import changes
{
const usync = new USync(parentName);
const parentGit = new Git(parentName);
const childGit = new Git(childName);
const commitMessage = 'Make a bunch of changes';
// import changes
{
const usync = new USync(parentName);
const parentGit = new Git(parentName);
const childGit = new Git(childName);
const commitMessage = 'Make a bunch of changes';

await usync.import({
baseRepoName: childName,
headBranch: changeBranch,
message: commitMessage,
newBranch: `imports/${changeBranch}`,
});
await usync.import({
baseRepoName: childName,
headBranch: changeBranch,
message: commitMessage,
newBranch: `imports/${changeBranch}`,
});

await parentGit.raw(['checkout', `imports/${changeBranch}`]);
await childGit.raw(['checkout', changeBranch]);
await parentGit.raw(['checkout', `imports/${changeBranch}`]);
await childGit.raw(['checkout', changeBranch]);

expect(
await filesMatch(
childGit.repoPath,
path.join(parentGit.repoPath, subdir),
),
).toBe(true);
expect(
await parentGit.log([-1], {author: '%an <%ae>', message: '%B'}),
).toEqual([
{
author: commitAuthor,
message: `${commitMessage}\n\nCo-authored-by: ${contribAuthor}`,
},
]);
}
});
expect(
await filesMatch(
childGit.repoPath,
path.join(parentGit.repoPath, subdir),
),
).toBe(true);
expect(
await parentGit.log([-1], {author: '%an <%ae>', message: '%B'}),
).toEqual([
{
author: commitAuthor,
message: `${commitMessage}\n\nCo-authored-by: ${contribAuthor}`,
},
]);
}
},
10000,
);

test.concurrent('handles importing from a fork', async () => {
const parentName = 'foo/import-fork-parent';
Expand Down
3 changes: 3 additions & 0 deletions lib/git.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ class Git {
* @returns {Promise<string[]>} authors in `name <email>` format
*/
async getLogAuthors(logArgs) {
// exclude merge commits
if (!logArgs.includes('--no-merges')) logArgs.push('--no-merges');

const commits = await this.log(logArgs, {
authorEmail: '%ae',
authorName: '%an',
Expand Down
23 changes: 23 additions & 0 deletions lib/git.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,29 @@ test.concurrent('git.getLogAuthors()', async () => {
);
});

test.concurrent('git.getLogAuthors() excludes merge commits', async () => {
const {git} = await createFixture(TEMP_DIR);

// commit in second branch
await git.raw(['checkout', '-b', 'second-branch']);
await fse.writeFile(path.join(git.repoPath, 'bar.txt'), 'bar');
await git.raw(['add', 'bar.txt']);
await git.raw(['commit', '-m', 'add bar.txt']);
// commit in master
await git.raw(['checkout', 'master']);
await fse.writeFile(path.join(git.repoPath, 'baz.txt'), 'baz');
await git.raw(['add', 'baz.txt']);
await git.raw(['commit', '-m', 'add baz.txt']);
// now merge will generate merge commit
await git.raw(['config', 'user.name', 'Merge User']);
await git.raw(['config', 'user.email', '[email protected]']);
await git.raw(['merge', 'second-branch', '--no-edit']);

expect(await git.getLogAuthors([])).not.toContain(
'Merge User <[email protected]>',
);
});

test.concurrent('git.workdirIsClean()', async () => {
const {git} = await createFixture(TEMP_DIR);

Expand Down

0 comments on commit 36b090a

Please sign in to comment.