-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommit.go
More file actions
139 lines (111 loc) · 2.83 KB
/
commit.go
File metadata and controls
139 lines (111 loc) · 2.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package main
import (
"bufio"
"bytes"
"encoding/gob"
"fmt"
"io/fs"
"os"
)
type CommitObject struct {
Message string
TreeHash string
SubtreeHash string
}
func commit(args []string) error {
// Check if message is passed
if len(args) == 0 {
return fmt.Errorf("No commit message found. Aborting!")
}
// Get staged files
idx, err := os.ReadFile(".tgit/INDEX")
if err != nil {
return err
}
if len(idx) == 0 {
return fmt.Errorf("Nothing to commit")
}
// Get the current branch
headInf, err := os.Stat(".tgit/refs/HEAD")
if err != nil {
return err
}
currBranch, err := currBranch(headInf)
if err != nil {
return err
}
if _, err := os.Stat(".tgit/refs/heads/" + currBranch); err != nil {
return err
}
cbFile, err := os.OpenFile(".tgit/refs/heads/"+currBranch, os.O_RDWR, fs.ModePerm)
if err != nil {
return fmt.Errorf("Unable to read curr branch file")
}
defer cbFile.Close()
// Get the latest commit information from curr branch
var latestHash string
if headInf.Size() > 0 {
sc := bufio.NewScanner(cbFile)
for sc.Scan() {
latestHash = sc.Text()
}
}
var staged map[string]TreeItem
idxbuf := bytes.NewBuffer(idx)
idxdec := gob.NewDecoder(idxbuf)
if err := idxdec.Decode(&staged); err != nil {
return fmt.Errorf("Unable to decode INDEX file, %v", err)
}
stageHash := getSha1(idx)
// Create a commit struct
cmtMsg := args[0]
co := CommitObject{
Message: cmtMsg,
TreeHash: stageHash,
SubtreeHash: latestHash,
}
// Create hash for the commit struct
cmtHash := getSha1([]byte(cmtMsg + stageHash + latestHash))
for stagedFile := range staged {
hash, err := fileSha1(stagedFile)
if err != nil {
return err
}
f, err := os.ReadFile(stagedFile)
if err != nil {
return err
}
if err := os.WriteFile(".tgit/objects/"+hash, f, fs.ModePerm); err != nil {
fmt.Println("Aborting commit")
return err
}
}
// Write tree-object to a file
if err := os.WriteFile(".tgit/objects/"+stageHash, idx, fs.ModePerm); err != nil {
return fmt.Errorf("Unable to create tree-object")
}
cmtFile, err := os.OpenFile(".tgit/objects/"+cmtHash, os.O_CREATE|os.O_RDWR, fs.ModePerm)
if err != nil {
return fmt.Errorf("Unable to open commit object, %v", err)
}
defer cmtFile.Close()
// Write commit-object to a file
cobuf := new(bytes.Buffer)
cog := gob.NewEncoder(cobuf)
if err := cog.Encode(co); err != nil {
return err
}
if _, err := cmtFile.Write(cobuf.Bytes()); err != nil {
return fmt.Errorf("Unable to commit, %v", err)
}
// Reset staging area
if err = os.Truncate(".tgit/INDEX", 0); err != nil {
return err
}
// Update the head to the latest commit hash
if err := os.WriteFile(".tgit/refs/heads/"+currBranch, []byte(cmtHash), fs.ModePerm); err != nil {
return fmt.Errorf("Unable to update latest commit to branch")
}
fmt.Println("Committed")
return nil
}