aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2021-01-25 12:39:34 +0100
committerMichael Muré <batolettre@gmail.com>2021-02-14 12:19:01 +0100
commitfe4237df3c62bd6dfd1f385893295f93072d0e51 (patch)
tree66eabac7a2aaae9f7b4f2aff07092556e3a2a2ac
parentdc5059bc3372941e2908739831188768335ac50b (diff)
downloadgit-bug-fe4237df3c62bd6dfd1f385893295f93072d0e51.tar.gz
entity: readAll and more testing
-rw-r--r--bug/bug_actions.go3
-rw-r--r--bug/bug_actions_test.go8
-rw-r--r--cache/repo_cache_test.go2
-rw-r--r--entity/dag/common_test.go38
-rw-r--r--entity/dag/entity.go48
-rw-r--r--entity/dag/entity_actions.go8
-rw-r--r--entity/dag/entity_actions_test.go110
-rw-r--r--repository/mock_repo.go4
-rw-r--r--repository/repo.go1
-rw-r--r--repository/repo_testing.go3
10 files changed, 203 insertions, 22 deletions
diff --git a/bug/bug_actions.go b/bug/bug_actions.go
index 40a2facb..0e240711 100644
--- a/bug/bug_actions.go
+++ b/bug/bug_actions.go
@@ -4,10 +4,11 @@ import (
"fmt"
"strings"
+ "github.com/pkg/errors"
+
"github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/identity"
"github.com/MichaelMure/git-bug/repository"
- "github.com/pkg/errors"
)
// Fetch retrieve updates from a remote
diff --git a/bug/bug_actions_test.go b/bug/bug_actions_test.go
index 7a9673d6..fc671063 100644
--- a/bug/bug_actions_test.go
+++ b/bug/bug_actions_test.go
@@ -12,7 +12,7 @@ import (
)
func TestPushPull(t *testing.T) {
- repoA, repoB, remote := repository.SetupReposAndRemote()
+ repoA, repoB, remote := repository.SetupGoGitReposAndRemote()
defer repository.CleanupTestRepos(repoA, repoB, remote)
reneA, err := identity.NewIdentity(repoA, "René Descartes", "rene@descartes.fr")
@@ -90,7 +90,7 @@ func BenchmarkRebaseTheirs(b *testing.B) {
}
func _RebaseTheirs(t testing.TB) {
- repoA, repoB, remote := repository.SetupReposAndRemote()
+ repoA, repoB, remote := repository.SetupGoGitReposAndRemote()
defer repository.CleanupTestRepos(repoA, repoB, remote)
reneA, err := identity.NewIdentity(repoA, "René Descartes", "rene@descartes.fr")
@@ -171,7 +171,7 @@ func BenchmarkRebaseOurs(b *testing.B) {
}
func _RebaseOurs(t testing.TB) {
- repoA, repoB, remote := repository.SetupReposAndRemote()
+ repoA, repoB, remote := repository.SetupGoGitReposAndRemote()
defer repository.CleanupTestRepos(repoA, repoB, remote)
reneA, err := identity.NewIdentity(repoA, "René Descartes", "rene@descartes.fr")
@@ -263,7 +263,7 @@ func BenchmarkRebaseConflict(b *testing.B) {
}
func _RebaseConflict(t testing.TB) {
- repoA, repoB, remote := repository.SetupReposAndRemote()
+ repoA, repoB, remote := repository.SetupGoGitReposAndRemote()
defer repository.CleanupTestRepos(repoA, repoB, remote)
reneA, err := identity.NewIdentity(repoA, "René Descartes", "rene@descartes.fr")
diff --git a/cache/repo_cache_test.go b/cache/repo_cache_test.go
index bd06e84d..9cdd584d 100644
--- a/cache/repo_cache_test.go
+++ b/cache/repo_cache_test.go
@@ -109,7 +109,7 @@ func TestCache(t *testing.T) {
}
func TestPushPull(t *testing.T) {
- repoA, repoB, remote := repository.SetupReposAndRemote()
+ repoA, repoB, remote := repository.SetupGoGitReposAndRemote()
defer repository.CleanupTestRepos(repoA, repoB, remote)
cacheA, err := NewRepoCache(repoA)
diff --git a/entity/dag/common_test.go b/entity/dag/common_test.go
index 29f1279e..b822fc79 100644
--- a/entity/dag/common_test.go
+++ b/entity/dag/common_test.go
@@ -26,16 +26,16 @@ func newOp1(author identity.Interface, field1 string) *op1 {
return &op1{author: author, OperationType: 1, Field1: field1}
}
-func (o op1) Id() entity.Id {
+func (o *op1) Id() entity.Id {
data, _ := json.Marshal(o)
return entity.DeriveId(data)
}
-func (o op1) Author() identity.Interface {
+func (o *op1) Author() identity.Interface {
return o.author
}
-func (o op1) Validate() error { return nil }
+func (o *op1) Validate() error { return nil }
type op2 struct {
author identity.Interface
@@ -48,16 +48,16 @@ func newOp2(author identity.Interface, field2 string) *op2 {
return &op2{author: author, OperationType: 2, Field2: field2}
}
-func (o op2) Id() entity.Id {
+func (o *op2) Id() entity.Id {
data, _ := json.Marshal(o)
return entity.DeriveId(data)
}
-func (o op2) Author() identity.Interface {
+func (o *op2) Author() identity.Interface {
return o.author
}
-func (o op2) Validate() error { return nil }
+func (o *op2) Validate() error { return nil }
func unmarshaler(author identity.Interface, raw json.RawMessage) (Operation, error) {
var t struct {
@@ -90,7 +90,31 @@ func unmarshaler(author identity.Interface, raw json.RawMessage) (Operation, err
func makeTestContext() (repository.ClockedRepo, identity.Interface, identity.Interface, Definition) {
repo := repository.NewMockRepo()
+ id1, id2, def := makeTestContextInternal(repo)
+ return repo, id1, id2, def
+}
+
+func makeTestContextRemote() (repository.ClockedRepo, repository.ClockedRepo, repository.ClockedRepo, identity.Interface, identity.Interface, Definition) {
+ repoA := repository.CreateGoGitTestRepo(false)
+ repoB := repository.CreateGoGitTestRepo(false)
+ remote := repository.CreateGoGitTestRepo(true)
+
+ err := repoA.AddRemote("origin", remote.GetLocalRemote())
+ if err != nil {
+ panic(err)
+ }
+ err = repoB.AddRemote("origin", remote.GetLocalRemote())
+ if err != nil {
+ panic(err)
+ }
+
+ id1, id2, def := makeTestContextInternal(repoA)
+
+ return repoA, repoB, remote, id1, id2, def
+}
+
+func makeTestContextInternal(repo repository.ClockedRepo) (identity.Interface, identity.Interface, Definition) {
id1, err := identity.NewIdentity(repo, "name1", "email1")
if err != nil {
panic(err)
@@ -127,7 +151,7 @@ func makeTestContext() (repository.ClockedRepo, identity.Interface, identity.Int
formatVersion: 1,
}
- return repo, id1, id2, def
+ return id1, id2, def
}
type identityResolverFunc func(id entity.Id) (identity.Interface, error)
diff --git a/entity/dag/entity.go b/entity/dag/entity.go
index 63d7fc3b..d3f5b482 100644
--- a/entity/dag/entity.go
+++ b/entity/dag/entity.go
@@ -58,7 +58,7 @@ func New(definition Definition) *Entity {
}
}
-// Read will read and decode a stored Entity from a repository
+// Read will read and decode a stored local Entity from a repository
func Read(def Definition, repo repository.ClockedRepo, id entity.Id) (*Entity, error) {
if err := id.Validate(); err != nil {
return nil, errors.Wrap(err, "invalid id")
@@ -69,6 +69,17 @@ func Read(def Definition, repo repository.ClockedRepo, id entity.Id) (*Entity, e
return read(def, repo, ref)
}
+// readRemote will read and decode a stored remote Entity from a repository
+func readRemote(def Definition, repo repository.ClockedRepo, remote string, id entity.Id) (*Entity, error) {
+ if err := id.Validate(); err != nil {
+ return nil, errors.Wrap(err, "invalid id")
+ }
+
+ ref := fmt.Sprintf("refs/remotes/%s/%s/%s", def.namespace, remote, id.String())
+
+ return read(def, repo, ref)
+}
+
// read fetch from git and decode an Entity at an arbitrary git reference.
func read(def Definition, repo repository.ClockedRepo, ref string) (*Entity, error) {
rootHash, err := repo.ResolveRef(ref)
@@ -232,6 +243,41 @@ func read(def Definition, repo repository.ClockedRepo, ref string) (*Entity, err
}, nil
}
+type StreamedEntity struct {
+ Entity *Entity
+ Err error
+}
+
+// ReadAll read and parse all local Entity
+func ReadAll(def Definition, repo repository.ClockedRepo) <-chan StreamedEntity {
+ out := make(chan StreamedEntity)
+
+ go func() {
+ defer close(out)
+
+ refPrefix := fmt.Sprintf("refs/%s/", def.namespace)
+
+ refs, err := repo.ListRefs(refPrefix)
+ if err != nil {
+ out <- StreamedEntity{Err: err}
+ return
+ }
+
+ for _, ref := range refs {
+ e, err := read(def, repo, ref)
+
+ if err != nil {
+ out <- StreamedEntity{Err: err}
+ return
+ }
+
+ out <- StreamedEntity{Entity: e}
+ }
+ }()
+
+ return out
+}
+
// Id return the Entity identifier
func (e *Entity) Id() entity.Id {
// id is the id of the first operation
diff --git a/entity/dag/entity_actions.go b/entity/dag/entity_actions.go
index 83ff7ddc..db3a545c 100644
--- a/entity/dag/entity_actions.go
+++ b/entity/dag/entity_actions.go
@@ -10,8 +10,8 @@ import (
)
// ListLocalIds list all the available local Entity's Id
-func ListLocalIds(typename string, repo repository.RepoData) ([]entity.Id, error) {
- refs, err := repo.ListRefs(fmt.Sprintf("refs/%s/", typename))
+func ListLocalIds(def Definition, repo repository.RepoData) ([]entity.Id, error) {
+ refs, err := repo.ListRefs(fmt.Sprintf("refs/%s/", def.namespace))
if err != nil {
return nil, err
}
@@ -75,10 +75,6 @@ func Pull(def Definition, repo repository.ClockedRepo, remote string) error {
func MergeAll(def Definition, repo repository.ClockedRepo, remote string) <-chan entity.MergeResult {
out := make(chan entity.MergeResult)
- // no caching for the merge, we load everything from git even if that means multiple
- // copy of the same entity in memory. The cache layer will intercept the results to
- // invalidate entities if necessary.
-
go func() {
defer close(out)
diff --git a/entity/dag/entity_actions_test.go b/entity/dag/entity_actions_test.go
new file mode 100644
index 00000000..6cc544b6
--- /dev/null
+++ b/entity/dag/entity_actions_test.go
@@ -0,0 +1,110 @@
+package dag
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/MichaelMure/git-bug/identity"
+ "github.com/MichaelMure/git-bug/repository"
+)
+
+func allEntities(t testing.TB, bugs <-chan StreamedEntity) []*Entity {
+ var result []*Entity
+ for streamed := range bugs {
+ if streamed.Err != nil {
+ t.Fatal(streamed.Err)
+ }
+ result = append(result, streamed.Entity)
+ }
+ return result
+}
+
+func TestPushPull(t *testing.T) {
+ repoA, repoB, remote, id1, id2, def := makeTestContextRemote()
+ defer repository.CleanupTestRepos(repoA, repoB, remote)
+
+ // distribute the identities
+ _, err := identity.Push(repoA, "origin")
+ require.NoError(t, err)
+ err = identity.Pull(repoB, "origin")
+ require.NoError(t, err)
+
+ // A --> remote --> B
+ entity := New(def)
+ entity.Append(newOp1(id1, "foo"))
+
+ err = entity.Commit(repoA)
+ require.NoError(t, err)
+
+ _, err = Push(def, repoA, "origin")
+ require.NoError(t, err)
+
+ err = Pull(def, repoB, "origin")
+ require.NoError(t, err)
+
+ entities := allEntities(t, ReadAll(def, repoB))
+ require.Len(t, entities, 1)
+
+ // B --> remote --> A
+ entity = New(def)
+ entity.Append(newOp2(id2, "bar"))
+
+ err = entity.Commit(repoB)
+ require.NoError(t, err)
+
+ _, err = Push(def, repoB, "origin")
+ require.NoError(t, err)
+
+ err = Pull(def, repoA, "origin")
+ require.NoError(t, err)
+
+ entities = allEntities(t, ReadAll(def, repoB))
+ require.Len(t, entities, 2)
+}
+
+func TestListLocalIds(t *testing.T) {
+ repoA, repoB, remote, id1, id2, def := makeTestContextRemote()
+ defer repository.CleanupTestRepos(repoA, repoB, remote)
+
+ // distribute the identities
+ _, err := identity.Push(repoA, "origin")
+ require.NoError(t, err)
+ err = identity.Pull(repoB, "origin")
+ require.NoError(t, err)
+
+ // A --> remote --> B
+ entity := New(def)
+ entity.Append(newOp1(id1, "foo"))
+ err = entity.Commit(repoA)
+ require.NoError(t, err)
+
+ entity = New(def)
+ entity.Append(newOp2(id2, "bar"))
+ err = entity.Commit(repoA)
+ require.NoError(t, err)
+
+ listLocalIds(t, def, repoA, 2)
+ listLocalIds(t, def, repoB, 0)
+
+ _, err = Push(def, repoA, "origin")
+ require.NoError(t, err)
+
+ _, err = Fetch(def, repoB, "origin")
+ require.NoError(t, err)
+
+ listLocalIds(t, def, repoA, 2)
+ listLocalIds(t, def, repoB, 0)
+
+ err = Pull(def, repoB, "origin")
+ require.NoError(t, err)
+
+ listLocalIds(t, def, repoA, 2)
+ listLocalIds(t, def, repoB, 2)
+}
+
+func listLocalIds(t *testing.T, def Definition, repo repository.RepoData, expectedCount int) {
+ ids, err := ListLocalIds(def, repo)
+ require.NoError(t, err)
+ require.Len(t, ids, expectedCount)
+}
diff --git a/repository/mock_repo.go b/repository/mock_repo.go
index 095ad61c..adbceec2 100644
--- a/repository/mock_repo.go
+++ b/repository/mock_repo.go
@@ -202,12 +202,12 @@ func NewMockRepoData() *mockRepoData {
}
func (r *mockRepoData) FetchRefs(remote string, refSpec string) (string, error) {
- return "", nil
+ panic("implement me")
}
// PushRefs push git refs to a remote
func (r *mockRepoData) PushRefs(remote string, refSpec string) (string, error) {
- return "", nil
+ panic("implement me")
}
func (r *mockRepoData) StoreData(data []byte) (Hash, error) {
diff --git a/repository/repo.go b/repository/repo.go
index 87426333..c31afa22 100644
--- a/repository/repo.go
+++ b/repository/repo.go
@@ -130,6 +130,7 @@ type RepoData interface {
ReadCommit(hash Hash) (Commit, error)
// GetTreeHash return the git tree hash referenced in a commit
+ // Deprecated
GetTreeHash(commit Hash) (Hash, error)
// ResolveRef returns the hash of the target commit of the given ref
diff --git a/repository/repo_testing.go b/repository/repo_testing.go
index 92aa1691..8fc109bb 100644
--- a/repository/repo_testing.go
+++ b/repository/repo_testing.go
@@ -10,6 +10,9 @@ import (
"github.com/MichaelMure/git-bug/util/lamport"
)
+// TODO: add tests for RepoBleve
+// TODO: add tests for RepoStorage
+
func CleanupTestRepos(repos ...Repo) {
var firstErr error
for _, repo := range repos {