Commit Diff


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 {