diff options
| author | jet2tlf <jet2tlf@gmail.com> | 2024-06-03 01:51:55 +0000 |
|---|---|---|
| committer | jet2tlf <jet2tlf@gmail.com> | 2024-06-03 01:51:55 +0000 |
| commit | 81e395cdeb0894423d0ad833a074538674a4bc2d (patch) | |
| tree | fdc4fddac6a215349e5781b8834d551856f01837 /cmd | |
| parent | 4234f96a8e52ce2eb329ee9b92f0eaa195fe2a7c (diff) | |
| download | git-go-81e395cdeb0894423d0ad833a074538674a4bc2d.tar.gz git-go-81e395cdeb0894423d0ad833a074538674a4bc2d.zip | |
codecrafters submit [skip ci]
Diffstat (limited to 'cmd')
| -rw-r--r-- | cmd/mygit/main.go | 62 |
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 + +} |