1 ;; pkginfo.el --- Update package-info.in files -*- mode:emacs-lisp -*-
3 ;; Copyright (C) 2020 Steve Youngs
5 ;; Author: Steve Youngs <steve@sxemacs.org>
6 ;; Maintainer: Steve Youngs <steve@sxemacs.org>
7 ;; Created: <2020-03-30>
8 ;; Time-stamp: <Monday Mar 30, 2020 20:43:57 steve>
9 ;; Homepage: https://git.sxemacs.org/slh
10 ;; Keywords: packaging, maintenence, convenience
12 ;; This file is part of SLH (Steve's Lisp Hacks)
14 ;; Redistribution and use in source and binary forms, with or without
15 ;; modification, are permitted provided that the following conditions
18 ;; 1. Redistributions of source code must retain the above copyright
19 ;; notice, this list of conditions and the following disclaimer.
21 ;; 2. Redistributions in binary form must reproduce the above copyright
22 ;; notice, this list of conditions and the following disclaimer in the
23 ;; documentation and/or other materials provided with the distribution.
25 ;; 3. Neither the name of the author nor the names of any contributors
26 ;; may be used to endorse or promote products derived from this
27 ;; software without specific prior written permission.
29 ;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
30 ;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31 ;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
32 ;; DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 ;; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 ;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 ;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
36 ;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
37 ;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
38 ;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
39 ;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 ;; This is a convenience lib to ease the pain of keeping package-info.in
44 ;; files in check. Specifically, the `provides' form within those files.
45 ;; If you are not a package maintainer or SXEmacs dev then you do not
46 ;; have any use for this. Move along, nothing to see here. :-)
48 ;; Getting it working:
50 ;; At a minimum, you need to tweak `pkginfo-dir-toplevel'. Set it to
51 ;; the toplevel directory of your SXEmacs packages source tree. It's
52 ;; the one that has the file `XEmacs.rules' in it. And that's really
53 ;; all you need to set.
57 ;; Updating a single package's package-info.in
58 ;; M-x pkginfo-update-provides RET
60 ;; You'll be prompted for the package's directory and after it completes
61 ;; it will pop you into the package-info.in buffer. If it's all good,
62 ;; just kill the buffer (the file has already been saved).
64 ;; It is also possible to update all standard packages, or all MULE
65 ;; packages, or even all packages (standard + MULE) at once. See:
67 ;; #'pkginfo-update-provides-std
68 ;; #'pkginfo-update-provides-mule
69 ;; #'pkginfo-update-all-provides
71 ;; In the cases of updating multiple packages at once you will be left
72 ;; in a `buffer-list' buffer that lists just the package-info.in files
73 ;; that were updated. This is so you can easily check through the
76 ;; Some packages do not get updated because they don't have any
77 ;; provides, and one package doesn't because it shouldn't be touched
78 ;; (it's `leim' and it contains code that is dangerous for SXEmacs
79 ;; because we don't yet have internal unicode support).
83 ;; 1) Incorporate this with sy-git.el in some fashion to maybe log
88 ;; Both of these are from the 'text-modes' package.
92 ;; Could be a defcustom, but I seriously don't think it's worth it.
93 (defvar pkginfo-dir-toplevel
94 (file-name-as-directory
96 (list (getenv "HOME") "programming" "SXEmacs" "packages")))
97 "Toplevel directory of package source tree.
99 Value must end with a directory separator.")
101 (defvar pkginfo-dir-std
102 (file-name-as-directory
103 (expand-file-name "xemacs-packages" pkginfo-dir-toplevel))
104 "Where the normal, non-MULE packages are at.")
106 (defvar pkginfo-dir-mule
107 (file-name-as-directory
108 (expand-file-name "mule-packages" pkginfo-dir-toplevel))
109 "Where the MULE packages are at.")
111 (defvar pkginfo-cant-update
112 '("general-docs" "psgml-dtds" "sounds-au" "sounds-wav")
113 "Non-MULE packages that don't have any provides.")
115 (defvar pkginfo-cant-update-mule
117 "MULE packages that shouldn't have their package-info.in updated.")
119 (defvar pkginfo-lispdir-lisp
120 '("bbdb" "gnus" "ess" "jde" "lookup" "mule-ucs" "patcher"
121 "riece" "tramp" "vm" "w3" "x-symbol" "xlib" "xslt-process"
123 "A list of packages who's lisp directory is \"lisp\".")
125 (defvar pkginfo-apel-grep
127 (concat "git grep -E '^%s(product-provide %1$s)?provide ' %2$s/*.el|"
128 "awk -F%3$s '{print $2;}'|"
129 "awk -F%4$s '{print $1;}'|"
130 "tr -d \"')\"|tr -s \"\n\" \" \"")
131 (shell-quote-argument "(")
133 (shell-quote-argument "'")
134 (shell-quote-argument ")"))
135 "Shell magic to extract APEL provides.")
137 (defvar pkginfo-cc-mode-grep
139 (concat "git grep -E '^%s(cc-)?provide ' %s/*.el|"
141 "tr -d \"')\"|tr -s \"\n\" \" \"")
142 (shell-quote-argument "(") "%s")
143 "Shell magic to extract cc-mode provides.")
145 (defun pkginfo-update-provides (pkgdir)
146 "Update the package-info.in provides for package in PKGDIR.
148 Take great care with this and ALWAYS check the results manually. There
149 are a couple of packages that are a little, shall we say, quirky, and
150 their package-info.in will probably need some manual attention.
154 text-modes -- puts a '\"' into the provides
155 ede -- has a template file that puts 'ede-proj-%NAME%'
158 There are also packages that will not be updated. Mostly, they are
159 packages that do not have any provides. But there is one, 'leim',
160 that can not, and must not, be done. leim contains code that is
161 dangerous to SXEmacs right now because we do not yet have internal
164 Packages with NO provides:
165 -------------------------
166 general-docs, psgml-dtds, sounds-au, sounds-wav, locale."
168 (list (expand-file-name
169 (read-directory-name "Package Directory: "
170 pkginfo-dir-toplevel nil t
171 "xemacs-packages/"))))
172 (let ((scmd (concat "git grep \"^(provide \" %s/*.el|"
174 "tr -d \"')\"|tr -s \"\n\" \" \""))
175 (pinfo (find-file-noselect
176 (expand-file-name "package-info.in" pkgdir)))
177 (pkg (file-basename pkgdir))
179 ;; Can't do these. They either have no provides, or we shouldn't
180 ;; attempt to update them.
181 (if (or (member pkg pkginfo-cant-update)
182 (member pkg pkginfo-cant-update-mule))
183 (error 'invalid-argument pkg))
184 ;; Special case cc-mode (it uses #'cc-provide and #'provide)
185 (when (equal pkg "cc-mode")
186 (setq scmd pkginfo-cc-mode-grep))
187 ;; Special case APEL (allow for its #'product-provide thing)
188 (when (equal pkg "apel")
189 (setq scmd pkginfo-apel-grep))
190 ;; The packages where the elisp isn't in the toplevel pkgdir
191 (setq lispd (cond ((member pkg pkginfo-lispdir-lisp) "lisp")
192 ((equal pkg "mew") "mew")
193 ((equal pkg "semantic") "{.,bovine,wisent}")
195 (with-current-buffer pinfo
196 (goto-char (point-min))
197 (setq p1 (search-forward "provides (" nil t))
198 (setq p2 (search-forward ")" nil t))
199 (delete-region p1 (- p2 1))
202 (substring (shell-command-to-string (format scmd lispd))
205 (fill-region p1 (point-at-bol 2))
206 (indent-region p1 (point) 8)
207 (untabify p1 (point))
210 (pop-to-buffer pinfo)
211 (bury-buffer pinfo))))
213 (defun pkginfo-update-provides-std ()
214 "Update package-info.in provides for all standard \(non-MULE\) pkgs."
216 (let ((pkgs (directory-files
217 pkginfo-dir-std t "[[:alnum:]]$" nil 'subdir)))
220 (setq pkgs (delete (expand-file-name pkg pkginfo-dir-std) pkgs)))
223 (mapfam #'pkginfo-update-provides pkgs)
224 (when (interactive-p)
225 (let ((buf (get-buffer-create "*STD package-infos*")))
226 (list-buffers-internal buf "package-info\\.in.*$")
227 (switch-to-buffer buf))))))
229 (defun pkginfo-update-provides-mule ()
230 "Update package-info.in provides for all MULE packages."
232 (let ((pkgs (directory-files
233 pkginfo-dir-mule t "[[:alnum:]]$" nil 'subdir)))
237 (delete (expand-file-name pkg pkginfo-dir-mule) pkgs)))
238 pkginfo-cant-update-mule)
240 (mapfam #'pkginfo-update-provides pkgs)
241 (when (interactive-p)
242 (let ((buf (get-buffer-create "*MULE package-infos*")))
243 (list-buffers-internal buf "package-info\\.in.*$")
244 (switch-to-buffer buf))))))
246 (defun pkginfo-update-all-provides ()
247 "Updates package-info.in provides for all packages, standard + MULE.
249 Take great care with this and ALWAYS check the results manually. There
250 are a couple of packages that are a little, shall we say, quirky, and
251 their package-info.in will probably need some manual attention.
254 text-modes -- puts a '\"' into the provides
255 ede -- has a template file that puts 'ede-proj-%NAME%'
258 There are also packages that will not be updated. Mostly, they are
259 packages that do not have any provides. But there is one, 'leim',
260 that can not, and must not, be done. leim contains code that is
261 dangerous to SXEmacs right now because we do not yet have internal
264 The packages that don't currently have any provides:
265 general-docs, psgml-dtds, sounds-au, sounds-wav, locale"
267 (when (yes-or-no-p "Are you ABSOLUTELY SURE you want to do this? ")
270 (pkginfo-update-provides-std)
271 (pkginfo-update-provides-mule))
272 (let ((buf (get-buffer-create "*All package-infos*")))
273 (list-buffers-internal buf "package-info\\.in.*$")
274 (switch-to-buffer buf)))))
278 ;;; pkginfo.el ends here