diff options
| author | Anton Medvedev <anton@medv.io> | 2025-11-30 12:46:34 +0100 |
|---|---|---|
| committer | Anton Medvedev <anton@medv.io> | 2025-11-30 12:46:34 +0100 |
| commit | f6b0f38af648d028422a7494378b5dabdc90573f (patch) | |
| tree | 3c26cfc269c021300a2d1e4e02623dd440c20226 /pkg/gitdiff/testdata/apply/bin.go | |
First commit
Diffstat (limited to 'pkg/gitdiff/testdata/apply/bin.go')
| -rw-r--r-- | pkg/gitdiff/testdata/apply/bin.go | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/pkg/gitdiff/testdata/apply/bin.go b/pkg/gitdiff/testdata/apply/bin.go new file mode 100644 index 0000000..e34f06b --- /dev/null +++ b/pkg/gitdiff/testdata/apply/bin.go @@ -0,0 +1,124 @@ +//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) + } +} |
