From 499dbc0a032ff28eea99e5308be9b6c8f2d208ad Mon Sep 17 00:00:00 2001 From: Michael Muré Date: Wed, 1 Jul 2020 20:00:53 +0200 Subject: identity: remove support for legacy identity --- bug/op_add_comment_test.go | 15 ++- bug/op_create_test.go | 17 +++- bug/op_edit_comment_test.go | 20 +++- bug/op_label_change_test.go | 17 +++- bug/op_noop_test.go | 17 +++- bug/op_set_metadata_test.go | 21 ++++- bug/op_set_status_test.go | 17 +++- bug/op_set_title_test.go | 17 +++- bug/operation_pack.go | 11 ++- bug/operation_pack_test.go | 29 ++++-- bug/operation_test.go | 12 +-- cache/bug_excerpt.go | 12 +-- cache/filter.go | 15 +-- cache/repo_cache.go | 3 +- commands/ls.go | 40 +++----- identity/bare.go | 218 -------------------------------------------- identity/bare_test.go | 37 -------- identity/common.go | 13 --- identity/identity.go | 2 +- identity/version.go | 1 + termui/bug_table.go | 22 ++--- 21 files changed, 178 insertions(+), 378 deletions(-) delete mode 100644 identity/bare.go delete mode 100644 identity/bare_test.go diff --git a/bug/op_add_comment_test.go b/bug/op_add_comment_test.go index 60364cf1..8bcc64e1 100644 --- a/bug/op_add_comment_test.go +++ b/bug/op_add_comment_test.go @@ -6,12 +6,18 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/MichaelMure/git-bug/identity" + "github.com/MichaelMure/git-bug/repository" ) func TestAddCommentSerialize(t *testing.T) { - var rene = identity.NewBare("René Descartes", "rene@descartes.fr") + repo := repository.NewMockRepoForTest() + rene := identity.NewIdentity("René Descartes", "rene@descartes.fr") + err := rene.Commit(repo) + require.NoError(t, err) + unix := time.Now().Unix() before := NewAddCommentOp(rene, unix, "message", nil) @@ -22,9 +28,12 @@ func TestAddCommentSerialize(t *testing.T) { err = json.Unmarshal(data, &after) assert.NoError(t, err) - // enforce creating the IDs + // enforce creating the ID before.Id() - rene.Id() + + // Replace the identity stub with the real thing + assert.Equal(t, rene.Id(), after.base().Author.Id()) + after.Author = rene assert.Equal(t, before, &after) } diff --git a/bug/op_create_test.go b/bug/op_create_test.go index ad9a30fd..f68b7637 100644 --- a/bug/op_create_test.go +++ b/bug/op_create_test.go @@ -6,14 +6,16 @@ import ( "time" "github.com/MichaelMure/git-bug/identity" + "github.com/MichaelMure/git-bug/repository" "github.com/MichaelMure/git-bug/util/timestamp" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestCreate(t *testing.T) { snapshot := Snapshot{} - rene := identity.NewBare("René Descartes", "rene@descartes.fr") + rene := identity.NewIdentity("René Descartes", "rene@descartes.fr") unix := time.Now().Unix() create := NewCreateOp(rene, unix, "title", "message", nil) @@ -50,7 +52,11 @@ func TestCreate(t *testing.T) { } func TestCreateSerialize(t *testing.T) { - var rene = identity.NewBare("René Descartes", "rene@descartes.fr") + repo := repository.NewMockRepoForTest() + rene := identity.NewIdentity("René Descartes", "rene@descartes.fr") + err := rene.Commit(repo) + require.NoError(t, err) + unix := time.Now().Unix() before := NewCreateOp(rene, unix, "title", "message", nil) @@ -61,9 +67,12 @@ func TestCreateSerialize(t *testing.T) { err = json.Unmarshal(data, &after) assert.NoError(t, err) - // enforce creating the IDs + // enforce creating the ID before.Id() - rene.Id() + + // Replace the identity stub with the real thing + assert.Equal(t, rene.Id(), after.base().Author.Id()) + after.Author = rene assert.Equal(t, before, &after) } diff --git a/bug/op_edit_comment_test.go b/bug/op_edit_comment_test.go index abd550cb..583ba656 100644 --- a/bug/op_edit_comment_test.go +++ b/bug/op_edit_comment_test.go @@ -9,12 +9,17 @@ import ( "github.com/stretchr/testify/require" "github.com/MichaelMure/git-bug/identity" + "github.com/MichaelMure/git-bug/repository" ) func TestEdit(t *testing.T) { snapshot := Snapshot{} - rene := identity.NewBare("René Descartes", "rene@descartes.fr") + repo := repository.NewMockRepoForTest() + rene := identity.NewIdentity("René Descartes", "rene@descartes.fr") + err := rene.Commit(repo) + require.NoError(t, err) + unix := time.Now().Unix() create := NewCreateOp(rene, unix, "title", "create", nil) @@ -74,7 +79,11 @@ func TestEdit(t *testing.T) { } func TestEditCommentSerialize(t *testing.T) { - var rene = identity.NewBare("René Descartes", "rene@descartes.fr") + repo := repository.NewMockRepoForTest() + rene := identity.NewIdentity("René Descartes", "rene@descartes.fr") + err := rene.Commit(repo) + require.NoError(t, err) + unix := time.Now().Unix() before := NewEditCommentOp(rene, unix, "target", "message", nil) @@ -85,9 +94,12 @@ func TestEditCommentSerialize(t *testing.T) { err = json.Unmarshal(data, &after) assert.NoError(t, err) - // enforce creating the IDs + // enforce creating the ID before.Id() - rene.Id() + + // Replace the identity stub with the real thing + assert.Equal(t, rene.Id(), after.base().Author.Id()) + after.Author = rene assert.Equal(t, before, &after) } diff --git a/bug/op_label_change_test.go b/bug/op_label_change_test.go index 2a93e362..c98b2207 100644 --- a/bug/op_label_change_test.go +++ b/bug/op_label_change_test.go @@ -5,12 +5,20 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + "github.com/MichaelMure/git-bug/identity" + "github.com/MichaelMure/git-bug/repository" + "github.com/stretchr/testify/assert" ) func TestLabelChangeSerialize(t *testing.T) { - var rene = identity.NewBare("René Descartes", "rene@descartes.fr") + repo := repository.NewMockRepoForTest() + rene := identity.NewIdentity("René Descartes", "rene@descartes.fr") + err := rene.Commit(repo) + require.NoError(t, err) + unix := time.Now().Unix() before := NewLabelChangeOperation(rene, unix, []Label{"added"}, []Label{"removed"}) @@ -21,9 +29,12 @@ func TestLabelChangeSerialize(t *testing.T) { err = json.Unmarshal(data, &after) assert.NoError(t, err) - // enforce creating the IDs + // enforce creating the ID before.Id() - rene.Id() + + // Replace the identity stub with the real thing + assert.Equal(t, rene.Id(), after.base().Author.Id()) + after.Author = rene assert.Equal(t, before, &after) } diff --git a/bug/op_noop_test.go b/bug/op_noop_test.go index ea815948..0e34c961 100644 --- a/bug/op_noop_test.go +++ b/bug/op_noop_test.go @@ -5,12 +5,20 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + "github.com/MichaelMure/git-bug/identity" + "github.com/MichaelMure/git-bug/repository" + "github.com/stretchr/testify/assert" ) func TestNoopSerialize(t *testing.T) { - var rene = identity.NewBare("René Descartes", "rene@descartes.fr") + repo := repository.NewMockRepoForTest() + rene := identity.NewIdentity("René Descartes", "rene@descartes.fr") + err := rene.Commit(repo) + require.NoError(t, err) + unix := time.Now().Unix() before := NewNoOpOp(rene, unix) @@ -21,9 +29,12 @@ func TestNoopSerialize(t *testing.T) { err = json.Unmarshal(data, &after) assert.NoError(t, err) - // enforce creating the IDs + // enforce creating the ID before.Id() - rene.Id() + + // Replace the identity stub with the real thing + assert.Equal(t, rene.Id(), after.base().Author.Id()) + after.Author = rene assert.Equal(t, before, &after) } diff --git a/bug/op_set_metadata_test.go b/bug/op_set_metadata_test.go index 389e91ac..d7711249 100644 --- a/bug/op_set_metadata_test.go +++ b/bug/op_set_metadata_test.go @@ -6,6 +6,8 @@ import ( "time" "github.com/MichaelMure/git-bug/identity" + "github.com/MichaelMure/git-bug/repository" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -13,7 +15,11 @@ import ( func TestSetMetadata(t *testing.T) { snapshot := Snapshot{} - rene := identity.NewBare("René Descartes", "rene@descartes.fr") + repo := repository.NewMockRepoForTest() + rene := identity.NewIdentity("René Descartes", "rene@descartes.fr") + err := rene.Commit(repo) + require.NoError(t, err) + unix := time.Now().Unix() create := NewCreateOp(rene, unix, "title", "create", nil) @@ -93,7 +99,11 @@ func TestSetMetadata(t *testing.T) { } func TestSetMetadataSerialize(t *testing.T) { - var rene = identity.NewBare("René Descartes", "rene@descartes.fr") + repo := repository.NewMockRepoForTest() + rene := identity.NewIdentity("René Descartes", "rene@descartes.fr") + err := rene.Commit(repo) + require.NoError(t, err) + unix := time.Now().Unix() before := NewSetMetadataOp(rene, unix, "message", map[string]string{ "key1": "value1", @@ -107,9 +117,12 @@ func TestSetMetadataSerialize(t *testing.T) { err = json.Unmarshal(data, &after) assert.NoError(t, err) - // enforce creating the IDs + // enforce creating the ID before.Id() - rene.Id() + + // Replace the identity stub with the real thing + assert.Equal(t, rene.Id(), after.base().Author.Id()) + after.Author = rene assert.Equal(t, before, &after) } diff --git a/bug/op_set_status_test.go b/bug/op_set_status_test.go index ea032184..cdea2dd2 100644 --- a/bug/op_set_status_test.go +++ b/bug/op_set_status_test.go @@ -5,12 +5,20 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + "github.com/MichaelMure/git-bug/identity" + "github.com/MichaelMure/git-bug/repository" + "github.com/stretchr/testify/assert" ) func TestSetStatusSerialize(t *testing.T) { - var rene = identity.NewBare("René Descartes", "rene@descartes.fr") + repo := repository.NewMockRepoForTest() + rene := identity.NewIdentity("René Descartes", "rene@descartes.fr") + err := rene.Commit(repo) + require.NoError(t, err) + unix := time.Now().Unix() before := NewSetStatusOp(rene, unix, ClosedStatus) @@ -21,9 +29,12 @@ func TestSetStatusSerialize(t *testing.T) { err = json.Unmarshal(data, &after) assert.NoError(t, err) - // enforce creating the IDs + // enforce creating the ID before.Id() - rene.Id() + + // Replace the identity stub with the real thing + assert.Equal(t, rene.Id(), after.base().Author.Id()) + after.Author = rene assert.Equal(t, before, &after) } diff --git a/bug/op_set_title_test.go b/bug/op_set_title_test.go index 19cbb12b..368ada61 100644 --- a/bug/op_set_title_test.go +++ b/bug/op_set_title_test.go @@ -5,12 +5,20 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + "github.com/MichaelMure/git-bug/identity" + "github.com/MichaelMure/git-bug/repository" + "github.com/stretchr/testify/assert" ) func TestSetTitleSerialize(t *testing.T) { - var rene = identity.NewBare("René Descartes", "rene@descartes.fr") + repo := repository.NewMockRepoForTest() + rene := identity.NewIdentity("René Descartes", "rene@descartes.fr") + err := rene.Commit(repo) + require.NoError(t, err) + unix := time.Now().Unix() before := NewSetTitleOp(rene, unix, "title", "was") @@ -21,9 +29,12 @@ func TestSetTitleSerialize(t *testing.T) { err = json.Unmarshal(data, &after) assert.NoError(t, err) - // enforce creating the IDs + // enforce creating the ID before.Id() - rene.Id() + + // Replace the identity stub with the real thing + assert.Equal(t, rene.Id(), after.base().Author.Id()) + after.Author = rene assert.Equal(t, before, &after) } diff --git a/bug/operation_pack.go b/bug/operation_pack.go index 6a134b94..0bd3fb7d 100644 --- a/bug/operation_pack.go +++ b/bug/operation_pack.go @@ -9,7 +9,9 @@ import ( "github.com/MichaelMure/git-bug/repository" ) -const formatVersion = 1 +// 1: original format +// 2: no more legacy identities +const formatVersion = 2 // OperationPack represent an ordered set of operation to apply // to a Bug. These operations are stored in a single Git commit. @@ -44,8 +46,11 @@ func (opp *OperationPack) UnmarshalJSON(data []byte) error { return err } - if aux.Version != formatVersion { - return fmt.Errorf("unknown format version %v", aux.Version) + if aux.Version < formatVersion { + return fmt.Errorf("outdated repository format, please use https://github.com/MichaelMure/git-bug-migration to upgrade") + } + if aux.Version > formatVersion { + return fmt.Errorf("your version of git-bug is too old for this repository (version %v), please upgrade to the latest version", aux.Version) } for _, raw := range aux.Operations { diff --git a/bug/operation_pack_test.go b/bug/operation_pack_test.go index b6707152..6aab0097 100644 --- a/bug/operation_pack_test.go +++ b/bug/operation_pack_test.go @@ -15,7 +15,11 @@ import ( func TestOperationPackSerialize(t *testing.T) { opp := &OperationPack{} - rene := identity.NewBare("René Descartes", "rene@descartes.fr") + repo := repository.NewMockRepoForTest() + rene := identity.NewIdentity("René Descartes", "rene@descartes.fr") + err := rene.Commit(repo) + require.NoError(t, err) + createOp := NewCreateOp(rene, time.Now().Unix(), "title", "message", nil) setTitleOp := NewSetTitleOp(rene, time.Now().Unix(), "title2", "title1") addCommentOp := NewAddCommentOp(rene, time.Now().Unix(), "message2", nil) @@ -49,16 +53,27 @@ func TestOperationPackSerialize(t *testing.T) { err = json.Unmarshal(data, &opp2) assert.NoError(t, err) - ensureIDs(t, opp) + ensureIds(opp) + ensureAuthors(t, opp, opp2) assert.Equal(t, opp, opp2) } -func ensureIDs(t *testing.T, opp *OperationPack) { +func ensureIds(opp *OperationPack) { for _, op := range opp.Operations { - id := op.Id() - require.NoError(t, id.Validate()) - id = op.GetAuthor().Id() - require.NoError(t, id.Validate()) + op.Id() + } +} + +func ensureAuthors(t *testing.T, opp1 *OperationPack, opp2 *OperationPack) { + require.Equal(t, len(opp1.Operations), len(opp2.Operations)) + for i := 0; i < len(opp1.Operations); i++ { + op1 := opp1.Operations[i] + op2 := opp2.Operations[i] + + // ensure we have equivalent authors (IdentityStub vs Identity) then + // enforce equality + require.Equal(t, op1.base().Author.Id(), op2.base().Author.Id()) + op1.base().Author = op2.base().Author } } diff --git a/bug/operation_test.go b/bug/operation_test.go index 64bff41f..20799bb1 100644 --- a/bug/operation_test.go +++ b/bug/operation_test.go @@ -88,32 +88,32 @@ func TestID(t *testing.T) { } for _, repo := range repos { - rene := identity.NewBare("René Descartes", "rene@descartes.fr") + rene := identity.NewIdentity("René Descartes", "rene@descartes.fr") + err := rene.Commit(repo) + require.NoError(t, err) b, op, err := Create(rene, time.Now().Unix(), "title", "message") - require.Nil(t, err) + require.NoError(t, err) id1 := op.Id() require.NoError(t, id1.Validate()) err = b.Commit(repo) - require.Nil(t, err) + require.NoError(t, err) op2 := b.FirstOp() id2 := op2.Id() require.NoError(t, id2.Validate()) - require.Equal(t, id1, id2) b2, err := ReadLocal(repo, b.Id()) - require.Nil(t, err) + require.NoError(t, err) op3 := b2.FirstOp() id3 := op3.Id() require.NoError(t, id3.Validate()) - require.Equal(t, id1, id3) } } diff --git a/cache/bug_excerpt.go b/cache/bug_excerpt.go index 631c13cb..6a9e7f75 100644 --- a/cache/bug_excerpt.go +++ b/cache/bug_excerpt.go @@ -26,6 +26,7 @@ type BugExcerpt struct { CreateUnixTime int64 EditUnixTime int64 + AuthorId entity.Id Status bug.Status Labels []bug.Label Title string @@ -33,12 +34,6 @@ type BugExcerpt struct { Actors []entity.Id Participants []entity.Id - // If author is identity.Bare, LegacyAuthor is set - // If author is identity.Identity, AuthorId is set and data is deported - // in a IdentityExcerpt - LegacyAuthor LegacyAuthorExcerpt - AuthorId entity.Id - CreateMetadata map[string]string } @@ -94,11 +89,6 @@ func NewBugExcerpt(b bug.Interface, snap *bug.Snapshot) *BugExcerpt { switch snap.Author.(type) { case *identity.Identity, *IdentityCache: e.AuthorId = snap.Author.Id() - case *identity.Bare: - e.LegacyAuthor = LegacyAuthorExcerpt{ - Login: snap.Author.Login(), - Name: snap.Author.Name(), - } default: panic("unhandled identity type") } diff --git a/cache/filter.go b/cache/filter.go index 166cd48d..2ac56ab5 100644 --- a/cache/filter.go +++ b/cache/filter.go @@ -29,19 +29,12 @@ func AuthorFilter(query string) Filter { return func(excerpt *BugExcerpt, resolver resolver) bool { query = strings.ToLower(query) - // Normal identity - if excerpt.AuthorId != "" { - author, err := resolver.ResolveIdentityExcerpt(excerpt.AuthorId) - if err != nil { - panic(err) - } - - return author.Match(query) + author, err := resolver.ResolveIdentityExcerpt(excerpt.AuthorId) + if err != nil { + panic(err) } - // Legacy identity support - return strings.Contains(strings.ToLower(excerpt.LegacyAuthor.Name), query) || - strings.Contains(strings.ToLower(excerpt.LegacyAuthor.Login), query) + return author.Match(query) } } diff --git a/cache/repo_cache.go b/cache/repo_cache.go index 51302932..4fc88015 100644 --- a/cache/repo_cache.go +++ b/cache/repo_cache.go @@ -19,7 +19,8 @@ import ( // 1: original format // 2: added cache for identities with a reference in the bug cache -const formatVersion = 2 +// 3: no more legacy identity +const formatVersion = 3 // The maximum number of bugs loaded in memory. After that, eviction will be done. const defaultMaxLoadedBugs = 1000 diff --git a/commands/ls.go b/commands/ls.go index 9eaabb12..fa653378 100644 --- a/commands/ls.go +++ b/commands/ls.go @@ -151,15 +151,11 @@ func lsJsonFormatter(env *Env, bugExcerpts []*cache.BugExcerpt) error { Metadata: b.CreateMetadata, } - if b.AuthorId != "" { - author, err := env.backend.ResolveIdentityExcerpt(b.AuthorId) - if err != nil { - return err - } - jsonBug.Author = NewJSONIdentityFromExcerpt(author) - } else { - jsonBug.Author = NewJSONIdentityFromLegacyExcerpt(&b.LegacyAuthor) + author, err := env.backend.ResolveIdentityExcerpt(b.AuthorId) + if err != nil { + return err } + jsonBug.Author = NewJSONIdentityFromExcerpt(author) jsonBug.Actors = make([]JSONIdentity, len(b.Actors)) for i, element := range b.Actors { @@ -188,15 +184,9 @@ func lsJsonFormatter(env *Env, bugExcerpts []*cache.BugExcerpt) error { func lsDefaultFormatter(env *Env, bugExcerpts []*cache.BugExcerpt) error { for _, b := range bugExcerpts { - var name string - if b.AuthorId != "" { - author, err := env.backend.ResolveIdentityExcerpt(b.AuthorId) - if err != nil { - return err - } - name = author.DisplayName() - } else { - name = b.LegacyAuthor.DisplayName() + author, err := env.backend.ResolveIdentityExcerpt(b.AuthorId) + if err != nil { + return err } var labelsTxt strings.Builder @@ -210,7 +200,7 @@ func lsDefaultFormatter(env *Env, bugExcerpts []*cache.BugExcerpt) error { // truncate + pad if needed labelsFmt := text.TruncateMax(labelsTxt.String(), 10) titleFmt := text.LeftPadMaxLine(strings.TrimSpace(b.Title), 50-text.Len(labelsFmt), 0) - authorFmt := text.LeftPadMaxLine(name, 15, 0) + authorFmt := text.LeftPadMaxLine(author.DisplayName(), 15, 0) comments := fmt.Sprintf("%3d 💬", b.LenComments-1) if b.LenComments-1 <= 0 { @@ -261,15 +251,9 @@ func lsOrgmodeFormatter(env *Env, bugExcerpts []*cache.BugExcerpt) error { title = b.Title } - var name string - if b.AuthorId != "" { - author, err := env.backend.ResolveIdentityExcerpt(b.AuthorId) - if err != nil { - return err - } - name = author.DisplayName() - } else { - name = b.LegacyAuthor.DisplayName() + author, err := env.backend.ResolveIdentityExcerpt(b.AuthorId) + if err != nil { + return err } var labels strings.Builder @@ -286,7 +270,7 @@ func lsOrgmodeFormatter(env *Env, bugExcerpts []*cache.BugExcerpt) error { status, b.Id.Human(), formatTime(b.CreateTime()), - name, + author.DisplayName(), title, labels.String(), ) diff --git a/identity/bare.go b/identity/bare.go deleted file mode 100644 index e6ae2384..00000000 --- a/identity/bare.go +++ /dev/null @@ -1,218 +0,0 @@ -package identity - -import ( - "crypto/sha256" - "encoding/json" - "fmt" - "strings" - - "github.com/MichaelMure/git-bug/entity" - "github.com/MichaelMure/git-bug/repository" - "github.com/MichaelMure/git-bug/util/lamport" - "github.com/MichaelMure/git-bug/util/text" - "github.com/MichaelMure/git-bug/util/timestamp" -) - -var _ Interface = &Bare{} -var _ entity.Interface = &Bare{} - -// Bare is a very minimal identity, designed to be fully embedded directly along -// other data. -// -// in particular, this identity is designed to be compatible with the handling of -// identities in the early version of git-bug. -// Deprecated: legacy identity for compat, might make sense to ditch entirely for -// simplicity but that would be a breaking change. -type Bare struct { - id entity.Id - name string - email string - login string - avatarUrl string -} - -func NewBare(name string, email string) *Bare { - return &Bare{id: entity.UnsetId, name: name, email: email} -} - -func NewBareFull(name string, email string, login string, avatarUrl string) *Bare { - return &Bare{id: entity.UnsetId, name: name, email: email, login: login, avatarUrl: avatarUrl} -} - -func deriveId(data []byte) entity.Id { - sum := sha256.Sum256(data) - return entity.Id(fmt.Sprintf("%x", sum)) -} - -type bareIdentityJSON struct { - Name string `json:"name,omitempty"` - Email string `json:"email,omitempty"` - Login string `json:"login,omitempty"` - AvatarUrl string `json:"avatar_url,omitempty"` -} - -func (i *Bare) MarshalJSON() ([]byte, error) { - return json.Marshal(bareIdentityJSON{ - Name: i.name, - Email: i.email, - Login: i.login, - AvatarUrl: i.avatarUrl, - }) -} - -func (i *Bare) UnmarshalJSON(data []byte) error { - // Compute the Id when loading the op from disk. - i.id = deriveId(data) - - aux := bareIdentityJSON{} - - if err := json.Unmarshal(data, &aux); err != nil { - return err - } - - i.name = aux.Name - i.email = aux.Email - i.login = aux.Login - i.avatarUrl = aux.AvatarUrl - - return nil -} - -// Id return the Identity identifier -func (i *Bare) Id() entity.Id { - // We don't have a proper Id at hand, so let's hash all the data to get one. - - if i.id == "" { - // something went really wrong - panic("identity's id not set") - } - if i.id == entity.UnsetId { - // This means we are trying to get the identity identifier *before* it has been stored - // As the Id is computed based on the actual bytes written on the disk, we are going to predict - // those and then get the Id. This is safe as it will be the exact same code writing on disk later. - - data, err := json.Marshal(i) - if err != nil { - panic(err) - } - - i.id = deriveId(data) - } - return i.id -} - -// Name return the last version of the name -func (i *Bare) Name() string { - return i.name -} - -// Email return the last version of the email -func (i *Bare) Email() string { - return i.email -} - -// Login return the last version of the login -func (i *Bare) Login() string { - return i.login -} - -// AvatarUrl return the last version of the Avatar URL -func (i *Bare) AvatarUrl() string { - return i.avatarUrl -} - -// Keys return the last version of the valid keys -func (i *Bare) Keys() []*Key { - return nil -} - -// ValidKeysAtTime return the set of keys valid at a given lamport time -func (i *Bare) ValidKeysAtTime(_ lamport.Time) []*Key { - return nil -} - -// DisplayName return a non-empty string to display, representing the -// identity, based on the non-empty values. -func (i *Bare) 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") -} - -// Validate check if the Identity data is valid -func (i *Bare) Validate() error { - if text.Empty(i.name) && text.Empty(i.login) { - return fmt.Errorf("either name or login should be set") - } - - if strings.Contains(i.name, "\n") { - return fmt.Errorf("name should be a single line") - } - - if !text.Safe(i.name) { - return fmt.Errorf("name is not fully printable") - } - - if strings.Contains(i.login, "\n") { - return fmt.Errorf("login should be a single line") - } - - if !text.Safe(i.login) { - return fmt.Errorf("login is not fully printable") - } - - if strings.Contains(i.email, "\n") { - return fmt.Errorf("email should be a single line") - } - - if !text.Safe(i.email) { - return fmt.Errorf("email is not fully printable") - } - - if i.avatarUrl != "" && !text.ValidUrl(i.avatarUrl) { - return fmt.Errorf("avatarUrl is not a valid URL") - } - - return nil -} - -// Write the identity into the Repository. In particular, this ensure that -// the Id is properly set. -func (i *Bare) CommitWithRepo(repo repository.ClockedRepo) error { - // Nothing to do, everything is directly embedded - return nil -} - -// If needed, write the identity into the Repository. In particular, this -// ensure that the Id is properly set. -func (i *Bare) CommitAsNeededWithRepo(repo repository.ClockedRepo) error { - // Nothing to do, everything is directly embedded - return nil -} - -// IsProtected return 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. -func (i *Bare) IsProtected() bool { - return false -} - -// LastModificationLamportTime return the Lamport time at which the last version of the identity became valid. -func (i *Bare) LastModificationLamport() lamport.Time { - return 0 -} - -// LastModification return the timestamp at which the last version of the identity became valid. -func (i *Bare) LastModification() timestamp.Timestamp { - return 0 -} - -func (i *Bare) NeedCommit() bool { - return false -} diff --git a/identity/bare_test.go b/identity/bare_test.go deleted file mode 100644 index 335c8d37..00000000 --- a/identity/bare_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package identity - -import ( - "encoding/json" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/MichaelMure/git-bug/entity" -) - -func TestBare_Id(t *testing.T) { - i := NewBare("name", "email") - id := i.Id() - expected := entity.Id("e18b853fbd89d5d40ca24811539c9a800c705abd9232f396954e8ca8bb63fa8a") - assert.Equal(t, expected, id) -} - -func TestBareSerialize(t *testing.T) { - before := &Bare{ - login: "login", - email: "email", - name: "name", - avatarUrl: "avatar", - } - - data, err := json.Marshal(before) - assert.NoError(t, err) - - var after Bare - err = json.Unmarshal(data, &after) - assert.NoError(t, err) - - before.id = after.id - - assert.Equal(t, before, &after) -} diff --git a/identity/common.go b/identity/common.go index 007e10d6..5c6445e9 100644 --- a/identity/common.go +++ b/identity/common.go @@ -33,18 +33,5 @@ func UnmarshalJSON(raw json.RawMessage) (Interface, error) { return nil, err } - // Fallback on a legacy Bare identity - b := &Bare{} - - err = json.Unmarshal(raw, b) - if err == nil && (b.name != "" || b.login != "") { - return b, nil - } - - // abort if we have an error other than the wrong type - if _, ok := err.(*json.UnmarshalTypeError); err != nil && !ok { - return nil, err - } - return nil, fmt.Errorf("unknown identity type") } diff --git a/identity/identity.go b/identity/identity.go index c960a1af..b7bf9e64 100644 --- a/identity/identity.go +++ b/identity/identity.go @@ -441,7 +441,7 @@ func (i *Identity) lastVersion() *Version { // Id return the Identity identifier func (i *Identity) Id() entity.Id { - if i.id == "" { + if i.id == "" || i.id == entity.UnsetId { // simply panic as it would be a coding error // (using an id of an identity not stored yet) panic("no id yet") diff --git a/identity/version.go b/identity/version.go index 8b6a7c24..73e4d7c7 100644 --- a/identity/version.go +++ b/identity/version.go @@ -13,6 +13,7 @@ import ( "github.com/MichaelMure/git-bug/util/text" ) +// 1: original format const formatVersion = 1 // Version is a complete set of information about an Identity at a point in time. diff --git a/termui/bug_table.go b/termui/bug_table.go index b8f20b76..d3a187db 100644 --- a/termui/bug_table.go +++ b/termui/bug_table.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/MichaelMure/go-term-text" + text "github.com/MichaelMure/go-term-text" "github.com/awesome-gocui/gocui" "github.com/dustin/go-humanize" @@ -314,33 +314,25 @@ func (bt *bugTable) render(v *gocui.View, maxX int) { labelsTxt.WriteString(lc256.Unescape()) } - var authorDisplayName string - if excerpt.AuthorId != "" { - author, err := bt.repo.ResolveIdentityExcerpt(excerpt.AuthorId) - if err != nil { - panic(err) - } - authorDisplayName = author.DisplayName() - } else { - authorDisplayName = excerpt.LegacyAuthor.DisplayName() + author, err := bt.repo.ResolveIdentityExcerpt(excerpt.AuthorId) + if err != nil { + panic(err) } - lastEditTime := excerpt.EditTime() - id := text.LeftPadMaxLine(excerpt.Id.Human(), columnWidths["id"], 0) status := text.LeftPadMaxLine(excerpt.Status.String(), columnWidths["status"], 0) labels := text.TruncateMax(labelsTxt.String(), minInt(columnWidths["title"]-2, 10)) title := text.LeftPadMaxLine(strings.TrimSpace(excerpt.Title), columnWidths["title"]-text.Len(labels), 0) - author := text.LeftPadMaxLine(authorDisplayName, columnWidths["author"], 0) + authorTxt := text.LeftPadMaxLine(author.DisplayName(), columnWidths["author"], 0) comments := text.LeftPadMaxLine(summaryTxt, columnWidths["comments"], 0) - lastEdit := text.LeftPadMaxLine(humanize.Time(lastEditTime), columnWidths["lastEdit"], 1) + lastEdit := text.LeftPadMaxLine(humanize.Time(excerpt.EditTime()), columnWidths["lastEdit"], 1) _, _ = fmt.Fprintf(v, "%s %s %s%s %s %s %s\n", colors.Cyan(id), colors.Yellow(status), title, labels, - colors.Magenta(author), + colors.Magenta(authorTxt), comments, lastEdit, ) -- cgit