Modify add to parse stdin
This commit is contained in:
parent
41b8e5db55
commit
b38a0ff437
3 changed files with 42 additions and 67 deletions
|
@ -41,7 +41,7 @@ Use "campaigner [command] --help" for more information about a command.
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
- [ ] Modify the add command to only act on `stdin`, using the
|
- [x] Modify the add command to only act on `stdin`, using the
|
||||||
`--grep` and `--govet` flags to distinguish how to parse the
|
`--grep` and `--govet` flags to distinguish how to parse the
|
||||||
input.
|
input.
|
||||||
- [ ] Add `--ag` to the `add` command.
|
- [ ] Add `--ag` to the `add` command.
|
||||||
|
|
103
cmd/add.go
103
cmd/add.go
|
@ -1,8 +1,9 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/exec"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -12,28 +13,29 @@ import (
|
||||||
"git.ctrlz.es/mgdelacroix/campaigner/model"
|
"git.ctrlz.es/mgdelacroix/campaigner/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultGrepOpts = "-nrFI"
|
|
||||||
|
|
||||||
func AddCmd() *cobra.Command {
|
func AddCmd() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "add",
|
Use: "add",
|
||||||
Short: "Adds tickets to the campaign",
|
Short: "Adds tickets to the campaign from the output of grep/ag/govet",
|
||||||
|
Long: `Generates tickets for the campaign reading from the standard input the output of one of the following three commands:
|
||||||
|
- grep (should be run with the -n flag)
|
||||||
|
- ag
|
||||||
|
- govet (should be run with the -json flag)`,
|
||||||
|
Example: ` grep -nriIF --include \*.go cobra.Command | campaigner add --grep
|
||||||
|
ag cobra.Command | campaigner add --ag
|
||||||
|
govet -json ./... | campaigner add --govet`,
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
Run: addCmdF,
|
RunE: addCmdF,
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().StringP("dir", "d", "", "directory containing the source code")
|
cmd.Flags().BoolP("ag", "a", false, "generates the tickets reading ag's output from stdin")
|
||||||
_ = cmd.MarkFlagRequired("dir")
|
cmd.Flags().BoolP("grep", "g", false, "generates the tickets reading grep's output from stdin")
|
||||||
cmd.Flags().StringSliceP("grep", "g", []string{}, "runs a grep command to generate the tickets")
|
cmd.Flags().BoolP("govet", "v", false, "generates the tickets reading govet's output from stdin")
|
||||||
cmd.Flags().BoolP("case-insensitive", "i", false, "makes the search case insensitive")
|
|
||||||
cmd.Flags().StringSliceP("ext", "e", []string{}, "limits the grep to files with certain extensions")
|
|
||||||
// cmd.Flags().StringP("govet", "v", "", "runs a govet command to generate the tickets")
|
|
||||||
// govet bin path?
|
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseLine(line string) (*model.Ticket, error) {
|
func parseGrepLine(line string) (*model.Ticket, error) {
|
||||||
// ToDo: it would be great to be able to relate a line with its
|
// ToDo: it would be great to be able to relate a line with its
|
||||||
// parent method, at least for JS and Golang
|
// parent method, at least for JS and Golang
|
||||||
parts := strings.Split(line, ":")
|
parts := strings.Split(line, ":")
|
||||||
|
@ -48,68 +50,40 @@ func parseLine(line string) (*model.Ticket, error) {
|
||||||
}
|
}
|
||||||
text := strings.Join(parts[2:], "")
|
text := strings.Join(parts[2:], "")
|
||||||
|
|
||||||
return &model.Ticket{filename, lineNo, text}, nil
|
return &model.Ticket{
|
||||||
|
Filename: filename,
|
||||||
|
LineNo: lineNo,
|
||||||
|
Text: text,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunGrep(dir, str string, exts []string, caseInsensitive bool) ([]*model.Ticket, error) {
|
func parseGrep() []*model.Ticket {
|
||||||
opts := defaultGrepOpts
|
|
||||||
if caseInsensitive {
|
|
||||||
opts = opts + "i"
|
|
||||||
}
|
|
||||||
|
|
||||||
includes := []string{}
|
|
||||||
for _, ext := range exts {
|
|
||||||
if strings.HasPrefix(ext, ".") {
|
|
||||||
ext = ext[1:]
|
|
||||||
}
|
|
||||||
includes = append(includes, []string{"--include", "*." + ext}...)
|
|
||||||
}
|
|
||||||
|
|
||||||
args := append([]string{opts}, includes...)
|
|
||||||
args = append(args, str, dir)
|
|
||||||
|
|
||||||
out, err := exec.Command("grep", args...).Output()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("execution of grep failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tickets := []*model.Ticket{}
|
tickets := []*model.Ticket{}
|
||||||
for _, line := range strings.Split(string(out), "\n") {
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
// ToDo: get and check error
|
for scanner.Scan() {
|
||||||
ticket, _ := parseLine(line)
|
ticket, _ := parseGrepLine(scanner.Text())
|
||||||
if ticket != nil {
|
if ticket != nil {
|
||||||
tickets = append(tickets, ticket)
|
tickets = append(tickets, ticket)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return tickets
|
||||||
return tickets, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunGreps(dir string, strs, exts []string, caseInsensitive bool) ([]*model.Ticket, error) {
|
func addCmdF(cmd *cobra.Command, _ []string) error {
|
||||||
tickets := []*model.Ticket{}
|
grep, _ := cmd.Flags().GetBool("grep")
|
||||||
for _, str := range strs {
|
ag, _ := cmd.Flags().GetBool("ag")
|
||||||
results, err := RunGrep(dir, str, exts, caseInsensitive)
|
govet, _ := cmd.Flags().GetBool("govet")
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
if !grep && !ag && !govet {
|
||||||
}
|
return fmt.Errorf("one of --grep --ag --govet flags should be active")
|
||||||
tickets = append(tickets, results...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tickets = model.RemoveDuplicateTickets(tickets)
|
var tickets []*model.Ticket
|
||||||
fmt.Printf("%d matches found\n", len(tickets))
|
switch {
|
||||||
|
case grep:
|
||||||
return tickets, nil
|
tickets = parseGrep()
|
||||||
}
|
default:
|
||||||
|
return fmt.Errorf("not implemented yet")
|
||||||
func addCmdF(cmd *cobra.Command, _ []string) {
|
|
||||||
dir, _ := cmd.Flags().GetString("dir")
|
|
||||||
grepStrs, _ := cmd.Flags().GetStringSlice("grep")
|
|
||||||
extStrs, _ := cmd.Flags().GetStringSlice("ext")
|
|
||||||
caseInsensitive, _ := cmd.Flags().GetBool("case-insensitive")
|
|
||||||
|
|
||||||
tickets, err := RunGreps(dir, grepStrs, extStrs, caseInsensitive)
|
|
||||||
if err != nil {
|
|
||||||
ErrorAndExit(cmd, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmp, err := campaign.Read()
|
cmp, err := campaign.Read()
|
||||||
|
@ -123,4 +97,5 @@ func addCmdF(cmd *cobra.Command, _ []string) {
|
||||||
if err := campaign.Save(cmp); err != nil {
|
if err := campaign.Save(cmp); err != nil {
|
||||||
ErrorAndExit(cmd, err)
|
ErrorAndExit(cmd, err)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ func InitCmd() *cobra.Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().StringP("epic", "e", "", "the epic id to associate this campaign with")
|
cmd.Flags().StringP("epic", "e", "", "the epic id to associate this campaign with")
|
||||||
cmd.MarkFlagRequired("epic")
|
_ = cmd.MarkFlagRequired("epic")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue