comparison lisp/gnus/gnus-cache.el @ 85712:a3c27999decb

Update Gnus to No Gnus 0.7 from the Gnus CVS trunk Revision: emacs@sv.gnu.org/emacs--devo--0--patch-911
author Miles Bader <miles@gnu.org>
date Sun, 28 Oct 2007 09:18:39 +0000
parents 24202b793a08
children 781256628613 880960b70474
comparison
equal deleted inserted replaced
85711:b6f5dc84b2e1 85712:a3c27999decb
28 ;;; Code: 28 ;;; Code:
29 29
30 (eval-when-compile (require 'cl)) 30 (eval-when-compile (require 'cl))
31 31
32 (require 'gnus) 32 (require 'gnus)
33 (require 'gnus-int)
34 (require 'gnus-range)
35 (require 'gnus-start)
36 (eval-when-compile 33 (eval-when-compile
37 (if (not (fboundp 'gnus-agent-load-alist)) 34 (unless (fboundp 'gnus-agent-load-alist)
38 (defun gnus-agent-load-alist (group))) 35 (defun gnus-agent-load-alist (group)))
39 (require 'gnus-sum)) 36 (require 'gnus-sum))
40 37
41 (defcustom gnus-cache-active-file 38 (defcustom gnus-cache-active-file
42 (expand-file-name "active" gnus-cache-directory) 39 (expand-file-name "active" gnus-cache-directory)
90 87
91 (defvar gnus-cache-removable-articles nil) 88 (defvar gnus-cache-removable-articles nil)
92 (defvar gnus-cache-buffer nil) 89 (defvar gnus-cache-buffer nil)
93 (defvar gnus-cache-active-hashtb nil) 90 (defvar gnus-cache-active-hashtb nil)
94 (defvar gnus-cache-active-altered nil) 91 (defvar gnus-cache-active-altered nil)
92 (defvar gnus-cache-total-fetched-hashtb nil)
95 93
96 (eval-and-compile 94 (eval-and-compile
97 (autoload 'nnml-generate-nov-databases-1 "nnml") 95 (autoload 'nnml-generate-nov-databases-1 "nnml")
98 (autoload 'nnvirtual-find-group-art "nnvirtual")) 96 (autoload 'nnvirtual-find-group-art "nnvirtual"))
99 97
131 (if (> (buffer-size) 0) 129 (if (> (buffer-size) 0)
132 ;; Non-empty overview, write it to a file. 130 ;; Non-empty overview, write it to a file.
133 (let ((coding-system-for-write 131 (let ((coding-system-for-write
134 gnus-cache-overview-coding-system)) 132 gnus-cache-overview-coding-system))
135 (gnus-write-buffer overview-file)) 133 (gnus-write-buffer overview-file))
136 ;; Empty overview file, remove it 134 (let ((file-name-coding-system nnmail-pathname-coding-system))
137 (when (file-exists-p overview-file) 135 ;; Empty overview file, remove it
138 (delete-file overview-file)) 136 (when (file-exists-p overview-file)
139 ;; If possible, remove group's cache subdirectory. 137 (delete-file overview-file))
140 (condition-case nil 138 ;; If possible, remove group's cache subdirectory.
141 ;; FIXME: we can detect the error type and warn the user 139 (condition-case nil
142 ;; of any inconsistencies (articles w/o nov entries?). 140 ;; FIXME: we can detect the error type and warn the user
143 ;; for now, just be conservative...delete only if safe -- sj 141 ;; of any inconsistencies (articles w/o nov entries?).
144 (delete-directory (file-name-directory overview-file)) 142 ;; for now, just be conservative...delete only if safe -- sj
145 (error nil))))) 143 (delete-directory (file-name-directory overview-file))
144 (error))))
145
146 (gnus-cache-update-overview-total-fetched-for
147 (car gnus-cache-buffer) overview-file)))
146 ;; Kill the buffer -- it's either unmodified or saved. 148 ;; Kill the buffer -- it's either unmodified or saved.
147 (gnus-kill-buffer buffer) 149 (gnus-kill-buffer buffer)
148 (setq gnus-cache-buffer nil)))) 150 (setq gnus-cache-buffer nil))))
149 151
150 (defun gnus-cache-possibly-enter-article 152 (defun gnus-cache-possibly-enter-article
151 (group article ticked dormant unread &optional force) 153 (group article ticked dormant unread &optional force)
152 (when (and (or force (not (eq gnus-use-cache 'passive))) 154 (when (and (or force (not (eq gnus-use-cache 'passive)))
153 (numberp article) 155 (numberp article)
154 (> article 0)) ; This might be a dummy article. 156 (> article 0)) ; This might be a dummy article.
155 (let ((number article) file headers) 157 (let ((number article)
158 file headers lines-chars
159 (file-name-coding-system nnmail-pathname-coding-system))
156 ;; If this is a virtual group, we find the real group. 160 ;; If this is a virtual group, we find the real group.
157 (when (gnus-virtual-group-p group) 161 (when (gnus-virtual-group-p group)
158 (let ((result (nnvirtual-find-group-art 162 (let ((result (nnvirtual-find-group-art
159 (gnus-group-real-name group) article))) 163 (gnus-group-real-name group) article)))
160 (setq group (car result) 164 (setq group (car result)
178 (let ((gnus-use-cache nil) 182 (let ((gnus-use-cache nil)
179 (gnus-article-decode-hook nil)) 183 (gnus-article-decode-hook nil))
180 (gnus-request-article-this-buffer number group)) 184 (gnus-request-article-this-buffer number group))
181 (when (> (buffer-size) 0) 185 (when (> (buffer-size) 0)
182 (let ((coding-system-for-write gnus-cache-coding-system)) 186 (let ((coding-system-for-write gnus-cache-coding-system))
183 (gnus-write-buffer file)) 187 (gnus-write-buffer file)
188 (gnus-cache-update-file-total-fetched-for group file))
189 (setq lines-chars (nnheader-get-lines-and-char))
184 (nnheader-remove-body) 190 (nnheader-remove-body)
185 (setq headers (nnheader-parse-naked-head)) 191 (setq headers (nnheader-parse-naked-head))
186 (mail-header-set-number headers number) 192 (mail-header-set-number headers number)
193 (mail-header-set-lines headers (car lines-chars))
194 (mail-header-set-chars headers (cadr lines-chars))
187 (gnus-cache-change-buffer group) 195 (gnus-cache-change-buffer group)
188 (set-buffer (cdr gnus-cache-buffer)) 196 (set-buffer (cdr gnus-cache-buffer))
189 (goto-char (point-max)) 197 (goto-char (point-max))
190 (forward-line -1) 198 (forward-line -1)
191 (while (condition-case () 199 (while (condition-case ()
234 (setq gnus-cache-removable-articles nil))) 242 (setq gnus-cache-removable-articles nil)))
235 243
236 (defun gnus-cache-possibly-remove-articles-1 () 244 (defun gnus-cache-possibly-remove-articles-1 ()
237 "Possibly remove some of the removable articles." 245 "Possibly remove some of the removable articles."
238 (when (gnus-cache-fully-p gnus-newsgroup-name) 246 (when (gnus-cache-fully-p gnus-newsgroup-name)
239 (let ((articles gnus-cache-removable-articles) 247 (let ((cache-articles gnus-newsgroup-cached))
240 (cache-articles gnus-newsgroup-cached)
241 article)
242 (gnus-cache-change-buffer gnus-newsgroup-name) 248 (gnus-cache-change-buffer gnus-newsgroup-name)
243 (while articles 249 (dolist (article gnus-cache-removable-articles)
244 (when (memq (setq article (pop articles)) cache-articles) 250 (when (memq article cache-articles)
245 ;; The article was in the cache, so we see whether we are 251 ;; The article was in the cache, so we see whether we are
246 ;; supposed to remove it from the cache. 252 ;; supposed to remove it from the cache.
247 (gnus-cache-possibly-remove-article 253 (gnus-cache-possibly-remove-article
248 article (memq article gnus-newsgroup-marked) 254 article (memq article gnus-newsgroup-marked)
249 (memq article gnus-newsgroup-dormant) 255 (memq article gnus-newsgroup-dormant)
254 (gnus-cache-save-buffers))) 260 (gnus-cache-save-buffers)))
255 261
256 (defun gnus-cache-request-article (article group) 262 (defun gnus-cache-request-article (article group)
257 "Retrieve ARTICLE in GROUP from the cache." 263 "Retrieve ARTICLE in GROUP from the cache."
258 (let ((file (gnus-cache-file-name group article)) 264 (let ((file (gnus-cache-file-name group article))
259 (buffer-read-only nil)) 265 (buffer-read-only nil)
266 (file-name-coding-system nnmail-pathname-coding-system))
260 (when (file-exists-p file) 267 (when (file-exists-p file)
261 (erase-buffer) 268 (erase-buffer)
262 (gnus-kill-all-overlays) 269 (gnus-kill-all-overlays)
263 (let ((coding-system-for-read gnus-cache-coding-system)) 270 (let ((coding-system-for-read gnus-cache-coding-system))
264 (insert-file-contents file)) 271 (insert-file-contents file))
283 ;; the normal way. 290 ;; the normal way.
284 (let ((gnus-use-cache nil)) 291 (let ((gnus-use-cache nil))
285 (gnus-retrieve-headers articles group fetch-old)) 292 (gnus-retrieve-headers articles group fetch-old))
286 (let ((uncached-articles (gnus-sorted-difference articles cached)) 293 (let ((uncached-articles (gnus-sorted-difference articles cached))
287 (cache-file (gnus-cache-file-name group ".overview")) 294 (cache-file (gnus-cache-file-name group ".overview"))
288 type) 295 type
296 (file-name-coding-system nnmail-pathname-coding-system))
289 ;; We first retrieve all the headers that we don't have in 297 ;; We first retrieve all the headers that we don't have in
290 ;; the cache. 298 ;; the cache.
291 (let ((gnus-use-cache nil)) 299 (let ((gnus-use-cache nil))
292 (when uncached-articles 300 (when uncached-articles
293 (setq type (and articles 301 (setq type (and articles
323 (defun gnus-cache-enter-article (&optional n) 331 (defun gnus-cache-enter-article (&optional n)
324 "Enter the next N articles into the cache. 332 "Enter the next N articles into the cache.
325 If not given a prefix, use the process marked articles instead. 333 If not given a prefix, use the process marked articles instead.
326 Returns the list of articles entered." 334 Returns the list of articles entered."
327 (interactive "P") 335 (interactive "P")
328 (let ((articles (gnus-summary-work-articles n)) 336 (let (out)
329 article out) 337 (dolist (article (gnus-summary-work-articles n))
330 (while (setq article (pop articles))
331 (gnus-summary-remove-process-mark article) 338 (gnus-summary-remove-process-mark article)
332 (if (natnump article) 339 (if (natnump article)
333 (when (gnus-cache-possibly-enter-article 340 (when (gnus-cache-possibly-enter-article
334 gnus-newsgroup-name article 341 gnus-newsgroup-name article
335 nil nil nil t) 342 nil nil nil t)
346 "Remove the next N articles from the cache. 353 "Remove the next N articles from the cache.
347 If not given a prefix, use the process marked articles instead. 354 If not given a prefix, use the process marked articles instead.
348 Returns the list of articles removed." 355 Returns the list of articles removed."
349 (interactive "P") 356 (interactive "P")
350 (gnus-cache-change-buffer gnus-newsgroup-name) 357 (gnus-cache-change-buffer gnus-newsgroup-name)
351 (let ((articles (gnus-summary-work-articles n)) 358 (let (out)
352 article out) 359 (dolist (article (gnus-summary-work-articles n))
353 (while articles
354 (setq article (pop articles))
355 (gnus-summary-remove-process-mark article) 360 (gnus-summary-remove-process-mark article)
356 (when (gnus-cache-possibly-remove-article article nil nil nil t) 361 (when (gnus-cache-possibly-remove-article article nil nil nil t)
357 (when gnus-newsgroup-agentized 362 (when gnus-newsgroup-agentized
358 (let ((alist (gnus-agent-load-alist gnus-newsgroup-name))) 363 (let ((alist (gnus-agent-load-alist gnus-newsgroup-name)))
359 (unless (cdr (assoc article alist)) 364 (unless (cdr (assoc article alist))
405 (cons group 410 (cons group
406 (set-buffer (gnus-get-buffer-create 411 (set-buffer (gnus-get-buffer-create
407 " *gnus-cache-overview*")))) 412 " *gnus-cache-overview*"))))
408 ;; Insert the contents of this group's cache overview. 413 ;; Insert the contents of this group's cache overview.
409 (erase-buffer) 414 (erase-buffer)
410 (let ((file (gnus-cache-file-name group ".overview"))) 415 (let ((file (gnus-cache-file-name group ".overview"))
416 (file-name-coding-system nnmail-pathname-coding-system))
411 (when (file-exists-p file) 417 (when (file-exists-p file)
412 (nnheader-insert-file-contents file))) 418 (nnheader-insert-file-contents file)))
413 ;; We have a fresh (empty/just loaded) buffer, 419 ;; We have a fresh (empty/just loaded) buffer,
414 ;; mark it as unmodified to save a redundant write later. 420 ;; mark it as unmodified to save a redundant write later.
415 (set-buffer-modified-p nil)))) 421 (set-buffer-modified-p nil))))
419 (or (and ticked (memq 'ticked class)) 425 (or (and ticked (memq 'ticked class))
420 (and dormant (memq 'dormant class)) 426 (and dormant (memq 'dormant class))
421 (and unread (memq 'unread class)) 427 (and unread (memq 'unread class))
422 (and (not unread) (not ticked) (not dormant) (memq 'read class)))) 428 (and (not unread) (not ticked) (not dormant) (memq 'read class))))
423 429
430 (defvar gnus-cache-decoded-group-names nil
431 "Alist of original group names and decoded group names.
432 Decoding is done according to `gnus-group-name-charset-method-alist'
433 or `gnus-group-name-charset-group-alist'.")
434
435 (defvar gnus-cache-unified-group-names nil
436 "Alist of unified decoded group names and original group names.
437 A group name is decoded according to
438 `gnus-group-name-charset-method-alist' or
439 `gnus-group-name-charset-group-alist' first, and is encoded and
440 decoded again according to `nnmail-pathname-coding-system',
441 `file-name-coding-system', or `default-file-name-coding-system'.
442
443 It is used when asking for a original group name from a cache
444 directory name, in which non-ASCII characters might have been unified
445 into the ones of a certain charset particularly if the `utf-8' coding
446 system for example was used.")
447
448 (defun gnus-cache-decoded-group-name (group)
449 "Return a decoded group name of GROUP."
450 (or (cdr (assoc group gnus-cache-decoded-group-names))
451 (let ((decoded (gnus-group-decoded-name group))
452 (coding (or nnmail-pathname-coding-system
453 (and (boundp 'file-name-coding-system)
454 file-name-coding-system)
455 (and (boundp 'default-file-name-coding-system)
456 default-file-name-coding-system))))
457 (push (cons group decoded) gnus-cache-decoded-group-names)
458 (push (cons (mm-decode-coding-string
459 (mm-encode-coding-string decoded coding)
460 coding)
461 group)
462 gnus-cache-unified-group-names)
463 decoded)))
464
424 (defun gnus-cache-file-name (group article) 465 (defun gnus-cache-file-name (group article)
425 (setq group (gnus-group-decoded-name group)) 466 (setq group (gnus-cache-decoded-group-name group))
426 (expand-file-name 467 (expand-file-name
427 (if (stringp article) article (int-to-string article)) 468 (if (stringp article) article (int-to-string article))
428 (file-name-as-directory 469 (file-name-as-directory
429 (expand-file-name 470 (expand-file-name
430 (nnheader-translate-file-chars 471 (nnheader-translate-file-chars
453 (defun gnus-cache-possibly-remove-article (article ticked dormant unread 494 (defun gnus-cache-possibly-remove-article (article ticked dormant unread
454 &optional force) 495 &optional force)
455 "Possibly remove ARTICLE from the cache." 496 "Possibly remove ARTICLE from the cache."
456 (let ((group gnus-newsgroup-name) 497 (let ((group gnus-newsgroup-name)
457 (number article) 498 (number article)
458 file) 499 file
500 (file-name-coding-system nnmail-pathname-coding-system))
459 ;; If this is a virtual group, we find the real group. 501 ;; If this is a virtual group, we find the real group.
460 (when (gnus-virtual-group-p group) 502 (when (gnus-virtual-group-p group)
461 (let ((result (nnvirtual-find-group-art 503 (let ((result (nnvirtual-find-group-art
462 (gnus-group-real-name group) article))) 504 (gnus-group-real-name group) article)))
463 (setq group (car result) 505 (setq group (car result)
466 (when (and (file-exists-p file) 508 (when (and (file-exists-p file)
467 (or force 509 (or force
468 (gnus-cache-member-of-class 510 (gnus-cache-member-of-class
469 gnus-cache-remove-articles ticked dormant unread))) 511 gnus-cache-remove-articles ticked dormant unread)))
470 (save-excursion 512 (save-excursion
513 (gnus-cache-update-file-total-fetched-for group file t)
471 (delete-file file) 514 (delete-file file)
515
472 (set-buffer (cdr gnus-cache-buffer)) 516 (set-buffer (cdr gnus-cache-buffer))
473 (goto-char (point-min)) 517 (goto-char (point-min))
474 (when (or (looking-at (concat (int-to-string number) "\t")) 518 (when (or (looking-at (concat (int-to-string number) "\t"))
475 (search-forward (concat "\n" (int-to-string number) "\t") 519 (search-forward (concat "\n" (int-to-string number) "\t")
476 (point-max) t)) 520 (point-max) t))
477 (gnus-delete-line))) 521 (gnus-delete-line)))
478 (unless (setq gnus-newsgroup-cached 522 (unless (setq gnus-newsgroup-cached
479 (delq article gnus-newsgroup-cached)) 523 (delq article gnus-newsgroup-cached))
480 (gnus-sethash gnus-newsgroup-name nil gnus-cache-active-hashtb) 524 (gnus-sethash gnus-newsgroup-name nil gnus-cache-active-hashtb)
481 (setq gnus-cache-active-altered t)) 525 (setq gnus-cache-active-altered t))
482 (gnus-summary-update-secondary-mark article) 526 (gnus-summary-update-secondary-mark article)
483 t))) 527 t)))
484 528
485 (defun gnus-cache-articles-in-group (group) 529 (defun gnus-cache-articles-in-group (group)
486 "Return a sorted list of cached articles in GROUP." 530 "Return a sorted list of cached articles in GROUP."
487 (let ((dir (file-name-directory (gnus-cache-file-name group 1))) 531 (let ((dir (file-name-directory (gnus-cache-file-name group 1)))
488 articles) 532 articles
533 (file-name-coding-system nnmail-pathname-coding-system))
489 (when (file-exists-p dir) 534 (when (file-exists-p dir)
490 (setq articles 535 (setq articles
491 (sort (mapcar (lambda (name) (string-to-number name)) 536 (sort (mapcar (lambda (name) (string-to-number name))
492 (directory-files dir nil "^[0-9]+$" t)) 537 (directory-files dir nil "^[0-9]+$" t))
493 '<)) 538 '<))
506 beg end) 551 beg end)
507 (gnus-cache-save-buffers) 552 (gnus-cache-save-buffers)
508 (save-excursion 553 (save-excursion
509 (set-buffer cache-buf) 554 (set-buffer cache-buf)
510 (erase-buffer) 555 (erase-buffer)
511 (let ((coding-system-for-read 556 (let ((coding-system-for-read gnus-cache-overview-coding-system)
512 gnus-cache-overview-coding-system)) 557 (file-name-coding-system nnmail-pathname-coding-system))
513 (insert-file-contents 558 (insert-file-contents
514 (or file (gnus-cache-file-name group ".overview")))) 559 (or file (gnus-cache-file-name group ".overview"))))
515 (goto-char (point-min)) 560 (goto-char (point-min))
516 (insert "\n") 561 (insert "\n")
517 (goto-char (point-min))) 562 (goto-char (point-min)))
523 (forward-line 1)) 568 (forward-line 1))
524 (beginning-of-line) 569 (beginning-of-line)
525 (set-buffer cache-buf) 570 (set-buffer cache-buf)
526 (if (search-forward (concat "\n" (int-to-string (car cached)) "\t") 571 (if (search-forward (concat "\n" (int-to-string (car cached)) "\t")
527 nil t) 572 nil t)
528 (setq beg (gnus-point-at-bol) 573 (setq beg (point-at-bol)
529 end (progn (end-of-line) (point))) 574 end (progn (end-of-line) (point)))
530 (setq beg nil)) 575 (setq beg nil))
531 (set-buffer nntp-server-buffer) 576 (set-buffer nntp-server-buffer)
532 (when beg 577 (when beg
533 (insert-buffer-substring cache-buf beg end) 578 (insert-buffer-substring cache-buf beg end)
535 (setq cached (cdr cached))) 580 (setq cached (cdr cached)))
536 (kill-buffer cache-buf))) 581 (kill-buffer cache-buf)))
537 582
538 (defun gnus-cache-braid-heads (group cached) 583 (defun gnus-cache-braid-heads (group cached)
539 (let ((cache-buf (gnus-get-buffer-create " *gnus-cache*"))) 584 (let ((cache-buf (gnus-get-buffer-create " *gnus-cache*")))
540 (save-excursion 585 (with-current-buffer cache-buf
541 (set-buffer cache-buf)
542 (erase-buffer)) 586 (erase-buffer))
543 (set-buffer nntp-server-buffer) 587 (set-buffer nntp-server-buffer)
544 (goto-char (point-min)) 588 (goto-char (point-min))
545 (while cached 589 (dolist (entry cached)
546 (while (and (not (eobp)) 590 (while (and (not (eobp))
547 (looking-at "2.. +\\([0-9]+\\) ") 591 (looking-at "2.. +\\([0-9]+\\) ")
548 (< (progn (goto-char (match-beginning 1)) 592 (< (progn (goto-char (match-beginning 1))
549 (read (current-buffer))) 593 (read (current-buffer)))
550 (car cached))) 594 entry))
551 (search-forward "\n.\n" nil 'move)) 595 (search-forward "\n.\n" nil 'move))
552 (beginning-of-line) 596 (beginning-of-line)
553 (set-buffer cache-buf) 597 (set-buffer cache-buf)
554 (erase-buffer) 598 (erase-buffer)
555 (let ((coding-system-for-read 599 (let ((coding-system-for-read gnus-cache-coding-system)
556 gnus-cache-coding-system)) 600 (file-name-coding-system nnmail-pathname-coding-system))
557 (insert-file-contents (gnus-cache-file-name group (car cached)))) 601 (insert-file-contents (gnus-cache-file-name group entry)))
558 (goto-char (point-min)) 602 (goto-char (point-min))
559 (insert "220 ") 603 (insert "220 ")
560 (princ (car cached) (current-buffer)) 604 (princ (car cached) (current-buffer))
561 (insert " Article retrieved.\n") 605 (insert " Article retrieved.\n")
562 (search-forward "\n\n" nil 'move) 606 (search-forward "\n\n" nil 'move)
563 (delete-region (point) (point-max)) 607 (delete-region (point) (point-max))
564 (forward-char -1) 608 (forward-char -1)
565 (insert ".") 609 (insert ".")
566 (set-buffer nntp-server-buffer) 610 (set-buffer nntp-server-buffer)
567 (insert-buffer-substring cache-buf) 611 (insert-buffer-substring cache-buf))
568 (setq cached (cdr cached)))
569 (kill-buffer cache-buf))) 612 (kill-buffer cache-buf)))
570 613
571 ;;;###autoload 614 ;;;###autoload
572 (defun gnus-jog-cache () 615 (defun gnus-jog-cache ()
573 "Go through all groups and put the articles into the cache. 616 "Go through all groups and put the articles into the cache.
659 (defun gnus-cache-generate-active (&optional directory) 702 (defun gnus-cache-generate-active (&optional directory)
660 "Generate the cache active file." 703 "Generate the cache active file."
661 (interactive) 704 (interactive)
662 (let* ((top (null directory)) 705 (let* ((top (null directory))
663 (directory (expand-file-name (or directory gnus-cache-directory))) 706 (directory (expand-file-name (or directory gnus-cache-directory)))
707 (file-name-coding-system nnmail-pathname-coding-system)
664 (files (directory-files directory 'full)) 708 (files (directory-files directory 'full))
665 (group 709 (group
666 (if top 710 (if top
667 "" 711 ""
668 (string-match 712 (string-match
684 (if (string-match "^[0-9]+$" (file-name-nondirectory (car files))) 728 (if (string-match "^[0-9]+$" (file-name-nondirectory (car files)))
685 (push (string-to-number (file-name-nondirectory (pop files))) nums) 729 (push (string-to-number (file-name-nondirectory (pop files))) nums)
686 (push (pop files) alphs))) 730 (push (pop files) alphs)))
687 ;; If we have nums, then this is probably a valid group. 731 ;; If we have nums, then this is probably a valid group.
688 (when (setq nums (sort nums '<)) 732 (when (setq nums (sort nums '<))
689 (gnus-sethash group (cons (car nums) (gnus-last-element nums)) 733 ;; Use non-decoded group name.
734 ;; FIXME: this is kind of a workaround. The active file should
735 ;; be updated at the time articles are cached. It will make
736 ;; `gnus-cache-unified-group-names' needless.
737 (gnus-sethash (or (cdr (assoc group gnus-cache-unified-group-names))
738 group)
739 (cons (car nums) (gnus-last-element nums))
690 gnus-cache-active-hashtb)) 740 gnus-cache-active-hashtb))
691 ;; Go through all the other files. 741 ;; Go through all the other files.
692 (while alphs 742 (dolist (file alphs)
693 (when (and (file-directory-p (car alphs)) 743 (when (and (file-directory-p file)
694 (not (string-match "^\\." 744 (not (string-match "^\\."
695 (file-name-nondirectory (car alphs))))) 745 (file-name-nondirectory file))))
696 ;; We descend directories. 746 ;; We descend directories.
697 (gnus-cache-generate-active (car alphs))) 747 (gnus-cache-generate-active file)))
698 (setq alphs (cdr alphs)))
699 ;; Write the new active file. 748 ;; Write the new active file.
700 (when top 749 (when top
701 (gnus-cache-write-active t) 750 (gnus-cache-write-active t)
702 (gnus-message 5 "Generating the cache active file...done")))) 751 (gnus-message 5 "Generating the cache active file...done"))))
703 752
706 "Generate NOV files recursively starting in DIR." 755 "Generate NOV files recursively starting in DIR."
707 (interactive (list gnus-cache-directory)) 756 (interactive (list gnus-cache-directory))
708 (gnus-cache-close) 757 (gnus-cache-close)
709 (let ((nnml-generate-active-function 'identity)) 758 (let ((nnml-generate-active-function 'identity))
710 (nnml-generate-nov-databases-1 dir)) 759 (nnml-generate-nov-databases-1 dir))
760
761 (setq gnus-cache-total-fetched-hashtb nil)
762
711 (gnus-cache-open)) 763 (gnus-cache-open))
712 764
713 (defun gnus-cache-move-cache (dir) 765 (defun gnus-cache-move-cache (dir)
714 "Move the cache tree to somewhere else." 766 "Move the cache tree to somewhere else."
715 (interactive "FMove the cache tree to: ") 767 (interactive "FMove the cache tree to: ")
734 Always updates the cache, even when disabled, as the old cache 786 Always updates the cache, even when disabled, as the old cache
735 files would corrupt Gnus when the cache was next enabled. It 787 files would corrupt Gnus when the cache was next enabled. It
736 depends on the caller to determine whether group renaming is 788 depends on the caller to determine whether group renaming is
737 supported." 789 supported."
738 (let ((old-dir (gnus-cache-file-name old-group "")) 790 (let ((old-dir (gnus-cache-file-name old-group ""))
739 (new-dir (gnus-cache-file-name new-group ""))) 791 (new-dir (gnus-cache-file-name new-group ""))
792 (file-name-coding-system nnmail-pathname-coding-system))
740 (gnus-rename-file old-dir new-dir t)) 793 (gnus-rename-file old-dir new-dir t))
794
795 (gnus-cache-rename-group-total-fetched-for old-group new-group)
741 796
742 (let ((no-save gnus-cache-active-hashtb)) 797 (let ((no-save gnus-cache-active-hashtb))
743 (unless gnus-cache-active-hashtb 798 (unless gnus-cache-active-hashtb
744 (gnus-cache-read-active)) 799 (gnus-cache-read-active))
745 (let* ((old-group-hash-value 800 (let* ((old-group-hash-value
760 "Delete GROUP from the cache. 815 "Delete GROUP from the cache.
761 Always updates the cache, even when disabled, as the old cache 816 Always updates the cache, even when disabled, as the old cache
762 files would corrupt gnus when the cache was next enabled. 817 files would corrupt gnus when the cache was next enabled.
763 Depends upon the caller to determine whether group deletion is 818 Depends upon the caller to determine whether group deletion is
764 supported." 819 supported."
765 (let ((dir (gnus-cache-file-name group ""))) 820 (let ((dir (gnus-cache-file-name group ""))
821 (file-name-coding-system nnmail-pathname-coding-system))
766 (gnus-delete-directory dir)) 822 (gnus-delete-directory dir))
823
824 (gnus-cache-delete-group-total-fetched-for group)
767 825
768 (let ((no-save gnus-cache-active-hashtb)) 826 (let ((no-save gnus-cache-active-hashtb))
769 (unless gnus-cache-active-hashtb 827 (unless gnus-cache-active-hashtb
770 (gnus-cache-read-active)) 828 (gnus-cache-read-active))
771 (let* ((group-hash-value (gnus-gethash group gnus-cache-active-hashtb))) 829 (let* ((group-hash-value (gnus-gethash group gnus-cache-active-hashtb)))
773 831
774 (if no-save 832 (if no-save
775 (setq gnus-cache-active-altered group-hash-value) 833 (setq gnus-cache-active-altered group-hash-value)
776 (gnus-cache-write-active group-hash-value))))) 834 (gnus-cache-write-active group-hash-value)))))
777 835
836 (defvar gnus-cache-inhibit-update-total-fetched-for nil)
837 (defvar gnus-cache-need-update-total-fetched-for nil)
838
839 (defmacro gnus-cache-with-refreshed-group (group &rest body)
840 `(prog1 (let ((gnus-cache-inhibit-update-total-fetched-for t))
841 ,@body)
842 (when (and gnus-cache-need-update-total-fetched-for
843 (not gnus-cache-inhibit-update-total-fetched-for))
844 (save-excursion
845 (set-buffer gnus-group-buffer)
846 (setq gnus-cache-need-update-total-fetched-for nil)
847 (gnus-group-update-group ,group t)))))
848
849 (defun gnus-cache-update-file-total-fetched-for (group file &optional subtract)
850 (when gnus-cache-total-fetched-hashtb
851 (gnus-cache-with-refreshed-group
852 group
853 (let* ((entry (or (gnus-gethash group gnus-cache-total-fetched-hashtb)
854 (gnus-sethash group (make-vector 2 0)
855 gnus-cache-total-fetched-hashtb)))
856 size)
857
858 (if file
859 (setq size (or (nth 7 (file-attributes file)) 0))
860 (let* ((file-name-coding-system nnmail-pathname-coding-system)
861 (files (directory-files (gnus-cache-file-name group "")
862 t nil t))
863 file attrs)
864 (setq size 0.0)
865 (while (setq file (pop files))
866 (setq attrs (file-attributes file))
867 (unless (nth 0 attrs)
868 (incf size (float (nth 7 attrs)))))))
869
870 (setq gnus-cache-need-update-total-fetched-for t)
871
872 (incf (nth 1 entry) (if subtract (- size) size))))))
873
874 (defun gnus-cache-update-overview-total-fetched-for (group file)
875 (when gnus-cache-total-fetched-hashtb
876 (gnus-cache-with-refreshed-group
877 group
878 (let* ((entry (or (gnus-gethash group gnus-cache-total-fetched-hashtb)
879 (gnus-sethash group (make-list 2 0)
880 gnus-cache-total-fetched-hashtb)))
881 (file-name-coding-system nnmail-pathname-coding-system)
882 (size (or (nth 7 (file-attributes
883 (or file
884 (gnus-cache-file-name group ".overview"))))
885 0)))
886 (setq gnus-cache-need-update-total-fetched-for t)
887 (setf (nth 0 entry) size)))))
888
889 (defun gnus-cache-rename-group-total-fetched-for (old-group new-group)
890 "Record of disk space used by OLD-GROUP now associated with NEW-GROUP."
891 (when gnus-cache-total-fetched-hashtb
892 (let ((entry (gnus-gethash old-group gnus-cache-total-fetched-hashtb)))
893 (gnus-sethash new-group entry gnus-cache-total-fetched-hashtb)
894 (gnus-sethash old-group nil gnus-cache-total-fetched-hashtb))))
895
896 (defun gnus-cache-delete-group-total-fetched-for (group)
897 "Delete record of disk space used by GROUP being deleted."
898 (when gnus-cache-total-fetched-hashtb
899 (gnus-sethash group nil gnus-cache-total-fetched-hashtb)))
900
901 (defun gnus-cache-total-fetched-for (group &optional no-inhibit)
902 "Get total disk space used by the cache for the specified GROUP."
903 (unless (equal group "dummy.group")
904 (unless gnus-cache-total-fetched-hashtb
905 (setq gnus-cache-total-fetched-hashtb (gnus-make-hashtable 1024)))
906
907 (let* ((entry (gnus-gethash group gnus-cache-total-fetched-hashtb)))
908 (if entry
909 (apply '+ entry)
910 (let ((gnus-cache-inhibit-update-total-fetched-for (not no-inhibit)))
911 (+
912 (gnus-cache-update-overview-total-fetched-for group nil)
913 (gnus-cache-update-file-total-fetched-for group nil)))))))
914
778 (provide 'gnus-cache) 915 (provide 'gnus-cache)
779 916
780 ;;; arch-tag: 05a79442-8c58-4e65-bd0a-3cbb1b89a33a 917 ;;; arch-tag: 05a79442-8c58-4e65-bd0a-3cbb1b89a33a
781 ;;; gnus-cache.el ends here 918 ;;; gnus-cache.el ends here