aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2016-01-18 13:32:22 +0000
committerAlan Mackenzie2016-01-18 13:32:22 +0000
commit20defc5538de705fc6b39d5a754244e6787db162 (patch)
tree0b68d5c295c3f7c0f878b4654955fb6b43ce0962
parent130d512045aa376333b664d58c501b3884187592 (diff)
downloademacs-20defc5538de705fc6b39d5a754244e6787db162.tar.gz
emacs-20defc5538de705fc6b39d5a754244e6787db162.zip
Desktop: protect users against inadvertant upgrading of desktop file.
An upgraded (version 208) desktop file cannot be read in Emacs < 25. * etc/NEWS: Add an entry about upgrading a desktop file. * lisp/desktop.el (desktop-file-version): Amend doc string. (desktop-native-file-version, desktop-io-file-version): new variables. (desktop-clear): Set desktop-io-file-version to nil. (desktop-buffer-info): make the presence of the last item on the list conditional on (>= desktop-io-file-version 208). (desktop-save): Add extra parameter VERSION to take user's C-u or C-u C-u. Amend the doc string. Add code to determine the output file version. (desktop-create-buffer): Set desktop-io-file-version to the input file's version.
-rw-r--r--etc/NEWS11
-rw-r--r--lisp/desktop.el151
2 files changed, 114 insertions, 48 deletions
diff --git a/etc/NEWS b/etc/NEWS
index c0be46f5ec8..e9b539a3785 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -315,6 +315,17 @@ current package keywords are recognized. Set the new option
315It's meant for use together with `compile': 315It's meant for use together with `compile':
316emacs -batch --eval "(checkdoc-file \"subr.el\")" 316emacs -batch --eval "(checkdoc-file \"subr.el\")"
317 317
318** Desktop
319
320---
321*** The desktop format version has been upgraded from 206 to 208.
322Although Emacs 25.1 can read a version 206 desktop, earlier Emacsen
323cannot read a version 208 desktop. To upgrade your desktop file, you
324must explicitly request the upgrade, by C-u M-x desktop-save. You are
325recommended to do this as soon as you have firmly upgraded to Emacs
32625.1 (or later). Should you ever need to downgrade your desktop file
327to version 206, you can do this with C-u C-u M-x desktop-save.
328
318+++ 329+++
319** New function `bookmark-set-no-overwrite' bound to C-x r M. 330** New function `bookmark-set-no-overwrite' bound to C-x r M.
320It raises an error if a bookmark of that name already exists, 331It raises an error if a bookmark of that name already exists,
diff --git a/lisp/desktop.el b/lisp/desktop.el
index cb973c48f8d..e795d9c2300 100644
--- a/lisp/desktop.el
+++ b/lisp/desktop.el
@@ -140,8 +140,15 @@
140 140
141(defvar desktop-file-version "208" 141(defvar desktop-file-version "208"
142 "Version number of desktop file format. 142 "Version number of desktop file format.
143Written into the desktop file and used at desktop read to provide 143Used at desktop read to provide backward compatibility.")
144backward compatibility.") 144
145(defconst desktop-native-file-version 208
146 "Format version of the current desktop package, an integer.")
147(defvar desktop-io-file-version nil
148 "The format version of the current desktop file (an integer) or nil.")
149;; Note: Historically, the version number is embedded in the entry for
150;; each buffer. It is highly inadvisable for different buffer entries
151;; to have different format versions.
145 152
146;; ---------------------------------------------------------------------------- 153;; ----------------------------------------------------------------------------
147;; USER OPTIONS -- settings you might want to play with. 154;; USER OPTIONS -- settings you might want to play with.
@@ -693,6 +700,7 @@ deletes all frames except the selected one (and its minibuffer frame,
693if different)." 700if different)."
694 (interactive) 701 (interactive)
695 (desktop-lazy-abort) 702 (desktop-lazy-abort)
703 (setq desktop-io-file-version nil)
696 (dolist (var desktop-globals-to-clear) 704 (dolist (var desktop-globals-to-clear)
697 (if (symbolp var) 705 (if (symbolp var)
698 (eval `(setq-default ,var nil)) 706 (eval `(setq-default ,var nil))
@@ -781,44 +789,46 @@ buffer, which is (in order):
781 local variables; 789 local variables;
782 auxiliary information given by `desktop-var-serdes-funs'." 790 auxiliary information given by `desktop-var-serdes-funs'."
783 (set-buffer buffer) 791 (set-buffer buffer)
784 (list 792 `(
785 ;; base name of the buffer; replaces the buffer name if managed by uniquify 793 ;; base name of the buffer; replaces the buffer name if managed by uniquify
786 (and (fboundp 'uniquify-buffer-base-name) (uniquify-buffer-base-name)) 794 ,(and (fboundp 'uniquify-buffer-base-name) (uniquify-buffer-base-name))
787 ;; basic information 795 ;; basic information
788 (desktop-file-name (buffer-file-name) desktop-dirname) 796 ,(desktop-file-name (buffer-file-name) desktop-dirname)
789 (buffer-name) 797 ,(buffer-name)
790 major-mode 798 ,major-mode
791 ;; minor modes 799 ;; minor modes
792 (let (ret) 800 ,(let (ret)
793 (dolist (minor-mode (mapcar #'car minor-mode-alist) ret) 801 (dolist (minor-mode (mapcar #'car minor-mode-alist) ret)
794 (and (boundp minor-mode) 802 (and (boundp minor-mode)
795 (symbol-value minor-mode) 803 (symbol-value minor-mode)
796 (let* ((special (assq minor-mode desktop-minor-mode-table)) 804 (let* ((special (assq minor-mode desktop-minor-mode-table))
797 (value (cond (special (cadr special)) 805 (value (cond (special (cadr special))
798 ((functionp minor-mode) minor-mode)))) 806 ((functionp minor-mode) minor-mode))))
799 (when value (cl-pushnew value ret)))))) 807 (when value (cl-pushnew value ret))))))
800 ;; point and mark, and read-only status 808 ;; point and mark, and read-only status
801 (point) 809 ,(point)
802 (list (mark t) mark-active) 810 ,(list (mark t) mark-active)
803 buffer-read-only 811 ,buffer-read-only
804 ;; auxiliary information 812 ;; auxiliary information
805 (when (functionp desktop-save-buffer) 813 ,(when (functionp desktop-save-buffer)
806 (funcall desktop-save-buffer desktop-dirname)) 814 (funcall desktop-save-buffer desktop-dirname))
807 ;; local variables 815 ;; local variables
808 (let ((loclist (buffer-local-variables)) 816 ,(let ((loclist (buffer-local-variables))
809 (ll nil)) 817 (ll nil))
810 (dolist (local desktop-locals-to-save) 818 (dolist (local desktop-locals-to-save)
811 (let ((here (assq local loclist))) 819 (let ((here (assq local loclist)))
812 (cond (here 820 (cond (here
813 (push here ll)) 821 (push here ll))
814 ((member local loclist) 822 ((member local loclist)
815 (push local ll))))) 823 (push local ll)))))
816 ll) 824 ll)
817 (mapcar (lambda (record) 825 ,@(when (>= desktop-io-file-version 208)
818 (let ((var (car record))) 826 (list
819 (list var 827 (mapcar (lambda (record)
820 (funcall (cadr record) (symbol-value var))))) 828 (let ((var (car record)))
821 desktop-var-serdes-funs))) 829 (list var
830 (funcall (cadr record) (symbol-value var)))))
831 desktop-var-serdes-funs)))))
822 832
823;; ---------------------------------------------------------------------------- 833;; ----------------------------------------------------------------------------
824(defun desktop--v2s (value) 834(defun desktop--v2s (value)
@@ -983,20 +993,41 @@ Frames with a non-nil `desktop-dont-save' parameter are not saved."
983 :predicate #'desktop--check-dont-save)))) 993 :predicate #'desktop--check-dont-save))))
984 994
985;;;###autoload 995;;;###autoload
986(defun desktop-save (dirname &optional release only-if-changed) 996(defun desktop-save (dirname &optional release only-if-changed version)
987 "Save the desktop in a desktop file. 997 "Save the desktop in a desktop file.
988Parameter DIRNAME specifies where to save the desktop file. 998Parameter DIRNAME specifies where to save the desktop file.
989Optional parameter RELEASE says whether we're done with this desktop. 999Optional parameter RELEASE says whether we're done with this
990If ONLY-IF-CHANGED is non-nil, compare the current desktop information 1000desktop. If ONLY-IF-CHANGED is non-nil, compare the current
991to that in the desktop file, and if the desktop information has not 1001desktop information to that in the desktop file, and if the
992changed since it was last saved then do not rewrite the file." 1002desktop information has not changed since it was last saved then
1003do not rewrite the file.
1004
1005This function can save the desktop in either format version
1006208 (which only Emacs 25.1 and later can read) or version
1007206 (which is readable by any Emacs from version 22.1 onwards).
1008By default, it will use the same format the desktop file had when
1009it was last saved, or version 208 when writing a fresh desktop
1010file.
1011
1012To upgrade a version 206 file to version 208, call this command
1013explicitly with a bare prefix argument: C-u M-x desktop-save.
1014You are recommended to do this once you have firmly upgraded to
1015Emacs 25.1 (or later). To downgrade a version 208 file to version
1016206, use a double command prefix: C-u C-u M-x desktop-save.
1017Confirmation will be requested in either case. In a non-interactive
1018call, VERSION can be given as an integer, either 206 or 208, which
1019will be accepted as the format version in which to save the file
1020without further confirmation."
993 (interactive (list 1021 (interactive (list
994 ;; Or should we just use (car desktop-path)? 1022 ;; Or should we just use (car desktop-path)?
995 (let ((default (if (member "." desktop-path) 1023 (let ((default (if (member "." desktop-path)
996 default-directory 1024 default-directory
997 user-emacs-directory))) 1025 user-emacs-directory)))
998 (read-directory-name "Directory to save desktop file in: " 1026 (read-directory-name "Directory to save desktop file in: "
999 default default t)))) 1027 default default t))
1028 nil
1029 nil
1030 current-prefix-arg))
1000 (setq desktop-dirname (file-name-as-directory (expand-file-name dirname))) 1031 (setq desktop-dirname (file-name-as-directory (expand-file-name dirname)))
1001 (save-excursion 1032 (save-excursion
1002 (let ((eager desktop-restore-eager) 1033 (let ((eager desktop-restore-eager)
@@ -1017,12 +1048,34 @@ changed since it was last saved then do not rewrite the file."
1017 (desktop-release-lock) 1048 (desktop-release-lock)
1018 (unless (and new-modtime (desktop-owner)) (desktop-claim-lock))) 1049 (unless (and new-modtime (desktop-owner)) (desktop-claim-lock)))
1019 1050
1051 ;; What format are we going to write the file in?
1052 (setq desktop-io-file-version
1053 (cond
1054 ((equal version '(4))
1055 (if (or (eq desktop-io-file-version 208)
1056 (yes-or-no-p "Save desktop file in format 208 \
1057\(Readable by Emacs 25.1 and later only)? "))
1058 208
1059 (or desktop-io-file-version desktop-native-file-version)))
1060 ((equal version '(16))
1061 (if (or (eq desktop-io-file-version 206)
1062 (yes-or-no-p "Save desktop file in format 206 \
1063\(Readable by all Emacs versions since 22.1)? "))
1064 206
1065 (or desktop-io-file-version desktop-native-file-version)))
1066 ((memq version '(206 208))
1067 version)
1068 ((null desktop-io-file-version) ; As yet, no desktop file exists.
1069 desktop-native-file-version)
1070 (t
1071 desktop-io-file-version)))
1072
1020 (with-temp-buffer 1073 (with-temp-buffer
1021 (insert 1074 (insert
1022 ";; -*- mode: emacs-lisp; coding: emacs-mule; -*-\n" 1075 ";; -*- mode: emacs-lisp; coding: emacs-mule; -*-\n"
1023 desktop-header 1076 desktop-header
1024 ";; Created " (current-time-string) "\n" 1077 ";; Created " (current-time-string) "\n"
1025 ";; Desktop file format version " desktop-file-version "\n" 1078 ";; Desktop file format version " (format "%d" desktop-io-file-version) "\n"
1026 ";; Emacs version " emacs-version "\n") 1079 ";; Emacs version " emacs-version "\n")
1027 (save-excursion (run-hooks 'desktop-save-hook)) 1080 (save-excursion (run-hooks 'desktop-save-hook))
1028 (goto-char (point-max)) 1081 (goto-char (point-max))
@@ -1052,7 +1105,7 @@ changed since it was last saved then do not rewrite the file."
1052 "desktop-create-buffer" 1105 "desktop-create-buffer"
1053 "desktop-append-buffer-args") 1106 "desktop-append-buffer-args")
1054 " " 1107 " "
1055 desktop-file-version) 1108 (format "%d" desktop-io-file-version))
1056 ;; If there's a non-empty base name, we save it instead of the buffer name 1109 ;; If there's a non-empty base name, we save it instead of the buffer name
1057 (when (and base (not (string= base ""))) 1110 (when (and base (not (string= base "")))
1058 (setcar (nthcdr 1 l) base)) 1111 (setcar (nthcdr 1 l) base))
@@ -1390,6 +1443,8 @@ and try to load that."
1390 compacted-vars 1443 compacted-vars
1391 &rest _unsupported) 1444 &rest _unsupported)
1392 1445
1446 (setq desktop-io-file-version file-version)
1447
1393 (let ((desktop-file-version file-version) 1448 (let ((desktop-file-version file-version)
1394 (desktop-buffer-file-name buffer-filename) 1449 (desktop-buffer-file-name buffer-filename)
1395 (desktop-buffer-name buffer-name) 1450 (desktop-buffer-name buffer-name)