From 65d5e42b8ea603abe25cbf3a832a204c15aeedd8 Mon Sep 17 00:00:00 2001 From: syl20bnr Date: Sun, 29 Oct 2017 00:28:22 -0400 Subject: [PATCH] core: add support for stable ELPA repository hosted on GitHub Use the official spacelpa ELPA repository. address: https://github.com/syl20bnr/spacelpa ELPA repository configuration is now in a file called .lock at the root of the git repository. Its goal is to setup the ELPA repositories for a given branch and it should not be modified! The philosophy of Spacemacs is to never fork the git repository and this lock file has been put in the repo on purpose. Only the master branch will have a .lock file that points to spacelpa, the develop branch won't use the stable ELPA repository and will continue to behave like it always did. BUT for testing purpose and until the first major version of Spacemacs that uses the stable ELPA repo is released I push a .lock file to develop branch that points to spacelpa. I understand that some people can be annoyed by this so the variable configuration-layer--elpa-archives can be overriden by putting a setq in your dotfile in the user-init function like this: (setq configuration-layer--elpa-archives '(("melpa" . "melpa.org/packages/") ("org" . "orgmode.org/elpa/") ("gnu" . "elpa.gnu.org/packages/"))) --- .lock | 19 ++++ core/core-configuration-layer.el | 141 +++++++++++++++++++++++++----- core/core-spacemacs-buffer.el | 2 +- core/core-spacemacs.el | 2 +- core/info/release-notes/0.300.txt | 40 +++++++++ init.el | 2 + 6 files changed, 184 insertions(+), 22 deletions(-) create mode 100644 .lock create mode 100644 core/info/release-notes/0.300.txt diff --git a/.lock b/.lock new file mode 100644 index 000000000..06de5f6cf --- /dev/null +++ b/.lock @@ -0,0 +1,19 @@ +;; -*- mode: emacs-lisp -*- + +(setq configuration-layer--stable-elpa-name "spacelpa") +(setq configuration-layer--stable-elpa-version "0.300") + +(setq configuration-layer--elpa-archives + `(("melpa" . "melpa.org/packages/") + ("org" . "orgmode.org/elpa/") + ("gnu" . "elpa.gnu.org/packages/") + ("spacelpa" . ,(concat configuration-layer--stable-elpa-directory + "spacelpa-" + configuration-layer--stable-elpa-version)))) + +(setq package-archive-priorities + '(("spacelpa" . 8) + ("melpa" . 4) + ("org" . 2) + ("gnu" . 1))) + diff --git a/core/core-configuration-layer.el b/core/core-configuration-layer.el index 688e0ba3f..3e67e3fe6 100644 --- a/core/core-configuration-layer.el +++ b/core/core-configuration-layer.el @@ -46,20 +46,48 @@ configuration-layer-private-directory)) "Spacemacs default directory for private layers.") +(defconst configuration-layer-lock-file + (concat spacemacs-start-directory ".lock") + "Absolute path to the lock file.") + +(defconst configuration-layer--stable-elpa-name "spacelpa" + "Name of the stable ELPA repository. Should be fixed by the lock file.") + +(defconst configuration-layer--stable-elpa-tarball-directory + "https://github.com/syl20bnr/spacelpa/archive/" + "Remote location of the tarball for the ELPA stable directory") + +(defconst configuration-layer--stable-elpa-directory + (expand-file-name + (concat spacemacs-cache-directory "stable-elpa/" emacs-version "/")) + "Remote location of the tarball for the ELPA stable directory") + +(defconst configuration-layer--stable-elpa-version-file + (concat configuration-layer--stable-elpa-directory "version") + "Absolute path to the file containing the current stable elpa repository +version") + +(defvar configuration-layer--stable-elpa-version spacemacs-version + "Version of ELPA stable repository. This value is aimed to be overwritten by +the .lock file at the root of the repository.") + (defun configuration-layer/elpa-directory (root) "Evaluate the correct package subdirectory of ROOT. This is done according to the value of `dotspacemacs-elpa-subdirectory'. -If it is nil, then ROOT is returned. Otherwise a subdirectory of -ROOT is returned." - (if (not dotspacemacs-elpa-subdirectory) - root - (let ((subdir (if (eq 'emacs-version dotspacemacs-elpa-subdirectory) - (format "%d%s%d" - emacs-major-version - version-separator - emacs-minor-version) - (eval dotspacemacs-elpa-subdirectory)))) - (file-name-as-directory (expand-file-name subdir root))))) +This function also appends the name of the current branch of Spacemacs. +If `dotspacemacs-elpa-subdirectory' is nil, then ROOT is used. Otherwise the +subdirectory of ROOT is used." + (concat + (if (not dotspacemacs-elpa-subdirectory) + root + (let ((subdir (if (eq 'emacs-version dotspacemacs-elpa-subdirectory) + (format "%d%s%d" + emacs-major-version + version-separator + emacs-minor-version) + (eval dotspacemacs-elpa-subdirectory)))) + (file-name-as-directory (expand-file-name subdir root)))) + (spacemacs//git-get-current-branch))) (defun configuration-layer/get-elpa-package-install-directory (pkg) "Return the install directory of elpa PKG. Return nil if it is not found." @@ -294,12 +322,9 @@ is not set for the given SLOT." (unless configuration-layer--package-properties-read-onlyp (eval `(oset pkg ,slot value)))) -(defvar configuration-layer--elpa-archives - '(("melpa" . "melpa.org/packages/") - ("org" . "orgmode.org/elpa/") - ("gnu" . "elpa.gnu.org/packages/")) - ;; '(("spacelpa" . "~/.emacs.d/.cache/spacelpa/")) - "List of ELPA archives required by Spacemacs.") +(defvar configuration-layer--elpa-archives nil + "List of ELPA archives required by Spacemacs. This value is set by the lock +file.") (defvar configuration-layer-exclude-all-layers nil "If non nil then only the distribution layer is loaded.") @@ -356,12 +381,17 @@ directory with a name starting with `+'.") "Used to collect information about rollback packages in the cache folder.") +(defun configuration-layer/load-lock-file () + "Load the .lock file" + (load-file configuration-layer-lock-file)) + (defun configuration-layer/initialize () "Initialize `package.el'." (setq configuration-layer--refresh-package-timeout dotspacemacs-elpa-timeout) (unless package--initialized (setq configuration-layer-rollback-directory - (configuration-layer/elpa-directory configuration-layer-rollback-directory)) + (configuration-layer/elpa-directory + configuration-layer-rollback-directory)) (setq package-user-dir (configuration-layer/elpa-directory package-user-dir)) (setq package-archives (configuration-layer//resolve-package-archives @@ -480,6 +510,7 @@ refreshed during the current session." "Load layers declared in dotfile and install associated packages. To prevent package from being installed or uninstalled set the variable `spacemacs-sync-packages' to nil." + (message "%s" (configuration-layer//stable-elpa-directory)) (run-hooks 'configuration-layer-pre-load-hook) (dotspacemacs|call-func dotspacemacs/layers "Calling dotfile layers...") (setq dotspacemacs--configuration-layers-saved @@ -2306,8 +2337,13 @@ depends on it." ,(package-desc-kind obj) ,(package-desc-extras obj)]))) +(defun configuration-layer//patch-package-descriptor (desc) + "Return a patched DESC. +The URL of the descriptor is patched to be the passed URL" + ) + (defun configuration-layer//download-elpa-file - (pkg-name filename archive-url output-dir + (pkg-name filename archive-url output-dirkkj &optional signaturep readmep) "Download FILENAME from distant ELPA repository to OUTPUT-DIR. @@ -2367,7 +2403,7 @@ Original code from dochang at https://github.com/dochang/elpa-clone" (archive-contents (mapcar 'configuration-layer//create-archive-contents-item packages)) - (path (file-name-as-directory (concat output-dir name)))) + (path (file-name-as-directory (concat output-dir "/" name)))) (unless (file-exists-p path) (make-directory path 'create-parents)) (configuration-layer//sync-elpa-packages-files packages path) (push 1 archive-contents) @@ -2377,6 +2413,71 @@ Original code from dochang at https://github.com/dochang/elpa-clone" (prin1 archive-contents (current-buffer)) (save-buffer))))) +(defun configuration-layer/stable-elpa-version () + "Set and return the current version of the ELPA repository. +Returns nil if the version is unknown." + (when (file-exists-p configuration-layer--stable-elpa-version-file) + (with-current-buffer (find-file-noselect + configuration-layer--stable-elpa-version-file) + (buffer-string)))) + +(defun configuration-layer//stable-elpa-tarball-distant-file () + "Return the distant file path of the downloaded tarball of ELPA stable +repository." + (format "%sv%s.tar.gz" + configuration-layer--stable-elpa-tarball-directory + configuration-layer--stable-elpa-version)) + +(defun configuration-layer//stable-elpa-directory () + "Return the local absolute path of the ELPA stable repository." + (cdr (assoc configuration-layer--stable-elpa-name + configuration-layer--elpa-archives))) + +(defun configuration-layer//stable-elpa-tarball-local-file () + "Return the local absolute path for the file of the downloaded tarball of +ELPA stable repository." + (format "%s.tar.gz" (configuration-layer//stable-elpa-directory))) + +(defun configuration-layer//stable-elpa-untar-archive () + "Untar the downloaded archive of stable ELPA." + (require 'tar-mode) + (let (large-file-warning-threshold) + (with-current-buffer (find-file-noselect + (configuration-layer//stable-elpa-tarball-local-file)) + (tar-mode) + (tar-untar-buffer)))) + +(defun configuration-layer/stable-elpa-download-tarball () + "Download and extract the tarball of the stable ELPA repository if it used." + (when (and (assoc configuration-layer--stable-elpa-name + configuration-layer--elpa-archives) + (not (string-equal (configuration-layer/stable-elpa-version) + configuration-layer--stable-elpa-version))) + (let ((address (configuration-layer//stable-elpa-tarball-distant-file)) + (local (configuration-layer//stable-elpa-tarball-local-file))) + (spacemacs-buffer/set-mode-line + (format "Downloading stable ELPA repository: %s..." + configuration-layer--stable-elpa-name)) + (spacemacs//redisplay) + ;; download + (make-directory configuration-layer--stable-elpa-directory t) + (url-copy-file address local 'ok-if-already-exists) + ;; extract + (configuration-layer//stable-elpa-untar-archive) + ;; delete archive + (delete-file local) + ;; update version file + (with-current-buffer (find-file-noselect + configuration-layer--stable-elpa-version-file) + (erase-buffer) + (beginning-of-buffer) + (insert (format "%s" configuration-layer--stable-elpa-version)) + (save-buffer))))) + +;; (configuration-layer/create-elpa-repository +;; "spacelpa" +;; spacemacs-cache-directory) + (defun configuration-layer//package-install-org (func &rest args) "Advice around `package-install' to patch package name and dependencies at install time in order to replace all `org' package installation by diff --git a/core/core-spacemacs-buffer.el b/core/core-spacemacs-buffer.el index b827838ee..0ecf0d41c 100644 --- a/core/core-spacemacs-buffer.el +++ b/core/core-spacemacs-buffer.el @@ -13,7 +13,7 @@ ;; ;;; Code: -(defconst spacemacs-buffer-version-info "0.200.9" +(defconst spacemacs-buffer-version-info "0.300" "Current version used to display addition release information.") (defconst spacemacs-buffer-name "*spacemacs*" diff --git a/core/core-spacemacs.el b/core/core-spacemacs.el index 17f31e677..f5a262289 100644 --- a/core/core-spacemacs.el +++ b/core/core-spacemacs.el @@ -15,6 +15,7 @@ (require 'page-break-lines) (require 'core-debug) (require 'core-command-line) +(require 'core-configuration-layer) (require 'core-dotspacemacs) (require 'core-custom-settings) (require 'core-release-management) @@ -79,7 +80,6 @@ the final step of executing code in `emacs-startup-hook'.") ;; instead. evil-want-C-i-jump nil) (dotspacemacs/load-file) - (require 'core-configuration-layer) (dotspacemacs|call-func dotspacemacs/init "Calling dotfile init...") (when dotspacemacs-maximized-at-startup (unless (frame-parameter nil 'fullscreen) diff --git a/core/info/release-notes/0.300.txt b/core/info/release-notes/0.300.txt new file mode 100644 index 000000000..074635f61 --- /dev/null +++ b/core/info/release-notes/0.300.txt @@ -0,0 +1,40 @@ + ╭───────────────────────────────────────────────────────────╮ + + VERSION 0.300 IS ALMOST OUT! + + ╰───────────────────────────────────────────────────────────╯ + +The long awaited feature to have stable ELPA packages is now available in the +develop branch and we need to test it out before we release the 0.300 version. + +The stable ELPA repository is a Git repository, the official one is called +Spacelpa and it is hosted on GitHub here: + + https://github.com/syl20bnr/spacelpa + +In the end only the master branch will use the stable ELPA repository and the +develop branch will continue to use bleeding edge packages from MELPA +essentially. + +Unfortunately this new feature requires at least Emacs 25.1 to work correctly as +we need the archive priority feature of package.el that shipped with this +version of Emacs. + +The ELPA repository configuration is set in a new immutable file called .lock +that sits at the root of the Spacemacs git repository. + +Spacemacs downloads the whole ELPA stable repository locally so it means that +once it is installed you don't need an Internet connection anymore to install +any packages covered by Spacemacs layers! + +Default installation location of the ELPA stable repository is in: + + ~/.emacs.d/.cache/stable-elpa + +If you want to disable the ELPA stable repository put this in your dotfile in +the user-init function: + + (setq configuration-layer--elpa-archives + '(("melpa" . "melpa.org/packages/") + ("org" . "orgmode.org/elpa/") + ("gnu" . "elpa.gnu.org/packages/"))) diff --git a/init.el b/init.el index 68588b42a..88f30d884 100644 --- a/init.el +++ b/init.el @@ -26,7 +26,9 @@ (load-file (concat (file-name-directory load-file-name) "core/core-load-paths.el")) (require 'core-spacemacs) + (configuration-layer/load-lock-file) (spacemacs/init) + (configuration-layer/stable-elpa-download-tarball) (configuration-layer/load) (spacemacs-buffer/display-startup-note) (spacemacs/setup-startup-hook)