-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathadd.go
106 lines (82 loc) · 1.86 KB
/
add.go
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
package main
import (
"bytes"
"encoding/gob"
"errors"
"fmt"
"io/fs"
"os"
)
type FileType string
const (
Blob FileType = "blob"
Tree FileType = "tree"
)
type TreeItem struct {
Filename string
Hash string
FileType FileType
}
func add(fargs []string) error {
idxinfo, err := os.Stat(".tgit/INDEX")
if err != nil {
return err
}
idxf, err := os.OpenFile(".tgit/INDEX", os.O_RDWR, fs.ModePerm)
if err != nil {
return err
}
defer idxf.Close()
filesize := idxinfo.Size()
staged := make(map[string]TreeItem)
// Read INDEX file
if filesize > 0 {
b := make([]byte, filesize)
_, err = idxf.Read(b)
if err != nil {
fmt.Printf("Unable to read %v", err)
return err
}
buf := bytes.NewBuffer(b)
dec := gob.NewDecoder(buf)
if err := dec.Decode(&staged); err != nil {
return fmt.Errorf("Unable to decode INDEX file, %v", err)
}
}
// Stage each files
for _, farg := range fargs {
hash, err := fileSha1(farg)
if err != nil {
return err
}
if _, err := os.Stat(".tgit/objects/" + hash); errors.Is(err, fs.ErrExist) {
fmt.Printf("No latest change in %v\n", farg)
continue
}
if canStage(farg, hash, staged) {
fmt.Printf("Added %v\n", farg)
staged[farg] = TreeItem{Filename: farg, Hash: hash, FileType: Blob}
}
}
// Write to INDEX
buf := new(bytes.Buffer)
g := gob.NewEncoder(buf)
if err := g.Encode(staged); err != nil {
return fmt.Errorf("Unable to perform staging")
}
if _, err := idxf.Write(buf.Bytes()); err != nil {
return fmt.Errorf("Unable to write to INDEX file")
}
return nil
}
func canStage(file string, fileHash string, staged map[string]TreeItem) bool {
if _, err := os.Stat(".tgit/objects/" + fileHash); err == nil {
fmt.Printf("No latest change in %v\n", file)
return false
}
if _, ok := staged[file]; ok {
fmt.Printf("%v already added\n", file)
return false
}
return true
}