mock_repo.go

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