Function: gnus-agent-regenerate-group

gnus-agent-regenerate-group is an autoloaded, interactive and byte-compiled function defined in gnus-agent.el.gz.

Signature

(gnus-agent-regenerate-group GROUP &optional REREAD)

Documentation

Regenerate GROUP.

If REREAD is t, all articles in the .overview are marked as unread. If REREAD is a list, the specified articles will be marked as unread. In addition, their NOV entries in .overview will be refreshed using the articles' current headers. If REREAD is not nil, downloaded articles are marked as unread.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/gnus/gnus-agent.el.gz
(defun gnus-agent-regenerate-group (group &optional reread)
  "Regenerate GROUP.
If REREAD is t, all articles in the .overview are marked as unread.
If REREAD is a list, the specified articles will be marked as unread.
In addition, their NOV entries in .overview will be refreshed using
the articles' current headers.
If REREAD is not nil, downloaded articles are marked as unread."
  (interactive
   (list (gnus-agent-read-group)
         (catch 'mark
           (while (let (c
                        (cursor-in-echo-area t)
                        (echo-keystrokes 0))
                    (message "Mark as unread: (n)one / (a)ll / all (d)ownloaded articles? (n) ")
                    (setq c (read-char-exclusive))

                    (cond ((or (eq c ?\r) (eq c ?n) (eq c ?N))
                           (throw 'mark nil))
                          ((or (eq c ?a) (eq c ?A))
                           (throw 'mark t))
                          ((or (eq c ?d) (eq c ?D))
                           (throw 'mark 'some)))
                    (gnus-message 3 "Ignoring unexpected input")
                    (sit-for 1)
                    t)))))
  (when group
    (gnus-message 5 "Regenerating in %s" group)
    (let* ((gnus-command-method (or gnus-command-method
				    (gnus-find-method-for-group group)))
	   (file (gnus-agent-article-name ".overview" group))
	   (dir (file-name-directory file))
	   (file-name-coding-system nnmail-pathname-coding-system)
	   (downloaded (if (file-exists-p dir)
			   (sort (delq nil (mapcar (lambda (name)
						     (and (not (file-directory-p (nnheader-concat dir name)))
							  (string-to-number name)))
						   (directory-files
                                                    dir nil "\\`[0-9]+\\'" t)))
				 #'>)
			 (progn (gnus-make-directory dir) nil)))
           nov-arts
	   alist header
	   regenerated)

      (mm-with-unibyte-buffer
	(if (file-exists-p file)
	    (let ((nnheader-file-coding-system
		   gnus-agent-file-coding-system))
	      (nnheader-insert-file-contents file)))
	(set-buffer-modified-p nil)

	;; Load the article IDs found in the overview file.  As a
	;; side-effect, validate the file contents.
	(let ((load t))
	  (while load
	    (setq load nil)
	    (goto-char (point-min))
	    (while (< (point) (point-max))
	      (cond ((and (looking-at "[0-9]+\t")
			  (<= (- (match-end 0) (match-beginning 0)) 9))
		     (push (read (current-buffer)) nov-arts)
		     (forward-line 1)
		     (let ((l1 (car nov-arts))
			   (l2 (cadr nov-arts)))
		       (cond ((and (listp reread) (memq l1 reread))
			      (gnus-delete-line)
			      (setq nov-arts (cdr nov-arts))
			      (gnus-message 4 "gnus-agent-regenerate-group: NOV\
 entry of article %s deleted." l1))
			     ((not l2)
			      nil)
			     ((< l1 l2)
			      (gnus-message 3 "gnus-agent-regenerate-group: NOV\
 entries are NOT in ascending order.")
			      ;; Don't sort now as I haven't verified
			      ;; that every line begins with a number
			      (setq load t))
			     ((= l1 l2)
			      (forward-line -1)
			      (gnus-message 4 "gnus-agent-regenerate-group: NOV\
 entries contained duplicate of article %s.	 Duplicate deleted." l1)
			      (gnus-delete-line)
			      (setq nov-arts (cdr nov-arts))))))
		    (t
		     (gnus-message 1 "gnus-agent-regenerate-group: NOV\
 entries contained line that did not begin with an article number.  Deleted\
 line.")
		     (gnus-delete-line))))
	    (when load
	      (gnus-message 5 "gnus-agent-regenerate-group: Sorting NOV\
 entries into ascending order.")
	      (sort-numeric-fields 1 (point-min) (point-max))
	      (setq nov-arts nil))))
	(gnus-agent-check-overview-buffer)

	;; Construct a new article alist whose nodes match every header
	;; in the .overview file.  As a side-effect, missing headers are
	;; reconstructed from the downloaded article file.
	(while (or downloaded nov-arts)
	  (cond ((and downloaded
		      (or (not nov-arts)
			  (> (car downloaded) (car nov-arts))))
		 ;; This entry is missing from the overview file
		 (gnus-message 3 "Regenerating NOV %s %d..."
			       group (car downloaded))
		 (let ((file (concat dir (number-to-string (car downloaded)))))
		   (mm-with-unibyte-buffer
		     (nnheader-insert-file-contents file)
		     (nnheader-remove-body)
		     (setq header (nnheader-parse-head t)))
		   (setf (mail-header-number header) (car downloaded))
		   (if nov-arts
		       (let ((key (concat "^" (int-to-string (car nov-arts))
					  "\t")))
			 (or (re-search-backward key nil t)
			     (re-search-forward key))
			 (forward-line 1))
		     (goto-char (point-min)))
		   (nnheader-insert-nov header))
		 (setq nov-arts (cons (car downloaded) nov-arts)))
		((eq (car downloaded) (car nov-arts))
		 ;; This entry in the overview has been downloaded
		 (push (cons (car downloaded)
			     (time-to-days
			      (file-attribute-modification-time
			       (file-attributes
				(concat dir (number-to-string
					     (car downloaded)))))))
		       alist)
		 (setq downloaded (cdr downloaded))
		 (setq nov-arts (cdr nov-arts)))
		(t
		 ;; This entry in the overview has not been downloaded
		 (push (cons (car nov-arts) nil) alist)
		 (setq nov-arts (cdr nov-arts)))))

	;; When gnus-agent-consider-all-articles is set,
	;; gnus-agent-regenerate-group should NOT remove article IDs from
	;; the alist.  Those IDs serve as markers to indicate that an
	;; attempt has been made to fetch that article's header.

	;; When gnus-agent-consider-all-articles is NOT set,
	;; gnus-agent-regenerate-group can remove the article ID of every
	;; article (with the exception of the last ID in the list - it's
	;; special) that no longer appears in the overview.  In this
	;; situation, the last article ID in the list implies that it,
	;; and every article ID preceding it, have been fetched from the
	;; server.

	(if gnus-agent-consider-all-articles
	    ;; Restore all article IDs that were not found in the overview file.
	    (let* ((n (cons nil alist))
		   (merged n)
		   (o (gnus-agent-load-alist group)))
	      (while o
		(let ((nID (caadr n))
		      (oID (caar o)))
		  (cond ((not nID)
			 (setq n (setcdr n (list (list oID))))
			 (setq o (cdr o)))
			((< oID nID)
			 (setcdr n (cons (list oID) (cdr n)))
			 (setq o (cdr o)))
			((= oID nID)
			 (setq o (cdr o))
			 (setq n (cdr n)))
			(t
			 (setq n (cdr n))))))
	      (setq alist (cdr merged)))
	  ;; Restore the last article ID if it is not already in the new alist
	  (let ((n (last alist))
		(o (last (gnus-agent-load-alist group))))
	    (cond ((not o)
		   nil)
		  ((not n)
		   (push (cons (caar o) nil) alist))
		  ((< (caar n) (caar o))
		   (setcdr n (list (car o)))))))

	(let ((inhibit-quit t))
	  (if (setq regenerated (buffer-modified-p))
	      (let ((coding-system-for-write gnus-agent-file-coding-system))
		(write-region (point-min) (point-max) file nil 'silent)))

	  (setq regenerated (or regenerated
				(and reread gnus-agent-article-alist)
				(not (equal alist gnus-agent-article-alist))))

	  (setq gnus-agent-article-alist alist)

	  (when regenerated
	    (gnus-agent-save-alist group)

	    ;; I have to alter the group's active range NOW as
	    ;; gnus-make-ascending-articles-unread will use it to
	    ;; recalculate the number of unread articles in the group

	    (let ((group (gnus-group-real-name group))
		  (group-active (or (gnus-active group)
				    (gnus-activate-group group))))
	      (gnus-agent-possibly-alter-active group group-active)))))

      (when (and reread gnus-agent-article-alist)
	(gnus-agent-synchronize-group-flags
	 group
	 (list (list
		(if (listp reread)
		    reread
                  (delq nil (mapcar (lambda (c)
                                      (cond ((eq reread t)
                                             (car c))
                                            ((cdr c)
                                             (car c))))
				    gnus-agent-article-alist)))
		'del '(read)))
	 gnus-command-method)

	(when regenerated
	  (gnus-agent-update-files-total-fetched-for group nil)))

      (gnus-message 5 "")
      regenerated)))