Skip to content

Commit

Permalink
Refactoring it all: a beginning. No time for testing yet, just showin…
Browse files Browse the repository at this point in the history
…g ideas.
  • Loading branch information
dimitri committed Sep 20, 2011
1 parent c9a772d commit 0433ca0
Show file tree
Hide file tree
Showing 27 changed files with 3,398 additions and 2,945 deletions.
158 changes: 158 additions & 0 deletions el-get-autoloads.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
;;; el-get.el --- Manage the external elisp bits and pieces you depend upon
;;
;; Copyright (C) 2010-2011 Dimitri Fontaine
;;
;; Author: Dimitri Fontaine <[email protected]>
;; URL: http://www.emacswiki.org/emacs/el-get
;; GIT: https://github.com/dimitri/el-get
;; 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

(require 'el-get-core)
(require 'autoload)

(defvar el-get-outdated-autoloads nil
"List of package names whose autoloads are outdated")

(defun el-get-save-and-kill (file)
"Save and kill all buffers visiting the named FILE"
(let (buf)
(while (setq buf (find-buffer-visiting file))
(with-current-buffer buf
(save-buffer)
(kill-buffer)))))

(defun el-get-ensure-byte-compilable-autoload-file (file)
"If FILE doesn't already exist, create it as a byte-compilable
autoload file (the default created by autoload.el has a local
no-byte-compile variable that suppresses byte compilation)."
;; If we don't explicitly strip out the no-byte-compile variable,
;; autoload.el will create it on demand
(unless (file-exists-p file)
(write-region
(replace-regexp-in-string ";; no-byte-compile: t\n" ""
(autoload-rubric file)) nil file)))

(defun el-get-load-fast (file)
"Load the compiled version of FILE if it exists; else load FILE verbatim"
(load (file-name-sans-extension file) nil (not el-get-verbose)))

(defun el-get-eval-autoloads ()
"Evaluate the autoloads from the autoload file."
(when (and el-get-generate-autoloads
(file-exists-p el-get-autoload-file))
(el-get-verbose-message "el-get: evaluating autoload file")
(el-get-load-fast el-get-autoload-file)))

(defun el-get-update-autoloads ()
"Regenerate, compile, and load any outdated packages' autoloads.
This function will run from a timer, and usually
shouldn't be invoked directly."

(message "el-get: updating outdated autoloads")
(setq el-get-autoload-timer nil) ;; Allow a new update to be primed

(let ((outdated el-get-outdated-autoloads)
;; Generating autoloads runs theses hooks; disable then
fundamental-mode-hook
prog-mode-hook
emacs-lisp-mode-hook
;; use dynamic scoping to set up our loaddefs file for
;; update-directory-autoloads
(generated-autoload-file el-get-autoload-file))

;; make sure we can actually byte-compile it
(el-get-ensure-byte-compilable-autoload-file generated-autoload-file)

;; clear the list early in case of errors
(setq el-get-outdated-autoloads nil)

(dolist (p outdated)
(if (string= (el-get-package-status p) "installed")
(apply 'update-directory-autoloads (el-get-load-path p))))

(el-get-save-and-kill el-get-autoload-file)

(when (file-exists-p el-get-autoload-file)
(message "el-get: byte-compiling autoload file")
(when el-get-byte-compile
(el-get-byte-compile-file el-get-autoload-file))

(el-get-eval-autoloads))))

(defconst el-get-load-suffix-regexp
(concat (mapconcat 'regexp-quote (get-load-suffixes) "\\|") "\\'"))

(defun el-get-remove-autoloads (package)
"Remove from `el-get-autoload-file' any autoloads associated
with the named PACKAGE"
;; Remove any compiled loaddefs file and schedule it for recompilation
(el-get-schedule-autoload-update)

(when (file-exists-p el-get-autoload-file)
(with-temp-buffer ;; empty buffer to trick `autoload-find-destination'
(let ((generated-autoload-file el-get-autoload-file)
;; Generating autoloads runs emacs-lisp-mode-hook; disable it
emacs-lisp-mode-hook
(autoload-modified-buffers (list (current-buffer))))
(dolist (dir (el-get-load-path package))
(when (file-directory-p dir)
(dolist (f (directory-files dir t el-get-load-suffix-regexp))
;; this will clear out any autoloads associated with the file
;; `autoload-find-destination' signature has changed in emacs24.
(if (> emacs-major-version 23)
(autoload-find-destination f (autoload-file-load-name f))
(autoload-find-destination f)))))))
(el-get-save-and-kill el-get-autoload-file)))

(defvar el-get-autoload-timer nil
"Where the currently primed autoload timer (if any) is stored")

(defun el-get-want-autoloads-p (package)
"Return t iff the given PACKAGE should have its autoloads
automatically generated by el-get"
(let ((source (el-get-package-def package)))
(or (not (plist-member source :autoloads))
(eq (plist-get source :autoloads) t))))

(defun el-get-schedule-autoload-update ()
"Autoloads need to be updated; delete any (now outdated)
compiled autoloads file and schedule the task to run later."
(let ((elc (concat (file-name-sans-extension el-get-autoload-file) ".elc")))
(when (file-exists-p elc)
(delete-file elc)))
(unless (or el-get-autoload-timer
(not el-get-generate-autoloads))
(setq el-get-autoload-timer
(run-with-idle-timer 0 nil 'el-get-update-autoloads))))

(defun el-get-invalidate-autoloads ( &optional package )
"Mark the named PACKAGE as needing new autoloads. If PACKAGE
is nil, marks all installed packages as needing new autoloads."

;; Trigger autoload recomputation unless it's already been done
(unless (or el-get-autoload-timer
(not el-get-generate-autoloads))
(setq el-get-autoload-timer
(run-with-idle-timer 0 nil 'el-get-update-autoloads)))

;; Save the package names for later
(mapc (lambda (p)
(when (el-get-want-autoloads-p p)
(add-to-list 'el-get-outdated-autoloads p)))
(if package (list package)
(el-get-list-package-names-with-status "installed")))

;; If we're invalidating everything, try to start from a clean slate
(unless package
(ignore-errors
(delete-file el-get-autoload-file)
(delete-file
(concat (file-name-sans-extension el-get-autoload-file) ".elc")))))

(provide 'el-get-autoloads)
173 changes: 173 additions & 0 deletions el-get-build.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
;;; el-get --- Manage the external elisp bits and pieces you depend upon
;;
;; Copyright (C) 2010-2011 Dimitri Fontaine
;;
;; Author: Dimitri Fontaine <[email protected]>
;; URL: http://www.emacswiki.org/emacs/el-get
;; GIT: https://github.com/dimitri/el-get
;; 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

(require 'el-get-core)

(defun el-get-build-commands (package)
"Return a list of build commands for the named PACKAGE.
The result will either be nil; a list of strings, each one to be
interpreted as a shell command; or a list of lists of
strings, each string representing a single shell argument."
(let* ((source (el-get-package-def package))
(build-type (intern (format ":build/%s" system-type)))
(build-commands
(or (plist-get source build-type)
(plist-get source :build))))

(unless (listp build-commands)
(error "build commands for package %s are not a list" package))

(unless (stringp (car build-commands))
(setq build-commands (eval build-commands)))

(mapcar (lambda (x) (if (stringp x) x (el-get-flatten x)))
build-commands)))

(defun el-get-build-command-program (name)
"Given the user command name, get the command program to execute.
That will find the program in current $PATH for you, unless given
command name is a relative filename beginning with \"./\", or its
absolute filename obtained with expand-file-name is executable."
(let ((fullname (expand-file-name name))
(exe (executable-find name)))
(cond ((string-match "^\./" name) name)
((file-executable-p fullname) fullname)
(t (or exe name)))))

(defun el-get-build
(package commands &optional subdir sync post-build-fun installing-info)
"Run each command from the package directory.
COMMANDS is a list of commands to run in order to build the
package.
The commands are run either synchronously or asynchronously
depending on the SYNC parameter, and can be run from SUBDIR
directory when given. By default COMMANDS are run from the
package directory as obtained by `el-get-package-directory'.
The function POST-BUILD-FUN will get called after the commands
are all successfully run. In case of asynchronous building, the
only way to have code running after the build is using this
parameter.
INSTALLING-INFO is t when called from
`el-get-install-or-init-info', as to avoid a nasty infinite
recursion.
"
(el-get-verbose-message "el-get-build %s" package)
(let* ((pdir (el-get-package-directory package))
(wdir (if subdir (concat (file-name-as-directory pdir) subdir) pdir))
(buf (format "*el-get-build: %s*" package))
(default-directory (file-name-as-directory wdir))
(process-list
(mapcar (lambda (c)
(let* ((split (if (stringp c)
(split-string c)
(mapcar 'shell-quote-argument c)))
(c (mapconcat 'identity split " "))
(name (car split))
(program (el-get-build-command-program name))
(args (cdr split)))

`(:command-name ,name
:buffer-name ,buf
:default-directory ,wdir
:shell t
:sync sync
:program ,program
:args (,@args)
:message ,(format "el-get-build %s: %s ok." package c)
:error ,(format
"el-get could not build %s [%s]" package c))))
commands))
(bytecomp-files (when el-get-byte-compile
(el-get-assemble-files-for-byte-compilation package)))
(full-process-list ;; includes byte compiling
(append
(when bytecomp-files
(list
(el-get-byte-compile-process package buf wdir sync bytecomp-files)))
process-list))
;; unless installing-info, post-build-fun should take care of
;; building info too
(build-info-then-post-build-fun
(if installing-info post-build-fun
`(lambda (package)
(el-get-install-or-init-info package 'build)
(funcall ,(if (symbolp post-build-fun)
(symbol-function post-build-fun)
;; it must be a lambda, just inline its value
post-build-fun)
package)))))

(el-get-start-process-list
package full-process-list build-info-then-post-build-fun)))

(defun el-get-set-info-path (package infodir-rel)
(require 'info)
(info-initialize)
(el-get-add-path-to-list package 'Info-directory-list infodir-rel))

(defun el-get-install-or-init-info (package build-or-init)
"Call `el-get-install-info' to create the necessary \"dir\"
file when build-or-init is 'build, or `el-get-set-info-path'
when build-or-init is 'init "
(let* ((source (el-get-package-def package))
(method (el-get-package-method source))
(infodir (plist-get source :info))
(pdir (el-get-package-directory package)))

;; apt-get, pacman and ELPA will set up Info-directory-list
(unless (member method '(elpa apt-get fink pacman))
(let* ((infodir-abs-conf (concat pdir infodir))
(infodir-abs (file-name-as-directory
(if (file-directory-p infodir-abs-conf)
infodir-abs-conf
(file-name-directory infodir-abs-conf))))
(infodir-rel (if (file-directory-p infodir-abs-conf)
infodir
(file-name-directory infodir)))
(info-dir (concat infodir-abs "dir"))
(infofile (if (and (file-exists-p infodir-abs-conf)
(not (file-directory-p infodir-abs-conf)))
infodir-abs-conf
(concat infodir-abs package))))

(cond
((eq build-or-init 'init)
(when (file-exists-p info-dir)
(el-get-set-info-path package infodir-rel)))

((eq build-or-init 'build)
;; rebuild each time asked --- e.g. on update
(when (and infodir
(file-directory-p infodir-abs)
(not (file-exists-p info-dir)))
(el-get-set-info-path package infodir-rel)
(el-get-build
package
`(,(format "%s %s dir"
el-get-install-info
(if (string= (substring infofile -5) ".info")
infofile
(concat infofile ".info")))) infodir-rel t nil t)))

(t
(error
"el-get-install-or-init-info: %s not supported" build-or-init)))))))

(provide 'el-get-build)
Loading

0 comments on commit 0433ca0

Please sign in to comment.