bug-gnu-emacs
[Top][All Lists]
Advanced

[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: Thu, 3 Dec 2015 08:40:31 +0000
User-agent: Mutt/1.5.23 (2014-03-12)

Hello, Eli.

On Wed, Dec 02, 2015 at 03:50:49PM +0200, Eli Zaretskii wrote:
> > Date: Wed, 2 Dec 2015 11:27:22 +0000
> > Cc: address@hidden
> > From: Alan Mackenzie <address@hidden>

> > > I think NEWS is the appropriate place to alert them to this.

> > I'm a bit wary about NEWS.  How many people actually read it thoroughly?
> > At each new release, I try to read NEWS, but my eyes start glazing over
> > before I even get half way through.

> If they don't pay attention, they will stay with the old format.  Do
> they lose much?

They will lose the mark ring being save.  Precisely that.  Possibly more
information will be added to buffer entries in the future (version 208
seems designed to allow that possibility whilst staying backward
compatible).

> > But that aside, how about the following NEWS entry (to be followed by
> > actual code)?

> LGTM, thanks.

OK, here is the patch.  Do you think I should solicit a review from
somebody else before I commit it to emacs-25?


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.



diff --git a/etc/NEWS b/etc/NEWS
index a18c9ce..e7439fd 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -371,6 +371,17 @@ current package keywords are recognized.  Set the new 
option
 It's meant for use together with `compile':
 emacs -batch --eval "(checkdoc-file \"subr.el\")"
 
+** Desktop
+
+---
+*** The desktop format version has been upgraded from 206 to 208.
+Although Emacs 25.1 can read a version 206 desktop, earlier Emacsen
+cannot read a version 208 desktop.  To upgrade your desktop file, you
+must explicitly request the upgrade, by C-u M-x desktop-save.  You are
+recommended to do this as soon as you have firmly upgraded to Emacs
+25.1 (or later).  Should you ever need to downgrade your desktop file
+to version 206, you can do this with C-u C-u M-x desktop-save.
+
 ** New function `bookmark-set-no-overwrite' bound to C-x r M.
 It raises an error if a bookmark of that name already exists,
 unlike `bookmark-set' which silently updates an existing bookmark.
diff --git a/lisp/desktop.el b/lisp/desktop.el
index 5a709b9..ee7a7ae 100644
--- a/lisp/desktop.el
+++ b/lisp/desktop.el
@@ -140,8 +140,15 @@
 
 (defvar desktop-file-version "208"
   "Version number of desktop file format.
-Written into the desktop file and used at desktop read to provide
-backward compatibility.")
+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-io-file-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.
 
 ;; ----------------------------------------------------------------------------
 ;; USER OPTIONS -- settings you might want to play with.
@@ -693,6 +700,7 @@ desktop-clear
 if different)."
   (interactive)
   (desktop-lazy-abort)
+  (setq desktop-io-file-version nil)
   (dolist (var desktop-globals-to-clear)
     (if (symbolp var)
        (eval `(setq-default ,var nil))
@@ -781,44 +789,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-io-file-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)
@@ -983,20 +993,33 @@ desktop-save-frameset
                            :predicate #'desktop--check-dont-save))))
 
 ;;;###autoload
-(defun desktop-save (dirname &optional release only-if-changed)
+(defun desktop-save (dirname &optional release only-if-changed version)
   "Save the desktop in a desktop file.
 Parameter DIRNAME specifies where to save the desktop file.
 Optional parameter RELEASE says whether we're done with this desktop.
 If ONLY-IF-CHANGED is non-nil, compare the current desktop information
 to that in the desktop file, and if the desktop information has not
-changed since it was last saved then do not rewrite the file."
+changed since it was last saved then do not rewrite the file.
+
+When called interactively, a bare command prefix, C-u, will cause
+the desktop file to be saved in format version 208 (which only
+Emacs 25.1 and later can read).  A double command prefix, C-u
+C-u, will save the file in version 206 (readable by any Emacs
+from version 22.1 onwards).  Confirmation will be requested in
+either case.  In a non-interactive call, VERSION can be given as
+either 206 or 208, and this will be accepted as the format
+version in which to save the desktop without further
+confirmation."
   (interactive (list
                 ;; Or should we just use (car desktop-path)?
                 (let ((default (if (member "." desktop-path)
                                    default-directory
                                  user-emacs-directory)))
                   (read-directory-name "Directory to save desktop file in: "
-                                       default default t))))
+                                       default default t))
+                nil
+                nil
+                current-prefix-arg))
   (setq desktop-dirname (file-name-as-directory (expand-file-name dirname)))
   (save-excursion
     (let ((eager desktop-restore-eager)
@@ -1017,12 +1040,34 @@ 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-io-file-version
+              (cond
+               ((equal version '(4))
+                (if (or (eq desktop-io-file-version 208)
+                        (yes-or-no-p "Save desktop file in format 208 \
+\(Readable by Emacs 25.1 and later only)? "))
+                    208
+                  (or desktop-io-file-version desktop-native-file-version)))
+               ((equal version '(16))
+                (if (or (eq desktop-io-file-version 206)
+                        (yes-or-no-p "Save desktop file in format 206 \
+\(Readable by all Emacs versions since 22.1)? "))
+                    206
+                  (or desktop-io-file-version desktop-native-file-version)))
+               ((memq version '(206 208))
+                version)
+               ((null desktop-io-file-version) ; As yet, no desktop file 
exists.
+                desktop-native-file-version)
+               (t
+                desktop-io-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-io-file-version) "\n"
           ";; Emacs version " emacs-version "\n")
          (save-excursion (run-hooks 'desktop-save-hook))
          (goto-char (point-max))
@@ -1052,7 +1097,7 @@ desktop-save
                            "desktop-create-buffer"
                          "desktop-append-buffer-args")
                        " "
-                       desktop-file-version)
+                       (format "%d" desktop-io-file-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))
@@ -1390,6 +1435,8 @@ desktop-create-buffer
      compacted-vars
      &rest _unsupported)
 
+  (setq desktop-io-file-version file-version)
+
   (let ((desktop-file-version      file-version)
        (desktop-buffer-file-name   buffer-filename)
        (desktop-buffer-name        buffer-name)


-- 
Alan Mackenzie (Nuremberg, Germany).





reply via email to

[Prev in Thread] Current Thread [Next in Thread]