aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/graphql/gen_graphql.go33
-rw-r--r--api/graphql/gqlgen.yml5
-rw-r--r--api/graphql/graph/bug.generated.go102
-rw-r--r--api/graphql/graph/identity.generated.go33
-rw-r--r--api/graphql/graph/mutations.generated.go16
-rw-r--r--api/graphql/graph/operations.generated.go193
-rw-r--r--api/graphql/graph/prelude.generated.go11
-rw-r--r--api/graphql/graph/root_.generated.go97
-rw-r--r--api/graphql/graph/timeline.generated.go41
-rw-r--r--api/graphql/graph/types.generated.go17
-rw-r--r--api/graphql/handler.go2
-rw-r--r--api/graphql/models/gen_models.go6
-rw-r--r--api/graphql/resolvers/bug.go4
-rw-r--r--api/graphql/resolvers/comment.go5
-rw-r--r--api/graphql/resolvers/mutation.go10
-rw-r--r--api/graphql/resolvers/operations.go24
-rw-r--r--api/graphql/resolvers/timeline.go21
-rw-r--r--api/graphql/schema/bug.graphql4
-rw-r--r--api/graphql/schema/identity.graphql2
-rw-r--r--api/graphql/schema/mutations.graphql6
-rw-r--r--api/graphql/schema/operations.graphql14
-rw-r--r--api/graphql/schema/timeline.graphql12
-rw-r--r--api/graphql/schema/types.graphql1
-rw-r--r--api/graphql/tools.go8
-rw-r--r--api/http/git_file_handler.go2
-rw-r--r--bridge/github/export_test.go7
-rw-r--r--bridge/github/import.go3
-rw-r--r--bridge/gitlab/export_test.go7
-rw-r--r--bridge/gitlab/import.go13
-rw-r--r--bridge/jira/import.go5
-rw-r--r--cache/bug_cache.go11
-rw-r--r--cache/repo_cache_bug.go14
-rw-r--r--commands/comment.go2
-rw-r--r--commands/show.go6
-rw-r--r--entities/bug/comment.go29
-rw-r--r--entities/bug/op_add_comment.go15
-rw-r--r--entities/bug/op_create.go13
-rw-r--r--entities/bug/op_create_test.go56
-rw-r--r--entities/bug/op_edit_comment.go17
-rw-r--r--entities/bug/op_label_change.go31
-rw-r--r--entities/bug/op_set_status.go25
-rw-r--r--entities/bug/op_set_title.go29
-rw-r--r--entities/bug/snapshot.go23
-rw-r--r--entities/bug/timeline.go42
-rw-r--r--entity/id.go18
-rw-r--r--entity/id_interleaved.go84
-rw-r--r--entity/id_interleaved_test.go2
-rw-r--r--go.mod2
-rw-r--r--go.sum2
-rw-r--r--repository/gogit.go1
-rw-r--r--termui/show_bug.go8
-rw-r--r--termui/termui.go2
52 files changed, 583 insertions, 553 deletions
diff --git a/api/graphql/gen_graphql.go b/api/graphql/gen_graphql.go
deleted file mode 100644
index 19c5f1e3..00000000
--- a/api/graphql/gen_graphql.go
+++ /dev/null
@@ -1,33 +0,0 @@
-//go:build ignore
-
-package main
-
-import (
- "fmt"
- "io/ioutil"
- "log"
- "os"
-
- "github.com/99designs/gqlgen/api"
- "github.com/99designs/gqlgen/codegen/config"
- "github.com/pkg/errors"
-)
-
-func main() {
- fmt.Println("Generating graphql code ...")
-
- log.SetOutput(ioutil.Discard)
-
- cfg, err := config.LoadConfigFromDefaultLocations()
- if os.IsNotExist(errors.Cause(err)) {
- cfg = config.DefaultConfig()
- } else if err != nil {
- _, _ = fmt.Fprintln(os.Stderr, err.Error())
- os.Exit(2)
- }
-
- if err = api.Generate(cfg); err != nil {
- _, _ = fmt.Fprintln(os.Stderr, err.Error())
- os.Exit(3)
- }
-}
diff --git a/api/graphql/gqlgen.yml b/api/graphql/gqlgen.yml
index fbb46db6..98d31a5c 100644
--- a/api/graphql/gqlgen.yml
+++ b/api/graphql/gqlgen.yml
@@ -6,17 +6,18 @@ exec:
model:
filename: models/gen_models.go
-skip_mod_tidy: true
-
autobind:
- "github.com/MichaelMure/git-bug/api/graphql/models"
- "github.com/MichaelMure/git-bug/repository"
+ - "github.com/MichaelMure/git-bug/entity"
- "github.com/MichaelMure/git-bug/entity/dag"
- "github.com/MichaelMure/git-bug/entities/common"
- "github.com/MichaelMure/git-bug/entities/bug"
- "github.com/MichaelMure/git-bug/entities/identity"
models:
+ ID:
+ model: github.com/MichaelMure/git-bug/entity.Id
Bug:
model: github.com/MichaelMure/git-bug/api/graphql/models.BugWrapper
Color:
diff --git a/api/graphql/graph/bug.generated.go b/api/graphql/graph/bug.generated.go
index 67af1933..ab9c6c34 100644
--- a/api/graphql/graph/bug.generated.go
+++ b/api/graphql/graph/bug.generated.go
@@ -15,6 +15,7 @@ import (
"github.com/MichaelMure/git-bug/api/graphql/models"
"github.com/MichaelMure/git-bug/entities/bug"
"github.com/MichaelMure/git-bug/entities/common"
+ "github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/repository"
"github.com/vektah/gqlparser/v2/ast"
)
@@ -22,7 +23,6 @@ import (
// region ************************** generated!.gotpl **************************
type BugResolver interface {
- ID(ctx context.Context, obj models.BugWrapper) (string, error)
HumanID(ctx context.Context, obj models.BugWrapper) (string, error)
Actors(ctx context.Context, obj models.BugWrapper, after *string, before *string, first *int, last *int) (*models.IdentityConnection, error)
@@ -32,6 +32,7 @@ type BugResolver interface {
Operations(ctx context.Context, obj models.BugWrapper, after *string, before *string, first *int, last *int) (*models.OperationConnection, error)
}
type CommentResolver interface {
+ ID(ctx context.Context, obj *bug.Comment) (entity.CombinedId, error)
Author(ctx context.Context, obj *bug.Comment) (models.IdentityWrapper, error)
}
@@ -271,7 +272,7 @@ func (ec *executionContext) _Bug_id(ctx context.Context, field graphql.Collected
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
- return ec.resolvers.Bug().ID(rctx, obj)
+ return obj.Id(), nil
})
if err != nil {
ec.Error(ctx, err)
@@ -283,9 +284,9 @@ func (ec *executionContext) _Bug_id(ctx context.Context, field graphql.Collected
}
return graphql.Null
}
- res := resTmp.(string)
+ res := resTmp.(entity.Id)
fc.Result = res
- return ec.marshalNString2string(ctx, field.Selections, res)
+ return ec.marshalNID2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐId(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Bug_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@@ -293,9 +294,9 @@ func (ec *executionContext) fieldContext_Bug_id(ctx context.Context, field graph
Object: "Bug",
Field: field,
IsMethod: true,
- IsResolver: true,
+ IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
- return nil, errors.New("field of type String does not have child fields")
+ return nil, errors.New("field of type ID does not have child fields")
},
}
return fc, nil
@@ -1294,6 +1295,50 @@ func (ec *executionContext) fieldContext_BugEdge_node(ctx context.Context, field
return fc, nil
}
+func (ec *executionContext) _Comment_id(ctx context.Context, field graphql.CollectedField, obj *bug.Comment) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_Comment_id(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Comment().ID(rctx, obj)
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if resTmp == nil {
+ if !graphql.HasFieldError(ctx, fc) {
+ ec.Errorf(ctx, "must not be null")
+ }
+ return graphql.Null
+ }
+ res := resTmp.(entity.CombinedId)
+ fc.Result = res
+ return ec.marshalNCombinedId2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐCombinedId(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_Comment_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "Comment",
+ Field: field,
+ IsMethod: true,
+ IsResolver: true,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type CombinedId does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
func (ec *executionContext) _Comment_author(ctx context.Context, field graphql.CollectedField, obj *bug.Comment) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Comment_author(ctx, field)
if err != nil {
@@ -1533,6 +1578,8 @@ func (ec *executionContext) fieldContext_CommentConnection_nodes(ctx context.Con
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name {
+ case "id":
+ return ec.fieldContext_Comment_id(ctx, field)
case "author":
return ec.fieldContext_Comment_author(ctx, field)
case "message":
@@ -1727,6 +1774,8 @@ func (ec *executionContext) fieldContext_CommentEdge_node(ctx context.Context, f
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name {
+ case "id":
+ return ec.fieldContext_Comment_id(ctx, field)
case "author":
return ec.fieldContext_Comment_author(ctx, field)
case "message":
@@ -1763,25 +1812,12 @@ func (ec *executionContext) _Bug(ctx context.Context, sel ast.SelectionSet, obj
case "__typename":
out.Values[i] = graphql.MarshalString("Bug")
case "id":
- field := field
- innerFunc := func(ctx context.Context) (res graphql.Marshaler) {
- defer func() {
- if r := recover(); r != nil {
- ec.Error(ctx, ec.Recover(ctx, r))
- }
- }()
- res = ec._Bug_id(ctx, field, obj)
- if res == graphql.Null {
- atomic.AddUint32(&invalids, 1)
- }
- return res
- }
-
- out.Concurrently(i, func() graphql.Marshaler {
- return innerFunc(ctx)
+ out.Values[i] = ec._Bug_id(ctx, field, obj)
- })
+ if out.Values[i] == graphql.Null {
+ atomic.AddUint32(&invalids, 1)
+ }
case "humanId":
field := field
@@ -2049,6 +2085,26 @@ func (ec *executionContext) _Comment(ctx context.Context, sel ast.SelectionSet,
switch field.Name {
case "__typename":
out.Values[i] = graphql.MarshalString("Comment")
+ case "id":
+ field := field
+
+ innerFunc := func(ctx context.Context) (res graphql.Marshaler) {
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ }
+ }()
+ res = ec._Comment_id(ctx, field, obj)
+ if res == graphql.Null {
+ atomic.AddUint32(&invalids, 1)
+ }
+ return res
+ }
+
+ out.Concurrently(i, func() graphql.Marshaler {
+ return innerFunc(ctx)
+
+ })
case "author":
field := field
diff --git a/api/graphql/graph/identity.generated.go b/api/graphql/graph/identity.generated.go
index 7fa9b9f0..51aa188b 100644
--- a/api/graphql/graph/identity.generated.go
+++ b/api/graphql/graph/identity.generated.go
@@ -12,13 +12,13 @@ import (
"github.com/99designs/gqlgen/graphql"
"github.com/MichaelMure/git-bug/api/graphql/models"
+ "github.com/MichaelMure/git-bug/entity"
"github.com/vektah/gqlparser/v2/ast"
)
// region ************************** generated!.gotpl **************************
type IdentityResolver interface {
- ID(ctx context.Context, obj models.IdentityWrapper) (string, error)
HumanID(ctx context.Context, obj models.IdentityWrapper) (string, error)
}
@@ -48,7 +48,7 @@ func (ec *executionContext) _Identity_id(ctx context.Context, field graphql.Coll
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
- return ec.resolvers.Identity().ID(rctx, obj)
+ return obj.Id(), nil
})
if err != nil {
ec.Error(ctx, err)
@@ -60,9 +60,9 @@ func (ec *executionContext) _Identity_id(ctx context.Context, field graphql.Coll
}
return graphql.Null
}
- res := resTmp.(string)
+ res := resTmp.(entity.Id)
fc.Result = res
- return ec.marshalNString2string(ctx, field.Selections, res)
+ return ec.marshalNID2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐId(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Identity_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@@ -70,9 +70,9 @@ func (ec *executionContext) fieldContext_Identity_id(ctx context.Context, field
Object: "Identity",
Field: field,
IsMethod: true,
- IsResolver: true,
+ IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
- return nil, errors.New("field of type String does not have child fields")
+ return nil, errors.New("field of type ID does not have child fields")
},
}
return fc, nil
@@ -713,25 +713,12 @@ func (ec *executionContext) _Identity(ctx context.Context, sel ast.SelectionSet,
case "__typename":
out.Values[i] = graphql.MarshalString("Identity")
case "id":
- field := field
-
- innerFunc := func(ctx context.Context) (res graphql.Marshaler) {
- defer func() {
- if r := recover(); r != nil {
- ec.Error(ctx, ec.Recover(ctx, r))
- }
- }()
- res = ec._Identity_id(ctx, field, obj)
- if res == graphql.Null {
- atomic.AddUint32(&invalids, 1)
- }
- return res
- }
- out.Concurrently(i, func() graphql.Marshaler {
- return innerFunc(ctx)
+ out.Values[i] = ec._Identity_id(ctx, field, obj)
- })
+ if out.Values[i] == graphql.Null {
+ atomic.AddUint32(&invalids, 1)
+ }
case "humanId":
field := field
diff --git a/api/graphql/graph/mutations.generated.go b/api/graphql/graph/mutations.generated.go
index 9d5df56e..11604d11 100644
--- a/api/graphql/graph/mutations.generated.go
+++ b/api/graphql/graph/mutations.generated.go
@@ -2097,7 +2097,7 @@ func (ec *executionContext) unmarshalInputEditCommentInput(ctx context.Context,
asMap[k] = v
}
- fieldsInOrder := [...]string{"clientMutationId", "repoRef", "prefix", "target", "message", "files"}
+ fieldsInOrder := [...]string{"clientMutationId", "repoRef", "targetPrefix", "message", "files"}
for _, k := range fieldsInOrder {
v, ok := asMap[k]
if !ok {
@@ -2120,19 +2120,11 @@ func (ec *executionContext) unmarshalInputEditCommentInput(ctx context.Context,
if err != nil {
return it, err
}
- case "prefix":
- var err error
-
- ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("prefix"))
- it.Prefix, err = ec.unmarshalNString2string(ctx, v)
- if err != nil {
- return it, err
- }
- case "target":
+ case "targetPrefix":
var err error
- ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("target"))
- it.Target, err = ec.unmarshalNString2string(ctx, v)
+ ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("targetPrefix"))
+ it.TargetPrefix, err = ec.unmarshalNString2string(ctx, v)
if err != nil {
return it, err
}
diff --git a/api/graphql/graph/operations.generated.go b/api/graphql/graph/operations.generated.go
index 39a216f4..cc3cd9b7 100644
--- a/api/graphql/graph/operations.generated.go
+++ b/api/graphql/graph/operations.generated.go
@@ -15,6 +15,7 @@ import (
"github.com/MichaelMure/git-bug/api/graphql/models"
"github.com/MichaelMure/git-bug/entities/bug"
"github.com/MichaelMure/git-bug/entities/common"
+ "github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/entity/dag"
"github.com/MichaelMure/git-bug/repository"
"github.com/vektah/gqlparser/v2/ast"
@@ -23,33 +24,27 @@ import (
// region ************************** generated!.gotpl **************************
type AddCommentOperationResolver interface {
- ID(ctx context.Context, obj *bug.AddCommentOperation) (string, error)
Author(ctx context.Context, obj *bug.AddCommentOperation) (models.IdentityWrapper, error)
Date(ctx context.Context, obj *bug.AddCommentOperation) (*time.Time, error)
}
type CreateOperationResolver interface {
- ID(ctx context.Context, obj *bug.CreateOperation) (string, error)
Author(ctx context.Context, obj *bug.CreateOperation) (models.IdentityWrapper, error)
Date(ctx context.Context, obj *bug.CreateOperation) (*time.Time, error)
}
type EditCommentOperationResolver interface {
- ID(ctx context.Context, obj *bug.EditCommentOperation) (string, error)
Author(ctx context.Context, obj *bug.EditCommentOperation) (models.IdentityWrapper, error)
Date(ctx context.Context, obj *bug.EditCommentOperation) (*time.Time, error)
Target(ctx context.Context, obj *bug.EditCommentOperation) (string, error)
}
type LabelChangeOperationResolver interface {
- ID(ctx context.Context, obj *bug.LabelChangeOperation) (string, error)
Author(ctx context.Context, obj *bug.LabelChangeOperation) (models.IdentityWrapper, error)
Date(ctx context.Context, obj *bug.LabelChangeOperation) (*time.Time, error)
}
type SetStatusOperationResolver interface {
- ID(ctx context.Context, obj *bug.SetStatusOperation) (string, error)
Author(ctx context.Context, obj *bug.SetStatusOperation) (models.IdentityWrapper, error)
Date(ctx context.Context, obj *bug.SetStatusOperation) (*time.Time, error)
}
type SetTitleOperationResolver interface {
- ID(ctx context.Context, obj *bug.SetTitleOperation) (string, error)
Author(ctx context.Context, obj *bug.SetTitleOperation) (models.IdentityWrapper, error)
Date(ctx context.Context, obj *bug.SetTitleOperation) (*time.Time, error)
}
@@ -80,7 +75,7 @@ func (ec *executionContext) _AddCommentOperation_id(ctx context.Context, field g
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
- return ec.resolvers.AddCommentOperation().ID(rctx, obj)
+ return obj.Id(), nil
})
if err != nil {
ec.Error(ctx, err)
@@ -92,9 +87,9 @@ func (ec *executionContext) _AddCommentOperation_id(ctx context.Context, field g
}
return graphql.Null
}
- res := resTmp.(string)
+ res := resTmp.(entity.Id)
fc.Result = res
- return ec.marshalNString2string(ctx, field.Selections, res)
+ return ec.marshalNID2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐId(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_AddCommentOperation_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@@ -102,9 +97,9 @@ func (ec *executionContext) fieldContext_AddCommentOperation_id(ctx context.Cont
Object: "AddCommentOperation",
Field: field,
IsMethod: true,
- IsResolver: true,
+ IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
- return nil, errors.New("field of type String does not have child fields")
+ return nil, errors.New("field of type ID does not have child fields")
},
}
return fc, nil
@@ -318,7 +313,7 @@ func (ec *executionContext) _CreateOperation_id(ctx context.Context, field graph
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
- return ec.resolvers.CreateOperation().ID(rctx, obj)
+ return obj.Id(), nil
})
if err != nil {
ec.Error(ctx, err)
@@ -330,9 +325,9 @@ func (ec *executionContext) _CreateOperation_id(ctx context.Context, field graph
}
return graphql.Null
}
- res := resTmp.(string)
+ res := resTmp.(entity.Id)
fc.Result = res
- return ec.marshalNString2string(ctx, field.Selections, res)
+ return ec.marshalNID2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐId(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_CreateOperation_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@@ -340,9 +335,9 @@ func (ec *executionContext) fieldContext_CreateOperation_id(ctx context.Context,
Object: "CreateOperation",
Field: field,
IsMethod: true,
- IsResolver: true,
+ IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
- return nil, errors.New("field of type String does not have child fields")
+ return nil, errors.New("field of type ID does not have child fields")
},
}
return fc, nil
@@ -600,7 +595,7 @@ func (ec *executionContext) _EditCommentOperation_id(ctx context.Context, field
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
- return ec.resolvers.EditCommentOperation().ID(rctx, obj)
+ return obj.Id(), nil
})
if err != nil {
ec.Error(ctx, err)
@@ -612,9 +607,9 @@ func (ec *executionContext) _EditCommentOperation_id(ctx context.Context, field
}
return graphql.Null
}
- res := resTmp.(string)
+ res := resTmp.(entity.Id)
fc.Result = res
- return ec.marshalNString2string(ctx, field.Selections, res)
+ return ec.marshalNID2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐId(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_EditCommentOperation_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@@ -622,9 +617,9 @@ func (ec *executionContext) fieldContext_EditCommentOperation_id(ctx context.Con
Object: "EditCommentOperation",
Field: field,
IsMethod: true,
- IsResolver: true,
+ IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
- return nil, errors.New("field of type String does not have child fields")
+ return nil, errors.New("field of type ID does not have child fields")
},
}
return fc, nil
@@ -882,7 +877,7 @@ func (ec *executionContext) _LabelChangeOperation_id(ctx context.Context, field
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
- return ec.resolvers.LabelChangeOperation().ID(rctx, obj)
+ return obj.Id(), nil
})
if err != nil {
ec.Error(ctx, err)
@@ -894,9 +889,9 @@ func (ec *executionContext) _LabelChangeOperation_id(ctx context.Context, field
}
return graphql.Null
}
- res := resTmp.(string)
+ res := resTmp.(entity.Id)
fc.Result = res
- return ec.marshalNString2string(ctx, field.Selections, res)
+ return ec.marshalNID2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐId(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_LabelChangeOperation_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@@ -904,9 +899,9 @@ func (ec *executionContext) fieldContext_LabelChangeOperation_id(ctx context.Con
Object: "LabelChangeOperation",
Field: field,
IsMethod: true,
- IsResolver: true,
+ IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
- return nil, errors.New("field of type String does not have child fields")
+ return nil, errors.New("field of type ID does not have child fields")
},
}
return fc, nil
@@ -1412,7 +1407,7 @@ func (ec *executionContext) _SetStatusOperation_id(ctx context.Context, field gr
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
- return ec.resolvers.SetStatusOperation().ID(rctx, obj)
+ return obj.Id(), nil
})
if err != nil {
ec.Error(ctx, err)
@@ -1424,9 +1419,9 @@ func (ec *executionContext) _SetStatusOperation_id(ctx context.Context, field gr
}
return graphql.Null
}
- res := resTmp.(string)
+ res := resTmp.(entity.Id)
fc.Result = res
- return ec.marshalNString2string(ctx, field.Selections, res)
+ return ec.marshalNID2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐId(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_SetStatusOperation_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@@ -1434,9 +1429,9 @@ func (ec *executionContext) fieldContext_SetStatusOperation_id(ctx context.Conte
Object: "SetStatusOperation",
Field: field,
IsMethod: true,
- IsResolver: true,
+ IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
- return nil, errors.New("field of type String does not have child fields")
+ return nil, errors.New("field of type ID does not have child fields")
},
}
return fc, nil
@@ -1606,7 +1601,7 @@ func (ec *executionContext) _SetTitleOperation_id(ctx context.Context, field gra
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
- return ec.resolvers.SetTitleOperation().ID(rctx, obj)
+ return obj.Id(), nil
})
if err != nil {
ec.Error(ctx, err)
@@ -1618,9 +1613,9 @@ func (ec *executionContext) _SetTitleOperation_id(ctx context.Context, field gra
}
return graphql.Null
}
- res := resTmp.(string)
+ res := resTmp.(entity.Id)
fc.Result = res
- return ec.marshalNString2string(ctx, field.Selections, res)
+ return ec.marshalNID2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐId(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_SetTitleOperation_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@@ -1628,9 +1623,9 @@ func (ec *executionContext) fieldContext_SetTitleOperation_id(ctx context.Contex
Object: "SetTitleOperation",
Field: field,
IsMethod: true,
- IsResolver: true,
+ IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
- return nil, errors.New("field of type String does not have child fields")
+ return nil, errors.New("field of type ID does not have child fields")
},
}
return fc, nil
@@ -1892,25 +1887,12 @@ func (ec *executionContext) _AddCommentOperation(ctx context.Context, sel ast.Se
case "__typename":
out.Values[i] = graphql.MarshalString("AddCommentOperation")
case "id":
- field := field
-
- innerFunc := func(ctx context.Context) (res graphql.Marshaler) {
- defer func() {
- if r := recover(); r != nil {
- ec.Error(ctx, ec.Recover(ctx, r))
- }
- }()
- res = ec._AddCommentOperation_id(ctx, field, obj)
- if res == graphql.Null {
- atomic.AddUint32(&invalids, 1)
- }
- return res
- }
- out.Concurrently(i, func() graphql.Marshaler {
- return innerFunc(ctx)
+ out.Values[i] = ec._AddCommentOperation_id(ctx, field, obj)
- })
+ if out.Values[i] == graphql.Null {
+ atomic.AddUint32(&invalids, 1)
+ }
case "author":
field := field
@@ -1987,25 +1969,12 @@ func (ec *executionContext) _CreateOperation(ctx context.Context, sel ast.Select
case "__typename":
out.Values[i] = graphql.MarshalString("CreateOperation")
case "id":
- field := field
-
- innerFunc := func(ctx context.Context) (res graphql.Marshaler) {
- defer func() {
- if r := recover(); r != nil {
- ec.Error(ctx, ec.Recover(ctx, r))
- }
- }()
- res = ec._CreateOperation_id(ctx, field, obj)
- if res == graphql.Null {
- atomic.AddUint32(&invalids, 1)
- }
- return res
- }
- out.Concurrently(i, func() graphql.Marshaler {
- return innerFunc(ctx)
+ out.Values[i] = ec._CreateOperation_id(ctx, field, obj)
- })
+ if out.Values[i] == graphql.Null {
+ atomic.AddUint32(&invalids, 1)
+ }
case "author":
field := field
@@ -2089,25 +2058,12 @@ func (ec *executionContext) _EditCommentOperation(ctx context.Context, sel ast.S
case "__typename":
out.Values[i] = graphql.MarshalString("EditCommentOperation")
case "id":
- field := field
-
- innerFunc := func(ctx context.Context) (res graphql.Marshaler) {
- defer func() {
- if r := recover(); r != nil {
- ec.Error(ctx, ec.Recover(ctx, r))
- }
- }()
- res = ec._EditCommentOperation_id(ctx, field, obj)
- if res == graphql.Null {
- atomic.AddUint32(&invalids, 1)
- }
- return res
- }
- out.Concurrently(i, func() graphql.Marshaler {
- return innerFunc(ctx)
+ out.Values[i] = ec._EditCommentOperation_id(ctx, field, obj)
- })
+ if out.Values[i] == graphql.Null {
+ atomic.AddUint32(&invalids, 1)
+ }
case "author":
field := field
@@ -2204,25 +2160,12 @@ func (ec *executionContext) _LabelChangeOperation(ctx context.Context, sel ast.S
case "__typename":
out.Values[i] = graphql.MarshalString("LabelChangeOperation")
case "id":
- field := field
-
- innerFunc := func(ctx context.Context) (res graphql.Marshaler) {
- defer func() {
- if r := recover(); r != nil {
- ec.Error(ctx, ec.Recover(ctx, r))
- }
- }()
- res = ec._LabelChangeOperation_id(ctx, field, obj)
- if res == graphql.Null {
- atomic.AddUint32(&invalids, 1)
- }
- return res
- }
- out.Concurrently(i, func() graphql.Marshaler {
- return innerFunc(ctx)
+ out.Values[i] = ec._LabelChangeOperation_id(ctx, field, obj)
- })
+ if out.Values[i] == graphql.Null {
+ atomic.AddUint32(&invalids, 1)
+ }
case "author":
field := field
@@ -2383,25 +2326,12 @@ func (ec *executionContext) _SetStatusOperation(ctx context.Context, sel ast.Sel
case "__typename":
out.Values[i] = graphql.MarshalString("SetStatusOperation")
case "id":
- field := field
-
- innerFunc := func(ctx context.Context) (res graphql.Marshaler) {
- defer func() {
- if r := recover(); r != nil {
- ec.Error(ctx, ec.Recover(ctx, r))
- }
- }()
- res = ec._SetStatusOperation_id(ctx, field, obj)
- if res == graphql.Null {
- atomic.AddUint32(&invalids, 1)
- }
- return res
- }
- out.Concurrently(i, func() graphql.Marshaler {
- return innerFunc(ctx)
+ out.Values[i] = ec._SetStatusOperation_id(ctx, field, obj)
- })
+ if out.Values[i] == graphql.Null {
+ atomic.AddUint32(&invalids, 1)
+ }
case "author":
field := field
@@ -2471,25 +2401,12 @@ func (ec *executionContext) _SetTitleOperation(ctx context.Context, sel ast.Sele
case "__typename":
out.Values[i] = graphql.MarshalString("SetTitleOperation")
case "id":
- field := field
- innerFunc := func(ctx context.Context) (res graphql.Marshaler) {
- defer func() {
- if r := recover(); r != nil {
- ec.Error(ctx, ec.Recover(ctx, r))
- }
- }()
- res = ec._SetTitleOperation_id(ctx, field, obj)
- if res == graphql.Null {
- atomic.AddUint32(&invalids, 1)
- }
- return res
- }
-
- out.Concurrently(i, func() graphql.Marshaler {
- return innerFunc(ctx)
+ out.Values[i] = ec._SetTitleOperation_id(ctx, field, obj)
- })
+ if out.Values[i] == graphql.Null {
+ atomic.AddUint32(&invalids, 1)
+ }
case "author":
field := field
diff --git a/api/graphql/graph/prelude.generated.go b/api/graphql/graph/prelude.generated.go
index 81978efa..3767b0cd 100644
--- a/api/graphql/graph/prelude.generated.go
+++ b/api/graphql/graph/prelude.generated.go
@@ -11,6 +11,7 @@ import (
"github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/graphql/introspection"
+ "github.com/MichaelMure/git-bug/entity"
"github.com/vektah/gqlparser/v2/ast"
)
@@ -2172,6 +2173,16 @@ func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.Se
return res
}
+func (ec *executionContext) unmarshalNID2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐId(ctx context.Context, v interface{}) (entity.Id, error) {
+ var res entity.Id
+ err := res.UnmarshalGQL(v)
+ return res, graphql.ErrorOnPath(ctx, err)
+}
+
+func (ec *executionContext) marshalNID2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐId(ctx context.Context, sel ast.SelectionSet, v entity.Id) graphql.Marshaler {
+ return v
+}
+
func (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) {
res, err := graphql.UnmarshalInt(v)
return res, graphql.ErrorOnPath(ctx, err)
diff --git a/api/graphql/graph/root_.generated.go b/api/graphql/graph/root_.generated.go
index 297fc6a2..a1434228 100644
--- a/api/graphql/graph/root_.generated.go
+++ b/api/graphql/graph/root_.generated.go
@@ -74,7 +74,7 @@ type ComplexityRoot struct {
Author func(childComplexity int) int
Date func(childComplexity int) int
Files func(childComplexity int) int
- ID func(childComplexity int) int
+ Id func(childComplexity int) int
Message func(childComplexity int) int
}
@@ -102,7 +102,7 @@ type ComplexityRoot struct {
Comments func(childComplexity int, after *string, before *string, first *int, last *int) int
CreatedAt func(childComplexity int) int
HumanID func(childComplexity int) int
- ID func(childComplexity int) int
+ Id func(childComplexity int) int
Labels func(childComplexity int) int
LastEdit func(childComplexity int) int
Operations func(childComplexity int, after *string, before *string, first *int, last *int) int
@@ -146,6 +146,7 @@ type ComplexityRoot struct {
Comment struct {
Author func(childComplexity int) int
Files func(childComplexity int) int
+ ID func(childComplexity int) int
Message func(childComplexity int) int
}
@@ -170,7 +171,7 @@ type ComplexityRoot struct {
Author func(childComplexity int) int
Date func(childComplexity int) int
Files func(childComplexity int) int
- ID func(childComplexity int) int
+ Id func(childComplexity int) int
Message func(childComplexity int) int
Title func(childComplexity int) int
}
@@ -191,7 +192,7 @@ type ComplexityRoot struct {
Author func(childComplexity int) int
Date func(childComplexity int) int
Files func(childComplexity int) int
- ID func(childComplexity int) int
+ Id func(childComplexity int) int
Message func(childComplexity int) int
Target func(childComplexity int) int
}
@@ -207,7 +208,7 @@ type ComplexityRoot struct {
DisplayName func(childComplexity int) int
Email func(childComplexity int) int
HumanID func(childComplexity int) int
- ID func(childComplexity int) int
+ Id func(childComplexity int) int
IsProtected func(childComplexity int) int
Login func(childComplexity int) int
Name func(childComplexity int) int
@@ -234,7 +235,7 @@ type ComplexityRoot struct {
Added func(childComplexity int) int
Author func(childComplexity int) int
Date func(childComplexity int) int
- ID func(childComplexity int) int
+ Id func(childComplexity int) int
Removed func(childComplexity int) int
}
@@ -323,7 +324,7 @@ type ComplexityRoot struct {
SetStatusOperation struct {
Author func(childComplexity int) int
Date func(childComplexity int) int
- ID func(childComplexity int) int
+ Id func(childComplexity int) int
Status func(childComplexity int) int
}
@@ -337,7 +338,7 @@ type ComplexityRoot struct {
SetTitleOperation struct {
Author func(childComplexity int) int
Date func(childComplexity int) int
- ID func(childComplexity int) int
+ Id func(childComplexity int) int
Title func(childComplexity int) int
Was func(childComplexity int) int
}
@@ -462,11 +463,11 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.AddCommentOperation.Files(childComplexity), true
case "AddCommentOperation.id":
- if e.complexity.AddCommentOperation.ID == nil {
+ if e.complexity.AddCommentOperation.Id == nil {
break
}
- return e.complexity.AddCommentOperation.ID(childComplexity), true
+ return e.complexity.AddCommentOperation.Id(childComplexity), true
case "AddCommentOperation.message":
if e.complexity.AddCommentOperation.Message == nil {
@@ -605,11 +606,11 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Bug.HumanID(childComplexity), true
case "Bug.id":
- if e.complexity.Bug.ID == nil {
+ if e.complexity.Bug.Id == nil {
break
}
- return e.complexity.Bug.ID(childComplexity), true
+ return e.complexity.Bug.Id(childComplexity), true
case "Bug.labels":
if e.complexity.Bug.Labels == nil {
@@ -801,6 +802,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Comment.Files(childComplexity), true
+ case "Comment.id":
+ if e.complexity.Comment.ID == nil {
+ break
+ }
+
+ return e.complexity.Comment.ID(childComplexity), true
+
case "Comment.message":
if e.complexity.Comment.Message == nil {
break
@@ -886,11 +894,11 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.CreateOperation.Files(childComplexity), true
case "CreateOperation.id":
- if e.complexity.CreateOperation.ID == nil {
+ if e.complexity.CreateOperation.Id == nil {
break
}
- return e.complexity.CreateOperation.ID(childComplexity), true
+ return e.complexity.CreateOperation.Id(childComplexity), true
case "CreateOperation.message":
if e.complexity.CreateOperation.Message == nil {
@@ -991,11 +999,11 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.EditCommentOperation.Files(childComplexity), true
case "EditCommentOperation.id":
- if e.complexity.EditCommentOperation.ID == nil {
+ if e.complexity.EditCommentOperation.Id == nil {
break
}
- return e.complexity.EditCommentOperation.ID(childComplexity), true
+ return e.complexity.EditCommentOperation.Id(childComplexity), true
case "EditCommentOperation.message":
if e.complexity.EditCommentOperation.Message == nil {
@@ -1061,11 +1069,11 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Identity.HumanID(childComplexity), true
case "Identity.id":
- if e.complexity.Identity.ID == nil {
+ if e.complexity.Identity.Id == nil {
break
}
- return e.complexity.Identity.ID(childComplexity), true
+ return e.complexity.Identity.Id(childComplexity), true
case "Identity.isProtected":
if e.complexity.Identity.IsProtected == nil {
@@ -1166,11 +1174,11 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.LabelChangeOperation.Date(childComplexity), true
case "LabelChangeOperation.id":
- if e.complexity.LabelChangeOperation.ID == nil {
+ if e.complexity.LabelChangeOperation.Id == nil {
break
}
- return e.complexity.LabelChangeOperation.ID(childComplexity), true
+ return e.complexity.LabelChangeOperation.Id(childComplexity), true
case "LabelChangeOperation.removed":
if e.complexity.LabelChangeOperation.Removed == nil {
@@ -1591,11 +1599,11 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.SetStatusOperation.Date(childComplexity), true
case "SetStatusOperation.id":
- if e.complexity.SetStatusOperation.ID == nil {
+ if e.complexity.SetStatusOperation.Id == nil {
break
}
- return e.complexity.SetStatusOperation.ID(childComplexity), true
+ return e.complexity.SetStatusOperation.Id(childComplexity), true
case "SetStatusOperation.status":
if e.complexity.SetStatusOperation.Status == nil {
@@ -1647,11 +1655,11 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.SetTitleOperation.Date(childComplexity), true
case "SetTitleOperation.id":
- if e.complexity.SetTitleOperation.ID == nil {
+ if e.complexity.SetTitleOperation.Id == nil {
break
}
- return e.complexity.SetTitleOperation.ID(childComplexity), true
+ return e.complexity.SetTitleOperation.Id(childComplexity), true
case "SetTitleOperation.title":
if e.complexity.SetTitleOperation.Title == nil {
@@ -1844,6 +1852,8 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er
var sources = []*ast.Source{
{Name: "../schema/bug.graphql", Input: `"""Represents a comment on a bug."""
type Comment implements Authored {
+ id: CombinedId!
+
"""The author of this comment."""
author: Identity!
@@ -1873,7 +1883,7 @@ enum Status {
type Bug implements Authored {
"""The identifier for this bug"""
- id: String!
+ id: ID!
"""The human version (truncated) identifier for this bug"""
humanId: String!
status: Status!
@@ -1964,7 +1974,7 @@ type BugEdge {
{Name: "../schema/identity.graphql", Input: `"""Represents an identity"""
type Identity {
"""The identifier for this identity"""
- id: String!
+ id: ID!
"""The human version (truncated) identifier for this identity"""
humanId: String!
"""The name of the person, if known."""
@@ -2109,10 +2119,8 @@ input EditCommentInput {
clientMutationId: String
"""The name of the repository. If not set, the default repository is used."""
repoRef: String
- """The bug ID's prefix."""
- prefix: String!
- """The ID of the comment to be changed."""
- target: String!
+ """A prefix of the CombinedId of the comment to be changed."""
+ targetPrefix: String!
"""The new message to be set."""
message: String!
"""The collection of file's hash required for the first message."""
@@ -2226,7 +2234,7 @@ type SetTitlePayload {
{Name: "../schema/operations.graphql", Input: `"""An operation applied to a bug."""
interface Operation {
"""The identifier of the operation"""
- id: String!
+ id: ID!
"""The operations author."""
author: Identity!
"""The datetime when this operation was issued."""
@@ -2253,7 +2261,7 @@ type OperationEdge {
type CreateOperation implements Operation & Authored {
"""The identifier of the operation"""
- id: String!
+ id: ID!
"""The author of this object."""
author: Identity!
"""The datetime when this operation was issued."""
@@ -2266,7 +2274,7 @@ type CreateOperation implements Operation & Authored {
type SetTitleOperation implements Operation & Authored {
"""The identifier of the operation"""
- id: String!
+ id: ID!
"""The author of this object."""
author: Identity!
"""The datetime when this operation was issued."""
@@ -2278,7 +2286,7 @@ type SetTitleOperation implements Operation & Authored {
type AddCommentOperation implements Operation & Authored {
"""The identifier of the operation"""
- id: String!
+ id: ID!
"""The author of this object."""
author: Identity!
"""The datetime when this operation was issued."""
@@ -2290,7 +2298,7 @@ type AddCommentOperation implements Operation & Authored {
type EditCommentOperation implements Operation & Authored {
"""The identifier of the operation"""
- id: String!
+ id: ID!
"""The author of this object."""
author: Identity!
"""The datetime when this operation was issued."""
@@ -2303,7 +2311,7 @@ type EditCommentOperation implements Operation & Authored {
type SetStatusOperation implements Operation & Authored {
"""The identifier of the operation"""
- id: String!
+ id: ID!
"""The author of this object."""
author: Identity!
"""The datetime when this operation was issued."""
@@ -2314,7 +2322,7 @@ type SetStatusOperation implements Operation & Authored {
type LabelChangeOperation implements Operation & Authored {
"""The identifier of the operation"""
- id: String!
+ id: ID!
"""The author of this object."""
author: Identity!
"""The datetime when this operation was issued."""
@@ -2404,7 +2412,7 @@ type Mutation {
{Name: "../schema/timeline.graphql", Input: `"""An item in the timeline of events"""
interface TimelineItem {
"""The identifier of the source operation"""
- id: String!
+ id: CombinedId!
}
"""CommentHistoryStep hold one version of a message in the history"""
@@ -2434,7 +2442,7 @@ type TimelineItemEdge {
"""CreateTimelineItem is a TimelineItem that represent the creation of a bug and its message edition history"""
type CreateTimelineItem implements TimelineItem & Authored {
"""The identifier of the source operation"""
- id: String!
+ id: CombinedId!
author: Identity!
message: String!
messageIsEmpty: Boolean!
@@ -2448,7 +2456,7 @@ type CreateTimelineItem implements TimelineItem & Authored {
"""AddCommentTimelineItem is a TimelineItem that represent a Comment and its edition history"""
type AddCommentTimelineItem implements TimelineItem & Authored {
"""The identifier of the source operation"""
- id: String!
+ id: CombinedId!
author: Identity!
message: String!
messageIsEmpty: Boolean!
@@ -2462,7 +2470,7 @@ type AddCommentTimelineItem implements TimelineItem & Authored {
"""LabelChangeTimelineItem is a TimelineItem that represent a change in the labels of a bug"""
type LabelChangeTimelineItem implements TimelineItem & Authored {
"""The identifier of the source operation"""
- id: String!
+ id: CombinedId!
author: Identity!
date: Time!
added: [Label!]!
@@ -2472,7 +2480,7 @@ type LabelChangeTimelineItem implements TimelineItem & Authored {
"""SetStatusTimelineItem is a TimelineItem that represent a change in the status of a bug"""
type SetStatusTimelineItem implements TimelineItem & Authored {
"""The identifier of the source operation"""
- id: String!
+ id: CombinedId!
author: Identity!
date: Time!
status: Status!
@@ -2481,14 +2489,15 @@ type SetStatusTimelineItem implements TimelineItem & Authored {
"""LabelChangeTimelineItem is a TimelineItem that represent a change in the title of a bug"""
type SetTitleTimelineItem implements TimelineItem & Authored {
"""The identifier of the source operation"""
- id: String!
+ id: CombinedId!
author: Identity!
date: Time!
title: String!
was: String!
}
`, BuiltIn: false},
- {Name: "../schema/types.graphql", Input: `scalar Time
+ {Name: "../schema/types.graphql", Input: `scalar CombinedId
+scalar Time
scalar Hash
"""Defines a color by red, green and blue components."""
diff --git a/api/graphql/graph/timeline.generated.go b/api/graphql/graph/timeline.generated.go
index 9ad32e0b..4833e274 100644
--- a/api/graphql/graph/timeline.generated.go
+++ b/api/graphql/graph/timeline.generated.go
@@ -15,6 +15,7 @@ import (
"github.com/MichaelMure/git-bug/api/graphql/models"
"github.com/MichaelMure/git-bug/entities/bug"
"github.com/MichaelMure/git-bug/entities/common"
+ "github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/repository"
"github.com/vektah/gqlparser/v2/ast"
)
@@ -22,7 +23,7 @@ import (
// region ************************** generated!.gotpl **************************
type AddCommentTimelineItemResolver interface {
- ID(ctx context.Context, obj *bug.AddCommentTimelineItem) (string, error)
+ ID(ctx context.Context, obj *bug.AddCommentTimelineItem) (entity.CombinedId, error)
Author(ctx context.Context, obj *bug.AddCommentTimelineItem) (models.IdentityWrapper, error)
CreatedAt(ctx context.Context, obj *bug.AddCommentTimelineItem) (*time.Time, error)
@@ -32,24 +33,24 @@ type CommentHistoryStepResolver interface {
Date(ctx context.Context, obj *bug.CommentHistoryStep) (*time.Time, error)
}
type CreateTimelineItemResolver interface {
- ID(ctx context.Context, obj *bug.CreateTimelineItem) (string, error)
+ ID(ctx context.Context, obj *bug.CreateTimelineItem) (entity.CombinedId, error)
Author(ctx context.Context, obj *bug.CreateTimelineItem) (models.IdentityWrapper, error)
CreatedAt(ctx context.Context, obj *bug.CreateTimelineItem) (*time.Time, error)
LastEdit(ctx context.Context, obj *bug.CreateTimelineItem) (*time.Time, error)
}
type LabelChangeTimelineItemResolver interface {
- ID(ctx context.Context, obj *bug.LabelChangeTimelineItem) (string, error)
+ ID(ctx context.Context, obj *bug.LabelChangeTimelineItem) (entity.CombinedId, error)
Author(ctx context.Context, obj *bug.LabelChangeTimelineItem) (models.IdentityWrapper, error)
Date(ctx context.Context, obj *bug.LabelChangeTimelineItem) (*time.Time, error)
}
type SetStatusTimelineItemResolver interface {
- ID(ctx context.Context, obj *bug.SetStatusTimelineItem) (string, error)
+ ID(ctx context.Context, obj *bug.SetStatusTimelineItem) (entity.CombinedId, error)
Author(ctx context.Context, obj *bug.SetStatusTimelineItem) (models.IdentityWrapper, error)
Date(ctx context.Context, obj *bug.SetStatusTimelineItem) (*time.Time, error)
}
type SetTitleTimelineItemResolver interface {
- ID(ctx context.Context, obj *bug.SetTitleTimelineItem) (string, error)
+ ID(ctx context.Context, obj *bug.SetTitleTimelineItem) (entity.CombinedId, error)
Author(ctx context.Context, obj *bug.SetTitleTimelineItem) (models.IdentityWrapper, error)
Date(ctx context.Context, obj *bug.SetTitleTimelineItem) (*time.Time, error)
}
@@ -92,9 +93,9 @@ func (ec *executionContext) _AddCommentTimelineItem_id(ctx context.Context, fiel
}
return graphql.Null
}
- res := resTmp.(string)
+ res := resTmp.(entity.CombinedId)
fc.Result = res
- return ec.marshalNString2string(ctx, field.Selections, res)
+ return ec.marshalNCombinedId2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐCombinedId(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_AddCommentTimelineItem_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@@ -104,7 +105,7 @@ func (ec *executionContext) fieldContext_AddCommentTimelineItem_id(ctx context.C
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
- return nil, errors.New("field of type String does not have child fields")
+ return nil, errors.New("field of type CombinedId does not have child fields")
},
}
return fc, nil
@@ -600,9 +601,9 @@ func (ec *executionContext) _CreateTimelineItem_id(ctx context.Context, field gr
}
return graphql.Null
}
- res := resTmp.(string)
+ res := resTmp.(entity.CombinedId)
fc.Result = res
- return ec.marshalNString2string(ctx, field.Selections, res)
+ return ec.marshalNCombinedId2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐCombinedId(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_CreateTimelineItem_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@@ -612,7 +613,7 @@ func (ec *executionContext) fieldContext_CreateTimelineItem_id(ctx context.Conte
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
- return nil, errors.New("field of type String does not have child fields")
+ return nil, errors.New("field of type CombinedId does not have child fields")
},
}
return fc, nil
@@ -1020,9 +1021,9 @@ func (ec *executionContext) _LabelChangeTimelineItem_id(ctx context.Context, fie
}
return graphql.Null
}
- res := resTmp.(string)
+ res := resTmp.(entity.CombinedId)
fc.Result = res
- return ec.marshalNString2string(ctx, field.Selections, res)
+ return ec.marshalNCombinedId2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐCombinedId(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_LabelChangeTimelineItem_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@@ -1032,7 +1033,7 @@ func (ec *executionContext) fieldContext_LabelChangeTimelineItem_id(ctx context.
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
- return nil, errors.New("field of type String does not have child fields")
+ return nil, errors.New("field of type CombinedId does not have child fields")
},
}
return fc, nil
@@ -1270,9 +1271,9 @@ func (ec *executionContext) _SetStatusTimelineItem_id(ctx context.Context, field
}
return graphql.Null
}
- res := resTmp.(string)
+ res := resTmp.(entity.CombinedId)
fc.Result = res
- return ec.marshalNString2string(ctx, field.Selections, res)
+ return ec.marshalNCombinedId2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐCombinedId(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_SetStatusTimelineItem_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@@ -1282,7 +1283,7 @@ func (ec *executionContext) fieldContext_SetStatusTimelineItem_id(ctx context.Co
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
- return nil, errors.New("field of type String does not have child fields")
+ return nil, errors.New("field of type CombinedId does not have child fields")
},
}
return fc, nil
@@ -1464,9 +1465,9 @@ func (ec *executionContext) _SetTitleTimelineItem_id(ctx context.Context, field
}
return graphql.Null
}
- res := resTmp.(string)
+ res := resTmp.(entity.CombinedId)
fc.Result = res
- return ec.marshalNString2string(ctx, field.Selections, res)
+ return ec.marshalNCombinedId2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐCombinedId(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_SetTitleTimelineItem_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@@ -1476,7 +1477,7 @@ func (ec *executionContext) fieldContext_SetTitleTimelineItem_id(ctx context.Con
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
- return nil, errors.New("field of type String does not have child fields")
+ return nil, errors.New("field of type CombinedId does not have child fields")
},
}
return fc, nil
diff --git a/api/graphql/graph/types.generated.go b/api/graphql/graph/types.generated.go
index 9095c7ac..b75604ab 100644
--- a/api/graphql/graph/types.generated.go
+++ b/api/graphql/graph/types.generated.go
@@ -14,6 +14,7 @@ import (
"github.com/99designs/gqlgen/graphql"
"github.com/MichaelMure/git-bug/api/graphql/models"
"github.com/MichaelMure/git-bug/entities/bug"
+ "github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/repository"
"github.com/vektah/gqlparser/v2/ast"
)
@@ -410,22 +411,16 @@ func (ec *executionContext) _Authored(ctx context.Context, sel ast.SelectionSet,
return graphql.Null
}
return ec._AddCommentTimelineItem(ctx, sel, obj)
- case bug.LabelChangeTimelineItem:
- return ec._LabelChangeTimelineItem(ctx, sel, &obj)
case *bug.LabelChangeTimelineItem:
if obj == nil {
return graphql.Null
}
return ec._LabelChangeTimelineItem(ctx, sel, obj)
- case bug.SetStatusTimelineItem:
- return ec._SetStatusTimelineItem(ctx, sel, &obj)
case *bug.SetStatusTimelineItem:
if obj == nil {
return graphql.Null
}
return ec._SetStatusTimelineItem(ctx, sel, obj)
- case bug.SetTitleTimelineItem:
- return ec._SetTitleTimelineItem(ctx, sel, &obj)
case *bug.SetTitleTimelineItem:
if obj == nil {
return graphql.Null
@@ -588,6 +583,16 @@ func (ec *executionContext) marshalNColor2ᚖimageᚋcolorᚐRGBA(ctx context.Co
return ec._Color(ctx, sel, v)
}
+func (ec *executionContext) unmarshalNCombinedId2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐCombinedId(ctx context.Context, v interface{}) (entity.CombinedId, error) {
+ var res entity.CombinedId
+ err := res.UnmarshalGQL(v)
+ return res, graphql.ErrorOnPath(ctx, err)
+}
+
+func (ec *executionContext) marshalNCombinedId2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋentityᚐCombinedId(ctx context.Context, sel ast.SelectionSet, v entity.CombinedId) graphql.Marshaler {
+ return v
+}
+
func (ec *executionContext) unmarshalNHash2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋrepositoryᚐHash(ctx context.Context, v interface{}) (repository.Hash, error) {
var res repository.Hash
err := res.UnmarshalGQL(v)
diff --git a/api/graphql/handler.go b/api/graphql/handler.go
index 03dc32e9..00141f01 100644
--- a/api/graphql/handler.go
+++ b/api/graphql/handler.go
@@ -1,4 +1,4 @@
-//go:generate go run gen_graphql.go
+//go:generate go run github.com/99designs/gqlgen generate
// Package graphql contains the root GraphQL http handler
package graphql
diff --git a/api/graphql/models/gen_models.go b/api/graphql/models/gen_models.go
index c4e40cba..d75b3d27 100644
--- a/api/graphql/models/gen_models.go
+++ b/api/graphql/models/gen_models.go
@@ -161,10 +161,8 @@ type EditCommentInput struct {
ClientMutationID *string `json:"clientMutationId"`
// The name of the repository. If not set, the default repository is used.
RepoRef *string `json:"repoRef"`
- // The bug ID's prefix.
- Prefix string `json:"prefix"`
- // The ID of the comment to be changed.
- Target string `json:"target"`
+ // A prefix of the CombinedId of the comment to be changed.
+ TargetPrefix string `json:"targetPrefix"`
// The new message to be set.
Message string `json:"message"`
// The collection of file's hash required for the first message.
diff --git a/api/graphql/resolvers/bug.go b/api/graphql/resolvers/bug.go
index d17a4469..c40949fa 100644
--- a/api/graphql/resolvers/bug.go
+++ b/api/graphql/resolvers/bug.go
@@ -14,10 +14,6 @@ var _ graph.BugResolver = &bugResolver{}
type bugResolver struct{}
-func (bugResolver) ID(_ context.Context, obj models.BugWrapper) (string, error) {
- return obj.Id().String(), nil
-}
-
func (bugResolver) HumanID(_ context.Context, obj models.BugWrapper) (string, error) {
return obj.Id().Human(), nil
}
diff --git a/api/graphql/resolvers/comment.go b/api/graphql/resolvers/comment.go
index 78548156..7dddc3c8 100644
--- a/api/graphql/resolvers/comment.go
+++ b/api/graphql/resolvers/comment.go
@@ -6,12 +6,17 @@ import (
"github.com/MichaelMure/git-bug/api/graphql/graph"
"github.com/MichaelMure/git-bug/api/graphql/models"
"github.com/MichaelMure/git-bug/entities/bug"
+ "github.com/MichaelMure/git-bug/entity"
)
var _ graph.CommentResolver = &commentResolver{}
type commentResolver struct{}
+func (c commentResolver) ID(ctx context.Context, obj *bug.Comment) (entity.CombinedId, error) {
+ return obj.CombinedId(), nil
+}
+
func (c commentResolver) Author(_ context.Context, obj *bug.Comment) (models.IdentityWrapper, error) {
return models.NewLoadedIdentity(obj.Author), nil
}
diff --git a/api/graphql/resolvers/mutation.go b/api/graphql/resolvers/mutation.go
index 6ad81db4..f6296d63 100644
--- a/api/graphql/resolvers/mutation.go
+++ b/api/graphql/resolvers/mutation.go
@@ -9,7 +9,6 @@ import (
"github.com/MichaelMure/git-bug/api/graphql/models"
"github.com/MichaelMure/git-bug/cache"
"github.com/MichaelMure/git-bug/entities/bug"
- "github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/util/text"
)
@@ -177,7 +176,12 @@ func (r mutationResolver) AddCommentAndReopen(ctx context.Context, input models.
}
func (r mutationResolver) EditComment(ctx context.Context, input models.EditCommentInput) (*models.EditCommentPayload, error) {
- repo, b, err := r.getBug(input.RepoRef, input.Prefix)
+ repo, err := r.getRepo(input.RepoRef)
+ if err != nil {
+ return nil, err
+ }
+
+ b, target, err := repo.ResolveComment(input.TargetPrefix)
if err != nil {
return nil, err
}
@@ -190,7 +194,7 @@ func (r mutationResolver) EditComment(ctx context.Context, input models.EditComm
op, err := b.EditCommentRaw(
author,
time.Now().Unix(),
- entity.Id(input.Target),
+ target,
text.Cleanup(input.Message),
nil,
)
diff --git a/api/graphql/resolvers/operations.go b/api/graphql/resolvers/operations.go
index 53c3c0bc..91194213 100644
--- a/api/graphql/resolvers/operations.go
+++ b/api/graphql/resolvers/operations.go
@@ -13,10 +13,6 @@ var _ graph.CreateOperationResolver = createOperationResolver{}
type createOperationResolver struct{}
-func (createOperationResolver) ID(_ context.Context, obj *bug.CreateOperation) (string, error) {
- return obj.Id().String(), nil
-}
-
func (createOperationResolver) Author(_ context.Context, obj *bug.CreateOperation) (models.IdentityWrapper, error) {
return models.NewLoadedIdentity(obj.Author()), nil
}
@@ -30,10 +26,6 @@ var _ graph.AddCommentOperationResolver = addCommentOperationResolver{}
type addCommentOperationResolver struct{}
-func (addCommentOperationResolver) ID(_ context.Context, obj *bug.AddCommentOperation) (string, error) {
- return obj.Id().String(), nil
-}
-
func (addCommentOperationResolver) Author(_ context.Context, obj *bug.AddCommentOperation) (models.IdentityWrapper, error) {
return models.NewLoadedIdentity(obj.Author()), nil
}
@@ -47,10 +39,6 @@ var _ graph.EditCommentOperationResolver = editCommentOperationResolver{}
type editCommentOperationResolver struct{}
-func (editCommentOperationResolver) ID(_ context.Context, obj *bug.EditCommentOperation) (string, error) {
- return obj.Id().String(), nil
-}
-
func (editCommentOperationResolver) Target(_ context.Context, obj *bug.EditCommentOperation) (string, error) {
return obj.Target.String(), nil
}
@@ -68,10 +56,6 @@ var _ graph.LabelChangeOperationResolver = labelChangeOperationResolver{}
type labelChangeOperationResolver struct{}
-func (labelChangeOperationResolver) ID(_ context.Context, obj *bug.LabelChangeOperation) (string, error) {
- return obj.Id().String(), nil
-}
-
func (labelChangeOperationResolver) Author(_ context.Context, obj *bug.LabelChangeOperation) (models.IdentityWrapper, error) {
return models.NewLoadedIdentity(obj.Author()), nil
}
@@ -85,10 +69,6 @@ var _ graph.SetStatusOperationResolver = setStatusOperationResolver{}
type setStatusOperationResolver struct{}
-func (setStatusOperationResolver) ID(_ context.Context, obj *bug.SetStatusOperation) (string, error) {
- return obj.Id().String(), nil
-}
-
func (setStatusOperationResolver) Author(_ context.Context, obj *bug.SetStatusOperation) (models.IdentityWrapper, error) {
return models.NewLoadedIdentity(obj.Author()), nil
}
@@ -102,10 +82,6 @@ var _ graph.SetTitleOperationResolver = setTitleOperationResolver{}
type setTitleOperationResolver struct{}
-func (setTitleOperationResolver) ID(_ context.Context, obj *bug.SetTitleOperation) (string, error) {
- return obj.Id().String(), nil
-}
-
func (setTitleOperationResolver) Author(_ context.Context, obj *bug.SetTitleOperation) (models.IdentityWrapper, error) {
return models.NewLoadedIdentity(obj.Author()), nil
}
diff --git a/api/graphql/resolvers/timeline.go b/api/graphql/resolvers/timeline.go
index 2481784e..2d691173 100644
--- a/api/graphql/resolvers/timeline.go
+++ b/api/graphql/resolvers/timeline.go
@@ -7,6 +7,7 @@ import (
"github.com/MichaelMure/git-bug/api/graphql/graph"
"github.com/MichaelMure/git-bug/api/graphql/models"
"github.com/MichaelMure/git-bug/entities/bug"
+ "github.com/MichaelMure/git-bug/entity"
)
var _ graph.CommentHistoryStepResolver = commentHistoryStepResolver{}
@@ -22,8 +23,8 @@ var _ graph.AddCommentTimelineItemResolver = addCommentTimelineItemResolver{}
type addCommentTimelineItemResolver struct{}
-func (addCommentTimelineItemResolver) ID(_ context.Context, obj *bug.AddCommentTimelineItem) (string, error) {
- return obj.Id().String(), nil
+func (addCommentTimelineItemResolver) ID(_ context.Context, obj *bug.AddCommentTimelineItem) (entity.CombinedId, error) {
+ return obj.CombinedId(), nil
}
func (addCommentTimelineItemResolver) Author(_ context.Context, obj *bug.AddCommentTimelineItem) (models.IdentityWrapper, error) {
@@ -44,8 +45,8 @@ var _ graph.CreateTimelineItemResolver = createTimelineItemResolver{}
type createTimelineItemResolver struct{}
-func (createTimelineItemResolver) ID(_ context.Context, obj *bug.CreateTimelineItem) (string, error) {
- return obj.Id().String(), nil
+func (createTimelineItemResolver) ID(_ context.Context, obj *bug.CreateTimelineItem) (entity.CombinedId, error) {
+ return obj.CombinedId(), nil
}
func (r createTimelineItemResolver) Author(_ context.Context, obj *bug.CreateTimelineItem) (models.IdentityWrapper, error) {
@@ -66,8 +67,8 @@ var _ graph.LabelChangeTimelineItemResolver = labelChangeTimelineItem{}
type labelChangeTimelineItem struct{}
-func (labelChangeTimelineItem) ID(_ context.Context, obj *bug.LabelChangeTimelineItem) (string, error) {
- return obj.Id().String(), nil
+func (labelChangeTimelineItem) ID(_ context.Context, obj *bug.LabelChangeTimelineItem) (entity.CombinedId, error) {
+ return obj.CombinedId(), nil
}
func (i labelChangeTimelineItem) Author(_ context.Context, obj *bug.LabelChangeTimelineItem) (models.IdentityWrapper, error) {
@@ -83,8 +84,8 @@ var _ graph.SetStatusTimelineItemResolver = setStatusTimelineItem{}
type setStatusTimelineItem struct{}
-func (setStatusTimelineItem) ID(_ context.Context, obj *bug.SetStatusTimelineItem) (string, error) {
- return obj.Id().String(), nil
+func (setStatusTimelineItem) ID(_ context.Context, obj *bug.SetStatusTimelineItem) (entity.CombinedId, error) {
+ return obj.CombinedId(), nil
}
func (i setStatusTimelineItem) Author(_ context.Context, obj *bug.SetStatusTimelineItem) (models.IdentityWrapper, error) {
@@ -100,8 +101,8 @@ var _ graph.SetTitleTimelineItemResolver = setTitleTimelineItem{}
type setTitleTimelineItem struct{}
-func (setTitleTimelineItem) ID(_ context.Context, obj *bug.SetTitleTimelineItem) (string, error) {
- return obj.Id().String(), nil
+func (setTitleTimelineItem) ID(_ context.Context, obj *bug.SetTitleTimelineItem) (entity.CombinedId, error) {
+ return obj.CombinedId(), nil
}
func (i setTitleTimelineItem) Author(_ context.Context, obj *bug.SetTitleTimelineItem) (models.IdentityWrapper, error) {
diff --git a/api/graphql/schema/bug.graphql b/api/graphql/schema/bug.graphql
index 03aa95b8..17d3a897 100644
--- a/api/graphql/schema/bug.graphql
+++ b/api/graphql/schema/bug.graphql
@@ -1,5 +1,7 @@
"""Represents a comment on a bug."""
type Comment implements Authored {
+ id: CombinedId!
+
"""The author of this comment."""
author: Identity!
@@ -29,7 +31,7 @@ enum Status {
type Bug implements Authored {
"""The identifier for this bug"""
- id: String!
+ id: ID!
"""The human version (truncated) identifier for this bug"""
humanId: String!
status: Status!
diff --git a/api/graphql/schema/identity.graphql b/api/graphql/schema/identity.graphql
index 93154a90..c910ea55 100644
--- a/api/graphql/schema/identity.graphql
+++ b/api/graphql/schema/identity.graphql
@@ -1,7 +1,7 @@
"""Represents an identity"""
type Identity {
"""The identifier for this identity"""
- id: String!
+ id: ID!
"""The human version (truncated) identifier for this identity"""
humanId: String!
"""The name of the person, if known."""
diff --git a/api/graphql/schema/mutations.graphql b/api/graphql/schema/mutations.graphql
index 078dc214..be6a0115 100644
--- a/api/graphql/schema/mutations.graphql
+++ b/api/graphql/schema/mutations.graphql
@@ -95,10 +95,8 @@ input EditCommentInput {
clientMutationId: String
"""The name of the repository. If not set, the default repository is used."""
repoRef: String
- """The bug ID's prefix."""
- prefix: String!
- """The ID of the comment to be changed."""
- target: String!
+ """A prefix of the CombinedId of the comment to be changed."""
+ targetPrefix: String!
"""The new message to be set."""
message: String!
"""The collection of file's hash required for the first message."""
diff --git a/api/graphql/schema/operations.graphql b/api/graphql/schema/operations.graphql
index 18e0929c..8e198753 100644
--- a/api/graphql/schema/operations.graphql
+++ b/api/graphql/schema/operations.graphql
@@ -1,7 +1,7 @@
"""An operation applied to a bug."""
interface Operation {
"""The identifier of the operation"""
- id: String!
+ id: ID!
"""The operations author."""
author: Identity!
"""The datetime when this operation was issued."""
@@ -28,7 +28,7 @@ type OperationEdge {
type CreateOperation implements Operation & Authored {
"""The identifier of the operation"""
- id: String!
+ id: ID!
"""The author of this object."""
author: Identity!
"""The datetime when this operation was issued."""
@@ -41,7 +41,7 @@ type CreateOperation implements Operation & Authored {
type SetTitleOperation implements Operation & Authored {
"""The identifier of the operation"""
- id: String!
+ id: ID!
"""The author of this object."""
author: Identity!
"""The datetime when this operation was issued."""
@@ -53,7 +53,7 @@ type SetTitleOperation implements Operation & Authored {
type AddCommentOperation implements Operation & Authored {
"""The identifier of the operation"""
- id: String!
+ id: ID!
"""The author of this object."""
author: Identity!
"""The datetime when this operation was issued."""
@@ -65,7 +65,7 @@ type AddCommentOperation implements Operation & Authored {
type EditCommentOperation implements Operation & Authored {
"""The identifier of the operation"""
- id: String!
+ id: ID!
"""The author of this object."""
author: Identity!
"""The datetime when this operation was issued."""
@@ -78,7 +78,7 @@ type EditCommentOperation implements Operation & Authored {
type SetStatusOperation implements Operation & Authored {
"""The identifier of the operation"""
- id: String!
+ id: ID!
"""The author of this object."""
author: Identity!
"""The datetime when this operation was issued."""
@@ -89,7 +89,7 @@ type SetStatusOperation implements Operation & Authored {
type LabelChangeOperation implements Operation & Authored {
"""The identifier of the operation"""
- id: String!
+ id: ID!
"""The author of this object."""
author: Identity!
"""The datetime when this operation was issued."""
diff --git a/api/graphql/schema/timeline.graphql b/api/graphql/schema/timeline.graphql
index 12462aa3..b7ab5ca8 100644
--- a/api/graphql/schema/timeline.graphql
+++ b/api/graphql/schema/timeline.graphql
@@ -1,7 +1,7 @@
"""An item in the timeline of events"""
interface TimelineItem {
"""The identifier of the source operation"""
- id: String!
+ id: CombinedId!
}
"""CommentHistoryStep hold one version of a message in the history"""
@@ -31,7 +31,7 @@ type TimelineItemEdge {
"""CreateTimelineItem is a TimelineItem that represent the creation of a bug and its message edition history"""
type CreateTimelineItem implements TimelineItem & Authored {
"""The identifier of the source operation"""
- id: String!
+ id: CombinedId!
author: Identity!
message: String!
messageIsEmpty: Boolean!
@@ -45,7 +45,7 @@ type CreateTimelineItem implements TimelineItem & Authored {
"""AddCommentTimelineItem is a TimelineItem that represent a Comment and its edition history"""
type AddCommentTimelineItem implements TimelineItem & Authored {
"""The identifier of the source operation"""
- id: String!
+ id: CombinedId!
author: Identity!
message: String!
messageIsEmpty: Boolean!
@@ -59,7 +59,7 @@ type AddCommentTimelineItem implements TimelineItem & Authored {
"""LabelChangeTimelineItem is a TimelineItem that represent a change in the labels of a bug"""
type LabelChangeTimelineItem implements TimelineItem & Authored {
"""The identifier of the source operation"""
- id: String!
+ id: CombinedId!
author: Identity!
date: Time!
added: [Label!]!
@@ -69,7 +69,7 @@ type LabelChangeTimelineItem implements TimelineItem & Authored {
"""SetStatusTimelineItem is a TimelineItem that represent a change in the status of a bug"""
type SetStatusTimelineItem implements TimelineItem & Authored {
"""The identifier of the source operation"""
- id: String!
+ id: CombinedId!
author: Identity!
date: Time!
status: Status!
@@ -78,7 +78,7 @@ type SetStatusTimelineItem implements TimelineItem & Authored {
"""LabelChangeTimelineItem is a TimelineItem that represent a change in the title of a bug"""
type SetTitleTimelineItem implements TimelineItem & Authored {
"""The identifier of the source operation"""
- id: String!
+ id: CombinedId!
author: Identity!
date: Time!
title: String!
diff --git a/api/graphql/schema/types.graphql b/api/graphql/schema/types.graphql
index 0182885e..f4284b2d 100644
--- a/api/graphql/schema/types.graphql
+++ b/api/graphql/schema/types.graphql
@@ -1,3 +1,4 @@
+scalar CombinedId
scalar Time
scalar Hash
diff --git a/api/graphql/tools.go b/api/graphql/tools.go
new file mode 100644
index 00000000..863672ec
--- /dev/null
+++ b/api/graphql/tools.go
@@ -0,0 +1,8 @@
+//go:build tools
+// +build tools
+
+package graphql
+
+import (
+ _ "github.com/99designs/gqlgen"
+)
diff --git a/api/http/git_file_handler.go b/api/http/git_file_handler.go
index 0bc0fd0c..b5676970 100644
--- a/api/http/git_file_handler.go
+++ b/api/http/git_file_handler.go
@@ -47,7 +47,7 @@ func (gfh *gitFileHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
return
}
- // TODO: this mean that the whole file will he buffered in memory
+ // TODO: this mean that the whole file will be buffered in memory
// This can be a problem for big files. There might be a way around
// that by implementing a io.ReadSeeker that would read and discard
// data when a seek is called.
diff --git a/bridge/github/export_test.go b/bridge/github/export_test.go
index 93cc47c0..de2d3f34 100644
--- a/bridge/github/export_test.go
+++ b/bridge/github/export_test.go
@@ -16,6 +16,7 @@ import (
"github.com/MichaelMure/git-bug/bridge/core"
"github.com/MichaelMure/git-bug/bridge/core/auth"
"github.com/MichaelMure/git-bug/cache"
+ "github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/entity/dag"
"github.com/MichaelMure/git-bug/repository"
"github.com/MichaelMure/git-bug/util/interrupt"
@@ -66,13 +67,15 @@ func testCases(t *testing.T, repo *cache.RepoCache) []*testCase {
bugWithCommentEditions, createOp, err := repo.NewBug("bug with comments editions", "new bug")
require.NoError(t, err)
- _, err = bugWithCommentEditions.EditComment(createOp.Id(), "first comment edited")
+ _, err = bugWithCommentEditions.EditComment(
+ entity.CombineIds(bugWithCommentEditions.Id(), createOp.Id()), "first comment edited")
require.NoError(t, err)
commentOp, err := bugWithCommentEditions.AddComment("first comment")
require.NoError(t, err)
- _, err = bugWithCommentEditions.EditComment(commentOp.Id(), "first comment edited")
+ _, err = bugWithCommentEditions.EditComment(
+ entity.CombineIds(bugWithCommentEditions.Id(), commentOp.Id()), "first comment edited")
require.NoError(t, err)
// bug status changed
diff --git a/bridge/github/import.go b/bridge/github/import.go
index 722bf256..5b2bf54b 100644
--- a/bridge/github/import.go
+++ b/bridge/github/import.go
@@ -405,6 +405,7 @@ func (gi *githubImporter) ensureCommentEdit(ctx context.Context, repo *cache.Rep
if err != nil {
return err
}
+ // check if the comment edition already exist
_, err = b.ResolveOperationWithMetadata(metaKeyGithubId, parseId(edit.Id))
if err == nil {
return nil
@@ -428,7 +429,7 @@ func (gi *githubImporter) ensureCommentEdit(ctx context.Context, repo *cache.Rep
op, err := b.EditCommentRaw(
editor,
edit.CreatedAt.Unix(),
- target,
+ entity.CombineIds(b.Id(), target),
text.Cleanup(string(*edit.Diff)),
map[string]string{
metaKeyGithubId: parseId(edit.Id),
diff --git a/bridge/gitlab/export_test.go b/bridge/gitlab/export_test.go
index b48254e6..e9f3ae75 100644
--- a/bridge/gitlab/export_test.go
+++ b/bridge/gitlab/export_test.go
@@ -11,6 +11,7 @@ import (
"github.com/xanzy/go-gitlab"
+ "github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/entity/dag"
"github.com/stretchr/testify/require"
@@ -63,13 +64,15 @@ func testCases(t *testing.T, repo *cache.RepoCache) []*testCase {
bugWithCommentEditions, createOp, err := repo.NewBug("bug with comments editions", "new bug")
require.NoError(t, err)
- _, err = bugWithCommentEditions.EditComment(createOp.Id(), "first comment edited")
+ _, err = bugWithCommentEditions.EditComment(
+ entity.CombineIds(bugWithCommentEditions.Id(), createOp.Id()), "first comment edited")
require.NoError(t, err)
commentOp, err := bugWithCommentEditions.AddComment("first comment")
require.NoError(t, err)
- _, err = bugWithCommentEditions.EditComment(commentOp.Id(), "first comment edited")
+ _, err = bugWithCommentEditions.EditComment(
+ entity.CombineIds(bugWithCommentEditions.Id(), commentOp.Id()), "first comment edited")
require.NoError(t, err)
// bug status changed
diff --git a/bridge/gitlab/import.go b/bridge/gitlab/import.go
index 8228c4a0..cf6b5ca6 100644
--- a/bridge/gitlab/import.go
+++ b/bridge/gitlab/import.go
@@ -55,7 +55,6 @@ func (gi *gitlabImporter) Init(_ context.Context, repo *cache.RepoCache, conf co
// ImportAll iterate over all the configured repository issues (notes) and ensure the creation
// of the missing issues / comments / label events / title changes ...
func (gi *gitlabImporter) ImportAll(ctx context.Context, repo *cache.RepoCache, since time.Time) (<-chan core.ImportResult, error) {
-
out := make(chan core.ImportResult)
gi.out = out
@@ -150,7 +149,6 @@ func (gi *gitlabImporter) ensureIssue(repo *cache.RepoCache, issue *gitlab.Issue
}
func (gi *gitlabImporter) ensureIssueEvent(repo *cache.RepoCache, b *cache.BugCache, issue *gitlab.Issue, event Event) error {
-
id, errResolve := b.ResolveOperationWithMetadata(metaKeyGitlabId, event.ID())
if errResolve != nil && errResolve != cache.ErrNoMatchingOp {
return errResolve
@@ -205,13 +203,14 @@ func (gi *gitlabImporter) ensureIssueEvent(repo *cache.RepoCache, b *cache.BugCa
// since gitlab doesn't provide the issue history
// we should check for "changed the description" notes and compare issue texts
// TODO: Check only one time and ignore next 'description change' within one issue
- if errResolve == cache.ErrNoMatchingOp && issue.Description != firstComment.Message {
+ cleanedDesc := text.Cleanup(issue.Description)
+ if errResolve == cache.ErrNoMatchingOp && cleanedDesc != firstComment.Message {
// comment edition
op, err := b.EditCommentRaw(
author,
event.(NoteEvent).UpdatedAt.Unix(),
- firstComment.Id(),
- text.Cleanup(issue.Description),
+ firstComment.CombinedId(),
+ cleanedDesc,
map[string]string{
metaKeyGitlabId: event.ID(),
},
@@ -249,7 +248,7 @@ func (gi *gitlabImporter) ensureIssueEvent(repo *cache.RepoCache, b *cache.BugCa
// if comment was already exported
// search for last comment update
- comment, err := b.Snapshot().SearchComment(id)
+ comment, err := b.Snapshot().SearchCommentByOpId(id)
if err != nil {
return err
}
@@ -260,7 +259,7 @@ func (gi *gitlabImporter) ensureIssueEvent(repo *cache.RepoCache, b *cache.BugCa
op, err := b.EditCommentRaw(
author,
event.(NoteEvent).UpdatedAt.Unix(),
- comment.Id(),
+ comment.CombinedId(),
cleanText,
nil,
)
diff --git a/bridge/jira/import.go b/bridge/jira/import.go
index c297abcf..8043acf4 100644
--- a/bridge/jira/import.go
+++ b/bridge/jira/import.go
@@ -270,8 +270,7 @@ func (ji *jiraImporter) ensureComment(repo *cache.RepoCache, b *cache.BugCache,
return err
}
- targetOpID, err := b.ResolveOperationWithMetadata(
- metaKeyJiraId, item.ID)
+ targetOpID, err := b.ResolveOperationWithMetadata(metaKeyJiraId, item.ID)
if err != nil && err != cache.ErrNoMatchingOp {
return err
}
@@ -334,7 +333,7 @@ func (ji *jiraImporter) ensureComment(repo *cache.RepoCache, b *cache.BugCache,
op, err := b.EditCommentRaw(
editor,
item.Updated.Unix(),
- targetOpID,
+ entity.CombineIds(b.Id(), targetOpID),
text.Cleanup(item.Body),
map[string]string{
metaKeyJiraId: derivedID,
diff --git a/cache/bug_cache.go b/cache/bug_cache.go
index e03b27ff..6caaeb11 100644
--- a/cache/bug_cache.go
+++ b/cache/bug_cache.go
@@ -209,7 +209,7 @@ func (c *BugCache) EditCreateCommentRaw(author *IdentityCache, unixTime int64, b
return op, c.notifyUpdated()
}
-func (c *BugCache) EditComment(target entity.Id, message string) (*bug.EditCommentOperation, error) {
+func (c *BugCache) EditComment(target entity.CombinedId, message string) (*bug.EditCommentOperation, error) {
author, err := c.repoCache.GetUserIdentity()
if err != nil {
return nil, err
@@ -218,9 +218,14 @@ func (c *BugCache) EditComment(target entity.Id, message string) (*bug.EditComme
return c.EditCommentRaw(author, time.Now().Unix(), target, message, nil)
}
-func (c *BugCache) EditCommentRaw(author *IdentityCache, unixTime int64, target entity.Id, message string, metadata map[string]string) (*bug.EditCommentOperation, error) {
+func (c *BugCache) EditCommentRaw(author *IdentityCache, unixTime int64, target entity.CombinedId, message string, metadata map[string]string) (*bug.EditCommentOperation, error) {
+ comment, err := c.Snapshot().SearchComment(target)
+ if err != nil {
+ return nil, err
+ }
+
c.mu.Lock()
- op, err := bug.EditComment(c.bug, author.Identity, unixTime, target, message, nil, metadata)
+ op, err := bug.EditComment(c.bug, author.Identity, unixTime, comment.TargetId(), message, nil, metadata)
c.mu.Unlock()
if err != nil {
return nil, err
diff --git a/cache/repo_cache_bug.go b/cache/repo_cache_bug.go
index 9843f9d9..226c4c13 100644
--- a/cache/repo_cache_bug.go
+++ b/cache/repo_cache_bug.go
@@ -263,7 +263,7 @@ func (c *RepoCache) resolveBugMatcher(f func(*BugExcerpt) bool) (entity.Id, erro
// ResolveComment search for a Bug/Comment combination matching the merged
// bug/comment Id prefix. Returns the Bug containing the Comment and the Comment's
// Id.
-func (c *RepoCache) ResolveComment(prefix string) (*BugCache, entity.Id, error) {
+func (c *RepoCache) ResolveComment(prefix string) (*BugCache, entity.CombinedId, error) {
bugPrefix, _ := entity.SeparateIds(prefix)
bugCandidate := make([]entity.Id, 0, 5)
@@ -277,7 +277,7 @@ func (c *RepoCache) ResolveComment(prefix string) (*BugCache, entity.Id, error)
c.muBug.RUnlock()
matchingBugIds := make([]entity.Id, 0, 5)
- matchingCommentId := entity.UnsetId
+ matchingCommentId := entity.UnsetCombinedId
var matchingBug *BugCache
// search for matching comments
@@ -286,22 +286,22 @@ func (c *RepoCache) ResolveComment(prefix string) (*BugCache, entity.Id, error)
for _, bugId := range bugCandidate {
b, err := c.ResolveBug(bugId)
if err != nil {
- return nil, entity.UnsetId, err
+ return nil, entity.UnsetCombinedId, err
}
for _, comment := range b.Snapshot().Comments {
- if comment.Id().HasPrefix(prefix) {
+ if comment.TargetId().HasPrefix(prefix) {
matchingBugIds = append(matchingBugIds, bugId)
matchingBug = b
- matchingCommentId = comment.Id()
+ matchingCommentId = comment.CombinedId()
}
}
}
if len(matchingBugIds) > 1 {
- return nil, entity.UnsetId, entity.NewErrMultipleMatch("bug/comment", matchingBugIds)
+ return nil, entity.UnsetCombinedId, entity.NewErrMultipleMatch("bug/comment", matchingBugIds)
} else if len(matchingBugIds) == 0 {
- return nil, entity.UnsetId, errors.New("comment doesn't exist")
+ return nil, entity.UnsetCombinedId, errors.New("comment doesn't exist")
}
return matchingBug, matchingCommentId, nil
diff --git a/commands/comment.go b/commands/comment.go
index b4b4628b..7cab447c 100644
--- a/commands/comment.go
+++ b/commands/comment.go
@@ -41,7 +41,7 @@ func runComment(env *Env, args []string) error {
}
env.out.Printf("Author: %s\n", colors.Magenta(comment.Author.DisplayName()))
- env.out.Printf("Id: %s\n", colors.Cyan(comment.Id().Human()))
+ env.out.Printf("Id: %s\n", colors.Cyan(comment.CombinedId().Human()))
env.out.Printf("Date: %s\n\n", comment.FormatTime())
env.out.Println(text.LeftPadLines(comment.Message, 4))
}
diff --git a/commands/show.go b/commands/show.go
index d145ffe7..1491372e 100644
--- a/commands/show.go
+++ b/commands/show.go
@@ -163,7 +163,7 @@ func showDefaultFormatter(env *Env, snapshot *bug.Snapshot) error {
var message string
env.out.Printf("%s%s #%d %s <%s>\n\n",
indent,
- comment.Id().Human(),
+ comment.CombinedId().Human(),
i,
comment.Author.DisplayName(),
comment.Author.Email(),
@@ -207,8 +207,8 @@ type JSONComment struct {
func NewJSONComment(comment bug.Comment) JSONComment {
return JSONComment{
- Id: comment.Id().String(),
- HumanId: comment.Id().Human(),
+ Id: comment.CombinedId().String(),
+ HumanId: comment.CombinedId().Human(),
Author: NewJSONIdentity(comment.Author),
Message: comment.Message,
}
diff --git a/entities/bug/comment.go b/entities/bug/comment.go
index fcf501ab..7835c5a8 100644
--- a/entities/bug/comment.go
+++ b/entities/bug/comment.go
@@ -11,34 +11,41 @@ import (
// Comment represent a comment in a Bug
type Comment struct {
- // id should be the result of entity.CombineIds with the Bug id and the id
+ // combinedId should be the result of entity.CombineIds with the Bug id and the id
// of the Operation that created the comment
- id entity.Id
+ combinedId entity.CombinedId
+
+ // targetId is the Id of the Operation that originally created that Comment
+ targetId entity.Id
+
Author identity.Interface
Message string
Files []repository.Hash
// Creation time of the comment.
// Should be used only for human display, never for ordering as we can't rely on it in a distributed system.
- UnixTime timestamp.Timestamp
+ unixTime timestamp.Timestamp
}
-// Id return the Comment identifier
-func (c Comment) Id() entity.Id {
- if c.id == "" {
+func (c Comment) CombinedId() entity.CombinedId {
+ if c.combinedId == "" {
// simply panic as it would be a coding error (no id provided at construction)
- panic("no id")
+ panic("no combined id")
}
- return c.id
+ return c.combinedId
+}
+
+func (c Comment) TargetId() entity.Id {
+ return c.targetId
}
-// FormatTimeRel format the UnixTime of the comment for human consumption
+// FormatTimeRel format the unixTime of the comment for human consumption
func (c Comment) FormatTimeRel() string {
- return humanize.Time(c.UnixTime.Time())
+ return humanize.Time(c.unixTime.Time())
}
func (c Comment) FormatTime() string {
- return c.UnixTime.Time().Format("Mon Jan 2 15:04:05 2006 +0200")
+ return c.unixTime.Time().Format("Mon Jan 2 15:04:05 2006 +0200")
}
// IsAuthored is a sign post method for gqlgen
diff --git a/entities/bug/op_add_comment.go b/entities/bug/op_add_comment.go
index 2e6a39f9..b049ef16 100644
--- a/entities/bug/op_add_comment.go
+++ b/entities/bug/op_add_comment.go
@@ -30,12 +30,15 @@ func (op *AddCommentOperation) Apply(snapshot *Snapshot) {
snapshot.addActor(op.Author())
snapshot.addParticipant(op.Author())
+ opId := op.Id()
+
comment := Comment{
- id: entity.CombineIds(snapshot.Id(), op.Id()),
- Message: op.Message,
- Author: op.Author(),
- Files: op.Files,
- UnixTime: timestamp.Timestamp(op.UnixTime),
+ combinedId: entity.CombineIds(snapshot.Id(), opId),
+ targetId: opId,
+ Message: op.Message,
+ Author: op.Author(),
+ Files: op.Files,
+ unixTime: timestamp.Timestamp(op.UnixTime),
}
snapshot.Comments = append(snapshot.Comments, comment)
@@ -71,7 +74,7 @@ func NewAddCommentOp(author identity.Interface, unixTime int64, message string,
}
}
-// AddCommentTimelineItem hold a comment in the timeline
+// AddCommentTimelineItem replace a AddComment operation in the Timeline and hold its edition history
type AddCommentTimelineItem struct {
CommentTimelineItem
}
diff --git a/entities/bug/op_create.go b/entities/bug/op_create.go
index fdfa131b..2afea406 100644
--- a/entities/bug/op_create.go
+++ b/entities/bug/op_create.go
@@ -32,7 +32,9 @@ func (op *CreateOperation) Apply(snapshot *Snapshot) {
return
}
- snapshot.id = op.Id()
+ // the Id of the Bug/Snapshot is the Id of the first Operation: CreateOperation
+ opId := op.Id()
+ snapshot.id = opId
snapshot.addActor(op.Author())
snapshot.addParticipant(op.Author())
@@ -40,10 +42,11 @@ func (op *CreateOperation) Apply(snapshot *Snapshot) {
snapshot.Title = op.Title
comment := Comment{
- id: entity.CombineIds(snapshot.Id(), op.Id()),
- Message: op.Message,
- Author: op.Author(),
- UnixTime: timestamp.Timestamp(op.UnixTime),
+ combinedId: entity.CombineIds(snapshot.id, opId),
+ targetId: opId,
+ Message: op.Message,
+ Author: op.Author(),
+ unixTime: timestamp.Timestamp(op.UnixTime),
}
snapshot.Comments = []Comment{comment}
diff --git a/entities/bug/op_create_test.go b/entities/bug/op_create_test.go
index f2c9e675..e534162b 100644
--- a/entities/bug/op_create_test.go
+++ b/entities/bug/op_create_test.go
@@ -6,55 +6,37 @@ import (
"github.com/stretchr/testify/require"
+ "github.com/MichaelMure/git-bug/entities/common"
"github.com/MichaelMure/git-bug/entities/identity"
"github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/entity/dag"
"github.com/MichaelMure/git-bug/repository"
- "github.com/MichaelMure/git-bug/util/timestamp"
)
func TestCreate(t *testing.T) {
- snapshot := Snapshot{}
-
- repo := repository.NewMockRepoClock()
+ repo := repository.NewMockRepo()
rene, err := identity.NewIdentity(repo, "René Descartes", "rene@descartes.fr")
require.NoError(t, err)
- unix := time.Now().Unix()
-
- create := NewCreateOp(rene, unix, "title", "message", nil)
-
- create.Apply(&snapshot)
-
- id := create.Id()
- require.NoError(t, id.Validate())
-
- comment := Comment{
- id: entity.CombineIds(create.Id(), create.Id()),
- Author: rene,
- Message: "message",
- UnixTime: timestamp.Timestamp(create.UnixTime),
- }
-
- expected := Snapshot{
- id: create.Id(),
- Title: "title",
- Comments: []Comment{
- comment,
- },
- Author: rene,
- Participants: []identity.Interface{rene},
- Actors: []identity.Interface{rene},
- CreateTime: create.Time(),
- Timeline: []TimelineItem{
- &CreateTimelineItem{
- CommentTimelineItem: NewCommentTimelineItem(comment),
- },
- },
- }
+ b, op, err := Create(rene, time.Now().Unix(), "title", "message", nil, nil)
+ require.NoError(t, err)
- require.Equal(t, expected, snapshot)
+ require.Equal(t, "title", op.Title)
+ require.Equal(t, "message", op.Message)
+
+ // Create generate the initial operation and create a new timeline item
+ snap := b.Compile()
+ require.Equal(t, common.OpenStatus, snap.Status)
+ require.Equal(t, rene, snap.Author)
+ require.Equal(t, "title", snap.Title)
+ require.Len(t, snap.Operations, 1)
+ require.Equal(t, op, snap.Operations[0])
+
+ require.Len(t, snap.Timeline, 1)
+ require.Equal(t, entity.CombineIds(b.Id(), op.Id()), snap.Timeline[0].CombinedId())
+ require.Equal(t, rene, snap.Timeline[0].(*CreateTimelineItem).Author)
+ require.Equal(t, "message", snap.Timeline[0].(*CreateTimelineItem).Message)
}
func TestCreateSerialize(t *testing.T) {
diff --git a/entities/bug/op_edit_comment.go b/entities/bug/op_edit_comment.go
index 41079f45..b0897b0a 100644
--- a/entities/bug/op_edit_comment.go
+++ b/entities/bug/op_edit_comment.go
@@ -33,12 +33,12 @@ func (op *EditCommentOperation) Apply(snapshot *Snapshot) {
// Todo: currently any message can be edited, even by a different author
// crypto signature are needed.
- // Recreate the Comment Id to match on
- commentId := entity.CombineIds(snapshot.Id(), op.Target)
+ // Recreate the combined Id to match on
+ combinedId := entity.CombineIds(snapshot.Id(), op.Target)
var target TimelineItem
for i, item := range snapshot.Timeline {
- if item.Id() == commentId {
+ if item.CombinedId() == combinedId {
target = snapshot.Timeline[i]
break
}
@@ -50,10 +50,11 @@ func (op *EditCommentOperation) Apply(snapshot *Snapshot) {
}
comment := Comment{
- id: commentId,
- Message: op.Message,
- Files: op.Files,
- UnixTime: timestamp.Timestamp(op.UnixTime),
+ combinedId: combinedId,
+ targetId: op.Target,
+ Message: op.Message,
+ Files: op.Files,
+ unixTime: timestamp.Timestamp(op.UnixTime),
}
switch target := target.(type) {
@@ -72,7 +73,7 @@ func (op *EditCommentOperation) Apply(snapshot *Snapshot) {
// Updating the corresponding comment
for i := range snapshot.Comments {
- if snapshot.Comments[i].Id() == commentId {
+ if snapshot.Comments[i].CombinedId() == combinedId {
snapshot.Comments[i].Message = op.Message
snapshot.Comments[i].Files = op.Files
break
diff --git a/entities/bug/op_label_change.go b/entities/bug/op_label_change.go
index 45441f7c..76b2ebef 100644
--- a/entities/bug/op_label_change.go
+++ b/entities/bug/op_label_change.go
@@ -59,12 +59,14 @@ AddLoop:
return string(snapshot.Labels[i]) < string(snapshot.Labels[j])
})
+ id := op.Id()
item := &LabelChangeTimelineItem{
- id: op.Id(),
- Author: op.Author(),
- UnixTime: timestamp.Timestamp(op.UnixTime),
- Added: op.Added,
- Removed: op.Removed,
+ // id: id,
+ combinedId: entity.CombineIds(snapshot.Id(), id),
+ Author: op.Author(),
+ UnixTime: timestamp.Timestamp(op.UnixTime),
+ Added: op.Added,
+ Removed: op.Removed,
}
snapshot.Timeline = append(snapshot.Timeline, item)
@@ -103,19 +105,20 @@ func NewLabelChangeOperation(author identity.Interface, unixTime int64, added, r
}
type LabelChangeTimelineItem struct {
- id entity.Id
- Author identity.Interface
- UnixTime timestamp.Timestamp
- Added []Label
- Removed []Label
+ // id entity.Id
+ combinedId entity.CombinedId
+ Author identity.Interface
+ UnixTime timestamp.Timestamp
+ Added []Label
+ Removed []Label
}
-func (l LabelChangeTimelineItem) Id() entity.Id {
- return l.id
+func (l LabelChangeTimelineItem) CombinedId() entity.CombinedId {
+ return l.combinedId
}
// IsAuthored is a sign post method for gqlgen
-func (l LabelChangeTimelineItem) IsAuthored() {}
+func (l *LabelChangeTimelineItem) IsAuthored() {}
// ChangeLabels is a convenience function to change labels on a bug
func ChangeLabels(b Interface, author identity.Interface, unixTime int64, add, remove []string, metadata map[string]string) ([]LabelChangeResult, *LabelChangeOperation, error) {
@@ -180,7 +183,7 @@ func ChangeLabels(b Interface, author identity.Interface, unixTime int64, add, r
}
// ForceChangeLabels is a convenience function to apply the operation
-// The difference with ChangeLabels is that no checks of deduplications are done. You are entirely
+// The difference with ChangeLabels is that no checks for deduplication are done. You are entirely
// responsible for what you are doing. In the general case, you want to use ChangeLabels instead.
// The intended use of this function is to allow importers to create legal but unexpected label changes,
// like removing a label with no information of when it was added before.
diff --git a/entities/bug/op_set_status.go b/entities/bug/op_set_status.go
index cf17901a..23be59a0 100644
--- a/entities/bug/op_set_status.go
+++ b/entities/bug/op_set_status.go
@@ -26,11 +26,13 @@ func (op *SetStatusOperation) Apply(snapshot *Snapshot) {
snapshot.Status = op.Status
snapshot.addActor(op.Author())
+ id := op.Id()
item := &SetStatusTimelineItem{
- id: op.Id(),
- Author: op.Author(),
- UnixTime: timestamp.Timestamp(op.UnixTime),
- Status: op.Status,
+ // id: id,
+ combinedId: entity.CombineIds(snapshot.Id(), id),
+ Author: op.Author(),
+ UnixTime: timestamp.Timestamp(op.UnixTime),
+ Status: op.Status,
}
snapshot.Timeline = append(snapshot.Timeline, item)
@@ -56,18 +58,19 @@ func NewSetStatusOp(author identity.Interface, unixTime int64, status common.Sta
}
type SetStatusTimelineItem struct {
- id entity.Id
- Author identity.Interface
- UnixTime timestamp.Timestamp
- Status common.Status
+ // id entity.Id
+ combinedId entity.CombinedId
+ Author identity.Interface
+ UnixTime timestamp.Timestamp
+ Status common.Status
}
-func (s SetStatusTimelineItem) Id() entity.Id {
- return s.id
+func (s SetStatusTimelineItem) CombinedId() entity.CombinedId {
+ return s.combinedId
}
// IsAuthored is a sign post method for gqlgen
-func (s SetStatusTimelineItem) IsAuthored() {}
+func (s *SetStatusTimelineItem) IsAuthored() {}
// Open is a convenience function to change a bugs state to Open
func Open(b Interface, author identity.Interface, unixTime int64, metadata map[string]string) (*SetStatusOperation, error) {
diff --git a/entities/bug/op_set_title.go b/entities/bug/op_set_title.go
index 75efd08e..e9526b64 100644
--- a/entities/bug/op_set_title.go
+++ b/entities/bug/op_set_title.go
@@ -28,12 +28,14 @@ func (op *SetTitleOperation) Apply(snapshot *Snapshot) {
snapshot.Title = op.Title
snapshot.addActor(op.Author())
+ id := op.Id()
item := &SetTitleTimelineItem{
- id: op.Id(),
- Author: op.Author(),
- UnixTime: timestamp.Timestamp(op.UnixTime),
- Title: op.Title,
- Was: op.Was,
+ id: id,
+ combinedId: entity.CombineIds(snapshot.Id(), id),
+ Author: op.Author(),
+ UnixTime: timestamp.Timestamp(op.UnixTime),
+ Title: op.Title,
+ Was: op.Was,
}
snapshot.Timeline = append(snapshot.Timeline, item)
@@ -68,19 +70,24 @@ func NewSetTitleOp(author identity.Interface, unixTime int64, title string, was
}
type SetTitleTimelineItem struct {
- id entity.Id
- Author identity.Interface
- UnixTime timestamp.Timestamp
- Title string
- Was string
+ id entity.Id
+ combinedId entity.CombinedId
+ Author identity.Interface
+ UnixTime timestamp.Timestamp
+ Title string
+ Was string
}
func (s SetTitleTimelineItem) Id() entity.Id {
return s.id
}
+func (s SetTitleTimelineItem) CombinedId() entity.CombinedId {
+ return s.combinedId
+}
+
// IsAuthored is a sign post method for gqlgen
-func (s SetTitleTimelineItem) IsAuthored() {}
+func (s *SetTitleTimelineItem) IsAuthored() {}
// SetTitle is a convenience function to change a bugs title
func SetTitle(b Interface, author identity.Interface, unixTime int64, title string, metadata map[string]string) (*SetTitleOperation, error) {
diff --git a/entities/bug/snapshot.go b/entities/bug/snapshot.go
index 442496f7..333fe207 100644
--- a/entities/bug/snapshot.go
+++ b/entities/bug/snapshot.go
@@ -58,9 +58,9 @@ func (snap *Snapshot) GetCreateMetadata(key string) (string, bool) {
}
// SearchTimelineItem will search in the timeline for an item matching the given hash
-func (snap *Snapshot) SearchTimelineItem(id entity.Id) (TimelineItem, error) {
+func (snap *Snapshot) SearchTimelineItem(id entity.CombinedId) (TimelineItem, error) {
for i := range snap.Timeline {
- if snap.Timeline[i].Id() == id {
+ if snap.Timeline[i].CombinedId() == id {
return snap.Timeline[i], nil
}
}
@@ -68,15 +68,26 @@ func (snap *Snapshot) SearchTimelineItem(id entity.Id) (TimelineItem, error) {
return nil, fmt.Errorf("timeline item not found")
}
-// SearchComment will search for a comment matching the given hash
-func (snap *Snapshot) SearchComment(id entity.Id) (*Comment, error) {
+// SearchComment will search for a comment matching the given id
+func (snap *Snapshot) SearchComment(id entity.CombinedId) (*Comment, error) {
for _, c := range snap.Comments {
- if c.id == id {
+ if c.combinedId == id {
return &c, nil
}
}
- return nil, fmt.Errorf("comment item not found")
+ return nil, fmt.Errorf("comment not found")
+}
+
+// SearchCommentByOpId will search for a comment generated by the given operation Id
+func (snap *Snapshot) SearchCommentByOpId(id entity.Id) (*Comment, error) {
+ for _, c := range snap.Comments {
+ if c.targetId == id {
+ return &c, nil
+ }
+ }
+
+ return nil, fmt.Errorf("comment not found")
}
// append the operation author to the actors list
diff --git a/entities/bug/timeline.go b/entities/bug/timeline.go
index d7f042db..84ece262 100644
--- a/entities/bug/timeline.go
+++ b/entities/bug/timeline.go
@@ -10,8 +10,8 @@ import (
)
type TimelineItem interface {
- // Id return the identifier of the item
- Id() entity.Id
+ // CombinedId returns the global identifier of the item
+ CombinedId() entity.CombinedId
}
// CommentHistoryStep hold one version of a message in the history
@@ -26,46 +26,46 @@ type CommentHistoryStep struct {
// CommentTimelineItem is a TimelineItem that holds a Comment and its edition history
type CommentTimelineItem struct {
- // id should be the same as in Comment
- id entity.Id
- Author identity.Interface
- Message string
- Files []repository.Hash
- CreatedAt timestamp.Timestamp
- LastEdit timestamp.Timestamp
- History []CommentHistoryStep
+ combinedId entity.CombinedId
+ Author identity.Interface
+ Message string
+ Files []repository.Hash
+ CreatedAt timestamp.Timestamp
+ LastEdit timestamp.Timestamp
+ History []CommentHistoryStep
}
func NewCommentTimelineItem(comment Comment) CommentTimelineItem {
return CommentTimelineItem{
- id: comment.id,
- Author: comment.Author,
- Message: comment.Message,
- Files: comment.Files,
- CreatedAt: comment.UnixTime,
- LastEdit: comment.UnixTime,
+ // id: comment.id,
+ combinedId: comment.combinedId,
+ Author: comment.Author,
+ Message: comment.Message,
+ Files: comment.Files,
+ CreatedAt: comment.unixTime,
+ LastEdit: comment.unixTime,
History: []CommentHistoryStep{
{
Message: comment.Message,
- UnixTime: comment.UnixTime,
+ UnixTime: comment.unixTime,
},
},
}
}
-func (c *CommentTimelineItem) Id() entity.Id {
- return c.id
+func (c *CommentTimelineItem) CombinedId() entity.CombinedId {
+ return c.combinedId
}
// Append will append a new comment in the history and update the other values
func (c *CommentTimelineItem) Append(comment Comment) {
c.Message = comment.Message
c.Files = comment.Files
- c.LastEdit = comment.UnixTime
+ c.LastEdit = comment.unixTime
c.History = append(c.History, CommentHistoryStep{
Author: comment.Author,
Message: comment.Message,
- UnixTime: comment.UnixTime,
+ UnixTime: comment.unixTime,
})
}
diff --git a/entity/id.go b/entity/id.go
index 8f3dc25b..49398da8 100644
--- a/entity/id.go
+++ b/entity/id.go
@@ -79,21 +79,3 @@ func (i Id) Validate() error {
}
return nil
}
-
-/*
- * Sorting
- */
-
-type Alphabetical []Id
-
-func (a Alphabetical) Len() int {
- return len(a)
-}
-
-func (a Alphabetical) Less(i, j int) bool {
- return a[i] < a[j]
-}
-
-func (a Alphabetical) Swap(i, j int) {
- a[i], a[j] = a[j], a[i]
-}
diff --git a/entity/id_interleaved.go b/entity/id_interleaved.go
index 0ce2ba00..28c59a42 100644
--- a/entity/id_interleaved.go
+++ b/entity/id_interleaved.go
@@ -1,13 +1,91 @@
package entity
import (
+ "fmt"
+ "io"
"strings"
+
+ "github.com/pkg/errors"
)
+const UnsetCombinedId = CombinedId("unset")
+
+// CombinedId is an Id holding information from both a primary Id and a secondary Id.
+// While it looks like a regular Id, do not just cast from one to another.
+// Instead, use CombineIds and SeparateIds to create it and split it.
+type CombinedId string
+
+// String return the identifier as a string
+func (ci CombinedId) String() string {
+ return string(ci)
+}
+
+// Human return the identifier, shortened for human consumption
+func (ci CombinedId) Human() string {
+ format := fmt.Sprintf("%%.%ds", humanIdLength)
+ return fmt.Sprintf(format, ci)
+}
+
+func (ci CombinedId) HasPrefix(prefix string) bool {
+ return strings.HasPrefix(string(ci), prefix)
+}
+
+// UnmarshalGQL implement the Unmarshaler interface for gqlgen
+func (ci *CombinedId) UnmarshalGQL(v interface{}) error {
+ _, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("CombinedIds must be strings")
+ }
+
+ *ci = v.(CombinedId)
+
+ if err := ci.Validate(); err != nil {
+ return errors.Wrap(err, "invalid CombinedId")
+ }
+
+ return nil
+}
+
+// MarshalGQL implement the Marshaler interface for gqlgen
+func (ci CombinedId) MarshalGQL(w io.Writer) {
+ _, _ = w.Write([]byte(`"` + ci.String() + `"`))
+}
+
+// Validate tell if the Id is valid
+func (ci CombinedId) Validate() error {
+ // Special case to detect outdated repo
+ if len(ci) == 40 {
+ return fmt.Errorf("outdated repository format, please use https://github.com/MichaelMure/git-bug-migration to upgrade")
+ }
+ if len(ci) != idLength {
+ return fmt.Errorf("invalid length")
+ }
+ for _, r := range ci {
+ if (r < 'a' || r > 'z') && (r < '0' || r > '9') {
+ return fmt.Errorf("invalid character")
+ }
+ }
+ return nil
+}
+
+// PrimaryPrefix is a helper to extract the primary prefix.
+// If practical, use SeparateIds instead.
+func (ci CombinedId) PrimaryPrefix() string {
+ primaryPrefix, _ := SeparateIds(string(ci))
+ return primaryPrefix
+}
+
+// SecondaryPrefix is a helper to extract the secondary prefix.
+// If practical, use SeparateIds instead.
+func (ci CombinedId) SecondaryPrefix() string {
+ _, secondaryPrefix := SeparateIds(string(ci))
+ return secondaryPrefix
+}
+
// CombineIds compute a merged Id holding information from both the primary Id
// and the secondary Id.
//
-// This allow to later find efficiently a secondary element because we can access
+// This allows to later find efficiently a secondary element because we can access
// the primary one directly instead of searching for a primary that has a
// secondary matching the Id.
//
@@ -32,7 +110,7 @@ import (
// 7: 4P, 3S
// 10: 6P, 4S
// 16: 11P, 5S
-func CombineIds(primary Id, secondary Id) Id {
+func CombineIds(primary Id, secondary Id) CombinedId {
var id strings.Builder
for i := 0; i < idLength; i++ {
@@ -46,7 +124,7 @@ func CombineIds(primary Id, secondary Id) Id {
}
}
- return Id(id.String())
+ return CombinedId(id.String())
}
// SeparateIds extract primary and secondary prefix from an arbitrary length prefix
diff --git a/entity/id_interleaved_test.go b/entity/id_interleaved_test.go
index ef9218c9..1dc79145 100644
--- a/entity/id_interleaved_test.go
+++ b/entity/id_interleaved_test.go
@@ -9,7 +9,7 @@ import (
func TestInterleaved(t *testing.T) {
primary := Id("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX______________")
secondary := Id("YZ0123456789+/________________________________________________")
- expectedId := Id("aYbZc0def1ghij2klmn3opqr4stuv5wxyz6ABCD7EFGH8IJKL9MNOP+QRST/UVWX")
+ expectedId := CombinedId("aYbZc0def1ghij2klmn3opqr4stuv5wxyz6ABCD7EFGH8IJKL9MNOP+QRST/UVWX")
interleaved := CombineIds(primary, secondary)
require.Equal(t, expectedId, interleaved)
diff --git a/go.mod b/go.mod
index 8ff7a40e..ffebd2a8 100644
--- a/go.mod
+++ b/go.mod
@@ -89,8 +89,10 @@ require (
github.com/steveyen/gtreap v0.1.0 // indirect
github.com/stretchr/objx v0.4.0 // indirect
github.com/tinylib/msgp v1.1.0 // indirect
+ github.com/urfave/cli/v2 v2.8.1 // indirect
github.com/willf/bitset v1.1.10 // indirect
github.com/xanzy/ssh-agent v0.3.0 // indirect
+ github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
go.etcd.io/bbolt v1.3.5 // indirect
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 // indirect
diff --git a/go.sum b/go.sum
index 7289e676..b8853e7e 100644
--- a/go.sum
+++ b/go.sum
@@ -365,6 +365,7 @@ github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7
github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU=
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
+github.com/urfave/cli/v2 v2.8.1 h1:CGuYNZF9IKZY/rfBe3lJpccSoIY1ytfvmgQT90cNOl4=
github.com/urfave/cli/v2 v2.8.1/go.mod h1:Z41J9TPoffeoqP0Iza0YbAhGvymRdZAd2uPmZ5JxRdY=
github.com/vektah/gqlparser/v2 v2.4.6 h1:Yjzp66g6oVq93Jihbi0qhGnf/6zIWjcm8H6gA27zstE=
github.com/vektah/gqlparser/v2 v2.4.6/go.mod h1:flJWIR04IMQPGz+BXLrORkrARBxv/rtyIAFvd/MceW0=
@@ -375,6 +376,7 @@ github.com/xanzy/go-gitlab v0.68.0/go.mod h1:o4yExCtdaqlM8YGdDJWuZoBmfxBsmA9TPEj
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/repository/gogit.go b/repository/gogit.go
index d94965cb..4e3ccfb8 100644
--- a/repository/gogit.go
+++ b/repository/gogit.go
@@ -476,6 +476,7 @@ func (repo *GoGitRepo) ReadData(hash Hash) ([]byte, error) {
return nil, err
}
+ // TODO: return a io.Reader instead
return ioutil.ReadAll(r)
}
diff --git a/termui/show_bug.go b/termui/show_bug.go
index 6cace04a..8bcae842 100644
--- a/termui/show_bug.go
+++ b/termui/show_bug.go
@@ -244,7 +244,7 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error {
y0 += lines + 1
for _, op := range snap.Timeline {
- viewName := op.Id().String()
+ viewName := op.CombinedId().String()
// TODO: me might skip the rendering of blocks that are outside of the view
// but to do that we need to rework how sb.mainSelectableView is maintained
@@ -647,16 +647,16 @@ func (sb *showBug) edit(g *gocui.Gui, v *gocui.View) error {
return nil
}
- op, err := snap.SearchTimelineItem(entity.Id(sb.selected))
+ op, err := snap.SearchTimelineItem(entity.CombinedId(sb.selected))
if err != nil {
return err
}
switch op := op.(type) {
case *bug.AddCommentTimelineItem:
- return editCommentWithEditor(sb.bug, op.Id(), op.Message)
+ return editCommentWithEditor(sb.bug, op.CombinedId(), op.Message)
case *bug.CreateTimelineItem:
- return editCommentWithEditor(sb.bug, op.Id(), op.Message)
+ return editCommentWithEditor(sb.bug, op.CombinedId(), op.Message)
case *bug.LabelChangeTimelineItem:
return sb.editLabels(g, snap)
}
diff --git a/termui/termui.go b/termui/termui.go
index bbbc1c6c..15476d89 100644
--- a/termui/termui.go
+++ b/termui/termui.go
@@ -250,7 +250,7 @@ func addCommentWithEditor(bug *cache.BugCache) error {
return errTerminateMainloop
}
-func editCommentWithEditor(bug *cache.BugCache, target entity.Id, preMessage string) error {
+func editCommentWithEditor(bug *cache.BugCache, target entity.CombinedId, preMessage string) error {
// This is somewhat hacky.
// As there is no way to pause gocui, run the editor and restart gocui,
// we have to stop it entirely and start a new one later.