emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] Changes to emacs/lisp/gnus/nnmaildir.el,v


From: Miles Bader
Subject: [Emacs-diffs] Changes to emacs/lisp/gnus/nnmaildir.el,v
Date: Sun, 28 Oct 2007 09:19:26 +0000

CVSROOT:        /cvsroot/emacs
Module name:    emacs
Changes by:     Miles Bader <miles>     07/10/28 09:18:40

Index: lisp/gnus/nnmaildir.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/gnus/nnmaildir.el,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- lisp/gnus/nnmaildir.el      26 Jul 2007 05:27:03 -0000      1.7
+++ lisp/gnus/nnmaildir.el      28 Oct 2007 09:18:33 -0000      1.8
@@ -41,6 +41,8 @@
 ;;   copying, restoring, etc.
 ;;
 ;; Todo:
+;; * When moving an article for expiry, copy all the marks except 'expire
+;;   from the original article.
 ;; * Add a hook for when moving messages from new/ to cur/, to support
 ;;   nnmail's duplicate detection.
 ;; * Improve generated Xrefs, so crossposts are detectable.
@@ -54,6 +56,7 @@
    (put 'nnmaildir--with-work-buffer 'lisp-indent-function 0)
    (put 'nnmaildir--with-nov-buffer  'lisp-indent-function 0)
    (put 'nnmaildir--with-move-buffer 'lisp-indent-function 0)
+   (put 'nnmaildir--condcase         'lisp-indent-function 2)
    )
 ]
 
