mirror of
https://github.com/bluekeyes/go-gitdiff
synced 2026-06-08 13:18:30 +00:00
a34334d6ef
These cover some of the possible errors with delta fragments. Many of the same tests could be implemented slightly easier by testing the helper functions, but the infrastructure is already set up to test the full function. This is made easier by the bin.go CLI, which can parse and encode binary patch data. Once parsed, fragments were manipulated with truncate and dd, encoded, and placed in the patch files.
125 lines
2.5 KiB
Go
125 lines
2.5 KiB
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)
|
|
}
|
|
}
|