diff --git a/api/graphql/connections/connections.go b/api/graphql/connections/connections.go index 0083f8b24..edf3c27e6 100644 --- a/api/graphql/connections/connections.go +++ b/api/graphql/connections/connections.go @@ -2,10 +2,16 @@ //go:generate genny -in=connection_template.go -out=gen_lazy_identity.go gen "Name=LazyIdentity NodeType=entity.Id EdgeType=LazyIdentityEdge ConnectionType=models.IdentityConnection" //go:generate genny -in=connection_template.go -out=gen_identity.go gen "Name=Identity NodeType=models.IdentityWrapper EdgeType=models.IdentityEdge ConnectionType=models.IdentityConnection" //go:generate genny -in=connection_template.go -out=gen_operation.go gen "Name=Operation NodeType=bug.Operation EdgeType=models.OperationEdge ConnectionType=models.OperationConnection" -//go:generate genny -in=connection_template.go -out=gen_comment.go gen "Name=Comment NodeType=bug.Comment EdgeType=models.CommentEdge ConnectionType=models.CommentConnection" +//go:generate genny -in=connection_template.go -out=gen_comment.go gen "Name=Comment NodeType=commentary.Comment EdgeType=models.CommentEdge ConnectionType=models.CommentConnection" //go:generate genny -in=connection_template.go -out=gen_timeline.go gen "Name=TimelineItem NodeType=bug.TimelineItem EdgeType=models.TimelineItemEdge ConnectionType=models.TimelineItemConnection" //go:generate genny -in=connection_template.go -out=gen_label.go gen "Name=Label NodeType=bug.Label EdgeType=models.LabelEdge ConnectionType=models.LabelConnection" +// NOTE If above files arn't re/generated by genny, do following: +// 1. Get genny by calling: `go get github.com/cheekybits/genny` in this +// projects root directory. +// 2. Call `go generate` while being in the directory of this file. +// E.g. api/graphql/connections + // Package connections implement a generic GraphQL relay connection package connections diff --git a/api/graphql/connections/gen_comment.go b/api/graphql/connections/gen_comment.go index bae740304..cf4505f18 100644 --- a/api/graphql/connections/gen_comment.go +++ b/api/graphql/connections/gen_comment.go @@ -8,23 +8,23 @@ import ( "fmt" "github.com/MichaelMure/git-bug/api/graphql/models" - "github.com/MichaelMure/git-bug/bug" + "github.com/MichaelMure/git-bug/commentary" ) -// BugCommentEdgeMaker define a function that take a bug.Comment and an offset and +// CommentaryCommentEdgeMaker define a function that take a commentary.Comment and an offset and // create an Edge. -type CommentEdgeMaker func(value bug.Comment, offset int) Edge +type CommentEdgeMaker func(value commentary.Comment, offset int) Edge // CommentConMaker define a function that create a models.CommentConnection type CommentConMaker func( edges []*models.CommentEdge, - nodes []bug.Comment, + nodes []commentary.Comment, info *models.PageInfo, totalCount int) (*models.CommentConnection, error) // CommentCon will paginate a source according to the input of a relay connection -func CommentCon(source []bug.Comment, edgeMaker CommentEdgeMaker, conMaker CommentConMaker, input models.ConnectionInput) (*models.CommentConnection, error) { - var nodes []bug.Comment +func CommentCon(source []commentary.Comment, edgeMaker CommentEdgeMaker, conMaker CommentConMaker, input models.ConnectionInput) (*models.CommentConnection, error) { + var nodes []commentary.Comment var edges []*models.CommentEdge var cursors []string var pageInfo = &models.PageInfo{} diff --git a/api/graphql/gqlgen.yml b/api/graphql/gqlgen.yml index b8019076b..a2f882de0 100644 --- a/api/graphql/gqlgen.yml +++ b/api/graphql/gqlgen.yml @@ -25,7 +25,9 @@ models: Color: model: image/color.RGBA Comment: - model: github.com/MichaelMure/git-bug/bug.Comment + model: github.com/MichaelMure/git-bug/commentary.Comment + Alteration: + model: github.com/MichaelMure/git-bug/commentary.Alteration Identity: model: github.com/MichaelMure/git-bug/api/graphql/models.IdentityWrapper Label: @@ -48,12 +50,8 @@ models: model: github.com/MichaelMure/git-bug/bug.LabelChangeOperation TimelineItem: model: github.com/MichaelMure/git-bug/bug.TimelineItem - CommentHistoryStep: - model: github.com/MichaelMure/git-bug/bug.CommentHistoryStep - CreateTimelineItem: - model: github.com/MichaelMure/git-bug/bug.CreateTimelineItem - AddCommentTimelineItem: - model: github.com/MichaelMure/git-bug/bug.AddCommentTimelineItem + CommentTimelineItem: + model: github.com/MichaelMure/git-bug/bug.CommentTimelineItem LabelChangeTimelineItem: model: github.com/MichaelMure/git-bug/bug.LabelChangeTimelineItem SetStatusTimelineItem: diff --git a/api/graphql/graph/gen_graph.go b/api/graphql/graph/gen_graph.go index b94effede..08f101481 100644 --- a/api/graphql/graph/gen_graph.go +++ b/api/graphql/graph/gen_graph.go @@ -17,6 +17,7 @@ import ( "github.com/99designs/gqlgen/graphql/introspection" "github.com/MichaelMure/git-bug/api/graphql/models" "github.com/MichaelMure/git-bug/bug" + "github.com/MichaelMure/git-bug/commentary" "github.com/MichaelMure/git-bug/repository" "github.com/vektah/gqlparser" "github.com/vektah/gqlparser/ast" @@ -41,13 +42,12 @@ type Config struct { type ResolverRoot interface { AddCommentOperation() AddCommentOperationResolver - AddCommentTimelineItem() AddCommentTimelineItemResolver + Alteration() AlterationResolver Bug() BugResolver Color() ColorResolver Comment() CommentResolver - CommentHistoryStep() CommentHistoryStepResolver + CommentTimelineItem() CommentTimelineItemResolver CreateOperation() CreateOperationResolver - CreateTimelineItem() CreateTimelineItemResolver EditCommentOperation() EditCommentOperationResolver Identity() IdentityResolver Label() LabelResolver @@ -95,16 +95,9 @@ type ComplexityRoot struct { Operation func(childComplexity int) int } - AddCommentTimelineItem struct { - Author func(childComplexity int) int - CreatedAt func(childComplexity int) int - Edited func(childComplexity int) int - Files func(childComplexity int) int - History func(childComplexity int) int - ID func(childComplexity int) int - LastEdit func(childComplexity int) int - Message func(childComplexity int) int - MessageIsEmpty func(childComplexity int) int + Alteration struct { + Date func(childComplexity int) int + Message func(childComplexity int) int } Bug struct { @@ -112,6 +105,7 @@ type ComplexityRoot struct { Author func(childComplexity int) int Comments func(childComplexity int, after *string, before *string, first *int, last *int) int CreatedAt func(childComplexity int) int + Description func(childComplexity int) int HumanID func(childComplexity int) int ID func(childComplexity int) int Labels func(childComplexity int) int @@ -155,9 +149,15 @@ type ComplexityRoot struct { } Comment struct { - Author func(childComplexity int) int - Files func(childComplexity int) int - Message func(childComplexity int) int + Author func(childComplexity int) int + CreatedAt func(childComplexity int) int + Files func(childComplexity int) int + HasEmptyMessage func(childComplexity int) int + History func(childComplexity int) int + ID func(childComplexity int) int + LastEdited func(childComplexity int) int + Message func(childComplexity int) int + WasEdited func(childComplexity int) int } CommentConnection struct { @@ -172,9 +172,16 @@ type ComplexityRoot struct { Node func(childComplexity int) int } - CommentHistoryStep struct { - Date func(childComplexity int) int - Message func(childComplexity int) int + CommentTimelineItem struct { + Author func(childComplexity int) int + CreatedAt func(childComplexity int) int + Files func(childComplexity int) int + HasEmptyMessage func(childComplexity int) int + History func(childComplexity int) int + ID func(childComplexity int) int + LastEdited func(childComplexity int) int + Message func(childComplexity int) int + WasEdited func(childComplexity int) int } CreateOperation struct { @@ -186,18 +193,6 @@ type ComplexityRoot struct { Title func(childComplexity int) int } - CreateTimelineItem struct { - Author func(childComplexity int) int - CreatedAt func(childComplexity int) int - Edited func(childComplexity int) int - Files func(childComplexity int) int - History func(childComplexity int) int - ID func(childComplexity int) int - LastEdit func(childComplexity int) int - Message func(childComplexity int) int - MessageIsEmpty func(childComplexity int) int - } - EditCommentOperation struct { Author func(childComplexity int) int Date func(childComplexity int) int @@ -385,18 +380,16 @@ type AddCommentOperationResolver interface { Author(ctx context.Context, obj *bug.AddCommentOperation) (models.IdentityWrapper, error) Date(ctx context.Context, obj *bug.AddCommentOperation) (*time.Time, error) } -type AddCommentTimelineItemResolver interface { - ID(ctx context.Context, obj *bug.AddCommentTimelineItem) (string, error) - Author(ctx context.Context, obj *bug.AddCommentTimelineItem) (models.IdentityWrapper, error) - - CreatedAt(ctx context.Context, obj *bug.AddCommentTimelineItem) (*time.Time, error) - LastEdit(ctx context.Context, obj *bug.AddCommentTimelineItem) (*time.Time, error) +type AlterationResolver interface { + Date(ctx context.Context, obj *commentary.Alteration) (*time.Time, error) } type BugResolver interface { ID(ctx context.Context, obj models.BugWrapper) (string, error) HumanID(ctx context.Context, obj models.BugWrapper) (string, error) Status(ctx context.Context, obj models.BugWrapper) (models.Status, error) + Author(ctx context.Context, obj models.BugWrapper) (models.IdentityWrapper, error) + Actors(ctx context.Context, obj models.BugWrapper, after *string, before *string, first *int, last *int) (*models.IdentityConnection, error) Participants(ctx context.Context, obj models.BugWrapper, after *string, before *string, first *int, last *int) (*models.IdentityConnection, error) Comments(ctx context.Context, obj models.BugWrapper, after *string, before *string, first *int, last *int) (*models.CommentConnection, error) @@ -409,23 +402,28 @@ type ColorResolver interface { B(ctx context.Context, obj *color.RGBA) (int, error) } type CommentResolver interface { - Author(ctx context.Context, obj *bug.Comment) (models.IdentityWrapper, error) -} -type CommentHistoryStepResolver interface { - Date(ctx context.Context, obj *bug.CommentHistoryStep) (*time.Time, error) + ID(ctx context.Context, obj *commentary.Comment) (string, error) + Author(ctx context.Context, obj *commentary.Comment) (models.IdentityWrapper, error) + + CreatedAt(ctx context.Context, obj *commentary.Comment) (*time.Time, error) + LastEdited(ctx context.Context, obj *commentary.Comment) (*time.Time, error) +} +type CommentTimelineItemResolver interface { + ID(ctx context.Context, obj *bug.CommentTimelineItem) (string, error) + Author(ctx context.Context, obj *bug.CommentTimelineItem) (models.IdentityWrapper, error) + Message(ctx context.Context, obj *bug.CommentTimelineItem) (string, error) + HasEmptyMessage(ctx context.Context, obj *bug.CommentTimelineItem) (bool, error) + Files(ctx context.Context, obj *bug.CommentTimelineItem) ([]repository.Hash, error) + CreatedAt(ctx context.Context, obj *bug.CommentTimelineItem) (*time.Time, error) + LastEdited(ctx context.Context, obj *bug.CommentTimelineItem) (*time.Time, error) + WasEdited(ctx context.Context, obj *bug.CommentTimelineItem) (bool, error) + History(ctx context.Context, obj *bug.CommentTimelineItem) ([]*commentary.Alteration, 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 CreateTimelineItemResolver interface { - ID(ctx context.Context, obj *bug.CreateTimelineItem) (string, 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 EditCommentOperationResolver interface { ID(ctx context.Context, obj *bug.EditCommentOperation) (string, error) Author(ctx context.Context, obj *bug.EditCommentOperation) (models.IdentityWrapper, error) @@ -626,68 +624,19 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.AddCommentPayload.Operation(childComplexity), true - case "AddCommentTimelineItem.author": - if e.complexity.AddCommentTimelineItem.Author == nil { - break - } - - return e.complexity.AddCommentTimelineItem.Author(childComplexity), true - - case "AddCommentTimelineItem.createdAt": - if e.complexity.AddCommentTimelineItem.CreatedAt == nil { - break - } - - return e.complexity.AddCommentTimelineItem.CreatedAt(childComplexity), true - - case "AddCommentTimelineItem.edited": - if e.complexity.AddCommentTimelineItem.Edited == nil { - break - } - - return e.complexity.AddCommentTimelineItem.Edited(childComplexity), true - - case "AddCommentTimelineItem.files": - if e.complexity.AddCommentTimelineItem.Files == nil { - break - } - - return e.complexity.AddCommentTimelineItem.Files(childComplexity), true - - case "AddCommentTimelineItem.history": - if e.complexity.AddCommentTimelineItem.History == nil { - break - } - - return e.complexity.AddCommentTimelineItem.History(childComplexity), true - - case "AddCommentTimelineItem.id": - if e.complexity.AddCommentTimelineItem.ID == nil { - break - } - - return e.complexity.AddCommentTimelineItem.ID(childComplexity), true - - case "AddCommentTimelineItem.lastEdit": - if e.complexity.AddCommentTimelineItem.LastEdit == nil { - break - } - - return e.complexity.AddCommentTimelineItem.LastEdit(childComplexity), true - - case "AddCommentTimelineItem.message": - if e.complexity.AddCommentTimelineItem.Message == nil { + case "Alteration.date": + if e.complexity.Alteration.Date == nil { break } - return e.complexity.AddCommentTimelineItem.Message(childComplexity), true + return e.complexity.Alteration.Date(childComplexity), true - case "AddCommentTimelineItem.messageIsEmpty": - if e.complexity.AddCommentTimelineItem.MessageIsEmpty == nil { + case "Alteration.message": + if e.complexity.Alteration.Message == nil { break } - return e.complexity.AddCommentTimelineItem.MessageIsEmpty(childComplexity), true + return e.complexity.Alteration.Message(childComplexity), true case "Bug.actors": if e.complexity.Bug.Actors == nil { @@ -727,6 +676,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Bug.CreatedAt(childComplexity), true + case "Bug.description": + if e.complexity.Bug.Description == nil { + break + } + + return e.complexity.Bug.Description(childComplexity), true + case "Bug.humanId": if e.complexity.Bug.HumanID == nil { break @@ -924,6 +880,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Comment.Author(childComplexity), true + case "Comment.createdAt": + if e.complexity.Comment.CreatedAt == nil { + break + } + + return e.complexity.Comment.CreatedAt(childComplexity), true + case "Comment.files": if e.complexity.Comment.Files == nil { break @@ -931,6 +894,34 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Comment.Files(childComplexity), true + case "Comment.hasEmptyMessage": + if e.complexity.Comment.HasEmptyMessage == nil { + break + } + + return e.complexity.Comment.HasEmptyMessage(childComplexity), true + + case "Comment.history": + if e.complexity.Comment.History == nil { + break + } + + return e.complexity.Comment.History(childComplexity), true + + case "Comment.id": + if e.complexity.Comment.ID == nil { + break + } + + return e.complexity.Comment.ID(childComplexity), true + + case "Comment.lastEdited": + if e.complexity.Comment.LastEdited == nil { + break + } + + return e.complexity.Comment.LastEdited(childComplexity), true + case "Comment.message": if e.complexity.Comment.Message == nil { break @@ -938,6 +929,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Comment.Message(childComplexity), true + case "Comment.wasEdited": + if e.complexity.Comment.WasEdited == nil { + break + } + + return e.complexity.Comment.WasEdited(childComplexity), true + case "CommentConnection.edges": if e.complexity.CommentConnection.Edges == nil { break @@ -980,124 +978,110 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.CommentEdge.Node(childComplexity), true - case "CommentHistoryStep.date": - if e.complexity.CommentHistoryStep.Date == nil { - break - } - - return e.complexity.CommentHistoryStep.Date(childComplexity), true - - case "CommentHistoryStep.message": - if e.complexity.CommentHistoryStep.Message == nil { - break - } - - return e.complexity.CommentHistoryStep.Message(childComplexity), true - - case "CreateOperation.author": - if e.complexity.CreateOperation.Author == nil { + case "CommentTimelineItem.author": + if e.complexity.CommentTimelineItem.Author == nil { break } - return e.complexity.CreateOperation.Author(childComplexity), true + return e.complexity.CommentTimelineItem.Author(childComplexity), true - case "CreateOperation.date": - if e.complexity.CreateOperation.Date == nil { + case "CommentTimelineItem.createdAt": + if e.complexity.CommentTimelineItem.CreatedAt == nil { break } - return e.complexity.CreateOperation.Date(childComplexity), true + return e.complexity.CommentTimelineItem.CreatedAt(childComplexity), true - case "CreateOperation.files": - if e.complexity.CreateOperation.Files == nil { + case "CommentTimelineItem.files": + if e.complexity.CommentTimelineItem.Files == nil { break } - return e.complexity.CreateOperation.Files(childComplexity), true + return e.complexity.CommentTimelineItem.Files(childComplexity), true - case "CreateOperation.id": - if e.complexity.CreateOperation.ID == nil { + case "CommentTimelineItem.hasEmptyMessage": + if e.complexity.CommentTimelineItem.HasEmptyMessage == nil { break } - return e.complexity.CreateOperation.ID(childComplexity), true + return e.complexity.CommentTimelineItem.HasEmptyMessage(childComplexity), true - case "CreateOperation.message": - if e.complexity.CreateOperation.Message == nil { + case "CommentTimelineItem.history": + if e.complexity.CommentTimelineItem.History == nil { break } - return e.complexity.CreateOperation.Message(childComplexity), true + return e.complexity.CommentTimelineItem.History(childComplexity), true - case "CreateOperation.title": - if e.complexity.CreateOperation.Title == nil { + case "CommentTimelineItem.id": + if e.complexity.CommentTimelineItem.ID == nil { break } - return e.complexity.CreateOperation.Title(childComplexity), true + return e.complexity.CommentTimelineItem.ID(childComplexity), true - case "CreateTimelineItem.author": - if e.complexity.CreateTimelineItem.Author == nil { + case "CommentTimelineItem.lastEdited": + if e.complexity.CommentTimelineItem.LastEdited == nil { break } - return e.complexity.CreateTimelineItem.Author(childComplexity), true + return e.complexity.CommentTimelineItem.LastEdited(childComplexity), true - case "CreateTimelineItem.createdAt": - if e.complexity.CreateTimelineItem.CreatedAt == nil { + case "CommentTimelineItem.message": + if e.complexity.CommentTimelineItem.Message == nil { break } - return e.complexity.CreateTimelineItem.CreatedAt(childComplexity), true + return e.complexity.CommentTimelineItem.Message(childComplexity), true - case "CreateTimelineItem.edited": - if e.complexity.CreateTimelineItem.Edited == nil { + case "CommentTimelineItem.wasEdited": + if e.complexity.CommentTimelineItem.WasEdited == nil { break } - return e.complexity.CreateTimelineItem.Edited(childComplexity), true + return e.complexity.CommentTimelineItem.WasEdited(childComplexity), true - case "CreateTimelineItem.files": - if e.complexity.CreateTimelineItem.Files == nil { + case "CreateOperation.author": + if e.complexity.CreateOperation.Author == nil { break } - return e.complexity.CreateTimelineItem.Files(childComplexity), true + return e.complexity.CreateOperation.Author(childComplexity), true - case "CreateTimelineItem.history": - if e.complexity.CreateTimelineItem.History == nil { + case "CreateOperation.date": + if e.complexity.CreateOperation.Date == nil { break } - return e.complexity.CreateTimelineItem.History(childComplexity), true + return e.complexity.CreateOperation.Date(childComplexity), true - case "CreateTimelineItem.id": - if e.complexity.CreateTimelineItem.ID == nil { + case "CreateOperation.files": + if e.complexity.CreateOperation.Files == nil { break } - return e.complexity.CreateTimelineItem.ID(childComplexity), true + return e.complexity.CreateOperation.Files(childComplexity), true - case "CreateTimelineItem.lastEdit": - if e.complexity.CreateTimelineItem.LastEdit == nil { + case "CreateOperation.id": + if e.complexity.CreateOperation.ID == nil { break } - return e.complexity.CreateTimelineItem.LastEdit(childComplexity), true + return e.complexity.CreateOperation.ID(childComplexity), true - case "CreateTimelineItem.message": - if e.complexity.CreateTimelineItem.Message == nil { + case "CreateOperation.message": + if e.complexity.CreateOperation.Message == nil { break } - return e.complexity.CreateTimelineItem.Message(childComplexity), true + return e.complexity.CreateOperation.Message(childComplexity), true - case "CreateTimelineItem.messageIsEmpty": - if e.complexity.CreateTimelineItem.MessageIsEmpty == nil { + case "CreateOperation.title": + if e.complexity.CreateOperation.Title == nil { break } - return e.complexity.CreateTimelineItem.MessageIsEmpty(childComplexity), true + return e.complexity.CreateOperation.Title(childComplexity), true case "EditCommentOperation.author": if e.complexity.EditCommentOperation.Author == nil { @@ -1959,19 +1943,7 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er } var sources = []*ast.Source{ - &ast.Source{Name: "schema/bug.graphql", Input: `"""Represents a comment on a bug.""" -type Comment implements Authored { - """The author of this comment.""" - author: Identity! - - """The message of this comment.""" - message: String! - - """All media's hash referenced in this comment""" - files: [Hash!]! -} - -type CommentConnection { + &ast.Source{Name: "schema/bug.graphql", Input: `type CommentConnection { edges: [CommentEdge!]! nodes: [Comment!]! pageInfo: PageInfo! @@ -1995,6 +1967,7 @@ type Bug implements Authored { humanId: String! status: Status! title: String! + description: Comment! labels: [Label!]! author: Identity! createdAt: Time! @@ -2077,6 +2050,36 @@ type BugEdge { """The item at the end of the edge.""" node: Bug! } +`, BuiltIn: false}, + &ast.Source{Name: "schema/comment.graphql", Input: `"""Alteration represents a previouse version of the comment message in the +comment history""" +type Alteration { + message: String! + date: Time! +} + +"""Represents a comment on a bug.""" +type Comment implements Authored { + """The id of this comment.""" + id: String! + """The author of this comment.""" + author: Identity! + """The message of this comment.""" + message: String! + """Indicates, if the comments message is empty or made up of whitespace.""" + hasEmptyMessage: Boolean! + """Indicates, if the comment was previously edited.""" + wasEdited: Boolean! + """All media's hash referenced in this comment.""" + files: [Hash!]! + """Represents the point in time, the comment was created at.""" + createdAt: Time! + """Represents the point in time, the comment last edited.""" + lastEdited: Time! + """Represents a collection of all previously comment alterations.""" + history: [Alteration!]! +} + `, BuiltIn: false}, &ast.Source{Name: "schema/identity.graphql", Input: `"""Represents an identity""" type Identity { @@ -2524,12 +2527,6 @@ interface TimelineItem { id: String! } -"""CommentHistoryStep hold one version of a message in the history""" -type CommentHistoryStep { - message: String! - date: Time! -} - # Connection """The connection type for TimelineItem""" @@ -2548,32 +2545,18 @@ type TimelineItemEdge { # Items -"""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! - author: Identity! - message: String! - messageIsEmpty: Boolean! - files: [Hash!]! - createdAt: Time! - lastEdit: Time! - edited: Boolean! - history: [CommentHistoryStep!]! -} - -"""AddCommentTimelineItem is a TimelineItem that represent a Comment and its edition history""" -type AddCommentTimelineItem implements TimelineItem & Authored { +"""CommentTimelineItem is a TimelineItem that represent a Comment and its edition history""" +type CommentTimelineItem implements TimelineItem & Authored { """The identifier of the source operation""" id: String! author: Identity! message: String! - messageIsEmpty: Boolean! + hasEmptyMessage: Boolean! files: [Hash!]! createdAt: Time! - lastEdit: Time! - edited: Boolean! - history: [CommentHistoryStep!]! + lastEdited: Time! + wasEdited: Boolean! + history: [Alteration!]! } """LabelChangeTimelineItem is a TimelineItem that represent a change in the labels of a bug""" @@ -3708,7 +3691,7 @@ func (ec *executionContext) _AddCommentPayload_operation(ctx context.Context, fi return ec.marshalNAddCommentOperation2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐAddCommentOperation(ctx, field.Selections, res) } -func (ec *executionContext) _AddCommentTimelineItem_id(ctx context.Context, field graphql.CollectedField, obj *bug.AddCommentTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _Alteration_message(ctx context.Context, field graphql.CollectedField, obj *commentary.Alteration) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3716,16 +3699,16 @@ func (ec *executionContext) _AddCommentTimelineItem_id(ctx context.Context, fiel } }() fc := &graphql.FieldContext{ - Object: "AddCommentTimelineItem", + Object: "Alteration", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.AddCommentTimelineItem().ID(rctx, obj) + return obj.Message, nil }) if err != nil { ec.Error(ctx, err) @@ -3742,7 +3725,7 @@ func (ec *executionContext) _AddCommentTimelineItem_id(ctx context.Context, fiel return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _AddCommentTimelineItem_author(ctx context.Context, field graphql.CollectedField, obj *bug.AddCommentTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _Alteration_date(ctx context.Context, field graphql.CollectedField, obj *commentary.Alteration) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3750,7 +3733,7 @@ func (ec *executionContext) _AddCommentTimelineItem_author(ctx context.Context, } }() fc := &graphql.FieldContext{ - Object: "AddCommentTimelineItem", + Object: "Alteration", Field: field, Args: nil, IsMethod: true, @@ -3759,7 +3742,7 @@ func (ec *executionContext) _AddCommentTimelineItem_author(ctx context.Context, ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.AddCommentTimelineItem().Author(rctx, obj) + return ec.resolvers.Alteration().Date(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -3771,12 +3754,12 @@ func (ec *executionContext) _AddCommentTimelineItem_author(ctx context.Context, } return graphql.Null } - res := resTmp.(models.IdentityWrapper) + res := resTmp.(*time.Time) fc.Result = res - return ec.marshalNIdentity2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐIdentityWrapper(ctx, field.Selections, res) + return ec.marshalNTime2ᚖtimeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _AddCommentTimelineItem_message(ctx context.Context, field graphql.CollectedField, obj *bug.AddCommentTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _Bug_id(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3784,16 +3767,16 @@ func (ec *executionContext) _AddCommentTimelineItem_message(ctx context.Context, } }() fc := &graphql.FieldContext{ - Object: "AddCommentTimelineItem", + Object: "Bug", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Message, nil + return ec.resolvers.Bug().ID(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -3810,7 +3793,7 @@ func (ec *executionContext) _AddCommentTimelineItem_message(ctx context.Context, return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _AddCommentTimelineItem_messageIsEmpty(ctx context.Context, field graphql.CollectedField, obj *bug.AddCommentTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _Bug_humanId(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3818,7 +3801,7 @@ func (ec *executionContext) _AddCommentTimelineItem_messageIsEmpty(ctx context.C } }() fc := &graphql.FieldContext{ - Object: "AddCommentTimelineItem", + Object: "Bug", Field: field, Args: nil, IsMethod: true, @@ -3827,7 +3810,7 @@ func (ec *executionContext) _AddCommentTimelineItem_messageIsEmpty(ctx context.C ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.MessageIsEmpty(), nil + return ec.resolvers.Bug().HumanID(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -3839,12 +3822,12 @@ func (ec *executionContext) _AddCommentTimelineItem_messageIsEmpty(ctx context.C } return graphql.Null } - res := resTmp.(bool) + res := resTmp.(string) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _AddCommentTimelineItem_files(ctx context.Context, field graphql.CollectedField, obj *bug.AddCommentTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _Bug_status(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3852,16 +3835,16 @@ func (ec *executionContext) _AddCommentTimelineItem_files(ctx context.Context, f } }() fc := &graphql.FieldContext{ - Object: "AddCommentTimelineItem", + Object: "Bug", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Files, nil + return ec.resolvers.Bug().Status(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -3873,12 +3856,12 @@ func (ec *executionContext) _AddCommentTimelineItem_files(ctx context.Context, f } return graphql.Null } - res := resTmp.([]repository.Hash) + res := resTmp.(models.Status) fc.Result = res - return ec.marshalNHash2ᚕgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋrepositoryᚐHashᚄ(ctx, field.Selections, res) + return ec.marshalNStatus2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐStatus(ctx, field.Selections, res) } -func (ec *executionContext) _AddCommentTimelineItem_createdAt(ctx context.Context, field graphql.CollectedField, obj *bug.AddCommentTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _Bug_title(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3886,7 +3869,7 @@ func (ec *executionContext) _AddCommentTimelineItem_createdAt(ctx context.Contex } }() fc := &graphql.FieldContext{ - Object: "AddCommentTimelineItem", + Object: "Bug", Field: field, Args: nil, IsMethod: true, @@ -3895,7 +3878,7 @@ func (ec *executionContext) _AddCommentTimelineItem_createdAt(ctx context.Contex ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.AddCommentTimelineItem().CreatedAt(rctx, obj) + return obj.Title(), nil }) if err != nil { ec.Error(ctx, err) @@ -3907,12 +3890,12 @@ func (ec *executionContext) _AddCommentTimelineItem_createdAt(ctx context.Contex } return graphql.Null } - res := resTmp.(*time.Time) + res := resTmp.(string) fc.Result = res - return ec.marshalNTime2ᚖtimeᚐTime(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _AddCommentTimelineItem_lastEdit(ctx context.Context, field graphql.CollectedField, obj *bug.AddCommentTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _Bug_description(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3920,7 +3903,7 @@ func (ec *executionContext) _AddCommentTimelineItem_lastEdit(ctx context.Context } }() fc := &graphql.FieldContext{ - Object: "AddCommentTimelineItem", + Object: "Bug", Field: field, Args: nil, IsMethod: true, @@ -3929,7 +3912,7 @@ func (ec *executionContext) _AddCommentTimelineItem_lastEdit(ctx context.Context ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.AddCommentTimelineItem().LastEdit(rctx, obj) + return obj.Description() }) if err != nil { ec.Error(ctx, err) @@ -3941,12 +3924,12 @@ func (ec *executionContext) _AddCommentTimelineItem_lastEdit(ctx context.Context } return graphql.Null } - res := resTmp.(*time.Time) + res := resTmp.(*commentary.Comment) fc.Result = res - return ec.marshalNTime2ᚖtimeᚐTime(ctx, field.Selections, res) + return ec.marshalNComment2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋcommentaryᚐComment(ctx, field.Selections, res) } -func (ec *executionContext) _AddCommentTimelineItem_edited(ctx context.Context, field graphql.CollectedField, obj *bug.AddCommentTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _Bug_labels(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3954,7 +3937,7 @@ func (ec *executionContext) _AddCommentTimelineItem_edited(ctx context.Context, } }() fc := &graphql.FieldContext{ - Object: "AddCommentTimelineItem", + Object: "Bug", Field: field, Args: nil, IsMethod: true, @@ -3963,7 +3946,7 @@ func (ec *executionContext) _AddCommentTimelineItem_edited(ctx context.Context, ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Edited(), nil + return obj.Labels(), nil }) if err != nil { ec.Error(ctx, err) @@ -3975,12 +3958,12 @@ func (ec *executionContext) _AddCommentTimelineItem_edited(ctx context.Context, } return graphql.Null } - res := resTmp.(bool) + res := resTmp.([]bug.Label) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalNLabel2ᚕgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐLabelᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _AddCommentTimelineItem_history(ctx context.Context, field graphql.CollectedField, obj *bug.AddCommentTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _Bug_author(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3988,16 +3971,16 @@ func (ec *executionContext) _AddCommentTimelineItem_history(ctx context.Context, } }() fc := &graphql.FieldContext{ - Object: "AddCommentTimelineItem", + Object: "Bug", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.History, nil + return ec.resolvers.Bug().Author(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -4009,12 +3992,12 @@ func (ec *executionContext) _AddCommentTimelineItem_history(ctx context.Context, } return graphql.Null } - res := resTmp.([]bug.CommentHistoryStep) + res := resTmp.(models.IdentityWrapper) fc.Result = res - return ec.marshalNCommentHistoryStep2ᚕgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐCommentHistoryStepᚄ(ctx, field.Selections, res) + return ec.marshalNIdentity2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐIdentityWrapper(ctx, field.Selections, res) } -func (ec *executionContext) _Bug_id(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { +func (ec *executionContext) _Bug_createdAt(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4031,7 +4014,7 @@ func (ec *executionContext) _Bug_id(ctx context.Context, field graphql.Collected ctx = graphql.WithFieldContext(ctx, fc) 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.CreatedAt(), nil }) if err != nil { ec.Error(ctx, err) @@ -4043,12 +4026,12 @@ func (ec *executionContext) _Bug_id(ctx context.Context, field graphql.Collected } return graphql.Null } - res := resTmp.(string) + res := resTmp.(time.Time) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _Bug_humanId(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { +func (ec *executionContext) _Bug_lastEdit(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4065,7 +4048,7 @@ func (ec *executionContext) _Bug_humanId(ctx context.Context, field graphql.Coll ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Bug().HumanID(rctx, obj) + return obj.LastEdit(), nil }) if err != nil { ec.Error(ctx, err) @@ -4077,12 +4060,12 @@ func (ec *executionContext) _Bug_humanId(ctx context.Context, field graphql.Coll } return graphql.Null } - res := resTmp.(string) + res := resTmp.(time.Time) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _Bug_status(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { +func (ec *executionContext) _Bug_actors(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4097,9 +4080,16 @@ func (ec *executionContext) _Bug_status(ctx context.Context, field graphql.Colle } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Bug_actors_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Bug().Status(rctx, obj) + return ec.resolvers.Bug().Actors(rctx, obj, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int)) }) if err != nil { ec.Error(ctx, err) @@ -4111,12 +4101,12 @@ func (ec *executionContext) _Bug_status(ctx context.Context, field graphql.Colle } return graphql.Null } - res := resTmp.(models.Status) + res := resTmp.(*models.IdentityConnection) fc.Result = res - return ec.marshalNStatus2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐStatus(ctx, field.Selections, res) + return ec.marshalNIdentityConnection2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐIdentityConnection(ctx, field.Selections, res) } -func (ec *executionContext) _Bug_title(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { +func (ec *executionContext) _Bug_participants(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4131,9 +4121,16 @@ func (ec *executionContext) _Bug_title(ctx context.Context, field graphql.Collec } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Bug_participants_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Title(), nil + return ec.resolvers.Bug().Participants(rctx, obj, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int)) }) if err != nil { ec.Error(ctx, err) @@ -4145,12 +4142,12 @@ func (ec *executionContext) _Bug_title(ctx context.Context, field graphql.Collec } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*models.IdentityConnection) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNIdentityConnection2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐIdentityConnection(ctx, field.Selections, res) } -func (ec *executionContext) _Bug_labels(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { +func (ec *executionContext) _Bug_comments(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4165,43 +4162,16 @@ func (ec *executionContext) _Bug_labels(ctx context.Context, field graphql.Colle } ctx = graphql.WithFieldContext(ctx, fc) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Labels(), nil - }) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Bug_comments_args(ctx, rawArgs) 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.([]bug.Label) - fc.Result = res - return ec.marshalNLabel2ᚕgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐLabelᚄ(ctx, field.Selections, res) -} - -func (ec *executionContext) _Bug_author(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - fc := &graphql.FieldContext{ - Object: "Bug", - Field: field, - Args: nil, - IsMethod: true, - } - - ctx = graphql.WithFieldContext(ctx, fc) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Author() + return ec.resolvers.Bug().Comments(rctx, obj, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int)) }) if err != nil { ec.Error(ctx, err) @@ -4213,12 +4183,12 @@ func (ec *executionContext) _Bug_author(ctx context.Context, field graphql.Colle } return graphql.Null } - res := resTmp.(models.IdentityWrapper) + res := resTmp.(*models.CommentConnection) fc.Result = res - return ec.marshalNIdentity2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐIdentityWrapper(ctx, field.Selections, res) + return ec.marshalNCommentConnection2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐCommentConnection(ctx, field.Selections, res) } -func (ec *executionContext) _Bug_createdAt(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { +func (ec *executionContext) _Bug_timeline(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4233,43 +4203,16 @@ func (ec *executionContext) _Bug_createdAt(ctx context.Context, field graphql.Co } ctx = graphql.WithFieldContext(ctx, fc) - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.CreatedAt(), nil - }) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Bug_timeline_args(ctx, rawArgs) 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.(time.Time) - fc.Result = res - return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) -} - -func (ec *executionContext) _Bug_lastEdit(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - fc := &graphql.FieldContext{ - Object: "Bug", - Field: field, - Args: nil, - IsMethod: true, - } - - ctx = graphql.WithFieldContext(ctx, fc) + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.LastEdit(), nil + return ec.resolvers.Bug().Timeline(rctx, obj, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int)) }) if err != nil { ec.Error(ctx, err) @@ -4281,12 +4224,12 @@ func (ec *executionContext) _Bug_lastEdit(ctx context.Context, field graphql.Col } return graphql.Null } - res := resTmp.(time.Time) + res := resTmp.(*models.TimelineItemConnection) fc.Result = res - return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) + return ec.marshalNTimelineItemConnection2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐTimelineItemConnection(ctx, field.Selections, res) } -func (ec *executionContext) _Bug_actors(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { +func (ec *executionContext) _Bug_operations(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4302,7 +4245,7 @@ func (ec *executionContext) _Bug_actors(ctx context.Context, field graphql.Colle ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Bug_actors_args(ctx, rawArgs) + args, err := ec.field_Bug_operations_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null @@ -4310,7 +4253,7 @@ func (ec *executionContext) _Bug_actors(ctx context.Context, field graphql.Colle fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Bug().Actors(rctx, obj, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int)) + return ec.resolvers.Bug().Operations(rctx, obj, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int)) }) if err != nil { ec.Error(ctx, err) @@ -4322,12 +4265,12 @@ func (ec *executionContext) _Bug_actors(ctx context.Context, field graphql.Colle } return graphql.Null } - res := resTmp.(*models.IdentityConnection) + res := resTmp.(*models.OperationConnection) fc.Result = res - return ec.marshalNIdentityConnection2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐIdentityConnection(ctx, field.Selections, res) + return ec.marshalNOperationConnection2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐOperationConnection(ctx, field.Selections, res) } -func (ec *executionContext) _Bug_participants(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { +func (ec *executionContext) _BugConnection_edges(ctx context.Context, field graphql.CollectedField, obj *models.BugConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4335,23 +4278,16 @@ func (ec *executionContext) _Bug_participants(ctx context.Context, field graphql } }() fc := &graphql.FieldContext{ - Object: "Bug", + Object: "BugConnection", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Bug_participants_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Bug().Participants(rctx, obj, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int)) + return obj.Edges, nil }) if err != nil { ec.Error(ctx, err) @@ -4363,12 +4299,12 @@ func (ec *executionContext) _Bug_participants(ctx context.Context, field graphql } return graphql.Null } - res := resTmp.(*models.IdentityConnection) + res := resTmp.([]*models.BugEdge) fc.Result = res - return ec.marshalNIdentityConnection2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐIdentityConnection(ctx, field.Selections, res) + return ec.marshalNBugEdge2ᚕᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐBugEdgeᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _Bug_comments(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { +func (ec *executionContext) _BugConnection_nodes(ctx context.Context, field graphql.CollectedField, obj *models.BugConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4376,23 +4312,16 @@ func (ec *executionContext) _Bug_comments(ctx context.Context, field graphql.Col } }() fc := &graphql.FieldContext{ - Object: "Bug", + Object: "BugConnection", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Bug_comments_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Bug().Comments(rctx, obj, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int)) + return obj.Nodes, nil }) if err != nil { ec.Error(ctx, err) @@ -4404,12 +4333,12 @@ func (ec *executionContext) _Bug_comments(ctx context.Context, field graphql.Col } return graphql.Null } - res := resTmp.(*models.CommentConnection) + res := resTmp.([]models.BugWrapper) fc.Result = res - return ec.marshalNCommentConnection2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐCommentConnection(ctx, field.Selections, res) + return ec.marshalNBug2ᚕgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐBugWrapperᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _Bug_timeline(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { +func (ec *executionContext) _BugConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *models.BugConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4417,23 +4346,16 @@ func (ec *executionContext) _Bug_timeline(ctx context.Context, field graphql.Col } }() fc := &graphql.FieldContext{ - Object: "Bug", + Object: "BugConnection", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Bug_timeline_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Bug().Timeline(rctx, obj, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int)) + return obj.PageInfo, nil }) if err != nil { ec.Error(ctx, err) @@ -4445,12 +4367,12 @@ func (ec *executionContext) _Bug_timeline(ctx context.Context, field graphql.Col } return graphql.Null } - res := resTmp.(*models.TimelineItemConnection) + res := resTmp.(*models.PageInfo) fc.Result = res - return ec.marshalNTimelineItemConnection2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐTimelineItemConnection(ctx, field.Selections, res) + return ec.marshalNPageInfo2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) _Bug_operations(ctx context.Context, field graphql.CollectedField, obj models.BugWrapper) (ret graphql.Marshaler) { +func (ec *executionContext) _BugConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *models.BugConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4458,23 +4380,16 @@ func (ec *executionContext) _Bug_operations(ctx context.Context, field graphql.C } }() fc := &graphql.FieldContext{ - Object: "Bug", + Object: "BugConnection", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Bug_operations_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Bug().Operations(rctx, obj, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int)) + return obj.TotalCount, nil }) if err != nil { ec.Error(ctx, err) @@ -4486,12 +4401,12 @@ func (ec *executionContext) _Bug_operations(ctx context.Context, field graphql.C } return graphql.Null } - res := resTmp.(*models.OperationConnection) + res := resTmp.(int) fc.Result = res - return ec.marshalNOperationConnection2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐOperationConnection(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _BugConnection_edges(ctx context.Context, field graphql.CollectedField, obj *models.BugConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _BugEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *models.BugEdge) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4499,7 +4414,7 @@ func (ec *executionContext) _BugConnection_edges(ctx context.Context, field grap } }() fc := &graphql.FieldContext{ - Object: "BugConnection", + Object: "BugEdge", Field: field, Args: nil, IsMethod: false, @@ -4508,7 +4423,7 @@ func (ec *executionContext) _BugConnection_edges(ctx context.Context, field grap ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Edges, nil + return obj.Cursor, nil }) if err != nil { ec.Error(ctx, err) @@ -4520,12 +4435,12 @@ func (ec *executionContext) _BugConnection_edges(ctx context.Context, field grap } return graphql.Null } - res := resTmp.([]*models.BugEdge) + res := resTmp.(string) fc.Result = res - return ec.marshalNBugEdge2ᚕᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐBugEdgeᚄ(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _BugConnection_nodes(ctx context.Context, field graphql.CollectedField, obj *models.BugConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _BugEdge_node(ctx context.Context, field graphql.CollectedField, obj *models.BugEdge) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4533,7 +4448,7 @@ func (ec *executionContext) _BugConnection_nodes(ctx context.Context, field grap } }() fc := &graphql.FieldContext{ - Object: "BugConnection", + Object: "BugEdge", Field: field, Args: nil, IsMethod: false, @@ -4542,7 +4457,7 @@ func (ec *executionContext) _BugConnection_nodes(ctx context.Context, field grap ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Nodes, nil + return obj.Node, nil }) if err != nil { ec.Error(ctx, err) @@ -4554,12 +4469,12 @@ func (ec *executionContext) _BugConnection_nodes(ctx context.Context, field grap } return graphql.Null } - res := resTmp.([]models.BugWrapper) + res := resTmp.(models.BugWrapper) fc.Result = res - return ec.marshalNBug2ᚕgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐBugWrapperᚄ(ctx, field.Selections, res) + return ec.marshalNBug2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐBugWrapper(ctx, field.Selections, res) } -func (ec *executionContext) _BugConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *models.BugConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _ChangeLabelPayload_clientMutationId(ctx context.Context, field graphql.CollectedField, obj *models.ChangeLabelPayload) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4567,7 +4482,7 @@ func (ec *executionContext) _BugConnection_pageInfo(ctx context.Context, field g } }() fc := &graphql.FieldContext{ - Object: "BugConnection", + Object: "ChangeLabelPayload", Field: field, Args: nil, IsMethod: false, @@ -4576,24 +4491,21 @@ func (ec *executionContext) _BugConnection_pageInfo(ctx context.Context, field g ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.PageInfo, nil + return obj.ClientMutationID, nil }) 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.(*models.PageInfo) + res := resTmp.(*string) fc.Result = res - return ec.marshalNPageInfo2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐPageInfo(ctx, field.Selections, res) + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) _BugConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *models.BugConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _ChangeLabelPayload_bug(ctx context.Context, field graphql.CollectedField, obj *models.ChangeLabelPayload) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4601,7 +4513,7 @@ func (ec *executionContext) _BugConnection_totalCount(ctx context.Context, field } }() fc := &graphql.FieldContext{ - Object: "BugConnection", + Object: "ChangeLabelPayload", Field: field, Args: nil, IsMethod: false, @@ -4610,7 +4522,7 @@ func (ec *executionContext) _BugConnection_totalCount(ctx context.Context, field ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.TotalCount, nil + return obj.Bug, nil }) if err != nil { ec.Error(ctx, err) @@ -4622,12 +4534,12 @@ func (ec *executionContext) _BugConnection_totalCount(ctx context.Context, field } return graphql.Null } - res := resTmp.(int) + res := resTmp.(models.BugWrapper) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNBug2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐBugWrapper(ctx, field.Selections, res) } -func (ec *executionContext) _BugEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *models.BugEdge) (ret graphql.Marshaler) { +func (ec *executionContext) _ChangeLabelPayload_operation(ctx context.Context, field graphql.CollectedField, obj *models.ChangeLabelPayload) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4635,7 +4547,7 @@ func (ec *executionContext) _BugEdge_cursor(ctx context.Context, field graphql.C } }() fc := &graphql.FieldContext{ - Object: "BugEdge", + Object: "ChangeLabelPayload", Field: field, Args: nil, IsMethod: false, @@ -4644,7 +4556,7 @@ func (ec *executionContext) _BugEdge_cursor(ctx context.Context, field graphql.C ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Cursor, nil + return obj.Operation, nil }) if err != nil { ec.Error(ctx, err) @@ -4656,12 +4568,12 @@ func (ec *executionContext) _BugEdge_cursor(ctx context.Context, field graphql.C } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*bug.LabelChangeOperation) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNLabelChangeOperation2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐLabelChangeOperation(ctx, field.Selections, res) } -func (ec *executionContext) _BugEdge_node(ctx context.Context, field graphql.CollectedField, obj *models.BugEdge) (ret graphql.Marshaler) { +func (ec *executionContext) _ChangeLabelPayload_results(ctx context.Context, field graphql.CollectedField, obj *models.ChangeLabelPayload) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4669,7 +4581,7 @@ func (ec *executionContext) _BugEdge_node(ctx context.Context, field graphql.Col } }() fc := &graphql.FieldContext{ - Object: "BugEdge", + Object: "ChangeLabelPayload", Field: field, Args: nil, IsMethod: false, @@ -4678,7 +4590,7 @@ func (ec *executionContext) _BugEdge_node(ctx context.Context, field graphql.Col ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Node, nil + return obj.Results, nil }) if err != nil { ec.Error(ctx, err) @@ -4690,12 +4602,12 @@ func (ec *executionContext) _BugEdge_node(ctx context.Context, field graphql.Col } return graphql.Null } - res := resTmp.(models.BugWrapper) + res := resTmp.([]*bug.LabelChangeResult) fc.Result = res - return ec.marshalNBug2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐBugWrapper(ctx, field.Selections, res) + return ec.marshalNLabelChangeResult2ᚕᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐLabelChangeResult(ctx, field.Selections, res) } -func (ec *executionContext) _ChangeLabelPayload_clientMutationId(ctx context.Context, field graphql.CollectedField, obj *models.ChangeLabelPayload) (ret graphql.Marshaler) { +func (ec *executionContext) _CloseBugPayload_clientMutationId(ctx context.Context, field graphql.CollectedField, obj *models.CloseBugPayload) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4703,7 +4615,7 @@ func (ec *executionContext) _ChangeLabelPayload_clientMutationId(ctx context.Con } }() fc := &graphql.FieldContext{ - Object: "ChangeLabelPayload", + Object: "CloseBugPayload", Field: field, Args: nil, IsMethod: false, @@ -4726,7 +4638,7 @@ func (ec *executionContext) _ChangeLabelPayload_clientMutationId(ctx context.Con return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) _ChangeLabelPayload_bug(ctx context.Context, field graphql.CollectedField, obj *models.ChangeLabelPayload) (ret graphql.Marshaler) { +func (ec *executionContext) _CloseBugPayload_bug(ctx context.Context, field graphql.CollectedField, obj *models.CloseBugPayload) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4734,7 +4646,7 @@ func (ec *executionContext) _ChangeLabelPayload_bug(ctx context.Context, field g } }() fc := &graphql.FieldContext{ - Object: "ChangeLabelPayload", + Object: "CloseBugPayload", Field: field, Args: nil, IsMethod: false, @@ -4760,7 +4672,7 @@ func (ec *executionContext) _ChangeLabelPayload_bug(ctx context.Context, field g return ec.marshalNBug2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐBugWrapper(ctx, field.Selections, res) } -func (ec *executionContext) _ChangeLabelPayload_operation(ctx context.Context, field graphql.CollectedField, obj *models.ChangeLabelPayload) (ret graphql.Marshaler) { +func (ec *executionContext) _CloseBugPayload_operation(ctx context.Context, field graphql.CollectedField, obj *models.CloseBugPayload) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4768,7 +4680,7 @@ func (ec *executionContext) _ChangeLabelPayload_operation(ctx context.Context, f } }() fc := &graphql.FieldContext{ - Object: "ChangeLabelPayload", + Object: "CloseBugPayload", Field: field, Args: nil, IsMethod: false, @@ -4789,12 +4701,12 @@ func (ec *executionContext) _ChangeLabelPayload_operation(ctx context.Context, f } return graphql.Null } - res := resTmp.(*bug.LabelChangeOperation) + res := resTmp.(*bug.SetStatusOperation) fc.Result = res - return ec.marshalNLabelChangeOperation2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐLabelChangeOperation(ctx, field.Selections, res) + return ec.marshalNSetStatusOperation2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐSetStatusOperation(ctx, field.Selections, res) } -func (ec *executionContext) _ChangeLabelPayload_results(ctx context.Context, field graphql.CollectedField, obj *models.ChangeLabelPayload) (ret graphql.Marshaler) { +func (ec *executionContext) _Color_R(ctx context.Context, field graphql.CollectedField, obj *color.RGBA) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4802,16 +4714,16 @@ func (ec *executionContext) _ChangeLabelPayload_results(ctx context.Context, fie } }() fc := &graphql.FieldContext{ - Object: "ChangeLabelPayload", + Object: "Color", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Results, nil + return ec.resolvers.Color().R(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -4823,12 +4735,12 @@ func (ec *executionContext) _ChangeLabelPayload_results(ctx context.Context, fie } return graphql.Null } - res := resTmp.([]*bug.LabelChangeResult) + res := resTmp.(int) fc.Result = res - return ec.marshalNLabelChangeResult2ᚕᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐLabelChangeResult(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _CloseBugPayload_clientMutationId(ctx context.Context, field graphql.CollectedField, obj *models.CloseBugPayload) (ret graphql.Marshaler) { +func (ec *executionContext) _Color_G(ctx context.Context, field graphql.CollectedField, obj *color.RGBA) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4836,30 +4748,33 @@ func (ec *executionContext) _CloseBugPayload_clientMutationId(ctx context.Contex } }() fc := &graphql.FieldContext{ - Object: "CloseBugPayload", + Object: "Color", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ClientMutationID, nil + return ec.resolvers.Color().G(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.(*string) + res := resTmp.(int) fc.Result = res - return ec.marshalOString2ᚖstring(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _CloseBugPayload_bug(ctx context.Context, field graphql.CollectedField, obj *models.CloseBugPayload) (ret graphql.Marshaler) { +func (ec *executionContext) _Color_B(ctx context.Context, field graphql.CollectedField, obj *color.RGBA) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4867,16 +4782,16 @@ func (ec *executionContext) _CloseBugPayload_bug(ctx context.Context, field grap } }() fc := &graphql.FieldContext{ - Object: "CloseBugPayload", + Object: "Color", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Bug, nil + return ec.resolvers.Color().B(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -4888,12 +4803,12 @@ func (ec *executionContext) _CloseBugPayload_bug(ctx context.Context, field grap } return graphql.Null } - res := resTmp.(models.BugWrapper) + res := resTmp.(int) fc.Result = res - return ec.marshalNBug2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐBugWrapper(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _CloseBugPayload_operation(ctx context.Context, field graphql.CollectedField, obj *models.CloseBugPayload) (ret graphql.Marshaler) { +func (ec *executionContext) _Comment_id(ctx context.Context, field graphql.CollectedField, obj *commentary.Comment) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4901,16 +4816,16 @@ func (ec *executionContext) _CloseBugPayload_operation(ctx context.Context, fiel } }() fc := &graphql.FieldContext{ - Object: "CloseBugPayload", + Object: "Comment", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Operation, nil + return ec.resolvers.Comment().ID(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -4922,12 +4837,12 @@ func (ec *executionContext) _CloseBugPayload_operation(ctx context.Context, fiel } return graphql.Null } - res := resTmp.(*bug.SetStatusOperation) + res := resTmp.(string) fc.Result = res - return ec.marshalNSetStatusOperation2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐSetStatusOperation(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Color_R(ctx context.Context, field graphql.CollectedField, obj *color.RGBA) (ret graphql.Marshaler) { +func (ec *executionContext) _Comment_author(ctx context.Context, field graphql.CollectedField, obj *commentary.Comment) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4935,7 +4850,7 @@ func (ec *executionContext) _Color_R(ctx context.Context, field graphql.Collecte } }() fc := &graphql.FieldContext{ - Object: "Color", + Object: "Comment", Field: field, Args: nil, IsMethod: true, @@ -4944,7 +4859,7 @@ func (ec *executionContext) _Color_R(ctx context.Context, field graphql.Collecte ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Color().R(rctx, obj) + return ec.resolvers.Comment().Author(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -4956,12 +4871,12 @@ func (ec *executionContext) _Color_R(ctx context.Context, field graphql.Collecte } return graphql.Null } - res := resTmp.(int) + res := resTmp.(models.IdentityWrapper) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNIdentity2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐIdentityWrapper(ctx, field.Selections, res) } -func (ec *executionContext) _Color_G(ctx context.Context, field graphql.CollectedField, obj *color.RGBA) (ret graphql.Marshaler) { +func (ec *executionContext) _Comment_message(ctx context.Context, field graphql.CollectedField, obj *commentary.Comment) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4969,7 +4884,7 @@ func (ec *executionContext) _Color_G(ctx context.Context, field graphql.Collecte } }() fc := &graphql.FieldContext{ - Object: "Color", + Object: "Comment", Field: field, Args: nil, IsMethod: true, @@ -4978,7 +4893,7 @@ func (ec *executionContext) _Color_G(ctx context.Context, field graphql.Collecte ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Color().G(rctx, obj) + return obj.Message(), nil }) if err != nil { ec.Error(ctx, err) @@ -4990,12 +4905,12 @@ func (ec *executionContext) _Color_G(ctx context.Context, field graphql.Collecte } return graphql.Null } - res := resTmp.(int) + res := resTmp.(string) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Color_B(ctx context.Context, field graphql.CollectedField, obj *color.RGBA) (ret graphql.Marshaler) { +func (ec *executionContext) _Comment_hasEmptyMessage(ctx context.Context, field graphql.CollectedField, obj *commentary.Comment) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5003,7 +4918,7 @@ func (ec *executionContext) _Color_B(ctx context.Context, field graphql.Collecte } }() fc := &graphql.FieldContext{ - Object: "Color", + Object: "Comment", Field: field, Args: nil, IsMethod: true, @@ -5012,7 +4927,7 @@ func (ec *executionContext) _Color_B(ctx context.Context, field graphql.Collecte ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Color().B(rctx, obj) + return obj.HasEmptyMessage(), nil }) if err != nil { ec.Error(ctx, err) @@ -5024,12 +4939,12 @@ func (ec *executionContext) _Color_B(ctx context.Context, field graphql.Collecte } return graphql.Null } - res := resTmp.(int) + res := resTmp.(bool) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _Comment_author(ctx context.Context, field graphql.CollectedField, obj *bug.Comment) (ret graphql.Marshaler) { +func (ec *executionContext) _Comment_wasEdited(ctx context.Context, field graphql.CollectedField, obj *commentary.Comment) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5046,7 +4961,7 @@ func (ec *executionContext) _Comment_author(ctx context.Context, field graphql.C ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Comment().Author(rctx, obj) + return obj.WasEdited(), nil }) if err != nil { ec.Error(ctx, err) @@ -5058,12 +4973,12 @@ func (ec *executionContext) _Comment_author(ctx context.Context, field graphql.C } return graphql.Null } - res := resTmp.(models.IdentityWrapper) + res := resTmp.(bool) fc.Result = res - return ec.marshalNIdentity2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐIdentityWrapper(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _Comment_message(ctx context.Context, field graphql.CollectedField, obj *bug.Comment) (ret graphql.Marshaler) { +func (ec *executionContext) _Comment_files(ctx context.Context, field graphql.CollectedField, obj *commentary.Comment) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5074,13 +4989,13 @@ func (ec *executionContext) _Comment_message(ctx context.Context, field graphql. Object: "Comment", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Message, nil + return obj.Files(), nil }) if err != nil { ec.Error(ctx, err) @@ -5092,12 +5007,12 @@ func (ec *executionContext) _Comment_message(ctx context.Context, field graphql. } return graphql.Null } - res := resTmp.(string) + res := resTmp.([]repository.Hash) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNHash2ᚕgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋrepositoryᚐHashᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _Comment_files(ctx context.Context, field graphql.CollectedField, obj *bug.Comment) (ret graphql.Marshaler) { +func (ec *executionContext) _Comment_createdAt(ctx context.Context, field graphql.CollectedField, obj *commentary.Comment) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5108,13 +5023,13 @@ func (ec *executionContext) _Comment_files(ctx context.Context, field graphql.Co Object: "Comment", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Files, nil + return ec.resolvers.Comment().CreatedAt(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -5126,12 +5041,12 @@ func (ec *executionContext) _Comment_files(ctx context.Context, field graphql.Co } return graphql.Null } - res := resTmp.([]repository.Hash) + res := resTmp.(*time.Time) fc.Result = res - return ec.marshalNHash2ᚕgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋrepositoryᚐHashᚄ(ctx, field.Selections, res) + return ec.marshalNTime2ᚖtimeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _CommentConnection_edges(ctx context.Context, field graphql.CollectedField, obj *models.CommentConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _Comment_lastEdited(ctx context.Context, field graphql.CollectedField, obj *commentary.Comment) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5139,16 +5054,16 @@ func (ec *executionContext) _CommentConnection_edges(ctx context.Context, field } }() fc := &graphql.FieldContext{ - Object: "CommentConnection", + Object: "Comment", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Edges, nil + return ec.resolvers.Comment().LastEdited(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -5160,12 +5075,12 @@ func (ec *executionContext) _CommentConnection_edges(ctx context.Context, field } return graphql.Null } - res := resTmp.([]*models.CommentEdge) + res := resTmp.(*time.Time) fc.Result = res - return ec.marshalNCommentEdge2ᚕᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐCommentEdgeᚄ(ctx, field.Selections, res) + return ec.marshalNTime2ᚖtimeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _CommentConnection_nodes(ctx context.Context, field graphql.CollectedField, obj *models.CommentConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _Comment_history(ctx context.Context, field graphql.CollectedField, obj *commentary.Comment) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5173,16 +5088,16 @@ func (ec *executionContext) _CommentConnection_nodes(ctx context.Context, field } }() fc := &graphql.FieldContext{ - Object: "CommentConnection", + Object: "Comment", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Nodes, nil + return obj.History(), nil }) if err != nil { ec.Error(ctx, err) @@ -5194,12 +5109,12 @@ func (ec *executionContext) _CommentConnection_nodes(ctx context.Context, field } return graphql.Null } - res := resTmp.([]*bug.Comment) + res := resTmp.([]commentary.Alteration) fc.Result = res - return ec.marshalNComment2ᚕᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐCommentᚄ(ctx, field.Selections, res) + return ec.marshalNAlteration2ᚕgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋcommentaryᚐAlterationᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _CommentConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *models.CommentConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _CommentConnection_edges(ctx context.Context, field graphql.CollectedField, obj *models.CommentConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5216,7 +5131,7 @@ func (ec *executionContext) _CommentConnection_pageInfo(ctx context.Context, fie ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.PageInfo, nil + return obj.Edges, nil }) if err != nil { ec.Error(ctx, err) @@ -5228,12 +5143,12 @@ func (ec *executionContext) _CommentConnection_pageInfo(ctx context.Context, fie } return graphql.Null } - res := resTmp.(*models.PageInfo) + res := resTmp.([]*models.CommentEdge) fc.Result = res - return ec.marshalNPageInfo2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐPageInfo(ctx, field.Selections, res) + return ec.marshalNCommentEdge2ᚕᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐCommentEdgeᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _CommentConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *models.CommentConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _CommentConnection_nodes(ctx context.Context, field graphql.CollectedField, obj *models.CommentConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5250,7 +5165,7 @@ func (ec *executionContext) _CommentConnection_totalCount(ctx context.Context, f ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.TotalCount, nil + return obj.Nodes, nil }) if err != nil { ec.Error(ctx, err) @@ -5262,12 +5177,12 @@ func (ec *executionContext) _CommentConnection_totalCount(ctx context.Context, f } return graphql.Null } - res := resTmp.(int) + res := resTmp.([]*commentary.Comment) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNComment2ᚕᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋcommentaryᚐCommentᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _CommentEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *models.CommentEdge) (ret graphql.Marshaler) { +func (ec *executionContext) _CommentConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *models.CommentConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5275,7 +5190,7 @@ func (ec *executionContext) _CommentEdge_cursor(ctx context.Context, field graph } }() fc := &graphql.FieldContext{ - Object: "CommentEdge", + Object: "CommentConnection", Field: field, Args: nil, IsMethod: false, @@ -5284,7 +5199,7 @@ func (ec *executionContext) _CommentEdge_cursor(ctx context.Context, field graph ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Cursor, nil + return obj.PageInfo, nil }) if err != nil { ec.Error(ctx, err) @@ -5296,12 +5211,12 @@ func (ec *executionContext) _CommentEdge_cursor(ctx context.Context, field graph } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*models.PageInfo) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNPageInfo2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) _CommentEdge_node(ctx context.Context, field graphql.CollectedField, obj *models.CommentEdge) (ret graphql.Marshaler) { +func (ec *executionContext) _CommentConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *models.CommentConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5309,7 +5224,7 @@ func (ec *executionContext) _CommentEdge_node(ctx context.Context, field graphql } }() fc := &graphql.FieldContext{ - Object: "CommentEdge", + Object: "CommentConnection", Field: field, Args: nil, IsMethod: false, @@ -5318,7 +5233,7 @@ func (ec *executionContext) _CommentEdge_node(ctx context.Context, field graphql ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Node, nil + return obj.TotalCount, nil }) if err != nil { ec.Error(ctx, err) @@ -5330,12 +5245,12 @@ func (ec *executionContext) _CommentEdge_node(ctx context.Context, field graphql } return graphql.Null } - res := resTmp.(*bug.Comment) + res := resTmp.(int) fc.Result = res - return ec.marshalNComment2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐComment(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _CommentHistoryStep_message(ctx context.Context, field graphql.CollectedField, obj *bug.CommentHistoryStep) (ret graphql.Marshaler) { +func (ec *executionContext) _CommentEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *models.CommentEdge) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5343,7 +5258,7 @@ func (ec *executionContext) _CommentHistoryStep_message(ctx context.Context, fie } }() fc := &graphql.FieldContext{ - Object: "CommentHistoryStep", + Object: "CommentEdge", Field: field, Args: nil, IsMethod: false, @@ -5352,7 +5267,7 @@ func (ec *executionContext) _CommentHistoryStep_message(ctx context.Context, fie ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Message, nil + return obj.Cursor, nil }) if err != nil { ec.Error(ctx, err) @@ -5369,7 +5284,7 @@ func (ec *executionContext) _CommentHistoryStep_message(ctx context.Context, fie return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _CommentHistoryStep_date(ctx context.Context, field graphql.CollectedField, obj *bug.CommentHistoryStep) (ret graphql.Marshaler) { +func (ec *executionContext) _CommentEdge_node(ctx context.Context, field graphql.CollectedField, obj *models.CommentEdge) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5377,16 +5292,16 @@ func (ec *executionContext) _CommentHistoryStep_date(ctx context.Context, field } }() fc := &graphql.FieldContext{ - Object: "CommentHistoryStep", + Object: "CommentEdge", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.CommentHistoryStep().Date(rctx, obj) + return obj.Node, nil }) if err != nil { ec.Error(ctx, err) @@ -5398,12 +5313,12 @@ func (ec *executionContext) _CommentHistoryStep_date(ctx context.Context, field } return graphql.Null } - res := resTmp.(*time.Time) + res := resTmp.(*commentary.Comment) fc.Result = res - return ec.marshalNTime2ᚖtimeᚐTime(ctx, field.Selections, res) + return ec.marshalNComment2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋcommentaryᚐComment(ctx, field.Selections, res) } -func (ec *executionContext) _CreateOperation_id(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) (ret graphql.Marshaler) { +func (ec *executionContext) _CommentTimelineItem_id(ctx context.Context, field graphql.CollectedField, obj *bug.CommentTimelineItem) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5411,7 +5326,7 @@ func (ec *executionContext) _CreateOperation_id(ctx context.Context, field graph } }() fc := &graphql.FieldContext{ - Object: "CreateOperation", + Object: "CommentTimelineItem", Field: field, Args: nil, IsMethod: true, @@ -5420,7 +5335,7 @@ func (ec *executionContext) _CreateOperation_id(ctx context.Context, field graph ctx = graphql.WithFieldContext(ctx, fc) 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 ec.resolvers.CommentTimelineItem().ID(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -5437,7 +5352,7 @@ func (ec *executionContext) _CreateOperation_id(ctx context.Context, field graph return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _CreateOperation_author(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) (ret graphql.Marshaler) { +func (ec *executionContext) _CommentTimelineItem_author(ctx context.Context, field graphql.CollectedField, obj *bug.CommentTimelineItem) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5445,7 +5360,7 @@ func (ec *executionContext) _CreateOperation_author(ctx context.Context, field g } }() fc := &graphql.FieldContext{ - Object: "CreateOperation", + Object: "CommentTimelineItem", Field: field, Args: nil, IsMethod: true, @@ -5454,7 +5369,7 @@ func (ec *executionContext) _CreateOperation_author(ctx context.Context, field g ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.CreateOperation().Author(rctx, obj) + return ec.resolvers.CommentTimelineItem().Author(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -5471,7 +5386,7 @@ func (ec *executionContext) _CreateOperation_author(ctx context.Context, field g return ec.marshalNIdentity2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐIdentityWrapper(ctx, field.Selections, res) } -func (ec *executionContext) _CreateOperation_date(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) (ret graphql.Marshaler) { +func (ec *executionContext) _CommentTimelineItem_message(ctx context.Context, field graphql.CollectedField, obj *bug.CommentTimelineItem) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5479,7 +5394,7 @@ func (ec *executionContext) _CreateOperation_date(ctx context.Context, field gra } }() fc := &graphql.FieldContext{ - Object: "CreateOperation", + Object: "CommentTimelineItem", Field: field, Args: nil, IsMethod: true, @@ -5488,7 +5403,7 @@ func (ec *executionContext) _CreateOperation_date(ctx context.Context, field gra ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.CreateOperation().Date(rctx, obj) + return ec.resolvers.CommentTimelineItem().Message(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -5500,12 +5415,12 @@ func (ec *executionContext) _CreateOperation_date(ctx context.Context, field gra } return graphql.Null } - res := resTmp.(*time.Time) + res := resTmp.(string) fc.Result = res - return ec.marshalNTime2ᚖtimeᚐTime(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _CreateOperation_title(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) (ret graphql.Marshaler) { +func (ec *executionContext) _CommentTimelineItem_hasEmptyMessage(ctx context.Context, field graphql.CollectedField, obj *bug.CommentTimelineItem) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5513,16 +5428,16 @@ func (ec *executionContext) _CreateOperation_title(ctx context.Context, field gr } }() fc := &graphql.FieldContext{ - Object: "CreateOperation", + Object: "CommentTimelineItem", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Title, nil + return ec.resolvers.CommentTimelineItem().HasEmptyMessage(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -5534,12 +5449,12 @@ func (ec *executionContext) _CreateOperation_title(ctx context.Context, field gr } return graphql.Null } - res := resTmp.(string) + res := resTmp.(bool) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _CreateOperation_message(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) (ret graphql.Marshaler) { +func (ec *executionContext) _CommentTimelineItem_files(ctx context.Context, field graphql.CollectedField, obj *bug.CommentTimelineItem) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5547,16 +5462,16 @@ func (ec *executionContext) _CreateOperation_message(ctx context.Context, field } }() fc := &graphql.FieldContext{ - Object: "CreateOperation", + Object: "CommentTimelineItem", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Message, nil + return ec.resolvers.CommentTimelineItem().Files(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -5568,12 +5483,12 @@ func (ec *executionContext) _CreateOperation_message(ctx context.Context, field } return graphql.Null } - res := resTmp.(string) + res := resTmp.([]repository.Hash) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNHash2ᚕgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋrepositoryᚐHashᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _CreateOperation_files(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) (ret graphql.Marshaler) { +func (ec *executionContext) _CommentTimelineItem_createdAt(ctx context.Context, field graphql.CollectedField, obj *bug.CommentTimelineItem) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5581,16 +5496,16 @@ func (ec *executionContext) _CreateOperation_files(ctx context.Context, field gr } }() fc := &graphql.FieldContext{ - Object: "CreateOperation", + Object: "CommentTimelineItem", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Files, nil + return ec.resolvers.CommentTimelineItem().CreatedAt(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -5602,12 +5517,12 @@ func (ec *executionContext) _CreateOperation_files(ctx context.Context, field gr } return graphql.Null } - res := resTmp.([]repository.Hash) + res := resTmp.(*time.Time) fc.Result = res - return ec.marshalNHash2ᚕgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋrepositoryᚐHashᚄ(ctx, field.Selections, res) + return ec.marshalNTime2ᚖtimeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _CreateTimelineItem_id(ctx context.Context, field graphql.CollectedField, obj *bug.CreateTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _CommentTimelineItem_lastEdited(ctx context.Context, field graphql.CollectedField, obj *bug.CommentTimelineItem) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5615,7 +5530,7 @@ func (ec *executionContext) _CreateTimelineItem_id(ctx context.Context, field gr } }() fc := &graphql.FieldContext{ - Object: "CreateTimelineItem", + Object: "CommentTimelineItem", Field: field, Args: nil, IsMethod: true, @@ -5624,7 +5539,7 @@ func (ec *executionContext) _CreateTimelineItem_id(ctx context.Context, field gr ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.CreateTimelineItem().ID(rctx, obj) + return ec.resolvers.CommentTimelineItem().LastEdited(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -5636,12 +5551,12 @@ func (ec *executionContext) _CreateTimelineItem_id(ctx context.Context, field gr } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*time.Time) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNTime2ᚖtimeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _CreateTimelineItem_author(ctx context.Context, field graphql.CollectedField, obj *bug.CreateTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _CommentTimelineItem_wasEdited(ctx context.Context, field graphql.CollectedField, obj *bug.CommentTimelineItem) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5649,7 +5564,7 @@ func (ec *executionContext) _CreateTimelineItem_author(ctx context.Context, fiel } }() fc := &graphql.FieldContext{ - Object: "CreateTimelineItem", + Object: "CommentTimelineItem", Field: field, Args: nil, IsMethod: true, @@ -5658,7 +5573,7 @@ func (ec *executionContext) _CreateTimelineItem_author(ctx context.Context, fiel ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.CreateTimelineItem().Author(rctx, obj) + return ec.resolvers.CommentTimelineItem().WasEdited(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -5670,12 +5585,12 @@ func (ec *executionContext) _CreateTimelineItem_author(ctx context.Context, fiel } return graphql.Null } - res := resTmp.(models.IdentityWrapper) + res := resTmp.(bool) fc.Result = res - return ec.marshalNIdentity2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐIdentityWrapper(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _CreateTimelineItem_message(ctx context.Context, field graphql.CollectedField, obj *bug.CreateTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _CommentTimelineItem_history(ctx context.Context, field graphql.CollectedField, obj *bug.CommentTimelineItem) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5683,16 +5598,16 @@ func (ec *executionContext) _CreateTimelineItem_message(ctx context.Context, fie } }() fc := &graphql.FieldContext{ - Object: "CreateTimelineItem", + Object: "CommentTimelineItem", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Message, nil + return ec.resolvers.CommentTimelineItem().History(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -5704,12 +5619,12 @@ func (ec *executionContext) _CreateTimelineItem_message(ctx context.Context, fie } return graphql.Null } - res := resTmp.(string) + res := resTmp.([]*commentary.Alteration) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNAlteration2ᚕᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋcommentaryᚐAlterationᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _CreateTimelineItem_messageIsEmpty(ctx context.Context, field graphql.CollectedField, obj *bug.CreateTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _CreateOperation_id(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5717,7 +5632,7 @@ func (ec *executionContext) _CreateTimelineItem_messageIsEmpty(ctx context.Conte } }() fc := &graphql.FieldContext{ - Object: "CreateTimelineItem", + Object: "CreateOperation", Field: field, Args: nil, IsMethod: true, @@ -5726,7 +5641,7 @@ func (ec *executionContext) _CreateTimelineItem_messageIsEmpty(ctx context.Conte ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.MessageIsEmpty(), nil + return ec.resolvers.CreateOperation().ID(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -5738,12 +5653,12 @@ func (ec *executionContext) _CreateTimelineItem_messageIsEmpty(ctx context.Conte } return graphql.Null } - res := resTmp.(bool) + res := resTmp.(string) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _CreateTimelineItem_files(ctx context.Context, field graphql.CollectedField, obj *bug.CreateTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _CreateOperation_author(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5751,16 +5666,16 @@ func (ec *executionContext) _CreateTimelineItem_files(ctx context.Context, field } }() fc := &graphql.FieldContext{ - Object: "CreateTimelineItem", + Object: "CreateOperation", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Files, nil + return ec.resolvers.CreateOperation().Author(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -5772,12 +5687,12 @@ func (ec *executionContext) _CreateTimelineItem_files(ctx context.Context, field } return graphql.Null } - res := resTmp.([]repository.Hash) + res := resTmp.(models.IdentityWrapper) fc.Result = res - return ec.marshalNHash2ᚕgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋrepositoryᚐHashᚄ(ctx, field.Selections, res) + return ec.marshalNIdentity2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋapiᚋgraphqlᚋmodelsᚐIdentityWrapper(ctx, field.Selections, res) } -func (ec *executionContext) _CreateTimelineItem_createdAt(ctx context.Context, field graphql.CollectedField, obj *bug.CreateTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _CreateOperation_date(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5785,7 +5700,7 @@ func (ec *executionContext) _CreateTimelineItem_createdAt(ctx context.Context, f } }() fc := &graphql.FieldContext{ - Object: "CreateTimelineItem", + Object: "CreateOperation", Field: field, Args: nil, IsMethod: true, @@ -5794,7 +5709,7 @@ func (ec *executionContext) _CreateTimelineItem_createdAt(ctx context.Context, f ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.CreateTimelineItem().CreatedAt(rctx, obj) + return ec.resolvers.CreateOperation().Date(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -5811,7 +5726,7 @@ func (ec *executionContext) _CreateTimelineItem_createdAt(ctx context.Context, f return ec.marshalNTime2ᚖtimeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _CreateTimelineItem_lastEdit(ctx context.Context, field graphql.CollectedField, obj *bug.CreateTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _CreateOperation_title(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5819,16 +5734,16 @@ func (ec *executionContext) _CreateTimelineItem_lastEdit(ctx context.Context, fi } }() fc := &graphql.FieldContext{ - Object: "CreateTimelineItem", + Object: "CreateOperation", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.CreateTimelineItem().LastEdit(rctx, obj) + return obj.Title, nil }) if err != nil { ec.Error(ctx, err) @@ -5840,12 +5755,12 @@ func (ec *executionContext) _CreateTimelineItem_lastEdit(ctx context.Context, fi } return graphql.Null } - res := resTmp.(*time.Time) + res := resTmp.(string) fc.Result = res - return ec.marshalNTime2ᚖtimeᚐTime(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _CreateTimelineItem_edited(ctx context.Context, field graphql.CollectedField, obj *bug.CreateTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _CreateOperation_message(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5853,16 +5768,16 @@ func (ec *executionContext) _CreateTimelineItem_edited(ctx context.Context, fiel } }() fc := &graphql.FieldContext{ - Object: "CreateTimelineItem", + Object: "CreateOperation", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Edited(), nil + return obj.Message, nil }) if err != nil { ec.Error(ctx, err) @@ -5874,12 +5789,12 @@ func (ec *executionContext) _CreateTimelineItem_edited(ctx context.Context, fiel } return graphql.Null } - res := resTmp.(bool) + res := resTmp.(string) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _CreateTimelineItem_history(ctx context.Context, field graphql.CollectedField, obj *bug.CreateTimelineItem) (ret graphql.Marshaler) { +func (ec *executionContext) _CreateOperation_files(ctx context.Context, field graphql.CollectedField, obj *bug.CreateOperation) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -5887,7 +5802,7 @@ func (ec *executionContext) _CreateTimelineItem_history(ctx context.Context, fie } }() fc := &graphql.FieldContext{ - Object: "CreateTimelineItem", + Object: "CreateOperation", Field: field, Args: nil, IsMethod: false, @@ -5896,7 +5811,7 @@ func (ec *executionContext) _CreateTimelineItem_history(ctx context.Context, fie ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.History, nil + return obj.Files, nil }) if err != nil { ec.Error(ctx, err) @@ -5908,9 +5823,9 @@ func (ec *executionContext) _CreateTimelineItem_history(ctx context.Context, fie } return graphql.Null } - res := resTmp.([]bug.CommentHistoryStep) + res := resTmp.([]repository.Hash) fc.Result = res - return ec.marshalNCommentHistoryStep2ᚕgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐCommentHistoryStepᚄ(ctx, field.Selections, res) + return ec.marshalNHash2ᚕgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋrepositoryᚐHashᚄ(ctx, field.Selections, res) } func (ec *executionContext) _EditCommentOperation_id(ctx context.Context, field graphql.CollectedField, obj *bug.EditCommentOperation) (ret graphql.Marshaler) { @@ -10967,18 +10882,18 @@ func (ec *executionContext) _Authored(ctx context.Context, sel ast.SelectionSet, switch obj := (obj).(type) { case nil: return graphql.Null - case bug.Comment: - return ec._Comment(ctx, sel, &obj) - case *bug.Comment: + case models.BugWrapper: if obj == nil { return graphql.Null } - return ec._Comment(ctx, sel, obj) - case models.BugWrapper: + return ec._Bug(ctx, sel, obj) + case commentary.Comment: + return ec._Comment(ctx, sel, &obj) + case *commentary.Comment: if obj == nil { return graphql.Null } - return ec._Bug(ctx, sel, obj) + return ec._Comment(ctx, sel, obj) case *bug.CreateOperation: if obj == nil { return graphql.Null @@ -11009,16 +10924,11 @@ func (ec *executionContext) _Authored(ctx context.Context, sel ast.SelectionSet, return graphql.Null } return ec._LabelChangeOperation(ctx, sel, obj) - case *bug.CreateTimelineItem: + case *bug.CommentTimelineItem: if obj == nil { return graphql.Null } - return ec._CreateTimelineItem(ctx, sel, obj) - case *bug.AddCommentTimelineItem: - if obj == nil { - return graphql.Null - } - return ec._AddCommentTimelineItem(ctx, sel, obj) + return ec._CommentTimelineItem(ctx, sel, obj) case *bug.LabelChangeTimelineItem: if obj == nil { return graphql.Null @@ -11082,32 +10992,21 @@ func (ec *executionContext) _TimelineItem(ctx context.Context, sel ast.Selection switch obj := (obj).(type) { case nil: return graphql.Null - case *bug.CreateTimelineItem: - if obj == nil { - return graphql.Null - } - return ec._CreateTimelineItem(ctx, sel, obj) - case *bug.AddCommentTimelineItem: + case *bug.CommentTimelineItem: if obj == nil { return graphql.Null } - return ec._AddCommentTimelineItem(ctx, sel, obj) - case bug.LabelChangeTimelineItem: - return ec._LabelChangeTimelineItem(ctx, sel, &obj) + return ec._CommentTimelineItem(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 @@ -11308,75 +11207,23 @@ func (ec *executionContext) _AddCommentPayload(ctx context.Context, sel ast.Sele return out } -var addCommentTimelineItemImplementors = []string{"AddCommentTimelineItem", "TimelineItem", "Authored"} +var alterationImplementors = []string{"Alteration"} -func (ec *executionContext) _AddCommentTimelineItem(ctx context.Context, sel ast.SelectionSet, obj *bug.AddCommentTimelineItem) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, addCommentTimelineItemImplementors) +func (ec *executionContext) _Alteration(ctx context.Context, sel ast.SelectionSet, obj *commentary.Alteration) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, alterationImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("AddCommentTimelineItem") - case "id": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._AddCommentTimelineItem_id(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) - case "author": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._AddCommentTimelineItem_author(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) + out.Values[i] = graphql.MarshalString("Alteration") case "message": - out.Values[i] = ec._AddCommentTimelineItem_message(ctx, field, obj) + out.Values[i] = ec._Alteration_message(ctx, field, obj) if out.Values[i] == graphql.Null { atomic.AddUint32(&invalids, 1) } - case "messageIsEmpty": - out.Values[i] = ec._AddCommentTimelineItem_messageIsEmpty(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "files": - out.Values[i] = ec._AddCommentTimelineItem_files(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "createdAt": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._AddCommentTimelineItem_createdAt(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) - case "lastEdit": + case "date": field := field out.Concurrently(i, func() (res graphql.Marshaler) { defer func() { @@ -11384,22 +11231,12 @@ func (ec *executionContext) _AddCommentTimelineItem(ctx context.Context, sel ast ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._AddCommentTimelineItem_lastEdit(ctx, field, obj) + res = ec._Alteration_date(ctx, field, obj) if res == graphql.Null { atomic.AddUint32(&invalids, 1) } return res }) - case "edited": - out.Values[i] = ec._AddCommentTimelineItem_edited(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "history": - out.Values[i] = ec._AddCommentTimelineItem_history(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -11469,16 +11306,30 @@ func (ec *executionContext) _Bug(ctx context.Context, sel ast.SelectionSet, obj if out.Values[i] == graphql.Null { atomic.AddUint32(&invalids, 1) } - case "labels": - out.Values[i] = ec._Bug_labels(ctx, field, obj) + case "description": + out.Values[i] = ec._Bug_description(ctx, field, obj) if out.Values[i] == graphql.Null { atomic.AddUint32(&invalids, 1) } - case "author": - out.Values[i] = ec._Bug_author(ctx, field, obj) + case "labels": + out.Values[i] = ec._Bug_labels(ctx, field, obj) if out.Values[i] == graphql.Null { atomic.AddUint32(&invalids, 1) } + case "author": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Bug_author(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) case "createdAt": out.Values[i] = ec._Bug_createdAt(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -11783,7 +11634,7 @@ func (ec *executionContext) _Color(ctx context.Context, sel ast.SelectionSet, ob var commentImplementors = []string{"Comment", "Authored"} -func (ec *executionContext) _Comment(ctx context.Context, sel ast.SelectionSet, obj *bug.Comment) graphql.Marshaler { +func (ec *executionContext) _Comment(ctx context.Context, sel ast.SelectionSet, obj *commentary.Comment) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, commentImplementors) out := graphql.NewFieldSet(fields) @@ -11792,6 +11643,20 @@ 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 + out.Concurrently(i, func() (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 + }) case "author": field := field out.Concurrently(i, func() (res graphql.Marshaler) { @@ -11811,11 +11676,54 @@ func (ec *executionContext) _Comment(ctx context.Context, sel ast.SelectionSet, if out.Values[i] == graphql.Null { atomic.AddUint32(&invalids, 1) } + case "hasEmptyMessage": + out.Values[i] = ec._Comment_hasEmptyMessage(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + case "wasEdited": + out.Values[i] = ec._Comment_wasEdited(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } case "files": out.Values[i] = ec._Comment_files(ctx, field, obj) if out.Values[i] == graphql.Null { atomic.AddUint32(&invalids, 1) } + case "createdAt": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Comment_createdAt(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "lastEdited": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Comment_lastEdited(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "history": + out.Values[i] = ec._Comment_history(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -11901,23 +11809,46 @@ func (ec *executionContext) _CommentEdge(ctx context.Context, sel ast.SelectionS return out } -var commentHistoryStepImplementors = []string{"CommentHistoryStep"} +var commentTimelineItemImplementors = []string{"CommentTimelineItem", "TimelineItem", "Authored"} -func (ec *executionContext) _CommentHistoryStep(ctx context.Context, sel ast.SelectionSet, obj *bug.CommentHistoryStep) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, commentHistoryStepImplementors) +func (ec *executionContext) _CommentTimelineItem(ctx context.Context, sel ast.SelectionSet, obj *bug.CommentTimelineItem) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, commentTimelineItemImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("CommentHistoryStep") + out.Values[i] = graphql.MarshalString("CommentTimelineItem") + case "id": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._CommentTimelineItem_id(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "author": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._CommentTimelineItem_author(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) case "message": - out.Values[i] = ec._CommentHistoryStep_message(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "date": field := field out.Concurrently(i, func() (res graphql.Marshaler) { defer func() { @@ -11925,35 +11856,13 @@ func (ec *executionContext) _CommentHistoryStep(ctx context.Context, sel ast.Sel ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._CommentHistoryStep_date(ctx, field, obj) + res = ec._CommentTimelineItem_message(ctx, field, obj) if res == graphql.Null { atomic.AddUint32(&invalids, 1) } return res }) - default: - panic("unknown field " + strconv.Quote(field.Name)) - } - } - out.Dispatch() - if invalids > 0 { - return graphql.Null - } - return out -} - -var createOperationImplementors = []string{"CreateOperation", "Operation", "Authored"} - -func (ec *executionContext) _CreateOperation(ctx context.Context, sel ast.SelectionSet, obj *bug.CreateOperation) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, createOperationImplementors) - - out := graphql.NewFieldSet(fields) - var invalids uint32 - for i, field := range fields { - switch field.Name { - case "__typename": - out.Values[i] = graphql.MarshalString("CreateOperation") - case "id": + case "hasEmptyMessage": field := field out.Concurrently(i, func() (res graphql.Marshaler) { defer func() { @@ -11961,13 +11870,13 @@ func (ec *executionContext) _CreateOperation(ctx context.Context, sel ast.Select ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._CreateOperation_id(ctx, field, obj) + res = ec._CommentTimelineItem_hasEmptyMessage(ctx, field, obj) if res == graphql.Null { atomic.AddUint32(&invalids, 1) } return res }) - case "author": + case "files": field := field out.Concurrently(i, func() (res graphql.Marshaler) { defer func() { @@ -11975,13 +11884,13 @@ func (ec *executionContext) _CreateOperation(ctx context.Context, sel ast.Select ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._CreateOperation_author(ctx, field, obj) + res = ec._CommentTimelineItem_files(ctx, field, obj) if res == graphql.Null { atomic.AddUint32(&invalids, 1) } return res }) - case "date": + case "createdAt": field := field out.Concurrently(i, func() (res graphql.Marshaler) { defer func() { @@ -11989,27 +11898,54 @@ func (ec *executionContext) _CreateOperation(ctx context.Context, sel ast.Select ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._CreateOperation_date(ctx, field, obj) + res = ec._CommentTimelineItem_createdAt(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "lastEdited": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._CommentTimelineItem_lastEdited(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "wasEdited": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._CommentTimelineItem_wasEdited(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "history": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._CommentTimelineItem_history(ctx, field, obj) if res == graphql.Null { atomic.AddUint32(&invalids, 1) } return res }) - case "title": - out.Values[i] = ec._CreateOperation_title(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "message": - out.Values[i] = ec._CreateOperation_message(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "files": - out.Values[i] = ec._CreateOperation_files(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -12021,17 +11957,17 @@ func (ec *executionContext) _CreateOperation(ctx context.Context, sel ast.Select return out } -var createTimelineItemImplementors = []string{"CreateTimelineItem", "TimelineItem", "Authored"} +var createOperationImplementors = []string{"CreateOperation", "Operation", "Authored"} -func (ec *executionContext) _CreateTimelineItem(ctx context.Context, sel ast.SelectionSet, obj *bug.CreateTimelineItem) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, createTimelineItemImplementors) +func (ec *executionContext) _CreateOperation(ctx context.Context, sel ast.SelectionSet, obj *bug.CreateOperation) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, createOperationImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("CreateTimelineItem") + out.Values[i] = graphql.MarshalString("CreateOperation") case "id": field := field out.Concurrently(i, func() (res graphql.Marshaler) { @@ -12040,7 +11976,7 @@ func (ec *executionContext) _CreateTimelineItem(ctx context.Context, sel ast.Sel ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._CreateTimelineItem_id(ctx, field, obj) + res = ec._CreateOperation_id(ctx, field, obj) if res == graphql.Null { atomic.AddUint32(&invalids, 1) } @@ -12054,42 +11990,13 @@ func (ec *executionContext) _CreateTimelineItem(ctx context.Context, sel ast.Sel ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._CreateTimelineItem_author(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - }) - case "message": - out.Values[i] = ec._CreateTimelineItem_message(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "messageIsEmpty": - out.Values[i] = ec._CreateTimelineItem_messageIsEmpty(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "files": - out.Values[i] = ec._CreateTimelineItem_files(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "createdAt": - field := field - out.Concurrently(i, func() (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._CreateTimelineItem_createdAt(ctx, field, obj) + res = ec._CreateOperation_author(ctx, field, obj) if res == graphql.Null { atomic.AddUint32(&invalids, 1) } return res }) - case "lastEdit": + case "date": field := field out.Concurrently(i, func() (res graphql.Marshaler) { defer func() { @@ -12097,19 +12004,24 @@ func (ec *executionContext) _CreateTimelineItem(ctx context.Context, sel ast.Sel ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._CreateTimelineItem_lastEdit(ctx, field, obj) + res = ec._CreateOperation_date(ctx, field, obj) if res == graphql.Null { atomic.AddUint32(&invalids, 1) } return res }) - case "edited": - out.Values[i] = ec._CreateTimelineItem_edited(ctx, field, obj) + case "title": + out.Values[i] = ec._CreateOperation_title(ctx, field, obj) if out.Values[i] == graphql.Null { atomic.AddUint32(&invalids, 1) } - case "history": - out.Values[i] = ec._CreateTimelineItem_history(ctx, field, obj) + case "message": + out.Values[i] = ec._CreateOperation_message(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + case "files": + out.Values[i] = ec._CreateOperation_files(ctx, field, obj) if out.Values[i] == graphql.Null { atomic.AddUint32(&invalids, 1) } @@ -13830,6 +13742,94 @@ func (ec *executionContext) marshalNAddCommentPayload2ᚖgithubᚗcomᚋMichaelM return ec._AddCommentPayload(ctx, sel, v) } +func (ec *executionContext) marshalNAlteration2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋcommentaryᚐAlteration(ctx context.Context, sel ast.SelectionSet, v commentary.Alteration) graphql.Marshaler { + return ec._Alteration(ctx, sel, &v) +} + +func (ec *executionContext) marshalNAlteration2ᚕgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋcommentaryᚐAlterationᚄ(ctx context.Context, sel ast.SelectionSet, v []commentary.Alteration) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNAlteration2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋcommentaryᚐAlteration(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) marshalNAlteration2ᚕᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋcommentaryᚐAlterationᚄ(ctx context.Context, sel ast.SelectionSet, v []*commentary.Alteration) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNAlteration2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋcommentaryᚐAlteration(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + return ret +} + +func (ec *executionContext) marshalNAlteration2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋcommentaryᚐAlteration(ctx context.Context, sel ast.SelectionSet, v *commentary.Alteration) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._Alteration(ctx, sel, v) +} + func (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v interface{}) (bool, error) { return graphql.UnmarshalBoolean(v) } @@ -14002,11 +14002,11 @@ func (ec *executionContext) marshalNColor2ᚖimageᚋcolorᚐRGBA(ctx context.Co return ec._Color(ctx, sel, v) } -func (ec *executionContext) marshalNComment2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐComment(ctx context.Context, sel ast.SelectionSet, v bug.Comment) graphql.Marshaler { +func (ec *executionContext) marshalNComment2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋcommentaryᚐComment(ctx context.Context, sel ast.SelectionSet, v commentary.Comment) graphql.Marshaler { return ec._Comment(ctx, sel, &v) } -func (ec *executionContext) marshalNComment2ᚕᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐCommentᚄ(ctx context.Context, sel ast.SelectionSet, v []*bug.Comment) graphql.Marshaler { +func (ec *executionContext) marshalNComment2ᚕᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋcommentaryᚐCommentᚄ(ctx context.Context, sel ast.SelectionSet, v []*commentary.Comment) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup isLen1 := len(v) == 1 @@ -14030,7 +14030,7 @@ func (ec *executionContext) marshalNComment2ᚕᚖgithubᚗcomᚋMichaelMureᚋg if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalNComment2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐComment(ctx, sel, v[i]) + ret[i] = ec.marshalNComment2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋcommentaryᚐComment(ctx, sel, v[i]) } if isLen1 { f(i) @@ -14043,7 +14043,7 @@ func (ec *executionContext) marshalNComment2ᚕᚖgithubᚗcomᚋMichaelMureᚋg return ret } -func (ec *executionContext) marshalNComment2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐComment(ctx context.Context, sel ast.SelectionSet, v *bug.Comment) graphql.Marshaler { +func (ec *executionContext) marshalNComment2ᚖgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋcommentaryᚐComment(ctx context.Context, sel ast.SelectionSet, v *commentary.Comment) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") @@ -14118,47 +14118,6 @@ func (ec *executionContext) marshalNCommentEdge2ᚖgithubᚗcomᚋMichaelMureᚋ return ec._CommentEdge(ctx, sel, v) } -func (ec *executionContext) marshalNCommentHistoryStep2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐCommentHistoryStep(ctx context.Context, sel ast.SelectionSet, v bug.CommentHistoryStep) graphql.Marshaler { - return ec._CommentHistoryStep(ctx, sel, &v) -} - -func (ec *executionContext) marshalNCommentHistoryStep2ᚕgithubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐCommentHistoryStepᚄ(ctx context.Context, sel ast.SelectionSet, v []bug.CommentHistoryStep) graphql.Marshaler { - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - fc := &graphql.FieldContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithFieldContext(ctx, fc) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalNCommentHistoryStep2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐCommentHistoryStep(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - return ret -} - func (ec *executionContext) marshalNCreateOperation2githubᚗcomᚋMichaelMureᚋgitᚑbugᚋbugᚐCreateOperation(ctx context.Context, sel ast.SelectionSet, v bug.CreateOperation) graphql.Marshaler { return ec._CreateOperation(ctx, sel, &v) } diff --git a/api/graphql/graphql_test.go b/api/graphql/graphql_test.go index 69d96cab7..7b04e172b 100644 --- a/api/graphql/graphql_test.go +++ b/api/graphql/graphql_test.go @@ -43,13 +43,22 @@ func TestQueries(t *testing.T) { email avatarUrl } - + createdAt humanId id lastEdit status title + description { + author { + name + email + avatarUrl + } + message + files + } actors(first: 10) { pageInfo { @@ -80,7 +89,7 @@ func TestQueries(t *testing.T) { displayName } } - + comments(first: 2) { pageInfo { endCursor @@ -93,7 +102,7 @@ func TestQueries(t *testing.T) { message } } - + operations(first: 20) { pageInfo { endCursor @@ -178,6 +187,12 @@ func TestQueries(t *testing.T) { Status string Title string + Description struct { + Author Identity + Message string + Files []string + } + Actors struct { PageInfo models.PageInfo Nodes []Identity diff --git a/api/graphql/models/gen_models.go b/api/graphql/models/gen_models.go index 203d64510..80260a4cb 100644 --- a/api/graphql/models/gen_models.go +++ b/api/graphql/models/gen_models.go @@ -8,6 +8,7 @@ import ( "strconv" "github.com/MichaelMure/git-bug/bug" + "github.com/MichaelMure/git-bug/commentary" "github.com/MichaelMure/git-bug/repository" ) @@ -148,15 +149,15 @@ type CloseBugPayload struct { } type CommentConnection struct { - Edges []*CommentEdge `json:"edges"` - Nodes []*bug.Comment `json:"nodes"` - PageInfo *PageInfo `json:"pageInfo"` - TotalCount int `json:"totalCount"` + Edges []*CommentEdge `json:"edges"` + Nodes []*commentary.Comment `json:"nodes"` + PageInfo *PageInfo `json:"pageInfo"` + TotalCount int `json:"totalCount"` } type CommentEdge struct { - Cursor string `json:"cursor"` - Node *bug.Comment `json:"node"` + Cursor string `json:"cursor"` + Node *commentary.Comment `json:"node"` } type EditCommentInput struct { diff --git a/api/graphql/models/lazy_bug.go b/api/graphql/models/lazy_bug.go index a7840df28..81fc0af28 100644 --- a/api/graphql/models/lazy_bug.go +++ b/api/graphql/models/lazy_bug.go @@ -6,6 +6,7 @@ import ( "github.com/MichaelMure/git-bug/bug" "github.com/MichaelMure/git-bug/cache" + "github.com/MichaelMure/git-bug/commentary" "github.com/MichaelMure/git-bug/entity" ) @@ -17,11 +18,12 @@ type BugWrapper interface { LastEdit() time.Time Status() bug.Status Title() string - Comments() ([]bug.Comment, error) + Description() (*commentary.Comment, error) + Comments() ([]commentary.Comment, error) Labels() []bug.Label - Author() (IdentityWrapper, error) - Actors() ([]IdentityWrapper, error) - Participants() ([]IdentityWrapper, error) + Author() entity.Id + Actors() []entity.Id + Participants() []entity.Id CreatedAt() time.Time Timeline() ([]bug.TimelineItem, error) Operations() ([]bug.Operation, error) @@ -92,44 +94,37 @@ func (lb *lazyBug) Title() string { return lb.excerpt.Title } -func (lb *lazyBug) Comments() ([]bug.Comment, error) { +func (lb *lazyBug) Description() (*commentary.Comment, error) { err := lb.load() if err != nil { return nil, err } - return lb.snap.Comments, nil + desc := lb.snap.Description() + return &desc, nil +} + +func (lb *lazyBug) Comments() ([]commentary.Comment, error) { + err := lb.load() + if err != nil { + return nil, err + } + return lb.snap.Comments(), nil } func (lb *lazyBug) Labels() []bug.Label { return lb.excerpt.Labels } -func (lb *lazyBug) Author() (IdentityWrapper, error) { - return lb.identity(lb.excerpt.AuthorId) +func (lb *lazyBug) Author() entity.Id { + return lb.excerpt.AuthorId } -func (lb *lazyBug) Actors() ([]IdentityWrapper, error) { - result := make([]IdentityWrapper, len(lb.excerpt.Actors)) - for i, actorId := range lb.excerpt.Actors { - actor, err := lb.identity(actorId) - if err != nil { - return nil, err - } - result[i] = actor - } - return result, nil +func (lb *lazyBug) Actors() []entity.Id { + return lb.excerpt.Actors } -func (lb *lazyBug) Participants() ([]IdentityWrapper, error) { - result := make([]IdentityWrapper, len(lb.excerpt.Participants)) - for i, participantId := range lb.excerpt.Participants { - participant, err := lb.identity(participantId) - if err != nil { - return nil, err - } - result[i] = participant - } - return result, nil +func (lb *lazyBug) Participants() []entity.Id { + return lb.excerpt.Participants } func (lb *lazyBug) CreatedAt() time.Time { @@ -141,7 +136,7 @@ func (lb *lazyBug) Timeline() ([]bug.TimelineItem, error) { if err != nil { return nil, err } - return lb.snap.Timeline, nil + return lb.snap.Timeline(), nil } func (lb *lazyBug) Operations() ([]bug.Operation, error) { @@ -167,39 +162,36 @@ func (l *loadedBug) LastEdit() time.Time { } func (l *loadedBug) Status() bug.Status { - return l.Snapshot.Status + return l.Snapshot.Status() } func (l *loadedBug) Title() string { - return l.Snapshot.Title + return l.Snapshot.Title() +} + +func (l *loadedBug) Description() (*commentary.Comment, error) { + desc := l.Snapshot.Description() + return &desc, nil } -func (l *loadedBug) Comments() ([]bug.Comment, error) { - return l.Snapshot.Comments, nil +func (l *loadedBug) Comments() ([]commentary.Comment, error) { + return l.Snapshot.Comments(), nil } func (l *loadedBug) Labels() []bug.Label { - return l.Snapshot.Labels + return l.Snapshot.Labels() } -func (l *loadedBug) Author() (IdentityWrapper, error) { - return NewLoadedIdentity(l.Snapshot.Author), nil +func (l *loadedBug) Author() entity.Id { + return l.Snapshot.Author() } -func (l *loadedBug) Actors() ([]IdentityWrapper, error) { - res := make([]IdentityWrapper, len(l.Snapshot.Actors)) - for i, actor := range l.Snapshot.Actors { - res[i] = NewLoadedIdentity(actor) - } - return res, nil +func (l *loadedBug) Actors() []entity.Id { + return l.Snapshot.Actors() } -func (l *loadedBug) Participants() ([]IdentityWrapper, error) { - res := make([]IdentityWrapper, len(l.Snapshot.Participants)) - for i, participant := range l.Snapshot.Participants { - res[i] = NewLoadedIdentity(participant) - } - return res, nil +func (l *loadedBug) Participants() []entity.Id { + return l.Snapshot.Participants() } func (l *loadedBug) CreatedAt() time.Time { @@ -207,7 +199,7 @@ func (l *loadedBug) CreatedAt() time.Time { } func (l *loadedBug) Timeline() ([]bug.TimelineItem, error) { - return l.Snapshot.Timeline, nil + return l.Snapshot.Timeline(), nil } func (l *loadedBug) Operations() ([]bug.Operation, error) { diff --git a/api/graphql/resolvers/bug.go b/api/graphql/resolvers/bug.go index 815cba8d4..2b089e640 100644 --- a/api/graphql/resolvers/bug.go +++ b/api/graphql/resolvers/bug.go @@ -7,11 +7,32 @@ import ( "github.com/MichaelMure/git-bug/api/graphql/graph" "github.com/MichaelMure/git-bug/api/graphql/models" "github.com/MichaelMure/git-bug/bug" + "github.com/MichaelMure/git-bug/commentary" + "github.com/MichaelMure/git-bug/entity" ) var _ graph.BugResolver = &bugResolver{} -type bugResolver struct{} +type bugResolver struct { + identityResolver +} + +// resolveIdentity is a helper function to call the identityResolver +func (r bugResolver) resolveIdentity(id entity.Id) (models.IdentityWrapper, error) { + return r.identityResolver.resolveIdentity(id) +} + +func (r bugResolver) resolveAllIdentities(ids []entity.Id) ([]models.IdentityWrapper, error) { + result := make([]models.IdentityWrapper, len(ids)) + for i, id := range ids { + identity, err := r.resolveIdentity(id) + if err != nil { + return nil, err + } + result[i] = identity + } + return result, nil +} func (bugResolver) ID(_ context.Context, obj models.BugWrapper) (string, error) { return obj.Id().String(), nil @@ -21,6 +42,10 @@ func (bugResolver) HumanID(_ context.Context, obj models.BugWrapper) (string, er return obj.Id().Human(), nil } +func (r bugResolver) Author(_ context.Context, obj models.BugWrapper) (models.IdentityWrapper, error) { + return r.resolveIdentity(obj.Author()) +} + func (bugResolver) Status(_ context.Context, obj models.BugWrapper) (models.Status, error) { return convertStatus(obj.Status()) } @@ -33,15 +58,15 @@ func (bugResolver) Comments(_ context.Context, obj models.BugWrapper, after *str Last: last, } - edger := func(comment bug.Comment, offset int) connections.Edge { + edger := func(comment commentary.Comment, offset int) connections.Edge { return models.CommentEdge{ Node: &comment, Cursor: connections.OffsetToCursor(offset), } } - conMaker := func(edges []*models.CommentEdge, nodes []bug.Comment, info *models.PageInfo, totalCount int) (*models.CommentConnection, error) { - var commentNodes []*bug.Comment + conMaker := func(edges []*models.CommentEdge, nodes []commentary.Comment, info *models.PageInfo, totalCount int) (*models.CommentConnection, error) { + var commentNodes []*commentary.Comment for _, c := range nodes { commentNodes = append(commentNodes, &c) } @@ -125,7 +150,7 @@ func (bugResolver) Timeline(_ context.Context, obj models.BugWrapper, after *str return connections.TimelineItemCon(timeline, edger, conMaker, input) } -func (bugResolver) Actors(_ context.Context, obj models.BugWrapper, after *string, before *string, first *int, last *int) (*models.IdentityConnection, error) { +func (r bugResolver) Actors(_ context.Context, obj models.BugWrapper, after *string, before *string, first *int, last *int) (*models.IdentityConnection, error) { input := models.ConnectionInput{ Before: before, After: after, @@ -149,7 +174,7 @@ func (bugResolver) Actors(_ context.Context, obj models.BugWrapper, after *strin }, nil } - actors, err := obj.Actors() + actors, err := r.resolveAllIdentities(obj.Actors()) if err != nil { return nil, err } @@ -157,7 +182,7 @@ func (bugResolver) Actors(_ context.Context, obj models.BugWrapper, after *strin return connections.IdentityCon(actors, edger, conMaker, input) } -func (bugResolver) Participants(_ context.Context, obj models.BugWrapper, after *string, before *string, first *int, last *int) (*models.IdentityConnection, error) { +func (r bugResolver) Participants(_ context.Context, obj models.BugWrapper, after *string, before *string, first *int, last *int) (*models.IdentityConnection, error) { input := models.ConnectionInput{ Before: before, After: after, @@ -181,7 +206,7 @@ func (bugResolver) Participants(_ context.Context, obj models.BugWrapper, after }, nil } - participants, err := obj.Participants() + participants, err := r.resolveAllIdentities(obj.Participants()) if err != nil { return nil, err } diff --git a/api/graphql/resolvers/comment.go b/api/graphql/resolvers/comment.go index 5206e8a79..fbc1a1485 100644 --- a/api/graphql/resolvers/comment.go +++ b/api/graphql/resolvers/comment.go @@ -2,16 +2,120 @@ package resolvers import ( "context" + "time" "github.com/MichaelMure/git-bug/api/graphql/graph" "github.com/MichaelMure/git-bug/api/graphql/models" - "github.com/MichaelMure/git-bug/bug" + "github.com/MichaelMure/git-bug/cache" + "github.com/MichaelMure/git-bug/commentary" + "github.com/MichaelMure/git-bug/entity" + "github.com/MichaelMure/git-bug/repository" ) +var _ graph.AlterationResolver = alterationResolver{} + +type alterationResolver struct{} + +func (alterationResolver) Date(_ context.Context, obj *commentary.Alteration) (*time.Time, error) { + t := obj.CreatedAt.Time() + return &t, nil +} + var _ graph.CommentResolver = &commentResolver{} -type commentResolver struct{} +type commentResolver struct { + cache *cache.MultiRepoCache +} + +// getComment is a helper function to fetch a comment with the given Id from +// the repository. +func (r commentResolver) getComment(id entity.Id) (*commentary.Comment, error) { + var repo, err = r.cache.DefaultRepo() + if err != nil { + return nil, err + } + + bug, commentId, err := repo.ResolveComment(id.String()) + if err != nil { + return nil, err + } + return bug.Snapshot().SearchComment(commentId) +} + +func (commentResolver) ID(_ context.Context, obj *commentary.Comment) (string, error) { + return obj.Id().String(), nil +} + +func (r commentResolver) Author(_ context.Context, obj *commentary.Comment) (models.IdentityWrapper, error) { + comment, err := r.getComment(obj.Id()) + if err != nil { + return nil, err + } + return models.NewLoadedIdentity(comment.Author()), nil +} + +func (r commentResolver) CreatedAt(_ context.Context, obj *commentary.Comment) (*time.Time, error) { + comment, err := r.getComment(obj.Id()) + if err != nil { + return nil, err + } + t := comment.CreatedAt().Time() + return &t, nil +} + +func (r commentResolver) LastEdited(_ context.Context, obj *commentary.Comment) (*time.Time, error) { + comment, err := r.getComment(obj.Id()) + if err != nil { + return nil, err + } + t := comment.LastEdited().Time() + return &t, nil +} + +func (r commentResolver) WasEdited(_ context.Context, obj *commentary.Comment) (bool, error) { + comment, err := r.getComment(obj.Id()) + if err != nil { + return false, err + } + return comment.WasEdited(), nil +} + +func (r commentResolver) Message(_ context.Context, obj *commentary.Comment) (string, error) { + comment, err := r.getComment(obj.Id()) + if err != nil { + return "", err + } + return comment.Message(), nil +} + +func (r commentResolver) HasEmptyMessage(_ context.Context, obj *commentary.Comment) (bool, error) { + comment, err := r.getComment(obj.Id()) + if err != nil { + return false, err + } + return comment.HasEmptyMessage(), nil +} + +func (r commentResolver) Files(_ context.Context, obj *commentary.Comment) ([]repository.Hash, error) { + comment, err := r.getComment(obj.Id()) + if err != nil { + return nil, err + } + return comment.Files(), nil +} -func (c commentResolver) Author(_ context.Context, obj *bug.Comment) (models.IdentityWrapper, error) { - return models.NewLoadedIdentity(obj.Author), nil +func (r commentResolver) History(_ context.Context, obj *commentary.Comment) ([]*commentary.Alteration, error) { + comment, err := r.getComment(obj.Id()) + if err != nil { + return nil, err + } + // NOTE have to convert the comment history of type []Alteration + // to type of []*Alteration. This is due to the gqlgen generated + // the code, which expects a slice of pointers as return. Don't know how + // to fix this otherwise *sigh* + history := make([]*commentary.Alteration, len(comment.History())) + for edit := range comment.History() { + history[edit] = &comment.History()[edit] + } + return history, nil } diff --git a/api/graphql/resolvers/identity.go b/api/graphql/resolvers/identity.go index 69a32c98c..534f69d79 100644 --- a/api/graphql/resolvers/identity.go +++ b/api/graphql/resolvers/identity.go @@ -5,11 +5,40 @@ import ( "github.com/MichaelMure/git-bug/api/graphql/graph" "github.com/MichaelMure/git-bug/api/graphql/models" + "github.com/MichaelMure/git-bug/cache" + "github.com/MichaelMure/git-bug/entity" ) var _ graph.IdentityResolver = &identityResolver{} -type identityResolver struct{} +type identityResolver struct { + cache *cache.MultiRepoCache +} + +func (r identityResolver) resolveIdentity(id entity.Id) (models.IdentityWrapper, error) { + var repo, err = r.cache.DefaultRepo() + if err != nil { + return nil, err + } + + excerpt, err := repo.ResolveIdentityExcerpt(id) + if err != nil { + return nil, err + } + + return models.NewLazyIdentity(repo, excerpt), nil + + //var repo, err = r.cache.DefaultRepo() + //if err != nil { + // return nil, err + //} + + //identity, err := repo.ResolveIdentity(id) + //if err != nil { + // return nil, err + //} + //return models.NewLoadedIdentity(identity.Identity), nil +} func (identityResolver) ID(ctx context.Context, obj models.IdentityWrapper) (string, error) { return obj.Id().String(), nil diff --git a/api/graphql/resolvers/root.go b/api/graphql/resolvers/root.go index bb3bf5cfb..134771d4c 100644 --- a/api/graphql/resolvers/root.go +++ b/api/graphql/resolvers/root.go @@ -34,8 +34,12 @@ func (RootResolver) Repository() graph.RepositoryResolver { return &repoResolver{} } -func (RootResolver) Bug() graph.BugResolver { - return &bugResolver{} +func (r RootResolver) Bug() graph.BugResolver { + return &bugResolver{ + identityResolver{ + cache: r.MultiRepoCache, + }, + } } func (RootResolver) Color() graph.ColorResolver { @@ -43,7 +47,9 @@ func (RootResolver) Color() graph.ColorResolver { } func (r RootResolver) Comment() graph.CommentResolver { - return &commentResolver{} + return &commentResolver{ + cache: r.MultiRepoCache, + } } func (RootResolver) Label() graph.LabelResolver { @@ -51,19 +57,21 @@ func (RootResolver) Label() graph.LabelResolver { } func (r RootResolver) Identity() graph.IdentityResolver { - return &identityResolver{} -} - -func (RootResolver) CommentHistoryStep() graph.CommentHistoryStepResolver { - return &commentHistoryStepResolver{} + return &identityResolver{ + cache: r.MultiRepoCache, + } } -func (RootResolver) AddCommentTimelineItem() graph.AddCommentTimelineItemResolver { - return &addCommentTimelineItemResolver{} +func (RootResolver) Alteration() graph.AlterationResolver { + return &alterationResolver{} } -func (RootResolver) CreateTimelineItem() graph.CreateTimelineItemResolver { - return &createTimelineItemResolver{} +func (r RootResolver) CommentTimelineItem() graph.CommentTimelineItemResolver { + return &commentTimelineItemResolver{ + commentResolver{ + cache: r.MultiRepoCache, + }, + } } func (r RootResolver) LabelChangeTimelineItem() graph.LabelChangeTimelineItemResolver { @@ -86,7 +94,7 @@ func (RootResolver) AddCommentOperation() graph.AddCommentOperationResolver { return &addCommentOperationResolver{} } -func (r RootResolver) EditCommentOperation() graph.EditCommentOperationResolver { +func (RootResolver) EditCommentOperation() graph.EditCommentOperationResolver { return &editCommentOperationResolver{} } @@ -102,6 +110,6 @@ func (RootResolver) SetTitleOperation() graph.SetTitleOperationResolver { return &setTitleOperationResolver{} } -func (r RootResolver) LabelChangeResult() graph.LabelChangeResultResolver { +func (RootResolver) LabelChangeResult() graph.LabelChangeResultResolver { return &labelChangeResultResolver{} } diff --git a/api/graphql/resolvers/timeline.go b/api/graphql/resolvers/timeline.go index 3223b3a0a..f18464662 100644 --- a/api/graphql/resolvers/timeline.go +++ b/api/graphql/resolvers/timeline.go @@ -7,59 +7,97 @@ import ( "github.com/MichaelMure/git-bug/api/graphql/graph" "github.com/MichaelMure/git-bug/api/graphql/models" "github.com/MichaelMure/git-bug/bug" + "github.com/MichaelMure/git-bug/commentary" + "github.com/MichaelMure/git-bug/entity" + "github.com/MichaelMure/git-bug/repository" ) -var _ graph.CommentHistoryStepResolver = commentHistoryStepResolver{} +var _ graph.CommentTimelineItemResolver = commentTimelineItemResolver{} -type commentHistoryStepResolver struct{} - -func (commentHistoryStepResolver) Date(_ context.Context, obj *bug.CommentHistoryStep) (*time.Time, error) { - t := obj.UnixTime.Time() - return &t, nil +type commentTimelineItemResolver struct { + commentResolver } -var _ graph.AddCommentTimelineItemResolver = addCommentTimelineItemResolver{} - -type addCommentTimelineItemResolver struct{} - -func (addCommentTimelineItemResolver) ID(_ context.Context, obj *bug.AddCommentTimelineItem) (string, error) { - return obj.Id().String(), nil +func (r commentTimelineItemResolver) getComment(id entity.Id) (*commentary.Comment, error) { + return r.commentResolver.getComment(id) } -func (addCommentTimelineItemResolver) Author(_ context.Context, obj *bug.AddCommentTimelineItem) (models.IdentityWrapper, error) { - return models.NewLoadedIdentity(obj.Author), nil +func (commentTimelineItemResolver) ID(_ context.Context, obj *bug.CommentTimelineItem) (string, error) { + return obj.Id().String(), nil } -func (addCommentTimelineItemResolver) CreatedAt(_ context.Context, obj *bug.AddCommentTimelineItem) (*time.Time, error) { - t := obj.CreatedAt.Time() - return &t, nil +func (r commentTimelineItemResolver) Author(_ context.Context, obj *bug.CommentTimelineItem) (models.IdentityWrapper, error) { + comment, err := r.getComment(obj.Id()) + if err != nil { + return nil, err + } + return models.NewLoadedIdentity(comment.Author()), nil } -func (addCommentTimelineItemResolver) LastEdit(_ context.Context, obj *bug.AddCommentTimelineItem) (*time.Time, error) { - t := obj.LastEdit.Time() +func (r commentTimelineItemResolver) CreatedAt(_ context.Context, obj *bug.CommentTimelineItem) (*time.Time, error) { + comment, err := r.getComment(obj.Id()) + if err != nil { + return nil, err + } + t := comment.CreatedAt().Time() return &t, nil } -var _ graph.CreateTimelineItemResolver = createTimelineItemResolver{} - -type createTimelineItemResolver struct{} - -func (createTimelineItemResolver) ID(_ context.Context, obj *bug.CreateTimelineItem) (string, error) { - return obj.Id().String(), nil -} - -func (r createTimelineItemResolver) Author(_ context.Context, obj *bug.CreateTimelineItem) (models.IdentityWrapper, error) { - return models.NewLoadedIdentity(obj.Author), nil -} - -func (createTimelineItemResolver) CreatedAt(_ context.Context, obj *bug.CreateTimelineItem) (*time.Time, error) { - t := obj.CreatedAt.Time() +func (r commentTimelineItemResolver) LastEdited(_ context.Context, obj *bug.CommentTimelineItem) (*time.Time, error) { + comment, err := r.getComment(obj.Id()) + if err != nil { + return nil, err + } + t := comment.LastEdited().Time() return &t, nil } -func (createTimelineItemResolver) LastEdit(_ context.Context, obj *bug.CreateTimelineItem) (*time.Time, error) { - t := obj.LastEdit.Time() - return &t, nil +func (r commentTimelineItemResolver) WasEdited(_ context.Context, obj *bug.CommentTimelineItem) (bool, error) { + comment, err := r.getComment(obj.Id()) + if err != nil { + return false, err + } + return comment.WasEdited(), nil +} + +func (r commentTimelineItemResolver) Message(_ context.Context, obj *bug.CommentTimelineItem) (string, error) { + comment, err := r.getComment(obj.Id()) + if err != nil { + return "", err + } + return comment.Message(), nil +} + +func (r commentTimelineItemResolver) HasEmptyMessage(_ context.Context, obj *bug.CommentTimelineItem) (bool, error) { + comment, err := r.getComment(obj.Id()) + if err != nil { + return false, err + } + return comment.HasEmptyMessage(), nil +} + +func (r commentTimelineItemResolver) Files(_ context.Context, obj *bug.CommentTimelineItem) ([]repository.Hash, error) { + comment, err := r.getComment(obj.Id()) + if err != nil { + return nil, err + } + return comment.Files(), nil +} + +func (r commentTimelineItemResolver) History(_ context.Context, obj *bug.CommentTimelineItem) ([]*commentary.Alteration, error) { + comment, err := r.getComment(obj.Id()) + if err != nil { + return nil, err + } + // NOTE have to convert the comment history of type []commentary.Alteration + // to type of []*commentary.Alteration. This is due to the gqlgen generated + // the code, which expects a slice of pointers as return. Don't know how + // to fix this otherwise *sigh* + history := make([]*commentary.Alteration, len(comment.History())) + for edit := range comment.History() { + history[edit] = &comment.History()[edit] + } + return history, nil } var _ graph.LabelChangeTimelineItemResolver = labelChangeTimelineItem{} diff --git a/api/graphql/schema/bug.graphql b/api/graphql/schema/bug.graphql index 03aa95b85..a9bc01872 100644 --- a/api/graphql/schema/bug.graphql +++ b/api/graphql/schema/bug.graphql @@ -1,15 +1,3 @@ -"""Represents a comment on a bug.""" -type Comment implements Authored { - """The author of this comment.""" - author: Identity! - - """The message of this comment.""" - message: String! - - """All media's hash referenced in this comment""" - files: [Hash!]! -} - type CommentConnection { edges: [CommentEdge!]! nodes: [Comment!]! @@ -34,6 +22,7 @@ type Bug implements Authored { humanId: String! status: Status! title: String! + description: Comment! labels: [Label!]! author: Identity! createdAt: Time! diff --git a/api/graphql/schema/comment.graphql b/api/graphql/schema/comment.graphql new file mode 100644 index 000000000..ee0070972 --- /dev/null +++ b/api/graphql/schema/comment.graphql @@ -0,0 +1,29 @@ +"""Alteration represents a previouse version of the comment message in the +comment history""" +type Alteration { + message: String! + date: Time! +} + +"""Represents a comment on a bug.""" +type Comment implements Authored { + """The id of this comment.""" + id: String! + """The author of this comment.""" + author: Identity! + """The message of this comment.""" + message: String! + """Indicates, if the comments message is empty or made up of whitespace.""" + hasEmptyMessage: Boolean! + """Indicates, if the comment was previously edited.""" + wasEdited: Boolean! + """All media's hash referenced in this comment.""" + files: [Hash!]! + """Represents the point in time, the comment was created at.""" + createdAt: Time! + """Represents the point in time, the comment last edited.""" + lastEdited: Time! + """Represents a collection of all previously comment alterations.""" + history: [Alteration!]! +} + diff --git a/api/graphql/schema/timeline.graphql b/api/graphql/schema/timeline.graphql index 12462aa35..28c17fb05 100644 --- a/api/graphql/schema/timeline.graphql +++ b/api/graphql/schema/timeline.graphql @@ -4,12 +4,6 @@ interface TimelineItem { id: String! } -"""CommentHistoryStep hold one version of a message in the history""" -type CommentHistoryStep { - message: String! - date: Time! -} - # Connection """The connection type for TimelineItem""" @@ -28,32 +22,18 @@ type TimelineItemEdge { # Items -"""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! - author: Identity! - message: String! - messageIsEmpty: Boolean! - files: [Hash!]! - createdAt: Time! - lastEdit: Time! - edited: Boolean! - history: [CommentHistoryStep!]! -} - -"""AddCommentTimelineItem is a TimelineItem that represent a Comment and its edition history""" -type AddCommentTimelineItem implements TimelineItem & Authored { +"""CommentTimelineItem is a TimelineItem that represent a Comment and its edition history""" +type CommentTimelineItem implements TimelineItem & Authored { """The identifier of the source operation""" id: String! author: Identity! message: String! - messageIsEmpty: Boolean! + hasEmptyMessage: Boolean! files: [Hash!]! createdAt: Time! - lastEdit: Time! - edited: Boolean! - history: [CommentHistoryStep!]! + lastEdited: Time! + wasEdited: Boolean! + history: [Alteration!]! } """LabelChangeTimelineItem is a TimelineItem that represent a change in the labels of a bug""" diff --git a/backup-comment-commit b/backup-comment-commit new file mode 100644 index 000000000..025f883b0 --- /dev/null +++ b/backup-comment-commit @@ -0,0 +1,892 @@ +commit 079072562eee5b51cec781cbce0f87926a9055a0 +Author: Sascha +Date: Wed Aug 11 14:25:47 2021 +0200 + + backup commit + +diff --git a/bridge/gitlab/import.go b/bridge/gitlab/import.go +index 9e55bf77..7ac23eb8 100644 +--- a/bridge/gitlab/import.go ++++ b/bridge/gitlab/import.go +@@ -227,7 +227,7 @@ func (gi *gitlabImporter) ensureNote(repo *cache.RepoCache, b *cache.BugCache, n + op, err := b.EditCommentRaw( + author, + note.UpdatedAt.Unix(), +- firstComment.Id(), ++ firstComment.ID(), + text.Cleanup(issue.Description), + map[string]string{ + metaKeyGitlabId: gitlabID, +@@ -277,7 +277,7 @@ func (gi *gitlabImporter) ensureNote(repo *cache.RepoCache, b *cache.BugCache, n + op, err := b.EditCommentRaw( + author, + note.UpdatedAt.Unix(), +- comment.Id(), ++ comment.ID(), + cleanText, + nil, + ) +diff --git a/bug/op_add_comment.go b/bug/op_add_comment.go +index 4e2619e4..2d947482 100644 +--- a/bug/op_add_comment.go ++++ b/bug/op_add_comment.go +@@ -29,19 +29,20 @@ func (op *AddCommentOperation) Id() entity.Id { + } + + func (op *AddCommentOperation) Apply(snapshot *Snapshot) { +- snapshot.addActor(op.Author_) +- snapshot.addParticipant(op.Author_) +- var comment, _ = commentary.UnsafeComment{ +- Id: entity.CombineIds(snapshot.Id(), op.Id()), +- Message: op.Message, +- Author: op.Author_, +- Files: op.Files, +- CreatedAt: timestamp.Timestamp(op.UnixTime), ++ var comment, err = commentary.UnsafeComment{ ++ ID: op.Id(), ++ SubjectID: snapshot.Id(), ++ Message: op.Message, ++ AuthorID: op.Author_.Id(), ++ Attachments: op.Files, ++ CreatedAt: timestamp.Timestamp(op.UnixTime), + }.Validate() +- if comment != nil { ++ if err == nil { ++ snapshot.addActor(op.Author_) ++ snapshot.addParticipant(op.Author_) + snapshot.appendComment(*comment) + snapshot.appendTimelineItem(&CommentTimelineItem{ +- commentId: comment.Id(), ++ commentId: comment.ID(), + }) + } + } +diff --git a/bug/op_create.go b/bug/op_create.go +index 637a679b..40a96785 100644 +--- a/bug/op_create.go ++++ b/bug/op_create.go +@@ -54,13 +54,15 @@ func (op *CreateOperation) Apply(snapshot *Snapshot) { + snapshot.addParticipant(op.Author_) + snapshot.changeTitleTo(op.Title) + +- var desc, _ = commentary.UnsafeComment{ +- Id: entity.CombineIds(snapshot.Id(), op.Id()), +- Message: op.Message, +- Author: op.Author_, +- CreatedAt: timestamp.Timestamp(op.UnixTime), ++ var desc, err = commentary.UnsafeComment{ ++ ID: op.Id(), ++ SubjectID: snapshot.Id(), ++ Message: op.Message, ++ AuthorID: op.Author_.Id(), ++ Attachments: op.Files, ++ CreatedAt: timestamp.Timestamp(op.UnixTime), + }.Validate() +- if desc != nil { ++ if err == nil { + snapshot.description = *desc + snapshot.author = op.Author_ + snapshot.CreateTime = op.Time() +diff --git a/bug/op_edit_comment.go b/bug/op_edit_comment.go +index 32bb36d9..176aefcf 100644 +--- a/bug/op_edit_comment.go ++++ b/bug/op_edit_comment.go +@@ -41,7 +41,7 @@ func (op *EditCommentOperation) Apply(snapshot *Snapshot) { + comment, _ := snapshot.SearchComment(commentId) + err := comment.Edit(commentary.Alteration{ + Message: op.Message, +- Author: op.Author_, ++ AuthorID: op.Author_.Id(), + CreatedAt: timestamp.Timestamp(op.UnixTime), + }) + if err == nil { +diff --git a/bug/snapshot.go b/bug/snapshot.go +index 1676d4f4..eb3cea1c 100644 +--- a/bug/snapshot.go ++++ b/bug/snapshot.go +@@ -109,12 +109,12 @@ func (snap *Snapshot) SearchTimelineItem(id entity.Id) (TimelineItem, error) { + + // SearchComment will search for a comment matching the given hash + func (snap *Snapshot) SearchComment(id entity.Id) (*commentary.Comment, error) { +- if snap.description.Id() == id { ++ if snap.description.ID() == id { + return &snap.description, nil + } + + for i, c := range snap.comments { +- if c.Id() == id { ++ if c.ID() == id { + return &snap.comments[i], nil + } + } +diff --git a/cache/repo_cache_bug.go b/cache/repo_cache_bug.go +index 7af73976..58b7ec5b 100644 +--- a/cache/repo_cache_bug.go ++++ b/cache/repo_cache_bug.go +@@ -289,10 +289,10 @@ func (c *RepoCache) ResolveComment(prefix string) (*BugCache, entity.Id, error) + return nil, entity.UnsetId, err + } + +- if b.Snapshot().Description().Id().HasPrefix(prefix) { ++ if b.Snapshot().Description().ID().HasPrefix(prefix) { + matchingBugIds = append(matchingBugIds, bugId) + matchingBug = b +- matchingCommentId = b.Snapshot().Description().Id() ++ matchingCommentId = b.Snapshot().Description().ID() + } + + //TODO iteration of comments should be replaced via *SearchComment*. +@@ -300,10 +300,10 @@ func (c *RepoCache) ResolveComment(prefix string) (*BugCache, entity.Id, error) + // clear interface to operate on these comments. Especially as the returned array is a reference... + // E.g. provide Snapshot::Comments(Handler), with Handler being the function to operate on comments + for _, comment := range b.Snapshot().Comments() { +- if comment.Id().HasPrefix(prefix) { ++ if comment.ID().HasPrefix(prefix) { + matchingBugIds = append(matchingBugIds, bugId) + matchingBug = b +- matchingCommentId = comment.Id() ++ matchingCommentId = comment.ID() + } + } + } +diff --git a/commentary/TODO.md b/commentary/TODO.md +new file mode 100644 +index 00000000..ab602edc +--- /dev/null ++++ b/commentary/TODO.md +@@ -0,0 +1,18 @@ ++- PostedEvent takes a comment in constructor, to prevent creation of PostedEvent without a valid *Posted* command. ++ - Op_add_comment should take a struct for posting, but this would then require op_add_comment to construct a comment. ++ - Why should it take a struct? It is easier to read then a long parameter list. ++ - If Op_add_comment is able to construct a comment, PostedEvent could also be constructed... ++ - Maybe PostService should save the comment and return posted as persistance success. ++ - Exposing the command aggregate to other aggregates (e.g. bug) would enable those, to edit the comment. ++ Possible making it possible to store references to a comment from multiple aggregates... ++ But if EditCommand is exposed (which has to be), it is also possible to edit a comment from diffrent aggregates (which hold a comment ID) ++- Maybe move post.go into comment/service or comment/commands, then it can refer to comment.go ++ - But then comment.Post() won't work ++ - Solution: Put PostedEvent into PostCommand as the event on itself might be never needed. ++ If someone calls Post(), Posted-event is required too. Both never come alone. ++- Serialize and Deserialize Event => read/store in repository ++ - Create internal/event/store or internal/store ++- Go files within commentary directory are use-cases/application services ++- internal holds the implementation of the comment aggregate ++ - Move comment.go into internal ++- Rename commentary to comment. +diff --git a/commentary/command/post.go b/commentary/command/post.go +new file mode 100644 +index 00000000..b9239c1b +--- /dev/null ++++ b/commentary/command/post.go +@@ -0,0 +1,45 @@ ++// This file (comment/bug) should provide the workflow, to post to a bug. ++// For pull requests, create another file. E.g. (comment/pull). ++// This is flexible enough to also provide comment/website, to comment a ++// website. ++// ++// Why put this workflow not into bug? A comment could refer to everything ++// without the referee knowing about it. So this package could provide a ++// service to comment something and store this comments within git. Optionally, ++// this comments could be synced to other services. E.g. the comment could be ++// sent to the commented website, or a bug is notified that a comment was left. ++ ++package command ++ ++import ( ++ "time" ++ ++ "github.com/MichaelMure/git-bug/commentary/event" ++ "github.com/MichaelMure/git-bug/commentary/internal" ++ "github.com/MichaelMure/git-bug/entity" ++ "github.com/MichaelMure/git-bug/repository" ++) ++ ++// TODO this has to be provided by store! ++func store_GetNextID() entity.Id { ++ panic("To be implemented ID") ++ return entity.Id("abc") ++} ++ ++func Post(subjectID entity.Id, authorID entity.Id, message string, attachments []repository.Hash) (event.CommentPosted, error) { ++ commentID := entity.CombineIds(subjectID, store_GetNextID()) ++ ++ var comment, err = internal.UnsafeComment{ ++ Id: commentID, ++ SubjectID: subjectID, ++ AuthorID: authorID, ++ Message: message, ++ Attachments: attachments, ++ CreatedAt: time.Now(), ++ }.Validate() ++ if err != nil { ++ return event.CommentPosted{}, err ++ } ++ ++ return event.NewCommentPosted(*comment), nil ++} +diff --git a/commentary/comment.go b/commentary/comment.go +index 1884cd4f..3bf22f16 100644 +--- a/commentary/comment.go ++++ b/commentary/comment.go +@@ -5,7 +5,6 @@ import ( + "strings" + + "github.com/MichaelMure/git-bug/entity" +- "github.com/MichaelMure/git-bug/identity" + "github.com/MichaelMure/git-bug/repository" + "github.com/MichaelMure/git-bug/util/text" + "github.com/MichaelMure/git-bug/util/timestamp" +@@ -15,10 +14,11 @@ import ( + type UnsafeComment struct { + // id should be the result of entity.CombineIds with the Bug id and the id + // of the Operation that created the comment +- Id entity.Id +- Author identity.Interface +- Message string +- Files []repository.Hash ++ ID entity.Id ++ SubjectID entity.Id ++ AuthorID entity.Id ++ Message string ++ Attachments []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. +@@ -29,7 +29,7 @@ type UnsafeComment struct { + type Alteration struct { + // The author of the edition, not necessarily the same as the author of the + // original comment +- Author identity.Interface ++ AuthorID entity.Id + // The new message + Message string + // The time the alteration was created +@@ -43,9 +43,9 @@ type Comment struct { + } + + func (unsafeComment UnsafeComment) Validate() (*Comment, error) { +- if unsafeComment.Id == "" { ++ if unsafeComment.ID == "" { + // simply panic as it would be a coding error (no id provided at construction) +- panic("no id") ++ panic("no ID") + } + + if !text.Safe(unsafeComment.Message) { +@@ -56,8 +56,13 @@ func (unsafeComment UnsafeComment) Validate() (*Comment, error) { + } + + // Id return the Comment identifier. +-func (c Comment) Id() entity.Id { +- return c.valid.Id ++func (c Comment) ID() entity.Id { ++ return c.valid.ID ++} ++ ++// SubjectId return the Comment subject identifier. ++func (c Comment) SubjectID() entity.Id { ++ return c.valid.SubjectID + } + + // Message returns the message text of the comment. +@@ -66,8 +71,8 @@ func (c Comment) Message() string { + } + + // Author returns the author of the comment. +-func (c Comment) Author() identity.Interface { +- return c.valid.Author ++func (c Comment) AuthorID() entity.Id { ++ return c.valid.AuthorID + } + + // Edited say if the comment was edited. +@@ -88,24 +93,24 @@ func (c *Comment) Edit(alteration Alteration) error { + } + c.history = append(c.history, Alteration{ + Message: c.valid.Message, +- Author: c.valid.Author, ++ AuthorID: c.valid.AuthorID, + CreatedAt: c.valid.CreatedAt, + }) + c.lastEdited = alteration.CreatedAt + c.valid.Message = alteration.Message +- c.valid.Author = alteration.Author ++ c.valid.AuthorID = alteration.AuthorID + c.valid.CreatedAt = alteration.CreatedAt + return nil + } + + // AttacheFiles attaches the given files to the comment. +-func (c Comment) AttacheFiles(files []repository.Hash) { +- c.valid.Files = files ++func (c Comment) AttacheFiles(attachments []repository.Hash) { ++ c.valid.Attachments = attachments + } + + // Files return the comments attached files. +-func (c Comment) Files() []repository.Hash { +- return c.valid.Files ++func (c Comment) Attachments() []repository.Hash { ++ return c.valid.Attachments + } + + // History returns the comments alterations. +@@ -113,7 +118,7 @@ func (c Comment) History() []Alteration { + return c.history + } + +-// CreationTimestamp returns the date and time of comments creation. ++// CreationAt returns the date and time of comments creation. + func (c Comment) CreatedAt() timestamp.Timestamp { + return c.valid.CreatedAt + } +diff --git a/commentary/event/posted.go b/commentary/event/posted.go +new file mode 100644 +index 00000000..ec9b52bb +--- /dev/null ++++ b/commentary/event/posted.go +@@ -0,0 +1,41 @@ ++package event ++ ++import ( ++ "time" ++ ++ "github.com/MichaelMure/git-bug/commentary/internal" ++ "github.com/MichaelMure/git-bug/entity" ++) ++ ++// Posted represents an immutable event about a posted comment. ++type CommentPosted struct { ++ id entity.Id ++ subjectID entity.Id ++ authorID entity.Id ++ createdAt time.Time ++} ++ ++func NewCommentPosted(comment internal.Comment) CommentPosted { ++ return CommentPosted{ ++ id: comment.ID(), ++ subjectID: comment.SubjectID(), ++ authorID: comment.AuthorID(), ++ createdAt: comment.CreatedAt(), ++ } ++} ++ ++func (event CommentPosted) ID() entity.Id { ++ return event.id ++} ++ ++func (event CommentPosted) Subject() entity.Id { ++ return event.subjectID ++} ++ ++func (event CommentPosted) Author() entity.Id { ++ return event.authorID ++} ++ ++func (event CommentPosted) CreatedAt() time.Time { ++ return event.createdAt ++} +diff --git a/commentary/internal/comment.go b/commentary/internal/comment.go +new file mode 100644 +index 00000000..7f2f1385 +--- /dev/null ++++ b/commentary/internal/comment.go +@@ -0,0 +1,132 @@ ++package internal ++ ++import ( ++ "fmt" ++ "strings" ++ "time" ++ ++ "github.com/MichaelMure/git-bug/entity" ++ "github.com/MichaelMure/git-bug/repository" ++ "github.com/MichaelMure/git-bug/util/text" ++) ++ ++// Comment represent a comment in a Bug ++type UnsafeComment struct { ++ // id should be the result of entity.CombineIds with the Bug id and the id ++ // of the Operation that created the comment ++ ID entity.Id ++ SubjectID entity.Id ++ AuthorID entity.Id ++ Message string ++ Attachments []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. ++ CreatedAt time.Time ++} ++ ++// Edit hold one version of a message in the history ++type Alteration struct { ++ // The author of the edition, not necessarily the same as the author of the ++ // original comment ++ AuthorID entity.Id ++ // The new message ++ Message string ++ // The time the alteration was created ++ CreatedAt time.Time ++} ++ ++type Comment struct { ++ valid UnsafeComment ++ history []Alteration ++ lastEdited time.Time ++} ++ ++func (unsafeComment UnsafeComment) Validate() (*Comment, error) { ++ if unsafeComment.ID == "" { ++ // simply panic as it would be a coding error (no id provided at construction) ++ panic("no ID") ++ } ++ ++ if !text.Safe(unsafeComment.Message) { ++ return nil, fmt.Errorf("message is not fully printable") ++ } ++ ++ return &Comment{valid: unsafeComment}, nil ++} ++ ++// Id return the Comment identifier. ++func (c Comment) ID() entity.Id { ++ return c.valid.ID ++} ++ ++// SubjectId return the Comment subject identifier. ++func (c Comment) SubjectID() entity.Id { ++ return c.valid.SubjectID ++} ++ ++// Message returns the message text of the comment. ++func (c Comment) Message() string { ++ return c.valid.Message ++} ++ ++// Author returns the author of the comment. ++func (c Comment) AuthorID() entity.Id { ++ return c.valid.AuthorID ++} ++ ++// Edited say if the comment was edited. ++func (c Comment) WasEdited() bool { ++ return len(c.history) > 1 ++} ++ ++// MessageIsEmpty return true is the message is empty or only made of spaces. ++func (c Comment) HasEmptyMessage() bool { ++ return len(strings.TrimSpace(c.Message())) == 0 ++} ++ ++// Propose requests an alteration of the comment. If something wents wrong, ++// nothing happens to the comment and an error is returned instead. ++func (c *Comment) Edit(alteration Alteration) error { ++ if !text.Safe(alteration.Message) { ++ return fmt.Errorf("message is not fully printable") ++ } ++ c.history = append(c.history, Alteration{ ++ Message: c.valid.Message, ++ AuthorID: c.valid.AuthorID, ++ CreatedAt: c.valid.CreatedAt, ++ }) ++ c.lastEdited = alteration.CreatedAt ++ c.valid.Message = alteration.Message ++ c.valid.AuthorID = alteration.AuthorID ++ c.valid.CreatedAt = alteration.CreatedAt ++ return nil ++} ++ ++// AttacheFiles attaches the given files to the comment. ++func (c Comment) AttacheFiles(attachments []repository.Hash) { ++ c.valid.Attachments = attachments ++} ++ ++// Files return the comments attached files. ++func (c Comment) Attachments() []repository.Hash { ++ return c.valid.Attachments ++} ++ ++// History returns the comments alterations. ++func (c Comment) History() []Alteration { ++ return c.history ++} ++ ++// CreationAt returns the date and time of comments creation. ++func (c Comment) CreatedAt() time.Time { ++ return c.valid.CreatedAt ++} ++ ++// LastEdited returns the date and time of comments last edit. ++func (c Comment) LastEdited() time.Time { ++ return c.lastEdited ++} ++ ++// Sign post method for gqlgen ++func (c Comment) IsAuthored() {} +diff --git a/commentary/internal/event.go_bak b/commentary/internal/event.go_bak +new file mode 100644 +index 00000000..29efc50c +--- /dev/null ++++ b/commentary/internal/event.go_bak +@@ -0,0 +1,268 @@ ++package internal ++ ++//import ( ++// "crypto/rand" ++// "encoding/json" ++// "fmt" ++// "time" ++// ++// "github.com/pkg/errors" ++// ++// "github.com/MichaelMure/git-bug/entity" ++// "github.com/MichaelMure/git-bug/entity/dag" ++// "github.com/MichaelMure/git-bug/identity" ++//) ++// ++//// EventType is an event type identifier ++//type EventType int ++// ++//const ( ++// _ EventType = iota ++// Posted ++//) ++// ++//// Event define the interface to fulfill for a comment event. ++//type Event interface { ++// dag.Operation ++// ++// // Type return the type of the event ++// Type() EventType ++// ++// // Time return the time when the event was added ++// Time() time.Time ++// // Apply the event to a Snapshot to create the final state ++// Apply(snapshot *Snapshot) ++// ++// // SetMetadata store arbitrary metadata about the event ++// SetMetadata(key string, value string) ++// // GetMetadata retrieve arbitrary metadata about the event ++// GetMetadata(key string) (string, bool) ++// // AllMetadata return all metadata for this event ++// AllMetadata() map[string]string ++// ++// setExtraMetadataImmutable(key string, value string) ++//} ++// ++//func idEvent(event Event, base *EventBase) entity.Id { ++// if base.id == "" { ++// // something went really wrong ++// panic("event's id not set") ++// } ++// if base.id == entity.UnsetId { ++// // This means we are trying to get the event's Id *before* it has been stored, for instance when ++// // adding multiple events in one go in an EventPack. ++// // As the Id is computed based on the actual bytes written on the disk, we are going to predict ++// // those and then get the Id. This is safe as it will be the exact same code writing on disk later. ++// ++// data, err := json.Marshal(event) ++// if err != nil { ++// panic(err) ++// } ++// ++// base.id = entity.DeriveId(data) ++// } ++// return base.id ++//} ++// ++//func eventUnmarshaller(author identity.Interface, raw json.RawMessage) (dag.Operation, error) { ++// var t struct { ++// EventType EventType `json:"type"` ++// } ++// ++// if err := json.Unmarshal(raw, &t); err != nil { ++// return nil, err ++// } ++// ++// var event Event ++// ++// switch t.EventType { ++// case Posted: ++// event = &Posted{} ++// default: ++// panic(fmt.Sprintf("unknown event type %v", t.EventType)) ++// } ++// ++// err := json.Unmarshal(raw, &event) ++// if err != nil { ++// return nil, err ++// } ++// ++// switch event := event.(type) { ++// case *Posted: ++// event.Author_ = author ++// default: ++// panic(fmt.Sprintf("unknown event type %T", event)) ++// } ++// ++// return event, nil ++//} ++// ++//// EventBase implement the common code for all events ++//type EventBase struct { ++// EventType EventType `json:"type"` ++// Author_ identity.Interface `json:"author"` ++// // TODO: part of the data model upgrade, this should eventually be a timestamp + lamport ++// UnixTime int64 `json:"timestamp"` ++// Metadata map[string]string `json:"metadata,omitempty"` ++// ++// // mandatory random bytes to ensure a better randomness of the data used to later generate the ID ++// // len(Nonce) should be > 20 and < 64 bytes ++// // It has no functional purpose and should be ignored. ++// Nonce []byte `json:"nonce"` ++// ++// // Not serialized. Store the event's id in memory. ++// id entity.Id ++// // Not serialized. Store the extra metadata in memory, ++// // compiled from SetMetadataEvent. ++// extraMetadata map[string]string ++//} ++// ++//// newEventBase is the constructor for an EventBase ++//func newEventBase(eventType EventType, author identity.Interface, unixTime int64) EventBase { ++// return EventBase{ ++// EventType: eventType, ++// Author_: author, ++// UnixTime: unixTime, ++// Nonce: makeNonce(20), ++// id: entity.UnsetId, ++// } ++//} ++// ++//func makeNonce(len int) []byte { ++// result := make([]byte, len) ++// _, err := rand.Read(result) ++// if err != nil { ++// panic(err) ++// } ++// return result ++//} ++// ++//func (base *EventBase) UnmarshalJSON(data []byte) error { ++// // Compute the Id when loading the event from disk. ++// base.id = entity.DeriveId(data) ++// ++// aux := struct { ++// EventType EventType `json:"type"` ++// Author json.RawMessage `json:"author"` ++// UnixTime int64 `json:"timestamp"` ++// Metadata map[string]string `json:"metadata,omitempty"` ++// Nonce []byte `json:"nonce"` ++// }{} ++// ++// if err := json.Unmarshal(data, &aux); err != nil { ++// return err ++// } ++// ++// // delegate the decoding of the identity ++// author, err := identity.UnmarshalJSON(aux.Author) ++// if err != nil { ++// return err ++// } ++// ++// base.EventType = aux.EventType ++// base.Author_ = author ++// base.UnixTime = aux.UnixTime ++// base.Metadata = aux.Metadata ++// base.Nonce = aux.Nonce ++// ++// return nil ++//} ++// ++//func (base *EventBase) Type() EventType { ++// return base.EventType ++//} ++// ++//// Time return the time when the event was added ++//func (base *EventBase) Time() time.Time { ++// return time.Unix(base.UnixTime, 0) ++//} ++// ++//// Validate check the EventBase for errors ++//func (base *EventBase) Validate(event Event, eventType EventType) error { ++// if base.EventType != eventType { ++// return fmt.Errorf("incorrect event type (expected: %v, actual: %v)", eventType, base.EventType) ++// } ++// ++// if event.Time().Unix() == 0 { ++// return fmt.Errorf("time not set") ++// } ++// ++// if base.Author_ == nil { ++// return fmt.Errorf("author not set") ++// } ++// ++// if err := event.Author().Validate(); err != nil { ++// return errors.Wrap(err, "author") ++// } ++// ++// if event, ok := event.(dag.OperationWithFiles); ok { ++// for _, hash := range event.GetFiles() { ++// if !hash.IsValid() { ++// return fmt.Errorf("file with invalid hash %v", hash) ++// } ++// } ++// } ++// ++// if len(base.Nonce) > 64 { ++// return fmt.Errorf("nonce is too big") ++// } ++// if len(base.Nonce) < 20 { ++// return fmt.Errorf("nonce is too small") ++// } ++// ++// return nil ++//} ++// ++//// SetMetadata store arbitrary metadata about the event ++//func (base *EventBase) SetMetadata(key string, value string) { ++// if base.Metadata == nil { ++// base.Metadata = make(map[string]string) ++// } ++// ++// base.Metadata[key] = value ++// base.id = entity.UnsetId ++//} ++// ++//// GetMetadata retrieve arbitrary metadata about the event ++//func (base *EventBase) GetMetadata(key string) (string, bool) { ++// val, ok := base.Metadata[key] ++// ++// if ok { ++// return val, true ++// } ++// ++// // extraMetadata can't replace the original events value if any ++// val, ok = base.extraMetadata[key] ++// ++// return val, ok ++//} ++// ++//// AllMetadata return all metadata for this event ++//func (base *EventBase) AllMetadata() map[string]string { ++// result := make(map[string]string) ++// ++// for key, val := range base.extraMetadata { ++// result[key] = val ++// } ++// ++// // Original metadata take precedence ++// for key, val := range base.Metadata { ++// result[key] = val ++// } ++// ++// return result ++//} ++// ++//func (base *EventBase) setExtraMetadataImmutable(key string, value string) { ++// if base.extraMetadata == nil { ++// base.extraMetadata = make(map[string]string) ++// } ++// if _, exist := base.extraMetadata[key]; !exist { ++// base.extraMetadata[key] = value ++// } ++//} ++// ++//// Author return author identity ++//func (base *EventBase) Author() identity.Interface { ++// return base.Author_ ++//} +diff --git a/commentary/internal/git_store.go b/commentary/internal/git_store.go +new file mode 100644 +index 00000000..137b08f5 +--- /dev/null ++++ b/commentary/internal/git_store.go +@@ -0,0 +1,41 @@ ++package internal ++ ++// import ( ++// "github.com/MichaelMure/git-bug/entity" ++// "github.com/MichaelMure/git-bug/entity/dag" ++// "github.com/MichaelMure/git-bug/identity" ++// "github.com/MichaelMure/git-bug/repository" ++// ) ++// ++// // 1: original format ++// // 2: no more legacy identities ++// // 3: Ids are generated from the create operation serialized data instead of from the first git commit ++// // 4: with DAG entity framework ++// const formatVersion = 4 ++// ++// var def = dag.Definition{ ++// Typename: "comment", ++// Namespace: "comments", ++// OperationUnmarshaller: eventUnmarshaller, ++// FormatVersion: formatVersion, ++// } ++// ++// var ClockLoader = dag.ClockLoader(def) ++// ++// type Comment struct { ++// *dag.Entity ++// } ++// ++// func NewComment() *Comment { ++// return &Comment{ ++// Entity: dag.New(def), ++// } ++// } ++// ++// func Read(repo repository.ClockedRepo, id entity.Id) (*Comment, error) { ++// e, err := dag.Read(def, repo, identity.NewSimpleResolver(repo), id) ++// if err != nil { ++// return nil, err ++// } ++// return &Comment{Entity: e}, nil ++// } +diff --git a/commentary/internal/store.go b/commentary/internal/store.go +new file mode 100644 +index 00000000..d3673456 +--- /dev/null ++++ b/commentary/internal/store.go +@@ -0,0 +1,7 @@ ++package internal ++ ++type ReadStore interface { ++} ++ ++type WriteStore interface { ++} +diff --git a/termui/show_bug.go b/termui/show_bug.go +index 53ade8b5..b06f6f2a 100644 +--- a/termui/show_bug.go ++++ b/termui/show_bug.go +@@ -247,7 +247,7 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error { + content, lines = text.WrapLeftPadded(desc.Message(), maxX-1, 4) + } + +- v, err = sb.createOpView(g, desc.Id().String(), x0, y0, maxX+1, lines, true) ++ v, err = sb.createOpView(g, desc.ID().String(), x0, y0, maxX+1, lines, true) + if err != nil { + return err + } +@@ -276,7 +276,7 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error { + } + + content := fmt.Sprintf("%s commented on %s%s\n\n%s", +- colors.Magenta(comment.Author().DisplayName()), ++ colors.Magenta(comment.AuthorID().DisplayName()), + comment.CreatedAt().Time().Format(timeLayout), + edited, + message, +@@ -649,7 +649,7 @@ func (sb *showBug) edit(g *gocui.Gui, v *gocui.View) error { + switch op := op.(type) { + case *bug.CommentTimelineItem: + comment, _ := snap.SearchComment(op.Id()) +- return editCommentWithEditor(sb.bug, comment.Id(), comment.Message()) ++ return editCommentWithEditor(sb.bug, comment.ID(), comment.Message()) + case *bug.LabelChangeTimelineItem: + return sb.editLabels(g, snap) + } diff --git a/bridge/github/export.go b/bridge/github/export.go index 264f2a23b..b85e56220 100644 --- a/bridge/github/export.go +++ b/bridge/github/export.go @@ -203,7 +203,7 @@ func (ge *githubExporter) exportBug(ctx context.Context, b *cache.BugCache, out // first operation is always createOp createOp := snapshot.Operations[0].(*bug.CreateOperation) - author := snapshot.Author + authorID := snapshot.Author() // skip bug if origin is not allowed origin, ok := snapshot.GetCreateMetadata(core.MetaKeyOrigin) @@ -242,7 +242,7 @@ func (ge *githubExporter) exportBug(ctx context.Context, b *cache.BugCache, out } else { // check that we have a token for operation author - client, err := ge.getClientForIdentity(author.Id()) + client, err := ge.getClientForIdentity(authorID) if err != nil { // if bug is still not exported and we do not have the author stop the execution out <- core.NewExportNothing(b.Id(), fmt.Sprintf("missing author token")) diff --git a/bridge/gitlab/export.go b/bridge/gitlab/export.go index 9c3864ecc..4d4b4d861 100644 --- a/bridge/gitlab/export.go +++ b/bridge/gitlab/export.go @@ -171,7 +171,7 @@ func (ge *gitlabExporter) exportBug(ctx context.Context, b *cache.BugCache, out // first operation is always createOp createOp := snapshot.Operations[0].(*bug.CreateOperation) - author := snapshot.Author + authorID := snapshot.Author() // get gitlab bug ID gitlabID, ok := snapshot.GetCreateMetadata(metaKeyGitlabId) @@ -204,7 +204,7 @@ func (ge *gitlabExporter) exportBug(ctx context.Context, b *cache.BugCache, out } else { // check that we have a token for operation author - client, err := ge.getIdentityClient(author.Id()) + client, err := ge.getIdentityClient(authorID) if err != nil { // if bug is still not exported and we do not have the author stop the execution out <- core.NewExportNothing(b.Id(), fmt.Sprintf("missing author token")) diff --git a/bridge/gitlab/import.go b/bridge/gitlab/import.go index 79a92dac9..9e55bf774 100644 --- a/bridge/gitlab/import.go +++ b/bridge/gitlab/import.go @@ -218,11 +218,11 @@ func (gi *gitlabImporter) ensureNote(repo *cache.RepoCache, b *cache.BugCache, n case NOTE_DESCRIPTION_CHANGED: issue := gi.iterator.IssueValue() - firstComment := b.Snapshot().Comments[0] + firstComment := b.Snapshot().Comments()[0] // 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 { + if errResolve == cache.ErrNoMatchingOp && issue.Description != firstComment.Message() { // comment edition op, err := b.EditCommentRaw( author, @@ -272,7 +272,7 @@ func (gi *gitlabImporter) ensureNote(repo *cache.RepoCache, b *cache.BugCache, n } // compare local bug comment with the new note body - if comment.Message != cleanText { + if comment.Message() != cleanText { // comment edition op, err := b.EditCommentRaw( author, diff --git a/bridge/jira/export.go b/bridge/jira/export.go index 34f41d097..4fe5ad269 100644 --- a/bridge/jira/export.go +++ b/bridge/jira/export.go @@ -200,7 +200,7 @@ func (je *jiraExporter) exportBug(ctx context.Context, b *cache.BugCache, out ch // first operation is always createOp createOp := snapshot.Operations[0].(*bug.CreateOperation) - author := snapshot.Author + authorID := snapshot.Author() // skip bug if it was imported from some other bug system origin, ok := snapshot.GetCreateMetadata(core.MetaKeyOrigin) @@ -226,13 +226,13 @@ func (je *jiraExporter) exportBug(ctx context.Context, b *cache.BugCache, out ch bugJiraID = jiraID } else { // check that we have credentials for operation author - client, err := je.getClientForIdentity(author.Id()) + client, err := je.getClientForIdentity(authorID) if err != nil { // if bug is not yet exported and we do not have the author's credentials // then there is nothing we can do, so just skip this bug out <- core.NewExportNothing( b.Id(), fmt.Sprintf("missing author credentials for user %.8s", - author.Id().String())) + authorID.String())) return err } @@ -314,7 +314,7 @@ func (je *jiraExporter) exportBug(ctx context.Context, b *cache.BugCache, out ch if err != nil { out <- core.NewExportError( fmt.Errorf("missing operation author credentials for user %.8s", - author.Id().String()), op.Id()) + authorID.String()), op.Id()) continue } diff --git a/bug/bug.go b/bug/bug.go index 9d19a42cb..9c2eeeeb0 100644 --- a/bug/bug.go +++ b/bug/bug.go @@ -147,7 +147,7 @@ func (bug *Bug) Operations() []Operation { func (bug *Bug) Compile() Snapshot { snap := Snapshot{ id: bug.Id(), - Status: OpenStatus, + status: OpenStatus, } for _, op := range bug.Operations() { diff --git a/bug/comment.go b/bug/comment.go deleted file mode 100644 index c1cfc7e53..000000000 --- a/bug/comment.go +++ /dev/null @@ -1,45 +0,0 @@ -package bug - -import ( - "github.com/dustin/go-humanize" - - "github.com/MichaelMure/git-bug/entity" - "github.com/MichaelMure/git-bug/identity" - "github.com/MichaelMure/git-bug/repository" - "github.com/MichaelMure/git-bug/util/timestamp" -) - -// 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 - // of the Operation that created the comment - id 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 -} - -// Id return the Comment identifier -func (c Comment) Id() entity.Id { - if c.id == "" { - // simply panic as it would be a coding error (no id provided at construction) - panic("no id") - } - return c.id -} - -// FormatTimeRel format the UnixTime of the comment for human consumption -func (c Comment) FormatTimeRel() string { - return humanize.Time(c.UnixTime.Time()) -} - -func (c Comment) FormatTime() string { - return c.UnixTime.Time().Format("Mon Jan 2 15:04:05 2006 +0200") -} - -// Sign post method for gqlgen -func (c Comment) IsAuthored() {} diff --git a/bug/op_add_comment.go b/bug/op_add_comment.go index 15e622263..edbf9e7d1 100644 --- a/bug/op_add_comment.go +++ b/bug/op_add_comment.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" + "github.com/MichaelMure/git-bug/commentary" "github.com/MichaelMure/git-bug/entity" "github.com/MichaelMure/git-bug/entity/dag" "github.com/MichaelMure/git-bug/identity" @@ -28,24 +29,21 @@ func (op *AddCommentOperation) Id() entity.Id { } func (op *AddCommentOperation) Apply(snapshot *Snapshot) { - snapshot.addActor(op.Author_) - snapshot.addParticipant(op.Author_) - - comment := Comment{ - id: entity.CombineIds(snapshot.Id(), op.Id()), - Message: op.Message, - Author: op.Author_, - Files: op.Files, - UnixTime: timestamp.Timestamp(op.UnixTime), + snapshot.addActor(op.Author_.Id()) + snapshot.addParticipant(op.Author_.Id()) + var comment, _ = commentary.UnsafeComment{ + Id: entity.CombineIds(snapshot.Id(), op.Id()), + Message: op.Message, + Author: op.Author_, + Files: op.Files, + CreatedAt: timestamp.Timestamp(op.UnixTime), + }.Validate() + if comment != nil { + snapshot.appendComment(*comment) + snapshot.appendTimelineItem(&CommentTimelineItem{ + commentId: comment.Id(), + }) } - - snapshot.Comments = append(snapshot.Comments, comment) - - item := &AddCommentTimelineItem{ - CommentTimelineItem: NewCommentTimelineItem(comment), - } - - snapshot.Timeline = append(snapshot.Timeline, item) } func (op *AddCommentOperation) GetFiles() []repository.Hash { @@ -104,13 +102,17 @@ func NewAddCommentOp(author identity.Interface, unixTime int64, message string, } } -// CreateTimelineItem replace a AddComment operation in the Timeline and hold its edition history -type AddCommentTimelineItem struct { - CommentTimelineItem +// CommentTimelineItem is a TimelineItem that references a Comments by Id +type CommentTimelineItem struct { + commentId entity.Id +} + +func (c *CommentTimelineItem) Id() entity.Id { + return c.commentId } // Sign post method for gqlgen -func (a *AddCommentTimelineItem) IsAuthored() {} +func (a *CommentTimelineItem) IsAuthored() {} // Convenience function to apply the operation func AddComment(b Interface, author identity.Interface, unixTime int64, message string) (*AddCommentOperation, error) { diff --git a/bug/op_create.go b/bug/op_create.go index 9c9721959..ec7bb4b0f 100644 --- a/bug/op_create.go +++ b/bug/op_create.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" + "github.com/MichaelMure/git-bug/commentary" "github.com/MichaelMure/git-bug/entity" "github.com/MichaelMure/git-bug/entity/dag" "github.com/MichaelMure/git-bug/identity" @@ -49,27 +50,22 @@ func (op *CreateOperation) Apply(snapshot *Snapshot) { } snapshot.id = op.Id() - - snapshot.addActor(op.Author_) - snapshot.addParticipant(op.Author_) - - snapshot.Title = op.Title - - comment := Comment{ - id: entity.CombineIds(snapshot.Id(), op.Id()), - Message: op.Message, - Author: op.Author_, - UnixTime: timestamp.Timestamp(op.UnixTime), - } - - snapshot.Comments = []Comment{comment} - snapshot.Author = op.Author_ - snapshot.CreateTime = op.Time() - - snapshot.Timeline = []TimelineItem{ - &CreateTimelineItem{ - CommentTimelineItem: NewCommentTimelineItem(comment), - }, + snapshot.addActor(op.Author_.Id()) + snapshot.addParticipant(op.Author_.Id()) + snapshot.changeTitleTo(op.Title) + + var desc, _ = commentary.UnsafeComment{ + Id: entity.CombineIds(snapshot.Id(), op.Id()), + Message: op.Message, + Author: op.Author_, + CreatedAt: timestamp.Timestamp(op.UnixTime), + }.Validate() + if desc != nil { + snapshot.description = *desc + snapshot.authorID = op.Author_.Id() + snapshot.CreateTime = op.Time() + snapshot.comments = []commentary.Comment{} + snapshot.timeline = []TimelineItem{} } } @@ -148,14 +144,6 @@ func NewCreateOp(author identity.Interface, unixTime int64, title, message strin } } -// CreateTimelineItem replace a Create operation in the Timeline and hold its edition history -type CreateTimelineItem struct { - CommentTimelineItem -} - -// Sign post method for gqlgen -func (c *CreateTimelineItem) IsAuthored() {} - // Convenience function to apply the operation func Create(author identity.Interface, unixTime int64, title, message string) (*Bug, *CreateOperation, error) { return CreateWithFiles(author, unixTime, title, message, nil) diff --git a/bug/op_create_test.go b/bug/op_create_test.go index 25b87cfe2..57d02cfb8 100644 --- a/bug/op_create_test.go +++ b/bug/op_create_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/MichaelMure/git-bug/commentary" "github.com/MichaelMure/git-bug/entity" "github.com/MichaelMure/git-bug/identity" "github.com/MichaelMure/git-bug/repository" @@ -30,28 +31,24 @@ func TestCreate(t *testing.T) { 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), - } + desc, err := commentary.UnsafeComment{ + Id: entity.CombineIds(create.Id(), create.Id()), + Author: rene, + Message: "message", + CreatedAt: timestamp.Timestamp(create.UnixTime), + }.Validate() + require.NoError(t, err) 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), - }, - }, + id: create.Id(), + title: "title", + description: *desc, + comments: []commentary.Comment{}, + authorID: rene.Id(), + participantIDs: []entity.Id{rene.Id()}, + actorIDs: []entity.Id{rene.Id()}, + CreateTime: create.Time(), + timeline: []TimelineItem{}, } require.Equal(t, expected, snapshot) diff --git a/bug/op_edit_comment.go b/bug/op_edit_comment.go index a69cb599e..7ae7e1b11 100644 --- a/bug/op_edit_comment.go +++ b/bug/op_edit_comment.go @@ -6,6 +6,7 @@ import ( "github.com/pkg/errors" + "github.com/MichaelMure/git-bug/commentary" "github.com/MichaelMure/git-bug/entity" "github.com/MichaelMure/git-bug/entity/dag" "github.com/MichaelMure/git-bug/identity" @@ -37,47 +38,14 @@ func (op *EditCommentOperation) Apply(snapshot *Snapshot) { // Recreate the Comment Id to match on commentId := entity.CombineIds(snapshot.Id(), op.Target) - var target TimelineItem - for i, item := range snapshot.Timeline { - if item.Id() == commentId { - target = snapshot.Timeline[i] - break - } - } - - if target == nil { - // Target not found, edit is a no-op - return - } - - comment := Comment{ - id: commentId, - Message: op.Message, - Files: op.Files, - UnixTime: timestamp.Timestamp(op.UnixTime), - } - - switch target := target.(type) { - case *CreateTimelineItem: - target.Append(comment) - case *AddCommentTimelineItem: - target.Append(comment) - default: - // somehow, the target matched on something that is not a comment - // we make the op a no-op - return - } - - snapshot.addActor(op.Author_) - - // Updating the corresponding comment - - for i := range snapshot.Comments { - if snapshot.Comments[i].Id() == commentId { - snapshot.Comments[i].Message = op.Message - snapshot.Comments[i].Files = op.Files - break - } + comment, _ := snapshot.SearchComment(commentId) + err := comment.Edit(commentary.Alteration{ + Message: op.Message, + Author: op.Author_, + CreatedAt: timestamp.Timestamp(op.UnixTime), + }) + if err == nil { + snapshot.addActor(op.Author_.Id()) } } diff --git a/bug/op_edit_comment_test.go b/bug/op_edit_comment_test.go index 5ba947065..528887fbf 100644 --- a/bug/op_edit_comment_test.go +++ b/bug/op_edit_comment_test.go @@ -43,35 +43,35 @@ func TestEdit(t *testing.T) { edit := NewEditCommentOp(rene, unix, create.Id(), "create edited", nil) edit.Apply(&snapshot) - require.Len(t, snapshot.Timeline, 4) - require.Len(t, snapshot.Timeline[0].(*CreateTimelineItem).History, 2) - require.Len(t, snapshot.Timeline[1].(*AddCommentTimelineItem).History, 1) - require.Len(t, snapshot.Timeline[3].(*AddCommentTimelineItem).History, 1) - require.Equal(t, snapshot.Comments[0].Message, "create edited") - require.Equal(t, snapshot.Comments[1].Message, "comment 1") - require.Equal(t, snapshot.Comments[2].Message, "comment 2") + require.Len(t, snapshot.Timeline(), 3) + require.Len(t, snapshot.Description().History(), 1) + require.Len(t, snapshot.Comments()[0].History(), 0) + require.Len(t, snapshot.Comments()[1].History(), 0) + require.Equal(t, snapshot.Description().Message(), "create edited") + require.Equal(t, snapshot.Comments()[0].Message(), "comment 1") + require.Equal(t, snapshot.Comments()[1].Message(), "comment 2") edit2 := NewEditCommentOp(rene, unix, comment1.Id(), "comment 1 edited", nil) edit2.Apply(&snapshot) - require.Len(t, snapshot.Timeline, 4) - require.Len(t, snapshot.Timeline[0].(*CreateTimelineItem).History, 2) - require.Len(t, snapshot.Timeline[1].(*AddCommentTimelineItem).History, 2) - require.Len(t, snapshot.Timeline[3].(*AddCommentTimelineItem).History, 1) - require.Equal(t, snapshot.Comments[0].Message, "create edited") - require.Equal(t, snapshot.Comments[1].Message, "comment 1 edited") - require.Equal(t, snapshot.Comments[2].Message, "comment 2") + require.Len(t, snapshot.Timeline(), 3) + require.Len(t, snapshot.Description().History(), 1) + require.Len(t, snapshot.Comments()[0].History(), 1) + require.Len(t, snapshot.Comments()[1].History(), 0) + require.Equal(t, snapshot.Description().Message(), "create edited") + require.Equal(t, snapshot.Comments()[0].Message(), "comment 1 edited") + require.Equal(t, snapshot.Comments()[1].Message(), "comment 2") edit3 := NewEditCommentOp(rene, unix, comment2.Id(), "comment 2 edited", nil) edit3.Apply(&snapshot) - require.Len(t, snapshot.Timeline, 4) - require.Len(t, snapshot.Timeline[0].(*CreateTimelineItem).History, 2) - require.Len(t, snapshot.Timeline[1].(*AddCommentTimelineItem).History, 2) - require.Len(t, snapshot.Timeline[3].(*AddCommentTimelineItem).History, 2) - require.Equal(t, snapshot.Comments[0].Message, "create edited") - require.Equal(t, snapshot.Comments[1].Message, "comment 1 edited") - require.Equal(t, snapshot.Comments[2].Message, "comment 2 edited") + require.Len(t, snapshot.Timeline(), 3) + require.Len(t, snapshot.Description().History(), 1) + require.Len(t, snapshot.Comments()[0].History(), 1) + require.Len(t, snapshot.Comments()[1].History(), 1) + require.Equal(t, snapshot.Description().Message(), "create edited") + require.Equal(t, snapshot.Comments()[0].Message(), "comment 1 edited") + require.Equal(t, snapshot.Comments()[1].Message(), "comment 2 edited") } func TestEditCommentSerialize(t *testing.T) { diff --git a/bug/op_label_change.go b/bug/op_label_change.go index 8b0e5ec89..9f434afef 100644 --- a/bug/op_label_change.go +++ b/bug/op_label_change.go @@ -3,7 +3,6 @@ package bug import ( "encoding/json" "fmt" - "sort" "github.com/pkg/errors" @@ -25,47 +24,27 @@ func (op *LabelChangeOperation) Id() entity.Id { return idOperation(op, &op.OpBase) } -// Apply apply the operation +// Apply applies the operation func (op *LabelChangeOperation) Apply(snapshot *Snapshot) { - snapshot.addActor(op.Author_) + snapshot.addActor(op.Author_.Id()) // Add in the set -AddLoop: - for _, added := range op.Added { - for _, label := range snapshot.Labels { - if label == added { - // Already exist - continue AddLoop - } - } - - snapshot.Labels = append(snapshot.Labels, added) + for _, label := range op.Added { + snapshot.addLabel(label) } // Remove in the set - for _, removed := range op.Removed { - for i, label := range snapshot.Labels { - if label == removed { - snapshot.Labels[i] = snapshot.Labels[len(snapshot.Labels)-1] - snapshot.Labels = snapshot.Labels[:len(snapshot.Labels)-1] - } - } + for _, label := range op.Removed { + snapshot.removeLabel(label) } - // Sort - sort.Slice(snapshot.Labels, func(i, j int) bool { - return string(snapshot.Labels[i]) < string(snapshot.Labels[j]) - }) - - item := &LabelChangeTimelineItem{ + snapshot.appendTimelineItem(&LabelChangeTimelineItem{ id: op.Id(), Author: op.Author_, UnixTime: timestamp.Timestamp(op.UnixTime), Added: op.Added, Removed: op.Removed, - } - - snapshot.Timeline = append(snapshot.Timeline, item) + }) } func (op *LabelChangeOperation) Validate() error { @@ -164,7 +143,7 @@ func ChangeLabels(b Interface, author identity.Interface, unixTime int64, add, r } // check that the label doesn't already exist - if labelExist(snap.Labels, label) { + if labelExist(snap.labels, label) { results = append(results, LabelChangeResult{Label: label, Status: LabelChangeAlreadySet}) continue } @@ -183,7 +162,7 @@ func ChangeLabels(b Interface, author identity.Interface, unixTime int64, add, r } // check that the label actually exist - if !labelExist(snap.Labels, label) { + if !labelExist(snap.labels, label) { results = append(results, LabelChangeResult{Label: label, Status: LabelChangeDoesntExist}) continue } diff --git a/bug/op_set_status.go b/bug/op_set_status.go index e22ded54c..8cd7dc8bf 100644 --- a/bug/op_set_status.go +++ b/bug/op_set_status.go @@ -23,17 +23,14 @@ func (op *SetStatusOperation) Id() entity.Id { } func (op *SetStatusOperation) Apply(snapshot *Snapshot) { - snapshot.Status = op.Status - snapshot.addActor(op.Author_) - - item := &SetStatusTimelineItem{ + snapshot.setStatusTo(op.Status) + snapshot.addActor(op.Author_.Id()) + snapshot.appendTimelineItem(&SetStatusTimelineItem{ id: op.Id(), Author: op.Author_, UnixTime: timestamp.Timestamp(op.UnixTime), Status: op.Status, - } - - snapshot.Timeline = append(snapshot.Timeline, item) + }) } func (op *SetStatusOperation) Validate() error { diff --git a/bug/op_set_title.go b/bug/op_set_title.go index badd192c9..6d236f3cc 100644 --- a/bug/op_set_title.go +++ b/bug/op_set_title.go @@ -25,18 +25,15 @@ func (op *SetTitleOperation) Id() entity.Id { } func (op *SetTitleOperation) Apply(snapshot *Snapshot) { - snapshot.Title = op.Title - snapshot.addActor(op.Author_) - - item := &SetTitleTimelineItem{ + snapshot.changeTitleTo(op.Title) + snapshot.addActor(op.Author_.Id()) + snapshot.appendTimelineItem(&SetTitleTimelineItem{ id: op.Id(), Author: op.Author_, UnixTime: timestamp.Timestamp(op.UnixTime), Title: op.Title, Was: op.Was, - } - - snapshot.Timeline = append(snapshot.Timeline, item) + }) } func (op *SetTitleOperation) Validate() error { diff --git a/bug/snapshot.go b/bug/snapshot.go index ce84cce12..7f5880061 100644 --- a/bug/snapshot.go +++ b/bug/snapshot.go @@ -4,24 +4,25 @@ import ( "fmt" "time" + "github.com/MichaelMure/git-bug/commentary" "github.com/MichaelMure/git-bug/entity" - "github.com/MichaelMure/git-bug/identity" ) // Snapshot is a compiled form of the Bug data structure used for storage and merge type Snapshot struct { id entity.Id - Status Status - Title string - Comments []Comment - Labels []Label - Author identity.Interface - Actors []identity.Interface - Participants []identity.Interface - CreateTime time.Time + status Status + title string + description commentary.Comment + comments []commentary.Comment + labels []Label + authorID entity.Id + actorIDs []entity.Id + participantIDs []entity.Id + CreateTime time.Time - Timeline []TimelineItem + timeline []TimelineItem Operations []Operation } @@ -35,6 +36,51 @@ func (snap *Snapshot) Id() entity.Id { return snap.id } +// Description returns the description of the bug. +func (snap *Snapshot) Description() commentary.Comment { + return snap.description +} + +// Return the bugs status +func (snap *Snapshot) Status() Status { + return snap.status +} + +// Return the bugs title +func (snap *Snapshot) Title() string { + return snap.title +} + +// Return the bugs attached comments +func (snap *Snapshot) Comments() []commentary.Comment { + return snap.comments +} + +// Return the bugs assigned labels +func (snap *Snapshot) Labels() []Label { + return snap.labels +} + +// Return the bugs author +func (snap *Snapshot) Author() entity.Id { + return snap.authorID +} + +// Return the bugs actors +func (snap *Snapshot) Actors() []entity.Id { + return snap.actorIDs +} + +// Return the bugs participants +func (snap *Snapshot) Participants() []entity.Id { + return snap.participantIDs +} + +// Return the bugs timeline +func (snap *Snapshot) Timeline() []TimelineItem { + return snap.timeline +} + // Return the last time a bug was modified func (snap *Snapshot) EditTime() time.Time { if len(snap.Operations) == 0 { @@ -51,9 +97,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) { - for i := range snap.Timeline { - if snap.Timeline[i].Id() == id { - return snap.Timeline[i], nil + for i := range snap.timeline { + if snap.timeline[i].Id() == id { + return snap.timeline[i], nil } } @@ -61,42 +107,75 @@ func (snap *Snapshot) SearchTimelineItem(id entity.Id) (TimelineItem, error) { } // SearchComment will search for a comment matching the given hash -func (snap *Snapshot) SearchComment(id entity.Id) (*Comment, error) { - for _, c := range snap.Comments { - if c.id == id { - return &c, nil +func (snap *Snapshot) SearchComment(id entity.Id) (*commentary.Comment, error) { + if snap.description.Id() == id { + return &snap.description, nil + } + + for i, c := range snap.comments { + if c.Id() == id { + return &snap.comments[i], nil } } return nil, fmt.Errorf("comment item not found") } -// append the operation author to the actors list -func (snap *Snapshot) addActor(actor identity.Interface) { - for _, a := range snap.Actors { - if actor.Id() == a.Id() { - return +// Change current status to the new status +func (snap *Snapshot) setStatusTo(newStatus Status) { + snap.status = newStatus +} + +// Change current title to the new title +func (snap *Snapshot) changeTitleTo(newTitle string) { + snap.title = newTitle +} + +// Append the supplied comment to the snapshots comments +func (snap *Snapshot) appendComment(comment commentary.Comment) { + snap.comments = append(snap.comments, comment) +} + +// Add the supplied label to the snapshots labels +func (snap *Snapshot) addLabel(label Label) { + if !snap.HasLabel(label) { + snap.labels = append(snap.labels, label) + } +} + +// Remove the supplied label from the snapshots labels +func (snap *Snapshot) removeLabel(removed Label) { + for i, label := range snap.labels { + if label == removed { + snap.labels[i] = snap.labels[len(snap.labels)-1] + snap.labels = snap.labels[:len(snap.labels)-1] } } +} - snap.Actors = append(snap.Actors, actor) +// append the operation author to the actors list +func (snap *Snapshot) addActor(actor entity.Id) { + if !snap.HasActor(actor) { + snap.actorIDs = append(snap.actorIDs, actor) + } } // append the operation author to the participants list -func (snap *Snapshot) addParticipant(participant identity.Interface) { - for _, p := range snap.Participants { - if participant.Id() == p.Id() { - return - } +func (snap *Snapshot) addParticipant(participant entity.Id) { + if !snap.HasParticipant(participant) { + snap.participantIDs = append(snap.participantIDs, participant) } +} - snap.Participants = append(snap.Participants, participant) +// Append the supplied timelineitem to the snapshots timeline +func (snap *Snapshot) appendTimelineItem(item TimelineItem) { + snap.timeline = append(snap.timeline, item) } // HasParticipant return true if the id is a participant func (snap *Snapshot) HasParticipant(id entity.Id) bool { - for _, p := range snap.Participants { - if p.Id() == id { + for _, participantID := range snap.participantIDs { + if participantID == id { return true } } @@ -115,8 +194,8 @@ func (snap *Snapshot) HasAnyParticipant(ids ...entity.Id) bool { // HasActor return true if the id is a actor func (snap *Snapshot) HasActor(id entity.Id) bool { - for _, p := range snap.Actors { - if p.Id() == id { + for _, actorID := range snap.actorIDs { + if actorID == id { return true } } @@ -133,5 +212,14 @@ func (snap *Snapshot) HasAnyActor(ids ...entity.Id) bool { return false } +func (snap *Snapshot) HasLabel(label Label) bool { + for _, l := range snap.labels { + if l == label { + return true + } + } + return false +} + // Sign post method for gqlgen func (snap *Snapshot) IsAuthored() {} diff --git a/bug/timeline.go b/bug/timeline.go index a5ca4da5a..65740fcf0 100644 --- a/bug/timeline.go +++ b/bug/timeline.go @@ -1,80 +1,12 @@ package bug import ( - "strings" - "github.com/MichaelMure/git-bug/entity" - "github.com/MichaelMure/git-bug/identity" - "github.com/MichaelMure/git-bug/repository" - "github.com/MichaelMure/git-bug/util/timestamp" ) type TimelineItem interface { // ID return the identifier of the item Id() entity.Id -} - -// CommentHistoryStep hold one version of a message in the history -type CommentHistoryStep struct { - // The author of the edition, not necessarily the same as the author of the - // original comment - Author identity.Interface - // The new message - Message string - UnixTime timestamp.Timestamp -} - -// 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 -} - -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, - History: []CommentHistoryStep{ - { - Message: comment.Message, - UnixTime: comment.UnixTime, - }, - }, - } -} - -func (c *CommentTimelineItem) Id() entity.Id { - return c.id -} - -// 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.History = append(c.History, CommentHistoryStep{ - Author: comment.Author, - Message: comment.Message, - UnixTime: comment.UnixTime, - }) -} - -// Edited say if the comment was edited -func (c *CommentTimelineItem) Edited() bool { - return len(c.History) > 1 -} - -// MessageIsEmpty return true is the message is empty or only made of spaces -func (c *CommentTimelineItem) MessageIsEmpty() bool { - return len(strings.TrimSpace(c.Message)) == 0 + // Sign post method for gqlgen + IsAuthored() } diff --git a/cache/bug_excerpt.go b/cache/bug_excerpt.go index 342a05539..7cce92dd7 100644 --- a/cache/bug_excerpt.go +++ b/cache/bug_excerpt.go @@ -7,7 +7,6 @@ import ( "github.com/MichaelMure/git-bug/bug" "github.com/MichaelMure/git-bug/entity" - "github.com/MichaelMure/git-bug/identity" "github.com/MichaelMure/git-bug/util/lamport" ) @@ -57,14 +56,14 @@ func (l LegacyAuthorExcerpt) DisplayName() string { } func NewBugExcerpt(b bug.Interface, snap *bug.Snapshot) *BugExcerpt { - participantsIds := make([]entity.Id, 0, len(snap.Participants)) - for _, participant := range snap.Participants { - participantsIds = append(participantsIds, participant.Id()) + participantsIds := make([]entity.Id, 0, len(snap.Participants())) + for _, participantID := range snap.Participants() { + participantsIds = append(participantsIds, participantID) } - actorsIds := make([]entity.Id, 0, len(snap.Actors)) - for _, actor := range snap.Actors { - actorsIds = append(actorsIds, actor.Id()) + actorsIds := make([]entity.Id, 0, len(snap.Actors())) + for _, actorID := range snap.Actors() { + actorsIds = append(actorsIds, actorID) } e := &BugExcerpt{ @@ -73,22 +72,16 @@ func NewBugExcerpt(b bug.Interface, snap *bug.Snapshot) *BugExcerpt { EditLamportTime: b.EditLamportTime(), CreateUnixTime: b.FirstOp().Time().Unix(), EditUnixTime: snap.EditTime().Unix(), - Status: snap.Status, - Labels: snap.Labels, + Status: snap.Status(), + Labels: snap.Labels(), Actors: actorsIds, Participants: participantsIds, - Title: snap.Title, - LenComments: len(snap.Comments), + Title: snap.Title(), + LenComments: len(snap.Comments()), CreateMetadata: b.FirstOp().AllMetadata(), } - switch snap.Author.(type) { - case *identity.Identity, *identity.IdentityStub, *IdentityCache: - e.AuthorId = snap.Author.Id() - default: - panic("unhandled identity type") - } - + e.AuthorId = snap.Author() return e } diff --git a/cache/repo_cache_bug.go b/cache/repo_cache_bug.go index c019da68a..7af739768 100644 --- a/cache/repo_cache_bug.go +++ b/cache/repo_cache_bug.go @@ -289,7 +289,17 @@ func (c *RepoCache) ResolveComment(prefix string) (*BugCache, entity.Id, error) return nil, entity.UnsetId, err } - for _, comment := range b.Snapshot().Comments { + if b.Snapshot().Description().Id().HasPrefix(prefix) { + matchingBugIds = append(matchingBugIds, bugId) + matchingBug = b + matchingCommentId = b.Snapshot().Description().Id() + } + + //TODO iteration of comments should be replaced via *SearchComment*. + // To prevent this error in further code, the removal of the access to comments and instead provide a + // clear interface to operate on these comments. Especially as the returned array is a reference... + // E.g. provide Snapshot::Comments(Handler), with Handler being the function to operate on comments + for _, comment := range b.Snapshot().Comments() { if comment.Id().HasPrefix(prefix) { matchingBugIds = append(matchingBugIds, bugId) matchingBug = b @@ -538,11 +548,11 @@ func (c *RepoCache) addBugToSearchIndex(snap *bug.Snapshot) error { return sb.String() } - for _, comment := range snap.Comments { - searchableBug.Text = append(searchableBug.Text, normalize(comment.Message)) + for _, comment := range snap.Comments() { + searchableBug.Text = append(searchableBug.Text, normalize(comment.Message())) } - searchableBug.Text = append(searchableBug.Text, normalize(snap.Title)) + searchableBug.Text = append(searchableBug.Text, normalize(snap.Title())) index, err := c.repo.GetBleveIndex("bug") if err != nil { diff --git a/commands/comment.go b/commands/comment.go index 90657e4a9..a67cfadbe 100644 --- a/commands/comment.go +++ b/commands/comment.go @@ -34,15 +34,15 @@ func runComment(env *Env, args []string) error { snap := b.Snapshot() - for i, comment := range snap.Comments { + for i, comment := range snap.Comments() { if i != 0 { env.out.Println() } - env.out.Printf("Author: %s\n", colors.Magenta(comment.Author.DisplayName())) + 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("Date: %s\n\n", comment.FormatTime()) - env.out.Println(text.LeftPadLines(comment.Message, 4)) + env.out.Printf("Date: %s\n\n", comment.CreatedAt().FormatTime()) + env.out.Println(text.LeftPadLines(comment.Message(), 4)) } return nil diff --git a/commands/label.go b/commands/label.go index d108b0894..5268fb00a 100644 --- a/commands/label.go +++ b/commands/label.go @@ -32,7 +32,7 @@ func runLabel(env *Env, args []string) error { snap := b.Snapshot() - for _, l := range snap.Labels { + for _, l := range snap.Labels() { env.out.Println(l) } diff --git a/commands/ls.go b/commands/ls.go index 9134d7527..fcca8f3bf 100644 --- a/commands/ls.go +++ b/commands/ls.go @@ -223,11 +223,11 @@ func lsDefaultFormatter(env *Env, bugExcerpts []*cache.BugExcerpt) error { titleFmt := text.LeftPadMaxLine(strings.TrimSpace(b.Title), 50-text.Len(labelsFmt), 0) authorFmt := text.LeftPadMaxLine(author.DisplayName(), 15, 0) - comments := fmt.Sprintf("%3d 💬", b.LenComments-1) - if b.LenComments-1 <= 0 { + comments := fmt.Sprintf("%3d 💬", b.LenComments) + if b.LenComments <= 0 { comments = "" } - if b.LenComments-1 > 999 { + if b.LenComments > 999 { comments = " ∞ 💬" } diff --git a/commands/select.go b/commands/select.go index 34d00a325..333189c83 100644 --- a/commands/select.go +++ b/commands/select.go @@ -53,7 +53,7 @@ func runSelect(env *Env, args []string) error { return err } - env.out.Printf("selected bug %s: %s\n", b.Id().Human(), b.Snapshot().Title) + env.out.Printf("selected bug %s: %s\n", b.Id().Human(), b.Snapshot().Title()) return nil } diff --git a/commands/show.go b/commands/show.go index 551403578..ce9cda1de 100644 --- a/commands/show.go +++ b/commands/show.go @@ -2,7 +2,6 @@ package commands import ( "encoding/json" - "errors" "fmt" "strings" @@ -10,6 +9,7 @@ import ( "github.com/MichaelMure/git-bug/bug" _select "github.com/MichaelMure/git-bug/commands/select" + "github.com/MichaelMure/git-bug/commentary" "github.com/MichaelMure/git-bug/util/colors" ) @@ -50,16 +50,17 @@ func runShow(env *Env, opts showOptions, args []string) error { snap := b.Snapshot() - if len(snap.Comments) == 0 { - return errors.New("invalid bug: no comment") + author, err := env.backend.ResolveIdentity(snap.Author()) + if err != nil { + return err } if opts.fields != "" { switch opts.fields { case "author": - env.out.Printf("%s\n", snap.Author.DisplayName()) + env.out.Printf("%s\n", author.DisplayName()) case "authorEmail": - env.out.Printf("%s\n", snap.Author.Email()) + env.out.Printf("%s\n", author.Email()) case "createTime": env.out.Printf("%s\n", snap.CreateTime.String()) case "lastEdit": @@ -69,23 +70,31 @@ func runShow(env *Env, opts showOptions, args []string) error { case "id": env.out.Printf("%s\n", snap.Id()) case "labels": - for _, l := range snap.Labels { + for _, l := range snap.Labels() { env.out.Printf("%s\n", l.String()) } case "actors": - for _, a := range snap.Actors { - env.out.Printf("%s\n", a.DisplayName()) + for _, id := range snap.Actors() { + actor, err := env.backend.ResolveIdentityExcerpt(id) + if err != nil { + return err + } + env.out.Printf("%s\n", actor.DisplayName()) } case "participants": - for _, p := range snap.Participants { - env.out.Printf("%s\n", p.DisplayName()) + for _, id := range snap.Participants() { + participant, err := env.backend.ResolveIdentityExcerpt(id) + if err != nil { + return err + } + env.out.Printf("%s\n", participant.DisplayName()) } case "shortId": env.out.Printf("%s\n", snap.Id().Human()) case "status": - env.out.Printf("%s\n", snap.Status) + env.out.Printf("%s\n", snap.Status()) case "title": - env.out.Printf("%s\n", snap.Title) + env.out.Printf("%s\n", snap.Title()) default: return fmt.Errorf("\nUnsupported field: %s\n", opts.fields) } @@ -106,15 +115,20 @@ func runShow(env *Env, opts showOptions, args []string) error { } func showDefaultFormatter(env *Env, snapshot *bug.Snapshot) error { + author, err := env.backend.ResolveIdentityExcerpt(snapshot.Author()) + if err != nil { + return err + } + // Header env.out.Printf("%s [%s] %s\n\n", colors.Cyan(snapshot.Id().Human()), - colors.Yellow(snapshot.Status), - snapshot.Title, + colors.Yellow(snapshot.Status()), + snapshot.Title(), ) env.out.Printf("%s opened this issue %s\n", - colors.Magenta(snapshot.Author.DisplayName()), + colors.Magenta(author.DisplayName()), snapshot.CreateTime.String(), ) @@ -123,9 +137,9 @@ func showDefaultFormatter(env *Env, snapshot *bug.Snapshot) error { ) // Labels - var labels = make([]string, len(snapshot.Labels)) - for i := range snapshot.Labels { - labels[i] = string(snapshot.Labels[i]) + var labels = make([]string, len(snapshot.Labels())) + for _, label := range snapshot.Labels() { + labels = append(labels, label.String()) } env.out.Printf("labels: %s\n", @@ -133,9 +147,13 @@ func showDefaultFormatter(env *Env, snapshot *bug.Snapshot) error { ) // Actors - var actors = make([]string, len(snapshot.Actors)) - for i := range snapshot.Actors { - actors[i] = snapshot.Actors[i].DisplayName() + var actors = make([]string, len(snapshot.Actors())) + for i, id := range snapshot.Actors() { + actor, err := env.backend.ResolveIdentityExcerpt(id) + if err != nil { + return err + } + actors[i] = actor.DisplayName() } env.out.Printf("actors: %s\n", @@ -143,32 +161,61 @@ func showDefaultFormatter(env *Env, snapshot *bug.Snapshot) error { ) // Participants - var participants = make([]string, len(snapshot.Participants)) - for i := range snapshot.Participants { - participants[i] = snapshot.Participants[i].DisplayName() + var participants = make([]string, len(snapshot.Participants())) + for i, id := range snapshot.Participants() { + participant, err := env.backend.ResolveIdentityExcerpt(id) + if err != nil { + return err + } + participants[i] = participant.DisplayName() } env.out.Printf("participants: %s\n\n", strings.Join(participants, ", "), ) - // Comments + // Description + env.out.Printf("Description:\n\n") indent := " " + description := snapshot.Description() + // print description header + env.out.Printf("%s%s %s <%s>\n\n", + indent, + description.Id().Human(), + description.Author().DisplayName(), + description.Author().Email(), + ) + // print description message + if description.HasEmptyMessage() { + env.out.Printf("%s%s\n\n\n", + indent, + colors.BlackBold(colors.WhiteBg("No description provided.")), + ) + } else { + env.out.Printf("%s%s\n\n\n", + indent, + description.Message(), + ) + } + + // Comments + env.out.Printf("Comments:\n\n") + indent = " " - for i, comment := range snapshot.Comments { + for i, comment := range snapshot.Comments() { var message string env.out.Printf("%s%s #%d %s <%s>\n\n", indent, comment.Id().Human(), i, - comment.Author.DisplayName(), - comment.Author.Email(), + comment.Author().DisplayName(), + comment.Author().Email(), ) - if comment.Message == "" { - message = colors.BlackBold(colors.WhiteBg("No description provided.")) + if comment.Message() == "" { + message = colors.BlackBold(colors.WhiteBg("This comment has no message.")) } else { - message = comment.Message + message = comment.Message() } env.out.Printf("%s%s\n\n\n", @@ -201,39 +248,52 @@ type JSONComment struct { Message string `json:"message"` } -func NewJSONComment(comment bug.Comment) JSONComment { +func NewJSONComment(comment commentary.Comment) JSONComment { return JSONComment{ Id: comment.Id().String(), HumanId: comment.Id().Human(), - Author: NewJSONIdentity(comment.Author), - Message: comment.Message, + Author: NewJSONIdentity(comment.Author()), + Message: comment.Message(), } } func showJsonFormatter(env *Env, snapshot *bug.Snapshot) error { + author, err := env.backend.ResolveIdentity(snapshot.Author()) + if err != nil { + return err + } + jsonBug := JSONBugSnapshot{ Id: snapshot.Id().String(), HumanId: snapshot.Id().Human(), CreateTime: NewJSONTime(snapshot.CreateTime, 0), EditTime: NewJSONTime(snapshot.EditTime(), 0), - Status: snapshot.Status.String(), - Labels: snapshot.Labels, - Title: snapshot.Title, - Author: NewJSONIdentity(snapshot.Author), + Status: snapshot.Status().String(), + Labels: snapshot.Labels(), + Title: snapshot.Title(), + Author: NewJSONIdentity(author), } - jsonBug.Actors = make([]JSONIdentity, len(snapshot.Actors)) - for i, element := range snapshot.Actors { - jsonBug.Actors[i] = NewJSONIdentity(element) + jsonBug.Actors = make([]JSONIdentity, len(snapshot.Actors())) + for i, id := range snapshot.Actors() { + actor, err := env.backend.ResolveIdentity(id) + if err != nil { + return err + } + jsonBug.Actors[i] = NewJSONIdentity(actor) } - jsonBug.Participants = make([]JSONIdentity, len(snapshot.Participants)) - for i, element := range snapshot.Participants { - jsonBug.Participants[i] = NewJSONIdentity(element) + jsonBug.Participants = make([]JSONIdentity, len(snapshot.Participants())) + for i, id := range snapshot.Participants() { + participant, err := env.backend.ResolveIdentity(id) + if err != nil { + return err + } + jsonBug.Participants[i] = NewJSONIdentity(participant) } - jsonBug.Comments = make([]JSONComment, len(snapshot.Comments)) - for i, comment := range snapshot.Comments { + jsonBug.Comments = make([]JSONComment, len(snapshot.Comments())) + for i, comment := range snapshot.Comments() { jsonBug.Comments[i] = NewJSONComment(comment) } @@ -244,15 +304,20 @@ func showJsonFormatter(env *Env, snapshot *bug.Snapshot) error { } func showOrgModeFormatter(env *Env, snapshot *bug.Snapshot) error { + author, err := env.backend.ResolveIdentityExcerpt(snapshot.Author()) + if err != nil { + return err + } + // Header env.out.Printf("%s [%s] %s\n", snapshot.Id().Human(), - snapshot.Status, - snapshot.Title, + snapshot.Status(), + snapshot.Title(), ) env.out.Printf("* Author: %s\n", - snapshot.Author.DisplayName(), + author.DisplayName(), ) env.out.Printf("* Creation Time: %s\n", @@ -264,8 +329,8 @@ func showOrgModeFormatter(env *Env, snapshot *bug.Snapshot) error { ) // Labels - var labels = make([]string, len(snapshot.Labels)) - for i, label := range snapshot.Labels { + var labels = make([]string, len(snapshot.Labels())) + for i, label := range snapshot.Labels() { labels[i] = string(label) } @@ -277,10 +342,14 @@ func showOrgModeFormatter(env *Env, snapshot *bug.Snapshot) error { } // Actors - var actors = make([]string, len(snapshot.Actors)) - for i, actor := range snapshot.Actors { + var actors = make([]string, len(snapshot.Actors())) + for i, id := range snapshot.Actors() { + actor, err := env.backend.ResolveIdentityExcerpt(id) + if err != nil { + return err + } actors[i] = fmt.Sprintf("%s %s", - actor.Id().Human(), + actor.Id.Human(), actor.DisplayName(), ) } @@ -290,10 +359,14 @@ func showOrgModeFormatter(env *Env, snapshot *bug.Snapshot) error { ) // Participants - var participants = make([]string, len(snapshot.Participants)) - for i, participant := range snapshot.Participants { + var participants = make([]string, len(snapshot.Participants())) + for i, id := range snapshot.Participants() { + participant, err := env.backend.ResolveIdentityExcerpt(id) + if err != nil { + return err + } participants[i] = fmt.Sprintf("%s %s", - participant.Id().Human(), + participant.Id.Human(), participant.DisplayName(), ) } @@ -304,15 +377,15 @@ func showOrgModeFormatter(env *Env, snapshot *bug.Snapshot) error { env.out.Printf("* Comments:\n") - for i, comment := range snapshot.Comments { + for i, comment := range snapshot.Comments() { var message string env.out.Printf("** #%d %s\n", - i, comment.Author.DisplayName()) + i, comment.Author().DisplayName()) - if comment.Message == "" { + if comment.Message() == "" { message = "No description provided." } else { - message = strings.ReplaceAll(comment.Message, "\n", "\n: ") + message = strings.ReplaceAll(comment.Message(), "\n", "\n: ") } env.out.Printf(": %s\n", message) diff --git a/commands/status.go b/commands/status.go index c1e45c5fa..08e5f2853 100644 --- a/commands/status.go +++ b/commands/status.go @@ -31,7 +31,7 @@ func runStatus(env *Env, args []string) error { snap := b.Snapshot() - env.out.Println(snap.Status) + env.out.Println(snap.Status()) return nil } diff --git a/commands/title.go b/commands/title.go index c42935306..4c5d0ea0f 100644 --- a/commands/title.go +++ b/commands/title.go @@ -30,7 +30,7 @@ func runTitle(env *Env, args []string) error { snap := b.Snapshot() - env.out.Println(snap.Title) + env.out.Println(snap.Title()) return nil } diff --git a/commands/title_edit.go b/commands/title_edit.go index 810c5e622..3fe6e2f45 100644 --- a/commands/title_edit.go +++ b/commands/title_edit.go @@ -50,7 +50,7 @@ func runTitleEdit(env *Env, opts titleEditOptions, args []string) error { env.err.Println("No title given. Use -m or -F option to specify a title. Aborting.") return nil } - opts.title, err = input.BugTitleEditorInput(env.repo, snap.Title) + opts.title, err = input.BugTitleEditorInput(env.repo, snap.Title()) if err == input.ErrEmptyTitle { env.out.Println("Empty title, aborting.") return nil @@ -60,7 +60,7 @@ func runTitleEdit(env *Env, opts titleEditOptions, args []string) error { } } - if opts.title == snap.Title { + if opts.title == snap.Title() { env.err.Println("No change, aborting.") } diff --git a/commentary/comment.go b/commentary/comment.go new file mode 100644 index 000000000..1884cd4f8 --- /dev/null +++ b/commentary/comment.go @@ -0,0 +1,127 @@ +package commentary + +import ( + "fmt" + "strings" + + "github.com/MichaelMure/git-bug/entity" + "github.com/MichaelMure/git-bug/identity" + "github.com/MichaelMure/git-bug/repository" + "github.com/MichaelMure/git-bug/util/text" + "github.com/MichaelMure/git-bug/util/timestamp" +) + +// Comment represent a comment in a Bug +type UnsafeComment struct { + // id should be the result of entity.CombineIds with the Bug id and the id + // of the Operation that created the comment + Id 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. + CreatedAt timestamp.Timestamp +} + +// Edit hold one version of a message in the history +type Alteration struct { + // The author of the edition, not necessarily the same as the author of the + // original comment + Author identity.Interface + // The new message + Message string + // The time the alteration was created + CreatedAt timestamp.Timestamp +} + +type Comment struct { + valid UnsafeComment + history []Alteration + lastEdited timestamp.Timestamp +} + +func (unsafeComment UnsafeComment) Validate() (*Comment, error) { + if unsafeComment.Id == "" { + // simply panic as it would be a coding error (no id provided at construction) + panic("no id") + } + + if !text.Safe(unsafeComment.Message) { + return nil, fmt.Errorf("message is not fully printable") + } + + return &Comment{valid: unsafeComment}, nil +} + +// Id return the Comment identifier. +func (c Comment) Id() entity.Id { + return c.valid.Id +} + +// Message returns the message text of the comment. +func (c Comment) Message() string { + return c.valid.Message +} + +// Author returns the author of the comment. +func (c Comment) Author() identity.Interface { + return c.valid.Author +} + +// Edited say if the comment was edited. +func (c Comment) WasEdited() bool { + return len(c.history) > 1 +} + +// MessageIsEmpty return true is the message is empty or only made of spaces. +func (c Comment) HasEmptyMessage() bool { + return len(strings.TrimSpace(c.Message())) == 0 +} + +// Propose requests an alteration of the comment. If something wents wrong, +// nothing happens to the comment and an error is returned instead. +func (c *Comment) Edit(alteration Alteration) error { + if !text.Safe(alteration.Message) { + return fmt.Errorf("message is not fully printable") + } + c.history = append(c.history, Alteration{ + Message: c.valid.Message, + Author: c.valid.Author, + CreatedAt: c.valid.CreatedAt, + }) + c.lastEdited = alteration.CreatedAt + c.valid.Message = alteration.Message + c.valid.Author = alteration.Author + c.valid.CreatedAt = alteration.CreatedAt + return nil +} + +// AttacheFiles attaches the given files to the comment. +func (c Comment) AttacheFiles(files []repository.Hash) { + c.valid.Files = files +} + +// Files return the comments attached files. +func (c Comment) Files() []repository.Hash { + return c.valid.Files +} + +// History returns the comments alterations. +func (c Comment) History() []Alteration { + return c.history +} + +// CreationTimestamp returns the date and time of comments creation. +func (c Comment) CreatedAt() timestamp.Timestamp { + return c.valid.CreatedAt +} + +// LastEdited returns the date and time of comments last edit. +func (c Comment) LastEdited() timestamp.Timestamp { + return c.lastEdited +} + +// Sign post method for gqlgen +func (c Comment) IsAuthored() {} diff --git a/go.mod b/go.mod index fb9882a7a..0404790f3 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/araddon/dateparse v0.0.0-20190622164848-0fb0a474d195 github.com/awesome-gocui/gocui v0.6.1-0.20191115151952-a34ffb055986 github.com/blevesearch/bleve v1.0.14 - github.com/cheekybits/genny v0.0.0-20170328200008-9127e812e1e9 + github.com/cheekybits/genny v1.0.0 github.com/corpix/uarand v0.1.1 // indirect github.com/dustin/go-humanize v1.0.0 github.com/fatih/color v1.12.0 diff --git a/go.sum b/go.sum index b880a86e9..257773320 100644 --- a/go.sum +++ b/go.sum @@ -112,6 +112,8 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cheekybits/genny v0.0.0-20170328200008-9127e812e1e9 h1:a1zrFsLFac2xoM6zG1u72DWJwZG3ayttYLfmLbxVETk= github.com/cheekybits/genny v0.0.0-20170328200008-9127e812e1e9/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= +github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= +github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -544,6 +546,7 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -701,6 +704,7 @@ golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d h1:W07d4xkoAUSNOkOzdzXCdFGxT7o2rW4q8M34tB2i//k= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/termui/label_select.go b/termui/label_select.go index dfba20a62..6b380be0a 100644 --- a/termui/label_select.go +++ b/termui/label_select.go @@ -39,7 +39,7 @@ func (ls *labelSelect) SetBug(cache *cache.RepoCache, bug *cache.BugCache) { ls.labels = cache.ValidLabels() // Find which labels are currently applied to the bug - bugLabels := bug.Snapshot().Labels + bugLabels := bug.Snapshot().Labels() labelSelect := make([]bool, len(ls.labels)) for i, label := range ls.labels { for _, bugLabel := range bugLabels { @@ -270,7 +270,7 @@ func (ls *labelSelect) abort(g *gocui.Gui, v *gocui.View) error { } func (ls *labelSelect) saveAndReturn(g *gocui.Gui, v *gocui.View) error { - bugLabels := ls.bug.Snapshot().Labels + bugLabels := ls.bug.Snapshot().Labels() var selectedLabels []bug.Label for i, label := range ls.labels { if ls.labelSelect[i] { diff --git a/termui/show_bug.go b/termui/show_bug.go index 0710fa34b..54917dc95 100644 --- a/termui/show_bug.go +++ b/termui/show_bug.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/MichaelMure/go-term-text" + text "github.com/MichaelMure/go-term-text" "github.com/awesome-gocui/gocui" "github.com/MichaelMure/git-bug/bug" @@ -216,18 +216,21 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error { sb.mainSelectableView = nil - createTimelineItem := snap.Timeline[0].(*bug.CreateTimelineItem) - edited := "" - if createTimelineItem.Edited() { + if snap.Description().WasEdited() { edited = " (edited)" } + author, err := sb.cache.ResolveIdentityExcerpt(snap.Author()) + if err != nil { + return err + } + bugHeader := fmt.Sprintf("[%s] %s\n\n[%s] %s opened this bug on %s%s", colors.Cyan(snap.Id().Human()), - colors.Bold(snap.Title), - colors.Yellow(snap.Status), - colors.Magenta(snap.Author.DisplayName()), + colors.Bold(snap.Title()), + colors.Yellow(snap.Status()), + colors.Magenta(author.DisplayName()), snap.CreateTime.Format(timeLayout), edited, ) @@ -241,47 +244,45 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error { _, _ = fmt.Fprint(v, bugHeader) y0 += lines + 1 - for _, op := range snap.Timeline { + var content string + desc := snap.Description() + if desc.HasEmptyMessage() { + content, lines = text.WrapLeftPadded(emptyMessagePlaceholder(), maxX-1, 4) + } else { + content, lines = text.WrapLeftPadded(desc.Message(), maxX-1, 4) + } + + v, err = sb.createOpView(g, desc.Id().String(), x0, y0, maxX+1, lines, true) + if err != nil { + return err + } + _, _ = fmt.Fprint(v, content) + y0 += lines + 2 + + for _, op := range snap.Timeline() { viewName := op.Id().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 switch op := op.(type) { - - case *bug.CreateTimelineItem: - var content string - var lines int - - if op.MessageIsEmpty() { - content, lines = text.WrapLeftPadded(emptyMessagePlaceholder(), maxX-1, 4) - } else { - content, lines = text.WrapLeftPadded(op.Message, maxX-1, 4) - } - - v, err := sb.createOpView(g, viewName, x0, y0, maxX+1, lines, true) - if err != nil { - return err - } - _, _ = fmt.Fprint(v, content) - y0 += lines + 2 - - case *bug.AddCommentTimelineItem: + case *bug.CommentTimelineItem: edited := "" - if op.Edited() { + comment, _ := snap.SearchComment(op.Id()) + if comment.WasEdited() { edited = " (edited)" } var message string - if op.MessageIsEmpty() { + if comment.HasEmptyMessage() { message, _ = text.WrapLeftPadded(emptyMessagePlaceholder(), maxX-1, 4) } else { - message, _ = text.WrapLeftPadded(op.Message, maxX-1, 4) + message, _ = text.WrapLeftPadded(comment.Message(), maxX-1, 4) } content := fmt.Sprintf("%s commented on %s%s\n\n%s", - colors.Magenta(op.Author.DisplayName()), - op.CreatedAt.Time().Format(timeLayout), + colors.Magenta(comment.Author().DisplayName()), + comment.CreatedAt().Time().Format(timeLayout), edited, message, ) @@ -427,8 +428,8 @@ func (sb *showBug) renderSidebar(g *gocui.Gui, sideView *gocui.View) error { sb.sideSelectableView = nil - labelStr := make([]string, len(snap.Labels)) - for i, l := range snap.Labels { + labelStr := make([]string, len(snap.Labels())) + for i, l := range snap.Labels() { lc := l.Color() lc256 := lc.Term256() labelStr[i] = lc256.Escape() + "◼ " + lc256.Unescape() + l.String() @@ -622,7 +623,7 @@ func (sb *showBug) setTitle(g *gocui.Gui, v *gocui.View) error { } func (sb *showBug) toggleOpenClose(g *gocui.Gui, v *gocui.View) error { - switch sb.bug.Snapshot().Status { + switch sb.bug.Snapshot().Status() { case bug.OpenStatus: _, err := sb.bug.Close() return err @@ -651,10 +652,9 @@ func (sb *showBug) edit(g *gocui.Gui, v *gocui.View) error { } switch op := op.(type) { - case *bug.AddCommentTimelineItem: - return editCommentWithEditor(sb.bug, op.Id(), op.Message) - case *bug.CreateTimelineItem: - return editCommentWithEditor(sb.bug, op.Id(), op.Message) + case *bug.CommentTimelineItem: + comment, _ := snap.SearchComment(op.Id()) + return editCommentWithEditor(sb.bug, comment.Id(), comment.Message()) case *bug.LabelChangeTimelineItem: return sb.editLabels(g, snap) } diff --git a/termui/termui.go b/termui/termui.go index 3e7f43b93..1283edf4f 100644 --- a/termui/termui.go +++ b/termui/termui.go @@ -300,7 +300,7 @@ func setTitleWithEditor(bug *cache.BugCache) error { snap := bug.Snapshot() - title, err := input.BugTitleEditorInput(ui.cache, snap.Title) + title, err := input.BugTitleEditorInput(ui.cache, snap.Title()) if err != nil && err != input.ErrEmptyTitle { return err @@ -308,7 +308,7 @@ func setTitleWithEditor(bug *cache.BugCache) error { if err == input.ErrEmptyTitle { ui.msgPopup.Activate(msgPopupErrorTitle, "Empty title, aborting.") - } else if title == snap.Title { + } else if title == snap.Title() { ui.msgPopup.Activate(msgPopupErrorTitle, "No change, aborting.") } else { _, err := bug.SetTitle(text.CleanupOneLine(title)) diff --git a/util/timestamp/timestamp.go b/util/timestamp/timestamp.go index 4f587cb46..57a3e56ad 100644 --- a/util/timestamp/timestamp.go +++ b/util/timestamp/timestamp.go @@ -1,9 +1,22 @@ package timestamp -import "time" +import ( + "time" + + "github.com/dustin/go-humanize" +) type Timestamp int64 func (t Timestamp) Time() time.Time { return time.Unix(int64(t), 0) } + +// FormatTimeRel format the timestamp for human consumption +func (t Timestamp) FormatTimeRel() string { + return humanize.Time(t.Time()) +} + +func (t Timestamp) FormatTime() string { + return t.Time().Format("Mon Jan 2 15:04:05 2006 +0200") +} diff --git a/webui/src/pages/bug/Bug.graphql b/webui/src/pages/bug/Bug.graphql index 498242c0a..1c3163278 100644 --- a/webui/src/pages/bug/Bug.graphql +++ b/webui/src/pages/bug/Bug.graphql @@ -1,10 +1,14 @@ #import "../components/fragments.graphql" +#import "./MessageCommentFragment.graphql" fragment Bug on Bug { id humanId status title + description { + ...Description + } labels { ...Label } diff --git a/webui/src/pages/bug/EditCommentForm.graphql b/webui/src/pages/bug/EditCommentForm.graphql index 4765b75ca..49a8f5338 100644 --- a/webui/src/pages/bug/EditCommentForm.graphql +++ b/webui/src/pages/bug/EditCommentForm.graphql @@ -1,5 +1,4 @@ #import "./MessageCommentFragment.graphql" -#import "./MessageCreateFragment.graphql" mutation EditComment($input: EditCommentInput!) { editComment(input: $input) { @@ -7,8 +6,7 @@ mutation EditComment($input: EditCommentInput!) { id timeline { comments: nodes { - ...Create - ...AddComment + ...Comment } } } diff --git a/webui/src/pages/bug/EditCommentForm.tsx b/webui/src/pages/bug/EditCommentForm.tsx index 8fa659b3b..55e5aaf44 100644 --- a/webui/src/pages/bug/EditCommentForm.tsx +++ b/webui/src/pages/bug/EditCommentForm.tsx @@ -8,8 +8,10 @@ import CommentInput from '../../components/CommentInput/CommentInput'; import { BugFragment } from './Bug.generated'; import { useEditCommentMutation } from './EditCommentForm.generated'; -import { AddCommentFragment } from './MessageCommentFragment.generated'; -import { CreateFragment } from './MessageCreateFragment.generated'; +import { + DescriptionFragment, + CommentFragment, +} from './MessageCommentFragment.generated'; type StyleProps = { loading: boolean }; const useStyles = makeStyles((theme) => ({ @@ -41,7 +43,7 @@ const useStyles = makeStyles((theme) => ({ type Props = { bug: BugFragment; - comment: AddCommentFragment | CreateFragment; + comment: DescriptionFragment | CommentFragment; onCancel?: () => void; onPostSubmit?: (comments: any) => void; }; @@ -63,10 +65,8 @@ function EditCommentForm({ bug, comment, onCancel, onPostSubmit }: Props) { }, }, }).then((result) => { - const comments = result.data?.editComment.bug.timeline.comments as ( - | AddCommentFragment - | CreateFragment - )[]; + const comments = result.data?.editComment.bug.timeline + .comments as CommentFragment[]; // NOTE Searching for the changed comment could be dropped if GraphQL get // filter by id argument for timelineitems const modifiedComment = comments.find((elem) => elem.id === comment.id); diff --git a/webui/src/pages/bug/Message.tsx b/webui/src/pages/bug/Message.tsx index 51087faa3..778ff93a5 100644 --- a/webui/src/pages/bug/Message.tsx +++ b/webui/src/pages/bug/Message.tsx @@ -14,8 +14,10 @@ import IfLoggedIn from 'src/components/IfLoggedIn/IfLoggedIn'; import { BugFragment } from './Bug.generated'; import EditCommentForm from './EditCommentForm'; -import { AddCommentFragment } from './MessageCommentFragment.generated'; -import { CreateFragment } from './MessageCreateFragment.generated'; +import { + DescriptionFragment, + CommentFragment, +} from './MessageCommentFragment.generated'; import MessageHistoryDialog from './MessageHistoryDialog'; const useStyles = makeStyles((theme) => ({ @@ -118,7 +120,7 @@ function HistoryMenuToggleButton({ bugId, commentId }: HistBtnProps) { type Props = { bug: BugFragment; - op: AddCommentFragment | CreateFragment; + op: DescriptionFragment | CommentFragment; }; function Message({ bug, op }: Props) { const classes = useStyles(); @@ -138,7 +140,7 @@ function Message({ bug, op }: Props) { commented - {comment.edited && ( + {comment.wasEdited && ( )} @@ -172,7 +174,7 @@ function Message({ bug, op }: Props) { switchToEditMode(false); }; - const onPostSubmit = (comment: AddCommentFragment | CreateFragment) => { + const onPostSubmit = (comment: CommentFragment) => { setComment(comment); switchToEditMode(false); }; diff --git a/webui/src/pages/bug/MessageCommentFragment.graphql b/webui/src/pages/bug/MessageCommentFragment.graphql index c852b4b0b..091c6029a 100644 --- a/webui/src/pages/bug/MessageCommentFragment.graphql +++ b/webui/src/pages/bug/MessageCommentFragment.graphql @@ -1,10 +1,22 @@ #import "../../components/fragments.graphql" -fragment AddComment on AddCommentTimelineItem { +fragment Description on Comment { id createdAt ...authored - edited + wasEdited + message + history { + message + date + } +} + +fragment Comment on CommentTimelineItem { + id + createdAt + ...authored + wasEdited message history { message diff --git a/webui/src/pages/bug/MessageCreateFragment.graphql b/webui/src/pages/bug/MessageCreateFragment.graphql deleted file mode 100644 index 1f4647b65..000000000 --- a/webui/src/pages/bug/MessageCreateFragment.graphql +++ /dev/null @@ -1,13 +0,0 @@ -#import "../../components/fragments.graphql" - -fragment Create on CreateTimelineItem { - id - createdAt - ...authored - edited - message - history { - message - date - } -} diff --git a/webui/src/pages/bug/MessageHistory.graphql b/webui/src/pages/bug/MessageHistory.graphql index e90eb4595..32afac7d5 100644 --- a/webui/src/pages/bug/MessageHistory.graphql +++ b/webui/src/pages/bug/MessageHistory.graphql @@ -1,13 +1,11 @@ #import "./MessageCommentFragment.graphql" -#import "./MessageCreateFragment.graphql" query MessageHistory($bugIdPrefix: String!) { repository { bug(prefix: $bugIdPrefix) { timeline { comments: nodes { - ...Create - ...AddComment + ...Comment } } } diff --git a/webui/src/pages/bug/MessageHistoryDialog.tsx b/webui/src/pages/bug/MessageHistoryDialog.tsx index df8915d9c..7d7c5fa5a 100644 --- a/webui/src/pages/bug/MessageHistoryDialog.tsx +++ b/webui/src/pages/bug/MessageHistoryDialog.tsx @@ -24,8 +24,7 @@ import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import Content from '../../components/Content'; -import { AddCommentFragment } from './MessageCommentFragment.generated'; -import { CreateFragment } from './MessageCreateFragment.generated'; +import { CommentFragment } from './MessageCommentFragment.generated'; import { useMessageHistoryQuery } from './MessageHistory.generated'; const styles = (theme: Theme) => @@ -167,10 +166,8 @@ function MessageHistoryDialog({ bugId, commentId, open, onClose }: Props) { ); } - const comments = data?.repository?.bug?.timeline.comments as ( - | AddCommentFragment - | CreateFragment - )[]; + const comments = data?.repository?.bug?.timeline + .comments as CommentFragment[]; // NOTE Searching for the changed comment could be dropped if GraphQL get // filter by id argument for timelineitems const comment = comments.find((elem) => elem.id === commentId); diff --git a/webui/src/pages/bug/Timeline.tsx b/webui/src/pages/bug/Timeline.tsx index 60459a532..cb6209749 100644 --- a/webui/src/pages/bug/Timeline.tsx +++ b/webui/src/pages/bug/Timeline.tsx @@ -27,11 +27,10 @@ function Timeline({ bug, ops }: Props) { return (
+ {ops.map((op, index) => { switch (op.__typename) { - case 'CreateTimelineItem': - return ; - case 'AddCommentTimelineItem': + case 'CommentTimelineItem': return ; case 'LabelChangeTimelineItem': return ; diff --git a/webui/src/pages/bug/TimelineQuery.graphql b/webui/src/pages/bug/TimelineQuery.graphql index 6d78ab7f8..1cdc00a6f 100644 --- a/webui/src/pages/bug/TimelineQuery.graphql +++ b/webui/src/pages/bug/TimelineQuery.graphql @@ -1,4 +1,3 @@ -#import "./MessageCreateFragment.graphql" #import "./MessageCommentFragment.graphql" #import "./LabelChangeFragment.graphql" #import "./SetTitleFragment.graphql" @@ -30,10 +29,7 @@ fragment TimelineItem on TimelineItem { ... on SetTitleTimelineItem { ...SetTitle } - ... on AddCommentTimelineItem { - ...AddComment - } - ... on CreateTimelineItem { - ...Create + ... on CommentTimelineItem { + ...Comment } } diff --git a/webui/src/pages/list/BugRow.tsx b/webui/src/pages/list/BugRow.tsx index 68a3b2990..c32174d5f 100644 --- a/webui/src/pages/list/BugRow.tsx +++ b/webui/src/pages/list/BugRow.tsx @@ -101,8 +101,7 @@ type Props = { function BugRow({ bug }: Props) { const classes = useStyles(); - // Subtract 1 from totalCount as 1 comment is the bug description - const commentCount = bug.comments.totalCount - 1; + const commentCount = bug.comments.totalCount; return (