Revision: miles@gnu.org--gnu-2004/gnus--devo--0--patch-21
[gnus] / lisp / gnus-int.el
index da22bb5..fca55d9 100644 (file)
@@ -1,5 +1,5 @@
 ;;; gnus-int.el --- backend interface functions for Gnus
-;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
 ;;        Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 (eval-when-compile (require 'cl))
 
 (require 'gnus)
+(require 'message)
+(require 'gnus-range)
+
+(autoload 'gnus-agent-expire "gnus-agent")
+(autoload 'gnus-agent-regenerate-group "gnus-agent")
+(autoload 'gnus-agent-read-servers-validate-native "gnus-agent")
 
 (defcustom gnus-open-server-hook nil
   "Hook called just before opening connection to the news server."
   "The default status if the server is not able to open.
 If the server is covered by Gnus agent, the possible values are
 `denied', set the server denied; `offline', set the server offline;
-`nil', ask user.  If the server is not covered by Gnus agent, set the
+nil, ask user.  If the server is not covered by Gnus agent, set the
 server denied."
   :group 'gnus-start
   :type '(choice (const :tag "Ask" nil)
                 (const :tag "Deny server" denied)
-                (const :tag "Unplugg Agent" offline)))
+                (const :tag "Unplug Agent" offline)))
+
+(defvar gnus-internal-registry-spool-current-method nil
+  "The current method, for the registry.")
 
 ;;;
 ;;; Server Communication
@@ -64,7 +73,7 @@ If CONFIRM is non-nil, the user will be asked for an NNTP server."
        ;; Read server name with completion.
        (setq gnus-nntp-server
              (completing-read "NNTP server: "
-                              (mapcar (lambda (server) (list server))
+                              (mapcar 'list
                                       (cons (list gnus-nntp-server)
                                             gnus-secondary-servers))
                               nil nil gnus-nntp-server)))
@@ -98,6 +107,18 @@ If CONFIRM is non-nil, the user will be asked for an NNTP server."
        (require 'nntp)))
       (setq gnus-current-select-method gnus-select-method)
       (gnus-run-hooks 'gnus-open-server-hook)
+
+      ;; Partially validate agent covered methods now that the
+      ;; gnus-select-method is known.
+
+      (if gnus-agent
+          ;; NOTE: This is here for one purpose only.  By validating
+          ;; the current select method, it converts the old 5.10.3,
+          ;; and earlier, format to the current format.  That enables
+          ;; the agent code within gnus-open-server to function
+          ;; correctly.
+          (gnus-agent-read-servers-validate-native gnus-select-method))
+
       (or
        ;; gnus-open-server-hook might have opened it
        (gnus-server-opened gnus-select-method)
@@ -155,7 +176,7 @@ If it is down, start it up (again)."
     (setq method (gnus-server-to-method method)))
   ;; Check cache of constructed names.
   (let* ((method-sym (if gnus-agent
-                        (gnus-agent-get-function method)
+                        (inline (gnus-agent-get-function method))
                       (car method)))
         (method-fns (get method-sym 'gnus-method-functions))
         (func (let ((method-fnlist-elt (assq function method-fns)))
@@ -193,38 +214,66 @@ If it is down, start it up (again)."
          (gnus-message 1 "Denied server")
          nil)
       ;; Open the server.
-      (let ((result
-            (condition-case ()
-                (funcall (gnus-get-function gnus-command-method 'open-server)
-                         (nth 1 gnus-command-method)
-                         (nthcdr 2 gnus-command-method))
-              (quit
-               (message "Quit trying to open server")
-               nil))))
+      (let* ((open-server-function (gnus-get-function gnus-command-method 'open-server))
+             (result
+             (condition-case err
+                 (funcall open-server-function
+                          (nth 1 gnus-command-method)
+                          (nthcdr 2 gnus-command-method))
+               (error
+                (gnus-message 1 (format
+                                 "Unable to open server due to: %s"
+                                 (error-message-string err)))
+                nil)
+               (quit
+                (gnus-message 1 "Quit trying to open server")
+                nil)))
+            open-offline)
        ;; If this hasn't been opened before, we add it to the list.
        (unless elem
          (setq elem (list gnus-command-method nil)
                gnus-opened-servers (cons elem gnus-opened-servers)))
        ;; Set the status of this server.
-       (setcar (cdr elem)
-               (if result
-                   (if (eq (cadr elem) 'offline)
-                       'offline
-                     'ok)
-                 (if (and gnus-agent
-                          (not (eq (cadr elem) 'offline))
-                          (gnus-agent-method-p gnus-command-method))
-                     (or gnus-server-unopen-status
-                         (if (gnus-y-or-n-p
-                              (format "Unable to open %s:%s, go offline? "
-                                      (car gnus-command-method)
-                                      (cadr gnus-command-method)))
-                             'offline
-                           'denied))
-                   'denied)))
-       ;; Return the result from the "open" call.
-       (or (eq (cadr elem) 'offline)
-           result)))))
+        (setcar (cdr elem)
+                (cond (result
+                       (if (eq open-server-function #'nnagent-open-server)
+                           ;; The agent's backend has a "special" status
+                           'offline
+                         'ok))
+                      ((and gnus-agent
+                            (gnus-agent-method-p gnus-command-method))
+                       (cond (gnus-server-unopen-status
+                              ;; Set the server's status to the unopen
+                              ;; status.  If that status is offline,
+                              ;; recurse to open the agent's backend.
+                              (setq open-offline (eq gnus-server-unopen-status 'offline))
+                              gnus-server-unopen-status)
+                             ((gnus-y-or-n-p
+                               (format "Unable to open %s:%s, go offline? "
+                                       (car gnus-command-method)
+                                       (cadr gnus-command-method)))
+                              (setq open-offline t)
+                              'offline)
+                             (t
+                              ;; This agentized server was still denied
+                              'denied)))
+                      (t
+                       ;; This unagentized server must be denied
+                       'denied)))
+
+        ;; NOTE: I MUST set the server's status to offline before this
+        ;; recursive call as this status will drive the
+        ;; gnus-get-function (called above) to return the agent's
+        ;; backend.
+        (if open-offline
+            ;; Recursively open this offline server to perform the
+            ;; open-server function of the agent's backend.
+            (let ((gnus-server-unopen-status 'denied))
+              ;; Bind gnus-server-unopen-status to avoid recursively
+              ;; prompting with "go offline?".  This is only a concern
+              ;; when the agent's backend fails to open the server.
+              (gnus-open-server gnus-command-method))
+          result)))))
 
 (defun gnus-close-server (gnus-command-method)
   "Close the connection to GNUS-COMMAND-METHOD."
@@ -266,8 +315,8 @@ If it is down, start it up (again)."
 
 (defun gnus-status-message (gnus-command-method)
   "Return the status message from GNUS-COMMAND-METHOD.
-If GNUS-COMMAND-METHOD is a string, it is interpreted as a group name.  The method
-this group uses will be queried."
+If GNUS-COMMAND-METHOD is a string, it is interpreted as a group
+name.  The method this group uses will be queried."
   (let ((gnus-command-method
         (if (stringp gnus-command-method)
             (gnus-find-method-for-group gnus-command-method)
@@ -289,7 +338,7 @@ this group uses will be queried."
     (when (stringp gnus-command-method)
       (setq gnus-command-method
            (inline (gnus-server-to-method gnus-command-method))))
-    (funcall (inline (gnus-get-function gnus-command-method 'request-group))
+        (funcall (inline (gnus-get-function gnus-command-method 'request-group))
             (gnus-group-real-name group) (nth 1 gnus-command-method)
             dont-check)))
 
@@ -330,7 +379,7 @@ If FETCH-OLD, retrieve all headers (or some subset thereof) in the group."
     (cond
      ((and gnus-use-cache (numberp (car articles)))
       (gnus-cache-retrieve-headers articles group fetch-old))
-     ((and gnus-agent gnus-agent-cache (gnus-online gnus-command-method)
+     ((and gnus-agent (gnus-online gnus-command-method)
           (gnus-agent-method-p gnus-command-method))
       (gnus-agent-retrieve-headers articles group fetch-old))
      (t
@@ -362,7 +411,7 @@ If FETCH-OLD, retrieve all headers (or some subset thereof) in the group."
               (gnus-group-real-name group) article))))
 
 (defun gnus-request-set-mark (group action)
-  "Set marks on articles in the backend."
+  "Set marks on articles in the back end."
   (let ((gnus-command-method (gnus-find-method-for-group group)))
     (if (not (gnus-check-backend-function
              'request-set-mark (car gnus-command-method)))
@@ -372,7 +421,7 @@ If FETCH-OLD, retrieve all headers (or some subset thereof) in the group."
               (nth 1 gnus-command-method)))))
 
 (defun gnus-request-update-mark (group article mark)
-  "Allow the backend to change the mark the user tries to put on an article."
+  "Allow the back end to change the mark the user tries to put on an article."
   (let ((gnus-command-method (gnus-find-method-for-group group)))
     (if (not (gnus-check-backend-function
              'request-update-mark (car gnus-command-method)))
@@ -402,9 +451,7 @@ If BUFFER, insert the article in that group."
       (setq res (cons group article)
            clean-up t))
      ;; Check the agent cache.
-     ((and gnus-agent gnus-agent-cache gnus-plugged
-          (numberp article)
-          (gnus-agent-request-article article group))
+     ((gnus-agent-request-article article group)
       (setq res (cons group article)
            clean-up t))
      ;; Use `head' function.
@@ -437,9 +484,7 @@ If BUFFER, insert the article in that group."
       (setq res (cons group article)
            clean-up t))
      ;; Check the agent cache.
-     ((and gnus-agent gnus-agent-cache gnus-plugged
-          (numberp article)
-          (gnus-agent-request-article article group))
+     ((gnus-agent-request-article article group)
       (setq res (cons group article)
            clean-up t))
      ;; Use `head' function.
@@ -472,10 +517,11 @@ If GROUP is nil, all groups on GNUS-COMMAND-METHOD are scanned."
         (if group (gnus-find-method-for-group group) gnus-command-method))
        (gnus-inhibit-demon t)
        (mail-source-plugged gnus-plugged))
-    (if (or gnus-plugged (not (gnus-agent-method-p gnus-command-method)))
-       (funcall (gnus-get-function gnus-command-method 'request-scan)
-                (and group (gnus-group-real-name group))
-                (nth 1 gnus-command-method)))))
+    (when (or gnus-plugged (not (gnus-agent-method-p gnus-command-method)))
+      (setq gnus-internal-registry-spool-current-method gnus-command-method)
+      (funcall (gnus-get-function gnus-command-method 'request-scan)
+              (and group (gnus-group-real-name group))
+              (nth 1 gnus-command-method)))))
 
 (defsubst gnus-request-update-info (info gnus-command-method)
   "Request that GNUS-COMMAND-METHOD update INFO."
@@ -502,23 +548,27 @@ If GROUP is nil, all groups on GNUS-COMMAND-METHOD are scanned."
 
 (defun gnus-request-expire-articles (articles group &optional force)
   (let* ((gnus-command-method (gnus-find-method-for-group group))
-        (not-deleted 
-         (funcall 
+        (not-deleted
+         (funcall
           (gnus-get-function gnus-command-method 'request-expire-articles)
           articles (gnus-group-real-name group) (nth 1 gnus-command-method)
           force)))
-    (when (and gnus-agent gnus-agent-cache
-              (gnus-sorted-difference articles not-deleted))
-      (gnus-agent-expire (gnus-sorted-difference articles not-deleted)
-                        group 'force))
+    (when (and gnus-agent
+              (gnus-agent-method-p gnus-command-method))
+      (let ((expired-articles (gnus-sorted-difference articles not-deleted)))
+        (when expired-articles
+          (gnus-agent-expire expired-articles group 'force))))
     not-deleted))
 
-(defun gnus-request-move-article (article group server accept-function &optional last)
+(defun gnus-request-move-article (article group server accept-function
+                                         &optional last)
   (let* ((gnus-command-method (gnus-find-method-for-group group))
-        (result (funcall (gnus-get-function gnus-command-method 'request-move-article)
+        (result (funcall (gnus-get-function gnus-command-method
+                                            'request-move-article)
                          article (gnus-group-real-name group)
                          (nth 1 gnus-command-method) accept-function last)))
-    (when (and result gnus-agent gnus-agent-cache)
+    (when (and result gnus-agent
+              (gnus-agent-method-p gnus-command-method))
       (gnus-agent-expire (list article) group 'force))
     result))
     
@@ -529,7 +579,8 @@ If GROUP is nil, all groups on GNUS-COMMAND-METHOD are scanned."
     (setq gnus-command-method (gnus-server-to-method gnus-command-method)))
   (when (and (not gnus-command-method)
             (stringp group))
-    (setq gnus-command-method (gnus-group-name-to-method group)))
+    (setq gnus-command-method (or (gnus-find-method-for-group group)
+                                  (gnus-group-name-to-method group))))
   (goto-char (point-max))
   (unless (bolp)
     (insert "\n"))
@@ -542,11 +593,16 @@ If GROUP is nil, all groups on GNUS-COMMAND-METHOD are scanned."
          (mail-encode-encoded-word-buffer)))
       (message-encode-message-body)))
   (let ((gnus-command-method (or gnus-command-method
-                                (gnus-find-method-for-group group))))
-    (funcall (gnus-get-function gnus-command-method 'request-accept-article)
-            (if (stringp group) (gnus-group-real-name group) group)
-            (cadr gnus-command-method)
-            last)))
+                                (gnus-find-method-for-group group)))
+       (result 
+        (funcall 
+         (gnus-get-function gnus-command-method 'request-accept-article)
+         (if (stringp group) (gnus-group-real-name group) group)
+         (cadr gnus-command-method)
+         last)))
+    (when (and gnus-agent (gnus-agent-method-p gnus-command-method))
+      (gnus-agent-regenerate-group group (list (cdr result))))
+    result))
 
 (defun gnus-request-replace-article (article group buffer &optional no-encode)
   (unless no-encode
@@ -557,9 +613,12 @@ If GROUP is nil, all groups on GNUS-COMMAND-METHOD are scanned."
        (let ((mail-parse-charset message-default-charset))
          (mail-encode-encoded-word-buffer)))
       (message-encode-message-body)))
-  (let ((func (car (gnus-group-name-to-method group))))
-    (funcall (intern (format "%s-request-replace-article" func))
-            article (gnus-group-real-name group) buffer)))
+  (let* ((func (car (gnus-group-name-to-method group)))
+         (result (funcall (intern (format "%s-request-replace-article" func))
+                         article (gnus-group-real-name group) buffer)))
+    (when (and gnus-agent (gnus-agent-method-p gnus-command-method))
+      (gnus-agent-regenerate-group group (list article)))
+    result))
 
 (defun gnus-request-associate-buffer (group)
   (let ((gnus-command-method (gnus-find-method-for-group group)))
@@ -582,15 +641,25 @@ If GROUP is nil, all groups on GNUS-COMMAND-METHOD are scanned."
             (gnus-group-real-name group) (nth 1 gnus-command-method) args)))
 
 (defun gnus-request-delete-group (group &optional force)
-  (let ((gnus-command-method (gnus-find-method-for-group group)))
-    (funcall (gnus-get-function gnus-command-method 'request-delete-group)
-            (gnus-group-real-name group) force (nth 1 gnus-command-method))))
+  (let* ((gnus-command-method (gnus-find-method-for-group group))
+        (result
+         (funcall (gnus-get-function gnus-command-method 'request-delete-group)
+                  (gnus-group-real-name group) force (nth 1 gnus-command-method))))
+    (when result
+      (gnus-cache-delete-group group)
+      (gnus-agent-delete-group group))
+    result))
 
 (defun gnus-request-rename-group (group new-name)
-  (let ((gnus-command-method (gnus-find-method-for-group group)))
-    (funcall (gnus-get-function gnus-command-method 'request-rename-group)
-            (gnus-group-real-name group)
-            (gnus-group-real-name new-name) (nth 1 gnus-command-method))))
+  (let* ((gnus-command-method (gnus-find-method-for-group group))
+        (result
+         (funcall (gnus-get-function gnus-command-method 'request-rename-group)
+                  (gnus-group-real-name group)
+                  (gnus-group-real-name new-name) (nth 1 gnus-command-method))))
+    (when result
+      (gnus-cache-rename-group group new-name)
+      (gnus-agent-rename-group group new-name))
+    result))
 
 (defun gnus-close-backends ()
   ;; Send a close request to all backends that support such a request.
@@ -620,4 +689,5 @@ If GROUP is nil, all groups on GNUS-COMMAND-METHOD are scanned."
 
 (provide 'gnus-int)
 
+;;; arch-tag: bbc90087-9b7f-4017-a92c-3abf180ac86d
 ;;; gnus-int.el ends here