This repository was archived by the owner on Dec 15, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 406
Fix: git tab keeps popping open when there's a merge conflict #1822
Merged
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
804602f
do not ensureGitTabVisible everytime
vanessayuenn e8df0ea
All pull errors should pop the git tab open.
vanessayuenn 034afef
:fire: remove unused prop
vanessayuenn 516db46
remove merge conflict notification test from StatusBarTileController …
vanessayuenn fe8b345
ok maybe not.. i think we should keep the repo pipeline side effects …
vanessayuenn 5f318de
just remove test steps related to ensureGitTabVisible
vanessayuenn e313690
add getRepoPipelineManager tests
vanessayuenn d6ca9b6
push pipeline tests
vanessayuenn e8a0e11
async set-push-in-progress test
vanessayuenn 8aa1659
typo oops
vanessayuenn 060cb23
add barebone for tests to be implemented
vanessayuenn 1f4ef51
gitErrorStub helper method
vanessayuenn c3ab6d2
pull pipeline tests
vanessayuenn f13f390
fetch pipeline tests
vanessayuenn af3962b
fetch and checkout pipelines tests
vanessayuenn b99bbc4
addremote pipeline tests
vanessayuenn ec8dbe7
commit pipeline tests
vanessayuenn 2deb9f8
some clean up
vanessayuenn 9942199
moar cleanup
vanessayuenn 10dd118
Merge branch 'master' into vy/merge-conflict-pane
kuychaco d9875d4
Merge branch 'master' of github.com:atom/github into pr-1822/atom/vy/…
smashwilson File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -72,6 +72,7 @@ export default function({confirm, notificationManager, workspace}) { | |
return result; | ||
} catch (error) { | ||
if (error instanceof GitError) { | ||
repository.didPullError(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the reason for generalizing this from specifically merge errors to any pull errors? |
||
if (/error: Your local changes to the following files would be overwritten by merge/.test(error.stdErr)) { | ||
const lines = error.stdErr.split('\n'); | ||
const files = lines.slice(3, lines.length - 3).map(l => `\`${l.trim()}\``).join('\n'); | ||
|
@@ -82,7 +83,6 @@ export default function({confirm, notificationManager, workspace}) { | |
dismissable: true, | ||
}); | ||
} else if (/Automatic merge failed; fix conflicts and then commit the result./.test(error.stdOut)) { | ||
repository.didMergeError(); | ||
notificationManager.addWarning('Merge conflicts', { | ||
description: `Your local changes conflicted with changes made on the remote branch. Resolve the conflicts | ||
with the Git panel and commit to continue.`, | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,245 @@ | ||
import {cloneRepository, buildRepositoryWithPipeline} from './helpers'; | ||
import {GitError} from '../lib/git-shell-out-strategy'; | ||
|
||
|
||
describe('getRepoPipelineManager()', function() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for doing this 🙏 Go go gadget test coverage 📈 |
||
|
||
let atomEnv, workspace, notificationManager, repo, pipelineManager, confirm; | ||
|
||
const getPipeline = (pm, actionName) => { | ||
const actionKey = pm.actionKeys[actionName]; | ||
return pm.getPipeline(actionKey); | ||
}; | ||
|
||
const buildRepo = (workdir, override = {}) => { | ||
const option = { | ||
confirm, | ||
notificationManager, | ||
workspace, | ||
...override, | ||
}; | ||
return buildRepositoryWithPipeline(workdir, option); | ||
}; | ||
|
||
const gitErrorStub = (stdErr = '', stdOut = '') => { | ||
return sinon.stub().throws(() => { | ||
const err = new GitError(); | ||
err.stdErr = stdErr; | ||
err.stdOut = stdOut; | ||
return err; | ||
}); | ||
}; | ||
|
||
beforeEach(async function() { | ||
atomEnv = global.buildAtomEnvironment(); | ||
workspace = atomEnv.workspace; | ||
notificationManager = atomEnv.notifications; | ||
confirm = sinon.stub(atomEnv, 'confirm'); | ||
|
||
const workdir = await cloneRepository('multiple-commits'); | ||
repo = await buildRepo(workdir); | ||
pipelineManager = repo.pipelineManager; | ||
}); | ||
|
||
afterEach(function() { | ||
atomEnv.destroy(); | ||
}); | ||
|
||
it('has all the action pipelines', function() { | ||
const expectedActions = ['PUSH', 'PULL', 'FETCH', 'COMMIT', 'CHECKOUT', 'ADDREMOTE']; | ||
for (const actionName of expectedActions) { | ||
assert.ok(getPipeline(pipelineManager, actionName)); | ||
} | ||
}); | ||
|
||
describe('PUSH pipeline', function() { | ||
|
||
it('confirm-force-push', function() { | ||
it('before confirming', function() { | ||
const pushPipeline = getPipeline(pipelineManager, 'PUSH'); | ||
const pushStub = sinon.stub(); | ||
sinon.spy(notificationManager, 'addError'); | ||
pushPipeline.run(pushStub, repo, '', {force: true}); | ||
assert.isTrue(confirm.calledWith({ | ||
message: 'Are you sure you want to force push?', | ||
detailedMessage: 'This operation could result in losing data on the remote.', | ||
buttons: ['Force Push', 'Cancel'], | ||
})); | ||
assert.isTrue(pushStub.called()); | ||
}); | ||
|
||
it('after confirming', async function() { | ||
const nWorkdir = await cloneRepository('multiple-commits'); | ||
const confirmStub = sinon.stub(atomEnv, 'confirm').return(0); | ||
const nRepo = buildRepo(nWorkdir, {confirm: confirmStub}); | ||
const pushPipeline = getPipeline(nRepo.pipelineManager, 'PUSH'); | ||
const pushStub = sinon.stub(); | ||
sinon.spy(notificationManager, 'addError'); | ||
|
||
pushPipeline.run(pushStub, repo, '', {force: true}); | ||
assert.isFalse(confirm.called); | ||
assert.isFalse(pushStub.called); | ||
}); | ||
}); | ||
|
||
it('set-push-in-progress', async function() { | ||
const pushPipeline = getPipeline(pipelineManager, 'PUSH'); | ||
const pushStub = sinon.stub().callsFake(() => { | ||
assert.isTrue(repo.getOperationStates().isPushInProgress()); | ||
return Promise.resolve(); | ||
}); | ||
pushPipeline.run(pushStub, repo, '', {}); | ||
assert.isTrue(pushStub.called); | ||
await assert.async.isFalse(repo.getOperationStates().isPushInProgress()); | ||
}); | ||
|
||
it('failed-to-push-error', function() { | ||
const pushPipeline = getPipeline(pipelineManager, 'PUSH'); | ||
sinon.spy(notificationManager, 'addError'); | ||
|
||
|
||
pushPipeline.run(gitErrorStub('rejected failed to push'), repo, '', {}); | ||
assert.isTrue(notificationManager.addError.calledWithMatch('Push rejected', {dismissable: true})); | ||
|
||
pushPipeline.run(gitErrorStub('something else'), repo, '', {}); | ||
assert.isTrue(notificationManager.addError.calledWithMatch('Unable to push', {dismissable: true})); | ||
}); | ||
}); | ||
|
||
describe('PULL pipeline', function() { | ||
it('set-pull-in-progress', async function() { | ||
const pull = getPipeline(pipelineManager, 'PULL'); | ||
const pullStub = sinon.stub().callsFake(() => { | ||
assert.isTrue(repo.getOperationStates().isPullInProgress()); | ||
return Promise.resolve(); | ||
}); | ||
pull.run(pullStub, repo, '', {}); | ||
assert.isTrue(pullStub.called); | ||
await assert.async.isFalse(repo.getOperationStates().isPullInProgress()); | ||
}); | ||
|
||
it('failed-to-pull-error', function() { | ||
const pullPipeline = getPipeline(pipelineManager, 'PULL'); | ||
sinon.spy(notificationManager, 'addError'); | ||
sinon.spy(notificationManager, 'addWarning'); | ||
|
||
pullPipeline.run(gitErrorStub('error: Your local changes to the following files would be overwritten by merge:\n\ta.txt\n\tb.txt'), repo, '', {}); | ||
assert.isTrue(notificationManager.addError.calledWithMatch('Pull aborted', {dismissable: true})); | ||
|
||
pullPipeline.run(gitErrorStub('', 'Automatic merge failed; fix conflicts and then commit the result.'), repo, '', {}); | ||
assert.isTrue(notificationManager.addWarning.calledWithMatch('Merge conflicts', {dismissable: true})); | ||
|
||
pullPipeline.run(gitErrorStub('fatal: Not possible to fast-forward, aborting.'), repo, '', {}); | ||
assert.isTrue(notificationManager.addWarning.calledWithMatch('Unmerged changes', {dismissable: true})); | ||
|
||
pullPipeline.run(gitErrorStub('something else'), repo, '', {}); | ||
assert.isTrue(notificationManager.addError.calledWithMatch('Unable to pull', {dismissable: true})); | ||
}); | ||
}); | ||
|
||
describe('FETCH pipeline', function() { | ||
let fetchPipeline; | ||
|
||
beforeEach(function() { | ||
fetchPipeline = getPipeline(pipelineManager, 'FETCH'); | ||
}); | ||
|
||
it('set-fetch-in-progress', async function() { | ||
const fetchStub = sinon.stub().callsFake(() => { | ||
assert.isTrue(repo.getOperationStates().isFetchInProgress()); | ||
return Promise.resolve(); | ||
}); | ||
fetchPipeline.run(fetchStub, repo, '', {}); | ||
assert.isTrue(fetchStub.called); | ||
await assert.async.isFalse(repo.getOperationStates().isFetchInProgress()); | ||
}); | ||
|
||
it('failed-to-fetch-error', function() { | ||
sinon.spy(notificationManager, 'addError'); | ||
|
||
fetchPipeline.run(gitErrorStub('this is a nice error msg'), repo, '', {}); | ||
assert.isTrue(notificationManager.addError.calledWithMatch('Unable to fetch', { | ||
detail: 'this is a nice error msg', | ||
dismissable: true, | ||
})); | ||
}); | ||
}); | ||
|
||
describe('CHECKOUT pipeline', function() { | ||
let checkoutPipeline; | ||
|
||
beforeEach(function() { | ||
checkoutPipeline = getPipeline(pipelineManager, 'CHECKOUT'); | ||
}); | ||
|
||
it('set-checkout-in-progress', async function() { | ||
const checkoutStub = sinon.stub().callsFake(() => { | ||
assert.isTrue(repo.getOperationStates().isCheckoutInProgress()); | ||
return Promise.resolve(); | ||
}); | ||
checkoutPipeline.run(checkoutStub, repo, '', {}); | ||
assert.isTrue(checkoutStub.called); | ||
await assert.async.isFalse(repo.getOperationStates().isCheckoutInProgress()); | ||
}); | ||
|
||
it('failed-to-checkout-error', function() { | ||
sinon.spy(notificationManager, 'addError'); | ||
|
||
checkoutPipeline.run(gitErrorStub('local changes would be overwritten: \n\ta.txt\n\tb.txt'), repo, '', {createNew: false}); | ||
assert.isTrue(notificationManager.addError.calledWithMatch('Checkout aborted', {dismissable: true})); | ||
|
||
checkoutPipeline.run(gitErrorStub('branch x already exists'), repo, '', {createNew: false}); | ||
assert.isTrue(notificationManager.addError.calledWithMatch('Checkout aborted', {dismissable: true})); | ||
|
||
checkoutPipeline.run(gitErrorStub('error: you need to resolve your current index first'), repo, '', {createNew: false}); | ||
assert.isTrue(notificationManager.addError.calledWithMatch('Checkout aborted', {dismissable: true})); | ||
|
||
checkoutPipeline.run(gitErrorStub('something else'), repo, '', {createNew: true}); | ||
assert.isTrue(notificationManager.addError.calledWithMatch('Cannot create branch', {detail: 'something else', dismissable: true})); | ||
}); | ||
}); | ||
|
||
describe('COMMIT pipeline', function() { | ||
let commitPipeline; | ||
|
||
beforeEach(function() { | ||
commitPipeline = getPipeline(pipelineManager, 'COMMIT'); | ||
}); | ||
|
||
it('set-commit-in-progress', async function() { | ||
const commitStub = sinon.stub().callsFake(() => { | ||
assert.isTrue(repo.getOperationStates().isCommitInProgress()); | ||
return Promise.resolve(); | ||
}); | ||
commitPipeline.run(commitStub, repo, '', {}); | ||
assert.isTrue(commitStub.called); | ||
await assert.async.isFalse(repo.getOperationStates().isCommitInProgress()); | ||
}); | ||
|
||
it('failed-to-commit-error', function() { | ||
sinon.spy(notificationManager, 'addError'); | ||
|
||
commitPipeline.run(gitErrorStub('a nice msg'), repo, '', {}); | ||
assert.isTrue(notificationManager.addError.calledWithMatch('Unable to commit', {detail: 'a nice msg', dismissable: true})); | ||
}); | ||
}); | ||
|
||
describe('ADDREMOTE pipeline', function() { | ||
it('failed-to-add-remote', function() { | ||
const addRemotePipeline = getPipeline(pipelineManager, 'ADDREMOTE'); | ||
sinon.spy(notificationManager, 'addError'); | ||
|
||
addRemotePipeline.run(gitErrorStub('fatal: remote x already exists.'), repo, 'existential-crisis'); | ||
assert.isTrue(notificationManager.addError.calledWithMatch('Cannot create remote', { | ||
detail: 'The repository already contains a remote named existential-crisis.', | ||
dismissable: true, | ||
})); | ||
|
||
addRemotePipeline.run(gitErrorStub('something else'), repo, 'remotename'); | ||
assert.isTrue(notificationManager.addError.calledWithMatch('Cannot create remote', { | ||
detail: 'something else', | ||
dismissable: true, | ||
})); | ||
}); | ||
}); | ||
}); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