feat/multi-repo
  1//go:build ignore
  2
  3// bin.go is a helper CLI to manipulate binary diff data for testing purposes.
  4// It can decode patches generated by git using the standard parsing functions
  5// or it can encode binary data back into the format expected by Git. It
  6// operates on stdin writes results (possibly binary) to stdout.
  7
  8package main
  9
 10import (
 11	"bytes"
 12	"compress/zlib"
 13	"encoding/binary"
 14	"flag"
 15	"io/ioutil"
 16	"log"
 17	"os"
 18	"strings"
 19
 20	"github.com/bluekeyes/go-gitdiff/gitdiff"
 21)
 22
 23var (
 24	b85Powers = []uint32{52200625, 614125, 7225, 85, 1}
 25	b85Alpha  = []byte(
 26		"0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "!#$%&()*+-;<=>?@^_`{|}~",
 27	)
 28)
 29
 30var mode string
 31
 32func base85Encode(data []byte) []byte {
 33	chunks, remaining := len(data)/4, len(data)%4
 34	if remaining > 0 {
 35		data = append(data, make([]byte, 4-remaining)...)
 36		chunks++
 37	}
 38
 39	var n int
 40	out := make([]byte, 5*chunks)
 41
 42	for i := 0; i < len(data); i += 4 {
 43		v := binary.BigEndian.Uint32(data[i : i+4])
 44		for j := 0; j < 5; j++ {
 45			p := v / b85Powers[j]
 46			out[n+j] = b85Alpha[p]
 47			v -= b85Powers[j] * p
 48		}
 49		n += 5
 50	}
 51
 52	return out
 53}
 54
 55func compress(data []byte) ([]byte, error) {
 56	var b bytes.Buffer
 57	w := zlib.NewWriter(&b)
 58
 59	if _, err := w.Write(data); err != nil {
 60		return nil, err
 61	}
 62	if err := w.Close(); err != nil {
 63		return nil, err
 64	}
 65
 66	return b.Bytes(), nil
 67}
 68
 69func wrap(data []byte) string {
 70	var s strings.Builder
 71	for i := 0; i < len(data); i += 52 {
 72		c := 52
 73		if c > len(data)-i {
 74			c = len(data) - i
 75		}
 76		b := (c / 5) * 4
 77
 78		if b <= 26 {
 79			s.WriteByte(byte('A' + b - 1))
 80		} else {
 81			s.WriteByte(byte('a' + b - 27))
 82		}
 83		s.Write(data[i : i+c])
 84		s.WriteByte('\n')
 85	}
 86	return s.String()
 87}
 88
 89func init() {
 90	flag.StringVar(&mode, "mode", "parse", "operation mode, one of 'parse' or 'encode'")
 91}
 92
 93func main() {
 94	flag.Parse()
 95
 96	switch mode {
 97	case "parse":
 98		files, _, err := gitdiff.Parse(os.Stdin)
 99		if err != nil {
100			log.Fatalf("failed to parse file: %v", err)
101		}
102		if len(files) != 1 {
103			log.Fatalf("patch contains more than one file: %d", len(files))
104		}
105		if files[0].BinaryFragment == nil {
106			log.Fatalf("patch file does not contain a binary fragment")
107		}
108		os.Stdout.Write(files[0].BinaryFragment.Data)
109
110	case "encode":
111		data, err := ioutil.ReadAll(os.Stdin)
112		if err != nil {
113			log.Fatalf("failed to read input: %v", err)
114		}
115		data, err = compress(data)
116		if err != nil {
117			log.Fatalf("failed to compress data: %v", err)
118		}
119		os.Stdout.WriteString(wrap(base85Encode(data)))
120
121	default:
122		log.Fatalf("unknown mode: %s", mode)
123	}
124}