]> code.delx.au - gnu-emacs-elpa/blobdiff - packages/debbugs/debbugs-gnu.el
Improvement on debbugs
[gnu-emacs-elpa] / packages / debbugs / debbugs-gnu.el
index e2607a2b9a0d69ad2d2ce52f1896e6a530a52df1..51f5bf15501e768a8c6d071620487fe9f9648189 100644 (file)
@@ -1,13 +1,11 @@
 ;;; debbugs-gnu.el --- interface for the GNU bug tracker
 
-;; Copyright (C) 2011-2015 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2016 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;         Michael Albinus <michael.albinus@gmx.org>
 ;; Keywords: comm, hypermedia, maint
 ;; Package: debbugs
-;; Package-Requires: ((async))
-;; Version: 0.8
 
 ;; This file is not part of GNU Emacs.
 
 (require 'tabulated-list)
 (require 'add-log)
 (require 'subr-x)
-(require 'async)
 (eval-when-compile (require 'cl))
 
 (autoload 'article-decode-charset "gnus-art")
 (autoload 'gnus-with-article-buffer "gnus-art")
 (autoload 'log-edit-insert-changelog "log-edit")
 (autoload 'mail-header-subject "nnheader")
+(autoload 'message-goto-body "message")
 (autoload 'message-make-from "message")
 (autoload 'rmail-get-new-mail "rmail")
 (autoload 'rmail-show-message "rmail")
   "*The list severities bugs are searched for.
 \"tagged\" is not a severity but marks locally tagged bugs."
   ;; <http://debbugs.gnu.org/Developer.html#severities>
+  ;; /ssh:debbugs:/etc/debbugs/config @gSeverityList
+  ;; We don't use "critical" and "grave".
   :group 'debbugs-gnu
   :type '(set (const "serious")
              (const "important")
   (mapcar 'cadr (cdr (get 'debbugs-gnu-default-packages 'custom-type)))
   "*List of all possible package names.")
 
-;; Please do not increase this value, otherwise we would run into
-;; performance problems on the server.
-(defconst debbugs-gnu-default-hits-per-page 500
-  "The number of bugs shown per page.")
-
 (defcustom debbugs-gnu-default-suppress-bugs
   '((pending . "done"))
   "*A list of specs for bugs to be suppressed.
 An element of this list is a cons cell \(KEY . REGEXP\), with key
-being returned by `debbugs-get-status', and VAL a regular
+being returned by `debbugs-get-status', and REGEXP a regular
 expression matching the corresponding value, a string.  Showing
 suppressed bugs is toggled by `debbugs-gnu-toggle-suppress'."
   :group 'debbugs-gnu
@@ -296,7 +291,7 @@ If this is 'rmail, use Rmail instead."
      ";; -*- emacs-lisp -*-\n"
      ";; Debbugs tags connection history.  Don't change this file.\n\n"
      (format "(setq debbugs-gnu-local-tags '%S)"
-            (sort (copy-sequence debbugs-gnu-local-tags) '<)))))
+            (sort (copy-sequence debbugs-gnu-local-tags) '>)))))
 
 (defvar debbugs-gnu-current-query nil
   "The query object of the current search.
@@ -347,6 +342,8 @@ marked as \"client-side filter\"."
        (if (zerop (length phrase))
            (setq phrase nil)
          (add-to-list 'debbugs-gnu-current-query (cons 'phrase phrase)))
+       ;; We suppress the bugs if there is no phrase.
+       (setq-default debbugs-gnu-current-suppress (null phrase))
 
        ;; The other queries.
        (catch :finished
@@ -463,8 +460,13 @@ marked as \"client-side filter\"."
     (setq debbugs-gnu-current-query nil
          debbugs-gnu-current-filter nil)))
 
-(defvar debbugs-gnu-current-limit nil)
-(defvar debbugs-gnu-current-suppress nil)
+(defvar debbugs-gnu-current-limit nil
+  "List of bug ids to be shown, if non-nil")
+
+(defvar debbugs-gnu-current-suppress nil
+  "Whether bugs shall be suppressed.
+The specification which bugs shall be suppressed is taken from
+  `debbugs-gnu-default-suppress-bugs'.")
 
 ;;;###autoload
 (defun debbugs-gnu (severities &optional packages archivedp suppress tags)
@@ -496,20 +498,26 @@ marked as \"client-side filter\"."
     (with-temp-buffer
       (insert-file-contents debbugs-gnu-persistency-file)
       (eval (read (current-buffer)))))
+  ;; Per default, we suppress retrieved unwanted bugs.
+  (when (called-interactively-p 'any)
+    (setq-default debbugs-gnu-current-suppress t))
 
   ;; Add queries.
   (dolist (severity (if (consp severities) severities (list severities)))
     (when (not (zerop (length severity)))
+      (when (string-equal severity "tagged")
+       (setq-default debbugs-gnu-current-suppress nil))
       (add-to-list 'debbugs-gnu-current-query (cons 'severity severity))))
   (dolist (package (if (consp packages) packages (list packages)))
     (when (not (zerop (length package)))
       (add-to-list 'debbugs-gnu-current-query (cons 'package package))))
   (when archivedp
+    (setq-default debbugs-gnu-current-suppress nil)
     (add-to-list 'debbugs-gnu-current-query '(archive . "1")))
   (when suppress
+    (setq-default debbugs-gnu-current-suppress t)
     (add-to-list 'debbugs-gnu-current-query '(status . "open"))
-    (add-to-list 'debbugs-gnu-current-query '(status . "forwarded"))
-    (setq debbugs-gnu-current-suppress suppress))
+    (add-to-list 'debbugs-gnu-current-query '(status . "forwarded")))
   (dolist (tag (if (consp tags) tags (list tags)))
     (when (not (zerop (length tag)))
       (add-to-list 'debbugs-gnu-current-query (cons 'tag tag))))
@@ -551,33 +559,29 @@ marked as \"client-side filter\"."
                 (list (intern (concat ":" (symbol-name (car elt))))
                       (cdr elt)))))))
 
-    (sort
-     (cond
-      ;; If the query is just a list of bug numbers, we return them.
-      (bugs (cdr bugs))
-      ;; If the query contains the pseudo-severity "tagged", we return
-      ;; just the local tagged bugs.
-      (local-tags (copy-sequence debbugs-gnu-local-tags))
-      ;; A full text query.
-      (phrase
-       (mapcar
-       (lambda (x) (cdr (assoc "id" x)))
-       (apply 'debbugs-search-est args)))
-      ;; User tags.
-      (tags
-       (setq args (mapcar (lambda (x) (if (eq x :package) :user x)) args))
-       (apply 'debbugs-get-usertag args))
-      ;; Otherwise, we retrieve the bugs from the server.
-      (t (apply 'debbugs-get-bugs args)))
-     ;; Sort function.
-     '<)))
+    (cond
+     ;; If the query is just a list of bug numbers, we return them.
+     (bugs (cdr bugs))
+     ;; If the query contains the pseudo-severity "tagged", we return
+     ;; just the local tagged bugs.
+     (local-tags (copy-sequence debbugs-gnu-local-tags))
+     ;; A full text query.
+     (phrase
+      (mapcar
+       (lambda (x) (cdr (assoc "id" x)))
+       (apply 'debbugs-search-est args)))
+     ;; User tags.
+     (tags
+      (setq args (mapcar (lambda (x) (if (eq x :package) :user x)) args))
+      (apply 'debbugs-get-usertag args))
+     ;; Otherwise, we retrieve the bugs from the server.
+     (t (apply 'debbugs-get-bugs args)))))
 
 (defun debbugs-gnu-show-reports ()
   "Show bug reports."
   (let ((inhibit-read-only t)
        (debbugs-port "gnu.org")
-       (buffer-name "*Emacs Bugs*")
-       all-proc)
+       (buffer-name "*Emacs Bugs*"))
     ;; The tabulated mode sets several local variables.  We must get
     ;; rid of them.
     (when (get-buffer buffer-name)
@@ -585,113 +589,98 @@ marked as \"client-side filter\"."
     (switch-to-buffer (get-buffer-create buffer-name))
     (debbugs-gnu-mode)
 
-    ;; Retrieve all bugs in chunks of `debbugs-gnu-default-hits-per-page'.
-    (let ((bug-ids (debbugs-gnu-get-bugs debbugs-gnu-current-query))
-         (hits debbugs-gnu-default-hits-per-page)
-         curr-ids)
-      (while bug-ids
-       (setq curr-ids (butlast bug-ids (- (length bug-ids) hits))
-             bug-ids (last bug-ids (- (length bug-ids) hits))
-             all-proc
-             (append all-proc
-                     (list
-                      (async-start
-                       `(lambda ()
-                          (load ,(locate-library "debbugs"))
-                          (apply 'debbugs-get-status ',curr-ids))))))))
-
     ;; Print bug reports.
-    (dolist (proc all-proc)
-      (dolist (status (async-get proc))
-       (let* ((id (cdr (assq 'id status)))
-              (words
-               (mapconcat
-                'identity
-                (cons (cdr (assq 'severity status))
-                      (cdr (assq 'keywords status)))
-                ","))
-              (address (mail-header-parse-address
-                        (decode-coding-string (cdr (assq 'originator status))
-                                              'utf-8)))
-              (owner (if (cdr (assq 'owner status))
-                         (car (mail-header-parse-address
-                               (decode-coding-string (cdr (assq 'owner status))
-                                                     'utf-8)))))
-              (subject (decode-coding-string (cdr (assq 'subject status))
-                                             'utf-8))
-              merged)
-         (unless (equal (cdr (assq 'pending status)) "pending")
-           (setq words (concat words "," (cdr (assq 'pending status)))))
-         (let ((packages (delete "emacs" (cdr (assq 'package status)))))
-           (when packages
-             (setq words
-                   (concat words "," (mapconcat 'identity packages ",")))))
-         (when (setq merged (cdr (assq 'mergedwith status)))
-           (setq words (format "%s,%s"
-                               (if (numberp merged)
-                                   merged
-                                 (mapconcat 'number-to-string merged ","))
-                               words)))
-         (when (or (not merged)
-                   (not (let ((found nil))
-                          (dolist (id (if (listp merged)
-                                          merged
-                                        (list merged)))
-                            (dolist (entry tabulated-list-entries)
-                              (when (equal id (cdr (assq 'id (car entry))))
-                                (setq found t))))
-                          found)))
-           (add-to-list
-            'tabulated-list-entries
-            (list
-             status
-             (vector
-              (propertize
-               (format "%5d" id)
-               'face
-               ;; Mark tagged bugs.
-               (if (memq id debbugs-gnu-local-tags)
-                   'debbugs-gnu-tagged
-                 'default))
-              (propertize
-               ;; Mark status and age.
-               words
-               'face
-               (cond
-                ((cdr (assq 'archived status))
-                 'debbugs-gnu-archived)
-                ((equal (cdr (assq 'pending status)) "done")
-                 'debbugs-gnu-done)
-                ((member "pending" (cdr (assq 'keywords status)))
-                 'debbugs-gnu-pending)
-                ((= (cdr (assq 'date status))
-                    (cdr (assq 'log_modified status)))
-                 'debbugs-gnu-new)
-                ((< (- (float-time)
-                       (cdr (assq 'log_modified status)))
-                    (* 60 60 24 7 2))
-                 'debbugs-gnu-handled)
-                (t
-                 'debbugs-gnu-stale)))
-              (propertize
-               ;; Prefer the name over the address.
-               (or (cdr address)
-                   (car address))
-               'face
-               ;; Mark own submitted bugs.
-               (if (and (stringp (car address))
-                        (string-equal (car address) user-mail-address))
-                   'debbugs-gnu-tagged
-                 'default))
-              (propertize
-               subject
-               'face
-               ;; Mark owned bugs.
-               (if (and (stringp owner)
-                        (string-equal owner user-mail-address))
-                   'debbugs-gnu-tagged
-                 'default))))
-            'append)))))
+    (dolist (status
+            (apply 'debbugs-get-status
+                   (debbugs-gnu-get-bugs debbugs-gnu-current-query)))
+      (let* ((id (cdr (assq 'id status)))
+            (words
+             (mapconcat
+              'identity
+              (cons (cdr (assq 'severity status))
+                    (cdr (assq 'keywords status)))
+              ","))
+            (address (mail-header-parse-address
+                      (decode-coding-string (cdr (assq 'originator status))
+                                            'utf-8)))
+            (owner (if (cdr (assq 'owner status))
+                       (car (mail-header-parse-address
+                             (decode-coding-string (cdr (assq 'owner status))
+                                                   'utf-8)))))
+            (subject (decode-coding-string (cdr (assq 'subject status))
+                                           'utf-8))
+            merged)
+       (unless (equal (cdr (assq 'pending status)) "pending")
+         (setq words (concat words "," (cdr (assq 'pending status)))))
+       (let ((packages (delete "emacs" (cdr (assq 'package status)))))
+         (when packages
+           (setq words (concat words "," (mapconcat 'identity packages ",")))))
+       (when (setq merged (cdr (assq 'mergedwith status)))
+         (setq words (format "%s,%s"
+                             (if (numberp merged)
+                                 merged
+                               (mapconcat 'number-to-string merged ","))
+                             words)))
+       (when (or (not merged)
+                 (not (let ((found nil))
+                        (dolist (id (if (listp merged)
+                                        merged
+                                      (list merged)))
+                          (dolist (entry tabulated-list-entries)
+                            (when (equal id (cdr (assq 'id (car entry))))
+                              (setq found t))))
+                        found)))
+         (add-to-list
+          'tabulated-list-entries
+          (list
+           status
+           (vector
+            (propertize
+             (format "%5d" id)
+             'face
+             ;; Mark tagged bugs.
+             (if (memq id debbugs-gnu-local-tags)
+                 'debbugs-gnu-tagged
+               'default))
+            (propertize
+             ;; Mark status and age.
+             words
+             'face
+             (cond
+              ((cdr (assq 'archived status))
+               'debbugs-gnu-archived)
+              ((equal (cdr (assq 'pending status)) "done")
+               'debbugs-gnu-done)
+              ((member "pending" (cdr (assq 'keywords status)))
+               'debbugs-gnu-pending)
+              ((= (cdr (assq 'date status))
+                  (cdr (assq 'log_modified status)))
+               'debbugs-gnu-new)
+              ((< (- (float-time)
+                     (cdr (assq 'log_modified status)))
+                  (* 60 60 24 7 2))
+               'debbugs-gnu-handled)
+              (t
+               'debbugs-gnu-stale)))
+            (propertize
+             ;; Prefer the name over the address.
+             (or (cdr address)
+                 (car address))
+             'face
+             ;; Mark own submitted bugs.
+             (if (and (stringp (car address))
+                      (string-equal (car address) user-mail-address))
+                 'debbugs-gnu-tagged
+               'default))
+            (propertize
+             subject
+             'face
+             ;; Mark owned bugs.
+             (if (and (stringp owner)
+                      (string-equal owner user-mail-address))
+                 'debbugs-gnu-tagged
+               'default))))
+          'append))))
 
     (tabulated-list-init-header)
     (tabulated-list-print)
@@ -719,14 +708,13 @@ Used instead of `tabulated-list-print-entry'."
               (memq (cdr (assq 'id list-id)) debbugs-gnu-current-limit))
           ;; Filter suppressed bugs.
           (or (not debbugs-gnu-current-suppress)
-              (and (not (memq (cdr (assq 'id list-id)) debbugs-gnu-local-tags))
-                   (not (catch :suppress
-                          (dolist (check debbugs-gnu-default-suppress-bugs)
-                            (when
-                                (string-match
-                                 (cdr check)
-                                 (or (cdr (assq (car check) list-id)) ""))
-                              (throw :suppress t)))))))
+              (not (catch :suppress
+                     (dolist (check debbugs-gnu-default-suppress-bugs)
+                       (when
+                           (string-match
+                            (cdr check)
+                            (or (cdr (assq (car check) list-id)) ""))
+                         (throw :suppress t))))))
           ;; Filter search list.
           (not (catch :suppress
                  (dolist (check debbugs-gnu-current-filter)
@@ -769,7 +757,8 @@ Used instead of `tabulated-list-print-entry'."
       (insert ?\n))))
 
 (defvar debbugs-gnu-mode-map
-  (let ((map (make-sparse-keymap)))
+  (let ((map (make-sparse-keymap))
+       (menu-map (make-sparse-keymap)))
     (set-keymap-parent map tabulated-list-mode-map)
     (define-key map "\r" 'debbugs-gnu-select-report)
     (define-key map [mouse-1] 'debbugs-gnu-select-report)
@@ -785,6 +774,35 @@ Used instead of `tabulated-list-print-entry'."
     (define-key map "B" 'debbugs-gnu-show-blocking-reports)
     (define-key map "C" 'debbugs-gnu-send-control-message)
     (define-key map "R" 'debbugs-gnu-show-all-blocking-reports)
+
+    (define-key map [menu-bar debbugs] (cons "Debbugs" menu-map))
+    (define-key menu-map [debbugs-gnu-select-report]
+      '(menu-item "Show Reports" debbugs-gnu-select-report
+                 :help "Show all reports belonging to this bug"))
+    (define-key-after menu-map [debbugs-gnu-rescan]
+      '(menu-item "Refresh Bugs" debbugs-gnu-rescan
+                 :help "Refresh bug list")
+      'debbugs-gnu-select-report)
+    (define-key-after menu-map [debbugs-gnu-show-all-blocking-reports]
+      '(menu-item "Show Release Blocking Bugs"
+                 debbugs-gnu-show-all-blocking-reports
+                 :help "Show all bugs blocking next Emacs release")
+                 ;:enable '(assq 'phrase debbugs-gnu-current-query))
+      'debbugs-gnu-rescan)
+    (define-key-after menu-map [debbugs-gnu-separator]
+      '(menu-item "--") 'debbugs-gnu-show-all-blocking-reports)
+    (define-key-after menu-map [debbugs-gnu-search]
+      '(menu-item "Search Bugs" debbugs-gnu-search
+                 :help "Search bugs on debbugs.gnu.org")
+      'debbugs-gnu-separator)
+    (define-key-after menu-map [debbugs-gnu]
+      '(menu-item "Retrieve Bugs" debbugs-gnu
+                 :help "Retrieve bugs from debbugs.gnu.org")
+      'debbugs-gnu-search)
+    (define-key-after menu-map [debbugs-gnu-bugs]
+      '(menu-item "Retrieve Bugs by Number" debbugs-gnu-bugs
+                 :help "Retrieve selected bugs from debbugs.gnu.org")
+      'debbugs-gnu)
     map))
 
 (defun debbugs-gnu-rescan ()
@@ -792,6 +810,7 @@ Used instead of `tabulated-list-print-entry'."
   (interactive)
   ;; Refresh the buffer.  `save-excursion' does not work, so we
   ;; remember the position.
+  (setq-default debbugs-gnu-current-suppress debbugs-gnu-current-suppress)
   (let ((pos (point)))
     (debbugs-gnu-show-reports)
     (goto-char pos)))
@@ -809,7 +828,8 @@ The following commands are available:
 \\{debbugs-gnu-mode-map}"
   (set (make-local-variable 'debbugs-gnu-sort-state) 'number)
   (set (make-local-variable 'debbugs-gnu-current-limit) nil)
-  (set (make-local-variable 'debbugs-gnu-current-suppress) nil)
+  (set (make-local-variable 'debbugs-gnu-current-suppress)
+       debbugs-gnu-current-suppress)
   (setq tabulated-list-format [("Id"         5 debbugs-gnu-sort-id)
                               ("State"     20 debbugs-gnu-sort-state)
                               ("Submitter" 25 t)
@@ -821,7 +841,7 @@ The following commands are available:
   (setq buffer-read-only t))
 
 (defun debbugs-gnu-sort-id (s1 s2)
-  (< (cdr (assq 'id (car s1)))
+  (> (cdr (assq 'id (car s1)))
      (cdr (assq 'id (car s2)))))
 
 (defconst debbugs-gnu-state-preference
@@ -1249,7 +1269,10 @@ removed instead."
                (format "tags %d%s %s\n"
                        id (if reverse " -" "")
                        message))))
-      (funcall send-mail-function))))
+      (funcall send-mail-function)
+      (message-goto-body)
+      (message "Control message sent:\n%s"
+              (buffer-substring-no-properties (point) (1- (point-max)))))))
 
 (defvar debbugs-gnu-usertags-mode-map
   (let ((map (make-sparse-keymap)))
@@ -1349,6 +1372,8 @@ The following commands are available:
   (dolist (elt bugs)
     (unless (natnump elt) (signal 'wrong-type-argument (list 'natnump elt))))
   (add-to-list 'debbugs-gnu-current-query (cons 'bugs bugs))
+  ;; We do not suppress bugs requested explicitely.
+  (setq-default debbugs-gnu-current-suppress nil)
   (debbugs-gnu nil))
 
 (defvar debbugs-gnu-trunk-directory "~/src/emacs/trunk/"
@@ -1574,4 +1599,7 @@ If given a prefix, patch in the branch directory instead."
 
 ;;; TODO:
 
+;; * Another random thought - is it possible to implement some local
+;;   cache, so only changed bugs are fetched?  Glenn Morris.
+
 ;;; debbugs-gnu.el ends here