aboutsummaryrefslogtreecommitdiffstats
path: root/repository
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2020-11-08 17:54:28 +0100
committerMichael Muré <batolettre@gmail.com>2021-02-14 12:15:41 +0100
commitfb0c5fd06184f33a03d8d4fb29a3aef8b1dafe78 (patch)
treea0d87d04a991368840645591f11284b7ea27160c /repository
parent44d7587940f842a343a64d9107601591bdfb1027 (diff)
downloadgit-bug-fb0c5fd06184f33a03d8d4fb29a3aef8b1dafe78.tar.gz
repo: expose all lamport clocks, move clocks in their own folder
Diffstat (limited to 'repository')
-rw-r--r--repository/git.go98
-rw-r--r--repository/gogit.go55
-rw-r--r--repository/mock_repo.go70
-rw-r--r--repository/mock_repo_test.go2
-rw-r--r--repository/repo.go11
-rw-r--r--repository/repo_testing.go13
6 files changed, 207 insertions, 42 deletions
diff --git a/repository/git.go b/repository/git.go
index bc9d8772..57c07c89 100644
--- a/repository/git.go
+++ b/repository/git.go
@@ -4,6 +4,7 @@ package repository
import (
"bytes"
"fmt"
+ "io/ioutil"
"os"
"path/filepath"
"strings"
@@ -16,10 +17,6 @@ import (
"github.com/MichaelMure/git-bug/util/lamport"
)
-const (
- clockPath = "git-bug"
-)
-
var _ ClockedRepo = &GitRepo{}
var _ TestedRepo = &GitRepo{}
@@ -34,7 +31,8 @@ type GitRepo struct {
indexesMutex sync.Mutex
indexes map[string]bleve.Index
- keyring Keyring
+ keyring Keyring
+ localStorage billy.Filesystem
}
// OpenGitRepo determines if the given working directory is inside of a git repository,
@@ -66,6 +64,7 @@ func OpenGitRepo(path string, clockLoaders []ClockLoader) (*GitRepo, error) {
// Fix the path to be sure we are at the root
repo.path = stdout
repo.gitCli.path = stdout
+ repo.localStorage = osfs.New(filepath.Join(path, "git-bug"))
for _, loader := range clockLoaders {
allExist := true
@@ -88,14 +87,21 @@ func OpenGitRepo(path string, clockLoaders []ClockLoader) (*GitRepo, error) {
// InitGitRepo create a new empty git repo at the given path
func InitGitRepo(path string) (*GitRepo, error) {
+ k, err := defaultKeyring()
+ if err != nil {
+ return nil, err
+ }
+
repo := &GitRepo{
- gitCli: gitCli{path: path},
- path: path + "/.git",
- clocks: make(map[string]lamport.Clock),
- indexes: make(map[string]bleve.Index),
+ gitCli: gitCli{path: path},
+ path: filepath.Join(path, ".git"),
+ clocks: make(map[string]lamport.Clock),
+ indexes: make(map[string]bleve.Index),
+ keyring: k,
+ localStorage: osfs.New(filepath.Join(path, ".git", "git-bug")),
}
- _, err := repo.runGitCommand("init", path)
+ _, err = repo.runGitCommand("init", path)
if err != nil {
return nil, err
}
@@ -105,14 +111,21 @@ func InitGitRepo(path string) (*GitRepo, error) {
// InitBareGitRepo create a new --bare empty git repo at the given path
func InitBareGitRepo(path string) (*GitRepo, error) {
+ k, err := defaultKeyring()
+ if err != nil {
+ return nil, err
+ }
+
repo := &GitRepo{
- gitCli: gitCli{path: path},
- path: path,
- clocks: make(map[string]lamport.Clock),
- indexes: make(map[string]bleve.Index),
+ gitCli: gitCli{path: path},
+ path: path,
+ clocks: make(map[string]lamport.Clock),
+ indexes: make(map[string]bleve.Index),
+ keyring: k,
+ localStorage: osfs.New(filepath.Join(path, "git-bug")),
}
- _, err := repo.runGitCommand("init", "--bare", path)
+ _, err = repo.runGitCommand("init", "--bare", path)
if err != nil {
return nil, err
}
@@ -198,7 +211,7 @@ func (repo *GitRepo) GetRemotes() (map[string]string, error) {
// LocalStorage return a billy.Filesystem giving access to $RepoPath/.git/git-bug
func (repo *GitRepo) LocalStorage() billy.Filesystem {
- return osfs.New(repo.path)
+ return repo.localStorage
}
// GetBleveIndex return a bleve.Index that can be used to index documents
@@ -434,6 +447,37 @@ func (repo *GitRepo) GetTreeHash(commit Hash) (Hash, error) {
return Hash(stdout), nil
}
+func (repo *GitRepo) AllClocks() (map[string]lamport.Clock, error) {
+ repo.clocksMutex.Lock()
+ defer repo.clocksMutex.Unlock()
+
+ result := make(map[string]lamport.Clock)
+
+ files, err := ioutil.ReadDir(filepath.Join(repo.path, "git-bug", clockPath))
+ if os.IsNotExist(err) {
+ return nil, nil
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ for _, file := range files {
+ name := file.Name()
+ if c, ok := repo.clocks[name]; ok {
+ result[name] = c
+ } else {
+ c, err := lamport.LoadPersistedClock(repo.LocalStorage(), filepath.Join(clockPath, name))
+ if err != nil {
+ return nil, err
+ }
+ repo.clocks[name] = c
+ result[name] = c
+ }
+ }
+
+ return result, nil
+}
+
// GetOrCreateClock return a Lamport clock stored in the Repo.
// If the clock doesn't exist, it's created.
func (repo *GitRepo) GetOrCreateClock(name string) (lamport.Clock, error) {
@@ -448,7 +492,7 @@ func (repo *GitRepo) GetOrCreateClock(name string) (lamport.Clock, error) {
return nil, err
}
- c, err = lamport.NewPersistedClock(repo.LocalStorage(), name+"-clock")
+ c, err = lamport.NewPersistedClock(repo.LocalStorage(), filepath.Join(clockPath, name))
if err != nil {
return nil, err
}
@@ -462,7 +506,7 @@ func (repo *GitRepo) getClock(name string) (lamport.Clock, error) {
return c, nil
}
- c, err := lamport.LoadPersistedClock(repo.LocalStorage(), name+"-clock")
+ c, err := lamport.LoadPersistedClock(repo.LocalStorage(), filepath.Join(clockPath, name))
if err == nil {
repo.clocks[name] = c
return c, nil
@@ -473,6 +517,24 @@ func (repo *GitRepo) getClock(name string) (lamport.Clock, error) {
return nil, err
}
+// Increment is equivalent to c = GetOrCreateClock(name) + c.Increment()
+func (repo *GitRepo) Increment(name string) (lamport.Time, error) {
+ c, err := repo.GetOrCreateClock(name)
+ if err != nil {
+ return lamport.Time(0), err
+ }
+ return c.Increment()
+}
+
+// Witness is equivalent to c = GetOrCreateClock(name) + c.Witness(time)
+func (repo *GitRepo) Witness(name string, time lamport.Time) error {
+ c, err := repo.GetOrCreateClock(name)
+ if err != nil {
+ return err
+ }
+ return c.Witness(time)
+}
+
// AddRemote add a new remote to the repository
// Not in the interface because it's only used for testing
func (repo *GitRepo) AddRemote(name string, url string) error {
diff --git a/repository/gogit.go b/repository/gogit.go
index bdac259d..5abdef39 100644
--- a/repository/gogit.go
+++ b/repository/gogit.go
@@ -24,6 +24,8 @@ import (
"github.com/MichaelMure/git-bug/util/lamport"
)
+const clockPath = "clocks"
+
var _ ClockedRepo = &GoGitRepo{}
var _ TestedRepo = &GoGitRepo{}
@@ -677,6 +679,37 @@ func (repo *GoGitRepo) ListCommits(ref string) ([]Hash, error) {
return hashes, nil
}
+func (repo *GoGitRepo) AllClocks() (map[string]lamport.Clock, error) {
+ repo.clocksMutex.Lock()
+ defer repo.clocksMutex.Unlock()
+
+ result := make(map[string]lamport.Clock)
+
+ files, err := ioutil.ReadDir(filepath.Join(repo.path, "git-bug", clockPath))
+ if os.IsNotExist(err) {
+ return nil, nil
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ for _, file := range files {
+ name := file.Name()
+ if c, ok := repo.clocks[name]; ok {
+ result[name] = c
+ } else {
+ c, err := lamport.LoadPersistedClock(repo.LocalStorage(), filepath.Join(clockPath, name))
+ if err != nil {
+ return nil, err
+ }
+ repo.clocks[name] = c
+ result[name] = c
+ }
+ }
+
+ return result, nil
+}
+
// GetOrCreateClock return a Lamport clock stored in the Repo.
// If the clock doesn't exist, it's created.
func (repo *GoGitRepo) GetOrCreateClock(name string) (lamport.Clock, error) {
@@ -691,7 +724,7 @@ func (repo *GoGitRepo) GetOrCreateClock(name string) (lamport.Clock, error) {
return nil, err
}
- c, err = lamport.NewPersistedClock(repo.localStorage, name+"-clock")
+ c, err = lamport.NewPersistedClock(repo.LocalStorage(), filepath.Join(clockPath, name))
if err != nil {
return nil, err
}
@@ -705,7 +738,7 @@ func (repo *GoGitRepo) getClock(name string) (lamport.Clock, error) {
return c, nil
}
- c, err := lamport.LoadPersistedClock(repo.localStorage, name+"-clock")
+ c, err := lamport.LoadPersistedClock(repo.LocalStorage(), filepath.Join(clockPath, name))
if err == nil {
repo.clocks[name] = c
return c, nil
@@ -716,6 +749,24 @@ func (repo *GoGitRepo) getClock(name string) (lamport.Clock, error) {
return nil, err
}
+// Increment is equivalent to c = GetOrCreateClock(name) + c.Increment()
+func (repo *GoGitRepo) Increment(name string) (lamport.Time, error) {
+ c, err := repo.GetOrCreateClock(name)
+ if err != nil {
+ return lamport.Time(0), err
+ }
+ return c.Increment()
+}
+
+// Witness is equivalent to c = GetOrCreateClock(name) + c.Witness(time)
+func (repo *GoGitRepo) Witness(name string, time lamport.Time) error {
+ c, err := repo.GetOrCreateClock(name)
+ if err != nil {
+ return err
+ }
+ return c.Witness(time)
+}
+
// AddRemote add a new remote to the repository
// Not in the interface because it's only used for testing
func (repo *GoGitRepo) AddRemote(name string, url string) error {
diff --git a/repository/mock_repo.go b/repository/mock_repo.go
index 8a1724ef..974c3fb2 100644
--- a/repository/mock_repo.go
+++ b/repository/mock_repo.go
@@ -14,11 +14,11 @@ import (
"github.com/MichaelMure/git-bug/util/lamport"
)
-var _ ClockedRepo = &mockRepoForTest{}
-var _ TestedRepo = &mockRepoForTest{}
+var _ ClockedRepo = &mockRepo{}
+var _ TestedRepo = &mockRepo{}
-// mockRepoForTest defines an instance of Repo that can be used for testing.
-type mockRepoForTest struct {
+// mockRepo defines an instance of Repo that can be used for testing.
+type mockRepo struct {
*mockRepoConfig
*mockRepoKeyring
*mockRepoCommon
@@ -26,12 +26,13 @@ type mockRepoForTest struct {
*mockRepoBleve
*mockRepoData
*mockRepoClock
+ *mockRepoTest
}
-func (m *mockRepoForTest) Close() error { return nil }
+func (m *mockRepo) Close() error { return nil }
-func NewMockRepoForTest() *mockRepoForTest {
- return &mockRepoForTest{
+func NewMockRepo() *mockRepo {
+ return &mockRepo{
mockRepoConfig: NewMockRepoConfig(),
mockRepoKeyring: NewMockRepoKeyring(),
mockRepoCommon: NewMockRepoCommon(),
@@ -39,6 +40,7 @@ func NewMockRepoForTest() *mockRepoForTest {
mockRepoBleve: newMockRepoBleve(),
mockRepoData: NewMockRepoData(),
mockRepoClock: NewMockRepoClock(),
+ mockRepoTest: NewMockRepoTest(),
}
}
@@ -371,18 +373,7 @@ func (r *mockRepoData) GetTreeHash(commit Hash) (Hash, error) {
return c.treeHash, nil
}
-func (r *mockRepoData) AddRemote(name string, url string) error {
- panic("implement me")
-}
-
-func (m mockRepoForTest) GetLocalRemote() string {
- panic("implement me")
-}
-
-func (m mockRepoForTest) EraseFromDisk() error {
- // nothing to do
- return nil
-}
+var _ RepoClock = &mockRepoClock{}
type mockRepoClock struct {
mu sync.Mutex
@@ -395,6 +386,10 @@ func NewMockRepoClock() *mockRepoClock {
}
}
+func (r *mockRepoClock) AllClocks() (map[string]lamport.Clock, error) {
+ return r.clocks, nil
+}
+
func (r *mockRepoClock) GetOrCreateClock(name string) (lamport.Clock, error) {
r.mu.Lock()
defer r.mu.Unlock()
@@ -407,3 +402,40 @@ func (r *mockRepoClock) GetOrCreateClock(name string) (lamport.Clock, error) {
r.clocks[name] = c
return c, nil
}
+
+func (r *mockRepoClock) Increment(name string) (lamport.Time, error) {
+ c, err := r.GetOrCreateClock(name)
+ if err != nil {
+ return lamport.Time(0), err
+ }
+ return c.Increment()
+}
+
+func (r *mockRepoClock) Witness(name string, time lamport.Time) error {
+ c, err := r.GetOrCreateClock(name)
+ if err != nil {
+ return err
+ }
+ return c.Witness(time)
+}
+
+var _ repoTest = &mockRepoTest{}
+
+type mockRepoTest struct{}
+
+func NewMockRepoTest() *mockRepoTest {
+ return &mockRepoTest{}
+}
+
+func (r *mockRepoTest) AddRemote(name string, url string) error {
+ panic("implement me")
+}
+
+func (r mockRepoTest) GetLocalRemote() string {
+ panic("implement me")
+}
+
+func (r mockRepoTest) EraseFromDisk() error {
+ // nothing to do
+ return nil
+}
diff --git a/repository/mock_repo_test.go b/repository/mock_repo_test.go
index b56b94f2..dec09380 100644
--- a/repository/mock_repo_test.go
+++ b/repository/mock_repo_test.go
@@ -3,7 +3,7 @@ package repository
import "testing"
func TestMockRepo(t *testing.T) {
- creator := func(bare bool) TestedRepo { return NewMockRepoForTest() }
+ creator := func(bare bool) TestedRepo { return NewMockRepo() }
cleaner := func(repos ...Repo) {}
RepoTest(t, creator, cleaner)
diff --git a/repository/repo.go b/repository/repo.go
index eb9296d4..625e0143 100644
--- a/repository/repo.go
+++ b/repository/repo.go
@@ -22,9 +22,9 @@ type Repo interface {
RepoConfig
RepoKeyring
RepoCommon
- RepoData
RepoStorage
RepoBleve
+ RepoData
Close() error
}
@@ -142,9 +142,18 @@ type RepoData interface {
// RepoClock give access to Lamport clocks
type RepoClock interface {
+ // AllClocks return all the known clocks
+ AllClocks() (map[string]lamport.Clock, error)
+
// GetOrCreateClock return a Lamport clock stored in the Repo.
// If the clock doesn't exist, it's created.
GetOrCreateClock(name string) (lamport.Clock, error)
+
+ // Increment is equivalent to c = GetOrCreateClock(name) + c.Increment()
+ Increment(name string) (lamport.Time, error)
+
+ // Witness is equivalent to c = GetOrCreateClock(name) + c.Witness(time)
+ Witness(name string, time lamport.Time) error
}
// ClockLoader hold which logical clock need to exist for an entity and
diff --git a/repository/repo_testing.go b/repository/repo_testing.go
index c0e1fa79..2c8705d6 100644
--- a/repository/repo_testing.go
+++ b/repository/repo_testing.go
@@ -191,13 +191,17 @@ func RepoDataTest(t *testing.T, repo RepoData) {
// helper to test a RepoClock
func RepoClockTest(t *testing.T, repo RepoClock) {
+ allClocks, err := repo.AllClocks()
+ require.NoError(t, err)
+ require.Len(t, allClocks, 0)
+
clock, err := repo.GetOrCreateClock("foo")
require.NoError(t, err)
require.Equal(t, lamport.Time(1), clock.Time())
time, err := clock.Increment()
require.NoError(t, err)
- require.Equal(t, lamport.Time(1), time)
+ require.Equal(t, lamport.Time(2), time)
require.Equal(t, lamport.Time(2), clock.Time())
clock2, err := repo.GetOrCreateClock("foo")
@@ -207,6 +211,13 @@ func RepoClockTest(t *testing.T, repo RepoClock) {
clock3, err := repo.GetOrCreateClock("bar")
require.NoError(t, err)
require.Equal(t, lamport.Time(1), clock3.Time())
+
+ allClocks, err = repo.AllClocks()
+ require.NoError(t, err)
+ require.Equal(t, map[string]lamport.Clock{
+ "foo": clock,
+ "bar": clock3,
+ }, allClocks)
}
func randomData() []byte {