commit 526e3589871e57459568bb7a0000fc6d72d9f410 from: Oliver Lowe date: Sun Jun 22 11:02:56 2025 UTC jira: keep http and json decoding plumbing in one spot commit - 0254f2be89712d6952cb4fdd5c8d0524b61e69ea commit + 526e3589871e57459568bb7a0000fc6d72d9f410 blob - 4d1e1db84b507a58115d0337db70d758bbdbda88 blob + e8eccf29cb00a8e02467174bfd2d2a556b0773d1 --- cmd/Jira/Jira.go +++ cmd/Jira/Jira.go @@ -64,24 +64,26 @@ func (w *awin) Look(text string) bool { w.Err(err.Error()) return true } + wname := path.Join("/jira", pathname) + var dent fs.DirEntry if d, ok := f.(fs.DirEntry); ok { - if d.IsDir() { - wname += "/" - } + dent = d } else { stat, err := f.Stat() if err != nil { w.Err(err.Error()) return true } - if stat.IsDir() { - wname += "/" - } + dent = fs.FileInfoToDirEntry(stat) } + if dent.IsDir() { + wname += "/" + } + win.Name(wname) if path.Base(pathname) == "issue" { - win.Fprintf("tag", "Comment ") + win.Fprintf("tag", "New ") } ww := &awin{win, w.fsys} go ww.EventLoop(ww) @@ -176,7 +178,7 @@ func (w *awin) Get(f fs.File) error { b, err := io.ReadAll(f) if err != nil { - return fmt.Errorf("read %s: %w", stat.Name(), err) + return &fs.PathError{"read", stat.Name(), err} } w.Clear() if _, err := w.Write("body", b); err != nil { @@ -185,6 +187,8 @@ func (w *awin) Get(f fs.File) error { return nil } +const defaultSearch = "status != 'done' and status != 'not done' and assignee = currentuser()" + func newSearch(fsys fs.FS, query string) { win, err := acme.New() if err != nil { @@ -219,18 +223,6 @@ func printIssues(issues []jira.Issue) string { const usage string = "usage: Jira [-d]" -func readCreds(name string) (username, password string, err error) { - b, err := os.ReadFile(name) - if err != nil { - return "", "", err - } - u, p, found := strings.Cut(strings.TrimSpace(string(b)), ":") - if !found { - return "", "", fmt.Errorf("missing userpass field separator %q", ":") - } - return u, p, nil -} - var debug bool func init() { blob - 0fca4f89803514e2c44e429cccfbf22ca671a43a blob + 07014927557760f42e5abfb20972f21ee6f02c40 --- jira/http.go +++ jira/http.go @@ -36,36 +36,16 @@ func (resp errorResponse) Error() string { func (c *Client) Projects() ([]Project, error) { u := *c.APIRoot u.Path = path.Join(u.Path, "project") - resp, err := c.get(u.String()) - if err != nil { - return nil, err - } - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("non-ok status: %s", resp.Status) - } - defer resp.Body.Close() var p []Project - if err := json.NewDecoder(resp.Body).Decode(&p); err != nil { - return nil, fmt.Errorf("decode project: %w", err) - } - return p, nil + err := c.getJSON(u.String(), &p) + return p, err } func (c *Client) Project(name string) (*Project, error) { u := fmt.Sprintf("%s/project/%s", c.APIRoot, name) - resp, err := c.get(u) - if err != nil { - return nil, err - } - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("non-ok status: %s", resp.Status) - } - defer resp.Body.Close() var p Project - if err := json.NewDecoder(resp.Body).Decode(&p); err != nil { - return nil, fmt.Errorf("decode project: %w", err) - } - return &p, nil + err := c.getJSON(u, &p) + return &p, err } func (c *Client) Issues(project string) ([]Issue, error) { @@ -118,19 +98,9 @@ func (c *Client) CheckIssue(name string) (bool, error) func (c *Client) Issue(name string) (*Issue, error) { u := *c.APIRoot u.Path = path.Join(u.Path, "issue", name) - resp, err := c.get(u.String()) - if err != nil { - return nil, err - } - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("non-ok status: %s", resp.Status) - } - defer resp.Body.Close() var is Issue - if err := json.NewDecoder(resp.Body).Decode(&is); err != nil { - return nil, fmt.Errorf("decode issue: %w", err) - } - return &is, nil + err := c.getJSON(u.String(), &is) + return &is, err } func (c *Client) checkComment(ikey, id string) (bool, error) { @@ -153,16 +123,9 @@ func (c *Client) checkComment(ikey, id string) (bool, func (c *Client) Comment(ikey, id string) (*Comment, error) { u := *c.APIRoot u.Path = path.Join(u.Path, "issue", ikey, "comment", id) - resp, err := c.get(u.String()) - if err != nil { - return nil, err - } - defer resp.Body.Close() var com Comment - if err := json.NewDecoder(resp.Body).Decode(&com); err != nil { - return nil, fmt.Errorf("decode comment: %w", err) - } - return &com, nil + err := c.getJSON(u.String(), &com) + return &com, err } func (c *Client) CreateIssue(issue Issue) (*Issue, error) { @@ -204,6 +167,23 @@ func (c *Client) PostComment(issueKey string, body io. return nil } +func (c *Client) getJSON(url string, v any) error { + resp, err := c.get(url) + if err != nil { + return err + } + defer resp.Body.Close() + dec := json.NewDecoder(resp.Body) + if resp.StatusCode != http.StatusOK { + var eresp errorResponse + if err := dec.Decode(&eresp); err != nil { + return fmt.Errorf("status %s: decode error response: %w", resp.Status, err) + } + return eresp + } + return dec.Decode(v) +} + func (c *Client) get(url string) (*http.Response, error) { req, err := http.NewRequest(http.MethodGet, url, nil) if err != nil {