commit e80961fe8ae238bac3883d9cffc9fe1941ae7bb6 from: Oliver Lowe via: Oliver Lowe date: Mon Jul 21 09:28:59 2025 UTC jira: common config file commit - ca426ad963867dc9a8223817e4f70d5a96bb5d5a commit + e80961fe8ae238bac3883d9cffc9fe1941ae7bb6 blob - 45c7a4005010362dbf4e6924b2eea2556a0839bc blob + e501bac2d3569b5e694aec6c5745416d8e8ff284 --- cmd/jiraexport/jiraexport.go +++ cmd/jiraexport/jiraexport.go @@ -29,14 +29,12 @@ package main import ( - "bytes" "flag" "fmt" "io" "io/fs" "log" "net/mail" - "net/url" "os" "path" "strings" @@ -45,23 +43,6 @@ import ( "olowe.co/issues/jira" ) -func readJiraAuth() (user, pass string, err error) { - confDir, err := os.UserConfigDir() - if err != nil { - return "", "", err - } - b, err := os.ReadFile(path.Join(confDir, "atlassian/jira")) - if err != nil { - return "", "", err - } - b = bytes.TrimSpace(b) - u, p, ok := strings.Cut(string(b), ":") - if !ok { - return "", "", fmt.Errorf(`missing ":" between username and password`) - } - return u, p, nil -} - func copyMessage(w io.Writer, msg *mail.Message) (n int, err error) { for k, v := range msg.Header { for i := range v { @@ -98,19 +79,19 @@ func main() { log.Fatal(usage) } - user, pass, err := readJiraAuth() + confDir, err := os.UserConfigDir() if err != nil { - log.Fatalf("read jira auth credentials: %v", err) + log.Fatal(err) } - u, err := url.Parse(*apiRoot) + confDir = path.Join(confDir, "atlassian/jira") + config, err := readConfig(confDir) if err != nil { - log.Fatalln("parse api url:", err) + log.Fatalln("read config:", err) } - u.Path = path.Join(u.Path, "rest/api/2") jclient := &jira.Client{ - APIRoot: u, - Username: user, - Password: pass, + APIRoot: config.BaseURL, + Username: config.Username, + Password: config.Password, Debug: false, } fsys := &jira.FS{Client: jclient} blob - /dev/null blob + 8446f85284e03a77313b0d7f5fde033016c1fbfb (mode 644) --- /dev/null +++ cmd/jiraexport/config.go @@ -0,0 +1,54 @@ +package main + +import ( + "bufio" + "fmt" + "net/url" + "os" + "strings" +) + +type Config struct { + BaseURL *url.URL + Username string + Password string +} + +func readConfig(name string) (*Config, error) { + f, err := os.Open(name) + if err != nil { + return nil, err + } + defer f.Close() + var conf Config + sc := bufio.NewScanner(f) + for sc.Scan() { + line := strings.TrimSpace(sc.Text()) + if strings.HasPrefix(line, "#") { + continue + } else if line == "" { + continue + } + k, v, ok := strings.Cut(line, " ") + if !ok { + return nil, fmt.Errorf("key %s: expected whitespace after configuration key", k) + } else if v == "" { + return nil, fmt.Errorf("key %s: missing parameter", k) + } + switch k { + case "url": + u, err := url.Parse(v) + if err != nil { + return nil, fmt.Errorf("parse base url: %w", err) + } + conf.BaseURL = u + case "username": + conf.Username = v + case "password": + conf.Password = v + default: + return nil, fmt.Errorf("unknown configuration key %q", k) + } + } + return &conf, sc.Err() +} blob - c0cf2f7316e4f8104c39eaa0c3a0d25b1b134670 blob + e8fccfe56b4bd2765fc93bd3aa497e24dff8fbf6 --- cmd/jiraq/jiraq.go +++ cmd/jiraq/jiraq.go @@ -30,11 +30,9 @@ package main import ( - "bytes" "flag" "fmt" "log" - "net/url" "os" "path" "strings" @@ -42,23 +40,6 @@ import ( "olowe.co/issues/jira" ) -func readJiraAuth() (user, pass string, err error) { - confDir, err := os.UserConfigDir() - if err != nil { - return "", "", err - } - b, err := os.ReadFile(path.Join(confDir, "atlassian/jira")) - if err != nil { - return "", "", err - } - b = bytes.TrimSpace(b) - u, p, ok := strings.Cut(string(b), ":") - if !ok { - return "", "", fmt.Errorf(`missing ":" between username and password`) - } - return u, p, nil -} - var apiRoot = flag.String("u", "http://[::1]:8080", "base URL for the JIRA API") const usage = "usage: jiraq [-u url] query" @@ -74,19 +55,20 @@ func main() { log.Fatal(usage) } - user, pass, err := readJiraAuth() + confDir, err := os.UserConfigDir() if err != nil { - log.Fatalf("read jira auth credentials: %v", err) + log.Fatal(err) } - u, err := url.Parse(*apiRoot) + confDir = path.Join(confDir, "atlassian/jira") + config, err := readConfig(confDir) if err != nil { - log.Fatalln("parse api url:", err) + log.Fatalln("read config:", err) } - u.Path = path.Join(u.Path, "rest/api/2") + client := &jira.Client{ - APIRoot: u, - Username: user, - Password: pass, + APIRoot: config.BaseURL, + Username: config.Username, + Password: config.Password, } issues, err := client.SearchIssues(strings.Join(flag.Args(), " ")) blob - /dev/null blob + 8446f85284e03a77313b0d7f5fde033016c1fbfb (mode 644) --- /dev/null +++ cmd/jiraq/config.go @@ -0,0 +1,54 @@ +package main + +import ( + "bufio" + "fmt" + "net/url" + "os" + "strings" +) + +type Config struct { + BaseURL *url.URL + Username string + Password string +} + +func readConfig(name string) (*Config, error) { + f, err := os.Open(name) + if err != nil { + return nil, err + } + defer f.Close() + var conf Config + sc := bufio.NewScanner(f) + for sc.Scan() { + line := strings.TrimSpace(sc.Text()) + if strings.HasPrefix(line, "#") { + continue + } else if line == "" { + continue + } + k, v, ok := strings.Cut(line, " ") + if !ok { + return nil, fmt.Errorf("key %s: expected whitespace after configuration key", k) + } else if v == "" { + return nil, fmt.Errorf("key %s: missing parameter", k) + } + switch k { + case "url": + u, err := url.Parse(v) + if err != nil { + return nil, fmt.Errorf("parse base url: %w", err) + } + conf.BaseURL = u + case "username": + conf.Username = v + case "password": + conf.Password = v + default: + return nil, fmt.Errorf("unknown configuration key %q", k) + } + } + return &conf, sc.Err() +}