Skip to content

Instantly share code, notes, and snippets.

@imjasonh
Created July 29, 2019 07:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save imjasonh/85f48260448ae445facfa6b0fcf42551 to your computer and use it in GitHub Desktop.
Save imjasonh/85f48260448ae445facfa6b0fcf42551 to your computer and use it in GitHub Desktop.
hacking on trying to write git objects (https://github.com/ImJasonH/ideas/issues/77)
package main
import (
"bytes"
"compress/zlib"
"crypto/sha1"
"fmt"
"io"
"log"
"os"
)
func writeCommit(files map[string]string, message, person string) (string, error) {
//TODO: parents
treeSHA, err := writeTree(files)
if err != nil {
return "", err
}
commit := fmt.Sprintf(
`tree %s
author %s
committer %s
%s
`, treeSHA, person, person, message)
size := len(commit)
obj := fmt.Sprintf("commit %d\000%s", size, commit)
log.Println("writing commit...")
return writeObject(obj)
}
// TODO: subdirectries/subtrees
func writeTree(files map[string]string) (string, error) {
var buf bytes.Buffer
for fn, c := range files {
log.Println("writing blob...")
size := len(c)
obj := fmt.Sprintf("blob %d\000%s", size, c)
sha, err := writeObject(obj)
if err != nil {
return "", err
}
fmt.Fprintf(&buf, "100644 blob %s %s\n", sha, fn)
}
c := buf.String()
obj := fmt.Sprintf("tree %d\000%s", len(c), c)
log.Println("writing tree...")
return writeObject(obj)
}
func writeObject(obj string) (string, error) {
h := sha1.New()
io.WriteString(h, obj)
sha := fmt.Sprintf("%x", h.Sum(nil))
log.Println("writing object", sha, obj)
prefix := sha[0:2]
rest := sha[2:]
os.MkdirAll(fmt.Sprintf(".git/objects/%s", prefix), 0777)
// TODO:O skip if exists
f, err := os.Create(fmt.Sprintf(".git/objects/%s/%s", prefix, rest))
if err != nil {
return "", err
}
defer f.Close()
zw := zlib.NewWriter(f)
defer zw.Close()
fmt.Fprint(zw, obj)
return sha, nil
}
func main() {
files := map[string]string{
"date": `Sun Jul 28 08:47:45 EDT 2019
`,
}
message := "the date is"
person := "Jason Hall <jasonhall@google.com> 1564318077 -0400"
_, err := writeCommit(files, message, person)
if err != nil {
log.Fatal(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment