(gnus-cache-file-name): Do not replace file name character in base path.
[elisp/gnus.git-] / lisp / nnfolder.el
index 3168ac5..c1bbb10 100644 (file)
@@ -119,8 +119,9 @@ If NIL, NNFOLDER-FILE-CODING-SYSTEM is used.")
            (set-buffer nnfolder-current-buffer)
            (when (nnfolder-goto-article article)
              (setq start (point))
-             (search-forward "\n\n" nil t)
-             (setq stop (1- (point)))
+             (setq stop (if (search-forward "\n\n" nil t)
+                            (1- (point))
+                          (point-max)))
              (set-buffer nntp-server-buffer)
              (insert (format "221 %d Article retrieved.\n" article))
              (insert-buffer-substring nnfolder-current-buffer start stop)
@@ -183,11 +184,13 @@ If NIL, NNFOLDER-FILE-CODING-SYSTEM is used.")
          (if (numberp article)
              (cons nnfolder-current-group article)
            (goto-char (point-min))
-           (search-forward (concat "\n" nnfolder-article-marker))
            (cons nnfolder-current-group
-                 (string-to-int
-                  (buffer-substring
-                   (point) (progn (end-of-line) (point)))))))))))
+                 (if (search-forward (concat "\n" nnfolder-article-marker) 
+                                     nil t)
+                     (string-to-int
+                      (buffer-substring
+                       (point) (progn (end-of-line) (point))))
+                   -1))))))))
 
 (deffoo nnfolder-request-group (group &optional server dont-check)
   (nnfolder-possibly-change-group group server t)
@@ -295,39 +298,66 @@ If NIL, NNFOLDER-FILE-CODING-SYSTEM is used.")
     (let ((nnmail-file-coding-system nnfolder-file-coding-system))
       (nnmail-find-file nnfolder-newsgroups-file))))
 
+;; Return a list consisting of all article numbers existing in the
+;; current folder.
+
+(defun nnfolder-existing-articles ()
+  (save-excursion
+    (when nnfolder-current-buffer
+      (set-buffer nnfolder-current-buffer)
+      (goto-char (point-min))
+      (let ((marker (concat "\n" nnfolder-article-marker))
+           (number "[0-9]+")
+           numbers)
+      
+       (while (and (search-forward marker nil t)
+                   (re-search-forward number nil t))
+         (let ((newnum (string-to-number (match-string 0))))
+           (if (nnmail-within-headers-p)
+               (push newnum numbers))))
+       numbers))))
+
 (deffoo nnfolder-request-expire-articles
   (articles newsgroup &optional server force)
   (nnfolder-possibly-change-group newsgroup server)
   (let* ((is-old t)
-        rest)
+        ;; The articles we have deleted so far.
+        (deleted-articles nil)
+        ;; The articles that really exist and will
+        ;; be expired if they are old enough.
+        (maybe-expirable
+         (gnus-intersection articles (nnfolder-existing-articles))))
     (nnmail-activate 'nnfolder)
 
     (save-excursion
       (set-buffer nnfolder-current-buffer)
-      (while (and articles is-old)
+      ;; Since messages are sorted in arrival order and expired in the
+      ;; same order, we can stop as soon as we find a message that is
+      ;; too old.
+      (while (and maybe-expirable is-old)
        (goto-char (point-min))
-       (when (and (nnfolder-goto-article (car articles))
+       (when (and (nnfolder-goto-article (car maybe-expirable))
                   (search-forward (concat "\n" nnfolder-article-marker)
                                   nil t))
          (forward-sexp)
-         (if (setq is-old
+         (when (setq is-old
                    (nnmail-expired-article-p
                     newsgroup
                     (buffer-substring
                      (point) (progn (end-of-line) (point)))
                     force nnfolder-inhibit-expiry))
-             (progn
                (nnheader-message 5 "Deleting article %d..."
-                                 (car articles) newsgroup)
-               (nnfolder-delete-mail))
-           (push (car articles) rest)))
-       (setq articles (cdr articles)))
+                             (car maybe-expirable) newsgroup)
+           (nnfolder-delete-mail)
+           ;; Must remember which articles were actually deleted
+           (push (car maybe-expirable) deleted-articles)))
+       (setq maybe-expirable (cdr maybe-expirable)))
       (unless nnfolder-inhibit-expiry
        (nnheader-message 5 "Deleting articles...done"))
       (nnfolder-save-buffer)
       (nnfolder-adjust-min-active newsgroup)
       (nnfolder-save-active nnfolder-group-alist nnfolder-active-file)
-      (nconc rest articles))))
+      (gnus-sorted-complement articles (nreverse deleted-articles)))))
 
 (deffoo nnfolder-request-move-article (article group server
                                               accept-form &optional last)
@@ -343,7 +373,8 @@ If NIL, NNFOLDER-FILE-CODING-SYSTEM is used.")
         (goto-char (point-min))
         (while (re-search-forward
                 (concat "^" nnfolder-article-marker)
-                (save-excursion (search-forward "\n\n" nil t) (point)) t)
+                (save-excursion (and (search-forward "\n\n" nil t) (point))) 
+                t)
           (delete-region (progn (beginning-of-line) (point))
                          (progn (forward-line 1) (point))))
         (setq result (eval accept-form))
@@ -375,8 +406,9 @@ If NIL, NNFOLDER-FILE-CODING-SYSTEM is used.")
        (save-excursion
         (set-buffer buf)
         (goto-char (point-min))
-        (search-forward "\n\n" nil t)
-        (forward-line -1)
+        (if (search-forward "\n\n" nil t)
+            (forward-line -1)
+          (goto-char (point-max)))
         (while (re-search-backward (concat "^" nnfolder-article-marker) nil t)
           (delete-region (point) (progn (forward-line 1) (point))))
         (when nnmail-cache-accepted-message-ids
@@ -450,7 +482,9 @@ If NIL, NNFOLDER-FILE-CODING-SYSTEM is used.")
         (ignore-errors
           (rename-file
            buffer-file-name
-           (nnfolder-group-pathname new-name))
+           (let ((new-file (nnfolder-group-pathname new-name)))
+             (gnus-make-directory (file-name-directory new-file))
+             new-file))
           t)
         ;; That went ok, so we change the internal structures.
         (let ((entry (assoc group nnfolder-group-alist)))
@@ -620,8 +654,9 @@ deleted.  Point is left where the deleted region was."
     (while (setq group-art (pop group-art-list))
       ;; Kill any previous newsgroup markers.
       (goto-char (point-min))
-      (search-forward "\n\n" nil t)
-      (forward-line -1)
+      (if (search-forward "\n\n" nil t)
+         (forward-line -1)
+       (goto-char (point-max)))
       (while (search-backward (concat "\n" nnfolder-article-marker) nil t)
        (delete-region (1+ (point)) (progn (forward-line 2) (point))))
 
@@ -650,10 +685,12 @@ deleted.  Point is left where the deleted region was."
 (defun nnfolder-insert-newsgroup-line (group-art)
   (save-excursion
     (goto-char (point-min))
-    (when (search-forward "\n\n" nil t)
-      (forward-char -1)
-      (insert (format (concat nnfolder-article-marker "%d   %s\n")
-                     (cdr group-art) (current-time-string))))))
+    (unless (search-forward "\n\n" nil t)
+      (goto-char (point-max))
+      (insert "\n"))
+    (forward-char -1)
+    (insert (format (concat nnfolder-article-marker "%d   %s\n")
+                   (cdr group-art) (current-time-string)))))
 
 (defun nnfolder-active-number (group)
   ;; Find the next article number in GROUP.
@@ -710,6 +747,10 @@ deleted.  Point is left where the deleted region was."
          (save-buffer))
       ;; Parse the damn thing.
       (save-excursion
+       (goto-char (point-min))
+       ;; Remove any blank lines at the start.
+       (while (eq (following-char) ?\n)
+         (delete-char 1))
        (nnmail-activate 'nnfolder)
        ;; Read in the file.
        (let ((delim "^From ")