From bdbe9e7e8256fff820efe1ce707e7154d517ecb3 Mon Sep 17 00:00:00 2001 From: Michael Muré Date: Thu, 17 Jan 2019 03:09:08 +0100 Subject: identity: more progress and fixes --- bridge/github/import.go | 23 ++-- bridge/launchpad/launchpad.go | 2 +- cache/bug_excerpt.go | 2 +- cache/repo_cache.go | 70 ++++++++++++ commands/id.go | 18 +++- graphql/gqlgen.yml | 2 +- graphql/graph/gen_graph.go | 244 +++++++++++++++++------------------------- repository/repo.go | 2 +- termui/bug_table.go | 10 +- 9 files changed, 206 insertions(+), 167 deletions(-) diff --git a/bridge/github/import.go b/bridge/github/import.go index 93390408..de125793 100644 --- a/bridge/github/import.go +++ b/bridge/github/import.go @@ -8,18 +8,20 @@ import ( "github.com/MichaelMure/git-bug/bridge/core" "github.com/MichaelMure/git-bug/bug" "github.com/MichaelMure/git-bug/cache" + "github.com/MichaelMure/git-bug/identity" "github.com/MichaelMure/git-bug/util/git" "github.com/shurcooL/githubv4" ) const keyGithubId = "github-id" const keyGithubUrl = "github-url" +const keyGithubLogin = "github-login" // githubImporter implement the Importer interface type githubImporter struct { client *githubv4.Client conf core.Configuration - ghost bug.Person + ghost identity.Interface } func (gi *githubImporter) Init(conf core.Configuration) error { @@ -69,7 +71,10 @@ func (gi *githubImporter) ImportAll(repo *cache.RepoCache) error { } for _, itemEdge := range q.Repository.Issues.Nodes[0].Timeline.Edges { - gi.ensureTimelineItem(b, itemEdge.Cursor, itemEdge.Node, variables) + err = gi.ensureTimelineItem(b, itemEdge.Cursor, itemEdge.Node, variables) + if err != nil { + return err + } } if !issue.Timeline.PageInfo.HasNextPage { @@ -561,7 +566,7 @@ func (gi *githubImporter) ensureCommentEdit(b *cache.BugCache, target git.Hash, } // makePerson create a bug.Person from the Github data -func (gi *githubImporter) makePerson(actor *actor) bug.Person { +func (gi *githubImporter) makePerson(actor *actor) identity.Interface { if actor == nil { return gi.ghost } @@ -609,12 +614,12 @@ func (gi *githubImporter) fetchGhost() error { name = string(*q.User.Name) } - gi.ghost = bug.Person{ - Name: name, - Login: string(q.User.Login), - AvatarUrl: string(q.User.AvatarUrl), - Email: string(q.User.Email), - } + gi.ghost = identity.NewIdentityFull( + name, + string(q.User.Login), + string(q.User.AvatarUrl), + string(q.User.Email), + ) return nil } diff --git a/bridge/launchpad/launchpad.go b/bridge/launchpad/launchpad.go index f862f24e..1fd9edc2 100644 --- a/bridge/launchpad/launchpad.go +++ b/bridge/launchpad/launchpad.go @@ -1,4 +1,4 @@ -// Package launchad contains the Launchpad bridge implementation +// Package launchpad contains the Launchpad bridge implementation package launchpad import ( diff --git a/cache/bug_excerpt.go b/cache/bug_excerpt.go index 77c18175..f5844b64 100644 --- a/cache/bug_excerpt.go +++ b/cache/bug_excerpt.go @@ -20,7 +20,7 @@ type BugExcerpt struct { EditUnixTime int64 Status bug.Status - Author *identity.Identity + Author identity.Interface Labels []bug.Label CreateMetadata map[string]string diff --git a/cache/repo_cache.go b/cache/repo_cache.go index a149fd73..7d3e7d1d 100644 --- a/cache/repo_cache.go +++ b/cache/repo_cache.go @@ -30,6 +30,8 @@ type RepoCache struct { excerpts map[string]*BugExcerpt // bug loaded in memory bugs map[string]*BugCache + // identities loaded in memory + identities map[string]*identity.Identity } func NewRepoCache(r repository.ClockedRepo) (*RepoCache, error) { @@ -279,6 +281,7 @@ func (c *RepoCache) ResolveBugCreateMetadata(key string, value string) (*BugCach return c.ResolveBug(matching[0]) } +// QueryBugs return the id of all Bug matching the given Query func (c *RepoCache) QueryBugs(query *Query) []string { if query == nil { return c.AllBugsIds() @@ -525,3 +528,70 @@ func repoIsAvailable(repo repository.Repo) error { return nil } + +// ResolveIdentity retrieve an identity matching the exact given id +func (c *RepoCache) ResolveIdentity(id string) (*identity.Identity, error) { + cached, ok := c.identities[id] + if ok { + return cached, nil + } + + i, err := identity.Read(c.repo, id) + if err != nil { + return nil, err + } + + c.identities[id] = i + + return i, nil +} + +// ResolveIdentityPrefix retrieve an Identity matching an id prefix. It fails if multiple +// bugs match. +// func (c *RepoCache) ResolveIdentityPrefix(prefix string) (*BugCache, error) { +// // preallocate but empty +// matching := make([]string, 0, 5) +// +// for id := range c.excerpts { +// if strings.HasPrefix(id, prefix) { +// matching = append(matching, id) +// } +// } +// +// if len(matching) > 1 { +// return nil, bug.ErrMultipleMatch{Matching: matching} +// } +// +// if len(matching) == 0 { +// return nil, bug.ErrBugNotExist +// } +// +// return c.ResolveBug(matching[0]) +// } + +// ResolveIdentityImmutableMetadata retrieve an Identity that has the exact given metadata on +// one of it's version. If multiple version have the same key, the first defined take precedence. +func (c *RepoCache) ResolveIdentityImmutableMetadata(key string, value string) (*BugCache, error) { + // // preallocate but empty + // matching := make([]string, 0, 5) + // + // for id, excerpt := range c.excerpts { + // if excerpt.CreateMetadata[key] == value { + // matching = append(matching, id) + // } + // } + // + // if len(matching) > 1 { + // return nil, bug.ErrMultipleMatch{Matching: matching} + // } + // + // if len(matching) == 0 { + // return nil, bug.ErrBugNotExist + // } + // + // return c.ResolveBug(matching[0]) + + // TODO + + return nil, nil +} diff --git a/commands/id.go b/commands/id.go index 485c5457..44294132 100644 --- a/commands/id.go +++ b/commands/id.go @@ -1,6 +1,7 @@ package commands import ( + "errors" "fmt" "github.com/MichaelMure/git-bug/identity" @@ -8,7 +9,19 @@ import ( ) func runId(cmd *cobra.Command, args []string) error { - id, err := identity.GetIdentity(repo) + if len(args) > 1 { + return errors.New("only one identity can be displayed at a time") + } + + var id *identity.Identity + var err error + + if len(args) == 1 { + id, err = identity.Read(repo, args[0]) + } else { + id, err = identity.GetIdentity(repo) + } + if err != nil { return err } @@ -24,7 +37,7 @@ func runId(cmd *cobra.Command, args []string) error { } var idCmd = &cobra.Command{ - Use: "id", + Use: "id []", Short: "Display or change the user identity", PreRunE: loadRepo, RunE: runId, @@ -32,4 +45,5 @@ var idCmd = &cobra.Command{ func init() { RootCmd.AddCommand(idCmd) + selectCmd.Flags().SortFlags = false } diff --git a/graphql/gqlgen.yml b/graphql/gqlgen.yml index 019f3444..0e389a53 100644 --- a/graphql/gqlgen.yml +++ b/graphql/gqlgen.yml @@ -14,7 +14,7 @@ models: Comment: model: github.com/MichaelMure/git-bug/bug.Comment Identity: - model: github.com/MichaelMure/git-bug/identity.Identity + model: github.com/MichaelMure/git-bug/identity.Interface Label: model: github.com/MichaelMure/git-bug/bug.Label Hash: diff --git a/graphql/graph/gen_graph.go b/graphql/graph/gen_graph.go index cc714ecc..fa8e4acb 100644 --- a/graphql/graph/gen_graph.go +++ b/graphql/graph/gen_graph.go @@ -44,6 +44,7 @@ type ResolverRoot interface { CreateOperation() CreateOperationResolver CreateTimelineItem() CreateTimelineItemResolver EditCommentOperation() EditCommentOperationResolver + Identity() IdentityResolver LabelChangeOperation() LabelChangeOperationResolver LabelChangeTimelineItem() LabelChangeTimelineItemResolver Mutation() MutationResolver @@ -292,6 +293,13 @@ type CreateTimelineItemResolver interface { type EditCommentOperationResolver interface { Date(ctx context.Context, obj *bug.EditCommentOperation) (time.Time, error) } +type IdentityResolver interface { + Name(ctx context.Context, obj *identity.Interface) (*string, error) + Email(ctx context.Context, obj *identity.Interface) (*string, error) + Login(ctx context.Context, obj *identity.Interface) (*string, error) + DisplayName(ctx context.Context, obj *identity.Interface) (string, error) + AvatarURL(ctx context.Context, obj *identity.Interface) (*string, error) +} type LabelChangeOperationResolver interface { Date(ctx context.Context, obj *bug.LabelChangeOperation) (time.Time, error) } @@ -2065,18 +2073,11 @@ func (ec *executionContext) _AddCommentOperation_author(ctx context.Context, fie } return graphql.Null } - res := resTmp.(*identity.Identity) + res := resTmp.(identity.Interface) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - if res == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - - return ec._Identity(ctx, field.Selections, res) + return ec._Identity(ctx, field.Selections, &res) } // nolint: vetshadow @@ -2296,18 +2297,11 @@ func (ec *executionContext) _AddCommentTimelineItem_author(ctx context.Context, } return graphql.Null } - res := resTmp.(*identity.Identity) + res := resTmp.(identity.Interface) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - if res == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - - return ec._Identity(ctx, field.Selections, res) + return ec._Identity(ctx, field.Selections, &res) } // nolint: vetshadow @@ -2807,18 +2801,11 @@ func (ec *executionContext) _Bug_author(ctx context.Context, field graphql.Colle } return graphql.Null } - res := resTmp.(*identity.Identity) + res := resTmp.(identity.Interface) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - if res == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - - return ec._Identity(ctx, field.Selections, res) + return ec._Identity(ctx, field.Selections, &res) } // nolint: vetshadow @@ -3348,18 +3335,11 @@ func (ec *executionContext) _Comment_author(ctx context.Context, field graphql.C } return graphql.Null } - res := resTmp.(*identity.Identity) + res := resTmp.(identity.Interface) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - if res == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - - return ec._Identity(ctx, field.Selections, res) + return ec._Identity(ctx, field.Selections, &res) } // nolint: vetshadow @@ -3937,18 +3917,11 @@ func (ec *executionContext) _CreateOperation_author(ctx context.Context, field g } return graphql.Null } - res := resTmp.(*identity.Identity) + res := resTmp.(identity.Interface) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - if res == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - - return ec._Identity(ctx, field.Selections, res) + return ec._Identity(ctx, field.Selections, &res) } // nolint: vetshadow @@ -4195,18 +4168,11 @@ func (ec *executionContext) _CreateTimelineItem_author(ctx context.Context, fiel } return graphql.Null } - res := resTmp.(*identity.Identity) + res := resTmp.(identity.Interface) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - if res == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - - return ec._Identity(ctx, field.Selections, res) + return ec._Identity(ctx, field.Selections, &res) } // nolint: vetshadow @@ -4548,18 +4514,11 @@ func (ec *executionContext) _EditCommentOperation_author(ctx context.Context, fi } return graphql.Null } - res := resTmp.(*identity.Identity) + res := resTmp.(identity.Interface) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - if res == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - - return ec._Identity(ctx, field.Selections, res) + return ec._Identity(ctx, field.Selections, &res) } // nolint: vetshadow @@ -4682,9 +4641,10 @@ func (ec *executionContext) _EditCommentOperation_files(ctx context.Context, fie var identityImplementors = []string{"Identity"} // nolint: gocyclo, errcheck, gas, goconst -func (ec *executionContext) _Identity(ctx context.Context, sel ast.SelectionSet, obj *identity.Identity) graphql.Marshaler { +func (ec *executionContext) _Identity(ctx context.Context, sel ast.SelectionSet, obj *identity.Interface) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, identityImplementors) + var wg sync.WaitGroup out := graphql.NewOrderedMap(len(fields)) invalid := false for i, field := range fields { @@ -4694,23 +4654,43 @@ func (ec *executionContext) _Identity(ctx context.Context, sel ast.SelectionSet, case "__typename": out.Values[i] = graphql.MarshalString("Identity") case "name": - out.Values[i] = ec._Identity_name(ctx, field, obj) + wg.Add(1) + go func(i int, field graphql.CollectedField) { + out.Values[i] = ec._Identity_name(ctx, field, obj) + wg.Done() + }(i, field) case "email": - out.Values[i] = ec._Identity_email(ctx, field, obj) + wg.Add(1) + go func(i int, field graphql.CollectedField) { + out.Values[i] = ec._Identity_email(ctx, field, obj) + wg.Done() + }(i, field) case "login": - out.Values[i] = ec._Identity_login(ctx, field, obj) + wg.Add(1) + go func(i int, field graphql.CollectedField) { + out.Values[i] = ec._Identity_login(ctx, field, obj) + wg.Done() + }(i, field) case "displayName": - out.Values[i] = ec._Identity_displayName(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalid = true - } + wg.Add(1) + go func(i int, field graphql.CollectedField) { + out.Values[i] = ec._Identity_displayName(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalid = true + } + wg.Done() + }(i, field) case "avatarUrl": - out.Values[i] = ec._Identity_avatarUrl(ctx, field, obj) + wg.Add(1) + go func(i int, field graphql.CollectedField) { + out.Values[i] = ec._Identity_avatarUrl(ctx, field, obj) + wg.Done() + }(i, field) default: panic("unknown field " + strconv.Quote(field.Name)) } } - + wg.Wait() if invalid { return graphql.Null } @@ -4718,7 +4698,7 @@ func (ec *executionContext) _Identity(ctx context.Context, sel ast.SelectionSet, } // nolint: vetshadow -func (ec *executionContext) _Identity_name(ctx context.Context, field graphql.CollectedField, obj *identity.Identity) graphql.Marshaler { +func (ec *executionContext) _Identity_name(ctx context.Context, field graphql.CollectedField, obj *identity.Interface) graphql.Marshaler { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { ec.Tracer.EndFieldExecution(ctx) }() rctx := &graphql.ResolverContext{ @@ -4730,19 +4710,23 @@ func (ec *executionContext) _Identity_name(ctx context.Context, field graphql.Co ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Name(), nil + return ec.resolvers.Identity().Name(rctx, obj) }) if resTmp == nil { return graphql.Null } - res := resTmp.(string) + res := resTmp.(*string) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - return graphql.MarshalString(res) + + if res == nil { + return graphql.Null + } + return graphql.MarshalString(*res) } // nolint: vetshadow -func (ec *executionContext) _Identity_email(ctx context.Context, field graphql.CollectedField, obj *identity.Identity) graphql.Marshaler { +func (ec *executionContext) _Identity_email(ctx context.Context, field graphql.CollectedField, obj *identity.Interface) graphql.Marshaler { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { ec.Tracer.EndFieldExecution(ctx) }() rctx := &graphql.ResolverContext{ @@ -4754,19 +4738,23 @@ func (ec *executionContext) _Identity_email(ctx context.Context, field graphql.C ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Email(), nil + return ec.resolvers.Identity().Email(rctx, obj) }) if resTmp == nil { return graphql.Null } - res := resTmp.(string) + res := resTmp.(*string) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - return graphql.MarshalString(res) + + if res == nil { + return graphql.Null + } + return graphql.MarshalString(*res) } // nolint: vetshadow -func (ec *executionContext) _Identity_login(ctx context.Context, field graphql.CollectedField, obj *identity.Identity) graphql.Marshaler { +func (ec *executionContext) _Identity_login(ctx context.Context, field graphql.CollectedField, obj *identity.Interface) graphql.Marshaler { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { ec.Tracer.EndFieldExecution(ctx) }() rctx := &graphql.ResolverContext{ @@ -4778,19 +4766,23 @@ func (ec *executionContext) _Identity_login(ctx context.Context, field graphql.C ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Login(), nil + return ec.resolvers.Identity().Login(rctx, obj) }) if resTmp == nil { return graphql.Null } - res := resTmp.(string) + res := resTmp.(*string) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - return graphql.MarshalString(res) + + if res == nil { + return graphql.Null + } + return graphql.MarshalString(*res) } // nolint: vetshadow -func (ec *executionContext) _Identity_displayName(ctx context.Context, field graphql.CollectedField, obj *identity.Identity) graphql.Marshaler { +func (ec *executionContext) _Identity_displayName(ctx context.Context, field graphql.CollectedField, obj *identity.Interface) graphql.Marshaler { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { ec.Tracer.EndFieldExecution(ctx) }() rctx := &graphql.ResolverContext{ @@ -4802,7 +4794,7 @@ func (ec *executionContext) _Identity_displayName(ctx context.Context, field gra ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.DisplayName(), nil + return ec.resolvers.Identity().DisplayName(rctx, obj) }) if resTmp == nil { if !ec.HasError(rctx) { @@ -4817,7 +4809,7 @@ func (ec *executionContext) _Identity_displayName(ctx context.Context, field gra } // nolint: vetshadow -func (ec *executionContext) _Identity_avatarUrl(ctx context.Context, field graphql.CollectedField, obj *identity.Identity) graphql.Marshaler { +func (ec *executionContext) _Identity_avatarUrl(ctx context.Context, field graphql.CollectedField, obj *identity.Interface) graphql.Marshaler { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { ec.Tracer.EndFieldExecution(ctx) }() rctx := &graphql.ResolverContext{ @@ -4829,15 +4821,19 @@ func (ec *executionContext) _Identity_avatarUrl(ctx context.Context, field graph ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.AvatarURL(), nil + return ec.resolvers.Identity().AvatarURL(rctx, obj) }) if resTmp == nil { return graphql.Null } - res := resTmp.(string) + res := resTmp.(*string) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - return graphql.MarshalString(res) + + if res == nil { + return graphql.Null + } + return graphql.MarshalString(*res) } var labelChangeOperationImplementors = []string{"LabelChangeOperation", "Operation", "Authored"} @@ -4943,18 +4939,11 @@ func (ec *executionContext) _LabelChangeOperation_author(ctx context.Context, fi } return graphql.Null } - res := resTmp.(*identity.Identity) + res := resTmp.(identity.Interface) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - if res == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - - return ec._Identity(ctx, field.Selections, res) + return ec._Identity(ctx, field.Selections, &res) } // nolint: vetshadow @@ -5159,18 +5148,11 @@ func (ec *executionContext) _LabelChangeTimelineItem_author(ctx context.Context, } return graphql.Null } - res := resTmp.(*identity.Identity) + res := resTmp.(identity.Interface) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - if res == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - - return ec._Identity(ctx, field.Selections, res) + return ec._Identity(ctx, field.Selections, &res) } // nolint: vetshadow @@ -6423,18 +6405,11 @@ func (ec *executionContext) _SetStatusOperation_author(ctx context.Context, fiel } return graphql.Null } - res := resTmp.(*identity.Identity) + res := resTmp.(identity.Interface) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - if res == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - - return ec._Identity(ctx, field.Selections, res) + return ec._Identity(ctx, field.Selections, &res) } // nolint: vetshadow @@ -6593,18 +6568,11 @@ func (ec *executionContext) _SetStatusTimelineItem_author(ctx context.Context, f } return graphql.Null } - res := resTmp.(*identity.Identity) + res := resTmp.(identity.Interface) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - if res == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - - return ec._Identity(ctx, field.Selections, res) + return ec._Identity(ctx, field.Selections, &res) } // nolint: vetshadow @@ -6764,18 +6732,11 @@ func (ec *executionContext) _SetTitleOperation_author(ctx context.Context, field } return graphql.Null } - res := resTmp.(*identity.Identity) + res := resTmp.(identity.Interface) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - if res == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - - return ec._Identity(ctx, field.Selections, res) + return ec._Identity(ctx, field.Selections, &res) } // nolint: vetshadow @@ -6962,18 +6923,11 @@ func (ec *executionContext) _SetTitleTimelineItem_author(ctx context.Context, fi } return graphql.Null } - res := resTmp.(*identity.Identity) + res := resTmp.(identity.Interface) rctx.Result = res ctx = ec.Tracer.StartFieldChildExecution(ctx) - if res == nil { - if !ec.HasError(rctx) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - - return ec._Identity(ctx, field.Selections, res) + return ec._Identity(ctx, field.Selections, &res) } // nolint: vetshadow diff --git a/repository/repo.go b/repository/repo.go index 3ae09057..100feaed 100644 --- a/repository/repo.go +++ b/repository/repo.go @@ -122,7 +122,7 @@ func prepareTreeEntries(entries []TreeEntry) bytes.Buffer { } func readTreeEntries(s string) ([]TreeEntry, error) { - split := strings.Split(s, "\n") + split := strings.Split(strings.TrimSpace(s), "\n") casted := make([]TreeEntry, len(split)) for i, line := range split { diff --git a/termui/bug_table.go b/termui/bug_table.go index ba946c86..69634151 100644 --- a/termui/bug_table.go +++ b/termui/bug_table.go @@ -6,7 +6,6 @@ import ( "github.com/MichaelMure/git-bug/bug" "github.com/MichaelMure/git-bug/cache" - "github.com/MichaelMure/git-bug/identity" "github.com/MichaelMure/git-bug/util/colors" "github.com/MichaelMure/git-bug/util/text" "github.com/MichaelMure/gocui" @@ -290,12 +289,9 @@ func (bt *bugTable) render(v *gocui.View, maxX int) { columnWidths := bt.getColumnWidths(maxX) for _, b := range bt.bugs { - person := &identity.Identity{} snap := b.Snapshot() - if len(snap.Comments) > 0 { - create := snap.Comments[0] - person = create.Author - } + create := snap.Comments[0] + authorIdentity := create.Author summaryTxt := fmt.Sprintf("C:%-2d L:%-2d", len(snap.Comments)-1, @@ -305,7 +301,7 @@ func (bt *bugTable) render(v *gocui.View, maxX int) { id := text.LeftPadMaxLine(snap.HumanId(), columnWidths["id"], 1) status := text.LeftPadMaxLine(snap.Status.String(), columnWidths["status"], 1) title := text.LeftPadMaxLine(snap.Title, columnWidths["title"], 1) - author := text.LeftPadMaxLine(person.DisplayName(), columnWidths["author"], 1) + author := text.LeftPadMaxLine(authorIdentity.DisplayName(), columnWidths["author"], 1) summary := text.LeftPadMaxLine(summaryTxt, columnWidths["summary"], 1) lastEdit := text.LeftPadMaxLine(humanize.Time(snap.LastEditTime()), columnWidths["lastEdit"], 1) -- cgit