X-Git-Url: https://cgit.sxemacs.org/?a=blobdiff_plain;f=lisp%2Fgnus-cache.el;h=bc1f221a5c3f084b94d6f50fe3f556e260f6e7f1;hb=5b8ecce52d86ed7352e6e5b5d768c34321a4c58d;hp=00136f10a5e77ab4fa1c661a67dca93d7e2c0b38;hpb=27e50870dcbd1442e8fe2d14ddfb89cd7c706495;p=gnus diff --git a/lisp/gnus-cache.el b/lisp/gnus-cache.el index 00136f10a..bc1f221a5 100644 --- a/lisp/gnus-cache.el +++ b/lisp/gnus-cache.el @@ -1,7 +1,7 @@ ;;; gnus-cache.el --- cache interface for Gnus -;; Copyright (C) 1995,96 Free Software Foundation, Inc. +;; Copyright (C) 1995,96,97,98,99 Free Software Foundation, Inc. -;; Author: Lars Magne Ingebrigtsen +;; Author: Lars Magne Ingebrigtsen ;; Keywords: news ;; This file is part of GNU Emacs. @@ -25,23 +25,16 @@ ;;; Code: +(eval-when-compile (require 'cl)) + (require 'gnus) (require 'gnus-int) (require 'gnus-range) -(require 'gnus-sum) (require 'gnus-start) +(eval-when-compile + (require 'gnus-sum)) -(defgroup gnus-cache nil - "Cache interface." - :group 'gnus) - -(defcustom gnus-cache-directory - (nnheader-concat gnus-directory "cache/") - "*The directory where cached articles will be stored." - :group 'gnus-cache - :type 'directory) - -(defcustom gnus-cache-active-file +(defcustom gnus-cache-active-file (concat (file-name-as-directory gnus-cache-directory) "active") "*The cache active file." :group 'gnus-cache @@ -57,15 +50,36 @@ :group 'gnus-cache :type '(set (const ticked) (const dormant) (const unread) (const read))) +(defcustom gnus-cacheable-groups nil + "*Groups that match this regexp will be cached. + +If you only want to cache your nntp groups, you could set this +variable to \"^nntp\". + +If a group matches both gnus-cacheable-groups and gnus-uncacheable-groups +it's not cached." + :group 'gnus-cache + :type '(choice (const :tag "off" nil) + regexp)) + (defcustom gnus-uncacheable-groups nil "*Groups that match this regexp will not be cached. If you want to avoid caching your nnml groups, you could set this -variable to \"^nnml\"." +variable to \"^nnml\". + +If a group matches both gnus-cacheable-groups and gnus-uncacheable-groups +it's not cached." :group 'gnus-cache :type '(choice (const :tag "off" nil) regexp)) +(defvar gnus-cache-overview-coding-system 'raw-text + "Coding system used on Gnus cache files.") + +(defvar gnus-cache-coding-system 'binary + "Coding system used on Gnus cache files.") + ;;; Internal variables. @@ -113,7 +127,9 @@ variable to \"^nnml\"." (set-buffer buffer) (if (> (buffer-size) 0) ;; Non-empty overview, write it to a file. - (gnus-write-buffer overview-file) + (let ((coding-system-for-write + gnus-cache-overview-coding-system)) + (gnus-write-buffer overview-file)) ;; Empty overview file, remove it (when (file-exists-p overview-file) (delete-file overview-file)) @@ -128,25 +144,24 @@ variable to \"^nnml\"." (gnus-kill-buffer buffer) (setq gnus-cache-buffer nil)))) -(defun gnus-cache-possibly-enter-article - (group article headers ticked dormant unread &optional force) +(defun gnus-cache-possibly-enter-article + (group article ticked dormant unread &optional force) (when (and (or force (not (eq gnus-use-cache 'passive))) (numberp article) - (> article 0) - (vectorp headers)) - ; This might be a dummy article. - ;; If this is a virtual group, we find the real group. - (when (gnus-virtual-group-p group) - (let ((result (nnvirtual-find-group-art - (gnus-group-real-name group) article))) - (setq group (car result) - headers (copy-sequence headers)) - (mail-header-set-number headers (cdr result)))) - (let ((number (mail-header-number headers)) - file dir) - (when (and (> number 0) ; Reffed article. + (> article 0)) ; This might be a dummy article. + (let ((number article) file headers) + ;; If this is a virtual group, we find the real group. + (when (gnus-virtual-group-p group) + (let ((result (nnvirtual-find-group-art + (gnus-group-real-name group) article))) + (setq group (car result) + number (cdr result)))) + (when (and number + (> number 0) ; Reffed article. (or force - (and (or (not gnus-uncacheable-groups) + (and (or (not gnus-cacheable-groups) + (string-match gnus-cacheable-groups group)) + (or (not gnus-uncacheable-groups) (not (string-match gnus-uncacheable-groups group))) (gnus-cache-member-of-class @@ -154,13 +169,14 @@ variable to \"^nnml\"." (not (file-exists-p (setq file (gnus-cache-file-name group number))))) ;; Possibly create the cache directory. - (gnus-make-directory (setq dir (file-name-directory file))) + (gnus-make-directory (file-name-directory file)) ;; Save the article in the cache. (if (file-exists-p file) t ; The article already is saved. (save-excursion (set-buffer nntp-server-buffer) - (let ((gnus-use-cache nil)) + (let ((gnus-use-cache nil) + (gnus-article-decode-hook nil)) (gnus-request-article-this-buffer number group)) (when (> (buffer-size) 0) (gnus-write-buffer file) @@ -185,17 +201,7 @@ variable to \"^nnml\"." (beginning-of-line)) (forward-line 1)) (beginning-of-line) - ;; [number subject from date id references chars lines xref] - (insert (format "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n" - (mail-header-number headers) - (mail-header-subject headers) - (mail-header-from headers) - (mail-header-date headers) - (mail-header-id headers) - (or (mail-header-references headers) "") - (or (mail-header-chars headers) "") - (or (mail-header-lines headers) "") - (or (mail-header-xref headers) ""))) + (nnheader-insert-nov headers) ;; Update the active info. (set-buffer gnus-summary-buffer) (gnus-cache-update-active group number) @@ -249,24 +255,23 @@ variable to \"^nnml\"." (when (file-exists-p file) (erase-buffer) (gnus-kill-all-overlays) - (insert-file-contents file) + (let ((coding-system-for-read gnus-cache-coding-system)) + (insert-file-contents file)) t))) (defun gnus-cache-possibly-alter-active (group active) "Alter the ACTIVE info for GROUP to reflect the articles in the cache." - (when (equal group "no.norsk") (error "hie")) (when gnus-cache-active-hashtb (let ((cache-active (gnus-gethash group gnus-cache-active-hashtb))) - (and cache-active - (< (car cache-active) (car active)) - (setcar active (car cache-active))) - (and cache-active - (> (cdr cache-active) (cdr active)) - (setcdr active (cdr cache-active)))))) + (when cache-active + (when (< (car cache-active) (car active)) + (setcar active (car cache-active))) + (when (> (cdr cache-active) (cdr active)) + (setcdr active (cdr cache-active))))))) (defun gnus-cache-retrieve-headers (articles group &optional fetch-old) "Retrieve the headers for ARTICLES in GROUP." - (let ((cached + (let ((cached (setq gnus-newsgroup-cached (gnus-cache-articles-in-group group)))) (if (not cached) ;; No cached articles here, so we just retrieve them @@ -278,12 +283,12 @@ variable to \"^nnml\"." articles)) (cache-file (gnus-cache-file-name group ".overview")) type) - ;; We first retrieve all the headers that we don't have in + ;; We first retrieve all the headers that we don't have in ;; the cache. (let ((gnus-use-cache nil)) (when uncached-articles - (setq type (and articles - (gnus-retrieve-headers + (setq type (and articles + (gnus-retrieve-headers uncached-articles group fetch-old))))) (gnus-cache-save-buffers) ;; Then we insert the cached headers. @@ -293,7 +298,7 @@ variable to \"^nnml\"." ;; There are no cached headers. type) ((null type) - ;; There were no uncached headers (or retrieval was + ;; There were no uncached headers (or retrieval was ;; unsuccessful), so we use the cached headers exclusively. (set-buffer nntp-server-buffer) (erase-buffer) @@ -315,18 +320,16 @@ variable to \"^nnml\"." If not given a prefix, use the process marked articles instead. Returns the list of articles entered." (interactive "P") - (gnus-set-global-variables) (let ((articles (gnus-summary-work-articles n)) article out) (while (setq article (pop articles)) + (gnus-summary-remove-process-mark article) (if (natnump article) - (when (gnus-cache-possibly-enter-article - gnus-newsgroup-name article - (gnus-summary-article-header article) + (when (gnus-cache-possibly-enter-article + gnus-newsgroup-name article nil nil nil t) (push article out)) (gnus-message 2 "Can't cache article %d" article)) - (gnus-summary-remove-process-mark article) (gnus-summary-update-secondary-mark article)) (gnus-summary-next-subject 1) (gnus-summary-position-point) @@ -337,15 +340,14 @@ Returns the list of articles entered." If not given a prefix, use the process marked articles instead. Returns the list of articles removed." (interactive "P") - (gnus-set-global-variables) (gnus-cache-change-buffer gnus-newsgroup-name) (let ((articles (gnus-summary-work-articles n)) article out) (while articles (setq article (pop articles)) + (gnus-summary-remove-process-mark article) (when (gnus-cache-possibly-remove-article article nil nil nil t) (push article out)) - (gnus-summary-remove-process-mark article) (gnus-summary-update-secondary-mark article)) (gnus-summary-next-subject 1) (gnus-summary-position-point) @@ -358,13 +360,16 @@ Returns the list of articles removed." (defun gnus-summary-insert-cached-articles () "Insert all the articles cached for this group into the current buffer." (interactive) - (let ((cached gnus-newsgroup-cached) + (let ((cached (sort (copy-sequence gnus-newsgroup-cached) '<)) (gnus-verbose (max 6 gnus-verbose))) (unless cached - (error "No cached articles for this group")) + (gnus-message 3 "No cached articles for this group")) (while cached (gnus-summary-goto-subject (pop cached) t)))) +(defalias 'gnus-summary-limit-include-cached + 'gnus-summary-insert-cached-articles) + ;;; Internal functions. (defun gnus-cache-change-buffer (group) @@ -379,14 +384,14 @@ Returns the list of articles removed." (save-excursion (setq gnus-cache-buffer (cons group - (set-buffer (get-buffer-create " *gnus-cache-overview*")))) - (buffer-disable-undo (current-buffer)) + (set-buffer (gnus-get-buffer-create + " *gnus-cache-overview*")))) ;; Insert the contents of this group's cache overview. (erase-buffer) (let ((file (gnus-cache-file-name group ".overview"))) (when (file-exists-p file) (nnheader-insert-file-contents file))) - ;; We have a fresh (empty/just loaded) buffer, + ;; We have a fresh (empty/just loaded) buffer, ;; mark it as unmodified to save a redundant write later. (set-buffer-modified-p nil)))) @@ -407,18 +412,20 @@ Returns the list of articles removed." ;; Translate the first colon into a slash. (when (string-match ":" group) (aset group (match-beginning 0) ?/)) - (nnheader-replace-chars-in-string group ?. ?/))))) + (nnheader-replace-chars-in-string group ?. ?/))) + t)) (if (stringp article) article (int-to-string article)))) (defun gnus-cache-update-article (group article) "If ARTICLE is in the cache, remove it and re-enter it." + (gnus-cache-change-buffer group) (when (gnus-cache-possibly-remove-article article nil nil nil t) (let ((gnus-use-cache nil)) - (gnus-cache-possibly-enter-article - gnus-newsgroup-name article (gnus-summary-article-header article) + (gnus-cache-possibly-enter-article + gnus-newsgroup-name article nil nil nil t)))) -(defun gnus-cache-possibly-remove-article (article ticked dormant unread +(defun gnus-cache-possibly-remove-article (article ticked dormant unread &optional force) "Possibly remove ARTICLE from the cache." (let ((group gnus-newsgroup-name) @@ -426,7 +433,7 @@ Returns the list of articles removed." file) ;; If this is a virtual group, we find the real group. (when (gnus-virtual-group-p group) - (let ((result (nnvirtual-find-group-art + (let ((result (nnvirtual-find-group-art (gnus-group-real-name group) article))) (setq group (car result) number (cdr result)))) @@ -451,21 +458,27 @@ Returns the list of articles removed." (defun gnus-cache-articles-in-group (group) "Return a sorted list of cached articles in GROUP." - (let ((dir (file-name-directory (gnus-cache-file-name group 1)))) + (let ((dir (file-name-directory (gnus-cache-file-name group 1))) + articles) (when (file-exists-p dir) - (sort (mapcar (lambda (name) (string-to-int name)) - (directory-files dir nil "^[0-9]+$" t)) - '<)))) - -(defun gnus-cache-braid-nov (group cached) - (let ((cache-buf (get-buffer-create " *gnus-cache*")) + (setq articles + (sort (mapcar (lambda (name) (string-to-int name)) + (directory-files dir nil "^[0-9]+$" t)) + '<)) + ;; Update the cache active file, just to synch more. + (when articles + (gnus-cache-update-active group (car articles) t) + (gnus-cache-update-active group (car (last articles)))) + articles))) + +(defun gnus-cache-braid-nov (group cached &optional file) + (let ((cache-buf (gnus-get-buffer-create " *gnus-cache*")) beg end) (gnus-cache-save-buffers) (save-excursion (set-buffer cache-buf) - (buffer-disable-undo (current-buffer)) (erase-buffer) - (insert-file-contents (gnus-cache-file-name group ".overview")) + (insert-file-contents (or file (gnus-cache-file-name group ".overview"))) (goto-char (point-min)) (insert "\n") (goto-char (point-min))) @@ -490,10 +503,9 @@ Returns the list of articles removed." (kill-buffer cache-buf))) (defun gnus-cache-braid-heads (group cached) - (let ((cache-buf (get-buffer-create " *gnus-cache*"))) + (let ((cache-buf (gnus-get-buffer-create " *gnus-cache*"))) (save-excursion (set-buffer cache-buf) - (buffer-disable-undo (current-buffer)) (erase-buffer)) (set-buffer nntp-server-buffer) (goto-char (point-min)) @@ -538,22 +550,22 @@ $ emacs -batch -l ~/.emacs -l gnus -f gnus-jog-cache" (gnus) ;; Go through all groups... (gnus-group-mark-buffer) - (gnus-group-universal-argument - nil nil - (lambda () - (interactive) - (gnus-summary-read-group (gnus-group-group-name) nil t) - ;; ... and enter the articles into the cache. - (when (eq major-mode 'gnus-summary-mode) - (gnus-uu-mark-buffer) - (gnus-cache-enter-article) - (kill-buffer (current-buffer))))))) + (gnus-group-iterate nil + (lambda (group) + (let (gnus-auto-select-next) + (gnus-summary-read-group group nil t) + ;; ... and enter the articles into the cache. + (when (eq major-mode 'gnus-summary-mode) + (gnus-uu-mark-buffer) + (gnus-cache-enter-article) + (kill-buffer (current-buffer)))))))) (defun gnus-cache-read-active (&optional force) "Read the cache active file." (gnus-make-directory gnus-cache-directory) - (if (not (and (file-exists-p gnus-cache-active-file) - (or force (not gnus-cache-active-hashtb)))) + (if (or (not (file-exists-p gnus-cache-active-file)) + (zerop (nth 7 (file-attributes gnus-cache-active-file))) + force) ;; There is no active file, so we generate one. (gnus-cache-generate-active) ;; We simply read the active file. @@ -561,17 +573,17 @@ $ emacs -batch -l ~/.emacs -l gnus -f gnus-jog-cache" (gnus-set-work-buffer) (insert-file-contents gnus-cache-active-file) (gnus-active-to-gnus-format - nil (setq gnus-cache-active-hashtb - (gnus-make-hashtable + nil (setq gnus-cache-active-hashtb + (gnus-make-hashtable (count-lines (point-min) (point-max))))) (setq gnus-cache-active-altered nil)))) - + (defun gnus-cache-write-active (&optional force) "Write the active hashtb to the active file." (when (or force (and gnus-cache-active-hashtb gnus-cache-active-altered)) - (nnheader-temp-write gnus-cache-active-file + (with-temp-file gnus-cache-active-file (mapatoms (lambda (sym) (when (and sym (boundp sym)) @@ -603,20 +615,23 @@ If LOW, update the lower bound instead." (let* ((top (null directory)) (directory (expand-file-name (or directory gnus-cache-directory))) (files (directory-files directory 'full)) - (group + (group (if top "" - (string-match - (concat "^" (file-name-as-directory - (expand-file-name gnus-cache-directory))) + (string-match + (concat "^" (regexp-quote + (file-name-as-directory + (expand-file-name gnus-cache-directory)))) (directory-file-name directory)) - (nnheader-replace-chars-in-string + (nnheader-replace-chars-in-string (substring (directory-file-name directory) (match-end 0)) ?/ ?.))) nums alphs) (when top (gnus-message 5 "Generating the cache active file...") (setq gnus-cache-active-hashtb (gnus-make-hashtable 123))) + (when (string-match "^\\(nn[^_]+\\)_" group) + (setq group (replace-match "\\1:" t t group))) ;; Separate articles from all other files and directories. (while files (if (string-match "^[0-9]+$" (file-name-nondirectory (car files))) @@ -629,7 +644,7 @@ If LOW, update the lower bound instead." ;; Go through all the other files. (while alphs (when (and (file-directory-p (car alphs)) - (not (string-match "^\\.\\.?$" + (not (string-match "^\\." (file-name-nondirectory (car alphs))))) ;; We descend directories. (gnus-cache-generate-active (car alphs))) @@ -649,9 +664,9 @@ If LOW, update the lower bound instead." (defun gnus-cache-move-cache (dir) "Move the cache tree to somewhere else." - (interactive "DMove the cache tree to: ") + (interactive "FMove the cache tree to: ") (rename-file gnus-cache-directory dir)) (provide 'gnus-cache) - + ;;; gnus-cache.el ends here