From: Katsumi Yamaoka Date: Tue, 2 Jul 2013 10:38:58 +0000 (+0000) Subject: Merge changes made in Gnus trunk X-Git-Tag: emacs-24.3.90~173^2^2~42^2~45^2~387^2~1954 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=eaa610c3b428121b0d9abb7580016a0747aaaf72;p=emacs.git Merge changes made in Gnus trunk 2012-03-22 Lars Magne Ingebrigtsen * gnus.texi (Client-Side IMAP Splitting): Note that `nnimap-inbox' now can be a list. 2013-06-05 David Engster * gnus-sum.el (gnus-update-marks): Do not remove empty 'unexist' ranges, since `nnimap-retrieve-group-data-early' also uses it as a flag to see whether the group was synced before. 2012-09-05 Martin Stjernholm * nnimap.el (nnimap-request-move-article): Decode the group name when doing internal moves to avoid charset issues. 2012-09-05 Julien Danjou * nnimap.el (nnimap-request-list): Revert change that made listing synchronous. (nnimap-get-responses): Restore. 2012-08-31 Dave Abrahams * nnimap.el (nnimap-change-group): Document result value. * nnimap.el (nnimap-find-article-by-message-id): Account for the fact that nnimap-change-group can return t. 2012-08-06 Julien Danjou * nnimap.el (nnimap-request-head): Resture to-buffer parameter, used by `nnimap-request-move-article'. * nnimap.el (nnimap-request-head): Remove to-buffer argument. * gnus-int.el (gnus-request-head): Remove to-buffer argument, only supported by nnimap actually. Reverts previous change. * gnus-int.el (gnus-request-head): Add an optional to-buffer parameter to mimic `gnus-request-article' and enjoy backends the nn*-request-head to-buffer argument that is already supported. 2012-07-24 Julien Danjou * nnimap.el (nnimap-get-responses): Remove, unused. 2012-06-25 Julien Danjou * nnimap.el (nnimap-request-articles-find-limit): Rename from `nnimap-request-move-articles-find-limit' since we do not use it only for move operations. (nnimap-request-accept-article): Use `nnimap-request-articles-find-limit' to limit search by message-id. 2012-06-19 Julien Danjou * nnir.el (nnir-run-imap): Fix, use `nnimap-change-group'. * nnimap.el (nnimap-log-buffer): Check that `window-point-insertion-type' is boundp, since it's not available in XEmacs. 2012-06-19 Michael Welsh Duggan * nnimap.el (nnimap-log-buffer): Add this, setting `window-point-insertion-type' in the buffer to t. (nnimap-log-command): Use nnimap-log-buffer. 2012-06-19 Julien Danjou * nnimap.el (nnimap-find-article-by-message-id): Add an optional limit argument to be able to limit the search. (nnimap-request-move-article): Use `nnimap-request-move-articles-find-limit'. (nnimap-request-move-articles-find-limit): Add this to limit the search by Message-Id after a message move. (nnimap): Add defgroup. 2012-06-15 Julien Danjou * nnimap.el (nnimap-find-article-by-message-id): Use `nnimap-possibly-change-group' rather than its own EXAMINE call. (nnimap-possibly-change-group): Add read-only argument. (nnimap-request-list): Use nnimap-possibly-change-group rather than issuing EXAMINE manually. (nnimap-find-article-by-message-id): Use `nnimap-possibly-change-group' with read-only argument. (nnimap-change-group): Rename from `nnimap-possibly-change-group'. We cannot possibly change because we need to be sure that it's either read-write or read-only. 2012-06-10 Lars Magne Ingebrigtsen * gnus-sum.el (gnus-summary-insert-old-articles): Don't include unexistent messages. 2012-04-10 Lars Magne Ingebrigtsen * gnus-start.el (gnus-clean-old-newsrc): Remove totally bogus `unexists' entries. (gnus-clean-old-newsrc): Fix last checkin. * nnimap.el (nnimap-update-info): None of the articles below the active low-water mark exist. 2012-03-27 Katsumi Yamaoka * nnimap.el (gnus-refer-thread-use-nnir): Silence the byte compiler. 2012-03-22 Sergio Martinez (tiny change) * nnimap.el (nnimap-request-scan): Allow `nnimap-inbox' to be a list of inboxes. 2012-03-10 Lars Magne Ingebrigtsen * gnus-group.el (gnus-group-expire-articles-1): Don't try to expire messages that don't exist. * gnus-sum.el (gnus-summary-expire-articles): Ditto. 2012-02-20 Lars Ingebrigtsen * gnus-start.el (gnus-clean-old-newsrc): Allow a FORCE parameter. 2012-02-15 Lars Ingebrigtsen * gnus-start.el (gnus-clean-old-newsrc): Delete `unexist' from pre-Ma Gnus 0.3. 2012-02-15 Lars Ingebrigtsen * gnus-sum.el (gnus-summary-local-variables): Make `gnus-newsgroup-unexist' into a local variable. 2012-02-11 Lars Ingebrigtsen * gnus-sum.el (gnus-adjust-marked-articles): Add to `gnus-newsgroup-unexist'. * gnus.el (gnus-article-mark-lists): Add `unexist' to the list of marks. (gnus-article-special-mark-lists): Put the `unexist' in the special marks list instead. * gnus-sum.el (gnus-articles-to-read): Don't include unexisting articles in the list of articles to be selected. * nnimap.el (nnimap-retrieve-group-data-early): Query for unexisting articles. (nnimap-update-info): Keep track of unexisting articles. (nnimap-update-qresync-info): Ditto. 2012-02-01 Lars Ingebrigtsen * gnus-start.el (gnus-clean-old-newsrc): New function. (gnus-read-newsrc-file): Use it. --- diff --git a/doc/misc/ChangeLog b/doc/misc/ChangeLog index 016b0e8340f..d0f229a9c9e 100644 --- a/doc/misc/ChangeLog +++ b/doc/misc/ChangeLog @@ -1,3 +1,8 @@ +2013-07-02 Lars Magne Ingebrigtsen + + * gnus.texi (Client-Side IMAP Splitting): + Note that `nnimap-inbox' now can be a list. + 2013-06-24 Glenn Morris * eshell.texi: Fix cross-references to other manuals. diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi index b4d786c4d45..6df72f87fc7 100644 --- a/doc/misc/gnus.texi +++ b/doc/misc/gnus.texi @@ -14240,7 +14240,8 @@ variables are relevant: @table @code @item nnimap-inbox -This is the @acronym{IMAP} mail box that will be scanned for new mail. +This is the @acronym{IMAP} mail box that will be scanned for new +mail. This can also be a list of mail box names. @item nnimap-split-methods Uses the same syntax as @code{nnmail-split-methods} (@pxref{Splitting diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog index 9639f21c2fb..49b45380575 100644 --- a/lisp/gnus/ChangeLog +++ b/lisp/gnus/ChangeLog @@ -1,3 +1,157 @@ +2013-07-02 David Engster + + * gnus-sum.el (gnus-update-marks): Do not remove empty 'unexist' + ranges, since `nnimap-retrieve-group-data-early' also uses it as a flag + to see whether the group was synced before. + +2013-07-02 Martin Stjernholm + + * nnimap.el (nnimap-request-move-article): Decode the group name when + doing internal moves to avoid charset issues. + +2013-07-02 Julien Danjou + + * nnimap.el (nnimap-request-list): + Revert change that made listing synchronous. + (nnimap-get-responses): Restore. + +2013-07-02 Dave Abrahams + + * nnimap.el (nnimap-change-group): Document result value. + + * nnimap.el (nnimap-find-article-by-message-id): + Account for the fact that nnimap-change-group can return t. + +2013-07-02 Julien Danjou + + * nnimap.el (nnimap-request-head): + Resture to-buffer parameter, used by `nnimap-request-move-article'. + + * nnimap.el (nnimap-request-head): Remove to-buffer argument. + + * gnus-int.el (gnus-request-head): Remove to-buffer argument, only + supported by nnimap actually. Reverts previous change. + + * gnus-int.el (gnus-request-head): Add an optional to-buffer parameter + to mimic `gnus-request-article' and enjoy backends the nn*-request-head + to-buffer argument that is already supported. + +2013-07-02 Julien Danjou + + * nnimap.el (nnimap-get-responses): Remove, unused. + +2013-07-02 Julien Danjou + + * nnimap.el (nnimap-request-articles-find-limit): Rename from + `nnimap-request-move-articles-find-limit' since we do not use it + only for move operations. + (nnimap-request-accept-article): + Use `nnimap-request-articles-find-limit' to limit search by message-id. + +2013-07-02 Julien Danjou + + * nnir.el (nnir-run-imap): Fix, use `nnimap-change-group'. + + * nnimap.el (nnimap-log-buffer): + Check that `window-point-insertion-type' is boundp, since it's not + available in XEmacs. + +2013-07-02 Michael Welsh Duggan + + * nnimap.el (nnimap-log-buffer): + Add this, setting `window-point-insertion-type' in the buffer to t. + (nnimap-log-command): Use nnimap-log-buffer. + +2013-07-02 Julien Danjou + + * nnimap.el (nnimap-find-article-by-message-id): + Add an optional limit argument to be able to limit the search. + (nnimap-request-move-article): + Use `nnimap-request-move-articles-find-limit'. + (nnimap-request-move-articles-find-limit): + Add this to limit the search by Message-Id after a message move. + (nnimap): Add defgroup. + +2013-07-02 Julien Danjou + + * nnimap.el (nnimap-find-article-by-message-id): + Use `nnimap-possibly-change-group' rather than its own EXAMINE call. + (nnimap-possibly-change-group): Add read-only argument. + (nnimap-request-list): Use nnimap-possibly-change-group rather than + issuing EXAMINE manually. + (nnimap-find-article-by-message-id): + Use `nnimap-possibly-change-group' with read-only argument. + (nnimap-change-group): Rename from `nnimap-possibly-change-group'. + We cannot possibly change because we need to be sure that it's either + read-write or read-only. + +2013-07-02 Lars Magne Ingebrigtsen + + * gnus-sum.el (gnus-summary-insert-old-articles): + Don't include unexistent messages. + +2013-07-02 Lars Magne Ingebrigtsen + + * gnus-start.el (gnus-clean-old-newsrc): + Remove totally bogus `unexists' entries. + (gnus-clean-old-newsrc): Fix last checkin. + + * nnimap.el (nnimap-update-info): + None of the articles below the active low-water mark exist. + +2013-07-02 Katsumi Yamaoka + + * nnimap.el (gnus-refer-thread-use-nnir): Silence the byte compiler. + +2013-07-02 Sergio Martinez (tiny change) + + * nnimap.el (nnimap-request-scan): + Allow `nnimap-inbox' to be a list of inboxes. + +2013-07-02 Lars Magne Ingebrigtsen + + * gnus-group.el (gnus-group-expire-articles-1): + Don't try to expire messages that don't exist. + + * gnus-sum.el (gnus-summary-expire-articles): Ditto. + +2013-07-02 Lars Ingebrigtsen + + * gnus-start.el (gnus-clean-old-newsrc): Allow a FORCE parameter. + +2013-07-02 Lars Ingebrigtsen + + * gnus-start.el (gnus-clean-old-newsrc): + Delete `unexist' from pre-Ma Gnus 0.3. + +2013-07-02 Lars Ingebrigtsen + + * gnus-sum.el (gnus-summary-local-variables): + Make `gnus-newsgroup-unexist' into a local variable. + +2013-07-02 Lars Ingebrigtsen + + * gnus-sum.el (gnus-adjust-marked-articles): + Add to `gnus-newsgroup-unexist'. + + * gnus.el (gnus-article-mark-lists): + Add `unexist' to the list of marks. + (gnus-article-special-mark-lists): + Put the `unexist' in the special marks list instead. + + * gnus-sum.el (gnus-articles-to-read): Don't include unexisting + articles in the list of articles to be selected. + + * nnimap.el (nnimap-retrieve-group-data-early): + Query for unexisting articles. + (nnimap-update-info): Keep track of unexisting articles. + (nnimap-update-qresync-info): Ditto. + +2013-07-02 Lars Ingebrigtsen + + * gnus-start.el (gnus-clean-old-newsrc): New function. + (gnus-read-newsrc-file): Use it. + 2013-07-02 Daiki Ueno * mml2015.el (mml2015-epg-key-image): Use 'gnus-create-image' instead diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el index 207877364fe..8050f5d59d7 100644 --- a/lisp/gnus/gnus-group.el +++ b/lisp/gnus/gnus-group.el @@ -3654,6 +3654,10 @@ Uses the process/prefix convention." (expirable (if (gnus-group-total-expirable-p group) (cons nil (gnus-list-of-read-articles group)) (assq 'expire (gnus-info-marks info)))) + (articles-to-expire + (gnus-list-range-difference + (gnus-uncompress-sequence (cdr expirable)) + (cdr (assq 'unexist (gnus-info-marks info))))) (expiry-wait (gnus-group-find-parameter group 'expiry-wait)) (nnmail-expiry-target (or (gnus-group-find-parameter group 'expiry-target) @@ -3668,11 +3672,9 @@ Uses the process/prefix convention." ;; parameter. (let ((nnmail-expiry-wait-function nil) (nnmail-expiry-wait expiry-wait)) - (gnus-request-expire-articles - (gnus-uncompress-sequence (cdr expirable)) group)) + (gnus-request-expire-articles articles-to-expire group)) ;; Just expire using the normal expiry values. - (gnus-request-expire-articles - (gnus-uncompress-sequence (cdr expirable)) group)))) + (gnus-request-expire-articles articles-to-expire group)))) (gnus-close-group group)) (gnus-message 6 "Expiring articles in %s...done" (gnus-group-decoded-name group)) diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el index 48bb99bfbce..084af884930 100644 --- a/lisp/gnus/gnus-start.el +++ b/lisp/gnus/gnus-start.el @@ -2301,7 +2301,27 @@ If FORCE is non-nil, the .newsrc file is read." (gnus-message 5 "Reading %s...done" newsrc-file))) ;; Convert old to new. - (gnus-convert-old-newsrc)))) + (gnus-convert-old-newsrc) + (gnus-clean-old-newsrc)))) + +(defun gnus-clean-old-newsrc (&optional force) + (when gnus-newsrc-file-version + ;; Remove totally bogus `unexists' entries. The name is + ;; `unexist'. + (dolist (info (cdr gnus-newsrc-alist)) + (let ((exist (assoc 'unexists (gnus-info-marks info)))) + (when exist + (gnus-info-set-marks + info (delete exist (gnus-info-marks info)))))) + (when (or force + (< (gnus-continuum-version gnus-newsrc-file-version) + (gnus-continuum-version "Ma Gnus v0.03"))) + ;; Remove old `exist' marks from old nnimap groups. + (dolist (info (cdr gnus-newsrc-alist)) + (let ((exist (assoc 'unexist (gnus-info-marks info)))) + (when exist + (gnus-info-set-marks + info (delete exist (gnus-info-marks info))))))))) (defun gnus-convert-old-newsrc () "Convert old newsrc formats into the current format, if needed." diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el index c8f593ea403..e136d4f8173 100644 --- a/lisp/gnus/gnus-sum.el +++ b/lisp/gnus/gnus-sum.el @@ -1524,6 +1524,9 @@ This list will always be a subset of gnus-newsgroup-undownloaded.") (defvar gnus-newsgroup-seen nil "Range of seen articles in the current newsgroup.") +(defvar gnus-newsgroup-unexist nil + "Range of unexistent articles in the current newsgroup.") + (defvar gnus-newsgroup-articles nil "List of articles in the current newsgroup.") @@ -1571,6 +1574,7 @@ This list will always be a subset of gnus-newsgroup-undownloaded.") gnus-newsgroup-killed gnus-newsgroup-unseen gnus-newsgroup-seen + gnus-newsgroup-unexist gnus-newsgroup-cached gnus-newsgroup-downloadable gnus-newsgroup-undownloaded @@ -5789,6 +5793,7 @@ If SELECT-ARTICLES, only select those articles from GROUP." "Find out what articles the user wants to read." (let* ((only-read-p t) (articles + (gnus-list-range-difference ;; Select all articles if `read-all' is non-nil, or if there ;; are no unread articles. (if (or read-all @@ -5815,7 +5820,8 @@ If SELECT-ARTICLES, only select those articles from GROUP." (setq only-read-p nil) (gnus-sorted-nunion (gnus-sorted-union gnus-newsgroup-dormant gnus-newsgroup-marked) - gnus-newsgroup-unreads))) + gnus-newsgroup-unreads)) + (cdr (assq 'unexist (gnus-info-marks (gnus-get-info group)))))) (scored-list (gnus-killed-articles gnus-newsgroup-killed articles)) (scored (length scored-list)) (number (length articles)) @@ -5985,7 +5991,9 @@ If SELECT-ARTICLES, only select those articles from GROUP." (and (numberp (car articles)) (> min (car articles))))) (pop articles)) - (set var articles)))))))) + (set var articles)) + ((eq mark 'unexist) + (set var (cdr marks))))))))) (defun gnus-update-missing-marks (missing) "Go through the list of MISSING articles and remove them from the mark lists." @@ -6061,7 +6069,8 @@ If SELECT-ARTICLES, only select those articles from GROUP." (gnus-active gnus-newsgroup-name) del)) (push (list del 'del (list (cdr type))) delta-marks)))) - (when list + (when (or list + (eq (cdr type) 'unexist)) (push (cons (cdr type) list) newmarked))) (when delta-marks @@ -10305,16 +10314,19 @@ This will be the case if the article has both been mailed and posted." 'request-expire-articles gnus-newsgroup-name)) ;; This backend supports expiry. (let* ((total (gnus-group-total-expirable-p gnus-newsgroup-name)) - (expirable (if total - (progn - ;; We need to update the info for - ;; this group for `gnus-list-of-read-articles' - ;; to give us the right answer. - (gnus-run-hooks 'gnus-exit-group-hook) - (gnus-summary-update-info) - (gnus-list-of-read-articles gnus-newsgroup-name)) - (setq gnus-newsgroup-expirable - (sort gnus-newsgroup-expirable '<)))) + (expirable + (gnus-list-range-difference + (if total + (progn + ;; We need to update the info for + ;; this group for `gnus-list-of-read-articles' + ;; to give us the right answer. + (gnus-run-hooks 'gnus-exit-group-hook) + (gnus-summary-update-info) + (gnus-list-of-read-articles gnus-newsgroup-name)) + (setq gnus-newsgroup-expirable + (sort gnus-newsgroup-expirable '<))) + gnus-newsgroup-unexist)) (expiry-wait (if now 'immediate (gnus-group-find-parameter gnus-newsgroup-name 'expiry-wait))) @@ -12847,7 +12859,9 @@ If ALL is a number, fetch this number of articles." ;; Some nntp servers lie about their active range. When ;; this happens, the active range can be in the millions. ;; Use a compressed range to avoid creating a huge list. - (gnus-range-difference (list gnus-newsgroup-active) old)) + (gnus-range-difference + (gnus-range-difference (list gnus-newsgroup-active) old) + gnus-newsgroup-unexist)) (setq len (gnus-range-length older)) (cond ((null older) nil) diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el index 2c2dbd90c56..9a927a1cfab 100644 --- a/lisp/gnus/gnus.el +++ b/lisp/gnus/gnus.el @@ -2636,10 +2636,11 @@ a string, be sure to use a valid format, see RFC 2616." (scored . score) (saved . save) (cached . cache) (downloadable . download) (unsendable . unsend) (forwarded . forward) - (seen . seen))) + (seen . seen) (unexist . unexist))) (defconst gnus-article-special-mark-lists '((seen range) + (unexist range) (killed range) (bookmark tuple) (uid tuple) @@ -2654,7 +2655,7 @@ a string, be sure to use a valid format, see RFC 2616." ;; `score' is not a proper mark ;; `bookmark': don't propagated it, or fix the bug in update-mark. (defconst gnus-article-unpropagated-mark-lists - '(seen cache download unsend score bookmark) + '(seen cache download unsend score bookmark unexist) "Marks that shouldn't be propagated to back ends. Typical marks are those that make no sense in a standalone back end, such as a mark that says whether an article is stored in the cache diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el index 8fdd69b47da..4d9320b995f 100644 --- a/lisp/gnus/nnimap.el +++ b/lisp/gnus/nnimap.el @@ -82,7 +82,8 @@ back on `network'.") (defvoo nnimap-inbox nil "The mail box where incoming mail arrives and should be split out of. -For example, \"INBOX\".") +This can be a string or a list of strings +For example, \"INBOX\" or (\"INBOX\" \"SENT\").") (defvoo nnimap-split-methods nil "How mail is split. @@ -123,6 +124,16 @@ will fetch all parts that have types that match that string. A likely value would be \"text/\" to automatically fetch all textual parts.") +(defgroup nnimap nil + "IMAP for Gnus." + :group 'gnus) + +(defcustom nnimap-request-articles-find-limit nil + "Limit the number of articles to look for after moving an article." + :type 'integer + :version "24.3" + :group 'nnimap) + (defvar nnimap-process nil) (defvar nnimap-status-string "") @@ -173,7 +184,7 @@ textual parts.") (setq group (nnimap-decode-gnus-group group))) (with-current-buffer nntp-server-buffer (erase-buffer) - (when (nnimap-possibly-change-group group server) + (when (nnimap-change-group group server) (with-current-buffer (nnimap-buffer) (erase-buffer) (nnimap-wait-for-response @@ -567,10 +578,10 @@ textual parts.") (when group (setq group (nnimap-decode-gnus-group group))) (with-current-buffer nntp-server-buffer - (let ((result (nnimap-possibly-change-group group server)) + (let ((result (nnimap-change-group group server)) parts structure) (when (stringp article) - (setq article (nnimap-find-article-by-message-id group article))) + (setq article (nnimap-find-article-by-message-id group server article))) (when (and result article) (erase-buffer) @@ -599,10 +610,10 @@ textual parts.") (deffoo nnimap-request-head (article &optional group server to-buffer) (when group (setq group (nnimap-decode-gnus-group group))) - (when (nnimap-possibly-change-group group server) + (when (nnimap-change-group group server) (with-current-buffer (nnimap-buffer) (when (stringp article) - (setq article (nnimap-find-article-by-message-id group article))) + (setq article (nnimap-find-article-by-message-id group server article))) (if (null article) nil (nnimap-get-whole-article @@ -751,7 +762,7 @@ textual parts.") (deffoo nnimap-request-group (group &optional server dont-check info) (setq group (nnimap-decode-gnus-group group)) - (let ((result (nnimap-possibly-change-group + (let ((result (nnimap-change-group ;; Don't SELECT the group if we're going to select it ;; later, anyway. (if (and (not dont-check) @@ -801,19 +812,19 @@ textual parts.") (deffoo nnimap-request-create-group (group &optional server args) (setq group (nnimap-decode-gnus-group group)) - (when (nnimap-possibly-change-group nil server) + (when (nnimap-change-group nil server) (with-current-buffer (nnimap-buffer) (car (nnimap-command "CREATE %S" (utf7-encode group t)))))) (deffoo nnimap-request-delete-group (group &optional force server) (setq group (nnimap-decode-gnus-group group)) - (when (nnimap-possibly-change-group nil server) + (when (nnimap-change-group nil server) (with-current-buffer (nnimap-buffer) (car (nnimap-command "DELETE %S" (utf7-encode group t)))))) (deffoo nnimap-request-rename-group (group new-name &optional server) (setq group (nnimap-decode-gnus-group group)) - (when (nnimap-possibly-change-group nil server) + (when (nnimap-change-group nil server) (with-current-buffer (nnimap-buffer) (nnimap-unselect-group) (car (nnimap-command "RENAME %S %S" @@ -828,7 +839,7 @@ textual parts.") (deffoo nnimap-request-expunge-group (group &optional server) (setq group (nnimap-decode-gnus-group group)) - (when (nnimap-possibly-change-group group server) + (when (nnimap-change-group group server) (with-current-buffer (nnimap-buffer) (car (nnimap-command "EXPUNGE"))))) @@ -856,6 +867,8 @@ textual parts.") (deffoo nnimap-request-move-article (article group server accept-form &optional last internal-move-group) (setq group (nnimap-decode-gnus-group group)) + (when internal-move-group + (setq internal-move-group (nnimap-decode-gnus-group internal-move-group))) (with-temp-buffer (mm-disable-multibyte) (when (funcall (if internal-move-group @@ -876,11 +889,12 @@ textual parts.") (cons internal-move-group (or (nnimap-find-uid-response "COPYUID" (cadr result)) (nnimap-find-article-by-message-id - internal-move-group message-id))))) + internal-move-group server message-id + nnimap-request-articles-find-limit))))) ;; Move the article to a different method. (let ((result (eval accept-form))) (when result - (nnimap-possibly-change-group group server) + (nnimap-change-group group server) (nnimap-delete-article article) result))))))) @@ -889,7 +903,7 @@ textual parts.") (cond ((null articles) nil) - ((not (nnimap-possibly-change-group group server)) + ((not (nnimap-change-group group server)) articles) ((and force (eq nnmail-expiry-target 'delete)) @@ -926,7 +940,7 @@ textual parts.") (gnus-server-equal (gnus-group-method nnmail-expiry-target) (gnus-server-to-method (format "nnimap:%s" server)))) - (and (nnimap-possibly-change-group group server) + (and (nnimap-change-group group server) (with-current-buffer (nnimap-buffer) (nnheader-message 7 "Expiring articles from %s: %s" group articles) (nnimap-command @@ -956,7 +970,7 @@ textual parts.") (when target (push article deleted-articles)))))))) ;; Change back to the current group again. - (nnimap-possibly-change-group group server) + (nnimap-change-group group server) (setq deleted-articles (nreverse deleted-articles)) (nnimap-delete-article (gnus-compress-sequence deleted-articles)) deleted-articles)) @@ -978,23 +992,37 @@ textual parts.") (cdr (assoc "SEARCH" (cdr result)))))))))) -(defun nnimap-find-article-by-message-id (group message-id) +(defun nnimap-find-article-by-message-id (group server message-id + &optional limit) + "Search for message with MESSAGE-ID in GROUP from SERVER. +If LIMIT, first try to limit the search to the N last articles." (with-current-buffer (nnimap-buffer) (erase-buffer) - (unless (or (not group) (equal group (nnimap-group nnimap-object))) - (setf (nnimap-group nnimap-object) nil) - (setf (nnimap-examined nnimap-object) group) - (nnimap-send-command "EXAMINE %S" (utf7-encode group t))) - (let ((sequence - (nnimap-send-command "UID SEARCH HEADER Message-Id %S" message-id)) - article result) - (setq result (nnimap-wait-for-response sequence)) - (when (and result - (car (setq result (nnimap-parse-response)))) - ;; Select the last instance of the message in the group. - (and (setq article - (car (last (cdr (assoc "SEARCH" (cdr result)))))) - (string-to-number article)))))) + (let* ((change-group-result (nnimap-change-group group server nil t)) + (number-of-article + (and (listp change-group-result) + (catch 'found + (dolist (result (cdr change-group-result)) + (when (equal "EXISTS" (cadr result)) + (throw 'found (car result))))))) + (sequence + (nnimap-send-command + "UID SEARCH%s HEADER Message-Id %S" + (if (and limit number-of-article) + ;; The -1 is because IMAP message + ;; numbers are one-based rather than + ;; zero-based. + (format " %s:*" (- (string-to-number number-of-article) + limit -1)) + "") + message-id))) + (when (nnimap-wait-for-response sequence) + (let ((article (car (last (cdr (assoc "SEARCH" + (nnimap-parse-response))))))) + (if article + (string-to-number article) + (when (and limit number-of-article) + (nnimap-find-article-by-message-id group server message-id)))))))) (defun nnimap-delete-article (articles) (with-current-buffer (nnimap-buffer) @@ -1015,11 +1043,14 @@ textual parts.") (deffoo nnimap-request-scan (&optional group server) (when group (setq group (nnimap-decode-gnus-group group))) - (when (and (nnimap-possibly-change-group nil server) + (when (and (nnimap-change-group nil server) nnimap-inbox nnimap-split-methods) (nnheader-message 7 "nnimap %s splitting mail..." server) - (nnimap-split-incoming-mail) + (if (listp nnimap-inbox) + (dolist (nnimap-inbox nnimap-inbox) + (nnimap-split-incoming-mail)) + (nnimap-split-incoming-mail)) (nnheader-message 7 "nnimap %s splitting mail...done" server))) (defun nnimap-marks-to-flags (marks) @@ -1031,7 +1062,7 @@ textual parts.") (deffoo nnimap-request-update-group-status (group status &optional server) (setq group (nnimap-decode-gnus-group group)) - (when (nnimap-possibly-change-group nil server) + (when (nnimap-change-group nil server) (let ((command (assoc status '((subscribe "SUBSCRIBE") @@ -1042,7 +1073,7 @@ textual parts.") (deffoo nnimap-request-set-mark (group actions &optional server) (setq group (nnimap-decode-gnus-group group)) - (when (nnimap-possibly-change-group group server) + (when (nnimap-change-group group server) (let (sequence) (with-current-buffer (nnimap-buffer) (erase-buffer) @@ -1067,7 +1098,7 @@ textual parts.") (deffoo nnimap-request-accept-article (group &optional server last) (setq group (nnimap-decode-gnus-group group)) - (when (nnimap-possibly-change-group nil server) + (when (nnimap-change-group nil server) (nnmail-check-syntax) (let ((message-id (message-field-value "message-id")) sequence message) @@ -1099,7 +1130,8 @@ textual parts.") (cons group (or (nnimap-find-uid-response "APPENDUID" (car result)) (nnimap-find-article-by-message-id - group message-id)))))))))) + group server message-id + nnimap-request-articles-find-limit)))))))))) (defun nnimap-process-quirk (greeting-match type data) (when (and (nnimap-greeting nnimap-object) @@ -1145,7 +1177,7 @@ textual parts.") (deffoo nnimap-request-replace-article (article group buffer) (setq group (nnimap-decode-gnus-group group)) (let (group-art) - (when (and (nnimap-possibly-change-group group nil) + (when (and (nnimap-change-group group) ;; Put the article into the group. (with-current-buffer buffer (setq group-art @@ -1180,8 +1212,17 @@ textual parts.") groups)))) (nreverse groups))) +(defun nnimap-get-responses (sequences) + (let (responses) + (dolist (sequence sequences) + (goto-char (point-min)) + (when (re-search-forward (format "^%d " sequence) nil t) + (push (list sequence (nnimap-parse-response)) + responses))) + responses)) + (deffoo nnimap-request-list (&optional server) - (when (nnimap-possibly-change-group nil server) + (when (nnimap-change-group nil server) (with-current-buffer nntp-server-buffer (erase-buffer) (let ((groups @@ -1228,7 +1269,7 @@ textual parts.") t))))) (deffoo nnimap-request-newgroups (date &optional server) - (when (nnimap-possibly-change-group nil server) + (when (nnimap-change-group nil server) (with-current-buffer nntp-server-buffer (erase-buffer) (dolist (group (with-current-buffer (nnimap-buffer) @@ -1239,14 +1280,15 @@ textual parts.") t))) (deffoo nnimap-retrieve-group-data-early (server infos) - (when (and (nnimap-possibly-change-group nil server) + (when (and (nnimap-change-group nil server) infos) (with-current-buffer (nnimap-buffer) (erase-buffer) (setf (nnimap-group nnimap-object) nil) (setf (nnimap-initial-resync nnimap-object) 0) (let ((qresyncp (nnimap-capability "QRESYNC")) - params groups sequences active uidvalidity modseq group) + params groups sequences active uidvalidity modseq group + unexist) ;; Go through the infos and gather the data needed to know ;; what and how to request the data. (dolist (info infos) @@ -1254,13 +1296,15 @@ textual parts.") group (nnimap-decode-gnus-group (gnus-group-real-name (gnus-info-group info))) active (cdr (assq 'active params)) + unexist (assq 'unexist (gnus-info-marks info)) uidvalidity (cdr (assq 'uidvalidity params)) modseq (cdr (assq 'modseq params))) (setf (nnimap-examined nnimap-object) group) (if (and qresyncp uidvalidity active - modseq) + modseq + unexist) (push (list (nnimap-send-command "EXAMINE %S (%s (%s %s))" (utf7-encode group t) @@ -1279,11 +1323,10 @@ textual parts.") ;; is read-only or not. "SELECT")) start) - (if (and active uidvalidity) + (if (and active uidvalidity unexist) ;; Fetch the last 100 flags. (setq start (max 1 (- (cdr active) 100))) - (setf (nnimap-initial-resync nnimap-object) - (1+ (nnimap-initial-resync nnimap-object))) + (incf (nnimap-initial-resync nnimap-object)) (setq start 1)) (push (list (nnimap-send-command "%s %S" command (utf7-encode group t)) @@ -1303,7 +1346,7 @@ textual parts.") (deffoo nnimap-finish-retrieve-group-infos (server infos sequences) (when (and sequences - (nnimap-possibly-change-group nil server t) + (nnimap-change-group nil server t) ;; Check that the process is still alive. (get-buffer-process (nnimap-buffer)) (memq (process-status (get-buffer-process (nnimap-buffer))) @@ -1462,6 +1505,25 @@ textual parts.") (setq new-marks (gnus-range-nconcat old-marks new-marks))) (when new-marks (push (cons (car type) new-marks) marks))))) + ;; Keep track of non-existing articles. + (let* ((old-unexists (assq 'unexist marks)) + (active (gnus-active group)) + (unexists + (if completep + (gnus-range-difference + active + (gnus-compress-sequence existing)) + (gnus-add-to-range + (cdr old-unexists) + (gnus-list-range-difference + existing (gnus-active group)))))) + (when (> (car active) 1) + (setq unexists (gnus-range-add + (cons 1 (1- (car active))) + unexists))) + (if old-unexists + (setcdr old-unexists unexists) + (push (cons 'unexist unexists) marks))) (gnus-info-set-marks info marks t)))) ;; Tell Gnus whether there are any \Recent messages in any of ;; the groups. @@ -1505,6 +1567,14 @@ textual parts.") (gnus-sorted-complement existing new-marks)))) (when ticks (push (cons (car type) ticks) marks))) + (gnus-info-set-marks info marks t)) + ;; Add vanished to the list of unexisting articles. + (when vanished + (let* ((old-unexists (assq 'unexist marks)) + (unexists (gnus-range-add (cdr old-unexists) vanished))) + (if old-unexists + (setcdr old-unexists unexists) + (push (cons 'unexist unexists) marks))) (gnus-info-set-marks info marks t)))) (defun nnimap-imap-ranges-to-gnus-ranges (irange) @@ -1642,7 +1712,7 @@ textual parts.") (setq nnimap-status-string "Read-only server") nil) -(defvar gnus-refer-thread-use-nnir) ; gnus-sum +(defvar gnus-refer-thread-use-nnir) ;; gnus-sum.el (declare-function gnus-fetch-headers "gnus-sum" (articles &optional limit force-new dependencies)) @@ -1653,7 +1723,7 @@ textual parts.") (setq group (nnimap-decode-gnus-group group))) (if gnus-refer-thread-use-nnir (nnir-search-thread header) - (when (nnimap-possibly-change-group group server) + (when (nnimap-change-group group server) (let* ((cmd (nnimap-make-thread-query header)) (result (with-current-buffer (nnimap-buffer) (nnimap-command "UID SEARCH %s" cmd)))) @@ -1664,7 +1734,14 @@ textual parts.") (cdr (assoc "SEARCH" (cdr result)))))) nil t)))))) -(defun nnimap-possibly-change-group (group server &optional no-reconnect) +(defun nnimap-change-group (group &optional server no-reconnect read-only) + "Change group to GROUP if non-nil. +If SERVER is set, check that server is connected, otherwise retry +to reconnect, unless NO-RECONNECT is set to t. Return nil if +unsuccessful in connecting. +If GROUP is nil, return t. +If READ-ONLY is set, send EXAMINE rather than SELECT to the server. +Return the server's response to the SELECT or EXAMINE command." (let ((open-result t)) (when (and server (not (nnimap-server-opened server))) @@ -1676,13 +1753,15 @@ textual parts.") t) (t (with-current-buffer (nnimap-buffer) - (if (equal group (nnimap-group nnimap-object)) - t - (let ((result (nnimap-command "SELECT %S" (utf7-encode group t)))) - (when (car result) - (setf (nnimap-group nnimap-object) group - (nnimap-select-result nnimap-object) result) - result)))))))) + (let ((result (nnimap-command "%s %S" + (if read-only + "EXAMINE" + "SELECT") + (utf7-encode group t)))) + (when (car result) + (setf (nnimap-group nnimap-object) group + (nnimap-select-result nnimap-object) result) + result))))))) (defun nnimap-find-connection (buffer) "Find the connection delivering to BUFFER." @@ -1718,15 +1797,24 @@ textual parts.") (defvar nnimap-record-commands nil "If non-nil, log commands to the \"*imap log*\" buffer.") +(defun nnimap-log-buffer () + (let ((name "*imap log*")) + (or (get-buffer name) + (with-current-buffer (get-buffer-create name) + (when (boundp 'window-point-insertion-type) + (make-local-variable 'window-point-insertion-type) + (setq window-point-insertion-type t)) + (current-buffer))))) + (defun nnimap-log-command (command) (when nnimap-record-commands - (with-current-buffer (get-buffer-create "*imap log*") + (with-current-buffer (nnimap-log-buffer) (goto-char (point-max)) (insert (format-time-string "%H:%M:%S") - " [" nnimap-address "] " - (if nnimap-inhibit-logging - "(inhibited)\n" - command)))) + " [" nnimap-address "] " + (if nnimap-inhibit-logging + "(inhibited)\n" + command)))) command) (defun nnimap-command (&rest args) @@ -1865,15 +1953,6 @@ textual parts.") (forward-line 1))) (buffer-substring (point) end)))) -(defun nnimap-get-responses (sequences) - (let (responses) - (dolist (sequence sequences) - (goto-char (point-min)) - (when (re-search-forward (format "^%d " sequence) nil t) - (push (list sequence (nnimap-parse-response)) - responses))) - responses)) - (defvar nnimap-incoming-split-list nil) (defun nnimap-fetch-inbox (articles) diff --git a/lisp/gnus/nnir.el b/lisp/gnus/nnir.el index 120149ae0fb..22dee30e8fa 100644 --- a/lisp/gnus/nnir.el +++ b/lisp/gnus/nnir.el @@ -288,7 +288,7 @@ is `(valuefunc member)'." (eval-when-compile (autoload 'nnimap-buffer "nnimap") (autoload 'nnimap-command "nnimap") - (autoload 'nnimap-possibly-change-group "nnimap") + (autoload 'nnimap-change-group "nnimap") (autoload 'nnimap-make-thread-query "nnimap") (autoload 'gnus-registry-action "gnus-registry") (autoload 'gnus-registry-get-id-key "gnus-registry") @@ -973,7 +973,7 @@ details on the language and supported extensions." #'(lambda (group) (let (artlist) (condition-case () - (when (nnimap-possibly-change-group + (when (nnimap-change-group (gnus-group-short-name group) server) (with-current-buffer (nnimap-buffer) (message "Searching %s..." group)