diff --git a/diff/diff_test.go b/diff/diff_test.go index 442f0f4..6ce0571 100644 --- a/diff/diff_test.go +++ b/diff/diff_test.go @@ -388,6 +388,76 @@ func TestParseMultiFileDiffHeaders(t *testing.T) { }, }, }, + { + filename: "sample_binary_inline.diff", + wantDiffs: []*FileDiff{ + { + OrigName: "a/logo-old.png", + OrigTime: nil, + NewName: "/dev/null", + NewTime: nil, + Extended: []string{ + "diff --git a/logo-old.png b/logo-old.png", + "deleted file mode 100644", + "index d29d0e9757e0d9b854a8ed58f170bcb454cc1ae3..0000000000000000000000000000000000000000", + "GIT binary patch", + "literal 0", + "HcmV?d00001", + "", + "literal 0", + "HcmV?d00001", + "", + }, + }, + { + OrigName: "a/logo-old.png", + OrigTime: nil, + NewName: "b/logo-old.png", + NewTime: nil, + Extended: []string{ + "diff --git a/logo-old.png b/logo-old.png", + "index ff82e793467f2050d731d75b4968d2e6b9c5d33b..d29d0e9757e0d9b854a8ed58f170bcb454cc1ae3 100644", + "GIT binary patch", + "literal 0", + "HcmV?d00001", + "", + "literal 0", + "HcmV?d00001", + "", + }, + }, + { + OrigName: "a/logo.png", + OrigTime: nil, + NewName: "b/logo-old.png", + NewTime: nil, + Extended: []string{ + "diff --git a/logo.png b/logo-old.png", + "similarity index 100%", + "rename from logo.png", + "rename to logo-old.png", + }, + }, + { + OrigName: "/dev/null", + OrigTime: nil, + NewName: "b/logo.png", + NewTime: nil, + Extended: []string{ + "diff --git a/logo.png b/logo.png", + "new file mode 100644", + "index 0000000000000000000000000000000000000000..ff82e793467f2050d731d75b4968d2e6b9c5d33b", + "GIT binary patch", + "literal 0", + "HcmV?d00001", + "", + "literal 0", + "HcmV?d00001", + "", + }, + }, + }, + }, { filename: "sample_multi_file_new_win.diff", wantDiffs: []*FileDiff{ diff --git a/diff/parse.go b/diff/parse.go index f788e7e..08cba66 100644 --- a/diff/parse.go +++ b/diff/parse.go @@ -80,7 +80,7 @@ func (r *MultiFileDiffReader) ReadFile() (*FileDiff, error) { // need to perform the check here. hr := fr.HunksReader() line, err := readLine(r.reader) - if err != nil { + if err != nil && err != io.EOF { return fd, err } line = bytes.TrimSuffix(line, []byte{'\n'}) @@ -340,9 +340,13 @@ func (r *FileDiffReader) ReadExtendedHeaders() ([]string, error) { // that follow. It updates fd fields from the parsed extended headers. func handleEmpty(fd *FileDiff) (wasEmpty bool) { var err error + lineCount := len(fd.Extended) + if lineCount > 0 && !strings.HasPrefix(fd.Extended[0], "diff --git ") { + return false + } switch { - case (len(fd.Extended) == 3 || len(fd.Extended) == 4 && strings.HasPrefix(fd.Extended[3], "Binary files ")) && - strings.HasPrefix(fd.Extended[1], "new file mode ") && strings.HasPrefix(fd.Extended[0], "diff --git "): + case (lineCount == 3 || lineCount == 4 && strings.HasPrefix(fd.Extended[3], "Binary files ") || lineCount > 4 && strings.HasPrefix(fd.Extended[3], "GIT binary patch")) && + strings.HasPrefix(fd.Extended[1], "new file mode "): names := strings.SplitN(fd.Extended[0][len("diff --git "):], " ", 2) fd.OrigName = "/dev/null" @@ -351,8 +355,8 @@ func handleEmpty(fd *FileDiff) (wasEmpty bool) { fd.NewName = names[1] } return true - case (len(fd.Extended) == 3 || len(fd.Extended) == 4 && strings.HasPrefix(fd.Extended[3], "Binary files ")) && - strings.HasPrefix(fd.Extended[1], "deleted file mode ") && strings.HasPrefix(fd.Extended[0], "diff --git "): + case (lineCount == 3 || lineCount == 4 && strings.HasPrefix(fd.Extended[3], "Binary files ") || lineCount > 4 && strings.HasPrefix(fd.Extended[3], "GIT binary patch")) && + strings.HasPrefix(fd.Extended[1], "deleted file mode "): names := strings.SplitN(fd.Extended[0][len("diff --git "):], " ", 2) fd.OrigName, err = strconv.Unquote(names[0]) @@ -361,7 +365,7 @@ func handleEmpty(fd *FileDiff) (wasEmpty bool) { } fd.NewName = "/dev/null" return true - case len(fd.Extended) == 4 && strings.HasPrefix(fd.Extended[2], "rename from ") && strings.HasPrefix(fd.Extended[3], "rename to ") && strings.HasPrefix(fd.Extended[0], "diff --git "): + case lineCount == 4 && strings.HasPrefix(fd.Extended[2], "rename from ") && strings.HasPrefix(fd.Extended[3], "rename to "): names := strings.SplitN(fd.Extended[0][len("diff --git "):], " ", 2) fd.OrigName, err = strconv.Unquote(names[0]) if err != nil { @@ -372,7 +376,7 @@ func handleEmpty(fd *FileDiff) (wasEmpty bool) { fd.NewName = names[1] } return true - case len(fd.Extended) == 3 && strings.HasPrefix(fd.Extended[2], "Binary files ") && strings.HasPrefix(fd.Extended[0], "diff --git "): + case lineCount == 3 && strings.HasPrefix(fd.Extended[2], "Binary files ") || lineCount > 3 && strings.HasPrefix(fd.Extended[2], "GIT binary patch"): names := strings.SplitN(fd.Extended[0][len("diff --git "):], " ", 2) fd.OrigName, err = strconv.Unquote(names[0]) if err != nil { diff --git a/diff/testdata/sample_binary_inline.diff b/diff/testdata/sample_binary_inline.diff new file mode 100644 index 0000000..10fca65 --- /dev/null +++ b/diff/testdata/sample_binary_inline.diff @@ -0,0 +1,33 @@ +diff --git a/logo-old.png b/logo-old.png +deleted file mode 100644 +index d29d0e9757e0d9b854a8ed58f170bcb454cc1ae3..0000000000000000000000000000000000000000 +GIT binary patch +literal 0 +HcmV?d00001 + +literal 0 +HcmV?d00001 + +diff --git a/logo-old.png b/logo-old.png +index ff82e793467f2050d731d75b4968d2e6b9c5d33b..d29d0e9757e0d9b854a8ed58f170bcb454cc1ae3 100644 +GIT binary patch +literal 0 +HcmV?d00001 + +literal 0 +HcmV?d00001 + +diff --git a/logo.png b/logo-old.png +similarity index 100% +rename from logo.png +rename to logo-old.png +diff --git a/logo.png b/logo.png +new file mode 100644 +index 0000000000000000000000000000000000000000..ff82e793467f2050d731d75b4968d2e6b9c5d33b +GIT binary patch +literal 0 +HcmV?d00001 + +literal 0 +HcmV?d00001 +