al-package.el 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. ;;; al-package.el --- Additional functionality for Emacs package system
  2. ;; Copyright © 2014-2016 Alex Kost
  3. ;; This program is free software; you can redistribute it and/or modify
  4. ;; it under the terms of the GNU General Public License as published by
  5. ;; the Free Software Foundation, either version 3 of the License, or
  6. ;; (at your option) any later version.
  7. ;; This program is distributed in the hope that it will be useful,
  8. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. ;; GNU General Public License for more details.
  11. ;; You should have received a copy of the GNU General Public License
  12. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ;;; Code:
  14. (require 'package)
  15. (require 'al-quelpa)
  16. (defun al/package-installed-p (fun package &rest args)
  17. "Do not check the version of a built-in package.
  18. Some built-in packages (e.g., `org', `erc') do not have 'Version'
  19. header field. This may break things if a third-party package
  20. relies on a particular version of a built-in package (e.g.,
  21. 'org-6.1' or 'erc-5.3'). So just ignore the version.
  22. This function is intendend to be used as an 'around' advice for
  23. `package-installed-p'."
  24. (or (package-built-in-p package)
  25. (apply fun package args)))
  26. ;;; Ignoring packages
  27. ;; Emacs packages have dependencies (written in "Package-Requires"
  28. ;; header of elisp files), and there is no easy way to ignore these
  29. ;; dependencies. I use the code below to install only those packages
  30. ;; that I want and to ignore packages from `al/ignored-packages' even if
  31. ;; they are required by the other ones.
  32. (defvar al/ignored-packages nil
  33. "List of names (symbols) of packages that shouldn't be installed.")
  34. (defun al/remove-ignored-packages (requirements)
  35. "Remove `al/ignored-packages' from the REQUIREMENTS."
  36. (cl-remove-if (lambda (req)
  37. (memq (car req) al/ignored-packages))
  38. requirements))
  39. ;; XXX In a better world, advising `package-desc-reqs' would work, but
  40. ;; it doesn't, presumably because it is `cl-defsubst' generated by
  41. ;; (cl-defstruct (package-desc ...)). Is there a workaround?
  42. ;; (defun al/package-desc-reqs (fun desc &rest args)
  43. ;; "Return requirements without `al/ignored-packages'."
  44. ;; (let ((reqs (apply fun desc args)))
  45. ;; (al/remove-ignored-packages reqs)))
  46. ;; (advice-add 'package-desc-reqs :around #'al/package-desc-reqs)
  47. ;; Since the above won't work, I have to mess with modifying other
  48. ;; functions:
  49. ;;
  50. ;; - `quelpa-package-install' and `package-compute-transaction': to
  51. ;; avoid building/installing unneeded dependencies;
  52. ;;
  53. ;; - `package-activate-1': to ignore unneeded dependencies from a
  54. ;; generated "…-pkg.el" file, thus to make sure startup activation will
  55. ;; not complain about missing packages. Obviously this function should
  56. ;; be advised before `package-initialize' is called.
  57. (defun al/quelpa-package-install (fun package &rest args)
  58. "Do not install PACKAGE if it is one of `al/ignored-packages'.
  59. This function is intendend to be used as an 'around' advice for
  60. `quelpa-package-install'."
  61. (let* ((name (al/package-name package))
  62. (ignore? (memq name al/ignored-packages)))
  63. (if ignore?
  64. (message "Ignoring '%s' package." name)
  65. (apply fun package args))))
  66. (defun al/package-compute-transaction (fun packages requirements
  67. &rest args)
  68. "Reduce REQUIREMENTS by excluding `al/ignored-packages'.
  69. This function is intendend to be used as an 'around' advice for
  70. `package-compute-transaction'."
  71. (apply fun packages
  72. (al/remove-ignored-packages requirements)
  73. args))
  74. (defun al/package-activate-1 (fun pkg-desc &rest args)
  75. "Reduce requirements from PKG-DESC by excluding `al/ignored-packages'.
  76. This function is intendend to be used as an 'around' advice for
  77. `package-activate-1'."
  78. (setf (package-desc-reqs pkg-desc)
  79. (al/remove-ignored-packages (package-desc-reqs pkg-desc)))
  80. (apply fun pkg-desc args))
  81. (provide 'al-package)
  82. ;;; al-package.el ends here