Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add cleanup sub-command that remove local bugs and identities #933

Merged
merged 3 commits into from
Jan 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions cache/bug_subcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func NewRepoCacheBug(repo repository.ClockedRepo,
ReadWithResolver: bug.ReadWithResolver,
ReadAllWithResolver: bug.ReadAllWithResolver,
Remove: bug.Remove,
RemoveAll: bug.RemoveAll,
MergeAll: bug.MergeAll,
}

Expand Down
3 changes: 2 additions & 1 deletion cache/identity_subcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ func NewRepoCacheIdentity(repo repository.ClockedRepo,
ReadAllWithResolver: func(repo repository.ClockedRepo, resolvers entity.Resolvers) <-chan entity.StreamedEntity[*identity.Identity] {
return identity.ReadAllLocal(repo)
},
Remove: identity.RemoveIdentity,
Remove: identity.Remove,
RemoveAll: identity.RemoveAll,
MergeAll: func(repo repository.ClockedRepo, resolvers entity.Resolvers, remote string, mergeAuthor identity.Interface) <-chan entity.MergeResult {
return identity.MergeAll(repo, remote)
},
Expand Down
1 change: 1 addition & 0 deletions cache/repo_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type cacheMgmt interface {
Load() error
Build() error
SetCacheSize(size int)
RemoveAll() error
MergeAll(remote string) <-chan entity.MergeResult
GetNamespace() string
Close() error
Expand Down
26 changes: 24 additions & 2 deletions cache/repo_cache_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package cache
import (
"sync"

"github.com/go-git/go-billy/v5"
"github.com/pkg/errors"

"github.com/MichaelMure/git-bug/entities/identity"
"github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/repository"
"github.com/MichaelMure/git-bug/util/multierr"
)

func (c *RepoCache) Name() string {
Expand Down Expand Up @@ -56,7 +56,7 @@ func (c *RepoCache) GetRemotes() (map[string]string, error) {
}

// LocalStorage return a billy.Filesystem giving access to $RepoPath/.git/git-bug
func (c *RepoCache) LocalStorage() billy.Filesystem {
func (c *RepoCache) LocalStorage() repository.LocalStorage {
return c.repo.LocalStorage()
}

Expand All @@ -82,6 +82,15 @@ func (c *RepoCache) Fetch(remote string) (string, error) {
return c.repo.FetchRefs(remote, prefixes...)
}

// RemoveAll deletes all entities from the cache and the disk.
func (c *RepoCache) RemoveAll() error {
var errWait multierr.ErrWaitGroup
for _, mgmt := range c.subcaches {
errWait.Go(mgmt.RemoveAll)
}
return errWait.Wait()
}

// MergeAll will merge all the available remote bug and identities
func (c *RepoCache) MergeAll(remote string) <-chan entity.MergeResult {
out := make(chan entity.MergeResult)
Expand Down Expand Up @@ -163,6 +172,19 @@ func (c *RepoCache) SetUserIdentity(i *IdentityCache) error {
return nil
}

func (c *RepoCache) ClearUserIdentity() error {
c.muUserIdentity.Lock()
defer c.muUserIdentity.Unlock()

err := identity.ClearUserIdentity(c.repo)
if err != nil {
return err
}

c.userIdentityId = ""
return nil
}

func (c *RepoCache) GetUserIdentity() (*IdentityCache, error) {
c.muUserIdentity.RLock()
if c.userIdentityId != "" {
Expand Down
33 changes: 33 additions & 0 deletions cache/repo_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,39 @@ func TestCache(t *testing.T) {
_, err = cache.Bugs().ResolvePrefix(bug1.Id().String()[:10])
require.NoError(t, err)

require.Len(t, cache.bugs.cached, 1)
require.Len(t, cache.bugs.excerpts, 2)
require.Len(t, cache.identities.cached, 1)
require.Len(t, cache.identities.excerpts, 2)
require.Equal(t, uint64(2), indexCount(t, identity.Namespace))
require.Equal(t, uint64(2), indexCount(t, bug.Namespace))

// Remove + RemoveAll
err = cache.Identities().Remove(iden1.Id().String()[:10])
require.NoError(t, err)
err = cache.Bugs().Remove(bug1.Id().String()[:10])
require.NoError(t, err)
require.Len(t, cache.bugs.cached, 0)
require.Len(t, cache.bugs.excerpts, 1)
require.Len(t, cache.identities.cached, 0)
require.Len(t, cache.identities.excerpts, 1)
require.Equal(t, uint64(1), indexCount(t, identity.Namespace))
require.Equal(t, uint64(1), indexCount(t, bug.Namespace))

_, err = cache.Identities().New("René Descartes", "rene@descartes.fr")
require.NoError(t, err)
_, _, err = cache.Bugs().NewRaw(iden2, time.Now().Unix(), "title", "message", nil, nil)
require.NoError(t, err)

err = cache.RemoveAll()
require.NoError(t, err)
require.Len(t, cache.bugs.cached, 0)
require.Len(t, cache.bugs.excerpts, 0)
require.Len(t, cache.identities.cached, 0)
require.Len(t, cache.identities.excerpts, 0)
require.Equal(t, uint64(0), indexCount(t, identity.Namespace))
require.Equal(t, uint64(0), indexCount(t, bug.Namespace))

// Close
require.NoError(t, cache.Close())
require.Empty(t, cache.bugs.cached)
Expand Down
43 changes: 43 additions & 0 deletions cache/subcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type Actions[EntityT entity.Interface] struct {
ReadWithResolver func(repo repository.ClockedRepo, resolvers entity.Resolvers, id entity.Id) (EntityT, error)
ReadAllWithResolver func(repo repository.ClockedRepo, resolvers entity.Resolvers) <-chan entity.StreamedEntity[EntityT]
Remove func(repo repository.ClockedRepo, id entity.Id) error
RemoveAll func(repo repository.ClockedRepo) error
MergeAll func(repo repository.ClockedRepo, resolvers entity.Resolvers, remote string, mergeAuthor identity.Interface) <-chan entity.MergeResult
}

Expand Down Expand Up @@ -399,7 +400,49 @@ func (sc *SubCache[EntityT, ExcerptT, CacheT]) Remove(prefix string) error {
delete(sc.excerpts, e.Id())
sc.lru.Remove(e.Id())

index, err := sc.repo.GetIndex(sc.namespace)
if err != nil {
sc.mu.Unlock()
return err
}

err = index.Remove(e.Id().String())
sc.mu.Unlock()
if err != nil {
return err
}

return sc.write()
}

func (sc *SubCache[EntityT, ExcerptT, CacheT]) RemoveAll() error {
sc.mu.Lock()

err := sc.actions.RemoveAll(sc.repo)
if err != nil {
sc.mu.Unlock()
return err
}

for id, _ := range sc.cached {
delete(sc.cached, id)
sc.lru.Remove(id)
}
for id, _ := range sc.excerpts {
delete(sc.excerpts, id)
}

index, err := sc.repo.GetIndex(sc.namespace)
if err != nil {
sc.mu.Unlock()
return err
}

err = index.Clear()
sc.mu.Unlock()
if err != nil {
return err
}

return sc.write()
}
Expand Down
1 change: 1 addition & 0 deletions commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ the same git remote you are already using to collaborate with other people.

cmd.AddCommand(newCommandsCommand())
cmd.AddCommand(newVersionCommand())
cmd.AddCommand(newWipeCommand())

return cmd
}
Expand Down
58 changes: 58 additions & 0 deletions commands/wipe.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package commands

import (
"github.com/spf13/cobra"

"github.com/MichaelMure/git-bug/commands/execenv"
)

func newWipeCommand() *cobra.Command {
env := execenv.NewEnv()

cmd := &cobra.Command{
Use: "wipe",
Short: "Wipe git-bug from the git repository",
PreRunE: execenv.LoadBackend(env),
RunE: func(cmd *cobra.Command, args []string) error {
return runWipe(env)
},
}

return cmd
}

func runWipe(env *execenv.Env) error {
env.Out.Println("cleaning entities...")
err := env.Backend.RemoveAll()
if err != nil {
_ = env.Backend.Close()
return err
}

env.Out.Println("cleaning git config ...")
err = env.Backend.ClearUserIdentity()
if err != nil {
_ = env.Backend.Close()
return err
}
err = env.Backend.LocalConfig().RemoveAll("git-bug")
if err != nil {
_ = env.Backend.Close()
return err
}

storage := env.Backend.LocalStorage()

err = env.Backend.Close()
if err != nil {
return err
}

env.Out.Println("cleaning caches ...")
err = storage.RemoveAll(".")
if err != nil {
return err
}

return nil
}
27 changes: 27 additions & 0 deletions doc/man/git-bug-wipe.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.nh
.TH "GIT-BUG" "1" "Apr 2019" "Generated from git-bug's source code" ""

.SH NAME
.PP
git-bug-wipe - Wipe git-bug from the git repository


.SH SYNOPSIS
.PP
\fBgit-bug wipe [flags]\fP


.SH DESCRIPTION
.PP
Wipe git-bug from the git repository


.SH OPTIONS
.PP
\fB-h\fP, \fB--help\fP[=false]
help for wipe


.SH SEE ALSO
.PP
\fBgit-bug(1)\fP
2 changes: 1 addition & 1 deletion doc/man/git-bug.1
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ the same git remote you are already using to collaborate with other people.

.SH SEE ALSO
.PP
\fBgit-bug-bridge(1)\fP, \fBgit-bug-bug(1)\fP, \fBgit-bug-commands(1)\fP, \fBgit-bug-label(1)\fP, \fBgit-bug-pull(1)\fP, \fBgit-bug-push(1)\fP, \fBgit-bug-termui(1)\fP, \fBgit-bug-user(1)\fP, \fBgit-bug-version(1)\fP, \fBgit-bug-webui(1)\fP
\fBgit-bug-bridge(1)\fP, \fBgit-bug-bug(1)\fP, \fBgit-bug-commands(1)\fP, \fBgit-bug-label(1)\fP, \fBgit-bug-pull(1)\fP, \fBgit-bug-push(1)\fP, \fBgit-bug-termui(1)\fP, \fBgit-bug-user(1)\fP, \fBgit-bug-version(1)\fP, \fBgit-bug-webui(1)\fP, \fBgit-bug-wipe(1)\fP
1 change: 1 addition & 0 deletions doc/md/git-bug.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ git-bug [flags]
* [git-bug user](git-bug_user.md) - List identities
* [git-bug version](git-bug_version.md) - Show git-bug version information
* [git-bug webui](git-bug_webui.md) - Launch the web UI
* [git-bug wipe](git-bug_wipe.md) - Wipe git-bug from the git repository

18 changes: 18 additions & 0 deletions doc/md/git-bug_wipe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## git-bug wipe

Wipe git-bug from the git repository

```
git-bug wipe [flags]
```

### Options

```
-h, --help help for wipe
```

### SEE ALSO

* [git-bug](git-bug.md) - A bug tracker embedded in Git

6 changes: 6 additions & 0 deletions entities/bug/bug_actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,9 @@ func MergeAll(repo repository.ClockedRepo, resolvers entity.Resolvers, remote st
func Remove(repo repository.ClockedRepo, id entity.Id) error {
return dag.Remove(def, repo, id)
}

// RemoveAll will remove all local bugs.
// RemoveAll is idempotent.
func RemoveAll(repo repository.ClockedRepo) error {
return dag.RemoveAll(def, repo)
}
50 changes: 0 additions & 50 deletions entities/identity/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,56 +164,6 @@ func ListLocalIds(repo repository.Repo) ([]entity.Id, error) {
return entity.RefsToIds(refs), nil
}

// RemoveIdentity will remove a local identity from its entity.Id
func RemoveIdentity(repo repository.ClockedRepo, id entity.Id) error {
var fullMatches []string

refs, err := repo.ListRefs(identityRefPattern + id.String())
if err != nil {
return err
}
if len(refs) > 1 {
return entity.NewErrMultipleMatch(Typename, entity.RefsToIds(refs))
}
if len(refs) == 1 {
// we have the identity locally
fullMatches = append(fullMatches, refs[0])
}

remotes, err := repo.GetRemotes()
if err != nil {
return err
}

for remote := range remotes {
remotePrefix := fmt.Sprintf(identityRemoteRefPattern+id.String(), remote)
remoteRefs, err := repo.ListRefs(remotePrefix)
if err != nil {
return err
}
if len(remoteRefs) > 1 {
return entity.NewErrMultipleMatch(Typename, entity.RefsToIds(refs))
}
if len(remoteRefs) == 1 {
// found the identity in a remote
fullMatches = append(fullMatches, remoteRefs[0])
}
}

if len(fullMatches) == 0 {
return entity.NewErrNotFound(Typename)
}

for _, ref := range fullMatches {
err = repo.RemoveRef(ref)
if err != nil {
return err
}
}

return nil
}

// ReadAllLocal read and parse all local Identity
func ReadAllLocal(repo repository.ClockedRepo) <-chan entity.StreamedEntity[*Identity] {
return readAll(repo, identityRefPattern)
Expand Down