Function: nnfolder-read-folder

nnfolder-read-folder is a byte-compiled function defined in nnfolder.el.gz.

Signature

(nnfolder-read-folder GROUP)

Source Code

;; Defined in /usr/src/emacs/lisp/gnus/nnfolder.el.gz
;; This method has a problem if you've accidentally let the active
;; list get out of sync with the files.  This could happen, say, if
;; you've accidentally gotten new mail with something other than Gnus
;; (but why would _that_ ever happen? :-).  In that case, we will be
;; in the middle of processing the file, ready to add new X-Gnus
;; article number markers, and we'll run across a message with no ID
;; yet - the active list _may_not_ be ready for us yet.

;; To handle this, I'm modifying this routine to maintain the maximum
;; ID seen so far, and when we hit a message with no ID, we will
;; _manually_ scan the rest of the message looking for any more,
;; possibly higher IDs.  We'll assume the maximum that we find is the
;; highest active.  Note that this shouldn't cost us much extra time
;; at all, but will be a lot less vulnerable to glitches between the
;; mbox and the active file.

(defun nnfolder-read-folder (group)
  (let* ((file (nnfolder-group-pathname group))
	 (nov  (nnfolder-group-nov-pathname group))
	 (buffer (set-buffer
		  (let ((nnheader-file-coding-system
			 nnfolder-file-coding-system))
		    (nnheader-find-file-noselect file t)))))
    (mm-enable-multibyte) ;; Use multibyte buffer for future copying.
    (buffer-disable-undo)
    (if (equal (cadr (assoc group nnfolder-scantime-alist))
	       (file-attribute-modification-time (file-attributes file)))
	;; This looks up-to-date, so we don't do any scanning.
	(if (file-exists-p file)
	    buffer
	  (push (list group buffer) nnfolder-buffer-alist)
	  (set-buffer-modified-p t)
	  (nnfolder-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 ")
	       (marker (concat "\n" nnfolder-article-marker))
	       (number "[0-9]+")
	       (active (or (cadr (assoc group nnfolder-group-alist))
			   (cons 1 0)))
	       (scantime (assoc group nnfolder-scantime-alist))
	       (minid (cdr active))
	       maxid start end newscantime
	       novbuf articles newnum
	       buffer-read-only)
	  (setq maxid minid)

	  (unless (or gnus-nov-is-evil nnfolder-nov-is-evil
		      (and (file-exists-p nov)
			   (file-newer-than-file-p nov file)))
	    (unless (file-exists-p nov)
	      (gnus-make-directory (file-name-directory nov)))
	    (with-current-buffer
		(setq novbuf (nnfolder-open-nov group))
	      (goto-char (point-min))
	      (while (not (eobp))
		(push (read novbuf) articles)
		(forward-line 1))
	      (setq articles (nreverse articles))))
	  (goto-char (point-min))

	  ;; Anytime the active number is 1 or 0, it is suspect.  In
	  ;; that case, search the file manually to find the active
	  ;; number.  Or, of course, if we're being paranoid.  (This
	  ;; would also be the place to build other lists from the
	  ;; header markers, such as expunge lists, etc., if we ever
	  ;; desired to abandon the active file entirely for mboxes.)
	  (when (or nnfolder-ignore-active-file
		    novbuf
		    (< maxid 2))
	    (while (and (search-forward marker nil t)
			(looking-at number))
	      (setq newnum (string-to-number (match-string 0)))
	      (when (nnmail-within-headers-p)
		(setq maxid (max maxid newnum)
		      minid (min minid newnum))
		(when novbuf
		  (if (memq newnum articles)
		      (setq articles (delq newnum articles))
		    (let ((headers (nnfolder-parse-head newnum)))
		      (with-current-buffer novbuf
			(nnheader-find-nov-line newnum)
			(nnheader-insert-nov headers)))))))
	    (when (and novbuf articles)
	      (with-current-buffer novbuf
		(dolist (article articles)
		  (when (nnheader-find-nov-line article)
		    (delete-region (point)
				   (progn (forward-line 1) (point)))))))
	    (setcar active (max 1 (min minid maxid)))
	    (setcdr active (max maxid (cdr active)))
	    (goto-char (point-min)))

	  ;; As long as we trust that the user will only insert
	  ;; unmarked mail at the end, go to the end and search
	  ;; backwards for the last marker.  Find the start of that
	  ;; message, and begin to search for unmarked messages from
	  ;; there.
	  (when (not (or nnfolder-distrust-mbox
			 (< maxid 2)))
	    (goto-char (point-max))
	    (unless (re-search-backward marker nil t)
	      (goto-char (point-min)))
	    ;;(when (nnmail-search-unix-mail-delim)
	    ;;  (goto-char (point-min)))
	    )

	  ;; Keep track of the active number on our own, and insert it
	  ;; back into the active list when we're done.  Also, prime
	  ;; the pump to cut down on the number of searches we do.
	  (unless (nnmail-search-unix-mail-delim)
	    (goto-char (point-max)))
	  (setq end (point-marker))
	  (while (not (= end (point-max)))
	    (setq start (marker-position end))
	    (goto-char end)
	    ;; There may be more than one "From " line, so we skip past
	    ;; them.
	    (while (looking-at delim)
	      (forward-line 1))
	    (set-marker end (if (nnmail-search-unix-mail-delim)
				(point)
			      (point-max)))
	    (goto-char start)
	    (when (not (search-forward marker end t))
	      (narrow-to-region start end)
	      (nnmail-insert-lines)
	      (nnfolder-insert-newsgroup-line
	       (cons nil
		     (setq newnum
			   (nnfolder-active-number group))))
	      (when novbuf
		(let ((headers (nnfolder-parse-head newnum (point-min)
						    (point-max))))
		  (with-current-buffer novbuf
		    (goto-char (point-max))
		    (nnheader-insert-nov headers))))
	      (widen)))

	  (set-marker end nil)
	  ;; Make absolutely sure that the active list reflects
	  ;; reality!
	  (nnfolder-save-active nnfolder-group-alist nnfolder-active-file)

	  ;; Set the scantime for this group.
	  (setq newscantime (visited-file-modtime))
	  (if scantime
	      (setcdr scantime (list newscantime))
	    (push (list group newscantime)
		  nnfolder-scantime-alist))
	  ;; Save nov.
	  (when novbuf
	    (nnfolder-save-nov))
	  (current-buffer))))))