mock_repo.go

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