Mercurial > emacs
comparison lisp/gnus/gnus-agent.el @ 91085:880960b70474
Merge from emacs--devo--0
Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-283
author | Miles Bader <miles@gnu.org> |
---|---|
date | Sun, 11 Nov 2007 00:56:44 +0000 |
parents | bdb3fe0ba9fa a3c27999decb |
children | 53108e6cea98 |
comparison
equal
deleted
inserted
replaced
91084:a4347a111894 | 91085:880960b70474 |
---|---|
113 "Function to confirm when error happens." | 113 "Function to confirm when error happens." |
114 :version "21.1" | 114 :version "21.1" |
115 :group 'gnus-agent | 115 :group 'gnus-agent |
116 :type 'function) | 116 :type 'function) |
117 | 117 |
118 (defcustom gnus-agent-synchronize-flags t | 118 (defcustom gnus-agent-synchronize-flags nil |
119 "Indicate if flags are synchronized when you plug in. | 119 "Indicate if flags are synchronized when you plug in. |
120 If this is `ask' the hook will query the user." | 120 If this is `ask' the hook will query the user." |
121 ;; If the default switches to something else than nil, then the function | 121 ;; If the default switches to something else than nil, then the function |
122 ;; should be fixed not be exceedingly slow. See 2005-09-20 ChangeLog entry. | 122 ;; should be fixed not be exceedingly slow. See 2005-09-20 ChangeLog entry. |
123 :version "21.1" | 123 :version "21.1" |
249 (defvar gnus-agent-spam-hashtb nil) | 249 (defvar gnus-agent-spam-hashtb nil) |
250 (defvar gnus-agent-file-name nil) | 250 (defvar gnus-agent-file-name nil) |
251 (defvar gnus-agent-send-mail-function nil) | 251 (defvar gnus-agent-send-mail-function nil) |
252 (defvar gnus-agent-file-coding-system 'raw-text) | 252 (defvar gnus-agent-file-coding-system 'raw-text) |
253 (defvar gnus-agent-file-loading-cache nil) | 253 (defvar gnus-agent-file-loading-cache nil) |
254 (defvar gnus-agent-total-fetched-hashtb nil) | |
255 (defvar gnus-agent-inhibit-update-total-fetched-for nil) | |
256 (defvar gnus-agent-need-update-total-fetched-for nil) | |
254 | 257 |
255 ;; Dynamic variables | 258 ;; Dynamic variables |
256 (defvar gnus-headers) | 259 (defvar gnus-headers) |
257 (defvar gnus-score) | 260 (defvar gnus-score) |
261 | |
262 ;; Added to support XEmacs | |
263 (eval-and-compile | |
264 (unless (fboundp 'directory-files-and-attributes) | |
265 (defun directory-files-and-attributes (directory | |
266 &optional full match nosort) | |
267 (let (result) | |
268 (dolist (file (directory-files directory full match nosort)) | |
269 (push (cons file (file-attributes file)) result)) | |
270 (nreverse result))))) | |
258 | 271 |
259 ;;; | 272 ;;; |
260 ;;; Setup | 273 ;;; Setup |
261 ;;; | 274 ;;; |
262 | 275 |
287 (gnus-kill-buffer gnus-agent-overview-buffer)) | 300 (gnus-kill-buffer gnus-agent-overview-buffer)) |
288 | 301 |
289 ;;; | 302 ;;; |
290 ;;; Utility functions | 303 ;;; Utility functions |
291 ;;; | 304 ;;; |
305 | |
306 (defmacro gnus-agent-with-refreshed-group (group &rest body) | |
307 "Performs the body then updates the group's line in the group | |
308 buffer. Automatically blocks multiple updates due to recursion." | |
309 `(prog1 (let ((gnus-agent-inhibit-update-total-fetched-for t)) ,@body) | |
310 (when (and gnus-agent-need-update-total-fetched-for | |
311 (not gnus-agent-inhibit-update-total-fetched-for)) | |
312 (save-excursion | |
313 (set-buffer gnus-group-buffer) | |
314 (setq gnus-agent-need-update-total-fetched-for nil) | |
315 (gnus-group-update-group ,group t))))) | |
292 | 316 |
293 (defun gnus-agent-read-file (file) | 317 (defun gnus-agent-read-file (file) |
294 "Load FILE and do a `read' there." | 318 "Load FILE and do a `read' there." |
295 (with-temp-buffer | 319 (with-temp-buffer |
296 (ignore-errors | 320 (ignore-errors |
343 | 367 |
344 (define-setf-method ,name (category) | 368 (define-setf-method ,name (category) |
345 (let* ((--category--temp-- (make-symbol "--category--")) | 369 (let* ((--category--temp-- (make-symbol "--category--")) |
346 (--value--temp-- (make-symbol "--value--"))) | 370 (--value--temp-- (make-symbol "--value--"))) |
347 (list (list --category--temp--) ; temporary-variables | 371 (list (list --category--temp--) ; temporary-variables |
348 (list category) ; value-forms | 372 (list category) ; value-forms |
349 (list --value--temp--) ; store-variables | 373 (list --value--temp--) ; store-variables |
350 (let* ((category --category--temp--) ; store-form | 374 (let* ((category --category--temp--) ; store-form |
351 (value --value--temp--)) | 375 (value --value--temp--)) |
352 (list (quote gnus-agent-cat-set-property) | 376 (list (quote gnus-agent-cat-set-property) |
353 category | 377 category |
354 (quote (quote ,prop-name)) | 378 (quote (quote ,prop-name)) |
432 (setcdr category (cons cell (cdr category))) | 456 (setcdr category (cons cell (cdr category))) |
433 cell)) groups)))))) | 457 cell)) groups)))))) |
434 | 458 |
435 (defsubst gnus-agent-cat-make (name &optional default-agent-predicate) | 459 (defsubst gnus-agent-cat-make (name &optional default-agent-predicate) |
436 (list name `(agent-predicate . ,(or default-agent-predicate 'false)))) | 460 (list name `(agent-predicate . ,(or default-agent-predicate 'false)))) |
461 | |
462 (defun gnus-agent-read-group () | |
463 "Read a group name in the minibuffer, with completion." | |
464 (let ((def (or (gnus-group-group-name) gnus-newsgroup-name))) | |
465 (when def | |
466 (setq def (gnus-group-decoded-name def))) | |
467 (gnus-group-completing-read (if def | |
468 (concat "Group Name (" def "): ") | |
469 "Group Name: ") | |
470 nil nil t nil nil def))) | |
437 | 471 |
438 ;;; Fetching setup functions. | 472 ;;; Fetching setup functions. |
439 | 473 |
440 (defun gnus-agent-start-fetch () | 474 (defun gnus-agent-start-fetch () |
441 "Initialize data structures for efficient fetching." | 475 "Initialize data structures for efficient fetching." |
890 (let (gnus-command-method old-command-method) | 924 (let (gnus-command-method old-command-method) |
891 (gnus-agent-group-pathname old-group)))) | 925 (gnus-agent-group-pathname old-group)))) |
892 (new-command-method (gnus-find-method-for-group new-group)) | 926 (new-command-method (gnus-find-method-for-group new-group)) |
893 (new-path (directory-file-name | 927 (new-path (directory-file-name |
894 (let (gnus-command-method new-command-method) | 928 (let (gnus-command-method new-command-method) |
895 (gnus-agent-group-pathname new-group))))) | 929 (gnus-agent-group-pathname new-group)))) |
930 (file-name-coding-system nnmail-pathname-coding-system)) | |
896 (gnus-rename-file old-path new-path t) | 931 (gnus-rename-file old-path new-path t) |
897 | 932 |
898 (let* ((old-real-group (gnus-group-real-name old-group)) | 933 (let* ((old-real-group (gnus-group-real-name old-group)) |
899 (new-real-group (gnus-group-real-name new-group)) | 934 (new-real-group (gnus-group-real-name new-group)) |
900 (old-active (gnus-agent-get-group-info old-command-method old-real-group))) | 935 (old-active (gnus-agent-get-group-info old-command-method old-real-group))) |
918 Depends upon the caller to determine whether group deletion is | 953 Depends upon the caller to determine whether group deletion is |
919 supported." | 954 supported." |
920 (let* ((command-method (gnus-find-method-for-group group)) | 955 (let* ((command-method (gnus-find-method-for-group group)) |
921 (path (directory-file-name | 956 (path (directory-file-name |
922 (let (gnus-command-method command-method) | 957 (let (gnus-command-method command-method) |
923 (gnus-agent-group-pathname group))))) | 958 (gnus-agent-group-pathname group)))) |
959 (file-name-coding-system nnmail-pathname-coding-system)) | |
924 (gnus-delete-directory path) | 960 (gnus-delete-directory path) |
925 | 961 |
926 (let* ((real-group (gnus-group-real-name group))) | 962 (let* ((real-group (gnus-group-real-name group))) |
927 (gnus-agent-save-group-info command-method real-group nil) | 963 (gnus-agent-save-group-info command-method real-group nil) |
928 | 964 |
1283 (new (gnus-make-hashtable (count-lines (point-min) (point-max)))) | 1319 (new (gnus-make-hashtable (count-lines (point-min) (point-max)))) |
1284 (file (gnus-agent-lib-file "active"))) | 1320 (file (gnus-agent-lib-file "active"))) |
1285 (gnus-active-to-gnus-format nil new) | 1321 (gnus-active-to-gnus-format nil new) |
1286 (gnus-agent-write-active file new) | 1322 (gnus-agent-write-active file new) |
1287 (erase-buffer) | 1323 (erase-buffer) |
1288 (nnheader-insert-file-contents file)))) | 1324 (let ((nnheader-file-coding-system gnus-agent-file-coding-system)) |
1325 (nnheader-insert-file-contents file))))) | |
1289 | 1326 |
1290 (defun gnus-agent-write-active (file new) | 1327 (defun gnus-agent-write-active (file new) |
1291 (gnus-make-directory (file-name-directory file)) | 1328 (gnus-make-directory (file-name-directory file)) |
1292 (let ((nnmail-active-file-coding-system gnus-agent-file-coding-system)) | 1329 (let ((nnmail-active-file-coding-system gnus-agent-file-coding-system)) |
1293 ;; The hashtable contains real names of groups. However, do NOT | 1330 ;; The hashtable contains real names of groups. However, do NOT |
1396 (save-excursion | 1433 (save-excursion |
1397 (setq oactive-max (read (current-buffer)) ;; max | 1434 (setq oactive-max (read (current-buffer)) ;; max |
1398 oactive-min (read (current-buffer))) ;; min | 1435 oactive-min (read (current-buffer))) ;; min |
1399 (cons oactive-min oactive-max)))))))) | 1436 (cons oactive-min oactive-max)))))))) |
1400 | 1437 |
1438 (defvar gnus-agent-decoded-group-names nil | |
1439 "Alist of non-ASCII group names and decoded ones.") | |
1440 | |
1441 (defun gnus-agent-decoded-group-name (group) | |
1442 "Return a decoded group name of GROUP." | |
1443 (or (cdr (assoc group gnus-agent-decoded-group-names)) | |
1444 (if (string-match "[^\000-\177]" group) | |
1445 (let ((decoded (gnus-group-decoded-name group))) | |
1446 (push (cons group decoded) gnus-agent-decoded-group-names) | |
1447 decoded) | |
1448 group))) | |
1449 | |
1401 (defun gnus-agent-group-path (group) | 1450 (defun gnus-agent-group-path (group) |
1402 "Translate GROUP into a file name." | 1451 "Translate GROUP into a file name." |
1403 | 1452 |
1404 ;; NOTE: This is what nnmail-group-pathname does as of Apr 2003. | 1453 ;; NOTE: This is what nnmail-group-pathname does as of Apr 2003. |
1405 ;; The two methods must be kept synchronized, which is why | 1454 ;; The two methods must be kept synchronized, which is why |
1407 | 1456 |
1408 (setq group | 1457 (setq group |
1409 (nnheader-translate-file-chars | 1458 (nnheader-translate-file-chars |
1410 (nnheader-replace-duplicate-chars-in-string | 1459 (nnheader-replace-duplicate-chars-in-string |
1411 (nnheader-replace-chars-in-string | 1460 (nnheader-replace-chars-in-string |
1412 (gnus-group-real-name (gnus-group-decoded-name group)) | 1461 (gnus-group-real-name (gnus-agent-decoded-group-name group)) |
1413 ?/ ?_) | 1462 ?/ ?_) |
1414 ?. ?_))) | 1463 ?. ?_))) |
1415 (if (or nnmail-use-long-file-names | 1464 (if (or nnmail-use-long-file-names |
1416 (file-directory-p (expand-file-name group (gnus-agent-directory)))) | 1465 (file-directory-p (expand-file-name group (gnus-agent-directory)))) |
1417 group | 1466 group |
1418 (mm-encode-coding-string | 1467 (nnheader-replace-chars-in-string group ?. ?/))) |
1419 (nnheader-replace-chars-in-string group ?. ?/) | |
1420 nnmail-pathname-coding-system))) | |
1421 | 1468 |
1422 (defun gnus-agent-group-pathname (group) | 1469 (defun gnus-agent-group-pathname (group) |
1423 "Translate GROUP into a file name." | 1470 "Translate GROUP into a file name." |
1424 ;; nnagent uses nnmail-group-pathname to read articles while | 1471 ;; nnagent uses nnmail-group-pathname to read articles while |
1425 ;; unplugged. The agent must, therefore, use the same directory | 1472 ;; unplugged. The agent must, therefore, use the same directory |
1426 ;; while plugged. | 1473 ;; while plugged. |
1427 (let ((gnus-command-method (or gnus-command-method | 1474 (nnmail-group-pathname |
1428 (gnus-find-method-for-group group)))) | 1475 (gnus-group-real-name (gnus-agent-decoded-group-name group)) |
1429 (nnmail-group-pathname (gnus-group-real-name | 1476 (if gnus-command-method |
1430 (gnus-group-decoded-name group)) | 1477 (gnus-agent-directory) |
1431 (gnus-agent-directory)))) | 1478 (let ((gnus-command-method (gnus-find-method-for-group group))) |
1479 (gnus-agent-directory))))) | |
1432 | 1480 |
1433 (defun gnus-agent-get-function (method) | 1481 (defun gnus-agent-get-function (method) |
1434 (if (gnus-online method) | 1482 (if (gnus-online method) |
1435 (car method) | 1483 (car method) |
1436 (require 'nnagent) | 1484 (require 'nnagent) |
1530 (let* ((fetched-articles (list nil)) | 1578 (let* ((fetched-articles (list nil)) |
1531 (tail-fetched-articles fetched-articles) | 1579 (tail-fetched-articles fetched-articles) |
1532 (dir (gnus-agent-group-pathname group)) | 1580 (dir (gnus-agent-group-pathname group)) |
1533 (date (time-to-days (current-time))) | 1581 (date (time-to-days (current-time))) |
1534 (case-fold-search t) | 1582 (case-fold-search t) |
1535 pos crosses id) | 1583 pos crosses id |
1584 (file-name-coding-system nnmail-pathname-coding-system)) | |
1536 | 1585 |
1537 (setcar selected-sets (nreverse (car selected-sets))) | 1586 (setcar selected-sets (nreverse (car selected-sets))) |
1538 (setq selected-sets (nreverse selected-sets)) | 1587 (setq selected-sets (nreverse selected-sets)) |
1539 | 1588 |
1540 (gnus-make-directory dir) | 1589 (gnus-make-directory dir) |
1599 tail-fetched-articles (caar pos))) | 1648 tail-fetched-articles (caar pos))) |
1600 (widen) | 1649 (widen) |
1601 (setq pos (cdr pos))))) | 1650 (setq pos (cdr pos))))) |
1602 | 1651 |
1603 (gnus-agent-save-alist group (cdr fetched-articles) date) | 1652 (gnus-agent-save-alist group (cdr fetched-articles) date) |
1653 (gnus-agent-update-files-total-fetched-for group (cdr fetched-articles)) | |
1654 | |
1604 (gnus-message 7 "")) | 1655 (gnus-message 7 "")) |
1605 (cdr fetched-articles)))))) | 1656 (cdr fetched-articles)))))) |
1606 | 1657 |
1607 (defun gnus-agent-unfetch-articles (group articles) | 1658 (defun gnus-agent-unfetch-articles (group articles) |
1608 "Delete ARTICLES that were fetched from GROUP into the agent." | 1659 "Delete ARTICLES that were fetched from GROUP into the agent." |
1609 (when articles | 1660 (when articles |
1610 (gnus-agent-load-alist group) | 1661 (gnus-agent-with-refreshed-group |
1611 (let* ((alist (cons nil gnus-agent-article-alist)) | 1662 group |
1612 (articles (sort articles #'<)) | 1663 (gnus-agent-load-alist group) |
1613 (next-possibility alist) | 1664 (let* ((alist (cons nil gnus-agent-article-alist)) |
1614 (delete-this (pop articles))) | 1665 (articles (sort articles #'<)) |
1615 (while (and (cdr next-possibility) delete-this) | 1666 (next-possibility alist) |
1616 (let ((have-this (caar (cdr next-possibility)))) | 1667 (delete-this (pop articles))) |
1617 (cond ((< delete-this have-this) | 1668 (while (and (cdr next-possibility) delete-this) |
1618 (setq delete-this (pop articles))) | 1669 (let ((have-this (caar (cdr next-possibility)))) |
1619 ((= delete-this have-this) | 1670 (cond |
1620 (let ((timestamp (cdar (cdr next-possibility)))) | 1671 ((< delete-this have-this) |
1621 (when timestamp | 1672 (setq delete-this (pop articles))) |
1622 (let* ((file-name (concat (gnus-agent-group-pathname group) | 1673 ((= delete-this have-this) |
1623 (number-to-string have-this)))) | 1674 (let ((timestamp (cdar (cdr next-possibility)))) |
1624 (delete-file file-name)))) | 1675 (when timestamp |
1625 | 1676 (let* ((file-name (concat (gnus-agent-group-pathname group) |
1626 (setcdr next-possibility (cddr next-possibility))) | 1677 (number-to-string have-this))) |
1627 (t | 1678 (size-file |
1628 (setq next-possibility (cdr next-possibility)))))) | 1679 (float (or (and gnus-agent-total-fetched-hashtb |
1629 (setq gnus-agent-article-alist (cdr alist)) | 1680 (nth 7 (file-attributes file-name))) |
1630 (gnus-agent-save-alist group)))) | 1681 0))) |
1682 (file-name-coding-system | |
1683 nnmail-pathname-coding-system)) | |
1684 (delete-file file-name) | |
1685 (gnus-agent-update-files-total-fetched-for | |
1686 group (- size-file))))) | |
1687 | |
1688 (setcdr next-possibility (cddr next-possibility))) | |
1689 (t | |
1690 (setq next-possibility (cdr next-possibility)))))) | |
1691 (setq gnus-agent-article-alist (cdr alist)) | |
1692 (gnus-agent-save-alist group))))) | |
1631 | 1693 |
1632 (defun gnus-agent-crosspost (crosses article &optional date) | 1694 (defun gnus-agent-crosspost (crosses article &optional date) |
1633 (setq date (or date t)) | 1695 (setq date (or date t)) |
1634 | 1696 |
1635 (let (gnus-agent-article-alist group alist beg end) | 1697 (let (gnus-agent-article-alist group alist beg end) |
1649 (set-buffer (gnus-get-buffer-create (format " *Gnus agent overview %s*" | 1711 (set-buffer (gnus-get-buffer-create (format " *Gnus agent overview %s*" |
1650 group))) | 1712 group))) |
1651 (when (= (point-max) (point-min)) | 1713 (when (= (point-max) (point-min)) |
1652 (push (cons group (current-buffer)) gnus-agent-buffer-alist) | 1714 (push (cons group (current-buffer)) gnus-agent-buffer-alist) |
1653 (ignore-errors | 1715 (ignore-errors |
1654 (nnheader-insert-file-contents | 1716 (let ((file-name-coding-system nnmail-pathname-coding-system)) |
1655 (gnus-agent-article-name ".overview" group)))) | 1717 (nnheader-insert-file-contents |
1718 (gnus-agent-article-name ".overview" group))))) | |
1656 (nnheader-find-nov-line (string-to-number (cdar crosses))) | 1719 (nnheader-find-nov-line (string-to-number (cdar crosses))) |
1657 (insert (string-to-number (cdar crosses))) | 1720 (insert (string-to-number (cdar crosses))) |
1658 (insert-buffer-substring gnus-agent-overview-buffer beg end) | 1721 (insert-buffer-substring gnus-agent-overview-buffer beg end) |
1659 (gnus-agent-check-overview-buffer)) | 1722 (gnus-agent-check-overview-buffer)) |
1660 (setq crosses (cdr crosses))))) | 1723 (setq crosses (cdr crosses))))) |
1661 | 1724 |
1662 (defun gnus-agent-backup-overview-buffer () | 1725 (defun gnus-agent-backup-overview-buffer () |
1663 (when gnus-newsgroup-name | 1726 (when gnus-newsgroup-name |
1664 (let ((root (gnus-agent-article-name ".overview" gnus-newsgroup-name)) | 1727 (let ((root (gnus-agent-article-name ".overview" gnus-newsgroup-name)) |
1665 (cnt 0) | 1728 (cnt 0) |
1666 name) | 1729 name |
1730 (file-name-coding-system nnmail-pathname-coding-system)) | |
1667 (while (file-exists-p | 1731 (while (file-exists-p |
1668 (setq name (concat root "~" | 1732 (setq name (concat root "~" |
1669 (int-to-string (setq cnt (1+ cnt))) "~")))) | 1733 (int-to-string (setq cnt (1+ cnt))) "~")))) |
1670 (write-region (point-min) (point-max) name nil 'no-msg) | 1734 (write-region (point-min) (point-max) name nil 'no-msg) |
1671 (gnus-message 1 "Created backup copy of overview in %s." name))) | 1735 (gnus-message 1 "Created backup copy of overview in %s." name))) |
1695 (or backed-up | 1759 (or backed-up |
1696 (setq backed-up (gnus-agent-backup-overview-buffer))) | 1760 (setq backed-up (gnus-agent-backup-overview-buffer))) |
1697 (gnus-message 1 | 1761 (gnus-message 1 |
1698 "Overview buffer contains garbage '%s'." | 1762 "Overview buffer contains garbage '%s'." |
1699 (buffer-substring | 1763 (buffer-substring |
1700 p (gnus-point-at-eol)))) | 1764 p (point-at-eol)))) |
1701 ((= cur prev-num) | 1765 ((= cur prev-num) |
1702 (or backed-up | 1766 (or backed-up |
1703 (setq backed-up (gnus-agent-backup-overview-buffer))) | 1767 (setq backed-up (gnus-agent-backup-overview-buffer))) |
1704 (gnus-message 1 | 1768 (gnus-message 1 |
1705 "Duplicate overview line for %d" cur) | 1769 "Duplicate overview line for %d" cur) |
1713 (setq prev-num -1)) | 1777 (setq prev-num -1)) |
1714 (t | 1778 (t |
1715 (setq prev-num cur))) | 1779 (setq prev-num cur))) |
1716 (forward-line 1))))))) | 1780 (forward-line 1))))))) |
1717 | 1781 |
1782 (defun gnus-agent-flush-server (&optional server-or-method) | |
1783 "Flush all agent index files for every subscribed group within | |
1784 the given SERVER-OR-METHOD. When called with nil, the current | |
1785 value of gnus-command-method identifies the server." | |
1786 (let* ((gnus-command-method (if server-or-method | |
1787 (gnus-server-to-method server-or-method) | |
1788 gnus-command-method)) | |
1789 (alist gnus-newsrc-alist)) | |
1790 (while alist | |
1791 (let ((entry (pop alist))) | |
1792 (when (gnus-methods-equal-p gnus-command-method (gnus-info-method entry)) | |
1793 (gnus-agent-flush-group (gnus-info-group entry))))))) | |
1794 | |
1795 (defun gnus-agent-flush-group (group) | |
1796 "Flush the agent's index files such that the GROUP no longer | |
1797 appears to have any local content. The actual content, the | |
1798 article files, may then be deleted using gnus-agent-expire-group. | |
1799 If flushing was a mistake, the gnus-agent-regenerate-group method | |
1800 provides an undo mechanism by reconstructing the index files from | |
1801 the article files." | |
1802 (interactive (list (gnus-agent-read-group))) | |
1803 | |
1804 (let* ((gnus-command-method (or gnus-command-method | |
1805 (gnus-find-method-for-group group))) | |
1806 (overview (gnus-agent-article-name ".overview" group)) | |
1807 (agentview (gnus-agent-article-name ".agentview" group)) | |
1808 (file-name-coding-system nnmail-pathname-coding-system)) | |
1809 | |
1810 (if (file-exists-p overview) | |
1811 (delete-file overview)) | |
1812 (if (file-exists-p agentview) | |
1813 (delete-file agentview)) | |
1814 | |
1815 (gnus-agent-update-view-total-fetched-for group nil gnus-command-method) | |
1816 (gnus-agent-update-view-total-fetched-for group t gnus-command-method) | |
1817 | |
1818 ;(gnus-agent-set-local group nil nil) | |
1819 ;(gnus-agent-save-local t) | |
1820 (gnus-agent-save-group-info nil group nil))) | |
1821 | |
1718 (defun gnus-agent-flush-cache () | 1822 (defun gnus-agent-flush-cache () |
1823 "Flush the agent's index files such that the group no longer | |
1824 appears to have any local content. The actual content, the | |
1825 article files, is then deleted using gnus-agent-expire-group. The | |
1826 gnus-agent-regenerate-group method provides an undo mechanism by | |
1827 reconstructing the index files from the article files." | |
1828 (interactive) | |
1719 (save-excursion | 1829 (save-excursion |
1720 (while gnus-agent-buffer-alist | 1830 (let ((file-name-coding-system nnmail-pathname-coding-system)) |
1721 (set-buffer (cdar gnus-agent-buffer-alist)) | 1831 (while gnus-agent-buffer-alist |
1722 (let ((coding-system-for-write | 1832 (set-buffer (cdar gnus-agent-buffer-alist)) |
1723 gnus-agent-file-coding-system)) | 1833 (let ((coding-system-for-write gnus-agent-file-coding-system)) |
1724 (write-region (point-min) (point-max) | 1834 (write-region (point-min) (point-max) |
1725 (gnus-agent-article-name ".overview" | 1835 (gnus-agent-article-name ".overview" |
1726 (caar gnus-agent-buffer-alist)) | 1836 (caar gnus-agent-buffer-alist)) |
1727 nil 'silent)) | 1837 nil 'silent)) |
1728 (setq gnus-agent-buffer-alist (cdr gnus-agent-buffer-alist))) | 1838 (setq gnus-agent-buffer-alist (cdr gnus-agent-buffer-alist))) |
1729 (while gnus-agent-group-alist | 1839 (while gnus-agent-group-alist |
1730 (with-temp-file (gnus-agent-article-name | 1840 (with-temp-file (gnus-agent-article-name |
1731 ".agentview" (caar gnus-agent-group-alist)) | 1841 ".agentview" (caar gnus-agent-group-alist)) |
1732 (princ (cdar gnus-agent-group-alist)) | 1842 (princ (cdar gnus-agent-group-alist)) |
1733 (insert "\n") | 1843 (insert "\n") |
1734 (princ 1 (current-buffer)) | 1844 (princ 1 (current-buffer)) |
1735 (insert "\n")) | 1845 (insert "\n")) |
1736 (setq gnus-agent-group-alist (cdr gnus-agent-group-alist))))) | 1846 (setq gnus-agent-group-alist (cdr gnus-agent-group-alist)))))) |
1737 | 1847 |
1738 ;;;###autoload | 1848 ;;;###autoload |
1739 (defun gnus-agent-find-parameter (group symbol) | 1849 (defun gnus-agent-find-parameter (group symbol) |
1740 "Search for GROUPs SYMBOL in the group's parameters, the group's | 1850 "Search for GROUPs SYMBOL in the group's parameters, the group's |
1741 topic parameters, the group's category, or the customizable | 1851 topic parameters, the group's category, or the customizable |
1775 (cdr active)))) | 1885 (cdr active)))) |
1776 (gnus-uncompress-range (gnus-active group))) | 1886 (gnus-uncompress-range (gnus-active group))) |
1777 (gnus-list-of-unread-articles group))) | 1887 (gnus-list-of-unread-articles group))) |
1778 (gnus-decode-encoded-word-function 'identity) | 1888 (gnus-decode-encoded-word-function 'identity) |
1779 (gnus-decode-encoded-address-function 'identity) | 1889 (gnus-decode-encoded-address-function 'identity) |
1780 (file (gnus-agent-article-name ".overview" group))) | 1890 (file (gnus-agent-article-name ".overview" group)) |
1891 (file-name-coding-system nnmail-pathname-coding-system)) | |
1781 | 1892 |
1782 (unless fetch-all | 1893 (unless fetch-all |
1783 ;; Add articles with marks to the list of article headers we want to | 1894 ;; Add articles with marks to the list of article headers we want to |
1784 ;; fetch. Don't fetch articles solely on the basis of a recent or seen | 1895 ;; fetch. Don't fetch articles solely on the basis of a recent or seen |
1785 ;; mark, but do fetch recent or seen articles if they have other, more | 1896 ;; mark, but do fetch recent or seen articles if they have other, more |
1855 (gnus-agent-braid-nov group articles file) | 1966 (gnus-agent-braid-nov group articles file) |
1856 (let ((coding-system-for-write | 1967 (let ((coding-system-for-write |
1857 gnus-agent-file-coding-system)) | 1968 gnus-agent-file-coding-system)) |
1858 (gnus-agent-check-overview-buffer) | 1969 (gnus-agent-check-overview-buffer) |
1859 (write-region (point-min) (point-max) file nil 'silent)) | 1970 (write-region (point-min) (point-max) file nil 'silent)) |
1971 (gnus-agent-update-view-total-fetched-for group t) | |
1860 (gnus-agent-save-alist group articles nil) | 1972 (gnus-agent-save-alist group articles nil) |
1861 articles) | 1973 articles) |
1862 (ignore-errors | 1974 (ignore-errors |
1863 (erase-buffer) | 1975 (erase-buffer) |
1864 (nnheader-insert-file-contents file))))) | 1976 (nnheader-insert-file-contents file))))) |
1924 ;; Replacing existing NOV entry | 2036 ;; Replacing existing NOV entry |
1925 (delete-region (point) (progn (forward-line 1) (point)))) | 2037 (delete-region (point) (progn (forward-line 1) (point)))) |
1926 (gnus-agent-copy-nov-line (pop articles)) | 2038 (gnus-agent-copy-nov-line (pop articles)) |
1927 | 2039 |
1928 (ignore-errors | 2040 (ignore-errors |
1929 (while articles | 2041 (while articles |
1930 (while (let ((art (read (current-buffer)))) | 2042 (while (let ((art (read (current-buffer)))) |
1931 (cond ((< art (car articles)) | 2043 (cond ((< art (car articles)) |
1932 (forward-line 1) | 2044 (forward-line 1) |
1933 t) | 2045 t) |
1934 ((= art (car articles)) | 2046 ((= art (car articles)) |
1935 (beginning-of-line) | 2047 (beginning-of-line) |
1936 (delete-region | 2048 (delete-region |
1937 (point) (progn (forward-line 1) (point))) | 2049 (point) (progn (forward-line 1) (point))) |
1938 nil) | 2050 nil) |
1939 (t | 2051 (t |
1940 (beginning-of-line) | 2052 (beginning-of-line) |
1941 nil)))) | 2053 nil)))) |
1942 | 2054 |
1943 (gnus-agent-copy-nov-line (pop articles))))) | 2055 (gnus-agent-copy-nov-line (pop articles))))) |
1944 | 2056 |
1945 (goto-char (point-max)) | 2057 (goto-char (point-max)) |
1946 | 2058 |
1947 ;; Append the remaining lines | 2059 ;; Append the remaining lines |
1948 (when articles | 2060 (when articles |
1955 (insert-buffer-substring gnus-agent-overview-buffer start) | 2067 (insert-buffer-substring gnus-agent-overview-buffer start) |
1956 (goto-char p)) | 2068 (goto-char p)) |
1957 | 2069 |
1958 (setq last (or last -134217728)) | 2070 (setq last (or last -134217728)) |
1959 (while (catch 'problems | 2071 (while (catch 'problems |
1960 (let (sort art) | 2072 (let (sort art) |
1961 (while (not (eobp)) | 2073 (while (not (eobp)) |
1962 (setq art (gnus-agent-read-article-number)) | 2074 (setq art (gnus-agent-read-article-number)) |
1963 (cond ((not art) | 2075 (cond ((not art) |
1964 ;; Bad art num - delete this line | 2076 ;; Bad art num - delete this line |
1965 (beginning-of-line) | 2077 (beginning-of-line) |
1966 (delete-region (point) (progn (forward-line 1) (point)))) | 2078 (delete-region (point) (progn (forward-line 1) (point)))) |
1967 ((< art last) | 2079 ((< art last) |
1968 ;; Art num out of order - enable sort | 2080 ;; Art num out of order - enable sort |
1969 (setq sort t) | 2081 (setq sort t) |
1970 (forward-line 1)) | 2082 (forward-line 1)) |
1971 ((= art last) | 2083 ((= art last) |
1972 ;; Bad repeat of art number - delete this line | 2084 ;; Bad repeat of art number - delete this line |
1973 (beginning-of-line) | 2085 (beginning-of-line) |
1974 (delete-region (point) (progn (forward-line 1) (point)))) | 2086 (delete-region (point) (progn (forward-line 1) (point)))) |
1975 (t | 2087 (t |
1976 ;; Good art num | 2088 ;; Good art num |
1977 (setq last art) | 2089 (setq last art) |
1978 (forward-line 1)))) | 2090 (forward-line 1)))) |
1979 (when sort | 2091 (when sort |
1980 ;; something is seriously wrong as we simply shouldn't see out-of-order data. | 2092 ;; something is seriously wrong as we simply shouldn't see out-of-order data. |
1981 ;; First, we'll fix the sort. | 2093 ;; First, we'll fix the sort. |
1982 (sort-numeric-fields 1 (point-min) (point-max)) | 2094 (sort-numeric-fields 1 (point-min) (point-max)) |
1983 | 2095 |
1984 ;; but now we have to consider that we may have duplicate rows... | 2096 ;; but now we have to consider that we may have duplicate rows... |
1996 (defvar gnus-agent-read-agentview)) | 2108 (defvar gnus-agent-read-agentview)) |
1997 | 2109 |
1998 (defun gnus-agent-load-alist (group) | 2110 (defun gnus-agent-load-alist (group) |
1999 "Load the article-state alist for GROUP." | 2111 "Load the article-state alist for GROUP." |
2000 ;; Bind free variable that's used in `gnus-agent-read-agentview'. | 2112 ;; Bind free variable that's used in `gnus-agent-read-agentview'. |
2001 (let ((gnus-agent-read-agentview group)) | 2113 (let ((gnus-agent-read-agentview group) |
2114 (file-name-coding-system nnmail-pathname-coding-system)) | |
2002 (setq gnus-agent-article-alist | 2115 (setq gnus-agent-article-alist |
2003 (gnus-cache-file-contents | 2116 (gnus-cache-file-contents |
2004 (gnus-agent-article-name ".agentview" group) | 2117 (gnus-agent-article-name ".agentview" group) |
2005 'gnus-agent-file-loading-cache | 2118 'gnus-agent-file-loading-cache |
2006 'gnus-agent-read-agentview)))) | 2119 'gnus-agent-read-agentview)))) |
2007 | 2120 |
2008 (defun gnus-agent-read-agentview (file) | 2121 (defun gnus-agent-read-agentview (file) |
2009 "Load FILE and do a `read' there." | 2122 "Load FILE and do a `read' there." |
2010 (with-temp-buffer | 2123 (with-temp-buffer |
2011 (condition-case nil | 2124 (condition-case nil |
2012 (progn | 2125 (progn |
2013 (nnheader-insert-file-contents file) | 2126 (nnheader-insert-file-contents file) |
2014 (goto-char (point-min)) | 2127 (goto-char (point-min)) |
2015 (let ((alist (read (current-buffer))) | 2128 (let ((alist (read (current-buffer))) |
2016 (version (condition-case nil (read (current-buffer)) | 2129 (version (condition-case nil (read (current-buffer)) |
2017 (end-of-file 0))) | 2130 (end-of-file 0))) |
2018 changed-version) | 2131 changed-version) |
2019 | 2132 |
2020 (cond | 2133 (cond |
2021 ((= version 0) | 2134 ((= version 0) |
2022 (let ((inhibit-quit t) | 2135 (let ((inhibit-quit t) |
2023 entry) | 2136 entry) |
2024 (gnus-agent-open-history) | 2137 (gnus-agent-open-history) |
2025 (set-buffer (gnus-agent-history-buffer)) | 2138 (set-buffer (gnus-agent-history-buffer)) |
2026 (goto-char (point-min)) | 2139 (goto-char (point-min)) |
2027 (while (not (eobp)) | 2140 (while (not (eobp)) |
2028 (if (and (looking-at | 2141 (if (and (looking-at |
2029 "[^\t\n]+\t\\([0-9]+\\)\t\\([^ \n]+\\) \\([0-9]+\\)") | 2142 "[^\t\n]+\t\\([0-9]+\\)\t\\([^ \n]+\\) \\([0-9]+\\)") |
2030 (string= (match-string 2) | 2143 (string= (match-string 2) |
2031 gnus-agent-read-agentview) | 2144 gnus-agent-read-agentview) |
2032 (setq entry (assoc (string-to-number (match-string 3)) alist))) | 2145 (setq entry (assoc (string-to-number (match-string 3)) alist))) |
2033 (setcdr entry (string-to-number (match-string 1)))) | 2146 (setcdr entry (string-to-number (match-string 1)))) |
2034 (forward-line 1)) | 2147 (forward-line 1)) |
2035 (gnus-agent-close-history) | 2148 (gnus-agent-close-history) |
2036 (setq changed-version t))) | 2149 (setq changed-version t))) |
2037 ((= version 1) | 2150 ((= version 1) |
2038 (setq changed-version (not (= 1 gnus-agent-article-alist-save-format)))) | 2151 (setq changed-version (not (= 1 gnus-agent-article-alist-save-format)))) |
2039 ((= version 2) | 2152 ((= version 2) |
2040 (let (uncomp) | 2153 (let (state sequence uncomp) |
2041 (mapcar | 2154 (while alist |
2042 (lambda (comp-list) | 2155 (setq state (caar alist) |
2043 (let ((state (car comp-list)) | 2156 sequence (inline (gnus-uncompress-range (cdar alist))) |
2044 (sequence (inline | 2157 alist (cdr alist)) |
2045 (gnus-uncompress-range | 2158 (while sequence |
2046 (cdr comp-list))))) | 2159 (push (cons (pop sequence) state) uncomp))) |
2047 (mapcar (lambda (article-id) | |
2048 (setq uncomp (cons (cons article-id state) uncomp))) | |
2049 sequence))) | |
2050 alist) | |
2051 (setq alist (sort uncomp 'car-less-than-car))) | 2160 (setq alist (sort uncomp 'car-less-than-car))) |
2052 (setq changed-version (not (= 2 gnus-agent-article-alist-save-format))))) | 2161 (setq changed-version (not (= 2 gnus-agent-article-alist-save-format))))) |
2053 (when changed-version | 2162 (when changed-version |
2054 (let ((gnus-agent-article-alist alist)) | 2163 (let ((gnus-agent-article-alist alist)) |
2055 (gnus-agent-save-alist gnus-agent-read-agentview))) | 2164 (gnus-agent-save-alist gnus-agent-read-agentview))) |
2056 alist)) | 2165 alist)) |
2057 (file-error nil)))) | 2166 ((end-of-file file-error) |
2167 ;; The agentview file is missing. | |
2168 (condition-case nil | |
2169 ;; If the agent directory exists, attempt to perform a brute-force | |
2170 ;; reconstruction of its contents. | |
2171 (let* (alist | |
2172 (file-name-coding-system nnmail-pathname-coding-system) | |
2173 (file-attributes (directory-files-and-attributes | |
2174 (gnus-agent-article-name "" | |
2175 gnus-agent-read-agentview) nil "^[0-9]+$" t))) | |
2176 (while file-attributes | |
2177 (let ((fa (pop file-attributes))) | |
2178 (unless (nth 1 fa) | |
2179 (push (cons (string-to-number (nth 0 fa)) (time-to-days (nth 5 fa))) alist)))) | |
2180 alist) | |
2181 (file-error nil)))))) | |
2058 | 2182 |
2059 (defun gnus-agent-save-alist (group &optional articles state) | 2183 (defun gnus-agent-save-alist (group &optional articles state) |
2060 "Save the article-state alist for GROUP." | 2184 "Save the article-state alist for GROUP." |
2061 (let* ((file-name-coding-system nnmail-pathname-coding-system) | 2185 (let* ((file-name-coding-system nnmail-pathname-coding-system) |
2062 (prev (cons nil gnus-agent-article-alist)) | 2186 (prev (cons nil gnus-agent-article-alist)) |
2083 (gnus-make-directory (gnus-agent-article-name "" group)) | 2207 (gnus-make-directory (gnus-agent-article-name "" group)) |
2084 (with-temp-file (gnus-agent-article-name ".agentview" group) | 2208 (with-temp-file (gnus-agent-article-name ".agentview" group) |
2085 (cond ((eq gnus-agent-article-alist-save-format 1) | 2209 (cond ((eq gnus-agent-article-alist-save-format 1) |
2086 (princ gnus-agent-article-alist (current-buffer))) | 2210 (princ gnus-agent-article-alist (current-buffer))) |
2087 ((eq gnus-agent-article-alist-save-format 2) | 2211 ((eq gnus-agent-article-alist-save-format 2) |
2088 (let ((compressed nil)) | 2212 (let ((alist gnus-agent-article-alist) |
2089 (mapcar (lambda (pair) | 2213 article-id day-of-download comp-list compressed) |
2090 (let* ((article-id (car pair)) | 2214 (while alist |
2091 (day-of-download (cdr pair)) | 2215 (setq article-id (caar alist) |
2092 (comp-list (assq day-of-download compressed))) | 2216 day-of-download (cdar alist) |
2093 (if comp-list | 2217 comp-list (assq day-of-download compressed) |
2094 (setcdr comp-list | 2218 alist (cdr alist)) |
2095 (cons article-id (cdr comp-list))) | 2219 (if comp-list |
2096 (setq compressed | 2220 (setcdr comp-list (cons article-id (cdr comp-list))) |
2097 (cons (list day-of-download article-id) | 2221 (push (list day-of-download article-id) compressed))) |
2098 compressed))) | 2222 (setq alist compressed) |
2099 nil)) gnus-agent-article-alist) | 2223 (while alist |
2100 (mapcar (lambda (comp-list) | 2224 (setq comp-list (pop alist)) |
2101 (setcdr comp-list | 2225 (setcdr comp-list |
2102 (gnus-compress-sequence | 2226 (gnus-compress-sequence (nreverse (cdr comp-list))))) |
2103 (nreverse (cdr comp-list))))) | |
2104 compressed) | |
2105 (princ compressed (current-buffer))))) | 2227 (princ compressed (current-buffer))))) |
2106 (insert "\n") | 2228 (insert "\n") |
2107 (princ gnus-agent-article-alist-save-format (current-buffer)) | 2229 (princ gnus-agent-article-alist-save-format (current-buffer)) |
2108 (insert "\n")))) | 2230 (insert "\n")) |
2231 | |
2232 (gnus-agent-update-view-total-fetched-for group nil))) | |
2109 | 2233 |
2110 (defvar gnus-agent-article-local nil) | 2234 (defvar gnus-agent-article-local nil) |
2111 (defvar gnus-agent-file-loading-local nil) | 2235 (defvar gnus-agent-file-loading-local nil) |
2112 | 2236 |
2113 (defun gnus-agent-load-local (&optional method) | 2237 (defun gnus-agent-load-local (&optional method) |
2181 (let* ((gnus-command-method (symbol-value (intern "+method" my-obarray))) | 2305 (let* ((gnus-command-method (symbol-value (intern "+method" my-obarray))) |
2182 ;; NOTE: gnus-command-method is used within gnus-agent-lib-file. | 2306 ;; NOTE: gnus-command-method is used within gnus-agent-lib-file. |
2183 (dest (gnus-agent-lib-file "local"))) | 2307 (dest (gnus-agent-lib-file "local"))) |
2184 (gnus-make-directory (gnus-agent-lib-file "")) | 2308 (gnus-make-directory (gnus-agent-lib-file "")) |
2185 | 2309 |
2186 (let ((buffer-file-coding-system gnus-agent-file-coding-system)) | 2310 (let ((coding-system-for-write gnus-agent-file-coding-system) |
2311 (file-name-coding-system nnmail-pathname-coding-system)) | |
2187 (with-temp-file dest | 2312 (with-temp-file dest |
2188 (let ((gnus-command-method (symbol-value (intern "+method" my-obarray))) | 2313 (let ((gnus-command-method (symbol-value (intern "+method" my-obarray))) |
2189 (file-name-coding-system nnmail-pathname-coding-system) | |
2190 print-level print-length item article | 2314 print-level print-length item article |
2191 (standard-output (current-buffer))) | 2315 (standard-output (current-buffer))) |
2192 (mapatoms (lambda (symbol) | 2316 (mapatoms (lambda (symbol) |
2193 (cond ((not (boundp symbol)) | 2317 (cond ((not (boundp symbol)) |
2194 nil) | 2318 nil) |
2195 ((member (symbol-name symbol) '("+dirty" "+method")) | 2319 ((member (symbol-name symbol) '("+dirty" "+method")) |
2196 nil) | 2320 nil) |
2197 (t | 2321 (t |
2198 (let ((range (symbol-value symbol))) | 2322 (let ((range (symbol-value symbol))) |
2199 (when range | 2323 (when range |
2200 (prin1 symbol) | 2324 (prin1 symbol) |
2201 (princ " ") | 2325 (princ " ") |
2202 (princ (car range)) | 2326 (princ (car range)) |
2203 (princ " ") | 2327 (princ " ") |
2204 (princ (cdr range)) | 2328 (princ (cdr range)) |
2205 (princ "\n")))))) | 2329 (princ "\n")))))) |
2206 my-obarray)))))))) | 2330 my-obarray)))))))) |
2207 | 2331 |
2208 (defun gnus-agent-get-local (group &optional gmane method) | 2332 (defun gnus-agent-get-local (group &optional gmane method) |
2209 (let* ((gmane (or gmane (gnus-group-real-name group))) | 2333 (let* ((gmane (or gmane (gnus-group-real-name group))) |
2460 (gnus-summary-set-agent-mark article t)) | 2584 (gnus-summary-set-agent-mark article t)) |
2461 (dolist (article fetched-articles) | 2585 (dolist (article fetched-articles) |
2462 (when gnus-agent-mark-unread-after-downloaded | 2586 (when gnus-agent-mark-unread-after-downloaded |
2463 (setq gnus-newsgroup-downloadable | 2587 (setq gnus-newsgroup-downloadable |
2464 (delq article gnus-newsgroup-downloadable)) | 2588 (delq article gnus-newsgroup-downloadable)) |
2465 (gnus-summary-mark-article | 2589 (gnus-summary-mark-article |
2466 article gnus-unread-mark)) | 2590 article gnus-unread-mark)) |
2467 (when (gnus-summary-goto-subject article nil t) | 2591 (when (gnus-summary-goto-subject article nil t) |
2468 (gnus-summary-update-download-mark article))) | 2592 (gnus-summary-update-download-mark article))) |
2469 (dolist (article unfetched-articles) | 2593 (dolist (article unfetched-articles) |
2470 (gnus-summary-mark-article | 2594 (gnus-summary-mark-article |
2471 article gnus-canceled-mark))) | 2595 article gnus-canceled-mark))) |
2652 (gnus-category-insert-line (pop alist))) | 2776 (gnus-category-insert-line (pop alist))) |
2653 (goto-char (point-min)) | 2777 (goto-char (point-min)) |
2654 (gnus-category-position-point))) | 2778 (gnus-category-position-point))) |
2655 | 2779 |
2656 (defun gnus-category-name () | 2780 (defun gnus-category-name () |
2657 (or (intern (get-text-property (gnus-point-at-bol) 'gnus-category)) | 2781 (or (intern (get-text-property (point-at-bol) 'gnus-category)) |
2658 (error "No category on the current line"))) | 2782 (error "No category on the current line"))) |
2659 | 2783 |
2660 (defun gnus-category-read () | 2784 (defun gnus-category-read () |
2661 "Read the category alist." | 2785 "Read the category alist." |
2662 (setq gnus-category-alist | 2786 (setq gnus-category-alist |
2973 The articles on which the expiration process runs are selected as follows: | 3097 The articles on which the expiration process runs are selected as follows: |
2974 if ARTICLES is null, all read and unmarked articles. | 3098 if ARTICLES is null, all read and unmarked articles. |
2975 if ARTICLES is t, all articles. | 3099 if ARTICLES is t, all articles. |
2976 if ARTICLES is a list, just those articles. | 3100 if ARTICLES is a list, just those articles. |
2977 FORCE is equivalent to setting the expiration predicates to true." | 3101 FORCE is equivalent to setting the expiration predicates to true." |
2978 (interactive | 3102 (interactive (list (gnus-agent-read-group))) |
2979 (list (let ((def (or (gnus-group-group-name) | |
2980 gnus-newsgroup-name))) | |
2981 (let ((select (read-string (if def | |
2982 (concat "Group Name (" | |
2983 def "): ") | |
2984 "Group Name: ")))) | |
2985 (if (and (equal "" select) | |
2986 def) | |
2987 def | |
2988 select))))) | |
2989 | 3103 |
2990 (if (not group) | 3104 (if (not group) |
2991 (gnus-agent-expire articles group force) | 3105 (gnus-agent-expire articles group force) |
2992 (let ( ;; Bind gnus-agent-expire-stats to enable tracking of | 3106 (let ( ;; Bind gnus-agent-expire-stats to enable tracking of |
2993 ;; expiration statistics of this single group | 3107 ;; expiration statistics of this single group |
2994 (gnus-agent-expire-stats (list 0 0 0.0))) | 3108 (gnus-agent-expire-stats (list 0 0 0.0))) |
2995 (if (or (not (eq articles t)) | 3109 (if (or (not (eq articles t)) |
2996 (yes-or-no-p | 3110 (yes-or-no-p |
2997 (concat "Are you sure that you want to " | 3111 (concat "Are you sure that you want to " |
2998 "expire all articles in " group "? "))) | 3112 "expire all articles in " group "? "))) |
3018 (defun gnus-agent-expire-group-1 (group overview active articles force) | 3132 (defun gnus-agent-expire-group-1 (group overview active articles force) |
3019 ;; Internal function - requires caller to have set | 3133 ;; Internal function - requires caller to have set |
3020 ;; gnus-command-method, initialized overview buffer, and to have | 3134 ;; gnus-command-method, initialized overview buffer, and to have |
3021 ;; provided a non-nil active | 3135 ;; provided a non-nil active |
3022 | 3136 |
3023 (let ((dir (gnus-agent-group-pathname group))) | 3137 (let ((dir (gnus-agent-group-pathname group)) |
3024 (when (boundp 'gnus-agent-expire-current-dirs) | 3138 (file-name-coding-system nnmail-pathname-coding-system) |
3025 (set 'gnus-agent-expire-current-dirs | 3139 (decoded (gnus-agent-decoded-group-name group))) |
3026 (cons dir | 3140 (gnus-agent-with-refreshed-group |
3027 (symbol-value 'gnus-agent-expire-current-dirs)))) | 3141 group |
3028 | 3142 (when (boundp 'gnus-agent-expire-current-dirs) |
3029 (if (and (not force) | 3143 (set 'gnus-agent-expire-current-dirs |
3030 (eq 'DISABLE (gnus-agent-find-parameter group | 3144 (cons dir |
3031 'agent-enable-expiration))) | 3145 (symbol-value 'gnus-agent-expire-current-dirs)))) |
3032 (gnus-message 5 "Expiry skipping over %s" group) | 3146 |
3033 (gnus-message 5 "Expiring articles in %s" group) | 3147 (if (and (not force) |
3034 (gnus-agent-load-alist group) | 3148 (eq 'DISABLE (gnus-agent-find-parameter group |
3035 (let* ((bytes-freed 0) | 3149 'agent-enable-expiration))) |
3036 (files-deleted 0) | 3150 (gnus-message 5 "Expiry skipping over %s" decoded) |
3037 (nov-entries-deleted 0) | 3151 (gnus-message 5 "Expiring articles in %s" decoded) |
3038 (info (gnus-get-info group)) | 3152 (gnus-agent-load-alist group) |
3039 (alist gnus-agent-article-alist) | 3153 (let* ((bytes-freed 0) |
3040 (day (- (time-to-days (current-time)) | 3154 (size-files-deleted 0.0) |
3041 (gnus-agent-find-parameter group 'agent-days-until-old))) | 3155 (files-deleted 0) |
3042 (specials (if (and alist | 3156 (nov-entries-deleted 0) |
3043 (not force)) | 3157 (info (gnus-get-info group)) |
3044 ;; This could be a bit of a problem. I need to | 3158 (alist gnus-agent-article-alist) |
3045 ;; keep the last article to avoid refetching | 3159 (day (- (time-to-days (current-time)) |
3046 ;; headers when using nntp in the backend. At | 3160 (gnus-agent-find-parameter group 'agent-days-until-old))) |
3047 ;; the same time, if someone uses a backend | 3161 (specials (if (and alist |
3048 ;; that supports article moving then I may have | 3162 (not force)) |
3049 ;; to remove the last article to complete the | 3163 ;; This could be a bit of a problem. I need to |
3050 ;; move. Right now, I'm going to assume that | 3164 ;; keep the last article to avoid refetching |
3051 ;; FORCE overrides specials. | 3165 ;; headers when using nntp in the backend. At |
3052 (list (caar (last alist))))) | 3166 ;; the same time, if someone uses a backend |
3053 (unreads ;; Articles that are excluded from the | 3167 ;; that supports article moving then I may have |
3054 ;; expiration process | 3168 ;; to remove the last article to complete the |
3055 (cond (gnus-agent-expire-all | 3169 ;; move. Right now, I'm going to assume that |
3056 ;; All articles are marked read by global decree | 3170 ;; FORCE overrides specials. |
3057 nil) | 3171 (list (caar (last alist))))) |
3058 ((eq articles t) | 3172 (unreads ;; Articles that are excluded from the |
3059 ;; All articles are marked read by function | 3173 ;; expiration process |
3060 ;; parameter | 3174 (cond (gnus-agent-expire-all |
3061 nil) | 3175 ;; All articles are marked read by global decree |
3062 ((not articles) | 3176 nil) |
3063 ;; Unread articles are marked protected from | 3177 ((eq articles t) |
3064 ;; expiration Don't call | 3178 ;; All articles are marked read by function |
3065 ;; gnus-list-of-unread-articles as it returns | 3179 ;; parameter |
3066 ;; articles that have not been fetched into the | 3180 nil) |
3067 ;; agent. | 3181 ((not articles) |
3068 (ignore-errors | 3182 ;; Unread articles are marked protected from |
3069 (gnus-agent-unread-articles group))) | 3183 ;; expiration Don't call |
3070 (t | 3184 ;; gnus-list-of-unread-articles as it returns |
3071 ;; All articles EXCEPT those named by the caller | 3185 ;; articles that have not been fetched into the |
3072 ;; are protected from expiration | 3186 ;; agent. |
3073 (gnus-sorted-difference | 3187 (ignore-errors |
3074 (gnus-uncompress-range | 3188 (gnus-agent-unread-articles group))) |
3075 (cons (caar alist) | 3189 (t |
3076 (caar (last alist)))) | 3190 ;; All articles EXCEPT those named by the caller |
3077 (sort articles '<))))) | 3191 ;; are protected from expiration |
3078 (marked ;; More articles that are excluded from the | 3192 (gnus-sorted-difference |
3079 ;; expiration process | 3193 (gnus-uncompress-range |
3080 (cond (gnus-agent-expire-all | 3194 (cons (caar alist) |
3081 ;; All articles are unmarked by global decree | 3195 (caar (last alist)))) |
3082 nil) | 3196 (sort articles '<))))) |
3083 ((eq articles t) | 3197 (marked ;; More articles that are excluded from the |
3084 ;; All articles are unmarked by function | 3198 ;; expiration process |
3085 ;; parameter | 3199 (cond (gnus-agent-expire-all |
3086 nil) | 3200 ;; All articles are unmarked by global decree |
3087 (articles | 3201 nil) |
3088 ;; All articles may as well be unmarked as the | 3202 ((eq articles t) |
3089 ;; unreads list already names the articles we are | 3203 ;; All articles are unmarked by function |
3090 ;; going to keep | 3204 ;; parameter |
3091 nil) | 3205 nil) |
3092 (t | 3206 (articles |
3093 ;; Ticked and/or dormant articles are excluded | 3207 ;; All articles may as well be unmarked as the |
3094 ;; from expiration | 3208 ;; unreads list already names the articles we are |
3095 (nconc | 3209 ;; going to keep |
3096 (gnus-uncompress-range | 3210 nil) |
3097 (cdr (assq 'tick (gnus-info-marks info)))) | 3211 (t |
3098 (gnus-uncompress-range | 3212 ;; Ticked and/or dormant articles are excluded |
3099 (cdr (assq 'dormant | 3213 ;; from expiration |
3100 (gnus-info-marks info)))))))) | 3214 (nconc |
3101 (nov-file (concat dir ".overview")) | 3215 (gnus-uncompress-range |
3102 (cnt 0) | 3216 (cdr (assq 'tick (gnus-info-marks info)))) |
3103 (completed -1) | 3217 (gnus-uncompress-range |
3104 dlist | 3218 (cdr (assq 'dormant |
3105 type) | 3219 (gnus-info-marks info)))))))) |
3106 | 3220 (nov-file (concat dir ".overview")) |
3107 ;; The normal article alist contains elements that look like | 3221 (cnt 0) |
3108 ;; (article# . fetch_date) I need to combine other | 3222 (completed -1) |
3109 ;; information with this list. For example, a flag indicating | 3223 dlist |
3110 ;; that a particular article MUST BE KEPT. To do this, I'm | 3224 type) |
3111 ;; going to transform the elements to look like (article# | 3225 |
3112 ;; fetch_date keep_flag NOV_entry_marker) Later, I'll reverse | 3226 ;; The normal article alist contains elements that look like |
3113 ;; the process to generate the expired article alist. | 3227 ;; (article# . fetch_date) I need to combine other |
3114 | 3228 ;; information with this list. For example, a flag indicating |
3115 ;; Convert the alist elements to (article# fetch_date nil | 3229 ;; that a particular article MUST BE KEPT. To do this, I'm |
3116 ;; nil). | 3230 ;; going to transform the elements to look like (article# |
3117 (setq dlist (mapcar (lambda (e) | 3231 ;; fetch_date keep_flag NOV_entry_position) Later, I'll reverse |
3118 (list (car e) (cdr e) nil nil)) alist)) | 3232 ;; the process to generate the expired article alist. |
3119 | 3233 |
3120 ;; Convert the keep lists to elements that look like (article# | 3234 ;; Convert the alist elements to (article# fetch_date nil |
3121 ;; nil keep_flag nil) then append it to the expanded dlist | 3235 ;; nil). |
3122 ;; These statements are sorted by ascending precidence of the | 3236 (setq dlist (mapcar (lambda (e) |
3123 ;; keep_flag. | 3237 (list (car e) (cdr e) nil nil)) alist)) |
3124 (setq dlist (nconc dlist | 3238 |
3125 (mapcar (lambda (e) | 3239 ;; Convert the keep lists to elements that look like (article# |
3126 (list e nil 'unread nil)) | 3240 ;; nil keep_flag nil) then append it to the expanded dlist |
3127 unreads))) | 3241 ;; These statements are sorted by ascending precidence of the |
3128 (setq dlist (nconc dlist | 3242 ;; keep_flag. |
3129 (mapcar (lambda (e) | 3243 (setq dlist (nconc dlist |
3130 (list e nil 'marked nil)) | 3244 (mapcar (lambda (e) |
3131 marked))) | 3245 (list e nil 'unread nil)) |
3132 (setq dlist (nconc dlist | 3246 unreads))) |
3133 (mapcar (lambda (e) | 3247 (setq dlist (nconc dlist |
3134 (list e nil 'special nil)) | 3248 (mapcar (lambda (e) |
3135 specials))) | 3249 (list e nil 'marked nil)) |
3136 | 3250 marked))) |
3137 (set-buffer overview) | 3251 (setq dlist (nconc dlist |
3138 (erase-buffer) | 3252 (mapcar (lambda (e) |
3139 (buffer-disable-undo) | 3253 (list e nil 'special nil)) |
3140 (when (file-exists-p nov-file) | 3254 specials))) |
3141 (gnus-message 7 "gnus-agent-expire: Loading overview...") | 3255 |
3142 (nnheader-insert-file-contents nov-file) | 3256 (set-buffer overview) |
3143 (goto-char (point-min)) | 3257 (erase-buffer) |
3144 | 3258 (buffer-disable-undo) |
3145 (let (p) | 3259 (when (file-exists-p nov-file) |
3146 (while (< (setq p (point)) (point-max)) | 3260 (gnus-message 7 "gnus-agent-expire: Loading overview...") |
3147 (condition-case nil | 3261 (nnheader-insert-file-contents nov-file) |
3148 ;; If I successfully read an integer (the plus zero | 3262 (goto-char (point-min)) |
3149 ;; ensures a numeric type), prepend a marker entry | 3263 |
3150 ;; to the list | 3264 (let (p) |
3151 (push (list (+ 0 (read (current-buffer))) nil nil | 3265 (while (< (setq p (point)) (point-max)) |
3152 (set-marker (make-marker) p)) | 3266 (condition-case nil |
3153 dlist) | 3267 ;; If I successfully read an integer (the plus zero |
3154 (error | 3268 ;; ensures a numeric type), append the position |
3155 (gnus-message 1 "gnus-agent-expire: read error \ | 3269 ;; to the list |
3270 (push (list (+ 0 (read (current-buffer))) nil nil | |
3271 p) | |
3272 dlist) | |
3273 (error | |
3274 (gnus-message 1 "gnus-agent-expire: read error \ | |
3156 occurred when reading expression at %s in %s. Skipping to next \ | 3275 occurred when reading expression at %s in %s. Skipping to next \ |
3157 line." (point) nov-file))) | 3276 line." (point) nov-file))) |
3158 ;; Whether I succeeded, or failed, it doesn't matter. | 3277 ;; Whether I succeeded, or failed, it doesn't matter. |
3159 ;; Move to the next line then try again. | 3278 ;; Move to the next line then try again. |
3160 (forward-line 1))) | 3279 (forward-line 1))) |
3161 | 3280 |
3162 (gnus-message | 3281 (gnus-message |
3163 7 "gnus-agent-expire: Loading overview... Done")) | 3282 7 "gnus-agent-expire: Loading overview... Done")) |
3164 (set-buffer-modified-p nil) | 3283 (set-buffer-modified-p nil) |
3165 | 3284 |
3166 ;; At this point, all of the information is in dlist. The | 3285 ;; At this point, all of the information is in dlist. The |
3167 ;; only problem is that much of it is spread across multiple | 3286 ;; only problem is that much of it is spread across multiple |
3168 ;; entries. Sort then MERGE!! | 3287 ;; entries. Sort then MERGE!! |
3169 (gnus-message 7 "gnus-agent-expire: Sorting entries... ") | 3288 (gnus-message 7 "gnus-agent-expire: Sorting entries... ") |
3170 ;; If two entries have the same article-number then sort by | 3289 ;; If two entries have the same article-number then sort by |
3171 ;; ascending keep_flag. | 3290 ;; ascending keep_flag. |
3172 (let ((special 0) | 3291 (let ((special 0) |
3173 (marked 1) | 3292 (marked 1) |
3174 (unread 2)) | 3293 (unread 2)) |
3175 (setq dlist | 3294 (setq dlist |
3176 (sort dlist | 3295 (sort dlist |
3177 (lambda (a b) | 3296 (lambda (a b) |
3178 (cond ((< (nth 0 a) (nth 0 b)) | 3297 (cond ((< (nth 0 a) (nth 0 b)) |
3179 t) | 3298 t) |
3180 ((> (nth 0 a) (nth 0 b)) | 3299 ((> (nth 0 a) (nth 0 b)) |
3181 nil) | 3300 nil) |
3182 (t | 3301 (t |
3183 (let ((a (or (symbol-value (nth 2 a)) | 3302 (let ((a (or (symbol-value (nth 2 a)) |
3184 3)) | 3303 3)) |
3185 (b (or (symbol-value (nth 2 b)) | 3304 (b (or (symbol-value (nth 2 b)) |
3186 3))) | 3305 3))) |
3187 (<= a b)))))))) | 3306 (<= a b)))))))) |
3188 (gnus-message 7 "gnus-agent-expire: Sorting entries... Done") | 3307 (gnus-message 7 "gnus-agent-expire: Sorting entries... Done") |
3189 (gnus-message 7 "gnus-agent-expire: Merging entries... ") | 3308 (gnus-message 7 "gnus-agent-expire: Merging entries... ") |
3190 (let ((dlist dlist)) | 3309 (let ((dlist dlist)) |
3191 (while (cdr dlist) ; I'm not at the end-of-list | 3310 (while (cdr dlist) ; I'm not at the end-of-list |
3192 (if (eq (caar dlist) (caadr dlist)) | 3311 (if (eq (caar dlist) (caadr dlist)) |
3193 (let ((first (cdr (car dlist))) | 3312 (let ((first (cdr (car dlist))) |
3194 (secnd (cdr (cadr dlist)))) | 3313 (secnd (cdr (cadr dlist)))) |
3195 (setcar first (or (car first) | 3314 (setcar first (or (car first) |
3196 (car secnd))) ; fetch_date | 3315 (car secnd))) ; fetch_date |
3197 (setq first (cdr first) | 3316 (setq first (cdr first) |
3198 secnd (cdr secnd)) | 3317 secnd (cdr secnd)) |
3199 (setcar first (or (car first) | 3318 (setcar first (or (car first) |
3200 (car secnd))) ; Keep_flag | 3319 (car secnd))) ; Keep_flag |
3201 (setq first (cdr first) | 3320 (setq first (cdr first) |
3202 secnd (cdr secnd)) | 3321 secnd (cdr secnd)) |
3203 (setcar first (or (car first) | 3322 (setcar first (or (car first) |
3204 (car secnd))) ; NOV_entry_marker | 3323 (car secnd))) ; NOV_entry_position |
3205 | 3324 |
3206 (setcdr dlist (cddr dlist))) | 3325 (setcdr dlist (cddr dlist))) |
3207 (setq dlist (cdr dlist))))) | 3326 (setq dlist (cdr dlist))))) |
3208 (gnus-message 7 "gnus-agent-expire: Merging entries... Done") | 3327 |
3209 | 3328 ;; Check the order of the entry positions. They should be in |
3210 (let* ((len (float (length dlist))) | 3329 ;; ascending order. If they aren't, the positions must be |
3211 (alist (list nil)) | 3330 ;; converted to markers. |
3212 (tail-alist alist)) | 3331 (when (catch 'sort-results |
3213 (while dlist | 3332 (let ((dlist dlist) |
3214 (let ((new-completed (truncate (* 100.0 | 3333 (prev-pos -1) |
3215 (/ (setq cnt (1+ cnt)) | 3334 pos) |
3216 len)))) | 3335 (while dlist |
3217 message-log-max) | 3336 (if (setq pos (nth 3 (pop dlist))) |
3218 (when (> new-completed completed) | 3337 (if (< pos prev-pos) |
3219 (setq completed new-completed) | 3338 (throw 'sort-results 'unsorted) |
3220 (gnus-message 7 "%3d%% completed..." completed))) | 3339 (setq prev-pos pos)))))) |
3221 (let* ((entry (car dlist)) | 3340 (gnus-message 7 "gnus-agent-expire: Unsorted overview; inserting markers to compensate.") |
3222 (article-number (nth 0 entry)) | 3341 (mapc (lambda (entry) |
3223 (fetch-date (nth 1 entry)) | 3342 (let ((pos (nth 3 entry))) |
3224 (keep (nth 2 entry)) | 3343 (if pos |
3225 (marker (nth 3 entry))) | 3344 (setf (nth 3 entry) |
3226 | 3345 (set-marker (make-marker) |
3227 (cond | 3346 pos))))) |
3228 ;; Kept articles are unread, marked, or special. | 3347 dlist)) |
3229 (keep | 3348 |
3230 (gnus-agent-message 10 | 3349 (gnus-message 7 "gnus-agent-expire: Merging entries... Done") |
3231 "gnus-agent-expire: %s:%d: Kept %s article%s." | 3350 |
3232 group article-number keep (if fetch-date " and file" "")) | 3351 (let* ((len (float (length dlist))) |
3233 (when fetch-date | 3352 (alist (list nil)) |
3234 (unless (file-exists-p | 3353 (tail-alist alist) |
3235 (concat dir (number-to-string | 3354 (position-offset 0) |
3236 article-number))) | 3355 ) |
3237 (setf (nth 1 entry) nil) | 3356 |
3238 (gnus-agent-message 3 "gnus-agent-expire cleared \ | 3357 (while dlist |
3358 (let ((new-completed (truncate (* 100.0 | |
3359 (/ (setq cnt (1+ cnt)) | |
3360 len)))) | |
3361 message-log-max) | |
3362 (when (> new-completed completed) | |
3363 (setq completed new-completed) | |
3364 (gnus-message 7 "%3d%% completed..." completed))) | |
3365 (let* ((entry (car dlist)) | |
3366 (article-number (nth 0 entry)) | |
3367 (fetch-date (nth 1 entry)) | |
3368 (keep (nth 2 entry)) | |
3369 (marker (nth 3 entry))) | |
3370 | |
3371 (cond | |
3372 ;; Kept articles are unread, marked, or special. | |
3373 (keep | |
3374 (gnus-agent-message 10 | |
3375 "gnus-agent-expire: %s:%d: Kept %s article%s." | |
3376 decoded article-number keep (if fetch-date " and file" "")) | |
3377 (when fetch-date | |
3378 (unless (file-exists-p | |
3379 (concat dir (number-to-string | |
3380 article-number))) | |
3381 (setf (nth 1 entry) nil) | |
3382 (gnus-agent-message 3 "gnus-agent-expire cleared \ | |
3239 download flag on %s:%d as the cached article file is missing." | 3383 download flag on %s:%d as the cached article file is missing." |
3240 group (caar dlist))) | 3384 decoded (caar dlist))) |
3241 (unless marker | 3385 (unless marker |
3242 (gnus-message 1 "gnus-agent-expire detected a \ | 3386 (gnus-message 1 "gnus-agent-expire detected a \ |
3243 missing NOV entry. Run gnus-agent-regenerate-group to restore it."))) | 3387 missing NOV entry. Run gnus-agent-regenerate-group to restore it."))) |
3244 (gnus-agent-append-to-list | 3388 (gnus-agent-append-to-list |
3245 tail-alist | 3389 tail-alist |
3246 (cons article-number fetch-date))) | 3390 (cons article-number fetch-date))) |
3247 | 3391 |
3248 ;; The following articles are READ, UNMARKED, and | 3392 ;; The following articles are READ, UNMARKED, and |
3249 ;; ORDINARY. See if they can be EXPIRED!!! | 3393 ;; ORDINARY. See if they can be EXPIRED!!! |
3250 ((setq type | 3394 ((setq type |
3251 (cond | 3395 (cond |
3252 ((not (integerp fetch-date)) | 3396 ((not (integerp fetch-date)) |
3253 'read) ;; never fetched article (may expire | 3397 'read) ;; never fetched article (may expire |
3254 ;; right now) | 3398 ;; right now) |
3255 ((not (file-exists-p | 3399 ((not (file-exists-p |
3256 (concat dir (number-to-string | 3400 (concat dir (number-to-string |
3257 article-number)))) | 3401 article-number)))) |
3258 (setf (nth 1 entry) nil) | 3402 (setf (nth 1 entry) nil) |
3259 'externally-expired) ;; Can't find the cached | 3403 'externally-expired) ;; Can't find the cached |
3260 ;; article. Handle case | 3404 ;; article. Handle case |
3261 ;; as though this article | 3405 ;; as though this article |
3262 ;; was never fetched. | 3406 ;; was never fetched. |
3263 | 3407 |
3264 ;; We now have the arrival day, so we see | 3408 ;; We now have the arrival day, so we see |
3265 ;; whether it's old enough to be expired. | 3409 ;; whether it's old enough to be expired. |
3266 ((< fetch-date day) | 3410 ((< fetch-date day) |
3267 'expired) | 3411 'expired) |
3268 (force | 3412 (force |
3269 'forced))) | 3413 'forced))) |
3270 | 3414 |
3271 ;; I found some reason to expire this entry. | 3415 ;; I found some reason to expire this entry. |
3272 | 3416 |
3273 (let ((actions nil)) | 3417 (let ((actions nil)) |
3274 (when (memq type '(forced expired)) | 3418 (when (memq type '(forced expired)) |
3275 (ignore-errors ; Just being paranoid. | 3419 (ignore-errors ; Just being paranoid. |
3276 (let* ((file-name (nnheader-concat dir (number-to-string | 3420 (let* ((file-name (nnheader-concat dir (number-to-string |
3277 article-number))) | 3421 article-number))) |
3278 (size (float (nth 7 (file-attributes file-name))))) | 3422 (size (float (nth 7 (file-attributes file-name))))) |
3279 (incf bytes-freed size) | 3423 (incf bytes-freed size) |
3280 (incf files-deleted) | 3424 (incf size-files-deleted size) |
3281 (delete-file file-name)) | 3425 (incf files-deleted) |
3282 (push "expired cached article" actions)) | 3426 (delete-file file-name)) |
3283 (setf (nth 1 entry) nil) | 3427 (push "expired cached article" actions)) |
3284 ) | 3428 (setf (nth 1 entry) nil) |
3285 | 3429 ) |
3286 (when marker | 3430 |
3287 (push "NOV entry removed" actions) | 3431 (when marker |
3288 (goto-char marker) | 3432 (push "NOV entry removed" actions) |
3289 | 3433 |
3290 (incf nov-entries-deleted) | 3434 (goto-char (if (markerp marker) |
3291 | 3435 marker |
3292 (let ((from (gnus-point-at-bol)) | 3436 (- marker position-offset))) |
3293 (to (progn (forward-line 1) (point)))) | 3437 |
3294 (incf bytes-freed (- to from)) | 3438 (incf nov-entries-deleted) |
3295 (delete-region from to))) | 3439 |
3296 | 3440 (let* ((from (point-at-bol)) |
3297 ;; If considering all articles is set, I can only | 3441 (to (progn (forward-line 1) (point))) |
3298 ;; expire article IDs that are no longer in the | 3442 (freed (- to from))) |
3299 ;; active range (That is, articles that preceed the | 3443 (incf bytes-freed freed) |
3300 ;; first article in the new alist). | 3444 (incf position-offset freed) |
3301 (if (and gnus-agent-consider-all-articles | 3445 (delete-region from to))) |
3302 (>= article-number (car active))) | 3446 |
3303 ;; I have to keep this ID in the alist | 3447 ;; If considering all articles is set, I can only |
3304 (gnus-agent-append-to-list | 3448 ;; expire article IDs that are no longer in the |
3305 tail-alist (cons article-number fetch-date)) | 3449 ;; active range (That is, articles that preceed the |
3306 (push (format "Removed %s article number from \ | 3450 ;; first article in the new alist). |
3451 (if (and gnus-agent-consider-all-articles | |
3452 (>= article-number (car active))) | |
3453 ;; I have to keep this ID in the alist | |
3454 (gnus-agent-append-to-list | |
3455 tail-alist (cons article-number fetch-date)) | |
3456 (push (format "Removed %s article number from \ | |
3307 article alist" type) actions)) | 3457 article alist" type) actions)) |
3308 | 3458 |
3309 (when actions | 3459 (when actions |
3310 (gnus-agent-message 8 "gnus-agent-expire: %s:%d: %s" | 3460 (gnus-agent-message 8 "gnus-agent-expire: %s:%d: %s" |
3311 group article-number | 3461 decoded article-number |
3312 (mapconcat 'identity actions ", "))))) | 3462 (mapconcat 'identity actions ", "))))) |
3313 (t | 3463 (t |
3314 (gnus-agent-message | 3464 (gnus-agent-message |
3315 10 "gnus-agent-expire: %s:%d: Article kept as \ | 3465 10 "gnus-agent-expire: %s:%d: Article kept as \ |
3316 expiration tests failed." group article-number) | 3466 expiration tests failed." decoded article-number) |
3317 (gnus-agent-append-to-list | 3467 (gnus-agent-append-to-list |
3318 tail-alist (cons article-number fetch-date))) | 3468 tail-alist (cons article-number fetch-date))) |
3319 ) | 3469 ) |
3320 | 3470 |
3321 ;; Clean up markers as I want to recycle this buffer | 3471 ;; Remove markers as I intend to reuse this buffer again. |
3322 ;; over several groups. | 3472 (when (and marker |
3323 (when marker | 3473 (markerp marker)) |
3324 (set-marker marker nil)) | 3474 (set-marker marker nil)) |
3325 | 3475 |
3326 (setq dlist (cdr dlist)))) | 3476 (setq dlist (cdr dlist)))) |
3327 | 3477 |
3328 (setq alist (cdr alist)) | 3478 (setq alist (cdr alist)) |
3329 | 3479 |
3330 (let ((inhibit-quit t)) | 3480 (let ((inhibit-quit t)) |
3331 (unless (equal alist gnus-agent-article-alist) | 3481 (unless (equal alist gnus-agent-article-alist) |
3332 (setq gnus-agent-article-alist alist) | 3482 (setq gnus-agent-article-alist alist) |
3333 (gnus-agent-save-alist group)) | 3483 (gnus-agent-save-alist group)) |
3334 | 3484 |
3335 (when (buffer-modified-p) | 3485 (when (buffer-modified-p) |
3336 (let ((coding-system-for-write | 3486 (let ((coding-system-for-write |
3337 gnus-agent-file-coding-system)) | 3487 gnus-agent-file-coding-system)) |
3338 (gnus-make-directory dir) | 3488 (gnus-make-directory dir) |
3339 (write-region (point-min) (point-max) nov-file nil | 3489 (write-region (point-min) (point-max) nov-file nil |
3340 'silent) | 3490 'silent) |
3341 ;; clear the modified flag as that I'm not confused by | 3491 ;; clear the modified flag as that I'm not confused by |
3342 ;; its status on the next pass through this routine. | 3492 ;; its status on the next pass through this routine. |
3343 (set-buffer-modified-p nil))) | 3493 (set-buffer-modified-p nil) |
3344 | 3494 (gnus-agent-update-view-total-fetched-for group t))) |
3345 (when (eq articles t) | 3495 |
3346 (gnus-summary-update-info)))) | 3496 (when (eq articles t) |
3347 | 3497 (gnus-summary-update-info)))) |
3348 (when (boundp 'gnus-agent-expire-stats) | 3498 |
3349 (let ((stats (symbol-value 'gnus-agent-expire-stats))) | 3499 (when (boundp 'gnus-agent-expire-stats) |
3350 (incf (nth 2 stats) bytes-freed) | 3500 (let ((stats (symbol-value 'gnus-agent-expire-stats))) |
3351 (incf (nth 1 stats) files-deleted) | 3501 (incf (nth 2 stats) bytes-freed) |
3352 (incf (nth 0 stats) nov-entries-deleted))) | 3502 (incf (nth 1 stats) files-deleted) |
3353 )))) | 3503 (incf (nth 0 stats) nov-entries-deleted))) |
3504 | |
3505 (gnus-agent-update-files-total-fetched-for group (- size-files-deleted))))))) | |
3354 | 3506 |
3355 (defun gnus-agent-expire (&optional articles group force) | 3507 (defun gnus-agent-expire (&optional articles group force) |
3356 "Expire all old articles. | 3508 "Expire all old articles. |
3357 If you want to force expiring of certain articles, this function can | 3509 If you want to force expiring of certain articles, this function can |
3358 take ARTICLES, GROUP and FORCE parameters as well. | 3510 take ARTICLES, GROUP and FORCE parameters as well. |
3426 (let* ((keep (gnus-make-hashtable)) | 3578 (let* ((keep (gnus-make-hashtable)) |
3427 ;; Formally bind gnus-agent-expire-current-dirs so that the | 3579 ;; Formally bind gnus-agent-expire-current-dirs so that the |
3428 ;; compiler will not complain about free references. | 3580 ;; compiler will not complain about free references. |
3429 (gnus-agent-expire-current-dirs | 3581 (gnus-agent-expire-current-dirs |
3430 (symbol-value 'gnus-agent-expire-current-dirs)) | 3582 (symbol-value 'gnus-agent-expire-current-dirs)) |
3431 dir) | 3583 dir |
3584 (file-name-coding-system nnmail-pathname-coding-system)) | |
3432 | 3585 |
3433 (gnus-sethash gnus-agent-directory t keep) | 3586 (gnus-sethash gnus-agent-directory t keep) |
3434 (while gnus-agent-expire-current-dirs | 3587 (while gnus-agent-expire-current-dirs |
3435 (setq dir (pop gnus-agent-expire-current-dirs)) | 3588 (setq dir (pop gnus-agent-expire-current-dirs)) |
3436 (when (and (stringp dir) | 3589 (when (and (stringp dir) |
3483 deleting them?"))) | 3636 deleting them?"))) |
3484 (while to-remove | 3637 (while to-remove |
3485 (let ((dir (pop to-remove))) | 3638 (let ((dir (pop to-remove))) |
3486 (if (gnus-y-or-n-p (format "Delete %s? " dir)) | 3639 (if (gnus-y-or-n-p (format "Delete %s? " dir)) |
3487 (let* (delete-recursive | 3640 (let* (delete-recursive |
3641 files f | |
3488 (delete-recursive | 3642 (delete-recursive |
3489 (function | 3643 (function |
3490 (lambda (f-or-d) | 3644 (lambda (f-or-d) |
3491 (ignore-errors | 3645 (ignore-errors |
3492 (if (file-directory-p f-or-d) | 3646 (if (file-directory-p f-or-d) |
3493 (condition-case nil | 3647 (condition-case nil |
3494 (delete-directory f-or-d) | 3648 (delete-directory f-or-d) |
3495 (file-error | 3649 (file-error |
3496 (mapcar (lambda (f) | 3650 (setq files (directory-files f-or-d)) |
3497 (or (member f '("." "..")) | 3651 (while files |
3498 (funcall delete-recursive | 3652 (setq f (pop files)) |
3499 (nnheader-concat | 3653 (or (member f '("." "..")) |
3500 f-or-d f)))) | 3654 (funcall delete-recursive |
3501 (directory-files f-or-d)) | 3655 (nnheader-concat |
3656 f-or-d f)))) | |
3502 (delete-directory f-or-d))) | 3657 (delete-directory f-or-d))) |
3503 (delete-file f-or-d))))))) | 3658 (delete-file f-or-d))))))) |
3504 (funcall delete-recursive dir)))))))))) | 3659 (funcall delete-recursive dir)))))))))) |
3505 | 3660 |
3506 ;;;###autoload | 3661 ;;;###autoload |
3580 (save-excursion | 3735 (save-excursion |
3581 (gnus-agent-create-buffer) | 3736 (gnus-agent-create-buffer) |
3582 (let ((gnus-decode-encoded-word-function 'identity) | 3737 (let ((gnus-decode-encoded-word-function 'identity) |
3583 (gnus-decode-encoded-address-function 'identity) | 3738 (gnus-decode-encoded-address-function 'identity) |
3584 (file (gnus-agent-article-name ".overview" group)) | 3739 (file (gnus-agent-article-name ".overview" group)) |
3585 cached-articles uncached-articles) | 3740 cached-articles uncached-articles |
3741 (file-name-coding-system nnmail-pathname-coding-system)) | |
3586 (gnus-make-directory (nnheader-translate-file-chars | 3742 (gnus-make-directory (nnheader-translate-file-chars |
3587 (file-name-directory file) t)) | 3743 (file-name-directory file) t)) |
3588 | 3744 |
3589 ;; Populate temp buffer with known headers | 3745 ;; Populate temp buffer with known headers |
3590 (when (file-exists-p file) | 3746 (when (file-exists-p file) |
3683 (let ((coding-system-for-write | 3839 (let ((coding-system-for-write |
3684 gnus-agent-file-coding-system)) | 3840 gnus-agent-file-coding-system)) |
3685 (gnus-agent-check-overview-buffer) | 3841 (gnus-agent-check-overview-buffer) |
3686 (write-region (point-min) (point-max) file nil 'silent)) | 3842 (write-region (point-min) (point-max) file nil 'silent)) |
3687 | 3843 |
3844 (gnus-agent-update-view-total-fetched-for group t) | |
3845 | |
3688 ;; Update the group's article alist to include the newly | 3846 ;; Update the group's article alist to include the newly |
3689 ;; fetched articles. | 3847 ;; fetched articles. |
3690 (gnus-agent-load-alist group) | 3848 (gnus-agent-load-alist group) |
3691 (gnus-agent-save-alist group uncached-articles nil) | 3849 (gnus-agent-save-alist group uncached-articles nil) |
3692 ) | 3850 ) |
3713 (or gnus-agent-cache | 3871 (or gnus-agent-cache |
3714 (not gnus-plugged)) | 3872 (not gnus-plugged)) |
3715 (numberp article)) | 3873 (numberp article)) |
3716 (let* ((gnus-command-method (gnus-find-method-for-group group)) | 3874 (let* ((gnus-command-method (gnus-find-method-for-group group)) |
3717 (file (gnus-agent-article-name (number-to-string article) group)) | 3875 (file (gnus-agent-article-name (number-to-string article) group)) |
3718 (buffer-read-only nil)) | 3876 (buffer-read-only nil) |
3877 (file-name-coding-system nnmail-pathname-coding-system)) | |
3719 (when (and (file-exists-p file) | 3878 (when (and (file-exists-p file) |
3720 (> (nth 7 (file-attributes file)) 0)) | 3879 (> (nth 7 (file-attributes file)) 0)) |
3721 (erase-buffer) | 3880 (erase-buffer) |
3722 (gnus-kill-all-overlays) | 3881 (gnus-kill-all-overlays) |
3723 (let ((coding-system-for-read gnus-cache-coding-system)) | 3882 (let ((coding-system-for-read gnus-cache-coding-system)) |
3730 If REREAD is a list, the specified articles will be marked as unread. | 3889 If REREAD is a list, the specified articles will be marked as unread. |
3731 In addition, their NOV entries in .overview will be refreshed using | 3890 In addition, their NOV entries in .overview will be refreshed using |
3732 the articles' current headers. | 3891 the articles' current headers. |
3733 If REREAD is not nil, downloaded articles are marked as unread." | 3892 If REREAD is not nil, downloaded articles are marked as unread." |
3734 (interactive | 3893 (interactive |
3735 (list (let ((def (or (gnus-group-group-name) | 3894 (list (gnus-agent-read-group) |
3736 gnus-newsgroup-name))) | |
3737 (let ((select (read-string (if def | |
3738 (concat "Group Name (" | |
3739 def "): ") | |
3740 "Group Name: ")))) | |
3741 (if (and (equal "" select) | |
3742 def) | |
3743 def | |
3744 select))) | |
3745 (catch 'mark | 3895 (catch 'mark |
3746 (while (let (c | 3896 (while (let (c |
3747 (cursor-in-echo-area t) | 3897 (cursor-in-echo-area t) |
3748 (echo-keystrokes 0)) | 3898 (echo-keystrokes 0)) |
3749 (message "Mark as unread: (n)one / (a)ll / all (d)ownloaded articles? (n) ") | 3899 (message "Mark as unread: (n)one / (a)ll / all (d)ownloaded articles? (n) ") |
3757 (throw 'mark 'some))) | 3907 (throw 'mark 'some))) |
3758 (gnus-message 3 "Ignoring unexpected input") | 3908 (gnus-message 3 "Ignoring unexpected input") |
3759 (sit-for 1) | 3909 (sit-for 1) |
3760 t))))) | 3910 t))))) |
3761 (when group | 3911 (when group |
3762 (gnus-message 5 "Regenerating in %s" group) | 3912 (gnus-message 5 "Regenerating in %s" group) |
3763 (let* ((gnus-command-method (or gnus-command-method | 3913 (let* ((gnus-command-method (or gnus-command-method |
3764 (gnus-find-method-for-group group))) | 3914 (gnus-find-method-for-group group))) |
3765 (file (gnus-agent-article-name ".overview" group)) | 3915 (file (gnus-agent-article-name ".overview" group)) |
3766 (dir (file-name-directory file)) | 3916 (dir (file-name-directory file)) |
3767 point | 3917 point |
3768 (downloaded (if (file-exists-p dir) | 3918 (file-name-coding-system nnmail-pathname-coding-system) |
3919 (downloaded (if (file-exists-p dir) | |
3769 (sort (delq nil (mapcar (lambda (name) | 3920 (sort (delq nil (mapcar (lambda (name) |
3770 (and (not (file-directory-p (nnheader-concat dir name))) | 3921 (and (not (file-directory-p (nnheader-concat dir name))) |
3771 (string-to-number name))) | 3922 (string-to-number name))) |
3772 (directory-files dir nil "^[0-9]+$" t))) | 3923 (directory-files dir nil "^[0-9]+$" t))) |
3773 '>) | 3924 '>) |
3774 (progn (gnus-make-directory dir) nil))) | 3925 (progn (gnus-make-directory dir) nil))) |
3775 dl nov-arts | 3926 dl nov-arts |
3776 alist header | 3927 alist header |
3777 regenerated) | 3928 regenerated) |
3778 | 3929 |
3779 (mm-with-unibyte-buffer | 3930 (mm-with-unibyte-buffer |
3780 (if (file-exists-p file) | 3931 (if (file-exists-p file) |
3781 (let ((nnheader-file-coding-system | 3932 (let ((nnheader-file-coding-system |
3782 gnus-agent-file-coding-system)) | 3933 gnus-agent-file-coding-system)) |
3783 (nnheader-insert-file-contents file))) | 3934 (nnheader-insert-file-contents file))) |
3784 (set-buffer-modified-p nil) | 3935 (set-buffer-modified-p nil) |
3785 | 3936 |
3786 ;; Load the article IDs found in the overview file. As a | 3937 ;; Load the article IDs found in the overview file. As a |
3787 ;; side-effect, validate the file contents. | 3938 ;; side-effect, validate the file contents. |
3788 (let ((load t)) | 3939 (let ((load t)) |
3789 (while load | 3940 (while load |
3790 (setq load nil) | 3941 (setq load nil) |
3791 (goto-char (point-min)) | 3942 (goto-char (point-min)) |
3792 (while (< (point) (point-max)) | 3943 (while (< (point) (point-max)) |
3793 (cond ((and (looking-at "[0-9]+\t") | 3944 (cond ((and (looking-at "[0-9]+\t") |
3794 (<= (- (match-end 0) (match-beginning 0)) 9)) | 3945 (<= (- (match-end 0) (match-beginning 0)) 9)) |
3795 (push (read (current-buffer)) nov-arts) | 3946 (push (read (current-buffer)) nov-arts) |
3796 (forward-line 1) | 3947 (forward-line 1) |
3797 (let ((l1 (car nov-arts)) | 3948 (let ((l1 (car nov-arts)) |
3798 (l2 (cadr nov-arts))) | 3949 (l2 (cadr nov-arts))) |
3799 (cond ((and (listp reread) (memq l1 reread)) | 3950 (cond ((and (listp reread) (memq l1 reread)) |
3800 (gnus-delete-line) | 3951 (gnus-delete-line) |
3801 (setq nov-arts (cdr nov-arts)) | 3952 (setq nov-arts (cdr nov-arts)) |
3802 (gnus-message 4 "gnus-agent-regenerate-group: NOV\ | 3953 (gnus-message 4 "gnus-agent-regenerate-group: NOV\ |
3803 entry of article %s deleted." l1)) | 3954 entry of article %s deleted." l1)) |
3804 ((not l2) | 3955 ((not l2) |
3805 nil) | 3956 nil) |
3806 ((< l1 l2) | 3957 ((< l1 l2) |
3807 (gnus-message 3 "gnus-agent-regenerate-group: NOV\ | 3958 (gnus-message 3 "gnus-agent-regenerate-group: NOV\ |
3808 entries are NOT in ascending order.") | 3959 entries are NOT in ascending order.") |
3809 ;; Don't sort now as I haven't verified | 3960 ;; Don't sort now as I haven't verified |
3810 ;; that every line begins with a number | 3961 ;; that every line begins with a number |
3811 (setq load t)) | 3962 (setq load t)) |
3812 ((= l1 l2) | 3963 ((= l1 l2) |
3813 (forward-line -1) | 3964 (forward-line -1) |
3814 (gnus-message 4 "gnus-agent-regenerate-group: NOV\ | 3965 (gnus-message 4 "gnus-agent-regenerate-group: NOV\ |
3815 entries contained duplicate of article %s. Duplicate deleted." l1) | 3966 entries contained duplicate of article %s. Duplicate deleted." l1) |
3816 (gnus-delete-line) | 3967 (gnus-delete-line) |
3817 (setq nov-arts (cdr nov-arts)))))) | 3968 (setq nov-arts (cdr nov-arts)))))) |
3818 (t | 3969 (t |
3819 (gnus-message 1 "gnus-agent-regenerate-group: NOV\ | 3970 (gnus-message 1 "gnus-agent-regenerate-group: NOV\ |
3820 entries contained line that did not begin with an article number. Deleted\ | 3971 entries contained line that did not begin with an article number. Deleted\ |
3821 line.") | 3972 line.") |
3822 (gnus-delete-line)))) | 3973 (gnus-delete-line)))) |
3823 (when load | 3974 (when load |
3824 (gnus-message 5 "gnus-agent-regenerate-group: Sorting NOV\ | 3975 (gnus-message 5 "gnus-agent-regenerate-group: Sorting NOV\ |
3825 entries into ascending order.") | 3976 entries into ascending order.") |
3826 (sort-numeric-fields 1 (point-min) (point-max)) | 3977 (sort-numeric-fields 1 (point-min) (point-max)) |
3827 (setq nov-arts nil)))) | 3978 (setq nov-arts nil)))) |
3828 (gnus-agent-check-overview-buffer) | 3979 (gnus-agent-check-overview-buffer) |
3829 | 3980 |
3830 ;; Construct a new article alist whose nodes match every header | 3981 ;; Construct a new article alist whose nodes match every header |
3831 ;; in the .overview file. As a side-effect, missing headers are | 3982 ;; in the .overview file. As a side-effect, missing headers are |
3832 ;; reconstructed from the downloaded article file. | 3983 ;; reconstructed from the downloaded article file. |
3833 (while (or downloaded nov-arts) | 3984 (while (or downloaded nov-arts) |
3834 (cond ((and downloaded | 3985 (cond ((and downloaded |
3835 (or (not nov-arts) | 3986 (or (not nov-arts) |
3836 (> (car downloaded) (car nov-arts)))) | 3987 (> (car downloaded) (car nov-arts)))) |
3837 ;; This entry is missing from the overview file | 3988 ;; This entry is missing from the overview file |
3838 (gnus-message 3 "Regenerating NOV %s %d..." group | 3989 (gnus-message 3 "Regenerating NOV %s %d..." group |
3839 (car downloaded)) | 3990 (car downloaded)) |
3840 (let ((file (concat dir (number-to-string (car downloaded))))) | 3991 (let ((file (concat dir (number-to-string (car downloaded))))) |
3841 (mm-with-unibyte-buffer | 3992 (mm-with-unibyte-buffer |
3842 (nnheader-insert-file-contents file) | 3993 (nnheader-insert-file-contents file) |
3843 (nnheader-remove-body) | 3994 (nnheader-remove-body) |
3844 (setq header (nnheader-parse-naked-head))) | 3995 (setq header (nnheader-parse-naked-head))) |
3845 (mail-header-set-number header (car downloaded)) | 3996 (mail-header-set-number header (car downloaded)) |
3846 (if nov-arts | 3997 (if nov-arts |
3847 (let ((key (concat "^" (int-to-string (car nov-arts)) | 3998 (let ((key (concat "^" (int-to-string (car nov-arts)) |
3848 "\t"))) | 3999 "\t"))) |
3849 (or (re-search-backward key nil t) | 4000 (or (re-search-backward key nil t) |
3850 (re-search-forward key)) | 4001 (re-search-forward key)) |
3851 (forward-line 1)) | 4002 (forward-line 1)) |
3852 (goto-char (point-min))) | 4003 (goto-char (point-min))) |
3853 (nnheader-insert-nov header)) | 4004 (nnheader-insert-nov header)) |
3854 (setq nov-arts (cons (car downloaded) nov-arts))) | 4005 (setq nov-arts (cons (car downloaded) nov-arts))) |
3855 ((eq (car downloaded) (car nov-arts)) | 4006 ((eq (car downloaded) (car nov-arts)) |
3856 ;; This entry in the overview has been downloaded | 4007 ;; This entry in the overview has been downloaded |
3857 (push (cons (car downloaded) | 4008 (push (cons (car downloaded) |
3858 (time-to-days | 4009 (time-to-days |
3859 (nth 5 (file-attributes | 4010 (nth 5 (file-attributes |
3860 (concat dir (number-to-string | 4011 (concat dir (number-to-string |
3861 (car downloaded))))))) alist) | 4012 (car downloaded))))))) alist) |
3862 (setq downloaded (cdr downloaded)) | 4013 (setq downloaded (cdr downloaded)) |
3863 (setq nov-arts (cdr nov-arts))) | 4014 (setq nov-arts (cdr nov-arts))) |
3864 (t | 4015 (t |
3865 ;; This entry in the overview has not been downloaded | 4016 ;; This entry in the overview has not been downloaded |
3866 (push (cons (car nov-arts) nil) alist) | 4017 (push (cons (car nov-arts) nil) alist) |
3867 (setq nov-arts (cdr nov-arts))))) | 4018 (setq nov-arts (cdr nov-arts))))) |
3868 | 4019 |
3869 ;; When gnus-agent-consider-all-articles is set, | 4020 ;; When gnus-agent-consider-all-articles is set, |
3870 ;; gnus-agent-regenerate-group should NOT remove article IDs from | 4021 ;; gnus-agent-regenerate-group should NOT remove article IDs from |
3871 ;; the alist. Those IDs serve as markers to indicate that an | 4022 ;; the alist. Those IDs serve as markers to indicate that an |
3872 ;; attempt has been made to fetch that article's header. | 4023 ;; attempt has been made to fetch that article's header. |
3873 | 4024 |
3874 ;; When gnus-agent-consider-all-articles is NOT set, | 4025 ;; When gnus-agent-consider-all-articles is NOT set, |
3875 ;; gnus-agent-regenerate-group can remove the article ID of every | 4026 ;; gnus-agent-regenerate-group can remove the article ID of every |
3876 ;; article (with the exception of the last ID in the list - it's | 4027 ;; article (with the exception of the last ID in the list - it's |
3877 ;; special) that no longer appears in the overview. In this | 4028 ;; special) that no longer appears in the overview. In this |
3878 ;; situtation, the last article ID in the list implies that it, | 4029 ;; situtation, the last article ID in the list implies that it, |
3879 ;; and every article ID preceeding it, have been fetched from the | 4030 ;; and every article ID preceeding it, have been fetched from the |
3880 ;; server. | 4031 ;; server. |
3881 | 4032 |
3882 (if gnus-agent-consider-all-articles | 4033 (if gnus-agent-consider-all-articles |
3883 ;; Restore all article IDs that were not found in the overview file. | 4034 ;; Restore all article IDs that were not found in the overview file. |
3884 (let* ((n (cons nil alist)) | 4035 (let* ((n (cons nil alist)) |
3885 (merged n) | 4036 (merged n) |
3886 (o (gnus-agent-load-alist group))) | 4037 (o (gnus-agent-load-alist group))) |
3887 (while o | 4038 (while o |
3888 (let ((nID (caadr n)) | 4039 (let ((nID (caadr n)) |
3889 (oID (caar o))) | 4040 (oID (caar o))) |
3890 (cond ((not nID) | 4041 (cond ((not nID) |
3891 (setq n (setcdr n (list (list oID)))) | 4042 (setq n (setcdr n (list (list oID)))) |
3892 (setq o (cdr o))) | 4043 (setq o (cdr o))) |
3893 ((< oID nID) | 4044 ((< oID nID) |
3894 (setcdr n (cons (list oID) (cdr n))) | 4045 (setcdr n (cons (list oID) (cdr n))) |
3895 (setq o (cdr o))) | 4046 (setq o (cdr o))) |
3896 ((= oID nID) | 4047 ((= oID nID) |
3897 (setq o (cdr o)) | 4048 (setq o (cdr o)) |
3898 (setq n (cdr n))) | 4049 (setq n (cdr n))) |
3899 (t | 4050 (t |
3900 (setq n (cdr n)))))) | 4051 (setq n (cdr n)))))) |
3901 (setq alist (cdr merged))) | 4052 (setq alist (cdr merged))) |
3902 ;; Restore the last article ID if it is not already in the new alist | 4053 ;; Restore the last article ID if it is not already in the new alist |
3903 (let ((n (last alist)) | 4054 (let ((n (last alist)) |
3904 (o (last (gnus-agent-load-alist group)))) | 4055 (o (last (gnus-agent-load-alist group)))) |
3905 (cond ((not o) | 4056 (cond ((not o) |
3906 nil) | 4057 nil) |
3907 ((not n) | 4058 ((not n) |
3908 (push (cons (caar o) nil) alist)) | 4059 (push (cons (caar o) nil) alist)) |
3909 ((< (caar n) (caar o)) | 4060 ((< (caar n) (caar o)) |
3910 (setcdr n (list (car o))))))) | 4061 (setcdr n (list (car o))))))) |
3911 | 4062 |
3912 (let ((inhibit-quit t)) | 4063 (let ((inhibit-quit t)) |
3913 (if (setq regenerated (buffer-modified-p)) | 4064 (if (setq regenerated (buffer-modified-p)) |
3914 (let ((coding-system-for-write gnus-agent-file-coding-system)) | 4065 (let ((coding-system-for-write gnus-agent-file-coding-system)) |
3915 (write-region (point-min) (point-max) file nil 'silent))) | 4066 (write-region (point-min) (point-max) file nil 'silent))) |
3916 | 4067 |
3917 (setq regenerated (or regenerated | 4068 (setq regenerated (or regenerated |
3918 (and reread gnus-agent-article-alist) | 4069 (and reread gnus-agent-article-alist) |
3919 (not (equal alist gnus-agent-article-alist)))) | 4070 (not (equal alist gnus-agent-article-alist)))) |
3920 | 4071 |
3921 (setq gnus-agent-article-alist alist) | 4072 (setq gnus-agent-article-alist alist) |
3922 | 4073 |
3923 (when regenerated | 4074 (when regenerated |
3924 (gnus-agent-save-alist group) | 4075 (gnus-agent-save-alist group) |
3925 | 4076 |
3926 ;; I have to alter the group's active range NOW as | 4077 ;; I have to alter the group's active range NOW as |
3927 ;; gnus-make-ascending-articles-unread will use it to | 4078 ;; gnus-make-ascending-articles-unread will use it to |
3928 ;; recalculate the number of unread articles in the group | 4079 ;; recalculate the number of unread articles in the group |
3929 | 4080 |
3930 (let ((group (gnus-group-real-name group)) | 4081 (let ((group (gnus-group-real-name group)) |
3931 (group-active (or (gnus-active group) | 4082 (group-active (or (gnus-active group) |
3932 (gnus-activate-group group)))) | 4083 (gnus-activate-group group)))) |
3933 (gnus-agent-possibly-alter-active group group-active))))) | 4084 (gnus-agent-possibly-alter-active group group-active))))) |
3934 | 4085 |
3935 (when (and reread gnus-agent-article-alist) | 4086 (when (and reread gnus-agent-article-alist) |
3936 (gnus-agent-synchronize-group-flags | 4087 (gnus-agent-synchronize-group-flags |
3937 group | 4088 group |
3938 (list (list | 4089 (list (list |
3939 (if (listp reread) | 4090 (if (listp reread) |
3940 reread | 4091 reread |
3941 (delq nil (mapcar (function (lambda (c) | 4092 (delq nil (mapcar (function (lambda (c) |
3942 (cond ((eq reread t) | 4093 (cond ((eq reread t) |
3943 (car c)) | 4094 (car c)) |
3944 ((cdr c) | 4095 ((cdr c) |
3945 (car c))))) | 4096 (car c))))) |
3946 gnus-agent-article-alist))) | 4097 gnus-agent-article-alist))) |
3947 'del '(read))) | 4098 'del '(read))) |
3948 gnus-command-method) | 4099 gnus-command-method) |
3949 | 4100 |
3950 (when (gnus-buffer-live-p gnus-group-buffer) | 4101 (when regenerated |
3951 (gnus-group-update-group group t))) | 4102 (gnus-agent-update-files-total-fetched-for group nil))) |
3952 | 4103 |
3953 (gnus-message 5 "") | 4104 (gnus-message 5 "") |
3954 regenerated))) | 4105 regenerated))) |
3955 | 4106 |
3956 ;;;###autoload | 4107 ;;;###autoload |
3957 (defun gnus-agent-regenerate (&optional clean reread) | 4108 (defun gnus-agent-regenerate (&optional clean reread) |
3958 "Regenerate all agent covered files. | 4109 "Regenerate all agent covered files. |
3959 If CLEAN, obsolete (ignore)." | 4110 If CLEAN, obsolete (ignore)." |
3994 (if (eq status 'offline) 'online 'offline)))) | 4145 (if (eq status 'offline) 'online 'offline)))) |
3995 | 4146 |
3996 (defun gnus-agent-group-covered-p (group) | 4147 (defun gnus-agent-group-covered-p (group) |
3997 (gnus-agent-method-p (gnus-group-method group))) | 4148 (gnus-agent-method-p (gnus-group-method group))) |
3998 | 4149 |
4150 (defun gnus-agent-update-files-total-fetched-for | |
4151 (group delta &optional method path) | |
4152 "Update, or set, the total disk space used by the articles that the | |
4153 agent has fetched." | |
4154 (when gnus-agent-total-fetched-hashtb | |
4155 (gnus-agent-with-refreshed-group | |
4156 group | |
4157 ;; if null, gnus-agent-group-pathname will calc method. | |
4158 (let* ((gnus-command-method method) | |
4159 (path (or path (gnus-agent-group-pathname group))) | |
4160 (entry (or (gnus-gethash path gnus-agent-total-fetched-hashtb) | |
4161 (gnus-sethash path (make-list 3 0) | |
4162 gnus-agent-total-fetched-hashtb))) | |
4163 (file-name-coding-system nnmail-pathname-coding-system)) | |
4164 (when (listp delta) | |
4165 (if delta | |
4166 (let ((sum 0.0) | |
4167 file) | |
4168 (while (setq file (pop delta)) | |
4169 (incf sum (float (or (nth 7 (file-attributes | |
4170 (nnheader-concat | |
4171 path | |
4172 (if (numberp file) | |
4173 (number-to-string file) | |
4174 file)))) 0)))) | |
4175 (setq delta sum)) | |
4176 (let ((sum (- (nth 2 entry))) | |
4177 (info (directory-files-and-attributes path nil "^-?[0-9]+$" t)) | |
4178 file) | |
4179 (while (setq file (pop info)) | |
4180 (incf sum (float (or (nth 8 file) 0)))) | |
4181 (setq delta sum)))) | |
4182 | |
4183 (setq gnus-agent-need-update-total-fetched-for t) | |
4184 (incf (nth 2 entry) delta))))) | |
4185 | |
4186 (defun gnus-agent-update-view-total-fetched-for | |
4187 (group agent-over &optional method path) | |
4188 "Update, or set, the total disk space used by the .agentview and | |
4189 .overview files. These files are calculated separately as they can be | |
4190 modified." | |
4191 (when gnus-agent-total-fetched-hashtb | |
4192 (gnus-agent-with-refreshed-group | |
4193 group | |
4194 ;; if null, gnus-agent-group-pathname will calc method. | |
4195 (let* ((gnus-command-method method) | |
4196 (path (or path (gnus-agent-group-pathname group))) | |
4197 (entry (or (gnus-gethash path gnus-agent-total-fetched-hashtb) | |
4198 (gnus-sethash path (make-list 3 0) | |
4199 gnus-agent-total-fetched-hashtb))) | |
4200 (file-name-coding-system nnmail-pathname-coding-system) | |
4201 (size (or (nth 7 (file-attributes | |
4202 (nnheader-concat | |
4203 path (if agent-over | |
4204 ".overview" | |
4205 ".agentview")))) | |
4206 0))) | |
4207 (setq gnus-agent-need-update-total-fetched-for t) | |
4208 (setf (nth (if agent-over 1 0) entry) size))))) | |
4209 | |
4210 (defun gnus-agent-total-fetched-for (group &optional method no-inhibit) | |
4211 "Get the total disk space used by the specified GROUP." | |
4212 (unless (equal group "dummy.group") | |
4213 (unless gnus-agent-total-fetched-hashtb | |
4214 (setq gnus-agent-total-fetched-hashtb (gnus-make-hashtable 1024))) | |
4215 | |
4216 ;; if null, gnus-agent-group-pathname will calc method. | |
4217 (let* ((gnus-command-method method) | |
4218 (path (gnus-agent-group-pathname group)) | |
4219 (entry (gnus-gethash path gnus-agent-total-fetched-hashtb))) | |
4220 (if entry | |
4221 (apply '+ entry) | |
4222 (let ((gnus-agent-inhibit-update-total-fetched-for (not no-inhibit))) | |
4223 (+ | |
4224 (gnus-agent-update-view-total-fetched-for group nil method path) | |
4225 (gnus-agent-update-view-total-fetched-for group t method path) | |
4226 (gnus-agent-update-files-total-fetched-for group nil method path))))))) | |
4227 | |
3999 (provide 'gnus-agent) | 4228 (provide 'gnus-agent) |
4000 | 4229 |
4001 ;;; arch-tag: b0ba4afc-5229-4cee-ad25-9956daa4e91e | 4230 ;;; arch-tag: b0ba4afc-5229-4cee-ad25-9956daa4e91e |
4002 ;;; gnus-agent.el ends here | 4231 ;;; gnus-agent.el ends here |