diff options
author | Michael Muré <batolettre@gmail.com> | 2022-12-22 23:19:31 +0100 |
---|---|---|
committer | Michael Muré <batolettre@gmail.com> | 2022-12-23 01:41:03 +0100 |
commit | 95911100823b5c809225d664de74ad2d64e91972 (patch) | |
tree | c352848904d82b046646b4074f26b0ce5235fa40 | |
parent | d65e8837aa7bb1a6abb6892b9f2664e1b7edb02e (diff) | |
download | git-bug-95911100823b5c809225d664de74ad2d64e91972.tar.gz |
cache: fix some bugs after refactor
-rw-r--r-- | bridge/github/export_test.go | 10 | ||||
-rw-r--r-- | bridge/github/import_integration_test.go | 6 | ||||
-rw-r--r-- | bridge/github/import_test.go | 5 | ||||
-rw-r--r-- | bridge/gitlab/export_test.go | 10 | ||||
-rw-r--r-- | bridge/gitlab/import_test.go | 5 | ||||
-rw-r--r-- | cache/bug_subcache.go | 4 | ||||
-rw-r--r-- | cache/cached.go | 6 | ||||
-rw-r--r-- | cache/identity_cache.go | 14 | ||||
-rw-r--r-- | cache/identity_subcache.go | 2 | ||||
-rw-r--r-- | cache/multi_repo_cache.go | 12 | ||||
-rw-r--r-- | cache/repo_cache.go | 34 | ||||
-rw-r--r-- | cache/repo_cache_test.go | 52 | ||||
-rw-r--r-- | cache/subcache.go | 18 | ||||
-rw-r--r-- | commands/bug/select/select_test.go | 5 | ||||
-rw-r--r-- | commands/execenv/env.go | 24 | ||||
-rw-r--r-- | commands/execenv/env_testing.go | 5 | ||||
-rw-r--r-- | commands/root.go | 2 | ||||
-rw-r--r-- | commands/webui.go | 24 | ||||
-rw-r--r-- | entities/bug/bug.go | 7 | ||||
-rw-r--r-- | entities/identity/identity.go | 11 | ||||
-rw-r--r-- | entities/identity/identity_actions.go | 4 | ||||
-rw-r--r-- | repository/gogit.go | 3 | ||||
-rw-r--r-- | util/multierr/errwaitgroup.go | 2 |
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() } }() |