diff options
Diffstat (limited to 'repository/mock_repo.go')
-rw-r--r-- | repository/mock_repo.go | 257 |
1 files changed, 159 insertions, 98 deletions
diff --git a/repository/mock_repo.go b/repository/mock_repo.go index 8a1724ef..2749bfbd 100644 --- a/repository/mock_repo.go +++ b/repository/mock_repo.go @@ -1,6 +1,7 @@ package repository import ( + "bytes" "crypto/sha1" "fmt" "strings" @@ -10,15 +11,16 @@ import ( "github.com/blevesearch/bleve" "github.com/go-git/go-billy/v5" "github.com/go-git/go-billy/v5/memfs" + "golang.org/x/crypto/openpgp" "github.com/MichaelMure/git-bug/util/lamport" ) -var _ ClockedRepo = &mockRepoForTest{} -var _ TestedRepo = &mockRepoForTest{} +var _ ClockedRepo = &mockRepo{} +var _ TestedRepo = &mockRepo{} -// mockRepoForTest defines an instance of Repo that can be used for testing. -type mockRepoForTest struct { +// mockRepo defines an instance of Repo that can be used for testing. +type mockRepo struct { *mockRepoConfig *mockRepoKeyring *mockRepoCommon @@ -26,12 +28,13 @@ type mockRepoForTest struct { *mockRepoBleve *mockRepoData *mockRepoClock + *mockRepoTest } -func (m *mockRepoForTest) Close() error { return nil } +func (m *mockRepo) Close() error { return nil } -func NewMockRepoForTest() *mockRepoForTest { - return &mockRepoForTest{ +func NewMockRepo() *mockRepo { + return &mockRepo{ mockRepoConfig: NewMockRepoConfig(), mockRepoKeyring: NewMockRepoKeyring(), mockRepoCommon: NewMockRepoCommon(), @@ -39,6 +42,7 @@ func NewMockRepoForTest() *mockRepoForTest { mockRepoBleve: newMockRepoBleve(), mockRepoData: NewMockRepoData(), mockRepoClock: NewMockRepoClock(), + mockRepoTest: NewMockRepoTest(), } } @@ -177,7 +181,8 @@ var _ RepoData = &mockRepoData{} type commit struct { treeHash Hash - parent Hash + parents []Hash + sig string } type mockRepoData struct { @@ -196,13 +201,13 @@ func NewMockRepoData() *mockRepoData { } } -// PushRefs push git refs to a remote -func (r *mockRepoData) PushRefs(remote string, refSpec string) (string, error) { - return "", nil +func (r *mockRepoData) FetchRefs(remote string, prefix string) (string, error) { + panic("implement me") } -func (r *mockRepoData) FetchRefs(remote string, refSpec string) (string, error) { - return "", nil +// PushRefs push git refs to a remote +func (r *mockRepoData) PushRefs(remote string, prefix string) (string, error) { + panic("implement me") } func (r *mockRepoData) StoreData(data []byte) (Hash, error) { @@ -214,7 +219,6 @@ func (r *mockRepoData) StoreData(data []byte) (Hash, error) { func (r *mockRepoData) ReadData(hash Hash) ([]byte, error) { data, ok := r.blobs[hash] - if !ok { return nil, fmt.Errorf("unknown hash") } @@ -231,48 +235,103 @@ func (r *mockRepoData) StoreTree(entries []TreeEntry) (Hash, error) { return hash, nil } -func (r *mockRepoData) StoreCommit(treeHash Hash) (Hash, error) { - rawHash := sha1.Sum([]byte(treeHash)) - hash := Hash(fmt.Sprintf("%x", rawHash)) - r.commits[hash] = commit{ - treeHash: treeHash, +func (r *mockRepoData) ReadTree(hash Hash) ([]TreeEntry, error) { + var data string + + data, ok := r.trees[hash] + + if !ok { + // Git will understand a commit hash to reach a tree + commit, ok := r.commits[hash] + + if !ok { + return nil, fmt.Errorf("unknown hash") + } + + data, ok = r.trees[commit.treeHash] + + if !ok { + return nil, fmt.Errorf("unknown hash") + } } - return hash, nil + + return readTreeEntries(data) +} + +func (r *mockRepoData) StoreCommit(treeHash Hash, parents ...Hash) (Hash, error) { + return r.StoreSignedCommit(treeHash, nil, parents...) } -func (r *mockRepoData) StoreCommitWithParent(treeHash Hash, parent Hash) (Hash, error) { - rawHash := sha1.Sum([]byte(treeHash + parent)) +func (r *mockRepoData) StoreSignedCommit(treeHash Hash, signKey *openpgp.Entity, parents ...Hash) (Hash, error) { + hasher := sha1.New() + hasher.Write([]byte(treeHash)) + for _, parent := range parents { + hasher.Write([]byte(parent)) + } + rawHash := hasher.Sum(nil) hash := Hash(fmt.Sprintf("%x", rawHash)) - r.commits[hash] = commit{ + c := commit{ treeHash: treeHash, - parent: parent, + parents: parents, + } + if signKey != nil { + // unlike go-git, we only sign the tree hash for simplicity instead of all the fields (parents ...) + var sig bytes.Buffer + if err := openpgp.DetachSign(&sig, signKey, strings.NewReader(string(treeHash)), nil); err != nil { + return "", err + } + c.sig = sig.String() } + r.commits[hash] = c return hash, nil } -func (r *mockRepoData) UpdateRef(ref string, hash Hash) error { - r.refs[ref] = hash - return nil -} +func (r *mockRepoData) ReadCommit(hash Hash) (Commit, error) { + c, ok := r.commits[hash] + if !ok { + return Commit{}, fmt.Errorf("unknown commit") + } -func (r *mockRepoData) RemoveRef(ref string) error { - delete(r.refs, ref) - return nil -} + result := Commit{ + Hash: hash, + Parents: c.parents, + TreeHash: c.treeHash, + } -func (r *mockRepoData) RefExist(ref string) (bool, error) { - _, exist := r.refs[ref] - return exist, nil + if c.sig != "" { + // Note: this is actually incorrect as the signed data should be the full commit (+comment, +date ...) + // but only the tree hash work for our purpose here. + result.SignedData = strings.NewReader(string(c.treeHash)) + result.Signature = strings.NewReader(c.sig) + } + + return result, nil } -func (r *mockRepoData) CopyRef(source string, dest string) error { - hash, exist := r.refs[source] +func (r *mockRepoData) GetTreeHash(commit Hash) (Hash, error) { + c, ok := r.commits[commit] + if !ok { + return "", fmt.Errorf("unknown commit") + } - if !exist { - return fmt.Errorf("Unknown ref") + return c.treeHash, nil +} + +func (r *mockRepoData) ResolveRef(ref string) (Hash, error) { + h, ok := r.refs[ref] + if !ok { + return "", fmt.Errorf("unknown ref") } + return h, nil +} - r.refs[dest] = hash +func (r *mockRepoData) UpdateRef(ref string, hash Hash) error { + r.refs[ref] = hash + return nil +} + +func (r *mockRepoData) RemoveRef(ref string) error { + delete(r.refs, ref) return nil } @@ -288,46 +347,20 @@ func (r *mockRepoData) ListRefs(refPrefix string) ([]string, error) { return keys, nil } -func (r *mockRepoData) ListCommits(ref string) ([]Hash, error) { - var hashes []Hash - - hash := r.refs[ref] - - for { - commit, ok := r.commits[hash] - - if !ok { - break - } - - hashes = append([]Hash{hash}, hashes...) - hash = commit.parent - } - - return hashes, nil +func (r *mockRepoData) RefExist(ref string) (bool, error) { + _, exist := r.refs[ref] + return exist, nil } -func (r *mockRepoData) ReadTree(hash Hash) ([]TreeEntry, error) { - var data string - - data, ok := r.trees[hash] - - if !ok { - // Git will understand a commit hash to reach a tree - commit, ok := r.commits[hash] - - if !ok { - return nil, fmt.Errorf("unknown hash") - } - - data, ok = r.trees[commit.treeHash] +func (r *mockRepoData) CopyRef(source string, dest string) error { + hash, exist := r.refs[source] - if !ok { - return nil, fmt.Errorf("unknown hash") - } + if !exist { + return fmt.Errorf("Unknown ref") } - return readTreeEntries(data) + r.refs[dest] = hash + return nil } func (r *mockRepoData) FindCommonAncestor(hash1 Hash, hash2 Hash) (Hash, error) { @@ -338,8 +371,11 @@ func (r *mockRepoData) FindCommonAncestor(hash1 Hash, hash2 Hash) (Hash, error) if !ok { return "", fmt.Errorf("unknown commit %v", hash1) } - ancestor1 = append(ancestor1, c.parent) - hash1 = c.parent + if len(c.parents) == 0 { + break + } + ancestor1 = append(ancestor1, c.parents[0]) + hash1 = c.parents[0] } for { @@ -354,35 +390,19 @@ func (r *mockRepoData) FindCommonAncestor(hash1 Hash, hash2 Hash) (Hash, error) return "", fmt.Errorf("unknown commit %v", hash1) } - if c.parent == "" { + if c.parents[0] == "" { return "", fmt.Errorf("no ancestor found") } - hash2 = c.parent - } -} - -func (r *mockRepoData) GetTreeHash(commit Hash) (Hash, error) { - c, ok := r.commits[commit] - if !ok { - return "", fmt.Errorf("unknown commit") + hash2 = c.parents[0] } - - return c.treeHash, nil } -func (r *mockRepoData) AddRemote(name string, url string) error { - panic("implement me") -} - -func (m mockRepoForTest) GetLocalRemote() string { - panic("implement me") +func (r *mockRepoData) ListCommits(ref string) ([]Hash, error) { + return nonNativeListCommits(r, ref) } -func (m mockRepoForTest) EraseFromDisk() error { - // nothing to do - return nil -} +var _ RepoClock = &mockRepoClock{} type mockRepoClock struct { mu sync.Mutex @@ -395,6 +415,10 @@ func NewMockRepoClock() *mockRepoClock { } } +func (r *mockRepoClock) AllClocks() (map[string]lamport.Clock, error) { + return r.clocks, nil +} + func (r *mockRepoClock) GetOrCreateClock(name string) (lamport.Clock, error) { r.mu.Lock() defer r.mu.Unlock() @@ -407,3 +431,40 @@ func (r *mockRepoClock) GetOrCreateClock(name string) (lamport.Clock, error) { r.clocks[name] = c return c, nil } + +func (r *mockRepoClock) Increment(name string) (lamport.Time, error) { + c, err := r.GetOrCreateClock(name) + if err != nil { + return lamport.Time(0), err + } + return c.Increment() +} + +func (r *mockRepoClock) Witness(name string, time lamport.Time) error { + c, err := r.GetOrCreateClock(name) + if err != nil { + return err + } + return c.Witness(time) +} + +var _ repoTest = &mockRepoTest{} + +type mockRepoTest struct{} + +func NewMockRepoTest() *mockRepoTest { + return &mockRepoTest{} +} + +func (r *mockRepoTest) AddRemote(name string, url string) error { + panic("implement me") +} + +func (r mockRepoTest) GetLocalRemote() string { + panic("implement me") +} + +func (r mockRepoTest) EraseFromDisk() error { + // nothing to do + return nil +} |