Importing Oort Gnus v0.02.
[elisp/gnus.git-] / lisp / nnml.el
index 06f016d..004c462 100644 (file)
@@ -1,7 +1,8 @@
 ;;; nnml.el --- mail spool access for Gnus
 ;;; nnml.el --- mail spool access for Gnus
-;; Copyright (C) 1995,96,97 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000
+;;        Free Software Foundation, Inc.
 
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;; Keywords: news, mail
 
 ;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;; Keywords: news, mail
 
   "Spool directory for the nnml mail backend.")
 
 (defvoo nnml-active-file
   "Spool directory for the nnml mail backend.")
 
 (defvoo nnml-active-file
-  (concat (file-name-as-directory nnml-directory) "active")
+    (expand-file-name "active" nnml-directory)
   "Mail active file.")
 
 (defvoo nnml-newsgroups-file
   "Mail active file.")
 
 (defvoo nnml-newsgroups-file
-  (concat (file-name-as-directory nnml-directory) "newsgroups")
+    (expand-file-name "newsgroups" nnml-directory)
   "Mail newsgroups description file.")
 
 (defvoo nnml-get-new-mail t
   "Mail newsgroups description file.")
 
 (defvoo nnml-get-new-mail t
@@ -86,6 +87,8 @@ all.  This may very well take some time.")
 
 (defvar nnml-nov-buffer-file-name nil)
 
 
 (defvar nnml-nov-buffer-file-name nil)
 
+(defvoo nnml-file-coding-system nnmail-file-coding-system)
+
 \f
 
 ;;; Interface functions.
 \f
 
 ;;; Interface functions.
@@ -100,7 +103,7 @@ all.  This may very well take some time.")
       (let ((file nil)
            (number (length sequence))
            (count 0)
       (let ((file nil)
            (number (length sequence))
            (count 0)
-           (pathname-coding-system 'binary)
+           (file-name-coding-system nnmail-pathname-coding-system)
            beg article)
        (if (stringp (car sequence))
            'headers
            beg article)
        (if (stringp (car sequence))
            'headers
@@ -140,9 +143,7 @@ all.  This may very well take some time.")
 (deffoo nnml-open-server (server &optional defs)
   (nnoo-change-server 'nnml server defs)
   (when (not (file-exists-p nnml-directory))
 (deffoo nnml-open-server (server &optional defs)
   (nnoo-change-server 'nnml server defs)
   (when (not (file-exists-p nnml-directory))
-    (condition-case ()
-       (make-directory nnml-directory t)
-      (error)))
+    (ignore-errors (make-directory nnml-directory t)))
   (cond
    ((not (file-exists-p nnml-directory))
     (nnml-close-server)
   (cond
    ((not (file-exists-p nnml-directory))
     (nnml-close-server)
@@ -155,17 +156,15 @@ all.  This may very well take some time.")
                     server nnml-directory)
     t)))
 
                     server nnml-directory)
     t)))
 
-(defun nnml-request-regenerate (server)
+(deffoo nnml-request-regenerate (server)
   (nnml-possibly-change-directory nil server)
   (nnml-possibly-change-directory nil server)
-  (nnml-generate-nov-databases)
+  (nnml-generate-nov-databases server)
   t)
 
 (deffoo nnml-request-article (id &optional group server buffer)
   (nnml-possibly-change-directory group server)
   (let* ((nntp-server-buffer (or buffer nntp-server-buffer))
   t)
 
 (deffoo nnml-request-article (id &optional group server buffer)
   (nnml-possibly-change-directory group server)
   (let* ((nntp-server-buffer (or buffer nntp-server-buffer))
-        ;; 1997/8/12 by MORIOKA Tomohiko
-        ;;     for XEmacs/mule.
-        (pathname-coding-system 'binary)
+        (file-name-coding-system nnmail-pathname-coding-system)
         path gpath group-num)
     (if (stringp id)
        (when (and (setq group-num (nnml-find-group-number id))
         path gpath group-num)
     (if (stringp id)
        (when (and (setq group-num (nnml-find-group-number id))
@@ -185,7 +184,9 @@ all.  This may very well take some time.")
       (nnheader-report 'nnml "No such file: %s" path))
      ((file-directory-p path)
       (nnheader-report 'nnml "File is a directory: %s" path))
       (nnheader-report 'nnml "No such file: %s" path))
      ((file-directory-p path)
       (nnheader-report 'nnml "File is a directory: %s" path))
-     ((not (save-excursion (nnmail-find-file path)))
+     ((not (save-excursion (let ((nnmail-file-coding-system
+                                 nnml-file-coding-system))
+                            (nnmail-find-file path))))
       (nnheader-report 'nnml "Couldn't read file: %s" path))
      (t
       (nnheader-report 'nnml "Article %s retrieved" id)
       (nnheader-report 'nnml "Couldn't read file: %s" path))
      (t
       (nnheader-report 'nnml "Article %s retrieved" id)
@@ -194,7 +195,7 @@ all.  This may very well take some time.")
            (string-to-int (file-name-nondirectory path)))))))
 
 (deffoo nnml-request-group (group &optional server dont-check)
            (string-to-int (file-name-nondirectory path)))))))
 
 (deffoo nnml-request-group (group &optional server dont-check)
-  (let ((pathname-coding-system 'binary))
+  (let ((file-name-coding-system nnmail-pathname-coding-system))
     (cond
      ((not (nnml-possibly-change-directory group server))
       (nnheader-report 'nnml "Invalid group (no such directory)"))
     (cond
      ((not (nnml-possibly-change-directory group server))
       (nnheader-report 'nnml "Invalid group (no such directory)"))
@@ -227,8 +228,16 @@ all.  This may very well take some time.")
   t)
 
 (deffoo nnml-request-create-group (group &optional server args)
   t)
 
 (deffoo nnml-request-create-group (group &optional server args)
+  (nnml-possibly-change-directory nil server)
   (nnmail-activate 'nnml)
   (nnmail-activate 'nnml)
-  (unless (assoc group nnml-group-alist)
+  (cond
+   ((assoc group nnml-group-alist)
+    t)
+   ((and (file-exists-p (nnmail-group-pathname group nnml-directory))
+        (not (file-directory-p (nnmail-group-pathname group nnml-directory))))
+    (nnheader-report 'nnml "%s is a file"
+                    (nnmail-group-pathname group nnml-directory)))
+   (t
     (let (active)
       (push (list group (setq active (cons 1 0)))
            nnml-group-alist)
     (let (active)
       (push (list group (setq active (cons 1 0)))
            nnml-group-alist)
@@ -238,17 +247,14 @@ all.  This may very well take some time.")
        (when articles
          (setcar active (apply 'min articles))
          (setcdr active (apply 'max articles))))
        (when articles
          (setcar active (apply 'min articles))
          (setcdr active (apply 'max articles))))
-      (nnmail-save-active nnml-group-alist nnml-active-file)))
-  t)
+      (nnmail-save-active nnml-group-alist nnml-active-file)
+      t))))
 
 (deffoo nnml-request-list (&optional server)
   (save-excursion
 
 (deffoo nnml-request-list (&optional server)
   (save-excursion
-    ;; 1997/8/12 by MORIOKA Tomohiko
-    ;; for XEmacs/mule.
     (let ((nnmail-file-coding-system nnmail-active-file-coding-system)
     (let ((nnmail-file-coding-system nnmail-active-file-coding-system)
-         (pathname-coding-system 'binary)) ; for XEmacs/mule
-      (nnmail-find-file nnml-active-file)
-      )
+         (file-name-coding-system nnmail-pathname-coding-system))
+      (nnmail-find-file nnml-active-file))
     (setq nnml-group-alist (nnmail-get-active))
     t))
 
     (setq nnml-group-alist (nnmail-get-active))
     t))
 
@@ -259,8 +265,7 @@ all.  This may very well take some time.")
   (save-excursion
     (nnmail-find-file nnml-newsgroups-file)))
 
   (save-excursion
     (nnmail-find-file nnml-newsgroups-file)))
 
-(deffoo nnml-request-expire-articles (articles group
-                                              &optional server force)
+(deffoo nnml-request-expire-articles (articles group &optional server force)
   (nnml-possibly-change-directory group server)
   (let ((active-articles
         (nnheader-directory-articles nnml-current-directory))
   (nnml-possibly-change-directory group server)
   (let ((active-articles
         (nnheader-directory-articles nnml-current-directory))
@@ -268,6 +273,11 @@ all.  This may very well take some time.")
        article rest mod-time number)
     (nnmail-activate 'nnml)
 
        article rest mod-time number)
     (nnmail-activate 'nnml)
 
+    (setq active-articles (sort active-articles '<))
+    ;; Articles not listed in active-articles are already gone,
+    ;; so don't try to expire them.
+    (setq articles (gnus-sorted-intersection articles active-articles))
+
     (while (and articles is-old)
       (when (setq article (nnml-article-to-file (setq number (pop articles))))
        (when (setq mod-time (nth 5 (file-attributes article)))
     (while (and articles is-old)
       (when (setq article (nnml-article-to-file (setq number (pop articles))))
        (when (setq mod-time (nth 5 (file-attributes article)))
@@ -276,8 +286,16 @@ all.  This may very well take some time.")
                         (nnmail-expired-article-p group mod-time force
                                                   nnml-inhibit-expiry)))
              (progn
                         (nnmail-expired-article-p group mod-time force
                                                   nnml-inhibit-expiry)))
              (progn
+               ;; Allow a special target group.
+               (unless (eq nnmail-expiry-target 'delete)
+                 (with-temp-buffer
+                   (nnml-request-article number group server
+                                         (current-buffer))
+                   (let ((nnml-current-directory nil))
+                     (nnmail-expiry-target-group
+                      nnmail-expiry-target group))))
                (nnheader-message 5 "Deleting article %s in %s"
                (nnheader-message 5 "Deleting article %s in %s"
-                                 article group)
+                                 number group)
                (condition-case ()
                    (funcall nnmail-delete-file-function article)
                  (file-error
                (condition-case ()
                    (funcall nnmail-delete-file-function article)
                  (file-error
@@ -295,7 +313,7 @@ all.  This may very well take some time.")
     (nconc rest articles)))
 
 (deffoo nnml-request-move-article
     (nconc rest articles)))
 
 (deffoo nnml-request-move-article
-  (article group server accept-form &optional last)
+    (article group server accept-form &optional last)
   (let ((buf (get-buffer-create " *nnml move*"))
        result)
     (nnml-possibly-change-directory group server)
   (let ((buf (get-buffer-create " *nnml move*"))
        result)
     (nnml-possibly-change-directory group server)
@@ -303,12 +321,15 @@ all.  This may very well take some time.")
     (and
      (nnml-deletable-article-p group article)
      (nnml-request-article article group server)
     (and
      (nnml-deletable-article-p group article)
      (nnml-request-article article group server)
-     (save-excursion
-       (set-buffer buf)
-       (insert-buffer-substring nntp-server-buffer)
-       (setq result (eval accept-form))
-       (kill-buffer (current-buffer))
-       result)
+     (let (nnml-current-directory 
+          nnml-current-group 
+          nnml-article-file-alist)
+       (save-excursion
+        (set-buffer buf)
+        (insert-buffer-substring nntp-server-buffer)
+        (setq result (eval accept-form))
+        (kill-buffer (current-buffer))
+        result))
      (progn
        (nnml-possibly-change-directory group server)
        (condition-case ()
      (progn
        (nnml-possibly-change-directory group server)
        (condition-case ()
@@ -356,16 +377,14 @@ all.  This may very well take some time.")
     (let ((chars (nnmail-insert-lines))
          (art (concat (int-to-string article) "\t"))
          headers)
     (let ((chars (nnmail-insert-lines))
          (art (concat (int-to-string article) "\t"))
          headers)
-      (when (condition-case ()
-               (progn
-                 (nnmail-write-region
-                  (point-min) (point-max)
-                  (or (nnml-article-to-file article)
-                      (concat nnml-current-directory
-                              (int-to-string article)))
-                  nil (if (nnheader-be-verbose 5) nil 'nomesg))
-                 t)
-             (error nil))
+      (when (ignore-errors
+             (nnmail-write-region
+              (point-min) (point-max)
+              (or (nnml-article-to-file article)
+                  (expand-file-name (int-to-string article)
+                                    nnml-current-directory))
+              nil (if (nnheader-be-verbose 5) nil 'nomesg))
+             t)
        (setq headers (nnml-parse-head chars article))
        ;; Replace the NOV line in the NOV file.
        (save-excursion
        (setq headers (nnml-parse-head chars article))
        ;; Replace the NOV line in the NOV file.
        (save-excursion
@@ -406,9 +425,7 @@ all.  This may very well take some time.")
          (nnheader-message 5 "Deleting article %s in %s..." article group)
          (funcall nnmail-delete-file-function article))))
     ;; Try to delete the directory itself.
          (nnheader-message 5 "Deleting article %s in %s..." article group)
          (funcall nnmail-delete-file-function article))))
     ;; Try to delete the directory itself.
-    (condition-case ()
-       (delete-directory nnml-current-directory)
-      (error nil)))
+    (ignore-errors (delete-directory nnml-current-directory)))
   ;; Remove the group from all structures.
   (setq nnml-group-alist
        (delq (assoc group nnml-group-alist) nnml-group-alist)
   ;; Remove the group from all structures.
   (setq nnml-group-alist
        (delq (assoc group nnml-group-alist) nnml-group-alist)
@@ -422,11 +439,9 @@ all.  This may very well take some time.")
   (nnml-possibly-change-directory group server)
   (let ((new-dir (nnmail-group-pathname new-name nnml-directory))
        (old-dir (nnmail-group-pathname group nnml-directory)))
   (nnml-possibly-change-directory group server)
   (let ((new-dir (nnmail-group-pathname new-name nnml-directory))
        (old-dir (nnmail-group-pathname group nnml-directory)))
-    (when (condition-case ()
-             (progn
-               (make-directory new-dir t)
-               t)
-           (error nil))
+    (when (ignore-errors
+           (make-directory new-dir t)
+           t)
       ;; We move the articles file by file instead of renaming
       ;; the directory -- there may be subgroups in this group.
       ;; One might be more clever, I guess.
       ;; We move the articles file by file instead of renaming
       ;; the directory -- there may be subgroups in this group.
       ;; One might be more clever, I guess.
@@ -441,9 +456,7 @@ all.  This may very well take some time.")
        (when (file-exists-p overview)
          (rename-file overview (concat new-dir nnml-nov-file-name))))
       (when (<= (length (directory-files old-dir)) 2)
        (when (file-exists-p overview)
          (rename-file overview (concat new-dir nnml-nov-file-name))))
       (when (<= (length (directory-files old-dir)) 2)
-       (condition-case ()
-           (delete-directory old-dir)
-         (error nil)))
+       (ignore-errors (delete-directory old-dir)))
       ;; That went ok, so we change the internal structures.
       (let ((entry (assoc group nnml-group-alist)))
        (when entry
       ;; That went ok, so we change the internal structures.
       (let ((entry (assoc group nnml-group-alist)))
        (when entry
@@ -461,7 +474,7 @@ all.  This may very well take some time.")
      ((not (file-exists-p file))
       (nnheader-report 'nnml "File %s does not exist" file))
      (t
      ((not (file-exists-p file))
       (nnheader-report 'nnml "File %s does not exist" file))
      (t
-      (nnheader-temp-write file
+      (with-temp-file file
        (nnheader-insert-file-contents file)
        (nnmail-replace-status name value))
       t))))
        (nnheader-insert-file-contents file)
        (nnmail-replace-status name value))
       t))))
@@ -473,12 +486,12 @@ all.  This may very well take some time.")
   (nnml-update-file-alist)
   (let (file)
     (if (setq file (cdr (assq article nnml-article-file-alist)))
   (nnml-update-file-alist)
   (let (file)
     (if (setq file (cdr (assq article nnml-article-file-alist)))
-       (concat nnml-current-directory file)
+       (expand-file-name file nnml-current-directory)
       ;; Just to make sure nothing went wrong when reading over NFS --
       ;; check once more.
       (when (file-exists-p
       ;; Just to make sure nothing went wrong when reading over NFS --
       ;; check once more.
       (when (file-exists-p
-            (setq file (concat nnml-current-directory "/"
-                               (number-to-string article))))
+            (setq file (expand-file-name (number-to-string article)
+                                         nnml-current-directory)))
        (nnml-update-file-alist t)
        file))))
 
        (nnml-update-file-alist t)
        file))))
 
@@ -495,7 +508,6 @@ all.  This may very well take some time.")
 (defun nnml-find-group-number (id)
   (save-excursion
     (set-buffer (get-buffer-create " *nnml id*"))
 (defun nnml-find-group-number (id)
   (save-excursion
     (set-buffer (get-buffer-create " *nnml id*"))
-    (buffer-disable-undo (current-buffer))
     (let ((alist nnml-group-alist)
          number)
       ;; We want to look through all .overview files, but we want to
     (let ((alist nnml-group-alist)
          number)
       ;; We want to look through all .overview files, but we want to
@@ -515,8 +527,8 @@ all.  This may very well take some time.")
 
 (defun nnml-find-id (group id)
   (erase-buffer)
 
 (defun nnml-find-id (group id)
   (erase-buffer)
-  (let ((nov (concat (nnmail-group-pathname group nnml-directory)
-                    nnml-nov-file-name))
+  (let ((nov (expand-file-name nnml-nov-file-name
+                              (nnmail-group-pathname group nnml-directory)))
        number found)
     (when (file-exists-p nov)
       (nnheader-insert-file-contents nov)
        number found)
     (when (file-exists-p nov)
       (nnheader-insert-file-contents nov)
@@ -530,15 +542,13 @@ all.  This may very well take some time.")
          (setq found t)
          ;; We return the article number.
          (setq number
          (setq found t)
          ;; We return the article number.
          (setq number
-               (condition-case ()
-                   (read (current-buffer))
-                 (error nil)))))
+               (ignore-errors (read (current-buffer))))))
       number)))
 
 (defun nnml-retrieve-headers-with-nov (articles &optional fetch-old)
   (if (or gnus-nov-is-evil nnml-nov-is-evil)
       nil
       number)))
 
 (defun nnml-retrieve-headers-with-nov (articles &optional fetch-old)
   (if (or gnus-nov-is-evil nnml-nov-is-evil)
       nil
-    (let ((nov (concat nnml-current-directory nnml-nov-file-name)))
+    (let ((nov (expand-file-name nnml-nov-file-name nnml-current-directory)))
       (when (file-exists-p nov)
        (save-excursion
          (set-buffer nntp-server-buffer)
       (when (file-exists-p nov)
        (save-excursion
          (set-buffer nntp-server-buffer)
@@ -560,7 +570,7 @@ all.  This may very well take some time.")
   (if (not group)
       t
     (let ((pathname (nnmail-group-pathname group nnml-directory))
   (if (not group)
       t
     (let ((pathname (nnmail-group-pathname group nnml-directory))
-         (pathname-coding-system 'binary))
+         (file-name-coding-system nnmail-pathname-coding-system))
       (when (not (equal pathname nnml-current-directory))
        (setq nnml-current-directory pathname
              nnml-current-group group
       (when (not (equal pathname nnml-current-directory))
        (setq nnml-current-directory pathname
              nnml-current-group group
@@ -568,15 +578,10 @@ all.  This may very well take some time.")
       (file-exists-p nnml-current-directory))))
 
 (defun nnml-possibly-create-directory (group)
       (file-exists-p nnml-current-directory))))
 
 (defun nnml-possibly-create-directory (group)
-  (let (dir dirs)
-    (setq dir (nnmail-group-pathname group nnml-directory))
-    (while (not (file-directory-p dir))
-      (push dir dirs)
-      (setq dir (file-name-directory (directory-file-name dir))))
-    (while dirs
-      (make-directory (directory-file-name (car dirs)))
-      (nnheader-message 5 "Creating mail directory %s" (car dirs))
-      (setq dirs (cdr dirs)))))
+  (let ((dir (nnmail-group-pathname group nnml-directory)))
+    (unless (file-exists-p dir)
+      (make-directory (directory-file-name dir) t)
+      (nnheader-message 5 "Creating mail directory %s" dir))))
 
 (defun nnml-save-mail (group-art)
   "Called narrowed to an article."
 
 (defun nnml-save-mail (group-art)
   "Called narrowed to an article."
@@ -639,8 +644,8 @@ all.  This may very well take some time.")
       (push (list group active) nnml-group-alist))
     (setcdr active (1+ (cdr active)))
     (while (file-exists-p
       (push (list group active) nnml-group-alist))
     (setcdr active (1+ (cdr active)))
     (while (file-exists-p
-           (concat (nnmail-group-pathname group nnml-directory)
-                   (int-to-string (cdr active))))
+           (expand-file-name (int-to-string (cdr active))
+                             (nnmail-group-pathname group nnml-directory)))
       (setcdr active (1+ (cdr active))))
     (cdr active)))
 
       (setcdr active (1+ (cdr active))))
     (cdr active)))
 
@@ -659,11 +664,10 @@ all.  This may very well take some time.")
   "Parse the head of the current buffer."
   (save-excursion
     (save-restriction
   "Parse the head of the current buffer."
   (save-excursion
     (save-restriction
-      (goto-char (point-min))
       (unless (zerop (buffer-size))
        (narrow-to-region
       (unless (zerop (buffer-size))
        (narrow-to-region
-        (point)
-        (1- (or (search-forward "\n\n" nil t) (point-max)))))
+        (goto-char (point-min))
+        (if (search-forward "\n\n" nil t) (1- (point)) (point-max))))
       ;; Fold continuation lines.
       (goto-char (point-min))
       (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
       ;; Fold continuation lines.
       (goto-char (point-min))
       (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
@@ -681,10 +685,12 @@ all.  This may very well take some time.")
        (save-excursion
          (set-buffer buffer)
          (set (make-local-variable 'nnml-nov-buffer-file-name)
        (save-excursion
          (set-buffer buffer)
          (set (make-local-variable 'nnml-nov-buffer-file-name)
-              (concat (nnmail-group-pathname group nnml-directory)
-                      nnml-nov-file-name))
+              (expand-file-name
+               nnml-nov-file-name
+               (nnmail-group-pathname group nnml-directory)))
          (erase-buffer)
          (erase-buffer)
-         (nnheader-insert-file-contents nnml-nov-buffer-file-name))
+         (when (file-exists-p nnml-nov-buffer-file-name)
+           (nnheader-insert-file-contents nnml-nov-buffer-file-name)))
        (push (cons group buffer) nnml-nov-buffer-alist)
        buffer)))
 
        (push (cons group buffer) nnml-nov-buffer-alist)
        buffer)))
 
@@ -701,13 +707,14 @@ all.  This may very well take some time.")
       (setq nnml-nov-buffer-alist (cdr nnml-nov-buffer-alist)))))
 
 ;;;###autoload
       (setq nnml-nov-buffer-alist (cdr nnml-nov-buffer-alist)))))
 
 ;;;###autoload
-(defun nnml-generate-nov-databases ()
+(defun nnml-generate-nov-databases (&optional server)
   "Generate NOV databases in all nnml directories."
   "Generate NOV databases in all nnml directories."
-  (interactive)
+  (interactive (list (or (nnoo-current-server 'nnml) "")))
   ;; Read the active file to make sure we don't re-use articles
   ;; numbers in empty groups.
   (nnmail-activate 'nnml)
   ;; Read the active file to make sure we don't re-use articles
   ;; numbers in empty groups.
   (nnmail-activate 'nnml)
-  (nnml-open-server (or (nnoo-current-server 'nnml) ""))
+  (unless (nnml-server-opened server)
+    (nnml-open-server server))
   (setq nnml-directory (expand-file-name nnml-directory))
   ;; Recurse down the directories.
   (nnml-generate-nov-databases-1 nnml-directory nil t)
   (setq nnml-directory (expand-file-name nnml-directory))
   ;; Recurse down the directories.
   (nnml-generate-nov-databases-1 nnml-directory nil t)
@@ -725,31 +732,39 @@ all.  This may very well take some time.")
     (let ((dirs (directory-files dir t nil t))
          dir)
       (while (setq dir (pop dirs))
     (let ((dirs (directory-files dir t nil t))
          dir)
       (while (setq dir (pop dirs))
-       (when (and (not (member (file-name-nondirectory dir) '("." "..")))
+       (when (and (not (string-match "^\\." (file-name-nondirectory dir)))
                   (file-directory-p dir))
          (nnml-generate-nov-databases-1 dir seen))))
     ;; Do this directory.
     (let ((files (sort (nnheader-article-to-file-alist dir)
                       'car-less-than-car)))
                   (file-directory-p dir))
          (nnml-generate-nov-databases-1 dir seen))))
     ;; Do this directory.
     (let ((files (sort (nnheader-article-to-file-alist dir)
                       'car-less-than-car)))
-      (when files
+      (if (not files)
+         (let* ((group (nnheader-file-to-group
+                        (directory-file-name dir) nnml-directory))
+                (info (cadr (assoc group nnml-group-alist))))
+           (when info
+             (setcar info (1+ (cdr info)))))
        (funcall nnml-generate-active-function dir)
        ;; Generate the nov file.
        (nnml-generate-nov-file dir files)
        (unless no-active
          (nnmail-save-active nnml-group-alist nnml-active-file))))))
 
        (funcall nnml-generate-active-function dir)
        ;; Generate the nov file.
        (nnml-generate-nov-file dir files)
        (unless no-active
          (nnmail-save-active nnml-group-alist nnml-active-file))))))
 
-(defvar files)
+(eval-when-compile (defvar files))
 (defun nnml-generate-active-info (dir)
   ;; Update the active info for this group.
 (defun nnml-generate-active-info (dir)
   ;; Update the active info for this group.
-  (let ((group (nnheader-file-to-group
-               (directory-file-name dir) nnml-directory)))
-    (setq nnml-group-alist
-         (delq (assoc group nnml-group-alist) nnml-group-alist))
+  (let* ((group (nnheader-file-to-group
+                (directory-file-name dir) nnml-directory))
+        (entry (assoc group nnml-group-alist))
+        (last (or (caadr entry) 0)))
+    (setq nnml-group-alist (delq entry nnml-group-alist))
     (push (list group
     (push (list group
-               (cons (caar files)
-                     (let ((f files))
-                       (while (cdr f) (setq f (cdr f)))
-                       (caar f))))
+               (cons (or (caar files) (1+ last))
+                     (max last
+                          (or (let ((f files))
+                                (while (cdr f) (setq f (cdr f)))
+                                (caar f))
+                              0))))
          nnml-group-alist)))
 
 (defun nnml-generate-nov-file (dir files)
          nnml-group-alist)))
 
 (defun nnml-generate-nov-file (dir files)
@@ -760,7 +775,7 @@ all.  This may very well take some time.")
     (save-excursion
       ;; Init the nov buffer.
       (set-buffer nov-buffer)
     (save-excursion
       ;; Init the nov buffer.
       (set-buffer nov-buffer)
-      (buffer-disable-undo (current-buffer))
+      (buffer-disable-undo)
       (erase-buffer)
       (set-buffer nntp-server-buffer)
       ;; Delete the old NOV file.
       (erase-buffer)
       (set-buffer nntp-server-buffer)
       ;; Delete the old NOV file.