aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2019-02-24 14:17:52 +0100
committerMichael Muré <batolettre@gmail.com>2019-03-01 22:48:51 +0100
commit7a80d8f849861a6033cd0765e5d85a52b08a8854 (patch)
tree30a2b00bec3e871aa18ba75acac626f9e7e1f1b2
parent8bba6d1493fdf064ac9fede0a5098b1abe969052 (diff)
downloadgit-bug-7a80d8f849861a6033cd0765e5d85a52b08a8854.tar.gz
commands: add a super-fast "user ls" command
-rw-r--r--cache/bug_excerpt.go4
-rw-r--r--cache/identity_excerpt.go26
-rw-r--r--cache/repo_cache.go12
-rw-r--r--commands/user_list.go47
-rw-r--r--doc/man/git-bug-user-ls.133
-rw-r--r--doc/man/git-bug-user.12
-rw-r--r--doc/md/git-bug_user.md1
-rw-r--r--doc/md/git-bug_user_ls.md23
-rw-r--r--identity/bare.go5
-rw-r--r--identity/identity.go17
-rw-r--r--identity/identity_stub.go4
-rw-r--r--identity/interface.go3
-rw-r--r--misc/bash_completion/git-bug24
-rw-r--r--misc/zsh_completion/git-bug2
14 files changed, 198 insertions, 5 deletions
diff --git a/cache/bug_excerpt.go b/cache/bug_excerpt.go
index 55518077..fd06e51b 100644
--- a/cache/bug_excerpt.go
+++ b/cache/bug_excerpt.go
@@ -68,6 +68,10 @@ func NewBugExcerpt(b bug.Interface, snap *bug.Snapshot) *BugExcerpt {
return e
}
+func (b *BugExcerpt) HumanId() string {
+ return bug.FormatHumanID(b.Id)
+}
+
/*
* Sorting
*/
diff --git a/cache/identity_excerpt.go b/cache/identity_excerpt.go
index 0539a76b..2a13bc60 100644
--- a/cache/identity_excerpt.go
+++ b/cache/identity_excerpt.go
@@ -2,10 +2,16 @@ package cache
import (
"encoding/gob"
+ "fmt"
"github.com/MichaelMure/git-bug/identity"
)
+// Package initialisation used to register the type for (de)serialization
+func init() {
+ gob.Register(IdentityExcerpt{})
+}
+
// IdentityExcerpt hold a subset of the identity values to be able to sort and
// filter identities efficiently without having to read and compile each raw
// identity.
@@ -26,9 +32,23 @@ func NewIdentityExcerpt(i *identity.Identity) *IdentityExcerpt {
}
}
-// Package initialisation used to register the type for (de)serialization
-func init() {
- gob.Register(IdentityExcerpt{})
+func (i *IdentityExcerpt) HumanId() string {
+ return identity.FormatHumanID(i.Id)
+}
+
+// DisplayName return a non-empty string to display, representing the
+// identity, based on the non-empty values.
+func (i *IdentityExcerpt) DisplayName() string {
+ switch {
+ case i.Name == "" && i.Login != "":
+ return i.Login
+ case i.Name != "" && i.Login == "":
+ return i.Name
+ case i.Name != "" && i.Login != "":
+ return fmt.Sprintf("%s (%s)", i.Name, i.Login)
+ }
+
+ panic("invalid person data")
}
/*
diff --git a/cache/repo_cache.go b/cache/repo_cache.go
index 78633a69..a50c745b 100644
--- a/cache/repo_cache.go
+++ b/cache/repo_cache.go
@@ -489,6 +489,12 @@ func (c *RepoCache) AllBugsIds() []string {
return result
}
+// AllBugExcerpt return all known bug excerpt.
+// This maps is read-only.
+func (c *RepoCache) AllBugExcerpt() map[string]*BugExcerpt {
+ return c.bugExcerpts
+}
+
// ValidLabels list valid labels
//
// Note: in the future, a proper label policy could be implemented where valid
@@ -765,6 +771,12 @@ func (c *RepoCache) AllIdentityIds() []string {
return result
}
+// AllIdentityExcerpt return all known identities excerpt.
+// This maps is read-only.
+func (c *RepoCache) AllIdentityExcerpt() map[string]*IdentityExcerpt {
+ return c.identitiesExcerpts
+}
+
func (c *RepoCache) SetUserIdentity(i *IdentityCache) error {
err := identity.SetUserIdentity(c.repo, i.Identity)
if err != nil {
diff --git a/commands/user_list.go b/commands/user_list.go
new file mode 100644
index 00000000..4d6e5e12
--- /dev/null
+++ b/commands/user_list.go
@@ -0,0 +1,47 @@
+package commands
+
+import (
+ "fmt"
+
+ "github.com/MichaelMure/git-bug/cache"
+ "github.com/MichaelMure/git-bug/util/colors"
+ "github.com/MichaelMure/git-bug/util/interrupt"
+ "github.com/spf13/cobra"
+)
+
+var (
+ userLsVerbose bool
+)
+
+func runUserLs(cmd *cobra.Command, args []string) error {
+ backend, err := cache.NewRepoCache(repo)
+ if err != nil {
+ return err
+ }
+ defer backend.Close()
+ interrupt.RegisterCleaner(backend.Close)
+
+ for _, i := range backend.AllIdentityExcerpt() {
+ fmt.Printf("%s %s\n",
+ colors.Cyan(i.HumanId()),
+ i.DisplayName(),
+ )
+ }
+
+ return nil
+}
+
+var userLsCmd = &cobra.Command{
+ Use: "ls",
+ Short: "List identities",
+ PreRunE: loadRepo,
+ RunE: runUserLs,
+}
+
+func init() {
+ userCmd.AddCommand(userLsCmd)
+ userLsCmd.Flags().SortFlags = false
+
+ userLsCmd.Flags().BoolVarP(&userLsVerbose, "verbose", "v", false,
+ "Print extra information")
+}
diff --git a/doc/man/git-bug-user-ls.1 b/doc/man/git-bug-user-ls.1
new file mode 100644
index 00000000..6820a28d
--- /dev/null
+++ b/doc/man/git-bug-user-ls.1
@@ -0,0 +1,33 @@
+.TH "GIT-BUG" "1" "Feb 2019" "Generated from git-bug's source code" ""
+.nh
+.ad l
+
+
+.SH NAME
+.PP
+git\-bug\-user\-ls \- List identities
+
+
+.SH SYNOPSIS
+.PP
+\fBgit\-bug user ls [flags]\fP
+
+
+.SH DESCRIPTION
+.PP
+List identities
+
+
+.SH OPTIONS
+.PP
+\fB\-v\fP, \fB\-\-verbose\fP[=false]
+ Print extra information
+
+.PP
+\fB\-h\fP, \fB\-\-help\fP[=false]
+ help for ls
+
+
+.SH SEE ALSO
+.PP
+\fBgit\-bug\-user(1)\fP
diff --git a/doc/man/git-bug-user.1 b/doc/man/git-bug-user.1
index eb074973..acb9259f 100644
--- a/doc/man/git-bug-user.1
+++ b/doc/man/git-bug-user.1
@@ -26,4 +26,4 @@ Display or change the user identity
.SH SEE ALSO
.PP
-\fBgit\-bug(1)\fP, \fBgit\-bug\-user\-create(1)\fP
+\fBgit\-bug(1)\fP, \fBgit\-bug\-user\-create(1)\fP, \fBgit\-bug\-user\-ls(1)\fP
diff --git a/doc/md/git-bug_user.md b/doc/md/git-bug_user.md
index 5692b40a..f6a3d91b 100644
--- a/doc/md/git-bug_user.md
+++ b/doc/md/git-bug_user.md
@@ -20,4 +20,5 @@ git-bug user [<id>] [flags]
* [git-bug](git-bug.md) - A bug tracker embedded in Git
* [git-bug user create](git-bug_user_create.md) - Create a new identity
+* [git-bug user ls](git-bug_user_ls.md) - List identities
diff --git a/doc/md/git-bug_user_ls.md b/doc/md/git-bug_user_ls.md
new file mode 100644
index 00000000..9c9651f5
--- /dev/null
+++ b/doc/md/git-bug_user_ls.md
@@ -0,0 +1,23 @@
+## git-bug user ls
+
+List identities
+
+### Synopsis
+
+List identities
+
+```
+git-bug user ls [flags]
+```
+
+### Options
+
+```
+ -v, --verbose Print extra information
+ -h, --help help for ls
+```
+
+### SEE ALSO
+
+* [git-bug user](git-bug_user.md) - Display or change the user identity
+
diff --git a/identity/bare.go b/identity/bare.go
index d3f7655a..b6cbe491 100644
--- a/identity/bare.go
+++ b/identity/bare.go
@@ -85,6 +85,11 @@ func (i *Bare) Id() string {
return i.id
}
+// HumanId return the Identity identifier truncated for human consumption
+func (i *Bare) HumanId() string {
+ return FormatHumanID(i.Id())
+}
+
// Name return the last version of the name
func (i *Bare) Name() string {
return i.name
diff --git a/identity/identity.go b/identity/identity.go
index 114b954e..d57e8ce0 100644
--- a/identity/identity.go
+++ b/identity/identity.go
@@ -20,6 +20,9 @@ const identityRemoteRefPattern = "refs/remotes/%s/identities/"
const versionEntryName = "version"
const identityConfigKey = "git-bug.identity"
+const idLength = 40
+const humanIdLength = 7
+
var ErrNonFastForwardMerge = errors.New("non fast-forward identity merge")
var ErrNoIdentitySet = errors.New("user identity first needs to be created using \"git bug user create\"")
var ErrMultipleIdentitiesSet = errors.New("multiple user identities set")
@@ -93,6 +96,10 @@ func read(repo repository.Repo, ref string) (*Identity, error) {
refSplit := strings.Split(ref, "/")
id := refSplit[len(refSplit)-1]
+ if len(id) != idLength {
+ return nil, fmt.Errorf("invalid ref length")
+ }
+
hashes, err := repo.ListCommits(ref)
// TODO: this is not perfect, it might be a command invoke error
@@ -461,6 +468,16 @@ func (i *Identity) Id() string {
return i.id
}
+// HumanId return the Identity identifier truncated for human consumption
+func (i *Identity) HumanId() string {
+ return FormatHumanID(i.Id())
+}
+
+func FormatHumanID(id string) string {
+ format := fmt.Sprintf("%%.%ds", humanIdLength)
+ return fmt.Sprintf(format, id)
+}
+
// Name return the last version of the name
func (i *Identity) Name() string {
return i.lastVersion().name
diff --git a/identity/identity_stub.go b/identity/identity_stub.go
index 830cfb99..1bfc18d0 100644
--- a/identity/identity_stub.go
+++ b/identity/identity_stub.go
@@ -44,6 +44,10 @@ func (i *IdentityStub) Id() string {
return i.id
}
+func (i *IdentityStub) HumanId() string {
+ return FormatHumanID(i.Id())
+}
+
func (IdentityStub) Name() string {
panic("identities needs to be properly loaded with identity.ReadLocal()")
}
diff --git a/identity/interface.go b/identity/interface.go
index 9fe4db4f..d5c80543 100644
--- a/identity/interface.go
+++ b/identity/interface.go
@@ -9,6 +9,9 @@ type Interface interface {
// Id return the Identity identifier
Id() string
+ // HumanId return the Identity identifier truncated for human consumption
+ HumanId() string
+
// Name return the last version of the name
Name() string
// Email return the last version of the email
diff --git a/misc/bash_completion/git-bug b/misc/bash_completion/git-bug
index 4ec1e472..237a0df0 100644
--- a/misc/bash_completion/git-bug
+++ b/misc/bash_completion/git-bug
@@ -819,6 +819,29 @@ _git-bug_user_create()
noun_aliases=()
}
+_git-bug_user_ls()
+{
+ last_command="git-bug_user_ls"
+
+ command_aliases=()
+
+ commands=()
+
+ flags=()
+ two_word_flags=()
+ local_nonpersistent_flags=()
+ flags_with_completion=()
+ flags_completion=()
+
+ flags+=("--verbose")
+ flags+=("-v")
+ local_nonpersistent_flags+=("--verbose")
+
+ must_have_one_flag=()
+ must_have_one_noun=()
+ noun_aliases=()
+}
+
_git-bug_user()
{
last_command="git-bug_user"
@@ -827,6 +850,7 @@ _git-bug_user()
commands=()
commands+=("create")
+ commands+=("ls")
flags=()
two_word_flags=()
diff --git a/misc/zsh_completion/git-bug b/misc/zsh_completion/git-bug
index 1a705f7d..6fc3cf8e 100644
--- a/misc/zsh_completion/git-bug
+++ b/misc/zsh_completion/git-bug
@@ -33,7 +33,7 @@ case $state in
_arguments '2: :(edit)'
;;
user)
- _arguments '2: :(create)'
+ _arguments '2: :(create ls)'
;;
*)
_arguments '*: :_files'