[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#22025: Emacs 25 corrupts Emacs 24 .emacs.desktop.
From: |
Alan Mackenzie |
Subject: |
bug#22025: Emacs 25 corrupts Emacs 24 .emacs.desktop. |
Date: |
Tue, 1 Dec 2015 12:19:41 +0000 |
User-agent: |
Mutt/1.5.23 (2014-03-12) |
On Fri, Nov 27, 2015 at 11:05:25AM +0200, Eli Zaretskii wrote:
> > Date: Fri, 27 Nov 2015 08:38:37 +0000
> > From: Alan Mackenzie <acm@muc.de>
> > Emacs 25 has read a version 206 .desktop file, but written a version 208
> > file on termination. Emacs 24 cannot execute this version.
> > There was no yes-or-no-p asking "are you sure you want to convert your
> > desktop to a format incompatible with previous Emacs versions?".
> > Manually restoring a .desktop to version 206 is fraught with
> > difficulties, even for somebody (myself) who understands the issues
> > reasonably well, and has an old version of .desktop saved "just in
> > case".
> > Recommendation
> > --------------
> > Emacs 25, having loaded a version 206 .desktop, should save it in the
> > same format until the user has positively consented to it being
> > converted to version 208.
> This would be a nice enhancement, but it certainly isn't a bug in my
> book.
> Of course, if making that happen is relatively easy, it would be good
> to have such a compatibility mode. Patches welcome.
OK, here is a patch. It introduces a customizable variable,
`desktop-version-strategy' which specifies in which version (206 or 208),
the desktop file should be saved. Until that variable is set to non-nil,
the user is prompted each time the desktop is loaded. She is given the
opportunity at that time to customize it immediately via a `yes-or-no-p'.
diff --git a/lisp/desktop.el b/lisp/desktop.el
index 5a709b9..e5b4395 100644
--- a/lisp/desktop.el
+++ b/lisp/desktop.el
@@ -143,6 +143,16 @@ desktop-file-version
Written into the desktop file and used at desktop read to provide
backward compatibility.")
+(defconst desktop-native-file-version 208
+ "Format version of the current desktop package, an integer.")
+(defvar desktop-infile-version nil
+ "The format version of the current desktop file, an integer or nil.")
+;; Note: Historically, the version number is embedded in the entry for
+;; each buffer. It is highly inadvisable for different buffer entries
+;; to have different format versions.
+(defvar desktop-outfile-version nil
+ "The format version in which the desktop file will next be written, or nil")
+
;; ----------------------------------------------------------------------------
;; USER OPTIONS -- settings you might want to play with.
;; ----------------------------------------------------------------------------
@@ -240,6 +250,19 @@ desktop-load-locked-desktop
:group 'desktop
:version "22.2")
+(defcustom desktop-version-strategy nil
+ "Strategy to chose format version when writing .emacs.desktop file.
+Version 206 is compatible with Emacs 22.x, 23.x and 24.x, and also with Emacs
25.x.
+Version 208 is enhanced, but incompatible with Emacs 24.x and earlier."
+ :type '(radio
+ (const :tag "Keep current format, and prompt user again when there's
\
+an old format at next desktop load." nil)
+ (const :tag "Keep current format, but don't prompt the user again."
t)
+ (const :tag "Save desktop file in format 206 (compatible with Emacs
<= 24)." 206)
+ (const :tag "Save desktop file in format 208 (Emacs >= 25)." 208))
+ :group 'desktop
+ :version "25.1")
+
(define-obsolete-variable-alias 'desktop-basefilename
'desktop-base-file-name "22.1")
@@ -781,44 +804,46 @@ desktop-buffer-info
local variables;
auxiliary information given by `desktop-var-serdes-funs'."
(set-buffer buffer)
- (list
- ;; base name of the buffer; replaces the buffer name if managed by uniquify
- (and (fboundp 'uniquify-buffer-base-name) (uniquify-buffer-base-name))
- ;; basic information
- (desktop-file-name (buffer-file-name) desktop-dirname)
- (buffer-name)
- major-mode
- ;; minor modes
- (let (ret)
- (dolist (minor-mode (mapcar #'car minor-mode-alist) ret)
- (and (boundp minor-mode)
- (symbol-value minor-mode)
- (let* ((special (assq minor-mode desktop-minor-mode-table))
- (value (cond (special (cadr special))
- ((functionp minor-mode) minor-mode))))
- (when value (cl-pushnew value ret))))))
- ;; point and mark, and read-only status
- (point)
- (list (mark t) mark-active)
- buffer-read-only
- ;; auxiliary information
- (when (functionp desktop-save-buffer)
- (funcall desktop-save-buffer desktop-dirname))
- ;; local variables
- (let ((loclist (buffer-local-variables))
- (ll nil))
- (dolist (local desktop-locals-to-save)
- (let ((here (assq local loclist)))
- (cond (here
- (push here ll))
- ((member local loclist)
- (push local ll)))))
- ll)
- (mapcar (lambda (record)
- (let ((var (car record)))
- (list var
- (funcall (cadr record) (symbol-value var)))))
- desktop-var-serdes-funs)))
+ `(
+ ;; base name of the buffer; replaces the buffer name if managed by uniquify
+ ,(and (fboundp 'uniquify-buffer-base-name) (uniquify-buffer-base-name))
+ ;; basic information
+ ,(desktop-file-name (buffer-file-name) desktop-dirname)
+ ,(buffer-name)
+ ,major-mode
+ ;; minor modes
+ ,(let (ret)
+ (dolist (minor-mode (mapcar #'car minor-mode-alist) ret)
+ (and (boundp minor-mode)
+ (symbol-value minor-mode)
+ (let* ((special (assq minor-mode desktop-minor-mode-table))
+ (value (cond (special (cadr special))
+ ((functionp minor-mode) minor-mode))))
+ (when value (cl-pushnew value ret))))))
+ ;; point and mark, and read-only status
+ ,(point)
+ ,(list (mark t) mark-active)
+ ,buffer-read-only
+ ;; auxiliary information
+ ,(when (functionp desktop-save-buffer)
+ (funcall desktop-save-buffer desktop-dirname))
+ ;; local variables
+ ,(let ((loclist (buffer-local-variables))
+ (ll nil))
+ (dolist (local desktop-locals-to-save)
+ (let ((here (assq local loclist)))
+ (cond (here
+ (push here ll))
+ ((member local loclist)
+ (push local ll)))))
+ ll)
+ ,@(when (>= desktop-outfile-version 208)
+ (list
+ (mapcar (lambda (record)
+ (let ((var (car record)))
+ (list var
+ (funcall (cadr record) (symbol-value var)))))
+ desktop-var-serdes-funs)))))
;; ----------------------------------------------------------------------------
(defun desktop--v2s (value)
@@ -1017,12 +1042,22 @@ desktop-save
(desktop-release-lock)
(unless (and new-modtime (desktop-owner)) (desktop-claim-lock)))
+ ;; What format are we going to write the file in?
+ (setq desktop-outfile-version
+ (cond
+ ((memq desktop-version-strategy '(208 206))
+ desktop-version-strategy)
+ (desktop-infile-version)
+ (desktop-outfile-version)
+ (t ; As yet, no desktop file exists.
+ desktop-native-file-version)))
+
(with-temp-buffer
(insert
";; -*- mode: emacs-lisp; coding: emacs-mule; -*-\n"
desktop-header
";; Created " (current-time-string) "\n"
- ";; Desktop file format version " desktop-file-version "\n"
+ ";; Desktop file format version " (format "%d"
desktop-outfile-version) "\n"
";; Emacs version " emacs-version "\n")
(save-excursion (run-hooks 'desktop-save-hook))
(goto-char (point-max))
@@ -1052,7 +1087,7 @@ desktop-save
"desktop-create-buffer"
"desktop-append-buffer-args")
" "
- desktop-file-version)
+ (format "%d" desktop-outfile-version))
;; If there's a non-empty base name, we save it instead of the
buffer name
(when (and base (not (string= base "")))
(setcar (nthcdr 1 l) base))
@@ -1121,6 +1156,44 @@ desktop-first-buffer
(defvar desktop-buffer-ok-count)
(defvar desktop-buffer-fail-count)
+;; ----------------------------------------------------------------------------
+;; Instruct and prompt the user about desktop format version change.
+(defvar desktop-customize-strategy-flag nil
+ "Non-nil when the user has requested cutomization of
`desktop-version-strategy'")
+
+(defun desktop-warn-about-and-prompt-for-strategy ()
+ "Warn the user that her desktop file is in an old format, and
+prompt her to customize `desktop-version-strategy'."
+ (save-window-excursion
+ (with-output-to-temp-buffer "*Desktop Format Strategy*"
+ (mapc
+ #'princ
+ `("Your desktop file appears to be in an old format "
+ ,(format "%d" desktop-infile-version)
+ ",\nwhich Emacs "
+ ,(format "%s" emacs-version)
+ " should be able to read successfully.\n\n"
+ "Until you configure Emacs to deal with this, you will be\n"
+ "prompted like this each time you load your desktop.\n\n"
+ "You can chose to preserve the original format of your desktop
file,\n"
+ "always to set the format to version 206 (which dates back to Emacs
22.1)\n"
+ "or always to set it to version 208 (the new Emacs 25.x format).\n\n"
+ "BE AWARE THAT Emacs 24.x AND EARLIER CANNOT READ A VERSION 208\n"
+ "DESKTOP FILE!\n\n"
+ "Customize `desktop-version-strategy' to make this choice.\n"
+ "You can do this now (after your buffers have been loaded), or at\n"
+ "any later time.\n\n"
+ "You are recommended to set this user option to version 208 as soon\n"
+ "as you have firmly upgraded to Emacs 25.1 (or later), so as to
enjoy\n"
+ "the enhancements which version 208 provides.\n")))
+
+ (setq desktop-customize-strategy-flag
+ (condition-case nil ; Prevent C-g aborting the desktop load.
+ (yes-or-no-p "Customize desktop-version-strategy now \
+\(after buffers are loaded)? ")
+ (quit nil)))
+ (kill-buffer "*Desktop Format Strategy*")))
+
;; FIXME Interactively, this should have the option to prompt for dirname.
;;;###autoload
(defun desktop-read (&optional dirname)
@@ -1230,6 +1303,11 @@ desktop-read
(set-window-next-buffers window nil))))
(setq desktop-saved-frameset nil)
(if desktop-autosave-was-enabled (desktop-auto-save-enable))
+
+ ;; Has the user requested to configure `desktop-version-strategy'?
+ (when desktop-customize-strategy-flag
+ (setq desktop-customize-strategy-flag nil)
+ (customize-variable 'desktop-version-strategy))
t))
;; No desktop file found.
(let ((default-directory desktop-dirname))
@@ -1400,6 +1478,17 @@ desktop-create-buffer
(desktop-buffer-read-only buffer-readonly)
(desktop-buffer-misc buffer-misc)
(desktop-buffer-locals buffer-locals))
+
+ ;; If this is the first buffer of the session, and the user
+ ;; appears to have just updated to the current Emacs version, warn
+ ;; her about the change in the desktop file format, and prompt her
+ ;; to set `desktop-version-strategy.
+ (when (null desktop-infile-version)
+ (setq desktop-infile-version file-version)
+ (when (and (null desktop-version-strategy)
+ (/= desktop-infile-version desktop-native-file-version))
+ (desktop-warn-about-and-prompt-for-strategy)))
+
;; To make desktop files with relative file names possible, we cannot
;; allow `default-directory' to change. Therefore we save current buffer.
(save-current-buffer
--
Alan Mackenzie (Nuremberg, Germany).
- bug#22025: Emacs 25 corrupts Emacs 24 .emacs.desktop.,
Alan Mackenzie <=
- bug#22025: Emacs 25 corrupts Emacs 24 .emacs.desktop., Eli Zaretskii, 2015/12/01
- bug#22025: Emacs 25 corrupts Emacs 24 .emacs.desktop., Eli Zaretskii, 2015/12/01
- bug#22025: Emacs 25 corrupts Emacs 24 .emacs.desktop., Alan Mackenzie, 2015/12/02
- bug#22025: Emacs 25 corrupts Emacs 24 .emacs.desktop., Andy Moreton, 2015/12/02
- bug#22025: Emacs 25 corrupts Emacs 24 .emacs.desktop., Eli Zaretskii, 2015/12/02
- bug#22025: Emacs 25 corrupts Emacs 24 .emacs.desktop., Alan Mackenzie, 2015/12/03