From c26ee14fbff9597f5f460d863a00c801c63535ea Mon Sep 17 00:00:00 2001 From: justbur Date: Sun, 21 Jun 2015 12:37:41 -0400 Subject: [PATCH] dotfile-template: Add version and change test First tests for a change in the version. If this test is positive, show a note with a link to the diff. This first result will persist through restarts until the version is updated. Second tests for a change between the last cached template and the current template. Again, show a note for a positive test. This is not a persistent note though and will disappear on restart (even if the user does nothing). --- core/core-dotspacemacs.el | 54 ++++++++++++++++++++++++++++++ core/core-spacemacs-buffer.el | 34 +++++++++++++++++++ core/templates/.spacemacs.template | 5 +++ 3 files changed, 93 insertions(+) diff --git a/core/core-dotspacemacs.el b/core/core-dotspacemacs.el index 68c198de16fb..28da2d5cb3e3 100644 --- a/core/core-dotspacemacs.el +++ b/core/core-dotspacemacs.el @@ -49,6 +49,10 @@ then this is used. If ~/.spacemacs does not exist, then check for init.el in dotspacemacs-directory and use this if it exists. Otherwise, fallback to ~/.spacemacs") +(defvar dotspacemacs-version nil + "Set in .spacemacs and used to check user's .spacemacs file +format version against the .spacemacs template.") + (defvar dotspacemacs-verbose-loading nil "If non nil output loading progess in `*Messages*' buffer.") @@ -295,6 +299,56 @@ before copying the file if the destination already exists." ".spacemacs.template") dotspacemacs-filepath t) (message "%s has been installed." dotspacemacs-filepath)))) +(defun dotspacemacs//file-hash (file) + "Get SHA1 hash of FILE." + (with-temp-buffer + (insert-file-contents-literally file) + (secure-hash 'sha1 (buffer-string)))) + +(defun dotspacemacs/template-changed-p () + "Compare hash of current template against cached template and +return t if the template has changed. If there is a change (or no +template has been chached yet) save new template value to cache +file, meaning this function should only be called once on +startup." + (let* ((cached-file + (expand-file-name (concat spacemacs-cache-directory + ".spacemacs.template"))) + (old-hash + (when (file-exists-p cached-file) + (dotspacemacs//file-hash cached-file))) + (current-file + (expand-file-name (concat dotspacemacs-template-directory + ".spacemacs.template"))) + (current-hash + (dotspacemacs//file-hash current-file)) + (no-change? (and old-hash + (string= old-hash current-hash)))) + (unless no-change? + (copy-file current-file cached-file t)) + (not no-change?))) + +(defun dotspacemacs//get-template-version () + "Read the template version from .spacemacs.template" + (let (success) + (with-temp-buffer + (insert-file-contents + (concat dotspacemacs-template-directory ".spacemacs.template")) + (setq success + (re-search-forward + "^\\s-*?(setq\\s-+?dotspacemacs-version\\s-+?\"\\([0-9.]+\\)\"\\s-*?)" + nil t)) + (if success + (match-string 1) + (error "error: Cannot read .spacemacs.template version"))))) + +(defun dotspacemacs/new-template-version-p () + "Compare version of current template against user's .spacemacs +version and return t if the template has changed." + (let ((dotspacemacs-template-version (dotspacemacs//get-template-version))) + (when dotspacemacs-version + (version< dotspacemacs-version dotspacemacs-template-version)))) + (defun dotspacemacs//ido-completing-read (prompt candidates) "Call `ido-completing-read' with a CANDIDATES alist where the key is a display strng and the value is the actual value to return." diff --git a/core/core-spacemacs-buffer.el b/core/core-spacemacs-buffer.el index 3cdd71e6c2b7..2da91c20f753 100644 --- a/core/core-spacemacs-buffer.el +++ b/core/core-spacemacs-buffer.el @@ -27,6 +27,9 @@ version the release note it displayed") (defvar spacemacs-buffer--note-widgets nil "List of widgets used to display the release note.") +(defvar spacemacs-buffer--dotfile-version-widget nil + "Widget displaying note about old dotfile version") + (defvar spacemacs-buffer--previous-insert-type nil "Previous type of note inserted.") @@ -63,6 +66,15 @@ Doge special text banner can be reachable via `999', `doge' or `random*'. spacemacs-version))) (spacemacs-buffer/toggle-note (concat spacemacs-release-notes-directory "0.104.txt") 'release-note)) + ;; If the dotfile is installed first check for a change in the template + ;; version, then check for a change from the cached version + (when (file-exists-p dotspacemacs-filepath) + (if (dotspacemacs/new-template-version-p) + (spacemacs-buffer//insert-dotfile-template-note t) + ;; note the template changed function will always be nil if called a + ;; second time + (when (dotspacemacs/template-changed-p) + (spacemacs-buffer//insert-dotfile-template-note nil)))) (spacemacs//redisplay)))) (defun spacemacs-buffer//choose-banner () @@ -248,6 +260,28 @@ If TYPE is nil, just remove widgets." (spacemacs/dump-vars-to-file '(spacemacs-buffer--release-note-version) spacemacs-buffer--cache-file)) +(defun spacemacs-buffer//insert-dotfile-template-note (version-change?) + (let ((note (if version-change? + "Your dotfile version is older than the version of the template " + "Detected change in dotfile template "))) + (widget-insert (concat "\n" note)) + (setq spacemacs-buffer--dotfile-version-widget + (widget-create 'push-button + :tag (propertize "Show diff with your dotfile" 'face 'font-lock-warning-face) + :help-echo "Open ediff between your .spacemacs and template." + :action (lambda (&rest ignore) + (spacemacs/ediff-dotfile-and-template) + (widget-delete spacemacs-buffer--dotfile-version-widget) + (with-current-buffer "*spacemacs*" + (let ((inhibit-read-only t)) + (save-excursion + (goto-char (point-min)) + (search-forward note nil t) + (replace-match ""))))) + :mouse-face 'highlight + :follow-link "\C-m")) + (widget-insert "\n"))) + (defun spacemacs-buffer/set-mode-line (format) "Set mode-line format for spacemacs buffer." (with-current-buffer (get-buffer-create "*spacemacs*") diff --git a/core/templates/.spacemacs.template b/core/templates/.spacemacs.template index 0b946ecaa298..e472902abaaf 100644 --- a/core/templates/.spacemacs.template +++ b/core/templates/.spacemacs.template @@ -2,6 +2,11 @@ ;; This file is loaded by Spacemacs at startup. ;; It must be stored in your home directory. +;; Version of the .spacemacs file format. When the .spacemacs template is +;; updated this version number will increase. If you comment out this line, +;; the version check will be disabled. +(setq dotspacemacs-version "0.0") + (defun dotspacemacs/layers () "Configuration Layers declaration. You should not put any user code in this function besides modifying the variable