aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/mygit/main.go62
1 files changed, 62 insertions, 0 deletions
diff --git a/cmd/mygit/main.go b/cmd/mygit/main.go
index 2f84bde..1443195 100644
--- a/cmd/mygit/main.go
+++ b/cmd/mygit/main.go
@@ -4,8 +4,10 @@ import (
"bytes"
"compress/zlib"
"crypto/sha1"
+ "encoding/hex"
"fmt"
"io"
+ "io/ioutil"
"os"
"path/filepath"
"sort"
@@ -131,8 +133,68 @@ func main() {
sort.Strings(fileNames)
fmt.Println(strings.Join(fileNames, "\n"))
+ case "write-tree":
+ currentDir, _ := os.Getwd()
+ h, c := calcTreeHash(currentDir)
+ treeHash := hex.EncodeToString(h)
+ os.Mkdir(filepath.Join(".git", "objects", treeHash[:2]), 0755)
+ var compressed bytes.Buffer
+ w := zlib.NewWriter(&compressed)
+ w.Write(c)
+ w.Close()
+ os.WriteFile(filepath.Join(".git", "objects", treeHash[:2], treeHash[2:]), compressed.Bytes(), 0644)
+ fmt.Println(treeHash)
+
default:
fmt.Fprintf(os.Stderr, "Unknown command %s\n", command)
os.Exit(1)
}
}
+
+func calcTreeHash(dir string) ([]byte, []byte) {
+ fileInfos, _ := ioutil.ReadDir(dir)
+
+ type entry struct {
+ fileName string
+ b []byte
+ }
+
+ var entries []entry
+ contentSize := 0
+
+ for _, fileInfo := range fileInfos {
+ if fileInfo.Name() == ".git" {
+ continue
+ }
+
+ if !fileInfo.IsDir() {
+ f, _ := os.Open(filepath.Join(dir, fileInfo.Name()))
+ b, _ := ioutil.ReadAll(f)
+ s := fmt.Sprintf("blob %d\u0000%s", len(b), string(b))
+ sha1 := sha1.New()
+ io.WriteString(sha1, s)
+ s = fmt.Sprintf("100644 %s\u0000", fileInfo.Name())
+ b = append([]byte(s), sha1.Sum(nil)...)
+ entries = append(entries, entry{fileInfo.Name(), b})
+ contentSize += len(b)
+ } else {
+ b, _ := calcTreeHash(filepath.Join(dir, fileInfo.Name()))
+ s := fmt.Sprintf("40000 %s\u0000", fileInfo.Name())
+ b2 := append([]byte(s), b...)
+ entries = append(entries, entry{fileInfo.Name(), b2})
+ contentSize += len(b2)
+ }
+ }
+ sort.Slice(entries, func(i, j int) bool { return entries[i].fileName < entries[j].fileName })
+ s := fmt.Sprintf("tree %d\u0000", contentSize)
+ b := []byte(s)
+
+ for _, entry := range entries {
+ b = append(b, entry.b...)
+ }
+
+ sha1 := sha1.New()
+ io.WriteString(sha1, string(b))
+ return sha1.Sum(nil), b
+
+}