1package commands
2
3import (
4 "fmt"
5 "strings"
6
7 "github.com/MichaelMure/git-bug/cache"
8 "github.com/MichaelMure/git-bug/util/colors"
9 "github.com/MichaelMure/git-bug/util/interrupt"
10 "github.com/MichaelMure/git-bug/util/text"
11 "github.com/spf13/cobra"
12)
13
14var (
15 lsStatusQuery []string
16 lsAuthorQuery []string
17 lsParticipantQuery []string
18 lsLabelQuery []string
19 lsTitleQuery []string
20 lsActorQuery []string
21 lsNoQuery []string
22 lsSortBy string
23 lsSortDirection string
24)
25
26func runLsBug(cmd *cobra.Command, args []string) error {
27 backend, err := cache.NewRepoCache(repo)
28 if err != nil {
29 return err
30 }
31 defer backend.Close()
32 interrupt.RegisterCleaner(backend.Close)
33
34 var query *cache.Query
35 if len(args) >= 1 {
36 query, err = cache.ParseQuery(strings.Join(args, " "))
37
38 if err != nil {
39 return err
40 }
41 } else {
42 query, err = lsQueryFromFlags()
43 if err != nil {
44 return err
45 }
46 }
47
48 allIds := backend.QueryBugs(query)
49
50 for _, id := range allIds {
51 b, err := backend.ResolveBugExcerpt(id)
52 if err != nil {
53 return err
54 }
55
56 var name string
57 if b.AuthorId != "" {
58 author, err := backend.ResolveIdentityExcerpt(b.AuthorId)
59 if err != nil {
60 name = "<missing author data>"
61 } else {
62 name = author.DisplayName()
63 }
64 } else {
65 name = b.LegacyAuthor.DisplayName()
66 }
67
68 // truncate + pad if needed
69 titleFmt := text.LeftPadMaxLine(b.Title, 50, 0)
70 authorFmt := text.LeftPadMaxLine(name, 15, 0)
71
72 fmt.Printf("%s %s\t%s\t%s\tC:%d L:%d\n",
73 colors.Cyan(b.Id.Human()),
74 colors.Yellow(b.Status),
75 titleFmt,
76 colors.Magenta(authorFmt),
77 b.LenComments,
78 len(b.Labels),
79 )
80 }
81
82 return nil
83}
84
85// Transform the command flags into a query
86func lsQueryFromFlags() (*cache.Query, error) {
87 query := cache.NewQuery()
88
89 for _, status := range lsStatusQuery {
90 f, err := cache.StatusFilter(status)
91 if err != nil {
92 return nil, err
93 }
94 query.Status = append(query.Status, f)
95 }
96
97 for _, title := range lsTitleQuery {
98 f := cache.TitleFilter(title)
99 query.Title = append(query.Title, f)
100 }
101
102 for _, author := range lsAuthorQuery {
103 f := cache.AuthorFilter(author)
104 query.Author = append(query.Author, f)
105 }
106
107 for _, actor := range lsActorQuery {
108 f := cache.ActorFilter(actor)
109 query.Actor = append(query.Actor, f)
110 }
111
112 for _, participant := range lsParticipantQuery {
113 f := cache.ParticipantFilter(participant)
114 query.Participant = append(query.Participant, f)
115 }
116
117 for _, label := range lsLabelQuery {
118 f := cache.LabelFilter(label)
119 query.Label = append(query.Label, f)
120 }
121
122 for _, no := range lsNoQuery {
123 switch no {
124 case "label":
125 query.NoFilters = append(query.NoFilters, cache.NoLabelFilter())
126 default:
127 return nil, fmt.Errorf("unknown \"no\" filter %s", no)
128 }
129 }
130
131 switch lsSortBy {
132 case "id":
133 query.OrderBy = cache.OrderById
134 case "creation":
135 query.OrderBy = cache.OrderByCreation
136 case "edit":
137 query.OrderBy = cache.OrderByEdit
138 default:
139 return nil, fmt.Errorf("unknown sort flag %s", lsSortBy)
140 }
141
142 switch lsSortDirection {
143 case "asc":
144 query.OrderDirection = cache.OrderAscending
145 case "desc":
146 query.OrderDirection = cache.OrderDescending
147 default:
148 return nil, fmt.Errorf("unknown sort direction %s", lsSortDirection)
149 }
150
151 return query, nil
152}
153
154var lsCmd = &cobra.Command{
155 Use: "ls [<query>]",
156 Short: "List bugs.",
157 Long: `Display a summary of each bugs.
158
159You can pass an additional query to filter and order the list. This query can be expressed either with a simple query language or with flags.`,
160 Example: `List open bugs sorted by last edition with a query:
161git bug ls status:open sort:edit-desc
162
163List closed bugs sorted by creation with flags:
164git bug ls --status closed --by creation
165`,
166 PreRunE: loadRepo,
167 RunE: runLsBug,
168}
169
170func init() {
171 RootCmd.AddCommand(lsCmd)
172
173 lsCmd.Flags().SortFlags = false
174
175 lsCmd.Flags().StringSliceVarP(&lsStatusQuery, "status", "s", nil,
176 "Filter by status. Valid values are [open,closed]")
177 lsCmd.Flags().StringSliceVarP(&lsAuthorQuery, "author", "a", nil,
178 "Filter by author")
179 lsCmd.Flags().StringSliceVarP(&lsParticipantQuery, "participant", "p", nil,
180 "Filter by participant")
181 lsCmd.Flags().StringSliceVarP(&lsActorQuery, "actor", "A", nil,
182 "Filter by actor")
183 lsCmd.Flags().StringSliceVarP(&lsLabelQuery, "label", "l", nil,
184 "Filter by label")
185 lsCmd.Flags().StringSliceVarP(&lsTitleQuery, "title", "t", nil,
186 "Filter by title")
187 lsCmd.Flags().StringSliceVarP(&lsNoQuery, "no", "n", nil,
188 "Filter by absence of something. Valid values are [label]")
189 lsCmd.Flags().StringVarP(&lsSortBy, "by", "b", "creation",
190 "Sort the results by a characteristic. Valid values are [id,creation,edit]")
191 lsCmd.Flags().StringVarP(&lsSortDirection, "direction", "d", "asc",
192 "Select the sorting direction. Valid values are [asc,desc]")
193}