2010-08-24 23:30:32 +08:00
;;; el-get.el --- Manage the external elisp bits and pieces you depend upon
2010-06-19 04:21:02 +08:00
;;
2011-09-20 21:15:52 +08:00
;; Copyright (C) 2010-2011 Dimitri Fontaine
2010-06-19 04:21:02 +08:00
;;
;; Author: Dimitri Fontaine <dim@tapoueh.org>
2011-09-16 04:07:54 +08:00
;; URL: http://www.emacswiki.org/emacs/el-get
;; GIT: https://github.com/dimitri/el-get
2011-09-19 16:55:20 +08:00
;; Version: 4.0
2010-06-19 04:21:02 +08:00
;; Created: 2010-06-17
2010-11-15 03:40:53 +08:00
;; Keywords: emacs package elisp install elpa git git-svn bzr cvs svn darcs hg
;; apt-get fink pacman http http-tar emacswiki
2010-06-19 04:21:02 +08:00
;; Licence: WTFPL, grab your copy here: http://sam.zoy.org/wtfpl/
;;
;; This file is NOT part of GNU Emacs.
;;
2010-09-01 23:52:53 +08:00
;; Install
;; Please see the README.asciidoc file from the same distribution
2011-03-11 04:15:12 +08:00
;;; 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.
2010-08-05 04:10:34 +08:00
;;
2011-05-26 03:59:32 +08:00
;; Please note that this versioning policy has been picked while backing
2011-03-11 04:15:12 +08:00
;; 1.2~dev, so 1.0 was a "stable" release in fact. Ah, history.
2012-02-02 08:25:17 +08:00
;;
;; 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.
2011-03-11 04:15:12 +08:00
;;; Change Log:
2010-08-05 04:10:34 +08:00
;;
2011-09-16 04:40:30 +08:00
;; 4.0 - WIP - To infinity, and beyond!
;;
2011-09-24 05:05:02 +08:00
;; - code refactoring
;; - fix dependency tracking at install and init times
;; - fix autoloading so that it happens before notifying install is done
;; - add some tests
2011-10-01 02:55:40 +08:00
;; - deprecate package.el from the old days, only include the Emacs24 one
2011-10-02 04:31:07 +08:00
;; - implement :builtin property (useful for dealing with package.el)
2011-10-08 04:57:08 +08:00
;; - fix recipes :build commands, must be either lists of strings or expr
2011-10-11 16:37:52 +08:00
;; - add support for el-get-reload and do that at update time
2011-10-29 00:02:38 +08:00
;; - implement :checksum property for http kinds of files
2012-01-30 14:11:44 +08:00
;; - Add new command el-get-reinstall
2012-01-30 14:19:43 +08:00
;; - implement :checkout property for git packages
2012-02-13 04:59:14 +08:00
;; - implement :shallow property for git packages
2012-02-19 04:34:24 +08:00
;; - add support for auto-building of ELPA recipes
2012-02-19 05:03:19 +08:00
;; - implement :submodule property for git packages (allow bypassing them)
2012-01-30 13:14:23 +08:00
;; - New package types: github, emacsmirror
2012-02-29 10:22:15 +08:00
;; - Support for installing CVS packages through non-transparent
;; http proxy servers
2012-03-01 00:14:55 +08:00
;; - `el-get-update-all' now prompts before updating packages
2011-09-24 05:05:02 +08:00
;;
2011-09-16 04:07:54 +08:00
;; 3.1 - 2011-09-15 - Get a fix
2011-05-26 04:07:37 +08:00
;;
2011-09-16 04:07:54 +08:00
;; - support for package dependencies
2011-06-22 18:00:30 +08:00
;; - rely on package status for `el-get' to install and init them
2011-08-18 00:17:22 +08:00
;; - M-x el-get-list-packages
2011-08-19 21:14:06 +08:00
;; - support for :branch in git
2011-08-18 00:17:22 +08:00
;; - new recipes, galore
;; - bug fixes, byte compiling, windows compatibility, etc
2011-09-07 03:22:46 +08:00
;; - recipe files are now *.rcp rather than *.el (el still supported)
2011-09-12 01:55:09 +08:00
;; - el-get-user-package-directory allows to setup init-<package>.el files
2011-09-16 04:07:54 +08:00
;; - remove M-x el-get-sync, now obsolete
2011-05-26 04:07:37 +08:00
;;
2011-05-26 16:46:05 +08:00
;; 2.2 - 2011-05-26 - Fix the merge
;;
;; - Revert changes introduced by a merge done by mistake
;;
;; 2.1 - 2011-05-25 - Still growing, getting lazy
2011-01-03 01:22:51 +08:00
;;
2011-01-05 05:10:35 +08:00
;; - Add support for autoloads, per Dave Abrahams
2011-01-03 01:22:51 +08:00
;; - fix 'wait support for http (using sync retrieval)
2011-01-05 05:10:35 +08:00
;; - code cleanup per Dave Abrahams, lots of it
2011-01-07 20:30:47 +08:00
;; - add function M-x el-get-update-all
2011-01-11 05:39:17 +08:00
;; - Implement M-x el-get-make-recipes
2011-01-30 06:10:47 +08:00
;; - byte-compile at build time rather than at init time
;; - and use a "clean room" external emacs -Q for byte compiling
2011-02-02 00:09:25 +08:00
;; - allow to skip autoloads either globally or per-package
2011-02-05 02:48:15 +08:00
;; - better checks and errors for commands used when installing packages
2011-02-20 04:24:19 +08:00
;; - register `el-get-sources' against the custom interface
2011-02-22 05:20:57 +08:00
;; - el-get will now accept a list of sources to install or init
2011-02-22 05:55:45 +08:00
;; - open el-get-{install,init,remove,update} from `el-get-sources' only
2011-02-25 05:03:47 +08:00
;; - add :prepare and :post-init and :lazy, and `el-get-is-lazy'
2011-03-17 05:31:00 +08:00
;; - add support for :repo for ELPA packages
2011-01-03 01:22:51 +08:00
;;
2010-12-20 22:37:13 +08:00
;; 1.1 - 2010-12-20 - Nobody's testing until the release
2010-10-08 18:37:50 +08:00
;;
;; - Adapt to package.el from Emacs24 by using relative symlinks to ELPA
;; packages ((package-user-dir) is "~/.emacs.d/elpa" now, so needs to
;; get expanded at least)
2010-10-09 20:41:02 +08:00
;; - Allow to bypass byte compiling entirely with a single global var
2010-10-09 21:10:22 +08:00
;; - Have http local file default to something sane, not package.el
2010-10-10 03:19:57 +08:00
;; - Implement support for svn and darcs too
2010-10-09 21:10:22 +08:00
;; - Still more recipes
2010-11-08 20:45:04 +08:00
;; - Add support for the `pacman' package manager (ARCH Linux)
2010-11-15 03:40:53 +08:00
;; - Add support for mercurial
2010-11-13 05:22:19 +08:00
;; - (el-get 'sync) now really means synchronous, and serialized too
;; - el-get-start-process-list implements :sync, defaults to nil (async)
2010-11-26 23:32:23 +08:00
;; - Implement a :localname package property to help with some kind of URLs
2010-11-27 05:07:02 +08:00
;; - Add el-get-post-init-hooks
2010-11-28 23:37:18 +08:00
;; - Allow build commands to be evaluated, hence using some emacs variables
2010-11-30 00:41:21 +08:00
;; - Finaly walk the extra mile and remove "required" packages at install
2010-11-30 01:02:25 +08:00
;; - Implement support for the "Do you want to continue" apt-get prompt
2010-12-01 20:32:39 +08:00
;; - implement :before user defined function to run before init
2010-10-08 18:37:50 +08:00
;;
2010-10-07 18:18:04 +08:00
;; 1.0 - 2010-10-07 - Can I haz your recipes?
2010-08-31 04:59:05 +08:00
;;
;; - Implement el-get recipes so that el-get-sources can be a simple list
;; of symbols. Now that there's an authoritative git repository, where
2010-09-01 23:52:53 +08:00
;; to share the recipes is easy.
2010-09-02 03:48:50 +08:00
;; - Add support for emacswiki directly, save from having to enter the URL
2010-09-02 05:39:39 +08:00
;; - Implement package status on-disk saving so that installing over a
;; previously failed install is in theory possible. Currently `el-get'
;; will refrain from removing your package automatically, though.
2010-09-03 21:02:49 +08:00
;; - Fix ELPA remove method, adding a "removed" state too.
2010-09-06 05:23:15 +08:00
;; - Implement CVS login support.
2010-09-10 03:54:18 +08:00
;; - Add lots of recipes
;; - Add support for `system-type' specific build commands
2010-09-15 23:34:37 +08:00
;; - Byte compile files from the load-path entries or :compile files
2010-09-20 03:28:07 +08:00
;; - Implement support for git submodules with the command
;; `git submodule update --init --recursive`
2010-09-22 16:38:52 +08:00
;; - Add catch-all post-install and post-update hooks
2010-09-22 16:56:33 +08:00
;; - Add desktop notification on install/update.
2010-08-31 04:59:05 +08:00
;;
2010-08-24 23:37:06 +08:00
;; 0.9 - 2010-08-24 - build me a shell
;;
;; - have `el-get-build' use start-process-shell-command so that you can
;; pass-in shell commands. Beware of poor command argument "parsing"
;; though, done with a simple `split-string'.
;;
2010-08-23 21:12:30 +08:00
;; 0.8 - 2010-08-23 - listen to the users
;;
;; - implement :after user defined function to run at the end of init
2010-08-24 23:30:32 +08:00
;; - add CVS support (no login support)
2010-08-23 22:55:36 +08:00
;; - improve el-get-build to use async building
;; - fix el-get-update doing so
2010-08-23 21:12:30 +08:00
;;
2010-08-23 06:19:47 +08:00
;; 0.7 - 2010-08-23 - archive
;;
;; - http support is extended to `tar' archives, via the http-tar type
;;
2010-08-13 03:00:15 +08:00
;; 0.6 - 2010-08-12 - towards a stable version
;;
;; - fix when asynchronous http support call post-install-fun
;; - fix el-get-remove calling convention
;; - add support for bzr, thanks to Kevin Fletcher
;;
2010-08-06 18:19:39 +08:00
;; 0.5 - 2010-08-06 - release early, fix often
;;
;; - fix apt-get and fink install hooks to call el-get-dpkg-symlink
;; - fix elpa and http support to follow the new call convention
;; - use asynchronous url-retrieve facility so that http is async too
;;
2010-08-05 04:10:34 +08:00
;; 0.4 - 2010-08-04 - foxy release
;;
;; - support asynchronous processes for system commands
;; apt-get, fink, git and git-svn are run in background
;; - support `sudo' password prompts (classic and ubuntu variants)
;; - fix fink support
;; - ELPA support is an option so that you can install ELPA from el-get
;; - implement el-get-rmdir
2010-06-19 04:21:02 +08:00
2011-03-11 04:15:12 +08:00
;;; Code:
2011-09-16 04:07:54 +08:00
2011-09-23 03:48:11 +08:00
;; first some essential variables, used in other parts of the code.
2010-06-19 04:21:02 +08:00
( defgroup el-get nil " el-get customization group "
:group 'convenience )
2012-02-12 18:41:20 +08:00
( defconst el-get-version " 4.0.7 " " el-get version number " )
2011-09-20 21:15:52 +08:00
2011-09-23 03:48:11 +08:00
( defconst el-get-script ( or load-file-name buffer-file-name ) )
( defcustom el-get-dir " ~/.emacs.d/el-get/ "
" Path where to install the packages. "
:group 'el-get
:type 'directory )
( 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 " )
( defvar el-get-emacs ( concat invocation-directory invocation-name )
" Where to find the currently running emacs, a facility for :build commands " )
2010-10-07 20:27:28 +08:00
2011-09-23 03:48:11 +08:00
;;
;; Now load the rest of the el-get code
;;
2011-09-21 22:06:18 +08:00
( 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
2011-09-23 17:41:24 +08:00
( require 'el-get-autoloads ) ; manages updating el-get's loaddefs.el
2011-06-25 23:07:14 +08:00
2011-09-23 03:48:11 +08:00
;;
;; 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.
;;
2010-11-27 05:07:02 +08:00
( defcustom el-get-post-init-hooks nil
" Hooks to run after a package init.
2011-05-23 08:08:36 +08:00
Each hook is a unary function accepting a package "
2010-11-27 05:07:02 +08:00
:group 'el-get
:type 'hook )
2010-09-22 14:36:43 +08:00
( defcustom el-get-post-install-hooks nil
" Hooks to run after installing a package.
2011-05-26 21:49:30 +08:00
Each hook is a unary function accepting a package "
2010-09-22 14:36:43 +08:00
:group 'el-get
:type 'hook )
( defcustom el-get-post-update-hooks nil
2010-09-22 16:38:52 +08:00
" Hooks to run after updating a package.
2011-05-26 21:49:30 +08:00
Each hook is a unary function accepting a package "
:group 'el-get
:type 'hook )
2011-05-26 22:11:01 +08:00
( defcustom el-get-post-error-hooks nil
" Hooks to run after package installation fails.
Each hook is a binay function accepting a package and error data "
2010-09-22 14:36:43 +08:00
:group 'el-get
:type 'hook )
2010-10-08 21:00:38 +08:00
( defcustom el-get-byte-compile t
2011-03-28 18:43:48 +08:00
" Whether or not to byte-compile packages. Can be used to
2011-08-14 23:49:46 +08:00
disable byte-compilation globally, unless this process is not
controlled by ` el-get ' itself.
The cases when ` el-get ' loses control are with \"advanced\"
packaging systems ( apt-get, fink, pacman, elpa ) or when the
recipe contains a :build rule ( using a Makefile for example ) . "
2010-10-08 21:00:38 +08:00
:group 'el-get
:type 'boolean )
2011-05-22 12:06:45 +08:00
( defcustom el-get-verbose nil
" Non-nil means print messages describing progress of el-get even for fast operations. "
:group 'el-get
:type 'boolean )
2011-03-28 18:43:48 +08:00
( defcustom el-get-byte-compile-at-init nil
" Whether or not to byte-compile packages at init.
Turn this to t if you happen to update your packages from under
` el-get ', e.g. doing ` cd el-get-dir/package && git pull `
directly. "
:group 'el-get
:type 'boolean )
2011-01-31 23:50:41 +08:00
( 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 )
2011-02-25 05:03:47 +08:00
( defcustom el-get-is-lazy nil
" Whether or not to defer evaluation of :post-init and :after
functions until libraries are required. Will also have el-get
skip the :load and :features properties when set. See :lazy to
force their evaluation on some packages only. "
2011-02-23 04:39:37 +08:00
:group 'el-get
:type 'boolean )
2011-09-21 22:06:18 +08:00
( defvar el-get-next-packages nil
" List of packages to install next, used when dealing with dependencies. " )
2011-05-26 22:37:28 +08:00
2011-05-26 22:11:01 +08:00
( defun el-get-installation-failed ( package signal-data )
" Run all the failure hooks for PACKAGE and `signal' the car and cdr of SIGNAL-DATA. "
( run-hook-with-args 'el-get-post-error-hooks package signal-data )
( signal ( car signal-data ) ( cdr signal-data ) ) )
2010-07-30 17:16:56 +08:00
2010-06-29 00:35:15 +08:00
;;
;; User Interface, Interactive part
;;
2011-10-14 22:28:52 +08:00
;;;###autoload
2010-10-07 20:27:28 +08:00
( defun el-get-version ( )
" Message the current el-get version "
( interactive )
2012-02-19 04:46:32 +08:00
( let ( ( version
( if ( string= ( cadr ( split-string el-get-version " \\ . " ) ) " 0 " )
;; devel version, add the current git sha1 (short form)
( let ( ( default-directory ( file-name-directory el-get-script ) ) )
( concat el-get-version " . "
( shell-command-to-string
" git --no-pager log -n1 --format=format:%h " ) ) )
el-get-version ) ) )
( kill-new version )
( message " el-get version %s " version ) ) )
2010-10-07 20:27:28 +08:00
2011-06-22 05:13:48 +08:00
( defun el-get-read-all-recipe-names ( )
2011-03-17 05:21:52 +08:00
" Return the list of all known recipe names.
This is useful to use for providing completion candidates for
2011-06-22 05:13:48 +08:00
package names. "
( mapcar 'el-get-source-name ( el-get-read-all-recipes ) ) )
2011-03-17 05:21:52 +08:00
2010-09-02 02:00:49 +08:00
( defun el-get-error-unless-package-p ( package )
2011-02-22 05:55:45 +08:00
" Raise an error if PACKAGE does not name a package that has a valid recipe. "
;; check for recipe
2010-11-29 21:03:37 +08:00
( let ( ( recipe ( el-get-package-def package ) ) )
( unless recipe
( error " el-get: package `%s' has no recipe " package ) )
( unless ( plist-member recipe :type )
( error " el-get: package `%s' has incomplete recipe (no :type) " package ) ) ) )
2010-09-02 02:00:49 +08:00
2011-06-22 06:33:33 +08:00
( defun el-get-package-is-installed ( package )
2012-03-06 16:34:27 +08:00
" Return whether package is installed "
( and ( file-directory-p ( el-get-package-directory package ) )
( string= " installed "
( el-get-read-package-status ( el-get-as-string package ) ) ) ) )
2011-06-22 06:01:53 +08:00
2011-06-06 03:28:59 +08:00
( defun el-get-read-package-name ( action &optional filtered )
2011-03-17 05:21:52 +08:00
" Ask user for a package name in minibuffer, with completion.
2011-06-06 03:28:59 +08:00
Completions are offered from all known package names, after
removing any packages in FILTERED. "
2011-06-22 05:13:48 +08:00
( let ( ( packages ( el-get-read-all-recipe-names ) ) )
2011-02-22 05:55:45 +08:00
( completing-read ( format " %s package: " action )
2011-05-24 23:46:42 +08:00
( set-difference packages filtered :test 'string= ) nil t ) ) )
2010-09-02 02:00:49 +08:00
2011-05-24 23:46:42 +08:00
( defun el-get-read-recipe-name ( action )
2011-03-17 05:21:52 +08:00
" Ask user for a recipe name, with completion from the list of known recipe files.
This function does not deal with ` el-get-sources ' at all. "
( completing-read ( format " %s recipe: " action )
2011-06-22 05:13:48 +08:00
( el-get-read-all-recipe-names ) nil ) )
2011-03-17 05:21:52 +08:00
( defun el-get-find-recipe-file ( package &optional dir )
" Find recipe file for PACKAGE.
If no recipe file exists for PACKAGE, create a new one in DIR,
which defaults to the first element in ` el-get-recipe-path '. "
( interactive ( list ( el-get-read-recipe-name " Find or create " ) ) )
2011-09-07 03:22:46 +08:00
( let* ( ( package-el ( concat ( el-get-as-string package ) " .rcp " ) )
2011-03-17 05:21:52 +08:00
( recipe-file ( or
;; If dir was specified, open or create the
;; recipe file in that directory.
2011-05-23 09:33:32 +08:00
( when dir ( expand-file-name package-el dir ) )
2011-03-17 05:21:52 +08:00
;; Next, try to find an existing recipe file anywhere.
( el-get-recipe-filename package )
;; Lastly, create a new recipe file in the first
;; directory in `el-get-recipe-path'
2011-06-20 05:47:42 +08:00
( expand-file-name package-el
2011-05-23 09:33:32 +08:00
( car el-get-recipe-path ) ) ) ) )
2011-03-17 05:21:52 +08:00
( find-file recipe-file ) ) )
2012-02-24 05:53:16 +08:00
( defun el-get-eval-after-load ( package form )
" Like `eval-after-load' , but first arg is an el-get package name. "
( let* ( ( package ( el-get-as-symbol package ) )
( source ( el-get-package-def package ) )
( pkgname ( plist-get source :pkgname ) )
( feats ( el-get-as-list ( plist-get source :features ) ) )
( library ( or ( plist-get source :library )
( car feats )
pkgname
package ) ) )
2012-02-25 09:56:36 +08:00
( el-get-verbose-message " Using library `%s' for `eval-after-load' for package `%s' "
library package )
2012-02-25 09:55:57 +08:00
( eval-after-load ( el-get-as-string library ) form ) ) )
2012-02-24 05:53:16 +08:00
( put 'el-get-eval-after-load 'lisp-indent-function
( get 'eval-after-load 'lisp-indent-function ) )
2012-02-23 05:32:08 +08:00
( defun el-get-run-package-support ( form fname package )
" `eval' FORM for PACKAGE and report about FNAME when `el-get-verbose' "
( let* ( ;; Auto-strip quoting from form before doing anything else
( form ( if ( equal ( car-safe form ) 'quote )
2012-02-23 07:01:05 +08:00
( prog1 ( eval form )
2012-02-23 05:32:08 +08:00
( warn " The :%s form for package %s is quoted unnecessarily. "
fname package ) )
form ) )
;; Allow either function (symbol or lambda) or single lisp form
( form
2012-02-20 07:35:58 +08:00
( cond
;; Nil means do nothing
2012-02-23 05:32:08 +08:00
( ( null form ) nil )
;; A symbol is the name of a function to call
( ( symbolp form )
;; Convert it to a quoted call to that function
( prog1 ` ( , form )
2012-02-23 07:00:51 +08:00
( warn " The :%s form for package %s uses the old-style function form instead of a lisp form. The value should be changed from `%S' to `%S' "
2012-02-23 05:32:08 +08:00
fname package form ` ( , form ) )
( unless ( symbol-function form )
( warn " The function %s, which is called in the :%s form for package %s, does not seem to be defined. Calling it will probably fail. "
form fname package ) ) ) )
;; A non-symbol function (like a lambda or something)
( ( functionp form )
;; Convert it to a quoted call to that function
( prog1 ` ( , form )
( if ( and ( listp form )
( equal ( subseq form 0 2 ) ' ( lambda ( ) ) ) )
;; It's a zero-arg function, so it can be trivially
;; rewritten as a progn. Inform the user of such.
( warn " The :%s form for package %s uses the old-style lambda form instead of a lisp form. The leading \" (lambda () \" should be replaced with \" (progn \" . "
fname package )
;; Otherwise, provide a less informative warning
( warn " The :%s form for package %s uses the old-style function form instead of a lisp form. "
fname package ) ) ) )
;; A list is interpreted as a single lisp form to be passed
;; directly to `eval'.
( ( listp form ) form )
2012-02-20 07:35:58 +08:00
;; Anything else is an error
2012-02-23 07:00:51 +08:00
( t ( error " Unknown :%s form for package %s: `%S' "
2012-02-23 05:32:08 +08:00
fname package form ) ) ) ) )
( when form
( assert ( listp form ) )
( el-get-verbose-message " el-get: Evaluating :%s form for package %s "
2012-02-20 07:35:58 +08:00
fname package )
2011-06-20 03:30:51 +08:00
;; don't forget to make some variables available
2012-02-23 05:32:08 +08:00
( let* ( ( pdir ( el-get-package-directory package ) )
( default-directory pdir ) )
( eval form ) ) ) ) )
2011-05-22 12:06:45 +08:00
2012-02-24 07:05:49 +08:00
( defun el-get-lazy-run-package-support ( form fname package )
" Like `el-get-run-package-support' , but using `eval-after-load' to wait until PACKAGE is loaded. "
2012-02-24 05:53:16 +08:00
( el-get-eval-after-load package
2012-02-24 07:05:49 +08:00
` ( el-get-run-package-support ',form ',fname ',package ) ) )
2011-05-22 12:06:45 +08:00
2011-09-21 22:06:18 +08:00
2012-03-06 01:51:33 +08:00
( defun el-get-init ( package &optional package-status-alist )
2010-12-29 16:43:46 +08:00
" Make the named PACKAGE available for use.
Add PACKAGE 's directory ( or ` :load-path ' if specified ) to the
` load-path ', add any its ` :info ' directory to
` Info-directory-list ', and ` require ' its ` :features '. Will be
2011-06-22 06:01:53 +08:00
called by ` el-get ' ( usually at startup ) for each installed package. "
2010-09-02 02:00:49 +08:00
( interactive ( list ( el-get-read-package-name " Init " ) ) )
2011-06-26 04:56:29 +08:00
( el-get-verbose-message " el-get-init: %s " package )
2011-05-26 22:11:01 +08:00
( condition-case err
2012-03-06 01:51:33 +08:00
( let* ( ( source
( el-get-read-package-status-recipe package package-status-alist ) )
2011-06-22 04:28:58 +08:00
( method ( el-get-package-method source ) )
2011-05-26 22:11:01 +08:00
( loads ( el-get-as-list ( plist-get source :load ) ) )
( autoloads ( plist-get source :autoloads ) )
( feats ( el-get-as-list ( plist-get source :features ) ) )
( el-path ( el-get-as-list ( el-get-load-path package ) ) )
2012-02-24 05:52:45 +08:00
( lazy ( el-get-plist-get-with-default source :lazy
el-get-is-lazy ) )
2011-05-26 22:11:01 +08:00
( prepare ( plist-get source :prepare ) )
( before ( plist-get source :before ) )
( postinit ( plist-get source :post-init ) )
( after ( plist-get source :after ) )
( pkgname ( plist-get source :pkgname ) )
( library ( or ( plist-get source :library ) pkgname package ) )
2012-02-23 05:32:08 +08:00
( pdir ( el-get-package-directory package ) ) )
2011-05-26 22:11:01 +08:00
2011-10-03 01:50:17 +08:00
;; a builtin package initialisation is about calling recipe and user
;; code only, no load-path nor byte-compiling support needed here.
2011-10-04 17:53:35 +08:00
( unless ( eq method 'builtin )
2011-10-03 01:48:21 +08:00
;; append entries to load-path and Info-directory-list
2011-11-23 16:45:07 +08:00
( unless ( member method ' ( apt-get fink pacman ) )
2011-10-03 01:48:21 +08:00
;; append entries to load-path
( dolist ( path el-path )
( el-get-add-path-to-list package 'load-path path ) )
;; and Info-directory-list
( el-get-install-or-init-info package 'init ) )
( 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 ) ) ) )
2011-05-26 22:11:01 +08:00
;; first, the :prepare function, usually defined in the recipe
2012-02-23 05:32:08 +08:00
( el-get-run-package-support prepare " prepare " package )
2011-05-26 22:11:01 +08:00
;; now call the :before user function
2012-02-23 05:32:08 +08:00
( el-get-run-package-support before " before " package )
2011-05-26 22:11:01 +08:00
;; loads and feature are skipped when el-get-is-lazy
2012-02-24 05:52:45 +08:00
( unless lazy
2011-05-26 22:11:01 +08:00
;; loads
( dolist ( file loads )
( let ( ( pfile ( concat pdir file ) ) )
( unless ( file-exists-p pfile )
( error " el-get could not find file '%s' " pfile ) )
( el-get-verbose-message " el-get: load '%s' " pfile )
( el-get-load-fast pfile ) ) )
;; features, only ELPA will handle them on its own
( unless ( eq method 'elpa )
;; if a feature is provided, require it now
( dolist ( feat feats )
( let ( ( feature ( el-get-as-symbol feat ) ) )
( el-get-verbose-message " require '%s " feature )
( require feature ) ) ) ) )
2012-02-24 07:05:49 +08:00
( let ( ( el-get-maybe-lazy-runsupp
2012-02-24 06:22:18 +08:00
( if lazy
2012-02-24 07:05:49 +08:00
#' el-get-lazy-run-package-support
#' el-get-run-package-support ) )
2012-02-24 06:40:45 +08:00
( maybe-lazy-eval
( if lazy
( apply-partially 'el-get-eval-after-load package )
'eval ) ) )
2012-02-24 07:05:49 +08:00
( funcall el-get-maybe-lazy-runsupp
2012-02-24 06:22:18 +08:00
postinit " post-init " package )
2012-02-24 06:40:45 +08:00
( funcall maybe-lazy-eval ` ( el-get-load-package-user-init-file ',package ) )
2012-02-24 07:05:49 +08:00
( funcall el-get-maybe-lazy-runsupp
2012-02-24 06:22:18 +08:00
after " after " package ) )
2011-05-26 22:11:01 +08:00
;; and call the global init hooks
( run-hook-with-args 'el-get-post-init-hooks package )
;; return the package
package )
2011-06-20 05:47:42 +08:00
( debug error
2011-05-26 22:11:01 +08:00
( el-get-installation-failed package err ) ) ) )
2010-06-28 23:03:42 +08:00
2011-09-21 22:06:18 +08:00
( defun el-get-install ( package )
" Cause the named PACKAGE to be installed after all of its
dependencies ( if any ) .
PACKAGE may be either a string or the corresponding symbol. "
( interactive ( list ( el-get-read-package-name " Install " ) ) )
2011-10-09 03:27:55 +08:00
( let ( ( packages ( el-get-dependencies ( el-get-as-symbol package ) ) ) )
( when ( cdr packages )
;; tweak el-get-post-install-hooks to install remaining packages
;; once the first is installed
( el-get-verbose-message " el-get-install %s: %S " package packages )
( setq el-get-next-packages ( cdr packages ) )
2012-02-19 08:36:45 +08:00
( add-hook 'el-get-post-init-hooks 'el-get-install-next-packages ) )
2011-10-09 03:27:55 +08:00
( let ( ( package ( car packages ) ) )
( if ( not ( el-get-package-is-installed package ) )
( el-get-do-install package )
;; if package is already installed, skip to the next
( message " el-get: `%s' package is already installed " package )
2012-02-21 04:58:45 +08:00
( el-get-init package ) ) ) ) )
2011-09-21 22:06:18 +08:00
2012-02-19 08:39:48 +08:00
( defun el-get-install-next-packages ( &rest ignored )
2011-09-21 22:06:18 +08:00
" Run as part of `el-get-post-init-hooks' when dealing with dependencies. "
( let ( ( package ( pop el-get-next-packages ) ) )
2011-09-23 03:48:11 +08:00
( el-get-verbose-message " el-get-install-next-packages: %s " package )
2011-09-21 22:06:18 +08:00
( if package
2011-10-12 02:27:01 +08:00
;; el-get-do-install will either init the package, installing it
;; first only when necessary to do so
( el-get-do-install ( el-get-as-string package ) )
2011-09-21 22:06:18 +08:00
;; no more packages to install in the dependency walk, clean up
( remove-hook 'el-get-post-init-hooks 'el-get-install-next-packages ) ) ) )
2011-06-26 05:13:06 +08:00
( defun el-get-post-install-build ( package )
" Function to call after building the package while installing it. "
2011-09-23 20:06:29 +08:00
( el-get-save-package-status package " installed " )
( el-get-invalidate-autoloads package ) ; that will also update them
( el-get-init package ) )
2011-06-25 12:49:17 +08:00
2011-03-01 17:59:17 +08:00
( defun el-get-post-install ( package )
" Post install PACKAGE. This will get run by a sentinel. "
2011-10-28 00:27:10 +08:00
( let* ( ( sync el-get-default-process-sync )
( type ( el-get-package-type package ) )
( hooks ( el-get-method type :install-hook ) )
( commands ( el-get-build-commands package ) )
( checksum ( plist-get ( el-get-package-def package ) :checksum ) )
( compute-checksum ( el-get-method type :compute-checksum ) ) )
;; check the checksum of the package here, as early as possible
2011-10-29 00:02:38 +08:00
( when ( and checksum ( not compute-checksum ) )
( error
" Checksum verification of package %s is not supported with method %s. "
package type ) )
2011-10-28 00:27:10 +08:00
( when compute-checksum
( let ( ( computed ( funcall compute-checksum package ) ) )
( if checksum
2011-10-31 17:58:12 +08:00
( if ( equal computed ( el-get-as-string checksum ) )
( el-get-verbose-message " el-get: package %s passed checksum with \" %s \" . "
package computed )
( error " Checksum verification failed. Required: \" %s \" , actual: \" %s \" . "
2011-10-28 00:27:10 +08:00
checksum computed ) )
2011-10-29 00:02:38 +08:00
( el-get-verbose-message " el-get: pakage %s checksum is %s. "
package computed ) ) ) )
2010-12-27 17:33:14 +08:00
2010-08-04 03:35:04 +08:00
;; post-install is the right place to run install-hook
2010-09-04 03:38:53 +08:00
( run-hook-with-args hooks package )
2010-12-27 17:33:14 +08:00
2011-06-26 05:13:06 +08:00
;; el-get-post-build will care about autoloads and initializing the
;; package, and will change the status to "installed"
( el-get-build package commands nil sync 'el-get-post-install-build ) )
2010-09-22 16:56:32 +08:00
( run-hook-with-args 'el-get-post-install-hooks package ) )
2010-08-04 03:35:04 +08:00
2011-06-06 03:28:59 +08:00
( defun el-get-do-install ( package )
2011-06-05 07:15:54 +08:00
" Install any PACKAGE for which you have a recipe. "
2011-06-22 06:01:53 +08:00
( el-get-error-unless-package-p package )
2012-03-06 16:34:27 +08:00
( if ( el-get-package-is-installed package )
2011-10-08 03:46:34 +08:00
( el-get-init package )
2011-09-20 23:55:14 +08:00
( let* ( ( status ( el-get-read-package-status package ) )
( source ( el-get-package-def package ) )
( method ( el-get-package-method source ) )
( install ( el-get-method method :install ) )
2011-10-08 06:43:55 +08:00
( url ( plist-get source :url ) )
( pdir ( el-get-package-directory package ) ) )
( cond ( ( string= " installed " status )
( error " Package %s is already installed. " package ) )
( ( string= " required " status )
( message " Package %s failed to install, removing it first. " package )
( el-get-remove package ) )
( ( file-exists-p pdir )
( message " Package %s has an install dir but is not known to be installed. Removing it so we can install a known version. " package )
( el-get-remove package ) ) )
2011-09-20 23:55:14 +08:00
2011-10-04 05:13:07 +08:00
;; check we can install the package and save to "required" status
( el-get-check-init )
( el-get-save-package-status package " required " )
2011-09-20 23:55:14 +08:00
2011-10-04 05:13:07 +08:00
;; and install the package now, *then* message about it
( funcall install package url 'el-get-post-install )
( message " el-get install %s " package ) ) ) )
2010-06-28 23:03:42 +08:00
2011-10-11 16:37:52 +08:00
( defun el-get-reload ( package )
" Reload PACKAGE. "
( interactive
( list ( el-get-read-package-with-status " Update " " installed " ) ) )
( el-get-verbose-message " el-get-reload: %s " package )
( let* ( ( all-features features )
( package-features ( el-get-package-features package ) )
( package-files ( el-get-package-files package ) )
( other-features
( remove-if ( lambda ( x ) ( memq x package-features ) ) all-features ) ) )
( unwind-protect
( progn
;; We cannot let-bind `features' here, becauses the changes
;; made by `el-get-init' must persist.
( setq features other-features )
;; Reload all loaded files in package dir if they still
;; exist.
( loop for file in package-files
do ( load file 'noerror ) )
;; Redo package initialization
( el-get-init package )
;; Reload all features provided by the package. This ensures
;; that autoloaded packages (which normally don't load
;; anything until one of their entry points is called) are
;; forced to reload immediately if they were already loaded.
( loop for f in package-features
do ( require f nil 'noerror ) ) )
;; We have to add all the removed features back in no matter
;; what, or else we would be lying about what has been loaded.
;; This covers the corner case where an updated package no
;; longer provides a certain feature. Technically that feature
;; is still provided, so not adding it back would be wrong.
( let ( ( missing-features
( remove-if ( lambda ( x ) ( memq x features ) ) package-features ) ) )
( when missing-features
( warn " Adding %S back onto features, because the reloaded package did not provide them. "
missing-features )
( setq features ( append missing-features features ) ) ) ) ) ) )
2011-09-21 22:06:18 +08:00
2010-08-04 03:35:04 +08:00
( defun el-get-post-update ( package )
2010-09-02 02:00:49 +08:00
" Post update PACKAGE. This will get run by a sentinel. "
2010-08-04 03:35:04 +08:00
( let* ( ( source ( el-get-package-def package ) )
2011-01-07 20:08:14 +08:00
( commands ( el-get-build-commands package ) ) )
2011-01-29 06:12:32 +08:00
( el-get-build package commands nil el-get-default-process-sync
2011-01-07 20:08:14 +08:00
( lambda ( package )
( el-get-init package )
;; fix trailing failed installs
( when ( string= ( el-get-read-package-status package ) " required " )
( el-get-save-package-status package " installed " ) )
2011-10-11 16:37:52 +08:00
( el-get-reload package )
2010-09-28 02:24:39 +08:00
( run-hook-with-args 'el-get-post-update-hooks package ) ) ) ) )
2010-06-28 23:03:42 +08:00
2010-09-02 02:00:49 +08:00
( defun el-get-update ( package )
" Update PACKAGE. "
2011-02-22 05:55:45 +08:00
( interactive
( list ( el-get-read-package-with-status " Update " " required " " installed " ) ) )
2010-09-02 02:00:49 +08:00
( el-get-error-unless-package-p package )
( let* ( ( source ( el-get-package-def package ) )
2011-06-22 04:28:58 +08:00
( method ( el-get-package-method source ) )
2011-01-07 20:08:14 +08:00
( update ( el-get-method method :update ) )
( url ( plist-get source :url ) )
( commands ( plist-get source :build ) ) )
2010-06-28 23:03:42 +08:00
;; update the package now
2011-10-31 17:41:25 +08:00
( if ( plist-get source :checksum )
2011-10-31 17:58:12 +08:00
( error " el-get: remove checksum from package %s to update it. " package )
2011-10-31 17:41:25 +08:00
( funcall update package url 'el-get-post-update )
( message " el-get update %s " package ) ) ) )
2010-06-28 23:03:42 +08:00
2011-10-14 22:28:52 +08:00
;;;###autoload
2012-03-01 01:09:04 +08:00
( defun el-get-update-all ( &optional no-prompt )
2011-06-22 17:50:49 +08:00
" Performs update of all installed packages. "
2011-06-16 03:46:09 +08:00
( interactive )
2012-03-01 01:09:04 +08:00
( when ( or no-prompt
( yes-or-no-p
" Do you really want to update all installed packages? " ) )
2012-02-29 21:50:27 +08:00
( mapc 'el-get-update ( el-get-list-package-names-with-status " installed " ) ) ) )
2011-01-07 20:09:06 +08:00
2011-10-14 22:28:52 +08:00
;;;###autoload
2011-06-16 03:46:09 +08:00
( defun el-get-self-update ( )
" Update el-get itself. The standard recipe takes care of reloading the code. "
( interactive )
2011-08-16 21:51:04 +08:00
( let ( ( el-get-default-process-sync t )
( el-get-dir
( expand-file-name " .. " ( file-name-directory el-get-script ) ) ) )
2011-06-22 03:56:07 +08:00
( el-get-update " el-get " ) ) )
2011-06-16 03:46:09 +08:00
2011-09-21 22:06:18 +08:00
2010-08-05 03:57:42 +08:00
( defun el-get-post-remove ( package )
2010-09-02 02:00:49 +08:00
" Run the post-remove hooks for PACKAGE. "
2011-06-22 04:28:58 +08:00
( let* ( ( hooks ( el-get-method ( el-get-package-method package ) :remove-hook ) ) )
2011-06-17 17:36:41 +08:00
( run-hook-with-args hooks package )
( run-hook-with-args 'el-get-post-remove-hooks package ) ) )
2010-08-05 03:57:42 +08:00
2010-09-04 06:42:12 +08:00
( defun el-get-remove ( package )
2011-02-22 05:55:45 +08:00
" Remove any PACKAGE that is know to be installed or required. "
( interactive
( list ( el-get-read-package-with-status " Remove " " required " " installed " ) ) )
2011-06-22 06:01:53 +08:00
( el-get-error-unless-package-p package )
2011-06-20 05:47:42 +08:00
2011-06-22 06:01:53 +08:00
( let* ( ( source ( el-get-package-def package ) )
( method ( el-get-package-method source ) )
( remove ( el-get-method method :remove ) )
( url ( plist-get source :url ) ) )
;; remove the package now
( el-get-remove-autoloads package )
( funcall remove package url 'el-get-post-remove )
( el-get-save-package-status package " removed " )
( message " el-get remove %s " package ) ) )
2010-06-28 23:03:42 +08:00
2012-02-19 08:39:48 +08:00
( defun el-get-reinstall ( package )
" Remove PACKAGE and then install it again. "
( interactive ( list ( el-get-read-package-name " Reinstall " ) ) )
( el-get-remove package )
( el-get-install package ) )
2011-10-14 22:28:52 +08:00
;;;###autoload
2010-09-02 02:00:49 +08:00
( defun el-get-cd ( package )
2010-08-04 03:44:29 +08:00
" Open dired in the package directory. "
2011-02-22 05:55:45 +08:00
( interactive
( list ( el-get-read-package-with-status " cd to " " required " " installed " ) ) )
2010-09-02 02:00:49 +08:00
( el-get-error-unless-package-p package )
( dired ( el-get-package-directory package ) ) )
2010-08-04 03:44:29 +08:00
2011-03-17 05:21:52 +08:00
( defun el-get-write-recipe ( source dir &optional filename )
" Given an SOURCE entry, write it to FILENAME "
( let* ( ;; Replace a package name with its definition
( source ( if ( symbolp source ) ( el-get-read-recipe source ) source ) )
;; Autogenerate filename if unspecified
2011-09-07 03:22:46 +08:00
( filename ( or filename ( format " %s.rcp " ( el-get-source-name source ) ) ) ) )
2011-03-17 05:21:52 +08:00
;; Filepath is dir/file
( let ( ( filepath ( format " %s/%s " dir filename ) ) )
( with-temp-file filepath
( insert ( prin1-to-string source ) ) ) ) ) )
2011-10-14 22:28:52 +08:00
;;;###autoload
2011-01-11 05:36:55 +08:00
( defun el-get-make-recipes ( &optional dir )
2011-01-11 05:44:56 +08:00
" Loop over `el-get-sources' and write a recipe file for each
2011-01-11 05:36:55 +08:00
entry which is not a symbol and is not already a known recipe. "
( interactive " Dsave recipes in directory: " )
( let* ( ( all ( mapcar 'el-get-source-name ( el-get-read-all-recipes ) ) )
( new ( loop for r in el-get-sources
when ( and ( not ( symbolp r ) )
( not ( member ( el-get-source-name r ) all ) ) )
collect r ) ) )
( dolist ( r new )
( message " el-get: preparing recipe file for %s " ( el-get-source-name r ) )
2011-03-17 05:21:52 +08:00
( el-get-write-recipe r dir ) ) )
2011-01-11 05:36:55 +08:00
( dired dir ) )
2011-10-29 00:02:38 +08:00
;;;###autoload
( defun el-get-checksum ( package )
" Compute the checksum of the given package, and put it in the kill-ring "
( interactive
( list ( el-get-read-package-with-status " Checksum " " installed " ) ) )
( 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 ) ) )
2012-02-02 08:25:17 +08:00
( message " Checksum for package %s is: %s. It has been copied to the kill-ring. "
package checksum )
2012-03-01 06:21:01 +08:00
( kill-new checksum )
checksum ) ) ) )
2011-10-29 00:02:38 +08:00
2012-02-02 08:20:39 +08:00
( defun el-get-self-checksum ( )
" Compute the checksum of the running version of el-get itself.
Also put the checksum in the kill-ring. "
( interactive )
( el-get-checksum 'el-get ) )
2010-07-30 17:16:56 +08:00
2010-06-29 00:35:15 +08:00
;;
;; User Interface, Non Interactive part
;;
2011-06-22 17:38:40 +08:00
( defun el-get-init-and-install ( &optional packages )
" Install \" required \" packages, init \" installed \" packages.
When PACKAGES is non-nil, only process entries from this list.
Those packages from the list we don 't know the status of are
considered \"required\". "
2012-03-06 01:51:33 +08:00
( let* ( ( p-s-alist ( el-get-read-status-file ) )
( required ( el-get-filter-package-alist-with-status p-s-alist " required " ) )
( installed ( el-get-filter-package-alist-with-status p-s-alist " installed " ) )
2011-06-22 17:38:40 +08:00
( to-init ( if packages
( loop for p in packages
when ( member ( el-get-as-string p ) installed )
2011-09-23 17:39:12 +08:00
collect p )
( mapcar 'el-get-as-symbol installed ) ) )
( init-deps ( el-get-dependencies to-init ) )
2011-06-22 17:38:40 +08:00
( to-install ( if packages
( loop for p in packages
2011-09-23 17:39:12 +08:00
unless ( member p init-deps )
collect p )
( mapcar 'el-get-as-symbol required ) ) )
( install-deps ( el-get-dependencies to-install ) )
2011-06-26 06:16:25 +08:00
done )
2011-09-23 17:39:12 +08:00
( el-get-verbose-message " el-get-init-and-install: install %S " install-deps )
( el-get-verbose-message " el-get-init-and-install: init %S " init-deps )
( loop for p in install-deps do ( el-get-do-install p ) collect p into done )
( loop for p in init-deps do ( el-get-init p ) collect p into done )
2011-06-26 06:16:25 +08:00
done ) )
2011-06-22 17:38:40 +08:00
( defun el-get ( &optional sync &rest packages )
2011-05-26 22:15:00 +08:00
" Ensure that packages have been downloaded once and init them as needed.
2010-06-28 03:13:22 +08:00
This will not update the sources by using ` apt-get install ' or
2011-05-26 22:15:00 +08:00
` git pull ', but it will ensure that:
2010-06-28 03:13:22 +08:00
2011-05-26 22:15:00 +08:00
* the packages have been installed
* load-path is set so their elisp files can be found
* Info-directory-list is set so their info files can be found
* Autoloads have been prepared and evaluated for each package
* Any post-installation setup ( e.g. ` ( require 'feature ) ' ) happens
2010-09-20 03:49:00 +08:00
2011-05-26 22:15:00 +08:00
When SYNC is nil ( the default ) , all installations run
concurrently, in the background.
2010-11-13 05:22:19 +08:00
2011-05-26 22:15:00 +08:00
When SYNC is 'sync, each package will be installed synchronously,
and any error will stop it all.
2010-11-13 05:22:19 +08:00
When SYNC is 'wait, then ` el-get ' will enter a wait-loop and only
let you use Emacs once it has finished with its job. That 's
useful an option to use in your ` user-init-file '. Note that each
package in the list gets installed in parallel with this option.
2010-09-20 03:49:00 +08:00
Please note that the ` el-get-init ' part of ` el-get ' is always
done synchronously, so you will have to wait here. There 's
` byte-compile ' support though, and the packages you use are
2011-02-22 05:20:57 +08:00
welcome to use ` autoload ' too.
2011-06-22 17:38:40 +08:00
PACKAGES is expected to be a list of packages you want to install
or init. When PACKAGES is omited ( the default ) , the list of
already installed packages is considered. "
2010-11-13 05:22:19 +08:00
( unless ( or ( null sync )
2011-01-07 20:08:14 +08:00
( member sync ' ( sync wait ) ) )
2011-01-03 01:22:51 +08:00
( error " el-get sync parameter should be either nil, sync or wait " ) )
2011-06-17 00:27:58 +08:00
2010-12-27 17:33:14 +08:00
;; If there's no autoload file, everything needs to be regenerated.
2011-09-23 17:41:24 +08:00
( unless ( file-exists-p el-get-autoload-file ) ( el-get-invalidate-autoloads ) )
2010-12-27 17:33:14 +08:00
2011-02-25 06:57:27 +08:00
;; Autoloads path are relative to el-get-dir, so add it to load-path
( add-to-list 'load-path ( file-name-as-directory el-get-dir ) )
2011-09-23 03:48:11 +08:00
( 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 " ) )
( progress ( and ( eq sync 'wait )
2010-11-13 05:22:19 +08:00
( make-progress-reporter
2011-09-04 03:57:56 +08:00
" Waiting for `el-get' to complete... "
2011-09-23 03:48:11 +08:00
0 ( - total installed ) 0 ) ) )
2010-12-25 15:27:58 +08:00
( el-get-default-process-sync sync ) )
2011-05-26 22:37:28 +08:00
2011-06-22 17:38:40 +08:00
;; keep the result of `el-get-init-and-install' to return it even in the
;; 'wait case
2010-11-10 19:15:30 +08:00
( prog1
2011-09-23 17:39:12 +08:00
( el-get-init-and-install ( mapcar 'el-get-as-symbol packages ) )
2010-11-10 19:15:30 +08:00
2011-09-23 03:48:11 +08:00
;; el-get-install is async, that's now ongoing.
2010-11-10 19:15:30 +08:00
( when progress
2011-09-23 03:48:11 +08:00
( while ( > ( - total installed ) 0 )
( sleep-for 0.2 )
;; don't forget to account for installation failure
( setq installed ( el-get-count-packages-with-status packages " installed " " required " ) )
( progress-reporter-update progress ( - total installed ) ) )
2011-10-12 00:02:20 +08:00
( progress-reporter-done progress ) )
;; now is a good time to care about autoloads
( el-get-eval-autoloads ) ) ) )
2010-11-10 19:15:30 +08:00
2010-06-28 03:13:22 +08:00
( provide 'el-get )
2011-03-11 04:15:12 +08:00
;;; el-get.el ends here