diff options
| author | Lars Magne Ingebrigtsen | 2010-09-21 23:13:46 +0000 |
|---|---|---|
| committer | Katsumi Yamaoka | 2010-09-21 23:13:46 +0000 |
| commit | 0617bb00a422ec62d2e7656d0d83636c7dd00e57 (patch) | |
| tree | 9cee393567600cfded5fd36d57cb76deb6cdaea7 | |
| parent | 4ddea91b84a1947e027a2996e92e3d9c32e337a3 (diff) | |
| download | emacs-0617bb00a422ec62d2e7656d0d83636c7dd00e57.tar.gz emacs-0617bb00a422ec62d2e7656d0d83636c7dd00e57.zip | |
Merge changes made in Gnus trunk.
gnus-group.el (gnus-group-line-format-alist): Have the ?U (unseen) spec inserr "*" if the group isn't active instead of 0.
nnimap.el (nnimap-request-create-group): Implement.
nnimap.el: Use the IMAP version of utf7-encode throughout.
nnimap.el: Implement the nnimap article expunging interface method, and make it more general.
gnus-group.el: Put back the nnimap autoloads needed to do the acl stuff.
gnus-sum.el (gnus-summary-move-article): When respooling to the same method, this would bug out.
nnimap.el (nnimap-request-group): When we have zero articles, return the right data to Gnus.
nnimap.el (nnimap-request-expire-articles): Only delete articles immediately if the target is 'delete.
nnmail.el (nnmail-expired-article-p): Allow returning the cutoff time for oldness in addition to being a predicate.
nnimap.el: Implement nnimap expiry.
nnimap.el (nnimap-request-move-article): Request the article before looking at what the Message-ID is.
nnimap.el (nnimap-mark-and-expunge-incoming): Wait for the last sequence.
gnus-sum.el (gnus-summary-move-article): Use gnus-server-equal to find out whether methods are equal.
nnimap.el (nnimap-find-expired-articles): Don't refer to nnml-inhibit-expiry.
nnmail.el (nnmail-expired-article-p): Fix typo: time-subtract.
gnus-start.el (gnus-get-unread-articles): Fix the prefixed select method in the presence of many similar methods.
When we have several similar methods, try to create as few extended methods as possible.
gnus-sum.el (gnus-adjust-marked-articles): Hack to avoid adjusting marks for nnimap, which is seldom the right thing to do.
gnus-int.el (gnus-open-server): Give a better error message in the "go offline" case.
gnus-sum.el (gnus-adjust-marked-articles): Fix another typo.
nnml.el (nnml-generate-nov-file): Fix variable name clobbering from previous patch.
gnus-start.el (gnus-get-unread-articles): Get the extended method slightly later to avoid double-getting it.
| -rw-r--r-- | doc/misc/gnus.texi | 2 | ||||
| -rw-r--r-- | lisp/gnus/ChangeLog | 54 | ||||
| -rw-r--r-- | lisp/gnus/gnus-group.el | 29 | ||||
| -rw-r--r-- | lisp/gnus/gnus-int.el | 14 | ||||
| -rw-r--r-- | lisp/gnus/gnus-start.el | 22 | ||||
| -rw-r--r-- | lisp/gnus/gnus-sum.el | 9 | ||||
| -rw-r--r-- | lisp/gnus/gnus.el | 84 | ||||
| -rw-r--r-- | lisp/gnus/nnimap.el | 162 | ||||
| -rw-r--r-- | lisp/gnus/nnmail.el | 15 | ||||
| -rw-r--r-- | lisp/gnus/nnml.el | 33 |
10 files changed, 295 insertions, 129 deletions
diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi index 841cf8c510c..52c8bb642f0 100644 --- a/doc/misc/gnus.texi +++ b/doc/misc/gnus.texi | |||
| @@ -18384,7 +18384,7 @@ INBOX.mailbox). | |||
| 18384 | @cindex expunge | 18384 | @cindex expunge |
| 18385 | @cindex manual expunging | 18385 | @cindex manual expunging |
| 18386 | @kindex G x (Group) | 18386 | @kindex G x (Group) |
| 18387 | @findex gnus-group-nnimap-expunge | 18387 | @findex gnus-group-expunge-group |
| 18388 | 18388 | ||
| 18389 | If you're using the @code{never} setting of @code{nnimap-expunge-on-close}, | 18389 | If you're using the @code{never} setting of @code{nnimap-expunge-on-close}, |
| 18390 | you may want the option of expunging all deleted articles in a mailbox | 18390 | you may want the option of expunging all deleted articles in a mailbox |
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog index 6ca3a0198c6..eeba68f81a2 100644 --- a/lisp/gnus/ChangeLog +++ b/lisp/gnus/ChangeLog | |||
| @@ -1,3 +1,57 @@ | |||
| 1 | 2010-09-21 Adam Sjøgren <asjo@koldfront.dk> | ||
| 2 | |||
| 3 | * gnus-sum.el (gnus-adjust-marked-articles): Fix typo. | ||
| 4 | |||
| 5 | 2010-09-21 Lars Magne Ingebrigtsen <larsi@gnus.org> | ||
| 6 | |||
| 7 | * gnus-int.el (gnus-open-server): Give a better error message in the | ||
| 8 | "go offline" case. | ||
| 9 | |||
| 10 | * gnus-sum.el (gnus-adjust-marked-articles): Hack to avoid adjusting | ||
| 11 | marks for nnimap, which is seldom the right thing to do. | ||
| 12 | |||
| 13 | * gnus.el (gnus-sloppily-equal-method-parameters): Refactor out. | ||
| 14 | (gnus-same-method-different-name): New function. | ||
| 15 | |||
| 16 | * nnimap.el (parse-time): Require. | ||
| 17 | |||
| 18 | * gnus-start.el (gnus-get-unread-articles): Fix the prefixed select | ||
| 19 | method in the presence of many similar methods. | ||
| 20 | |||
| 21 | * nnmail.el (nnmail-expired-article-p): Fix typo: time-subtract. | ||
| 22 | |||
| 23 | * nnimap.el (nnimap-find-expired-articles): Don't refer to | ||
| 24 | nnml-inhibit-expiry. | ||
| 25 | |||
| 26 | * gnus-sum.el (gnus-summary-move-article): Use gnus-server-equal to | ||
| 27 | find out whether methods are equal. | ||
| 28 | |||
| 29 | * nnimap.el (nnimap-find-expired-articles): New function. | ||
| 30 | (nnimap-process-expiry-targets): New function. | ||
| 31 | (nnimap-request-move-article): Request the article before looking at | ||
| 32 | what the Message-ID is. Fix found by Andrew Cohen. | ||
| 33 | (nnimap-mark-and-expunge-incoming): Wait for the last sequence. | ||
| 34 | |||
| 35 | * nnmail.el (nnmail-expired-article-p): Allow returning the cutoff time | ||
| 36 | for oldness in addition to being a predicate. | ||
| 37 | |||
| 38 | * nnimap.el (nnimap-request-group): When we have zero articles, return | ||
| 39 | the right data to Gnus. | ||
| 40 | (nnimap-request-expire-articles): Only delete articles immediately if | ||
| 41 | the target is 'delete. | ||
| 42 | |||
| 43 | * gnus-sum.el (gnus-summary-move-article): When respooling to the same | ||
| 44 | method, this would bug out. | ||
| 45 | |||
| 46 | * gnus-group.el (gnus-group-expunge-group): Renamed from | ||
| 47 | gnus-group-nnimap-expunge, and implemented as a normal interface | ||
| 48 | function. | ||
| 49 | |||
| 50 | * gnus-int.el (gnus-request-expunge-group): New function. | ||
| 51 | |||
| 52 | * nnimap.el (nnimap-request-create-group): Implement. | ||
| 53 | (nnimap-request-expunge-group): New function. | ||
| 54 | |||
| 1 | 2010-09-21 Julien Danjou <julien@danjou.info> | 55 | 2010-09-21 Julien Danjou <julien@danjou.info> |
| 2 | 56 | ||
| 3 | * gnus-html.el (gnus-html-image-cache-ttl): Add new variable. | 57 | * gnus-html.el (gnus-html-image-cache-ttl): Add new variable. |
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el index fa6ae51886c..80cf580b84a 100644 --- a/lisp/gnus/gnus-group.el +++ b/lisp/gnus/gnus-group.el | |||
| @@ -509,7 +509,10 @@ simple manner.") | |||
| 509 | (gnus-range-length (cdr (assq 'tick gnus-tmp-marked)))))) | 509 | (gnus-range-length (cdr (assq 'tick gnus-tmp-marked)))))) |
| 510 | (t number)) ?s) | 510 | (t number)) ?s) |
| 511 | (?R gnus-tmp-number-of-read ?s) | 511 | (?R gnus-tmp-number-of-read ?s) |
| 512 | (?U (gnus-number-of-unseen-articles-in-group gnus-tmp-group) ?d) | 512 | (?U (if (gnus-active gnus-tmp-group) |
| 513 | (gnus-number-of-unseen-articles-in-group gnus-tmp-group) | ||
| 514 | "*") | ||
| 515 | ?s) | ||
| 513 | (?t gnus-tmp-number-total ?d) | 516 | (?t gnus-tmp-number-total ?d) |
| 514 | (?y gnus-tmp-number-of-unread ?s) | 517 | (?y gnus-tmp-number-of-unread ?s) |
| 515 | (?I (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked))) ?d) | 518 | (?I (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked))) ?d) |
| @@ -675,7 +678,7 @@ simple manner.") | |||
| 675 | "R" gnus-group-make-rss-group | 678 | "R" gnus-group-make-rss-group |
| 676 | "c" gnus-group-customize | 679 | "c" gnus-group-customize |
| 677 | "z" gnus-group-compact-group | 680 | "z" gnus-group-compact-group |
| 678 | "x" gnus-group-nnimap-expunge | 681 | "x" gnus-group-expunge-group |
| 679 | "\177" gnus-group-delete-group | 682 | "\177" gnus-group-delete-group |
| 680 | [delete] gnus-group-delete-group) | 683 | [delete] gnus-group-delete-group) |
| 681 | 684 | ||
| @@ -3163,21 +3166,17 @@ mail messages or news articles in files that have numeric names." | |||
| 3163 | 'summary 'group))) | 3166 | 'summary 'group))) |
| 3164 | (error "Couldn't enter %s" dir)))) | 3167 | (error "Couldn't enter %s" dir)))) |
| 3165 | 3168 | ||
| 3166 | (autoload 'nnimap-expunge "nnimap") | 3169 | (defun gnus-group-expunge-group (group) |
| 3167 | (autoload 'nnimap-acl-get "nnimap") | ||
| 3168 | (autoload 'nnimap-acl-edit "nnimap") | ||
| 3169 | |||
| 3170 | (defun gnus-group-nnimap-expunge (group) | ||
| 3171 | "Expunge deleted articles in current nnimap GROUP." | 3170 | "Expunge deleted articles in current nnimap GROUP." |
| 3172 | (interactive (list (gnus-group-group-name))) | 3171 | (interactive (list (gnus-group-group-name))) |
| 3173 | (let ((mailbox (gnus-group-real-name group)) method) | 3172 | (let ((method (gnus-find-method-for-group group))) |
| 3174 | (unless group | 3173 | (if (not (gnus-check-backend-function |
| 3175 | (error "No group on current line")) | 3174 | 'request-expunge-group (car method))) |
| 3176 | (unless (gnus-get-info group) | 3175 | (error "%s does not support expunging" (car method)) |
| 3177 | (error "Killed group; can't be edited")) | 3176 | (gnus-request-expunge-group group method)))) |
| 3178 | (unless (eq 'nnimap (car (setq method (gnus-find-method-for-group group)))) | 3177 | |
| 3179 | (error "%s is not an nnimap group" group)) | 3178 | (autoload 'nnimap-acl-get "nnimap") |
| 3180 | (nnimap-expunge mailbox (cadr method)))) | 3179 | (autoload 'nnimap-acl-edit "nnimap") |
| 3181 | 3180 | ||
| 3182 | (defun gnus-group-nnimap-edit-acl (group) | 3181 | (defun gnus-group-nnimap-edit-acl (group) |
| 3183 | "Edit the Access Control List of current nnimap GROUP." | 3182 | "Edit the Access Control List of current nnimap GROUP." |
diff --git a/lisp/gnus/gnus-int.el b/lisp/gnus/gnus-int.el index f245907ed1b..5ef58834df7 100644 --- a/lisp/gnus/gnus-int.el +++ b/lisp/gnus/gnus-int.el | |||
| @@ -275,8 +275,10 @@ If it is down, start it up (again)." | |||
| 275 | (not gnus-batch-mode) | 275 | (not gnus-batch-mode) |
| 276 | (gnus-y-or-n-p | 276 | (gnus-y-or-n-p |
| 277 | (format | 277 | (format |
| 278 | "Unable to open server %s, go offline? " | 278 | "Unable to open server %s (%s), go offline? " |
| 279 | server))) | 279 | server |
| 280 | (nnheader-get-report | ||
| 281 | (car gnus-command-method))))) | ||
| 280 | (setq open-offline t) | 282 | (setq open-offline t) |
| 281 | 'offline) | 283 | 'offline) |
| 282 | (t | 284 | (t |
| @@ -552,6 +554,14 @@ If BUFFER, insert the article in that group." | |||
| 552 | (funcall (gnus-get-function gnus-command-method 'request-post) | 554 | (funcall (gnus-get-function gnus-command-method 'request-post) |
| 553 | (nth 1 gnus-command-method))) | 555 | (nth 1 gnus-command-method))) |
| 554 | 556 | ||
| 557 | (defun gnus-request-expunge-group (group gnus-command-method) | ||
| 558 | "Expunge GROUP, which is removing articles that have been marked as deleted." | ||
| 559 | (when (stringp gnus-command-method) | ||
| 560 | (setq gnus-command-method (gnus-server-to-method gnus-command-method))) | ||
| 561 | (funcall (gnus-get-function gnus-command-method 'request-expunge-group) | ||
| 562 | (gnus-group-real-name group) | ||
| 563 | (nth 1 gnus-command-method))) | ||
| 564 | |||
| 555 | (defun gnus-request-scan (group gnus-command-method) | 565 | (defun gnus-request-scan (group gnus-command-method) |
| 556 | "Request a SCAN being performed in GROUP from GNUS-COMMAND-METHOD. | 566 | "Request a SCAN being performed in GROUP from GNUS-COMMAND-METHOD. |
| 557 | If GROUP is nil, all groups on GNUS-COMMAND-METHOD are scanned." | 567 | If GROUP is nil, all groups on GNUS-COMMAND-METHOD are scanned." |
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el index f4745c184e5..c2f09a83c07 100644 --- a/lisp/gnus/gnus-start.el +++ b/lisp/gnus/gnus-start.el | |||
| @@ -705,6 +705,7 @@ the first newsgroup." | |||
| 705 | nnoo-state-alist nil | 705 | nnoo-state-alist nil |
| 706 | gnus-current-select-method nil | 706 | gnus-current-select-method nil |
| 707 | nnmail-split-history nil | 707 | nnmail-split-history nil |
| 708 | gnus-extended-servers nil | ||
| 708 | gnus-ephemeral-servers nil) | 709 | gnus-ephemeral-servers nil) |
| 709 | (gnus-shutdown 'gnus) | 710 | (gnus-shutdown 'gnus) |
| 710 | ;; Kill the startup file. | 711 | ;; Kill the startup file. |
| @@ -1693,28 +1694,19 @@ If SCAN, request a scan of that group as well." | |||
| 1693 | (while newsrc | 1694 | (while newsrc |
| 1694 | (setq active (gnus-active (setq group (gnus-info-group | 1695 | (setq active (gnus-active (setq group (gnus-info-group |
| 1695 | (setq info (pop newsrc)))))) | 1696 | (setq info (pop newsrc)))))) |
| 1696 | |||
| 1697 | ;; Check newsgroups. If the user doesn't want to check them, or | ||
| 1698 | ;; they can't be checked (for instance, if the news server can't | ||
| 1699 | ;; be reached) we just set the number of unread articles in this | ||
| 1700 | ;; newsgroup to t. This means that Gnus thinks that there are | ||
| 1701 | ;; unread articles, but it has no idea how many. | ||
| 1702 | |||
| 1703 | ;; To be more explicit: | ||
| 1704 | ;; >0 for an active group with messages | ||
| 1705 | ;; 0 for an active group with no unread messages | ||
| 1706 | ;; nil for non-foreign groups that the user has requested not be checked | ||
| 1707 | ;; t for unchecked foreign groups or bogus groups, or groups that can't | ||
| 1708 | ;; be checked, for one reason or other. | ||
| 1709 | |||
| 1710 | ;; First go through all the groups, see what select methods they | 1697 | ;; First go through all the groups, see what select methods they |
| 1711 | ;; belong to, and then collect them into lists per unique select | 1698 | ;; belong to, and then collect them into lists per unique select |
| 1712 | ;; method. | 1699 | ;; method. |
| 1713 | (if (not (setq method (gnus-info-method info))) | 1700 | (if (not (setq method (gnus-info-method info))) |
| 1714 | (setq method gnus-select-method) | 1701 | (setq method gnus-select-method) |
| 1702 | ;; There may be several similar methods. Possibly extend the | ||
| 1703 | ;; method. | ||
| 1715 | (if (setq cmethod (assoc method methods-cache)) | 1704 | (if (setq cmethod (assoc method methods-cache)) |
| 1716 | (setq method (cdr cmethod)) | 1705 | (setq method (cdr cmethod)) |
| 1717 | (setq cmethod (inline (gnus-server-get-method nil method))) | 1706 | (setq cmethod (if (stringp method) |
| 1707 | (gnus-server-to-method method) | ||
| 1708 | (inline (gnus-find-method-for-group | ||
| 1709 | (gnus-info-group info) info)))) | ||
| 1718 | (push (cons method cmethod) methods-cache) | 1710 | (push (cons method cmethod) methods-cache) |
| 1719 | (setq method cmethod))) | 1711 | (setq method cmethod))) |
| 1720 | (setq method-group-list (assoc method type-cache)) | 1712 | (setq method-group-list (assoc method type-cache)) |
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el index d0c50c8fec0..5997339a335 100644 --- a/lisp/gnus/gnus-sum.el +++ b/lisp/gnus/gnus-sum.el | |||
| @@ -5850,6 +5850,10 @@ If SELECT-ARTICLES, only select those articles from GROUP." | |||
| 5850 | (types gnus-article-mark-lists) | 5850 | (types gnus-article-mark-lists) |
| 5851 | marks var articles article mark mark-type | 5851 | marks var articles article mark mark-type |
| 5852 | bgn end) | 5852 | bgn end) |
| 5853 | ;; Hack to avoid adjusting marks for imap. | ||
| 5854 | (when (eq (car (gnus-find-method-for-group (gnus-info-group info))) | ||
| 5855 | 'nnimap) | ||
| 5856 | (setq min 1)) | ||
| 5853 | 5857 | ||
| 5854 | (dolist (marks marked-lists) | 5858 | (dolist (marks marked-lists) |
| 5855 | (setq mark (car marks) | 5859 | (setq mark (car marks) |
| @@ -9681,7 +9685,7 @@ ACTION can be either `move' (the default), `crosspost' or `copy'." | |||
| 9681 | gnus-newsgroup-name)) | 9685 | gnus-newsgroup-name)) |
| 9682 | (to-method (or select-method | 9686 | (to-method (or select-method |
| 9683 | (gnus-find-method-for-group to-newsgroup))) | 9687 | (gnus-find-method-for-group to-newsgroup))) |
| 9684 | (move-is-internal (gnus-method-equal from-method to-method))) | 9688 | (move-is-internal (gnus-server-equal from-method to-method))) |
| 9685 | (gnus-request-move-article | 9689 | (gnus-request-move-article |
| 9686 | article ; Article to move | 9690 | article ; Article to move |
| 9687 | gnus-newsgroup-name ; From newsgroup | 9691 | gnus-newsgroup-name ; From newsgroup |
| @@ -9692,7 +9696,8 @@ ACTION can be either `move' (the default), `crosspost' or `copy'." | |||
| 9692 | (not articles) t) ; Accept form | 9696 | (not articles) t) ; Accept form |
| 9693 | (not articles) ; Only save nov last time | 9697 | (not articles) ; Only save nov last time |
| 9694 | (and move-is-internal | 9698 | (and move-is-internal |
| 9695 | (gnus-group-real-name to-newsgroup))))) ; is this move internal? | 9699 | to-newsgroup ; Not respooling |
| 9700 | (gnus-group-real-name to-newsgroup))))) ; Is this move internal? | ||
| 9696 | ;; Copy the article. | 9701 | ;; Copy the article. |
| 9697 | ((eq action 'copy) | 9702 | ((eq action 'copy) |
| 9698 | (with-current-buffer copy-buf | 9703 | (with-current-buffer copy-buf |
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el index 68f7f5f5e1a..3f18858fc64 100644 --- a/lisp/gnus/gnus.el +++ b/lisp/gnus/gnus.el | |||
| @@ -2682,6 +2682,7 @@ a string, be sure to use a valid format, see RFC 2616." | |||
| 2682 | (defvar gnus-newsgroup-name nil) | 2682 | (defvar gnus-newsgroup-name nil) |
| 2683 | (defvar gnus-ephemeral-servers nil) | 2683 | (defvar gnus-ephemeral-servers nil) |
| 2684 | (defvar gnus-server-method-cache nil) | 2684 | (defvar gnus-server-method-cache nil) |
| 2685 | (defvar gnus-extended-servers nil) | ||
| 2685 | 2686 | ||
| 2686 | (defvar gnus-agent-fetching nil | 2687 | (defvar gnus-agent-fetching nil |
| 2687 | "Whether Gnus agent is in fetching mode.") | 2688 | "Whether Gnus agent is in fetching mode.") |
| @@ -3686,32 +3687,35 @@ that that variable is buffer-local to the summary buffers." | |||
| 3686 | (and | 3687 | (and |
| 3687 | (eq (car m1) (car m2)) | 3688 | (eq (car m1) (car m2)) |
| 3688 | (equal (cadr m1) (cadr m2)) | 3689 | (equal (cadr m1) (cadr m2)) |
| 3689 | ;; Check parameters for sloppy equalness. | 3690 | (gnus-sloppily-equal-method-parameters m1 m2)))) |
| 3690 | (let ((p1 (copy-list (cddr m1))) | 3691 | |
| 3691 | (p2 (copy-list (cddr m2))) | 3692 | (defsubst gnus-sloppily-equal-method-parameters (m1 m2) |
| 3692 | e1 e2) | 3693 | ;; Check parameters for sloppy equalness. |
| 3693 | (block nil | 3694 | (let ((p1 (copy-list (cddr m1))) |
| 3694 | (while (setq e1 (pop p1)) | 3695 | (p2 (copy-list (cddr m2))) |
| 3695 | (unless (setq e2 (assq (car e1) p2)) | 3696 | e1 e2) |
| 3696 | ;; The parameter doesn't exist in p2. | 3697 | (block nil |
| 3697 | (return nil)) | 3698 | (while (setq e1 (pop p1)) |
| 3698 | (setq p2 (delq e2 p2)) | 3699 | (unless (setq e2 (assq (car e1) p2)) |
| 3699 | (unless (equalp e1 e2) | 3700 | ;; The parameter doesn't exist in p2. |
| 3700 | (if (not (and (stringp (cadr e1)) | 3701 | (return nil)) |
| 3701 | (stringp (cadr e2)))) | 3702 | (setq p2 (delq e2 p2)) |
| 3702 | (return nil) | 3703 | (unless (equalp e1 e2) |
| 3703 | ;; Special-case string parameter comparison so that we | 3704 | (if (not (and (stringp (cadr e1)) |
| 3704 | ;; can uniquify them. | 3705 | (stringp (cadr e2)))) |
| 3705 | (let ((s1 (cadr e1)) | 3706 | (return nil) |
| 3706 | (s2 (cadr e2))) | 3707 | ;; Special-case string parameter comparison so that we |
| 3707 | (when (string-match "/$" s1) | 3708 | ;; can uniquify them. |
| 3708 | (setq s1 (directory-file-name s1))) | 3709 | (let ((s1 (cadr e1)) |
| 3709 | (when (string-match "/$" s2) | 3710 | (s2 (cadr e2))) |
| 3710 | (setq s2 (directory-file-name s2))) | 3711 | (when (string-match "/$" s1) |
| 3711 | (unless (equal s1 s2) | 3712 | (setq s1 (directory-file-name s1))) |
| 3712 | (return nil)))))) | 3713 | (when (string-match "/$" s2) |
| 3713 | ;; If p2 now is empty, they were equal. | 3714 | (setq s2 (directory-file-name s2))) |
| 3714 | (null p2)))))) | 3715 | (unless (equal s1 s2) |
| 3716 | (return nil)))))) | ||
| 3717 | ;; If p2 now is empty, they were equal. | ||
| 3718 | (null p2)))) | ||
| 3715 | 3719 | ||
| 3716 | (defun gnus-server-equal (m1 m2) | 3720 | (defun gnus-server-equal (m1 m2) |
| 3717 | "Say whether two methods are equal." | 3721 | "Say whether two methods are equal." |
| @@ -4200,9 +4204,12 @@ parameters." | |||
| 4200 | (if (or (not (inline (gnus-similar-server-opened method))) | 4204 | (if (or (not (inline (gnus-similar-server-opened method))) |
| 4201 | (not (cddr method))) | 4205 | (not (cddr method))) |
| 4202 | method | 4206 | method |
| 4203 | `(,(car method) ,(concat (cadr method) "+" group) | 4207 | (setq method |
| 4204 | (,(intern (format "%s-address" (car method))) ,(cadr method)) | 4208 | `(,(car method) ,(concat (cadr method) "+" group) |
| 4205 | ,@(cddr method)))) | 4209 | (,(intern (format "%s-address" (car method))) ,(cadr method)) |
| 4210 | ,@(cddr method))) | ||
| 4211 | (push method gnus-extended-servers) | ||
| 4212 | method)) | ||
| 4206 | 4213 | ||
| 4207 | (defun gnus-server-status (method) | 4214 | (defun gnus-server-status (method) |
| 4208 | "Return the status of METHOD." | 4215 | "Return the status of METHOD." |
| @@ -4227,6 +4234,20 @@ parameters." | |||
| 4227 | (format "%s using %s" address (car server)) | 4234 | (format "%s using %s" address (car server)) |
| 4228 | (format "%s" (car server))))) | 4235 | (format "%s" (car server))))) |
| 4229 | 4236 | ||
| 4237 | (defun gnus-same-method-different-name (method) | ||
| 4238 | (let ((slot (intern (concat (symbol-name (car method)) "-address")))) | ||
| 4239 | (unless (assq slot (cddr method)) | ||
| 4240 | (setq method | ||
| 4241 | (append method (list (list slot (nth 1 method))))))) | ||
| 4242 | (let ((methods gnus-extended-servers) | ||
| 4243 | open found) | ||
| 4244 | (while (and (not found) | ||
| 4245 | (setq open (pop methods))) | ||
| 4246 | (when (and (eq (car method) (car open)) | ||
| 4247 | (gnus-sloppily-equal-method-parameters method open)) | ||
| 4248 | (setq found open))) | ||
| 4249 | found)) | ||
| 4250 | |||
| 4230 | (defun gnus-find-method-for-group (group &optional info) | 4251 | (defun gnus-find-method-for-group (group &optional info) |
| 4231 | "Find the select method that GROUP uses." | 4252 | "Find the select method that GROUP uses." |
| 4232 | (or gnus-override-method | 4253 | (or gnus-override-method |
| @@ -4249,7 +4270,10 @@ parameters." | |||
| 4249 | (cond ((stringp method) | 4270 | (cond ((stringp method) |
| 4250 | (inline (gnus-server-to-method method))) | 4271 | (inline (gnus-server-to-method method))) |
| 4251 | ((stringp (cadr method)) | 4272 | ((stringp (cadr method)) |
| 4252 | (inline (gnus-server-extend-method group method))) | 4273 | (or |
| 4274 | (inline | ||
| 4275 | (gnus-same-method-different-name method)) | ||
| 4276 | (inline (gnus-server-extend-method group method)))) | ||
| 4253 | (t | 4277 | (t |
| 4254 | method))) | 4278 | method))) |
| 4255 | (cond ((equal (cadr method) "") | 4279 | (cond ((equal (cadr method) "") |
diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el index 434ad01bc19..e43cd2d8afb 100644 --- a/lisp/gnus/nnimap.el +++ b/lisp/gnus/nnimap.el | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | (require 'gnus) | 37 | (require 'gnus) |
| 38 | (require 'nnoo) | 38 | (require 'nnoo) |
| 39 | (require 'netrc) | 39 | (require 'netrc) |
| 40 | (require 'parse-time) | ||
| 40 | 41 | ||
| 41 | (nnoo-declare nnimap) | 42 | (nnoo-declare nnimap) |
| 42 | 43 | ||
| @@ -77,6 +78,8 @@ will fetch all parts that have types that match that string. A | |||
| 77 | likely value would be \"text/\" to automatically fetch all | 78 | likely value would be \"text/\" to automatically fetch all |
| 78 | textual parts.") | 79 | textual parts.") |
| 79 | 80 | ||
| 81 | (defvoo nnimap-expunge nil) | ||
| 82 | |||
| 80 | (defvoo nnimap-connection-alist nil) | 83 | (defvoo nnimap-connection-alist nil) |
| 81 | 84 | ||
| 82 | (defvoo nnimap-current-infos nil) | 85 | (defvoo nnimap-current-infos nil) |
| @@ -405,7 +408,7 @@ textual parts.") | |||
| 405 | (with-current-buffer (nnimap-buffer) | 408 | (with-current-buffer (nnimap-buffer) |
| 406 | (erase-buffer) | 409 | (erase-buffer) |
| 407 | (let ((group-sequence | 410 | (let ((group-sequence |
| 408 | (nnimap-send-command "SELECT %S" (utf7-encode group))) | 411 | (nnimap-send-command "SELECT %S" (utf7-encode group t))) |
| 409 | (flag-sequence | 412 | (flag-sequence |
| 410 | (nnimap-send-command "UID FETCH 1:* FLAGS"))) | 413 | (nnimap-send-command "UID FETCH 1:* FLAGS"))) |
| 411 | (nnimap-wait-for-response flag-sequence) | 414 | (nnimap-wait-for-response flag-sequence) |
| @@ -421,20 +424,28 @@ textual parts.") | |||
| 421 | (setq high (nth 3 (car marks)) | 424 | (setq high (nth 3 (car marks)) |
| 422 | low (nth 4 (car marks)))) | 425 | low (nth 4 (car marks)))) |
| 423 | ((re-search-backward "UIDNEXT \\([0-9]+\\)" nil t) | 426 | ((re-search-backward "UIDNEXT \\([0-9]+\\)" nil t) |
| 424 | (setq high (string-to-number (match-string 1)) | 427 | (setq high (1- (string-to-number (match-string 1))) |
| 425 | low 1))))) | 428 | low 1))))) |
| 426 | (erase-buffer) | 429 | (erase-buffer) |
| 427 | (insert | 430 | (insert |
| 428 | (format | 431 | (format |
| 429 | "211 %d %d %d %S\n" | 432 | "211 %d %d %d %S\n" (1+ (- high low)) low high group))) |
| 430 | (1+ (- high low)) | 433 | t)))) |
| 431 | low high group)))) | 434 | |
| 432 | t))) | 435 | (deffoo nnimap-request-create-group (group &optional server args) |
| 436 | (when (nnimap-possibly-change-group nil server) | ||
| 437 | (with-current-buffer (nnimap-buffer) | ||
| 438 | (car (nnimap-command "CREATE %S" (utf7-encode group t)))))) | ||
| 433 | 439 | ||
| 434 | (deffoo nnimap-request-delete-group (group &optional force server) | 440 | (deffoo nnimap-request-delete-group (group &optional force server) |
| 435 | (when (nnimap-possibly-change-group nil server) | 441 | (when (nnimap-possibly-change-group nil server) |
| 436 | (with-current-buffer (nnimap-buffer) | 442 | (with-current-buffer (nnimap-buffer) |
| 437 | (car (nnimap-command "DELETE %S" (utf7-encode group)))))) | 443 | (car (nnimap-command "DELETE %S" (utf7-encode group t)))))) |
| 444 | |||
| 445 | (deffoo nnimap-request-expunge-group (group &optional server) | ||
| 446 | (when (nnimap-possibly-change-group group server) | ||
| 447 | (with-current-buffer (nnimap-buffer) | ||
| 448 | (car (nnimap-command "EXPUNGE"))))) | ||
| 438 | 449 | ||
| 439 | (defun nnimap-get-flags (spec) | 450 | (defun nnimap-get-flags (spec) |
| 440 | (let ((articles nil) | 451 | (let ((articles nil) |
| @@ -456,38 +467,95 @@ textual parts.") | |||
| 456 | 467 | ||
| 457 | (deffoo nnimap-request-move-article (article group server accept-form | 468 | (deffoo nnimap-request-move-article (article group server accept-form |
| 458 | &optional last internal-move-group) | 469 | &optional last internal-move-group) |
| 459 | (when (nnimap-possibly-change-group group server) | 470 | (with-temp-buffer |
| 460 | ;; If the move is internal (on the same server), just do it the easy | 471 | (when (nnimap-request-article article group server (current-buffer)) |
| 461 | ;; way. | 472 | ;; If the move is internal (on the same server), just do it the easy |
| 462 | (let ((message-id (message-field-value "message-id"))) | 473 | ;; way. |
| 463 | (if internal-move-group | 474 | (let ((message-id (message-field-value "message-id"))) |
| 464 | (let ((result | 475 | (if internal-move-group |
| 465 | (with-current-buffer (nnimap-buffer) | 476 | (let ((result |
| 466 | (nnimap-command "UID COPY %d %S" | 477 | (with-current-buffer (nnimap-buffer) |
| 467 | article | 478 | (nnimap-command "UID COPY %d %S" |
| 468 | (utf7-encode internal-move-group t))))) | 479 | article |
| 469 | (when (car result) | 480 | (utf7-encode internal-move-group t))))) |
| 470 | (nnimap-delete-article article) | 481 | (when (car result) |
| 471 | (cons internal-move-group | ||
| 472 | (nnimap-find-article-by-message-id | ||
| 473 | internal-move-group message-id)))) | ||
| 474 | (with-temp-buffer | ||
| 475 | (when (nnimap-request-article article group server (current-buffer)) | ||
| 476 | (let ((result (eval accept-form))) | ||
| 477 | (when result | ||
| 478 | (nnimap-delete-article article) | 482 | (nnimap-delete-article article) |
| 479 | result)))))))) | 483 | (cons internal-move-group |
| 484 | (nnimap-find-article-by-message-id | ||
| 485 | internal-move-group message-id)))) | ||
| 486 | ;; Move the article to a different method. | ||
| 487 | (let ((result (eval accept-form))) | ||
| 488 | (when result | ||
| 489 | (nnimap-delete-article article) | ||
| 490 | result))))))) | ||
| 480 | 491 | ||
| 481 | (deffoo nnimap-request-expire-articles (articles group &optional server force) | 492 | (deffoo nnimap-request-expire-articles (articles group &optional server force) |
| 482 | (cond | 493 | (cond |
| 494 | ((null articles) | ||
| 495 | nil) | ||
| 483 | ((not (nnimap-possibly-change-group group server)) | 496 | ((not (nnimap-possibly-change-group group server)) |
| 484 | articles) | 497 | articles) |
| 485 | (force | 498 | ((and force |
| 499 | (eq nnmail-expiry-target 'delete)) | ||
| 486 | (unless (nnimap-delete-article articles) | 500 | (unless (nnimap-delete-article articles) |
| 487 | (message "Article marked for deletion, but not expunged.")) | 501 | (message "Article marked for deletion, but not expunged.")) |
| 488 | nil) | 502 | nil) |
| 489 | (t | 503 | (t |
| 490 | articles))) | 504 | (let ((deletable-articles |
| 505 | (if force | ||
| 506 | articles | ||
| 507 | (gnus-sorted-intersection | ||
| 508 | articles | ||
| 509 | (nnimap-find-expired-articles group))))) | ||
| 510 | (if (null deletable-articles) | ||
| 511 | articles | ||
| 512 | (if (eq nnmail-expiry-target 'delete) | ||
| 513 | (nnimap-delete-article deletable-articles) | ||
| 514 | (setq deletable-articles | ||
| 515 | (nnimap-process-expiry-targets | ||
| 516 | deletable-articles group server))) | ||
| 517 | ;; Return the articles we didn't delete. | ||
| 518 | (gnus-sorted-complement articles deletable-articles)))))) | ||
| 519 | |||
| 520 | (defun nnimap-process-expiry-targets (articles group server) | ||
| 521 | (let ((deleted-articles nil)) | ||
| 522 | (dolist (article articles) | ||
| 523 | (let ((target nnmail-expiry-target)) | ||
| 524 | (with-temp-buffer | ||
| 525 | (when (nnimap-request-article article group server (current-buffer)) | ||
| 526 | (message "Expiring article %s:%d" group article) | ||
| 527 | (when (functionp target) | ||
| 528 | (setq target (funcall target group))) | ||
| 529 | (when (and target | ||
| 530 | (not (eq target 'delete))) | ||
| 531 | (if (or (gnus-request-group target t) | ||
| 532 | (gnus-request-create-group target)) | ||
| 533 | (nnmail-expiry-target-group target group) | ||
| 534 | (setq target nil))) | ||
| 535 | (when target | ||
| 536 | (push article deleted-articles)))))) | ||
| 537 | ;; Change back to the current group again. | ||
| 538 | (nnimap-possibly-change-group group server) | ||
| 539 | (setq deleted-articles (nreverse deleted-articles)) | ||
| 540 | (nnimap-delete-article deleted-articles) | ||
| 541 | deleted-articles)) | ||
| 542 | |||
| 543 | (defun nnimap-find-expired-articles (group) | ||
| 544 | (let ((cutoff (nnmail-expired-article-p group nil nil))) | ||
| 545 | (with-current-buffer (nnimap-buffer) | ||
| 546 | (let ((result | ||
| 547 | (nnimap-command | ||
| 548 | "UID SEARCH SENTBEFORE %s" | ||
| 549 | (format-time-string | ||
| 550 | (format "%%d-%s-%%Y" | ||
| 551 | (upcase | ||
| 552 | (car (rassoc (nth 4 (decode-time cutoff)) | ||
| 553 | parse-time-months)))) | ||
| 554 | cutoff)))) | ||
| 555 | (and (car result) | ||
| 556 | (delete 0 (mapcar #'string-to-number | ||
| 557 | (cdr (assoc "SEARCH" (cdr result)))))))))) | ||
| 558 | |||
| 491 | 559 | ||
| 492 | (defun nnimap-find-article-by-message-id (group message-id) | 560 | (defun nnimap-find-article-by-message-id (group message-id) |
| 493 | (when (nnimap-possibly-change-group group nil) | 561 | (when (nnimap-possibly-change-group group nil) |
| @@ -505,10 +573,14 @@ textual parts.") | |||
| 505 | (with-current-buffer (nnimap-buffer) | 573 | (with-current-buffer (nnimap-buffer) |
| 506 | (nnimap-command "UID STORE %s +FLAGS.SILENT (\\Deleted)" | 574 | (nnimap-command "UID STORE %s +FLAGS.SILENT (\\Deleted)" |
| 507 | (nnimap-article-ranges articles)) | 575 | (nnimap-article-ranges articles)) |
| 508 | (when (member "UIDPLUS" (nnimap-capabilities nnimap-object)) | 576 | (cond |
| 509 | (nnimap-send-command "UID EXPUNGE %s" | 577 | ((member "UIDPLUS" (nnimap-capabilities nnimap-object)) |
| 510 | (nnimap-article-ranges articles)) | 578 | (nnimap-command "UID EXPUNGE %s" |
| 511 | t))) | 579 | (nnimap-article-ranges articles)) |
| 580 | t) | ||
| 581 | (nnimap-expunge | ||
| 582 | (nnimap-command "EXPUNGE") | ||
| 583 | t)))) | ||
| 512 | 584 | ||
| 513 | (deffoo nnimap-request-scan (&optional group server) | 585 | (deffoo nnimap-request-scan (&optional group server) |
| 514 | (when (and (nnimap-possibly-change-group nil server) | 586 | (when (and (nnimap-possibly-change-group nil server) |
| @@ -1040,17 +1112,19 @@ textual parts.") | |||
| 1040 | (defun nnimap-mark-and-expunge-incoming (range) | 1112 | (defun nnimap-mark-and-expunge-incoming (range) |
| 1041 | (when range | 1113 | (when range |
| 1042 | (setq range (nnimap-article-ranges range)) | 1114 | (setq range (nnimap-article-ranges range)) |
| 1043 | (nnimap-send-command | 1115 | (let ((sequence |
| 1044 | "UID STORE %s +FLAGS.SILENT (\\Deleted)" range) | 1116 | (nnimap-send-command |
| 1045 | (cond | 1117 | "UID STORE %s +FLAGS.SILENT (\\Deleted)" range))) |
| 1046 | ;; If the server supports it, we now delete the message we have | 1118 | (cond |
| 1047 | ;; just copied over. | 1119 | ;; If the server supports it, we now delete the message we have |
| 1048 | ((member "UIDPLUS" (nnimap-capabilities nnimap-object)) | 1120 | ;; just copied over. |
| 1049 | (nnimap-send-command "UID EXPUNGE %s" range)) | 1121 | ((member "UIDPLUS" (nnimap-capabilities nnimap-object)) |
| 1050 | ;; If it doesn't support UID EXPUNGE, then we only expunge if the | 1122 | (setq sequence (nnimap-send-command "UID EXPUNGE %s" range))) |
| 1051 | ;; user has configured it. | 1123 | ;; If it doesn't support UID EXPUNGE, then we only expunge if the |
| 1052 | (nnimap-expunge-inbox | 1124 | ;; user has configured it. |
| 1053 | (nnimap-send-command "EXPUNGE"))))) | 1125 | (nnimap-expunge-inbox |
| 1126 | (setq sequence (nnimap-send-command "EXPUNGE")))) | ||
| 1127 | (nnimap-wait-for-response sequence)))) | ||
| 1054 | 1128 | ||
| 1055 | (defun nnimap-parse-copied-articles (sequences) | 1129 | (defun nnimap-parse-copied-articles (sequences) |
| 1056 | (let (sequence copied range) | 1130 | (let (sequence copied range) |
diff --git a/lisp/gnus/nnmail.el b/lisp/gnus/nnmail.el index 3e6cee82521..95a98352f00 100644 --- a/lisp/gnus/nnmail.el +++ b/lisp/gnus/nnmail.el | |||
| @@ -1858,9 +1858,12 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details." | |||
| 1858 | (run-hooks 'nnmail-post-get-new-mail-hook)))) | 1858 | (run-hooks 'nnmail-post-get-new-mail-hook)))) |
| 1859 | 1859 | ||
| 1860 | (defun nnmail-expired-article-p (group time force &optional inhibit) | 1860 | (defun nnmail-expired-article-p (group time force &optional inhibit) |
| 1861 | "Say whether an article that is TIME old in GROUP should be expired." | 1861 | "Say whether an article that is TIME old in GROUP should be expired. |
| 1862 | If TIME is nil, then return the cutoff time for oldness instead." | ||
| 1862 | (if force | 1863 | (if force |
| 1863 | t | 1864 | (if (null time) |
| 1865 | (current-time) | ||
| 1866 | t) | ||
| 1864 | (let ((days (or (and nnmail-expiry-wait-function | 1867 | (let ((days (or (and nnmail-expiry-wait-function |
| 1865 | (funcall nnmail-expiry-wait-function group)) | 1868 | (funcall nnmail-expiry-wait-function group)) |
| 1866 | nnmail-expiry-wait))) | 1869 | nnmail-expiry-wait))) |
| @@ -1871,14 +1874,18 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details." | |||
| 1871 | nil) | 1874 | nil) |
| 1872 | ((eq days 'immediate) | 1875 | ((eq days 'immediate) |
| 1873 | ;; We expire all articles on sight. | 1876 | ;; We expire all articles on sight. |
| 1874 | t) | 1877 | (if (null time) |
| 1878 | (current-time) | ||
| 1879 | t)) | ||
| 1875 | ((equal time '(0 0)) | 1880 | ((equal time '(0 0)) |
| 1876 | ;; This is an ange-ftp group, and we don't have any dates. | 1881 | ;; This is an ange-ftp group, and we don't have any dates. |
| 1877 | nil) | 1882 | nil) |
| 1878 | ((numberp days) | 1883 | ((numberp days) |
| 1879 | (setq days (days-to-time days)) | 1884 | (setq days (days-to-time days)) |
| 1880 | ;; Compare the time with the current time. | 1885 | ;; Compare the time with the current time. |
| 1881 | (ignore-errors (time-less-p days (time-since time)))))))) | 1886 | (if (null time) |
| 1887 | (time-subtract (current-time) days) | ||
| 1888 | (ignore-errors (time-less-p days (time-since time))))))))) | ||
| 1882 | 1889 | ||
| 1883 | (declare-function gnus-group-mark-article-read "gnus-group" (group article)) | 1890 | (declare-function gnus-group-mark-article-read "gnus-group" (group article)) |
| 1884 | 1891 | ||
diff --git a/lisp/gnus/nnml.el b/lisp/gnus/nnml.el index 11cdfd768c3..d05485b32f3 100644 --- a/lisp/gnus/nnml.el +++ b/lisp/gnus/nnml.el | |||
| @@ -942,22 +942,23 @@ Unless no-active is non-nil, update the active file too." | |||
| 942 | (when (file-exists-p nov) | 942 | (when (file-exists-p nov) |
| 943 | (funcall nnmail-delete-file-function nov)) | 943 | (funcall nnmail-delete-file-function nov)) |
| 944 | (dolist (file files) | 944 | (dolist (file files) |
| 945 | (unless (file-directory-p (setq file (concat dir (cdr file)))) | 945 | (let ((path (concat dir (cdr file)))) |
| 946 | (erase-buffer) | 946 | (unless (file-directory-p path) |
| 947 | (nnheader-insert-file-contents file) | 947 | (erase-buffer) |
| 948 | (narrow-to-region | 948 | (nnheader-insert-file-contents path) |
| 949 | (goto-char (point-min)) | 949 | (narrow-to-region |
| 950 | (progn | 950 | (goto-char (point-min)) |
| 951 | (re-search-forward "\n\r?\n" nil t) | 951 | (progn |
| 952 | (setq chars (- (point-max) (point))) | 952 | (re-search-forward "\n\r?\n" nil t) |
| 953 | (max (point-min) (1- (point))))) | 953 | (setq chars (- (point-max) (point))) |
| 954 | (unless (zerop (buffer-size)) | 954 | (max (point-min) (1- (point))))) |
| 955 | (goto-char (point-min)) | 955 | (unless (zerop (buffer-size)) |
| 956 | (setq headers (nnml-parse-head chars (car file))) | 956 | (goto-char (point-min)) |
| 957 | (with-current-buffer nov-buffer | 957 | (setq headers (nnml-parse-head chars (car file))) |
| 958 | (goto-char (point-max)) | 958 | (with-current-buffer nov-buffer |
| 959 | (nnheader-insert-nov headers))) | 959 | (goto-char (point-max)) |
| 960 | (widen))) | 960 | (nnheader-insert-nov headers))) |
| 961 | (widen)))) | ||
| 961 | (with-current-buffer nov-buffer | 962 | (with-current-buffer nov-buffer |
| 962 | (nnmail-write-region (point-min) (point-max) nov nil 'nomesg) | 963 | (nnmail-write-region (point-min) (point-max) nov nil 'nomesg) |
| 963 | (kill-buffer (current-buffer)))))) | 964 | (kill-buffer (current-buffer)))))) |