aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/package/package-misc.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/package/package-misc.el')
-rw-r--r--lisp/package/package-misc.el129
1 files changed, 129 insertions, 0 deletions
diff --git a/lisp/package/package-misc.el b/lisp/package/package-misc.el
new file mode 100644
index 00000000000..0432ab06f83
--- /dev/null
+++ b/lisp/package/package-misc.el
@@ -0,0 +1,129 @@
1;;; package-misc.el --- Miscellaneous Packaging Functionality -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2025 Philip Kaludercic
4
5;; Author: Philip Kaludercic <philipk@posteo.net>
6
7;; This program is free software; you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version.
11
12;; This program is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with this program. If not, see <https://www.gnu.org/licenses/>.
19
20;;; Commentary:
21
22;;; Code:
23
24(require 'package-core)
25
26(require 'macroexp)
27
28(defun package--print-email-button (recipient)
29 "Insert a button whose action will send an email to RECIPIENT.
30NAME should have the form (FULLNAME . EMAIL) where FULLNAME is
31either a full name or nil, and EMAIL is a valid email address."
32 (when (car recipient)
33 (insert (car recipient)))
34 (when (and (car recipient) (cdr recipient))
35 (insert " "))
36 (when (cdr recipient)
37 (insert "<")
38 (insert-text-button (cdr recipient)
39 'follow-link t
40 'action (lambda (_)
41 (compose-mail
42 (format "%s <%s>" (car recipient) (cdr recipient)))))
43 (insert ">"))
44 (insert "\n"))
45
46(declare-function ietf-drums-parse-address "ietf-drums"
47 (string &optional decode))
48
49(defun package-maintainers (pkg-desc &optional no-error)
50 "Return an email address for the maintainers of PKG-DESC.
51The email address may contain commas, if there are multiple
52maintainers. If no maintainers are found, an error will be
53signaled. If the optional argument NO-ERROR is non-nil no error
54will be signaled in that case."
55 (unless (package-desc-p pkg-desc)
56 (error "Invalid package description: %S" pkg-desc))
57 (let* ((name (package-desc-name pkg-desc))
58 (extras (package-desc-extras pkg-desc))
59 (maint (alist-get :maintainer extras)))
60 (unless (listp (cdr maint))
61 (setq maint (list maint)))
62 (cond
63 ((and (null maint) (null no-error))
64 (user-error "Package `%s' has no explicit maintainer" name))
65 ((and (not (progn
66 (require 'ietf-drums)
67 (ietf-drums-parse-address (cdar maint))))
68 (null no-error))
69 (user-error "Package `%s' has no maintainer address" name))
70 (t
71 (with-temp-buffer
72 (mapc #'package--print-email-button maint)
73 (replace-regexp-in-string
74 "\n" ", " (string-trim
75 (buffer-substring-no-properties
76 (point-min) (point-max)))))))))
77
78;;;###autoload
79(defun package-report-bug (desc)
80 "Prepare a message to send to the maintainers of a package.
81DESC must be a `package-desc' object.
82
83Of interest to package maintainers: By default, the command will use
84`reporter-submit-bug-report' to generate a message buffer. If your
85package has specific needs, you can set the symbol property
86`package-report-bug-function' of the symbol designating your package
87name.
88"
89 (interactive (list (package--query-desc package-alist))
90 package-menu-mode)
91 (let ((maint (package-maintainers desc))
92 (name (symbol-name (package-desc-name desc)))
93 (pkgdir (package-desc-dir desc))
94 vars)
95 (when pkgdir
96 (dolist-with-progress-reporter (group custom-current-group-alist)
97 "Scanning for modified user options..."
98 (when (and (car group)
99 (file-in-directory-p (car group) pkgdir))
100 (dolist (ent (get (cdr group) 'custom-group))
101 (when (and (custom-variable-p (car ent))
102 (boundp (car ent))
103 (not (eq (custom--standard-value (car ent))
104 (default-toplevel-value (car ent)))))
105 (push (car ent) vars))))))
106 (dlet ((reporter-prompt-for-summary-p t))
107 (funcall (or (get name 'package-report-bug-function)
108 #'reporter-submit-bug-report)
109 maint name vars))))
110
111;;;; Inferring package from current buffer
112(defun package-read-from-string (str)
113 "Read a Lisp expression from STR.
114Signal an error if the entire string was not used."
115 (pcase-let ((`(,expr . ,offset) (read-from-string str)))
116 (condition-case ()
117 ;; The call to `ignore' suppresses a compiler warning.
118 (progn (ignore (read-from-string str offset))
119 (error "Can't read whole string"))
120 (end-of-file expr))))
121
122
123(defun package--alist-to-plist-args (alist)
124 (mapcar #'macroexp-quote
125 (apply #'nconc
126 (mapcar (lambda (pair) (list (car pair) (cdr pair))) alist))))
127
128(provide 'package-misc)
129;;; package-misc.el ends here