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