@@ -229,7 +232,6 @@
 (defmacro nnmaildir--nov-dir   (dir) `(nnmaildir--subdir ,dir "nov"))
 (defmacro nnmaildir--marks-dir (dir) `(nnmaildir--subdir ,dir "marks"))
 (defmacro nnmaildir--num-dir   (dir) `(nnmaildir--subdir ,dir "num"))
-(defmacro nnmaildir--num-file  (dir) `(concat ,dir ":"))
 
 (defmacro nnmaildir--unlink (file-arg)
   `(let ((file ,file-arg))
@@ -237,20 +239,36 @@
 (defun nnmaildir--mkdir (dir)
   (or (file-exists-p (file-name-as-directory dir))
       (make-directory-internal (directory-file-name dir))))
+(defun nnmaildir--mkfile (file)
+  (write-region "" nil file nil 'no-message))
 (defun nnmaildir--delete-dir-files (dir ls)
   (when (file-attributes dir)
-    (mapcar 'delete-file (funcall ls dir 'full "\\`[^.]" 'nosort))
+    (mapc 'delete-file (funcall ls dir 'full "\\`[^.]" 'nosort))
     (delete-directory dir)))
 
 (defun nnmaildir--group-maxnum (server group)
-  (if (zerop (nnmaildir--grp-count group)) 0
-    (let ((x (nnmaildir--srvgrp-dir (nnmaildir--srv-dir server)
-                                   (nnmaildir--grp-name group))))
-      (setq x (nnmaildir--nndir x)
-           x (nnmaildir--num-dir x)
-           x (nnmaildir--num-file x)
-           x (file-attributes x))
-      (if x (1- (nth 1 x)) 0))))
+  (catch 'return
+    (if (zerop (nnmaildir--grp-count group)) (throw 'return 0))
+    (let ((dir (nnmaildir--srvgrp-dir (nnmaildir--srv-dir server)
+                                   (nnmaildir--grp-name group)))
+         (number-opened 1)
+         attr ino-opened nlink number-linked)
+      (setq dir (nnmaildir--nndir dir)
+           dir (nnmaildir--num-dir dir))
+      (while t
+       (setq attr (file-attributes
+                   (concat dir (number-to-string number-opened))))
+       (or attr (throw 'return (1- number-opened)))
+       (setq ino-opened (nth 10 attr)
+             nlink (nth 1 attr)
+             number-linked (+ number-opened nlink))
+       (if (or (< nlink 1) (< number-linked nlink))
+           (signal 'error '("Arithmetic overflow")))
+       (setq attr (file-attributes
+                   (concat dir (number-to-string number-linked))))
+       (or attr (throw 'return (1- number-linked)))
+       (if (/= ino-opened (nth 10 attr))
+           (setq number-opened number-linked))))))
 
 ;; Make the given server, if non-nil, be the current server.  Then make the
 ;; given group, if non-nil, be the current group of the current server.  Then
@@ -287,6 +305,64 @@
       (setq pos (match-end 0))))
   string)
 
+(defmacro nnmaildir--condcase (errsym body &rest handler)
+  `(condition-case ,errsym
+       (let ((system-messages-locale "C")) ,body)
+     (error . ,handler)))
+
+(defun nnmaildir--emlink-p (err)
+  (and (eq (car err) 'file-error)
+       (string= (downcase (caddr err)) "too many links")))
+
+(defun nnmaildir--enoent-p (err)
+  (and (eq (car err) 'file-error)
+       (string= (downcase (caddr err)) "no such file or directory")))
+
+(defun nnmaildir--eexist-p (err)
+  (eq (car err) 'file-already-exists))
+
+(defun nnmaildir--new-number (nndir)
+  "Allocate a new article number by atomically creating a file under NNDIR."
+  (let ((numdir (nnmaildir--num-dir nndir))
+       (make-new-file t)
+       (number-open 1)
+       number-link previous-number-link path-open path-link ino-open)
+    (nnmaildir--mkdir numdir)
+    (catch 'return
+      (while t
+       (setq path-open (concat numdir (number-to-string number-open)))
+       (if (not make-new-file)
+           (setq previous-number-link number-link)
+         (nnmaildir--mkfile path-open)
+         ;; If Emacs had O_CREAT|O_EXCL, we could return number-open here.
+         (setq make-new-file nil
+               previous-number-link 0))
+       (let* ((attr (file-attributes path-open))
+              (nlink (nth 1 attr)))
+         (setq ino-open (nth 10 attr)
+               number-link (+ number-open nlink))
+         (if (or (< nlink 1) (< number-link nlink))
+             (signal 'error '("Arithmetic overflow"))))
+       (if (= number-link previous-number-link)
+           ;; We've already tried this number, in the previous loop iteration,
+           ;; and failed.
+           (signal 'error `("Corrupt internal nnmaildir data" ,path-open)))
+       (setq path-link (concat numdir (number-to-string number-link)))
+       (nnmaildir--condcase err
+           (progn
+             (add-name-to-file path-open path-link)
+             (throw 'return number-link))
+         (cond
+          ((nnmaildir--emlink-p err)
+           (setq make-new-file t
+                 number-open number-link))
+          ((nnmaildir--eexist-p err)
+           (let ((attr (file-attributes path-link)))
+             (if (/= (nth 10 attr) ino-open)
+                 (setq number-open number-link
+                       number-link 0))))
+          (t (signal (car err) (cdr err)))))))))
+
 (defun nnmaildir--update-nov (server group article)
   (let ((nnheader-file-coding-system 'binary)
        (srv-dir (nnmaildir--srv-dir server))
@@ -398,30 +474,7 @@
                                      nnmaildir--extra)
              num (nnmaildir--art-num article))
        (unless num
-         ;; Allocate a new article number.
-         (erase-buffer)
-         (setq numdir (nnmaildir--num-dir dir)
-               file (nnmaildir--num-file numdir)
-               num -1)
-         (nnmaildir--mkdir numdir)
-         (write-region "" nil file nil 'no-message)
-         (while file
-           ;; Get the number of links to file.
-           (setq attr (nth 1 (file-attributes file)))
-           (if (= attr num)
-               ;; We've already tried this number, in the previous loop
-               ;; iteration, and failed.
-               (signal 'error `("Corrupt internal nnmaildir data" ,numdir)))
-           ;; If attr is 123, try to link file to "123".  This atomically
-           ;; increases the link count and creates the "123" link, failing
-           ;; if that link was already created by another Gnus, just after
-           ;; we stat()ed file.
-           (condition-case nil
-               (progn
-                 (add-name-to-file file (concat numdir (format "%x" attr)))
-                 (setq file nil)) ;; Stop looping.
-             (file-already-exists nil))
-           (setq num attr))
+         (setq num (nnmaildir--new-number dir))
          (setf (nnmaildir--art-num article) num))
        ;; Store this new NOV data in a file
        (erase-buffer)
@@ -683,8 +736,7 @@
              group (make-nnmaildir--grp :name gname :index 0))
        (nnmaildir--mkdir nndir)
        (nnmaildir--mkdir (nnmaildir--nov-dir   nndir))
-       (nnmaildir--mkdir (nnmaildir--marks-dir nndir))
-       (write-region "" nil (concat nndir "markfile") nil 'no-message))
+       (nnmaildir--mkdir (nnmaildir--marks-dir nndir)))
       (setq read-only (nnmaildir--param pgname 'read-only)
            ls (or (nnmaildir--param pgname 'directory-files) srv-ls))
       (unless read-only
@@ -693,12 +745,10 @@
          (setf (nnmaildir--srv-error nnmaildir--cur-server)
                (concat "Maildir spans filesystems: " absdir))
          (throw 'return nil))
-       (mapcar
-        (lambda (file)
+       (dolist (file (funcall ls tdir 'full "\\`[^.]" 'nosort))
           (setq x (file-attributes file))
           (if (or (> (cadr x) 1) (< (car (nth 4 x)) 36h-ago))
-              (delete-file file)))
-        (funcall ls tdir 'full "\\`[^.]" 'nosort)))
+             (delete-file file))))
       (or scan-msgs
          isnew
          (throw 'return t))
@@ -707,12 +757,10 @@
          (setq nattr nil))
       (if read-only (setq dir (and (or isnew nattr) ndir))
        (when (or isnew nattr)
-         (mapcar
-          (lambda (file)
-            (let ((path (concat ndir file)))
-              (and (time-less-p (nth 5 (file-attributes path)) (current-time))
-                   (rename-file path (concat cdir file ":2,")))))
-          (funcall ls ndir nil "\\`[^.]" 'nosort))
+         (dolist (file  (funcall ls ndir nil "\\`[^.]" 'nosort))
+           (setq x (concat ndir file))
+           (and (time-less-p (nth 5 (file-attributes x)) (current-time))
+                (rename-file x (concat cdir file ":2,"))))
          (setf (nnmaildir--grp-new group) nattr))
        (setq cattr (nth 5 (file-attributes cdir)))
        (if (equal cattr (nnmaildir--grp-cur group))
@@ -737,13 +785,11 @@
                cdir (nnmaildir--marks-dir nndir)
                ndir (nnmaildir--subdir cdir "tick")
                cdir (nnmaildir--subdir cdir "read"))
-         (mapcar
-          (lambda (file)
+         (dolist (file files)
             (setq file (car file))
             (if (or (not (file-exists-p (concat cdir file)))
                     (file-exists-p (concat ndir file)))
-                (setq num (1+ num))))
-          files))
+               (setq num (1+ num)))))
        (setf (nnmaildir--grp-cache group) (make-vector num nil))
         (let ((inhibit-quit t))
           (set (intern gname groups) group))
@@ -757,12 +803,10 @@
            files (delq nil files)
            files (mapcar 'nnmaildir--parse-filename files)
            files (sort files 'nnmaildir--sort-files))
-      (mapcar
-       (lambda (file)
+      (dolist (file files)
         (setq file (if (consp file) file (aref file 3))
               x (make-nnmaildir--art :prefix (car file) :suffix (cdr file)))
         (nnmaildir--grp-add-art nnmaildir--cur-server group x))
-       files)
       (if read-only (setf (nnmaildir--grp-new group) nattr)
        (setf (nnmaildir--grp-cur group) cattr)))
     t))
@@ -809,19 +853,18 @@
                          dirs))
                  seen (nnmaildir--up2-1 (length dirs))
                  seen (make-vector seen 0))
-           (mapcar
-            (lambda (grp-dir)
+           (dolist (grp-dir dirs)
               (if (nnmaildir--scan grp-dir scan-group groups method srv-dir
                                    srv-ls)
                   (intern grp-dir seen)))
-            dirs)
            (setq x nil)
            (mapatoms (lambda (group)
                        (setq group (symbol-name group))
                        (unless (intern-soft group seen)
                          (setq x (cons group x))))
                      groups)
-           (mapcar (lambda (grp) (unintern grp groups)) x)
+           (dolist (grp x)
+             (unintern grp groups))
            (setf (nnmaildir--srv-mtime nnmaildir--cur-server)
                  (nth 5 (file-attributes srv-dir))))
          (and scan-group
@@ -857,8 +900,7 @@
     (nnmaildir--prepare server nil)
     (nnmaildir--with-nntp-buffer
       (erase-buffer)
-      (mapcar
-       (lambda (gname)
+      (dolist (gname groups)
         (setq group (nnmaildir--prepare nil gname))
         (if (null group) (insert "411 no such news group\n")
           (insert "211 ")
@@ -868,8 +910,7 @@
           (insert " ")
           (princ (nnmaildir--group-maxnum nnmaildir--cur-server group)
                  nntp-server-buffer)
-          (insert " " gname "\n")))
-       groups)))
+         (insert " " gname "\n")))))
   'group)
 
 (defun nnmaildir-request-update-info (gname info &optional server)
@@ -909,8 +950,7 @@
            new-mmth (nnmaildir--up2-1 (length markdirs))
            new-mmth (make-vector new-mmth 0)
            old-mmth (nnmaildir--grp-mmth group))
-      (mapcar
-       (lambda (mark)
+      (dolist (mark markdirs)
         (setq markdir (nnmaildir--subdir dir mark)
               mark-sym (intern mark)
               ranges nil)
@@ -925,17 +965,14 @@
             (setq ranges (assq mark-sym old-marks))
             (if ranges (setq ranges (cdr ranges)))
             (throw 'got-ranges nil))
-          (mapcar
-           (lambda (prefix)
+         (dolist (prefix (funcall ls markdir nil "\\`[^.]" 'nosort))
              (setq article (nnmaildir--flist-art flist prefix))
              (if article
                  (setq ranges
                        (gnus-add-to-range ranges
-                                          `(,(nnmaildir--art-num article))))))
-           (funcall ls markdir nil "\\`[^.]" 'nosort)))
+                                        `(,(nnmaildir--art-num article)))))))
         (if (eq mark-sym 'read) (setq read ranges)
           (if ranges (setq marks (cons (cons mark-sym ranges) marks)))))
-       markdirs)
       (gnus-info-set-read info (gnus-range-add read missing))
       (gnus-info-set-marks info marks 'extend)
       (setf (nnmaildir--grp-mmth group) new-mmth)
@@ -1087,10 +1124,10 @@
          (nnmaildir--delete-dir-files (nnmaildir--new grp-dir) ls)
          (nnmaildir--delete-dir-files (nnmaildir--cur grp-dir) ls))
        (setq dir (nnmaildir--nndir grp-dir))
-       (mapcar (lambda (subdir) (nnmaildir--delete-dir-files subdir ls))
-               `(,(nnmaildir--nov-dir dir) ,(nnmaildir--num-dir dir)
-                 ,@(funcall ls (nnmaildir--marks-dir dir) 'full "\\`[^.]"
-                            'nosort)))
+       (dolist (subdir `(,(nnmaildir--nov-dir dir) ,(nnmaildir--num-dir dir)
+                         ,@(funcall ls (nnmaildir--marks-dir dir)
+                                    'full "\\`[^.]" 'nosort)))
+         (nnmaildir--delete-dir-files subdir ls))
        (setq dir (nnmaildir--nndir grp-dir))
        (nnmaildir--unlink (concat dir "markfile"))
        (nnmaildir--unlink (concat dir "markfile{new}"))
@@ -1144,11 +1181,9 @@
          (nnmaildir--nlist-iterate nlist 'all insert-nov))
         ((null articles))
         ((stringp (car articles))
-         (mapcar
-          (lambda (msgid)
+         (dolist (msgid articles)
             (setq article (nnmaildir--mlist-art mlist msgid))
-            (if article (funcall insert-nov article)))
-          articles))
+           (if article (funcall insert-nov article))))
         (t
          (if fetch-old
              ;; Assume the article range list is sorted ascending
@@ -1254,7 +1289,7 @@
       t)))
 
 (defun nnmaildir-request-move-article (article gname server accept-form
-                                              &optional last)
+                                              &optional last move-is-internal)
   (let ((group (nnmaildir--prepare server gname))
        pgname suffix result nnmaildir--file deactivate-mark)
     (catch 'return
@@ -1339,8 +1374,7 @@
                                          nnmaildir--cur-server)
                                        "24-hour timer expired")
                                  (throw 'return nil))))
-      (condition-case nil
-         (add-name-to-file nnmaildir--file tmpfile)
+      (condition-case nil (add-name-to-file nnmaildir--file tmpfile)
        (error
         (gmm-write-region (point-min) (point-max) tmpfile nil 'no-message nil
                           'excl)
@@ -1470,7 +1504,12 @@
                        (not (string-equal target pgname))) ;; Move it.
               (erase-buffer)
               (nnheader-insert-file-contents nnmaildir--file)
-              (gnus-request-accept-article target nil nil 'no-encode))
+              (let ((group-art (gnus-request-accept-article
+                                target nil nil 'no-encode)))
+                (when (consp group-art)
+                  ;; Maybe also copy: dormant forward reply save tick
+                  ;; (gnus-add-mark? gnus-request-set-mark?)
+                  (gnus-group-mark-article-read target (cdr group-art)))))
             (if (equal target pgname)
                 ;; Leave it here.
                 (setq didnt (cons (nnmaildir--art-num article) didnt))
@@ -1484,8 +1523,8 @@
        (coding-system-for-write nnheader-file-coding-system)
        (buffer-file-coding-system nil)
        (file-coding-system-alist nil)
-       del-mark del-action add-action set-action marksdir markfile nlist
-       ranges begin end article all-marks todo-marks did-marks mdir mfile
+       del-mark del-action add-action set-action marksdir nlist
+       ranges begin end article all-marks todo-marks mdir mfile
        pgname ls permarkfile deactivate-mark)
     (setq del-mark
          (lambda (mark)
@@ -1500,17 +1539,19 @@
               (setq mdir (nnmaildir--subdir marksdir (symbol-name mark))
                     permarkfile (concat mdir ":")
                     mfile (concat mdir (nnmaildir--art-prefix article)))
-              (unless (memq mark did-marks)
-                (setq did-marks (cons mark did-marks))
+              (nnmaildir--condcase err (add-name-to-file permarkfile mfile)
+                (cond
+                 ((nnmaildir--eexist-p err))
+                 ((nnmaildir--enoent-p err)
                 (nnmaildir--mkdir mdir)
-                (unless (file-attributes permarkfile)
-                  (condition-case nil
-                      (add-name-to-file markfile permarkfile)
-                    (file-error
-                     ;; AFS can't make hard links in separate directories
-                     (write-region "" nil permarkfile nil 'no-message)))))
-              (unless (file-exists-p mfile)
+                  (nnmaildir--mkfile permarkfile)
+                  (add-name-to-file permarkfile mfile))
+                 ((nnmaildir--emlink-p err)
+                  (let ((permarkfilenew (concat permarkfile "{new}")))
+                    (nnmaildir--mkfile permarkfilenew)
+                    (rename-file permarkfilenew permarkfile 'replace)
                 (add-name-to-file permarkfile mfile)))
+                 (t (signal (car err) (cdr err))))))
             todo-marks))
          set-action (lambda (article)
                       (funcall add-action)
@@ -1522,32 +1563,29 @@
       (unless group
        (setf (nnmaildir--srv-error nnmaildir--cur-server)
              (concat "No such group: " gname))
-       (mapcar (lambda (action)
+       (dolist (action actions)
                  (setq ranges (gnus-range-add ranges (car action))))
-               actions)
        (throw 'return ranges))
       (setq nlist (nnmaildir--grp-nlist group)
            marksdir (nnmaildir--srv-dir nnmaildir--cur-server)
            marksdir (nnmaildir--srvgrp-dir marksdir gname)
            marksdir (nnmaildir--nndir marksdir)
-           markfile (concat marksdir "markfile")
            marksdir (nnmaildir--marks-dir marksdir)
            gname (nnmaildir--grp-name group)
             pgname (nnmaildir--pgname nnmaildir--cur-server gname)
             ls (nnmaildir--group-ls nnmaildir--cur-server pgname)
            all-marks (funcall ls marksdir nil "\\`[^.]" 'nosort)
            all-marks (mapcar 'intern all-marks))
-      (mapcar
-       (lambda (action)
+      (dolist (action actions)
         (setq ranges (car action)
               todo-marks (caddr action))
-        (mapcar (lambda (mark) (add-to-list 'all-marks mark)) todo-marks)
+       (dolist (mark todo-marks)
+         (add-to-list 'all-marks mark))
         (if (numberp (cdr ranges)) (setq ranges (list ranges)))
         (nnmaildir--nlist-iterate nlist ranges
                                   (cond ((eq 'del (cadr action)) del-action)
                                         ((eq 'add (cadr action)) add-action)
                                         (t set-action))))
-       actions)
       nil)))
 
 (defun nnmaildir-close-group (gname &optional server)
@@ -1576,22 +1614,16 @@
            flist (nnmaildir--up2-1 (length files))
            flist (make-vector flist 0))
       (save-match-data
-       (mapcar
-        (lambda (file)
+       (dolist (file files)
           (string-match "\\`\\([^:]*\\)\\(:.*\\)?\\'" file)
-          (intern (match-string 1 file) flist))
-        files))
-      (mapcar
-       (lambda (dir)
+         (intern (match-string 1 file) flist)))
+      (dolist (dir dirs)
         (setq files (cdr dir)
               dir (file-name-as-directory (car dir)))
-        (mapcar
-         (lambda (file)
+       (dolist (file files)
            (unless (or (intern-soft file flist) (string= file ":"))
              (setq file (concat dir file))
-             (delete-file file)))
-         files))
-       dirs)
+           (delete-file file))))
       t)))
 
 (defun nnmaildir-close-server (&optional server)
@@ -1608,7 +1640,7 @@
     (mapatoms (lambda (server)
                (setq servers (cons (symbol-name server) servers)))
              nnmaildir--servers)
-    (mapcar 'nnmaildir-close-server servers)
+    (mapc 'nnmaildir-close-server servers)
     (setq buffer (get-buffer " *nnmaildir work*"))
     (if buffer (kill-buffer buffer))
     (setq buffer (get-buffer " *nnmaildir nov*"))




reply via email to

[Prev in Thread] Current Thread [Next in Thread]