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))))))