Skip to content
This repository has been archived by the owner on Nov 8, 2017. It is now read-only.

Commit

Permalink
Fail gracefully for unterminated conflicts.
Browse files Browse the repository at this point in the history
  • Loading branch information
smashwilson committed Apr 25, 2016
1 parent 021910a commit b61a2ce
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 7 deletions.
28 changes: 21 additions & 7 deletions lib/conflict.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,22 @@ export class Conflict {
}

const visitor = new ConflictVisitor(merge, editor)
lastRow = parseConflict(merge, editor, conflictStartRow, visitor)
const conflict = visitor.conflict()

if (conflicts.length > 0) {
conflict.navigator.linkToPrevious(conflicts[conflicts.length - 1])
}
try {
lastRow = parseConflict(merge, editor, conflictStartRow, visitor)
const conflict = visitor.conflict()

if (conflicts.length > 0) {
conflict.navigator.linkToPrevious(conflicts[conflicts.length - 1])
}
conflicts.push(conflict)
} catch (e) {
if (!e.parserState) throw e

conflicts.push(conflict)
if (!atom.inSpecMode()) {
console.error(`Unable to parse conflict: ${e.message}\n${e.stack}`)
}
}
})

return conflicts
Expand Down Expand Up @@ -349,10 +357,16 @@ const parseConflict = function (merge, editor, row, visitor) {
// the editor.
const advanceToBoundary = (boundaryKinds = '<|=>') => {
let b = isAtBoundary(boundaryKinds)
while (b === null && row < editor.getLineCount()) {
while (b === null) {
row += 1
if (row > editor.getLastBufferRow()) {
const e = new Error('Unterminated conflict side')
e.parserState = true
throw e
}
b = isAtBoundary(boundaryKinds)
}

lastBoundary = b
return b
}
Expand Down
16 changes: 16 additions & 0 deletions spec/conflict-spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,22 @@ describe "Conflict", ->
expect(util.rowRangeFrom cs[1].ours.marker).toEqual([14, 15])
expect(util.rowRangeFrom cs[1].theirs.marker).toEqual([16, 17])

describe 'with corrupted diffs', ->

it 'handles corrupted diff output', ->
util.openPath 'corrupted-2way-diff.txt', (editorView) ->
cs = Conflict.all({}, editorView.getModel())
expect(cs.length).toBe(0)

it 'handles corrupted diff3 output', ->
util.openPath 'corrupted-3way-diff.txt', (editorView) ->
cs = Conflict.all({}, editorView.getModel())

expect(cs.length).toBe(1)
expect(util.rowRangeFrom cs[0].ours.marker).toEqual([13, 14])
expect(util.rowRangeFrom cs[0].base.marker).toEqual([15, 16])
expect(util.rowRangeFrom cs[0].theirs.marker).toEqual([17, 18])

describe 'when rebasing', ->
[conflict] = []

Expand Down
6 changes: 6 additions & 0 deletions spec/fixtures/corrupted-2way-diff.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<<<<<<< HEAD
These are my changes
=======
These are your changes

Oops, deleted the end marker.
21 changes: 21 additions & 0 deletions spec/fixtures/corrupted-3way-diff.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
This is a file containing a corrupted diff3 patch.

<<<<<<< HEAD
These are my changes
||||||| merged common ancestors
These are original texts
Oops, we never get a separator
These are your changes
>>>>>>> master

It also contains a valid one.

<<<<<<< HEAD
These are my changes
||||||| merged common ancestors
These are original texts
=======
These are your changes
>>>>>>> master

And some text after the end.

0 comments on commit b61a2ce

Please sign in to comment.