X-Git-Url: https://code.delx.au/gnu-emacs-elpa/blobdiff_plain/107b1a12ac495228056e826ecfeab3a047927d7f..7be79b87a498fb5611da3e361ec16f6b0ff25b1c:/packages/debbugs/debbugs-gnu.el diff --git a/packages/debbugs/debbugs-gnu.el b/packages/debbugs/debbugs-gnu.el index bc1357804..cc9599183 100644 --- a/packages/debbugs/debbugs-gnu.el +++ b/packages/debbugs/debbugs-gnu.el @@ -5,7 +5,7 @@ ;; Author: Lars Magne Ingebrigtsen ;; Keywords: comm, hypermedia, maint ;; Package: debbugs -;; Version: 0.1 +;; Version: 0.3 ;; This file is part of GNU Emacs. @@ -25,14 +25,15 @@ ;;; Commentary: ;; This package provides an interface to bug reports which are located -;; on the GNU bug tracker debbugs.gnu.org. It's main purpose is to +;; on the GNU bug tracker debbugs.gnu.org. Its main purpose is to ;; show and manipulate bug reports from Emacs, but it could be used ;; also for other GNU projects which use the same bug tracker. ;; If you have `debbugs-gnu.el' in your load-path, you could enable -;; the bug tracker command by the following line in your ~/.emacs +;; the bug tracker command by the following lines in your ~/.emacs ;; ;; (autoload 'debbugs-gnu "debbugs-gnu" "" 'interactive) +;; (autoload 'debbugs-gnu-search "debbugs-gnu" "" 'interactive) ;; The bug tracker is called interactively by ;; @@ -57,11 +58,14 @@ ;; ;; M-x debbugs-gnu-search -;; It behaves like `debbugs-gnu', additionally it asks for key-value -;; pairs to filter bugs. Keys are as described in +;; It behaves like `debbugs-gnu', but asks at the beginning for a +;; search phrase to be used for full text search. Additionally, it +;; asks for key-value pairs to filter bugs. Keys are as described in ;; `debbugs-get-status', the corresponding value must be a regular -;; expression to match for. The other parameters are as described -;; in `debbugs-gnu'. +;; expression to match for. The other parameters are as described in +;; `debbugs-gnu'. Usually, there is just one value except for the +;; attribute "date", which needs two arguments specifying a period in +;; which the bug has been submitted or modified. ;; The bug reports are downloaded from the bug tracker. In order to ;; not generate too much load of the server, up to 500 bugs will be @@ -116,7 +120,7 @@ :group 'debbugs :version "24.1") -(defcustom debbugs-gnu-default-severities '("normal") +(defcustom debbugs-gnu-default-severities '("serious" "important" "normal") "*The list severities bugs are searched for. \"tagged\" is not a severity but marks locally tagged bugs." :group 'debbugs-gnu @@ -133,9 +137,13 @@ :group 'debbugs-gnu :type '(set (const "automake") (const "coreutils") + (const "debbugs.gnu.org") (const "emacs") + (const "emacs-xwidgets") (const "gnus") - (const "libtool")) + (const "guile") + (const "libtool") + (const "woodchuck")) :version "24.1") (defcustom debbugs-gnu-default-hits-per-page 500 @@ -208,7 +216,7 @@ It has the same format as `debbugs-gnu-default-suppress-bugs'.") It will be applied client-side, when parsing the results of `debbugs-get-status'. It has a similar format as `debbugs-gnu-default-suppress-bugs'. In case of keys representing -a date, there are entries \(KEY FUNCTION . DATE\).") +a date, value is the cons cell \(BEFORE . AFTER\).") (defun debbugs-gnu-calendar-read (prompt acceptable &optional initial-contents) "Return a string read from the minibuffer. @@ -218,105 +226,155 @@ Derived from `calendar-read'." (setq value (read-string prompt initial-contents))) value)) +(defconst debbugs-gnu-phrase-prompt + (propertize + "Enter search phrase: " + 'help-echo "\ +The search phrase contains words to be searched for, combined by +operators like AND, ANDNOT and OR. If there is no operator +between the words, AND is used by default. The phrase can also +be empty, in this case only the following attributes are used for +search.")) + ;;;###autoload (defun debbugs-gnu-search () "Search for Emacs bugs interactively. -Key-value pairs are requested interactively. If a key cannot be -queried by a SOAP request, it is marked as \"client-side filter\"." +Search arguments are requested interactively. The \"search +phrase\" is used for full text search in the bugs database. +Further key-value pairs are requested until an empty key is +returned. If a key cannot be queried by a SOAP request, it is +marked as \"client-side filter\"." (interactive) - (let ((date-format "\\([[:digit:]]\\{4\\}\\)-\\([[:digit:]]\\{1,2\\}\\)-\\([[:digit:]]\\{1,2\\}\\)") - key val severities packages archivedp) - (catch :finished - (while t - (setq key (completing-read - "Enter attribute: " - '("severity" "package" "archive" "src" "tag" - "owner" "submitter" "maint" "correspondent" - "date" "log_modified" "last_modified" - "found_date" "fixed_date" "unarchived" - "subject" "done" "forwarded" "msgid" "summary") - nil t)) - (cond - ;; Server-side queries. - ((equal key "severity") - (setq - severities - (completing-read-multiple - "Enter severities: " - (mapcar - 'cadr (cdr (get 'debbugs-gnu-default-severities 'custom-type))) - nil t (mapconcat 'identity debbugs-gnu-default-severities ",")))) - - ((equal key "package") - (setq - packages - (completing-read-multiple - "Enter packages: " - (mapcar - 'cadr (cdr (get 'debbugs-gnu-default-packages 'custom-type))) - nil t (mapconcat 'identity debbugs-gnu-default-packages ",")))) - - ((equal key "archive") - ;; We simplify, by assuming just archived bugs are requested. - (setq archivedp t)) - - ((member key '("src" "tag")) - (setq val (read-string (format "Enter %s: " key))) - (when (not (zerop (length val))) - (add-to-list 'debbugs-gnu-current-query (cons (intern key) val)))) - - ((member key '("owner" "submitter" "maint" "correspondent")) - (setq val (read-string "Enter email address: ")) - (when (not (zerop (length val))) - (add-to-list 'debbugs-gnu-current-query (cons (intern key) val)))) - - ;; Client-side filters. - ((member key '("date" "log_modified" "last_modified" - "found_date" "fixed_date" "unarchived")) - (setq val - (debbugs-gnu-calendar-read - (format "Enter %s before YYYY-MM-DD (client-side filter): " - key) - (lambda (x) - (string-match (concat "^\\(" date-format "\\|\\)$") x)))) - (when (string-match date-format val) - (add-to-list - 'debbugs-gnu-current-filter - (cons (intern key) - (cons '> - (float-time - (encode-time - 0 0 0 - (string-to-number (match-string 3 val)) - (string-to-number (match-string 2 val)) - (string-to-number (match-string 1 val)))))))) - (setq val - (debbugs-gnu-calendar-read - (format "Enter %s after YYYY-MM-DD (client-side filter): " key) - (lambda (x) - (string-match (concat "^\\(" date-format "\\|\\)$") x)))) - (when (string-match date-format val) + + (unwind-protect + (let ((date-format "\\([[:digit:]]\\{4\\}\\)-\\([[:digit:]]\\{1,2\\}\\)-\\([[:digit:]]\\{1,2\\}\\)") + key val1 val2 phrase severities packages archivedp) + + ;; Check for the phrase. + (setq phrase (read-string debbugs-gnu-phrase-prompt)) + (if (zerop (length phrase)) + (setq phrase nil) + (add-to-list 'debbugs-gnu-current-query (cons 'phrase phrase))) + + ;; The other queries. + (catch :finished + (while t + (setq key (completing-read + "Enter attribute: " + (if phrase + '("severity" "package" "tags" "submitter" "date" + "subject" "status") + '("severity" "package" "archive" "src" "tag" + "owner" "submitter" "maint" "correspondent" + "date" "log_modified" "last_modified" + "found_date" "fixed_date" "unarchived" + "subject" "done" "forwarded" "msgid" "summary")) + nil t)) + (cond + ;; Server-side queries. + ((equal key "severity") + (setq + severities + (completing-read-multiple + "Enter severities: " + (mapcar + 'cadr (cdr (get 'debbugs-gnu-default-severities 'custom-type))) + nil t + (mapconcat 'identity debbugs-gnu-default-severities ",")))) + + ((equal key "package") + (setq + packages + (completing-read-multiple + "Enter packages: " + (mapcar + 'cadr (cdr (get 'debbugs-gnu-default-packages 'custom-type))) + nil t (mapconcat 'identity debbugs-gnu-default-packages ",")))) + + ((equal key "archive") + ;; We simplify, by assuming just archived bugs are requested. + (setq archivedp t)) + + ((member key '("src" "tag" "tags")) + (setq val1 (read-string (format "Enter %s: " key))) + (when (not (zerop (length val1))) + (add-to-list + 'debbugs-gnu-current-query (cons (intern key) val1)))) + + ((member key '("owner" "submitter" "maint" "correspondent")) + (setq val1 (read-string "Enter email address: ")) + (when (not (zerop (length val1))) + (add-to-list + 'debbugs-gnu-current-query (cons (intern key) val1)))) + + ((equal key "status") + (setq + val1 + (completing-read "Enter status: " '("done" "forwarded" "open"))) + (when (not (zerop (length val1))) (add-to-list - 'debbugs-gnu-current-filter - (cons (intern key) - (cons '< - (float-time - (encode-time - 0 0 0 - (string-to-number (match-string 3 val)) - (string-to-number (match-string 2 val)) - (string-to-number (match-string 1 val))))))))) - - ((not (zerop (length key))) - (setq val (read-regexp "Enter regexp (client-side filter)")) - (when (not (zerop (length val))) - (add-to-list 'debbugs-gnu-current-filter (cons (intern key) val)))) - - ;; The End. - (t (throw :finished nil))))) - - ;; Do the search. - (debbugs-gnu severities packages archivedp))) + 'debbugs-gnu-current-query (cons (intern key) val1)))) + + ;; Client-side filters. + ((member key '("date" "log_modified" "last_modified" + "found_date" "fixed_date" "unarchived")) + (setq val1 + (debbugs-gnu-calendar-read + (format "Enter %s before YYYY-MM-DD%s: " + key (if phrase "" " (client-side filter)")) + (lambda (x) + (string-match (concat "^\\(" date-format "\\|\\)$") x)))) + (if (string-match date-format val1) + (setq val1 (floor + (float-time + (encode-time + 0 0 0 + (string-to-number (match-string 3 val1)) + (string-to-number (match-string 2 val1)) + (string-to-number (match-string 1 val1)))))) + (setq val1 nil)) + (setq val2 + (debbugs-gnu-calendar-read + (format "Enter %s after YYYY-MM-DD%s: " + key (if phrase "" " (client-side filter)")) + (lambda (x) + (string-match (concat "^\\(" date-format "\\|\\)$") x)))) + (if (string-match date-format val2) + (setq val2 (floor + (float-time + (encode-time + 0 0 0 + (string-to-number (match-string 3 val2)) + (string-to-number (match-string 2 val2)) + (string-to-number (match-string 1 val2)))))) + (setq val2 nil)) + (when (or val1 val2) + (add-to-list + (if phrase + 'debbugs-gnu-current-query 'debbugs-gnu-current-filter) + (cons (intern key) (cons val1 val2))))) + + ((not (zerop (length key))) + (setq val1 + (funcall + (if phrase 'read-string 'read-regexp) + (format "Enter %s%s" + key (if phrase ": " " (client-side filter)")))) + (when (not (zerop (length val1))) + (add-to-list + (if phrase + 'debbugs-gnu-current-query 'debbugs-gnu-current-filter) + (cons (intern key) val1)))) + + ;; The End. + (t (throw :finished nil))))) + + ;; Do the search. + (debbugs-gnu severities packages archivedp)) + + ;; Reset query and filter. + (setq debbugs-gnu-current-query nil + debbugs-gnu-current-filter nil))) ;;;###autoload (defun debbugs-gnu (severities &optional packages archivedp suppress) @@ -358,65 +416,67 @@ queried by a SOAP request, it is marked as \"client-side filter\"." (when archivedp (add-to-list 'debbugs-gnu-current-query '(archive . "1"))) - (let ((hits debbugs-gnu-default-hits-per-page) - (ids (debbugs-gnu-get-bugs debbugs-gnu-current-query))) - - (if (> (length ids) hits) - (let ((cursor-in-echo-area nil)) - (setq hits - (string-to-number - (read-string - (format - "How many reports (available %d, default %d): " - (length ids) hits) - nil - nil - (number-to-string hits)))))) - - (if (> (length ids) hits) - (let ((i 0) - curr-ids) - (while ids - (setq i (1+ i) - curr-ids (butlast ids (- (length ids) hits))) - (add-to-list - 'debbugs-gnu-widgets - (widget-convert - 'push-button - :follow-link 'mouse-face - :notify (lambda (widget &rest ignore) - (debbugs-gnu-show-reports widget)) - :keymap debbugs-gnu-widget-map - :suppress suppress - :buffer-name (format "*Emacs Bugs*<%d>" i) - :bug-ids curr-ids - :query debbugs-gnu-current-query - :filter debbugs-gnu-current-filter - :help-echo (format "%d-%d" (car ids) (car (last curr-ids))) - :format " %[%v%]" - (number-to-string i)) - 'append) - (setq ids (last ids (- (length ids) hits)))) - (debbugs-gnu-show-reports (car debbugs-gnu-widgets))) - - (debbugs-gnu-show-reports - (widget-convert - 'const - :suppress suppress - :buffer-name "*Emacs Bugs*" - :bug-ids ids - :query debbugs-gnu-current-query - :filter debbugs-gnu-current-filter)))) - - ;; Reset query and filter. - (setq debbugs-gnu-current-query nil - debbugs-gnu-current-filter nil)) + (unwind-protect + (let ((hits debbugs-gnu-default-hits-per-page) + (ids (debbugs-gnu-get-bugs debbugs-gnu-current-query))) + + (if (> (length ids) hits) + (let ((cursor-in-echo-area nil)) + (setq hits + (string-to-number + (read-string + (format + "How many reports (available %d, default %d): " + (length ids) hits) + nil + nil + (number-to-string hits)))))) + + (if (> (length ids) hits) + (let ((i 0) + curr-ids) + (while ids + (setq i (1+ i) + curr-ids (butlast ids (- (length ids) hits))) + (add-to-list + 'debbugs-gnu-widgets + (widget-convert + 'push-button + :follow-link 'mouse-face + :notify (lambda (widget &rest ignore) + (debbugs-gnu-show-reports widget)) + :keymap debbugs-gnu-widget-map + :suppress suppress + :buffer-name (format "*Emacs Bugs*<%d>" i) + :bug-ids curr-ids + :query debbugs-gnu-current-query + :filter debbugs-gnu-current-filter + :help-echo (format "%d-%d" (car ids) (car (last curr-ids))) + :format " %[%v%]" + (number-to-string i)) + 'append) + (setq ids (last ids (- (length ids) hits)))) + (debbugs-gnu-show-reports (car debbugs-gnu-widgets))) + + (debbugs-gnu-show-reports + (widget-convert + 'const + :suppress suppress + :buffer-name "*Emacs Bugs*" + :bug-ids ids + :query debbugs-gnu-current-query + :filter debbugs-gnu-current-filter)))) + + ;; Reset query and filter. + (setq debbugs-gnu-current-query nil + debbugs-gnu-current-filter nil))) (defun debbugs-gnu-get-bugs (query) "Retrieve bugs numbers from debbugs.gnu.org according search criteria." (let ((debbugs-port "gnu.org") (tagged (when (member '(severity . "tagged") query) (copy-sequence debbugs-gnu-local-tags))) + (phrase (assoc 'phrase query)) args) ;; Compile query arguments. (unless query @@ -425,14 +485,35 @@ queried by a SOAP request, it is marked as \"client-side filter\"." (dolist (elt query) (unless (equal elt '(severity . "tagged")) (setq args - (append args (list (intern (concat ":" (symbol-name (car elt)))) - (cdr elt)))))) - (if (and tagged (not (memq :severity args))) - ;; If the query contains only the pseudo-severity - ;; "tagged", we return just the local tagged bugs. - (sort tagged '<) - ;; Otherwise, we retrieve the bugs from the server. - (sort (append (apply 'debbugs-get-bugs args) tagged) '<)))) + (append + args + (if phrase + (cond + ((eq (car elt) 'phrase) + (list (list :phrase (cdr elt) :max 500))) + ((eq (car elt) 'date) + (list (list :date (cddr elt) (cadr elt) + :operator "NUMBT"))) + (t + (list (list (intern (concat ":" (symbol-name (car elt)))) + (cdr elt) :operator "ISTRINC")))) + (list (intern (concat ":" (symbol-name (car elt)))) + (cdr elt))))))) + + (cond + ;; If the query contains only the pseudo-severity "tagged", we + ;; return just the local tagged bugs. + ((and tagged (not (memq :severity args))) + (sort tagged '<)) + ;; A full text query. + (phrase + (append + (mapcar + (lambda (x) (cdr (assoc "id" x))) + (apply 'debbugs-search-est args)) + tagged)) + ;; Otherwise, we retrieve the bugs from the server. + (t (sort (append (apply 'debbugs-get-bugs args) tagged) '<))))) (defvar debbugs-gnu-current-widget nil) @@ -478,55 +559,64 @@ queried by a SOAP request, it is marked as \"client-side filter\"." merged (mapconcat 'number-to-string merged ",")) words))) - (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 - ((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)) - '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))) + (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 + ((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) @@ -566,6 +656,9 @@ Used instead of `tabulated-list-print-entry'." (title (aref cols 3)) (title-length (nth 1 (aref tabulated-list-format 3)))) (when (and + ;; We may have a narrowing in effect. + (or (not debbugs-gnu-current-limit) + (memq (cdr (assq 'id list-id)) debbugs-gnu-current-limit)) ;; Filter suppressed bugs. (or (not (widget-get debbugs-gnu-current-widget :suppress)) (not (catch :suppress @@ -579,18 +672,17 @@ Used instead of `tabulated-list-print-entry'." (not (catch :suppress (dolist (check (widget-get debbugs-gnu-current-widget :filter)) - ;; Regular expression. - (if (stringp (cdr check)) - (when (not - (string-match - (cdr check) - (or (cdr (assq (car check) list-id)) ""))) - (throw :suppress t))) - ;; Time value. - (when (and (numberp (cdr (assq (car check) list-id))) - (funcall (cadr check) (cddr check) - (cdr (assq (car check) list-id)))) - (throw :suppress t)))))) + (let ((val (cdr (assq (car check) list-id)))) + (if (stringp (cdr check)) + ;; Regular expression. + (when (not (string-match (cdr check) (or val ""))) + (throw :suppress t)) + ;; Time value. + (when (or (and (numberp (cadr check)) + (< (cadr check) val)) + (and (numberp (cddr check)) + (> (cddr check) val))) + (throw :suppress t)))))))) ;; Insert id. (indent-to (- id-length (length id))) @@ -623,12 +715,13 @@ Used instead of `tabulated-list-print-entry'." (define-key map "\r" 'debbugs-gnu-select-report) (define-key map [mouse-1] 'debbugs-gnu-select-report) (define-key map [mouse-2] 'debbugs-gnu-select-report) - (define-key map "q" 'bury-buffer) (define-key map "s" 'debbugs-gnu-toggle-sort) (define-key map "t" 'debbugs-gnu-toggle-tag) (define-key map "d" 'debbugs-gnu-display-status) (define-key map "g" 'debbugs-gnu-rescan) (define-key map "x" 'debbugs-gnu-toggle-suppress) + (define-key map "/" 'debbugs-gnu-narrow-to-status) + (define-key map "w" 'debbugs-gnu-widen) (define-key map "C" 'debbugs-gnu-send-control-message) map)) @@ -659,6 +752,7 @@ Used instead of `tabulated-list-print-entry'." (goto-char pos))) (defvar debbugs-gnu-sort-state 'number) +(defvar debbugs-gnu-current-limit nil) (define-derived-mode debbugs-gnu-mode tabulated-list-mode "Debbugs" "Major mode for listing bug reports. @@ -669,8 +763,8 @@ All normal editing commands are switched off. The following commands are available: \\{debbugs-gnu-mode-map}" - (set (make-local-variable 'debbugs-gnu-sort-state) - 'number) + (set (make-local-variable 'debbugs-gnu-sort-state) 'number) + (set (make-local-variable 'debbugs-gnu-current-limit) nil) (setq tabulated-list-format [("Id" 5 debbugs-gnu-sort-id) ("State" 20 debbugs-gnu-sort-state) ("Submitter" 25 t) @@ -753,6 +847,48 @@ The following commands are available: (tabulated-list-init-header) (tabulated-list-print)) +(defun debbugs-gnu-widen () + "Display all the currently selected bug reports." + (interactive) + (let ((id (debbugs-gnu-current-id t)) + (inhibit-read-only t)) + (setq debbugs-gnu-current-limit nil) + (tabulated-list-init-header) + (tabulated-list-print) + (when id + (debbugs-gnu-goto id)))) + +(defun debbugs-gnu-narrow-to-status (string &optional status-only) + "Only display the bugs matching STRING. +If STATUS-ONLY (the prefix), ignore matches in the From and +Subject fields." + (interactive "sNarrow to: \np") + (let ((id (debbugs-gnu-current-id t)) + (inhibit-read-only t) + status) + (setq debbugs-gnu-current-limit nil) + (goto-char (point-min)) + (while (not (eobp)) + (setq status (debbugs-gnu-current-status)) + (if (and (not (member string (assq 'keywords status))) + (not (member string (assq 'severity status))) + (or status-only + (not (string-match string (cdr (assq 'originator status))))) + (or status-only + (not (string-match string (cdr (assq 'subject status)))))) + (delete-region (point) (progn (forward-line 1) (point))) + (push (cdr (assq 'id status)) debbugs-gnu-current-limit) + (forward-line 1))) + (when id + (debbugs-gnu-goto id)))) + +(defun debbugs-gnu-goto (id) + "Go to the line displaying bug ID." + (goto-char (point-min)) + (while (and (not (eobp)) + (not (equal (debbugs-gnu-current-id t) id))) + (forward-line 1))) + (defun debbugs-gnu-toggle-tag () "Toggle tag of the report in the current line." (interactive) @@ -878,6 +1014,7 @@ removed instead." "merge" "forcemerge" "owner" "noowner" "invalid" + "reassign" "patch" "wontfix" "moreinfo" "unreproducible" "fixed" "notabug" "pending" "help" "security" "confirmed") nil t) @@ -916,6 +1053,8 @@ removed instead." (read-string "Merge with bug #: "))) ((equal message "owner") (format "owner %d !\n" id)) + ((equal message "reassign") + (format "reassign %d %s\n" id (read-string "Package: "))) ((equal message "close") (format "close %d %s\n" id version)) ((equal message "done")