el --- Manage the external elisp bits and pieces you depend upon
;;
;; Copyright (C) 2010-2012 Dimitri Fontaine
;;
;; Author: Dimitri Fontaine <dim@tapoueh.org>
;; URL: http://www.emacswiki.org/emacs/el-get
;; GIT: https://github.com/dimitri/el-get
;; Version: 4.1
;; Created: 2010-06-17
;; Keywords: emacs package elisp install elpa git git-svn bzr cvs svn darcs hg
;; apt-get fink pacman http http-tar emacswiki
;; Licence: WTFPL, grab your copy here: http://sam.zoy.org/wtfpl/
;;
;; This file is NOT part of GNU Emacs.
;;
;; Install
;; Please see the README.asciidoc file from the same distribution
;;; Commentary:
;;
;; Version String are now inspired by how Emacs itself numbers its version.
;; First is the major version number, then a dot, then the minor version
;; number. The minor version number is 0 when still developping the next
;; major version.
;;
;; So 2.0 is a developer release while 2.1 will be the next stable release.
;;
;; Please note that this versioning policy has been picked while backing
;; 1.2~dev, so 1.0 was a "stable" release in fact. Ah, history.
;;
;; In addition to the version, you can also get the exact git revision
;; by running M-x `el-get-self-checksum'. You should provide this
;; checksum when seeking support or reporting a bug, so that the
;; developers will know exactly which version you are using.
;;; Code:
;; first some essential variables, used in other parts of the code.
(defgroup el-get nil "el-get customization group"
:group 'convenience)
(defcustom el-get-status-file
(concat (file-name-as-directory el-get-dir) ".status.el")
"Define where to store and read the package statuses")
(defvar el-get-autoload-file
(concat (file-name-as-directory el-get-dir) ".loaddefs.el")
"Where generated autoloads are saved")
;;
;; Now load the rest of the el-get code
;;
(require 'el-get-core) ; core facilities used everywhere
(require 'el-get-custom) ; user tweaks and `el-get-sources'
(require 'el-get-methods) ; support for `el-get-methods', backends
(require 'el-get-recipes) ; support for dealing with recipes
(require 'el-get-status) ; support for dealing with status
(require 'el-get-build) ; building packages
(require 'el-get-byte-compile) ; byte compiling in a subprocess
(require 'el-get-dependencies) ; topological-sort of package dep graph
(require 'el-get-notify) ; notification support (dbus, growl...)
(require 'el-get-list-packages) ; menu and `el-get-describe' facilities
(require 'el-get-autoloads) ; manages updating el-get's loaddefs.el
;;
;; And then define some more code-level customs. They stay here so that
;; it's easier for elisp programmers to find them and know about them. If
;; that is too lame of an excuse, let's move them to el-get-custom.el.
;;
(defcustom el-get-post-init-hooks nil
"Hooks to run after a package init.
Each hook is a unary function accepting a package"
:group 'el-get
:type 'hook)
(defcustom el-get-byte-compile t
"Whether or not to byte-compile packages. Can be used to
disable byte-compilation globally, unless this process is not
controlled by `el-get' itself.
(defcustom el-get-generate-autoloads t
"Whether or not to generate autoloads for packages. Can be used
to disable autoloads globally."
:group 'el-get
:type 'boolean)
(defcustom el-get-auto-update-cached-recipes t
"When non-nil, auto-update certain properties in cached recipes.
(defun el-get-read-all-recipe-names ()
"Return the list of all known recipe names.
(el-get-error-unless-required-emacs-version source)
(when el-get-byte-compile-at-init
;; If the package has been updated outside el-get, the .el files will be
;; out of date, so just check if we need to recompile them.
;;
;; when using el-get-update to update packages, though, there's no
;; need to byte compile at init.
(el-get-byte-compile package))
;; load any autoloads file if needed
(unless (eq autoloads t)
(dolist (file (el-get-as-list autoloads))
(el-get-load-fast file))))
(let ((el-get-maybe-lazy-runsupp
(if lazy
#'el-get-lazy-run-package-support
#'el-get-run-package-support))
(maybe-lazy-eval
(if lazy
(apply-partially 'el-get-eval-after-load package)
'eval)))
(funcall el-get-maybe-lazy-runsupp
postinit "post-init" package)
(funcall maybe-lazy-eval `(el-get-load-package-user-init-file ',package))
(funcall el-get-maybe-lazy-runsupp
after "after" package)))
(debug error
(el-get-installation-failed package err)))
;; and call the global init hooks
(run-hook-with-args 'el-get-post-init-hooks package)
(el-get-error-unless-required-emacs-version source)
This happens if the cached recipe and the current one have
different install methods."
(let* ((source (el-get-package-def package))
(old-source (el-get-read-package-status-recipe package))
(method (el-get-package-method source))
(old-method (el-get-package-method old-source)))
(not (eq method old-method))))
;;;###autoload
(defun el-get-update-all (&optional no-prompt)
"Performs update of all installed packages."
(interactive)
(when (or no-prompt
(yes-or-no-p
"Do you really want to update all installed packages?"))
;; The let and flet forms here ensure that
;; `package-refresh-contents' is only called once, regardless of
;; how many ELPA-type packages need to be installed. Without this,
;; a refresh would happen for every ELPA package, which is totally
;; unnecessary when updating them all at once.
(let ((refreshed nil)
(orig-package-refresh-contents
(ignore-errors (symbol-function 'package-refresh-contents))))
(flet ((package-refresh-contents
;; This is the only way to get sane auto-indentation
(cdr (lambda (&rest args)
(unless refreshed
(apply orig-package-refresh-contents args)
(setq refreshed t))))))
;; This is the only line that really matters
(mapc 'el-get-update (el-get-list-package-names-with-status
"installed"))))))
;;;###autoload
(defun el-get-self-update ()
"Update el-get itself. The standard recipe takes care of reloading the code."
(interactive)
(let ((el-get-default-process-sync t)
(el-get-dir
(expand-file-name ".." (file-name-directory el-get-script))))
(el-get-update "el-get")))
(defun el-get-post-remove (package)
"Run the post-remove hooks for PACKAGE."
(let* ((hooks (el-get-method (el-get-package-method package) :remove-hook)))
(run-hook-with-args hooks package)
(run-hook-with-args 'el-get-post-remove-hooks package)))
;;;###autoload
(defun el-get-cd (package)
"Open dired in the package directory."
(interactive
(list (el-get-read-package-with-status "cd to" "required" "installed")))
(el-get-error-unless-package-p package)
(dired (el-get-package-directory package)))
;;;###autoload
(defun el-get-checksum (package &optional package-status-alist)
"Compute the checksum of the given package, and put it in the kill-ring"
(interactive
(list (el-get-read-package-with-status "Checksum" "installed")))
(el-get-with-status-sources package-status-alist
(let* ((type (el-get-package-type package))
(checksum (plist-get (el-get-package-def package) :checksum))
(compute-checksum (el-get-method type :compute-checksum)))
(when (and checksum (not compute-checksum))
(error "package method %s does not support checksums" type))
(when compute-checksum
(let ((checksum (funcall compute-checksum package)))
(message "Checksum for package %s is: %s. It has been copied to the kill-
ring."
package checksum)
(kill-new checksum)
checksum)))))
(defun el-get-self-checksum ()
"Compute the checksum of the running version of el-get itself.
(let* ((packages
;; (el-get 'sync 'a 'b my-package-list)
(loop for p in packages when (listp p) append p else collect p))
(total (length packages))
(installed (el-get-count-packages-with-status packages "installed"))
(el-get-default-process-sync sync))
(provide 'el-get)