summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2015-12-29 21:40:28 -0800
committerJohn Wiegley <johnw@newartisans.com>2015-12-29 21:40:28 -0800
commit9f2f14a0725211b13a744573344636b57b9c98b9 (patch)
tree7190e0fb3d4aa06018d8cf997f06b806fb09a9c8 /lisp/emacs-lisp
parentd259328fb87db8cc67d52771efcfa653e52c5b71 (diff)
parente823c34072bf045800d91e12c7ddb61fa23c6e30 (diff)
downloademacs-9f2f14a0725211b13a744573344636b57b9c98b9.tar.gz
Merge emacs-25 into master (using imerge)
Diffstat (limited to 'lisp/emacs-lisp')
-rw-r--r--lisp/emacs-lisp/advice.el4
-rw-r--r--lisp/emacs-lisp/avl-tree.el2
-rw-r--r--lisp/emacs-lisp/backquote.el4
-rw-r--r--lisp/emacs-lisp/bytecomp.el93
-rw-r--r--lisp/emacs-lisp/cconv.el41
-rw-r--r--lisp/emacs-lisp/chart.el4
-rw-r--r--lisp/emacs-lisp/checkdoc.el1
-rw-r--r--lisp/emacs-lisp/cl-generic.el8
-rw-r--r--lisp/emacs-lisp/cl-macs.el13
-rw-r--r--lisp/emacs-lisp/cl-preloaded.el1
-rw-r--r--lisp/emacs-lisp/easy-mmode.el4
-rw-r--r--lisp/emacs-lisp/eieio-compat.el1
-rw-r--r--lisp/emacs-lisp/ert.el339
-rw-r--r--lisp/emacs-lisp/gv.el4
-rw-r--r--lisp/emacs-lisp/let-alist.el8
-rw-r--r--lisp/emacs-lisp/lisp-mode.el6
-rw-r--r--lisp/emacs-lisp/nadvice.el10
-rw-r--r--lisp/emacs-lisp/package.el235
-rw-r--r--lisp/emacs-lisp/pcase.el4
-rw-r--r--lisp/emacs-lisp/smie.el14
20 files changed, 433 insertions, 363 deletions
diff --git a/lisp/emacs-lisp/advice.el b/lisp/emacs-lisp/advice.el
index 4ee830023fc..d13bc2ff4ff 100644
--- a/lisp/emacs-lisp/advice.el
+++ b/lisp/emacs-lisp/advice.el
@@ -1629,7 +1629,7 @@ COMPILE argument of `ad-activate' was supplied as nil."
Only proper subtrees are considered, for example, if TREE is (1 (2 (3)) 4)
then the subtrees will be 1 (2 (3)) 2 (3) 3 4, dotted structures are
allowed too. Once a qualifying subtree has been found its subtrees will
-not be considered anymore. (ad-substitute-tree 'atom 'identity tree)
+not be considered anymore. (ad-substitute-tree \\='atom \\='identity tree)
generates a copy of TREE."
(cond ((consp tReE)
(cons (if (funcall sUbTrEe-TeSt (car tReE))
@@ -2419,7 +2419,7 @@ as if they had been supplied to a function with TARGET-ARGLIST directly.
Excess source arguments will be neglected, missing source arguments will be
supplied as nil. Returns a `funcall' or `apply' form with the second element
being `function' which has to be replaced by an actual function argument.
-Example: (ad-map-arglists '(a &rest args) '(w x y z)) will return
+Example: (ad-map-arglists \\='(a &rest args) \\='(w x y z)) will return
(funcall ad--addoit-function a (car args) (car (cdr args)) (nth 2 args))."
(let* ((parsed-source-arglist (ad-parse-arglist source-arglist))
(source-reqopt-args (append (nth 0 parsed-source-arglist)
diff --git a/lisp/emacs-lisp/avl-tree.el b/lisp/emacs-lisp/avl-tree.el
index 99a329b021e..9dcebb2bf42 100644
--- a/lisp/emacs-lisp/avl-tree.el
+++ b/lisp/emacs-lisp/avl-tree.el
@@ -561,7 +561,7 @@ Note that if you don't care about the order in which FUNCTION is
applied, just that the resulting list is in the correct order,
then
- (avl-tree-mapf function 'cons tree (not reverse))
+ (avl-tree-mapf function \\='cons tree (not reverse))
is more efficient."
(nreverse (avl-tree-mapf fun 'cons tree reverse)))
diff --git a/lisp/emacs-lisp/backquote.el b/lisp/emacs-lisp/backquote.el
index dc61e156130..12bd8dae08c 100644
--- a/lisp/emacs-lisp/backquote.el
+++ b/lisp/emacs-lisp/backquote.el
@@ -43,7 +43,7 @@
(defun backquote-list*-function (first &rest list)
"Like `list' but the last argument is the tail of the new list.
-For example (backquote-list* 'a 'b 'c) => (a b . c)"
+For example (backquote-list* \\='a \\='b \\='c) => (a b . c)"
;; The recursive solution is much nicer:
;; (if list (cons first (apply 'backquote-list*-function list)) first))
;; but Emacs is not very good at efficiently processing recursion.
@@ -60,7 +60,7 @@ For example (backquote-list* 'a 'b 'c) => (a b . c)"
(defmacro backquote-list*-macro (first &rest list)
"Like `list' but the last argument is the tail of the new list.
-For example (backquote-list* 'a 'b 'c) => (a b . c)"
+For example (backquote-list* \\='a \\='b \\='c) => (a b . c)"
;; The recursive solution is much nicer:
;; (if list (list 'cons first (cons 'backquote-list*-macro list)) first))
;; but Emacs is not very good at efficiently processing such things.
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index db200f3c504..b5b618e87d7 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -265,8 +265,8 @@ This option is enabled by default because it reduces Emacs memory usage."
(defcustom byte-optimize-log nil
"If non-nil, the byte-compiler will log its optimizations.
-If this is 'source, then only source-level optimizations will be logged.
-If it is 'byte, then only byte-level optimizations will be logged.
+If this is `source', then only source-level optimizations will be logged.
+If it is `byte', then only byte-level optimizations will be logged.
The information is logged to `byte-compile-log-buffer'."
:group 'bytecomp
:type '(choice (const :tag "none" nil)
@@ -456,10 +456,20 @@ Return the compile-time value of FORM."
(byte-compile-recurse-toplevel
(macroexp-progn body)
(lambda (form)
- (setf result
- (byte-compile-eval
- (byte-compile-top-level
- (byte-compile-preprocess form))))))
+ ;; Insulate the following variables
+ ;; against changes made in the
+ ;; subsidiary compilation. This
+ ;; prevents spurious warning
+ ;; messages: "not defined at runtime"
+ ;; etc.
+ (let ((byte-compile-unresolved-functions
+ byte-compile-unresolved-functions)
+ (byte-compile-new-defuns
+ byte-compile-new-defuns))
+ (setf result
+ (byte-compile-eval
+ (byte-compile-top-level
+ (byte-compile-preprocess form)))))))
(list 'quote result))))
(eval-and-compile . ,(lambda (&rest body)
(byte-compile-recurse-toplevel
@@ -503,6 +513,11 @@ defined with incorrect args.")
Used for warnings about calling a function that is defined during compilation
but won't necessarily be defined when the compiled file is loaded.")
+(defvar byte-compile-new-defuns nil
+ "List of (runtime) functions defined in this compilation run.
+This variable is used to qualify `byte-compile-noruntime-functions' when
+outputting warnings about functions not being defined at runtime.")
+
;; Variables for lexical binding
(defvar byte-compile--lexical-environment nil
"The current lexical environment.")
@@ -1503,8 +1518,9 @@ extra args."
;; Separate the functions that will not be available at runtime
;; from the truly unresolved ones.
(dolist (f byte-compile-unresolved-functions)
- (setq f (car f))
- (if (fboundp f) (push f noruntime) (push f unresolved)))
+ (setq f (car f))
+ (when (not (memq f byte-compile-new-defuns))
+ (if (fboundp f) (push f noruntime) (push f unresolved))))
;; Complain about the no-run-time functions
(byte-compile-print-syms
"the function `%s' might not be defined at runtime."
@@ -1691,7 +1707,7 @@ Any other non-nil value of ARG means to ask the user.
If optional argument LOAD is non-nil, loads the file after compiling.
If compilation is needed, this functions returns the result of
-`byte-compile-file'; otherwise it returns 'no-byte-compile."
+`byte-compile-file'; otherwise it returns `no-byte-compile'."
(interactive
(let ((file buffer-file-name)
(file-name nil)
@@ -1961,6 +1977,8 @@ With argument ARG, insert value in current buffer after the form."
;; compiled. A: Yes! b-c-u-f might contain dross from a
;; previous byte-compile.
(setq byte-compile-unresolved-functions nil)
+ (setq byte-compile-noruntime-functions nil)
+ (setq byte-compile-new-defuns nil)
;; Compile the forms from the input buffer.
(while (progn
@@ -2287,8 +2305,7 @@ list that represents a doc string reference.
;; byte-compile-warn-about-unresolved-functions.
(if (memq funsym byte-compile-noruntime-functions)
(setq byte-compile-noruntime-functions
- (delq funsym byte-compile-noruntime-functions)
- byte-compile-noruntime-functions)
+ (delq funsym byte-compile-noruntime-functions))
(setq byte-compile-unresolved-functions
(delq (assq funsym byte-compile-unresolved-functions)
byte-compile-unresolved-functions)))))
@@ -2346,8 +2363,21 @@ list that represents a doc string reference.
(defun byte-compile-file-form-require (form)
(let ((args (mapcar 'eval (cdr form)))
(hist-orig load-history)
- hist-new)
+ hist-new prov-cons)
(apply 'require args)
+
+ ;; Record the functions defined by the require in `byte-compile-new-defuns'.
+ (setq hist-new load-history)
+ (setq prov-cons (cons 'provide (car args)))
+ (while (and hist-new
+ (not (member prov-cons (car hist-new))))
+ (setq hist-new (cdr hist-new)))
+ (when hist-new
+ (dolist (x (car hist-new))
+ (when (and (consp x)
+ (memq (car x) '(defun t)))
+ (push (cdr x) byte-compile-new-defuns))))
+
(when (byte-compile-warning-enabled-p 'cl-functions)
;; Detect (require 'cl) in a way that works even if cl is already loaded.
(if (member (car args) '("cl" cl))
@@ -2403,6 +2433,7 @@ not to take responsibility for the actual compilation of the code."
(byte-compile-current-form name)) ; For warnings.
(byte-compile-set-symbol-position name)
+ (push name byte-compile-new-defuns)
;; When a function or macro is defined, add it to the call tree so that
;; we can tell when functions are not used.
(if byte-compile-generate-call-tree
@@ -3710,16 +3741,25 @@ discarding."
(byte-defop-compiler-1 quote)
(defun byte-compile-setq (form)
- (let ((args (cdr form)))
- (if args
- (while args
- (byte-compile-form (car (cdr args)))
- (or byte-compile--for-effect (cdr (cdr args))
- (byte-compile-out 'byte-dup 0))
- (byte-compile-variable-set (car args))
- (setq args (cdr (cdr args))))
- ;; (setq), with no arguments.
- (byte-compile-form nil byte-compile--for-effect))
+ (let* ((args (cdr form))
+ (len (length args)))
+ (if (= (logand len 1) 1)
+ (progn
+ (byte-compile-log-warning
+ (format "missing value for `%S' at end of setq" (car (last args)))
+ nil :error)
+ (byte-compile-form
+ `(signal 'wrong-number-of-arguments '(setq ,len))
+ byte-compile--for-effect))
+ (if args
+ (while args
+ (byte-compile-form (car (cdr args)))
+ (or byte-compile--for-effect (cdr (cdr args))
+ (byte-compile-out 'byte-dup 0))
+ (byte-compile-variable-set (car args))
+ (setq args (cdr (cdr args))))
+ ;; (setq), with no arguments.
+ (byte-compile-form nil byte-compile--for-effect)))
(setq byte-compile--for-effect nil)))
(defun byte-compile-setq-default (form)
@@ -3973,8 +4013,13 @@ that suppresses all warnings during execution of BODY."
(setq byte-compile--for-effect nil)))
(defun byte-compile-funcall (form)
- (mapc 'byte-compile-form (cdr form))
- (byte-compile-out 'byte-call (length (cdr (cdr form)))))
+ (if (cdr form)
+ (progn
+ (mapc 'byte-compile-form (cdr form))
+ (byte-compile-out 'byte-call (length (cdr (cdr form)))))
+ (byte-compile-log-warning "`funcall' called with no arguments" nil :error)
+ (byte-compile-form '(signal 'wrong-number-of-arguments '(funcall 0))
+ byte-compile--for-effect)))
;; let binding
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el
index efa9a3da011..355913acbed 100644
--- a/lisp/emacs-lisp/cconv.el
+++ b/lisp/emacs-lisp/cconv.el
@@ -473,25 +473,28 @@ places where they originally did not directly appear."
:fun-body ,(cconv--convert-function () body env form)))
(`(setq . ,forms) ; setq special form
- (let ((prognlist ()))
- (while forms
- (let* ((sym (pop forms))
- (sym-new (or (cdr (assq sym env)) sym))
- (value (cconv-convert (pop forms) env extend)))
- (push (pcase sym-new
- ((pred symbolp) `(setq ,sym-new ,value))
- (`(car-safe ,iexp) `(setcar ,iexp ,value))
- ;; This "should never happen", but for variables which are
- ;; mutated+captured+unused, we may end up trying to `setq'
- ;; on a closed-over variable, so just drop the setq.
- (_ ;; (byte-compile-report-error
- ;; (format "Internal error in cconv of (setq %s ..)"
- ;; sym-new))
- value))
- prognlist)))
- (if (cdr prognlist)
- `(progn . ,(nreverse prognlist))
- (car prognlist))))
+ (if (= (logand (length forms) 1) 1)
+ ;; With an odd number of args, let bytecomp.el handle the error.
+ form
+ (let ((prognlist ()))
+ (while forms
+ (let* ((sym (pop forms))
+ (sym-new (or (cdr (assq sym env)) sym))
+ (value (cconv-convert (pop forms) env extend)))
+ (push (pcase sym-new
+ ((pred symbolp) `(setq ,sym-new ,value))
+ (`(car-safe ,iexp) `(setcar ,iexp ,value))
+ ;; This "should never happen", but for variables which are
+ ;; mutated+captured+unused, we may end up trying to `setq'
+ ;; on a closed-over variable, so just drop the setq.
+ (_ ;; (byte-compile-report-error
+ ;; (format "Internal error in cconv of (setq %s ..)"
+ ;; sym-new))
+ value))
+ prognlist)))
+ (if (cdr prognlist)
+ `(progn . ,(nreverse prognlist))
+ (car prognlist)))))
(`(,(and (or `funcall `apply) callsym) ,fun . ,args)
;; These are not special forms but we treat them separately for the needs
diff --git a/lisp/emacs-lisp/chart.el b/lisp/emacs-lisp/chart.el
index 06601252a4c..c0a42038e94 100644
--- a/lisp/emacs-lisp/chart.el
+++ b/lisp/emacs-lisp/chart.el
@@ -479,7 +479,7 @@ See `chart-sort-matchlist' for more details."
(defun chart-sort-matchlist (namelst numlst pred)
"Sort NAMELST and NUMLST (both sequence objects) based on predicate PRED.
-PRED should be the equivalent of '<, except it must expect two
+PRED should be the equivalent of `<', except it must expect two
cons cells of the form (NAME . NUM). See `sort' for more details."
;; 1 - create 1 list of cons cells
(let ((newlist nil)
@@ -571,7 +571,7 @@ R1 and R2 are dotted pairs. Colorize it with FACE."
(defun chart-bar-quickie (dir title namelst nametitle numlst numtitle
&optional max sort-pred)
"Wash over the complex EIEIO stuff and create a nice bar chart.
-Create it going in direction DIR ['horizontal 'vertical] with TITLE
+Create it going in direction DIR [`horizontal' `vertical'] with TITLE
using a name sequence NAMELST labeled NAMETITLE with values NUMLST
labeled NUMTITLE.
Optional arguments:
diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el
index bf1a21acaf1..88d5f323f86 100644
--- a/lisp/emacs-lisp/checkdoc.el
+++ b/lisp/emacs-lisp/checkdoc.el
@@ -270,6 +270,7 @@ made in the style guide relating to order."
(defcustom checkdoc-package-keywords-flag nil
"Non-nil means warn if this file's package keywords are not recognized.
Currently, all recognized keywords must be on `finder-known-keywords'."
+ :version "25.1"
:type 'boolean)
(define-obsolete-variable-alias 'checkdoc-style-hooks
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index 9e6102c7300..78f580cbfd0 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -797,10 +797,10 @@ methods.")
;;; Define some pre-defined generic functions, used internally.
-(define-error 'cl-no-method "No method for %S")
-(define-error 'cl-no-next-method "No next method for %S" 'cl-no-method)
-(define-error 'cl-no-primary-method "No primary method for %S" 'cl-no-method)
-(define-error 'cl-no-applicable-method "No applicable method for %S"
+(define-error 'cl-no-method "No method")
+(define-error 'cl-no-next-method "No next method" 'cl-no-method)
+(define-error 'cl-no-primary-method "No primary method" 'cl-no-method)
+(define-error 'cl-no-applicable-method "No applicable method"
'cl-no-method)
(cl-defgeneric cl-no-next-method (generic method &rest args)
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index 80f0cd73cee..c8aad3aafc8 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -298,9 +298,10 @@ FORM is of the form (ARGS . BODY)."
(if (stringp (car header)) (pop header))
;; Be careful with make-symbol and (back)quote,
;; see bug#12884.
- (let ((print-gensym nil) (print-quoted t))
- (format "%S" (cons 'fn (cl--make-usage-args
- orig-args)))))
+ (help--docstring-quote
+ (let ((print-gensym nil) (print-quoted t))
+ (format "%S" (cons 'fn (cl--make-usage-args
+ orig-args))))))
header)))
;; FIXME: we'd want to choose an arg name for the &rest param
;; and pass that as `expr' to cl--do-arglist, but that ends up
@@ -2829,8 +2830,8 @@ is a shorthand for (NAME NAME)."
(defun cl-struct-sequence-type (struct-type)
"Return the sequence used to build STRUCT-TYPE.
-STRUCT-TYPE is a symbol naming a struct type. Return 'vector or
-'list, or nil if STRUCT-TYPE is not a struct type. "
+STRUCT-TYPE is a symbol naming a struct type. Return `vector' or
+`list', or nil if STRUCT-TYPE is not a struct type. "
(declare (side-effect-free t) (pure t))
(cl--struct-class-type (cl--struct-get-class struct-type)))
@@ -2884,7 +2885,7 @@ Of course, we really can't know that for sure, so it's just a heuristic."
(put 'real 'cl-deftype-satisfies #'numberp)
(put 'fixnum 'cl-deftype-satisfies #'integerp)
(put 'base-char 'cl-deftype-satisfies #'characterp)
-(put 'character 'cl-deftype-satisfies #'integerp)
+(put 'character 'cl-deftype-satisfies #'natnump)
;;;###autoload
diff --git a/lisp/emacs-lisp/cl-preloaded.el b/lisp/emacs-lisp/cl-preloaded.el
index 03480b2756b..4fc271b34ce 100644
--- a/lisp/emacs-lisp/cl-preloaded.el
+++ b/lisp/emacs-lisp/cl-preloaded.el
@@ -3,6 +3,7 @@
;; Copyright (C) 2015 Free Software Foundation, Inc
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+;; Package: emacs
;; This file is part of GNU Emacs.
diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el
index 56f95111ab8..321895de4e1 100644
--- a/lisp/emacs-lisp/easy-mmode.el
+++ b/lisp/emacs-lisp/easy-mmode.el
@@ -148,7 +148,7 @@ BODY contains code to execute each time the mode is enabled or disabled.
For example, you could write
(define-minor-mode foo-mode \"If enabled, foo on you!\"
- :lighter \" Foo\" :require 'foo :global t :group 'hassle :version \"27.5\"
+ :lighter \" Foo\" :require \\='foo :global t :group \\='hassle :version \"27.5\"
...BODY CODE...)"
(declare (doc-string 2)
(debug (&define name string-or-null-p
@@ -502,7 +502,7 @@ Valid keywords and arguments are:
:inherit Parent keymap.
:group Ignored.
:suppress Non-nil to call `suppress-keymap' on keymap,
- 'nodigits to suppress digits as prefix arguments."
+ `nodigits' to suppress digits as prefix arguments."
(let (inherit dense suppress)
(while args
(let ((key (pop args))
diff --git a/lisp/emacs-lisp/eieio-compat.el b/lisp/emacs-lisp/eieio-compat.el
index e48e2d2af83..9f1b8951a1c 100644
--- a/lisp/emacs-lisp/eieio-compat.el
+++ b/lisp/emacs-lisp/eieio-compat.el
@@ -4,6 +4,7 @@
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: OO, lisp
+;; Package: eieio
;; This file is part of GNU Emacs.
diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index 21c1f1be394..02ae41b9c6b 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -187,7 +187,7 @@ using :expected-result. See `ert-test-result-type-p' for a
description of valid values for RESULT-TYPE.
\(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] \
-[:tags '(TAG...)] BODY...)"
+[:tags \\='(TAG...)] BODY...)"
(declare (debug (&define :name test
name sexp [&optional stringp]
[&rest keywordp sexp] def-body))
@@ -374,9 +374,9 @@ Returns nil."
Determines whether CONDITION matches TYPE and EXCLUDE-SUBTYPES,
and aborts the current test as failed if it doesn't."
(let ((signaled-conditions (get (car condition) 'error-conditions))
- (handled-conditions (cl-etypecase type
- (list type)
- (symbol (list type)))))
+ (handled-conditions (pcase-exhaustive type
+ ((pred listp) type)
+ ((pred symbolp) (list type)))))
(cl-assert signaled-conditions)
(unless (cl-intersection signaled-conditions handled-conditions)
(ert-fail (append
@@ -466,18 +466,18 @@ Errors during evaluation are caught and handled like nil."
(defun ert--explain-format-atom (x)
"Format the atom X for `ert--explain-equal'."
- (cl-typecase x
- (character (list x (format "#x%x" x) (format "?%c" x)))
- (fixnum (list x (format "#x%x" x)))
- (t x)))
+ (pcase x
+ ((pred characterp) (list x (format "#x%x" x) (format "?%c" x)))
+ ((pred integerp) (list x (format "#x%x" x)))
+ (_ x)))
(defun ert--explain-equal-rec (a b)
"Return a programmer-readable explanation of why A and B are not `equal'.
Returns nil if they are."
(if (not (equal (type-of a) (type-of b)))
`(different-types ,a ,b)
- (cl-etypecase a
- (cons
+ (pcase-exhaustive a
+ ((pred consp)
(let ((a-proper-p (ert--proper-list-p a))
(b-proper-p (ert--proper-list-p b)))
(if (not (eql (not a-proper-p) (not b-proper-p)))
@@ -502,24 +502,26 @@ Returns nil if they are."
`(cdr ,cdr-x)
(cl-assert (equal a b) t)
nil))))))))
- (array (if (not (equal (length a) (length b)))
- `(arrays-of-different-length ,(length a) ,(length b)
- ,a ,b
- ,@(unless (char-table-p a)
- `(first-mismatch-at
- ,(cl-mismatch a b :test 'equal))))
- (cl-loop for i from 0
- for ai across a
- for bi across b
- for xi = (ert--explain-equal-rec ai bi)
- do (when xi (cl-return `(array-elt ,i ,xi)))
- finally (cl-assert (equal a b) t))))
- (atom (if (not (equal a b))
- (if (and (symbolp a) (symbolp b) (string= a b))
- `(different-symbols-with-the-same-name ,a ,b)
- `(different-atoms ,(ert--explain-format-atom a)
- ,(ert--explain-format-atom b)))
- nil)))))
+ ((pred arrayp)
+ (if (not (equal (length a) (length b)))
+ `(arrays-of-different-length ,(length a) ,(length b)
+ ,a ,b
+ ,@(unless (char-table-p a)
+ `(first-mismatch-at
+ ,(cl-mismatch a b :test 'equal))))
+ (cl-loop for i from 0
+ for ai across a
+ for bi across b
+ for xi = (ert--explain-equal-rec ai bi)
+ do (when xi (cl-return `(array-elt ,i ,xi)))
+ finally (cl-assert (equal a b) t))))
+ ((pred atom)
+ (if (not (equal a b))
+ (if (and (symbolp a) (symbolp b) (string= a b))
+ `(different-symbols-with-the-same-name ,a ,b)
+ `(different-atoms ,(ert--explain-format-atom a)
+ ,(ert--explain-format-atom b)))
+ nil)))))
(defun ert--explain-equal (a b)
"Explainer function for `equal'."
@@ -694,23 +696,20 @@ and is displayed in front of the value of MESSAGE-FORM."
(print-level 8)
(print-length 50))
(dolist (frame backtrace)
- (cl-ecase (car frame)
- ((nil)
+ (pcase-exhaustive frame
+ (`(nil ,special-operator . ,arg-forms)
;; Special operator.
- (cl-destructuring-bind (special-operator &rest arg-forms)
- (cdr frame)
- (insert
- (format " %S\n" (cons special-operator arg-forms)))))
- ((t)
+ (insert
+ (format " %S\n" (cons special-operator arg-forms))))
+ (`(t ,fn . ,args)
;; Function call.
- (cl-destructuring-bind (fn &rest args) (cdr frame)
- (insert (format " %S(" fn))
- (cl-loop for firstp = t then nil
- for arg in args do
- (unless firstp
- (insert " "))
- (insert (format "%S" arg)))
- (insert ")\n")))))))
+ (insert (format " %S(" fn))
+ (cl-loop for firstp = t then nil
+ for arg in args do
+ (unless firstp
+ (insert " "))
+ (insert (format "%S" arg)))
+ (insert ")\n"))))))
;; A container for the state of the execution of a single test and
;; environment data needed during its execution.
@@ -894,33 +893,32 @@ t -- Always matches.
RESULT."
;; It would be easy to add `member' and `eql' types etc., but I
;; haven't bothered yet.
- (cl-etypecase result-type
- ((member nil) nil)
- ((member t) t)
- ((member :failed) (ert-test-failed-p result))
- ((member :passed) (ert-test-passed-p result))
- ((member :skipped) (ert-test-skipped-p result))
- (cons
- (cl-destructuring-bind (operator &rest operands) result-type
- (cl-ecase operator
- (and
- (cl-case (length operands)
- (0 t)
- (t
- (and (ert-test-result-type-p result (car operands))
- (ert-test-result-type-p result `(and ,@(cdr operands)))))))
- (or
- (cl-case (length operands)
- (0 nil)
- (t
- (or (ert-test-result-type-p result (car operands))
- (ert-test-result-type-p result `(or ,@(cdr operands)))))))
- (not
- (cl-assert (eql (length operands) 1))
- (not (ert-test-result-type-p result (car operands))))
- (satisfies
- (cl-assert (eql (length operands) 1))
- (funcall (car operands) result)))))))
+ (pcase-exhaustive result-type
+ ('nil nil)
+ ('t t)
+ (:failed (ert-test-failed-p result))
+ (:passed (ert-test-passed-p result))
+ (:skipped (ert-test-skipped-p result))
+ (`(,operator . ,operands)
+ (cl-ecase operator
+ (and
+ (cl-case (length operands)
+ (0 t)
+ (t
+ (and (ert-test-result-type-p result (car operands))
+ (ert-test-result-type-p result `(and ,@(cdr operands)))))))
+ (or
+ (cl-case (length operands)
+ (0 nil)
+ (t
+ (or (ert-test-result-type-p result (car operands))
+ (ert-test-result-type-p result `(or ,@(cdr operands)))))))
+ (not
+ (cl-assert (eql (length operands) 1))
+ (not (ert-test-result-type-p result (car operands))))
+ (satisfies
+ (cl-assert (eql (length operands) 1))
+ (funcall (car operands) result))))))
(defun ert-test-result-expected-p (test result)
"Return non-nil if TEST's expected result type matches RESULT."
@@ -961,95 +959,96 @@ as (satisfies ...), strings, :new, etc. make use of UNIVERSE.
Selectors that do not, such as (member ...), just return the
set implied by them without checking whether it is really
contained in UNIVERSE."
- ;; This code needs to match the etypecase in
+ ;; This code needs to match the cases in
;; `ert-insert-human-readable-selector'.
- (cl-etypecase selector
- ((member nil) nil)
- ((member t) (cl-etypecase universe
- (list universe)
- ((member t) (ert-select-tests "" universe))))
- ((member :new) (ert-select-tests
- `(satisfies ,(lambda (test)
- (null (ert-test-most-recent-result test))))
- universe))
- ((member :failed) (ert-select-tests
- `(satisfies ,(lambda (test)
- (ert-test-result-type-p
- (ert-test-most-recent-result test)
- ':failed)))
- universe))
- ((member :passed) (ert-select-tests
- `(satisfies ,(lambda (test)
- (ert-test-result-type-p
- (ert-test-most-recent-result test)
- ':passed)))
- universe))
- ((member :expected) (ert-select-tests
- `(satisfies
- ,(lambda (test)
- (ert-test-result-expected-p
- test
- (ert-test-most-recent-result test))))
- universe))
- ((member :unexpected) (ert-select-tests `(not :expected) universe))
- (string
- (cl-etypecase universe
- ((member t) (mapcar #'ert-get-test
- (apropos-internal selector #'ert-test-boundp)))
- (list (cl-remove-if-not (lambda (test)
- (and (ert-test-name test)
- (string-match selector
- (symbol-name
- (ert-test-name test)))))
- universe))))
- (ert-test (list selector))
- (symbol
+ (pcase-exhaustive selector
+ ('nil nil)
+ ('t (pcase-exhaustive universe
+ ((pred listp) universe)
+ (`t (ert-select-tests "" universe))))
+ (:new (ert-select-tests
+ `(satisfies ,(lambda (test)
+ (null (ert-test-most-recent-result test))))
+ universe))
+ (:failed (ert-select-tests
+ `(satisfies ,(lambda (test)
+ (ert-test-result-type-p
+ (ert-test-most-recent-result test)
+ ':failed)))
+ universe))
+ (:passed (ert-select-tests
+ `(satisfies ,(lambda (test)
+ (ert-test-result-type-p
+ (ert-test-most-recent-result test)
+ ':passed)))
+ universe))
+ (:expected (ert-select-tests
+ `(satisfies
+ ,(lambda (test)
+ (ert-test-result-expected-p
+ test
+ (ert-test-most-recent-result test))))
+ universe))
+ (:unexpected (ert-select-tests `(not :expected) universe))
+ ((pred stringp)
+ (pcase-exhaustive universe
+ (`t (mapcar #'ert-get-test
+ (apropos-internal selector #'ert-test-boundp)))
+ ((pred listp)
+ (cl-remove-if-not (lambda (test)
+ (and (ert-test-name test)
+ (string-match selector
+ (symbol-name
+ (ert-test-name test)))))
+ universe))))
+ ((pred ert-test-p) (list selector))
+ ((pred symbolp)
(cl-assert (ert-test-boundp selector))
(list (ert-get-test selector)))
- (cons
- (cl-destructuring-bind (operator &rest operands) selector
- (cl-ecase operator
- (member
- (mapcar (lambda (purported-test)
- (cl-etypecase purported-test
- (symbol (cl-assert (ert-test-boundp purported-test))
- (ert-get-test purported-test))
- (ert-test purported-test)))
- operands))
- (eql
- (cl-assert (eql (length operands) 1))
- (ert-select-tests `(member ,@operands) universe))
- (and
- ;; Do these definitions of AND, NOT and OR satisfy de
- ;; Morgan's laws? Should they?
- (cl-case (length operands)
- (0 (ert-select-tests 't universe))
- (t (ert-select-tests `(and ,@(cdr operands))
- (ert-select-tests (car operands)
- universe)))))
- (not
- (cl-assert (eql (length operands) 1))
- (let ((all-tests (ert-select-tests 't universe)))
- (cl-set-difference all-tests
- (ert-select-tests (car operands)
- all-tests))))
- (or
- (cl-case (length operands)
- (0 (ert-select-tests 'nil universe))
- (t (cl-union (ert-select-tests (car operands) universe)
- (ert-select-tests `(or ,@(cdr operands))
- universe)))))
- (tag
- (cl-assert (eql (length operands) 1))
- (let ((tag (car operands)))
- (ert-select-tests `(satisfies
- ,(lambda (test)
- (member tag (ert-test-tags test))))
- universe)))
- (satisfies
- (cl-assert (eql (length operands) 1))
- (cl-remove-if-not (car operands)
- (ert-select-tests 't universe))))))))
+ (`(,operator . ,operands)
+ (cl-ecase operator
+ (member
+ (mapcar (lambda (purported-test)
+ (pcase-exhaustive purported-test
+ ((pred symbolp)
+ (cl-assert (ert-test-boundp purported-test))
+ (ert-get-test purported-test))
+ ((pred ert-test-p) purported-test)))
+ operands))
+ (eql
+ (cl-assert (eql (length operands) 1))
+ (ert-select-tests `(member ,@operands) universe))
+ (and
+ ;; Do these definitions of AND, NOT and OR satisfy de
+ ;; Morgan's laws? Should they?
+ (cl-case (length operands)
+ (0 (ert-select-tests 't universe))
+ (t (ert-select-tests `(and ,@(cdr operands))
+ (ert-select-tests (car operands)
+ universe)))))
+ (not
+ (cl-assert (eql (length operands) 1))
+ (let ((all-tests (ert-select-tests 't universe)))
+ (cl-set-difference all-tests
+ (ert-select-tests (car operands)
+ all-tests))))
+ (or
+ (cl-case (length operands)
+ (0 (ert-select-tests 'nil universe))
+ (t (cl-union (ert-select-tests (car operands) universe)
+ (ert-select-tests `(or ,@(cdr operands))
+ universe)))))
+ (tag
+ (cl-assert (eql (length operands) 1))
+ (let ((tag (car operands)))
+ (ert-select-tests `(satisfies
+ ,(lambda (test)
+ (member tag (ert-test-tags test))))
+ universe)))
+ (satisfies
+ (cl-assert (eql (length operands) 1))
+ (cl-remove-if-not (car operands)
+ (ert-select-tests 't universe)))))))
(defun ert--insert-human-readable-selector (selector)
"Insert a human-readable presentation of SELECTOR into the current buffer."
@@ -1058,26 +1057,24 @@ contained in UNIVERSE."
;; `most-recent-result' slots of test case objects in (eql ...) or
;; (member ...) selectors.
(cl-labels ((rec (selector)
- ;; This code needs to match the etypecase in
+ ;; This code needs to match the cases in
;; `ert-select-tests'.
- (cl-etypecase selector
- ((or (member nil t
- :new :failed :passed
- :expected :unexpected)
- string
- symbol)
+ (pcase-exhaustive selector
+ ((or
+ ;; 'nil 't :new :failed :passed :expected :unexpected
+ (pred stringp)
+ (pred symbolp))
selector)
- (ert-test
+ ((pred ert-test-p)
(if (ert-test-name selector)
(make-symbol (format "<%S>" (ert-test-name selector)))
(make-symbol "<unnamed test>")))
- (cons
- (cl-destructuring-bind (operator &rest operands) selector
- (cl-ecase operator
- ((member eql and not or)
- `(,operator ,@(mapcar #'rec operands)))
- ((member tag satisfies)
- selector)))))))
+ (`(,operator . ,operands)
+ (pcase operator
+ ((or 'member 'eql 'and 'not 'or)
+ `(,operator ,@(mapcar #'rec operands)))
+ ((or 'tag 'satisfies)
+ selector))))))
(insert (format "%S" (rec selector)))))
diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el
index 94fe6c3d441..1fea38c49c1 100644
--- a/lisp/emacs-lisp/gv.el
+++ b/lisp/emacs-lisp/gv.el
@@ -260,6 +260,8 @@ The return value is the last VAL in the list.
\(fn PLACE VAL PLACE VAL ...)"
(declare (debug (&rest [gv-place form])))
+ (if (/= (logand (length args) 1) 0)
+ (signal 'wrong-number-of-arguments (list 'setf (length args))))
(if (and args (null (cddr args)))
(let ((place (pop args))
(val (car args)))
@@ -534,7 +536,7 @@ This macro only makes sense when used in a place."
"Return a reference to PLACE.
This is like the `&' operator of the C language.
Note: this only works reliably with lexical binding mode, except for very
-simple PLACEs such as (function-symbol 'foo) which will also work in dynamic
+simple PLACEs such as (function-symbol \\='foo) which will also work in dynamic
binding mode."
(let ((code
(gv-letplace (getter setter) place
diff --git a/lisp/emacs-lisp/let-alist.el b/lisp/emacs-lisp/let-alist.el
index 0b5dedea9d2..0b647a028ca 100644
--- a/lisp/emacs-lisp/let-alist.el
+++ b/lisp/emacs-lisp/let-alist.el
@@ -120,10 +120,10 @@ For instance, the following code
essentially expands to
- (let ((.title (cdr (assq 'title alist)))
- (.body (cdr (assq 'body alist)))
- (.site (cdr (assq 'site alist)))
- (.site.contents (cdr (assq 'contents (cdr (assq 'site alist))))))
+ (let ((.title (cdr (assq \\='title alist)))
+ (.body (cdr (assq \\='body alist)))
+ (.site (cdr (assq \\='site alist)))
+ (.site.contents (cdr (assq \\='contents (cdr (assq \\='site alist))))))
(if (and .title .body)
.body
.site
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index 9ce0dfd49e8..3448b72c3f1 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -106,8 +106,10 @@
"define-global-minor-mode"
"define-globalized-minor-mode"
"define-derived-mode" "define-generic-mode"
+ "ert-deftest"
"cl-defun" "cl-defsubst" "cl-defmacro"
- "cl-define-compiler-macro"
+ "cl-define-compiler-macro" "cl-defgeneric"
+ "cl-defmethod"
;; CL.
"define-compiler-macro" "define-modify-macro"
"defsetf" "define-setf-expander"
@@ -270,7 +272,7 @@ This will generate compile-time constants from BINDINGS."
"define-derived-mode" "define-minor-mode"
"define-generic-mode" "define-global-minor-mode"
"define-globalized-minor-mode" "define-skeleton"
- "define-widget"))
+ "define-widget" "ert-deftest"))
(el-vdefs '("defconst" "defcustom" "defvaralias" "defvar-local"
"defface"))
(el-tdefs '("defgroup" "deftheme"))
diff --git a/lisp/emacs-lisp/nadvice.el b/lisp/emacs-lisp/nadvice.el
index 2cd34e12810..a1bc38ce2bf 100644
--- a/lisp/emacs-lisp/nadvice.el
+++ b/lisp/emacs-lisp/nadvice.el
@@ -279,7 +279,7 @@ a special meaning:
whereas a depth of -100 means that the advice should be outermost.
If PLACE is a symbol, its `default-value' will be affected.
-Use (local 'SYMBOL) if you want to apply FUNCTION to SYMBOL buffer-locally.
+Use (local \\='SYMBOL) if you want to apply FUNCTION to SYMBOL buffer-locally.
Use (var VAR) if you want to apply FUNCTION to the (lexical) VAR.
If one of FUNCTION or OLDFUN is interactive, then the resulting function
@@ -289,7 +289,10 @@ is also interactive. There are 3 cases:
argument (the interactive spec of OLDFUN, which it can pass to
`advice-eval-interactive-spec') and return the list of arguments to use.
- Else, use the interactive spec of FUNCTION and ignore the one of OLDFUN."
- (declare (debug t)) ;;(indent 2)
+ (declare
+ ;;(indent 2)
+ (debug (form [&or symbolp ("local" form) ("var" sexp) gv-place]
+ form &optional form)))
`(advice--add-function ,where (gv-ref ,(advice--normalize-place place))
,function ,props))
@@ -311,7 +314,8 @@ is also interactive. There are 3 cases:
If FUNCTION was not added to PLACE, do nothing.
Instead of FUNCTION being the actual function, it can also be the `name'
of the piece of advice."
- (declare (debug t))
+ (declare (debug ([&or symbolp ("local" form) ("var" sexp) gv-place]
+ form)))
(gv-letplace (getter setter) (advice--normalize-place place)
(macroexp-let2 nil new `(advice--remove-function ,getter ,function)
`(unless (eq ,new ,getter) ,(funcall setter new)))))
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index fdad84a117a..97b89975469 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -5,7 +5,7 @@
;; Author: Tom Tromey <tromey@redhat.com>
;; Daniel Hackney <dan@haxney.org>
;; Created: 10 Mar 2007
-;; Version: 1.0.1
+;; Version: 1.1.0
;; Keywords: tools
;; Package-Requires: ((tabulated-list "1.0"))
@@ -24,14 +24,6 @@
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
-;;; Change Log:
-
-;; 2 Apr 2007 - now using ChangeLog file
-;; 15 Mar 2007 - updated documentation
-;; 14 Mar 2007 - Changed how obsolete packages are handled
-;; 13 Mar 2007 - Wrote package-install-from-buffer
-;; 12 Mar 2007 - Wrote package-menu mode
-
;;; Commentary:
;; The idea behind package.el is to be able to download packages and
@@ -69,6 +61,7 @@
;; * Download. Fetching the package from ELPA.
;; * Install. Untar the package, or write the .el file, into
;; ~/.emacs.d/elpa/ directory.
+;; * Autoload generation.
;; * Byte compile. Currently this phase is done during install,
;; but we may change this.
;; * Activate. Evaluate the autoloads for the package to make it
@@ -127,14 +120,9 @@
;; - "installed" instead of a blank in the status column
;; - tramp needs its files to be compiled in a certain order.
;; how to handle this? fix tramp?
-;; - on emacs 21 we don't kill the -autoloads.el buffer. what about 22?
;; - maybe we need separate .elc directories for various emacs versions
;; and also emacs-vs-xemacs. That way conditional compilation can
;; work. But would this break anything?
-;; - should store the package's keywords in archive-contents, then
-;; let the users filter the package-menu by keyword. See
-;; finder-by-keyword. (We could also let people view the
-;; Commentary, but it isn't clear how useful this is.)
;; - William Xu suggests being able to open a package file without
;; installing it
;; - Interface with desktop.el so that restarting after an install
@@ -145,15 +133,9 @@
;; private data dir, aka ".../etc". Or, maybe data-directory
;; needs to be a list (though this would be less nice)
;; a few packages want this, eg sokoban
-;; - package menu needs:
-;; ability to know which packages are built-in & thus not deletable
-;; it can sometimes print odd results, like 0.3 available but 0.4 active
-;; why is that?
-;; - Allow multiple versions on the server...?
-;; [ why bother? ]
-;; - Don't install a package which will invalidate dependencies overall
-;; - Allow something like (or (>= emacs 21.0) (>= xemacs 21.5))
-;; [ currently thinking, why bother.. KISS ]
+;; - Allow multiple versions on the server, so that if a user doesn't
+;; meet the requirements for the most recent version they can still
+;; install an older one.
;; - Allow optional package dependencies
;; then if we require 'bbdb', bbdb-specific lisp in lisp/bbdb
;; and just don't compile to add to load path ...?
@@ -235,7 +217,7 @@ of it available such that:
This variable has three possible values:
nil: no packages are hidden;
- `archive': only criteria (a) is used;
+ `archive': only criterion (a) is used;
t: both criteria are used.
This variable has no effect if `package-menu--hide-packages' is
@@ -253,7 +235,7 @@ Each element has the form (ARCHIVE-ID . PRIORITY).
When installing packages, the package with the highest version
number from the archive with the highest priority is
-selected. When higher versions are available from archives with
+selected. When higher versions are available from archives with
lower priorities, the user has to select those manually.
Archives not in this list have the priority 0.
@@ -665,8 +647,30 @@ PKG-DESC is a `package-desc' object."
(defvar Info-directory-list)
(declare-function info-initialize "info" ())
-(defun package-activate-1 (pkg-desc &optional reload)
+(defun package--load-files-for-activation (pkg-desc reload)
+ "Load files for activating a package given by PKG-DESC.
+Load the autoloads file, and ensure `load-path' is setup. If
+RELOAD is non-nil, also load all files in the package that
+correspond to previously loaded files."
+ (let* ((loaded-files-list (when reload
+ (package--list-loaded-files (package-desc-dir pkg-desc)))))
+ ;; Add to load path, add autoloads, and activate the package.
+ (package--activate-autoloads-and-load-path pkg-desc)
+ ;; Call `load' on all files in `package-desc-dir' already present in
+ ;; `load-history'. This is done so that macros in these files are updated
+ ;; to their new definitions. If another package is being installed which
+ ;; depends on this new definition, not doing this update would cause
+ ;; compilation errors and break the installation.
+ (with-demoted-errors "Error in package--load-files-for-activation: %s"
+ (mapc (lambda (feature) (load feature nil t))
+ ;; Skip autoloads file since we already evaluated it above.
+ (remove (file-truename (package--autoloads-file-name pkg-desc))
+ loaded-files-list)))))
+
+(defun package-activate-1 (pkg-desc &optional reload deps)
"Activate package given by PKG-DESC, even if it was already active.
+If DEPS is non-nil, also activate its dependencies (unless they
+are already activated).
If RELOAD is non-nil, also `load' any files inside the package which
correspond to previously loaded files (those returned by
`package--list-loaded-files')."
@@ -675,20 +679,15 @@ correspond to previously loaded files (those returned by
(unless pkg-dir
(error "Internal error: unable to find directory for `%s'"
(package-desc-full-name pkg-desc)))
- (let* ((loaded-files-list (when reload
- (package--list-loaded-files pkg-dir))))
- ;; Add to load path, add autoloads, and activate the package.
- (package--activate-autoloads-and-load-path pkg-desc)
- ;; Call `load' on all files in `pkg-dir' already present in
- ;; `load-history'. This is done so that macros in these files are updated
- ;; to their new definitions. If another package is being installed which
- ;; depends on this new definition, not doing this update would cause
- ;; compilation errors and break the installation.
- (with-demoted-errors "Error in package-activate-1: %s"
- (mapc (lambda (feature) (load feature nil t))
- ;; Skip autoloads file since we already evaluated it above.
- (remove (file-truename (package--autoloads-file-name pkg-desc))
- loaded-files-list))))
+ ;; Activate its dependencies recursively.
+ ;; FIXME: This doesn't check whether the activated version is the
+ ;; required version.
+ (when deps
+ (dolist (req (package-desc-reqs pkg-desc))
+ (unless (package-activate (car req))
+ (error "Unable to activate package `%s'.\nRequired package `%s-%s' is unavailable"
+ name (car req) (package-version-join (cadr req))))))
+ (package--load-files-for-activation pkg-desc reload)
;; Add info node.
(when (file-exists-p (expand-file-name "dir" pkg-dir))
;; FIXME: not the friendliest, but simple.
@@ -740,7 +739,7 @@ DIR, sorted by most recently loaded last."
;; one was already activated. It also loads a features of this
;; package which were already loaded.
(defun package-activate (package &optional force)
- "Activate package PACKAGE.
+ "Activate the package named PACKAGE.
If FORCE is true, (re-)activate it if it's already activated.
Newer versions are always activated, regardless of FORCE."
(let ((pkg-descs (cdr (assq package package-alist))))
@@ -760,19 +759,7 @@ Newer versions are always activated, regardless of FORCE."
((and (memq package package-activated-list) (not force))
t)
;; Otherwise, proceed with activation.
- (t
- (let* ((pkg-vec (car pkg-descs))
- (fail (catch 'dep-failure
- ;; Activate its dependencies recursively.
- (dolist (req (package-desc-reqs pkg-vec))
- (unless (package-activate (car req))
- (throw 'dep-failure req))))))
- (if fail
- (warn "Unable to activate package `%s'.
-Required package `%s-%s' is unavailable"
- package (car fail) (package-version-join (cadr fail)))
- ;; If all goes well, activate the package itself.
- (package-activate-1 pkg-vec force)))))))
+ (t (package-activate-1 (car pkg-descs) nil 'deps)))))
;;; Installation -- Local operations
@@ -843,13 +830,21 @@ untar into a directory named DIR; otherwise, signal an error."
(package--make-autoloads-and-stuff pkg-desc pkg-dir)
;; Update package-alist.
(let ((new-desc (package-load-descriptor pkg-dir)))
- ;; FIXME: Check that `new-desc' matches `desc'!
+ (unless (equal (package-desc-full-name new-desc)
+ (package-desc-full-name pkg-desc))
+ (error "The retrieved package (`%s') doesn't match what the archive offered (`%s')"
+ (package-desc-full-name new-desc) (package-desc-full-name pkg-desc)))
+ ;; Activation has to be done before compilation, so that if we're
+ ;; upgrading and macros have changed we load the new definitions
+ ;; before compiling.
+ (package-activate-1 new-desc :reload :deps)
;; FIXME: Compilation should be done as a separate, optional, step.
;; E.g. for multi-package installs, we should first install all packages
;; and then compile them.
- (package--compile new-desc))
- ;; Try to activate it.
- (package-activate name 'force)
+ (package--compile new-desc)
+ ;; After compilation, load again any files loaded by
+ ;; `activate-1', so that we use the byte-compiled definitions.
+ (package--load-files-for-activation new-desc :reload))
pkg-dir))
(defun package-generate-description-file (pkg-desc pkg-file)
@@ -932,11 +927,12 @@ untar into a directory named DIR; otherwise, signal an error."
;;;; Compilation
(defvar warning-minimum-level)
(defun package--compile (pkg-desc)
- "Byte-compile installed package PKG-DESC."
+ "Byte-compile installed package PKG-DESC.
+This assumes that `pkg-desc' has already been activated with
+`package-activate-1'."
(let ((warning-minimum-level :error)
(save-silently inhibit-message)
(load-path load-path))
- (package--activate-autoloads-and-load-path pkg-desc)
(byte-recompile-directory (package-desc-dir pkg-desc) 0 t)))
;;;; Inferring package from current buffer
@@ -1142,46 +1138,50 @@ Point is after the headers when BODY runs.
FILE, if provided, is added to URL.
URL can be a local file name, which must be absolute.
ASYNC, if non-nil, runs the request asynchronously.
-ERROR-FORM is run only if an error occurs. If NOERROR is
-non-nil, don't propagate errors caused by the connection or by
-BODY (does not apply to errors signaled by ERROR-FORM).
+ERROR-FORM is run only if a connection error occurs. If NOERROR
+is non-nil, don't propagate connection errors (does not apply to
+errors signaled by ERROR-FORM or by BODY).
\(fn URL &key ASYNC FILE ERROR-FORM NOERROR &rest BODY)"
(declare (indent defun) (debug t))
(while (keywordp (car body))
(setq body (cdr (cdr body))))
- (macroexp-let2* nil ((url-1 url))
- `(cl-macrolet ((wrap-errors (&rest bodyforms)
- (let ((err (make-symbol "err")))
- `(condition-case ,err
- ,(macroexp-progn bodyforms)
- ,(list 'error ',error-form
- (list 'unless ',noerror
- `(signal (car ,err) (cdr ,err))))))))
+ (macroexp-let2* nil ((url-1 url)
+ (noerror-1 noerror))
+ `(cl-macrolet ((unless-error (body-2 &rest before-body)
+ (let ((err (make-symbol "err")))
+ `(with-temp-buffer
+ (when (condition-case ,err
+ (progn ,@before-body t)
+ ,(list 'error ',error-form
+ (list 'unless ',noerror-1
+ `(signal (car ,err) (cdr ,err)))))
+ ,@body-2)))))
(if (string-match-p "\\`https?:" ,url-1)
(let* ((url (concat ,url-1 ,file))
(callback (lambda (status)
(let ((b (current-buffer)))
- (unwind-protect (wrap-errors
- (when-let ((er (plist-get status :error)))
- (error "Error retrieving: %s %S" url er))
- (unless (search-forward-regexp "^\r?\n\r?" nil 'noerror)
- (error "Error retrieving: %s %S" url "incomprehensible buffer"))
- (with-temp-buffer
- (url-insert-buffer-contents b url)
- (kill-buffer b)
- (goto-char (point-min))
- ,@body)))))))
+ (require 'url-handlers)
+ (unless-error ,body
+ (when-let ((er (plist-get status :error)))
+ (error "Error retrieving: %s %S" url er))
+ (with-current-buffer b
+ (goto-char (point-min))
+ (unless (search-forward-regexp "^\r?\n\r?" nil 'noerror)
+ (error "Error retrieving: %s %S" url "incomprehensible buffer")))
+ (url-insert-buffer-contents b url)
+ (kill-buffer b)
+ (goto-char (point-min)))))))
(if ,async
- (wrap-errors (url-retrieve url callback nil 'silent))
- (with-current-buffer (wrap-errors (url-retrieve-synchronously url 'silent))
- (funcall callback nil))))
- (wrap-errors (with-temp-buffer
- (let ((url (expand-file-name ,file ,url-1)))
- (unless (file-name-absolute-p url)
- (error "Location %s is not a url nor an absolute file name" url))
- (insert-file-contents url))
- ,@body))))))
+ (unless-error nil (url-retrieve url callback nil 'silent))
+ (unless-error ,body (url-insert-file-contents url))))
+ (unless-error ,body
+ (let ((url (expand-file-name ,file ,url-1)))
+ (unless (file-name-absolute-p url)
+ (error "Location %s is not a url nor an absolute file name" url))
+ (insert-file-contents url)))))))
+
+(define-error 'bad-signature "Failed to verify signature")
(defun package--check-signature-content (content string &optional sig-file)
"Check signature CONTENT against STRING.
@@ -1193,7 +1193,7 @@ errors."
(condition-case error
(epg-verify-string context content string)
(error (package--display-verify-error context sig-file)
- (signal (car error) (cdr error))))
+ (signal 'bad-signature error)))
(let (good-signatures had-fatal-error)
;; The .sig file may contain multiple signatures. Success if one
;; of the signatures is good.
@@ -1209,10 +1209,10 @@ errors."
(setq had-fatal-error t))))
(when (and (null good-signatures) had-fatal-error)
(package--display-verify-error context sig-file)
- (error "Failed to verify signature %s" sig-file))
+ (signal 'bad-signature (list sig-file)))
good-signatures)))
-(defun package--check-signature (location file &optional string async callback)
+(defun package--check-signature (location file &optional string async callback unwind)
"Check signature of the current buffer.
Download the signature file from LOCATION by appending \".sig\"
to FILE.
@@ -1221,18 +1221,35 @@ STRING is the string to verify, it defaults to `buffer-string'.
If ASYNC is non-nil, the download of the signature file is
done asynchronously.
-If the signature is verified and CALLBACK was provided, CALLBACK
-is `funcall'ed with the list of good signatures as argument (the
-list can be empty). If the signatures file is not found,
-CALLBACK is called with no arguments."
+If the signature does not verify, signal an error.
+If the signature is verified and CALLBACK was provided, `funcall'
+CALLBACK with the list of good signatures as argument (the list
+can be empty).
+If no signatures file is found, and `package-check-signature' is
+`allow-unsigned', call CALLBACK with a nil argument.
+Otherwise, an error is signaled.
+
+UNWIND, if provided, is a function to be called after everything
+else, even if an error is signaled."
(let ((sig-file (concat file ".sig"))
(string (or string (buffer-string))))
(package--with-response-buffer location :file sig-file
:async async :noerror t
- :error-form (when callback (funcall callback nil))
- (let ((sig (package--check-signature-content (buffer-substring (point) (point-max)) string sig-file)))
- (when callback (funcall callback sig))
- sig))))
+ ;; Connection error is assumed to mean "no sig-file".
+ :error-form (let ((allow-unsigned (eq package-check-signature 'allow-unsigned)))
+ (when (and callback allow-unsigned)
+ (funcall callback nil))
+ (when unwind (funcall unwind))
+ (unless allow-unsigned
+ (error "Unsigned file `%s' at %s" file location)))
+ ;; OTOH, an error here means "bad signature", which we never
+ ;; suppress. (Bug#22089)
+ (unwind-protect
+ (let ((sig (package--check-signature-content (buffer-substring (point) (point-max))
+ string sig-file)))
+ (when callback (funcall callback sig))
+ sig)
+ (when unwind (funcall unwind))))))
;;; Packages on Archives
;; The following variables store information about packages available
@@ -1495,19 +1512,12 @@ similar to an entry in `package-alist'. Save the cached copy to
location file content async
;; This function will be called after signature checking.
(lambda (&optional good-sigs)
- (unless (or good-sigs (eq package-check-signature 'allow-unsigned))
- ;; Even if the sig fails, this download is done, so
- ;; remove it from the in-progress list.
- (package--update-downloads-in-progress archive)
- (error "Unsigned archive `%s'" name))
- ;; Either everything worked or we don't mind not signing.
- ;; Write out the archives file.
(write-region content nil local-file nil 'silent)
;; Write out good signatures into archive-contents.signed file.
(when good-sigs
(write-region (mapconcat #'epg-signature-to-string good-sigs "\n")
- nil (concat local-file ".signed") nil 'silent))
- (package--update-downloads-in-progress archive))))))))
+ nil (concat local-file ".signed") nil 'silent)))
+ (lambda () (package--update-downloads-in-progress archive))))))))
(defun package--download-and-read-archives (&optional async)
"Download descriptions of all `package-archives' and read them.
@@ -1789,11 +1799,6 @@ if all the in-between dependencies are also in PACKAGE-LIST."
location file content nil
;; This function will be called after signature checking.
(lambda (&optional good-sigs)
- (unless (or good-sigs (eq package-check-signature 'allow-unsigned))
- ;; Even if the sig fails, this download is done, so
- ;; remove it from the in-progress list.
- (error "Unsigned package: `%s'"
- (package-desc-name pkg-desc)))
;; Signature checked, unpack now.
(with-temp-buffer (insert content)
(let ((save-silently t))
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index bf6550dfa3d..c87c2314be3 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -865,8 +865,10 @@ Otherwise, it defers to REST which is a list of branches of the form
(def-edebug-spec
pcase-QPAT
+ ;; Cf. edebug spec for `backquote-form' in edebug.el.
(&or ("," pcase-PAT)
- (pcase-QPAT . pcase-QPAT)
+ (pcase-QPAT [&rest [&not ","] pcase-QPAT]
+ . [&or nil pcase-QPAT])
(vector &rest pcase-QPAT)
sexp))
diff --git a/lisp/emacs-lisp/smie.el b/lisp/emacs-lisp/smie.el
index 738bdddcddf..c9c002bc8fa 100644
--- a/lisp/emacs-lisp/smie.el
+++ b/lisp/emacs-lisp/smie.el
@@ -717,9 +717,10 @@ Possible return values:
(goto-char pos)
(throw 'return
(list t epos
- (buffer-substring-no-properties
- epos
- (+ epos (if (< (point) epos) -1 1))))))))
+ (unless (= (point) epos)
+ (buffer-substring-no-properties
+ epos
+ (+ epos (if (< (point) epos) -1 1)))))))))
(if (eq pos (point))
;; We did not move, so let's abort the loop.
(throw 'return (list t (point))))))
@@ -809,7 +810,12 @@ Possible return values:
nil: we skipped over an identifier, matched parentheses, ..."
(smie-next-sexp
(indirect-function smie-backward-token-function)
- (indirect-function #'backward-sexp)
+ (lambda (n)
+ (if (bobp)
+ ;; Arguably backward-sexp should signal this error for us.
+ (signal 'scan-error
+ (list "Beginning of buffer" (point) (point)))
+ (backward-sexp n)))
(indirect-function #'smie-op-left)
(indirect-function #'smie-op-right)
halfsexp))