Update vendor directory and make necessary code changes

Fixes for new geth version
This commit is contained in:
Elizabeth Engelman
2019-09-25 16:32:27 -05:00
parent 20ce0ab852
commit 36533f7c3f
3490 changed files with 903670 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
os:
- linux
language: go
go:
- 1.11.x
env:
global:
- GOTFLAGS="-race"
matrix:
- BUILD_DEPTYPE=gx
- BUILD_DEPTYPE=gomod
# disable travis install
install:
- true
script:
- bash <(curl -s https://raw.githubusercontent.com/ipfs/ci-helpers/master/travis-ci/run-standard-tests.sh)
cache:
directories:
- $GOPATH/src/gx
- $GOPATH/pkg/mod
- $HOME/.cache/go-build
notifications:
email: false
+99
View File
@@ -0,0 +1,99 @@
Git ipld format
==================
[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io)
[![](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io/)
[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)
[![Coverage Status](https://codecov.io/gh/ipfs/go-ipld-git/branch/master/graph/badge.svg)](https://codecov.io/gh/ipfs/go-ipld-git/branch/master)
[![Travis CI](https://travis-ci.org/ipfs/go-ipld-git.svg?branch=master)](https://travis-ci.org/ipfs/go-ipld-git)
> An ipld codec for git objects allowing path traversals across the git graph!
Note: This is WIP and may not be an entirely correct parser.
## Table of Contents
- [Install](#install)
- [About](#about)
- [Contribute](#contribute)
- [License](#license)
## Install
```sh
go get github.com/ipfs/go-ipld-git
```
## About
This is an IPLD codec which handles git objects. Objects are transformed
into IPLD graph in the following way:
* Commit:
```json
{
"author": {
"date": "1503667703 +0200",
"email": "author@mail",
"name": "Author Name"
},
"committer": {
"date": "1503667703 +0200",
"email": "author@mail",
"name": "Author Name"
},
"message": "Commit Message\n",
"parents": [
<LINK>, <LINK>, ...
],
"tree": <LINK>
}
```
* Tag:
```json
{
"message": "message\n",
"object": {
"/": "baf4bcfg3mbz3yj3njqyr3ifdaqyfv3prei6h6bq"
},
"tag": "tagname",
"tagger": {
"date": "1503667703 +0200",
"email": "author@mail",
"name": "Author Name"
},
"type": "commit"
}
```
* Tree:
```json
{
"file.name": {
"mode": "100664",
"hash": <LINK>
},
"directoryname": {
"mode": "40000",
"hash": <LINK>
},
...
}
```
* Blob:
```json
"<base64 of 'blob <size>\0<data>'>"
```
## Contribute
PRs are welcome!
Small note: If editing the Readme, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification.
## License
MIT © Jeromy Johnson
+71
View File
@@ -0,0 +1,71 @@
package ipldgit
import (
"encoding/json"
"errors"
cid "github.com/ipfs/go-cid"
node "github.com/ipfs/go-ipld-format"
)
type Blob struct {
rawData []byte
cid cid.Cid
}
func (b *Blob) Cid() cid.Cid {
return b.cid
}
func (b *Blob) Copy() node.Node {
nb := *b
return &nb
}
func (b *Blob) Links() []*node.Link {
return nil
}
func (b *Blob) Resolve(_ []string) (interface{}, []string, error) {
return nil, nil, errors.New("no such link")
}
func (b *Blob) ResolveLink(_ []string) (*node.Link, []string, error) {
return nil, nil, errors.New("no such link")
}
func (b *Blob) Loggable() map[string]interface{} {
return map[string]interface{}{
"type": "git_blob",
}
}
func (b *Blob) MarshalJSON() ([]byte, error) {
return json.Marshal(b.rawData)
}
func (b *Blob) RawData() []byte {
return []byte(b.rawData)
}
func (b *Blob) Size() (uint64, error) {
return uint64(len(b.rawData)), nil
}
func (b *Blob) Stat() (*node.NodeStat, error) {
return &node.NodeStat{}, nil
}
func (b *Blob) String() string {
return "[git blob]"
}
func (b *Blob) Tree(p string, depth int) []string {
return nil
}
func (b *Blob) GitSha() []byte {
return cidToSha(b.Cid())
}
var _ node.Node = (*Blob)(nil)
+3
View File
@@ -0,0 +1,3 @@
coverage:
range: "50...100"
comment: off
+286
View File
@@ -0,0 +1,286 @@
package ipldgit
import (
"bytes"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"strconv"
"sync"
cid "github.com/ipfs/go-cid"
node "github.com/ipfs/go-ipld-format"
)
type Commit struct {
DataSize string `json:"-"`
GitTree cid.Cid `json:"tree"`
Parents []cid.Cid `json:"parents"`
Message string `json:"message"`
Author *PersonInfo `json:"author"`
Committer *PersonInfo `json:"committer"`
Encoding string `json:"encoding,omitempty"`
Sig *GpgSig `json:"signature,omitempty"`
MergeTag []*MergeTag `json:"mergetag,omitempty"`
// Other contains all the non-standard headers, such as 'HG:extra'
Other []string `json:"other,omitempty"`
cid cid.Cid
rawData []byte
rawDataOnce sync.Once
}
type PersonInfo struct {
Name string
Email string
Date string
Timezone string
}
func (pi *PersonInfo) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]string{
"name": pi.Name,
"email": pi.Email,
"date": pi.Date + " " + pi.Timezone,
})
}
func (pi *PersonInfo) String() string {
f := "%s <%s>"
arg := []interface{}{pi.Name, pi.Email}
if pi.Date != "" {
f = f + " %s"
arg = append(arg, pi.Date)
}
if pi.Timezone != "" {
f = f + " %s"
arg = append(arg, pi.Timezone)
}
return fmt.Sprintf(f, arg...)
}
func (pi *PersonInfo) tree(name string, depth int) []string {
if depth == 1 {
return []string{name}
}
return []string{name + "/name", name + "/email", name + "/date"}
}
func (pi *PersonInfo) resolve(p []string) (interface{}, []string, error) {
switch p[0] {
case "name":
return pi.Name, p[1:], nil
case "email":
return pi.Email, p[1:], nil
case "date":
return pi.Date + " " + pi.Timezone, p[1:], nil
default:
return nil, nil, errors.New("no such link")
}
}
type MergeTag struct {
Object cid.Cid `json:"object"`
Type string `json:"type"`
Tag string `json:"tag"`
Tagger *PersonInfo `json:"tagger"`
Text string `json:"text"`
}
type GpgSig struct {
Text string
}
func (c *Commit) Cid() cid.Cid {
return c.cid
}
func (c *Commit) Copy() node.Node {
nc := *c
return &nc
}
func (c *Commit) Links() []*node.Link {
out := []*node.Link{
{Cid: c.GitTree},
}
for _, p := range c.Parents {
out = append(out, &node.Link{Cid: p})
}
return out
}
func (c *Commit) Loggable() map[string]interface{} {
return map[string]interface{}{
"type": "git_commit",
}
}
func (c *Commit) RawData() []byte {
c.rawDataOnce.Do(func() {
buf := new(bytes.Buffer)
fmt.Fprintf(buf, "commit %s\x00", c.DataSize)
fmt.Fprintf(buf, "tree %s\n", hex.EncodeToString(cidToSha(c.GitTree)))
for _, p := range c.Parents {
fmt.Fprintf(buf, "parent %s\n", hex.EncodeToString(cidToSha(p)))
}
fmt.Fprintf(buf, "author %s\n", c.Author.String())
fmt.Fprintf(buf, "committer %s\n", c.Committer.String())
if len(c.Encoding) > 0 {
fmt.Fprintf(buf, "encoding %s\n", c.Encoding)
}
for _, mtag := range c.MergeTag {
fmt.Fprintf(buf, "mergetag object %s\n", hex.EncodeToString(cidToSha(mtag.Object)))
fmt.Fprintf(buf, " type %s\n", mtag.Type)
fmt.Fprintf(buf, " tag %s\n", mtag.Tag)
fmt.Fprintf(buf, " tagger %s\n \n", mtag.Tagger.String())
fmt.Fprintf(buf, "%s", mtag.Text)
}
if c.Sig != nil {
fmt.Fprintln(buf, "gpgsig -----BEGIN PGP SIGNATURE-----")
fmt.Fprint(buf, c.Sig.Text)
fmt.Fprintln(buf, " -----END PGP SIGNATURE-----")
}
for _, line := range c.Other {
fmt.Fprintln(buf, line)
}
fmt.Fprintf(buf, "\n%s", c.Message)
c.rawData = buf.Bytes()
})
return c.rawData
}
func (c *Commit) Resolve(path []string) (interface{}, []string, error) {
if len(path) == 0 {
return nil, nil, fmt.Errorf("zero length path")
}
switch path[0] {
case "parents":
if len(path) == 1 {
return c.Parents, nil, nil
}
i, err := strconv.Atoi(path[1])
if err != nil {
return nil, nil, err
}
if i < 0 || i >= len(c.Parents) {
return nil, nil, fmt.Errorf("index out of range")
}
return &node.Link{Cid: c.Parents[i]}, path[2:], nil
case "author":
if len(path) == 1 {
return c.Author, nil, nil
}
return c.Author.resolve(path[1:])
case "committer":
if len(path) == 1 {
return c.Committer, nil, nil
}
return c.Committer.resolve(path[1:])
case "signature":
return c.Sig.Text, path[1:], nil
case "message":
return c.Message, path[1:], nil
case "tree":
return &node.Link{Cid: c.GitTree}, path[1:], nil
case "mergetag":
if len(path) == 1 {
return c.MergeTag, nil, nil
}
i, err := strconv.Atoi(path[1])
if err != nil {
return nil, nil, err
}
if i < 0 || i >= len(c.MergeTag) {
return nil, nil, fmt.Errorf("index out of range")
}
if len(path) == 2 {
return c.MergeTag[i], nil, nil
}
return c.MergeTag[i].resolve(path[2:])
default:
return nil, nil, errors.New("no such link")
}
}
func (c *Commit) ResolveLink(path []string) (*node.Link, []string, error) {
out, rest, err := c.Resolve(path)
if err != nil {
return nil, nil, err
}
lnk, ok := out.(*node.Link)
if !ok {
return nil, nil, errors.New("not a link")
}
return lnk, rest, nil
}
func (c *Commit) Size() (uint64, error) {
return uint64(len(c.RawData())), nil
}
func (c *Commit) Stat() (*node.NodeStat, error) {
return &node.NodeStat{}, nil
}
func (c *Commit) String() string {
return "[git commit object]"
}
func (c *Commit) Tree(p string, depth int) []string {
if depth != -1 {
panic("proper tree not yet implemented")
}
tree := []string{"tree", "parents", "message", "gpgsig"}
tree = append(tree, c.Author.tree("author", depth)...)
tree = append(tree, c.Committer.tree("committer", depth)...)
for i := range c.Parents {
tree = append(tree, fmt.Sprintf("parents/%d", i))
}
return tree
}
func (c *Commit) GitSha() []byte {
return cidToSha(c.Cid())
}
func (t *MergeTag) resolve(path []string) (interface{}, []string, error) {
if len(path) == 0 {
return nil, nil, fmt.Errorf("zero length path")
}
switch path[0] {
case "object":
return &node.Link{Cid: t.Object}, path[1:], nil
case "tag":
return t.Tag, path[1:], nil
case "tagger":
if len(path) == 1 {
return t.Tagger, nil, nil
}
return t.Tagger.resolve(path[1:])
case "text":
return t.Text, path[1:], nil
case "type":
return t.Type, path[1:], nil
default:
return nil, nil, errors.New("no such link")
}
}
var _ node.Node = (*Commit)(nil)
+478
View File
@@ -0,0 +1,478 @@
package ipldgit
import (
"bufio"
"bytes"
"compress/zlib"
"encoding/hex"
"errors"
"fmt"
"io"
"io/ioutil"
"strconv"
"strings"
blocks "github.com/ipfs/go-block-format"
cid "github.com/ipfs/go-cid"
node "github.com/ipfs/go-ipld-format"
mh "github.com/multiformats/go-multihash"
)
func DecodeBlock(block blocks.Block) (node.Node, error) {
prefix := block.Cid().Prefix()
if prefix.Codec != cid.GitRaw || prefix.MhType != mh.SHA1 || prefix.MhLength != mh.DefaultLengths[mh.SHA1] {
return nil, errors.New("invalid CID prefix")
}
return ParseObjectFromBuffer(block.RawData())
}
var _ node.DecodeBlockFunc = DecodeBlock
func ParseObjectFromBuffer(b []byte) (node.Node, error) {
return ParseObject(bytes.NewReader(b))
}
func ParseCompressedObject(r io.Reader) (node.Node, error) {
rc, err := zlib.NewReader(r)
if err != nil {
return nil, err
}
defer rc.Close()
return ParseObject(rc)
}
func ParseObject(r io.Reader) (node.Node, error) {
rd := bufio.NewReader(r)
typ, err := rd.ReadString(' ')
if err != nil {
return nil, err
}
typ = typ[:len(typ)-1]
switch typ {
case "tree":
return ReadTree(rd)
case "commit":
return ReadCommit(rd)
case "blob":
return ReadBlob(rd)
case "tag":
return ReadTag(rd)
default:
return nil, fmt.Errorf("unrecognized object type: %s", typ)
}
}
func ReadBlob(rd *bufio.Reader) (*Blob, error) {
size, err := rd.ReadString(0)
if err != nil {
return nil, err
}
sizen, err := strconv.Atoi(size[:len(size)-1])
if err != nil {
return nil, err
}
buf := new(bytes.Buffer)
fmt.Fprintf(buf, "blob %d\x00", sizen)
n, err := io.Copy(buf, rd)
if err != nil {
return nil, err
}
if n != int64(sizen) {
return nil, fmt.Errorf("blob size was not accurate")
}
out := &Blob{}
out.rawData = buf.Bytes()
out.cid = hashObject(out.RawData())
return out, nil
}
func ReadCommit(rd *bufio.Reader) (*Commit, error) {
size, err := rd.ReadString(0)
if err != nil {
return nil, err
}
out := &Commit{
DataSize: size[:len(size)-1],
}
for {
line, _, err := rd.ReadLine()
if err != nil {
if err == io.EOF {
break
}
return nil, err
}
err = parseCommitLine(out, line, rd)
if err != nil {
return nil, err
}
}
out.cid = hashObject(out.RawData())
return out, nil
}
func parseCommitLine(out *Commit, line []byte, rd *bufio.Reader) error {
switch {
case bytes.HasPrefix(line, []byte("tree ")):
sha, err := hex.DecodeString(string(line[5:]))
if err != nil {
return err
}
out.GitTree = shaToCid(sha)
case bytes.HasPrefix(line, []byte("parent ")):
psha, err := hex.DecodeString(string(line[7:]))
if err != nil {
return err
}
out.Parents = append(out.Parents, shaToCid(psha))
case bytes.HasPrefix(line, []byte("author ")):
a, err := parsePersonInfo(line)
if err != nil {
return err
}
out.Author = a
case bytes.HasPrefix(line, []byte("committer ")):
c, err := parsePersonInfo(line)
if err != nil {
return err
}
out.Committer = c
case bytes.HasPrefix(line, []byte("encoding ")):
out.Encoding = string(line[9:])
case bytes.HasPrefix(line, []byte("mergetag object ")):
sha, err := hex.DecodeString(string(line)[16:])
if err != nil {
return err
}
mt, rest, err := ReadMergeTag(sha, rd)
if err != nil {
return err
}
out.MergeTag = append(out.MergeTag, mt)
if rest != nil {
err = parseCommitLine(out, rest, rd)
if err != nil {
return err
}
}
case bytes.HasPrefix(line, []byte("gpgsig ")):
sig, err := ReadGpgSig(rd)
if err != nil {
return err
}
out.Sig = sig
case len(line) == 0:
rest, err := ioutil.ReadAll(rd)
if err != nil {
return err
}
out.Message = string(rest)
default:
out.Other = append(out.Other, string(line))
}
return nil
}
func ReadTag(rd *bufio.Reader) (*Tag, error) {
size, err := rd.ReadString(0)
if err != nil {
return nil, err
}
out := &Tag{
dataSize: size[:len(size)-1],
}
for {
line, _, err := rd.ReadLine()
if err != nil {
if err == io.EOF {
break
}
return nil, err
}
switch {
case bytes.HasPrefix(line, []byte("object ")):
sha, err := hex.DecodeString(string(line[7:]))
if err != nil {
return nil, err
}
out.Object = shaToCid(sha)
case bytes.HasPrefix(line, []byte("tag ")):
out.Tag = string(line[4:])
case bytes.HasPrefix(line, []byte("tagger ")):
c, err := parsePersonInfo(line)
if err != nil {
return nil, err
}
out.Tagger = c
case bytes.HasPrefix(line, []byte("type ")):
out.Type = string(line[5:])
case len(line) == 0:
rest, err := ioutil.ReadAll(rd)
if err != nil {
return nil, err
}
out.Message = string(rest)
default:
fmt.Println("unhandled line: ", string(line))
}
}
out.cid = hashObject(out.RawData())
return out, nil
}
func hashObject(data []byte) cid.Cid {
c, err := cid.Prefix{
MhType: mh.SHA1,
MhLength: -1,
Codec: cid.GitRaw,
Version: 1,
}.Sum(data)
if err != nil {
panic(err)
}
return c
}
func ReadMergeTag(hash []byte, rd *bufio.Reader) (*MergeTag, []byte, error) {
out := new(MergeTag)
out.Object = shaToCid(hash)
for {
line, _, err := rd.ReadLine()
if err != nil {
if err == io.EOF {
break
}
return nil, nil, err
}
switch {
case bytes.HasPrefix(line, []byte(" type ")):
out.Type = string(line[6:])
case bytes.HasPrefix(line, []byte(" tag ")):
out.Tag = string(line[5:])
case bytes.HasPrefix(line, []byte(" tagger ")):
tagger, err := parsePersonInfo(line[1:])
if err != nil {
return nil, nil, err
}
out.Tagger = tagger
case string(line) == " ":
for {
line, _, err := rd.ReadLine()
if err != nil {
return nil, nil, err
}
if !bytes.HasPrefix(line, []byte(" ")) {
return out, line, nil
}
out.Text += string(line) + "\n"
}
}
}
return out, nil, nil
}
func ReadGpgSig(rd *bufio.Reader) (*GpgSig, error) {
line, _, err := rd.ReadLine()
if err != nil {
return nil, err
}
out := new(GpgSig)
if string(line) != " " {
if strings.HasPrefix(string(line), " Version: ") || strings.HasPrefix(string(line), " Comment: ") {
out.Text += string(line) + "\n"
} else {
return nil, fmt.Errorf("expected first line of sig to be a single space or version")
}
} else {
out.Text += " \n"
}
for {
line, _, err := rd.ReadLine()
if err != nil {
return nil, err
}
if bytes.Equal(line, []byte(" -----END PGP SIGNATURE-----")) {
break
}
out.Text += string(line) + "\n"
}
return out, nil
}
func parsePersonInfo(line []byte) (*PersonInfo, error) {
parts := bytes.Split(line, []byte{' '})
if len(parts) < 3 {
fmt.Println(string(line))
return nil, fmt.Errorf("incorrectly formatted person info line")
}
//TODO: just use regex?
//skip prefix
at := 1
var pi PersonInfo
var name string
for {
if at == len(parts) {
return nil, fmt.Errorf("invalid personInfo: %s\n", line)
}
part := parts[at]
if len(part) != 0 {
if part[0] == '<' {
break
}
name += string(part) + " "
} else if len(name) > 0 {
name += " "
}
at++
}
if len(name) != 0 {
pi.Name = name[:len(name)-1]
}
var email string
for {
if at == len(parts) {
return nil, fmt.Errorf("invalid personInfo: %s\n", line)
}
part := parts[at]
if part[0] == '<' {
part = part[1:]
}
at++
if part[len(part)-1] == '>' {
email += string(part[:len(part)-1])
break
}
email += string(part) + " "
}
pi.Email = email
if at == len(parts) {
return &pi, nil
}
pi.Date = string(parts[at])
at++
if at == len(parts) {
return &pi, nil
}
pi.Timezone = string(parts[at])
return &pi, nil
}
func ReadTree(rd *bufio.Reader) (*Tree, error) {
lstr, err := rd.ReadString(0)
if err != nil {
return nil, err
}
lstr = lstr[:len(lstr)-1]
n, err := strconv.Atoi(lstr)
if err != nil {
return nil, err
}
t := &Tree{
entries: make(map[string]*TreeEntry),
size: n,
}
var order []string
for {
e, err := ReadEntry(rd)
if err != nil {
if err == io.EOF {
break
}
return nil, err
}
order = append(order, e.name)
t.entries[e.name] = e
}
t.order = order
t.cid = hashObject(t.RawData())
return t, nil
}
func cidToSha(c cid.Cid) []byte {
h := c.Hash()
return h[len(h)-20:]
}
func shaToCid(sha []byte) cid.Cid {
h, _ := mh.Encode(sha, mh.SHA1)
return cid.NewCidV1(cid.GitRaw, h)
}
func ReadEntry(r *bufio.Reader) (*TreeEntry, error) {
data, err := r.ReadString(' ')
if err != nil {
return nil, err
}
data = data[:len(data)-1]
name, err := r.ReadString(0)
if err != nil {
return nil, err
}
name = name[:len(name)-1]
sha := make([]byte, 20)
_, err = io.ReadFull(r, sha)
if err != nil {
return nil, err
}
return &TreeEntry{
name: name,
Mode: data,
Hash: shaToCid(sha),
}, nil
}
+8
View File
@@ -0,0 +1,8 @@
module github.com/ipfs/go-ipld-git
require (
github.com/ipfs/go-block-format v0.0.2
github.com/ipfs/go-cid v0.0.2
github.com/ipfs/go-ipld-format v0.0.1
github.com/multiformats/go-multihash v0.0.1
)
+30
View File
@@ -0,0 +1,30 @@
github.com/gxed/hashland/keccakpg v0.0.1 h1:wrk3uMNaMxbXiHibbPO4S0ymqJMm41WiudyFSs7UnsU=
github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU=
github.com/gxed/hashland/murmur3 v0.0.1 h1:SheiaIt0sda5K+8FLz952/1iWS9zrnKsEJaOJu4ZbSc=
github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48=
github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE=
github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY=
github.com/ipfs/go-cid v0.0.1 h1:GBjWPktLnNyX0JiQCNFpUuUSoMw5KMyqrsejHYlILBE=
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.2 h1:tuuKaZPU1M6HcejsO3AcYWW8sZ8MTvyxfc4uqB4eFE8=
github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-ipfs-util v0.0.1 h1:Wz9bL2wB2YBJqggkA4dD7oSmqB4cAnpNbGrlHJulv50=
github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc=
github.com/ipfs/go-ipld-format v0.0.1 h1:HCu4eB/Gh+KD/Q0M8u888RFkorTWNIL3da4oc5dwc80=
github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dCDnkOJhcZkms=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XCFOweFD3BNESdnO8ewyYTFT2R+/b8FQ=
github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
github.com/mr-tron/base58 v1.1.0 h1:Y51FGVJ91WBqCEabAi5OPUz38eAx8DakuAm5svLcsfQ=
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI=
github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA=
github.com/multiformats/go-multibase v0.0.1 h1:PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA=
github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs=
github.com/multiformats/go-multihash v0.0.1 h1:HHwN1K12I+XllBCrqKnhX949Orn4oawPkegHMu2vDqQ=
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/sys v0.0.0-20190219092855-153ac476189d h1:Z0Ahzd7HltpJtjAHHxX8QFP3j1yYgiuvjbjRzDj/KH0=
golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+119
View File
@@ -0,0 +1,119 @@
#!/usr/bin/env bash
set -x
CUR_DIR=$(pwd)
TEST_DIR=$(mktemp -d)
cd ${TEST_DIR}
git init
# Test generic commit/blob
git config user.name "John Doe"
git config user.email johndoe@example.com
echo "Hello world" > file
git add file
git commit -m "Init"
# Test generic commit/tree/blob, weird person info
mkdir dir
mkdir dir/subdir
mkdir dir2
echo "qwerty" > dir/f1
echo "123456" > dir/subdir/f2
echo "',.pyf" > dir2/f3
git add .
git config user.name "John Doe & John Other"
git config user.email "johndoe@example.com, johnother@example.com"
git commit -m "Commit 2"
# Test merge-tag
git config user.name "John Doe"
git config user.email johndoe@example.com
git branch dev
git checkout dev
echo ";qjkxb" > dir/f4
git add dir/f4
git commit -m "Release"
git tag -a v1 -m "Some version"
git checkout master
## defer eyes.Open()
## eyes.Close()
git cat-file tag $(cat .git/refs/tags/v1) | head -n4 | sed 's/v1/v1sig/g' > sigobj
cat >>sigobj <<EOF
Some signed version
-----BEGIN PGP SIGNATURE-----
NotReallyABase64Signature
ButItsGoodEnough
-----END PGP SIGNATURE-----
EOF
cat <(printf "tag %d\0" $(wc -c sigobj | cut -d' ' -f1); cat sigobj) > sigtag
FILE=.git/objects/$(sha1sum sigtag | cut -d' ' -f1 | sed 's/../\0\//')
mkdir -p $(dirname ${FILE})
cat sigtag | zlib-flate -compress > ${FILE}
echo $(sha1sum sigtag | cut -d' ' -f1) > .git/refs/tags/v1sig
git merge v1sig --no-ff -m "Merge tag v1"
# Test encoding
git config i18n.commitencoding "ISO-8859-1"
echo "fgcrl" > f6
git add f6
git commit -m "Encoded"
# Test iplBlob/tree tags
git tag -a v1-file -m "Some file" 933b7583b7767b07ea4cf242c1be29162eb8bb85
git tag -a v1-tree -m "Some tree" 672ef117424f54b71e5e058d1184de6a07450d0e
# Create test 'signed' objects
git cat-file commit $(cat .git/refs/heads/master) | head -n4 > sigobj
echo "gpgsig -----BEGIN PGP SIGNATURE-----" >> sigobj
echo " " >> sigobj
echo " NotReallyABase64Signature" >> sigobj
echo " ButItsGoodEnough" >> sigobj
echo " -----END PGP SIGNATURE-----" >> sigobj
echo "" >> sigobj
echo "Encoded" >> sigobj
cat <(printf "commit %d\0" $(wc -c sigobj | cut -d' ' -f1); cat sigobj) > sigcommit
FILE=.git/objects/$(sha1sum sigcommit | cut -d' ' -f1 | sed 's/../\0\//')
mkdir -p $(dirname ${FILE})
cat sigcommit | zlib-flate -compress > ${FILE}
git cat-file commit $(cat .git/refs/heads/master) | head -n4 > sigobj
echo "gpgsig -----BEGIN PGP SIGNATURE-----" >> sigobj
echo " Version: 0.1.2" >> sigobj
echo " " >> sigobj
echo " NotReallyABase64Signature" >> sigobj
echo " ButItsGoodEnough" >> sigobj
echo " -----END PGP SIGNATURE-----" >> sigobj
echo " " >> sigobj
echo "" >> sigobj
echo "Encoded" >> sigobj
cat <(printf "commit %d\0" $(wc -c sigobj | cut -d' ' -f1); cat sigobj) > sigcommit
FILE=.git/objects/$(sha1sum sigcommit | cut -d' ' -f1 | sed 's/../\0\//')
mkdir -p $(dirname ${FILE})
cat sigcommit | zlib-flate -compress >> ${FILE}
rm sigobj sigcommit
# Create test archive, clean up
tar czf git.tar.gz .git
mv git.tar.gz ${CUR_DIR}/testdata.tar.gz
cd ${CUR_DIR}
rm -rf ${TEST_DIR}
+42
View File
@@ -0,0 +1,42 @@
{
"author": "whyrusleeping",
"bugs": {
"url": "https://github.com/ipfs/go-ipld-git"
},
"gx": {
"dvcsimport": "github.com/ipfs/go-ipld-git"
},
"gxDependencies": [
{
"author": "whyrusleeping",
"hash": "QmZ6nzCLwGLVfRzYLpD7pW6UNuBDKEcA2imJtVpbEx2rxy",
"name": "go-ipld-format",
"version": "0.8.1"
},
{
"author": "whyrusleeping",
"hash": "QmTbxNB1NwDesLmKTscr4udL2tVP7MaxvXnD1D9yX7g3PN",
"name": "go-cid",
"version": "0.9.3"
},
{
"author": "stebalien",
"hash": "QmYYLnAzR28nAQ4U5MFniLprnktu6eTFKibeNt96V21EZK",
"name": "go-block-format",
"version": "0.2.2"
},
{
"author": "multiformats",
"hash": "QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW",
"name": "go-multihash",
"version": "1.0.9"
}
],
"gxVersion": "0.10.0",
"language": "go",
"license": "",
"name": "go-ipld-git",
"releaseCmd": "git commit -a -m \"gx publish $VERSION\"",
"version": "0.3.6"
}
+136
View File
@@ -0,0 +1,136 @@
package ipldgit
import (
"bytes"
"encoding/hex"
"errors"
"fmt"
"sync"
cid "github.com/ipfs/go-cid"
node "github.com/ipfs/go-ipld-format"
)
type Tag struct {
Object cid.Cid `json:"object"`
Type string `json:"type"`
Tag string `json:"tag"`
Tagger *PersonInfo `json:"tagger"`
Message string `json:"message"`
dataSize string
cid cid.Cid
rawData []byte
rawDataOnce sync.Once
}
func (t *Tag) Cid() cid.Cid {
return t.cid
}
func (t *Tag) Copy() node.Node {
nt := *t
return &nt
}
func (t *Tag) Links() []*node.Link {
return []*node.Link{{Cid: t.Object}}
}
func (t *Tag) Loggable() map[string]interface{} {
return map[string]interface{}{
"type": "git_tag",
}
}
func (t *Tag) RawData() []byte {
t.rawDataOnce.Do(func() {
buf := new(bytes.Buffer)
fmt.Fprintf(buf, "tag %s\x00", t.dataSize)
fmt.Fprintf(buf, "object %s\n", hex.EncodeToString(cidToSha(t.Object)))
fmt.Fprintf(buf, "type %s\n", t.Type)
fmt.Fprintf(buf, "tag %s\n", t.Tag)
if t.Tagger != nil {
fmt.Fprintf(buf, "tagger %s\n", t.Tagger.String())
}
if t.Message != "" {
fmt.Fprintf(buf, "\n%s", t.Message)
}
t.rawData = buf.Bytes()
})
return t.rawData
}
func (t *Tag) Resolve(path []string) (interface{}, []string, error) {
if len(path) == 0 {
return nil, nil, fmt.Errorf("zero length path")
}
switch path[0] {
case "object":
return &node.Link{Cid: t.Object}, path[1:], nil
case "type":
return t.Type, path[1:], nil
case "tagger":
if len(path) == 1 {
return t.Tagger, nil, nil
}
return t.Tagger.resolve(path[1:])
case "message":
return t.Message, path[1:], nil
case "tag":
return t.Tag, path[1:], nil
default:
return nil, nil, errors.New("no such link")
}
}
func (t *Tag) ResolveLink(path []string) (*node.Link, []string, error) {
out, rest, err := t.Resolve(path)
if err != nil {
return nil, nil, err
}
lnk, ok := out.(*node.Link)
if !ok {
return nil, nil, errors.New("not a link")
}
return lnk, rest, nil
}
func (t *Tag) Size() (uint64, error) {
return uint64(len(t.RawData())), nil
}
func (t *Tag) Stat() (*node.NodeStat, error) {
return &node.NodeStat{}, nil
}
func (t *Tag) String() string {
return "[git tag object]"
}
func (t *Tag) Tree(p string, depth int) []string {
if p != "" {
if p == "tagger" {
return []string{"name", "email", "date"}
}
return nil
}
if depth == 0 {
return nil
}
tree := []string{"object", "type", "tag", "message"}
tree = append(tree, t.Tagger.tree("tagger", depth)...)
return tree
}
func (t *Tag) GitSha() []byte {
return cidToSha(t.Cid())
}
var _ node.Node = (*Tag)(nil)
Binary file not shown.
+170
View File
@@ -0,0 +1,170 @@
package ipldgit
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"sync"
cid "github.com/ipfs/go-cid"
node "github.com/ipfs/go-ipld-format"
)
type Tree struct {
entries map[string]*TreeEntry
size int
order []string
cid cid.Cid
rawData []byte
rawDataOnce sync.Once
}
type TreeEntry struct {
name string
Mode string `json:"mode"`
Hash cid.Cid `json:"hash"`
}
func (t *Tree) Cid() cid.Cid {
return t.cid
}
func (t *Tree) String() string {
return "[git tree object]"
}
func (t *Tree) GitSha() []byte {
return cidToSha(t.cid)
}
func (t *Tree) Copy() node.Node {
out := &Tree{
entries: make(map[string]*TreeEntry),
cid: t.cid,
size: t.size,
order: t.order, // TODO: make a deep copy of this
}
for k, v := range t.entries {
nv := *v
out.entries[k] = &nv
}
return out
}
func (t *Tree) MarshalJSON() ([]byte, error) {
return json.Marshal(t.entries)
}
func (t *Tree) Tree(p string, depth int) []string {
if p != "" {
_, ok := t.entries[p]
if !ok {
return nil
}
return []string{"mode", "type", "hash"}
}
if depth == 0 {
return nil
}
if depth == 1 {
return t.order
}
var out []string
for k, _ := range t.entries {
out = append(out, k, k+"/mode", k+"/type", k+"/hash")
}
return out
}
func (t *Tree) Links() []*node.Link {
var out []*node.Link
for _, v := range t.entries {
out = append(out, &node.Link{Cid: v.Hash})
}
return out
}
func (t *Tree) Loggable() map[string]interface{} {
return map[string]interface{}{
"type": "git tree object",
}
}
func (t *Tree) RawData() []byte {
t.rawDataOnce.Do(func() {
buf := new(bytes.Buffer)
fmt.Fprintf(buf, "tree %d\x00", t.size)
for _, s := range t.order {
t.entries[s].WriteTo(buf)
}
t.rawData = buf.Bytes()
})
return t.rawData
}
func (t *Tree) Resolve(p []string) (interface{}, []string, error) {
e, ok := t.entries[p[0]]
if !ok {
return nil, nil, errors.New("no such link")
}
if len(p) == 1 {
return e, nil, nil
}
switch p[1] {
case "hash":
return &node.Link{Cid: e.Hash}, p[2:], nil
case "mode":
return e.Mode, p[2:], nil
default:
return nil, nil, errors.New("no such link")
}
}
func (t Tree) ResolveLink(path []string) (*node.Link, []string, error) {
out, rest, err := t.Resolve(path)
if err != nil {
return nil, nil, err
}
lnk, ok := out.(*node.Link)
if !ok {
return nil, nil, errors.New("not a link")
}
return lnk, rest, nil
}
func (t *Tree) Size() (uint64, error) {
return uint64(len(t.RawData())), nil
}
func (t *Tree) Stat() (*node.NodeStat, error) {
return &node.NodeStat{}, nil
}
func (te *TreeEntry) WriteTo(w io.Writer) (int, error) {
n, err := fmt.Fprintf(w, "%s %s\x00", te.Mode, te.name)
if err != nil {
return 0, err
}
nn, err := w.Write(cidToSha(te.Hash))
if err != nil {
return n, err
}
return n + nn, nil
}
var _ node.Node = (*Tree)(nil)