mock_repo.go

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