diff options
| author | Eric Abrahamsen | 2019-06-06 20:43:27 -0700 |
|---|---|---|
| committer | Eric Abrahamsen | 2019-08-03 14:52:56 -0700 |
| commit | 727e0eab0a0d8043d09225f63f8bef2abc045562 (patch) | |
| tree | df219ce120264cc4e4dde41efc37ce3bb3b2d0bf | |
| parent | cb12a84f2c519a48dd87453c925e3bc36d9944db (diff) | |
| download | emacs-727e0eab0a0d8043d09225f63f8bef2abc045562.tar.gz emacs-727e0eab0a0d8043d09225f63f8bef2abc045562.zip | |
Temporarily preserve encoded Gnus group names in Gnus files
Non-ascii Gnus groups should be written to files in their encoded
version until we're ready to bump Gnus' version and add an upgrade
routine.
* lisp/gnus/gnus-start.el (gnus-gnus-to-quick-newsrc-format):
* lisp/gnus/gnus-agent.el (gnus-category-read):
(gnus-category-write): Handle non-ascii group names appropriately.
* lisp/gnus/gnus-registry.el (gnus-registry--munge-group-names): New
function to encode/decode group names.
(gnus-registry-fixup-registry):
(gnus-registry-save): Use function.
| -rw-r--r-- | lisp/gnus/gnus-agent.el | 102 | ||||
| -rw-r--r-- | lisp/gnus/gnus-registry.el | 59 | ||||
| -rw-r--r-- | lisp/gnus/gnus-start.el | 39 |
3 files changed, 144 insertions, 56 deletions
diff --git a/lisp/gnus/gnus-agent.el b/lisp/gnus/gnus-agent.el index d9c9e940700..dd30dda2a10 100644 --- a/lisp/gnus/gnus-agent.el +++ b/lisp/gnus/gnus-agent.el | |||
| @@ -2693,52 +2693,74 @@ The following commands are available: | |||
| 2693 | "Read the category alist." | 2693 | "Read the category alist." |
| 2694 | (setq gnus-category-alist | 2694 | (setq gnus-category-alist |
| 2695 | (or | 2695 | (or |
| 2696 | (with-temp-buffer | 2696 | (let ((list |
| 2697 | (ignore-errors | 2697 | (with-temp-buffer |
| 2698 | (nnheader-insert-file-contents (nnheader-concat gnus-agent-directory "lib/categories")) | 2698 | (ignore-errors |
| 2699 | (goto-char (point-min)) | 2699 | (nnheader-insert-file-contents (nnheader-concat gnus-agent-directory "lib/categories")) |
| 2700 | ;; This code isn't temp, it will be needed so long as | 2700 | (goto-char (point-min)) |
| 2701 | ;; anyone may be migrating from an older version. | 2701 | ;; This code isn't temp, it will be needed so long as |
| 2702 | 2702 | ;; anyone may be migrating from an older version. | |
| 2703 | ;; Once we're certain that people will not revert to an | 2703 | |
| 2704 | ;; earlier version, we can take out the old-list code in | 2704 | ;; Once we're certain that people will not revert to an |
| 2705 | ;; gnus-category-write. | 2705 | ;; earlier version, we can take out the old-list code in |
| 2706 | (let* ((old-list (read (current-buffer))) | 2706 | ;; gnus-category-write. |
| 2707 | (new-list (ignore-errors (read (current-buffer))))) | 2707 | (let* ((old-list (read (current-buffer))) |
| 2708 | (if new-list | 2708 | (new-list (ignore-errors (read (current-buffer))))) |
| 2709 | new-list | 2709 | (if new-list |
| 2710 | ;; Convert from a positional list to an alist. | 2710 | new-list |
| 2711 | (mapcar | 2711 | ;; Convert from a positional list to an alist. |
| 2712 | (lambda (c) | 2712 | (mapcar |
| 2713 | (setcdr c | 2713 | (lambda (c) |
| 2714 | (delq nil | 2714 | (setcdr c |
| 2715 | (gnus-mapcar | 2715 | (delq nil |
| 2716 | (lambda (valu symb) | 2716 | (gnus-mapcar |
| 2717 | (if valu | 2717 | (lambda (valu symb) |
| 2718 | (cons symb valu))) | 2718 | (if valu |
| 2719 | (cdr c) | 2719 | (cons symb valu))) |
| 2720 | '(agent-predicate agent-score-file agent-groups)))) | 2720 | (cdr c) |
| 2721 | c) | 2721 | '(agent-predicate agent-score-file agent-groups)))) |
| 2722 | old-list))))) | 2722 | c) |
| 2723 | old-list))))))) | ||
| 2724 | ;; Possibly decode group names. | ||
| 2725 | (dolist (cat list) | ||
| 2726 | (setf (alist-get 'agent-groups cat) | ||
| 2727 | (mapcar (lambda (g) | ||
| 2728 | (if (string-match-p "[^[:ascii:]]" g) | ||
| 2729 | (decode-coding-string g 'utf-8-emacs) | ||
| 2730 | g)) | ||
| 2731 | (alist-get 'agent-groups cat)))) | ||
| 2732 | list) | ||
| 2723 | (list (gnus-agent-cat-make 'default 'short))))) | 2733 | (list (gnus-agent-cat-make 'default 'short))))) |
| 2724 | 2734 | ||
| 2725 | (defun gnus-category-write () | 2735 | (defun gnus-category-write () |
| 2726 | "Write the category alist." | 2736 | "Write the category alist." |
| 2727 | (setq gnus-category-predicate-cache nil | 2737 | (setq gnus-category-predicate-cache nil |
| 2728 | gnus-category-group-cache nil) | 2738 | gnus-category-group-cache nil) |
| 2729 | (gnus-make-directory (nnheader-concat gnus-agent-directory "lib")) | 2739 | ;; Temporarily encode non-ascii group names when saving to file, |
| 2730 | (with-temp-file (nnheader-concat gnus-agent-directory "lib/categories") | 2740 | ;; pending an upgrade of Gnus' file formats. |
| 2731 | ;; This prin1 is temporary. It exists so that people can revert | 2741 | (let ((gnus-category-alist |
| 2732 | ;; to an earlier version of gnus-agent. | 2742 | (mapcar (lambda (cat) |
| 2733 | (prin1 (mapcar (lambda (c) | 2743 | (setf (alist-get 'agent-groups cat) |
| 2734 | (list (car c) | 2744 | (mapcar (lambda (g) |
| 2735 | (cdr (assoc 'agent-predicate c)) | 2745 | (if (multibyte-string-p g) |
| 2736 | (cdr (assoc 'agent-score-file c)) | 2746 | (encode-coding-string g 'utf-8-emacs) |
| 2737 | (cdr (assoc 'agent-groups c)))) | 2747 | g)) |
| 2738 | gnus-category-alist) | 2748 | (alist-get 'agent-groups cat))) |
| 2739 | (current-buffer)) | 2749 | cat) |
| 2740 | (newline) | 2750 | (copy-tree gnus-category-alist)))) |
| 2741 | (prin1 gnus-category-alist (current-buffer)))) | 2751 | (gnus-make-directory (nnheader-concat gnus-agent-directory "lib")) |
| 2752 | (with-temp-file (nnheader-concat gnus-agent-directory "lib/categories") | ||
| 2753 | ;; This prin1 is temporary. It exists so that people can revert | ||
| 2754 | ;; to an earlier version of gnus-agent. | ||
| 2755 | (prin1 (mapcar (lambda (c) | ||
| 2756 | (list (car c) | ||
| 2757 | (cdr (assoc 'agent-predicate c)) | ||
| 2758 | (cdr (assoc 'agent-score-file c)) | ||
| 2759 | (cdr (assoc 'agent-groups c)))) | ||
| 2760 | gnus-category-alist) | ||
| 2761 | (current-buffer)) | ||
| 2762 | (newline) | ||
| 2763 | (prin1 gnus-category-alist (current-buffer))))) | ||
| 2742 | 2764 | ||
| 2743 | (defun gnus-category-edit-predicate (category) | 2765 | (defun gnus-category-edit-predicate (category) |
| 2744 | "Edit the predicate for CATEGORY." | 2766 | "Edit the predicate for CATEGORY." |
diff --git a/lisp/gnus/gnus-registry.el b/lisp/gnus/gnus-registry.el index e488858ebe0..e949179b3cc 100644 --- a/lisp/gnus/gnus-registry.el +++ b/lisp/gnus/gnus-registry.el | |||
| @@ -264,6 +264,50 @@ This can slow pruning down. Set to nil to perform no sorting." | |||
| 264 | (cadr (assq 'creation-time r)) | 264 | (cadr (assq 'creation-time r)) |
| 265 | (cadr (assq 'creation-time l)))) | 265 | (cadr (assq 'creation-time l)))) |
| 266 | 266 | ||
| 267 | ;; Remove this from the save routine (and fix it to only decode) at | ||
| 268 | ;; next Gnus version bump. | ||
| 269 | (defun gnus-registry--munge-group-names (db &optional encode) | ||
| 270 | "Encode/decode group names in DB, before saving or after loading. | ||
| 271 | Encode names if ENCODE is non-nil, otherwise decode." | ||
| 272 | (let ((datahash (slot-value db 'data)) | ||
| 273 | (grouphash (registry-lookup-secondary db 'group)) | ||
| 274 | reset-pairs) | ||
| 275 | (when (hash-table-p grouphash) | ||
| 276 | (maphash | ||
| 277 | (lambda (group-name val) | ||
| 278 | (if encode | ||
| 279 | (when (multibyte-string-p group-name) | ||
| 280 | (remhash group-name grouphash) | ||
| 281 | (puthash (encode-coding-string group-name 'utf-8-emacs) | ||
| 282 | val grouphash)) | ||
| 283 | (when (string-match-p "[^[:ascii:]]" group-name) | ||
| 284 | (remhash group-name grouphash) | ||
| 285 | (puthash (decode-coding-string group-name 'utf-8-emacs) val grouphash)))) | ||
| 286 | grouphash)) | ||
| 287 | (maphash | ||
| 288 | (lambda (id data) | ||
| 289 | (let ((groups (cdr-safe (assq 'group data)))) | ||
| 290 | (when (seq-some (lambda (g) | ||
| 291 | (if encode | ||
| 292 | (multibyte-string-p g) | ||
| 293 | (string-match-p "[^[:ascii:]]" g))) | ||
| 294 | groups) | ||
| 295 | ;; Create a replacement DATA. | ||
| 296 | (push (list id (cons (cons 'group (mapcar | ||
| 297 | (lambda (g) | ||
| 298 | (funcall | ||
| 299 | (if encode | ||
| 300 | #'encode-coding-string | ||
| 301 | #'decode-coding-string) | ||
| 302 | g 'utf-8-emacs)) | ||
| 303 | groups)) | ||
| 304 | (assq-delete-all 'group data))) | ||
| 305 | reset-pairs)))) | ||
| 306 | datahash) | ||
| 307 | (pcase-dolist (`(,id ,data) reset-pairs) | ||
| 308 | (remhash id datahash) | ||
| 309 | (puthash id data datahash)))) | ||
| 310 | |||
| 267 | (defun gnus-registry-fixup-registry (db) | 311 | (defun gnus-registry-fixup-registry (db) |
| 268 | (when db | 312 | (when db |
| 269 | (let ((old (oref db tracked))) | 313 | (let ((old (oref db tracked))) |
| @@ -281,7 +325,8 @@ This can slow pruning down. Set to nil to perform no sorting." | |||
| 281 | '(mark group keyword))) | 325 | '(mark group keyword))) |
| 282 | (when (not (equal old (oref db tracked))) | 326 | (when (not (equal old (oref db tracked))) |
| 283 | (gnus-message 9 "Reindexing the Gnus registry (tracked change)") | 327 | (gnus-message 9 "Reindexing the Gnus registry (tracked change)") |
| 284 | (registry-reindex db)))) | 328 | (registry-reindex db)) |
| 329 | (gnus-registry--munge-group-names db))) | ||
| 285 | db) | 330 | db) |
| 286 | 331 | ||
| 287 | (defun gnus-registry-make-db (&optional file) | 332 | (defun gnus-registry-make-db (&optional file) |
| @@ -358,14 +403,20 @@ non-nil." | |||
| 358 | (defun gnus-registry-save (&optional file db) | 403 | (defun gnus-registry-save (&optional file db) |
| 359 | "Save the registry cache file." | 404 | "Save the registry cache file." |
| 360 | (interactive) | 405 | (interactive) |
| 361 | (let ((file (or file gnus-registry-cache-file)) | 406 | (let* ((file (or file gnus-registry-cache-file)) |
| 362 | (db (or db gnus-registry-db))) | 407 | (db (or db gnus-registry-db)) |
| 408 | (clone (clone db))) | ||
| 363 | (gnus-message 5 "Saving Gnus registry (%d entries) to %s..." | 409 | (gnus-message 5 "Saving Gnus registry (%d entries) to %s..." |
| 364 | (registry-size db) file) | 410 | (registry-size db) file) |
| 365 | (registry-prune | 411 | (registry-prune |
| 366 | db gnus-registry-default-sort-function) | 412 | db gnus-registry-default-sort-function) |
| 413 | ;; Write a clone of the database with non-ascii group names | ||
| 414 | ;; encoded as 'utf-8. Let-bind `gnus-registry-db' so that | ||
| 415 | ;; functions in the munging process work on our clone. | ||
| 416 | (let ((gnus-registry-db clone)) | ||
| 417 | (gnus-registry--munge-group-names clone 'encode)) | ||
| 367 | ;; TODO: call (gnus-string-remove-all-properties v) on all elements? | 418 | ;; TODO: call (gnus-string-remove-all-properties v) on all elements? |
| 368 | (eieio-persistent-save db file) | 419 | (eieio-persistent-save clone file) |
| 369 | (gnus-message 5 "Saving Gnus registry (size %d) to %s...done" | 420 | (gnus-message 5 "Saving Gnus registry (size %d) to %s...done" |
| 370 | (registry-size db) file))) | 421 | (registry-size db) file))) |
| 371 | 422 | ||
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el index f7ede54b105..930d522c41b 100644 --- a/lisp/gnus/gnus-start.el +++ b/lisp/gnus/gnus-start.el | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | (defvar gnus-agent-covered-methods) | 42 | (defvar gnus-agent-covered-methods) |
| 43 | (defvar gnus-agent-file-loading-local) | 43 | (defvar gnus-agent-file-loading-local) |
| 44 | (defvar gnus-agent-file-loading-cache) | 44 | (defvar gnus-agent-file-loading-cache) |
| 45 | (defvar gnus-topic-alist) | ||
| 45 | 46 | ||
| 46 | (defcustom gnus-startup-file (nnheader-concat gnus-home-directory ".newsrc") | 47 | (defcustom gnus-startup-file (nnheader-concat gnus-home-directory ".newsrc") |
| 47 | "Your `.newsrc' file. | 48 | "Your `.newsrc' file. |
| @@ -2869,7 +2870,12 @@ SPECIFIC-VARIABLES, or those in `gnus-variable-list'." | |||
| 2869 | (princ "(setq gnus-newsrc-file-version ") | 2870 | (princ "(setq gnus-newsrc-file-version ") |
| 2870 | (princ (gnus-prin1-to-string gnus-version)) | 2871 | (princ (gnus-prin1-to-string gnus-version)) |
| 2871 | (princ ")\n")) | 2872 | (princ ")\n")) |
| 2872 | 2873 | ;; Sort `gnus-newsrc-alist' according to order in | |
| 2874 | ;; `gnus-group-list'. | ||
| 2875 | (setq gnus-newsrc-alist | ||
| 2876 | (mapcar (lambda (g) | ||
| 2877 | (nth 1 (gethash g gnus-newsrc-hashtb))) | ||
| 2878 | (delete "dummy.group" gnus-group-list))) | ||
| 2873 | (let* ((print-quoted t) | 2879 | (let* ((print-quoted t) |
| 2874 | (print-readably t) | 2880 | (print-readably t) |
| 2875 | (print-escape-multibyte nil) | 2881 | (print-escape-multibyte nil) |
| @@ -2889,18 +2895,27 @@ SPECIFIC-VARIABLES, or those in `gnus-variable-list'." | |||
| 2889 | ;; Remove the `gnus-killed-list' from the list of variables | 2895 | ;; Remove the `gnus-killed-list' from the list of variables |
| 2890 | ;; to be saved, if required. | 2896 | ;; to be saved, if required. |
| 2891 | (delq 'gnus-killed-list (copy-sequence gnus-variable-list))))) | 2897 | (delq 'gnus-killed-list (copy-sequence gnus-variable-list))))) |
| 2898 | ;; Encode group names in `gnus-newsrc-alist' and | ||
| 2899 | ;; `gnus-topic-alist' in order to keep newsrc.eld files | ||
| 2900 | ;; compatible with older versions of Gnus. At some point, | ||
| 2901 | ;; if/when a new version of Gnus is released, stop doing | ||
| 2902 | ;; this and move the corresponding decode in | ||
| 2903 | ;; `gnus-read-newsrc-el-file' into a conversion routine. | ||
| 2904 | (gnus-newsrc-alist | ||
| 2905 | (mapcar (lambda (info) | ||
| 2906 | (cons (encode-coding-string (car info) 'utf-8-emacs) | ||
| 2907 | (cdr info))) | ||
| 2908 | gnus-newsrc-alist)) | ||
| 2909 | (gnus-topic-alist | ||
| 2910 | (when (memq 'gnus-topic-alist variables) | ||
| 2911 | (mapcar (lambda (elt) | ||
| 2912 | (cons (car elt) ; Topic name | ||
| 2913 | (mapcar (lambda (g) | ||
| 2914 | (encode-coding-string | ||
| 2915 | g 'utf-8-emacs)) | ||
| 2916 | (cdr elt)))) | ||
| 2917 | gnus-topic-alist))) | ||
| 2892 | variable) | 2918 | variable) |
| 2893 | ;; A bit of a fake-out here: the original value of | ||
| 2894 | ;; `gnus-newsrc-alist' isn't written to file, instead it is | ||
| 2895 | ;; constructed at the last minute by combining the group | ||
| 2896 | ;; ordering in `gnus-group-list' with the group infos from | ||
| 2897 | ;; `gnus-newsrc-hashtb'. | ||
| 2898 | (set (nth (seq-position gnus-variable-list 'gnus-newsrc-alist) | ||
| 2899 | gnus-variable-list) | ||
| 2900 | (mapcar (lambda (g) | ||
| 2901 | (nth 1 (gethash g gnus-newsrc-hashtb))) | ||
| 2902 | (delete "dummy.group" gnus-group-list))) | ||
| 2903 | |||
| 2904 | ;; Insert the variables into the file. | 2919 | ;; Insert the variables into the file. |
| 2905 | (while variables | 2920 | (while variables |
| 2906 | (when (and (boundp (setq variable (pop variables))) | 2921 | (when (and (boundp (setq variable (pop variables))) |