Skip to content

Instantly share code, notes, and snippets.

@fcharlie

fcharlie/blobview.go

Created Aug 19, 2020
Embed
What would you like to do?
golang lookup git object
package main
import (
"compress/zlib"
"crypto/sha1"
"encoding/hex"
"errors"
"fmt"
"hash"
"io"
"os"
"strconv"
)
// git blob view
// BlobViewer todo
type BlobViewer struct {
w io.Writer
zr io.ReadCloser
fd *os.File
h hash.Hash
}
// NewBlobViewer new blob viewer
func NewBlobViewer(p string, w io.Writer) (*BlobViewer, error) {
fd, err := os.Open(p)
if err != nil {
return nil, err
}
return &BlobViewer{fd: fd, w: w, h: sha1.New()}, nil
}
func (bv *BlobViewer) readUntil(delim byte) ([]byte, error) {
var buf [1]byte
value := make([]byte, 0, 16)
for {
if n, err := bv.zr.Read(buf[:]); err != nil && (err != io.EOF || n == 0) {
if err == io.EOF {
return nil, errors.New("invalid header")
}
return nil, err
}
bv.h.Write(buf[:])
if buf[0] == delim {
return value, nil
}
value = append(value, buf[0])
}
}
// Header Lookup header
func (bv *BlobViewer) Header() error {
raw, err := bv.readUntil(' ')
if err != nil {
return err
}
fmt.Fprintf(os.Stderr, "object type is: \x1b[34m%s\x1b[0m\n", raw)
if raw, err = bv.readUntil(0); err != nil {
return err
}
size, err := strconv.ParseInt(string(raw), 10, 64)
if err != nil {
return err
}
fmt.Fprintf(os.Stderr, "object size: \x1b[34m%d\x1b[0m\n", size)
return nil
}
//Lookup blob details
func (bv *BlobViewer) Lookup() error {
zr, err := zlib.NewReader(bv.fd)
if err != nil {
return err
}
bv.zr = zr
bv.Header()
mw := io.MultiWriter(bv.w, bv.h)
_, _ = io.Copy(mw, bv.zr)
return nil
}
// Close close blob viewer
func (bv *BlobViewer) Close() error {
if bv.zr != nil {
bv.zr.Close()
}
fmt.Fprintf(os.Stderr, "Hash: %s\n", hex.EncodeToString(bv.h.Sum(nil)))
if bv.fd != nil {
return bv.fd.Close()
}
return nil
}
func main() {
if len(os.Args) < 2 {
fmt.Fprintf(os.Stderr, "usage: %s blob-id\n", os.Args[0])
os.Exit(1)
}
bv, err := NewBlobViewer(os.Args[1], os.Stdout)
if err != nil {
fmt.Fprintf(os.Stderr, "open: %s error %v\n", os.Args[1], err)
os.Exit(1)
}
defer bv.Close()
if err := bv.Lookup(); err != nil {
fmt.Fprintf(os.Stderr, "lookup: %s error %v\n", os.Args[1], err)
os.Exit(1)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.