Remove dead code
[gnus] / lisp / nnimap.el
index 11ebe71..ebd268e 100644 (file)
@@ -123,6 +123,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.2"
+  :group 'nnimap)
+
 (defvar nnimap-process nil)
 
 (defvar nnimap-status-string "")
@@ -173,7 +183,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
@@ -476,6 +486,8 @@ textual parts.")
            (when nnimap-object
              (when (nnimap-capability "QRESYNC")
                (nnimap-command "ENABLE QRESYNC"))
+              (nnheader-message 7 "Opening connection to %s...done"
+                               nnimap-address)
              (nnimap-process nnimap-object))))))))
 
 (autoload 'rfc2104-hash "rfc2104")
@@ -556,10 +568,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)
@@ -588,10 +600,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
@@ -740,7 +752,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)
@@ -790,19 +802,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"
@@ -817,7 +829,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")))))
 
@@ -865,11 +877,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)))))))
 
@@ -878,7 +891,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))
@@ -915,7 +928,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
@@ -945,7 +958,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))
@@ -967,23 +980,31 @@ 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 (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* ((number-of-article
+           (catch 'found
+             (dolist (result (cdr (nnimap-change-group group server nil t)))
+               (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)
@@ -1004,7 +1025,7 @@ 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)
@@ -1023,7 +1044,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")
@@ -1034,7 +1055,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)
@@ -1059,7 +1080,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)
@@ -1091,7 +1112,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)
@@ -1137,7 +1159,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
@@ -1173,54 +1195,41 @@ textual parts.")
     (nreverse groups)))
 
 (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
-            (with-current-buffer (nnimap-buffer)
-              (nnimap-get-groups)))
-           sequences responses)
-       (when groups
-         (with-current-buffer (nnimap-buffer)
-           (setf (nnimap-group nnimap-object) nil)
-           (dolist (group groups)
-             (setf (nnimap-examined nnimap-object) group)
-             (push (list (nnimap-send-command "EXAMINE %S"
-                                              (utf7-encode group t))
-                         group)
-                   sequences))
-           (nnimap-wait-for-response (caar sequences))
-           (setq responses
-                 (nnimap-get-responses (mapcar #'car sequences))))
-         (dolist (response responses)
-           (let* ((sequence (car response))
-                  (response (cadr response))
-                  (group (cadr (assoc sequence sequences)))
-                  (egroup (encode-coding-string group 'utf-8)))
-             (when (and group
-                        (equal (caar response) "OK"))
-               (let ((uidnext (nnimap-find-parameter "UIDNEXT" response))
-                     highest exists)
-                 (dolist (elem response)
-                   (when (equal (cadr elem) "EXISTS")
-                     (setq exists (string-to-number (car elem)))))
-                 (when uidnext
-                   (setq highest (1- (string-to-number (car uidnext)))))
-                 (cond
-                  ((null highest)
-                   (insert (format "%S 0 1 y\n" egroup)))
-                  ((zerop exists)
-                   ;; Empty group.
-                   (insert (format "%S %d %d y\n" egroup
-                                   highest (1+ highest))))
-                  (t
-                   ;; Return the widest possible range.
-                   (insert (format "%S %d 1 y\n" egroup
-                                   (or highest exists)))))))))
-         t)))))
+      (dolist (response
+               (with-current-buffer (nnimap-buffer)
+                 ;; Build a list of (group result-of-EXAMINE) for each group
+                 (mapcar
+                  (lambda (group)
+                    (list group (cdr (nnimap-change-group group server nil t))))
+                  (nnimap-get-groups))))
+        (let ((group (encode-coding-string (car response) 'utf-8))
+              (response (cadr response)))
+          (when (equal (caar response) "OK")
+            (let ((uidnext (nnimap-find-parameter "UIDNEXT" response))
+                highest exists)
+              (dolist (elem response)
+                (when (equal (cadr elem) "EXISTS")
+                  (setq exists (string-to-number (car elem)))))
+              (when uidnext
+                (setq highest (1- (string-to-number (car uidnext)))))
+              (cond
+               ((null highest)
+                (insert (format "%S 0 1 y\n" group)))
+               ((zerop exists)
+                ;; Empty group.
+                (insert (format "%S %d %d y\n" group
+                                highest (1+ highest))))
+               (t
+                ;; Return the widest possible range.
+                (insert (format "%S %d 1 y\n" group
+                                (or highest exists)))))))))
+      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)
@@ -1231,7 +1240,7 @@ 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)
@@ -1297,7 +1306,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)))
@@ -1672,7 +1681,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))))
@@ -1683,7 +1692,11 @@ 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 SERVER is set, check that server is connected, otherwise retry
+to reconnect, unless NO-RECONNECT is set to t.
+if READ-ONLY is set, send EXAMINE rather than SELECT to the server."
   (let ((open-result t))
     (when (and server
               (not (nnimap-server-opened server)))
@@ -1695,13 +1708,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."
@@ -1737,15 +1752,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)
@@ -1884,15 +1908,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)