fast-export.go
package main
import (
"crypto/sha512"
"fmt"
"os"
"time"
)
type FileModify struct {
Blob int
Path string
}
func (f FileModify) write() {
fmt.Printf("M 644 :%d %s\n", f.Blob, f.Path)
}
type Commit struct {
Mark int
Branch string
Committer string
Timestamp time.Time
Message string
From int
DeleteAll bool
Modifications []FileModify
}
func (c Commit) write() {
fmt.Println("commit refs/heads/" + c.Branch)
if c.Mark != 0 {
fmt.Printf("mark :%d\n", c.Mark)
}
fmt.Println("committer", c.Committer, formatTime(c.Timestamp))
fmt.Println("data", len(c.Message))
fmt.Println(c.Message)
if c.From != 0 {
fmt.Printf("from :%d\n", c.From)
}
if c.DeleteAll {
fmt.Println("deleteall")
}
for _, m := range c.Modifications {
m.write()
}
fmt.Println()
}
type Blob struct {
Mark int
Data []byte
}
func (b Blob) write() {
fmt.Println("blob")
if b.Mark != 0 {
fmt.Printf("mark :%d\n", b.Mark)
}
fmt.Println("data", len(b.Data))
os.Stdout.Write(b.Data)
fmt.Println()
}
// A FastExportStream is a representation of a fast-export stream.
type FastExportStream struct {
marks Marks
blobIndex map[[64]byte]int
}
func (f *FastExportStream) AddCommit(c Commit) {
if c.Mark == 0 {
c.Mark = f.marks.Next()
}
c.write()
}
// AddBlob adds a blob to the stream and returns its mark.
func (f *FastExportStream) AddBlob(data []byte) int {
hash := sha512.Sum512(data)
if mark, ok := f.blobIndex[hash]; ok {
return mark
}
b := Blob{
Mark: f.marks.Next(),
Data: data,
}
if f.blobIndex == nil {
f.blobIndex = make(map[[64]byte]int)
}
f.blobIndex[hash] = b.Mark
b.write()
return b.Mark
}