101 lines
1.9 KiB
Go
101 lines
1.9 KiB
Go
package mfer
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/gzip"
|
|
"crypto/sha256"
|
|
"errors"
|
|
"time"
|
|
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
//go:generate protoc --go_out=. --go_opt=paths=source_relative mf.proto
|
|
|
|
// rot13("MANIFEST")
|
|
const MAGIC string = "ZNAVSRFG"
|
|
|
|
func newTimestampFromTime(t time.Time) *Timestamp {
|
|
out := &Timestamp{
|
|
Seconds: t.Unix(),
|
|
Nanos: int32(t.UnixNano() - (t.Unix() * 1000000000)),
|
|
}
|
|
return out
|
|
}
|
|
|
|
func (m *manifest) generate() error {
|
|
if m.pbInner == nil {
|
|
e := m.generateInner()
|
|
if e != nil {
|
|
return e
|
|
}
|
|
}
|
|
if m.pbOuter == nil {
|
|
e := m.generateOuter()
|
|
if e != nil {
|
|
return e
|
|
}
|
|
}
|
|
dat, err := proto.MarshalOptions{Deterministic: true}.Marshal(m.pbOuter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
m.output = bytes.NewBuffer([]byte(MAGIC))
|
|
_, err = m.output.Write(dat)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *manifest) generateOuter() error {
|
|
if m.pbInner == nil {
|
|
return errors.New("internal error")
|
|
}
|
|
innerData, err := proto.MarshalOptions{Deterministic: true}.Marshal(m.pbInner)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
h := sha256.New()
|
|
h.Write(innerData)
|
|
|
|
idc := new(bytes.Buffer)
|
|
gzw, err := gzip.NewWriterLevel(idc, gzip.BestCompression)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = gzw.Write(innerData)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
gzw.Close()
|
|
|
|
o := &MFFileOuter{
|
|
InnerMessage: idc.Bytes(),
|
|
Size: int64(len(innerData)),
|
|
Sha256: h.Sum(nil),
|
|
Version: MFFileOuter_VERSION_ONE,
|
|
CompressionType: MFFileOuter_COMPRESSION_GZIP,
|
|
}
|
|
m.pbOuter = o
|
|
return nil
|
|
}
|
|
|
|
func (m *manifest) generateInner() error {
|
|
m.pbInner = &MFFile{
|
|
Version: MFFile_VERSION_ONE,
|
|
CreatedAt: newTimestampFromTime(time.Now()),
|
|
Files: []*MFFilePath{},
|
|
}
|
|
for _, f := range m.files {
|
|
nf := &MFFilePath{
|
|
Path: f.path,
|
|
// FIXME add more stuff
|
|
}
|
|
m.pbInner.Files = append(m.pbInner.Files, nf)
|
|
}
|
|
return nil
|
|
}
|