aboutsummaryrefslogtreecommitdiffstats
path: root/entities
diff options
context:
space:
mode:
Diffstat (limited to 'entities')
-rw-r--r--entities/bug/bug.go57
-rw-r--r--entities/bug/bug_actions.go23
-rw-r--r--entities/bug/err.go17
-rw-r--r--entities/bug/operation.go7
-rw-r--r--entities/bug/resolver.go2
-rw-r--r--entities/bug/snapshot.go4
-rw-r--r--entities/bug/with_snapshot.go53
-rw-r--r--entities/identity/common.go9
-rw-r--r--entities/identity/identity.go38
-rw-r--r--entities/identity/identity_actions.go4
-rw-r--r--entities/identity/identity_actions_test.go5
-rw-r--r--entities/identity/identity_test.go7
-rw-r--r--entities/identity/identity_user.go2
-rw-r--r--entities/identity/resolver.go15
14 files changed, 50 insertions, 193 deletions
diff --git a/entities/bug/bug.go b/entities/bug/bug.go
index b0f46c0b..deb00c7c 100644
--- a/entities/bug/bug.go
+++ b/entities/bug/bug.go
@@ -20,9 +20,12 @@ var _ entity.Interface = &Bug{}
// 4: with DAG entity framework
const formatVersion = 4
+const Typename = "bug"
+const Namespace = "bugs"
+
var def = dag.Definition{
- Typename: "bug",
- Namespace: "bugs",
+ Typename: Typename,
+ Namespace: Namespace,
OperationUnmarshaler: operationUnmarshaler,
FormatVersion: formatVersion,
}
@@ -42,9 +45,11 @@ type Bug struct {
// NewBug create a new Bug
func NewBug() *Bug {
- return &Bug{
- Entity: dag.New(def),
- }
+ return wrapper(dag.New(def))
+}
+
+func wrapper(e *dag.Entity) *Bug {
+ return &Bug{Entity: e}
}
func simpleResolvers(repo repository.ClockedRepo) entity.Resolvers {
@@ -60,49 +65,17 @@ func Read(repo repository.ClockedRepo, id entity.Id) (*Bug, error) {
// ReadWithResolver will read a bug from its Id, with custom resolvers
func ReadWithResolver(repo repository.ClockedRepo, resolvers entity.Resolvers, id entity.Id) (*Bug, error) {
- e, err := dag.Read(def, repo, resolvers, id)
- if err != nil {
- return nil, err
- }
- return &Bug{Entity: e}, nil
-}
-
-type StreamedBug struct {
- Bug *Bug
- Err error
+ return dag.Read(def, wrapper, repo, resolvers, id)
}
// ReadAll read and parse all local bugs
-func ReadAll(repo repository.ClockedRepo) <-chan StreamedBug {
- return readAll(repo, simpleResolvers(repo))
+func ReadAll(repo repository.ClockedRepo) <-chan entity.StreamedEntity[*Bug] {
+ return dag.ReadAll(def, wrapper, repo, simpleResolvers(repo))
}
// ReadAllWithResolver read and parse all local bugs
-func ReadAllWithResolver(repo repository.ClockedRepo, resolvers entity.Resolvers) <-chan StreamedBug {
- return readAll(repo, resolvers)
-}
-
-// Read and parse all available bug with a given ref prefix
-func readAll(repo repository.ClockedRepo, resolvers entity.Resolvers) <-chan StreamedBug {
- out := make(chan StreamedBug)
-
- go func() {
- defer close(out)
-
- for streamedEntity := range dag.ReadAll(def, repo, resolvers) {
- if streamedEntity.Err != nil {
- out <- StreamedBug{
- Err: streamedEntity.Err,
- }
- } else {
- out <- StreamedBug{
- Bug: &Bug{Entity: streamedEntity.Entity},
- }
- }
- }
- }()
-
- return out
+func ReadAllWithResolver(repo repository.ClockedRepo, resolvers entity.Resolvers) <-chan entity.StreamedEntity[*Bug] {
+ return dag.ReadAll(def, wrapper, repo, resolvers)
}
// ListLocalIds list all the available local bug ids
diff --git a/entities/bug/bug_actions.go b/entities/bug/bug_actions.go
index c25b9243..198e4ed0 100644
--- a/entities/bug/bug_actions.go
+++ b/entities/bug/bug_actions.go
@@ -23,33 +23,14 @@ func Push(repo repository.Repo, remote string) (string, error) {
// Note: an author is necessary for the case where a merge commit is created, as this commit will
// have an author and may be signed if a signing key is available.
func Pull(repo repository.ClockedRepo, resolvers entity.Resolvers, remote string, mergeAuthor identity.Interface) error {
- return dag.Pull(def, repo, resolvers, remote, mergeAuthor)
+ return dag.Pull(def, wrapper, repo, resolvers, remote, mergeAuthor)
}
// MergeAll will merge all the available remote bug
// Note: an author is necessary for the case where a merge commit is created, as this commit will
// have an author and may be signed if a signing key is available.
func MergeAll(repo repository.ClockedRepo, resolvers entity.Resolvers, remote string, mergeAuthor identity.Interface) <-chan entity.MergeResult {
- out := make(chan entity.MergeResult)
-
- go func() {
- defer close(out)
-
- results := dag.MergeAll(def, repo, resolvers, remote, mergeAuthor)
-
- // wrap the dag.Entity into a complete Bug
- for result := range results {
- result := result
- if result.Entity != nil {
- result.Entity = &Bug{
- Entity: result.Entity.(*dag.Entity),
- }
- }
- out <- result
- }
- }()
-
- return out
+ return dag.MergeAll(def, wrapper, repo, resolvers, remote, mergeAuthor)
}
// Remove will remove a local bug from its entity.Id
diff --git a/entities/bug/err.go b/entities/bug/err.go
deleted file mode 100644
index 1bd174bb..00000000
--- a/entities/bug/err.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package bug
-
-import (
- "errors"
-
- "github.com/MichaelMure/git-bug/entity"
-)
-
-var ErrBugNotExist = errors.New("bug doesn't exist")
-
-func NewErrMultipleMatchBug(matching []entity.Id) *entity.ErrMultipleMatch {
- return entity.NewErrMultipleMatch("bug", matching)
-}
-
-func NewErrMultipleMatchOp(matching []entity.Id) *entity.ErrMultipleMatch {
- return entity.NewErrMultipleMatch("operation", matching)
-}
diff --git a/entities/bug/operation.go b/entities/bug/operation.go
index 41d80700..04365046 100644
--- a/entities/bug/operation.go
+++ b/entities/bug/operation.go
@@ -21,12 +21,7 @@ const (
)
// Operation define the interface to fulfill for an edit operation of a Bug
-type Operation interface {
- dag.Operation
-
- // Apply the operation to a Snapshot to create the final state
- Apply(snapshot *Snapshot)
-}
+type Operation = dag.OperationWithApply[*Snapshot]
// make sure that package external operations do conform to our interface
var _ Operation = &dag.NoOpOperation[*Snapshot]{}
diff --git a/entities/bug/resolver.go b/entities/bug/resolver.go
index e7beb0e4..b0a05917 100644
--- a/entities/bug/resolver.go
+++ b/entities/bug/resolver.go
@@ -16,6 +16,6 @@ func NewSimpleResolver(repo repository.ClockedRepo) *SimpleResolver {
return &SimpleResolver{repo: repo}
}
-func (r *SimpleResolver) Resolve(id entity.Id) (entity.Interface, error) {
+func (r *SimpleResolver) Resolve(id entity.Id) (entity.Resolved, error) {
return Read(r.repo, id)
}
diff --git a/entities/bug/snapshot.go b/entities/bug/snapshot.go
index 333fe207..5c260d85 100644
--- a/entities/bug/snapshot.go
+++ b/entities/bug/snapshot.go
@@ -43,6 +43,10 @@ func (snap *Snapshot) AllOperations() []dag.Operation {
return snap.Operations
}
+func (snap *Snapshot) AppendOperation(op dag.Operation) {
+ snap.Operations = append(snap.Operations, op)
+}
+
// EditTime returns the last time a bug was modified
func (snap *Snapshot) EditTime() time.Time {
if len(snap.Operations) == 0 {
diff --git a/entities/bug/with_snapshot.go b/entities/bug/with_snapshot.go
deleted file mode 100644
index 0474cac7..00000000
--- a/entities/bug/with_snapshot.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package bug
-
-import (
- "github.com/MichaelMure/git-bug/repository"
-)
-
-var _ Interface = &WithSnapshot{}
-
-// WithSnapshot encapsulate a Bug and maintain the corresponding Snapshot efficiently
-type WithSnapshot struct {
- *Bug
- snap *Snapshot
-}
-
-func (b *WithSnapshot) Compile() *Snapshot {
- if b.snap == nil {
- snap := b.Bug.Compile()
- b.snap = snap
- }
- return b.snap
-}
-
-// Append intercept Bug.Append() to update the snapshot efficiently
-func (b *WithSnapshot) Append(op Operation) {
- b.Bug.Append(op)
-
- if b.snap == nil {
- return
- }
-
- op.Apply(b.snap)
- b.snap.Operations = append(b.snap.Operations, op)
-}
-
-// Commit intercept Bug.Commit() to update the snapshot efficiently
-func (b *WithSnapshot) Commit(repo repository.ClockedRepo) error {
- err := b.Bug.Commit(repo)
-
- if err != nil {
- b.snap = nil
- return err
- }
-
- // Commit() shouldn't change anything of the bug state apart from the
- // initial ID set
-
- if b.snap == nil {
- return nil
- }
-
- b.snap.id = b.Bug.Id()
- return nil
-}
diff --git a/entities/identity/common.go b/entities/identity/common.go
index 5c6445e9..88e30e33 100644
--- a/entities/identity/common.go
+++ b/entities/identity/common.go
@@ -2,18 +2,9 @@ package identity
import (
"encoding/json"
- "errors"
"fmt"
-
- "github.com/MichaelMure/git-bug/entity"
)
-var ErrIdentityNotExist = errors.New("identity doesn't exist")
-
-func NewErrMultipleMatch(matching []entity.Id) *entity.ErrMultipleMatch {
- return entity.NewErrMultipleMatch("identity", matching)
-}
-
// Custom unmarshaling function to allow package user to delegate
// the decoding of an Identity and distinguish between an Identity
// and a Bare.
diff --git a/entities/identity/identity.go b/entities/identity/identity.go
index d497dbcc..b0cee43b 100644
--- a/entities/identity/identity.go
+++ b/entities/identity/identity.go
@@ -19,16 +19,15 @@ const identityRemoteRefPattern = "refs/remotes/%s/identities/"
const versionEntryName = "version"
const identityConfigKey = "git-bug.identity"
+const Typename = "identity"
+const Namespace = "identities"
+
var ErrNonFastForwardMerge = errors.New("non fast-forward identity merge")
var ErrNoIdentitySet = errors.New("No identity is set.\n" +
"To interact with bugs, an identity first needs to be created using " +
"\"git bug user new\" or adopted with \"git bug user adopt\"")
var ErrMultipleIdentitiesSet = errors.New("multiple user identities set")
-func NewErrMultipleMatchIdentity(matching []entity.Id) *entity.ErrMultipleMatch {
- return entity.NewErrMultipleMatch("identity", matching)
-}
-
var _ Interface = &Identity{}
var _ entity.Interface = &Identity{}
@@ -109,7 +108,7 @@ func read(repo repository.Repo, ref string) (*Identity, error) {
hashes, err := repo.ListCommits(ref)
if err != nil {
- return nil, ErrIdentityNotExist
+ return nil, entity.NewErrNotFound(Typename)
}
if len(hashes) == 0 {
return nil, fmt.Errorf("empty identity")
@@ -174,7 +173,7 @@ func RemoveIdentity(repo repository.ClockedRepo, id entity.Id) error {
return err
}
if len(refs) > 1 {
- return NewErrMultipleMatchIdentity(entity.RefsToIds(refs))
+ return entity.NewErrMultipleMatch(Typename, entity.RefsToIds(refs))
}
if len(refs) == 1 {
// we have the identity locally
@@ -193,7 +192,7 @@ func RemoveIdentity(repo repository.ClockedRepo, id entity.Id) error {
return err
}
if len(remoteRefs) > 1 {
- return NewErrMultipleMatchIdentity(entity.RefsToIds(refs))
+ return entity.NewErrMultipleMatch(Typename, entity.RefsToIds(refs))
}
if len(remoteRefs) == 1 {
// found the identity in a remote
@@ -202,7 +201,7 @@ func RemoveIdentity(repo repository.ClockedRepo, id entity.Id) error {
}
if len(fullMatches) == 0 {
- return ErrIdentityNotExist
+ return entity.NewErrNotFound(Typename)
}
for _, ref := range fullMatches {
@@ -215,44 +214,39 @@ func RemoveIdentity(repo repository.ClockedRepo, id entity.Id) error {
return nil
}
-type StreamedIdentity struct {
- Identity *Identity
- Err error
-}
-
// ReadAllLocal read and parse all local Identity
-func ReadAllLocal(repo repository.ClockedRepo) <-chan StreamedIdentity {
+func ReadAllLocal(repo repository.ClockedRepo) <-chan entity.StreamedEntity[*Identity] {
return readAll(repo, identityRefPattern)
}
// ReadAllRemote read and parse all remote Identity for a given remote
-func ReadAllRemote(repo repository.ClockedRepo, remote string) <-chan StreamedIdentity {
+func ReadAllRemote(repo repository.ClockedRepo, remote string) <-chan entity.StreamedEntity[*Identity] {
refPrefix := fmt.Sprintf(identityRemoteRefPattern, remote)
return readAll(repo, refPrefix)
}
// readAll read and parse all available bug with a given ref prefix
-func readAll(repo repository.ClockedRepo, refPrefix string) <-chan StreamedIdentity {
- out := make(chan StreamedIdentity)
+func readAll(repo repository.ClockedRepo, refPrefix string) <-chan entity.StreamedEntity[*Identity] {
+ out := make(chan entity.StreamedEntity[*Identity])
go func() {
defer close(out)
refs, err := repo.ListRefs(refPrefix)
if err != nil {
- out <- StreamedIdentity{Err: err}
+ out <- entity.StreamedEntity[*Identity]{Err: err}
return
}
for _, ref := range refs {
- b, err := read(repo, ref)
+ i, err := read(repo, ref)
if err != nil {
- out <- StreamedIdentity{Err: err}
+ out <- entity.StreamedEntity[*Identity]{Err: err}
return
}
- out <- StreamedIdentity{Identity: b}
+ out <- entity.StreamedEntity[*Identity]{Entity: i}
}
}()
@@ -308,7 +302,7 @@ func (i *Identity) Mutate(repo repository.RepoClock, f func(orig *Mutator)) erro
return nil
}
-// Write the identity into the Repository. In particular, this ensure that
+// Commit write the identity into the Repository. In particular, this ensures that
// the Id is properly set.
func (i *Identity) Commit(repo repository.ClockedRepo) error {
if !i.NeedCommit() {
diff --git a/entities/identity/identity_actions.go b/entities/identity/identity_actions.go
index b58bb2d9..13776078 100644
--- a/entities/identity/identity_actions.go
+++ b/entities/identity/identity_actions.go
@@ -13,12 +13,12 @@ import (
// Fetch retrieve updates from a remote
// This does not change the local identities state
func Fetch(repo repository.Repo, remote string) (string, error) {
- return repo.FetchRefs(remote, "identities")
+ return repo.FetchRefs(remote, Namespace)
}
// Push update a remote with the local changes
func Push(repo repository.Repo, remote string) (string, error) {
- return repo.PushRefs(remote, "identities")
+ return repo.PushRefs(remote, Namespace)
}
// Pull will do a Fetch + MergeAll
diff --git a/entities/identity/identity_actions_test.go b/entities/identity/identity_actions_test.go
index 351fb7a4..e9626cb9 100644
--- a/entities/identity/identity_actions_test.go
+++ b/entities/identity/identity_actions_test.go
@@ -5,6 +5,7 @@ import (
"github.com/stretchr/testify/require"
+ "github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/repository"
)
@@ -145,13 +146,13 @@ func TestIdentityPushPull(t *testing.T) {
}
}
-func allIdentities(t testing.TB, identities <-chan StreamedIdentity) []*Identity {
+func allIdentities(t testing.TB, identities <-chan entity.StreamedEntity[*Identity]) []*Identity {
var result []*Identity
for streamed := range identities {
if streamed.Err != nil {
t.Fatal(streamed.Err)
}
- result = append(result, streamed.Identity)
+ result = append(result, streamed.Entity)
}
return result
}
diff --git a/entities/identity/identity_test.go b/entities/identity/identity_test.go
index f0c3bbe9..0ecc8058 100644
--- a/entities/identity/identity_test.go
+++ b/entities/identity/identity_test.go
@@ -6,6 +6,7 @@ import (
"github.com/stretchr/testify/require"
+ "github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/repository"
"github.com/MichaelMure/git-bug/util/lamport"
)
@@ -278,13 +279,13 @@ func TestIdentityRemove(t *testing.T) {
require.NoError(t, err)
_, err = ReadLocal(repo, rene.Id())
- require.Error(t, ErrIdentityNotExist, err)
+ require.ErrorAs(t, entity.ErrNotFound{}, err)
_, err = ReadRemote(repo, "remoteA", string(rene.Id()))
- require.Error(t, ErrIdentityNotExist, err)
+ require.ErrorAs(t, entity.ErrNotFound{}, err)
_, err = ReadRemote(repo, "remoteB", string(rene.Id()))
- require.Error(t, ErrIdentityNotExist, err)
+ require.ErrorAs(t, entity.ErrNotFound{}, err)
ids, err := ListLocalIds(repo)
require.NoError(t, err)
diff --git a/entities/identity/identity_user.go b/entities/identity/identity_user.go
index cd67459e..e671e662 100644
--- a/entities/identity/identity_user.go
+++ b/entities/identity/identity_user.go
@@ -23,7 +23,7 @@ func GetUserIdentity(repo repository.Repo) (*Identity, error) {
}
i, err := ReadLocal(repo, id)
- if err == ErrIdentityNotExist {
+ if entity.IsErrNotFound(err) {
innerErr := repo.LocalConfig().RemoveAll(identityConfigKey)
if innerErr != nil {
_, _ = fmt.Fprintln(os.Stderr, errors.Wrap(innerErr, "can't clear user identity").Error())
diff --git a/entities/identity/resolver.go b/entities/identity/resolver.go
index 5468a8f8..a4b676f3 100644
--- a/entities/identity/resolver.go
+++ b/entities/identity/resolver.go
@@ -16,19 +16,6 @@ func NewSimpleResolver(repo repository.Repo) *SimpleResolver {
return &SimpleResolver{repo: repo}
}
-func (r *SimpleResolver) Resolve(id entity.Id) (entity.Interface, error) {
+func (r *SimpleResolver) Resolve(id entity.Id) (entity.Resolved, error) {
return ReadLocal(r.repo, id)
}
-
-var _ entity.Resolver = &StubResolver{}
-
-// StubResolver is a Resolver that doesn't load anything, only returning IdentityStub instances
-type StubResolver struct{}
-
-func NewStubResolver() *StubResolver {
- return &StubResolver{}
-}
-
-func (s *StubResolver) Resolve(id entity.Id) (entity.Interface, error) {
- return &IdentityStub{id: id}, nil
-}