mock_repo.go

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