126 lines
3.1 KiB
Go
126 lines
3.1 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"os/exec"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"git.ctrlz.es/mgdelacroix/campaigner/campaign"
|
|
"git.ctrlz.es/mgdelacroix/campaigner/model"
|
|
)
|
|
|
|
const defaultGrepOpts = "-nrFI"
|
|
|
|
func AddCmd() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "add",
|
|
Short: "Adds tickets to the campaign",
|
|
Args: cobra.NoArgs,
|
|
Run: addCmdF,
|
|
}
|
|
|
|
cmd.Flags().StringP("dir", "d", "", "directory containing the source code")
|
|
_ = cmd.MarkFlagRequired("dir")
|
|
cmd.Flags().StringSliceP("grep", "g", []string{}, "runs a grep command to generate the tickets")
|
|
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
|
|
}
|
|
|
|
func parseLine(line string) (*model.Ticket, error) {
|
|
// ToDo: it would be great to be able to relate a line with its
|
|
// parent method, at least for JS and Golang
|
|
parts := strings.Split(line, ":")
|
|
if len(parts) < 3 {
|
|
return nil, fmt.Errorf("cannot parse line: %s", line)
|
|
}
|
|
|
|
filename := parts[0]
|
|
lineNo, err := strconv.Atoi(parts[1])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
text := strings.Join(parts[2:], "")
|
|
|
|
return &model.Ticket{filename, lineNo, text}, nil
|
|
}
|
|
|
|
func RunGrep(dir, str string, exts []string, caseInsensitive bool) ([]*model.Ticket, error) {
|
|
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{}
|
|
for _, line := range strings.Split(string(out), "\n") {
|
|
// ToDo: get and check error
|
|
ticket, _ := parseLine(line)
|
|
if ticket != nil {
|
|
tickets = append(tickets, ticket)
|
|
}
|
|
}
|
|
|
|
return tickets, nil
|
|
}
|
|
|
|
func RunGreps(dir string, strs, exts []string, caseInsensitive bool) ([]*model.Ticket, error) {
|
|
tickets := []*model.Ticket{}
|
|
for _, str := range strs {
|
|
results, err := RunGrep(dir, str, exts, caseInsensitive)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
tickets = append(tickets, results...)
|
|
}
|
|
|
|
tickets = model.RemoveDuplicateTickets(tickets)
|
|
fmt.Printf("%d matches found\n", len(tickets))
|
|
|
|
return tickets, nil
|
|
}
|
|
|
|
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()
|
|
if err != nil {
|
|
ErrorAndExit(cmd, err)
|
|
}
|
|
|
|
cmp.Tickets = append(cmp.Tickets, tickets...)
|
|
cmp.Tickets = model.RemoveDuplicateTickets(cmp.Tickets)
|
|
|
|
if err := campaign.Save(cmp); err != nil {
|
|
ErrorAndExit(cmd, err)
|
|
}
|
|
}
|