aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bridge/core/auth/credential.go6
-rw-r--r--bridge/core/auth/credential_test.go2
-rw-r--r--bridge/core/auth/options.go2
-rw-r--r--bridge/core/auth/token.go13
-rw-r--r--bridge/core/config.go42
-rw-r--r--bridge/github/config.go37
-rw-r--r--bridge/github/export.go41
-rw-r--r--bridge/github/export_test.go2
-rw-r--r--bridge/github/import.go2
-rw-r--r--bridge/launchpad/import.go1
-rw-r--r--bug/status.go2
-rw-r--r--cache/bug_excerpt.go18
-rw-r--r--cache/filter.go3
-rw-r--r--cache/identity_cache.go2
-rw-r--r--cache/identity_excerpt.go17
-rw-r--r--cache/query.go4
-rw-r--r--cache/repo_cache.go31
-rw-r--r--graphql/graph/gen_graph.go126
-rw-r--r--graphql/resolvers/identity.go4
-rw-r--r--graphql/schema/identity.graphql4
-rw-r--r--graphql/schema/root.graphql2
-rw-r--r--identity/bare.go8
-rw-r--r--identity/identity.go18
-rw-r--r--identity/identity_actions_test.go8
-rw-r--r--identity/identity_stub.go4
-rw-r--r--identity/identity_test.go45
-rw-r--r--identity/interface.go4
-rw-r--r--identity/key.go5
-rw-r--r--identity/version.go12
-rw-r--r--identity/version_test.go3
30 files changed, 313 insertions, 155 deletions
diff --git a/bridge/core/auth/credential.go b/bridge/core/auth/credential.go
index e843ede7..c1255aa6 100644
--- a/bridge/core/auth/credential.go
+++ b/bridge/core/auth/credential.go
@@ -40,7 +40,10 @@ type Credential interface {
Kind() CredentialKind
CreateTime() time.Time
Validate() error
+
Metadata() map[string]string
+ GetMetadata(key string) (string, bool)
+ SetMetadata(key string, value string)
// Return all the specific properties of the credential that need to be saved into the configuration.
// This does not include Target, Kind, CreateTime and Metadata.
@@ -124,6 +127,9 @@ func metaFromConfig(configs map[string]string) map[string]string {
result[key] = val
}
}
+ if len(result) == 0 {
+ return nil
+ }
return result
}
diff --git a/bridge/core/auth/credential_test.go b/bridge/core/auth/credential_test.go
index 49c138cf..2f8806c9 100644
--- a/bridge/core/auth/credential_test.go
+++ b/bridge/core/auth/credential_test.go
@@ -63,7 +63,7 @@ func TestCredential(t *testing.T) {
// Metadata
- token4.Metadata()["key"] = "value"
+ token4.SetMetadata("key", "value")
err = Store(repo, token4)
assert.NoError(t, err)
diff --git a/bridge/core/auth/options.go b/bridge/core/auth/options.go
index 0c780dc1..74189874 100644
--- a/bridge/core/auth/options.go
+++ b/bridge/core/auth/options.go
@@ -26,7 +26,7 @@ func (opts *options) Match(cred Credential) bool {
}
for key, val := range opts.meta {
- if v, ok := cred.Metadata()[key]; !ok || v != val {
+ if v, ok := cred.GetMetadata(key); !ok || v != val {
return false
}
}
diff --git a/bridge/core/auth/token.go b/bridge/core/auth/token.go
index 60137cd9..42f960bf 100644
--- a/bridge/core/auth/token.go
+++ b/bridge/core/auth/token.go
@@ -30,7 +30,6 @@ func NewToken(value, target string) *Token {
target: target,
createTime: time.Now(),
Value: value,
- meta: make(map[string]string),
}
}
@@ -88,6 +87,18 @@ func (t *Token) Metadata() map[string]string {
return t.meta
}
+func (t *Token) GetMetadata(key string) (string, bool) {
+ val, ok := t.meta[key]
+ return val, ok
+}
+
+func (t *Token) SetMetadata(key string, value string) {
+ if t.meta == nil {
+ t.meta = make(map[string]string)
+ }
+ t.meta[key] = value
+}
+
func (t *Token) toConfig() map[string]string {
return map[string]string{
tokenValueKey: t.Value,
diff --git a/bridge/core/config.go b/bridge/core/config.go
index 9a8bc959..adee5f08 100644
--- a/bridge/core/config.go
+++ b/bridge/core/config.go
@@ -1 +1,43 @@
package core
+
+import (
+ "github.com/MichaelMure/git-bug/cache"
+ "github.com/MichaelMure/git-bug/identity"
+)
+
+func FinishConfig(repo *cache.RepoCache, metaKey string, login string) error {
+ // if no user exist with the given login metadata
+ _, err := repo.ResolveIdentityImmutableMetadata(metaKey, login)
+ if err != nil && err != identity.ErrIdentityNotExist {
+ // real error
+ return err
+ }
+ if err == nil {
+ // found an already valid user, all good
+ return nil
+ }
+
+ // if a default user exist, tag it with the login
+ user, err := repo.GetUserIdentity()
+ if err != nil && err != identity.ErrIdentityNotExist {
+ // real error
+ return err
+ }
+ if err == nil {
+ // found one
+ user.SetMetadata(metaKey, login)
+ return user.CommitAsNeeded()
+ }
+
+ // otherwise create a user with that metadata
+ i, err := repo.NewIdentityFromGitUserRaw(map[string]string{
+ metaKey: login,
+ })
+
+ err = repo.SetUserIdentity(i)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/bridge/github/config.go b/bridge/github/config.go
index 40653afa..9ede72d4 100644
--- a/bridge/github/config.go
+++ b/bridge/github/config.go
@@ -22,7 +22,6 @@ import (
"github.com/MichaelMure/git-bug/bridge/core"
"github.com/MichaelMure/git-bug/bridge/core/auth"
"github.com/MichaelMure/git-bug/cache"
- "github.com/MichaelMure/git-bug/identity"
"github.com/MichaelMure/git-bug/input"
"github.com/MichaelMure/git-bug/repository"
"github.com/MichaelMure/git-bug/util/colors"
@@ -109,7 +108,7 @@ func (g *Github) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
}
case params.TokenRaw != "":
cred = auth.NewToken(params.TokenRaw, target)
- cred.Metadata()[auth.MetaKeyLogin] = login
+ cred.SetMetadata(auth.MetaKeyLogin, login)
default:
cred, err = promptTokenOptions(repo, login, owner, project)
if err != nil {
@@ -140,34 +139,6 @@ func (g *Github) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
return nil, err
}
- // TODO
- func(login string) error {
- // if no user exist with the given login
- _, err := repo.ResolveIdentityLogin(login)
- if err != nil && err != identity.ErrIdentityNotExist {
- return err
- }
-
- // tag the default user with the github login, if any
- user, err := repo.GetUserIdentity()
- if err == identity.ErrNoIdentitySet {
- return nil
- }
- if err != nil {
- return err
- }
-
- userLogin, ok := user.ImmutableMetadata()[metaKeyGithubLogin]
- if !ok {
- user.SetMetadata()
- }
-
- }(login)
-
- // Todo: if no user exist with the given login
- // - tag the default user with the github login
- // - add a command to manually tag a user ?
-
// don't forget to store the now known valid token
if !auth.IdExist(repo, cred.ID()) {
err = auth.Store(repo, cred)
@@ -176,7 +147,7 @@ func (g *Github) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
}
}
- return conf, nil
+ return conf, core.FinishConfig(repo, metaKeyGithubLogin, login)
}
func (*Github) ValidateConfig(conf core.Configuration) error {
@@ -318,7 +289,7 @@ func promptTokenOptions(repo repository.RepoConfig, login, owner, project string
return nil, err
}
token := auth.NewToken(value, target)
- token.Metadata()[auth.MetaKeyLogin] = login
+ token.SetMetadata(auth.MetaKeyLogin, login)
return token, nil
case 2:
value, err := loginAndRequestToken(login, owner, project)
@@ -326,7 +297,7 @@ func promptTokenOptions(repo repository.RepoConfig, login, owner, project string
return nil, err
}
token := auth.NewToken(value, target)
- token.Metadata()[auth.MetaKeyLogin] = login
+ token.SetMetadata(auth.MetaKeyLogin, login)
return token, nil
default:
return creds[index-3], nil
diff --git a/bridge/github/export.go b/bridge/github/export.go
index 1cc66dee..663361f5 100644
--- a/bridge/github/export.go
+++ b/bridge/github/export.go
@@ -21,7 +21,6 @@ import (
"github.com/MichaelMure/git-bug/cache"
"github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/identity"
- "github.com/MichaelMure/git-bug/repository"
)
var (
@@ -35,6 +34,13 @@ type githubExporter struct {
// cache identities clients
identityClient map[entity.Id]*githubv4.Client
+ // the client to use for non user-specific queries
+ // should be the client of the default user
+ defaultClient *githubv4.Client
+
+ // the token of the default user
+ defaultToken *auth.Token
+
// github repository ID
repositoryID string
@@ -53,12 +59,34 @@ func (ge *githubExporter) Init(repo *cache.RepoCache, conf core.Configuration) e
ge.cachedOperationIDs = make(map[entity.Id]string)
ge.cachedLabels = make(map[string]string)
+ user, err := repo.GetUserIdentity()
+ if err != nil {
+ return err
+ }
+
// preload all clients
- err := ge.cacheAllClient(repo)
+ err = ge.cacheAllClient(repo)
if err != nil {
return err
}
+ ge.defaultClient, err = ge.getClientForIdentity(user.Id())
+ if err != nil {
+ return err
+ }
+
+ login := user.ImmutableMetadata()[metaKeyGithubLogin]
+ creds, err := auth.List(repo, auth.WithMeta(metaKeyGithubLogin, login), auth.WithTarget(target), auth.WithKind(auth.KindToken))
+ if err != nil {
+ return err
+ }
+
+ if len(creds) == 0 {
+ return ErrMissingIdentityToken
+ }
+
+ ge.defaultToken = creds[0].(*auth.Token)
+
return nil
}
@@ -69,7 +97,7 @@ func (ge *githubExporter) cacheAllClient(repo *cache.RepoCache) error {
}
for _, cred := range creds {
- login, ok := cred.Metadata()[auth.MetaKeyLogin]
+ login, ok := cred.GetMetadata(auth.MetaKeyLogin)
if !ok {
_, _ = fmt.Fprintf(os.Stderr, "credential %s is not tagged with Github login\n", cred.ID().Human())
continue
@@ -80,9 +108,9 @@ func (ge *githubExporter) cacheAllClient(repo *cache.RepoCache) error {
continue
}
- if _, ok := ge.identityClient[cred.UserId()]; !ok {
+ if _, ok := ge.identityClient[user.Id()]; !ok {
client := buildClient(creds[0].(*auth.Token))
- ge.identityClient[cred.UserId()] = client
+ ge.identityClient[user.Id()] = client
}
}
@@ -462,11 +490,12 @@ func (ge *githubExporter) cacheGithubLabels(ctx context.Context, gc *githubv4.Cl
for hasNextPage {
// create a new timeout context at each iteration
ctx, cancel := context.WithTimeout(ctx, defaultTimeout)
- defer cancel()
if err := gc.Query(ctx, &q, variables); err != nil {
+ cancel()
return err
}
+ cancel()
for _, label := range q.Repository.Labels.Nodes {
ge.cachedLabels[label.Name] = label.ID
diff --git a/bridge/github/export_test.go b/bridge/github/export_test.go
index 5a0bc653..d2cfb1f9 100644
--- a/bridge/github/export_test.go
+++ b/bridge/github/export_test.go
@@ -176,7 +176,7 @@ func TestPushPull(t *testing.T) {
return deleteRepository(projectName, envUser, envToken)
})
- token := auth.NewToken(author.Id(), envToken, target)
+ token := auth.NewToken(envToken, target)
err = auth.Store(repo, token)
require.NoError(t, err)
diff --git a/bridge/github/import.go b/bridge/github/import.go
index aac4f119..f2c9a53d 100644
--- a/bridge/github/import.go
+++ b/bridge/github/import.go
@@ -543,7 +543,6 @@ func (gi *githubImporter) ensurePerson(repo *cache.RepoCache, actor *actor) (*ca
i, err = repo.NewIdentityRaw(
name,
email,
- string(actor.Login),
string(actor.AvatarUrl),
map[string]string{
metaKeyGithubLogin: string(actor.Login),
@@ -590,7 +589,6 @@ func (gi *githubImporter) getGhost(repo *cache.RepoCache) (*cache.IdentityCache,
return repo.NewIdentityRaw(
name,
"",
- string(q.User.Login),
string(q.User.AvatarUrl),
map[string]string{
metaKeyGithubLogin: string(q.User.Login),
diff --git a/bridge/launchpad/import.go b/bridge/launchpad/import.go
index 619631b3..ecbf74f8 100644
--- a/bridge/launchpad/import.go
+++ b/bridge/launchpad/import.go
@@ -38,7 +38,6 @@ func (li *launchpadImporter) ensurePerson(repo *cache.RepoCache, owner LPPerson)
return repo.NewIdentityRaw(
owner.Name,
"",
- owner.Login,
"",
map[string]string{
metaKeyLaunchpadLogin: owner.Login,
diff --git a/bug/status.go b/bug/status.go
index 737c8d31..9e998034 100644
--- a/bug/status.go
+++ b/bug/status.go
@@ -44,7 +44,7 @@ func StatusFromString(str string) (Status, error) {
case "closed":
return ClosedStatus, nil
default:
- return 0, fmt.Errorf("unknow status")
+ return 0, fmt.Errorf("unknown status")
}
}
diff --git a/cache/bug_excerpt.go b/cache/bug_excerpt.go
index 36c7dcfe..10e522f9 100644
--- a/cache/bug_excerpt.go
+++ b/cache/bug_excerpt.go
@@ -2,7 +2,6 @@ package cache
import (
"encoding/gob"
- "fmt"
"github.com/MichaelMure/git-bug/bug"
"github.com/MichaelMure/git-bug/entity"
@@ -43,21 +42,11 @@ type BugExcerpt struct {
// identity.Bare data are directly embedded in the bug excerpt
type LegacyAuthorExcerpt struct {
- Name string
- Login string
+ Name string
}
func (l LegacyAuthorExcerpt) DisplayName() string {
- switch {
- case l.Name == "" && l.Login != "":
- return l.Login
- case l.Name != "" && l.Login == "":
- return l.Name
- case l.Name != "" && l.Login != "":
- return fmt.Sprintf("%s (%s)", l.Name, l.Login)
- }
-
- panic("invalid person data")
+ return l.Name
}
func NewBugExcerpt(b bug.Interface, snap *bug.Snapshot) *BugExcerpt {
@@ -95,8 +84,7 @@ func NewBugExcerpt(b bug.Interface, snap *bug.Snapshot) *BugExcerpt {
e.AuthorId = snap.Author.Id()
case *identity.Bare:
e.LegacyAuthor = LegacyAuthorExcerpt{
- Login: snap.Author.Login(),
- Name: snap.Author.Name(),
+ Name: snap.Author.Name(),
}
default:
panic("unhandled identity type")
diff --git a/cache/filter.go b/cache/filter.go
index 27e92cf3..9b1de1d5 100644
--- a/cache/filter.go
+++ b/cache/filter.go
@@ -37,8 +37,7 @@ func AuthorFilter(query string) Filter {
}
// Legacy identity support
- return strings.Contains(strings.ToLower(excerpt.LegacyAuthor.Name), query) ||
- strings.Contains(strings.ToLower(excerpt.LegacyAuthor.Login), query)
+ return strings.Contains(strings.ToLower(excerpt.LegacyAuthor.Name), query)
}
}
diff --git a/cache/identity_cache.go b/cache/identity_cache.go
index e2129f84..eb5ee183 100644
--- a/cache/identity_cache.go
+++ b/cache/identity_cache.go
@@ -21,7 +21,7 @@ func (i *IdentityCache) notifyUpdated() error {
return i.repoCache.identityUpdated(i.Identity.Id())
}
-func (i *IdentityCache) Mutate(f func(identity.IdentityMutator) identity.IdentityMutator) error {
+func (i *IdentityCache) Mutate(f func(identity.Mutator) identity.Mutator) error {
i.Identity.Mutate(f)
return i.notifyUpdated()
}
diff --git a/cache/identity_excerpt.go b/cache/identity_excerpt.go
index 18514e9a..06788aa5 100644
--- a/cache/identity_excerpt.go
+++ b/cache/identity_excerpt.go
@@ -2,7 +2,6 @@ package cache
import (
"encoding/gob"
- "fmt"
"strings"
"github.com/MichaelMure/git-bug/entity"
@@ -21,7 +20,6 @@ type IdentityExcerpt struct {
Id entity.Id
Name string
- Login string
ImmutableMetadata map[string]string
}
@@ -29,7 +27,6 @@ func NewIdentityExcerpt(i *identity.Identity) *IdentityExcerpt {
return &IdentityExcerpt{
Id: i.Id(),
Name: i.Name(),
- Login: i.Login(),
ImmutableMetadata: i.ImmutableMetadata(),
}
}
@@ -37,23 +34,13 @@ func NewIdentityExcerpt(i *identity.Identity) *IdentityExcerpt {
// DisplayName return a non-empty string to display, representing the
// identity, based on the non-empty values.
func (i *IdentityExcerpt) DisplayName() string {
- switch {
- case i.Name == "" && i.Login != "":
- return i.Login
- case i.Name != "" && i.Login == "":
- return i.Name
- case i.Name != "" && i.Login != "":
- return fmt.Sprintf("%s (%s)", i.Name, i.Login)
- }
-
- panic("invalid person data")
+ return i.Name
}
// Match matches a query with the identity name, login and ID prefixes
func (i *IdentityExcerpt) Match(query string) bool {
return i.Id.HasPrefix(query) ||
- strings.Contains(strings.ToLower(i.Name), query) ||
- strings.Contains(strings.ToLower(i.Login), query)
+ strings.Contains(strings.ToLower(i.Name), query)
}
/*
diff --git a/cache/query.go b/cache/query.go
index 633ef1c2..967c18d6 100644
--- a/cache/query.go
+++ b/cache/query.go
@@ -91,7 +91,7 @@ func ParseQuery(query string) (*Query, error) {
sortingDone = true
default:
- return nil, fmt.Errorf("unknow qualifier name %s", qualifierName)
+ return nil, fmt.Errorf("unknown qualifier name %s", qualifierName)
}
}
@@ -165,7 +165,7 @@ func (q *Query) parseSorting(query string) error {
q.OrderDirection = OrderAscending
default:
- return fmt.Errorf("unknow sorting %s", query)
+ return fmt.Errorf("unknown sorting %s", query)
}
return nil
diff --git a/cache/repo_cache.go b/cache/repo_cache.go
index 99afeb41..18be9b5a 100644
--- a/cache/repo_cache.go
+++ b/cache/repo_cache.go
@@ -789,12 +789,6 @@ func (c *RepoCache) ResolveIdentityImmutableMetadata(key string, value string) (
})
}
-func (c *RepoCache) ResolveIdentityLogin(login string) (*IdentityCache, error) {
- return c.ResolveIdentityMatcher(func(excerpt *IdentityExcerpt) bool {
- return excerpt.Login == login
- })
-}
-
func (c *RepoCache) ResolveIdentityMatcher(f func(*IdentityExcerpt) bool) (*IdentityCache, error) {
// preallocate but empty
matching := make([]entity.Id, 0, 5)
@@ -869,21 +863,36 @@ func (c *RepoCache) IsUserIdentitySet() (bool, error) {
return identity.IsUserIdentitySet(c.repo)
}
+func (c *RepoCache) NewIdentityFromGitUser() (*IdentityCache, error) {
+ return c.NewIdentityFromGitUserRaw(nil)
+}
+
+func (c *RepoCache) NewIdentityFromGitUserRaw(metadata map[string]string) (*IdentityCache, error) {
+ i, err := identity.NewFromGitUser(c.repo)
+ if err != nil {
+ return nil, err
+ }
+ return c.finishIdentity(i, metadata)
+}
+
// NewIdentity create a new identity
// The new identity is written in the repository (commit)
func (c *RepoCache) NewIdentity(name string, email string) (*IdentityCache, error) {
- return c.NewIdentityRaw(name, email, "", "", nil)
+ return c.NewIdentityRaw(name, email, "", nil)
}
// NewIdentityFull create a new identity
// The new identity is written in the repository (commit)
-func (c *RepoCache) NewIdentityFull(name string, email string, login string, avatarUrl string) (*IdentityCache, error) {
- return c.NewIdentityRaw(name, email, login, avatarUrl, nil)
+func (c *RepoCache) NewIdentityFull(name string, email string, avatarUrl string) (*IdentityCache, error) {
+ return c.NewIdentityRaw(name, email, avatarUrl, nil)
}
-func (c *RepoCache) NewIdentityRaw(name string, email string, login string, avatarUrl string, metadata map[string]string) (*IdentityCache, error) {
- i := identity.NewIdentityFull(name, email, login, avatarUrl)
+func (c *RepoCache) NewIdentityRaw(name string, email string, avatarUrl string, metadata map[string]string) (*IdentityCache, error) {
+ i := identity.NewIdentityFull(name, email, avatarUrl)
+ return c.finishIdentity(i, metadata)
+}
+func (c *RepoCache) finishIdentity(i *identity.Identity, metadata map[string]string) (*IdentityCache, error) {
for key, value := range metadata {
i.SetMetadata(key, value)
}
diff --git a/graphql/graph/gen_graph.go b/graphql/graph/gen_graph.go
index 215603cb..ee170ecc 100644
--- a/graphql/graph/gen_graph.go
+++ b/graphql/graph/gen_graph.go
@@ -210,7 +210,6 @@ type ComplexityRoot struct {
HumanID func(childComplexity int) int
ID func(childComplexity int) int
IsProtected func(childComplexity int) int
- Login func(childComplexity int) int
Name func(childComplexity int) int
}
@@ -1139,13 +1138,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Identity.IsProtected(childComplexity), true
- case "Identity.login":
- if e.complexity.Identity.Login == nil {
- break
- }
-
- return e.complexity.Identity.Login(childComplexity), true
-
case "Identity.name":
if e.complexity.Identity.Name == nil {
break
@@ -2070,6 +2062,7 @@ type BugConnection {
An edge in a connection.
"""
type BugEdge {
+<<<<<<< HEAD
"""
A cursor for use in pagination.
"""
@@ -2078,6 +2071,105 @@ type BugEdge {
The item at the end of the edge.
"""
node: Bug!
+=======
+ """A cursor for use in pagination."""
+ cursor: String!
+ """The item at the end of the edge."""
+ node: Bug!
+}
+`},
+ &ast.Source{Name: "schema/identity.graphql", Input: `"""Represents an identity"""
+type Identity {
+ """The identifier for this identity"""
+ id: String!
+ """The human version (truncated) identifier for this identity"""
+ humanId: String!
+ """The name of the person, if known."""
+ name: String
+ """The email of the person, if known."""
+ email: String
+ """A non-empty string to display, representing the identity, based on the non-empty values."""
+ displayName: String!
+ """An url to an avatar"""
+ avatarUrl: String
+ """isProtected is true if the chain of git commits started to be signed.
+ If that's the case, only signed commit with a valid key for this identity can be added."""
+ isProtected: Boolean!
+}
+
+type IdentityConnection {
+ edges: [IdentityEdge!]!
+ nodes: [Identity!]!
+ pageInfo: PageInfo!
+ totalCount: Int!
+}
+
+type IdentityEdge {
+ cursor: String!
+ node: Identity!
+}`},
+ &ast.Source{Name: "schema/label.graphql", Input: `"""Label for a bug."""
+type Label {
+ """The name of the label."""
+ name: String!
+ """Color of the label."""
+ color: Color!
+}
+
+type LabelConnection {
+ edges: [LabelEdge!]!
+ nodes: [Label!]!
+ pageInfo: PageInfo!
+ totalCount: Int!
+}
+
+type LabelEdge {
+ cursor: String!
+ node: Label!
+}`},
+ &ast.Source{Name: "schema/mutations.graphql", Input: `input NewBugInput {
+ """A unique identifier for the client performing the mutation."""
+ clientMutationId: String
+ """"The name of the repository. If not set, the default repository is used."""
+ repoRef: String
+ """The title of the new bug."""
+ title: String!
+ """The first message of the new bug."""
+ message: String!
+ """The collection of file's hash required for the first message."""
+ files: [Hash!]
+}
+
+type NewBugPayload {
+ """A unique identifier for the client performing the mutation."""
+ clientMutationId: String
+ """The created bug."""
+ bug: Bug!
+ """The resulting operation."""
+ operation: CreateOperation!
+}
+
+input AddCommentInput {
+ """A unique identifier for the client performing the mutation."""
+ clientMutationId: String
+ """"The name of the repository. If not set, the default repository is used."""
+ repoRef: String
+ """The bug ID's prefix."""
+ prefix: String!
+ """The first message of the new bug."""
+ message: String!
+ """The collection of file's hash required for the first message."""
+ files: [Hash!]
+}
+
+type AddCommentPayload {
+ """A unique identifier for the client performing the mutation."""
+ clientMutationId: String
+ """The affected bug."""
+ bug: Bug!
+ """The resulting operation."""
+ operation: AddCommentOperation!
+>>>>>>> more more wip
}
input ChangeLabelInput {
"""
@@ -6215,6 +6307,7 @@ func (ec *executionContext) _Identity_email(ctx context.Context, field graphql.C
return ec.marshalOString2string(ctx, field.Selections, res)
}
+<<<<<<< HEAD
func (ec *executionContext) _Identity_login(ctx context.Context, field graphql.CollectedField, obj identity.Interface) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
@@ -6247,6 +6340,10 @@ func (ec *executionContext) _Identity_login(ctx context.Context, field graphql.C
}
func (ec *executionContext) _Identity_displayName(ctx context.Context, field graphql.CollectedField, obj identity.Interface) (ret graphql.Marshaler) {
+=======
+func (ec *executionContext) _Identity_displayName(ctx context.Context, field graphql.CollectedField, obj *identity.Interface) (ret graphql.Marshaler) {
+ ctx = ec.Tracer.StartFieldExecution(ctx, field)
+>>>>>>> more more wip
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
@@ -11945,9 +12042,22 @@ func (ec *executionContext) _Identity(ctx context.Context, sel ast.SelectionSet,
case "name":
out.Values[i] = ec._Identity_name(ctx, field, obj)
case "email":
+<<<<<<< HEAD
out.Values[i] = ec._Identity_email(ctx, field, obj)
case "login":
out.Values[i] = ec._Identity_login(ctx, field, obj)
+=======
+ field := field
+ out.Concurrently(i, func() (res graphql.Marshaler) {
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ }
+ }()
+ res = ec._Identity_email(ctx, field, obj)
+ return res
+ })
+>>>>>>> more more wip
case "displayName":
out.Values[i] = ec._Identity_displayName(ctx, field, obj)
if out.Values[i] == graphql.Null {
diff --git a/graphql/resolvers/identity.go b/graphql/resolvers/identity.go
index da8e7b08..2d1e909b 100644
--- a/graphql/resolvers/identity.go
+++ b/graphql/resolvers/identity.go
@@ -14,7 +14,3 @@ type identityResolver struct{}
func (identityResolver) ID(ctx context.Context, obj identity.Interface) (string, error) {
return obj.Id().String(), nil
}
-
-func (identityResolver) HumanID(ctx context.Context, obj identity.Interface) (string, error) {
- return obj.Id().Human(), nil
-}
diff --git a/graphql/schema/identity.graphql b/graphql/schema/identity.graphql
index 6872ecb9..6490d538 100644
--- a/graphql/schema/identity.graphql
+++ b/graphql/schema/identity.graphql
@@ -8,9 +8,7 @@ type Identity {
name: String
"""The email of the person, if known."""
email: String
- """The login of the person, if known."""
- login: String
- """A string containing the either the name of the person, its login or both"""
+ """A non-empty string to display, representing the identity, based on the non-empty values."""
displayName: String!
"""An url to an avatar"""
avatarUrl: String
diff --git a/graphql/schema/root.graphql b/graphql/schema/root.graphql
index f66272ca..2a12cc37 100644
--- a/graphql/schema/root.graphql
+++ b/graphql/schema/root.graphql
@@ -3,6 +3,8 @@ type Query {
defaultRepository: Repository
"""Access a repository by reference/name."""
repository(ref: String!): Repository
+
+ #TODO: connection for all repositories
}
type Mutation {
diff --git a/identity/bare.go b/identity/bare.go
index 26ecdf03..a02ec790 100644
--- a/identity/bare.go
+++ b/identity/bare.go
@@ -112,13 +112,13 @@ func (i *Bare) AvatarUrl() string {
}
// Keys return the last version of the valid keys
-func (i *Bare) Keys() []Key {
- return []Key{}
+func (i *Bare) Keys() []*Key {
+ return nil
}
// ValidKeysAtTime return the set of keys valid at a given lamport time
-func (i *Bare) ValidKeysAtTime(time lamport.Time) []Key {
- return []Key{}
+func (i *Bare) ValidKeysAtTime(_ lamport.Time) []*Key {
+ return nil
}
// DisplayName return a non-empty string to display, representing the
diff --git a/identity/identity.go b/identity/identity.go
index 655afd31..c33a8818 100644
--- a/identity/identity.go
+++ b/identity/identity.go
@@ -275,7 +275,7 @@ type Mutator struct {
Name string
Email string
AvatarUrl string
- Keys []Key
+ Keys []*Key
}
// Mutate allow to create a new version of the Identity
@@ -507,13 +507,13 @@ func (i *Identity) AvatarUrl() string {
}
// Keys return the last version of the valid keys
-func (i *Identity) Keys() []Key {
+func (i *Identity) Keys() []*Key {
return i.lastVersion().keys
}
// ValidKeysAtTime return the set of keys valid at a given lamport time
-func (i *Identity) ValidKeysAtTime(time lamport.Time) []Key {
- var result []Key
+func (i *Identity) ValidKeysAtTime(time lamport.Time) []*Key {
+ var result []*Key
for _, v := range i.versions {
if v.time > time {
@@ -550,11 +550,11 @@ func (i *Identity) LastModification() timestamp.Timestamp {
}
// SetMetadata store arbitrary metadata along the last not-commit Version.
-// If the Version has been commit to git already, a new version is added and will need to be
+// If the Version has been commit to git already, a new identical version is added and will need to be
// commit.
func (i *Identity) SetMetadata(key string, value string) {
if i.lastVersion().commitHash != "" {
-
+ i.versions = append(i.versions, i.lastVersion().Clone())
}
i.lastVersion().SetMetadata(key, value)
}
@@ -588,3 +588,9 @@ func (i *Identity) MutableMetadata() map[string]string {
return metadata
}
+
+// addVersionForTest add a new version to the identity
+// Only for testing !
+func (i *Identity) addVersionForTest(version *Version) {
+ i.versions = append(i.versions, version)
+}
diff --git a/identity/identity_actions_test.go b/identity/identity_actions_test.go
index 142ffaa6..713b3246 100644
--- a/identity/identity_actions_test.go
+++ b/identity/identity_actions_test.go
@@ -48,14 +48,14 @@ func TestPushPull(t *testing.T) {
// Update both
- identity1.AddVersion(&Version{
+ identity1.addVersionForTest(&Version{
name: "name1b",
email: "email1b",
})
err = identity1.Commit(repoA)
require.NoError(t, err)
- identity2.AddVersion(&Version{
+ identity2.addVersionForTest(&Version{
name: "name2b",
email: "email2b",
})
@@ -92,7 +92,7 @@ func TestPushPull(t *testing.T) {
// Concurrent update
- identity1.AddVersion(&Version{
+ identity1.addVersionForTest(&Version{
name: "name1c",
email: "email1c",
})
@@ -102,7 +102,7 @@ func TestPushPull(t *testing.T) {
identity1B, err := ReadLocal(repoB, identity1.Id())
require.NoError(t, err)
- identity1B.AddVersion(&Version{
+ identity1B.addVersionForTest(&Version{
name: "name1concurrent",
email: "email1concurrent",
})
diff --git a/identity/identity_stub.go b/identity/identity_stub.go
index be52ffc0..7e2fcd94 100644
--- a/identity/identity_stub.go
+++ b/identity/identity_stub.go
@@ -64,11 +64,11 @@ func (IdentityStub) AvatarUrl() string {
panic("identities needs to be properly loaded with identity.ReadLocal()")
}
-func (IdentityStub) Keys() []Key {
+func (IdentityStub) Keys() []*Key {
panic("identities needs to be properly loaded with identity.ReadLocal()")
}
-func (IdentityStub) ValidKeysAtTime(time lamport.Time) []Key {
+func (IdentityStub) ValidKeysAtTime(_ lamport.Time) []*Key {
panic("identities needs to be properly loaded with identity.ReadLocal()")
}
diff --git a/identity/identity_test.go b/identity/identity_test.go
index f91c548f..ee6ccdf7 100644
--- a/identity/identity_test.go
+++ b/identity/identity_test.go
@@ -44,7 +44,7 @@ func TestIdentityCommitLoad(t *testing.T) {
time: 100,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyA"},
},
},
@@ -52,7 +52,7 @@ func TestIdentityCommitLoad(t *testing.T) {
time: 200,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyB"},
},
},
@@ -60,7 +60,7 @@ func TestIdentityCommitLoad(t *testing.T) {
time: 201,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyC"},
},
},
@@ -79,20 +79,25 @@ func TestIdentityCommitLoad(t *testing.T) {
// add more version
- identity.AddVersion(&Version{
+ identity.Mutate(func(orig Mutator) Mutator {
+
+ return orig
+ })
+
+ identity.addVersionForTest(&Version{
time: 201,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyD"},
},
})
- identity.AddVersion(&Version{
+ identity.addVersionForTest(&Version{
time: 300,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyE"},
},
})
@@ -123,7 +128,7 @@ func TestIdentity_ValidKeysAtTime(t *testing.T) {
time: 100,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyA"},
},
},
@@ -131,7 +136,7 @@ func TestIdentity_ValidKeysAtTime(t *testing.T) {
time: 200,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyB"},
},
},
@@ -139,7 +144,7 @@ func TestIdentity_ValidKeysAtTime(t *testing.T) {
time: 201,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyC"},
},
},
@@ -147,7 +152,7 @@ func TestIdentity_ValidKeysAtTime(t *testing.T) {
time: 201,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyD"},
},
},
@@ -155,7 +160,7 @@ func TestIdentity_ValidKeysAtTime(t *testing.T) {
time: 300,
name: "René Descartes",
email: "rene.descartes@example.com",
- keys: []Key{
+ keys: []*Key{
{PubKey: "pubkeyE"},
},
},
@@ -163,13 +168,13 @@ func TestIdentity_ValidKeysAtTime(t *testing.T) {
}
assert.Nil(t, identity.ValidKeysAtTime(10))
- assert.Equal(t, identity.ValidKeysAtTime(100), []Key{{PubKey: "pubkeyA"}})
- assert.Equal(t, identity.ValidKeysAtTime(140), []Key{{PubKey: "pubkeyA"}})
- assert.Equal(t, identity.ValidKeysAtTime(200), []Key{{PubKey: "pubkeyB"}})
- assert.Equal(t, identity.ValidKeysAtTime(201), []Key{{PubKey: "pubkeyD"}})
- assert.Equal(t, identity.ValidKeysAtTime(202), []Key{{PubKey: "pubkeyD"}})
- assert.Equal(t, identity.ValidKeysAtTime(300), []Key{{PubKey: "pubkeyE"}})
- assert.Equal(t, identity.ValidKeysAtTime(3000), []Key{{PubKey: "pubkeyE"}})
+ assert.Equal(t, identity.ValidKeysAtTime(100), []*Key{{PubKey: "pubkeyA"}})
+ assert.Equal(t, identity.ValidKeysAtTime(140), []*Key{{PubKey: "pubkeyA"}})
+ assert.Equal(t, identity.ValidKeysAtTime(200), []*Key{{PubKey: "pubkeyB"}})
+ assert.Equal(t, identity.ValidKeysAtTime(201), []*Key{{PubKey: "pubkeyD"}})
+ assert.Equal(t, identity.ValidKeysAtTime(202), []*Key{{PubKey: "pubkeyD"}})
+ assert.Equal(t, identity.ValidKeysAtTime(300), []*Key{{PubKey: "pubkeyE"}})
+ assert.Equal(t, identity.ValidKeysAtTime(3000), []*Key{{PubKey: "pubkeyE"}})
}
// Test the immutable or mutable metadata search
@@ -189,7 +194,7 @@ func TestMetadata(t *testing.T) {
assertHasKeyValue(t, identity.MutableMetadata(), "key1", "value1")
// try override
- identity.AddVersion(&Version{
+ identity.addVersionForTest(&Version{
name: "René Descartes",
email: "rene.descartes@example.com",
})
diff --git a/identity/interface.go b/identity/interface.go
index 3407d7ab..d138362d 100644
--- a/identity/interface.go
+++ b/identity/interface.go
@@ -21,10 +21,10 @@ type Interface interface {
AvatarUrl() string
// Keys return the last version of the valid keys
- Keys() []Key
+ Keys() []*Key
// ValidKeysAtTime return the set of keys valid at a given lamport time
- ValidKeysAtTime(time lamport.Time) []Key
+ ValidKeysAtTime(time lamport.Time) []*Key
// DisplayName return a non-empty string to display, representing the
// identity, based on the non-empty values.
diff --git a/identity/key.go b/identity/key.go
index 90edfb60..cc948394 100644
--- a/identity/key.go
+++ b/identity/key.go
@@ -11,3 +11,8 @@ func (k *Key) Validate() error {
return nil
}
+
+func (k *Key) Clone() *Key {
+ clone := *k
+ return &clone
+}
diff --git a/identity/version.go b/identity/version.go
index 85195049..f9c7b262 100644
--- a/identity/version.go
+++ b/identity/version.go
@@ -30,7 +30,7 @@ type Version struct {
// The set of keys valid at that time, from this version onward, until they get removed
// in a new version. This allow to have multiple key for the same identity (e.g. one per
// device) as well as revoke key.
- keys []Key
+ keys []*Key
// This optional array is here to ensure a better randomness of the identity id to avoid collisions.
// It has no functional purpose and should be ignored.
@@ -53,24 +53,22 @@ type VersionJSON struct {
Name string `json:"name,omitempty"`
Email string `json:"email,omitempty"`
AvatarUrl string `json:"avatar_url,omitempty"`
- Keys []Key `json:"pub_keys,omitempty"`
+ Keys []*Key `json:"pub_keys,omitempty"`
Nonce []byte `json:"nonce,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
}
// Make a deep copy
func (v *Version) Clone() *Version {
-
clone := &Version{
name: v.name,
email: v.email,
avatarURL: v.avatarURL,
- keys: make([]Key, len(v.keys)),
- metadata: make(map[string]string),
+ keys: make([]*Key, len(v.keys)),
}
- for i, op := range opp.Operations {
- clone.Operations[i] = op
+ for i, key := range v.keys {
+ clone.keys[i] = key.Clone()
}
return clone
diff --git a/identity/version_test.go b/identity/version_test.go
index 8c4c8d99..25848eb5 100644
--- a/identity/version_test.go
+++ b/identity/version_test.go
@@ -9,11 +9,10 @@ import (
func TestVersionSerialize(t *testing.T) {
before := &Version{
- login: "login",
name: "name",
email: "email",
avatarURL: "avatarUrl",
- keys: []Key{
+ keys: []*Key{
{
Fingerprint: "fingerprint1",
PubKey: "pubkey1",