2014-07-28 19:26:10 +00:00
|
|
|
package pointer
|
2013-09-27 17:08:19 +00:00
|
|
|
|
|
|
|
import (
|
2014-07-24 21:23:02 +00:00
|
|
|
"bufio"
|
2013-09-27 17:08:19 +00:00
|
|
|
"bytes"
|
2014-06-04 15:38:16 +00:00
|
|
|
"errors"
|
2014-07-24 22:02:27 +00:00
|
|
|
"fmt"
|
2014-08-07 14:53:13 +00:00
|
|
|
"github.com/github/git-media/gitmedia"
|
2014-07-24 21:23:02 +00:00
|
|
|
ini "github.com/glacjay/goini"
|
2013-09-27 17:08:19 +00:00
|
|
|
"io"
|
2014-04-16 21:08:58 +00:00
|
|
|
"regexp"
|
2014-07-24 21:23:02 +00:00
|
|
|
"strconv"
|
|
|
|
"strings"
|
2013-09-27 17:08:19 +00:00
|
|
|
)
|
|
|
|
|
2014-07-24 20:28:37 +00:00
|
|
|
var (
|
2014-07-24 20:49:47 +00:00
|
|
|
MediaWarning = []byte("# git-media\n")
|
|
|
|
alpha = "http://git-media.io/v/1"
|
|
|
|
latest = "http://git-media.io/v/2"
|
|
|
|
oidType = "sha256"
|
|
|
|
alphaHeaderRE = regexp.MustCompile(`\A# (.*git-media|external)`)
|
2014-07-24 22:02:27 +00:00
|
|
|
template = `[git-media]
|
|
|
|
version=%s
|
|
|
|
oid=sha256:%s
|
|
|
|
size=%d
|
|
|
|
`
|
2014-07-24 20:28:37 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type Pointer struct {
|
|
|
|
Version string
|
|
|
|
Oid string
|
|
|
|
Size int64
|
2014-07-24 20:49:47 +00:00
|
|
|
OidType string
|
2014-07-24 20:28:37 +00:00
|
|
|
}
|
2013-09-27 17:08:53 +00:00
|
|
|
|
2014-07-24 20:34:19 +00:00
|
|
|
func NewPointer(oid string, size int64) *Pointer {
|
2014-07-24 21:23:02 +00:00
|
|
|
return &Pointer{latest, oid, size, oidType}
|
2014-07-24 20:34:19 +00:00
|
|
|
}
|
|
|
|
|
2014-08-07 14:53:13 +00:00
|
|
|
func (p *Pointer) Smudge(writer io.Writer, cb gitmedia.CopyCallback) error {
|
|
|
|
return Smudge(writer, p, cb)
|
2014-08-06 21:40:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Pointer) Encode(writer io.Writer) (int, error) {
|
|
|
|
return Encode(writer, p)
|
|
|
|
}
|
|
|
|
|
2014-07-24 20:34:19 +00:00
|
|
|
func Encode(writer io.Writer, pointer *Pointer) (int, error) {
|
2014-07-24 22:02:27 +00:00
|
|
|
return writer.Write([]byte(fmt.Sprintf(template,
|
|
|
|
latest, pointer.Oid, pointer.Size)))
|
2013-09-27 17:08:19 +00:00
|
|
|
}
|
|
|
|
|
2014-07-24 20:28:37 +00:00
|
|
|
func Decode(reader io.Reader) (*Pointer, error) {
|
2014-07-24 20:49:47 +00:00
|
|
|
buf := make([]byte, 200)
|
2013-10-04 13:48:02 +00:00
|
|
|
written, err := reader.Read(buf)
|
|
|
|
if err != nil {
|
2014-07-24 20:28:37 +00:00
|
|
|
return nil, err
|
2013-10-04 13:48:02 +00:00
|
|
|
}
|
2013-09-27 17:08:19 +00:00
|
|
|
|
2014-07-24 20:49:47 +00:00
|
|
|
data := bytes.TrimSpace(buf[0:written])
|
2013-09-27 17:08:19 +00:00
|
|
|
|
2014-07-24 20:49:47 +00:00
|
|
|
if alphaHeaderRE.Match(data) {
|
|
|
|
return decodeAlpha(data)
|
|
|
|
} else {
|
2014-07-24 21:23:02 +00:00
|
|
|
return decodeIni(data)
|
2014-06-04 16:01:45 +00:00
|
|
|
}
|
2014-07-24 20:49:47 +00:00
|
|
|
}
|
2014-06-04 16:01:45 +00:00
|
|
|
|
2014-07-24 21:23:02 +00:00
|
|
|
func decodeIni(data []byte) (*Pointer, error) {
|
|
|
|
dict, err := ini.LoadReader(bufio.NewReader(bytes.NewReader(data)))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
v, ok := dict.GetString("git-media", "version")
|
|
|
|
if !ok || v != latest {
|
|
|
|
if len(v) == 0 {
|
|
|
|
v = "--"
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, errors.New("Invalid version: " + v)
|
|
|
|
}
|
|
|
|
|
|
|
|
oidValue, ok := dict.GetString("git-media", "oid")
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.New("Invalid Oid")
|
|
|
|
}
|
|
|
|
|
|
|
|
oidParts := strings.SplitN(oidValue, ":", 2)
|
|
|
|
if len(oidParts) != 2 {
|
|
|
|
return nil, errors.New("Invalid Oid type in" + oidValue)
|
|
|
|
}
|
|
|
|
if oidParts[0] != oidType {
|
|
|
|
return nil, errors.New("Invalid Oid type: " + oidParts[0])
|
|
|
|
}
|
|
|
|
oid := oidParts[1]
|
|
|
|
|
|
|
|
var size int64
|
|
|
|
sizeStr, ok := dict.GetString("git-media", "size")
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.New("Invalid Oid")
|
|
|
|
} else {
|
|
|
|
size, err = strconv.ParseInt(sizeStr, 10, 0)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.New("Invalid size: " + sizeStr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NewPointer(oid, size), nil
|
|
|
|
}
|
|
|
|
|
2014-07-24 20:49:47 +00:00
|
|
|
func decodeAlpha(data []byte) (*Pointer, error) {
|
2014-07-24 21:23:02 +00:00
|
|
|
lines := bytes.Split(data, []byte("\n"))
|
2014-07-24 20:49:47 +00:00
|
|
|
last := len(lines) - 1
|
|
|
|
if last == 0 {
|
|
|
|
return nil, errors.New("No sha in pointer file")
|
2013-10-04 13:48:02 +00:00
|
|
|
}
|
2014-04-16 21:08:58 +00:00
|
|
|
|
2014-07-24 20:49:47 +00:00
|
|
|
return &Pointer{alpha, string(lines[last]), 0, oidType}, nil
|
2013-09-27 17:08:19 +00:00
|
|
|
}
|