aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2022-12-22 23:19:31 +0100
committerMichael Muré <batolettre@gmail.com>2022-12-23 01:41:03 +0100
commit95911100823b5c809225d664de74ad2d64e91972 (patch)
treec352848904d82b046646b4074f26b0ce5235fa40
parentd65e8837aa7bb1a6abb6892b9f2664e1b7edb02e (diff)
downloadgit-bug-95911100823b5c809225d664de74ad2d64e91972.tar.gz
cache: fix some bugs after refactor
-rw-r--r--bridge/github/export_test.go10
-rw-r--r--bridge/github/import_integration_test.go6
-rw-r--r--bridge/github/import_test.go5
-rw-r--r--bridge/gitlab/export_test.go10
-rw-r--r--bridge/gitlab/import_test.go5
-rw-r--r--cache/bug_subcache.go4
-rw-r--r--cache/cached.go6
-rw-r--r--cache/identity_cache.go14
-rw-r--r--cache/identity_subcache.go2
-rw-r--r--cache/multi_repo_cache.go12
-rw-r--r--cache/repo_cache.go34
-rw-r--r--cache/repo_cache_test.go52
-rw-r--r--cache/subcache.go18
-rw-r--r--commands/bug/select/select_test.go5
-rw-r--r--commands/execenv/env.go24
-rw-r--r--commands/execenv/env_testing.go5
-rw-r--r--commands/root.go2
-rw-r--r--commands/webui.go24
-rw-r--r--entities/bug/bug.go7
-rw-r--r--entities/identity/identity.go11
-rw-r--r--entities/identity/identity_actions.go4
-rw-r--r--repository/gogit.go3
-rw-r--r--util/multierr/errwaitgroup.go2
23 files changed, 149 insertions, 116 deletions
diff --git a/bridge/github/export_test.go b/bridge/github/export_test.go
index a2dbf7de..00d3c176 100644
--- a/bridge/github/export_test.go
+++ b/bridge/github/export_test.go
@@ -141,11 +141,8 @@ func TestGithubPushPull(t *testing.T) {
// create repo backend
repo := repository.CreateGoGitTestRepo(t, false)
- backend, events, err := cache.NewRepoCache(repo)
+ backend, err := cache.NewRepoCacheNoEvents(repo)
require.NoError(t, err)
- for event := range events {
- require.NoError(t, event.Err)
- }
// set author identity
login := "identity-test"
@@ -220,11 +217,8 @@ func TestGithubPushPull(t *testing.T) {
repoTwo := repository.CreateGoGitTestRepo(t, false)
// create a second backend
- backendTwo, events, err := cache.NewRepoCache(repoTwo)
+ backendTwo, err := cache.NewRepoCacheNoEvents(repoTwo)
require.NoError(t, err)
- for event := range events {
- require.NoError(t, event.Err)
- }
importer := &githubImporter{}
err = importer.Init(ctx, backend, core.Configuration{
diff --git a/bridge/github/import_integration_test.go b/bridge/github/import_integration_test.go
index 6a41517c..8c411d8d 100644
--- a/bridge/github/import_integration_test.go
+++ b/bridge/github/import_integration_test.go
@@ -34,11 +34,9 @@ func TestGithubImporterIntegration(t *testing.T) {
// arrange
repo := repository.CreateGoGitTestRepo(t, false)
- backend, buildEvents, err := cache.NewRepoCache(repo)
+ backend, err := cache.NewRepoCacheNoEvents(repo)
require.NoError(t, err)
- for event := range buildEvents {
- require.NoError(t, event.Err)
- }
+
defer backend.Close()
interrupt.RegisterCleaner(backend.Close)
require.NoError(t, err)
diff --git a/bridge/github/import_test.go b/bridge/github/import_test.go
index 6539a52f..5fafcce1 100644
--- a/bridge/github/import_test.go
+++ b/bridge/github/import_test.go
@@ -28,11 +28,8 @@ func TestGithubImporter(t *testing.T) {
repo := repository.CreateGoGitTestRepo(t, false)
- backend, buildEvents, err := cache.NewRepoCache(repo)
+ backend, err := cache.NewRepoCacheNoEvents(repo)
require.NoError(t, err)
- for event := range buildEvents {
- require.NoError(t, event.Err)
- }
defer backend.Close()
interrupt.RegisterCleaner(backend.Close)
diff --git a/bridge/gitlab/export_test.go b/bridge/gitlab/export_test.go
index 64bc43f4..7c826822 100644
--- a/bridge/gitlab/export_test.go
+++ b/bridge/gitlab/export_test.go
@@ -147,11 +147,8 @@ func TestGitlabPushPull(t *testing.T) {
// create repo backend
repo := repository.CreateGoGitTestRepo(t, false)
- backend, events, err := cache.NewRepoCache(repo)
+ backend, err := cache.NewRepoCacheNoEvents(repo)
require.NoError(t, err)
- for event := range events {
- require.NoError(t, event.Err)
- }
// set author identity
login := "test-identity"
@@ -223,11 +220,8 @@ func TestGitlabPushPull(t *testing.T) {
repoTwo := repository.CreateGoGitTestRepo(t, false)
// create a second backend
- backendTwo, events, err := cache.NewRepoCache(repoTwo)
+ backendTwo, err := cache.NewRepoCacheNoEvents(repoTwo)
require.NoError(t, err)
- for event := range events {
- require.NoError(t, event.Err)
- }
importer := &gitlabImporter{}
err = importer.Init(ctx, backend, core.Configuration{
diff --git a/bridge/gitlab/import_test.go b/bridge/gitlab/import_test.go
index ac91610d..bed93a80 100644
--- a/bridge/gitlab/import_test.go
+++ b/bridge/gitlab/import_test.go
@@ -33,11 +33,8 @@ func TestGitlabImport(t *testing.T) {
repo := repository.CreateGoGitTestRepo(t, false)
- backend, buildEvents, err := cache.NewRepoCache(repo)
+ backend, err := cache.NewRepoCacheNoEvents(repo)
require.NoError(t, err)
- for event := range buildEvents {
- require.NoError(t, event.Err)
- }
defer backend.Close()
interrupt.RegisterCleaner(backend.Close)
diff --git a/cache/bug_subcache.go b/cache/bug_subcache.go
index 14b56cdc..920fe1dc 100644
--- a/cache/bug_subcache.go
+++ b/cache/bug_subcache.go
@@ -44,7 +44,7 @@ func NewRepoCacheBug(repo repository.ClockedRepo,
sc := NewSubCache[*bug.Bug, *BugExcerpt, *BugCache](
repo, resolvers, getUserIdentity,
makeCached, NewBugExcerpt, makeIndexData, actions,
- "bug", "bugs",
+ bug.Typename, bug.Namespace,
formatVersion, defaultMaxLoadedBugs,
)
@@ -124,7 +124,7 @@ func (c *RepoCacheBug) Query(q *query.Query) ([]entity.Id, error) {
if q.Search != nil {
foundBySearch = map[entity.Id]*BugExcerpt{}
- index, err := c.repo.GetIndex("bug")
+ index, err := c.repo.GetIndex("bugs")
if err != nil {
return nil, err
}
diff --git a/cache/cached.go b/cache/cached.go
index ce1d6637..9f9e170d 100644
--- a/cache/cached.go
+++ b/cache/cached.go
@@ -9,6 +9,8 @@ import (
"github.com/MichaelMure/git-bug/util/lamport"
)
+var _ CacheEntity = &CachedEntityBase[dag.Snapshot, dag.Operation]{}
+
// CachedEntityBase provide the base function of an entity managed by the cache.
type CachedEntityBase[SnapT dag.Snapshot, OpT dag.Operation] struct {
repo repository.ClockedRepo
@@ -92,6 +94,10 @@ func (e *CachedEntityBase[SnapT, OpT]) NeedCommit() bool {
return e.entity.NeedCommit()
}
+func (e *CachedEntityBase[SnapT, OpT]) Lock() {
+ e.mu.Lock()
+}
+
func (e *CachedEntityBase[SnapT, OpT]) CreateLamportTime() lamport.Time {
return e.entity.CreateLamportTime()
}
diff --git a/cache/identity_cache.go b/cache/identity_cache.go
index 00f5ae95..466b6150 100644
--- a/cache/identity_cache.go
+++ b/cache/identity_cache.go
@@ -1,18 +1,22 @@
package cache
import (
+ "sync"
+
"github.com/MichaelMure/git-bug/entities/identity"
"github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/repository"
)
var _ identity.Interface = &IdentityCache{}
+var _ CacheEntity = &IdentityCache{}
// IdentityCache is a wrapper around an Identity for caching.
type IdentityCache struct {
repo repository.ClockedRepo
entityUpdated func(id entity.Id) error
+ mu sync.Mutex
*identity.Identity
}
@@ -29,7 +33,9 @@ func (i *IdentityCache) notifyUpdated() error {
}
func (i *IdentityCache) Mutate(repo repository.RepoClock, f func(*identity.Mutator)) error {
+ i.mu.Lock()
err := i.Identity.Mutate(repo, f)
+ i.mu.Unlock()
if err != nil {
return err
}
@@ -37,7 +43,9 @@ func (i *IdentityCache) Mutate(repo repository.RepoClock, f func(*identity.Mutat
}
func (i *IdentityCache) Commit() error {
+ i.mu.Lock()
err := i.Identity.Commit(i.repo)
+ i.mu.Unlock()
if err != nil {
return err
}
@@ -45,9 +53,15 @@ func (i *IdentityCache) Commit() error {
}
func (i *IdentityCache) CommitAsNeeded() error {
+ i.mu.Lock()
err := i.Identity.CommitAsNeeded(i.repo)
+ i.mu.Unlock()
if err != nil {
return err
}
return i.notifyUpdated()
}
+
+func (i *IdentityCache) Lock() {
+ i.mu.Lock()
+}
diff --git a/cache/identity_subcache.go b/cache/identity_subcache.go
index a623d0e1..f862ca8b 100644
--- a/cache/identity_subcache.go
+++ b/cache/identity_subcache.go
@@ -48,7 +48,7 @@ func NewRepoCacheIdentity(repo repository.ClockedRepo,
sc := NewSubCache[*identity.Identity, *IdentityExcerpt, *IdentityCache](
repo, resolvers, getUserIdentity,
makeCached, NewIdentityExcerpt, makeIndex, actions,
- "identity", "identities",
+ identity.Typename, identity.Namespace,
formatVersion, defaultMaxLoadedBugs,
)
diff --git a/cache/multi_repo_cache.go b/cache/multi_repo_cache.go
index 12d26e26..007737ad 100644
--- a/cache/multi_repo_cache.go
+++ b/cache/multi_repo_cache.go
@@ -21,13 +21,13 @@ func NewMultiRepoCache() *MultiRepoCache {
}
// RegisterRepository register a named repository. Use this for multi-repo setup
-func (c *MultiRepoCache) RegisterRepository(ref string, repo repository.ClockedRepo) (*RepoCache, chan BuildEvent, error) {
- r, events, err := NewRepoCache(repo)
+func (c *MultiRepoCache) RegisterRepository(name string, repo repository.ClockedRepo) (*RepoCache, chan BuildEvent, error) {
+ r, events, err := NewNamedRepoCache(repo, name)
if err != nil {
return nil, nil, err
}
- c.repos[ref] = r
+ c.repos[name] = r
return r, events, nil
}
@@ -55,9 +55,9 @@ func (c *MultiRepoCache) DefaultRepo() (*RepoCache, error) {
panic("unreachable")
}
-// ResolveRepo retrieve a repository with a reference
-func (c *MultiRepoCache) ResolveRepo(ref string) (*RepoCache, error) {
- r, ok := c.repos[ref]
+// ResolveRepo retrieve a repository by name
+func (c *MultiRepoCache) ResolveRepo(name string) (*RepoCache, error) {
+ r, ok := c.repos[name]
if !ok {
return nil, fmt.Errorf("unknown repo")
}
diff --git a/cache/repo_cache.go b/cache/repo_cache.go
index 2cac711b..7852ec7d 100644
--- a/cache/repo_cache.go
+++ b/cache/repo_cache.go
@@ -27,6 +27,7 @@ var _ repository.RepoCommon = &RepoCache{}
var _ repository.RepoConfig = &RepoCache{}
var _ repository.RepoKeyring = &RepoCache{}
+// cacheMgmt is the expected interface for a sub-cache.
type cacheMgmt interface {
Typename() string
Load() error
@@ -58,7 +59,7 @@ type RepoCache struct {
// the name of the repository, as defined in the MultiRepoCache
name string
- // resolvers for all known entities
+ // resolvers for all known entities and excerpts
resolvers entity.Resolvers
bugs *RepoCacheBug
@@ -71,10 +72,16 @@ type RepoCache struct {
userIdentityId entity.Id
}
+// NewRepoCache create or open an unnamed (aka default) cache on top of a raw repository.
+// If the returned BuildEvent channel is not nil, the caller is expected to read all events before the cache is considered
+// ready to use.
func NewRepoCache(r repository.ClockedRepo) (*RepoCache, chan BuildEvent, error) {
return NewNamedRepoCache(r, "")
}
+// NewNamedRepoCache create or open a named cache on top of a raw repository.
+// If the returned BuildEvent channel is not nil, the caller is expected to read all events before the cache is considered
+// ready to use.
func NewNamedRepoCache(r repository.ClockedRepo, name string) (*RepoCache, chan BuildEvent, error) {
c := &RepoCache{
repo: r,
@@ -96,16 +103,12 @@ func NewNamedRepoCache(r repository.ClockedRepo, name string) (*RepoCache, chan
err := c.lock()
if err != nil {
- closed := make(chan BuildEvent)
- close(closed)
- return &RepoCache{}, closed, err
+ return &RepoCache{}, nil, err
}
err = c.load()
if err == nil {
- closed := make(chan BuildEvent)
- close(closed)
- return c, closed, nil
+ return c, nil, nil
}
// Cache is either missing, broken or outdated. Rebuilding.
@@ -114,6 +117,23 @@ func NewNamedRepoCache(r repository.ClockedRepo, name string) (*RepoCache, chan
return c, events, nil
}
+func NewRepoCacheNoEvents(r repository.ClockedRepo) (*RepoCache, error) {
+ cache, events, err := NewRepoCache(r)
+ if err != nil {
+ return nil, err
+ }
+ if events != nil {
+ for event := range events {
+ if event.Err != nil {
+ for range events {
+ }
+ return nil, err
+ }
+ }
+ }
+ return cache, nil
+}
+
// Bugs gives access to the Bug entities
func (c *RepoCache) Bugs() *RepoCacheBug {
return c.bugs
diff --git a/cache/repo_cache_test.go b/cache/repo_cache_test.go
index 939cb154..796b5db9 100644
--- a/cache/repo_cache_test.go
+++ b/cache/repo_cache_test.go
@@ -8,23 +8,17 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+ "github.com/MichaelMure/git-bug/entities/bug"
+ "github.com/MichaelMure/git-bug/entities/identity"
"github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/query"
"github.com/MichaelMure/git-bug/repository"
)
-func noBuildEventErrors(t *testing.T, c chan BuildEvent) {
- t.Helper()
- for event := range c {
- require.NoError(t, event.Err)
- }
-}
-
func TestCache(t *testing.T) {
repo := repository.CreateGoGitTestRepo(t, false)
- cache, events, err := NewRepoCache(repo)
- noBuildEventErrors(t, events)
+ cache, err := NewRepoCacheNoEvents(repo)
require.NoError(t, err)
// Create, set and get user identity
@@ -43,17 +37,27 @@ func TestCache(t *testing.T) {
// Two identical identities yield a different id
require.NotEqual(t, iden1.Id(), iden2.Id())
+ indexCount := func(name string) uint64 {
+ idx, err := repo.GetIndex(name)
+ require.NoError(t, err)
+ count, err := idx.DocCount()
+ require.NoError(t, err)
+ return count
+ }
+
// There is now two identities in the cache
require.Len(t, cache.Identities().AllIds(), 2)
require.Len(t, cache.identities.excerpts, 2)
require.Len(t, cache.identities.cached, 2)
+ require.Equal(t, uint64(2), indexCount(identity.Namespace))
+ require.Equal(t, uint64(0), indexCount(bug.Namespace))
// Create a bug
bug1, _, err := cache.Bugs().New("title", "message")
require.NoError(t, err)
// It's possible to create two identical bugs
- bug2, _, err := cache.Bugs().New("title", "message")
+ bug2, _, err := cache.Bugs().New("title", "marker")
require.NoError(t, err)
// two identical bugs yield a different id
@@ -63,6 +67,8 @@ func TestCache(t *testing.T) {
require.Len(t, cache.Bugs().AllIds(), 2)
require.Len(t, cache.bugs.excerpts, 2)
require.Len(t, cache.bugs.cached, 2)
+ require.Equal(t, uint64(2), indexCount(identity.Namespace))
+ require.Equal(t, uint64(2), indexCount(bug.Namespace))
// Resolving
_, err = cache.Identities().Resolve(iden1.Id())
@@ -86,6 +92,12 @@ func TestCache(t *testing.T) {
require.NoError(t, err)
require.Len(t, res, 2)
+ q, err = query.Parse("status:open marker") // full-text search
+ require.NoError(t, err)
+ res, err = cache.Bugs().Query(q)
+ require.NoError(t, err)
+ require.Len(t, res, 1)
+
// Close
require.NoError(t, cache.Close())
require.Empty(t, cache.bugs.cached)
@@ -95,13 +107,14 @@ func TestCache(t *testing.T) {
// Reload, only excerpt are loaded, but as we need to load the identities used in the bugs
// to check the signatures, we also load the identity used above
- cache, events, err = NewRepoCache(repo)
- noBuildEventErrors(t, events)
+ cache, err = NewRepoCacheNoEvents(repo)
require.NoError(t, err)
require.Len(t, cache.bugs.cached, 0)
require.Len(t, cache.bugs.excerpts, 2)
require.Len(t, cache.identities.cached, 0)
require.Len(t, cache.identities.excerpts, 2)
+ require.Equal(t, uint64(2), indexCount(identity.Namespace))
+ require.Equal(t, uint64(2), indexCount(bug.Namespace))
// Resolving load from the disk
_, err = cache.Identities().Resolve(iden1.Id())
@@ -122,12 +135,10 @@ func TestCache(t *testing.T) {
func TestCachePushPull(t *testing.T) {
repoA, repoB, _ := repository.SetupGoGitReposAndRemote(t)
- cacheA, events, err := NewRepoCache(repoA)
- noBuildEventErrors(t, events)
+ cacheA, err := NewRepoCacheNoEvents(repoA)
require.NoError(t, err)
- cacheB, events, err := NewRepoCache(repoB)
- noBuildEventErrors(t, events)
+ cacheB, err := NewRepoCacheNoEvents(repoB)
require.NoError(t, err)
// Create, set and get user identity
@@ -190,8 +201,7 @@ func TestRemove(t *testing.T) {
err = repo.AddRemote("remoteB", remoteB.GetLocalRemote())
require.NoError(t, err)
- repoCache, events, err := NewRepoCache(repo)
- noBuildEventErrors(t, events)
+ repoCache, err := NewRepoCacheNoEvents(repo)
require.NoError(t, err)
rene, err := repoCache.Identities().New("René Descartes", "rene@descartes.fr")
@@ -230,8 +240,7 @@ func TestRemove(t *testing.T) {
func TestCacheEviction(t *testing.T) {
repo := repository.CreateGoGitTestRepo(t, false)
- repoCache, events, err := NewRepoCache(repo)
- noBuildEventErrors(t, events)
+ repoCache, err := NewRepoCacheNoEvents(repo)
require.NoError(t, err)
repoCache.setCacheSize(2)
@@ -299,8 +308,7 @@ func TestLongDescription(t *testing.T) {
repo := repository.CreateGoGitTestRepo(t, false)
- backend, events, err := NewRepoCache(repo)
- noBuildEventErrors(t, events)
+ backend, err := NewRepoCacheNoEvents(repo)
require.NoError(t, err)
i, err := backend.Identities().New("René Descartes", "rene@descartes.fr")
diff --git a/cache/subcache.go b/cache/subcache.go
index af75938a..7757ce82 100644
--- a/cache/subcache.go
+++ b/cache/subcache.go
@@ -4,6 +4,7 @@ import (
"bytes"
"encoding/gob"
"fmt"
+ "path/filepath"
"sync"
"github.com/pkg/errors"
@@ -21,6 +22,7 @@ type Excerpt interface {
type CacheEntity interface {
Id() entity.Id
NeedCommit() bool
+ Lock()
}
type getUserIdentityFunc func() (*IdentityCache, error)
@@ -94,7 +96,7 @@ func (sc *SubCache[EntityT, ExcerptT, CacheT]) Load() error {
sc.mu.Lock()
defer sc.mu.Unlock()
- f, err := sc.repo.LocalStorage().Open(sc.namespace + "-file")
+ f, err := sc.repo.LocalStorage().Open(filepath.Join("cache", sc.namespace))
if err != nil {
return err
}
@@ -123,7 +125,7 @@ func (sc *SubCache[EntityT, ExcerptT, CacheT]) Load() error {
sc.excerpts = aux.Excerpts
- index, err := sc.repo.GetIndex(sc.typename)
+ index, err := sc.repo.GetIndex(sc.namespace)
if err != nil {
return err
}
@@ -162,7 +164,7 @@ func (sc *SubCache[EntityT, ExcerptT, CacheT]) write() error {
return err
}
- f, err := sc.repo.LocalStorage().Create(sc.namespace + "-file")
+ f, err := sc.repo.LocalStorage().Create(filepath.Join("cache", sc.namespace))
if err != nil {
return err
}
@@ -180,7 +182,7 @@ func (sc *SubCache[EntityT, ExcerptT, CacheT]) Build() error {
allEntities := sc.actions.ReadAllWithResolver(sc.repo, sc.resolvers())
- index, err := sc.repo.GetIndex(sc.typename)
+ index, err := sc.repo.GetIndex(sc.namespace)
if err != nil {
return err
}
@@ -462,7 +464,7 @@ func (sc *SubCache[EntityT, ExcerptT, CacheT]) entityUpdated(id entity.Id) error
sc.excerpts[id] = sc.makeExcerpt(e)
sc.mu.Unlock()
- index, err := sc.repo.GetIndex(sc.typename)
+ index, err := sc.repo.GetIndex(sc.namespace)
if err != nil {
return err
}
@@ -489,8 +491,10 @@ func (sc *SubCache[EntityT, ExcerptT, CacheT]) evictIfNeeded() {
continue
}
- // TODO
- // b.Lock()
+ // as a form of assurance that evicted entities don't get manipulated, we lock them here.
+ // if something try to do it anyway, it will lock the program and make it obvious.
+ b.Lock()
+
sc.lru.Remove(id)
delete(sc.cached, id)
diff --git a/commands/bug/select/select_test.go b/commands/bug/select/select_test.go
index 5533ac2b..83ca6643 100644
--- a/commands/bug/select/select_test.go
+++ b/commands/bug/select/select_test.go
@@ -13,11 +13,8 @@ import (
func TestSelect(t *testing.T) {
repo := repository.CreateGoGitTestRepo(t, false)
- repoCache, events, err := cache.NewRepoCache(repo)
+ repoCache, err := cache.NewRepoCacheNoEvents(repo)
require.NoError(t, err)
- for event := range events {
- require.NoError(t, event.Err)
- }
_, _, err = ResolveBug(repoCache, []string{})
require.Equal(t, ErrNoValidId, err)
diff --git a/commands/execenv/env.go b/commands/execenv/env.go
index 0813ab7e..4c6ce204 100644
--- a/commands/execenv/env.go
+++ b/commands/execenv/env.go
@@ -136,19 +136,17 @@ func LoadBackend(env *Env) func(*cobra.Command, []string) error {
if events != nil {
env.Err.Println("Building cache... ")
- }
-
- for event := range events {
- if event.Err != nil {
- env.Err.Printf("Cache building error [%s]: %v\n", event.Typename, event.Err)
- continue
- }
-
- switch event.Event {
- case cache.BuildEventStarted:
- env.Err.Printf("[%s] started\n", event.Typename)
- case cache.BuildEventFinished:
- env.Err.Printf("[%s] done\n", event.Typename)
+ for event := range events {
+ if event.Err != nil {
+ env.Err.Printf("Cache building error [%s]: %v\n", event.Typename, event.Err)
+ continue
+ }
+ switch event.Event {
+ case cache.BuildEventStarted:
+ env.Err.Printf("[%s] started\n", event.Typename)
+ case cache.BuildEventFinished:
+ env.Err.Printf("[%s] done\n", event.Typename)
+ }
}
}
diff --git a/commands/execenv/env_testing.go b/commands/execenv/env_testing.go
index ddba735f..5761b410 100644
--- a/commands/execenv/env_testing.go
+++ b/commands/execenv/env_testing.go
@@ -34,11 +34,8 @@ func NewTestEnv(t *testing.T) *Env {
buf := new(bytes.Buffer)
- backend, events, err := cache.NewRepoCache(repo)
+ backend, err := cache.NewRepoCacheNoEvents(repo)
require.NoError(t, err)
- for event := range events {
- require.NoError(t, event.Err)
- }
t.Cleanup(func() {
backend.Close()
diff --git a/commands/root.go b/commands/root.go
index b28b77b8..d98f9448 100644
--- a/commands/root.go
+++ b/commands/root.go
@@ -61,7 +61,7 @@ the same git remote you are already using to collaborate with other people.
const remoteGroup = "remote"
cmd.AddGroup(&cobra.Group{ID: entityGroup, Title: "Entities"})
- cmd.AddGroup(&cobra.Group{ID: uiGroup, Title: "User interfaces"})
+ cmd.AddGroup(&cobra.Group{ID: uiGroup, Title: "Interactive interfaces"})
cmd.AddGroup(&cobra.Group{ID: remoteGroup, Title: "Interaction with the outside world"})
addCmdWithGroup := func(child *cobra.Command, groupID string) {
diff --git a/commands/webui.go b/commands/webui.go
index 4f7a02b5..6cbaff78 100644
--- a/commands/webui.go
+++ b/commands/webui.go
@@ -110,17 +110,19 @@ func runWebUI(env *execenv.Env, opts webUIOptions) error {
return err
}
- for event := range events {
- if event.Err != nil {
- env.Err.Printf("Cache building error [%s]: %v\n", event.Typename, event.Err)
- continue
- }
-
- switch event.Event {
- case cache.BuildEventStarted:
- env.Err.Printf("[%s] started\n", event.Typename)
- case cache.BuildEventFinished:
- env.Err.Printf("[%s] done\n", event.Typename)
+ if events != nil {
+ env.Err.Println("Building cache... ")
+ for event := range events {
+ if event.Err != nil {
+ env.Err.Printf("Cache building error [%s]: %v\n", event.Typename, event.Err)
+ continue
+ }
+ switch event.Event {
+ case cache.BuildEventStarted:
+ env.Err.Printf("[%s] started\n", event.Typename)
+ case cache.BuildEventFinished:
+ env.Err.Printf("[%s] done\n", event.Typename)
+ }
}
}
diff --git a/entities/bug/bug.go b/entities/bug/bug.go
index 271e7dbd..deb00c7c 100644
--- a/entities/bug/bug.go
+++ b/entities/bug/bug.go
@@ -20,9 +20,12 @@ var _ entity.Interface = &Bug{}
// 4: with DAG entity framework
const formatVersion = 4
+const Typename = "bug"
+const Namespace = "bugs"
+
var def = dag.Definition{
- Typename: "bug",
- Namespace: "bugs",
+ Typename: Typename,
+ Namespace: Namespace,
OperationUnmarshaler: operationUnmarshaler,
FormatVersion: formatVersion,
}
diff --git a/entities/identity/identity.go b/entities/identity/identity.go
index 572d2c14..b0cee43b 100644
--- a/entities/identity/identity.go
+++ b/entities/identity/identity.go
@@ -19,6 +19,9 @@ const identityRemoteRefPattern = "refs/remotes/%s/identities/"
const versionEntryName = "version"
const identityConfigKey = "git-bug.identity"
+const Typename = "identity"
+const Namespace = "identities"
+
var ErrNonFastForwardMerge = errors.New("non fast-forward identity merge")
var ErrNoIdentitySet = errors.New("No identity is set.\n" +
"To interact with bugs, an identity first needs to be created using " +
@@ -105,7 +108,7 @@ func read(repo repository.Repo, ref string) (*Identity, error) {
hashes, err := repo.ListCommits(ref)
if err != nil {
- return nil, entity.NewErrNotFound("identity")
+ return nil, entity.NewErrNotFound(Typename)
}
if len(hashes) == 0 {
return nil, fmt.Errorf("empty identity")
@@ -170,7 +173,7 @@ func RemoveIdentity(repo repository.ClockedRepo, id entity.Id) error {
return err
}
if len(refs) > 1 {
- return entity.NewErrMultipleMatch("identity", entity.RefsToIds(refs))
+ return entity.NewErrMultipleMatch(Typename, entity.RefsToIds(refs))
}
if len(refs) == 1 {
// we have the identity locally
@@ -189,7 +192,7 @@ func RemoveIdentity(repo repository.ClockedRepo, id entity.Id) error {
return err
}
if len(remoteRefs) > 1 {
- return entity.NewErrMultipleMatch("identity", entity.RefsToIds(refs))
+ return entity.NewErrMultipleMatch(Typename, entity.RefsToIds(refs))
}
if len(remoteRefs) == 1 {
// found the identity in a remote
@@ -198,7 +201,7 @@ func RemoveIdentity(repo repository.ClockedRepo, id entity.Id) error {
}
if len(fullMatches) == 0 {
- return entity.NewErrNotFound("identity")
+ return entity.NewErrNotFound(Typename)
}
for _, ref := range fullMatches {
diff --git a/entities/identity/identity_actions.go b/entities/identity/identity_actions.go
index b58bb2d9..13776078 100644
--- a/entities/identity/identity_actions.go
+++ b/entities/identity/identity_actions.go
@@ -13,12 +13,12 @@ import (
// Fetch retrieve updates from a remote
// This does not change the local identities state
func Fetch(repo repository.Repo, remote string) (string, error) {
- return repo.FetchRefs(remote, "identities")
+ return repo.FetchRefs(remote, Namespace)
}
// Push update a remote with the local changes
func Push(repo repository.Repo, remote string) (string, error) {
- return repo.PushRefs(remote, "identities")
+ return repo.PushRefs(remote, Namespace)
}
// Pull will do a Fetch + MergeAll
diff --git a/repository/gogit.go b/repository/gogit.go
index 781eec73..b14efbe5 100644
--- a/repository/gogit.go
+++ b/repository/gogit.go
@@ -217,11 +217,12 @@ func isGitDir(path string) (bool, error) {
func (repo *GoGitRepo) Close() error {
var firstErr error
- for _, index := range repo.indexes {
+ for name, index := range repo.indexes {
err := index.Close()
if err != nil && firstErr == nil {
firstErr = err
}
+ delete(repo.indexes, name)
}
return firstErr
}
diff --git a/util/multierr/errwaitgroup.go b/util/multierr/errwaitgroup.go
index 1c785b30..7279ed1f 100644
--- a/util/multierr/errwaitgroup.go
+++ b/util/multierr/errwaitgroup.go
@@ -63,7 +63,7 @@ func (g *ErrWaitGroup) Go(f func() error) {
if err := f(); err != nil {
g.mu.Lock()
- err = Join(g.err, err)
+ g.err = Join(g.err, err)
g.mu.Unlock()
}
}()