- (let ((file gnus-registry-cache-file))
- (save-excursion
- (set-buffer (gnus-get-buffer-create " *Gnus-registry-cache*"))
- (make-local-variable 'version-control)
- (setq version-control gnus-backup-startup-file)
- (setq buffer-file-name file)
- (setq default-directory (file-name-directory buffer-file-name))
- (buffer-disable-undo)
- (erase-buffer)
- (gnus-message 5 "Saving %s..." file)
- (if gnus-save-startup-file-via-temp-buffer
- (let ((coding-system-for-write gnus-ding-file-coding-system)
- (standard-output (current-buffer)))
- (gnus-gnus-to-quick-newsrc-format
- t "gnus registry startup file" 'gnus-registry-alist)
- (gnus-registry-cache-whitespace file)
- (save-buffer))
- (let ((coding-system-for-write gnus-ding-file-coding-system)
- (version-control gnus-backup-startup-file)
- (startup-file file)
- (working-dir (file-name-directory file))
- working-file
- (i -1))
- ;; Generate the name of a non-existent file.
- (while (progn (setq working-file
- (format
- (if (and (eq system-type 'ms-dos)
- (not (gnus-long-file-names)))
- "%s#%d.tm#" ; MSDOS limits files to 8+3
- (if (memq system-type '(vax-vms axp-vms))
- "%s$tmp$%d"
- "%s#tmp#%d"))
- working-dir (setq i (1+ i))))
- (file-exists-p working-file)))
-
- (unwind-protect
- (progn
- (gnus-with-output-to-file working-file
- (gnus-gnus-to-quick-newsrc-format
- t "gnus registry startup file" 'gnus-registry-alist))
-
- ;; These bindings will mislead the current buffer
- ;; into thinking that it is visiting the startup
- ;; file.
- (let ((buffer-backed-up nil)
- (buffer-file-name startup-file)
- (file-precious-flag t)
- (setmodes (file-modes startup-file)))
- ;; Backup the current version of the startup file.
- (backup-buffer)
-
- ;; Replace the existing startup file with the temp file.
- (rename-file working-file startup-file t)
- (gnus-set-file-modes startup-file setmodes)))
- (condition-case nil
- (delete-file working-file)
- (file-error nil)))))
-
- (gnus-kill-buffer (current-buffer))
- (gnus-message 5 "Saving %s...done" file))))
-
-;; Idea from Dan Christensen <jdc@chow.mat.jhu.edu>
-;; Save the gnus-registry file with extra line breaks.
-(defun gnus-registry-cache-whitespace (filename)
- (gnus-message 7 "Adding whitespace to %s" filename)
- (save-excursion
- (goto-char (point-min))
- (while (re-search-forward "^(\\|(\\\"" nil t)
- (replace-match "\n\\&" t))
- (goto-char (point-min))
- (while (re-search-forward " $" nil t)
- (replace-match "" t t))))
-
-(defun gnus-registry-save (&optional force)
- (when (or gnus-registry-dirty force)
- (let ((caching gnus-registry-entry-caching))
- ;; turn off entry caching, so mtime doesn't get recorded
- (setq gnus-registry-entry-caching nil)
- ;; remove entry caches
- (maphash
- (lambda (key value)
- (if (hash-table-p value)
- (remhash key gnus-registry-hashtb)))
- gnus-registry-hashtb)
- ;; remove empty entries
- (when gnus-registry-clean-empty
- (gnus-registry-clean-empty-function))
- ;; now trim and clean text properties from the registry appropriately
- (setq gnus-registry-alist
- (gnus-registry-remove-alist-text-properties
- (gnus-registry-trim
- (gnus-hashtable-to-alist
- gnus-registry-hashtb))))
- ;; really save
- (gnus-registry-cache-save)
- (setq gnus-registry-entry-caching caching)
- (setq gnus-registry-dirty nil))))
-
-(defun gnus-registry-clean-empty-function ()
- "Remove all empty entries from the registry. Returns count thereof."
- (let ((count 0))
-
- (maphash
- (lambda (key value)
- (when (stringp key)
- (dolist (group (gnus-registry-fetch-groups key))
- (when (gnus-parameter-registry-ignore group)
- (gnus-message
- 10
- "gnus-registry: deleted ignored group %s from key %s"
- group key)
- (gnus-registry-delete-group key group)))
-
- (unless (gnus-registry-group-count key)
- (gnus-registry-delete-id key))
-
- (unless (or
- (gnus-registry-fetch-group key)
- ;; TODO: look for specific extra data here!
- ;; in this example, we look for 'label
- (gnus-registry-fetch-extra key 'label))
- (incf count)
- (gnus-registry-delete-id key))
-
- (unless (stringp key)
- (gnus-message
- 10
- "gnus-registry key %s was not a string, removing"
- key)
- (gnus-registry-delete-id key))))
-
- gnus-registry-hashtb)
- count))
-
-(defun gnus-registry-read ()
- (gnus-registry-cache-read)
- (setq gnus-registry-hashtb (gnus-alist-to-hashtable gnus-registry-alist))
- (setq gnus-registry-dirty nil))
-
-(defun gnus-registry-remove-alist-text-properties (v)
- "Remove text properties from all strings in alist."
- (if (stringp v)
- (gnus-string-remove-all-properties v)
- (if (and (listp v) (listp (cdr v)))
- (mapcar 'gnus-registry-remove-alist-text-properties v)
- (if (and (listp v) (stringp (cdr v)))
- (cons (gnus-registry-remove-alist-text-properties (car v))
- (gnus-registry-remove-alist-text-properties (cdr v)))
- v))))
-
-(defun gnus-registry-trim (alist)
- "Trim alist to size, using gnus-registry-max-entries.
-Any entries with extra data (marks, currently) are left alone."
- (if (null gnus-registry-max-entries)
- alist ; just return the alist
- ;; else, when given max-entries, trim the alist
- (let* ((timehash (make-hash-table
- :size 20000
- :test 'equal))
- (precious (make-hash-table
- :size 20000
- :test 'equal))
- (trim-length (- (length alist) gnus-registry-max-entries))
- (trim-length (if (natnump trim-length) trim-length 0))
- precious-list junk-list)
- (maphash
- (lambda (key value)
- (let ((extra (gnus-registry-fetch-extra key)))
- (dolist (item gnus-registry-extra-entries-precious)
- (dolist (e extra)
- (when (equal (nth 0 e) item)
- (puthash key t precious)
- (return))))
- (puthash key (gnus-registry-fetch-extra key 'mtime) timehash)))
- gnus-registry-hashtb)
-
- (dolist (item alist)
- (let ((key (nth 0 item)))
- (if (gethash key precious)
- (push item precious-list)
- (push item junk-list))))
-
- (sort
- junk-list
- (lambda (a b)
- (let ((t1 (or (cdr (gethash (car a) timehash))
- '(0 0 0)))
- (t2 (or (cdr (gethash (car b) timehash))
- '(0 0 0))))
- (time-less-p t1 t2))))
-
- ;; we use the return value of this setq, which is the trimmed alist
- (setq alist (append precious-list
- (nthcdr trim-length junk-list))))))
-