//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) } }