Function: nnmaildir--update-nov

nnmaildir--update-nov is a byte-compiled function defined in nnmaildir.el.gz.

Signature

(nnmaildir--update-nov SERVER GROUP ARTICLE)

Source Code

;; Defined in /usr/src/emacs/lisp/gnus/nnmaildir.el.gz
(defun nnmaildir--update-nov (server group article)
  (let ((nnheader-file-coding-system 'undecided)
	(srv-dir (nnmaildir--srv-dir server))
	(storage-version 1) ;; [version article-number msgid [...nov...]]
	dir gname pgname msgdir prefix suffix file attr mtime novdir novfile
	nov msgid nov-beg nov-mid nov-end field val old-extra num
	deactivate-mark)
    (catch 'return
      (setq gname (nnmaildir--grp-name group)
	    pgname (nnmaildir--pgname server gname)
	    dir (nnmaildir--srvgrp-dir srv-dir gname)
	    msgdir (if (nnmaildir--param pgname 'read-only)
		       (nnmaildir--new dir) (nnmaildir--cur dir))
	    prefix (nnmaildir--art-prefix article)
	    suffix (nnmaildir--art-suffix article)
	    file (concat msgdir prefix suffix)
	    attr (file-attributes file))
      (unless attr
	(nnmaildir--expired-article group article)
	(throw 'return nil))
      (setq mtime (file-attribute-modification-time attr)
	    attr (file-attribute-size attr)
	    nov (nnmaildir--art-nov article)
	    dir (nnmaildir--nndir dir)
	    novdir (nnmaildir--nov-dir dir)
	    novfile (concat novdir prefix))
      (unless (equal nnmaildir--extra nnmail-extra-headers)
	(setq nnmaildir--extra (copy-sequence nnmail-extra-headers)))
      (nnmaildir--with-nov-buffer
	;; First we'll check for already-parsed NOV data.
	(cond ((not (file-exists-p novfile))
	       ;; The NOV file doesn't exist; we have to parse the message.
	       (setq nov nil))
	      ((not nov)
	       ;; The file exists, but the data isn't in memory; read the file.
	       (erase-buffer)
	       (nnheader-insert-file-contents novfile)
	       (setq nov (read (current-buffer)))
	       (if (not (and (vectorp nov)
			     (/= 0 (length nov))
			     (equal storage-version (aref nov 0))))
		   ;; This NOV data seems to be in the wrong format.
		   (setq nov nil)
		 (unless (nnmaildir--art-num   article)
		   (setf (nnmaildir--art-num   article) (aref nov 1)))
		 (unless (nnmaildir--art-msgid article)
		   (setf (nnmaildir--art-msgid article) (aref nov 2)))
		 (setq nov (aref nov 3)))))
	;; Now check whether the already-parsed data (if we have any) is
	;; usable: if the message has been edited or if nnmail-extra-headers
	;; has been augmented since this data was parsed from the message,
	;; then we have to reparse.  Otherwise it's up-to-date.
	(when (and nov (time-equal-p mtime (nnmaildir--nov-get-mtime nov)))
	  ;; The timestamp matches.  Now check nnmail-extra-headers.
	  (setq old-extra (nnmaildir--nov-get-extra nov))
	  (when (equal nnmaildir--extra old-extra) ;; common case
	    ;; Save memory; use a single copy of the list value.
	    (nnmaildir--nov-set-extra nov nnmaildir--extra)
	    (throw 'return nov))
	  ;; They're not equal, but maybe the new is a subset of the old.
	  (if (null nnmaildir--extra)
	      ;; The empty set is a subset of every set.
	      (throw 'return nov))
	  (if (not (memq nil (mapcar (lambda (e) (memq e old-extra))
				     nnmaildir--extra)))
	      (throw 'return nov)))
	;; Parse the NOV data out of the message.
	(erase-buffer)
	(nnheader-insert-file-contents file)
	(insert "\n")
	(goto-char (point-min))
	(save-restriction
	  (if (search-forward "\n\n" nil 'noerror)
	      (progn
		(setq nov-mid (count-lines (point) (point-max)))
		(narrow-to-region (point-min) (1- (point))))
	    (setq nov-mid 0))
	  (goto-char (point-min))
	  (delete-char 1)
	  (setq nov (nnheader-parse-head t)
		field (or (mail-header-lines nov) 0)))
	(unless (or (<= field 0) (nnmaildir--param pgname 'distrust-Lines:))
	  (setq nov-mid field))
	(setq nov-mid (number-to-string nov-mid)
	      nov-mid (concat (number-to-string attr) "\t" nov-mid))
	(save-match-data
	  (setq field (or (mail-header-references nov) ""))
	  (nnmaildir--tab-to-space field)
	  (setq nov-mid (concat field "\t" nov-mid)
		nov-beg (mapconcat
			  (lambda (f) (nnmaildir--tab-to-space (or f "")))
			  (list (mail-header-subject nov)
				(mail-header-from nov)
				(mail-header-date nov)) "\t")
		nov-end (mapconcat
			  (lambda (extra)
			    (setq field (symbol-name (car extra))
				  val (cdr extra))
			    (nnmaildir--tab-to-space field)
			    (nnmaildir--tab-to-space val)
			    (concat field ": " val))
			  (mail-header-extra nov) "\t")))
	(setq msgid (mail-header-id nov))
	(if (or (null msgid) (nnheader-fake-message-id-p msgid))
	    (setq msgid (concat "<" prefix "@nnmaildir>")))
	(nnmaildir--tab-to-space msgid)
	;; The data is parsed; create an nnmaildir NOV structure.
	(setq nov (nnmaildir--nov-new nov-beg nov-mid nov-end mtime
				      nnmaildir--extra)
	      num (nnmaildir--art-num article))
	(unless num
	  (setq num (nnmaildir--new-number dir))
	  (setf (nnmaildir--art-num article) num))
	;; Store this new NOV data in a file
	(erase-buffer)
	(prin1 (vector storage-version num msgid nov) (current-buffer))
	(setq file (concat novfile ":"))
	(nnmaildir--unlink file)
	(write-region (point-min) (point-max) file nil 'no-message nil
		      'excl))
      (rename-file file novfile 'replace)
      (setf (nnmaildir--art-msgid article) msgid)
      nov)))