From e4ed0342932b0aa741ee78d9e4fe135eba6e9ca7 Mon Sep 17 00:00:00 2001 From: mo khan Date: Fri, 30 Jan 2026 17:18:31 -0700 Subject: initial commit --- pkg/gitdiff/README.md | 1 - pkg/gitdiff/apply_test.go | 235 ------- pkg/gitdiff/assert_test.go | 30 - pkg/gitdiff/base85_test.go | 118 ---- pkg/gitdiff/binary_test.go | 324 --------- pkg/gitdiff/file_header_test.go | 766 --------------------- pkg/gitdiff/format_roundtrip_test.go | 157 ----- pkg/gitdiff/format_test.go | 28 - pkg/gitdiff/gitdiff_test.go | 161 ----- pkg/gitdiff/io_test.go | 254 ------- pkg/gitdiff/parser_test.go | 511 -------------- pkg/gitdiff/patch_header_test.go | 590 ---------------- pkg/gitdiff/patch_identity_test.go | 127 ---- pkg/gitdiff/testdata/apply/bin.go | 124 ---- .../testdata/apply/bin_fragment_delta_error.src | Bin 130 -> 0 bytes .../apply/bin_fragment_delta_error_dst_size.patch | 5 - .../bin_fragment_delta_error_incomplete_add.patch | 5 - .../bin_fragment_delta_error_incomplete_copy.patch | 5 - .../apply/bin_fragment_delta_error_src_size.patch | 5 - .../testdata/apply/bin_fragment_delta_modify.out | Bin 1084 -> 0 bytes .../testdata/apply/bin_fragment_delta_modify.patch | 13 - .../testdata/apply/bin_fragment_delta_modify.src | Bin 1024 -> 0 bytes .../apply/bin_fragment_delta_modify_large.out | Bin 131072 -> 0 bytes .../apply/bin_fragment_delta_modify_large.patch | 166 ----- .../apply/bin_fragment_delta_modify_large.src | Bin 131072 -> 0 bytes .../testdata/apply/bin_fragment_literal_create.out | Bin 32 -> 0 bytes .../apply/bin_fragment_literal_create.patch | 8 - .../testdata/apply/bin_fragment_literal_create.src | 0 .../testdata/apply/bin_fragment_literal_modify.out | Bin 32 -> 0 bytes .../apply/bin_fragment_literal_modify.patch | 8 - .../testdata/apply/bin_fragment_literal_modify.src | Bin 32 -> 0 bytes pkg/gitdiff/testdata/apply/file_bin_modify.out | Bin 1084 -> 0 bytes pkg/gitdiff/testdata/apply/file_bin_modify.patch | 13 - pkg/gitdiff/testdata/apply/file_bin_modify.src | Bin 1024 -> 0 bytes pkg/gitdiff/testdata/apply/file_mode_change.out | 2 - pkg/gitdiff/testdata/apply/file_mode_change.patch | 3 - pkg/gitdiff/testdata/apply/file_mode_change.src | 2 - pkg/gitdiff/testdata/apply/file_text.src | 200 ------ pkg/gitdiff/testdata/apply/file_text_delete.out | 0 pkg/gitdiff/testdata/apply/file_text_delete.patch | 206 ------ .../apply/file_text_error_partial_delete.patch | 106 --- pkg/gitdiff/testdata/apply/file_text_modify.out | 195 ------ pkg/gitdiff/testdata/apply/file_text_modify.patch | 62 -- .../testdata/apply/text_fragment_add_end.out | 5 - .../testdata/apply/text_fragment_add_end.patch | 9 - .../testdata/apply/text_fragment_add_end.src | 3 - .../testdata/apply/text_fragment_add_end_noeol.out | 5 - .../apply/text_fragment_add_end_noeol.patch | 11 - .../testdata/apply/text_fragment_add_end_noeol.src | 3 - .../testdata/apply/text_fragment_add_middle.out | 5 - .../testdata/apply/text_fragment_add_middle.patch | 9 - .../testdata/apply/text_fragment_add_middle.src | 3 - .../testdata/apply/text_fragment_add_start.out | 4 - .../testdata/apply/text_fragment_add_start.patch | 8 - .../testdata/apply/text_fragment_add_start.src | 3 - .../testdata/apply/text_fragment_change_end.out | 10 - .../testdata/apply/text_fragment_change_end.patch | 9 - .../testdata/apply/text_fragment_change_end.src | 10 - .../apply/text_fragment_change_end_eol.out | 3 - .../apply/text_fragment_change_end_eol.patch | 10 - .../apply/text_fragment_change_end_eol.src | 3 - .../testdata/apply/text_fragment_change_exact.out | 19 - .../apply/text_fragment_change_exact.patch | 12 - .../testdata/apply/text_fragment_change_exact.src | 30 - .../testdata/apply/text_fragment_change_middle.out | 9 - .../apply/text_fragment_change_middle.patch | 12 - .../testdata/apply/text_fragment_change_middle.src | 10 - .../apply/text_fragment_change_single_noeol.out | 1 - .../apply/text_fragment_change_single_noeol.patch | 8 - .../apply/text_fragment_change_single_noeol.src | 1 - .../testdata/apply/text_fragment_change_start.out | 4 - .../apply/text_fragment_change_start.patch | 9 - .../testdata/apply/text_fragment_change_start.src | 10 - .../testdata/apply/text_fragment_delete_all.out | 0 .../testdata/apply/text_fragment_delete_all.patch | 8 - .../testdata/apply/text_fragment_delete_all.src | 4 - pkg/gitdiff/testdata/apply/text_fragment_error.src | 13 - .../text_fragment_error_context_conflict.patch | 12 - .../text_fragment_error_delete_conflict.patch | 12 - .../apply/text_fragment_error_new_file.patch | 7 - .../apply/text_fragment_error_short_src.patch | 12 - .../text_fragment_error_short_src_before.patch | 12 - pkg/gitdiff/testdata/apply/text_fragment_new.out | 3 - pkg/gitdiff/testdata/apply/text_fragment_new.patch | 7 - pkg/gitdiff/testdata/apply/text_fragment_new.src | 0 pkg/gitdiff/testdata/new_binary_file.patch | 16 - pkg/gitdiff/testdata/no_files.patch | 8 - pkg/gitdiff/testdata/one_file.patch | 28 - pkg/gitdiff/testdata/string/binary_modify.patch | 9 - .../testdata/string/binary_modify_nodata.patch | 3 - pkg/gitdiff/testdata/string/binary_new.patch | 11 - pkg/gitdiff/testdata/string/copy.patch | 4 - pkg/gitdiff/testdata/string/copy_modify.patch | 21 - pkg/gitdiff/testdata/string/delete.patch | 16 - pkg/gitdiff/testdata/string/mode.patch | 3 - pkg/gitdiff/testdata/string/mode_modify.patch | 10 - pkg/gitdiff/testdata/string/modify.patch | 16 - pkg/gitdiff/testdata/string/new.patch | 16 - pkg/gitdiff/testdata/string/new_empty.patch | 3 - pkg/gitdiff/testdata/string/new_mode.patch | 16 - pkg/gitdiff/testdata/string/rename.patch | 4 - pkg/gitdiff/testdata/string/rename_modify.patch | 18 - pkg/gitdiff/testdata/two_files.patch | 48 -- pkg/gitdiff/text_test.go | 488 ------------- 104 files changed, 5496 deletions(-) delete mode 100644 pkg/gitdiff/README.md delete mode 100644 pkg/gitdiff/apply_test.go delete mode 100644 pkg/gitdiff/assert_test.go delete mode 100644 pkg/gitdiff/base85_test.go delete mode 100644 pkg/gitdiff/binary_test.go delete mode 100644 pkg/gitdiff/file_header_test.go delete mode 100644 pkg/gitdiff/format_roundtrip_test.go delete mode 100644 pkg/gitdiff/format_test.go delete mode 100644 pkg/gitdiff/gitdiff_test.go delete mode 100644 pkg/gitdiff/io_test.go delete mode 100644 pkg/gitdiff/parser_test.go delete mode 100644 pkg/gitdiff/patch_header_test.go delete mode 100644 pkg/gitdiff/patch_identity_test.go delete mode 100644 pkg/gitdiff/testdata/apply/bin.go delete mode 100644 pkg/gitdiff/testdata/apply/bin_fragment_delta_error.src delete mode 100644 pkg/gitdiff/testdata/apply/bin_fragment_delta_error_dst_size.patch delete mode 100644 pkg/gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_add.patch delete mode 100644 pkg/gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_copy.patch delete mode 100644 pkg/gitdiff/testdata/apply/bin_fragment_delta_error_src_size.patch delete mode 100644 pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.out delete mode 100644 pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.patch delete mode 100644 pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.src delete mode 100644 pkg/gitdiff/testdata/apply/bin_fragment_delta_modify_large.out delete mode 100644 pkg/gitdiff/testdata/apply/bin_fragment_delta_modify_large.patch delete mode 100644 pkg/gitdiff/testdata/apply/bin_fragment_delta_modify_large.src delete mode 100644 pkg/gitdiff/testdata/apply/bin_fragment_literal_create.out delete mode 100644 pkg/gitdiff/testdata/apply/bin_fragment_literal_create.patch delete mode 100644 pkg/gitdiff/testdata/apply/bin_fragment_literal_create.src delete mode 100644 pkg/gitdiff/testdata/apply/bin_fragment_literal_modify.out delete mode 100644 pkg/gitdiff/testdata/apply/bin_fragment_literal_modify.patch delete mode 100644 pkg/gitdiff/testdata/apply/bin_fragment_literal_modify.src delete mode 100644 pkg/gitdiff/testdata/apply/file_bin_modify.out delete mode 100644 pkg/gitdiff/testdata/apply/file_bin_modify.patch delete mode 100644 pkg/gitdiff/testdata/apply/file_bin_modify.src delete mode 100644 pkg/gitdiff/testdata/apply/file_mode_change.out delete mode 100644 pkg/gitdiff/testdata/apply/file_mode_change.patch delete mode 100644 pkg/gitdiff/testdata/apply/file_mode_change.src delete mode 100644 pkg/gitdiff/testdata/apply/file_text.src delete mode 100644 pkg/gitdiff/testdata/apply/file_text_delete.out delete mode 100644 pkg/gitdiff/testdata/apply/file_text_delete.patch delete mode 100644 pkg/gitdiff/testdata/apply/file_text_error_partial_delete.patch delete mode 100644 pkg/gitdiff/testdata/apply/file_text_modify.out delete mode 100644 pkg/gitdiff/testdata/apply/file_text_modify.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_add_end.out delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_add_end.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_add_end.src delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_add_end_noeol.out delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_add_end_noeol.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_add_end_noeol.src delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_add_middle.out delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_add_middle.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_add_middle.src delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_add_start.out delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_add_start.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_add_start.src delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_end.out delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_end.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_end.src delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_end_eol.out delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_end_eol.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_end_eol.src delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_exact.out delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_exact.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_exact.src delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_middle.out delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_middle.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_middle.src delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_single_noeol.out delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_single_noeol.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_single_noeol.src delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_start.out delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_start.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_change_start.src delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_delete_all.out delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_delete_all.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_delete_all.src delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_error.src delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_error_context_conflict.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_error_delete_conflict.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_error_new_file.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_error_short_src.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_error_short_src_before.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_new.out delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_new.patch delete mode 100644 pkg/gitdiff/testdata/apply/text_fragment_new.src delete mode 100644 pkg/gitdiff/testdata/new_binary_file.patch delete mode 100644 pkg/gitdiff/testdata/no_files.patch delete mode 100644 pkg/gitdiff/testdata/one_file.patch delete mode 100644 pkg/gitdiff/testdata/string/binary_modify.patch delete mode 100644 pkg/gitdiff/testdata/string/binary_modify_nodata.patch delete mode 100644 pkg/gitdiff/testdata/string/binary_new.patch delete mode 100644 pkg/gitdiff/testdata/string/copy.patch delete mode 100644 pkg/gitdiff/testdata/string/copy_modify.patch delete mode 100644 pkg/gitdiff/testdata/string/delete.patch delete mode 100644 pkg/gitdiff/testdata/string/mode.patch delete mode 100644 pkg/gitdiff/testdata/string/mode_modify.patch delete mode 100644 pkg/gitdiff/testdata/string/modify.patch delete mode 100644 pkg/gitdiff/testdata/string/new.patch delete mode 100644 pkg/gitdiff/testdata/string/new_empty.patch delete mode 100644 pkg/gitdiff/testdata/string/new_mode.patch delete mode 100644 pkg/gitdiff/testdata/string/rename.patch delete mode 100644 pkg/gitdiff/testdata/string/rename_modify.patch delete mode 100644 pkg/gitdiff/testdata/two_files.patch delete mode 100644 pkg/gitdiff/text_test.go (limited to 'pkg/gitdiff') diff --git a/pkg/gitdiff/README.md b/pkg/gitdiff/README.md deleted file mode 100644 index 974bb70..0000000 --- a/pkg/gitdiff/README.md +++ /dev/null @@ -1 +0,0 @@ -This is a vendored copy of the [bluekeyes/go-gitdiff](https://github.com/bluekeyes/go-gitdiff) package. diff --git a/pkg/gitdiff/apply_test.go b/pkg/gitdiff/apply_test.go deleted file mode 100644 index 05915ba..0000000 --- a/pkg/gitdiff/apply_test.go +++ /dev/null @@ -1,235 +0,0 @@ -package gitdiff - -import ( - "bytes" - "errors" - "io" - "io/ioutil" - "path/filepath" - "testing" -) - -func TestApplyTextFragment(t *testing.T) { - tests := map[string]applyTest{ - "createFile": {Files: getApplyFiles("text_fragment_new")}, - "deleteFile": {Files: getApplyFiles("text_fragment_delete_all")}, - - "addStart": {Files: getApplyFiles("text_fragment_add_start")}, - "addMiddle": {Files: getApplyFiles("text_fragment_add_middle")}, - "addEnd": {Files: getApplyFiles("text_fragment_add_end")}, - "addEndNoEOL": {Files: getApplyFiles("text_fragment_add_end_noeol")}, - - "changeStart": {Files: getApplyFiles("text_fragment_change_start")}, - "changeMiddle": {Files: getApplyFiles("text_fragment_change_middle")}, - "changeEnd": {Files: getApplyFiles("text_fragment_change_end")}, - "changeEndEOL": {Files: getApplyFiles("text_fragment_change_end_eol")}, - "changeExact": {Files: getApplyFiles("text_fragment_change_exact")}, - "changeSingleNoEOL": {Files: getApplyFiles("text_fragment_change_single_noeol")}, - - "errorShortSrcBefore": { - Files: applyFiles{ - Src: "text_fragment_error.src", - Patch: "text_fragment_error_short_src_before.patch", - }, - Err: &Conflict{}, - }, - "errorShortSrc": { - Files: applyFiles{ - Src: "text_fragment_error.src", - Patch: "text_fragment_error_short_src.patch", - }, - Err: &Conflict{}, - }, - "errorContextConflict": { - Files: applyFiles{ - Src: "text_fragment_error.src", - Patch: "text_fragment_error_context_conflict.patch", - }, - Err: &Conflict{}, - }, - "errorDeleteConflict": { - Files: applyFiles{ - Src: "text_fragment_error.src", - Patch: "text_fragment_error_delete_conflict.patch", - }, - Err: &Conflict{}, - }, - "errorNewFile": { - Files: applyFiles{ - Src: "text_fragment_error.src", - Patch: "text_fragment_error_new_file.patch", - }, - Err: &Conflict{}, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - test.run(t, func(dst io.Writer, src io.ReaderAt, file *File) error { - if len(file.TextFragments) != 1 { - t.Fatalf("patch should contain exactly one fragment, but it has %d", len(file.TextFragments)) - } - applier := NewTextApplier(dst, src) - return applier.ApplyFragment(file.TextFragments[0]) - }) - }) - } -} - -func TestApplyBinaryFragment(t *testing.T) { - tests := map[string]applyTest{ - "literalCreate": {Files: getApplyFiles("bin_fragment_literal_create")}, - "literalModify": {Files: getApplyFiles("bin_fragment_literal_modify")}, - "deltaModify": {Files: getApplyFiles("bin_fragment_delta_modify")}, - "deltaModifyLarge": {Files: getApplyFiles("bin_fragment_delta_modify_large")}, - - "errorIncompleteAdd": { - Files: applyFiles{ - Src: "bin_fragment_delta_error.src", - Patch: "bin_fragment_delta_error_incomplete_add.patch", - }, - Err: "incomplete add", - }, - "errorIncompleteCopy": { - Files: applyFiles{ - Src: "bin_fragment_delta_error.src", - Patch: "bin_fragment_delta_error_incomplete_copy.patch", - }, - Err: "incomplete copy", - }, - "errorSrcSize": { - Files: applyFiles{ - Src: "bin_fragment_delta_error.src", - Patch: "bin_fragment_delta_error_src_size.patch", - }, - Err: &Conflict{}, - }, - "errorDstSize": { - Files: applyFiles{ - Src: "bin_fragment_delta_error.src", - Patch: "bin_fragment_delta_error_dst_size.patch", - }, - Err: "insufficient or extra data", - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - test.run(t, func(dst io.Writer, src io.ReaderAt, file *File) error { - applier := NewBinaryApplier(dst, src) - return applier.ApplyFragment(file.BinaryFragment) - }) - }) - } -} - -func TestApplyFile(t *testing.T) { - tests := map[string]applyTest{ - "textModify": { - Files: applyFiles{ - Src: "file_text.src", - Patch: "file_text_modify.patch", - Out: "file_text_modify.out", - }, - }, - "textDelete": { - Files: applyFiles{ - Src: "file_text.src", - Patch: "file_text_delete.patch", - Out: "file_text_delete.out", - }, - }, - "textErrorPartialDelete": { - Files: applyFiles{ - Src: "file_text.src", - Patch: "file_text_error_partial_delete.patch", - }, - Err: &Conflict{}, - }, - "binaryModify": { - Files: getApplyFiles("file_bin_modify"), - }, - "modeChange": { - Files: getApplyFiles("file_mode_change"), - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - test.run(t, func(dst io.Writer, src io.ReaderAt, file *File) error { - return Apply(dst, src, file) - }) - }) - } -} - -type applyTest struct { - Files applyFiles - Err interface{} -} - -func (at applyTest) run(t *testing.T, apply func(io.Writer, io.ReaderAt, *File) error) { - src, patch, out := at.Files.Load(t) - - files, _, err := Parse(bytes.NewReader(patch)) - if err != nil { - t.Fatalf("failed to parse patch file: %v", err) - } - if len(files) != 1 { - t.Fatalf("patch should contain exactly one file, but it has %d", len(files)) - } - - var dst bytes.Buffer - err = apply(&dst, bytes.NewReader(src), files[0]) - if at.Err != nil { - assertError(t, at.Err, err, "applying fragment") - return - } - if err != nil { - var aerr *ApplyError - if errors.As(err, &aerr) { - t.Fatalf("unexpected error applying: at %d: fragment %d at %d: %v", aerr.Line, aerr.Fragment, aerr.FragmentLine, err) - } else { - t.Fatalf("unexpected error applying: %v", err) - } - } - - if !bytes.Equal(out, dst.Bytes()) { - t.Errorf("incorrect result after apply\nexpected:\n%q\nactual:\n%q", out, dst.Bytes()) - } -} - -type applyFiles struct { - Src string - Patch string - Out string -} - -func getApplyFiles(name string) applyFiles { - return applyFiles{ - Src: name + ".src", - Patch: name + ".patch", - Out: name + ".out", - } -} - -func (f applyFiles) Load(t *testing.T) (src []byte, patch []byte, out []byte) { - load := func(name, kind string) []byte { - d, err := ioutil.ReadFile(filepath.Join("testdata", "apply", name)) - if err != nil { - t.Fatalf("failed to read %s file: %v", kind, err) - } - return d - } - - if f.Src != "" { - src = load(f.Src, "source") - } - if f.Patch != "" { - patch = load(f.Patch, "patch") - } - if f.Out != "" { - out = load(f.Out, "output") - } - return -} diff --git a/pkg/gitdiff/assert_test.go b/pkg/gitdiff/assert_test.go deleted file mode 100644 index 878f13c..0000000 --- a/pkg/gitdiff/assert_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package gitdiff - -import ( - "errors" - "strings" - "testing" -) - -func assertError(t *testing.T, expected interface{}, actual error, action string) { - if actual == nil { - t.Fatalf("expected error %s, but got nil", action) - } - - switch exp := expected.(type) { - case bool: - if !exp { - t.Fatalf("unexpected error %s: %v", action, actual) - } - case string: - if !strings.Contains(actual.Error(), exp) { - t.Fatalf("incorrect error %s: %q does not contain %q", action, actual.Error(), exp) - } - case error: - if !errors.Is(actual, exp) { - t.Fatalf("incorrect error %s: expected %T (%v), actual: %T (%v)", action, exp, exp, actual, actual) - } - default: - t.Fatalf("unsupported expected error type: %T", exp) - } -} diff --git a/pkg/gitdiff/base85_test.go b/pkg/gitdiff/base85_test.go deleted file mode 100644 index 672c471..0000000 --- a/pkg/gitdiff/base85_test.go +++ /dev/null @@ -1,118 +0,0 @@ -package gitdiff - -import ( - "bytes" - "testing" -) - -func TestBase85Decode(t *testing.T) { - tests := map[string]struct { - Input string - Output []byte - Err bool - }{ - "twoBytes": { - Input: "%KiWV", - Output: []byte{0xCA, 0xFE}, - }, - "fourBytes": { - Input: "007GV", - Output: []byte{0x0, 0x0, 0xCA, 0xFE}, - }, - "sixBytes": { - Input: "007GV%KiWV", - Output: []byte{0x0, 0x0, 0xCA, 0xFE, 0xCA, 0xFE}, - }, - "invalidCharacter": { - Input: "00'GV", - Err: true, - }, - "underpaddedSequence": { - Input: "007G", - Err: true, - }, - "dataUnderrun": { - Input: "007GV", - Output: make([]byte, 8), - Err: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - dst := make([]byte, len(test.Output)) - err := base85Decode(dst, []byte(test.Input)) - if test.Err { - if err == nil { - t.Fatalf("expected error decoding base85 data, but got nil") - } - return - } - if err != nil { - t.Fatalf("unexpected error decoding base85 data: %v", err) - } - for i, b := range test.Output { - if dst[i] != b { - t.Errorf("incorrect byte at index %d: expected 0x%X, actual 0x%X", i, b, dst[i]) - } - } - }) - } -} - -func TestBase85Encode(t *testing.T) { - tests := map[string]struct { - Input []byte - Output string - }{ - "zeroBytes": { - Input: []byte{}, - Output: "", - }, - "twoBytes": { - Input: []byte{0xCA, 0xFE}, - Output: "%KiWV", - }, - "fourBytes": { - Input: []byte{0x0, 0x0, 0xCA, 0xFE}, - Output: "007GV", - }, - "sixBytes": { - Input: []byte{0x0, 0x0, 0xCA, 0xFE, 0xCA, 0xFE}, - Output: "007GV%KiWV", - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - dst := make([]byte, len(test.Output)) - base85Encode(dst, test.Input) - for i, b := range test.Output { - if dst[i] != byte(b) { - t.Errorf("incorrect character at index %d: expected '%c', actual '%c'", i, b, dst[i]) - } - } - }) - } -} - -func FuzzBase85Roundtrip(f *testing.F) { - f.Add([]byte{0x2b, 0x0d}) - f.Add([]byte{0xbc, 0xb4, 0x3f}) - f.Add([]byte{0xfa, 0x62, 0x05, 0x83, 0x24, 0x39, 0xd5, 0x25}) - f.Add([]byte{0x31, 0x59, 0x02, 0xa0, 0x61, 0x12, 0xd9, 0x43, 0xb8, 0x23, 0x1a, 0xb4, 0x02, 0xae, 0xfa, 0xcc, 0x22, 0xad, 0x41, 0xb9, 0xb8}) - - f.Fuzz(func(t *testing.T, in []byte) { - n := len(in) - dst := make([]byte, base85Len(n)) - out := make([]byte, n) - - base85Encode(dst, in) - if err := base85Decode(out, dst); err != nil { - t.Fatalf("unexpected error decoding base85 data: %v", err) - } - if !bytes.Equal(in, out) { - t.Errorf("decoded data differed from input data:\n input: %x\n output: %x\nencoding: %s\n", in, out, string(dst)) - } - }) -} diff --git a/pkg/gitdiff/binary_test.go b/pkg/gitdiff/binary_test.go deleted file mode 100644 index 64db243..0000000 --- a/pkg/gitdiff/binary_test.go +++ /dev/null @@ -1,324 +0,0 @@ -package gitdiff - -import ( - "encoding/binary" - "io" - "reflect" - "strings" - "testing" -) - -func TestParseBinaryMarker(t *testing.T) { - tests := map[string]struct { - Input string - IsBinary bool - HasData bool - Err bool - }{ - "binaryPatch": { - Input: "GIT binary patch\n", - IsBinary: true, - HasData: true, - }, - "binaryFileNoPatch": { - Input: "Binary files differ\n", - IsBinary: true, - HasData: false, - }, - "binaryFileNoPatchPaths": { - Input: "Binary files a/foo.bin and b/foo.bin differ\n", - IsBinary: true, - HasData: false, - }, - "fileNoPatch": { - Input: "Files differ\n", - IsBinary: true, - HasData: false, - }, - "textFile": { - Input: "@@ -10,14 +22,31 @@\n", - IsBinary: false, - HasData: false, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - p := newTestParser(test.Input, true) - - isBinary, hasData, err := p.ParseBinaryMarker() - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing binary marker, but got %v", err) - } - return - } - if err != nil { - t.Fatalf("unexpected error parsing binary marker: %v", err) - } - if test.IsBinary != isBinary { - t.Errorf("incorrect isBinary value: expected %t, actual %t", test.IsBinary, isBinary) - } - if test.HasData != hasData { - t.Errorf("incorrect hasData value: expected %t, actual %t", test.HasData, hasData) - } - }) - } -} - -func TestParseBinaryFragmentHeader(t *testing.T) { - tests := map[string]struct { - Input string - Output *BinaryFragment - Err bool - }{ - "delta": { - Input: "delta 1234\n", - Output: &BinaryFragment{ - Method: BinaryPatchDelta, - Size: 1234, - }, - }, - "literal": { - Input: "literal 1234\n", - Output: &BinaryFragment{ - Method: BinaryPatchLiteral, - Size: 1234, - }, - }, - "unknownMethod": { - Input: "compressed 1234\n", - Output: nil, - }, - "notAHeader": { - Input: "Binary files differ\n", - Output: nil, - }, - "invalidSize": { - Input: "delta 123abc\n", - Err: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - p := newTestParser(test.Input, true) - - frag, err := p.ParseBinaryFragmentHeader() - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing binary header, but got %v", err) - } - return - } - if err != nil { - t.Fatalf("unexpected error parsing binary header: %v", err) - } - if !reflect.DeepEqual(test.Output, frag) { - t.Errorf("incorrect binary fragment\nexpected: %+v\n actual: %+v", test.Output, frag) - } - }) - } -} - -func TestParseBinaryChunk(t *testing.T) { - tests := map[string]struct { - Input string - Fragment BinaryFragment - Output []byte - Err string - }{ - "singleline": { - Input: "TcmZQzU|?i`U?w2V48*Je09XJG\n\n", - Fragment: BinaryFragment{ - Size: 20, - }, - Output: fib(5, binary.BigEndian), - }, - "multiline": { - Input: "zcmZQzU|?i`U?w2V48*KJ%mKu_Kr9NxNf->s?WfX|B-=Vs{#X~svra7Ekg#T|4s}nH;WnAZ)|1Y*`&cB\n" + - "s(sh?X(Uz6L^!Ou&aF*u`J!eibJifSrv0z>$Q%Hd(^HIJ -Date: Tue Apr 2 22:30:00 2019 -0700 - - This is a sample commit message. - -diff --git a/file.txt b/file.txt -index cc34da1..1acbae5 100644 ---- a/file.txt -+++ b/file.txt -@@ -1,3 +1,4 @@ -`, - Output: &File{ - OldName: "file.txt", - NewName: "file.txt", - OldMode: os.FileMode(0100644), - OldOIDPrefix: "cc34da1", - NewOIDPrefix: "1acbae5", - }, - Preamble: `commit 1acbae563cd6ef5750a82ee64e116c6eb065cb94 -Author: Morton Haypenny -Date: Tue Apr 2 22:30:00 2019 -0700 - - This is a sample commit message. - -`, - }, - "traditionalHeader": { - Input: ` ---- file.txt 2019-04-01 22:58:14.833597918 -0700 -+++ file.txt 2019-04-01 22:58:14.833597918 -0700 -@@ -1,3 +1,4 @@ -`, - Output: &File{ - OldName: "file.txt", - NewName: "file.txt", - }, - Preamble: "\n", - }, - "noHeaders": { - Input: ` -this is a line -this is another line ---- could this be a header? -nope, it's just some dashes -`, - Output: nil, - Preamble: ` -this is a line -this is another line ---- could this be a header? -nope, it's just some dashes -`, - }, - "detatchedFragmentLike": { - Input: ` -a wild fragment appears? -@@ -1,3 +1,4 ~1,5 @@ -`, - Output: nil, - Preamble: ` -a wild fragment appears? -@@ -1,3 +1,4 ~1,5 @@ -`, - }, - "detatchedFragment": { - Input: ` -a wild fragment appears? -@@ -1,3 +1,4 @@ -`, - Err: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - p := newTestParser(test.Input, true) - - f, pre, err := p.ParseNextFileHeader() - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing next file header, but got %v", err) - } - return - } - if err != nil { - t.Fatalf("unexpected error parsing next file header: %v", err) - } - - if test.Preamble != pre { - t.Errorf("incorrect preamble\nexpected: %q\n actual: %q", test.Preamble, pre) - } - if !reflect.DeepEqual(test.Output, f) { - t.Errorf("incorrect file\nexpected: %+v\n actual: %+v", test.Output, f) - } - }) - } -} - -func TestParse(t *testing.T) { - textFragments := []*TextFragment{ - { - OldPosition: 3, - OldLines: 6, - NewPosition: 3, - NewLines: 8, - Comment: "fragment 1", - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 1\n"}, - {OpDelete, "old line 2\n"}, - {OpContext, "context line\n"}, - {OpAdd, "new line 1\n"}, - {OpAdd, "new line 2\n"}, - {OpAdd, "new line 3\n"}, - {OpContext, "context line\n"}, - {OpDelete, "old line 3\n"}, - {OpAdd, "new line 4\n"}, - {OpAdd, "new line 5\n"}, - }, - LinesAdded: 5, - LinesDeleted: 3, - LeadingContext: 1, - }, - { - OldPosition: 31, - OldLines: 2, - NewPosition: 33, - NewLines: 2, - Comment: "fragment 2", - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 4\n"}, - {OpAdd, "new line 6\n"}, - }, - LinesAdded: 1, - LinesDeleted: 1, - LeadingContext: 1, - }, - } - - textPreamble := `commit 5d9790fec7d95aa223f3d20936340bf55ff3dcbe -Author: Morton Haypenny -Date: Tue Apr 2 22:55:40 2019 -0700 - - A file with multiple fragments. - - The content is arbitrary. - -` - - binaryPreamble := `commit 5d9790fec7d95aa223f3d20936340bf55ff3dcbe -Author: Morton Haypenny -Date: Tue Apr 2 22:55:40 2019 -0700 - - A binary file with the first 10 fibonacci numbers. - -` - tests := map[string]struct { - InputFile string - Output []*File - Preamble string - Err bool - }{ - "oneFile": { - InputFile: "testdata/one_file.patch", - Output: []*File{ - { - OldName: "dir/file1.txt", - NewName: "dir/file1.txt", - OldMode: os.FileMode(0100644), - OldOIDPrefix: "ebe9fa54", - NewOIDPrefix: "fe103e1d", - TextFragments: textFragments, - }, - }, - Preamble: textPreamble, - }, - "twoFiles": { - InputFile: "testdata/two_files.patch", - Output: []*File{ - { - OldName: "dir/file1.txt", - NewName: "dir/file1.txt", - OldMode: os.FileMode(0100644), - OldOIDPrefix: "ebe9fa54", - NewOIDPrefix: "fe103e1d", - TextFragments: textFragments, - }, - { - OldName: "dir/file2.txt", - NewName: "dir/file2.txt", - OldMode: os.FileMode(0100644), - OldOIDPrefix: "417ebc70", - NewOIDPrefix: "67514b7f", - TextFragments: textFragments, - }, - }, - Preamble: textPreamble, - }, - "noFiles": { - InputFile: "testdata/no_files.patch", - Output: nil, - Preamble: textPreamble, - }, - "newBinaryFile": { - InputFile: "testdata/new_binary_file.patch", - Output: []*File{ - { - OldName: "", - NewName: "dir/ten.bin", - NewMode: os.FileMode(0100644), - OldOIDPrefix: "0000000000000000000000000000000000000000", - NewOIDPrefix: "77b068ba48c356156944ea714740d0d5ca07bfec", - IsNew: true, - IsBinary: true, - BinaryFragment: &BinaryFragment{ - Method: BinaryPatchLiteral, - Size: 40, - Data: fib(10, binary.BigEndian), - }, - ReverseBinaryFragment: &BinaryFragment{ - Method: BinaryPatchLiteral, - Size: 0, - Data: []byte{}, - }, - }, - }, - Preamble: binaryPreamble, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - f, err := os.Open(test.InputFile) - if err != nil { - t.Fatalf("unexpected error opening input file: %v", err) - } - - files, pre, err := Parse(f) - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing patch, but got %v", err) - } - return - } - if err != nil { - t.Fatalf("unexpected error parsing patch: %v", err) - } - - if len(test.Output) != len(files) { - t.Fatalf("incorrect number of parsed files: expected %d, actual %d", len(test.Output), len(files)) - } - if test.Preamble != pre { - t.Errorf("incorrect preamble\nexpected: %q\n actual: %q", test.Preamble, pre) - } - for i := range test.Output { - if !reflect.DeepEqual(test.Output[i], files[i]) { - exp, _ := json.MarshalIndent(test.Output[i], "", " ") - act, _ := json.MarshalIndent(files[i], "", " ") - t.Errorf("incorrect file at position %d\nexpected: %s\n actual: %s", i, exp, act) - } - } - }) - } -} - -func newTestParser(input string, init bool) *parser { - p := newParser(bytes.NewBufferString(input)) - if init { - _ = p.Next() - } - return p -} diff --git a/pkg/gitdiff/patch_header_test.go b/pkg/gitdiff/patch_header_test.go deleted file mode 100644 index c8559b0..0000000 --- a/pkg/gitdiff/patch_header_test.go +++ /dev/null @@ -1,590 +0,0 @@ -package gitdiff - -import ( - "testing" - "time" -) - -func TestParsePatchDate(t *testing.T) { - expected := time.Date(2020, 4, 9, 8, 7, 6, 0, time.UTC) - - tests := map[string]struct { - Input string - Output time.Time - Err interface{} - }{ - "default": { - Input: "Thu Apr 9 01:07:06 2020 -0700", - Output: expected, - }, - "defaultLocal": { - Input: "Thu Apr 9 01:07:06 2020", - Output: time.Date(2020, 4, 9, 1, 7, 6, 0, time.Local), - }, - "iso": { - Input: "2020-04-09 01:07:06 -0700", - Output: expected, - }, - "isoStrict": { - Input: "2020-04-09T01:07:06-07:00", - Output: expected, - }, - "rfc": { - Input: "Thu, 9 Apr 2020 01:07:06 -0700", - Output: expected, - }, - "short": { - Input: "2020-04-09", - Output: time.Date(2020, 4, 9, 0, 0, 0, 0, time.Local), - }, - "raw": { - Input: "1586419626 -0700", - Output: expected, - }, - "unix": { - Input: "1586419626", - Output: expected, - }, - "unknownFormat": { - Input: "4/9/2020 01:07:06 PDT", - Err: "unknown date format", - }, - "empty": { - Input: "", - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - d, err := ParsePatchDate(test.Input) - if test.Err != nil { - assertError(t, test.Err, err, "parsing date") - return - } - if err != nil { - t.Fatalf("unexpected error parsing date: %v", err) - } - if !test.Output.Equal(d) { - t.Errorf("incorrect parsed date: expected %v, actual %v", test.Output, d) - } - }) - } -} - -func TestParsePatchHeader(t *testing.T) { - expectedSHA := "61f5cd90bed4d204ee3feb3aa41ee91d4734855b" - expectedIdentity := &PatchIdentity{ - Name: "Morton Haypenny", - Email: "mhaypenny@example.com", - } - expectedDate := time.Date(2020, 04, 11, 15, 21, 23, 0, time.FixedZone("PDT", -7*60*60)) - expectedTitle := "A sample commit to test header parsing" - expectedEmojiOneLineTitle := "🤖 Enabling auto-merging" - expectedEmojiMultiLineTitle := "[IA64] Put ia64 config files on the Uwe Kleine-König diet" - expectedBody := "The medium format shows the body, which\nmay wrap on to multiple lines.\n\nAnother body line." - expectedBodyAppendix := "CC: Joe Smith " - - tests := map[string]struct { - Input string - Options []PatchHeaderOption - Header PatchHeader - Err interface{} - }{ - "prettyShort": { - Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b -Author: Morton Haypenny - - A sample commit to test header parsing -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - Title: expectedTitle, - }, - }, - "prettyMedium": { - Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b -Author: Morton Haypenny -Date: Sat Apr 11 15:21:23 2020 -0700 - - A sample commit to test header parsing - - The medium format shows the body, which - may wrap on to multiple lines. - - Another body line. -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Title: expectedTitle, - Body: expectedBody, - }, - }, - "prettyFull": { - Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b -Author: Morton Haypenny -Commit: Morton Haypenny - - A sample commit to test header parsing - - The medium format shows the body, which - may wrap on to multiple lines. - - Another body line. -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - Committer: expectedIdentity, - Title: expectedTitle, - Body: expectedBody, - }, - }, - "prettyFuller": { - Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b -Author: Morton Haypenny -AuthorDate: Sat Apr 11 15:21:23 2020 -0700 -Commit: Morton Haypenny -CommitDate: Sat Apr 11 15:21:23 2020 -0700 - - A sample commit to test header parsing - - The medium format shows the body, which - may wrap on to multiple lines. - - Another body line. -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Committer: expectedIdentity, - CommitterDate: expectedDate, - Title: expectedTitle, - Body: expectedBody, - }, - }, - "prettyAppendix": { - Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b -Author: Morton Haypenny -AuthorDate: Sat Apr 11 15:21:23 2020 -0700 -Commit: Morton Haypenny -CommitDate: Sat Apr 11 15:21:23 2020 -0700 - - A sample commit to test header parsing - - The medium format shows the body, which - may wrap on to multiple lines. - - Another body line. - --- - CC: Joe Smith -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Committer: expectedIdentity, - CommitterDate: expectedDate, - Title: expectedTitle, - Body: expectedBody + "\n---\n" + expectedBodyAppendix, - }, - }, - "mailbox": { - Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 -From: Morton Haypenny -Date: Sat, 11 Apr 2020 15:21:23 -0700 -Subject: [PATCH] A sample commit to test header parsing - -The medium format shows the body, which -may wrap on to multiple lines. - -Another body line. -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Title: expectedTitle, - Body: expectedBody, - }, - }, - "mailboxPatchOnly": { - Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 -From: Morton Haypenny -Date: Sat, 11 Apr 2020 15:21:23 -0700 -Subject: [PATCH] [BUG-123] A sample commit to test header parsing - -The medium format shows the body, which -may wrap on to multiple lines. - -Another body line. -`, - Options: []PatchHeaderOption{ - WithSubjectCleanMode(SubjectCleanPatchOnly), - }, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Title: "[BUG-123] " + expectedTitle, - Body: expectedBody, - }, - }, - "mailboxEmojiOneLine": { - Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 -From: Morton Haypenny -Date: Sat, 11 Apr 2020 15:21:23 -0700 -Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20Enabling=20auto-merging?= - -The medium format shows the body, which -may wrap on to multiple lines. - -Another body line. -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Title: expectedEmojiOneLineTitle, - Body: expectedBody, - }, - }, - "mailboxEmojiMultiLine": { - Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 -From: Morton Haypenny -Date: Sat, 11 Apr 2020 15:21:23 -0700 -Subject: [PATCH] =?UTF-8?q?[IA64]=20Put=20ia64=20config=20files=20on=20the=20?= - =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20diet?= - -The medium format shows the body, which -may wrap on to multiple lines. - -Another body line. -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Title: expectedEmojiMultiLineTitle, - Body: expectedBody, - }, - }, - "mailboxRFC5322SpecialCharacters": { - Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 -From: "dependabot[bot]" <12345+dependabot[bot]@users.noreply.github.com> -Date: Sat, 11 Apr 2020 15:21:23 -0700 -Subject: [PATCH] A sample commit to test header parsing - -The medium format shows the body, which -may wrap on to multiple lines. - -Another body line. -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: &PatchIdentity{ - Name: "dependabot[bot]", - Email: "12345+dependabot[bot]@users.noreply.github.com", - }, - AuthorDate: expectedDate, - Title: expectedTitle, - Body: expectedBody, - }, - }, - "mailboxAppendix": { - Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 -From: Morton Haypenny -Date: Sat, 11 Apr 2020 15:21:23 -0700 -Subject: [PATCH] A sample commit to test header parsing - -The medium format shows the body, which -may wrap on to multiple lines. - -Another body line. ---- -CC: Joe Smith -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Title: expectedTitle, - Body: expectedBody, - BodyAppendix: expectedBodyAppendix, - }, - }, - "mailboxMinimalNoName": { - Input: `From: -Subject: [PATCH] A sample commit to test header parsing - -The medium format shows the body, which -may wrap on to multiple lines. - -Another body line. -`, - Header: PatchHeader{ - Author: &PatchIdentity{expectedIdentity.Email, expectedIdentity.Email}, - Title: expectedTitle, - Body: expectedBody, - }, - }, - "mailboxMinimal": { - Input: `From: Morton Haypenny -Subject: [PATCH] A sample commit to test header parsing - -The medium format shows the body, which -may wrap on to multiple lines. - -Another body line. -`, - Header: PatchHeader{ - Author: expectedIdentity, - Title: expectedTitle, - Body: expectedBody, - }, - }, - "unwrapTitle": { - Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b -Author: Morton Haypenny -Date: Sat Apr 11 15:21:23 2020 -0700 - - A sample commit to test header parsing with a long - title that is wrapped. -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Title: expectedTitle + " with a long title that is wrapped.", - }, - }, - "normalizeBodySpace": { - Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b -Author: Morton Haypenny -Date: Sat Apr 11 15:21:23 2020 -0700 - - A sample commit to test header parsing - - - The medium format shows the body, which - may wrap on to multiple lines. - - - Another body line. - - -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Title: expectedTitle, - Body: expectedBody, - }, - }, - "ignoreLeadingBlankLines": { - Input: ` - -` + " " + ` -commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b -Author: Morton Haypenny - - A sample commit to test header parsing -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - Title: expectedTitle, - }, - }, - "emptyHeader": { - Input: "", - Header: PatchHeader{}, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - h, err := ParsePatchHeader(test.Input, test.Options...) - if test.Err != nil { - assertError(t, test.Err, err, "parsing patch header") - return - } - if err != nil { - t.Fatalf("unexpected error parsing patch header: %v", err) - } - if h == nil { - t.Fatalf("expected non-nil header, but got nil") - } - - exp := test.Header - act := *h - - if exp.SHA != act.SHA { - t.Errorf("incorrect parsed SHA: expected %q, actual %q", exp.SHA, act.SHA) - } - - assertPatchIdentity(t, "author", exp.Author, act.Author) - if !exp.AuthorDate.Equal(act.AuthorDate) { - t.Errorf("incorrect parsed author date: expected %v, but got %v", exp.AuthorDate, act.AuthorDate) - } - - assertPatchIdentity(t, "committer", exp.Committer, act.Committer) - if !exp.CommitterDate.Equal(act.CommitterDate) { - t.Errorf("incorrect parsed committer date: expected %v, but got %v", exp.CommitterDate, act.CommitterDate) - } - - if exp.Title != act.Title { - t.Errorf("incorrect parsed title:\n expected: %q\n actual: %q", exp.Title, act.Title) - } - if exp.Body != act.Body { - t.Errorf("incorrect parsed body:\n expected: %q\n actual: %q", exp.Body, act.Body) - } - if exp.BodyAppendix != act.BodyAppendix { - t.Errorf("incorrect parsed body appendix:\n expected: %q\n actual: %q", - exp.BodyAppendix, act.BodyAppendix) - } - }) - } -} - -func assertPatchIdentity(t *testing.T, kind string, exp, act *PatchIdentity) { - switch { - case exp == nil && act == nil: - case exp == nil && act != nil: - t.Errorf("incorrect parsed %s: expected nil, but got %+v", kind, act) - case exp != nil && act == nil: - t.Errorf("incorrect parsed %s: expected %+v, but got nil", kind, exp) - case exp.Name != act.Name || exp.Email != act.Email: - t.Errorf("incorrect parsed %s, expected %+v, bot got %+v", kind, exp, act) - } -} - -func TestCleanSubject(t *testing.T) { - expectedSubject := "A sample commit to test header parsing" - - tests := map[string]struct { - Input string - Mode SubjectCleanMode - Prefix string - Subject string - }{ - "CleanAll/noPrefix": { - Input: expectedSubject, - Mode: SubjectCleanAll, - Subject: expectedSubject, - }, - "CleanAll/patchPrefix": { - Input: "[PATCH] " + expectedSubject, - Mode: SubjectCleanAll, - Prefix: "[PATCH] ", - Subject: expectedSubject, - }, - "CleanAll/patchPrefixNoSpace": { - Input: "[PATCH]" + expectedSubject, - Mode: SubjectCleanAll, - Prefix: "[PATCH]", - Subject: expectedSubject, - }, - "CleanAll/patchPrefixContent": { - Input: "[PATCH 3/7] " + expectedSubject, - Mode: SubjectCleanAll, - Prefix: "[PATCH 3/7] ", - Subject: expectedSubject, - }, - "CleanAll/spacePrefix": { - Input: " " + expectedSubject, - Mode: SubjectCleanAll, - Subject: expectedSubject, - }, - "CleanAll/replyLowerPrefix": { - Input: "re: " + expectedSubject, - Mode: SubjectCleanAll, - Prefix: "re: ", - Subject: expectedSubject, - }, - "CleanAll/replyMixedPrefix": { - Input: "Re: " + expectedSubject, - Mode: SubjectCleanAll, - Prefix: "Re: ", - Subject: expectedSubject, - }, - "CleanAll/replyCapsPrefix": { - Input: "RE: " + expectedSubject, - Mode: SubjectCleanAll, - Prefix: "RE: ", - Subject: expectedSubject, - }, - "CleanAll/replyDoublePrefix": { - Input: "Re: re: " + expectedSubject, - Mode: SubjectCleanAll, - Prefix: "Re: re: ", - Subject: expectedSubject, - }, - "CleanAll/noPrefixSubjectHasRe": { - Input: "Reimplement parsing", - Mode: SubjectCleanAll, - Subject: "Reimplement parsing", - }, - "CleanAll/patchPrefixSubjectHasRe": { - Input: "[PATCH 1/2] Reimplement parsing", - Mode: SubjectCleanAll, - Prefix: "[PATCH 1/2] ", - Subject: "Reimplement parsing", - }, - "CleanAll/unclosedPrefix": { - Input: "[Just to annoy people", - Mode: SubjectCleanAll, - Subject: "[Just to annoy people", - }, - "CleanAll/multiplePrefix": { - Input: " Re:Re: [PATCH 1/2][DRAFT] " + expectedSubject + " ", - Mode: SubjectCleanAll, - Prefix: "Re:Re: [PATCH 1/2][DRAFT] ", - Subject: expectedSubject, - }, - "CleanPatchOnly/patchPrefix": { - Input: "[PATCH] " + expectedSubject, - Mode: SubjectCleanPatchOnly, - Prefix: "[PATCH] ", - Subject: expectedSubject, - }, - "CleanPatchOnly/mixedPrefix": { - Input: "[PATCH] [TICKET-123] " + expectedSubject, - Mode: SubjectCleanPatchOnly, - Prefix: "[PATCH] ", - Subject: "[TICKET-123] " + expectedSubject, - }, - "CleanPatchOnly/multiplePrefix": { - Input: "Re:Re: [PATCH 1/2][DRAFT] " + expectedSubject, - Mode: SubjectCleanPatchOnly, - Prefix: "Re:Re: [PATCH 1/2]", - Subject: "[DRAFT] " + expectedSubject, - }, - "CleanWhitespace/leadingSpace": { - Input: " [PATCH] " + expectedSubject, - Mode: SubjectCleanWhitespace, - Subject: "[PATCH] " + expectedSubject, - }, - "CleanWhitespace/trailingSpace": { - Input: "[PATCH] " + expectedSubject + " ", - Mode: SubjectCleanWhitespace, - Subject: "[PATCH] " + expectedSubject, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - prefix, subject := cleanSubject(test.Input, test.Mode) - if prefix != test.Prefix { - t.Errorf("incorrect prefix: expected %q, actual %q", test.Prefix, prefix) - } - if subject != test.Subject { - t.Errorf("incorrect subject: expected %q, actual %q", test.Subject, subject) - } - }) - } -} diff --git a/pkg/gitdiff/patch_identity_test.go b/pkg/gitdiff/patch_identity_test.go deleted file mode 100644 index f15fe38..0000000 --- a/pkg/gitdiff/patch_identity_test.go +++ /dev/null @@ -1,127 +0,0 @@ -package gitdiff - -import ( - "testing" -) - -func TestParsePatchIdentity(t *testing.T) { - tests := map[string]struct { - Input string - Output PatchIdentity - Err interface{} - }{ - "simple": { - Input: "Morton Haypenny ", - Output: PatchIdentity{ - Name: "Morton Haypenny", - Email: "mhaypenny@example.com", - }, - }, - "extraWhitespace": { - Input: "\t Morton Haypenny \r\n ", - Output: PatchIdentity{ - Name: "Morton Haypenny", - Email: "mhaypenny@example.com", - }, - }, - "trailingCharacters": { - Input: "Morton Haypenny II", - Output: PatchIdentity{ - Name: "Morton Haypenny II", - Email: "mhaypenny@example.com", - }, - }, - "onlyEmail": { - Input: "mhaypenny@example.com", - Output: PatchIdentity{ - Name: "mhaypenny@example.com", - Email: "mhaypenny@example.com", - }, - }, - "onlyEmailInBrackets": { - Input: "", - Output: PatchIdentity{ - Name: "mhaypenny@example.com", - Email: "mhaypenny@example.com", - }, - }, - "rfc5322SpecialCharacters": { - Input: `"dependabot[bot]" <12345+dependabot[bot]@users.noreply.github.com>`, - Output: PatchIdentity{ - Name: "dependabot[bot]", - Email: "12345+dependabot[bot]@users.noreply.github.com", - }, - }, - "rfc5322QuotedPairs": { - Input: `"Morton \"Old-Timer\" Haypenny" <"mhaypenny\+[1900]"@example.com> (III \(PhD\))`, - Output: PatchIdentity{ - Name: `Morton "Old-Timer" Haypenny (III (PhD))`, - Email: "mhaypenny+[1900]@example.com", - }, - }, - "rfc5322QuotedPairsOutOfContext": { - Input: `Morton \\Backslash Haypenny `, - Output: PatchIdentity{ - Name: `Morton \\Backslash Haypenny`, - Email: "mhaypenny@example.com", - }, - }, - "emptyEmail": { - Input: "Morton Haypenny <>", - Output: PatchIdentity{ - Name: "Morton Haypenny", - Email: "", - }, - }, - "unclosedEmail": { - Input: "Morton Haypenny ", - Output: PatchIdentity{ - Name: "Morton Haypenny", - Email: "mhaypenny", - }, - }, - "bogusEmailWithWhitespace": { - Input: "Morton Haypenny < mhaypenny >", - Output: PatchIdentity{ - Name: "Morton Haypenny", - Email: "mhaypenny", - }, - }, - "missingEmail": { - Input: "Morton Haypenny", - Err: "invalid identity", - }, - "missingNameAndEmptyEmail": { - Input: "<>", - Err: "invalid identity", - }, - "empty": { - Input: "", - Err: "invalid identity", - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - id, err := ParsePatchIdentity(test.Input) - if test.Err != nil { - assertError(t, test.Err, err, "parsing identity") - return - } - if err != nil { - t.Fatalf("unexpected error parsing identity: %v", err) - } - - if test.Output != id { - t.Errorf("incorrect identity: expected %#v, actual %#v", test.Output, id) - } - }) - } -} diff --git a/pkg/gitdiff/testdata/apply/bin.go b/pkg/gitdiff/testdata/apply/bin.go deleted file mode 100644 index e34f06b..0000000 --- a/pkg/gitdiff/testdata/apply/bin.go +++ /dev/null @@ -1,124 +0,0 @@ -//go:build ignore - -// bin.go is a helper CLI to manipulate binary diff data for testing purposes. -// It can decode patches generated by git using the standard parsing functions -// or it can encode binary data back into the format expected by Git. It -// operates on stdin writes results (possibly binary) to stdout. - -package main - -import ( - "bytes" - "compress/zlib" - "encoding/binary" - "flag" - "io/ioutil" - "log" - "os" - "strings" - - "github.com/bluekeyes/go-gitdiff/gitdiff" -) - -var ( - b85Powers = []uint32{52200625, 614125, 7225, 85, 1} - b85Alpha = []byte( - "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "!#$%&()*+-;<=>?@^_`{|}~", - ) -) - -var mode string - -func base85Encode(data []byte) []byte { - chunks, remaining := len(data)/4, len(data)%4 - if remaining > 0 { - data = append(data, make([]byte, 4-remaining)...) - chunks++ - } - - var n int - out := make([]byte, 5*chunks) - - for i := 0; i < len(data); i += 4 { - v := binary.BigEndian.Uint32(data[i : i+4]) - for j := 0; j < 5; j++ { - p := v / b85Powers[j] - out[n+j] = b85Alpha[p] - v -= b85Powers[j] * p - } - n += 5 - } - - return out -} - -func compress(data []byte) ([]byte, error) { - var b bytes.Buffer - w := zlib.NewWriter(&b) - - if _, err := w.Write(data); err != nil { - return nil, err - } - if err := w.Close(); err != nil { - return nil, err - } - - return b.Bytes(), nil -} - -func wrap(data []byte) string { - var s strings.Builder - for i := 0; i < len(data); i += 52 { - c := 52 - if c > len(data)-i { - c = len(data) - i - } - b := (c / 5) * 4 - - if b <= 26 { - s.WriteByte(byte('A' + b - 1)) - } else { - s.WriteByte(byte('a' + b - 27)) - } - s.Write(data[i : i+c]) - s.WriteByte('\n') - } - return s.String() -} - -func init() { - flag.StringVar(&mode, "mode", "parse", "operation mode, one of 'parse' or 'encode'") -} - -func main() { - flag.Parse() - - switch mode { - case "parse": - files, _, err := gitdiff.Parse(os.Stdin) - if err != nil { - log.Fatalf("failed to parse file: %v", err) - } - if len(files) != 1 { - log.Fatalf("patch contains more than one file: %d", len(files)) - } - if files[0].BinaryFragment == nil { - log.Fatalf("patch file does not contain a binary fragment") - } - os.Stdout.Write(files[0].BinaryFragment.Data) - - case "encode": - data, err := ioutil.ReadAll(os.Stdin) - if err != nil { - log.Fatalf("failed to read input: %v", err) - } - data, err = compress(data) - if err != nil { - log.Fatalf("failed to compress data: %v", err) - } - os.Stdout.WriteString(wrap(base85Encode(data))) - - default: - log.Fatalf("unknown mode: %s", mode) - } -} diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error.src b/pkg/gitdiff/testdata/apply/bin_fragment_delta_error.src deleted file mode 100644 index d4edf89..0000000 Binary files a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error.src and /dev/null differ diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_dst_size.patch b/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_dst_size.patch deleted file mode 100644 index 6d5bb42..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_dst_size.patch +++ /dev/null @@ -1,5 +0,0 @@ -diff --git a/gitdiff/testdata/apply/bin_fragment_delta_error.src b/gitdiff/testdata/apply/bin_fragment_delta_error.src -GIT binary patch -delta 18 -fc${itY+{<=z`_4AtEhVK$zKyatN;N30RR6$D+j^= - diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_add.patch b/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_add.patch deleted file mode 100644 index b8c1835..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_add.patch +++ /dev/null @@ -1,5 +0,0 @@ -diff --git a/gitdiff/testdata/apply/bin_fragment_delta_error.src b/gitdiff/testdata/apply/bin_fragment_delta_error.src -GIT binary patch -delta 11 -Xc${itY+{_?z`_4As|XMP0RR6K8UwQc - diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_copy.patch b/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_copy.patch deleted file mode 100644 index 8db8f84..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_copy.patch +++ /dev/null @@ -1,5 +0,0 @@ -diff --git a/gitdiff/testdata/apply/bin_fragment_delta_error.src b/gitdiff/testdata/apply/bin_fragment_delta_error.src -GIT binary patch -delta 17 -fc${itY+{_?z`_4AtEhVK$zKya00961|Nl5!2ZsOv - diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_src_size.patch b/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_src_size.patch deleted file mode 100644 index 29cb26b..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_src_size.patch +++ /dev/null @@ -1,5 +0,0 @@ -diff --git a/gitdiff/testdata/apply/bin_fragment_delta_error.src b/gitdiff/testdata/apply/bin_fragment_delta_error.src -GIT binary patch -delta 18 -fc${itYGRz=z`_4AtEhVK$zKyatN;N30RR6$EeFB? - diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.out b/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.out deleted file mode 100644 index f3386d1..0000000 Binary files a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.out and /dev/null differ diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.patch b/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.patch deleted file mode 100644 index 1801ef2..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/gitdiff/testdata/apply/bin_fragment_delta_modify.src b/gitdiff/testdata/apply/bin_fragment_delta_modify.src -GIT binary patch -delta 172 -zcmV;d08{^f2)qc8AP{I3VQ>J`s>wb0HU+h#6w8q?tUO~cHmDjZi2<8yZ9XmKhhMdo -zWu(4bg|8QwzZ|1e*rL4P#)`FenXTQ5=J2y;^BfB}4 -zWkisH791|vOVl5e-@^VLX0s~Ky_UyN!3;CgPr>Edj0j+0gOSwSsFsr$0q6zUJphJCY -zqz)g`N&ViW9W6D7kX7GX{y{m=JvFi1-r`PEE?SE&^2StK}qz5hC -zom0ywdCWuNb#YXdd0%FMNHft!FTER$>uzu5gxdoGBy789raJBW7jAhN2TWFL{P%2l -z|AX{}Jz8U}Y*X|~=?4<;F4)94!-e?w)#D0h8n1_ORWNCOC&7=!U0MP3BI0~M)pZ-cf6aFkVFzO&JOkcv7FeEq|)DcBDAP&_&ZgBk* -zVp(I^5-bN3L{~g{bHnkWX%0Hj02~njkKX8Zz%Ih#=LBD%Pk%TkW4ize_HweE#@_-2 -zvpyE#e@^n#rRGx;O84LB3bMdrxdv%Gkc)ZQq%8pkxT9b*)}Z&t5bibZ0)8H8T33vN -zgTj)j_%wz13x+TZ6LgdupD^ke2!n7E-YZ%8n3OTzK5*T(BH>ltfU|QJ7VTAur}ah?0sC%ZUY?&xwkEUw@Y9LqO1~eF>>5cDlg_YxuF| -zZ58JVlu7IBfP1@TDmG;<{X>(&*HyC-7zqRrY~#3W>hP8@a&jwYi_$k(j`D$Ta97 -z{(rL4B7Ysa#+5QC40p?w_V}r&G%{W$)8R1P`wet5K>`4D&EanFW{d2mOBvm~hJviTXh@a)Qp^TpF9X}vEVN-{LA%5Xp^*>%23c&{6HgPH4ahb@257yLNuno+(_9IJ!cgw97b*@K~X-9f8rdsd` -zOSj362)!mBsX%A -zQ*StV4WzVHG#+*IwPf7@BwNAUN{Tre0&7KHK8Gq6W2Jeqe%S(>+{1HM$cFn>J%6m& -z|8$kpBb=Dxh6$MwDCzl1g;Y`~f7F-wEny-#iI1X?l(D;Z$PLR3jay0@l4S5PR8fS< -zi+>Hek8mDV9ItDt3}cF;v-yN79ZUwT1^LyF1n$Cy%gt_C&r9r*A*)&$ZFlHnVf=mg#Q%sK{dyD8$2z{ndd#G^c?_~0mb!M$7ZxU$373E=vV}GR5OrWDm -zBsRhxx$#Ql_U#b2h}uPg{qm53MhlGO!F^=m@8@Ie88^`%?=q2+>^o91FPtaKgX{mUR_AEr9NwT^_^@8>UHx -z6Vql9ovz7$NpnPl5QlqsKP0|}EskXfTz-@ZpBlsI-~?B-4%w_GY9s9?ln=!A8wNMf -z=;eAIwp6&0nZ9Qq({C*2AXxKEGCjGa)2K^@ryP2!6dWiRy0M0vL*145f@BzR -z`IXs~3pGOq&;GIFDC=$JbDmK$C`A~nS$@*@hY$2e@kN0E;7jK@*TzW0 -z2FmwjqM0G-dfMDB3x5@pycb${TTJ7dzu+teFC9mUiSr(jrvQ~;sj`>uoen9{iXP5; -zbF9`-K065Zx&Tv2gK4wf8(U++M31oGlTiV$(^)qux97HP~_mSNPtqZA#7xOo;Q -zc-B?N(jYE1ix_L{M|cpCS4s5I3Tx_Hh1#!O-iBP5iS>iM{C~ZUez^pglqH5IAdOAD -zE;AjwjL)_IsQU6y4t4Uc9KXl~!BYeA;B8*wK)|cg^tiD0aN2iWzR>YnUUS9?3jKhiAKpgQ0 -zCRNTKwkeO~{pU2|S8)UYp21g#5$lGV|mN -zdQNSkH%R6}>C_cemrZCjR|-)D<8Y^P74a}>FKs&95{8d9SiTvhB4{eTUGFbTa-IbX -z8Lw1xoPPp_ZdIbl#dCzP1`N@V?eb7SizWtmm5ujG(rKZHZw$>Ozzf4E=Yf*+eH}kn -zL{&n><${iESA&t~5pz;&vs%HlLYxXMjPlLH{?*-#T4#$(P;pke+8K*f)n*Ph>SB9|8)|f;w=%OP6`nms -zdFVyjJf#&^=o+P_Y1Q{$$Aql8VqX+>=4)lx*&wB#{$tlb&SwC3E~G-pKOFXRQrRSk -zMt}Fa|4IQc;^N}stu@1BVjk>`8grvj#WVz9k#>7N?#JQZdag9deih!2aWVB}1klbo -zXKhuKy*h7m?``T}aM*}PexaGXqeZCm>ME7BQi64D>9lL0AoF2`Tzo^hNSMC9B=jT@ -zjA%viojl=gm6?1mPDg-)fy98Cb}Bdio_{dD+i;%nIJ6ZfQ^LPvl@~R#wk@K-##0ma -zj|D(^Fr8U(o(FRy$Z0FGyp@Yam&`H8oVv>6n8UKEVec>#*NVp)YrdOPgay4SxQ!PjT#gf^PISz?!W;(=9W -zC3sT|H>d}ErTr;c8LY_P{IPZ;Wq&_a4mM`dLu -zn^@7N(YC~q-qV~usbu?>{mD#~LNHhWdnNcaB&J>J@M)=+i^{*SwmS-XE-ywoYoZ3U -zdb4|M(!Ok$LY!K2m*Wjy>w_)zTm#k_g&J$VCb%~Wdvc^;lfge`vp1dg{O^Aqhg$$l5i=+C+Ser`KQQfEhZr}z4>;>#SGZZ*qGHd~H-az)BPnlSx{cgt);r6Mgt;@-+9-E2t@FXz( -zkh$)!g3>JMRK2Fj;(t$e?z7fJ;>m@#_j;z{x_|Hzf&NnB2s)A$gs4~;$GCPhUTy3P -z%V#3D9@E1QNOb5UL}Ny_3_nU3V+}u&a}K`lA2AVv-@33!d)C9C2b%Dl#4Wp`G3Y#VXS2vODOK -zH6Ik?Qx|Shj(@mOGi-V8X@6z3u=_{}wqW)r%+?8?joDa^!2`v;{CIT;J4sydrLxNW -zgUBvqK&gHOJyAP#hP2e3p;XKF@8~4;2})IVed0tk&>;1X$v5<9B1$g>xX)iE=u55Vhuq!Be_Zh7H_L0ojmJ-L7F -zFE;pV4HH_WmO_~*TJ#EHu@A`M)iV-3k0!7^nIQ%08mJA-{<~wkIj0>_AP%Vz_4#<* -vVkRz)@E~iIs*PG)1#O3 -z^y`3>TH+sKUrDep!F5A*^DLBShsp6!+cwX9)&)8gv+|D%3&Z;I1%KSpdiN0>xk9!c -zDy`)OH&-h44JMjA=aom~2^DT%XWWk@BGsF>T2qX9tzqChzyU07Q5O!7pHe8DLN|bp -zdlTM)yHOJqRKS{Ok~8#6aa|1~wdC!f6HE-YeYg|0WDJ@d5_mH_Xk7QkFCJ);Ovbo( -zM*o?Jc;mjWG9!T2#lADbM8kdZGB*L;W@^4gw!CX?raCf7DLTZhN{Ky@jK1r2x?YmoKqE|=?ny{_>M -zPW`hAEW;McTgizc-%KZOZ(LC{iJ26YFd!W@TJ{Cm#XaWxI)6edCQgN9H-J&#etfq2BL8u2mpTqV;-qg8O*hlGo~w*^QU&D8~wh* -zjRoXGhq}{c%8{%P7XC3-Gtv_4vPhC&G({}4=soxR<|OO8=U32O6B6X4cu}vawOLA8 -zUCsnRtC7@}bbt5OjoNEaRt9SW579M@O#ke{I?9P!pHGx8+mS!>XB(pRy3MCefz~7F -zw>%NX4brs~1S)zzfOF(+Ek>{e>P?F^u#}8;o=P;Q#CD^EyGpfE6zisF&7Wp0@PM#uQ8l(zm -zP$=UTG!hf$iSFO~fxdOLf78q%Z-e$nFbWUzJ1GphTCI4>g(9IgBR5F8ark@QBWdEc -z#zwo4Yk#W3G2@1tNzg@lLP}&U1pA#O7MZO99tC&}9^@dg>AOG&wsG)`L6)m8D^F-bi%B9Fk!}EJ;7-NTD*1)VJblm%?L@A$yiNR_ -zN*tPjf$n}UNI)oYV<>TQzBo6=Js6=KI%9xd0e}BZ7R)GU!se_DK2rXrAU6Li*}JNk -z#OhSK^H=?bSi&TwvW+tB(6HGW@aslSEso+M=;CSx(a|*2cpNSek=YCt0xna?)V|}{ -zTrlxT(K!Y~T&oi%3ZE#@!{L<{lsr)-9)*xnPKtF8N_ai2o#MZ0IBC!gL$Qsp6Z -z8Gn6s&gnB+R1tMMtKG)p(&tf2mQR=p-i$vp0Miv<=k6$|Zzncr&mA(7R@^rLWDs=I -zYQH*agSALP4X>gKE|9hMvV&2kw^AvZ!faW}gmNmbaQYn9l7n@!u{?2sM8nv;Tmv{O -zBGR5{oW=M)QBwCHaH^{#iZy8#xtUkH+J6it`5)T}v?(oj_fcQINt+8O%OF`^vYP4)mg#jyW+dip{0)NO!-BTlR_?Vq;{U272sSWrCqIVm8cQL -zrQmZDOJ2`L8Ma$4xNjy5tYTIfMP$0Cem%%TLvRcw`DGcD@_|S%DDQ4u3UK -z8OEd2toTA8!T^Fm!2&_{Jf5ZMEi=opVlV!Ik -z<##3|qPvm^@~emp!AcWqZnh=Kjei*4uG>XNb8+}}YQ^1W{{z9%$|}v5_lcs>dBQ)!1^xT1u+L5lB_@cL=1D~x9Wuz -zxNt@}3^A_ZoI>X}!Mx*>E&MhCXYogWFhGnpZyeU!If!?eQb$yAbIIg><^*Non_1wm3-B0LADTnL -z@Hcy)r!Y%8x7clRE|bsgq9dRISAT07rTRBH&nUUbh`5p}Mb34r|9T->C}v-0X5Ec}{F9eQ~ -zhpvHGyil+IHRzd!=^rDs{FlTe*YP3?X>tO`A|pa&VSnR#Teu~TOBJYPw~MpSAuLU& -zyl44lEnDGx9xOCB98{3a*(->ajsd_h%GmzCJno?Q&Pk&<XzvfiOofjV7KjkT8RO)tQL0)FS;%Xt5w2$x+^;B_k^yfQRtHC!ndJ& -z&$LQY(4EC(dem!kO3UB}z~JrL$`X9Qg4CLqd7*@Hn2yxVThL!~BW -za6(zTA3VB62Y($=87Nd(yuJH&{z_$9;Eo)VO3Rv;-+gC34F02W_29+|Br6D$(fQ&u -z--#+MO#x4xiRrjERDA?xBfD@AaPlspDCD~m)QT=JS6a}X`|BZPaBeJ2pzNE=Uv-7K -zn1=v3M4?6-!r&5zU^ey=zQ|mJwNTM3ynPRaeEP2%Ab&NAz23L!+3J78>DNz@ -zcRGVQ{T78^a%8e;7hmY!<1!>F%P3kh+(XpJvYZi2+_KJ{TpjXm2?SpLtC$kZ^u(dN -zk6GUPl;ciEb+#wFOVmH>IJ*$ACbE1kae%lKRxO7TlRgGD&%hdcWBJ_hl&X@eH`oP+ -zEE(=8aL=VamW$>w$<-v#=-Gn(S+ -z3;|DiLStTzl)8WRlm|&b);zFN)QobrszD9rwkLNNY*MK+{OAn&2FY03tEpf5Jpj54Gk>^{cy&yUeV3R*pRs^>fqgveU|_5X -zX+e%27qs2?7c(6BMHwnKprk+Z!)v4I=V4BAvdR#Lu7_d4gJ5#jsXEF%=!5*qv7*_k -zM%5WM$*Vou!Y7D@*jCa6 -zYHwni68{B(ythcY+j4tKR&BK~wpq+p_I^Ee5*>UjeSbn=Z@M{3)IDB1h`wTBv8Vf) -zGUabKI^vx;3Bt3)O=|zXZF^CRCWGFRoqrAlxT0y&$j5q6SnOOU5o0?&Ps&D6Ph}`# -zwY!d(eP-j3KN_5`jU!b3rM~A)_kI~RXoFy;RSw!9pX9GG#B*F)`BST~98N+GqC9J7 -zyK!;S%6g@oNzmD1wzp`{WZzW@_X`T-&+vR;$j+YidW6`>)~^xl)>6cuUrT~*Lu`sa -ztO}<9;#H(Q==8o5Tl}2UX=uGs%2mo19NqD{5U5NNDyo1Rz+mR`!bH$50%+yM7He^f -zdBH00TyclwDiI=}Q>9_P*rcl2Xnz%4ZX#_#&l$m~RIyIW^MA=hnUPFr%4bUq`Q(Rz -zpGTKslcC%{fbRe!3oa<}4EKVhQ%zS`J2GeEVr+blZ0VAxrNnYnS|C25Uov}{GHoRv -zfFHfa&Jwlv(G^#}8A+}RLJN4n=M4UA|@AT(`^>Fu_AKhK^yT$XPA9`v4eB_FD$ie0HD3Mi4;`s$hx2m9!(i8H!RzGg?C)?9Pb`H(UMj -z<8h|0U)ScABl{{?sOhBJJ+yFPUOt7$z&nj*C(+UXB1_UZbG@s_K&)51_vPKxQ4~mI -zVsBl7$^wYH(tS=4B*eHGsefF8JLWa`(eLnE!hn1l1gzVr56RAj0G_?aY8PsdnewAx -zZT0?fpiS{s0Aw+t2$UUQ8M-rW={ko_;sJpjJ1cye3c$(VR4{`2w#4pbFy+`(TlH;+ -zsRJ^EQ{%@!-i8GRBqYoy6jIyiS8YC#b<%d)^wC2C>^bvFCR##kmw%eyk5ClDOBLPk -z?ZY@ePP8_qq>U*{?_kesZmky4-_cLmu?|B2);KDCQ?spBIJE?6j8`9&{>UoVIRUPw -zrx_TuibGY$dcSSH{d>KOqk_s$i=X_v>|dz1MMzQ0CJX+$*Y(PaiAhNRl8^?%L6tN! -zoCVZZRG(i1T9lcmLVv7ZE)U68M1}eqD2QeQo3F+z`_kj^3BAQ~kifx^iJVoht|)uQ -zp@Zi4b(sUN|HikW5)IF|`VA(5R}Oig)4g3o@Edr6G~IUUj9NaSza}p$jk_pOfzO2r -z`Uq<(Z;%5A7DwJe@~J%KO>wC&&NuCjN8iAHC?0eTu|CfS+kf-2P)BX2mNxYJOt)<# -zud7R9Is%@q9H$%no|irWi2&HJ00Qekek!<&=4kke7cKnH-x$$Mg_!j+R4)~S@4-7 -zr5;gyzbMDhd4E#B$j(G@-z05T!$YZ=j)t^KKgHs!H_s_|8VC%~m+HAY-YK*Nx44gH -zaUG54Wez*M!YaxNS#)BjN)7?2M!A3NOY99Oa}Rb;C#RPNionqlK3@N0PTt)Op#&Rj>ipw!qDZki{+-V5CQD(Yj^-6 - diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify_large.src b/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify_large.src deleted file mode 100644 index 90a9f6d..0000000 Binary files a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify_large.src and /dev/null differ diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_literal_create.out b/pkg/gitdiff/testdata/apply/bin_fragment_literal_create.out deleted file mode 100644 index c62cba2..0000000 Binary files a/pkg/gitdiff/testdata/apply/bin_fragment_literal_create.out and /dev/null differ diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_literal_create.patch b/pkg/gitdiff/testdata/apply/bin_fragment_literal_create.patch deleted file mode 100644 index b3b846a..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_literal_create.patch +++ /dev/null @@ -1,8 +0,0 @@ -diff --git a/gitdiff/testdata/apply/bin_fragment_literal_create.src b/gitdiff/testdata/apply/bin_fragment_literal_create.src -GIT binary patch -literal 32 -ocmZQzU`lR_IpTEvL*`JUiBtu5L*`JUiBtu5J`s>wb0HU+h#6w8q?tUO~cHmDjZi2<8yZ9XmKhhMdo -zWu(4bg|8QwzZ|1e*rL4P#)`FenXTQ5=J2y;^BfB}4 -zWkisH791|vOVl5e-@^VLX0s~Ky_UyN!3;CgPr>Edj0j+0gOSwSsFsr$0q6zUJph -Date: Tue Apr 2 22:55:40 2019 -0700 - - A binary file with the first 10 fibonacci numbers. - -diff --git a/dir/ten.bin b/dir/ten.bin -new file mode 100644 -index 0000000000000000000000000000000000000000..77b068ba48c356156944ea714740d0d5ca07bfec -GIT binary patch -literal 40 -gcmZQzU|?i`U?w2V48*KJ%mKu_Kr9NxN -Date: Tue Apr 2 22:55:40 2019 -0700 - - A file with multiple fragments. - - The content is arbitrary. - diff --git a/pkg/gitdiff/testdata/one_file.patch b/pkg/gitdiff/testdata/one_file.patch deleted file mode 100644 index 1aefec3..0000000 --- a/pkg/gitdiff/testdata/one_file.patch +++ /dev/null @@ -1,28 +0,0 @@ -commit 5d9790fec7d95aa223f3d20936340bf55ff3dcbe -Author: Morton Haypenny -Date: Tue Apr 2 22:55:40 2019 -0700 - - A file with multiple fragments. - - The content is arbitrary. - -diff --git a/dir/file1.txt b/dir/file1.txt -index ebe9fa54..fe103e1d 100644 ---- a/dir/file1.txt -+++ b/dir/file1.txt -@@ -3,6 +3,8 @@ fragment 1 - context line --old line 1 --old line 2 - context line -+new line 1 -+new line 2 -+new line 3 - context line --old line 3 -+new line 4 -+new line 5 -@@ -31,2 +33,2 @@ fragment 2 - context line --old line 4 -+new line 6 diff --git a/pkg/gitdiff/testdata/string/binary_modify.patch b/pkg/gitdiff/testdata/string/binary_modify.patch deleted file mode 100644 index 12ddad5..0000000 --- a/pkg/gitdiff/testdata/string/binary_modify.patch +++ /dev/null @@ -1,9 +0,0 @@ -diff --git a/file.bin b/file.bin -index a7f4d5d6975ec021016c02b6d58345ebf434f38c..bdc9a70f055892146612dcdb413f0e339faaa0df 100644 -GIT binary patch -delta 66 -QcmeZhVVvM$!$1K50C&Ox;s5{u - -delta 5 -McmZo+^qAlQ00i9urT_o{ - diff --git a/pkg/gitdiff/testdata/string/binary_modify_nodata.patch b/pkg/gitdiff/testdata/string/binary_modify_nodata.patch deleted file mode 100644 index 833a534..0000000 --- a/pkg/gitdiff/testdata/string/binary_modify_nodata.patch +++ /dev/null @@ -1,3 +0,0 @@ -diff --git a/file.bin b/file.bin -index a7f4d5d..bdc9a70 100644 -Binary files a/file.bin and b/file.bin differ diff --git a/pkg/gitdiff/testdata/string/binary_new.patch b/pkg/gitdiff/testdata/string/binary_new.patch deleted file mode 100644 index c56f35e..0000000 --- a/pkg/gitdiff/testdata/string/binary_new.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff --git a/file.bin b/file.bin -new file mode 100644 -index 0000000000000000000000000000000000000000..a7f4d5d6975ec021016c02b6d58345ebf434f38c -GIT binary patch -literal 72 -zcmV-O0Jr~td-`u6JcK&{KDK= -Date: Tue Apr 2 22:55:40 2019 -0700 - - A file with multiple fragments. - - The content is arbitrary. - -diff --git a/dir/file1.txt b/dir/file1.txt -index ebe9fa54..fe103e1d 100644 ---- a/dir/file1.txt -+++ b/dir/file1.txt -@@ -3,6 +3,8 @@ fragment 1 - context line --old line 1 --old line 2 - context line -+new line 1 -+new line 2 -+new line 3 - context line --old line 3 -+new line 4 -+new line 5 -@@ -31,2 +33,2 @@ fragment 2 - context line --old line 4 -+new line 6 -diff --git a/dir/file2.txt b/dir/file2.txt -index 417ebc70..67514b7f 100644 ---- a/dir/file2.txt -+++ b/dir/file2.txt -@@ -3,6 +3,8 @@ fragment 1 - context line --old line 1 --old line 2 - context line -+new line 1 -+new line 2 -+new line 3 - context line --old line 3 -+new line 4 -+new line 5 -@@ -31,2 +33,2 @@ fragment 2 - context line --old line 4 -+new line 6 diff --git a/pkg/gitdiff/text_test.go b/pkg/gitdiff/text_test.go deleted file mode 100644 index 990b3bc..0000000 --- a/pkg/gitdiff/text_test.go +++ /dev/null @@ -1,488 +0,0 @@ -package gitdiff - -import ( - "io" - "reflect" - "testing" -) - -func TestParseTextFragmentHeader(t *testing.T) { - tests := map[string]struct { - Input string - Output *TextFragment - Err bool - }{ - "shortest": { - Input: "@@ -1 +1 @@\n", - Output: &TextFragment{ - OldPosition: 1, - OldLines: 1, - NewPosition: 1, - NewLines: 1, - }, - }, - "standard": { - Input: "@@ -21,5 +28,9 @@\n", - Output: &TextFragment{ - OldPosition: 21, - OldLines: 5, - NewPosition: 28, - NewLines: 9, - }, - }, - "trailingComment": { - Input: "@@ -21,5 +28,9 @@ func test(n int) {\n", - Output: &TextFragment{ - Comment: "func test(n int) {", - OldPosition: 21, - OldLines: 5, - NewPosition: 28, - NewLines: 9, - }, - }, - "incomplete": { - Input: "@@ -12,3 +2\n", - Err: true, - }, - "badNumbers": { - Input: "@@ -1a,2b +3c,4d @@\n", - Err: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - p := newTestParser(test.Input, true) - - frag, err := p.ParseTextFragmentHeader() - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing header, but got %v", err) - } - return - } - if err != nil { - t.Fatalf("error parsing header: %v", err) - } - - if !reflect.DeepEqual(test.Output, frag) { - t.Errorf("incorrect fragment\nexpected: %+v\nactual: %+v", test.Output, frag) - } - }) - } -} - -func TestParseTextChunk(t *testing.T) { - tests := map[string]struct { - Input string - Fragment TextFragment - - Output *TextFragment - Err bool - }{ - "addWithContext": { - Input: ` context line -+new line 1 -+new line 2 - context line -`, - Fragment: TextFragment{ - OldLines: 2, - NewLines: 4, - }, - Output: &TextFragment{ - OldLines: 2, - NewLines: 4, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpAdd, "new line 1\n"}, - {OpAdd, "new line 2\n"}, - {OpContext, "context line\n"}, - }, - LinesAdded: 2, - LeadingContext: 1, - TrailingContext: 1, - }, - }, - "deleteWithContext": { - Input: ` context line --old line 1 --old line 2 - context line -`, - Fragment: TextFragment{ - OldLines: 4, - NewLines: 2, - }, - Output: &TextFragment{ - OldLines: 4, - NewLines: 2, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 1\n"}, - {OpDelete, "old line 2\n"}, - {OpContext, "context line\n"}, - }, - LinesDeleted: 2, - LeadingContext: 1, - TrailingContext: 1, - }, - }, - "replaceWithContext": { - Input: ` context line --old line 1 -+new line 1 - context line -`, - Fragment: TextFragment{ - OldLines: 3, - NewLines: 3, - }, - Output: &TextFragment{ - OldLines: 3, - NewLines: 3, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 1\n"}, - {OpAdd, "new line 1\n"}, - {OpContext, "context line\n"}, - }, - LinesDeleted: 1, - LinesAdded: 1, - LeadingContext: 1, - TrailingContext: 1, - }, - }, - "middleContext": { - Input: ` context line --old line 1 - context line -+new line 1 - context line -`, - Fragment: TextFragment{ - OldLines: 4, - NewLines: 4, - }, - Output: &TextFragment{ - OldLines: 4, - NewLines: 4, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 1\n"}, - {OpContext, "context line\n"}, - {OpAdd, "new line 1\n"}, - {OpContext, "context line\n"}, - }, - LinesDeleted: 1, - LinesAdded: 1, - LeadingContext: 1, - TrailingContext: 1, - }, - }, - "deleteFinalNewline": { - Input: ` context line --old line 1 -+new line 1 -\ No newline at end of file -`, - Fragment: TextFragment{ - OldLines: 2, - NewLines: 2, - }, - Output: &TextFragment{ - OldLines: 2, - NewLines: 2, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 1\n"}, - {OpAdd, "new line 1"}, - }, - LinesDeleted: 1, - LinesAdded: 1, - LeadingContext: 1, - }, - }, - "addFinalNewline": { - Input: ` context line --old line 1 -\ No newline at end of file -+new line 1 -`, - Fragment: TextFragment{ - OldLines: 2, - NewLines: 2, - }, - Output: &TextFragment{ - OldLines: 2, - NewLines: 2, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 1"}, - {OpAdd, "new line 1\n"}, - }, - LinesDeleted: 1, - LinesAdded: 1, - LeadingContext: 1, - }, - }, - "addAll": { - Input: `+new line 1 -+new line 2 -+new line 3 -`, - Fragment: TextFragment{ - OldLines: 0, - NewLines: 3, - }, - Output: &TextFragment{ - OldLines: 0, - NewLines: 3, - Lines: []Line{ - {OpAdd, "new line 1\n"}, - {OpAdd, "new line 2\n"}, - {OpAdd, "new line 3\n"}, - }, - LinesAdded: 3, - }, - }, - "deleteAll": { - Input: `-old line 1 --old line 2 --old line 3 -`, - Fragment: TextFragment{ - OldLines: 3, - NewLines: 0, - }, - Output: &TextFragment{ - OldLines: 3, - NewLines: 0, - Lines: []Line{ - {OpDelete, "old line 1\n"}, - {OpDelete, "old line 2\n"}, - {OpDelete, "old line 3\n"}, - }, - LinesDeleted: 3, - }, - }, - "emptyContextLine": { - Input: ` context line - -+new line - context line -`, - Fragment: TextFragment{ - OldLines: 3, - NewLines: 4, - }, - Output: &TextFragment{ - OldLines: 3, - NewLines: 4, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpContext, "\n"}, - {OpAdd, "new line\n"}, - {OpContext, "context line\n"}, - }, - LinesAdded: 1, - LeadingContext: 2, - TrailingContext: 1, - }, - }, - "emptyChunk": { - Input: "", - Err: true, - }, - "invalidOperation": { - Input: ` context line -?wat line - context line -`, - Fragment: TextFragment{ - OldLines: 3, - NewLines: 3, - }, - Err: true, - }, - "unbalancedHeader": { - Input: ` context line --old line 1 -+new line 1 - context line -`, - Fragment: TextFragment{ - OldLines: 2, - NewLines: 5, - }, - Err: true, - }, - "onlyContext": { - Input: ` context line - context line -`, - Fragment: TextFragment{ - OldLines: 2, - NewLines: 2, - }, - Err: true, - }, - "unexpectedNoNewlineMarker": { - Input: `\ No newline at end of file`, - Fragment: TextFragment{ - OldLines: 1, - NewLines: 1, - }, - Err: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - p := newTestParser(test.Input, true) - - frag := test.Fragment - err := p.ParseTextChunk(&frag) - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing text chunk, but got %v", err) - } - return - } - if err != nil { - t.Fatalf("error parsing text chunk: %v", err) - } - - if !reflect.DeepEqual(test.Output, &frag) { - t.Errorf("incorrect fragment\nexpected: %+v\nactual: %+v", test.Output, &frag) - } - }) - } -} - -func TestParseTextFragments(t *testing.T) { - tests := map[string]struct { - Input string - File File - - Fragments []*TextFragment - Err bool - }{ - "multipleChanges": { - Input: `@@ -1,3 +1,2 @@ - context line --old line 1 - context line -@@ -8,3 +7,3 @@ - context line --old line 2 -+new line 1 - context line -@@ -15,3 +14,4 @@ - context line --old line 3 -+new line 2 -+new line 3 - context line -`, - Fragments: []*TextFragment{ - { - OldPosition: 1, - OldLines: 3, - NewPosition: 1, - NewLines: 2, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 1\n"}, - {OpContext, "context line\n"}, - }, - LinesDeleted: 1, - LeadingContext: 1, - TrailingContext: 1, - }, - { - OldPosition: 8, - OldLines: 3, - NewPosition: 7, - NewLines: 3, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 2\n"}, - {OpAdd, "new line 1\n"}, - {OpContext, "context line\n"}, - }, - LinesDeleted: 1, - LinesAdded: 1, - LeadingContext: 1, - TrailingContext: 1, - }, - { - OldPosition: 15, - OldLines: 3, - NewPosition: 14, - NewLines: 4, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 3\n"}, - {OpAdd, "new line 2\n"}, - {OpAdd, "new line 3\n"}, - {OpContext, "context line\n"}, - }, - LinesDeleted: 1, - LinesAdded: 2, - LeadingContext: 1, - TrailingContext: 1, - }, - }, - }, - "badNewFile": { - Input: `@@ -1 +1,2 @@ --old line 1 -+new line 1 -+new line 2 -`, - File: File{ - IsNew: true, - }, - Err: true, - }, - "badDeletedFile": { - Input: `@@ -1,2 +1 @@ --old line 1 - context line -`, - File: File{ - IsDelete: true, - }, - Err: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - p := newTestParser(test.Input, true) - - file := test.File - n, err := p.ParseTextFragments(&file) - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing text fragments, but got %v", err) - } - return - } - if err != nil { - t.Fatalf("error parsing text fragments: %v", err) - } - - if len(test.Fragments) != n { - t.Fatalf("incorrect number of added fragments: expected %d, actual %d", len(test.Fragments), n) - } - - for i, frag := range test.Fragments { - if !reflect.DeepEqual(frag, file.TextFragments[i]) { - t.Errorf("incorrect fragment at position %d\nexpected: %+v\nactual: %+v", i, frag, file.TextFragments[i]) - } - } - }) - } -} -- cgit v1.2.3