Detailed changes
@@ -2,6 +2,14 @@ package connections
import "github.com/git-bug/git-bug/entity"
+// CursorEdge is a minimal edge carrying only a cursor. Use it with
+// connections.Connection when the edge type needs no additional fields.
+type CursorEdge struct {
+ Cursor string
+}
+
+func (e CursorEdge) GetCursor() string { return e.Cursor }
+
// LazyBugEdge is a special relay edge used to implement a lazy loading connection
type LazyBugEdge struct {
Id entity.Id
@@ -0,0 +1,3998 @@
+// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.
+
+package graph
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "strconv"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/99designs/gqlgen/graphql"
+ "github.com/git-bug/git-bug/api/graphql/models"
+ "github.com/git-bug/git-bug/repository"
+ "github.com/vektah/gqlparser/v2/ast"
+)
+
+// region ************************** generated!.gotpl **************************
+
+type GitCommitResolver interface {
+ ShortHash(ctx context.Context, obj *models.GitCommitMeta) (string, error)
+
+ FullMessage(ctx context.Context, obj *models.GitCommitMeta) (string, error)
+
+ Parents(ctx context.Context, obj *models.GitCommitMeta) ([]string, error)
+ Files(ctx context.Context, obj *models.GitCommitMeta, after *string, before *string, first *int, last *int) (*models.GitChangedFileConnection, error)
+ Diff(ctx context.Context, obj *models.GitCommitMeta, path string) (*repository.FileDiff, error)
+}
+
+// endregion ************************** generated!.gotpl **************************
+
+// region ***************************** args.gotpl *****************************
+
+func (ec *executionContext) field_GitCommit_diff_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
+ var err error
+ args := map[string]any{}
+ arg0, err := ec.field_GitCommit_diff_argsPath(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["path"] = arg0
+ return args, nil
+}
+func (ec *executionContext) field_GitCommit_diff_argsPath(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (string, error) {
+ if _, ok := rawArgs["path"]; !ok {
+ var zeroVal string
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("path"))
+ if tmp, ok := rawArgs["path"]; ok {
+ return ec.unmarshalNString2string(ctx, tmp)
+ }
+
+ var zeroVal string
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_GitCommit_files_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
+ var err error
+ args := map[string]any{}
+ arg0, err := ec.field_GitCommit_files_argsAfter(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["after"] = arg0
+ arg1, err := ec.field_GitCommit_files_argsBefore(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["before"] = arg1
+ arg2, err := ec.field_GitCommit_files_argsFirst(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["first"] = arg2
+ arg3, err := ec.field_GitCommit_files_argsLast(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["last"] = arg3
+ return args, nil
+}
+func (ec *executionContext) field_GitCommit_files_argsAfter(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*string, error) {
+ if _, ok := rawArgs["after"]; !ok {
+ var zeroVal *string
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("after"))
+ if tmp, ok := rawArgs["after"]; ok {
+ return ec.unmarshalOString2αstring(ctx, tmp)
+ }
+
+ var zeroVal *string
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_GitCommit_files_argsBefore(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*string, error) {
+ if _, ok := rawArgs["before"]; !ok {
+ var zeroVal *string
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("before"))
+ if tmp, ok := rawArgs["before"]; ok {
+ return ec.unmarshalOString2αstring(ctx, tmp)
+ }
+
+ var zeroVal *string
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_GitCommit_files_argsFirst(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*int, error) {
+ if _, ok := rawArgs["first"]; !ok {
+ var zeroVal *int
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("first"))
+ if tmp, ok := rawArgs["first"]; ok {
+ return ec.unmarshalOInt2αint(ctx, tmp)
+ }
+
+ var zeroVal *int
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_GitCommit_files_argsLast(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*int, error) {
+ if _, ok := rawArgs["last"]; !ok {
+ var zeroVal *int
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("last"))
+ if tmp, ok := rawArgs["last"]; ok {
+ return ec.unmarshalOInt2αint(ctx, tmp)
+ }
+
+ var zeroVal *int
+ return zeroVal, nil
+}
+
+// endregion ***************************** args.gotpl *****************************
+
+// region ************************** directives.gotpl **************************
+
+// endregion ************************** directives.gotpl **************************
+
+// region **************************** field.gotpl *****************************
+
+func (ec *executionContext) _GitBlob_path(ctx context.Context, field graphql.CollectedField, obj *models.GitBlob) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitBlob_path(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Path, 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.(string)
+ fc.Result = res
+ return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitBlob_path(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitBlob",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitBlob_hash(ctx context.Context, field graphql.CollectedField, obj *models.GitBlob) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitBlob_hash(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Hash, 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.(string)
+ fc.Result = res
+ return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitBlob_hash(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitBlob",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitBlob_text(ctx context.Context, field graphql.CollectedField, obj *models.GitBlob) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitBlob_text(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Text, nil
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if resTmp == nil {
+ return graphql.Null
+ }
+ res := resTmp.(*string)
+ fc.Result = res
+ return ec.marshalOString2αstring(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitBlob_text(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitBlob",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitBlob_size(ctx context.Context, field graphql.CollectedField, obj *models.GitBlob) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitBlob_size(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Size, 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.(int)
+ fc.Result = res
+ return ec.marshalNInt2int(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitBlob_size(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitBlob",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Int does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitBlob_isBinary(ctx context.Context, field graphql.CollectedField, obj *models.GitBlob) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitBlob_isBinary(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.IsBinary, 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.(bool)
+ fc.Result = res
+ return ec.marshalNBoolean2bool(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitBlob_isBinary(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitBlob",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Boolean does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitBlob_isTruncated(ctx context.Context, field graphql.CollectedField, obj *models.GitBlob) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitBlob_isTruncated(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.IsTruncated, 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.(bool)
+ fc.Result = res
+ return ec.marshalNBoolean2bool(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitBlob_isTruncated(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitBlob",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Boolean does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitChangedFile_path(ctx context.Context, field graphql.CollectedField, obj *repository.ChangedFile) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitChangedFile_path(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Path, 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.(string)
+ fc.Result = res
+ return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitChangedFile_path(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitChangedFile",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitChangedFile_oldPath(ctx context.Context, field graphql.CollectedField, obj *repository.ChangedFile) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitChangedFile_oldPath(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.OldPath, nil
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if resTmp == nil {
+ return graphql.Null
+ }
+ res := resTmp.(*string)
+ fc.Result = res
+ return ec.marshalOString2αstring(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitChangedFile_oldPath(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitChangedFile",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitChangedFile_status(ctx context.Context, field graphql.CollectedField, obj *repository.ChangedFile) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitChangedFile_status(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Status, 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.(repository.ChangeStatus)
+ fc.Result = res
+ return ec.marshalNGitChangeStatus2githubαcomαgitαbugαgitαbugαrepositoryαChangeStatus(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitChangedFile_status(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitChangedFile",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type GitChangeStatus does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitChangedFileConnection_nodes(ctx context.Context, field graphql.CollectedField, obj *models.GitChangedFileConnection) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitChangedFileConnection_nodes(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Nodes, 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.([]*repository.ChangedFile)
+ fc.Result = res
+ return ec.marshalNGitChangedFile2ααgithubαcomαgitαbugαgitαbugαrepositoryαChangedFileα(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitChangedFileConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitChangedFileConnection",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "path":
+ return ec.fieldContext_GitChangedFile_path(ctx, field)
+ case "oldPath":
+ return ec.fieldContext_GitChangedFile_oldPath(ctx, field)
+ case "status":
+ return ec.fieldContext_GitChangedFile_status(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type GitChangedFile", field.Name)
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitChangedFileConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *models.GitChangedFileConnection) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitChangedFileConnection_pageInfo(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.PageInfo, 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)
+ fc.Result = res
+ return ec.marshalNPageInfo2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαPageInfo(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitChangedFileConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitChangedFileConnection",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "hasNextPage":
+ return ec.fieldContext_PageInfo_hasNextPage(ctx, field)
+ case "hasPreviousPage":
+ return ec.fieldContext_PageInfo_hasPreviousPage(ctx, field)
+ case "startCursor":
+ return ec.fieldContext_PageInfo_startCursor(ctx, field)
+ case "endCursor":
+ return ec.fieldContext_PageInfo_endCursor(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type PageInfo", field.Name)
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitChangedFileConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *models.GitChangedFileConnection) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitChangedFileConnection_totalCount(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.TotalCount, 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.(int)
+ fc.Result = res
+ return ec.marshalNInt2int(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitChangedFileConnection_totalCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitChangedFileConnection",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Int does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitCommit_hash(ctx context.Context, field graphql.CollectedField, obj *models.GitCommitMeta) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitCommit_hash(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Hash, 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.(repository.Hash)
+ fc.Result = res
+ return ec.marshalNString2githubαcomαgitαbugαgitαbugαrepositoryαHash(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitCommit_hash(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitCommit",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitCommit_shortHash(ctx context.Context, field graphql.CollectedField, obj *models.GitCommitMeta) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitCommit_shortHash(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.GitCommit().ShortHash(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)
+ fc.Result = res
+ return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitCommit_shortHash(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitCommit",
+ Field: field,
+ IsMethod: true,
+ IsResolver: true,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitCommit_message(ctx context.Context, field graphql.CollectedField, obj *models.GitCommitMeta) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitCommit_message(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Message, 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.(string)
+ fc.Result = res
+ return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitCommit_message(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitCommit",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitCommit_fullMessage(ctx context.Context, field graphql.CollectedField, obj *models.GitCommitMeta) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitCommit_fullMessage(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.GitCommit().FullMessage(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)
+ fc.Result = res
+ return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitCommit_fullMessage(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitCommit",
+ Field: field,
+ IsMethod: true,
+ IsResolver: true,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitCommit_authorName(ctx context.Context, field graphql.CollectedField, obj *models.GitCommitMeta) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitCommit_authorName(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.AuthorName, 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.(string)
+ fc.Result = res
+ return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitCommit_authorName(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitCommit",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitCommit_authorEmail(ctx context.Context, field graphql.CollectedField, obj *models.GitCommitMeta) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitCommit_authorEmail(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.AuthorEmail, 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.(string)
+ fc.Result = res
+ return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitCommit_authorEmail(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitCommit",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitCommit_date(ctx context.Context, field graphql.CollectedField, obj *models.GitCommitMeta) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitCommit_date(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Date, 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.(time.Time)
+ fc.Result = res
+ return ec.marshalNTime2timeαTime(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitCommit_date(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitCommit",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Time does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitCommit_parents(ctx context.Context, field graphql.CollectedField, obj *models.GitCommitMeta) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitCommit_parents(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.GitCommit().Parents(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)
+ fc.Result = res
+ return ec.marshalNString2αstringα(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitCommit_parents(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitCommit",
+ Field: field,
+ IsMethod: true,
+ IsResolver: true,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitCommit_files(ctx context.Context, field graphql.CollectedField, obj *models.GitCommitMeta) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitCommit_files(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.GitCommit().Files(rctx, obj, fc.Args["after"].(*string), fc.Args["before"].(*string), fc.Args["first"].(*int), fc.Args["last"].(*int))
+ })
+ 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.GitChangedFileConnection)
+ fc.Result = res
+ return ec.marshalNGitChangedFileConnection2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitChangedFileConnection(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitCommit_files(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitCommit",
+ Field: field,
+ IsMethod: true,
+ IsResolver: true,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "nodes":
+ return ec.fieldContext_GitChangedFileConnection_nodes(ctx, field)
+ case "pageInfo":
+ return ec.fieldContext_GitChangedFileConnection_pageInfo(ctx, field)
+ case "totalCount":
+ return ec.fieldContext_GitChangedFileConnection_totalCount(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type GitChangedFileConnection", field.Name)
+ },
+ }
+ defer func() {
+ if r := recover(); r != nil {
+ err = ec.Recover(ctx, r)
+ ec.Error(ctx, err)
+ }
+ }()
+ ctx = graphql.WithFieldContext(ctx, fc)
+ if fc.Args, err = ec.field_GitCommit_files_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
+ ec.Error(ctx, err)
+ return fc, err
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitCommit_diff(ctx context.Context, field graphql.CollectedField, obj *models.GitCommitMeta) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitCommit_diff(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.GitCommit().Diff(rctx, obj, fc.Args["path"].(string))
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if resTmp == nil {
+ return graphql.Null
+ }
+ res := resTmp.(*repository.FileDiff)
+ fc.Result = res
+ return ec.marshalOGitFileDiff2αgithubαcomαgitαbugαgitαbugαrepositoryαFileDiff(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitCommit_diff(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitCommit",
+ Field: field,
+ IsMethod: true,
+ IsResolver: true,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "path":
+ return ec.fieldContext_GitFileDiff_path(ctx, field)
+ case "oldPath":
+ return ec.fieldContext_GitFileDiff_oldPath(ctx, field)
+ case "isBinary":
+ return ec.fieldContext_GitFileDiff_isBinary(ctx, field)
+ case "isNew":
+ return ec.fieldContext_GitFileDiff_isNew(ctx, field)
+ case "isDelete":
+ return ec.fieldContext_GitFileDiff_isDelete(ctx, field)
+ case "hunks":
+ return ec.fieldContext_GitFileDiff_hunks(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type GitFileDiff", field.Name)
+ },
+ }
+ defer func() {
+ if r := recover(); r != nil {
+ err = ec.Recover(ctx, r)
+ ec.Error(ctx, err)
+ }
+ }()
+ ctx = graphql.WithFieldContext(ctx, fc)
+ if fc.Args, err = ec.field_GitCommit_diff_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
+ ec.Error(ctx, err)
+ return fc, err
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitCommitConnection_nodes(ctx context.Context, field graphql.CollectedField, obj *models.GitCommitConnection) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitCommitConnection_nodes(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Nodes, 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.GitCommitMeta)
+ fc.Result = res
+ return ec.marshalNGitCommit2ααgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitCommitMetaα(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitCommitConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitCommitConnection",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "hash":
+ return ec.fieldContext_GitCommit_hash(ctx, field)
+ case "shortHash":
+ return ec.fieldContext_GitCommit_shortHash(ctx, field)
+ case "message":
+ return ec.fieldContext_GitCommit_message(ctx, field)
+ case "fullMessage":
+ return ec.fieldContext_GitCommit_fullMessage(ctx, field)
+ case "authorName":
+ return ec.fieldContext_GitCommit_authorName(ctx, field)
+ case "authorEmail":
+ return ec.fieldContext_GitCommit_authorEmail(ctx, field)
+ case "date":
+ return ec.fieldContext_GitCommit_date(ctx, field)
+ case "parents":
+ return ec.fieldContext_GitCommit_parents(ctx, field)
+ case "files":
+ return ec.fieldContext_GitCommit_files(ctx, field)
+ case "diff":
+ return ec.fieldContext_GitCommit_diff(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type GitCommit", field.Name)
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitCommitConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *models.GitCommitConnection) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitCommitConnection_pageInfo(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.PageInfo, 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)
+ fc.Result = res
+ return ec.marshalNPageInfo2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαPageInfo(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitCommitConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitCommitConnection",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "hasNextPage":
+ return ec.fieldContext_PageInfo_hasNextPage(ctx, field)
+ case "hasPreviousPage":
+ return ec.fieldContext_PageInfo_hasPreviousPage(ctx, field)
+ case "startCursor":
+ return ec.fieldContext_PageInfo_startCursor(ctx, field)
+ case "endCursor":
+ return ec.fieldContext_PageInfo_endCursor(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type PageInfo", field.Name)
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitCommitConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *models.GitCommitConnection) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitCommitConnection_totalCount(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.TotalCount, 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.(int)
+ fc.Result = res
+ return ec.marshalNInt2int(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitCommitConnection_totalCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitCommitConnection",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Int does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitDiffHunk_oldStart(ctx context.Context, field graphql.CollectedField, obj *repository.DiffHunk) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitDiffHunk_oldStart(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.OldStart, 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.(int)
+ fc.Result = res
+ return ec.marshalNInt2int(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitDiffHunk_oldStart(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitDiffHunk",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Int does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitDiffHunk_oldLines(ctx context.Context, field graphql.CollectedField, obj *repository.DiffHunk) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitDiffHunk_oldLines(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.OldLines, 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.(int)
+ fc.Result = res
+ return ec.marshalNInt2int(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitDiffHunk_oldLines(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitDiffHunk",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Int does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitDiffHunk_newStart(ctx context.Context, field graphql.CollectedField, obj *repository.DiffHunk) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitDiffHunk_newStart(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.NewStart, 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.(int)
+ fc.Result = res
+ return ec.marshalNInt2int(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitDiffHunk_newStart(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitDiffHunk",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Int does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitDiffHunk_newLines(ctx context.Context, field graphql.CollectedField, obj *repository.DiffHunk) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitDiffHunk_newLines(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.NewLines, 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.(int)
+ fc.Result = res
+ return ec.marshalNInt2int(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitDiffHunk_newLines(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitDiffHunk",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Int does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitDiffHunk_lines(ctx context.Context, field graphql.CollectedField, obj *repository.DiffHunk) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitDiffHunk_lines(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Lines, 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.([]repository.DiffLine)
+ fc.Result = res
+ return ec.marshalNGitDiffLine2αgithubαcomαgitαbugαgitαbugαrepositoryαDiffLineα(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitDiffHunk_lines(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitDiffHunk",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "type":
+ return ec.fieldContext_GitDiffLine_type(ctx, field)
+ case "content":
+ return ec.fieldContext_GitDiffLine_content(ctx, field)
+ case "oldLine":
+ return ec.fieldContext_GitDiffLine_oldLine(ctx, field)
+ case "newLine":
+ return ec.fieldContext_GitDiffLine_newLine(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type GitDiffLine", field.Name)
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitDiffLine_type(ctx context.Context, field graphql.CollectedField, obj *repository.DiffLine) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitDiffLine_type(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Type, 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.(repository.DiffLineType)
+ fc.Result = res
+ return ec.marshalNGitDiffLineType2githubαcomαgitαbugαgitαbugαrepositoryαDiffLineType(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitDiffLine_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitDiffLine",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type GitDiffLineType does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitDiffLine_content(ctx context.Context, field graphql.CollectedField, obj *repository.DiffLine) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitDiffLine_content(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Content, 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.(string)
+ fc.Result = res
+ return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitDiffLine_content(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitDiffLine",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitDiffLine_oldLine(ctx context.Context, field graphql.CollectedField, obj *repository.DiffLine) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitDiffLine_oldLine(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.OldLine, 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.(int)
+ fc.Result = res
+ return ec.marshalNInt2int(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitDiffLine_oldLine(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitDiffLine",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Int does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitDiffLine_newLine(ctx context.Context, field graphql.CollectedField, obj *repository.DiffLine) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitDiffLine_newLine(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.NewLine, 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.(int)
+ fc.Result = res
+ return ec.marshalNInt2int(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitDiffLine_newLine(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitDiffLine",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Int does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitFileDiff_path(ctx context.Context, field graphql.CollectedField, obj *repository.FileDiff) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitFileDiff_path(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Path, 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.(string)
+ fc.Result = res
+ return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitFileDiff_path(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitFileDiff",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitFileDiff_oldPath(ctx context.Context, field graphql.CollectedField, obj *repository.FileDiff) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitFileDiff_oldPath(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.OldPath, nil
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if resTmp == nil {
+ return graphql.Null
+ }
+ res := resTmp.(*string)
+ fc.Result = res
+ return ec.marshalOString2αstring(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitFileDiff_oldPath(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitFileDiff",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitFileDiff_isBinary(ctx context.Context, field graphql.CollectedField, obj *repository.FileDiff) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitFileDiff_isBinary(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.IsBinary, 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.(bool)
+ fc.Result = res
+ return ec.marshalNBoolean2bool(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitFileDiff_isBinary(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitFileDiff",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Boolean does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitFileDiff_isNew(ctx context.Context, field graphql.CollectedField, obj *repository.FileDiff) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitFileDiff_isNew(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.IsNew, 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.(bool)
+ fc.Result = res
+ return ec.marshalNBoolean2bool(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitFileDiff_isNew(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitFileDiff",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Boolean does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitFileDiff_isDelete(ctx context.Context, field graphql.CollectedField, obj *repository.FileDiff) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitFileDiff_isDelete(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.IsDelete, 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.(bool)
+ fc.Result = res
+ return ec.marshalNBoolean2bool(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitFileDiff_isDelete(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitFileDiff",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Boolean does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitFileDiff_hunks(ctx context.Context, field graphql.CollectedField, obj *repository.FileDiff) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitFileDiff_hunks(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Hunks, 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.([]repository.DiffHunk)
+ fc.Result = res
+ return ec.marshalNGitDiffHunk2αgithubαcomαgitαbugαgitαbugαrepositoryαDiffHunkα(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitFileDiff_hunks(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitFileDiff",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "oldStart":
+ return ec.fieldContext_GitDiffHunk_oldStart(ctx, field)
+ case "oldLines":
+ return ec.fieldContext_GitDiffHunk_oldLines(ctx, field)
+ case "newStart":
+ return ec.fieldContext_GitDiffHunk_newStart(ctx, field)
+ case "newLines":
+ return ec.fieldContext_GitDiffHunk_newLines(ctx, field)
+ case "lines":
+ return ec.fieldContext_GitDiffHunk_lines(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type GitDiffHunk", field.Name)
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitLastCommit_name(ctx context.Context, field graphql.CollectedField, obj *models.GitLastCommit) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitLastCommit_name(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Name, 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.(string)
+ fc.Result = res
+ return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitLastCommit_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitLastCommit",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitLastCommit_commit(ctx context.Context, field graphql.CollectedField, obj *models.GitLastCommit) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitLastCommit_commit(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Commit, 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.GitCommitMeta)
+ fc.Result = res
+ return ec.marshalNGitCommit2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitCommitMeta(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitLastCommit_commit(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitLastCommit",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "hash":
+ return ec.fieldContext_GitCommit_hash(ctx, field)
+ case "shortHash":
+ return ec.fieldContext_GitCommit_shortHash(ctx, field)
+ case "message":
+ return ec.fieldContext_GitCommit_message(ctx, field)
+ case "fullMessage":
+ return ec.fieldContext_GitCommit_fullMessage(ctx, field)
+ case "authorName":
+ return ec.fieldContext_GitCommit_authorName(ctx, field)
+ case "authorEmail":
+ return ec.fieldContext_GitCommit_authorEmail(ctx, field)
+ case "date":
+ return ec.fieldContext_GitCommit_date(ctx, field)
+ case "parents":
+ return ec.fieldContext_GitCommit_parents(ctx, field)
+ case "files":
+ return ec.fieldContext_GitCommit_files(ctx, field)
+ case "diff":
+ return ec.fieldContext_GitCommit_diff(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type GitCommit", field.Name)
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitRef_name(ctx context.Context, field graphql.CollectedField, obj *models.GitRef) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitRef_name(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Name, 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.(string)
+ fc.Result = res
+ return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitRef_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitRef",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitRef_shortName(ctx context.Context, field graphql.CollectedField, obj *models.GitRef) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitRef_shortName(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.ShortName, 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.(string)
+ fc.Result = res
+ return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitRef_shortName(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitRef",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitRef_type(ctx context.Context, field graphql.CollectedField, obj *models.GitRef) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitRef_type(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Type, 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.GitRefType)
+ fc.Result = res
+ return ec.marshalNGitRefType2githubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefType(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitRef_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitRef",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type GitRefType does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitRef_hash(ctx context.Context, field graphql.CollectedField, obj *models.GitRef) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitRef_hash(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Hash, 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.(string)
+ fc.Result = res
+ return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitRef_hash(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitRef",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitRef_isDefault(ctx context.Context, field graphql.CollectedField, obj *models.GitRef) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitRef_isDefault(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.IsDefault, 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.(bool)
+ fc.Result = res
+ return ec.marshalNBoolean2bool(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitRef_isDefault(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitRef",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Boolean does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitRefConnection_nodes(ctx context.Context, field graphql.CollectedField, obj *models.GitRefConnection) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitRefConnection_nodes(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Nodes, 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.GitRef)
+ fc.Result = res
+ return ec.marshalNGitRef2ααgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefα(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitRefConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitRefConnection",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "name":
+ return ec.fieldContext_GitRef_name(ctx, field)
+ case "shortName":
+ return ec.fieldContext_GitRef_shortName(ctx, field)
+ case "type":
+ return ec.fieldContext_GitRef_type(ctx, field)
+ case "hash":
+ return ec.fieldContext_GitRef_hash(ctx, field)
+ case "isDefault":
+ return ec.fieldContext_GitRef_isDefault(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type GitRef", field.Name)
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitRefConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *models.GitRefConnection) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitRefConnection_pageInfo(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.PageInfo, 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)
+ fc.Result = res
+ return ec.marshalNPageInfo2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαPageInfo(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitRefConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitRefConnection",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "hasNextPage":
+ return ec.fieldContext_PageInfo_hasNextPage(ctx, field)
+ case "hasPreviousPage":
+ return ec.fieldContext_PageInfo_hasPreviousPage(ctx, field)
+ case "startCursor":
+ return ec.fieldContext_PageInfo_startCursor(ctx, field)
+ case "endCursor":
+ return ec.fieldContext_PageInfo_endCursor(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type PageInfo", field.Name)
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitRefConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *models.GitRefConnection) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitRefConnection_totalCount(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.TotalCount, 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.(int)
+ fc.Result = res
+ return ec.marshalNInt2int(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitRefConnection_totalCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitRefConnection",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type Int does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitTreeEntry_name(ctx context.Context, field graphql.CollectedField, obj *repository.TreeEntry) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitTreeEntry_name(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Name, 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.(string)
+ fc.Result = res
+ return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitTreeEntry_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitTreeEntry",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitTreeEntry_type(ctx context.Context, field graphql.CollectedField, obj *repository.TreeEntry) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitTreeEntry_type(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.ObjectType, 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.(repository.ObjectType)
+ fc.Result = res
+ return ec.marshalNGitObjectType2githubαcomαgitαbugαgitαbugαrepositoryαObjectType(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitTreeEntry_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitTreeEntry",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type GitObjectType does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _GitTreeEntry_hash(ctx context.Context, field graphql.CollectedField, obj *repository.TreeEntry) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_GitTreeEntry_hash(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Hash, 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.(repository.Hash)
+ fc.Result = res
+ return ec.marshalNString2githubαcomαgitαbugαgitαbugαrepositoryαHash(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_GitTreeEntry_hash(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "GitTreeEntry",
+ Field: field,
+ IsMethod: false,
+ IsResolver: false,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+// endregion **************************** field.gotpl *****************************
+
+// region **************************** input.gotpl *****************************
+
+// endregion **************************** input.gotpl *****************************
+
+// region ************************** interface.gotpl ***************************
+
+// endregion ************************** interface.gotpl ***************************
+
+// region **************************** object.gotpl ****************************
+
+var gitBlobImplementors = []string{"GitBlob"}
+
+func (ec *executionContext) _GitBlob(ctx context.Context, sel ast.SelectionSet, obj *models.GitBlob) graphql.Marshaler {
+ fields := graphql.CollectFields(ec.OperationContext, sel, gitBlobImplementors)
+
+ out := graphql.NewFieldSet(fields)
+ deferred := make(map[string]*graphql.FieldSet)
+ for i, field := range fields {
+ switch field.Name {
+ case "__typename":
+ out.Values[i] = graphql.MarshalString("GitBlob")
+ case "path":
+ out.Values[i] = ec._GitBlob_path(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "hash":
+ out.Values[i] = ec._GitBlob_hash(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "text":
+ out.Values[i] = ec._GitBlob_text(ctx, field, obj)
+ case "size":
+ out.Values[i] = ec._GitBlob_size(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "isBinary":
+ out.Values[i] = ec._GitBlob_isBinary(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "isTruncated":
+ out.Values[i] = ec._GitBlob_isTruncated(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+ out.Dispatch(ctx)
+ if out.Invalids > 0 {
+ return graphql.Null
+ }
+
+ atomic.AddInt32(&ec.deferred, int32(len(deferred)))
+
+ for label, dfs := range deferred {
+ ec.processDeferredGroup(graphql.DeferredGroup{
+ Label: label,
+ Path: graphql.GetPath(ctx),
+ FieldSet: dfs,
+ Context: ctx,
+ })
+ }
+
+ return out
+}
+
+var gitChangedFileImplementors = []string{"GitChangedFile"}
+
+func (ec *executionContext) _GitChangedFile(ctx context.Context, sel ast.SelectionSet, obj *repository.ChangedFile) graphql.Marshaler {
+ fields := graphql.CollectFields(ec.OperationContext, sel, gitChangedFileImplementors)
+
+ out := graphql.NewFieldSet(fields)
+ deferred := make(map[string]*graphql.FieldSet)
+ for i, field := range fields {
+ switch field.Name {
+ case "__typename":
+ out.Values[i] = graphql.MarshalString("GitChangedFile")
+ case "path":
+ out.Values[i] = ec._GitChangedFile_path(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "oldPath":
+ out.Values[i] = ec._GitChangedFile_oldPath(ctx, field, obj)
+ case "status":
+ out.Values[i] = ec._GitChangedFile_status(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+ out.Dispatch(ctx)
+ if out.Invalids > 0 {
+ return graphql.Null
+ }
+
+ atomic.AddInt32(&ec.deferred, int32(len(deferred)))
+
+ for label, dfs := range deferred {
+ ec.processDeferredGroup(graphql.DeferredGroup{
+ Label: label,
+ Path: graphql.GetPath(ctx),
+ FieldSet: dfs,
+ Context: ctx,
+ })
+ }
+
+ return out
+}
+
+var gitChangedFileConnectionImplementors = []string{"GitChangedFileConnection"}
+
+func (ec *executionContext) _GitChangedFileConnection(ctx context.Context, sel ast.SelectionSet, obj *models.GitChangedFileConnection) graphql.Marshaler {
+ fields := graphql.CollectFields(ec.OperationContext, sel, gitChangedFileConnectionImplementors)
+
+ out := graphql.NewFieldSet(fields)
+ deferred := make(map[string]*graphql.FieldSet)
+ for i, field := range fields {
+ switch field.Name {
+ case "__typename":
+ out.Values[i] = graphql.MarshalString("GitChangedFileConnection")
+ case "nodes":
+ out.Values[i] = ec._GitChangedFileConnection_nodes(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "pageInfo":
+ out.Values[i] = ec._GitChangedFileConnection_pageInfo(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "totalCount":
+ out.Values[i] = ec._GitChangedFileConnection_totalCount(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+ out.Dispatch(ctx)
+ if out.Invalids > 0 {
+ return graphql.Null
+ }
+
+ atomic.AddInt32(&ec.deferred, int32(len(deferred)))
+
+ for label, dfs := range deferred {
+ ec.processDeferredGroup(graphql.DeferredGroup{
+ Label: label,
+ Path: graphql.GetPath(ctx),
+ FieldSet: dfs,
+ Context: ctx,
+ })
+ }
+
+ return out
+}
+
+var gitCommitImplementors = []string{"GitCommit"}
+
+func (ec *executionContext) _GitCommit(ctx context.Context, sel ast.SelectionSet, obj *models.GitCommitMeta) graphql.Marshaler {
+ fields := graphql.CollectFields(ec.OperationContext, sel, gitCommitImplementors)
+
+ out := graphql.NewFieldSet(fields)
+ deferred := make(map[string]*graphql.FieldSet)
+ for i, field := range fields {
+ switch field.Name {
+ case "__typename":
+ out.Values[i] = graphql.MarshalString("GitCommit")
+ case "hash":
+ out.Values[i] = ec._GitCommit_hash(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ atomic.AddUint32(&out.Invalids, 1)
+ }
+ case "shortHash":
+ field := field
+
+ innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ }
+ }()
+ res = ec._GitCommit_shortHash(ctx, field, obj)
+ if res == graphql.Null {
+ atomic.AddUint32(&fs.Invalids, 1)
+ }
+ return res
+ }
+
+ if field.Deferrable != nil {
+ dfs, ok := deferred[field.Deferrable.Label]
+ di := 0
+ if ok {
+ dfs.AddField(field)
+ di = len(dfs.Values) - 1
+ } else {
+ dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
+ deferred[field.Deferrable.Label] = dfs
+ }
+ dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
+ return innerFunc(ctx, dfs)
+ })
+
+ // don't run the out.Concurrently() call below
+ out.Values[i] = graphql.Null
+ continue
+ }
+
+ out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
+ case "message":
+ out.Values[i] = ec._GitCommit_message(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ atomic.AddUint32(&out.Invalids, 1)
+ }
+ case "fullMessage":
+ field := field
+
+ innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ }
+ }()
+ res = ec._GitCommit_fullMessage(ctx, field, obj)
+ if res == graphql.Null {
+ atomic.AddUint32(&fs.Invalids, 1)
+ }
+ return res
+ }
+
+ if field.Deferrable != nil {
+ dfs, ok := deferred[field.Deferrable.Label]
+ di := 0
+ if ok {
+ dfs.AddField(field)
+ di = len(dfs.Values) - 1
+ } else {
+ dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
+ deferred[field.Deferrable.Label] = dfs
+ }
+ dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
+ return innerFunc(ctx, dfs)
+ })
+
+ // don't run the out.Concurrently() call below
+ out.Values[i] = graphql.Null
+ continue
+ }
+
+ out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
+ case "authorName":
+ out.Values[i] = ec._GitCommit_authorName(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ atomic.AddUint32(&out.Invalids, 1)
+ }
+ case "authorEmail":
+ out.Values[i] = ec._GitCommit_authorEmail(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ atomic.AddUint32(&out.Invalids, 1)
+ }
+ case "date":
+ out.Values[i] = ec._GitCommit_date(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ atomic.AddUint32(&out.Invalids, 1)
+ }
+ case "parents":
+ field := field
+
+ innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ }
+ }()
+ res = ec._GitCommit_parents(ctx, field, obj)
+ if res == graphql.Null {
+ atomic.AddUint32(&fs.Invalids, 1)
+ }
+ return res
+ }
+
+ if field.Deferrable != nil {
+ dfs, ok := deferred[field.Deferrable.Label]
+ di := 0
+ if ok {
+ dfs.AddField(field)
+ di = len(dfs.Values) - 1
+ } else {
+ dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
+ deferred[field.Deferrable.Label] = dfs
+ }
+ dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
+ return innerFunc(ctx, dfs)
+ })
+
+ // don't run the out.Concurrently() call below
+ out.Values[i] = graphql.Null
+ continue
+ }
+
+ out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
+ case "files":
+ field := field
+
+ innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ }
+ }()
+ res = ec._GitCommit_files(ctx, field, obj)
+ if res == graphql.Null {
+ atomic.AddUint32(&fs.Invalids, 1)
+ }
+ return res
+ }
+
+ if field.Deferrable != nil {
+ dfs, ok := deferred[field.Deferrable.Label]
+ di := 0
+ if ok {
+ dfs.AddField(field)
+ di = len(dfs.Values) - 1
+ } else {
+ dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
+ deferred[field.Deferrable.Label] = dfs
+ }
+ dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
+ return innerFunc(ctx, dfs)
+ })
+
+ // don't run the out.Concurrently() call below
+ out.Values[i] = graphql.Null
+ continue
+ }
+
+ out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
+ case "diff":
+ field := field
+
+ innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) {
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ }
+ }()
+ res = ec._GitCommit_diff(ctx, field, obj)
+ return res
+ }
+
+ if field.Deferrable != nil {
+ dfs, ok := deferred[field.Deferrable.Label]
+ di := 0
+ if ok {
+ dfs.AddField(field)
+ di = len(dfs.Values) - 1
+ } else {
+ dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
+ deferred[field.Deferrable.Label] = dfs
+ }
+ dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
+ return innerFunc(ctx, dfs)
+ })
+
+ // don't run the out.Concurrently() call below
+ out.Values[i] = graphql.Null
+ continue
+ }
+
+ out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+ out.Dispatch(ctx)
+ if out.Invalids > 0 {
+ return graphql.Null
+ }
+
+ atomic.AddInt32(&ec.deferred, int32(len(deferred)))
+
+ for label, dfs := range deferred {
+ ec.processDeferredGroup(graphql.DeferredGroup{
+ Label: label,
+ Path: graphql.GetPath(ctx),
+ FieldSet: dfs,
+ Context: ctx,
+ })
+ }
+
+ return out
+}
+
+var gitCommitConnectionImplementors = []string{"GitCommitConnection"}
+
+func (ec *executionContext) _GitCommitConnection(ctx context.Context, sel ast.SelectionSet, obj *models.GitCommitConnection) graphql.Marshaler {
+ fields := graphql.CollectFields(ec.OperationContext, sel, gitCommitConnectionImplementors)
+
+ out := graphql.NewFieldSet(fields)
+ deferred := make(map[string]*graphql.FieldSet)
+ for i, field := range fields {
+ switch field.Name {
+ case "__typename":
+ out.Values[i] = graphql.MarshalString("GitCommitConnection")
+ case "nodes":
+ out.Values[i] = ec._GitCommitConnection_nodes(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "pageInfo":
+ out.Values[i] = ec._GitCommitConnection_pageInfo(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "totalCount":
+ out.Values[i] = ec._GitCommitConnection_totalCount(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+ out.Dispatch(ctx)
+ if out.Invalids > 0 {
+ return graphql.Null
+ }
+
+ atomic.AddInt32(&ec.deferred, int32(len(deferred)))
+
+ for label, dfs := range deferred {
+ ec.processDeferredGroup(graphql.DeferredGroup{
+ Label: label,
+ Path: graphql.GetPath(ctx),
+ FieldSet: dfs,
+ Context: ctx,
+ })
+ }
+
+ return out
+}
+
+var gitDiffHunkImplementors = []string{"GitDiffHunk"}
+
+func (ec *executionContext) _GitDiffHunk(ctx context.Context, sel ast.SelectionSet, obj *repository.DiffHunk) graphql.Marshaler {
+ fields := graphql.CollectFields(ec.OperationContext, sel, gitDiffHunkImplementors)
+
+ out := graphql.NewFieldSet(fields)
+ deferred := make(map[string]*graphql.FieldSet)
+ for i, field := range fields {
+ switch field.Name {
+ case "__typename":
+ out.Values[i] = graphql.MarshalString("GitDiffHunk")
+ case "oldStart":
+ out.Values[i] = ec._GitDiffHunk_oldStart(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "oldLines":
+ out.Values[i] = ec._GitDiffHunk_oldLines(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "newStart":
+ out.Values[i] = ec._GitDiffHunk_newStart(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "newLines":
+ out.Values[i] = ec._GitDiffHunk_newLines(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "lines":
+ out.Values[i] = ec._GitDiffHunk_lines(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+ out.Dispatch(ctx)
+ if out.Invalids > 0 {
+ return graphql.Null
+ }
+
+ atomic.AddInt32(&ec.deferred, int32(len(deferred)))
+
+ for label, dfs := range deferred {
+ ec.processDeferredGroup(graphql.DeferredGroup{
+ Label: label,
+ Path: graphql.GetPath(ctx),
+ FieldSet: dfs,
+ Context: ctx,
+ })
+ }
+
+ return out
+}
+
+var gitDiffLineImplementors = []string{"GitDiffLine"}
+
+func (ec *executionContext) _GitDiffLine(ctx context.Context, sel ast.SelectionSet, obj *repository.DiffLine) graphql.Marshaler {
+ fields := graphql.CollectFields(ec.OperationContext, sel, gitDiffLineImplementors)
+
+ out := graphql.NewFieldSet(fields)
+ deferred := make(map[string]*graphql.FieldSet)
+ for i, field := range fields {
+ switch field.Name {
+ case "__typename":
+ out.Values[i] = graphql.MarshalString("GitDiffLine")
+ case "type":
+ out.Values[i] = ec._GitDiffLine_type(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "content":
+ out.Values[i] = ec._GitDiffLine_content(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "oldLine":
+ out.Values[i] = ec._GitDiffLine_oldLine(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "newLine":
+ out.Values[i] = ec._GitDiffLine_newLine(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+ out.Dispatch(ctx)
+ if out.Invalids > 0 {
+ return graphql.Null
+ }
+
+ atomic.AddInt32(&ec.deferred, int32(len(deferred)))
+
+ for label, dfs := range deferred {
+ ec.processDeferredGroup(graphql.DeferredGroup{
+ Label: label,
+ Path: graphql.GetPath(ctx),
+ FieldSet: dfs,
+ Context: ctx,
+ })
+ }
+
+ return out
+}
+
+var gitFileDiffImplementors = []string{"GitFileDiff"}
+
+func (ec *executionContext) _GitFileDiff(ctx context.Context, sel ast.SelectionSet, obj *repository.FileDiff) graphql.Marshaler {
+ fields := graphql.CollectFields(ec.OperationContext, sel, gitFileDiffImplementors)
+
+ out := graphql.NewFieldSet(fields)
+ deferred := make(map[string]*graphql.FieldSet)
+ for i, field := range fields {
+ switch field.Name {
+ case "__typename":
+ out.Values[i] = graphql.MarshalString("GitFileDiff")
+ case "path":
+ out.Values[i] = ec._GitFileDiff_path(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "oldPath":
+ out.Values[i] = ec._GitFileDiff_oldPath(ctx, field, obj)
+ case "isBinary":
+ out.Values[i] = ec._GitFileDiff_isBinary(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "isNew":
+ out.Values[i] = ec._GitFileDiff_isNew(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "isDelete":
+ out.Values[i] = ec._GitFileDiff_isDelete(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "hunks":
+ out.Values[i] = ec._GitFileDiff_hunks(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+ out.Dispatch(ctx)
+ if out.Invalids > 0 {
+ return graphql.Null
+ }
+
+ atomic.AddInt32(&ec.deferred, int32(len(deferred)))
+
+ for label, dfs := range deferred {
+ ec.processDeferredGroup(graphql.DeferredGroup{
+ Label: label,
+ Path: graphql.GetPath(ctx),
+ FieldSet: dfs,
+ Context: ctx,
+ })
+ }
+
+ return out
+}
+
+var gitLastCommitImplementors = []string{"GitLastCommit"}
+
+func (ec *executionContext) _GitLastCommit(ctx context.Context, sel ast.SelectionSet, obj *models.GitLastCommit) graphql.Marshaler {
+ fields := graphql.CollectFields(ec.OperationContext, sel, gitLastCommitImplementors)
+
+ out := graphql.NewFieldSet(fields)
+ deferred := make(map[string]*graphql.FieldSet)
+ for i, field := range fields {
+ switch field.Name {
+ case "__typename":
+ out.Values[i] = graphql.MarshalString("GitLastCommit")
+ case "name":
+ out.Values[i] = ec._GitLastCommit_name(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "commit":
+ out.Values[i] = ec._GitLastCommit_commit(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+ out.Dispatch(ctx)
+ if out.Invalids > 0 {
+ return graphql.Null
+ }
+
+ atomic.AddInt32(&ec.deferred, int32(len(deferred)))
+
+ for label, dfs := range deferred {
+ ec.processDeferredGroup(graphql.DeferredGroup{
+ Label: label,
+ Path: graphql.GetPath(ctx),
+ FieldSet: dfs,
+ Context: ctx,
+ })
+ }
+
+ return out
+}
+
+var gitRefImplementors = []string{"GitRef"}
+
+func (ec *executionContext) _GitRef(ctx context.Context, sel ast.SelectionSet, obj *models.GitRef) graphql.Marshaler {
+ fields := graphql.CollectFields(ec.OperationContext, sel, gitRefImplementors)
+
+ out := graphql.NewFieldSet(fields)
+ deferred := make(map[string]*graphql.FieldSet)
+ for i, field := range fields {
+ switch field.Name {
+ case "__typename":
+ out.Values[i] = graphql.MarshalString("GitRef")
+ case "name":
+ out.Values[i] = ec._GitRef_name(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "shortName":
+ out.Values[i] = ec._GitRef_shortName(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "type":
+ out.Values[i] = ec._GitRef_type(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "hash":
+ out.Values[i] = ec._GitRef_hash(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "isDefault":
+ out.Values[i] = ec._GitRef_isDefault(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+ out.Dispatch(ctx)
+ if out.Invalids > 0 {
+ return graphql.Null
+ }
+
+ atomic.AddInt32(&ec.deferred, int32(len(deferred)))
+
+ for label, dfs := range deferred {
+ ec.processDeferredGroup(graphql.DeferredGroup{
+ Label: label,
+ Path: graphql.GetPath(ctx),
+ FieldSet: dfs,
+ Context: ctx,
+ })
+ }
+
+ return out
+}
+
+var gitRefConnectionImplementors = []string{"GitRefConnection"}
+
+func (ec *executionContext) _GitRefConnection(ctx context.Context, sel ast.SelectionSet, obj *models.GitRefConnection) graphql.Marshaler {
+ fields := graphql.CollectFields(ec.OperationContext, sel, gitRefConnectionImplementors)
+
+ out := graphql.NewFieldSet(fields)
+ deferred := make(map[string]*graphql.FieldSet)
+ for i, field := range fields {
+ switch field.Name {
+ case "__typename":
+ out.Values[i] = graphql.MarshalString("GitRefConnection")
+ case "nodes":
+ out.Values[i] = ec._GitRefConnection_nodes(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "pageInfo":
+ out.Values[i] = ec._GitRefConnection_pageInfo(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "totalCount":
+ out.Values[i] = ec._GitRefConnection_totalCount(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+ out.Dispatch(ctx)
+ if out.Invalids > 0 {
+ return graphql.Null
+ }
+
+ atomic.AddInt32(&ec.deferred, int32(len(deferred)))
+
+ for label, dfs := range deferred {
+ ec.processDeferredGroup(graphql.DeferredGroup{
+ Label: label,
+ Path: graphql.GetPath(ctx),
+ FieldSet: dfs,
+ Context: ctx,
+ })
+ }
+
+ return out
+}
+
+var gitTreeEntryImplementors = []string{"GitTreeEntry"}
+
+func (ec *executionContext) _GitTreeEntry(ctx context.Context, sel ast.SelectionSet, obj *repository.TreeEntry) graphql.Marshaler {
+ fields := graphql.CollectFields(ec.OperationContext, sel, gitTreeEntryImplementors)
+
+ out := graphql.NewFieldSet(fields)
+ deferred := make(map[string]*graphql.FieldSet)
+ for i, field := range fields {
+ switch field.Name {
+ case "__typename":
+ out.Values[i] = graphql.MarshalString("GitTreeEntry")
+ case "name":
+ out.Values[i] = ec._GitTreeEntry_name(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "type":
+ out.Values[i] = ec._GitTreeEntry_type(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ case "hash":
+ out.Values[i] = ec._GitTreeEntry_hash(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ out.Invalids++
+ }
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+ out.Dispatch(ctx)
+ if out.Invalids > 0 {
+ return graphql.Null
+ }
+
+ atomic.AddInt32(&ec.deferred, int32(len(deferred)))
+
+ for label, dfs := range deferred {
+ ec.processDeferredGroup(graphql.DeferredGroup{
+ Label: label,
+ Path: graphql.GetPath(ctx),
+ FieldSet: dfs,
+ Context: ctx,
+ })
+ }
+
+ return out
+}
+
+// endregion **************************** object.gotpl ****************************
+
+// region ***************************** type.gotpl *****************************
+
+func (ec *executionContext) unmarshalNGitChangeStatus2githubαcomαgitαbugαgitαbugαrepositoryαChangeStatus(ctx context.Context, v any) (repository.ChangeStatus, error) {
+ var res repository.ChangeStatus
+ err := res.UnmarshalGQL(v)
+ return res, graphql.ErrorOnPath(ctx, err)
+}
+
+func (ec *executionContext) marshalNGitChangeStatus2githubαcomαgitαbugαgitαbugαrepositoryαChangeStatus(ctx context.Context, sel ast.SelectionSet, v repository.ChangeStatus) graphql.Marshaler {
+ return v
+}
+
+func (ec *executionContext) marshalNGitChangedFile2ααgithubαcomαgitαbugαgitαbugαrepositoryαChangedFileα(ctx context.Context, sel ast.SelectionSet, v []*repository.ChangedFile) 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.marshalNGitChangedFile2αgithubαcomαgitαbugαgitαbugαrepositoryαChangedFile(ctx, sel, v[i])
+ }
+ if isLen1 {
+ f(i)
+ } else {
+ go f(i)
+ }
+
+ }
+ wg.Wait()
+
+ for _, e := range ret {
+ if e == graphql.Null {
+ return graphql.Null
+ }
+ }
+
+ return ret
+}
+
+func (ec *executionContext) marshalNGitChangedFile2αgithubαcomαgitαbugαgitαbugαrepositoryαChangedFile(ctx context.Context, sel ast.SelectionSet, v *repository.ChangedFile) graphql.Marshaler {
+ if v == nil {
+ if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
+ ec.Errorf(ctx, "the requested element is null which the schema does not allow")
+ }
+ return graphql.Null
+ }
+ return ec._GitChangedFile(ctx, sel, v)
+}
+
+func (ec *executionContext) marshalNGitChangedFileConnection2githubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitChangedFileConnection(ctx context.Context, sel ast.SelectionSet, v models.GitChangedFileConnection) graphql.Marshaler {
+ return ec._GitChangedFileConnection(ctx, sel, &v)
+}
+
+func (ec *executionContext) marshalNGitChangedFileConnection2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitChangedFileConnection(ctx context.Context, sel ast.SelectionSet, v *models.GitChangedFileConnection) graphql.Marshaler {
+ if v == nil {
+ if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
+ ec.Errorf(ctx, "the requested element is null which the schema does not allow")
+ }
+ return graphql.Null
+ }
+ return ec._GitChangedFileConnection(ctx, sel, v)
+}
+
+func (ec *executionContext) marshalNGitCommit2ααgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitCommitMetaα(ctx context.Context, sel ast.SelectionSet, v []*models.GitCommitMeta) 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.marshalNGitCommit2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitCommitMeta(ctx, sel, v[i])
+ }
+ if isLen1 {
+ f(i)
+ } else {
+ go f(i)
+ }
+
+ }
+ wg.Wait()
+
+ for _, e := range ret {
+ if e == graphql.Null {
+ return graphql.Null
+ }
+ }
+
+ return ret
+}
+
+func (ec *executionContext) marshalNGitCommit2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitCommitMeta(ctx context.Context, sel ast.SelectionSet, v *models.GitCommitMeta) graphql.Marshaler {
+ if v == nil {
+ if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
+ ec.Errorf(ctx, "the requested element is null which the schema does not allow")
+ }
+ return graphql.Null
+ }
+ return ec._GitCommit(ctx, sel, v)
+}
+
+func (ec *executionContext) marshalNGitCommitConnection2githubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitCommitConnection(ctx context.Context, sel ast.SelectionSet, v models.GitCommitConnection) graphql.Marshaler {
+ return ec._GitCommitConnection(ctx, sel, &v)
+}
+
+func (ec *executionContext) marshalNGitCommitConnection2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitCommitConnection(ctx context.Context, sel ast.SelectionSet, v *models.GitCommitConnection) graphql.Marshaler {
+ if v == nil {
+ if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
+ ec.Errorf(ctx, "the requested element is null which the schema does not allow")
+ }
+ return graphql.Null
+ }
+ return ec._GitCommitConnection(ctx, sel, v)
+}
+
+func (ec *executionContext) marshalNGitDiffHunk2githubαcomαgitαbugαgitαbugαrepositoryαDiffHunk(ctx context.Context, sel ast.SelectionSet, v repository.DiffHunk) graphql.Marshaler {
+ return ec._GitDiffHunk(ctx, sel, &v)
+}
+
+func (ec *executionContext) marshalNGitDiffHunk2αgithubαcomαgitαbugαgitαbugαrepositoryαDiffHunkα(ctx context.Context, sel ast.SelectionSet, v []repository.DiffHunk) 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.marshalNGitDiffHunk2githubαcomαgitαbugαgitαbugαrepositoryαDiffHunk(ctx, sel, v[i])
+ }
+ if isLen1 {
+ f(i)
+ } else {
+ go f(i)
+ }
+
+ }
+ wg.Wait()
+
+ for _, e := range ret {
+ if e == graphql.Null {
+ return graphql.Null
+ }
+ }
+
+ return ret
+}
+
+func (ec *executionContext) marshalNGitDiffLine2githubαcomαgitαbugαgitαbugαrepositoryαDiffLine(ctx context.Context, sel ast.SelectionSet, v repository.DiffLine) graphql.Marshaler {
+ return ec._GitDiffLine(ctx, sel, &v)
+}
+
+func (ec *executionContext) marshalNGitDiffLine2αgithubαcomαgitαbugαgitαbugαrepositoryαDiffLineα(ctx context.Context, sel ast.SelectionSet, v []repository.DiffLine) 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.marshalNGitDiffLine2githubαcomαgitαbugαgitαbugαrepositoryαDiffLine(ctx, sel, v[i])
+ }
+ if isLen1 {
+ f(i)
+ } else {
+ go f(i)
+ }
+
+ }
+ wg.Wait()
+
+ for _, e := range ret {
+ if e == graphql.Null {
+ return graphql.Null
+ }
+ }
+
+ return ret
+}
+
+func (ec *executionContext) unmarshalNGitDiffLineType2githubαcomαgitαbugαgitαbugαrepositoryαDiffLineType(ctx context.Context, v any) (repository.DiffLineType, error) {
+ var res repository.DiffLineType
+ err := res.UnmarshalGQL(v)
+ return res, graphql.ErrorOnPath(ctx, err)
+}
+
+func (ec *executionContext) marshalNGitDiffLineType2githubαcomαgitαbugαgitαbugαrepositoryαDiffLineType(ctx context.Context, sel ast.SelectionSet, v repository.DiffLineType) graphql.Marshaler {
+ return v
+}
+
+func (ec *executionContext) marshalNGitLastCommit2ααgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitLastCommitα(ctx context.Context, sel ast.SelectionSet, v []*models.GitLastCommit) 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.marshalNGitLastCommit2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitLastCommit(ctx, sel, v[i])
+ }
+ if isLen1 {
+ f(i)
+ } else {
+ go f(i)
+ }
+
+ }
+ wg.Wait()
+
+ for _, e := range ret {
+ if e == graphql.Null {
+ return graphql.Null
+ }
+ }
+
+ return ret
+}
+
+func (ec *executionContext) marshalNGitLastCommit2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitLastCommit(ctx context.Context, sel ast.SelectionSet, v *models.GitLastCommit) graphql.Marshaler {
+ if v == nil {
+ if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
+ ec.Errorf(ctx, "the requested element is null which the schema does not allow")
+ }
+ return graphql.Null
+ }
+ return ec._GitLastCommit(ctx, sel, v)
+}
+
+func (ec *executionContext) unmarshalNGitObjectType2githubαcomαgitαbugαgitαbugαrepositoryαObjectType(ctx context.Context, v any) (repository.ObjectType, error) {
+ var res repository.ObjectType
+ err := res.UnmarshalGQL(v)
+ return res, graphql.ErrorOnPath(ctx, err)
+}
+
+func (ec *executionContext) marshalNGitObjectType2githubαcomαgitαbugαgitαbugαrepositoryαObjectType(ctx context.Context, sel ast.SelectionSet, v repository.ObjectType) graphql.Marshaler {
+ return v
+}
+
+func (ec *executionContext) marshalNGitRef2ααgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefα(ctx context.Context, sel ast.SelectionSet, v []*models.GitRef) 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.marshalNGitRef2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRef(ctx, sel, v[i])
+ }
+ if isLen1 {
+ f(i)
+ } else {
+ go f(i)
+ }
+
+ }
+ wg.Wait()
+
+ for _, e := range ret {
+ if e == graphql.Null {
+ return graphql.Null
+ }
+ }
+
+ return ret
+}
+
+func (ec *executionContext) marshalNGitRef2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRef(ctx context.Context, sel ast.SelectionSet, v *models.GitRef) graphql.Marshaler {
+ if v == nil {
+ if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
+ ec.Errorf(ctx, "the requested element is null which the schema does not allow")
+ }
+ return graphql.Null
+ }
+ return ec._GitRef(ctx, sel, v)
+}
+
+func (ec *executionContext) marshalNGitRefConnection2githubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefConnection(ctx context.Context, sel ast.SelectionSet, v models.GitRefConnection) graphql.Marshaler {
+ return ec._GitRefConnection(ctx, sel, &v)
+}
+
+func (ec *executionContext) marshalNGitRefConnection2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefConnection(ctx context.Context, sel ast.SelectionSet, v *models.GitRefConnection) graphql.Marshaler {
+ if v == nil {
+ if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
+ ec.Errorf(ctx, "the requested element is null which the schema does not allow")
+ }
+ return graphql.Null
+ }
+ return ec._GitRefConnection(ctx, sel, v)
+}
+
+func (ec *executionContext) unmarshalNGitRefType2githubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefType(ctx context.Context, v any) (models.GitRefType, error) {
+ tmp, err := graphql.UnmarshalString(v)
+ res := unmarshalNGitRefType2githubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefType[tmp]
+ return res, graphql.ErrorOnPath(ctx, err)
+}
+
+func (ec *executionContext) marshalNGitRefType2githubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefType(ctx context.Context, sel ast.SelectionSet, v models.GitRefType) graphql.Marshaler {
+ _ = sel
+ res := graphql.MarshalString(marshalNGitRefType2githubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefType[v])
+ if res == graphql.Null {
+ if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
+ ec.Errorf(ctx, "the requested element is null which the schema does not allow")
+ }
+ }
+ return res
+}
+
+var (
+ unmarshalNGitRefType2githubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefType = map[string]models.GitRefType{
+ "BRANCH": models.GitRefTypeBranch,
+ "TAG": models.GitRefTypeTag,
+ }
+ marshalNGitRefType2githubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefType = map[models.GitRefType]string{
+ models.GitRefTypeBranch: "BRANCH",
+ models.GitRefTypeTag: "TAG",
+ }
+)
+
+func (ec *executionContext) marshalNGitTreeEntry2ααgithubαcomαgitαbugαgitαbugαrepositoryαTreeEntryα(ctx context.Context, sel ast.SelectionSet, v []*repository.TreeEntry) 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.marshalNGitTreeEntry2αgithubαcomαgitαbugαgitαbugαrepositoryαTreeEntry(ctx, sel, v[i])
+ }
+ if isLen1 {
+ f(i)
+ } else {
+ go f(i)
+ }
+
+ }
+ wg.Wait()
+
+ for _, e := range ret {
+ if e == graphql.Null {
+ return graphql.Null
+ }
+ }
+
+ return ret
+}
+
+func (ec *executionContext) marshalNGitTreeEntry2αgithubαcomαgitαbugαgitαbugαrepositoryαTreeEntry(ctx context.Context, sel ast.SelectionSet, v *repository.TreeEntry) graphql.Marshaler {
+ if v == nil {
+ if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
+ ec.Errorf(ctx, "the requested element is null which the schema does not allow")
+ }
+ return graphql.Null
+ }
+ return ec._GitTreeEntry(ctx, sel, v)
+}
+
+func (ec *executionContext) marshalOGitBlob2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitBlob(ctx context.Context, sel ast.SelectionSet, v *models.GitBlob) graphql.Marshaler {
+ if v == nil {
+ return graphql.Null
+ }
+ return ec._GitBlob(ctx, sel, v)
+}
+
+func (ec *executionContext) marshalOGitCommit2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitCommitMeta(ctx context.Context, sel ast.SelectionSet, v *models.GitCommitMeta) graphql.Marshaler {
+ if v == nil {
+ return graphql.Null
+ }
+ return ec._GitCommit(ctx, sel, v)
+}
+
+func (ec *executionContext) marshalOGitFileDiff2αgithubαcomαgitαbugαgitαbugαrepositoryαFileDiff(ctx context.Context, sel ast.SelectionSet, v *repository.FileDiff) graphql.Marshaler {
+ if v == nil {
+ return graphql.Null
+ }
+ return ec._GitFileDiff(ctx, sel, v)
+}
+
+func (ec *executionContext) unmarshalOGitRefType2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefType(ctx context.Context, v any) (*models.GitRefType, error) {
+ if v == nil {
+ return nil, nil
+ }
+ tmp, err := graphql.UnmarshalString(v)
+ res := unmarshalOGitRefType2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefType[tmp]
+ return &res, graphql.ErrorOnPath(ctx, err)
+}
+
+func (ec *executionContext) marshalOGitRefType2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefType(ctx context.Context, sel ast.SelectionSet, v *models.GitRefType) graphql.Marshaler {
+ if v == nil {
+ return graphql.Null
+ }
+ _ = sel
+ _ = ctx
+ res := graphql.MarshalString(marshalOGitRefType2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefType[*v])
+ return res
+}
+
+var (
+ unmarshalOGitRefType2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefType = map[string]models.GitRefType{
+ "BRANCH": models.GitRefTypeBranch,
+ "TAG": models.GitRefTypeTag,
+ }
+ marshalOGitRefType2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefType = map[models.GitRefType]string{
+ models.GitRefTypeBranch: "BRANCH",
+ models.GitRefTypeTag: "TAG",
+ }
+)
+
+// endregion ***************************** type.gotpl *****************************
@@ -13,6 +13,7 @@ import (
"github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/graphql/introspection"
"github.com/git-bug/git-bug/entity"
+ "github.com/git-bug/git-bug/repository"
"github.com/vektah/gqlparser/v2/ast"
)
@@ -2539,6 +2540,16 @@ func (ec *executionContext) marshalNString2githubαcomαgitαbugαgitαbug
return v
}
+func (ec *executionContext) unmarshalNString2githubαcomαgitαbugαgitαbugαrepositoryαHash(ctx context.Context, v any) (repository.Hash, error) {
+ var res repository.Hash
+ err := res.UnmarshalGQL(v)
+ return res, graphql.ErrorOnPath(ctx, err)
+}
+
+func (ec *executionContext) marshalNString2githubαcomαgitαbugαgitαbugαrepositoryαHash(ctx context.Context, sel ast.SelectionSet, v repository.Hash) graphql.Marshaler {
+ return v
+}
+
func (ec *executionContext) unmarshalNString2string(ctx context.Context, v any) (string, error) {
res, err := graphql.UnmarshalString(v)
return res, graphql.ErrorOnPath(ctx, err)
@@ -2555,6 +2566,36 @@ func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.S
return res
}
+func (ec *executionContext) unmarshalNString2αstringα(ctx context.Context, v any) ([]string, error) {
+ var vSlice []any
+ vSlice = graphql.CoerceList(v)
+ var err error
+ res := make([]string, len(vSlice))
+ for i := range vSlice {
+ ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i))
+ res[i], err = ec.unmarshalNString2string(ctx, vSlice[i])
+ if err != nil {
+ return nil, err
+ }
+ }
+ return res, nil
+}
+
+func (ec *executionContext) marshalNString2αstringα(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler {
+ ret := make(graphql.Array, len(v))
+ for i := range v {
+ ret[i] = ec.marshalNString2string(ctx, sel, v[i])
+ }
+
+ for _, e := range ret {
+ if e == graphql.Null {
+ return graphql.Null
+ }
+ }
+
+ return ret
+}
+
func (ec *executionContext) marshalN__Directive2githubαcomα99designsαgqlgenαgraphqlαintrospectionαDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler {
return ec.___Directive(ctx, sel, &v)
}
@@ -9,9 +9,11 @@ import (
"strconv"
"sync"
"sync/atomic"
+ "time"
"github.com/99designs/gqlgen/graphql"
"github.com/git-bug/git-bug/api/graphql/models"
+ "github.com/git-bug/git-bug/repository"
"github.com/vektah/gqlparser/v2/ast"
)
@@ -24,6 +26,12 @@ type RepositoryResolver interface {
AllIdentities(ctx context.Context, obj *models.Repository, after *string, before *string, first *int, last *int) (*models.IdentityConnection, error)
Identity(ctx context.Context, obj *models.Repository, prefix string) (models.IdentityWrapper, error)
UserIdentity(ctx context.Context, obj *models.Repository) (models.IdentityWrapper, error)
+ Refs(ctx context.Context, obj *models.Repository, after *string, before *string, first *int, last *int, typeArg *models.GitRefType) (*models.GitRefConnection, error)
+ Tree(ctx context.Context, obj *models.Repository, ref string, path *string) ([]*repository.TreeEntry, error)
+ Blob(ctx context.Context, obj *models.Repository, ref string, path string) (*models.GitBlob, error)
+ Commits(ctx context.Context, obj *models.Repository, after *string, first *int, ref string, path *string, since *time.Time, until *time.Time) (*models.GitCommitConnection, error)
+ Commit(ctx context.Context, obj *models.Repository, hash string) (*models.GitCommitMeta, error)
+ LastCommits(ctx context.Context, obj *models.Repository, ref string, path *string, names []string) ([]*models.GitLastCommit, error)
ValidLabels(ctx context.Context, obj *models.Repository, after *string, before *string, first *int, last *int) (*models.LabelConnection, error)
}
@@ -248,6 +256,57 @@ func (ec *executionContext) field_Repository_allIdentities_argsLast(
return zeroVal, nil
}
+func (ec *executionContext) field_Repository_blob_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
+ var err error
+ args := map[string]any{}
+ arg0, err := ec.field_Repository_blob_argsRef(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["ref"] = arg0
+ arg1, err := ec.field_Repository_blob_argsPath(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["path"] = arg1
+ return args, nil
+}
+func (ec *executionContext) field_Repository_blob_argsRef(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (string, error) {
+ if _, ok := rawArgs["ref"]; !ok {
+ var zeroVal string
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("ref"))
+ if tmp, ok := rawArgs["ref"]; ok {
+ return ec.unmarshalNString2string(ctx, tmp)
+ }
+
+ var zeroVal string
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_blob_argsPath(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (string, error) {
+ if _, ok := rawArgs["path"]; !ok {
+ var zeroVal string
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("path"))
+ if tmp, ok := rawArgs["path"]; ok {
+ return ec.unmarshalNString2string(ctx, tmp)
+ }
+
+ var zeroVal string
+ return zeroVal, nil
+}
+
func (ec *executionContext) field_Repository_bug_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error
args := map[string]any{}
@@ -276,6 +335,177 @@ func (ec *executionContext) field_Repository_bug_argsPrefix(
return zeroVal, nil
}
+func (ec *executionContext) field_Repository_commit_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
+ var err error
+ args := map[string]any{}
+ arg0, err := ec.field_Repository_commit_argsHash(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["hash"] = arg0
+ return args, nil
+}
+func (ec *executionContext) field_Repository_commit_argsHash(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (string, error) {
+ if _, ok := rawArgs["hash"]; !ok {
+ var zeroVal string
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("hash"))
+ if tmp, ok := rawArgs["hash"]; ok {
+ return ec.unmarshalNString2string(ctx, tmp)
+ }
+
+ var zeroVal string
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_commits_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
+ var err error
+ args := map[string]any{}
+ arg0, err := ec.field_Repository_commits_argsAfter(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["after"] = arg0
+ arg1, err := ec.field_Repository_commits_argsFirst(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["first"] = arg1
+ arg2, err := ec.field_Repository_commits_argsRef(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["ref"] = arg2
+ arg3, err := ec.field_Repository_commits_argsPath(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["path"] = arg3
+ arg4, err := ec.field_Repository_commits_argsSince(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["since"] = arg4
+ arg5, err := ec.field_Repository_commits_argsUntil(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["until"] = arg5
+ return args, nil
+}
+func (ec *executionContext) field_Repository_commits_argsAfter(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*string, error) {
+ if _, ok := rawArgs["after"]; !ok {
+ var zeroVal *string
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("after"))
+ if tmp, ok := rawArgs["after"]; ok {
+ return ec.unmarshalOString2αstring(ctx, tmp)
+ }
+
+ var zeroVal *string
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_commits_argsFirst(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*int, error) {
+ if _, ok := rawArgs["first"]; !ok {
+ var zeroVal *int
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("first"))
+ if tmp, ok := rawArgs["first"]; ok {
+ return ec.unmarshalOInt2αint(ctx, tmp)
+ }
+
+ var zeroVal *int
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_commits_argsRef(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (string, error) {
+ if _, ok := rawArgs["ref"]; !ok {
+ var zeroVal string
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("ref"))
+ if tmp, ok := rawArgs["ref"]; ok {
+ return ec.unmarshalNString2string(ctx, tmp)
+ }
+
+ var zeroVal string
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_commits_argsPath(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*string, error) {
+ if _, ok := rawArgs["path"]; !ok {
+ var zeroVal *string
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("path"))
+ if tmp, ok := rawArgs["path"]; ok {
+ return ec.unmarshalOString2αstring(ctx, tmp)
+ }
+
+ var zeroVal *string
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_commits_argsSince(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*time.Time, error) {
+ if _, ok := rawArgs["since"]; !ok {
+ var zeroVal *time.Time
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("since"))
+ if tmp, ok := rawArgs["since"]; ok {
+ return ec.unmarshalOTime2αtimeαTime(ctx, tmp)
+ }
+
+ var zeroVal *time.Time
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_commits_argsUntil(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*time.Time, error) {
+ if _, ok := rawArgs["until"]; !ok {
+ var zeroVal *time.Time
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("until"))
+ if tmp, ok := rawArgs["until"]; ok {
+ return ec.unmarshalOTime2αtimeαTime(ctx, tmp)
+ }
+
+ var zeroVal *time.Time
+ return zeroVal, nil
+}
+
func (ec *executionContext) field_Repository_identity_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error
args := map[string]any{}
@@ -304,32 +534,111 @@ func (ec *executionContext) field_Repository_identity_argsPrefix(
return zeroVal, nil
}
-func (ec *executionContext) field_Repository_validLabels_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
+func (ec *executionContext) field_Repository_lastCommits_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error
args := map[string]any{}
- arg0, err := ec.field_Repository_validLabels_argsAfter(ctx, rawArgs)
+ arg0, err := ec.field_Repository_lastCommits_argsRef(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["ref"] = arg0
+ arg1, err := ec.field_Repository_lastCommits_argsPath(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["path"] = arg1
+ arg2, err := ec.field_Repository_lastCommits_argsNames(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["names"] = arg2
+ return args, nil
+}
+func (ec *executionContext) field_Repository_lastCommits_argsRef(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (string, error) {
+ if _, ok := rawArgs["ref"]; !ok {
+ var zeroVal string
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("ref"))
+ if tmp, ok := rawArgs["ref"]; ok {
+ return ec.unmarshalNString2string(ctx, tmp)
+ }
+
+ var zeroVal string
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_lastCommits_argsPath(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*string, error) {
+ if _, ok := rawArgs["path"]; !ok {
+ var zeroVal *string
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("path"))
+ if tmp, ok := rawArgs["path"]; ok {
+ return ec.unmarshalOString2αstring(ctx, tmp)
+ }
+
+ var zeroVal *string
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_lastCommits_argsNames(
+ ctx context.Context,
+ rawArgs map[string]any,
+) ([]string, error) {
+ if _, ok := rawArgs["names"]; !ok {
+ var zeroVal []string
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("names"))
+ if tmp, ok := rawArgs["names"]; ok {
+ return ec.unmarshalNString2αstringα(ctx, tmp)
+ }
+
+ var zeroVal []string
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_refs_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
+ var err error
+ args := map[string]any{}
+ arg0, err := ec.field_Repository_refs_argsAfter(ctx, rawArgs)
if err != nil {
return nil, err
}
args["after"] = arg0
- arg1, err := ec.field_Repository_validLabels_argsBefore(ctx, rawArgs)
+ arg1, err := ec.field_Repository_refs_argsBefore(ctx, rawArgs)
if err != nil {
return nil, err
}
args["before"] = arg1
- arg2, err := ec.field_Repository_validLabels_argsFirst(ctx, rawArgs)
+ arg2, err := ec.field_Repository_refs_argsFirst(ctx, rawArgs)
if err != nil {
return nil, err
}
args["first"] = arg2
- arg3, err := ec.field_Repository_validLabels_argsLast(ctx, rawArgs)
+ arg3, err := ec.field_Repository_refs_argsLast(ctx, rawArgs)
if err != nil {
return nil, err
}
args["last"] = arg3
+ arg4, err := ec.field_Repository_refs_argsType(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["type"] = arg4
return args, nil
}
-func (ec *executionContext) field_Repository_validLabels_argsAfter(
+func (ec *executionContext) field_Repository_refs_argsAfter(
ctx context.Context,
rawArgs map[string]any,
) (*string, error) {
@@ -337,80 +646,626 @@ func (ec *executionContext) field_Repository_validLabels_argsAfter(
var zeroVal *string
return zeroVal, nil
}
-
- ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("after"))
- if tmp, ok := rawArgs["after"]; ok {
- return ec.unmarshalOString2αstring(ctx, tmp)
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("after"))
+ if tmp, ok := rawArgs["after"]; ok {
+ return ec.unmarshalOString2αstring(ctx, tmp)
+ }
+
+ var zeroVal *string
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_refs_argsBefore(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*string, error) {
+ if _, ok := rawArgs["before"]; !ok {
+ var zeroVal *string
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("before"))
+ if tmp, ok := rawArgs["before"]; ok {
+ return ec.unmarshalOString2αstring(ctx, tmp)
+ }
+
+ var zeroVal *string
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_refs_argsFirst(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*int, error) {
+ if _, ok := rawArgs["first"]; !ok {
+ var zeroVal *int
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("first"))
+ if tmp, ok := rawArgs["first"]; ok {
+ return ec.unmarshalOInt2αint(ctx, tmp)
+ }
+
+ var zeroVal *int
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_refs_argsLast(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*int, error) {
+ if _, ok := rawArgs["last"]; !ok {
+ var zeroVal *int
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("last"))
+ if tmp, ok := rawArgs["last"]; ok {
+ return ec.unmarshalOInt2αint(ctx, tmp)
+ }
+
+ var zeroVal *int
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_refs_argsType(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*models.GitRefType, error) {
+ if _, ok := rawArgs["type"]; !ok {
+ var zeroVal *models.GitRefType
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("type"))
+ if tmp, ok := rawArgs["type"]; ok {
+ return ec.unmarshalOGitRefType2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαGitRefType(ctx, tmp)
+ }
+
+ var zeroVal *models.GitRefType
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_tree_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
+ var err error
+ args := map[string]any{}
+ arg0, err := ec.field_Repository_tree_argsRef(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["ref"] = arg0
+ arg1, err := ec.field_Repository_tree_argsPath(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["path"] = arg1
+ return args, nil
+}
+func (ec *executionContext) field_Repository_tree_argsRef(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (string, error) {
+ if _, ok := rawArgs["ref"]; !ok {
+ var zeroVal string
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("ref"))
+ if tmp, ok := rawArgs["ref"]; ok {
+ return ec.unmarshalNString2string(ctx, tmp)
+ }
+
+ var zeroVal string
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_tree_argsPath(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*string, error) {
+ if _, ok := rawArgs["path"]; !ok {
+ var zeroVal *string
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("path"))
+ if tmp, ok := rawArgs["path"]; ok {
+ return ec.unmarshalOString2αstring(ctx, tmp)
+ }
+
+ var zeroVal *string
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_validLabels_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
+ var err error
+ args := map[string]any{}
+ arg0, err := ec.field_Repository_validLabels_argsAfter(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["after"] = arg0
+ arg1, err := ec.field_Repository_validLabels_argsBefore(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["before"] = arg1
+ arg2, err := ec.field_Repository_validLabels_argsFirst(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["first"] = arg2
+ arg3, err := ec.field_Repository_validLabels_argsLast(ctx, rawArgs)
+ if err != nil {
+ return nil, err
+ }
+ args["last"] = arg3
+ return args, nil
+}
+func (ec *executionContext) field_Repository_validLabels_argsAfter(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*string, error) {
+ if _, ok := rawArgs["after"]; !ok {
+ var zeroVal *string
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("after"))
+ if tmp, ok := rawArgs["after"]; ok {
+ return ec.unmarshalOString2αstring(ctx, tmp)
+ }
+
+ var zeroVal *string
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_validLabels_argsBefore(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*string, error) {
+ if _, ok := rawArgs["before"]; !ok {
+ var zeroVal *string
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("before"))
+ if tmp, ok := rawArgs["before"]; ok {
+ return ec.unmarshalOString2αstring(ctx, tmp)
+ }
+
+ var zeroVal *string
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_validLabels_argsFirst(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*int, error) {
+ if _, ok := rawArgs["first"]; !ok {
+ var zeroVal *int
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("first"))
+ if tmp, ok := rawArgs["first"]; ok {
+ return ec.unmarshalOInt2αint(ctx, tmp)
+ }
+
+ var zeroVal *int
+ return zeroVal, nil
+}
+
+func (ec *executionContext) field_Repository_validLabels_argsLast(
+ ctx context.Context,
+ rawArgs map[string]any,
+) (*int, error) {
+ if _, ok := rawArgs["last"]; !ok {
+ var zeroVal *int
+ return zeroVal, nil
+ }
+
+ ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("last"))
+ if tmp, ok := rawArgs["last"]; ok {
+ return ec.unmarshalOInt2αint(ctx, tmp)
+ }
+
+ var zeroVal *int
+ return zeroVal, nil
+}
+
+// endregion ***************************** args.gotpl *****************************
+
+// region ************************** directives.gotpl **************************
+
+// endregion ************************** directives.gotpl **************************
+
+// region **************************** field.gotpl *****************************
+
+func (ec *executionContext) _Repository_name(ctx context.Context, field graphql.CollectedField, obj *models.Repository) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_Repository_name(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Repository().Name(rctx, obj)
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if resTmp == nil {
+ return graphql.Null
+ }
+ res := resTmp.(*string)
+ fc.Result = res
+ return ec.marshalOString2αstring(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_Repository_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "Repository",
+ Field: field,
+ IsMethod: true,
+ IsResolver: true,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ return nil, errors.New("field of type String does not have child fields")
+ },
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _Repository_allBugs(ctx context.Context, field graphql.CollectedField, obj *models.Repository) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_Repository_allBugs(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Repository().AllBugs(rctx, obj, fc.Args["after"].(*string), fc.Args["before"].(*string), fc.Args["first"].(*int), fc.Args["last"].(*int), fc.Args["query"].(*string))
+ })
+ 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.BugConnection)
+ fc.Result = res
+ return ec.marshalNBugConnection2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαBugConnection(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_Repository_allBugs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "Repository",
+ Field: field,
+ IsMethod: true,
+ IsResolver: true,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "edges":
+ return ec.fieldContext_BugConnection_edges(ctx, field)
+ case "nodes":
+ return ec.fieldContext_BugConnection_nodes(ctx, field)
+ case "pageInfo":
+ return ec.fieldContext_BugConnection_pageInfo(ctx, field)
+ case "totalCount":
+ return ec.fieldContext_BugConnection_totalCount(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type BugConnection", field.Name)
+ },
+ }
+ defer func() {
+ if r := recover(); r != nil {
+ err = ec.Recover(ctx, r)
+ ec.Error(ctx, err)
+ }
+ }()
+ ctx = graphql.WithFieldContext(ctx, fc)
+ if fc.Args, err = ec.field_Repository_allBugs_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
+ ec.Error(ctx, err)
+ return fc, err
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _Repository_bug(ctx context.Context, field graphql.CollectedField, obj *models.Repository) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_Repository_bug(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Repository().Bug(rctx, obj, fc.Args["prefix"].(string))
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if resTmp == nil {
+ return graphql.Null
+ }
+ res := resTmp.(models.BugWrapper)
+ fc.Result = res
+ return ec.marshalOBug2githubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαBugWrapper(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_Repository_bug(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "Repository",
+ Field: field,
+ IsMethod: true,
+ IsResolver: true,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "id":
+ return ec.fieldContext_Bug_id(ctx, field)
+ case "humanId":
+ return ec.fieldContext_Bug_humanId(ctx, field)
+ case "status":
+ return ec.fieldContext_Bug_status(ctx, field)
+ case "title":
+ return ec.fieldContext_Bug_title(ctx, field)
+ case "labels":
+ return ec.fieldContext_Bug_labels(ctx, field)
+ case "author":
+ return ec.fieldContext_Bug_author(ctx, field)
+ case "createdAt":
+ return ec.fieldContext_Bug_createdAt(ctx, field)
+ case "lastEdit":
+ return ec.fieldContext_Bug_lastEdit(ctx, field)
+ case "actors":
+ return ec.fieldContext_Bug_actors(ctx, field)
+ case "participants":
+ return ec.fieldContext_Bug_participants(ctx, field)
+ case "comments":
+ return ec.fieldContext_Bug_comments(ctx, field)
+ case "timeline":
+ return ec.fieldContext_Bug_timeline(ctx, field)
+ case "operations":
+ return ec.fieldContext_Bug_operations(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type Bug", field.Name)
+ },
+ }
+ defer func() {
+ if r := recover(); r != nil {
+ err = ec.Recover(ctx, r)
+ ec.Error(ctx, err)
+ }
+ }()
+ ctx = graphql.WithFieldContext(ctx, fc)
+ if fc.Args, err = ec.field_Repository_bug_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
+ ec.Error(ctx, err)
+ return fc, err
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _Repository_allIdentities(ctx context.Context, field graphql.CollectedField, obj *models.Repository) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_Repository_allIdentities(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Repository().AllIdentities(rctx, obj, fc.Args["after"].(*string), fc.Args["before"].(*string), fc.Args["first"].(*int), fc.Args["last"].(*int))
+ })
+ 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.IdentityConnection)
+ fc.Result = res
+ return ec.marshalNIdentityConnection2αgithubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαIdentityConnection(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_Repository_allIdentities(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "Repository",
+ Field: field,
+ IsMethod: true,
+ IsResolver: true,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "edges":
+ return ec.fieldContext_IdentityConnection_edges(ctx, field)
+ case "nodes":
+ return ec.fieldContext_IdentityConnection_nodes(ctx, field)
+ case "pageInfo":
+ return ec.fieldContext_IdentityConnection_pageInfo(ctx, field)
+ case "totalCount":
+ return ec.fieldContext_IdentityConnection_totalCount(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type IdentityConnection", field.Name)
+ },
+ }
+ defer func() {
+ if r := recover(); r != nil {
+ err = ec.Recover(ctx, r)
+ ec.Error(ctx, err)
+ }
+ }()
+ ctx = graphql.WithFieldContext(ctx, fc)
+ if fc.Args, err = ec.field_Repository_allIdentities_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
+ ec.Error(ctx, err)
+ return fc, err
+ }
+ return fc, nil
+}
+
+func (ec *executionContext) _Repository_identity(ctx context.Context, field graphql.CollectedField, obj *models.Repository) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_Repository_identity(ctx, field)
+ if err != nil {
+ return graphql.Null
+ }
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Repository().Identity(rctx, obj, fc.Args["prefix"].(string))
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if resTmp == nil {
+ return graphql.Null
}
-
- var zeroVal *string
- return zeroVal, nil
+ res := resTmp.(models.IdentityWrapper)
+ fc.Result = res
+ return ec.marshalOIdentity2githubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαIdentityWrapper(ctx, field.Selections, res)
}
-func (ec *executionContext) field_Repository_validLabels_argsBefore(
- ctx context.Context,
- rawArgs map[string]any,
-) (*string, error) {
- if _, ok := rawArgs["before"]; !ok {
- var zeroVal *string
- return zeroVal, nil
+func (ec *executionContext) fieldContext_Repository_identity(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "Repository",
+ Field: field,
+ IsMethod: true,
+ IsResolver: true,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "id":
+ return ec.fieldContext_Identity_id(ctx, field)
+ case "humanId":
+ return ec.fieldContext_Identity_humanId(ctx, field)
+ case "name":
+ return ec.fieldContext_Identity_name(ctx, field)
+ case "email":
+ return ec.fieldContext_Identity_email(ctx, field)
+ case "login":
+ return ec.fieldContext_Identity_login(ctx, field)
+ case "displayName":
+ return ec.fieldContext_Identity_displayName(ctx, field)
+ case "avatarUrl":
+ return ec.fieldContext_Identity_avatarUrl(ctx, field)
+ case "isProtected":
+ return ec.fieldContext_Identity_isProtected(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type Identity", field.Name)
+ },
}
-
- ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("before"))
- if tmp, ok := rawArgs["before"]; ok {
- return ec.unmarshalOString2αstring(ctx, tmp)
+ defer func() {
+ if r := recover(); r != nil {
+ err = ec.Recover(ctx, r)
+ ec.Error(ctx, err)
+ }
+ }()
+ ctx = graphql.WithFieldContext(ctx, fc)
+ if fc.Args, err = ec.field_Repository_identity_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
+ ec.Error(ctx, err)
+ return fc, err
}
-
- var zeroVal *string
- return zeroVal, nil
+ return fc, nil
}
-func (ec *executionContext) field_Repository_validLabels_argsFirst(
- ctx context.Context,
- rawArgs map[string]any,
-) (*int, error) {
- if _, ok := rawArgs["first"]; !ok {
- var zeroVal *int
- return zeroVal, nil
+func (ec *executionContext) _Repository_userIdentity(ctx context.Context, field graphql.CollectedField, obj *models.Repository) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_Repository_userIdentity(ctx, field)
+ if err != nil {
+ return graphql.Null
}
-
- ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("first"))
- if tmp, ok := rawArgs["first"]; ok {
- return ec.unmarshalOInt2αint(ctx, tmp)
+ ctx = graphql.WithFieldContext(ctx, fc)
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Repository().UserIdentity(rctx, obj)
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
}
-
- var zeroVal *int
- return zeroVal, nil
-}
-
-func (ec *executionContext) field_Repository_validLabels_argsLast(
- ctx context.Context,
- rawArgs map[string]any,
-) (*int, error) {
- if _, ok := rawArgs["last"]; !ok {
- var zeroVal *int
- return zeroVal, nil
+ if resTmp == nil {
+ return graphql.Null
}
+ res := resTmp.(models.IdentityWrapper)
+ fc.Result = res
+ return ec.marshalOIdentity2githubαcomαgitαbugαgitαbugαapiαgraphqlαmodelsαIdentityWrapper(ctx, field.Selections, res)
+}
- ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("last"))
- if tmp, ok := rawArgs["last"]; ok {
- return ec.unmarshalOInt2αint(ctx, tmp)
+func (ec *executionContext) fieldContext_Repository_userIdentity(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+ fc = &graphql.FieldContext{
+ Object: "Repository",
+ Field: field,
+ IsMethod: true,
+ IsResolver: true,
+ Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+ switch field.Name {
+ case "id":
+ return ec.fieldContext_Identity_id(ctx, field)
+ case "humanId":
+ return ec.fieldContext_Identity_humanId(ctx, field)
+ case "name":
+ return ec.fieldContext_Identity_name(ctx, field)
+ case "email":
+ return ec.fieldContext_Identity_email(ctx, field)
+ case "login":
+ return ec.fieldContext_Identity_login(ctx, field)
+ case "displayName":
+ return ec.fieldContext_Identity_displayName(ctx, field)
+ case "avatarUrl":
+ return ec.fieldContext_Identity_avatarUrl(ctx, field)
+ case "isProtected":
+ return ec.fieldContext_Identity_isProtected(ctx, field)
+ }
+ return nil, fmt.Errorf("no field named %q was found under type Identity", field.Name)
+ },
}
-
- var zeroVal *int
- return zeroVal, nil
+ return fc, nil
}
-// endregion ***************************** args.gotpl *****************************
-
-// region ************************** directives.gotpl **************************
-
-// endregion ************************** directives.gotpl **************************
-
-// region **************************** field.gotpl *****************************
-
-func (ec *executionContext) _Repository_name(ctx context.Context, field graphql.CollectedField, obj *models.Repository) (ret graphql.Marshaler) {
- fc, err := ec.fieldContext_Repository_name(ctx, field)
+func (ec *executionContext) _Repository_refs(ctx context.Context, field graphql.CollectedField, obj *models.Repository) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_Repository_refs(ctx, field)
if err != nil {
return graphql.Null
}
@@ -1070,6 +1070,18 @@ func (ec *executionContext) fieldContext_Query_repository(ctx context.Context, f
return ec.fieldContext_Repository_identity(ctx, field)
case "userIdentity":
return ec.fieldContext_Repository_userIdentity(ctx, field)
+ case "refs":
+ return ec.fieldContext_Repository_refs(ctx, field)
+ case "tree":
+ return ec.fieldContext_Repository_tree(ctx, field)
+ case "blob":
+ return ec.fieldContext_Repository_blob(ctx, field)
+ case "commits":
+ return ec.fieldContext_Repository_commits(ctx, field)
+ case "commit":
+ return ec.fieldContext_Repository_commit(ctx, field)
+ case "lastCommits":
+ return ec.fieldContext_Repository_lastCommits(ctx, field)
case "validLabels":
return ec.fieldContext_Repository_validLabels(ctx, field)
}
@@ -7,6 +7,7 @@ import (
"context"
"errors"
"sync/atomic"
+ "time"
"github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/graphql/introspection"
@@ -48,6 +49,7 @@ type ResolverRoot interface {
BugSetTitleOperation() BugSetTitleOperationResolver
BugSetTitleTimelineItem() BugSetTitleTimelineItemResolver
Color() ColorResolver
+ GitCommit() GitCommitResolver
Identity() IdentityResolver
Label() LabelResolver
Mutation() MutationResolver
@@ -293,6 +295,95 @@ type ComplexityRoot struct {
Type func(childComplexity int) int
}
+ GitBlob struct {
+ Hash func(childComplexity int) int
+ IsBinary func(childComplexity int) int
+ IsTruncated func(childComplexity int) int
+ Path func(childComplexity int) int
+ Size func(childComplexity int) int
+ Text func(childComplexity int) int
+ }
+
+ GitChangedFile struct {
+ OldPath func(childComplexity int) int
+ Path func(childComplexity int) int
+ Status func(childComplexity int) int
+ }
+
+ GitChangedFileConnection struct {
+ Nodes func(childComplexity int) int
+ PageInfo func(childComplexity int) int
+ TotalCount func(childComplexity int) int
+ }
+
+ GitCommit struct {
+ AuthorEmail func(childComplexity int) int
+ AuthorName func(childComplexity int) int
+ Date func(childComplexity int) int
+ Diff func(childComplexity int, path string) int
+ Files func(childComplexity int, after *string, before *string, first *int, last *int) int
+ FullMessage func(childComplexity int) int
+ Hash func(childComplexity int) int
+ Message func(childComplexity int) int
+ Parents func(childComplexity int) int
+ ShortHash func(childComplexity int) int
+ }
+
+ GitCommitConnection struct {
+ Nodes func(childComplexity int) int
+ PageInfo func(childComplexity int) int
+ TotalCount func(childComplexity int) int
+ }
+
+ GitDiffHunk struct {
+ Lines func(childComplexity int) int
+ NewLines func(childComplexity int) int
+ NewStart func(childComplexity int) int
+ OldLines func(childComplexity int) int
+ OldStart func(childComplexity int) int
+ }
+
+ GitDiffLine struct {
+ Content func(childComplexity int) int
+ NewLine func(childComplexity int) int
+ OldLine func(childComplexity int) int
+ Type func(childComplexity int) int
+ }
+
+ GitFileDiff struct {
+ Hunks func(childComplexity int) int
+ IsBinary func(childComplexity int) int
+ IsDelete func(childComplexity int) int
+ IsNew func(childComplexity int) int
+ OldPath func(childComplexity int) int
+ Path func(childComplexity int) int
+ }
+
+ GitLastCommit struct {
+ Commit func(childComplexity int) int
+ Name func(childComplexity int) int
+ }
+
+ GitRef struct {
+ Hash func(childComplexity int) int
+ IsDefault func(childComplexity int) int
+ Name func(childComplexity int) int
+ ShortName func(childComplexity int) int
+ Type func(childComplexity int) int
+ }
+
+ GitRefConnection struct {
+ Nodes func(childComplexity int) int
+ PageInfo func(childComplexity int) int
+ TotalCount func(childComplexity int) int
+ }
+
+ GitTreeEntry struct {
+ Hash func(childComplexity int) int
+ Name func(childComplexity int) int
+ ObjectType func(childComplexity int) int
+ }
+
Identity struct {
AvatarUrl func(childComplexity int) int
DisplayName func(childComplexity int) int
@@ -382,9 +473,15 @@ type ComplexityRoot struct {
Repository struct {
AllBugs func(childComplexity int, after *string, before *string, first *int, last *int, query *string) int
AllIdentities func(childComplexity int, after *string, before *string, first *int, last *int) int
+ Blob func(childComplexity int, ref string, path string) int
Bug func(childComplexity int, prefix string) int
+ Commit func(childComplexity int, hash string) int
+ Commits func(childComplexity int, after *string, first *int, ref string, path *string, since *time.Time, until *time.Time) int
Identity func(childComplexity int, prefix string) int
+ LastCommits func(childComplexity int, ref string, path *string, names []string) int
Name func(childComplexity int) int
+ Refs func(childComplexity int, after *string, before *string, first *int, last *int, typeArg *models.GitRefType) int
+ Tree func(childComplexity int, ref string, path *string) int
UserIdentity func(childComplexity int) int
ValidLabels func(childComplexity int, after *string, before *string, first *int, last *int) int
}
@@ -1411,6 +1508,387 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.EntityEvent.Type(childComplexity), true
+ case "GitBlob.hash":
+ if e.complexity.GitBlob.Hash == nil {
+ break
+ }
+
+ return e.complexity.GitBlob.Hash(childComplexity), true
+
+ case "GitBlob.isBinary":
+ if e.complexity.GitBlob.IsBinary == nil {
+ break
+ }
+
+ return e.complexity.GitBlob.IsBinary(childComplexity), true
+
+ case "GitBlob.isTruncated":
+ if e.complexity.GitBlob.IsTruncated == nil {
+ break
+ }
+
+ return e.complexity.GitBlob.IsTruncated(childComplexity), true
+
+ case "GitBlob.path":
+ if e.complexity.GitBlob.Path == nil {
+ break
+ }
+
+ return e.complexity.GitBlob.Path(childComplexity), true
+
+ case "GitBlob.size":
+ if e.complexity.GitBlob.Size == nil {
+ break
+ }
+
+ return e.complexity.GitBlob.Size(childComplexity), true
+
+ case "GitBlob.text":
+ if e.complexity.GitBlob.Text == nil {
+ break
+ }
+
+ return e.complexity.GitBlob.Text(childComplexity), true
+
+ case "GitChangedFile.oldPath":
+ if e.complexity.GitChangedFile.OldPath == nil {
+ break
+ }
+
+ return e.complexity.GitChangedFile.OldPath(childComplexity), true
+
+ case "GitChangedFile.path":
+ if e.complexity.GitChangedFile.Path == nil {
+ break
+ }
+
+ return e.complexity.GitChangedFile.Path(childComplexity), true
+
+ case "GitChangedFile.status":
+ if e.complexity.GitChangedFile.Status == nil {
+ break
+ }
+
+ return e.complexity.GitChangedFile.Status(childComplexity), true
+
+ case "GitChangedFileConnection.nodes":
+ if e.complexity.GitChangedFileConnection.Nodes == nil {
+ break
+ }
+
+ return e.complexity.GitChangedFileConnection.Nodes(childComplexity), true
+
+ case "GitChangedFileConnection.pageInfo":
+ if e.complexity.GitChangedFileConnection.PageInfo == nil {
+ break
+ }
+
+ return e.complexity.GitChangedFileConnection.PageInfo(childComplexity), true
+
+ case "GitChangedFileConnection.totalCount":
+ if e.complexity.GitChangedFileConnection.TotalCount == nil {
+ break
+ }
+
+ return e.complexity.GitChangedFileConnection.TotalCount(childComplexity), true
+
+ case "GitCommit.authorEmail":
+ if e.complexity.GitCommit.AuthorEmail == nil {
+ break
+ }
+
+ return e.complexity.GitCommit.AuthorEmail(childComplexity), true
+
+ case "GitCommit.authorName":
+ if e.complexity.GitCommit.AuthorName == nil {
+ break
+ }
+
+ return e.complexity.GitCommit.AuthorName(childComplexity), true
+
+ case "GitCommit.date":
+ if e.complexity.GitCommit.Date == nil {
+ break
+ }
+
+ return e.complexity.GitCommit.Date(childComplexity), true
+
+ case "GitCommit.diff":
+ if e.complexity.GitCommit.Diff == nil {
+ break
+ }
+
+ args, err := ec.field_GitCommit_diff_args(ctx, rawArgs)
+ if err != nil {
+ return 0, false
+ }
+
+ return e.complexity.GitCommit.Diff(childComplexity, args["path"].(string)), true
+
+ case "GitCommit.files":
+ if e.complexity.GitCommit.Files == nil {
+ break
+ }
+
+ args, err := ec.field_GitCommit_files_args(ctx, rawArgs)
+ if err != nil {
+ return 0, false
+ }
+
+ return e.complexity.GitCommit.Files(childComplexity, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int)), true
+
+ case "GitCommit.fullMessage":
+ if e.complexity.GitCommit.FullMessage == nil {
+ break
+ }
+
+ return e.complexity.GitCommit.FullMessage(childComplexity), true
+
+ case "GitCommit.hash":
+ if e.complexity.GitCommit.Hash == nil {
+ break
+ }
+
+ return e.complexity.GitCommit.Hash(childComplexity), true
+
+ case "GitCommit.message":
+ if e.complexity.GitCommit.Message == nil {
+ break
+ }
+
+ return e.complexity.GitCommit.Message(childComplexity), true
+
+ case "GitCommit.parents":
+ if e.complexity.GitCommit.Parents == nil {
+ break
+ }
+
+ return e.complexity.GitCommit.Parents(childComplexity), true
+
+ case "GitCommit.shortHash":
+ if e.complexity.GitCommit.ShortHash == nil {
+ break
+ }
+
+ return e.complexity.GitCommit.ShortHash(childComplexity), true
+
+ case "GitCommitConnection.nodes":
+ if e.complexity.GitCommitConnection.Nodes == nil {
+ break
+ }
+
+ return e.complexity.GitCommitConnection.Nodes(childComplexity), true
+
+ case "GitCommitConnection.pageInfo":
+ if e.complexity.GitCommitConnection.PageInfo == nil {
+ break
+ }
+
+ return e.complexity.GitCommitConnection.PageInfo(childComplexity), true
+
+ case "GitCommitConnection.totalCount":
+ if e.complexity.GitCommitConnection.TotalCount == nil {
+ break
+ }
+
+ return e.complexity.GitCommitConnection.TotalCount(childComplexity), true
+
+ case "GitDiffHunk.lines":
+ if e.complexity.GitDiffHunk.Lines == nil {
+ break
+ }
+
+ return e.complexity.GitDiffHunk.Lines(childComplexity), true
+
+ case "GitDiffHunk.newLines":
+ if e.complexity.GitDiffHunk.NewLines == nil {
+ break
+ }
+
+ return e.complexity.GitDiffHunk.NewLines(childComplexity), true
+
+ case "GitDiffHunk.newStart":
+ if e.complexity.GitDiffHunk.NewStart == nil {
+ break
+ }
+
+ return e.complexity.GitDiffHunk.NewStart(childComplexity), true
+
+ case "GitDiffHunk.oldLines":
+ if e.complexity.GitDiffHunk.OldLines == nil {
+ break
+ }
+
+ return e.complexity.GitDiffHunk.OldLines(childComplexity), true
+
+ case "GitDiffHunk.oldStart":
+ if e.complexity.GitDiffHunk.OldStart == nil {
+ break
+ }
+
+ return e.complexity.GitDiffHunk.OldStart(childComplexity), true
+
+ case "GitDiffLine.content":
+ if e.complexity.GitDiffLine.Content == nil {
+ break
+ }
+
+ return e.complexity.GitDiffLine.Content(childComplexity), true
+
+ case "GitDiffLine.newLine":
+ if e.complexity.GitDiffLine.NewLine == nil {
+ break
+ }
+
+ return e.complexity.GitDiffLine.NewLine(childComplexity), true
+
+ case "GitDiffLine.oldLine":
+ if e.complexity.GitDiffLine.OldLine == nil {
+ break
+ }
+
+ return e.complexity.GitDiffLine.OldLine(childComplexity), true
+
+ case "GitDiffLine.type":
+ if e.complexity.GitDiffLine.Type == nil {
+ break
+ }
+
+ return e.complexity.GitDiffLine.Type(childComplexity), true
+
+ case "GitFileDiff.hunks":
+ if e.complexity.GitFileDiff.Hunks == nil {
+ break
+ }
+
+ return e.complexity.GitFileDiff.Hunks(childComplexity), true
+
+ case "GitFileDiff.isBinary":
+ if e.complexity.GitFileDiff.IsBinary == nil {
+ break
+ }
+
+ return e.complexity.GitFileDiff.IsBinary(childComplexity), true
+
+ case "GitFileDiff.isDelete":
+ if e.complexity.GitFileDiff.IsDelete == nil {
+ break
+ }
+
+ return e.complexity.GitFileDiff.IsDelete(childComplexity), true
+
+ case "GitFileDiff.isNew":
+ if e.complexity.GitFileDiff.IsNew == nil {
+ break
+ }
+
+ return e.complexity.GitFileDiff.IsNew(childComplexity), true
+
+ case "GitFileDiff.oldPath":
+ if e.complexity.GitFileDiff.OldPath == nil {
+ break
+ }
+
+ return e.complexity.GitFileDiff.OldPath(childComplexity), true
+
+ case "GitFileDiff.path":
+ if e.complexity.GitFileDiff.Path == nil {
+ break
+ }
+
+ return e.complexity.GitFileDiff.Path(childComplexity), true
+
+ case "GitLastCommit.commit":
+ if e.complexity.GitLastCommit.Commit == nil {
+ break
+ }
+
+ return e.complexity.GitLastCommit.Commit(childComplexity), true
+
+ case "GitLastCommit.name":
+ if e.complexity.GitLastCommit.Name == nil {
+ break
+ }
+
+ return e.complexity.GitLastCommit.Name(childComplexity), true
+
+ case "GitRef.hash":
+ if e.complexity.GitRef.Hash == nil {
+ break
+ }
+
+ return e.complexity.GitRef.Hash(childComplexity), true
+
+ case "GitRef.isDefault":
+ if e.complexity.GitRef.IsDefault == nil {
+ break
+ }
+
+ return e.complexity.GitRef.IsDefault(childComplexity), true
+
+ case "GitRef.name":
+ if e.complexity.GitRef.Name == nil {
+ break
+ }
+
+ return e.complexity.GitRef.Name(childComplexity), true
+
+ case "GitRef.shortName":
+ if e.complexity.GitRef.ShortName == nil {
+ break
+ }
+
+ return e.complexity.GitRef.ShortName(childComplexity), true
+
+ case "GitRef.type":
+ if e.complexity.GitRef.Type == nil {
+ break
+ }
+
+ return e.complexity.GitRef.Type(childComplexity), true
+
+ case "GitRefConnection.nodes":
+ if e.complexity.GitRefConnection.Nodes == nil {
+ break
+ }
+
+ return e.complexity.GitRefConnection.Nodes(childComplexity), true
+
+ case "GitRefConnection.pageInfo":
+ if e.complexity.GitRefConnection.PageInfo == nil {
+ break
+ }
+
+ return e.complexity.GitRefConnection.PageInfo(childComplexity), true
+
+ case "GitRefConnection.totalCount":
+ if e.complexity.GitRefConnection.TotalCount == nil {
+ break
+ }
+
+ return e.complexity.GitRefConnection.TotalCount(childComplexity), true
+
+ case "GitTreeEntry.hash":
+ if e.complexity.GitTreeEntry.Hash == nil {
+ break
+ }
+
+ return e.complexity.GitTreeEntry.Hash(childComplexity), true
+
+ case "GitTreeEntry.name":
+ if e.complexity.GitTreeEntry.Name == nil {
+ break
+ }
+
+ return e.complexity.GitTreeEntry.Name(childComplexity), true
+
+ case "GitTreeEntry.type":
+ if e.complexity.GitTreeEntry.ObjectType == nil {
+ break
+ }
+
+ return e.complexity.GitTreeEntry.ObjectType(childComplexity), true
+
case "Identity.avatarUrl":
if e.complexity.Identity.AvatarUrl == nil {
break
@@ -1819,6 +2297,18 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.Repository.AllIdentities(childComplexity, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int)), true
+ case "Repository.blob":
+ if e.complexity.Repository.Blob == nil {
+ break
+ }
+
+ args, err := ec.field_Repository_blob_args(ctx, rawArgs)
+ if err != nil {
+ return 0, false
+ }
+
+ return e.complexity.Repository.Blob(childComplexity, args["ref"].(string), args["path"].(string)), true
+
case "Repository.bug":
if e.complexity.Repository.Bug == nil {
break
@@ -1831,6 +2321,30 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.Repository.Bug(childComplexity, args["prefix"].(string)), true
+ case "Repository.commit":
+ if e.complexity.Repository.Commit == nil {
+ break
+ }
+
+ args, err := ec.field_Repository_commit_args(ctx, rawArgs)
+ if err != nil {
+ return 0, false
+ }
+
+ return e.complexity.Repository.Commit(childComplexity, args["hash"].(string)), true
+
+ case "Repository.commits":
+ if e.complexity.Repository.Commits == nil {
+ break
+ }
+
+ args, err := ec.field_Repository_commits_args(ctx, rawArgs)
+ if err != nil {
+ return 0, false
+ }
+
+ return e.complexity.Repository.Commits(childComplexity, args["after"].(*string), args["first"].(*int), args["ref"].(string), args["path"].(*string), args["since"].(*time.Time), args["until"].(*time.Time)), true
+
case "Repository.identity":
if e.complexity.Repository.Identity == nil {
break
@@ -1843,6 +2357,18 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.Repository.Identity(childComplexity, args["prefix"].(string)), true
+ case "Repository.lastCommits":
+ if e.complexity.Repository.LastCommits == nil {
+ break
+ }
+
+ args, err := ec.field_Repository_lastCommits_args(ctx, rawArgs)
+ if err != nil {
+ return 0, false
+ }
+
+ return e.complexity.Repository.LastCommits(childComplexity, args["ref"].(string), args["path"].(*string), args["names"].([]string)), true
+
case "Repository.name":
if e.complexity.Repository.Name == nil {
break
@@ -1850,6 +2376,30 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
return e.complexity.Repository.Name(childComplexity), true
+ case "Repository.refs":
+ if e.complexity.Repository.Refs == nil {
+ break
+ }
+
+ args, err := ec.field_Repository_refs_args(ctx, rawArgs)
+ if err != nil {
+ return 0, false
+ }
+
+ return e.complexity.Repository.Refs(childComplexity, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int), args["type"].(*models.GitRefType)), true
+
+ case "Repository.tree":
+ if e.complexity.Repository.Tree == nil {
+ break
+ }
+
+ args, err := ec.field_Repository_tree_args(ctx, rawArgs)
+ if err != nil {
+ return 0, false
+ }
+
+ return e.complexity.Repository.Tree(childComplexity, args["ref"].(string), args["path"].(*string)), true
+
case "Repository.userIdentity":
if e.complexity.Repository.UserIdentity == nil {
break
@@ -2601,6 +3151,225 @@ directive @goTag(
key: String!
value: String
) on INPUT_FIELD_DEFINITION | FIELD_DEFINITION
+
+directive @goEnum(
+ value: String
+) on ENUM_VALUE
+`, BuiltIn: false},
+ {Name: "../schema/git.graphql", Input: `"""A git branch or tag reference."""
+type GitRef {
+ """Full reference name, e.g. refs/heads/main or refs/tags/v1.0."""
+ name: String!
+ """Short name, e.g. main or v1.0."""
+ shortName: String!
+ """Whether this reference is a branch or a tag."""
+ type: GitRefType!
+ """Commit hash the reference points to."""
+ hash: String!
+ """True for the branch HEAD currently points to."""
+ isDefault: Boolean!
+}
+
+"""An entry in a git tree (directory listing)."""
+type GitTreeEntry
+@goModel(model: "github.com/git-bug/git-bug/repository.TreeEntry") {
+ """File or directory name within the parent tree."""
+ name: String!
+ """Whether this entry is a file, directory, symlink, or submodule."""
+ type: GitObjectType! @goField(name: "ObjectType")
+ """Git object hash."""
+ hash: String!
+}
+
+"""The content of a git blob (file)."""
+type GitBlob {
+ """Path of the file relative to the repository root."""
+ path: String!
+ """Git object hash. Can be used as a stable cache key or to construct a
+ raw download URL."""
+ hash: String!
+ """UTF-8 text content of the file. Null when isBinary is true or when
+ the file is too large to be returned inline (see isTruncated)."""
+ text: String
+ """Size in bytes."""
+ size: Int!
+ """True when the file contains null bytes and is treated as binary.
+ text will be null."""
+ isBinary: Boolean!
+ """True when the file exceeds the maximum inline size and text has been
+ omitted. Use the raw download endpoint to retrieve the full content."""
+ isTruncated: Boolean!
+}
+
+"""Metadata for a single git commit."""
+type GitCommit
+@goModel(model: "github.com/git-bug/git-bug/api/graphql/models.GitCommitMeta") {
+ """Full SHA-1 commit hash."""
+ hash: String!
+ """Abbreviated commit hash, typically 8 characters."""
+ shortHash: String!
+ """First line of the commit message."""
+ message: String!
+ """Full commit message."""
+ fullMessage: String!
+ """Name of the commit author."""
+ authorName: String!
+ """Email address of the commit author."""
+ authorEmail: String!
+ """Timestamp from the author field (when the change was originally made)."""
+ date: Time!
+ """Hashes of parent commits. Empty for the initial commit."""
+ parents: [String!]!
+ """Files changed relative to the first parent (or the empty tree for the
+ initial commit)."""
+ files(
+ """Returns the elements in the list that come after the specified cursor."""
+ after: String
+ """Returns the elements in the list that come before the specified cursor."""
+ before: String
+ """Returns the first _n_ elements from the list."""
+ first: Int
+ """Returns the last _n_ elements from the list."""
+ last: Int
+ ): GitChangedFileConnection!
+ """Unified diff for a single file in this commit."""
+ diff(path: String!): GitFileDiff
+}
+
+"""The last commit that touched each requested entry in a directory."""
+type GitLastCommit {
+ """Entry name within the directory."""
+ name: String!
+ """Most recent commit that modified this entry."""
+ commit: GitCommit!
+}
+
+# ββ connection types ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+type GitRefConnection {
+ nodes: [GitRef!]!
+ pageInfo: PageInfo!
+ totalCount: Int!
+}
+
+"""Paginated list of commits."""
+type GitCommitConnection {
+ nodes: [GitCommit!]!
+ pageInfo: PageInfo!
+ totalCount: Int!
+}
+
+type GitChangedFileConnection {
+ nodes: [GitChangedFile!]!
+ pageInfo: PageInfo!
+ totalCount: Int!
+}
+
+# ββ commit sub-types ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+"""A file that was changed in a commit."""
+type GitChangedFile
+@goModel(model: "github.com/git-bug/git-bug/repository.ChangedFile") {
+ """Path of the file in the new version of the commit."""
+ path: String!
+ """Previous path, non-null only for renames."""
+ oldPath: String
+ """How the file was affected by the commit."""
+ status: GitChangeStatus!
+}
+
+"""The diff for a single file in a commit."""
+type GitFileDiff
+@goModel(model: "github.com/git-bug/git-bug/repository.FileDiff") {
+ """Path of the file in the new version."""
+ path: String!
+ """Previous path, non-null only for renames."""
+ oldPath: String
+ """True when the file is binary and no textual diff is available."""
+ isBinary: Boolean!
+ """True when the file was created in this commit."""
+ isNew: Boolean!
+ """True when the file was deleted in this commit."""
+ isDelete: Boolean!
+ """Contiguous blocks of changes. Empty for binary files."""
+ hunks: [GitDiffHunk!]!
+}
+
+"""A contiguous block of changes in a unified diff."""
+type GitDiffHunk
+@goModel(model: "github.com/git-bug/git-bug/repository.DiffHunk") {
+ """Starting line number in the old file."""
+ oldStart: Int!
+ """Number of lines from the old file included in this hunk."""
+ oldLines: Int!
+ """Starting line number in the new file."""
+ newStart: Int!
+ """Number of lines from the new file included in this hunk."""
+ newLines: Int!
+ """Lines in this hunk, including context, additions, and deletions."""
+ lines: [GitDiffLine!]!
+}
+
+"""A single line in a unified diff hunk."""
+type GitDiffLine
+@goModel(model: "github.com/git-bug/git-bug/repository.DiffLine") {
+ """Whether this line is context, an addition, or a deletion."""
+ type: GitDiffLineType!
+ """Raw line content, without the leading +/- prefix."""
+ content: String!
+ """Line number in the old file. 0 for added lines."""
+ oldLine: Int!
+ """Line number in the new file. 0 for deleted lines."""
+ newLine: Int!
+}
+
+# ββ enums βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+"""The kind of git reference: a branch or a tag."""
+enum GitRefType
+@goModel(model: "github.com/git-bug/git-bug/api/graphql/models.GitRefType") {
+ """A local branch (refs/heads/*)."""
+ BRANCH @goEnum(value: "github.com/git-bug/git-bug/api/graphql/models.GitRefTypeBranch")
+ """An annotated or lightweight tag (refs/tags/*)."""
+ TAG @goEnum(value: "github.com/git-bug/git-bug/api/graphql/models.GitRefTypeTag")
+}
+
+"""The type of object a git tree entry points to."""
+enum GitObjectType
+@goModel(model: "github.com/git-bug/git-bug/repository.ObjectType") {
+ """A directory."""
+ TREE
+ """A regular or executable file."""
+ BLOB
+ """A symbolic link."""
+ SYMLINK
+ """A git submodule."""
+ SUBMODULE
+}
+
+"""How a file was affected by a commit."""
+enum GitChangeStatus
+@goModel(model: "github.com/git-bug/git-bug/repository.ChangeStatus") {
+ """File was created in this commit."""
+ ADDED
+ """File content changed in this commit."""
+ MODIFIED
+ """File was removed in this commit."""
+ DELETED
+ """File was moved or renamed in this commit."""
+ RENAMED
+}
+
+"""The role of a line within a unified diff hunk."""
+enum GitDiffLineType
+@goModel(model: "github.com/git-bug/git-bug/repository.DiffLineType") {
+ """An unchanged line present in both old and new versions."""
+ CONTEXT
+ """A line added in the new version."""
+ ADDED
+ """A line removed from the old version."""
+ DELETED
+}
`, BuiltIn: false},
{Name: "../schema/identity.graphql", Input: `"""Represents an identity"""
type Identity implements Entity {
@@ -2734,6 +3503,53 @@ type OperationEdge {
"""The identity created or selected by the user as its own"""
userIdentity: Identity
+ """All branches and tags, optionally filtered by type."""
+ refs(
+ """Returns the elements in the list that come after the specified cursor."""
+ after: String
+ """Returns the elements in the list that come before the specified cursor."""
+ before: String
+ """Returns the first _n_ elements from the list."""
+ first: Int
+ """Returns the last _n_ elements from the list."""
+ last: Int
+ """Restrict to references of this type."""
+ type: GitRefType
+ ): GitRefConnection!
+
+ """Directory listing at path under ref. An empty path returns the root tree."""
+ tree(ref: String!, path: String): [GitTreeEntry!]!
+
+ """Content of the file at path under ref. Null if the path does not exist
+ or resolves to a tree rather than a blob."""
+ blob(ref: String!, path: String!): GitBlob
+
+ """Paginated commit log reachable from ref, optionally filtered to commits
+ touching path."""
+ commits(
+ """Returns the elements in the list that come after the specified cursor."""
+ after: String
+ """Returns the first _n_ elements from the list (max 100, default 20)."""
+ first: Int
+ """Branch name, tag name, full ref (e.g. refs/heads/main), or commit hash
+ to start the log from."""
+ ref: String!
+ """Restrict to commits that touched this path."""
+ path: String
+ """Restrict to commits authored on or after this timestamp."""
+ since: Time
+ """Restrict to commits authored before or on this timestamp."""
+ until: Time
+ ): GitCommitConnection!
+
+ """A single commit by hash."""
+ commit(hash: String!): GitCommit
+
+ """The most recent commit that touched each of the named entries in the
+ directory at path under ref. Use this to populate last-commit info on a
+ tree listing without blocking the initial tree fetch."""
+ lastCommits(ref: String!, path: String, names: [String!]!): [GitLastCommit!]!
+
"""List of valid labels."""
validLabels(
"""Returns the elements in the list that come after the specified cursor."""
@@ -809,4 +809,22 @@ func (ec *executionContext) marshalOHash2αgithubαcomαgitαbugαgitαbug
return ret
}
+func (ec *executionContext) unmarshalOTime2αtimeαTime(ctx context.Context, v any) (*time.Time, error) {
+ if v == nil {
+ return nil, nil
+ }
+ res, err := graphql.UnmarshalTime(v)
+ return &res, graphql.ErrorOnPath(ctx, err)
+}
+
+func (ec *executionContext) marshalOTime2αtimeαTime(ctx context.Context, sel ast.SelectionSet, v *time.Time) graphql.Marshaler {
+ if v == nil {
+ return graphql.Null
+ }
+ _ = sel
+ _ = ctx
+ res := graphql.MarshalTime(*v)
+ return res
+}
+
// endregion ***************************** type.gotpl *****************************
@@ -220,6 +220,232 @@ func TestQueries(t *testing.T) {
assert.NoError(t, err)
}
+// TestGitBrowseQueries exercises the git-browsing GraphQL fields (commit, blob,
+// tree, commits, lastCommits) against a synthetic fixture repo with the same
+// commit graph used by RepoBrowseTest:
+//
+// c1 ββ c2 ββ c3 refs/heads/main
+// βββββββββ refs/heads/feature
+// c1 βββ refs/tags/v1.0
+func TestGitBrowseQueries(t *testing.T) {
+ repo := repository.CreateGoGitTestRepo(t, false)
+ require.NoError(t, repo.LocalConfig().StoreString("init.defaultBranch", "main"))
+
+ // ββ build fixture βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+ readmeV1 := []byte("# Hello\n")
+ readmeV3 := []byte("# Hello\n\n## Updated\n")
+ mainV1 := []byte("package main\n")
+ mainV2 := []byte("package main\n\n// updated\n")
+ libV1 := []byte("package lib\n")
+ utilV1 := []byte("package util\n")
+
+ hReadmeV1, err := repo.StoreData(readmeV1)
+ require.NoError(t, err)
+ hReadmeV3, err := repo.StoreData(readmeV3)
+ require.NoError(t, err)
+ hMainV1, err := repo.StoreData(mainV1)
+ require.NoError(t, err)
+ hMainV2, err := repo.StoreData(mainV2)
+ require.NoError(t, err)
+ hLibV1, err := repo.StoreData(libV1)
+ require.NoError(t, err)
+ hUtilV1, err := repo.StoreData(utilV1)
+ require.NoError(t, err)
+
+ srcTreeV1, err := repo.StoreTree([]repository.TreeEntry{
+ {ObjectType: repository.Blob, Hash: hLibV1, Name: "lib.go"},
+ })
+ require.NoError(t, err)
+ rootTreeV1, err := repo.StoreTree([]repository.TreeEntry{
+ {ObjectType: repository.Blob, Hash: hReadmeV1, Name: "README.md"},
+ {ObjectType: repository.Blob, Hash: hMainV1, Name: "main.go"},
+ {ObjectType: repository.Tree, Hash: srcTreeV1, Name: "src"},
+ })
+ require.NoError(t, err)
+
+ srcTreeV2, err := repo.StoreTree([]repository.TreeEntry{
+ {ObjectType: repository.Blob, Hash: hLibV1, Name: "lib.go"},
+ {ObjectType: repository.Blob, Hash: hUtilV1, Name: "util.go"},
+ })
+ require.NoError(t, err)
+ rootTreeV2, err := repo.StoreTree([]repository.TreeEntry{
+ {ObjectType: repository.Blob, Hash: hReadmeV1, Name: "README.md"},
+ {ObjectType: repository.Blob, Hash: hMainV2, Name: "main.go"},
+ {ObjectType: repository.Tree, Hash: srcTreeV2, Name: "src"},
+ })
+ require.NoError(t, err)
+
+ rootTreeV3, err := repo.StoreTree([]repository.TreeEntry{
+ {ObjectType: repository.Blob, Hash: hReadmeV3, Name: "README.md"},
+ {ObjectType: repository.Blob, Hash: hMainV2, Name: "main.go"},
+ {ObjectType: repository.Tree, Hash: srcTreeV2, Name: "src"},
+ })
+ require.NoError(t, err)
+
+ c1, err := repo.StoreCommit(rootTreeV1)
+ require.NoError(t, err)
+ c2, err := repo.StoreCommit(rootTreeV2, c1)
+ require.NoError(t, err)
+ c3, err := repo.StoreCommit(rootTreeV3, c2)
+ require.NoError(t, err)
+
+ require.NoError(t, repo.UpdateRef("refs/heads/main", c3))
+ require.NoError(t, repo.UpdateRef("refs/heads/feature", c2))
+ require.NoError(t, repo.UpdateRef("refs/tags/v1.0", c1))
+
+ // ββ set up GraphQL handler βββββββββββββββββββββββββββββββββββββββββββββββββ
+
+ mrc := cache.NewMultiRepoCache()
+ _, events := mrc.RegisterDefaultRepository(repo)
+ for event := range events {
+ require.NoError(t, event.Err)
+ }
+ c := client.New(NewHandler(mrc, nil))
+
+ // ββ commit ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+ t.Run("commit", func(t *testing.T) {
+ var resp struct {
+ Repository struct {
+ Commit struct {
+ Hash string
+ Parents []string
+ }
+ }
+ }
+ require.NoError(t, c.Post(`query($hash: String!) {
+ repository { commit(hash: $hash) { hash parents } }
+ }`, &resp, client.Var("hash", string(c3))))
+ got := resp.Repository.Commit
+ require.Equal(t, string(c3), got.Hash)
+ require.Equal(t, []string{string(c2)}, got.Parents)
+ })
+
+ t.Run("commit_not_found", func(t *testing.T) {
+ var resp struct {
+ Repository struct {
+ Commit *struct{ Hash string }
+ }
+ }
+ require.NoError(t, c.Post(`query {
+ repository { commit(hash: "0000000000000000000000000000000000000000") { hash } }
+ }`, &resp))
+ require.Nil(t, resp.Repository.Commit)
+ })
+
+ // ββ blob ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+ t.Run("blob", func(t *testing.T) {
+ var resp struct {
+ Repository struct {
+ Blob struct {
+ Hash string
+ IsBinary bool
+ Size int
+ Text *string
+ }
+ }
+ }
+ require.NoError(t, c.Post(`query {
+ repository { blob(ref: "main", path: "README.md") { hash isBinary size text } }
+ }`, &resp))
+ got := resp.Repository.Blob
+ require.Equal(t, string(hReadmeV3), got.Hash)
+ require.False(t, got.IsBinary)
+ require.Equal(t, len(readmeV3), got.Size)
+ require.NotNil(t, got.Text)
+ require.Equal(t, string(readmeV3), *got.Text)
+ })
+
+ t.Run("blob_not_found", func(t *testing.T) {
+ var resp struct {
+ Repository struct {
+ Blob *struct{ Hash string }
+ }
+ }
+ require.NoError(t, c.Post(`query {
+ repository { blob(ref: "main", path: "nonexistent.go") { hash } }
+ }`, &resp))
+ require.Nil(t, resp.Repository.Blob)
+ })
+
+ // ββ tree ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+ t.Run("tree", func(t *testing.T) {
+ var resp struct {
+ Repository struct {
+ Tree []struct {
+ Name string
+ Type string `json:"type"`
+ }
+ }
+ }
+ require.NoError(t, c.Post(`query {
+ repository { tree(ref: "main", path: "") { name type } }
+ }`, &resp))
+ byName := make(map[string]string)
+ for _, e := range resp.Repository.Tree {
+ byName[e.Name] = e.Type
+ }
+ require.Equal(t, "BLOB", byName["README.md"])
+ require.Equal(t, "BLOB", byName["main.go"])
+ require.Equal(t, "TREE", byName["src"])
+ })
+
+ // ββ commits βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+ t.Run("commits", func(t *testing.T) {
+ var resp struct {
+ Repository struct {
+ Commits struct {
+ TotalCount int
+ PageInfo struct{ HasNextPage bool }
+ Nodes []struct{ Hash string }
+ }
+ }
+ }
+ require.NoError(t, c.Post(`query {
+ repository {
+ commits(ref: "main", first: 2) {
+ totalCount pageInfo { hasNextPage } nodes { hash }
+ }
+ }
+ }`, &resp))
+ got := resp.Repository.Commits
+ require.Equal(t, 2, got.TotalCount)
+ require.True(t, got.PageInfo.HasNextPage)
+ require.Equal(t, string(c3), got.Nodes[0].Hash)
+ require.Equal(t, string(c2), got.Nodes[1].Hash)
+ })
+
+ // ββ lastCommits βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+ t.Run("lastCommits", func(t *testing.T) {
+ var resp struct {
+ Repository struct {
+ LastCommits []struct {
+ Name string
+ Commit struct{ Hash string }
+ }
+ }
+ }
+ require.NoError(t, c.Post(`query {
+ repository {
+ lastCommits(ref: "main", names: ["README.md", "main.go"]) {
+ name commit { hash }
+ }
+ }
+ }`, &resp))
+ byName := make(map[string]string)
+ for _, lc := range resp.Repository.LastCommits {
+ byName[lc.Name] = lc.Commit.Hash
+ }
+ require.Equal(t, string(c3), byName["README.md"]) // changed in c3
+ require.Equal(t, string(c2), byName["main.go"]) // changed in c2
+ })
+}
+
func TestBugEventsSubscription(t *testing.T) {
repo := repository.CreateGoGitTestRepo(t, false)
@@ -0,0 +1,58 @@
+package models
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "strconv"
+)
+
+// GitRefType is the kind of git reference: a branch or a tag.
+type GitRefType string
+
+const (
+ // GitRefTypeBranch refers to a local branch (refs/heads/*).
+ GitRefTypeBranch GitRefType = "BRANCH"
+ // GitRefTypeTag refers to an annotated or lightweight tag (refs/tags/*).
+ GitRefTypeTag GitRefType = "TAG"
+)
+
+func (e GitRefType) IsValid() bool {
+ switch e {
+ case GitRefTypeBranch, GitRefTypeTag:
+ return true
+ }
+ return false
+}
+
+func (e GitRefType) String() string { return string(e) }
+
+func (e *GitRefType) UnmarshalGQL(v any) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+ *e = GitRefType(str)
+ if !e.IsValid() {
+ return fmt.Errorf("%s is not a valid GitRefType", str)
+ }
+ return nil
+}
+
+func (e GitRefType) MarshalGQL(w io.Writer) {
+ fmt.Fprint(w, strconv.Quote(e.String()))
+}
+
+func (e *GitRefType) UnmarshalJSON(b []byte) error {
+ s, err := strconv.Unquote(string(b))
+ if err != nil {
+ return err
+ }
+ return e.UnmarshalGQL(s)
+}
+
+func (e GitRefType) MarshalJSON() ([]byte, error) {
+ var buf bytes.Buffer
+ e.MarshalGQL(&buf)
+ return buf.Bytes(), nil
+}
@@ -269,6 +269,67 @@ type EntityEvent struct {
Entity Entity `json:"entity,omitempty"`
}
+// The content of a git blob (file).
+type GitBlob struct {
+ // Path of the file relative to the repository root.
+ Path string `json:"path"`
+ // Git object hash. Can be used as a stable cache key or to construct a
+ // raw download URL.
+ Hash string `json:"hash"`
+ // UTF-8 text content of the file. Null when isBinary is true or when
+ // the file is too large to be returned inline (see isTruncated).
+ Text *string `json:"text,omitempty"`
+ // Size in bytes.
+ Size int `json:"size"`
+ // True when the file contains null bytes and is treated as binary.
+ // text will be null.
+ IsBinary bool `json:"isBinary"`
+ // True when the file exceeds the maximum inline size and text has been
+ // omitted. Use the raw download endpoint to retrieve the full content.
+ IsTruncated bool `json:"isTruncated"`
+}
+
+type GitChangedFileConnection struct {
+ Nodes []*repository.ChangedFile `json:"nodes"`
+ PageInfo *PageInfo `json:"pageInfo"`
+ TotalCount int `json:"totalCount"`
+}
+
+// Paginated list of commits.
+type GitCommitConnection struct {
+ Nodes []*GitCommitMeta `json:"nodes"`
+ PageInfo *PageInfo `json:"pageInfo"`
+ TotalCount int `json:"totalCount"`
+}
+
+// The last commit that touched each requested entry in a directory.
+type GitLastCommit struct {
+ // Entry name within the directory.
+ Name string `json:"name"`
+ // Most recent commit that modified this entry.
+ Commit *GitCommitMeta `json:"commit"`
+}
+
+// A git branch or tag reference.
+type GitRef struct {
+ // Full reference name, e.g. refs/heads/main or refs/tags/v1.0.
+ Name string `json:"name"`
+ // Short name, e.g. main or v1.0.
+ ShortName string `json:"shortName"`
+ // Whether this reference is a branch or a tag.
+ Type GitRefType `json:"type"`
+ // Commit hash the reference points to.
+ Hash string `json:"hash"`
+ // True for the branch HEAD currently points to.
+ IsDefault bool `json:"isDefault"`
+}
+
+type GitRefConnection struct {
+ Nodes []*GitRef `json:"nodes"`
+ PageInfo *PageInfo `json:"pageInfo"`
+ TotalCount int `json:"totalCount"`
+}
+
type IdentityConnection struct {
Edges []*IdentityEdge `json:"edges"`
Nodes []IdentityWrapper `json:"nodes"`
@@ -3,6 +3,7 @@ package models
import (
"github.com/git-bug/git-bug/cache"
+ "github.com/git-bug/git-bug/repository"
)
type ConnectionInput struct {
@@ -13,6 +14,12 @@ type ConnectionInput struct {
}
type Repository struct {
- Cache *cache.MultiRepoCache
- Repo *cache.RepoCache
+ Repo *cache.RepoCache
+}
+
+// GitCommitMeta is a wrapper around a CommitMeta that includes the Repo,
+// to keep the repo context in sub-resolvers.
+type GitCommitMeta struct {
+ Repo *cache.RepoCache
+ repository.CommitMeta
}
@@ -0,0 +1,74 @@
+package resolvers
+
+import (
+ "context"
+
+ "github.com/git-bug/git-bug/api/graphql/connections"
+ "github.com/git-bug/git-bug/api/graphql/graph"
+ "github.com/git-bug/git-bug/api/graphql/models"
+ "github.com/git-bug/git-bug/cache"
+ "github.com/git-bug/git-bug/repository"
+)
+
+const blobTruncateSize = 1 << 20 // 1 MiB
+
+var _ graph.GitCommitResolver = &gitCommitResolver{}
+
+type gitCommitResolver struct {
+ cache *cache.MultiRepoCache
+}
+
+func (r gitCommitResolver) ShortHash(_ context.Context, obj *models.GitCommitMeta) (string, error) {
+ s := string(obj.Hash)
+ if len(s) > 8 {
+ s = s[:8]
+ }
+ return s, nil
+}
+
+func (r gitCommitResolver) FullMessage(_ context.Context, obj *models.GitCommitMeta) (string, error) {
+ repo := obj.Repo.BrowseRepo()
+ detail, err := repo.CommitDetail(obj.Hash)
+ if err != nil {
+ return "", err
+ }
+ return detail.FullMessage, nil
+}
+
+func (r gitCommitResolver) Parents(_ context.Context, obj *models.GitCommitMeta) ([]string, error) {
+ out := make([]string, len(obj.Parents))
+ for i, h := range obj.Parents {
+ out[i] = string(h)
+ }
+ return out, nil
+}
+
+func (r gitCommitResolver) Files(_ context.Context, obj *models.GitCommitMeta, after *string, before *string, first *int, last *int) (*models.GitChangedFileConnection, error) {
+ repo := obj.Repo.BrowseRepo()
+ detail, err := repo.CommitDetail(obj.Hash)
+ if err != nil {
+ return nil, err
+ }
+
+ input := models.ConnectionInput{After: after, Before: before, First: first, Last: last}
+ edger := func(f repository.ChangedFile, offset int) connections.Edge {
+ return connections.CursorEdge{Cursor: connections.OffsetToCursor(offset)}
+ }
+ conMaker := func(_ []*connections.CursorEdge, nodes []repository.ChangedFile, info *models.PageInfo, total int) (*models.GitChangedFileConnection, error) {
+ ptrs := make([]*repository.ChangedFile, len(nodes))
+ for i := range nodes {
+ ptrs[i] = &nodes[i]
+ }
+ return &models.GitChangedFileConnection{Nodes: ptrs, PageInfo: info, TotalCount: total}, nil
+ }
+ return connections.Connection(detail.Files, edger, conMaker, input)
+}
+
+func (r gitCommitResolver) Diff(_ context.Context, obj *models.GitCommitMeta, path string) (*repository.FileDiff, error) {
+ repo := obj.Repo.BrowseRepo()
+ fd, err := repo.CommitFileDiff(obj.Hash, path)
+ if err != nil {
+ return nil, err
+ }
+ return &fd, nil
+}
@@ -26,12 +26,11 @@ func (r rootQueryResolver) Repository(_ context.Context, ref *string) (*models.R
}
if err != nil {
- return nil, err
+ return nil, nil
}
return &models.Repository{
- Cache: r.cache,
- Repo: repo,
+ Repo: repo,
}, nil
}
@@ -48,7 +47,7 @@ func (r rootQueryResolver) Repositories(_ context.Context, after *string, before
edger := func(repo *cache.RepoCache, offset int) connections.Edge {
return models.RepositoryEdge{
- Node: &models.Repository{Cache: r.cache, Repo: repo},
+ Node: &models.Repository{Repo: repo},
Cursor: connections.OffsetToCursor(offset),
}
}
@@ -1,7 +1,13 @@
package resolvers
import (
+ "bytes"
"context"
+ "errors"
+ "io"
+ "math"
+ "sort"
+ "time"
"github.com/git-bug/git-bug/api/auth"
"github.com/git-bug/git-bug/api/graphql/connections"
@@ -10,6 +16,7 @@ import (
"github.com/git-bug/git-bug/entities/common"
"github.com/git-bug/git-bug/entity"
"github.com/git-bug/git-bug/query"
+ "github.com/git-bug/git-bug/repository"
)
var _ graph.RepositoryResolver = &repoResolver{}
@@ -17,6 +24,9 @@ var _ graph.RepositoryResolver = &repoResolver{}
type repoResolver struct{}
func (repoResolver) Name(_ context.Context, obj *models.Repository) (*string, error) {
+ if obj.Repo.IsDefaultRepo() {
+ return nil, nil
+ }
name := obj.Repo.Name()
return &name, nil
}
@@ -87,6 +97,9 @@ func (repoResolver) AllBugs(_ context.Context, obj *models.Repository, after *st
func (repoResolver) Bug(_ context.Context, obj *models.Repository, prefix string) (models.BugWrapper, error) {
excerpt, err := obj.Repo.Bugs().ResolveExcerptPrefix(prefix)
+ if entity.IsErrNotFound(err) {
+ return nil, nil
+ }
if err != nil {
return nil, err
}
@@ -146,6 +159,9 @@ func (repoResolver) AllIdentities(_ context.Context, obj *models.Repository, aft
func (repoResolver) Identity(_ context.Context, obj *models.Repository, prefix string) (models.IdentityWrapper, error) {
excerpt, err := obj.Repo.Identities().ResolveExcerptPrefix(prefix)
+ if entity.IsErrNotFound(err) {
+ return nil, nil
+ }
if err != nil {
return nil, err
}
@@ -189,3 +205,216 @@ func (repoResolver) ValidLabels(_ context.Context, obj *models.Repository, after
return connections.Connection(obj.Repo.Bugs().ValidLabels(), edger, conMaker, input)
}
+
+func (repoResolver) Refs(_ context.Context, obj *models.Repository, after *string, before *string, first *int, last *int, typeArg *models.GitRefType) (*models.GitRefConnection, error) {
+ repo := obj.Repo.BrowseRepo()
+
+ var refs []*models.GitRef
+
+ if typeArg == nil || *typeArg == models.GitRefTypeBranch {
+ branches, err := repo.Branches()
+ if err != nil {
+ return nil, err
+ }
+ for _, b := range branches {
+ refs = append(refs, &models.GitRef{
+ Name: "refs/heads/" + b.Name,
+ ShortName: b.Name,
+ Type: models.GitRefTypeBranch,
+ Hash: string(b.Hash),
+ IsDefault: b.IsDefault,
+ })
+ }
+ }
+
+ if typeArg == nil || *typeArg == models.GitRefTypeTag {
+ tags, err := repo.Tags()
+ if err != nil {
+ return nil, err
+ }
+ for _, t := range tags {
+ refs = append(refs, &models.GitRef{
+ Name: "refs/tags/" + t.Name,
+ ShortName: t.Name,
+ Type: models.GitRefTypeTag,
+ Hash: string(t.Hash),
+ })
+ }
+ }
+
+ // Sort by type (branches before tags) then by short name for stable cursors.
+ sort.Slice(refs, func(i, j int) bool {
+ if refs[i].Type != refs[j].Type {
+ return refs[i].Type < refs[j].Type
+ }
+ return refs[i].ShortName < refs[j].ShortName
+ })
+
+ input := models.ConnectionInput{After: after, Before: before, First: first, Last: last}
+ edger := func(r *models.GitRef, offset int) connections.Edge {
+ return connections.CursorEdge{Cursor: connections.OffsetToCursor(offset)}
+ }
+ conMaker := func(edges []*connections.CursorEdge, nodes []*models.GitRef, info *models.PageInfo, total int) (*models.GitRefConnection, error) {
+ return &models.GitRefConnection{Nodes: nodes, PageInfo: info, TotalCount: total}, nil
+ }
+ return connections.Connection(refs, edger, conMaker, input)
+}
+
+func (repoResolver) Tree(_ context.Context, obj *models.Repository, ref string, path *string) ([]*repository.TreeEntry, error) {
+ repo := obj.Repo.BrowseRepo()
+ p := ""
+ if path != nil {
+ p = *path
+ }
+ entries, err := repo.TreeAtPath(ref, p)
+ if err != nil {
+ return nil, err
+ }
+ ptrs := make([]*repository.TreeEntry, len(entries))
+ for i := range entries {
+ ptrs[i] = &entries[i]
+ }
+ return ptrs, nil
+}
+
+func (repoResolver) Blob(_ context.Context, obj *models.Repository, ref string, path string) (*models.GitBlob, error) {
+ repo := obj.Repo.BrowseRepo()
+ rc, size, hash, err := repo.BlobAtPath(ref, path)
+ if errors.Is(err, repository.ErrNotFound) {
+ return nil, nil
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer rc.Close()
+
+ limited := io.LimitReader(rc, blobTruncateSize+1)
+ data, err := io.ReadAll(limited)
+ if err != nil {
+ return nil, err
+ }
+
+ // Binary detection: same heuristic as git β a null byte anywhere in the
+ // content means binary. Git caps its probe at 8000 bytes; we probe all
+ // bytes read (up to blobTruncateSize+1) before slicing, so a NUL in the
+ // extra byte also triggers the flag. Files whose first blobTruncateSize
+ // bytes are all non-NUL will be reported as text even if the remainder is
+ // binary; this is a documented prefix-based heuristic.
+ isBinary := bytes.IndexByte(data, 0) >= 0
+
+ isTruncated := int64(len(data)) > blobTruncateSize
+ if isTruncated {
+ data = data[:blobTruncateSize]
+ }
+
+ blob := &models.GitBlob{
+ Path: path,
+ Hash: string(hash),
+ // GraphQL Int is 32-bit; clamp to avoid overflow on 32-bit platforms or for
+ // exceptionally large files (which will be truncated anyway).
+ Size: int(min(size, int64(math.MaxInt32))),
+ IsBinary: isBinary,
+ IsTruncated: isTruncated,
+ }
+ if !isBinary {
+ text := string(data)
+ blob.Text = &text
+ }
+ return blob, nil
+}
+
+func (repoResolver) Commits(_ context.Context, obj *models.Repository, after *string, first *int, ref string, path *string, since *time.Time, until *time.Time) (*models.GitCommitConnection, error) {
+ // This is not using the normal relay pagination (connection.Connection()), because that requires having the
+ // full list in memory. Here, go-git does a partial walk only, which is better.
+
+ repo := obj.Repo.BrowseRepo()
+
+ p := ""
+ if path != nil {
+ p = *path
+ }
+
+ const defaultFirst = 20
+ const maxFirst = 100
+
+ n := defaultFirst
+ if first != nil {
+ n = *first
+ if n > maxFirst {
+ n = maxFirst
+ }
+ }
+ limit := n + 1 // fetch one extra to detect hasNextPage
+
+ var afterHash repository.Hash
+ if after != nil {
+ afterHash = repository.Hash(*after)
+ }
+
+ commits, err := repo.CommitLog(ref, p, limit, afterHash, since, until)
+ if err != nil {
+ return nil, err
+ }
+
+ hasNextPage := false
+ if len(commits) > n {
+ hasNextPage = true
+ commits = commits[:n]
+ }
+
+ nodes := make([]*models.GitCommitMeta, len(commits))
+ for i := range commits {
+ nodes[i] = &models.GitCommitMeta{Repo: obj.Repo, CommitMeta: commits[i]}
+ }
+
+ startCursor := ""
+ endCursor := ""
+ if len(nodes) > 0 {
+ startCursor = string(nodes[0].Hash)
+ endCursor = string(nodes[len(nodes)-1].Hash)
+ }
+
+ return &models.GitCommitConnection{
+ Nodes: nodes,
+ PageInfo: &models.PageInfo{
+ HasNextPage: hasNextPage,
+ HasPreviousPage: after != nil,
+ StartCursor: startCursor,
+ EndCursor: endCursor,
+ },
+ TotalCount: len(nodes), // lower bound; exact total unknown without full walk
+ }, nil
+}
+
+func (repoResolver) Commit(_ context.Context, obj *models.Repository, hash string) (*models.GitCommitMeta, error) {
+ repo := obj.Repo.BrowseRepo()
+ detail, err := repo.CommitDetail(repository.Hash(hash))
+ if errors.Is(err, repository.ErrNotFound) {
+ return nil, nil
+ }
+ if err != nil {
+ return nil, err
+ }
+ return &models.GitCommitMeta{Repo: obj.Repo, CommitMeta: detail.CommitMeta}, nil
+}
+
+func (repoResolver) LastCommits(_ context.Context, obj *models.Repository, ref string, path *string, names []string) ([]*models.GitLastCommit, error) {
+ repo := obj.Repo.BrowseRepo()
+ p := ""
+ if path != nil {
+ p = *path
+ }
+ byName, err := repo.LastCommitForEntries(ref, p, names)
+ if err != nil {
+ return nil, err
+ }
+ // Iterate over the input names to preserve caller-specified order.
+ result := make([]*models.GitLastCommit, 0, len(names))
+ for _, name := range names {
+ if meta, ok := byName[name]; ok {
+ m := meta
+ result = append(result, &models.GitLastCommit{Name: name, Commit: &models.GitCommitMeta{Repo: obj.Repo, CommitMeta: m}})
+ }
+ }
+ return result, nil
+}
@@ -56,3 +56,9 @@ func (RootResolver) Repository() graph.RepositoryResolver {
func (RootResolver) Bug() graph.BugResolver {
return &bugResolver{}
}
+
+func (r RootResolver) GitCommit() graph.GitCommitResolver {
+ return &gitCommitResolver{
+ cache: r.MultiRepoCache,
+ }
+}
@@ -16,3 +16,7 @@ directive @goTag(
key: String!
value: String
) on INPUT_FIELD_DEFINITION | FIELD_DEFINITION
+
+directive @goEnum(
+ value: String
+) on ENUM_VALUE
@@ -0,0 +1,214 @@
+"""A git branch or tag reference."""
+type GitRef {
+ """Full reference name, e.g. refs/heads/main or refs/tags/v1.0."""
+ name: String!
+ """Short name, e.g. main or v1.0."""
+ shortName: String!
+ """Whether this reference is a branch or a tag."""
+ type: GitRefType!
+ """Commit hash the reference points to."""
+ hash: String!
+ """True for the branch HEAD currently points to."""
+ isDefault: Boolean!
+}
+
+"""An entry in a git tree (directory listing)."""
+type GitTreeEntry
+@goModel(model: "github.com/git-bug/git-bug/repository.TreeEntry") {
+ """File or directory name within the parent tree."""
+ name: String!
+ """Whether this entry is a file, directory, symlink, or submodule."""
+ type: GitObjectType! @goField(name: "ObjectType")
+ """Git object hash."""
+ hash: String!
+}
+
+"""The content of a git blob (file)."""
+type GitBlob {
+ """Path of the file relative to the repository root."""
+ path: String!
+ """Git object hash. Can be used as a stable cache key or to construct a
+ raw download URL."""
+ hash: String!
+ """UTF-8 text content of the file. Null when isBinary is true or when
+ the file is too large to be returned inline (see isTruncated)."""
+ text: String
+ """Size in bytes."""
+ size: Int!
+ """True when the file contains null bytes and is treated as binary.
+ text will be null."""
+ isBinary: Boolean!
+ """True when the file exceeds the maximum inline size and text has been
+ omitted. Use the raw download endpoint to retrieve the full content."""
+ isTruncated: Boolean!
+}
+
+"""Metadata for a single git commit."""
+type GitCommit
+@goModel(model: "github.com/git-bug/git-bug/api/graphql/models.GitCommitMeta") {
+ """Full SHA-1 commit hash."""
+ hash: String!
+ """Abbreviated commit hash, typically 8 characters."""
+ shortHash: String!
+ """First line of the commit message."""
+ message: String!
+ """Full commit message."""
+ fullMessage: String!
+ """Name of the commit author."""
+ authorName: String!
+ """Email address of the commit author."""
+ authorEmail: String!
+ """Timestamp from the author field (when the change was originally made)."""
+ date: Time!
+ """Hashes of parent commits. Empty for the initial commit."""
+ parents: [String!]!
+ """Files changed relative to the first parent (or the empty tree for the
+ initial commit)."""
+ files(
+ """Returns the elements in the list that come after the specified cursor."""
+ after: String
+ """Returns the elements in the list that come before the specified cursor."""
+ before: String
+ """Returns the first _n_ elements from the list."""
+ first: Int
+ """Returns the last _n_ elements from the list."""
+ last: Int
+ ): GitChangedFileConnection!
+ """Unified diff for a single file in this commit."""
+ diff(path: String!): GitFileDiff
+}
+
+"""The last commit that touched each requested entry in a directory."""
+type GitLastCommit {
+ """Entry name within the directory."""
+ name: String!
+ """Most recent commit that modified this entry."""
+ commit: GitCommit!
+}
+
+# ββ connection types ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+type GitRefConnection {
+ nodes: [GitRef!]!
+ pageInfo: PageInfo!
+ totalCount: Int!
+}
+
+"""Paginated list of commits."""
+type GitCommitConnection {
+ nodes: [GitCommit!]!
+ pageInfo: PageInfo!
+ totalCount: Int!
+}
+
+type GitChangedFileConnection {
+ nodes: [GitChangedFile!]!
+ pageInfo: PageInfo!
+ totalCount: Int!
+}
+
+# ββ commit sub-types ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+"""A file that was changed in a commit."""
+type GitChangedFile
+@goModel(model: "github.com/git-bug/git-bug/repository.ChangedFile") {
+ """Path of the file in the new version of the commit."""
+ path: String!
+ """Previous path, non-null only for renames."""
+ oldPath: String
+ """How the file was affected by the commit."""
+ status: GitChangeStatus!
+}
+
+"""The diff for a single file in a commit."""
+type GitFileDiff
+@goModel(model: "github.com/git-bug/git-bug/repository.FileDiff") {
+ """Path of the file in the new version."""
+ path: String!
+ """Previous path, non-null only for renames."""
+ oldPath: String
+ """True when the file is binary and no textual diff is available."""
+ isBinary: Boolean!
+ """True when the file was created in this commit."""
+ isNew: Boolean!
+ """True when the file was deleted in this commit."""
+ isDelete: Boolean!
+ """Contiguous blocks of changes. Empty for binary files."""
+ hunks: [GitDiffHunk!]!
+}
+
+"""A contiguous block of changes in a unified diff."""
+type GitDiffHunk
+@goModel(model: "github.com/git-bug/git-bug/repository.DiffHunk") {
+ """Starting line number in the old file."""
+ oldStart: Int!
+ """Number of lines from the old file included in this hunk."""
+ oldLines: Int!
+ """Starting line number in the new file."""
+ newStart: Int!
+ """Number of lines from the new file included in this hunk."""
+ newLines: Int!
+ """Lines in this hunk, including context, additions, and deletions."""
+ lines: [GitDiffLine!]!
+}
+
+"""A single line in a unified diff hunk."""
+type GitDiffLine
+@goModel(model: "github.com/git-bug/git-bug/repository.DiffLine") {
+ """Whether this line is context, an addition, or a deletion."""
+ type: GitDiffLineType!
+ """Raw line content, without the leading +/- prefix."""
+ content: String!
+ """Line number in the old file. 0 for added lines."""
+ oldLine: Int!
+ """Line number in the new file. 0 for deleted lines."""
+ newLine: Int!
+}
+
+# ββ enums βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+"""The kind of git reference: a branch or a tag."""
+enum GitRefType
+@goModel(model: "github.com/git-bug/git-bug/api/graphql/models.GitRefType") {
+ """A local branch (refs/heads/*)."""
+ BRANCH @goEnum(value: "github.com/git-bug/git-bug/api/graphql/models.GitRefTypeBranch")
+ """An annotated or lightweight tag (refs/tags/*)."""
+ TAG @goEnum(value: "github.com/git-bug/git-bug/api/graphql/models.GitRefTypeTag")
+}
+
+"""The type of object a git tree entry points to."""
+enum GitObjectType
+@goModel(model: "github.com/git-bug/git-bug/repository.ObjectType") {
+ """A directory."""
+ TREE
+ """A regular or executable file."""
+ BLOB
+ """A symbolic link."""
+ SYMLINK
+ """A git submodule."""
+ SUBMODULE
+}
+
+"""How a file was affected by a commit."""
+enum GitChangeStatus
+@goModel(model: "github.com/git-bug/git-bug/repository.ChangeStatus") {
+ """File was created in this commit."""
+ ADDED
+ """File content changed in this commit."""
+ MODIFIED
+ """File was removed in this commit."""
+ DELETED
+ """File was moved or renamed in this commit."""
+ RENAMED
+}
+
+"""The role of a line within a unified diff hunk."""
+enum GitDiffLineType
+@goModel(model: "github.com/git-bug/git-bug/repository.DiffLineType") {
+ """An unchanged line present in both old and new versions."""
+ CONTEXT
+ """A line added in the new version."""
+ ADDED
+ """A line removed from the old version."""
+ DELETED
+}
@@ -1,5 +1,5 @@
type Repository {
- """The name of the repository"""
+ """The name of the repository. Null for the default (unnamed) repository in a single-repo setup."""
name: String
"""All the bugs"""
@@ -16,6 +16,7 @@ type Repository {
query: String
): BugConnection!
+ """Look up a bug by id prefix. Returns null if no bug matches the prefix."""
bug(prefix: String!): Bug
"""All the identities"""
@@ -30,11 +31,59 @@ type Repository {
last: Int
): IdentityConnection!
+ """Look up an identity by id prefix. Returns null if no identity matches the prefix."""
identity(prefix: String!): Identity
"""The identity created or selected by the user as its own"""
userIdentity: Identity
+ """All branches and tags, optionally filtered by type."""
+ refs(
+ """Returns the elements in the list that come after the specified cursor."""
+ after: String
+ """Returns the elements in the list that come before the specified cursor."""
+ before: String
+ """Returns the first _n_ elements from the list."""
+ first: Int
+ """Returns the last _n_ elements from the list."""
+ last: Int
+ """Restrict to references of this type."""
+ type: GitRefType
+ ): GitRefConnection!
+
+ """Directory listing at path under ref. An empty path returns the root tree."""
+ tree(ref: String!, path: String): [GitTreeEntry!]!
+
+ """Content of the file at path under ref. Null if the path does not exist
+ or resolves to a tree rather than a blob."""
+ blob(ref: String!, path: String!): GitBlob
+
+ """Paginated commit log reachable from ref, optionally filtered to commits
+ touching path."""
+ commits(
+ """Returns the elements in the list that come after the specified cursor."""
+ after: String
+ """Returns the first _n_ elements from the list (max 100, default 20)."""
+ first: Int
+ """Branch name, tag name, full ref (e.g. refs/heads/main), or commit hash
+ to start the log from."""
+ ref: String!
+ """Restrict to commits that touched this path."""
+ path: String
+ """Restrict to commits authored on or after this timestamp."""
+ since: Time
+ """Restrict to commits authored before or on this timestamp."""
+ until: Time
+ ): GitCommitConnection!
+
+ """A single commit by hash. Returns null if the hash does not exist in the repository."""
+ commit(hash: String!): GitCommit
+
+ """The most recent commit that touched each of the named entries in the
+ directory at path under ref. Use this to populate last-commit info on a
+ tree listing without blocking the initial tree fetch."""
+ lastCommits(ref: String!, path: String, names: [String!]!): [GitLastCommit!]!
+
"""List of valid labels."""
validLabels(
"""Returns the elements in the list that come after the specified cursor."""
@@ -1,5 +1,6 @@
type Query {
- """Access a repository by reference/name. If no ref is given, the default repository is returned if any."""
+ """Access a repository by reference/name. If no ref is given, the default repository is returned if any.
+ Returns null if the referenced repository does not exist."""
repository(ref: String): Repository
"""List all registered repositories."""
@@ -15,6 +15,16 @@ func (c *RepoCache) Name() string {
return c.name
}
+// IsDefaultRepo reports whether this is an unnamed (single-repo) repository.
+func (c *RepoCache) IsDefaultRepo() bool {
+ return c.name == defaultRepoName
+}
+
+// BrowseRepo returns the underlying RepoBrowse implementation.
+func (c *RepoCache) BrowseRepo() repository.RepoBrowse {
+ return c.repo
+}
+
// LocalConfig give access to the repository scoped configuration
func (c *RepoCache) LocalConfig() repository.Config {
return c.repo.LocalConfig()
@@ -0,0 +1,160 @@
+package repository
+
+import (
+ "fmt"
+ "io"
+ "strconv"
+ "time"
+)
+
+// ChangeStatus describes how a file was affected by a commit.
+type ChangeStatus string
+
+const (
+ ChangeStatusAdded ChangeStatus = "added"
+ ChangeStatusModified ChangeStatus = "modified"
+ ChangeStatusDeleted ChangeStatus = "deleted"
+ ChangeStatusRenamed ChangeStatus = "renamed"
+)
+
+func (s ChangeStatus) MarshalGQL(w io.Writer) {
+ switch s {
+ case ChangeStatusAdded:
+ fmt.Fprint(w, strconv.Quote("ADDED"))
+ case ChangeStatusModified:
+ fmt.Fprint(w, strconv.Quote("MODIFIED"))
+ case ChangeStatusDeleted:
+ fmt.Fprint(w, strconv.Quote("DELETED"))
+ case ChangeStatusRenamed:
+ fmt.Fprint(w, strconv.Quote("RENAMED"))
+ default:
+ panic(fmt.Sprintf("unknown ChangeStatus value %q", string(s)))
+ }
+}
+
+func (s *ChangeStatus) UnmarshalGQL(v any) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+ switch str {
+ case "ADDED":
+ *s = ChangeStatusAdded
+ case "MODIFIED":
+ *s = ChangeStatusModified
+ case "DELETED":
+ *s = ChangeStatusDeleted
+ case "RENAMED":
+ *s = ChangeStatusRenamed
+ default:
+ return fmt.Errorf("%q is not a valid ChangeStatus", str)
+ }
+ return nil
+}
+
+// DiffLineType is the role of a line within a unified diff hunk.
+type DiffLineType string
+
+const (
+ DiffLineContext DiffLineType = "context"
+ DiffLineAdded DiffLineType = "added"
+ DiffLineDeleted DiffLineType = "deleted"
+)
+
+func (t DiffLineType) MarshalGQL(w io.Writer) {
+ switch t {
+ case DiffLineContext:
+ fmt.Fprint(w, strconv.Quote("CONTEXT"))
+ case DiffLineAdded:
+ fmt.Fprint(w, strconv.Quote("ADDED"))
+ case DiffLineDeleted:
+ fmt.Fprint(w, strconv.Quote("DELETED"))
+ default:
+ panic(fmt.Sprintf("unknown DiffLineType value %q", string(t)))
+ }
+}
+
+func (t *DiffLineType) UnmarshalGQL(v any) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+ switch str {
+ case "CONTEXT":
+ *t = DiffLineContext
+ case "ADDED":
+ *t = DiffLineAdded
+ case "DELETED":
+ *t = DiffLineDeleted
+ default:
+ return fmt.Errorf("%q is not a valid DiffLineType", str)
+ }
+ return nil
+}
+
+// CommitMeta holds the metadata for a single commit, suitable for listing.
+type CommitMeta struct {
+ Hash Hash
+ Message string
+ AuthorName string
+ AuthorEmail string
+ Date time.Time
+ Parents []Hash
+}
+
+// ChangedFile describes a file that was modified in a commit.
+type ChangedFile struct {
+ Path string
+ OldPath *string // non-nil for renames
+ Status ChangeStatus
+}
+
+// CommitDetail extends CommitMeta with the full message and the list of
+// changed files (relative to the first parent).
+type CommitDetail struct {
+ CommitMeta
+ FullMessage string
+ Files []ChangedFile
+}
+
+// DiffLine represents one line in a unified diff hunk.
+type DiffLine struct {
+ Type DiffLineType
+ Content string
+ OldLine int
+ NewLine int
+}
+
+// DiffHunk is a contiguous block of changes in a unified diff.
+type DiffHunk struct {
+ OldStart int
+ OldLines int
+ NewStart int
+ NewLines int
+ Lines []DiffLine
+}
+
+// FileDiff is the diff for a single file in a commit.
+type FileDiff struct {
+ Path string
+ OldPath *string // non-nil for renames
+ IsBinary bool
+ IsNew bool
+ IsDelete bool
+ Hunks []DiffHunk
+}
+
+// BranchInfo describes a local branch returned by RepoBrowse.Branches.
+type BranchInfo struct {
+ Name string
+ Hash Hash // commit hash
+ IsDefault bool // true for the branch HEAD points to
+}
+
+// TagInfo describes a tag returned by RepoBrowse.Tags.
+type TagInfo struct {
+ Name string
+ // Hash is always the target commit hash. For annotated tags the tag
+ // object is dereferenced; for lightweight tags this is the ref hash.
+ Hash Hash
+}
@@ -65,3 +65,10 @@ func deArmorSignature(armoredSig io.Reader) (io.Reader, error) {
}
return block.Body, nil
}
+
+func must[T any](v T, err error) T {
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
@@ -19,7 +19,9 @@ import (
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/filemode"
+ fdiff "github.com/go-git/go-git/v5/plumbing/format/diff"
"github.com/go-git/go-git/v5/plumbing/object"
+ lru "github.com/hashicorp/golang-lru/v2"
"golang.org/x/sync/errgroup"
"golang.org/x/sys/execabs"
@@ -29,6 +31,17 @@ import (
const clockPath = "clocks"
const indexPath = "indexes"
+// lastCommitDepthLimit is the maximum number of commits walked by
+// LastCommitForEntries. Entries not found within this horizon are omitted from
+// the result rather than stalling the caller indefinitely.
+const lastCommitDepthLimit = 1000
+
+// lastCommitCacheSize is the number of (resolvedHash, dirPath) pairs kept in
+// the LRU cache for LastCommitForEntries. Each entry holds one CommitMeta per
+// directory entry (β a few KB for a typical directory), so 256 slots β a few
+// MB of memory at most.
+const lastCommitCacheSize = 256
+
var _ ClockedRepo = &GoGitRepo{}
var _ TestedRepo = &GoGitRepo{}
@@ -47,6 +60,13 @@ type GoGitRepo struct {
indexesMutex sync.Mutex
indexes map[string]Index
+ // lastCommitCache caches LastCommitForEntries results keyed by
+ // "<treeHash>\x00<path>". Git trees are content-addressed and
+ // immutable, so entries never need invalidation and can be shared
+ // across refs that point to the same directory tree. The LRU bounds
+ // memory to lastCommitCacheSize unique (treeHash, directory) pairs.
+ lastCommitCache *lru.Cache[string, map[string]CommitMeta]
+
keyring Keyring
localStorage LocalStorage
}
@@ -72,12 +92,13 @@ func OpenGoGitRepo(path, namespace string, clockLoaders []ClockLoader) (*GoGitRe
}
repo := &GoGitRepo{
- r: r,
- path: path,
- clocks: make(map[string]lamport.Clock),
- indexes: make(map[string]Index),
- keyring: k,
- localStorage: billyLocalStorage{Filesystem: osfs.New(filepath.Join(path, namespace))},
+ r: r,
+ path: path,
+ clocks: make(map[string]lamport.Clock),
+ indexes: make(map[string]Index),
+ lastCommitCache: must(lru.New[string, map[string]CommitMeta](lastCommitCacheSize)),
+ keyring: k,
+ localStorage: billyLocalStorage{Filesystem: osfs.New(filepath.Join(path, namespace))},
}
loaderToRun := make([]ClockLoader, 0, len(clockLoaders))
@@ -126,12 +147,13 @@ func InitGoGitRepo(path, namespace string) (*GoGitRepo, error) {
}
return &GoGitRepo{
- r: r,
- path: filepath.Join(path, ".git"),
- clocks: make(map[string]lamport.Clock),
- indexes: make(map[string]Index),
- keyring: k,
- localStorage: billyLocalStorage{Filesystem: osfs.New(filepath.Join(path, ".git", namespace))},
+ r: r,
+ path: filepath.Join(path, ".git"),
+ clocks: make(map[string]lamport.Clock),
+ indexes: make(map[string]Index),
+ lastCommitCache: must(lru.New[string, map[string]CommitMeta](lastCommitCacheSize)),
+ keyring: k,
+ localStorage: billyLocalStorage{Filesystem: osfs.New(filepath.Join(path, ".git", namespace))},
}, nil
}
@@ -151,12 +173,13 @@ func InitBareGoGitRepo(path, namespace string) (*GoGitRepo, error) {
}
return &GoGitRepo{
- r: r,
- path: path,
- clocks: make(map[string]lamport.Clock),
- indexes: make(map[string]Index),
- keyring: k,
- localStorage: billyLocalStorage{Filesystem: osfs.New(filepath.Join(path, namespace))},
+ r: r,
+ path: path,
+ clocks: make(map[string]lamport.Clock),
+ indexes: make(map[string]Index),
+ lastCommitCache: must(lru.New[string, map[string]CommitMeta](lastCommitCacheSize)),
+ keyring: k,
+ localStorage: billyLocalStorage{Filesystem: osfs.New(filepath.Join(path, namespace))},
}, nil
}
@@ -915,6 +938,739 @@ func (repo *GoGitRepo) Witness(name string, time lamport.Time) error {
return c.Witness(time)
}
+// commitToMeta converts a go-git Commit to a CommitMeta.
+func commitToMeta(c *object.Commit) CommitMeta {
+ h := Hash(c.Hash.String())
+ parents := make([]Hash, len(c.ParentHashes))
+ for i, p := range c.ParentHashes {
+ parents[i] = Hash(p.String())
+ }
+ // Use first line of message as the short message.
+ msg := strings.TrimSpace(c.Message)
+ if idx := strings.Index(msg, "\n"); idx >= 0 {
+ msg = msg[:idx]
+ }
+ return CommitMeta{
+ Hash: h,
+ Message: msg,
+ AuthorName: c.Author.Name,
+ AuthorEmail: c.Author.Email,
+ Date: c.Author.When,
+ Parents: parents,
+ }
+}
+
+// peelToCommit follows tag objects until it reaches a commit hash.
+// This is necessary for annotated tags, whose ref hash points to a tag object
+// rather than directly to a commit.
+func (repo *GoGitRepo) peelToCommit(h plumbing.Hash) (plumbing.Hash, error) {
+ for {
+ if _, err := repo.r.CommitObject(h); err == nil {
+ return h, nil
+ }
+ tagObj, err := repo.r.TagObject(h)
+ if err != nil {
+ return plumbing.ZeroHash, ErrNotFound
+ }
+ h = tagObj.Target
+ }
+}
+
+// resolveRefToHash resolves a branch/tag name or raw hash to a commit hash.
+// Resolution order: refs/heads/<ref>, refs/tags/<ref>, full ref name, raw commit hash.
+// Annotated tags are peeled to their target commit.
+func (repo *GoGitRepo) resolveRefToHash(ref string) (plumbing.Hash, error) {
+ for _, prefix := range []string{"refs/heads/", "refs/tags/"} {
+ r, err := repo.r.Reference(plumbing.ReferenceName(prefix+ref), true)
+ if err == nil {
+ return repo.peelToCommit(r.Hash())
+ }
+ }
+ // try as a full ref name
+ r, err := repo.r.Reference(plumbing.ReferenceName(ref), true)
+ if err == nil {
+ return repo.peelToCommit(r.Hash())
+ }
+ // try as a raw commit hash
+ h := plumbing.NewHash(ref)
+ if h != plumbing.ZeroHash {
+ if _, err := repo.r.CommitObject(h); err == nil {
+ return h, nil
+ }
+ }
+ return plumbing.ZeroHash, ErrNotFound
+}
+
+// defaultBranchName returns the short name of the default branch.
+func (repo *GoGitRepo) defaultBranchName() string {
+ repo.rMutex.Lock()
+ defer repo.rMutex.Unlock()
+
+ // refs/remotes/origin/HEAD is a symbolic ref set by git clone that points
+ // to the remote's default branch (e.g. refs/remotes/origin/main). It is
+ // the most reliable signal for "what does the upstream consider default".
+ ref, err := repo.r.Reference("refs/remotes/origin/HEAD", false)
+ if err == nil && ref.Type() == plumbing.SymbolicReference {
+ const prefix = "refs/remotes/origin/"
+ if target := ref.Target().String(); strings.HasPrefix(target, prefix) {
+ return strings.TrimPrefix(target, prefix)
+ }
+ }
+ // Fall back to well-known names for repos without a configured remote.
+ for _, name := range []string{"main", "master", "trunk", "develop"} {
+ _, err := repo.r.Reference(plumbing.NewBranchReferenceName(name), false)
+ if err == nil {
+ return name
+ }
+ }
+ return ""
+}
+
+// Branches returns all local branches. IsDefault marks the upstream's default
+// branch, determined in order:
+// 1. refs/remotes/origin/HEAD (set by git clone, reflects the server default)
+// 2. First match among: main, master, trunk, develop
+// 3. No branch marked if none of the above resolve
+func (repo *GoGitRepo) Branches() ([]BranchInfo, error) {
+ defaultBranch := repo.defaultBranchName()
+
+ repo.rMutex.Lock()
+ defer repo.rMutex.Unlock()
+
+ refs, err := repo.r.References()
+ if err != nil {
+ return nil, err
+ }
+
+ var branches []BranchInfo
+ err = refs.ForEach(func(r *plumbing.Reference) error {
+ if !r.Name().IsBranch() {
+ return nil
+ }
+ branches = append(branches, BranchInfo{
+ Name: r.Name().Short(),
+ Hash: Hash(r.Hash().String()),
+ IsDefault: r.Name().Short() == defaultBranch,
+ })
+ return nil
+ })
+ if err != nil {
+ return nil, err
+ }
+ if branches == nil {
+ branches = []BranchInfo{}
+ }
+ return branches, nil
+}
+
+// Tags returns all tags. For annotated tags the hash is dereferenced to the
+// target commit; for lightweight tags it is the commit hash directly.
+func (repo *GoGitRepo) Tags() ([]TagInfo, error) {
+ repo.rMutex.Lock()
+ defer repo.rMutex.Unlock()
+
+ refs, err := repo.r.References()
+ if err != nil {
+ return nil, err
+ }
+
+ var tags []TagInfo
+ err = refs.ForEach(func(r *plumbing.Reference) error {
+ if !r.Name().IsTag() {
+ return nil
+ }
+ // Peel to the target commit hash, handling arbitrarily nested tag objects.
+ commit, err := repo.peelToCommit(r.Hash())
+ if err != nil {
+ // Skip refs that don't resolve to a commit (shouldn't happen for tags).
+ return nil
+ }
+ tags = append(tags, TagInfo{
+ Name: r.Name().Short(),
+ Hash: Hash(commit.String()),
+ })
+ return nil
+ })
+ if err != nil {
+ return nil, err
+ }
+ if tags == nil {
+ tags = []TagInfo{}
+ }
+ return tags, nil
+}
+
+// TreeAtPath returns the entries of the directory at path under ref.
+func (repo *GoGitRepo) TreeAtPath(ref, path string) ([]TreeEntry, error) {
+ path = strings.Trim(path, "/")
+
+ repo.rMutex.Lock()
+ defer repo.rMutex.Unlock()
+
+ startHash, err := repo.resolveRefToHash(ref)
+ if err != nil {
+ return nil, ErrNotFound
+ }
+ commit, err := repo.r.CommitObject(startHash)
+ if err != nil {
+ return nil, err
+ }
+ tree, err := commit.Tree()
+ if err != nil {
+ return nil, err
+ }
+ if path != "" {
+ subtree, err := tree.Tree(path)
+ if err != nil {
+ return nil, ErrNotFound
+ }
+ tree = subtree
+ }
+
+ entries := make([]TreeEntry, len(tree.Entries))
+ for i, e := range tree.Entries {
+ entries[i] = TreeEntry{
+ Name: e.Name,
+ Hash: Hash(e.Hash.String()),
+ ObjectType: objectTypeFromFileMode(e.Mode),
+ }
+ }
+ return entries, nil
+}
+
+// objectTypeFromFileMode maps a go-git filemode to the repository ObjectType.
+func objectTypeFromFileMode(m filemode.FileMode) ObjectType {
+ switch m {
+ case filemode.Dir:
+ return Tree
+ case filemode.Regular:
+ return Blob
+ case filemode.Executable:
+ return Executable
+ case filemode.Symlink:
+ return Symlink
+ case filemode.Submodule:
+ return Submodule
+ default:
+ return Unknown
+ }
+}
+
+// BlobAtPath returns the content, size, and git object hash of the file at
+// path under ref. rMutex is held for the entire function, covering all
+// shared-Scanner access (CommitObject, Tree, File). The returned reader is
+// safe to use without the mutex: small blobs are already materialized into a
+// MemoryObject (bytes.Reader) by the time File() returns; large blobs come
+// back as an FSObject whose Reader() opens its own independent file handle and
+// Scanner and then reads via ReadAt β no shared state is touched after this
+// function returns. Callers must Close the reader.
+func (repo *GoGitRepo) BlobAtPath(ref, path string) (io.ReadCloser, int64, Hash, error) {
+ path = strings.Trim(path, "/")
+ if path == "" {
+ return nil, 0, "", ErrNotFound
+ }
+
+ repo.rMutex.Lock()
+ defer repo.rMutex.Unlock()
+
+ startHash, err := repo.resolveRefToHash(ref)
+ if err != nil {
+ return nil, 0, "", ErrNotFound
+ }
+ commit, err := repo.r.CommitObject(startHash)
+ if err != nil {
+ return nil, 0, "", err
+ }
+ tree, err := commit.Tree()
+ if err != nil {
+ return nil, 0, "", err
+ }
+ f, err := tree.File(path)
+ if err != nil {
+ return nil, 0, "", ErrNotFound
+ }
+ r, err := f.Reader()
+ if err != nil {
+ return nil, 0, "", err
+ }
+
+ return r, f.Blob.Size, Hash(f.Blob.Hash.String()), nil
+}
+
+// CommitLog returns at most limit commits reachable from ref, optionally
+// filtered to those that touched path, starting after the given cursor hash,
+// and bounded by the since/until author-date range.
+func (repo *GoGitRepo) CommitLog(ref, path string, limit int, after Hash, since, until *time.Time) ([]CommitMeta, error) {
+ repo.rMutex.Lock()
+ defer repo.rMutex.Unlock()
+
+ startHash, err := repo.resolveRefToHash(ref)
+ if err != nil {
+ return nil, err
+ }
+
+ // Normalize path: strip leading/trailing slashes so prefix matching works.
+ path = strings.Trim(path, "/")
+
+ opts := &gogit.LogOptions{
+ From: startHash,
+ Order: gogit.LogOrderCommitterTime,
+ }
+ if path != "" {
+ opts.PathFilter = func(p string) bool {
+ return p == path || strings.HasPrefix(p, path+"/")
+ }
+ }
+
+ iter, err := repo.r.Log(opts)
+ if err != nil {
+ return nil, err
+ }
+ defer iter.Close()
+
+ var result []CommitMeta
+ skipping := after != ""
+ for {
+ c, err := iter.Next()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return nil, err
+ }
+ h := Hash(c.Hash.String())
+ if skipping {
+ if h == after {
+ skipping = false
+ }
+ continue
+ }
+ if since != nil && c.Author.When.Before(*since) {
+ continue
+ }
+ if until != nil && c.Author.When.After(*until) {
+ continue
+ }
+ result = append(result, commitToMeta(c))
+ if limit > 0 && len(result) >= limit {
+ break
+ }
+ }
+ return result, nil
+}
+
+// treeEntriesAtPath returns the tree hash and a nameβentry-hash map for the
+// directory at dirPath inside the given commit. An empty dirPath means the
+// root tree. The tree hash is content-addressed and can be used as a stable
+// cache key regardless of which branch or ref was resolved.
+func treeEntriesAtPath(c *object.Commit, dirPath string) (plumbing.Hash, map[string]plumbing.Hash, error) {
+ tree, err := c.Tree()
+ if err != nil {
+ return plumbing.ZeroHash, nil, err
+ }
+ if dirPath != "" {
+ subtree, err := tree.Tree(dirPath)
+ if err != nil {
+ return plumbing.ZeroHash, nil, err
+ }
+ tree = subtree
+ }
+ result := make(map[string]plumbing.Hash, len(tree.Entries))
+ for _, e := range tree.Entries {
+ result[e.Name] = e.Hash
+ }
+ return tree.Hash, result, nil
+}
+
+// LastCommitForEntries performs a single history walk to find, for each name,
+// the most recent commit that changed that entry in the directory at path.
+//
+// Results are cached by (dirTreeHash, path). Because git trees are
+// content-addressed, two refs that point to the same directory tree share one
+// cache entry, and the cache never needs invalidation: a changed directory
+// produces a new tree hash, which becomes a new key.
+func (repo *GoGitRepo) LastCommitForEntries(ref, path string, names []string) (map[string]CommitMeta, error) {
+ // Normalize path up front so the cache key is canonical.
+ path = strings.Trim(path, "/")
+
+ // Resolve ref and load the current directory tree in one brief lock.
+ // We need the tree hash for the cache key and we keep the entries to
+ // seed the parent-reuse optimisation in the walk below.
+ repo.rMutex.Lock()
+ startHash, err := repo.resolveRefToHash(ref)
+ if err != nil {
+ repo.rMutex.Unlock()
+ return nil, err
+ }
+ startCommit, err := repo.r.CommitObject(startHash)
+ if err != nil {
+ repo.rMutex.Unlock()
+ return nil, err
+ }
+ treeHash, startEntries, err := treeEntriesAtPath(startCommit, path)
+ repo.rMutex.Unlock()
+ if err != nil {
+ // path doesn't exist at HEAD β nothing to return.
+ return map[string]CommitMeta{}, nil
+ }
+
+ // The cache is keyed by the directory's tree hash (content-addressed)
+ // plus the path so two directories with identical content but different
+ // locations don't collide.
+ cacheKey := treeHash.String() + "\x00" + path
+
+ // Cache hit: filter the stored result down to the requested names.
+ if cached, ok := repo.lastCommitCache.Get(cacheKey); ok {
+ result := make(map[string]CommitMeta, len(names))
+ for _, n := range names {
+ if m, found := cached[n]; found {
+ result[n] = m
+ }
+ }
+ return result, nil
+ }
+
+ // Cache miss: walk history for ALL entries in this directory so the
+ // cached result is complete and valid for any future name subset.
+ remaining := make(map[string]bool, len(startEntries))
+ for name := range startEntries {
+ remaining[name] = true
+ }
+ result := make(map[string]CommitMeta, len(remaining))
+
+ repo.rMutex.Lock()
+
+ iter, err := repo.r.Log(&gogit.LogOptions{
+ From: startHash,
+ Order: gogit.LogOrderCommitterTime,
+ })
+ if err != nil {
+ repo.rMutex.Unlock()
+ return nil, err
+ }
+
+ // Seed the parent-reuse cache with the entries we already fetched above
+ // so the first iteration's current-tree read is skipped for free.
+ // In a linear history this halves tree reads for every subsequent step:
+ // the parent fetched at depth D is the current commit at depth D+1.
+ cachedParentHash := startHash
+ cachedParentEntries := startEntries
+
+ for depth := 0; len(remaining) > 0 && depth < lastCommitDepthLimit; depth++ {
+ c, err := iter.Next()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ iter.Close()
+ repo.rMutex.Unlock()
+ return nil, err
+ }
+
+ var currentEntries map[string]plumbing.Hash
+ if c.Hash == cachedParentHash && cachedParentEntries != nil {
+ currentEntries = cachedParentEntries
+ } else {
+ _, currentEntries, err = treeEntriesAtPath(c, path)
+ if err != nil {
+ // path may not exist in this commit; treat as empty
+ currentEntries = map[string]plumbing.Hash{}
+ }
+ }
+
+ var parentEntries map[string]plumbing.Hash
+ cachedParentHash = plumbing.ZeroHash
+ cachedParentEntries = nil
+ if len(c.ParentHashes) > 0 {
+ if parent, err := c.Parents().Next(); err == nil {
+ _, parentEntries, _ = treeEntriesAtPath(parent, path)
+ cachedParentHash = c.ParentHashes[0]
+ cachedParentEntries = parentEntries
+ }
+ }
+
+ meta := commitToMeta(c)
+ for name := range remaining {
+ curHash, inCurrent := currentEntries[name]
+ parentHash, inParent := parentEntries[name]
+ if inCurrent != inParent || (inCurrent && curHash != parentHash) {
+ result[name] = meta
+ delete(remaining, name)
+ }
+ }
+ }
+
+ iter.Close()
+ repo.rMutex.Unlock()
+
+ // Store a defensive copy so that callers cannot mutate cached entries.
+ // The cached map contains all directory entries, not just the requested
+ // names, so future calls for the same directory are fully served from
+ // cache regardless of which names they request.
+ cached := make(map[string]CommitMeta, len(result))
+ for k, v := range result {
+ cached[k] = v
+ }
+ repo.lastCommitCache.Add(cacheKey, cached)
+
+ // Return only the entries that were requested.
+ filtered := make(map[string]CommitMeta, len(names))
+ for _, n := range names {
+ if m, ok := result[n]; ok {
+ filtered[n] = m
+ }
+ }
+ return filtered, nil
+}
+
+// CommitDetail returns the full commit metadata and list of changed files.
+func (repo *GoGitRepo) CommitDetail(hash Hash) (CommitDetail, error) {
+ repo.rMutex.Lock()
+ defer repo.rMutex.Unlock()
+
+ c, err := repo.r.CommitObject(plumbing.NewHash(hash.String()))
+ if err == plumbing.ErrObjectNotFound {
+ return CommitDetail{}, ErrNotFound
+ }
+ if err != nil {
+ return CommitDetail{}, err
+ }
+
+ toTree, err := c.Tree()
+ if err != nil {
+ return CommitDetail{}, err
+ }
+
+ var fromTree *object.Tree
+ if len(c.ParentHashes) > 0 {
+ parent, err := repo.r.CommitObject(c.ParentHashes[0])
+ if err != nil {
+ return CommitDetail{}, fmt.Errorf("loading parent commit: %w", err)
+ }
+ fromTree, err = parent.Tree()
+ if err != nil {
+ return CommitDetail{}, fmt.Errorf("loading parent tree: %w", err)
+ }
+ }
+
+ changes, err := object.DiffTree(fromTree, toTree)
+ if err != nil {
+ return CommitDetail{}, err
+ }
+
+ // Use ch.From.Name / ch.To.Name directly β these come from the tree
+ // metadata and do not require reading any blob content.
+ files := make([]ChangedFile, 0, len(changes))
+ for _, ch := range changes {
+ files = append(files, changedFileFromChange(ch.From.Name, ch.To.Name))
+ }
+
+ return CommitDetail{
+ CommitMeta: commitToMeta(c),
+ FullMessage: c.Message,
+ Files: files,
+ }, nil
+}
+
+func changedFileFromChange(fromName, toName string) ChangedFile {
+ switch {
+ case fromName == "":
+ return ChangedFile{Path: toName, Status: ChangeStatusAdded}
+ case toName == "":
+ return ChangedFile{Path: fromName, Status: ChangeStatusDeleted}
+ case fromName != toName:
+ op := fromName
+ return ChangedFile{Path: toName, OldPath: &op, Status: ChangeStatusRenamed}
+ default:
+ return ChangedFile{Path: toName, Status: ChangeStatusModified}
+ }
+}
+
+// CommitFileDiff returns the unified diff for a single file in a commit,
+// relative to the first parent.
+func (repo *GoGitRepo) CommitFileDiff(hash Hash, filePath string) (FileDiff, error) {
+ repo.rMutex.Lock()
+ defer repo.rMutex.Unlock()
+
+ c, err := repo.r.CommitObject(plumbing.NewHash(hash.String()))
+ if err == plumbing.ErrObjectNotFound {
+ return FileDiff{}, ErrNotFound
+ }
+ if err != nil {
+ return FileDiff{}, err
+ }
+
+ toTree, err := c.Tree()
+ if err != nil {
+ return FileDiff{}, err
+ }
+
+ var fromTree *object.Tree
+ if len(c.ParentHashes) > 0 {
+ parent, err := repo.r.CommitObject(c.ParentHashes[0])
+ if err != nil {
+ return FileDiff{}, fmt.Errorf("loading parent commit: %w", err)
+ }
+ fromTree, err = parent.Tree()
+ if err != nil {
+ return FileDiff{}, fmt.Errorf("loading parent tree: %w", err)
+ }
+ }
+
+ changes, err := object.DiffTree(fromTree, toTree)
+ if err != nil {
+ return FileDiff{}, err
+ }
+
+ for _, ch := range changes {
+ name := ch.To.Name
+ if name == "" {
+ name = ch.From.Name
+ }
+ // match on either new or old path
+ if name != filePath && ch.From.Name != filePath {
+ continue
+ }
+
+ from, to, err := ch.Files()
+ if err != nil {
+ return FileDiff{}, err
+ }
+
+ patch, err := ch.Patch()
+ if err != nil {
+ return FileDiff{}, err
+ }
+
+ fd := FileDiff{
+ IsNew: from == nil,
+ IsDelete: to == nil,
+ }
+ if to != nil {
+ fd.Path = to.Name
+ }
+ if from != nil {
+ if fd.Path == "" {
+ fd.Path = from.Name
+ } else if from.Name != fd.Path {
+ op := from.Name
+ fd.OldPath = &op
+ }
+ }
+
+ fps := patch.FilePatches()
+ if len(fps) > 0 {
+ fp := fps[0]
+ fd.IsBinary = fp.IsBinary()
+ if !fd.IsBinary {
+ fd.Hunks = buildDiffHunks(fp)
+ }
+ }
+ return fd, nil
+ }
+ return FileDiff{}, ErrNotFound
+}
+
+// buildDiffHunks converts a go-git FilePatch into DiffHunks with line numbers
+// and context grouping.
+func buildDiffHunks(fp fdiff.FilePatch) []DiffHunk {
+ type pendingLine struct {
+ typ DiffLineType
+ content string
+ oldLine int
+ newLine int
+ }
+
+ var allLines []pendingLine
+ oldLine, newLine := 1, 1
+ for _, chunk := range fp.Chunks() {
+ lines := strings.Split(chunk.Content(), "\n")
+ // strip trailing empty element produced by a trailing newline
+ if len(lines) > 0 && lines[len(lines)-1] == "" {
+ lines = lines[:len(lines)-1]
+ }
+ switch chunk.Type() {
+ case fdiff.Equal:
+ for _, l := range lines {
+ allLines = append(allLines, pendingLine{DiffLineContext, l, oldLine, newLine})
+ oldLine++
+ newLine++
+ }
+ case fdiff.Add:
+ for _, l := range lines {
+ allLines = append(allLines, pendingLine{DiffLineAdded, l, 0, newLine})
+ newLine++
+ }
+ case fdiff.Delete:
+ for _, l := range lines {
+ allLines = append(allLines, pendingLine{DiffLineDeleted, l, oldLine, 0})
+ oldLine++
+ }
+ }
+ }
+ if len(allLines) == 0 {
+ return nil
+ }
+
+ const ctx = 3 // context lines around each changed block
+
+ // find spans of changed lines
+ type span struct{ start, end int }
+ var spans []span
+ for i, l := range allLines {
+ if l.typ == DiffLineContext {
+ continue
+ }
+ if len(spans) == 0 || i > spans[len(spans)-1].end+1 {
+ spans = append(spans, span{i, i})
+ } else {
+ spans[len(spans)-1].end = i
+ }
+ }
+
+ // expand each span by ctx lines and merge overlapping ones
+ var merged []span
+ for _, s := range spans {
+ s.start = max(0, s.start-ctx)
+ s.end = min(len(allLines)-1, s.end+ctx)
+ if len(merged) > 0 && s.start <= merged[len(merged)-1].end+1 {
+ merged[len(merged)-1].end = s.end
+ } else {
+ merged = append(merged, s)
+ }
+ }
+
+ hunks := make([]DiffHunk, 0, len(merged))
+ for _, s := range merged {
+ segment := allLines[s.start : s.end+1]
+ dl := make([]DiffLine, len(segment))
+ var oldStart, newStart, oldCount, newCount int
+ for i, l := range segment {
+ dl[i] = DiffLine{Type: l.typ, Content: l.content, OldLine: l.oldLine, NewLine: l.newLine}
+ if l.oldLine > 0 {
+ if oldStart == 0 {
+ oldStart = l.oldLine
+ }
+ oldCount++
+ }
+ if l.newLine > 0 {
+ if newStart == 0 {
+ newStart = l.newLine
+ }
+ newCount++
+ }
+ }
+ hunks = append(hunks, DiffHunk{
+ OldStart: oldStart,
+ OldLines: oldCount,
+ NewStart: newStart,
+ NewLines: newCount,
+ Lines: dl,
+ })
+ }
+ return hunks
+}
+
// AddRemote add a new remote to the repository
// Not in the interface because it's only used for testing
func (repo *GoGitRepo) AddRemote(name string, url string) error {
@@ -4,8 +4,10 @@ import (
"bytes"
"crypto/sha1"
"fmt"
+ "io"
"strings"
"sync"
+ "time"
"github.com/99designs/keyring"
"github.com/ProtonMail/go-crypto/openpgp"
@@ -24,7 +26,7 @@ type mockRepo struct {
*mockRepoCommon
*mockRepoStorage
*mockRepoIndex
- *mockRepoData
+ *mockRepoDataBrowse
*mockRepoClock
*mockRepoTest
}
@@ -33,14 +35,14 @@ func (m *mockRepo) Close() error { return nil }
func NewMockRepo() *mockRepo {
return &mockRepo{
- mockRepoConfig: NewMockRepoConfig(),
- mockRepoKeyring: NewMockRepoKeyring(),
- mockRepoCommon: NewMockRepoCommon(),
- mockRepoStorage: NewMockRepoStorage(),
- mockRepoIndex: newMockRepoIndex(),
- mockRepoData: NewMockRepoData(),
- mockRepoClock: NewMockRepoClock(),
- mockRepoTest: NewMockRepoTest(),
+ mockRepoConfig: NewMockRepoConfig(),
+ mockRepoKeyring: NewMockRepoKeyring(),
+ mockRepoCommon: NewMockRepoCommon(),
+ mockRepoStorage: NewMockRepoStorage(),
+ mockRepoIndex: newMockRepoIndex(),
+ mockRepoDataBrowse: newMockRepoDataBrowse(),
+ mockRepoClock: NewMockRepoClock(),
+ mockRepoTest: NewMockRepoTest(),
}
}
@@ -219,47 +221,51 @@ func (m *mockIndex) Close() error {
return nil
}
-var _ RepoData = &mockRepoData{}
+var _ RepoData = &mockRepoDataBrowse{}
type commit struct {
treeHash Hash
parents []Hash
sig string
+ date time.Time
+ message string
}
-type mockRepoData struct {
- blobs map[Hash][]byte
- trees map[Hash]string
- commits map[Hash]commit
- refs map[string]Hash
+type mockRepoDataBrowse struct {
+ blobs map[Hash][]byte
+ trees map[Hash]string
+ commits map[Hash]commit
+ refs map[string]Hash
+ defaultBranch string
}
-func NewMockRepoData() *mockRepoData {
- return &mockRepoData{
- blobs: make(map[Hash][]byte),
- trees: make(map[Hash]string),
- commits: make(map[Hash]commit),
- refs: make(map[string]Hash),
+func newMockRepoDataBrowse() *mockRepoDataBrowse {
+ return &mockRepoDataBrowse{
+ blobs: make(map[Hash][]byte),
+ trees: make(map[Hash]string),
+ commits: make(map[Hash]commit),
+ refs: make(map[string]Hash),
+ defaultBranch: "main",
}
}
-func (r *mockRepoData) FetchRefs(remote string, prefixes ...string) (string, error) {
+func (r *mockRepoDataBrowse) FetchRefs(remote string, prefixes ...string) (string, error) {
panic("implement me")
}
// PushRefs push git refs to a remote
-func (r *mockRepoData) PushRefs(remote string, prefixes ...string) (string, error) {
+func (r *mockRepoDataBrowse) PushRefs(remote string, prefixes ...string) (string, error) {
panic("implement me")
}
-func (r *mockRepoData) StoreData(data []byte) (Hash, error) {
+func (r *mockRepoDataBrowse) StoreData(data []byte) (Hash, error) {
rawHash := sha1.Sum(data)
hash := Hash(fmt.Sprintf("%x", rawHash))
r.blobs[hash] = data
return hash, nil
}
-func (r *mockRepoData) ReadData(hash Hash) ([]byte, error) {
+func (r *mockRepoDataBrowse) ReadData(hash Hash) ([]byte, error) {
data, ok := r.blobs[hash]
if !ok {
return nil, ErrNotFound
@@ -268,7 +274,7 @@ func (r *mockRepoData) ReadData(hash Hash) ([]byte, error) {
return data, nil
}
-func (r *mockRepoData) StoreTree(entries []TreeEntry) (Hash, error) {
+func (r *mockRepoDataBrowse) StoreTree(entries []TreeEntry) (Hash, error) {
buffer := prepareTreeEntries(entries)
rawHash := sha1.Sum(buffer.Bytes())
hash := Hash(fmt.Sprintf("%x", rawHash))
@@ -277,7 +283,7 @@ func (r *mockRepoData) StoreTree(entries []TreeEntry) (Hash, error) {
return hash, nil
}
-func (r *mockRepoData) ReadTree(hash Hash) ([]TreeEntry, error) {
+func (r *mockRepoDataBrowse) ReadTree(hash Hash) ([]TreeEntry, error) {
var data string
data, ok := r.trees[hash]
@@ -300,11 +306,11 @@ func (r *mockRepoData) ReadTree(hash Hash) ([]TreeEntry, error) {
return readTreeEntries(data)
}
-func (r *mockRepoData) StoreCommit(treeHash Hash, parents ...Hash) (Hash, error) {
+func (r *mockRepoDataBrowse) StoreCommit(treeHash Hash, parents ...Hash) (Hash, error) {
return r.StoreSignedCommit(treeHash, nil, parents...)
}
-func (r *mockRepoData) StoreSignedCommit(treeHash Hash, signKey *openpgp.Entity, parents ...Hash) (Hash, error) {
+func (r *mockRepoDataBrowse) StoreSignedCommit(treeHash Hash, signKey *openpgp.Entity, parents ...Hash) (Hash, error) {
hasher := sha1.New()
hasher.Write([]byte(treeHash))
for _, parent := range parents {
@@ -315,6 +321,7 @@ func (r *mockRepoData) StoreSignedCommit(treeHash Hash, signKey *openpgp.Entity,
c := commit{
treeHash: treeHash,
parents: parents,
+ date: time.Now(),
}
if signKey != nil {
// unlike go-git, we only sign the tree hash for simplicity instead of all the fields (parents ...)
@@ -328,7 +335,7 @@ func (r *mockRepoData) StoreSignedCommit(treeHash Hash, signKey *openpgp.Entity,
return hash, nil
}
-func (r *mockRepoData) ReadCommit(hash Hash) (Commit, error) {
+func (r *mockRepoDataBrowse) ReadCommit(hash Hash) (Commit, error) {
c, ok := r.commits[hash]
if !ok {
return Commit{}, ErrNotFound
@@ -350,7 +357,7 @@ func (r *mockRepoData) ReadCommit(hash Hash) (Commit, error) {
return result, nil
}
-func (r *mockRepoData) ResolveRef(ref string) (Hash, error) {
+func (r *mockRepoDataBrowse) ResolveRef(ref string) (Hash, error) {
h, ok := r.refs[ref]
if !ok {
return "", ErrNotFound
@@ -358,17 +365,17 @@ func (r *mockRepoData) ResolveRef(ref string) (Hash, error) {
return h, nil
}
-func (r *mockRepoData) UpdateRef(ref string, hash Hash) error {
+func (r *mockRepoDataBrowse) UpdateRef(ref string, hash Hash) error {
r.refs[ref] = hash
return nil
}
-func (r *mockRepoData) RemoveRef(ref string) error {
+func (r *mockRepoDataBrowse) RemoveRef(ref string) error {
delete(r.refs, ref)
return nil
}
-func (r *mockRepoData) ListRefs(refPrefix string) ([]string, error) {
+func (r *mockRepoDataBrowse) ListRefs(refPrefix string) ([]string, error) {
var keys []string
for k := range r.refs {
@@ -380,12 +387,12 @@ func (r *mockRepoData) ListRefs(refPrefix string) ([]string, error) {
return keys, nil
}
-func (r *mockRepoData) RefExist(ref string) (bool, error) {
+func (r *mockRepoDataBrowse) RefExist(ref string) (bool, error) {
_, exist := r.refs[ref]
return exist, nil
}
-func (r *mockRepoData) CopyRef(source string, dest string) error {
+func (r *mockRepoDataBrowse) CopyRef(source string, dest string) error {
hash, exist := r.refs[source]
if !exist {
@@ -396,10 +403,446 @@ func (r *mockRepoData) CopyRef(source string, dest string) error {
return nil
}
-func (r *mockRepoData) ListCommits(ref string) ([]Hash, error) {
+func (r *mockRepoDataBrowse) ListCommits(ref string) ([]Hash, error) {
return nonNativeListCommits(r, ref)
}
+// resolveRef resolves a ref matching the RepoBrowse contract:
+// refs/heads/<ref>, refs/tags/<ref>, full ref name, raw commit hash.
+func (r *mockRepoDataBrowse) resolveRef(ref string) (Hash, error) {
+ for _, candidate := range []string{"refs/heads/" + ref, "refs/tags/" + ref, ref} {
+ if h, ok := r.refs[candidate]; ok {
+ return h, nil
+ }
+ }
+ if _, ok := r.commits[Hash(ref)]; ok {
+ return Hash(ref), nil
+ }
+ return "", ErrNotFound
+}
+
+// treeEntriesAtHash parses the entries of the tree stored under hash.
+func (r *mockRepoDataBrowse) treeEntriesAtHash(hash Hash) ([]TreeEntry, error) {
+ data, ok := r.trees[hash]
+ if !ok {
+ return nil, ErrNotFound
+ }
+ return readTreeEntries(data)
+}
+
+// treeEntriesAt returns the directory entries at path inside the tree rooted at
+// treeHash. path="" returns root entries. Returns ErrNotFound if path doesn't
+// exist or resolves to a blob rather than a tree.
+func (r *mockRepoDataBrowse) treeEntriesAt(treeHash Hash, path string) ([]TreeEntry, error) {
+ path = strings.Trim(path, "/")
+ if path == "" {
+ return r.treeEntriesAtHash(treeHash)
+ }
+ seg, rest, _ := strings.Cut(path, "/")
+ entries, err := r.treeEntriesAtHash(treeHash)
+ if err != nil {
+ return nil, err
+ }
+ for _, e := range entries {
+ if e.Name != seg || e.ObjectType != Tree {
+ continue
+ }
+ if rest == "" {
+ return r.treeEntriesAtHash(e.Hash)
+ }
+ return r.treeEntriesAt(e.Hash, rest)
+ }
+ return nil, ErrNotFound
+}
+
+// blobHashAt walks the tree to find the blob hash for the file at path.
+func (r *mockRepoDataBrowse) blobHashAt(treeHash Hash, path string) (Hash, error) {
+ path = strings.Trim(path, "/")
+ seg, rest, hasRest := strings.Cut(path, "/")
+ entries, err := r.treeEntriesAtHash(treeHash)
+ if err != nil {
+ return "", err
+ }
+ for _, e := range entries {
+ if e.Name != seg {
+ continue
+ }
+ if !hasRest {
+ return e.Hash, nil
+ }
+ if e.ObjectType != Tree {
+ return "", ErrNotFound
+ }
+ return r.blobHashAt(e.Hash, rest)
+ }
+ return "", ErrNotFound
+}
+
+// diffTrees returns the changed files between two trees, recursing into
+// sub-trees. fromHash=="" means an empty (non-existent) tree.
+func (r *mockRepoDataBrowse) diffTrees(fromHash, toHash Hash, prefix string) []ChangedFile {
+ var fromEntries, toEntries []TreeEntry
+ if fromHash != "" {
+ fromEntries, _ = r.treeEntriesAtHash(fromHash)
+ }
+ if toHash != "" {
+ toEntries, _ = r.treeEntriesAtHash(toHash)
+ }
+
+ fromMap := make(map[string]TreeEntry, len(fromEntries))
+ for _, e := range fromEntries {
+ fromMap[e.Name] = e
+ }
+ toMap := make(map[string]TreeEntry, len(toEntries))
+ for _, e := range toEntries {
+ toMap[e.Name] = e
+ }
+
+ var result []ChangedFile
+ for _, e := range toEntries {
+ path := prefix + e.Name
+ f, existed := fromMap[e.Name]
+ if e.ObjectType == Tree {
+ var sub Hash
+ if existed {
+ sub = f.Hash
+ }
+ result = append(result, r.diffTrees(sub, e.Hash, path+"/")...)
+ } else if !existed {
+ result = append(result, ChangedFile{Path: path, Status: ChangeStatusAdded})
+ } else if f.Hash != e.Hash {
+ result = append(result, ChangedFile{Path: path, Status: ChangeStatusModified})
+ }
+ }
+ for _, f := range fromEntries {
+ if _, exists := toMap[f.Name]; exists {
+ continue
+ }
+ path := prefix + f.Name
+ if f.ObjectType == Tree {
+ result = append(result, r.diffTrees(f.Hash, "", path+"/")...)
+ } else {
+ result = append(result, ChangedFile{Path: path, Status: ChangeStatusDeleted})
+ }
+ }
+ return result
+}
+
+func mockCommitMeta(hash Hash, c commit) CommitMeta {
+ return CommitMeta{
+ Hash: hash,
+ Parents: c.parents,
+ Date: c.date,
+ Message: c.message,
+ }
+}
+
+func (r *mockRepoDataBrowse) Branches() ([]BranchInfo, error) {
+ var branches []BranchInfo
+ for ref, hash := range r.refs {
+ name, ok := strings.CutPrefix(ref, "refs/heads/")
+ if !ok {
+ continue
+ }
+ branches = append(branches, BranchInfo{
+ Name: name,
+ Hash: hash,
+ IsDefault: name == r.defaultBranch,
+ })
+ }
+ return branches, nil
+}
+
+func (r *mockRepoDataBrowse) Tags() ([]TagInfo, error) {
+ var tags []TagInfo
+ for ref, hash := range r.refs {
+ name, ok := strings.CutPrefix(ref, "refs/tags/")
+ if !ok {
+ continue
+ }
+ tags = append(tags, TagInfo{Name: name, Hash: hash})
+ }
+ return tags, nil
+}
+
+func (r *mockRepoDataBrowse) TreeAtPath(ref, path string) ([]TreeEntry, error) {
+ startHash, err := r.resolveRef(ref)
+ if err != nil {
+ return nil, ErrNotFound
+ }
+ c, ok := r.commits[startHash]
+ if !ok {
+ return nil, ErrNotFound
+ }
+ return r.treeEntriesAt(c.treeHash, path)
+}
+
+func (r *mockRepoDataBrowse) BlobAtPath(ref, path string) (io.ReadCloser, int64, Hash, error) {
+ startHash, err := r.resolveRef(ref)
+ if err != nil {
+ return nil, 0, "", ErrNotFound
+ }
+ c, ok := r.commits[startHash]
+ if !ok {
+ return nil, 0, "", ErrNotFound
+ }
+ blobHash, err := r.blobHashAt(c.treeHash, path)
+ if err != nil {
+ return nil, 0, "", ErrNotFound
+ }
+ data, ok := r.blobs[blobHash]
+ if !ok {
+ return nil, 0, "", ErrNotFound
+ }
+ return io.NopCloser(bytes.NewReader(data)), int64(len(data)), blobHash, nil
+}
+
+func (r *mockRepoDataBrowse) CommitLog(ref, path string, limit int, after Hash, since, until *time.Time) ([]CommitMeta, error) {
+ startHash, err := r.resolveRef(ref)
+ if err != nil {
+ return nil, ErrNotFound
+ }
+ path = strings.Trim(path, "/")
+ var result []CommitMeta
+ skipping := after != ""
+ current := startHash
+ seen := make(map[Hash]bool)
+ for {
+ if seen[current] {
+ break
+ }
+ seen[current] = true
+ c, ok := r.commits[current]
+ if !ok {
+ break
+ }
+ if skipping {
+ if current == after {
+ skipping = false
+ }
+ if len(c.parents) == 0 {
+ break
+ }
+ current = c.parents[0]
+ continue
+ }
+ meta := mockCommitMeta(current, c)
+ if since != nil && meta.Date.Before(*since) {
+ if len(c.parents) == 0 {
+ break
+ }
+ current = c.parents[0]
+ continue
+ }
+ if until != nil && meta.Date.After(*until) {
+ if len(c.parents) == 0 {
+ break
+ }
+ current = c.parents[0]
+ continue
+ }
+ if path != "" {
+ var fromTreeHash Hash
+ if len(c.parents) > 0 {
+ if parent, ok := r.commits[c.parents[0]]; ok {
+ fromTreeHash = parent.treeHash
+ }
+ }
+ touched := false
+ for _, f := range r.diffTrees(fromTreeHash, c.treeHash, "") {
+ if f.Path == path || strings.HasPrefix(f.Path, path+"/") {
+ touched = true
+ break
+ }
+ }
+ if !touched {
+ if len(c.parents) == 0 {
+ break
+ }
+ current = c.parents[0]
+ continue
+ }
+ }
+ result = append(result, meta)
+ if limit > 0 && len(result) >= limit {
+ break
+ }
+ if len(c.parents) == 0 {
+ break
+ }
+ current = c.parents[0]
+ }
+ return result, nil
+}
+
+func (r *mockRepoDataBrowse) LastCommitForEntries(ref, path string, names []string) (map[string]CommitMeta, error) {
+ startHash, err := r.resolveRef(ref)
+ if err != nil {
+ return nil, ErrNotFound
+ }
+ path = strings.Trim(path, "/")
+ remaining := make(map[string]bool, len(names))
+ for _, n := range names {
+ remaining[n] = true
+ }
+ result := make(map[string]CommitMeta)
+ current := startHash
+ seen := make(map[Hash]bool)
+ for len(remaining) > 0 {
+ if seen[current] {
+ break
+ }
+ seen[current] = true
+ c, ok := r.commits[current]
+ if !ok {
+ break
+ }
+ curEntries, err := r.treeEntriesAt(c.treeHash, path)
+ if err != nil {
+ if len(c.parents) == 0 {
+ break
+ }
+ current = c.parents[0]
+ continue
+ }
+ curMap := make(map[string]Hash, len(curEntries))
+ for _, e := range curEntries {
+ curMap[e.Name] = e.Hash
+ }
+ if len(c.parents) == 0 {
+ for name := range remaining {
+ if _, ok := curMap[name]; ok {
+ result[name] = mockCommitMeta(current, c)
+ delete(remaining, name)
+ }
+ }
+ break
+ }
+ pc, ok := r.commits[c.parents[0]]
+ if !ok {
+ break
+ }
+ parentEntries, _ := r.treeEntriesAt(pc.treeHash, path)
+ parentMap := make(map[string]Hash, len(parentEntries))
+ for _, e := range parentEntries {
+ parentMap[e.Name] = e.Hash
+ }
+ for name := range remaining {
+ cur, curExists := curMap[name]
+ par, parExists := parentMap[name]
+ if curExists && (!parExists || cur != par) {
+ result[name] = mockCommitMeta(current, c)
+ delete(remaining, name)
+ }
+ }
+ current = c.parents[0]
+ }
+ return result, nil
+}
+
+func (r *mockRepoDataBrowse) CommitDetail(hash Hash) (CommitDetail, error) {
+ c, ok := r.commits[hash]
+ if !ok {
+ return CommitDetail{}, ErrNotFound
+ }
+ var fromTreeHash Hash
+ if len(c.parents) > 0 {
+ if parent, ok := r.commits[c.parents[0]]; ok {
+ fromTreeHash = parent.treeHash
+ }
+ }
+ return CommitDetail{
+ CommitMeta: mockCommitMeta(hash, c),
+ Files: r.diffTrees(fromTreeHash, c.treeHash, ""),
+ }, nil
+}
+
+func (r *mockRepoDataBrowse) CommitFileDiff(hash Hash, filePath string) (FileDiff, error) {
+ c, ok := r.commits[hash]
+ if !ok {
+ return FileDiff{}, ErrNotFound
+ }
+ var fromTreeHash Hash
+ if len(c.parents) > 0 {
+ if parent, ok := r.commits[c.parents[0]]; ok {
+ fromTreeHash = parent.treeHash
+ }
+ }
+ files := r.diffTrees(fromTreeHash, c.treeHash, "")
+ var matched *ChangedFile
+ for i := range files {
+ if files[i].Path == filePath {
+ matched = &files[i]
+ break
+ }
+ }
+ if matched == nil {
+ return FileDiff{}, ErrNotFound
+ }
+ fd := FileDiff{
+ Path: filePath,
+ IsNew: matched.Status == ChangeStatusAdded,
+ IsDelete: matched.Status == ChangeStatusDeleted,
+ }
+ var oldContent, newContent []byte
+ if fromTreeHash != "" {
+ if bh, err := r.blobHashAt(fromTreeHash, filePath); err == nil {
+ oldContent = r.blobs[bh]
+ }
+ }
+ if bh, err := r.blobHashAt(c.treeHash, filePath); err == nil {
+ newContent = r.blobs[bh]
+ }
+ fd.Hunks = mockDiffHunks(oldContent, newContent)
+ return fd, nil
+}
+
+// mockDiffHunks produces a single DiffHunk using a prefix/suffix scan.
+func mockDiffHunks(old, new []byte) []DiffHunk {
+ oldLines := splitBlobLines(old)
+ newLines := splitBlobLines(new)
+ i := 0
+ for i < len(oldLines) && i < len(newLines) && oldLines[i] == newLines[i] {
+ i++
+ }
+ j, k := len(oldLines), len(newLines)
+ for j > i && k > i && oldLines[j-1] == newLines[k-1] {
+ j--
+ k--
+ }
+ if j == i && k == i {
+ return nil // no changed region
+ }
+ oldLine, newLine := 1, 1
+ var lines []DiffLine
+ for _, l := range oldLines[:i] {
+ lines = append(lines, DiffLine{Type: DiffLineContext, Content: l, OldLine: oldLine, NewLine: newLine})
+ oldLine++
+ newLine++
+ }
+ for _, l := range oldLines[i:j] {
+ lines = append(lines, DiffLine{Type: DiffLineDeleted, Content: l, OldLine: oldLine})
+ oldLine++
+ }
+ for _, l := range newLines[i:k] {
+ lines = append(lines, DiffLine{Type: DiffLineAdded, Content: l, NewLine: newLine})
+ newLine++
+ }
+ for _, l := range oldLines[j:] {
+ lines = append(lines, DiffLine{Type: DiffLineContext, Content: l, OldLine: oldLine, NewLine: newLine})
+ oldLine++
+ newLine++
+ }
+ return []DiffHunk{{OldStart: 1, OldLines: len(oldLines), NewStart: 1, NewLines: len(newLines), Lines: lines}}
+}
+
+func splitBlobLines(data []byte) []string {
+ if len(data) == 0 {
+ return nil
+ }
+ return strings.Split(strings.TrimRight(string(data), "\n"), "\n")
+}
+
var _ RepoClock = &mockRepoClock{}
type mockRepoClock struct {
@@ -4,6 +4,7 @@ package repository
import (
"errors"
"io"
+ "time"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/go-git/go-billy/v5"
@@ -28,6 +29,7 @@ type Repo interface {
RepoStorage
RepoIndex
RepoData
+ RepoBrowse
Close() error
}
@@ -182,7 +184,7 @@ type RepoData interface {
// ListRefs will return a list of Git ref matching the given refspec
ListRefs(refPrefix string) ([]string, error)
- // RefExist will check if a reference exist in Git
+ // RefExist will check if a reference exists in Git
RefExist(ref string) (bool, error)
// CopyRef will create a new reference with the same value as another one
@@ -209,11 +211,63 @@ type RepoClock interface {
Witness(name string, time lamport.Time) error
}
+// RepoBrowse is implemented by all Repo implementations and provides
+// code-browsing endpoints (file tree, history, diffs).
+//
+// All methods accepting a ref parameter resolve it in order:
+// refs/heads/<ref>, refs/tags/<ref>, full ref name, raw commit hash.
+type RepoBrowse interface {
+ // Branches returns all local branches (refs/heads/*).
+ // IsDefault marks the branch HEAD points to.
+ // All other ref namespaces β including git-bug's internal refs
+ // (refs/bugs/, refs/identities/, β¦) β are excluded.
+ Branches() ([]BranchInfo, error)
+
+ // Tags returns all tags (refs/tags/*).
+ // All other ref namespaces are excluded.
+ Tags() ([]TagInfo, error)
+
+ // TreeAtPath returns the entries of the directory at path under ref.
+ // An empty path returns the root tree.
+ // Returns ErrNotFound if ref or path does not exist, or if path
+ // resolves to a blob rather than a tree.
+ // Symlinks appear as entries with ObjectType Symlink; they are not followed.
+ TreeAtPath(ref, path string) ([]TreeEntry, error)
+
+ // BlobAtPath returns the raw content, byte size, and git object hash of
+ // the file at path under ref. Returns ErrNotFound if ref or path does
+ // not exist, or if path resolves to a tree. Symlinks are not followed.
+ // The caller must close the reader.
+ BlobAtPath(ref, path string) (io.ReadCloser, int64, Hash, error)
+
+ // CommitLog returns at most limit commits reachable from ref, filtered
+ // to those touching path (empty = unrestricted). after is an exclusive
+ // cursor; pass Hash("") for no cursor. since and until bound the author
+ // date (inclusive); pass nil for no bound. Merge commits appear once,
+ // compared against the first parent only.
+ CommitLog(ref, path string, limit int, after Hash, since, until *time.Time) ([]CommitMeta, error)
+
+ // LastCommitForEntries returns the most recent commit that touched each
+ // name in the directory at path under ref. Entries not resolved within
+ // the implementation's depth limit are silently absent from the result.
+ LastCommitForEntries(ref, path string, names []string) (map[string]CommitMeta, error)
+
+ // CommitDetail returns the full metadata and changed-file list for a
+ // single commit identified by its hash. Diffs against the first parent
+ // only; the initial commit is diffed against the empty tree.
+ CommitDetail(hash Hash) (CommitDetail, error)
+
+ // CommitFileDiff returns the unified diff for a single file in a commit
+ // identified by its hash. Diffs against the first parent only; the
+ // initial commit is diffed against the empty tree.
+ CommitFileDiff(hash Hash, filePath string) (FileDiff, error)
+}
+
// ClockLoader hold which logical clock need to exist for an entity and
// how to create them if they don't.
type ClockLoader struct {
- // Clocks hold the name of all the clocks this loader deal with.
- // Those clocks will be checked when the repo load. If not present or broken,
+ // Clocks hold the name of all the clocks this loader deals with.
+ // Those clocks will be checked when the repo loads. If not present or broken,
// Witnesser will be used to create them.
Clocks []string
// Witnesser is a function that will initialize the clocks of a repo
@@ -221,13 +275,13 @@ type ClockLoader struct {
Witnesser func(repo ClockedRepo) error
}
-// TestedRepo is an extended ClockedRepo with function for testing only
+// TestedRepo is an extended ClockedRepo with functions for testing only
type TestedRepo interface {
ClockedRepo
repoTest
}
-// repoTest give access to test only functions
+// repoTest give access to test-only functions
type repoTest interface {
// AddRemote add a new remote to the repository
AddRemote(name string, url string) error
@@ -1,9 +1,11 @@
package repository
import (
+ "io"
"math/rand"
"os"
"testing"
+ "time"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/stretchr/testify/require"
@@ -27,6 +29,10 @@ func RepoTest(t *testing.T, creator RepoCreator) {
RepoDataSignatureTest(t, repo)
})
+ t.Run("Browse", func(t *testing.T) {
+ RepoBrowseTest(t, repo)
+ })
+
t.Run("Config", func(t *testing.T) {
RepoConfigTest(t, repo)
})
@@ -360,3 +366,377 @@ func randomData() []byte {
}
return b
}
+
+// browsable is the interface required by RepoBrowseTest.
+type browsable interface {
+ RepoConfig
+ RepoData
+ RepoBrowse
+}
+
+// RepoBrowseTest exercises the RepoBrowse interface against any implementation.
+//
+// Commit graph (oldest β newest):
+//
+// c1 ββ c2 ββ c3 refs/heads/main (default)
+// βββββββββ refs/heads/feature
+// c1 βββ refs/tags/v1.0
+func RepoBrowseTest(t *testing.T, repo browsable) {
+ t.Helper()
+
+ require.NoError(t, repo.LocalConfig().StoreString("init.defaultBranch", "main"))
+
+ // ββ build fixture βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+ readmeV1 := []byte("# Hello\n")
+ readmeV3 := []byte("# Hello\n\n## Updated\n")
+ mainV1 := []byte("package main\n")
+ mainV2 := []byte("package main\n\n// updated\n")
+ libV1 := []byte("package lib\n")
+ utilV1 := []byte("package util\n")
+
+ hReadmeV1, err := repo.StoreData(readmeV1)
+ require.NoError(t, err)
+ hReadmeV3, err := repo.StoreData(readmeV3)
+ require.NoError(t, err)
+ hMainV1, err := repo.StoreData(mainV1)
+ require.NoError(t, err)
+ hMainV2, err := repo.StoreData(mainV2)
+ require.NoError(t, err)
+ hLibV1, err := repo.StoreData(libV1)
+ require.NoError(t, err)
+ hUtilV1, err := repo.StoreData(utilV1)
+ require.NoError(t, err)
+
+ srcTreeV1, err := repo.StoreTree([]TreeEntry{
+ {ObjectType: Blob, Hash: hLibV1, Name: "lib.go"},
+ })
+ require.NoError(t, err)
+ rootTreeV1, err := repo.StoreTree([]TreeEntry{
+ {ObjectType: Blob, Hash: hReadmeV1, Name: "README.md"},
+ {ObjectType: Blob, Hash: hMainV1, Name: "main.go"},
+ {ObjectType: Tree, Hash: srcTreeV1, Name: "src"},
+ })
+ require.NoError(t, err)
+
+ srcTreeV2, err := repo.StoreTree([]TreeEntry{
+ {ObjectType: Blob, Hash: hLibV1, Name: "lib.go"},
+ {ObjectType: Blob, Hash: hUtilV1, Name: "util.go"},
+ })
+ require.NoError(t, err)
+ rootTreeV2, err := repo.StoreTree([]TreeEntry{
+ {ObjectType: Blob, Hash: hReadmeV1, Name: "README.md"},
+ {ObjectType: Blob, Hash: hMainV2, Name: "main.go"},
+ {ObjectType: Tree, Hash: srcTreeV2, Name: "src"},
+ })
+ require.NoError(t, err)
+
+ rootTreeV3, err := repo.StoreTree([]TreeEntry{
+ {ObjectType: Blob, Hash: hReadmeV3, Name: "README.md"},
+ {ObjectType: Blob, Hash: hMainV2, Name: "main.go"},
+ {ObjectType: Tree, Hash: srcTreeV2, Name: "src"},
+ })
+ require.NoError(t, err)
+
+ c1, err := repo.StoreCommit(rootTreeV1)
+ require.NoError(t, err)
+ c2, err := repo.StoreCommit(rootTreeV2, c1)
+ require.NoError(t, err)
+ c3, err := repo.StoreCommit(rootTreeV3, c2)
+ require.NoError(t, err)
+
+ require.NoError(t, repo.UpdateRef("refs/heads/main", c3))
+ require.NoError(t, repo.UpdateRef("refs/heads/feature", c2))
+ require.NoError(t, repo.UpdateRef("refs/tags/v1.0", c1))
+
+ // ββ Branches ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+ t.Run("Branches", func(t *testing.T) {
+ branches, err := repo.Branches()
+ require.NoError(t, err)
+ require.Len(t, branches, 2)
+
+ byName := make(map[string]BranchInfo)
+ for _, b := range branches {
+ byName[b.Name] = b
+ }
+
+ require.Equal(t, c3, byName["main"].Hash)
+ require.True(t, byName["main"].IsDefault)
+
+ require.Equal(t, c2, byName["feature"].Hash)
+ require.False(t, byName["feature"].IsDefault)
+ })
+
+ // ββ Tags ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+ t.Run("Tags", func(t *testing.T) {
+ tags, err := repo.Tags()
+ require.NoError(t, err)
+ require.Len(t, tags, 1)
+ require.Equal(t, "v1.0", tags[0].Name)
+ require.Equal(t, c1, tags[0].Hash)
+ })
+
+ // ββ TreeAtPath ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+ t.Run("TreeAtPath", func(t *testing.T) {
+ entries, err := repo.TreeAtPath("main", "")
+ require.NoError(t, err)
+ byName := make(map[string]TreeEntry)
+ for _, e := range entries {
+ byName[e.Name] = e
+ }
+ require.Equal(t, Blob, byName["README.md"].ObjectType)
+ require.Equal(t, Blob, byName["main.go"].ObjectType)
+ require.Equal(t, Tree, byName["src"].ObjectType)
+
+ // subdirectory
+ srcEntries, err := repo.TreeAtPath("main", "src")
+ require.NoError(t, err)
+ srcByName := make(map[string]TreeEntry)
+ for _, e := range srcEntries {
+ srcByName[e.Name] = e
+ }
+ require.Equal(t, Blob, srcByName["lib.go"].ObjectType)
+ require.Equal(t, Blob, srcByName["util.go"].ObjectType)
+
+ // v1.0 tag (at c1) predates util.go β src only has lib.go
+ v1Src, err := repo.TreeAtPath("v1.0", "src")
+ require.NoError(t, err)
+ require.Len(t, v1Src, 1)
+ require.Equal(t, "lib.go", v1Src[0].Name)
+
+ // unknown ref
+ _, err = repo.TreeAtPath("nonexistent-ref", "")
+ require.ErrorIs(t, err, ErrNotFound)
+
+ // path resolves to a blob, not a tree
+ _, err = repo.TreeAtPath("main", "README.md")
+ require.Error(t, err)
+ })
+
+ // ββ BlobAtPath ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+ t.Run("BlobAtPath", func(t *testing.T) {
+ rc, size, hash, err := repo.BlobAtPath("main", "README.md")
+ require.NoError(t, err)
+ defer rc.Close()
+ data, err := io.ReadAll(rc)
+ require.NoError(t, err)
+ require.Equal(t, readmeV3, data)
+ require.Equal(t, int64(len(readmeV3)), size)
+ require.NotEmpty(t, hash)
+
+ // feature branch still has readmeV1
+ rc2, _, _, err := repo.BlobAtPath("feature", "README.md")
+ require.NoError(t, err)
+ data2, err := io.ReadAll(rc2)
+ rc2.Close()
+ require.NoError(t, err)
+ require.Equal(t, readmeV1, data2)
+
+ // file in subdirectory
+ rc3, _, _, err := repo.BlobAtPath("main", "src/lib.go")
+ require.NoError(t, err)
+ data3, err := io.ReadAll(rc3)
+ rc3.Close()
+ require.NoError(t, err)
+ require.Equal(t, libV1, data3)
+
+ // path not found
+ _, _, _, err = repo.BlobAtPath("main", "nonexistent.go")
+ require.ErrorIs(t, err, ErrNotFound)
+
+ // hash is stable across calls for the same content
+ rc4, _, hash2, err := repo.BlobAtPath("main", "README.md")
+ require.NoError(t, err)
+ rc4.Close()
+ require.Equal(t, hash, hash2, "blob hash should be stable across calls")
+
+ // different content β different hash
+ rc5, _, hashLib, err := repo.BlobAtPath("main", "src/lib.go")
+ require.NoError(t, err)
+ rc5.Close()
+ require.NotEqual(t, hash, hashLib, "different files should have different hashes")
+ })
+
+ // ββ CommitLog βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+ t.Run("CommitLog", func(t *testing.T) {
+ // all commits, newest first
+ commits, err := repo.CommitLog("main", "", 10, "", nil, nil)
+ require.NoError(t, err)
+ require.Len(t, commits, 3)
+ require.Equal(t, c3, commits[0].Hash)
+ require.Equal(t, c2, commits[1].Hash)
+ require.Equal(t, c1, commits[2].Hash)
+
+ // limit
+ limited, err := repo.CommitLog("main", "", 2, "", nil, nil)
+ require.NoError(t, err)
+ require.Len(t, limited, 2)
+ require.Equal(t, c3, limited[0].Hash)
+ require.Equal(t, c2, limited[1].Hash)
+
+ // after cursor (exclusive): start after c3 β get c2, c1
+ after, err := repo.CommitLog("main", "", 10, c3, nil, nil)
+ require.NoError(t, err)
+ require.Len(t, after, 2)
+ require.Equal(t, c2, after[0].Hash)
+ require.Equal(t, c1, after[1].Hash)
+
+ // feature branch only has c1, c2
+ featureLog, err := repo.CommitLog("feature", "", 10, "", nil, nil)
+ require.NoError(t, err)
+ require.Len(t, featureLog, 2)
+ require.Equal(t, c2, featureLog[0].Hash)
+
+ // path filtering: only commits that touched the given path
+ // README.md was created in c1 and updated in c3
+ readmeLog, err := repo.CommitLog("main", "README.md", 10, "", nil, nil)
+ require.NoError(t, err)
+ require.Len(t, readmeLog, 2)
+ require.Equal(t, c3, readmeLog[0].Hash)
+ require.Equal(t, c1, readmeLog[1].Hash)
+ })
+
+ t.Run("CommitLog/since-until", func(t *testing.T) {
+ // since = far future β no commits
+ future := time.Now().Add(24 * time.Hour)
+ none, err := repo.CommitLog("main", "", 10, "", &future, nil)
+ require.NoError(t, err)
+ require.Empty(t, none, "since=future should return no commits")
+
+ // until = zero time (long before any real commit) β no commits
+ zero := time.Time{}
+ none2, err := repo.CommitLog("main", "", 10, "", nil, &zero)
+ require.NoError(t, err)
+ require.Empty(t, none2, "until=zero should return no commits")
+
+ // Both bounds open β all commits returned (filtering is a no-op)
+ all, err := repo.CommitLog("main", "", 10, "", nil, nil)
+ require.NoError(t, err)
+ require.Len(t, all, 3, "nil since/until should return all commits")
+
+ // since = far past and until = far future β all commits still returned
+ past := time.Unix(0, 0)
+ all2, err := repo.CommitLog("main", "", 10, "", &past, &future)
+ require.NoError(t, err)
+ require.Len(t, all2, 3, "wide since/until bounds should return all commits")
+ })
+
+ // ββ LastCommitForEntries ββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+ t.Run("LastCommitForEntries", func(t *testing.T) {
+ result, err := repo.LastCommitForEntries("main", "", []string{"README.md", "main.go", "src"})
+ require.NoError(t, err)
+
+ // README.md was last changed in c3
+ require.Equal(t, c3, result["README.md"].Hash)
+ // main.go was last changed in c2
+ require.Equal(t, c2, result["main.go"].Hash)
+ // src tree changed in c2 (util.go added)
+ require.Equal(t, c2, result["src"].Hash)
+
+ // subdirectory: last commits for entries in src/
+ srcResult, err := repo.LastCommitForEntries("main", "src", []string{"lib.go", "util.go"})
+ require.NoError(t, err)
+ // lib.go was added in c1 and never changed
+ require.Equal(t, c1, srcResult["lib.go"].Hash)
+ // util.go was added in c2
+ require.Equal(t, c2, srcResult["util.go"].Hash)
+
+ // requesting a name that doesn't exist returns no entry for it
+ partial, err := repo.LastCommitForEntries("main", "", []string{"README.md", "ghost.txt"})
+ require.NoError(t, err)
+ require.Contains(t, partial, "README.md")
+ require.NotContains(t, partial, "ghost.txt")
+ })
+
+ t.Run("LastCommitForEntries/cache-subset", func(t *testing.T) {
+ // First call with one name β seeds (or hits) the cache for this directory.
+ r1, err := repo.LastCommitForEntries("main", "", []string{"README.md"})
+ require.NoError(t, err)
+ require.Contains(t, r1, "README.md")
+ require.Equal(t, c3, r1["README.md"].Hash)
+
+ // Second call for the same directory but a different name.
+ // A buggy implementation that caches only the requested subset would
+ // return an empty map here (cache hit, but "main.go" was never stored).
+ r2, err := repo.LastCommitForEntries("main", "", []string{"main.go"})
+ require.NoError(t, err)
+ require.Contains(t, r2, "main.go", "second call with different name should hit correct result, not empty cache")
+ require.Equal(t, c2, r2["main.go"].Hash)
+
+ // Third call requesting both names should also work.
+ r3, err := repo.LastCommitForEntries("main", "", []string{"README.md", "main.go"})
+ require.NoError(t, err)
+ require.Equal(t, c3, r3["README.md"].Hash)
+ require.Equal(t, c2, r3["main.go"].Hash)
+ })
+
+ // ββ CommitDetail ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+ t.Run("CommitDetail", func(t *testing.T) {
+ detail, err := repo.CommitDetail(c2)
+ require.NoError(t, err)
+ require.Equal(t, c2, detail.Hash)
+ require.Equal(t, []Hash{c1}, detail.Parents)
+
+ filesByPath := make(map[string]ChangedFile)
+ for _, f := range detail.Files {
+ filesByPath[f.Path] = f
+ }
+ require.Equal(t, ChangeStatusModified, filesByPath["main.go"].Status)
+ require.Equal(t, ChangeStatusAdded, filesByPath["src/util.go"].Status)
+
+ // initial commit: diffs against empty tree, everything is "added"
+ initDetail, err := repo.CommitDetail(c1)
+ require.NoError(t, err)
+ for _, f := range initDetail.Files {
+ require.Equal(t, ChangeStatusAdded, f.Status, "file %s", f.Path)
+ }
+
+ // unknown hash
+ _, err = repo.CommitDetail(randomHash())
+ require.ErrorIs(t, err, ErrNotFound)
+ })
+
+ // ββ CommitFileDiff ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+ t.Run("CommitFileDiff", func(t *testing.T) {
+ fd, err := repo.CommitFileDiff(c2, "main.go")
+ require.NoError(t, err)
+ require.Equal(t, "main.go", fd.Path)
+ require.False(t, fd.IsBinary)
+ require.False(t, fd.IsNew)
+ require.False(t, fd.IsDelete)
+ require.NotEmpty(t, fd.Hunks)
+
+ // find the added lines
+ var addedContent []string
+ for _, h := range fd.Hunks {
+ for _, l := range h.Lines {
+ if l.Type == DiffLineAdded {
+ addedContent = append(addedContent, l.Content)
+ }
+ }
+ }
+ require.Contains(t, addedContent, "// updated")
+
+ // new file in initial commit
+ initFD, err := repo.CommitFileDiff(c1, "main.go")
+ require.NoError(t, err)
+ require.True(t, initFD.IsNew)
+ require.Equal(t, "main.go", initFD.Path)
+
+ // file not in this commit's diff
+ _, err = repo.CommitFileDiff(c3, "main.go")
+ require.ErrorIs(t, err, ErrNotFound)
+
+ // unknown hash
+ _, err = repo.CommitFileDiff(randomHash(), "main.go")
+ require.ErrorIs(t, err, ErrNotFound)
+ })
+}
@@ -3,6 +3,8 @@ package repository
import (
"bytes"
"fmt"
+ "io"
+ "strconv"
"strings"
)
@@ -15,9 +17,12 @@ type TreeEntry struct {
type ObjectType int
const (
- Unknown ObjectType = iota
- Blob
- Tree
+ Unknown ObjectType = iota
+ Blob // regular file (100644)
+ Tree // directory (040000)
+ Executable // executable file (100755)
+ Symlink // symbolic link (120000)
+ Submodule // git submodule (160000)
)
func ParseTreeEntry(line string) (TreeEntry, error) {
@@ -54,17 +59,64 @@ func (ot ObjectType) Format() string {
return "100644 blob"
case Tree:
return "040000 tree"
+ case Executable:
+ return "100755 blob"
+ case Symlink:
+ return "120000 blob"
+ case Submodule:
+ return "160000 commit"
default:
panic("Unknown git object type")
}
}
+func (ot ObjectType) MarshalGQL(w io.Writer) {
+ switch ot {
+ case Tree:
+ fmt.Fprint(w, strconv.Quote("TREE"))
+ case Blob, Executable:
+ fmt.Fprint(w, strconv.Quote("BLOB"))
+ case Symlink:
+ fmt.Fprint(w, strconv.Quote("SYMLINK"))
+ case Submodule:
+ fmt.Fprint(w, strconv.Quote("SUBMODULE"))
+ default:
+ panic(fmt.Sprintf("unknown ObjectType value %d", int(ot)))
+ }
+}
+
+func (ot *ObjectType) UnmarshalGQL(v any) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+ switch str {
+ case "TREE":
+ *ot = Tree
+ case "BLOB":
+ *ot = Blob
+ case "SYMLINK":
+ *ot = Symlink
+ case "SUBMODULE":
+ *ot = Submodule
+ default:
+ return fmt.Errorf("%q is not a valid ObjectType", str)
+ }
+ return nil
+}
+
func ParseObjectType(mode, objType string) (ObjectType, error) {
switch {
case mode == "100644" && objType == "blob":
return Blob, nil
case mode == "040000" && objType == "tree":
return Tree, nil
+ case mode == "100755" && objType == "blob":
+ return Executable, nil
+ case mode == "120000" && objType == "blob":
+ return Symlink, nil
+ case mode == "160000" && objType == "commit":
+ return Submodule, nil
default:
return Unknown, fmt.Errorf("Unknown git object type %s %s", mode, objType)
}