Skip to content

Commit

Permalink
Fix error with redundant line breaks
Browse files Browse the repository at this point in the history
This fixes an error with a repository, where an added file has \r\r\n
as line breaks. This interesting combination is handled as a single
line break by the diff operation, while Java's Scanner implementation
handles this as two lines (the first one delimited by the first \r,
the second one delimited by \r\n. This led to empty lines inside the
diff, where we only expect lines that contain at least one character
(' ', '+' or '-'), and this in turn led to an index out of bounds
exception.

Now we handle each combination of any kind of new line delimiter
characters as a single delimiter. This should be safe, because, as
mentioned earlier, we always expect at least one character in a line
for a diff output.
  • Loading branch information
pfeuffer committed May 4, 2020
1 parent ffcc146 commit 17b67f3
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 5 deletions.
Expand Up @@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package sonia.scm.repository.spi;

import sonia.scm.repository.api.DiffLine;
Expand Down Expand Up @@ -49,9 +49,9 @@ final class GitHunkParser {
public List<Hunk> parse(String content) {
List<Hunk> hunks = new ArrayList<>();

try (Scanner scanner = new Scanner(content)) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
try (Scanner scanner = new Scanner(content).useDelimiter("[\n\r\u2028\u2029\u0085]+")) {
while (scanner.hasNext()) {
String line = scanner.next();
if (line.startsWith("@@")) {
parseHeader(hunks, line);
} else if (currentGitHunk != null) {
Expand Down
Expand Up @@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package sonia.scm.repository.spi;

import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -103,6 +103,15 @@ class GitHunkParserTest {
"+added line\n" +
"\\ No newline at end of file\n";

private static final String MULTIPLE_LINE_BREAKS = "diff --git a/.editorconfig b/.editorconfig\n" +
"index ea2a3ba..2f02f32 100644\n" +
"--- a/.editorconfig\n" +
"+++ b/.editorconfig\n" +
"@@ -10,3 +10,4 @@\n" +
" indent_style = space\r\r\n" +
" indent_size = 2\r\r\n" +
" charset = utf-8\n";

@Test
void shouldParseHunks() {
List<Hunk> hunks = new GitHunkParser().parse(DIFF_001);
Expand Down Expand Up @@ -183,6 +192,24 @@ void shouldIgnoreNoNewlineLine() {
assertThat(lastLine.getContent()).isEqualTo("added line");
}

@Test
void shouldHandleMultipleLineBreaks() {
List<Hunk> hunks = new GitHunkParser().parse(MULTIPLE_LINE_BREAKS);

Hunk hunk = hunks.get(0);

Iterator<DiffLine> lines = hunk.iterator();

DiffLine line1 = lines.next();
assertThat(line1.getOldLineNumber()).hasValue(10);
assertThat(line1.getNewLineNumber()).hasValue(10);
assertThat(line1.getContent()).isEqualTo("indent_style = space");

lines.next();
lines.next();
assertThat(lines.hasNext()).isFalse();
}

private void assertHunk(Hunk hunk, int oldStart, int oldLineCount, int newStart, int newLineCount) {
assertThat(hunk.getOldStart()).isEqualTo(oldStart);
assertThat(hunk.getOldLineCount()).isEqualTo(oldLineCount);
Expand Down

0 comments on commit 17b67f3

Please sign in to comment.