fork of go-gitdiff with jj support
1# go-gitdiff 2 3[![PkgGoDev](https://pkg.go.dev/badge/github.com/bluekeyes/go-gitdiff/gitdiff)](https://pkg.go.dev/github.com/bluekeyes/go-gitdiff/gitdiff) [![Go Report Card](https://goreportcard.com/badge/github.com/bluekeyes/go-gitdiff)](https://goreportcard.com/report/github.com/bluekeyes/go-gitdiff) 4 5A Go library for parsing and applying patches generated by `git diff`, `git 6show`, and `git format-patch`. It can also parse and apply unified diffs 7generated by the standard GNU `diff` tool. 8 9It supports standard line-oriented text patches and Git binary patches, and 10aims to parse anything accepted by the `git apply` command. 11 12```golang 13patch, err := os.Open("changes.patch") 14if err != nil { 15 log.Fatal(err) 16} 17 18// files is a slice of *gitdiff.File describing the files changed in the patch 19// preamble is a string of the content of the patch before the first file 20files, preamble, err := gitdiff.Parse(patch) 21if err != nil { 22 log.Fatal(err) 23} 24 25code, err := os.Open("code.go") 26if err != nil { 27 log.Fatal(err) 28} 29 30// apply the changes in the patch to a source file 31var output bytes.Buffer 32if err := gitdiff.Apply(&output, code, files[0]); err != nil { 33 log.Fatal(err) 34} 35``` 36 37## Development Status 38 39The parsing API and types are complete and I expect will remain stable. Version 400.7.0 introduced a new apply API that may change more in the future to support 41non-strict patch application. 42 43Parsing and strict application are well-covered by unit tests and the library 44is used in a production application that parses and applies thousands of 45patches every day. However, the space of all possible patches is large, so 46there are likely undiscovered bugs. 47 48The parsing code has also had a modest amount of fuzz testing. 49 50## Why another git/unified diff parser? 51 52[Several][sourcegraph] [packages][sergi] with [similar][waigani] 53[functionality][seletskiy] exist, so why did I write another? 54 551. No other packages I found support binary diffs, as generated with the 56 `--binary` flag. This is the main reason for writing a new package, as the 57 format is pretty different from line-oriented diffs and is unique to Git. 58 592. Most other packages only parse patches, so you need additional code to apply 60 them (and if applies are supported, it is only for text files.) 61 623. This package aims to accept anything that `git apply` accepts, and closely 63 follows the logic in [`apply.c`][apply.c]. 64 654. It seemed like a fun project and a way to learn more about Git. 66 67[sourcegraph]: https://github.com/sourcegraph/go-diff 68[sergi]: https://github.com/sergi/go-diff 69[waigani]: https://github.com/waigani/diffparser 70[seletskiy]: https://github.com/seletskiy/godiff 71 72[apply.c]: https://github.com/git/git/blob/master/apply.c 73 74## Differences From Git 75 761. Certain types of invalid input that are accepted by `git apply` generate 77 errors. These include: 78 79 - Numbers immediately followed by non-numeric characters 80 - Trailing characters on a line after valid or expected content 81 - Malformed file header lines (lines that start with `diff --git`) 82 832. Errors for invalid input are generally more verbose and specific than those 84 from `git apply`. 85 863. The translation from C to Go may have introduced inconsistencies in the way 87 Unicode file names are handled; these are bugs, so please report any issues 88 of this type. 89 904. When reading headers, there is no validation that OIDs present on an `index` 91 line are shorter than or equal to the maximum hash length, as this requires 92 knowing if the repository used SHA1 or SHA256 hashes. 93 945. When reading "traditional" patches (those not produced by `git`), prefixes 95 are not stripped from file names; `git apply` attempts to remove prefixes 96 that match the current repository directory/prefix. 97 986. Patches can only be applied in "strict" mode, where the line numbers and 99 context of each fragment must exactly match the source file; `git apply` 100 implements a search algorithm that tries different lines and amounts of 101 context, with further options to normalize or ignore whitespace changes. 102 1037. When parsing mail-formatted patch headers, leading and trailing whitespace 104 is always removed from `Subject` lines. There is no exact equivalent to `git 105 mailinfo -k`.