| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
|
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 |
|
|---|
| 30 |
|
|---|
| 31 |
|
|---|
| 32 |
|
|---|
| 33 |
|
|---|
| 34 |
(defgroup gulp nil |
|---|
| 35 |
"Ask for updates for Lisp packages." |
|---|
| 36 |
:prefix "-" |
|---|
| 37 |
:group 'maint) |
|---|
| 38 |
|
|---|
| 39 |
(defcustom gulp-discard "^;+ *Maintainer: *FSF *$" |
|---|
| 40 |
"*The regexp matching the packages not requiring the request for updates." |
|---|
| 41 |
:type 'regexp |
|---|
| 42 |
:group 'gulp) |
|---|
| 43 |
|
|---|
| 44 |
(defcustom gulp-tmp-buffer "*gulp*" "The name of the temporary buffer." |
|---|
| 45 |
:type 'string |
|---|
| 46 |
:group 'gulp) |
|---|
| 47 |
|
|---|
| 48 |
(defcustom gulp-max-len 2000 |
|---|
| 49 |
"*Distance into a Lisp source file to scan for keywords." |
|---|
| 50 |
:type 'integer |
|---|
| 51 |
:group 'gulp) |
|---|
| 52 |
|
|---|
| 53 |
(defcustom gulp-request-header |
|---|
| 54 |
(concat |
|---|
| 55 |
"This message was created automatically. |
|---|
| 56 |
I'm going to start pretesting a new version of GNU Emacs soon, so I'd |
|---|
| 57 |
like to ask if you have any updates for the Emacs packages you work on. |
|---|
| 58 |
You're listed as the maintainer of the following package(s):\n\n") |
|---|
| 59 |
"*The starting text of a gulp message." |
|---|
| 60 |
:type 'string |
|---|
| 61 |
:group 'gulp) |
|---|
| 62 |
|
|---|
| 63 |
(defcustom gulp-request-end |
|---|
| 64 |
(concat |
|---|
| 65 |
"\nIf you have any changes since the version in the previous release (" |
|---|
| 66 |
(format "%d.%d" emacs-major-version emacs-minor-version) |
|---|
| 67 |
"), |
|---|
| 68 |
please send them to me ASAP. |
|---|
| 69 |
|
|---|
| 70 |
Please don't send the whole file. Instead, please send a patch made with |
|---|
| 71 |
`diff -c' that shows precisely the changes you would like me to install. |
|---|
| 72 |
Also please include itemized change log entries for your changes; |
|---|
| 73 |
please use lisp/ChangeLog as a guide for the style and for what kinds |
|---|
| 74 |
of information to include. |
|---|
| 75 |
|
|---|
| 76 |
Thanks.") |
|---|
| 77 |
"*The closing text in a gulp message." |
|---|
| 78 |
:type 'string |
|---|
| 79 |
:group 'gulp) |
|---|
| 80 |
|
|---|
| 81 |
(defun gulp-send-requests (dir &optional time) |
|---|
| 82 |
"Send requests for updates to the authors of Lisp packages in directory DIR. |
|---|
| 83 |
For each maintainer, the message consists of `gulp-request-header', |
|---|
| 84 |
followed by the list of packages (with modification times if the optional |
|---|
| 85 |
prefix argument TIME is non-nil), concluded with `gulp-request-end'. |
|---|
| 86 |
|
|---|
| 87 |
You can't edit the messages, but you can confirm whether to send each one. |
|---|
| 88 |
|
|---|
| 89 |
The list of addresses for which you decided not to send mail |
|---|
| 90 |
is left in the `*gulp*' buffer at the end." |
|---|
| 91 |
(interactive "DRequest updates for Lisp directory: \nP") |
|---|
| 92 |
(save-excursion |
|---|
| 93 |
(set-buffer (get-buffer-create gulp-tmp-buffer)) |
|---|
| 94 |
(let ((m-p-alist (gulp-create-m-p-alist |
|---|
| 95 |
(directory-files dir nil "^[^=].*\\.el$" t) |
|---|
| 96 |
dir)) |
|---|
| 97 |
|
|---|
| 98 |
(buffer-undo-list t) |
|---|
| 99 |
mail-setup-hook msg node) |
|---|
| 100 |
(setq m-p-alist |
|---|
| 101 |
(sort m-p-alist |
|---|
| 102 |
(function (lambda (a b) |
|---|
| 103 |
(string< (car a) (car b)))))) |
|---|
| 104 |
(while (setq node (car m-p-alist)) |
|---|
| 105 |
(setq msg (gulp-create-message (cdr node) time)) |
|---|
| 106 |
(setq mail-setup-hook |
|---|
| 107 |
(lambda () |
|---|
| 108 |
(mail-subject) |
|---|
| 109 |
(insert "It's time for Emacs updates again") |
|---|
| 110 |
(goto-char (point-max)) |
|---|
| 111 |
(insert msg))) |
|---|
| 112 |
(mail nil (car node)) |
|---|
| 113 |
(goto-char (point-min)) |
|---|
| 114 |
(if (y-or-n-p "Send? ") (mail-send) |
|---|
| 115 |
(kill-this-buffer) |
|---|
| 116 |
(set-buffer gulp-tmp-buffer) |
|---|
| 117 |
(insert (format "%s\n\n" node))) |
|---|
| 118 |
(setq m-p-alist (cdr m-p-alist)))) |
|---|
| 119 |
(set-buffer gulp-tmp-buffer) |
|---|
| 120 |
(setq buffer-undo-list nil))) |
|---|
| 121 |
|
|---|
| 122 |
|
|---|
| 123 |
(defun gulp-create-message (rec time) |
|---|
| 124 |
"Return the message string for REC, which is a list like (FILE TIME)." |
|---|
| 125 |
(let (node (str gulp-request-header)) |
|---|
| 126 |
(while (setq node (car rec)) |
|---|
| 127 |
(setq str (concat str "\t" (car node) |
|---|
| 128 |
(if time (concat "\tLast modified:\t" (cdr node))) |
|---|
| 129 |
"\n")) |
|---|
| 130 |
(setq rec (cdr rec))) |
|---|
| 131 |
(concat str gulp-request-end))) |
|---|
| 132 |
|
|---|
| 133 |
|
|---|
| 134 |
(defun gulp-create-m-p-alist (flist dir) |
|---|
| 135 |
"Create the maintainer/package alist for files in FLIST in DIR. |
|---|
| 136 |
That is a list of elements, each of the form (MAINTAINER PACKAGES...)." |
|---|
| 137 |
(save-excursion |
|---|
| 138 |
(let (mplist filen node mnt-tm mnt tm fl-tm) |
|---|
| 139 |
(get-buffer-create gulp-tmp-buffer) |
|---|
| 140 |
(set-buffer gulp-tmp-buffer) |
|---|
| 141 |
(setq buffer-undo-list t) |
|---|
| 142 |
(while flist |
|---|
| 143 |
(setq fl-tm (gulp-maintainer (setq filen (car flist)) dir)) |
|---|
| 144 |
(if (setq tm (cdr fl-tm) mnt (car fl-tm)) |
|---|
| 145 |
(if (setq node (assoc mnt mplist)) |
|---|
| 146 |
(setq mplist (cons (cons mnt (cons (cons filen tm) (cdr node))) |
|---|
| 147 |
(delete node mplist))) |
|---|
| 148 |
(setq mplist (cons (list mnt (cons filen (cdr fl-tm))) mplist)))) |
|---|
| 149 |
(setq flist (cdr flist))) |
|---|
| 150 |
(erase-buffer) |
|---|
| 151 |
mplist))) |
|---|
| 152 |
|
|---|
| 153 |
(defun gulp-maintainer (filenm dir) |
|---|
| 154 |
"Return a list (MAINTAINER TIMESTAMP) for the package FILENM in directory DIR." |
|---|
| 155 |
(save-excursion |
|---|
| 156 |
(let* ((fl (expand-file-name filenm dir)) mnt |
|---|
| 157 |
(timest (format-time-string "%Y-%m-%d %a %T %Z" |
|---|
| 158 |
(elt (file-attributes fl) 5)))) |
|---|
| 159 |
(set-buffer gulp-tmp-buffer) |
|---|
| 160 |
(erase-buffer) |
|---|
| 161 |
(insert-file-contents fl nil 0 gulp-max-len) |
|---|
| 162 |
(goto-char 1) |
|---|
| 163 |
(if (re-search-forward gulp-discard nil t) |
|---|
| 164 |
(setq mnt nil) |
|---|
| 165 |
(goto-char 1) |
|---|
| 166 |
(if (and (re-search-forward "^;+ *Maintainer: \\(.*\\)$" nil t) |
|---|
| 167 |
(> (length (setq mnt (match-string 1))) 0)) |
|---|
| 168 |
() |
|---|
| 169 |
(goto-char 1) |
|---|
| 170 |
(if (re-search-forward "^;+ *Author: \\(.*\\)$" nil t) |
|---|
| 171 |
(setq mnt (match-string 1)))) |
|---|
| 172 |
(if (= (length mnt) 0) (setq mnt nil))) |
|---|
| 173 |
(cons mnt timest)))) |
|---|
| 174 |
|
|---|
| 175 |
(provide 'gulp) |
|---|
| 176 |
|
|---|
| 177 |
|
|---|
| 178 |
|
|---|
| 179 |
|
|---|