X-Git-Url: http://cgit.sxemacs.org/?a=blobdiff_plain;f=lisp%2Fgnus-cache.el;h=9c2014eecdbd02cba796aa26b4ef9e230eeb9ab1;hb=b423a72e0858d6510b2652befe441850043dca46;hp=b5c7aaa76b7ad8283e09fa503473251817169b53;hpb=4d7a7e68c1f2f85d35098352b0f870df5168a1b4;p=gnus diff --git a/lisp/gnus-cache.el b/lisp/gnus-cache.el index b5c7aaa76..9c2014eec 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 Free Software Foundation, Inc. -;; Author: Lars Magne Ingebrigtsen +;; Author: Lars Magne Ingebrigtsen ;; Keywords: news ;; This file is part of GNU Emacs. @@ -25,33 +25,45 @@ ;;; Code: -(require 'gnus) (eval-when-compile (require 'cl)) -(defvar gnus-cache-directory - (concat (file-name-as-directory gnus-article-save-directory) "cache/") - "*The directory where cached articles will be stored.") +(require 'gnus) +(require 'gnus-int) +(require 'gnus-range) +(require 'gnus-start) +(eval-when-compile + (require 'gnus-sum)) -(defvar gnus-cache-active-file +(defcustom gnus-cache-active-file (concat (file-name-as-directory gnus-cache-directory) "active") - "*The cache active file.") + "*The cache active file." + :group 'gnus-cache + :type 'file) -(defvar gnus-cache-enter-articles '(ticked dormant) - "*Classes of articles to enter into the cache.") +(defcustom gnus-cache-enter-articles '(ticked dormant) + "Classes of articles to enter into the cache." + :group 'gnus-cache + :type '(set (const ticked) (const dormant) (const unread) (const read))) -(defvar gnus-cache-remove-articles '(read) - "*Classes of articles to remove from the cache.") +(defcustom gnus-cache-remove-articles '(read) + "Classes of articles to remove from the cache." + :group 'gnus-cache + :type '(set (const ticked) (const dormant) (const unread) (const read))) -(defvar gnus-uncacheable-groups nil +(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\"." + :group 'gnus-cache + :type '(choice (const :tag "off" nil) + regexp)) ;;; Internal variables. +(defvar gnus-cache-removable-articles nil) (defvar gnus-cache-buffer nil) (defvar gnus-cache-active-hashtb nil) (defvar gnus-cache-active-altered nil) @@ -66,9 +78,14 @@ variable to \"^nnml\".") (defun gnus-cache-open () "Initialize the cache." - (gnus-cache-read-active)) + (when (or (file-exists-p gnus-cache-directory) + (and gnus-use-cache + (not (eq gnus-use-cache 'passive)))) + (gnus-cache-read-active))) -(gnus-add-shutdown 'gnus-cache-close 'gnus) +;; Complexities of byte-compiling make this kludge necessary. Eeek. +(ignore-errors + (gnus-add-shutdown 'gnus-cache-close 'gnus)) (defun gnus-cache-close () "Shut down the cache." @@ -79,86 +96,85 @@ variable to \"^nnml\".") (defun gnus-cache-save-buffers () ;; save the overview buffer if it exists and has been modified ;; delete empty cache subdirectories - (if (null gnus-cache-buffer) - () + (when gnus-cache-buffer (let ((buffer (cdr gnus-cache-buffer)) (overview-file (gnus-cache-file-name (car gnus-cache-buffer) ".overview"))) ;; write the overview only if it was modified - (if (buffer-modified-p buffer) - (save-excursion - (set-buffer buffer) - (if (> (buffer-size) 0) - ;; non-empty overview, write it out - (progn - (gnus-make-directory (file-name-directory overview-file)) - (write-region (point-min) (point-max) - overview-file nil 'quietly)) - ;; empty overview file, remove it - (and (file-exists-p overview-file) - (delete-file overview-file)) - ;; if possible, remove group's cache subdirectory - (condition-case nil - ;; FIXME: we can detect the error type and warn the user - ;; of any inconsistencies (articles w/o nov entries?). - ;; for now, just be conservative...delete only if safe -- sj - (delete-directory (file-name-directory overview-file)) - (error nil))))) - ;; kill the buffer, it's either unmodified or saved + (when (buffer-modified-p buffer) + (save-excursion + (set-buffer buffer) + (if (> (buffer-size) 0) + ;; Non-empty overview, write it to a file. + (gnus-write-buffer overview-file) + ;; Empty overview file, remove it + (when (file-exists-p overview-file) + (delete-file overview-file)) + ;; If possible, remove group's cache subdirectory. + (condition-case nil + ;; FIXME: we can detect the error type and warn the user + ;; of any inconsistencies (articles w/o nov entries?). + ;; for now, just be conservative...delete only if safe -- sj + (delete-directory (file-name-directory overview-file)) + (error nil))))) + ;; Kill the buffer -- it's either unmodified or saved. (gnus-kill-buffer buffer) (setq gnus-cache-buffer nil)))) -(defun gnus-cache-possibly-enter-article +(defun gnus-cache-possibly-enter-article (group article headers ticked dormant unread &optional force) (when (and (or force (not (eq gnus-use-cache 'passive))) - (vectorp headers)) ; This might be a dummy article. + (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 group article))) + (let ((result (nnvirtual-find-group-art + (gnus-group-real-name group) article))) (setq group (car result) - article (cdr result) headers (copy-sequence headers)) - (aset headers 0 article))) + (mail-header-set-number headers (cdr result)))) (let ((number (mail-header-number headers)) file dir) - (when (and (> number 0) ; Reffed article. - (or (not gnus-uncacheable-groups) - (not (string-match gnus-uncacheable-groups group))) + (when (and number + (> number 0) ; Reffed article. (or force - (gnus-cache-member-of-class - gnus-cache-enter-articles ticked dormant unread)) + (and (or (not gnus-uncacheable-groups) + (not (string-match + gnus-uncacheable-groups group))) + (gnus-cache-member-of-class + gnus-cache-enter-articles ticked dormant unread))) (not (file-exists-p (setq file (gnus-cache-file-name - group article))))) + group number))))) ;; Possibly create the cache directory. - (or (file-exists-p (setq dir (file-name-directory file))) - (gnus-make-directory dir)) + (gnus-make-directory (setq dir (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)) - (gnus-request-article-this-buffer article group)) + (gnus-request-article-this-buffer number group)) (when (> (buffer-size) 0) - (write-region (point-min) (point-max) file nil 'quiet) + (gnus-write-buffer file) (gnus-cache-change-buffer group) (set-buffer (cdr gnus-cache-buffer)) (goto-char (point-max)) (forward-line -1) (while (condition-case () - (and (not (bobp)) - (> (read (current-buffer)) number)) + (when (not (bobp)) + (> (read (current-buffer)) number)) (error ;; The line was malformed, so we just remove it!! (gnus-delete-line) t)) (forward-line -1)) - (if (bobp) + (if (bobp) (if (not (eobp)) (progn (beginning-of-line) - (if (< (read (current-buffer)) number) - (forward-line 1))) + (when (< (read (current-buffer)) number) + (forward-line 1))) (beginning-of-line)) (forward-line 1)) (beginning-of-line) @@ -176,7 +192,7 @@ variable to \"^nnml\".") ;; Update the active info. (set-buffer gnus-summary-buffer) (gnus-cache-update-active group number) - (push number gnus-newsgroup-cached) + (push article gnus-newsgroup-cached) (gnus-summary-update-secondary-mark article)) t)))))) @@ -193,7 +209,7 @@ variable to \"^nnml\".") ga) (while arts (when (setq ga (nnvirtual-find-group-art - gnus-newsgroup-name (pop arts))) + (gnus-group-real-name gnus-newsgroup-name) (pop arts))) (let ((gnus-cache-removable-articles (list (cdr ga))) (gnus-newsgroup-name (car ga))) (gnus-cache-possibly-remove-articles-1))))) @@ -207,14 +223,14 @@ variable to \"^nnml\".") article) (gnus-cache-change-buffer gnus-newsgroup-name) (while articles - (if (memq (setq article (pop articles)) cache-articles) - ;; The article was in the cache, so we see whether we are - ;; supposed to remove it from the cache. - (gnus-cache-possibly-remove-article - article (memq article gnus-newsgroup-marked) - (memq article gnus-newsgroup-dormant) - (or (memq article gnus-newsgroup-unreads) - (memq article gnus-newsgroup-unselected)))))) + (when (memq (setq article (pop articles)) cache-articles) + ;; The article was in the cache, so we see whether we are + ;; supposed to remove it from the cache. + (gnus-cache-possibly-remove-article + article (memq article gnus-newsgroup-marked) + (memq article gnus-newsgroup-dormant) + (or (memq article gnus-newsgroup-unreads) + (memq article gnus-newsgroup-unselected)))))) ;; The overview file might have been modified, save it ;; safe because we're only called at group exit anyway. (gnus-cache-save-buffers))) @@ -231,69 +247,76 @@ variable to \"^nnml\".") (defun gnus-cache-possibly-alter-active (group active) "Alter the ACTIVE info for GROUP to reflect the articles in the cache." - (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 gnus-cache-active-hashtb + (let ((cache-active (gnus-gethash group gnus-cache-active-hashtb))) + (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 - (setq gnus-newsgroup-cached (gnus-cache-articles-in-group group))) - (uncached-articles (gnus-sorted-intersection - (gnus-sorted-complement articles cached) - articles)) - (cache-file (gnus-cache-file-name group ".overview")) - type) - ;; We first retrieve all the headers that we don't have in - ;; the cache. - (let ((gnus-use-cache nil)) - (setq type (and articles - (gnus-retrieve-headers - uncached-articles group fetch-old)))) - (gnus-cache-save-buffers) - ;; Then we insert the cached headers. - (save-excursion - (cond - ((not (file-exists-p cache-file)) - ;; There are no cached headers. - type) - ((null type) - ;; There were no uncached headers (or retrieval was - ;; unsuccessful), so we use the cached headers exclusively. - (set-buffer nntp-server-buffer) - (erase-buffer) - (insert-file-contents cache-file) - 'nov) - ((eq type 'nov) - ;; We have both cached and uncached NOV headers, so we - ;; braid them. - (gnus-cache-braid-nov group cached) - type) - (t - ;; We braid HEADs. - (gnus-cache-braid-heads group (gnus-sorted-intersection - cached articles)) - type))))) + (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-headers articles group fetch-old)) + (let ((uncached-articles (gnus-sorted-intersection + (gnus-sorted-complement articles cached) + articles)) + (cache-file (gnus-cache-file-name group ".overview")) + type) + ;; 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 + uncached-articles group fetch-old))))) + (gnus-cache-save-buffers) + ;; Then we insert the cached headers. + (save-excursion + (cond + ((not (file-exists-p cache-file)) + ;; There are no cached headers. + type) + ((null type) + ;; There were no uncached headers (or retrieval was + ;; unsuccessful), so we use the cached headers exclusively. + (set-buffer nntp-server-buffer) + (erase-buffer) + (insert-file-contents cache-file) + 'nov) + ((eq type 'nov) + ;; We have both cached and uncached NOV headers, so we + ;; braid them. + (gnus-cache-braid-nov group cached) + type) + (t + ;; We braid HEADs. + (gnus-cache-braid-heads group (gnus-sorted-intersection + cached articles)) + type))))))) (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. Returns the list of articles entered." (interactive "P") - (gnus-set-global-variables) (let ((articles (gnus-summary-work-articles n)) article out) - (while articles - (setq article (pop articles)) - (when (gnus-cache-possibly-enter-article - gnus-newsgroup-name article (gnus-summary-article-header article) - nil nil nil t) - (push 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) + nil nil nil t) + (push article out)) + (gnus-message 2 "Can't cache article %d" article)) (gnus-summary-update-secondary-mark article)) (gnus-summary-next-subject 1) (gnus-summary-position-point) @@ -304,15 +327,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) @@ -322,6 +344,19 @@ Returns the list of articles removed." "Say whether ARTICLE is cached in the current group." (memq article gnus-newsgroup-cached)) +(defun gnus-summary-insert-cached-articles () + "Insert all the articles cached for this group into the current buffer." + (interactive) + (let ((cached gnus-newsgroup-cached) + (gnus-verbose (max 6 gnus-verbose))) + (unless cached + (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) @@ -331,51 +366,65 @@ Returns the list of articles removed." ;; Another overview cache is current, save it. (gnus-cache-save-buffers))) ;; if gnus-cache buffer is nil, create it - (or gnus-cache-buffer - ;; Create cache buffer - (save-excursion - (setq gnus-cache-buffer - (cons group - (set-buffer (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"))) - (and (file-exists-p file) - (insert-file-contents file))) - ;; We have a fresh (empty/just loaded) buffer, - ;; mark it as unmodified to save a redundant write later. - (set-buffer-modified-p nil)))) + (unless gnus-cache-buffer + ;; Create cache buffer + (save-excursion + (setq gnus-cache-buffer + (cons group + (set-buffer (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"))) + (when (file-exists-p file) + (nnheader-insert-file-contents file))) + ;; We have a fresh (empty/just loaded) buffer, + ;; mark it as unmodified to save a redundant write later. + (set-buffer-modified-p nil)))) ;; Return whether an article is a member of a class. (defun gnus-cache-member-of-class (class ticked dormant unread) (or (and ticked (memq 'ticked class)) (and dormant (memq 'dormant class)) (and unread (memq 'unread class)) - (and (not unread) (memq 'read class)))) + (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 - (if (gnus-use-long-file-name 'not-cache) - group - (let ((group (concat group ""))) - (if (string-match ":" group) - (aset group (match-beginning 0) ?/)) - (nnheader-replace-chars-in-string group ?. ?/)))) + (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)))) (defun gnus-cache-update-article (group article) "If ARTICLE is in the cache, remove it and re-enter it." - (when (gnus-cache-possibly-remove-article article nil nil nil t) - (gnus-cache-possibly-enter-article - gnus-newsgroup-name article (gnus-summary-article-header article) - nil nil nil t))) + (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) + nil nil nil t)))) -(defun gnus-cache-possibly-remove-article - (article ticked dormant unread &optional force) +(defun gnus-cache-possibly-remove-article (article ticked dormant unread + &optional force) "Possibly remove ARTICLE from the cache." - (let ((file (gnus-cache-file-name gnus-newsgroup-name article))) + (let ((group gnus-newsgroup-name) + (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)))) + (setq file (gnus-cache-file-name group number)) (when (and (file-exists-p file) (or force (gnus-cache-member-of-class @@ -384,11 +433,11 @@ Returns the list of articles removed." (delete-file file) (set-buffer (cdr gnus-cache-buffer)) (goto-char (point-min)) - (if (or (looking-at (concat (int-to-string article) "\t")) - (search-forward (concat "\n" (int-to-string article) "\t") - (point-max) t)) - (delete-region (progn (beginning-of-line) (point)) - (progn (forward-line 1) (point))))) + (when (or (looking-at (concat (int-to-string number) "\t")) + (search-forward (concat "\n" (int-to-string number) "\t") + (point-max) t)) + (delete-region (progn (beginning-of-line) (point)) + (progn (forward-line 1) (point))))) (setq gnus-newsgroup-cached (delq article gnus-newsgroup-cached)) (gnus-summary-update-secondary-mark article) @@ -399,11 +448,17 @@ Returns the list of articles removed." (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) + (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 (get-buffer-create " *gnus-cache*")) beg end) (gnus-cache-save-buffers) @@ -411,7 +466,7 @@ Returns the list of articles removed." (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))) @@ -429,8 +484,9 @@ Returns the list of articles removed." (setq beg (progn (beginning-of-line) (point)) end (progn (end-of-line) (point))) (setq beg nil))) - (if beg (progn (insert-buffer-substring cache-buf beg end) - (insert "\n"))) + (when beg + (insert-buffer-substring cache-buf beg end) + (insert "\n")) (setq cached (cdr cached))) (kill-buffer cache-buf))) @@ -455,7 +511,9 @@ Returns the list of articles removed." (erase-buffer) (insert-file-contents (gnus-cache-file-name group (car cached))) (goto-char (point-min)) - (insert "220 " (int-to-string (car cached)) " Article retrieved.\n") + (insert "220 ") + (princ (car cached) (current-buffer)) + (insert " Article retrieved.\n") (search-forward "\n\n" nil 'move) (delete-region (point) (point-max)) (forward-char -1) @@ -466,7 +524,10 @@ Returns the list of articles removed." ;;;###autoload (defun gnus-jog-cache () - "Go through all groups and put the articles into the cache." + "Go through all groups and put the articles into the cache. + +Usage: +$ emacs -batch -l ~/.emacs -l gnus -f gnus-jog-cache" (interactive) (let ((gnus-mark-article-hook nil) (gnus-expert-user t) @@ -478,20 +539,22 @@ Returns the list of articles removed." (gnus) ;; Go through all groups... (gnus-group-mark-buffer) - (gnus-group-universal-argument - nil nil - (lambda () - (gnus-summary-read-group nil 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." - (if (not (and (file-exists-p gnus-cache-active-file) - (or force (not gnus-cache-active-hashtb)))) + (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)))) + force) ;; There is no active file, so we generate one. (gnus-cache-generate-active) ;; We simply read the active file. @@ -499,28 +562,24 @@ Returns the list of articles removed." (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)) - (save-excursion - (gnus-set-work-buffer) + (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-make-directory (file-name-directory gnus-cache-active-file)) - (write-region - (point-min) (point-max) gnus-cache-active-file nil 'silent)) + gnus-cache-active-hashtb)) ;; Mark the active hashtb as unaltered. (setq gnus-cache-active-altered nil))) @@ -534,9 +593,9 @@ If LOW, update the lower bound instead." ;; Update the lower or upper bound. (if low (setcar active number) - (setcdr active number)) - ;; Mark the active hashtb as altered. - (setq gnus-cache-active-altered t)))) + (setcdr active number))) + ;; Mark the active hashtb as altered. + (setq gnus-cache-active-altered t))) ;;;###autoload (defun gnus-cache-generate-active (&optional directory) @@ -545,14 +604,15 @@ 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) @@ -589,6 +649,11 @@ If LOW, update the lower bound instead." (let ((nnml-generate-active-function 'identity)) (nnml-generate-nov-databases-1 dir))) +(defun gnus-cache-move-cache (dir) + "Move the cache tree to somewhere else." + (interactive "FMove the cache tree to: ") + (rename-file gnus-cache-directory dir)) + (provide 'gnus-cache) - + ;;; gnus-cache.el ends here