aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2019-02-19 00:19:27 +0100
committerMichael Muré <batolettre@gmail.com>2019-03-01 22:40:27 +0100
commit71f9290fdae7551f3d3ada2179ece4084304d734 (patch)
tree3494e4d4491012899ace256f534f5faea1ba2a88
parentffe35fece1b1526949107f154abc21a1a02fc74d (diff)
downloadgit-bug-71f9290fdae7551f3d3ada2179ece4084304d734.tar.gz
identity: store the times properly
-rw-r--r--bug/operation_pack.go2
-rw-r--r--cache/repo_cache.go2
-rw-r--r--commands/user.go2
-rw-r--r--identity/bare.go11
-rw-r--r--identity/identity.go13
-rw-r--r--identity/identity_stub.go4
-rw-r--r--identity/interface.go10
-rw-r--r--identity/version.go19
-rw-r--r--repository/git.go12
-rw-r--r--repository/mock_repo.go10
-rw-r--r--repository/repo.go7
11 files changed, 71 insertions, 21 deletions
diff --git a/bug/operation_pack.go b/bug/operation_pack.go
index 55fc018e..5f3e9da8 100644
--- a/bug/operation_pack.go
+++ b/bug/operation_pack.go
@@ -138,7 +138,7 @@ func (opp *OperationPack) Validate() error {
// Write will serialize and store the OperationPack as a git blob and return
// its hash
-func (opp *OperationPack) Write(repo repository.Repo) (git.Hash, error) {
+func (opp *OperationPack) Write(repo repository.ClockedRepo) (git.Hash, error) {
// make sure we don't write invalid data
err := opp.Validate()
if err != nil {
diff --git a/cache/repo_cache.go b/cache/repo_cache.go
index d5768125..e87119fe 100644
--- a/cache/repo_cache.go
+++ b/cache/repo_cache.go
@@ -712,7 +712,7 @@ func (c *RepoCache) ResolveIdentityPrefix(prefix string) (*IdentityCache, error)
// preallocate but empty
matching := make([]string, 0, 5)
- for id := range c.identities {
+ for id := range c.identitiesExcerpts {
if strings.HasPrefix(id, prefix) {
matching = append(matching, id)
}
diff --git a/commands/user.go b/commands/user.go
index e7a1da63..64482555 100644
--- a/commands/user.go
+++ b/commands/user.go
@@ -23,8 +23,6 @@ func runUser(cmd *cobra.Command, args []string) error {
var id *cache.IdentityCache
if len(args) == 1 {
- // TODO
- return errors.New("this is not working yet, cache need to be hacked on")
id, err = backend.ResolveIdentityPrefix(args[0])
} else {
id, err = backend.GetUserIdentity()
diff --git a/identity/bare.go b/identity/bare.go
index c54277a0..d3f7655a 100644
--- a/identity/bare.go
+++ b/identity/bare.go
@@ -65,6 +65,7 @@ func (i *Bare) UnmarshalJSON(data []byte) error {
return nil
}
+// Id return the Identity identifier
func (i *Bare) Id() string {
// We don't have a proper ID at hand, so let's hash all the data to get one.
// Hopefully the
@@ -84,18 +85,22 @@ func (i *Bare) Id() string {
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
}
@@ -164,12 +169,14 @@ func (i *Bare) Validate() error {
// Write the identity into the Repository. In particular, this ensure that
// the Id is properly set.
-func (i *Bare) Commit(repo repository.Repo) error {
+func (i *Bare) Commit(repo repository.ClockedRepo) error {
// Nothing to do, everything is directly embedded
return nil
}
-func (i *Bare) CommitAsNeeded(repo repository.Repo) error {
+// If needed, write the identity into the Repository. In particular, this
+// ensure that the Id is properly set.
+func (i *Bare) CommitAsNeeded(repo repository.ClockedRepo) error {
// Nothing to do, everything is directly embedded
return nil
}
diff --git a/identity/identity.go b/identity/identity.go
index 193a3013..b9d40967 100644
--- a/identity/identity.go
+++ b/identity/identity.go
@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"strings"
+ "time"
"github.com/pkg/errors"
@@ -252,8 +253,8 @@ func (i *Identity) AddVersion(version *Version) {
// Write the identity into the Repository. In particular, this ensure that
// the Id is properly set.
-func (i *Identity) Commit(repo repository.Repo) error {
- // Todo: check for mismatch between memory and commited data
+func (i *Identity) Commit(repo repository.ClockedRepo) error {
+ // Todo: check for mismatch between memory and commit data
if !i.NeedCommit() {
return fmt.Errorf("can't commit an identity with no pending version")
@@ -266,10 +267,14 @@ func (i *Identity) Commit(repo repository.Repo) error {
for _, v := range i.versions {
if v.commitHash != "" {
i.lastCommit = v.commitHash
- // ignore already commited versions
+ // ignore already commit versions
continue
}
+ // get the times where new versions starts to be valid
+ v.time = repo.EditTime()
+ v.unixTime = time.Now().Unix()
+
blobHash, err := v.Write(repo)
if err != nil {
return err
@@ -319,7 +324,7 @@ func (i *Identity) Commit(repo repository.Repo) error {
return nil
}
-func (i *Identity) CommitAsNeeded(repo repository.Repo) error {
+func (i *Identity) CommitAsNeeded(repo repository.ClockedRepo) error {
if !i.NeedCommit() {
return nil
}
diff --git a/identity/identity_stub.go b/identity/identity_stub.go
index e91600b0..830cfb99 100644
--- a/identity/identity_stub.go
+++ b/identity/identity_stub.go
@@ -76,11 +76,11 @@ func (IdentityStub) Validate() error {
panic("identities needs to be properly loaded with identity.ReadLocal()")
}
-func (IdentityStub) Commit(repo repository.Repo) error {
+func (IdentityStub) Commit(repo repository.ClockedRepo) error {
panic("identities needs to be properly loaded with identity.ReadLocal()")
}
-func (i *IdentityStub) CommitAsNeeded(repo repository.Repo) error {
+func (i *IdentityStub) CommitAsNeeded(repo repository.ClockedRepo) error {
panic("identities needs to be properly loaded with identity.ReadLocal()")
}
diff --git a/identity/interface.go b/identity/interface.go
index 55877c02..9fe4db4f 100644
--- a/identity/interface.go
+++ b/identity/interface.go
@@ -6,13 +6,17 @@ import (
)
type Interface interface {
+ // Id return the Identity identifier
Id() string
+ // Name return the last version of the name
Name() string
+ // Email return the last version of the email
Email() string
+ // Login return the last version of the login
Login() string
+ // AvatarUrl return the last version of the Avatar URL
AvatarUrl() string
-
// Keys return the last version of the valid keys
Keys() []Key
@@ -28,11 +32,11 @@ type Interface interface {
// Write the identity into the Repository. In particular, this ensure that
// the Id is properly set.
- Commit(repo repository.Repo) error
+ Commit(repo repository.ClockedRepo) error
// If needed, write the identity into the Repository. In particular, this
// ensure that the Id is properly set.
- CommitAsNeeded(repo repository.Repo) error
+ CommitAsNeeded(repo repository.ClockedRepo) error
// 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.
diff --git a/identity/version.go b/identity/version.go
index 90bf83f2..6ffffd99 100644
--- a/identity/version.go
+++ b/identity/version.go
@@ -17,14 +17,11 @@ const formatVersion = 1
// Version is a complete set of information about an Identity at a point in time.
type Version struct {
- // Not serialized
- commitHash git.Hash
-
- // Todo: add unix timestamp for ordering with identical lamport time ?
-
// The lamport time at which this version become effective
// The reference time is the bug edition lamport clock
- time lamport.Time
+ // It must be the first field in this struct due to https://github.com/golang/go/issues/599
+ time lamport.Time
+ unixTime int64
name string
email string
@@ -43,6 +40,9 @@ type Version struct {
// A set of arbitrary key/value to store metadata about a version or about an Identity in general.
metadata map[string]string
+
+ // Not serialized
+ commitHash git.Hash
}
type VersionJSON struct {
@@ -50,6 +50,7 @@ type VersionJSON struct {
FormatVersion uint `json:"version"`
Time lamport.Time `json:"time"`
+ UnixTime int64 `json:"unix_time"`
Name string `json:"name"`
Email string `json:"email"`
Login string `json:"login"`
@@ -63,6 +64,7 @@ func (v *Version) MarshalJSON() ([]byte, error) {
return json.Marshal(VersionJSON{
FormatVersion: formatVersion,
Time: v.time,
+ UnixTime: v.unixTime,
Name: v.name,
Email: v.email,
Login: v.login,
@@ -85,6 +87,7 @@ func (v *Version) UnmarshalJSON(data []byte) error {
}
v.time = aux.Time
+ v.unixTime = aux.UnixTime
v.name = aux.Name
v.email = aux.Email
v.login = aux.Login
@@ -97,6 +100,10 @@ func (v *Version) UnmarshalJSON(data []byte) error {
}
func (v *Version) Validate() error {
+ if v.unixTime == 0 {
+ return fmt.Errorf("unix time not set")
+ }
+
if text.Empty(v.name) && text.Empty(v.login) {
return fmt.Errorf("either name or login should be set")
}
diff --git a/repository/git.go b/repository/git.go
index 10fddac3..836de8f0 100644
--- a/repository/git.go
+++ b/repository/git.go
@@ -20,6 +20,8 @@ const editClockFile = "/.git/git-bug/edit-clock"
// ErrNotARepo is the error returned when the git repo root wan't be found
var ErrNotARepo = errors.New("not a git repository")
+var _ ClockedRepo = &GitRepo{}
+
// GitRepo represents an instance of a (local) git repository.
type GitRepo struct {
Path string
@@ -440,11 +442,21 @@ func (repo *GitRepo) WriteClocks() error {
return nil
}
+// CreateTime return the current value of the creation clock
+func (repo *GitRepo) CreateTime() lamport.Time {
+ return repo.createClock.Time()
+}
+
// CreateTimeIncrement increment the creation clock and return the new value.
func (repo *GitRepo) CreateTimeIncrement() (lamport.Time, error) {
return repo.createClock.Increment()
}
+// EditTime return the current value of the edit clock
+func (repo *GitRepo) EditTime() lamport.Time {
+ return repo.editClock.Time()
+}
+
// EditTimeIncrement increment the edit clock and return the new value.
func (repo *GitRepo) EditTimeIncrement() (lamport.Time, error) {
return repo.editClock.Increment()
diff --git a/repository/mock_repo.go b/repository/mock_repo.go
index 74de8f57..97a4504f 100644
--- a/repository/mock_repo.go
+++ b/repository/mock_repo.go
@@ -9,6 +9,8 @@ import (
"github.com/MichaelMure/git-bug/util/lamport"
)
+var _ ClockedRepo = &mockRepoForTest{}
+
// mockRepoForTest defines an instance of Repo that can be used for testing.
type mockRepoForTest struct {
config map[string]string
@@ -227,10 +229,18 @@ func (r *mockRepoForTest) WriteClocks() error {
return nil
}
+func (r *mockRepoForTest) CreateTime() lamport.Time {
+ return r.createClock.Time()
+}
+
func (r *mockRepoForTest) CreateTimeIncrement() (lamport.Time, error) {
return r.createClock.Increment(), nil
}
+func (r *mockRepoForTest) EditTime() lamport.Time {
+ return r.editClock.Time()
+}
+
func (r *mockRepoForTest) EditTimeIncrement() (lamport.Time, error) {
return r.editClock.Increment(), nil
}
diff --git a/repository/repo.go b/repository/repo.go
index 100feaed..8a66c320 100644
--- a/repository/repo.go
+++ b/repository/repo.go
@@ -83,6 +83,7 @@ type Repo interface {
GetTreeHash(commit git.Hash) (git.Hash, error)
}
+// ClockedRepo is a Repo that also has Lamport clocks
type ClockedRepo interface {
Repo
@@ -92,9 +93,15 @@ type ClockedRepo interface {
// WriteClocks write the clocks values into the repo
WriteClocks() error
+ // CreateTime return the current value of the creation clock
+ CreateTime() lamport.Time
+
// CreateTimeIncrement increment the creation clock and return the new value.
CreateTimeIncrement() (lamport.Time, error)
+ // EditTime return the current value of the edit clock
+ EditTime() lamport.Time
+
// EditTimeIncrement increment the edit clock and return the new value.
EditTimeIncrement() (lamport.Time, error)