mirror of
https://github.com/Threnklyn/jira.git
synced 2026-06-07 13:33:32 +02:00
adding request command, removing dead code
This commit is contained in:
+5
-281
@@ -254,6 +254,11 @@ func main() {
|
||||
Entry: cli.CmdBrowseRegistry(),
|
||||
Aliases: []string{"b"},
|
||||
},
|
||||
jiracli.CommandRegistry{
|
||||
Command: "request",
|
||||
Entry: cli.CmdRequestRegistry(),
|
||||
Aliases: []string{"req"},
|
||||
},
|
||||
}
|
||||
|
||||
cli.Register(app, registry)
|
||||
@@ -270,285 +275,4 @@ func main() {
|
||||
if err != nil {
|
||||
log.Fatalf("%s", err)
|
||||
}
|
||||
|
||||
// Usage:
|
||||
// jira (b|browse) ISSUE
|
||||
// jira request [-M METHOD] URI [DATA]
|
||||
// jira ISSUE
|
||||
|
||||
// General Options:
|
||||
// -b --browse Open your browser to the Jira issue
|
||||
// -e --endpoint=URI URI to use for jira
|
||||
// -k --insecure disable TLS certificate verification
|
||||
// -h --help Show this usage
|
||||
// -t --template=FILE Template file to use for output/editing
|
||||
// -u --user=USER Username to use for authenticaion (default: %s)
|
||||
// -v --verbose Increase output logging
|
||||
// --unixproxy=PATH Path for a unix-socket proxy (eg., --unixproxy /tmp/proxy.sock)
|
||||
// --version Print version
|
||||
|
||||
// Query Options:
|
||||
// -a --assignee=USER Username assigned the issue
|
||||
// -c --component=COMPONENT Component to Search for
|
||||
// -f --queryfields=FIELDS Fields that are used in "list" template: (default: %s)
|
||||
// -i --issuetype=ISSUETYPE The Issue Type
|
||||
// -l --limit=VAL Maximum number of results to return in query (default: %d)
|
||||
// --start=START Start parameter for pagination
|
||||
// -p --project=PROJECT Project to Search for
|
||||
// -q --query=JQL Jira Query Language expression for the search
|
||||
// -r --reporter=USER Reporter to search for
|
||||
// -s --sort=ORDER For list operations, sort issues (default: %s)
|
||||
|
||||
// Edit Options:
|
||||
// -m --comment=COMMENT Comment message for transition
|
||||
// -o --override=KEY=VAL Set custom key/value pairs
|
||||
|
||||
// Create Options:
|
||||
// -i --issuetype=ISSUETYPE Jira Issue Type (default: Bug)
|
||||
// -m --comment=COMMENT Comment message for transition
|
||||
// -o --override=KEY=VAL Set custom key/value pairs
|
||||
|
||||
// Worklog Options:
|
||||
// -T --time-spent=TIMESPENT Time spent working on issue
|
||||
// -m --comment=COMMENT Comment message for worklog
|
||||
|
||||
// Command Options:
|
||||
// -d --directory=DIR Directory to export templates to (default: %s)
|
||||
// `, user, defaultQueryFields, defaultMaxResults, defaultSort, user, fmt.Sprintf("%s/.jira.d/templates", home))
|
||||
// printer(output)
|
||||
// }
|
||||
|
||||
// jiraCommands := map[string]string{
|
||||
// "browse": "browse",
|
||||
// "req": "request",
|
||||
// "request": "request",
|
||||
// }
|
||||
|
||||
// defaults := map[string]interface{}{
|
||||
// "user": user,
|
||||
// "queryfields": defaultQueryFields,
|
||||
// "directory": fmt.Sprintf("%s/.jira.d/templates", home),
|
||||
// "sort": defaultSort,
|
||||
// "max_results": defaultMaxResults,
|
||||
// "method": "GET",
|
||||
// "quiet": false,
|
||||
// }
|
||||
// opts := make(map[string]interface{})
|
||||
|
||||
// setopt := func(name string, value interface{}) {
|
||||
// opts[name] = value
|
||||
// }
|
||||
|
||||
// op := optigo.NewDirectAssignParser(map[string]interface{}{
|
||||
// "h|help": usage,
|
||||
// "version": func() {
|
||||
// fmt.Println(fmt.Sprintf("version: %s", jira.VERSION))
|
||||
// os.Exit(0)
|
||||
// },
|
||||
// "v|verbose+": func() {
|
||||
// logging.SetLevel(logging.GetLevel("")+1, "")
|
||||
// },
|
||||
// "dryrun": setopt,
|
||||
// "b|browse": setopt,
|
||||
// "editor=s": setopt,
|
||||
// "u|user=s": setopt,
|
||||
// "endpoint=s": setopt,
|
||||
// "k|insecure": setopt,
|
||||
// "t|template=s": setopt,
|
||||
// "q|query=s": setopt,
|
||||
// "p|project=s": setopt,
|
||||
// "c|component=s": setopt,
|
||||
// "a|assignee=s": setopt,
|
||||
// "i|issuetype=s": setopt,
|
||||
// "remove": setopt,
|
||||
// "r|reporter=s": setopt,
|
||||
// "f|queryfields=s": setopt,
|
||||
// "x|expand=s": setopt,
|
||||
// "s|sort=s": setopt,
|
||||
// "l|limit|max_results=i": setopt,
|
||||
// "start|start_at=i": setopt,
|
||||
// "o|override=s%": &opts,
|
||||
// "noedit": setopt,
|
||||
// "edit": setopt,
|
||||
// "m|comment=s": setopt,
|
||||
// "d|dir|directory=s": setopt,
|
||||
// "M|method=s": setopt,
|
||||
// "S|saveFile=s": setopt,
|
||||
// "T|time-spent=s": setopt,
|
||||
// "Q|quiet": setopt,
|
||||
// "unixproxy": setopt,
|
||||
// "down": setopt,
|
||||
// "default": setopt,
|
||||
// })
|
||||
|
||||
// if err := op.ProcessAll(os.Args[1:]); err != nil {
|
||||
// log.Errorf("%s", err)
|
||||
// usage(false)
|
||||
// }
|
||||
// args := op.Args
|
||||
|
||||
// var command string
|
||||
// if len(args) > 0 {
|
||||
// if alias, ok := jiraCommands[args[0]]; ok {
|
||||
// command = alias
|
||||
// args = args[1:]
|
||||
// } else if len(args) > 1 {
|
||||
// // look at second arg for "dups" and "blocks" commands
|
||||
// // also for 'set/add/remove' actions like 'labels'
|
||||
// if alias, ok := jiraCommands[args[1]]; ok {
|
||||
// command = alias
|
||||
// args = append(args[:1], args[2:]...)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// if command == "" && len(args) > 0 {
|
||||
// command = args[0]
|
||||
// args = args[1:]
|
||||
// }
|
||||
|
||||
// os.Setenv("JIRA_OPERATION", command)
|
||||
// loadConfigs(opts)
|
||||
|
||||
// // check to see if it was set in the configs:
|
||||
// if value, ok := opts["command"].(string); ok {
|
||||
// command = value
|
||||
// } else if _, ok := jiraCommands[command]; !ok || command == "" {
|
||||
// if command != "" {
|
||||
// args = append([]string{command}, args...)
|
||||
// }
|
||||
// command = "view"
|
||||
// }
|
||||
|
||||
// // apply defaults
|
||||
// for k, v := range defaults {
|
||||
// if _, ok := opts[k]; !ok {
|
||||
// log.Debugf("Setting %q to %#v from defaults", k, v)
|
||||
// opts[k] = v
|
||||
// }
|
||||
// }
|
||||
|
||||
// log.Debugf("opts: %v", opts)
|
||||
// log.Debugf("args: %v", args)
|
||||
|
||||
// if _, ok := opts["endpoint"]; !ok {
|
||||
// log.Errorf("endpoint option required. Either use --endpoint or set a endpoint option in your ~/.jira.d/config.yml file")
|
||||
// os.Exit(1)
|
||||
// }
|
||||
|
||||
// c := jira.New(opts)
|
||||
|
||||
// log.Debugf("opts: %s", opts)
|
||||
|
||||
// setEditing := func(dflt bool) {
|
||||
// log.Debugf("Default Editing: %t", dflt)
|
||||
// if dflt {
|
||||
// if val, ok := opts["noedit"].(bool); ok && val {
|
||||
// log.Debugf("Setting edit = false")
|
||||
// opts["edit"] = false
|
||||
// } else {
|
||||
// log.Debugf("Setting edit = true")
|
||||
// opts["edit"] = true
|
||||
// }
|
||||
// } else {
|
||||
// if _, ok := opts["edit"].(bool); !ok {
|
||||
// log.Debugf("Setting edit = %t", dflt)
|
||||
// opts["edit"] = dflt
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// requireArgs := func(count int) {
|
||||
// if len(args) < count {
|
||||
// log.Errorf("Not enough arguments. %d required, %d provided", count, len(args))
|
||||
// usage(false)
|
||||
// }
|
||||
// }
|
||||
|
||||
// var err error
|
||||
// switch command {
|
||||
// case "request":
|
||||
// requireArgs(1)
|
||||
// data := ""
|
||||
// if len(args) > 1 {
|
||||
// data = args[1]
|
||||
// }
|
||||
// err = c.CmdRequest(args[0], data)
|
||||
// default:
|
||||
// log.Errorf("Unknown command %s", command)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
|
||||
// if err != nil {
|
||||
// log.Errorf("%s", err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// os.Exit(0)
|
||||
}
|
||||
|
||||
// func parseYaml(file string, opts map[string]interface{}) {
|
||||
// if fh, err := ioutil.ReadFile(file); err == nil {
|
||||
// log.Debugf("Found Config file: %s", file)
|
||||
// if err := yaml.Unmarshal(fh, &opts); err != nil {
|
||||
// log.Errorf("Unable to parse %s: %s", file, err)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// func populateEnv(opts map[string]interface{}) {
|
||||
// for k, v := range opts {
|
||||
// envName := fmt.Sprintf("JIRA_%s", strings.ToUpper(k))
|
||||
// var val string
|
||||
// switch t := v.(type) {
|
||||
// case string:
|
||||
// val = t
|
||||
// case int, int8, int16, int32, int64:
|
||||
// val = fmt.Sprintf("%d", t)
|
||||
// case float32, float64:
|
||||
// val = fmt.Sprintf("%f", t)
|
||||
// case bool:
|
||||
// val = fmt.Sprintf("%t", t)
|
||||
// default:
|
||||
// val = fmt.Sprintf("%v", t)
|
||||
// }
|
||||
// os.Setenv(envName, val)
|
||||
// }
|
||||
// }
|
||||
|
||||
// func loadConfigs(opts map[string]interface{}) {
|
||||
// populateEnv(opts)
|
||||
// paths := jira.FindParentPaths(".jira.d/config.yml")
|
||||
// // prepend
|
||||
// paths = append(paths, "/etc/go-jira.yml")
|
||||
|
||||
// // iterate paths in reverse
|
||||
// for i := 0; i < len(paths); i++ {
|
||||
// file := paths[i]
|
||||
// if stat, err := os.Stat(file); err == nil {
|
||||
// tmp := make(map[string]interface{})
|
||||
// // check to see if config file is exectuable
|
||||
// if stat.Mode()&0111 == 0 {
|
||||
// parseYaml(file, tmp)
|
||||
// } else {
|
||||
// log.Debugf("Found Executable Config file: %s", file)
|
||||
// // it is executable, so run it and try to parse the output
|
||||
// cmd := exec.Command(file)
|
||||
// stdout := bytes.NewBufferString("")
|
||||
// cmd.Stdout = stdout
|
||||
// cmd.Stderr = bytes.NewBufferString("")
|
||||
// if err := cmd.Run(); err != nil {
|
||||
// log.Errorf("%s is exectuable, but it failed to execute: %s\n%s", file, err, cmd.Stderr)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// yaml.Unmarshal(stdout.Bytes(), &tmp)
|
||||
// }
|
||||
// for k, v := range tmp {
|
||||
// if _, ok := opts[k]; !ok {
|
||||
// log.Debugf("Setting %q to %#v from %s", k, v, file)
|
||||
// opts[k] = v
|
||||
// }
|
||||
// }
|
||||
// populateEnv(opts)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
+64
-323
@@ -31,17 +31,6 @@ type JiraCli struct {
|
||||
oreoAgent *oreo.Client
|
||||
}
|
||||
|
||||
func New(configDir string) *JiraCli {
|
||||
agent := oreo.New().WithCookieFile(filepath.Join(homedir(), configDir, "cookies.js"))
|
||||
return &JiraCli{
|
||||
ConfigDir: configDir,
|
||||
Jira: jira.Jira{
|
||||
UA: agent,
|
||||
},
|
||||
oreoAgent: agent,
|
||||
}
|
||||
}
|
||||
|
||||
type Exit struct {
|
||||
Code int
|
||||
}
|
||||
@@ -55,6 +44,70 @@ type GlobalOptions struct {
|
||||
User string `json:"user,omitempty", yaml:"user,omitempty"`
|
||||
}
|
||||
|
||||
type CommandRegistryEntry struct {
|
||||
Help string
|
||||
ExecuteFunc func() error
|
||||
UsageFunc func(*kingpin.CmdClause) error
|
||||
}
|
||||
|
||||
type CommandRegistry struct {
|
||||
Command string
|
||||
Aliases []string
|
||||
Entry *CommandRegistryEntry
|
||||
Default bool
|
||||
}
|
||||
|
||||
// either kingpin.Application or kingpin.CmdClause fit this interface
|
||||
type kingpinAppOrCommand interface {
|
||||
Command(string, string) *kingpin.CmdClause
|
||||
GetCommand(string) *kingpin.CmdClause
|
||||
}
|
||||
|
||||
func New(configDir string) *JiraCli {
|
||||
agent := oreo.New().WithCookieFile(filepath.Join(homedir(), configDir, "cookies.js"))
|
||||
return &JiraCli{
|
||||
ConfigDir: configDir,
|
||||
Jira: jira.Jira{
|
||||
UA: agent,
|
||||
},
|
||||
oreoAgent: agent,
|
||||
}
|
||||
}
|
||||
|
||||
func (jc *JiraCli) Register(app *kingpin.Application, reg []CommandRegistry) {
|
||||
for _, command := range reg {
|
||||
copy := command
|
||||
commandFields := strings.Fields(copy.Command)
|
||||
var appOrCmd kingpinAppOrCommand = app
|
||||
if len(commandFields) > 1 {
|
||||
for _, name := range commandFields[0 : len(commandFields)-1] {
|
||||
tmp := appOrCmd.GetCommand(name)
|
||||
if tmp == nil {
|
||||
tmp = appOrCmd.Command(name, "")
|
||||
}
|
||||
appOrCmd = tmp
|
||||
}
|
||||
}
|
||||
|
||||
cmd := appOrCmd.Command(commandFields[len(commandFields)-1], copy.Entry.Help)
|
||||
for _, alias := range copy.Aliases {
|
||||
cmd = cmd.Alias(alias)
|
||||
}
|
||||
if copy.Default {
|
||||
cmd = cmd.Default()
|
||||
}
|
||||
if copy.Entry.UsageFunc != nil {
|
||||
copy.Entry.UsageFunc(cmd)
|
||||
}
|
||||
|
||||
cmd.Action(
|
||||
func(_ *kingpin.ParseContext) error {
|
||||
return copy.Entry.ExecuteFunc()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (jc *JiraCli) GlobalUsage(cmd *kingpin.CmdClause, opts *GlobalOptions) error {
|
||||
jc.LoadConfigs(cmd, opts)
|
||||
cmd.PreAction(func(_ *kingpin.ParseContext) error {
|
||||
@@ -265,315 +318,3 @@ func (jc *JiraCli) editLoop(opts *GlobalOptions, input interface{}, output inter
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// // New creates go-jira client object
|
||||
// func New(opts map[string]interface{}) *Cli {
|
||||
// homedir := homedir()
|
||||
// cookieJar, _ := cookiejar.New(nil)
|
||||
// endpoint, _ := opts["endpoint"].(string)
|
||||
// url, _ := url.Parse(strings.TrimRight(endpoint, "/"))
|
||||
|
||||
// if project, ok := opts["project"].(string); ok {
|
||||
// opts["project"] = strings.ToUpper(project)
|
||||
// }
|
||||
|
||||
// var ua *http.Client
|
||||
// if unixProxyPath, ok := opts["unixproxy"].(string); ok {
|
||||
// ua = &http.Client{
|
||||
// Jar: cookieJar,
|
||||
// Transport: UnixProxy(unixProxyPath),
|
||||
// }
|
||||
// } else {
|
||||
// transport := &http.Transport{
|
||||
// Proxy: http.ProxyFromEnvironment,
|
||||
// TLSClientConfig: &tls.Config{},
|
||||
// }
|
||||
// if insecureSkipVerify, ok := opts["insecure"].(bool); ok {
|
||||
// transport.TLSClientConfig.InsecureSkipVerify = insecureSkipVerify
|
||||
// }
|
||||
|
||||
// ua = &http.Client{
|
||||
// Jar: cookieJar,
|
||||
// Transport: transport,
|
||||
// }
|
||||
// }
|
||||
|
||||
// cli := &Cli{
|
||||
// endpoint: url,
|
||||
// opts: opts,
|
||||
// cookieFile: filepath.Join(homedir, ".jira.d", "cookies.js"),
|
||||
// ua: ua,
|
||||
// }
|
||||
|
||||
// cli.ua.Jar.SetCookies(url, cli.loadCookies())
|
||||
|
||||
// return cli
|
||||
// }
|
||||
|
||||
// // NoChangesFound is an error returned from when editing templates
|
||||
// // and no modifications were made while editing
|
||||
// type NoChangesFound struct{}
|
||||
|
||||
// func (f NoChangesFound) Error() string {
|
||||
// return "No changes found, aborting"
|
||||
// }
|
||||
|
||||
// func (c *Cli) editTemplate(template string, tmpFilePrefix string, templateData map[string]interface{}, templateProcessor func(string) error) error {
|
||||
|
||||
// tmpdir := filepath.Join(homedir(), ".jira.d", "tmp")
|
||||
// if err := mkdir(tmpdir); err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// fh, err := ioutil.TempFile(tmpdir, tmpFilePrefix)
|
||||
// if err != nil {
|
||||
// log.Errorf("Failed to make temp file in %s: %s", tmpdir, err)
|
||||
// return err
|
||||
// }
|
||||
|
||||
// oldFileName := fh.Name()
|
||||
// tmpFileName := fmt.Sprintf("%s.yml", oldFileName)
|
||||
|
||||
// // close tmpfile so we can rename on windows
|
||||
// fh.Close()
|
||||
|
||||
// if err := os.Rename(oldFileName, tmpFileName); err != nil {
|
||||
// log.Errorf("Failed to rename %s to %s: %s", oldFileName, tmpFileName, err)
|
||||
// return err
|
||||
// }
|
||||
|
||||
// fh, err = os.OpenFile(tmpFileName, os.O_RDWR|os.O_EXCL, 0600)
|
||||
// if err != nil {
|
||||
// log.Errorf("Failed to reopen temp file file in %s: %s", tmpFileName, err)
|
||||
// return err
|
||||
// }
|
||||
|
||||
// defer fh.Close()
|
||||
// defer func() {
|
||||
// os.Remove(tmpFileName)
|
||||
// }()
|
||||
|
||||
// err = runTemplate(template, templateData, fh)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// fh.Close()
|
||||
|
||||
// editor, ok := c.opts["editor"].(string)
|
||||
// if !ok {
|
||||
// editor = os.Getenv("JIRA_EDITOR")
|
||||
// if editor == "" {
|
||||
// editor = os.Getenv("EDITOR")
|
||||
// if editor == "" {
|
||||
// editor = "vim"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// editing := c.getOptBool("edit", true)
|
||||
|
||||
// tmpFileNameOrig := fmt.Sprintf("%s.orig", tmpFileName)
|
||||
// copyFile(tmpFileName, tmpFileNameOrig)
|
||||
// defer func() {
|
||||
// os.Remove(tmpFileNameOrig)
|
||||
// }()
|
||||
|
||||
// for true {
|
||||
// if editing {
|
||||
// shell, _ := shellquote.Split(editor)
|
||||
// shell = append(shell, tmpFileName)
|
||||
// log.Debugf("Running: %#v", shell)
|
||||
// cmd := exec.Command(shell[0], shell[1:]...)
|
||||
// cmd.Stdout, cmd.Stderr, cmd.Stdin = os.Stdout, os.Stderr, os.Stdin
|
||||
// if err := cmd.Run(); err != nil {
|
||||
// log.Errorf("Failed to edit template with %s: %s", editor, err)
|
||||
// if promptYN("edit again?", true) {
|
||||
// continue
|
||||
// }
|
||||
// return err
|
||||
// }
|
||||
|
||||
// diff := exec.Command("diff", "-q", tmpFileNameOrig, tmpFileName)
|
||||
// // if err == nil then diff found no changes
|
||||
// if err := diff.Run(); err == nil {
|
||||
// return NoChangesFound{}
|
||||
// }
|
||||
// }
|
||||
|
||||
// edited := make(map[string]interface{})
|
||||
// var data []byte
|
||||
// if data, err = ioutil.ReadFile(tmpFileName); err != nil {
|
||||
// log.Errorf("Failed to read tmpfile %s: %s", tmpFileName, err)
|
||||
// if editing && promptYN("edit again?", true) {
|
||||
// continue
|
||||
// }
|
||||
// return err
|
||||
// }
|
||||
// if err := yaml.Unmarshal(data, &edited); err != nil {
|
||||
// log.Errorf("Failed to parse YAML: %s", err)
|
||||
// if editing && promptYN("edit again?", true) {
|
||||
// continue
|
||||
// }
|
||||
// return err
|
||||
// }
|
||||
|
||||
// var fixed interface{}
|
||||
// if fixed, err = yamlFixup(edited); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// edited = fixed.(map[string]interface{})
|
||||
|
||||
// // if you want to abort editing a jira issue then
|
||||
// // you can add the "abort: true" flag to the document
|
||||
// // and we will abort now
|
||||
// if val, ok := edited["abort"].(bool); ok && val {
|
||||
// log.Infof("abort flag found in template, quiting")
|
||||
// return fmt.Errorf("abort flag found in template, quiting")
|
||||
// }
|
||||
|
||||
// if _, ok := templateData["meta"]; ok {
|
||||
// mf := templateData["meta"].(map[string]interface{})["fields"]
|
||||
// if f, ok := edited["fields"].(map[string]interface{}); ok {
|
||||
// for k := range f {
|
||||
// if _, ok := mf.(map[string]interface{})[k]; !ok {
|
||||
// err := fmt.Errorf("Field %s is not editable", k)
|
||||
// log.Errorf("%s", err)
|
||||
// if editing && promptYN("edit again?", true) {
|
||||
// continue
|
||||
// }
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// json, err := jsonEncode(edited)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// if err := templateProcessor(json); err != nil {
|
||||
// log.Errorf("%s", err)
|
||||
// if editing && promptYN("edit again?", true) {
|
||||
// continue
|
||||
// }
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// // SaveData will write out the yaml formated --saveFile file with provided data
|
||||
// func (c *Cli) SaveData(data interface{}) error {
|
||||
// if val, ok := c.opts["saveFile"].(string); ok && val != "" {
|
||||
// yamlWrite(val, data)
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// // FindIssues will return a list of issues that match the given options.
|
||||
// // If the "query" option is undefined it will generate a JQL query
|
||||
// // using any/all of the provide options: project, component, assignee,
|
||||
// // issuetype, watcher, reporter, sort
|
||||
// // Further it will restrict the fields being extracted from the jira
|
||||
// // response with the 'queryfields' option
|
||||
// func (c *Cli) FindIssues() (interface{}, error) {
|
||||
// var query string
|
||||
// var ok bool
|
||||
// // project = BAKERY and status not in (Resolved, Closed)
|
||||
// if query, ok = c.opts["query"].(string); !ok {
|
||||
// qbuff := bytes.NewBufferString("resolution = unresolved")
|
||||
// var project string
|
||||
// if project, ok = c.opts["project"].(string); !ok {
|
||||
// err := fmt.Errorf("Missing required arguments, either 'query' or 'project' are required")
|
||||
// log.Errorf("%s", err)
|
||||
// return nil, err
|
||||
// }
|
||||
// qbuff.WriteString(fmt.Sprintf(" AND project = '%s'", project))
|
||||
|
||||
// if component, ok := c.opts["component"]; ok {
|
||||
// qbuff.WriteString(fmt.Sprintf(" AND component = '%s'", component))
|
||||
// }
|
||||
|
||||
// if assignee, ok := c.opts["assignee"]; ok {
|
||||
// qbuff.WriteString(fmt.Sprintf(" AND assignee = '%s'", assignee))
|
||||
// }
|
||||
|
||||
// if issuetype, ok := c.opts["issuetype"]; ok {
|
||||
// qbuff.WriteString(fmt.Sprintf(" AND issuetype = '%s'", issuetype))
|
||||
// }
|
||||
|
||||
// if watcher, ok := c.opts["watcher"]; ok {
|
||||
// qbuff.WriteString(fmt.Sprintf(" AND watcher = '%s'", watcher))
|
||||
// }
|
||||
|
||||
// if reporter, ok := c.opts["reporter"]; ok {
|
||||
// qbuff.WriteString(fmt.Sprintf(" AND reporter = '%s'", reporter))
|
||||
// }
|
||||
|
||||
// if sort, ok := c.opts["sort"]; ok && sort != "" {
|
||||
// qbuff.WriteString(fmt.Sprintf(" ORDER BY %s", sort))
|
||||
// }
|
||||
|
||||
// query = qbuff.String()
|
||||
// }
|
||||
|
||||
// fields := []string{"summary"}
|
||||
// if qf, ok := c.opts["queryfields"].(string); ok {
|
||||
// fields = strings.Split(qf, ",")
|
||||
// }
|
||||
|
||||
// json, err := jsonEncode(map[string]interface{}{
|
||||
// "jql": query,
|
||||
// "startAt": c.opts["start_at"],
|
||||
// "maxResults": c.opts["max_results"],
|
||||
// "fields": fields,
|
||||
// "expand": c.expansions(),
|
||||
// })
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
// uri := fmt.Sprintf("%s/rest/api/2/search", c.endpoint)
|
||||
// var data interface{}
|
||||
// if data, err = responseToJSON(c.post(uri, json)); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// return data, nil
|
||||
// }
|
||||
|
||||
// // GetOptString will extract the string from the Cli object options
|
||||
// // otherwise return the provided default
|
||||
// func (c *Cli) GetOptString(optName string, dflt string) string {
|
||||
// return c.getOptString(optName, dflt)
|
||||
// }
|
||||
|
||||
// func (c *Cli) getOptString(optName string, dflt string) string {
|
||||
// if val, ok := c.opts[optName].(string); ok {
|
||||
// return val
|
||||
// }
|
||||
// return dflt
|
||||
// }
|
||||
|
||||
// // GetOptBool will extract the boolean value from the Client object options
|
||||
// // otherwise return the provided default\
|
||||
// func (c *Cli) GetOptBool(optName string, dflt bool) bool {
|
||||
// return c.getOptBool(optName, dflt)
|
||||
// }
|
||||
|
||||
// func (c *Cli) getOptBool(optName string, dflt bool) bool {
|
||||
// if val, ok := c.opts[optName].(bool); ok {
|
||||
// return val
|
||||
// }
|
||||
// return dflt
|
||||
// }
|
||||
|
||||
// // expansions returns a comma-separated list of values for field expansion
|
||||
// func (c *Cli) expansions() []string {
|
||||
// var expansions []string
|
||||
// if x, ok := c.opts["expand"].(string); ok {
|
||||
// expansions = strings.Split(x, ",")
|
||||
// }
|
||||
// return expansions
|
||||
// }
|
||||
|
||||
@@ -1,83 +1 @@
|
||||
package jiracli
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
type CommandRegistryEntry struct {
|
||||
Help string
|
||||
ExecuteFunc func() error
|
||||
UsageFunc func(*kingpin.CmdClause) error
|
||||
}
|
||||
|
||||
type CommandRegistry struct {
|
||||
Command string
|
||||
Aliases []string
|
||||
Entry *CommandRegistryEntry
|
||||
Default bool
|
||||
}
|
||||
|
||||
// either kingpin.Application or kingpin.CmdClause fit this interface
|
||||
type kingpinAppOrCommand interface {
|
||||
Command(string, string) *kingpin.CmdClause
|
||||
GetCommand(string) *kingpin.CmdClause
|
||||
}
|
||||
|
||||
func (jc *JiraCli) Register(app *kingpin.Application, reg []CommandRegistry) {
|
||||
for _, command := range reg {
|
||||
copy := command
|
||||
commandFields := strings.Fields(copy.Command)
|
||||
var appOrCmd kingpinAppOrCommand = app
|
||||
if len(commandFields) > 1 {
|
||||
for _, name := range commandFields[0 : len(commandFields)-1] {
|
||||
tmp := appOrCmd.GetCommand(name)
|
||||
if tmp == nil {
|
||||
tmp = appOrCmd.Command(name, "")
|
||||
}
|
||||
appOrCmd = tmp
|
||||
}
|
||||
}
|
||||
|
||||
cmd := appOrCmd.Command(commandFields[len(commandFields)-1], copy.Entry.Help)
|
||||
for _, alias := range copy.Aliases {
|
||||
cmd = cmd.Alias(alias)
|
||||
}
|
||||
if copy.Default {
|
||||
cmd = cmd.Default()
|
||||
}
|
||||
if copy.Entry.UsageFunc != nil {
|
||||
copy.Entry.UsageFunc(cmd)
|
||||
}
|
||||
|
||||
cmd.Action(
|
||||
func(_ *kingpin.ParseContext) error {
|
||||
return copy.Entry.ExecuteFunc()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// // CmdRequest will use the given uri to make a request and potentially send provided content.
|
||||
// func (c *Cli) CmdRequest(uri, content string) (err error) {
|
||||
// log.Debugf("request called")
|
||||
|
||||
// if !strings.HasPrefix(uri, "http") {
|
||||
// uri = fmt.Sprintf("%s%s", c.endpoint, uri)
|
||||
// }
|
||||
|
||||
// method := strings.ToUpper(c.opts["method"].(string))
|
||||
// var data interface{}
|
||||
// if method == "GET" {
|
||||
// data, err = responseToJSON(c.get(uri))
|
||||
// } else if method == "POST" {
|
||||
// data, err = responseToJSON(c.post(uri, content))
|
||||
// } else if method == "PUT" {
|
||||
// data, err = responseToJSON(c.put(uri, content))
|
||||
// }
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// return runTemplate(c.getTemplate("request"), data, nil)
|
||||
// }
|
||||
|
||||
@@ -43,15 +43,7 @@ func (jc *JiraCli) CmdEditUsage(cmd *kingpin.CmdClause, opts *EditOptions) error
|
||||
jc.EditorUsage(cmd, &opts.GlobalOptions)
|
||||
jc.TemplateUsage(cmd, &opts.GlobalOptions)
|
||||
cmd.Flag("noedit", "Disable opening the editor").BoolVar(&opts.SkipEditing)
|
||||
// cmd.Flag("assignee", "User assigned the issue").Short('a').StringVar(&opts.Assignee)
|
||||
// cmd.Flag("component", "Component to search for").Short('c').StringVar(&opts.Component)
|
||||
// cmd.Flag("issuetype", "Issue type to search for").Short('i').StringVar(&opts.IssueType)
|
||||
// cmd.Flag("limit", "Maximum number of results to return in search").Short('l').Default("500").IntVar(&opts.MaxResults)
|
||||
// cmd.Flag("project", "Project to search for").Short('p').StringVar(&opts.Project)
|
||||
cmd.Flag("query", "Jira Query Language (JQL) expression for the search to edit multiple issues").Short('q').StringVar(&opts.Query)
|
||||
// cmd.Flag("reporter", "Reporter to search for").Short('r').StringVar(&opts.Reporter)
|
||||
// cmd.Flag("sort", "Sort order to return").Short('s').Default("priority asc, key").StringVar(&opts.Sort)
|
||||
// cmd.Flag("watcher", "Watcher to search for").Short('w').StringVar(&opts.Watcher)
|
||||
cmd.Flag("comment", "Comment message for issue").Short('m').PreAction(func(ctx *kingpin.ParseContext) error {
|
||||
opts.Overrides["comment"] = flagValue(ctx, "comment")
|
||||
return nil
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package jiracli
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/coryb/oreo"
|
||||
|
||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
type RequestOptions struct {
|
||||
GlobalOptions
|
||||
Method string
|
||||
URI string
|
||||
Data string
|
||||
}
|
||||
|
||||
func (jc *JiraCli) CmdRequestRegistry() *CommandRegistryEntry {
|
||||
opts := RequestOptions{
|
||||
GlobalOptions: GlobalOptions{
|
||||
Template: "request",
|
||||
},
|
||||
Method: "GET",
|
||||
}
|
||||
|
||||
return &CommandRegistryEntry{
|
||||
"Open issue in requestr",
|
||||
func() error {
|
||||
return jc.CmdRequest(&opts)
|
||||
},
|
||||
func(cmd *kingpin.CmdClause) error {
|
||||
return jc.CmdRequestUsage(cmd, &opts)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (jc *JiraCli) CmdRequestUsage(cmd *kingpin.CmdClause, opts *RequestOptions) error {
|
||||
if err := jc.GlobalUsage(cmd, &opts.GlobalOptions); err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.Flag("method", "HTTP request method to use").Short('m').EnumVar(&opts.Method, "GET", "PUT", "POST", "DELETE")
|
||||
cmd.Arg("API", "Path to Jira API (ie: /rest/api/2/issue)").Required().StringVar(&opts.URI)
|
||||
cmd.Arg("JSON", "JSON Content to send to API").Required().StringVar(&opts.Data)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CmdRequest open the default system requestr to the provided issue
|
||||
func (jc *JiraCli) CmdRequest(opts *RequestOptions) error {
|
||||
uri := opts.URI
|
||||
if !strings.HasPrefix(uri, "http") {
|
||||
uri = jc.Endpoint + uri
|
||||
}
|
||||
|
||||
parsedURI, err := url.Parse(uri)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
builder := oreo.RequestBuilder(parsedURI).WithMethod(opts.Method)
|
||||
if opts.Data != "" {
|
||||
builder = builder.WithJSON(opts.Data)
|
||||
}
|
||||
|
||||
resp, err := jc.UA.Do(builder.Build())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
content, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(content) == 0 {
|
||||
fmt.Println("No Content")
|
||||
return nil
|
||||
}
|
||||
var data interface{}
|
||||
err = json.Unmarshal(content, &data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("JSON Parse Error: %s from %q", err, content)
|
||||
}
|
||||
|
||||
return jc.runTemplate(opts.Template, &data, nil)
|
||||
}
|
||||
-121
@@ -67,17 +67,6 @@ func flagValue(ctx *kingpin.ParseContext, name string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// func readFile(file string) string {
|
||||
// var bytes []byte
|
||||
// var err error
|
||||
// log.Debugf("readFile: reading %q", file)
|
||||
// if bytes, err = ioutil.ReadFile(file); err != nil {
|
||||
// log.Errorf("Failed to read file %s: %s", file, err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// return string(bytes)
|
||||
// }
|
||||
|
||||
func copyFile(src, dst string) (err error) {
|
||||
var s, d *os.File
|
||||
if s, err = os.Open(src); err == nil {
|
||||
@@ -121,98 +110,6 @@ func dateFormat(format string, content string) (string, error) {
|
||||
return t.Format(format), nil
|
||||
}
|
||||
|
||||
// // RunTemplate will run the give templateContent as a golang text/template
|
||||
// // and pass the provided data to the template execution. It will write
|
||||
// // the output to the provided "out" writer.
|
||||
// func RunTemplate(templateContent string, data interface{}, out io.Writer) error {
|
||||
// return runTemplate(templateContent, data, out)
|
||||
// }
|
||||
|
||||
// func responseToJSON(resp *http.Response, err error) (interface{}, error) {
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
// data := jsonDecode(resp.Body)
|
||||
// if resp.StatusCode == 400 {
|
||||
// if val, ok := data.(map[string]interface{})["errorMessages"]; ok {
|
||||
// for _, errMsg := range val.([]interface{}) {
|
||||
// log.Errorf("%s", errMsg)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// return data, nil
|
||||
// }
|
||||
|
||||
// func jsonDecode(io io.Reader) interface{} {
|
||||
// content, err := ioutil.ReadAll(io)
|
||||
// var data interface{}
|
||||
// err = json.Unmarshal(content, &data)
|
||||
// if err != nil {
|
||||
// log.Errorf("JSON Parse Error: %s from %s", err, content)
|
||||
// }
|
||||
// return data
|
||||
// }
|
||||
|
||||
// func jsonEncode(data interface{}) (string, error) {
|
||||
// buffer := bytes.NewBuffer(make([]byte, 0))
|
||||
// enc := json.NewEncoder(buffer)
|
||||
|
||||
// err := enc.Encode(data)
|
||||
// if err != nil {
|
||||
// log.Errorf("Failed to encode data %s: %s", data, err)
|
||||
// return "", err
|
||||
// }
|
||||
// return buffer.String(), nil
|
||||
// }
|
||||
|
||||
// func jsonWrite(file string, data interface{}) {
|
||||
// fh, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
||||
// defer fh.Close()
|
||||
// if err != nil {
|
||||
// log.Errorf("Failed to open %s: %s", file, err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// enc := json.NewEncoder(fh)
|
||||
// enc.Encode(data)
|
||||
// }
|
||||
|
||||
// func yamlWrite(file string, data interface{}) {
|
||||
// fh, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
||||
// defer fh.Close()
|
||||
// if err != nil {
|
||||
// log.Errorf("Failed to open %s: %s", file, err)
|
||||
// os.Exit(1)
|
||||
// }
|
||||
// if out, err := yaml.Marshal(data); err != nil {
|
||||
// log.Errorf("Failed to marshal yaml %v: %s", data, err)
|
||||
// os.Exit(1)
|
||||
// } else {
|
||||
// fh.Write(out)
|
||||
// }
|
||||
// }
|
||||
|
||||
// func promptYN(prompt string, yes bool) bool {
|
||||
// reader := bufio.NewReader(os.Stdin)
|
||||
// if !yes {
|
||||
// prompt = fmt.Sprintf("%s [y/N]: ", prompt)
|
||||
// } else {
|
||||
// prompt = fmt.Sprintf("%s [Y/n]: ", prompt)
|
||||
// }
|
||||
|
||||
// fmt.Printf("%s", prompt)
|
||||
// text, _ := reader.ReadString('\n')
|
||||
// ans := strings.ToLower(strings.TrimRight(text, "\n"))
|
||||
// if ans == "" {
|
||||
// return yes
|
||||
// }
|
||||
// if strings.HasPrefix(ans, "y") {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
|
||||
// this is a HACK to make yaml parsed documents to be serializable
|
||||
// to json, so prevent this:
|
||||
// json: unsupported type: map[interface {}]interface {}
|
||||
@@ -283,21 +180,3 @@ func yamlFixup(data interface{}) (interface{}, error) {
|
||||
return d, nil
|
||||
}
|
||||
}
|
||||
|
||||
// func mkdir(dir string) error {
|
||||
// if stat, err := os.Stat(dir); err != nil && !os.IsNotExist(err) {
|
||||
// log.Errorf("Failed to stat %s: %s", dir, err)
|
||||
// return err
|
||||
// } else if err == nil && !stat.IsDir() {
|
||||
// err := fmt.Errorf("%s exists and is not a directory", dir)
|
||||
// log.Errorf("%s", err)
|
||||
// return err
|
||||
// } else {
|
||||
// // dir does not exist, so try to create it
|
||||
// if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
// log.Errorf("Failed to mkdir -p %s: %s", dir, err)
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user