From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Alan Mackenzie Newsgroups: gmane.emacs.bugs Subject: bug#22025: Emacs 25 corrupts Emacs 24 .emacs.desktop. Date: Tue, 1 Dec 2015 12:19:41 +0000 Message-ID: <20151201121940.GA2611@acm.fritz.box> References: <20151127083837.GB1782@acm.fritz.box> <83r3jbstgq.fsf@gnu.org> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1448972302 14018 80.91.229.3 (1 Dec 2015 12:18:22 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Tue, 1 Dec 2015 12:18:22 +0000 (UTC) Cc: 22025@debbugs.gnu.org To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Tue Dec 01 13:18:13 2015 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1a3jsr-0004Kd-0a for geb-bug-gnu-emacs@m.gmane.org; Tue, 01 Dec 2015 13:18:13 +0100 Original-Received: from localhost ([::1]:52138 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a3jsq-0003xQ-IH for geb-bug-gnu-emacs@m.gmane.org; Tue, 01 Dec 2015 07:18:12 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:34832) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a3jsl-0003x0-4D for bug-gnu-emacs@gnu.org; Tue, 01 Dec 2015 07:18:08 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1a3jsg-0007fZ-SZ for bug-gnu-emacs@gnu.org; Tue, 01 Dec 2015 07:18:07 -0500 Original-Received: from debbugs.gnu.org ([208.118.235.43]:44094) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a3jsg-0007fU-ON for bug-gnu-emacs@gnu.org; Tue, 01 Dec 2015 07:18:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.80) (envelope-from ) id 1a3jsg-0003LQ-5F for bug-gnu-emacs@gnu.org; Tue, 01 Dec 2015 07:18:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Alan Mackenzie Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 01 Dec 2015 12:18:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 22025 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 22025-submit@debbugs.gnu.org id=B22025.144897227912847 (code B ref 22025); Tue, 01 Dec 2015 12:18:02 +0000 Original-Received: (at 22025) by debbugs.gnu.org; 1 Dec 2015 12:17:59 +0000 Original-Received: from localhost ([127.0.0.1]:33802 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1a3jsc-0003L8-1z for submit@debbugs.gnu.org; Tue, 01 Dec 2015 07:17:58 -0500 Original-Received: from mail.muc.de ([193.149.48.3]:37224) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1a3jsH-0003Kf-9h for 22025@debbugs.gnu.org; Tue, 01 Dec 2015 07:17:56 -0500 Original-Received: (qmail 60067 invoked by uid 3782); 1 Dec 2015 12:17:35 -0000 Original-Received: from acm.muc.de (p579E8AA8.dip0.t-ipconnect.de [87.158.138.168]) by colin.muc.de (tmda-ofmipd) with ESMTP; Tue, 01 Dec 2015 13:17:34 +0100 Original-Received: (qmail 2658 invoked by uid 1000); 1 Dec 2015 12:19:41 -0000 Content-Disposition: inline In-Reply-To: <83r3jbstgq.fsf@gnu.org> User-Agent: Mutt/1.5.23 (2014-03-12) X-Delivery-Agent: TMDA/1.1.12 (Macallan) X-Primary-Address: acm@muc.de X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:109495 Archived-At: 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 > > 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).