1package repository
2
3import (
4 "crypto/sha1"
5 "fmt"
6 "strings"
7
8 "github.com/MichaelMure/git-bug/util"
9)
10
11// mockRepoForTest defines an instance of Repo that can be used for testing.
12type mockRepoForTest struct {
13 blobs map[util.Hash][]byte
14 trees map[util.Hash]string
15 commits map[util.Hash]commit
16 refs map[string]util.Hash
17 createClock util.LamportClock
18 editClock util.LamportClock
19}
20
21type commit struct {
22 treeHash util.Hash
23 parent util.Hash
24}
25
26func NewMockRepoForTest() Repo {
27 return &mockRepoForTest{
28 blobs: make(map[util.Hash][]byte),
29 trees: make(map[util.Hash]string),
30 commits: make(map[util.Hash]commit),
31 refs: make(map[string]util.Hash),
32 createClock: util.NewLamportClock(),
33 editClock: util.NewLamportClock(),
34 }
35}
36
37// GetPath returns the path to the repo.
38func (r *mockRepoForTest) GetPath() string {
39 return "~/mockRepo/"
40}
41
42func (r *mockRepoForTest) GetUserName() (string, error) {
43 return "René Descartes", nil
44}
45
46// GetUserEmail returns the email address that the user has used to configure git.
47func (r *mockRepoForTest) GetUserEmail() (string, error) {
48 return "user@example.com", nil
49}
50
51// GetCoreEditor returns the name of the editor that the user has used to configure git.
52func (r *mockRepoForTest) GetCoreEditor() (string, error) {
53 return "vi", nil
54}
55
56// PushRefs push git refs to a remote
57func (r *mockRepoForTest) PushRefs(remote string, refSpec string) (string, error) {
58 return "", nil
59}
60
61func (r *mockRepoForTest) FetchRefs(remote string, refSpec string) (string, error) {
62 return "", nil
63}
64
65func (r *mockRepoForTest) StoreData(data []byte) (util.Hash, error) {
66 rawHash := sha1.Sum(data)
67 hash := util.Hash(fmt.Sprintf("%x", rawHash))
68 r.blobs[hash] = data
69 return hash, nil
70}
71
72func (r *mockRepoForTest) ReadData(hash util.Hash) ([]byte, error) {
73 data, ok := r.blobs[hash]
74
75 if !ok {
76 return nil, fmt.Errorf("unknown hash")
77 }
78
79 return data, nil
80}
81
82func (r *mockRepoForTest) StoreTree(entries []TreeEntry) (util.Hash, error) {
83 buffer := prepareTreeEntries(entries)
84 rawHash := sha1.Sum(buffer.Bytes())
85 hash := util.Hash(fmt.Sprintf("%x", rawHash))
86 r.trees[hash] = buffer.String()
87
88 return hash, nil
89}
90
91func (r *mockRepoForTest) StoreCommit(treeHash util.Hash) (util.Hash, error) {
92 rawHash := sha1.Sum([]byte(treeHash))
93 hash := util.Hash(fmt.Sprintf("%x", rawHash))
94 r.commits[hash] = commit{
95 treeHash: treeHash,
96 }
97 return hash, nil
98}
99
100func (r *mockRepoForTest) StoreCommitWithParent(treeHash util.Hash, parent util.Hash) (util.Hash, error) {
101 rawHash := sha1.Sum([]byte(treeHash + parent))
102 hash := util.Hash(fmt.Sprintf("%x", rawHash))
103 r.commits[hash] = commit{
104 treeHash: treeHash,
105 parent: parent,
106 }
107 return hash, nil
108}
109
110func (r *mockRepoForTest) UpdateRef(ref string, hash util.Hash) error {
111 r.refs[ref] = hash
112 return nil
113}
114
115func (r *mockRepoForTest) RefExist(ref string) (bool, error) {
116 _, exist := r.refs[ref]
117 return exist, nil
118}
119
120func (r *mockRepoForTest) CopyRef(source string, dest string) error {
121 hash, exist := r.refs[source]
122
123 if !exist {
124 return fmt.Errorf("Unknown ref")
125 }
126
127 r.refs[dest] = hash
128 return nil
129}
130
131func (r *mockRepoForTest) ListRefs(refspec string) ([]string, error) {
132 keys := make([]string, len(r.refs))
133
134 i := 0
135 for k := range r.refs {
136 keys[i] = k
137 i++
138 }
139
140 return keys, nil
141}
142
143// ListIds will return a list of Git ref matching the given refspec,
144// stripped to only the last part of the ref
145func (r *mockRepoForTest) ListIds(refspec string) ([]string, error) {
146 keys := make([]string, len(r.refs))
147
148 i := 0
149 for k := range r.refs {
150 splitted := strings.Split(k, "/")
151 keys[i] = splitted[len(splitted)-1]
152 i++
153 }
154
155 return keys, nil
156}
157
158func (r *mockRepoForTest) ListCommits(ref string) ([]util.Hash, error) {
159 var hashes []util.Hash
160
161 hash := r.refs[ref]
162
163 for {
164 commit, ok := r.commits[hash]
165
166 if !ok {
167 break
168 }
169
170 hashes = append([]util.Hash{hash}, hashes...)
171 hash = commit.parent
172 }
173
174 return hashes, nil
175}
176
177func (r *mockRepoForTest) ListEntries(hash util.Hash) ([]TreeEntry, error) {
178 var data string
179
180 data, ok := r.trees[hash]
181
182 if !ok {
183 // Git will understand a commit hash to reach a tree
184 commit, ok := r.commits[hash]
185
186 if !ok {
187 return nil, fmt.Errorf("unknown hash")
188 }
189
190 data, ok = r.trees[commit.treeHash]
191
192 if !ok {
193 return nil, fmt.Errorf("unknown hash")
194 }
195 }
196
197 return readTreeEntries(data)
198}
199
200func (r *mockRepoForTest) FindCommonAncestor(hash1 util.Hash, hash2 util.Hash) (util.Hash, error) {
201 panic("implement me")
202}
203
204func (r *mockRepoForTest) GetTreeHash(commit util.Hash) (util.Hash, error) {
205 panic("implement me")
206}
207
208func (r *mockRepoForTest) LoadClocks() error {
209 return nil
210}
211
212func (r *mockRepoForTest) WriteClocks() error {
213 return nil
214}
215
216func (r *mockRepoForTest) CreateTimeIncrement() (util.LamportTime, error) {
217 return r.createClock.Increment(), nil
218}
219
220func (r *mockRepoForTest) EditTimeIncrement() (util.LamportTime, error) {
221 return r.editClock.Increment(), nil
222}
223
224func (r *mockRepoForTest) CreateWitness(time util.LamportTime) error {
225 r.createClock.Witness(time)
226 return nil
227}
228
229func (r *mockRepoForTest) EditWitness(time util.LamportTime) error {
230 r.editClock.Witness(time)
231 return nil
232}