Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 53 additions & 28 deletions async-bytecomp.el
Original file line number Diff line number Diff line change
Expand Up @@ -54,27 +54,32 @@ all packages are always compiled asynchronously."
(const :tag "All packages" all)
(repeat symbol)))

(defvar async-byte-compile-log-file
(concat user-emacs-directory "async-bytecomp.log"))
(defvar async-byte-compile-log-file "async-bytecomp.log"
"Prefix for a file used to pass errors from async process to the caller.
The `file-name-nondirectory' part of the value is passed to
`make-temp-file' as a prefix. When the value is an absolute
path, then the `file-name-directory' part of it is expanded in
the calling process (with `expand-file-name') and used as a value
of variable `temporary-file-directory' in async processes.")

(defvar async-bytecomp-load-variable-regexp "\\`load-path\\'"
"The variable used by `async-inject-variables' when (re)compiling async.")

(defun async-bytecomp--file-to-comp-buffer (file-or-dir &optional quiet type)
(defun async-bytecomp--file-to-comp-buffer (file-or-dir &optional quiet type log-file)
(let ((bn (file-name-nondirectory file-or-dir))
(action-name (pcase type
('file "File")
('directory "Directory"))))
(if (file-exists-p async-byte-compile-log-file)
(if (and log-file (file-exists-p log-file))
(let ((buf (get-buffer-create byte-compile-log-buffer))
(n 0))
(with-current-buffer buf
(goto-char (point-max))
(let ((inhibit-read-only t))
(insert-file-contents async-byte-compile-log-file)
(insert-file-contents log-file)
(compilation-mode))
(display-buffer buf)
(delete-file async-byte-compile-log-file)
(delete-file log-file)
(unless quiet
(save-excursion
(goto-char (point-min))
Expand All @@ -87,6 +92,40 @@ all packages are always compiled asynchronously."
(unless quiet
(message "%s `%s' compiled asynchronously with success" action-name bn)))))

(defmacro async-bytecomp--comp-buffer-to-file ()
"Write contents of `byte-compile-log-buffer' to a log file.
The log file is a temporary file that name is determined by
`async-byte-compile-log-file', which see. Return the actual log
file name, or nil if no log file has been created."
`(when (get-buffer byte-compile-log-buffer)
(let ((error-data (with-current-buffer byte-compile-log-buffer
(buffer-substring-no-properties (point-min) (point-max)))))
(unless (string= error-data "")
;; The `async-byte-compile-log-file' used to be an absolute file name
;; shared amongst all compilation async processes. For backward
;; compatibility the directory part of it is used to create logs the same
;; directory while the nondirectory part denotes the PREFIX for
;; `make-temp-file' call. The `temporary-file-directory' is bound, such
;; that the async process uses one set by the caller.
(let ((temporary-file-directory
,(or (when (and async-byte-compile-log-file
(file-name-absolute-p
async-byte-compile-log-file))
(expand-file-name (file-name-directory
async-byte-compile-log-file)))
temporary-file-directory))
(log-file (make-temp-file ,(let ((log-file
(file-name-nondirectory
async-byte-compile-log-file)))
(format "%s%s"
log-file
(if (string-suffix-p "." log-file)
"" "."))))))
(with-temp-file log-file
(erase-buffer)
(insert error-data))
log-file)))))

;;;###autoload
(defun async-byte-recompile-directory (directory &optional quiet)
"Compile all *.el files in DIRECTORY asynchronously.
Expand All @@ -99,23 +138,16 @@ All *.elc files are systematically deleted before proceeding."
;; This happen when recompiling its own directory.
(load "async")
(let ((call-back
(lambda (&optional _ignore)
(async-bytecomp--file-to-comp-buffer directory quiet 'directory))))
(lambda (&optional log-file)
(async-bytecomp--file-to-comp-buffer directory quiet 'directory log-file))))
(async-start
`(lambda ()
(require 'bytecomp)
,(async-inject-variables async-bytecomp-load-variable-regexp)
(let ((default-directory (file-name-as-directory ,directory))
error-data)
(let ((default-directory (file-name-as-directory ,directory)))
(add-to-list 'load-path default-directory)
(byte-recompile-directory ,directory 0 t)
(when (get-buffer byte-compile-log-buffer)
(setq error-data (with-current-buffer byte-compile-log-buffer
(buffer-substring-no-properties (point-min) (point-max))))
(unless (string= error-data "")
(with-temp-file ,async-byte-compile-log-file
(erase-buffer)
(insert error-data))))))
,(macroexpand '(async-bytecomp--comp-buffer-to-file))))
call-back)
(unless quiet (message "Started compiling asynchronously directory %s" directory))))

Expand Down Expand Up @@ -177,23 +209,16 @@ Async compilation of packages can be controlled by
Same as `byte-compile-file' but asynchronous."
(interactive "fFile: ")
(let ((call-back
(lambda (&optional _ignore)
(async-bytecomp--file-to-comp-buffer file nil 'file))))
(lambda (&optional log-file)
(async-bytecomp--file-to-comp-buffer file nil 'file log-file))))
(async-start
`(lambda ()
(require 'bytecomp)
,(async-inject-variables async-bytecomp-load-variable-regexp)
(let ((default-directory ,(file-name-directory file))
error-data)
(let ((default-directory ,(file-name-directory file)))
(add-to-list 'load-path default-directory)
(byte-compile-file ,file)
(when (get-buffer byte-compile-log-buffer)
(setq error-data (with-current-buffer byte-compile-log-buffer
(buffer-substring-no-properties (point-min) (point-max))))
(unless (string= error-data "")
(with-temp-file ,async-byte-compile-log-file
(erase-buffer)
(insert error-data))))))
,(macroexpand '(async-bytecomp--comp-buffer-to-file))))
call-back)))

(provide 'async-bytecomp)
Expand Down
26 changes: 6 additions & 20 deletions async-package.el
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Argument ERROR-FILE is the file where errors are logged, if some."
package-user-dir ,package-user-dir
package-alist ',package-alist
load-path ',load-path)
(prog1
(cons
(condition-case err
(mapc ',fn ',packages)
(error
Expand All @@ -86,15 +86,7 @@ Argument ERROR-FILE is the file where errors are logged, if some."
(format
"%S:\n Please refresh package list before %s"
err ,action-string)))))
(let (error-data)
(when (get-buffer byte-compile-log-buffer)
(setq error-data (with-current-buffer byte-compile-log-buffer
(buffer-substring-no-properties
(point-min) (point-max))))
(unless (string= error-data "")
(with-temp-file ,async-byte-compile-log-file
(erase-buffer)
(insert error-data)))))))
,(macroexpand '(async-bytecomp--comp-buffer-to-file))))
(lambda (result)
(if (file-exists-p error-file)
(let ((buf (find-file-noselect error-file)))
Expand All @@ -104,7 +96,9 @@ Argument ERROR-FILE is the file where errors are logged, if some."
(delete-file error-file)
(async-package--modeline-mode -1))
(when result
(let ((pkgs (if (listp result) result (list result))))
(let ((pkgs (let ((pkgs (car result)))
(if (listp pkgs) pkgs (list pkgs))))
(log-file (cdr result)))
(when (eq action 'install)
(customize-save-variable
'package-selected-packages
Expand All @@ -121,15 +115,7 @@ Argument ERROR-FILE is the file where errors are logged, if some."
'async-package-message
str (length lst)))
packages action-string)
(when (file-exists-p async-byte-compile-log-file)
(let ((buf (get-buffer-create byte-compile-log-buffer)))
(with-current-buffer buf
(goto-char (point-max))
(let ((inhibit-read-only t))
(insert-file-contents async-byte-compile-log-file)
(compilation-mode))
(display-buffer buf)
(delete-file async-byte-compile-log-file)))))))
(async-bytecomp--file-to-comp-buffer nil 'quiet nil log-file))))
(run-hooks 'async-pkg-install-after-hook)))
'async-pkg-install t)
(async-package--modeline-mode 1)))
Expand Down