X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=lisp%2Fgnus-cache.el;h=befdb5c40b003964407860f5fec3c8081b52e01d;hb=e5bec5d05f433a43fa2d14cdb7bebeeefab8835f;hp=acf13b369ca3582d642a7c4473a3291c3e480d85;hpb=2c3c8d504c37c5fa0cf60370b9c0e7460972b9ef;p=elisp%2Fgnus.git- diff --git a/lisp/gnus-cache.el b/lisp/gnus-cache.el index acf13b3..befdb5c 100644 --- a/lisp/gnus-cache.el +++ b/lisp/gnus-cache.el @@ -1,7 +1,10 @@ ;;; gnus-cache.el --- cache interface for Gnus -;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc. +;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000 +;; Free Software Foundation, Inc. ;; Author: Lars Magne Ingebrigtsen +;; Tatsuya Ichikawa +;; MORIOKA Tomohiko ;; Keywords: news ;; This file is part of GNU Emacs. @@ -26,6 +29,7 @@ ;;; Code: (eval-when-compile (require 'cl)) +(eval-when-compile (require 'gnus-clfns)) (require 'gnus) (require 'gnus-int) @@ -35,7 +39,7 @@ (require 'gnus-sum)) (defcustom gnus-cache-active-file - (concat (file-name-as-directory gnus-cache-directory) "active") + (expand-file-name "active" gnus-cache-directory) "*The cache active file." :group 'gnus-cache :type 'file) @@ -60,7 +64,7 @@ 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)) + regexp)) (defcustom gnus-uncacheable-groups nil "*Groups that match this regexp will not be cached. @@ -77,6 +81,9 @@ it's not cached." (defvar gnus-cache-overview-coding-system 'raw-text "Coding system used on Gnus cache files.") +(defvar gnus-cache-coding-system 'raw-text + "Coding system used on Gnus cache files.") + ;;; Internal variables. @@ -85,6 +92,7 @@ it's not cached." (defvar gnus-cache-buffer nil) (defvar gnus-cache-active-hashtb nil) (defvar gnus-cache-active-altered nil) +(defvar gnus-cache-write-file-coding-system 'raw-text) (eval-and-compile (autoload 'nnml-generate-nov-databases-1 "nnml") @@ -124,9 +132,8 @@ it's not cached." (set-buffer buffer) (if (> (buffer-size) 0) ;; Non-empty overview, write it to a file. - (let ((coding-system-for-write - gnus-cache-overview-coding-system)) - (gnus-write-buffer overview-file)) + (gnus-write-buffer-as-coding-system + gnus-cache-overview-coding-system overview-file) ;; Empty overview file, remove it (when (file-exists-p overview-file) (delete-file overview-file)) @@ -147,15 +154,13 @@ it's not cached." (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) + (let ((number article) file) + ;; 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 @@ -175,10 +180,15 @@ it's not cached." t ; The article already is saved. (save-excursion (set-buffer nntp-server-buffer) - (let ((gnus-use-cache nil)) + (require 'gnus-art) + (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) + (gnus-write-buffer-as-coding-system + gnus-cache-write-file-coding-system file) + (setq headers (nnheader-parse-head t)) + (mail-header-set-number headers number) (gnus-cache-change-buffer group) (set-buffer (cdr gnus-cache-buffer)) (goto-char (point-max)) @@ -200,17 +210,7 @@ it's not cached." (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) @@ -264,7 +264,8 @@ it's not cached." (when (file-exists-p file) (erase-buffer) (gnus-kill-all-overlays) - (insert-file-contents file) + (let ((nnheader-file-coding-system gnus-cache-coding-system)) + (nnheader-insert-file-contents file)) t))) (defun gnus-cache-possibly-alter-active (group active) @@ -310,7 +311,9 @@ it's not cached." ;; unsuccessful), so we use the cached headers exclusively. (set-buffer nntp-server-buffer) (erase-buffer) - (insert-file-contents cache-file) + (let ((nnheader-file-coding-system + gnus-cache-overview-coding-system)) + (nnheader-insert-file-contents cache-file)) 'nov) ((eq type 'nov) ;; We have both cached and uncached NOV headers, so we @@ -323,6 +326,65 @@ it's not cached." cached articles)) type))))))) +(defun gnus-cache-retrieve-parsed-headers (articles group &optional fetch-old + dependencies force-new) + "Retrieve the parsed-headers for ARTICLES in GROUP." + (let ((cached + (setq gnus-newsgroup-cached (gnus-cache-articles-in-group group)))) + (if (not cached) + ;; No cached articles here, so we just retrieve them + ;; the normal way. + (let ((gnus-use-cache nil)) + (gnus-retrieve-parsed-headers articles group fetch-old + dependencies force-new)) + (let ((uncached-articles (gnus-sorted-intersection + (gnus-sorted-complement articles cached) + articles)) + (cache-file (gnus-cache-file-name group ".overview"))) + (gnus-cache-braid-headers + ;; We first retrieve all the headers that we don't have in + ;; the cache. + (prog1 + (let ((gnus-use-cache nil)) + (when uncached-articles + (and articles + (gnus-retrieve-parsed-headers + uncached-articles group fetch-old + dependencies)) + )) + (gnus-cache-save-buffers)) + ;; Then we insert the cached headers. + (cond ((not (file-exists-p cache-file)) + ;; There are no cached headers. + ) + ((eq gnus-headers-retrieved-by 'nov) + (with-current-buffer nntp-server-buffer + (erase-buffer) + (nnheader-insert-file-contents cache-file) + (nnheader-get-newsgroup-headers-xover* + articles nil dependencies group) + )) + (t + ;; We braid HEADs. + (nnheader-retrieve-headers-from-directory* + cached + (expand-file-name + (file-name-as-directory + (nnheader-translate-file-chars + (if (gnus-use-long-file-name 'not-cache) + group + (let ((group + (nnheader-replace-chars-in-string group ?/ ?_))) + ;; Translate the first colon into a slash. + (when (string-match ":" group) + (aset group (match-beginning 0) ?/)) + (nnheader-replace-chars-in-string group ?. ?/))) + t)) + gnus-cache-directory) + dependencies) + ))) + )))) + (defun gnus-cache-enter-article (&optional n) "Enter the next N articles into the cache. If not given a prefix, use the process marked articles instead. @@ -369,7 +431,7 @@ 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 (sort (copy-sequence gnus-newsgroup-cached) '<)) + (let ((cached (sort (copy-sequence gnus-newsgroup-cached) '>)) (gnus-verbose (max 6 gnus-verbose))) (unless cached (gnus-message 3 "No cached articles for this group")) @@ -395,7 +457,6 @@ Returns the list of articles removed." (cons group (set-buffer (gnus-get-buffer-create " *gnus-cache-overview*")))) - (buffer-disable-undo (current-buffer)) ;; Insert the contents of this group's cache overview. (erase-buffer) (let ((file (gnus-cache-file-name group ".overview"))) @@ -413,23 +474,28 @@ Returns the list of articles removed." (and (not unread) (not ticked) (not dormant) (memq 'read class)))) (defun gnus-cache-file-name (group article) - (concat (file-name-as-directory gnus-cache-directory) - (file-name-as-directory - (nnheader-translate-file-chars - (if (gnus-use-long-file-name 'not-cache) - group - (let ((group (nnheader-replace-chars-in-string group ?/ ?_))) - ;; Translate the first colon into a slash. - (when (string-match ":" group) - (aset group (match-beginning 0) ?/)) - (nnheader-replace-chars-in-string group ?. ?/))) - t)) - (if (stringp article) article (int-to-string article)))) + (expand-file-name + (if (stringp article) article (int-to-string article)) + (file-name-as-directory + (expand-file-name + (nnheader-translate-file-chars + (if (gnus-use-long-file-name 'not-cache) + group + (let ((group (nnheader-replace-duplicate-chars-in-string + (nnheader-replace-chars-in-string group ?/ ?_) + ?. ?_))) + ;; Translate the first colon into a slash. + (when (string-match ":" group) + (setq group (concat (substring group 0 (match-beginning 0)) + "/" (substring group (match-end 0))))) + (nnheader-replace-chars-in-string group ?. ?/))) + t) + gnus-cache-directory)))) (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) + (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) @@ -487,9 +553,10 @@ Returns the list of articles removed." (gnus-cache-save-buffers) (save-excursion (set-buffer cache-buf) - (buffer-disable-undo (current-buffer)) (erase-buffer) - (insert-file-contents (or file (gnus-cache-file-name group ".overview"))) + (let ((nnheader-file-coding-system gnus-cache-overview-coding-system)) + (nnheader-insert-file-contents + (or file (gnus-cache-file-name group ".overview")))) (goto-char (point-min)) (insert "\n") (goto-char (point-min))) @@ -517,7 +584,6 @@ Returns the list of articles removed." (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)) @@ -532,7 +598,9 @@ Returns the list of articles removed." (save-excursion (set-buffer cache-buf) (erase-buffer) - (insert-file-contents (gnus-cache-file-name group (car cached))) + (let ((nnheader-file-coding-system gnus-cache-coding-system)) + (nnheader-insert-file-contents + (gnus-cache-file-name group (car cached)))) (goto-char (point-min)) (insert "220 ") (princ (car cached) (current-buffer)) @@ -545,6 +613,36 @@ Returns the list of articles removed." (setq cached (cdr cached))) (kill-buffer cache-buf))) +(defun gnus-cache-braid-headers (headers cached-headers) + (if cached-headers + (if headers + (let (cached-header hrest nhrest) + (nconc (catch 'tag + (while cached-headers + (setq cached-header (car cached-headers)) + (if (< (mail-header-number cached-header) + (mail-header-number (car headers))) + (throw 'tag (nreverse cached-headers)) + (setq hrest headers + nhrest (cdr hrest)) + (while (and nhrest + (> (mail-header-number cached-header) + (mail-header-number (car nhrest)))) + (setq hrest nhrest + nhrest (cdr nhrest)) + ) + ;;(if nhrest + (setcdr hrest (cons cached-header nhrest)) + ;; (setq headers + ;; (nconc headers (list cached-header))) + ;; (throw 'tag nil) + ;;) + ) + (setq cached-headers (cdr cached-headers)))) + headers)) + (nreverse cached-headers)) + headers)) + ;;;###autoload (defun gnus-jog-cache () "Go through all groups and put the articles into the cache. @@ -555,6 +653,7 @@ $ emacs -batch -l ~/.emacs -l gnus -f gnus-jog-cache" (let ((gnus-mark-article-hook nil) (gnus-expert-user t) (nnmail-spool-file nil) + (mail-sources nil) (gnus-use-dribble-file nil) (gnus-novice-user nil) (gnus-large-newsgroup nil)) @@ -576,14 +675,14 @@ $ emacs -batch -l ~/.emacs -l gnus -f gnus-jog-cache" "Read the cache active file." (gnus-make-directory gnus-cache-directory) (if (or (not (file-exists-p gnus-cache-active-file)) - (not (zerop (nth 7 (file-attributes 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. (save-excursion (gnus-set-work-buffer) - (insert-file-contents gnus-cache-active-file) + (nnheader-insert-file-contents gnus-cache-active-file) (gnus-active-to-gnus-format nil (setq gnus-cache-active-hashtb (gnus-make-hashtable @@ -595,14 +694,7 @@ $ emacs -batch -l ~/.emacs -l gnus -f gnus-jog-cache" (when (or force (and gnus-cache-active-hashtb gnus-cache-active-altered)) - (nnheader-temp-write gnus-cache-active-file - (mapatoms - (lambda (sym) - (when (and sym (boundp sym)) - (insert (format "%s %d %d y\n" - (symbol-name sym) (cdr (symbol-value sym)) - (car (symbol-value sym)))))) - gnus-cache-active-hashtb)) + (gnus-write-active-file gnus-cache-active-file gnus-cache-active-hashtb t) ;; Mark the active hashtb as unaltered. (setq gnus-cache-active-altered nil))) @@ -672,7 +764,8 @@ If LOW, update the lower bound instead." (interactive (list gnus-cache-directory)) (gnus-cache-close) (let ((nnml-generate-active-function 'identity)) - (nnml-generate-nov-databases-1 dir))) + (nnml-generate-nov-databases-1 dir)) + (gnus-cache-open)) (defun gnus-cache-move-cache (dir) "Move the cache tree to somewhere else."