diff options
| author | Stefan Monnier | 2014-05-06 14:11:16 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2014-05-06 14:11:16 -0400 |
| commit | 5e87fcb1d7c55532cfb7163b1de68e7ddaed4201 (patch) | |
| tree | b4fbd39f117e1cda1e90fa620f45bffb68ae1ab3 | |
| parent | 8e102bcc97871ed6e0d2deba84fe46d9a78e9e44 (diff) | |
| download | emacs-5e87fcb1d7c55532cfb7163b1de68e7ddaed4201.tar.gz emacs-5e87fcb1d7c55532cfb7163b1de68e7ddaed4201.zip | |
* lisp/emacs-lisp/package.el (package-compute-transaction): Topological sort.
Add optional `seen' argument to detect and break infinite loops.
Fixes: debbugs:16994
| -rw-r--r-- | lisp/ChangeLog | 19 | ||||
| -rw-r--r-- | lisp/emacs-lisp/package.el | 28 |
2 files changed, 31 insertions, 16 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 7a737129bb7..8e5f5f54f16 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | 2014-05-06 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * emacs-lisp/package.el (package-compute-transaction): Topological sort. | ||
| 4 | Add optional `seen' argument to detect and break infinite loops. | ||
| 5 | |||
| 1 | 2014-05-06 Eli Zaretskii <eliz@gnu.org> | 6 | 2014-05-06 Eli Zaretskii <eliz@gnu.org> |
| 2 | 7 | ||
| 3 | * emacs-lisp/find-gc.el (find-gc-unsafe, find-unsafe-funcs) | 8 | * emacs-lisp/find-gc.el (find-gc-unsafe, find-unsafe-funcs) |
| @@ -6,11 +11,11 @@ | |||
| 6 | 11 | ||
| 7 | 2014-05-06 Michael Albinus <michael.albinus@gmx.de> | 12 | 2014-05-06 Michael Albinus <michael.albinus@gmx.de> |
| 8 | 13 | ||
| 9 | * net/tramp-sh.el (tramp-remote-process-environment): Remove | 14 | * net/tramp-sh.el (tramp-remote-process-environment): |
| 10 | HISTFILE and HISTSIZE; it's too late to set them here. Add | 15 | Remove HISTFILE and HISTSIZE; it's too late to set them here. |
| 11 | :version entry. | 16 | Add :version entry. |
| 12 | (tramp-open-shell): Do not let-bind `tramp-end-of-output'. Add | 17 | (tramp-open-shell): Do not let-bind `tramp-end-of-output'. |
| 13 | "HISTSIZE=/dev/null" to the shell's env arguments. Do not send | 18 | Add "HISTSIZE=/dev/null" to the shell's env arguments. Do not send |
| 14 | extra "PSx=..." commands. | 19 | extra "PSx=..." commands. |
| 15 | (tramp-maybe-open-connection): Setenv HISTFILE to /dev/null. | 20 | (tramp-maybe-open-connection): Setenv HISTFILE to /dev/null. |
| 16 | (Bug#17295) | 21 | (Bug#17295) |
| @@ -126,8 +131,8 @@ | |||
| 126 | (todo-edit-done-item--param-key-alist): New defconsts. | 131 | (todo-edit-done-item--param-key-alist): New defconsts. |
| 127 | (todo-edit-item--prompt): New variable. | 132 | (todo-edit-item--prompt): New variable. |
| 128 | (todo-edit-item--next-key): New function. | 133 | (todo-edit-item--next-key): New function. |
| 129 | (todo-key-bindings-t): Bind "e" to todo-edit-item. Remove | 134 | (todo-key-bindings-t): Bind "e" to todo-edit-item. |
| 130 | bindings of deleted commands. | 135 | Remove bindings of deleted commands. |
| 131 | 136 | ||
| 132 | 2014-05-02 Leo Liu <sdl.web@gmail.com> | 137 | 2014-05-02 Leo Liu <sdl.web@gmail.com> |
| 133 | 138 | ||
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 7be0354992f..c194e1352ac 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el | |||
| @@ -868,7 +868,7 @@ MIN-VERSION should be a version list." | |||
| 868 | ;; Also check built-in packages. | 868 | ;; Also check built-in packages. |
| 869 | (package-built-in-p package min-version))) | 869 | (package-built-in-p package min-version))) |
| 870 | 870 | ||
| 871 | (defun package-compute-transaction (packages requirements) | 871 | (defun package-compute-transaction (packages requirements &optional seen) |
| 872 | "Return a list of packages to be installed, including PACKAGES. | 872 | "Return a list of packages to be installed, including PACKAGES. |
| 873 | PACKAGES should be a list of `package-desc'. | 873 | PACKAGES should be a list of `package-desc'. |
| 874 | 874 | ||
| @@ -880,7 +880,9 @@ version of that package. | |||
| 880 | This function recursively computes the requirements of the | 880 | This function recursively computes the requirements of the |
| 881 | packages in REQUIREMENTS, and returns a list of all the packages | 881 | packages in REQUIREMENTS, and returns a list of all the packages |
| 882 | that must be installed. Packages that are already installed are | 882 | that must be installed. Packages that are already installed are |
| 883 | not included in this list." | 883 | not included in this list. |
| 884 | |||
| 885 | SEEN is used internally to detect infinite recursion." | ||
| 884 | ;; FIXME: We really should use backtracking to explore the whole | 886 | ;; FIXME: We really should use backtracking to explore the whole |
| 885 | ;; search space (e.g. if foo require bar-1.3, and bar-1.4 requires toto-1.1 | 887 | ;; search space (e.g. if foo require bar-1.3, and bar-1.4 requires toto-1.1 |
| 886 | ;; whereas bar-1.3 requires toto-1.0 and the user has put a hold on toto-1.0: | 888 | ;; whereas bar-1.3 requires toto-1.0 and the user has put a hold on toto-1.0: |
| @@ -893,15 +895,22 @@ not included in this list." | |||
| 893 | (dolist (pkg packages) | 895 | (dolist (pkg packages) |
| 894 | (if (eq next-pkg (package-desc-name pkg)) | 896 | (if (eq next-pkg (package-desc-name pkg)) |
| 895 | (setq already pkg))) | 897 | (setq already pkg))) |
| 896 | (cond | 898 | (when already |
| 897 | (already | ||
| 898 | (if (version-list-<= next-version (package-desc-version already)) | 899 | (if (version-list-<= next-version (package-desc-version already)) |
| 899 | ;; Move to front, so it gets installed early enough (bug#14082). | 900 | ;; `next-pkg' is already in `packages', but its position there |
| 900 | (setq packages (cons already (delq already packages))) | 901 | ;; means it might be installed too late: remove it from there, so |
| 902 | ;; we re-add it (along with its dependencies) at an earlier place | ||
| 903 | ;; below (bug#16994). | ||
| 904 | (if (memq already seen) ;Avoid inf-loop on dependency cycles. | ||
| 905 | (message "Dependency cycle going through %S" | ||
| 906 | (package-desc-full-name already)) | ||
| 907 | (setq packages (delq already packages)) | ||
| 908 | (setq already nil)) | ||
| 901 | (error "Need package `%s-%s', but only %s is being installed" | 909 | (error "Need package `%s-%s', but only %s is being installed" |
| 902 | next-pkg (package-version-join next-version) | 910 | next-pkg (package-version-join next-version) |
| 903 | (package-version-join (package-desc-version already))))) | 911 | (package-version-join (package-desc-version already))))) |
| 904 | 912 | (cond | |
| 913 | (already nil) | ||
| 905 | ((package-installed-p next-pkg next-version) nil) | 914 | ((package-installed-p next-pkg next-version) nil) |
| 906 | 915 | ||
| 907 | (t | 916 | (t |
| @@ -933,12 +942,13 @@ but version %s required" | |||
| 933 | (t (setq found pkg-desc))))) | 942 | (t (setq found pkg-desc))))) |
| 934 | (unless found | 943 | (unless found |
| 935 | (if problem | 944 | (if problem |
| 936 | (error problem) | 945 | (error "%s" problem) |
| 937 | (error "Package `%s-%s' is unavailable" | 946 | (error "Package `%s-%s' is unavailable" |
| 938 | next-pkg (package-version-join next-version)))) | 947 | next-pkg (package-version-join next-version)))) |
| 939 | (setq packages | 948 | (setq packages |
| 940 | (package-compute-transaction (cons found packages) | 949 | (package-compute-transaction (cons found packages) |
| 941 | (package-desc-reqs found)))))))) | 950 | (package-desc-reqs found) |
| 951 | (cons found seen)))))))) | ||
| 942 | packages) | 952 | packages) |
| 943 | 953 | ||
| 944 | (defun package-read-from-string (str) | 954 | (defun package-read-from-string (str) |