1 |
;;; authors.el --- utility for maintaining Emacs' AUTHORS file |
;;; authors.el --- utility for maintaining Emacs' AUTHORS file -*-coding: iso-2022-7bit;-*- |
2 |
|
|
3 |
;; Copyright (C) 2000 Free Software Foundation, Inc. |
;; Copyright (C) 2000, 2003 Free Software Foundation, Inc. |
4 |
|
|
5 |
;; Author: Gerd Moellmann <gerd@gnu.org> |
;; Author: Gerd Moellmann <gerd@gnu.org> |
6 |
;; Maintainer: FSF |
;; Maintainer: Kim F. Storm <storm@cua.dk> |
7 |
;; Keywords: maint |
;; Keywords: maint |
8 |
|
|
9 |
;; This file is part of GNU Emacs. |
;; This file is part of GNU Emacs. |
30 |
|
|
31 |
;;; Code: |
;;; Code: |
32 |
|
|
33 |
|
(defvar authors-coding-system 'iso-2022-7bit |
34 |
|
"Coding system used in the AUTHORS file.") |
35 |
|
|
36 |
(defconst authors-many-files 20 |
(defconst authors-many-files 20 |
37 |
"Maximum number of files for which to print individual information. |
"Maximum number of files for which to print individual information. |
38 |
If an author has modified more files, only a single entry is |
If an author has modified more files, only the names of the most |
39 |
printed telling how many files he changed, instead of listing each |
frequently modified files are printed and a count of the additional |
40 |
file individually.") |
files.") |
41 |
|
|
42 |
(defconst authors-aliases |
(defconst authors-aliases |
43 |
'(("eliz" . "Eli Zaretskii") |
'( |
44 |
("Richard Stallman" . "Richard M. Stallman") |
("Andrew Innes" "Andrw Innes") |
45 |
("Richard M. Stallman,,," . "Richard M. Stallman") |
("Barry A. Warsaw" "Barry A. Warsaw, Century Computing, Inc." |
46 |
("rms@gnu.org" . "Richard M. Stallman") |
"Barry A. Warsaw, ITB" "Barry Warsaw") |
47 |
("NIIBE Yutaka" . "Yutaka NIIBE") |
("Bj,Av(Brn Torkelsson" "Bjorn Torkelsson") |
48 |
("(saw@cebaf.gov)" . "Stephen A. Wood") |
("Brian Fox" "Brian J. Fox") |
49 |
("(pmr@legacy.pajato.com)" . "Paul Reilly") |
("Christoph Wedler" "Christoph.Wedler@sap.com") |
50 |
("(Eric Youngdale at youngdale@v6550c.nrl.navy.mil)" . "Eric Youngdale") |
("Daniel Pfeiffer" "<Daniel.Pfeiffer@Informatik.START.db.de>" |
51 |
("<Daniel.Pfeiffer@Informatik.START.db.de>" . "Daniel Pfeiffer") |
"<Daniel.Pfeiffer@Informatik.START.dbp.de>") |
52 |
("<Daniel.Pfeiffer@Informatik.START.dbp.de>" . "Daniel Pfeiffer") |
("David Gillespie" "Dave Gillespie") |
53 |
("(afs@hplb.hpl.hp.com)" . "ignore") |
("David K,Ae(Bgedal" "David K..edal") |
54 |
("<Use-Author-Address-Header@\\[127.1\\]>" . "ignore") |
("David M. Koppelman" "David M. Koppelman, Koppel@Ee.Lsu.Edu") |
55 |
("Code Extracted" . "ignore") |
("David M. Smith" "David Smith") |
56 |
("Fsf" . "ignore") |
("Edward M. Reingold" "Ed Reingold" "Edward M Reingold" |
57 |
("David M. Koppelman, Koppel@Ee.Lsu.Edu" . "David M. Koppelman") |
"Reingold Edward M") |
58 |
("jka@ece.cmu.edu" . "Jay K. Adams") |
("Eli Zaretskii" "eliz") |
59 |
("Per Abhiddenware; you can redistribute it and/or modify" . "Per Abrahamsen") |
("Eric M. Ludlam" "Eric Ludlam") |
60 |
("Andrw Innes" . "Andrew Innes") |
("Eric S. Raymond" "Eric Raymond") |
61 |
("Barry Warsaw" . "Barry A. Warsaw") |
("Eric Youngdale" "(Eric Youngdale at youngdale@v6550c.nrl.navy.mil)") |
62 |
("Barry A. Warsaw, Century Computing, Inc." . "Barry A. Warsaw") |
("Fran,Ag(Bois Pinard" "Francois Pinard") |
63 |
("Barry A. Warsaw, ITB" . "Barry A. Warsaw") |
("Francesco Potorti" "Francesco Potorti`") |
64 |
("Ken'ichi Handa" . "Kenichi Handa") |
("Frederic Pierresteguy" "Fred Pierresteguy") |
65 |
("Bob Chassell" . "Robert J. Chassell") |
("Geoff Voelker" "voelker") |
66 |
("SL Baur" . "Steven L. Baur") |
("Hallvard B. Furuseth" "Hallvard B Furuseth") |
67 |
("Steven L Baur" . "Steven L. Baur") |
(nil "(afs@hplb.hpl.hp.com)") |
68 |
("eggert" . "Paul Eggert") |
(nil "<Use-Author-Address-Header@\\[127.1\\]>") |
69 |
("voelker" . "Geoff Voelker") |
(nil "Code Extracted") |
70 |
("rms" . "Richard M. Stallman") |
(nil "Fsf") |
71 |
("Edward M Reingold" . "Edward M. Reingold") |
(nil "ISO-2022-JP") |
72 |
("Eric Ludlam" . "Eric M. Ludlam") |
("Jaeyoun Chung" "Jae-youn Chung" "Jae-you Chung" "Chung Jae-youn") |
73 |
("Eric Raymond" . "Eric S. Raymond") |
("Jan Dj,Ad(Brv" "Jan D." "Jan Djarv") |
74 |
("Francois Pinard" . "François Pinard") |
("Jay K. Adams" "jka@ece.cmu.edu") |
75 |
("Fred Pierresteguy" . "Frederic Pierresteguy") |
("Jay R. Adams" "Jay Adams") |
76 |
("Hallvard B Furuseth" . "Hallvard B. Furuseth") |
("Jens-Ulrik Holger Petersen" "Jens-Ulrik Petersen") |
77 |
("ISO-2022-JP" . "ignore") |
("Jonathan I. Kamens" "Jonathan Kamens") |
78 |
("Jens-Ulrik Petersen" . "Jens-Ulrik Holger Petersen") |
("Joseph Arceneaux" "Joe Arceneaux") |
79 |
("Christoph.Wedler@sap.com" . "Christoph Wedler") |
("K. Shane Hartman" "Shane Hartman") |
80 |
("Jonathan Kamens" . "Jonathan I. Kamens") |
("Kai Gro,A_(Bjohann" "Kai Grossjohann" "Kai Gro,b_(Bjohann" |
81 |
("Kim Storm" . "Kim F. Storm") |
"Kai.Grossjohann@Cs.Uni-Dortmund.De") |
82 |
("Marcus Daniels" . "Marcus G. Daniels") |
("Karl Berry" "K. Berry") |
83 |
("Michael I Bushnell" . "Michael I. Bushnell") |
("Ken Manheimer" "Kenneth Manheimer") |
84 |
("Michael I. Bushnell, P/Bsg" . "Michael I. Bushnell") |
("Kenichi Handa" "Ken'ichi Handa" "Kenichi HANDA") |
85 |
("Reingold Edward M" . "Edward M. Reingold") |
("Kim F. Storm" "Kim Storm") |
86 |
("Roland B Roberts" . "Roland B. Roberts") |
("Marcus G. Daniels" "Marcus Daniels") |
87 |
("Sam Shteingold" . "Sam Steingold") |
("Michael D. Ernst" "Michael Ernst") |
88 |
("W{\L}Odek Bzyl" . "Wlodzimierz Bzyl") |
("Michael I. Bushnell" "Michael I Bushnell" "Michael I. Bushnell, P/Bsg") |
89 |
("Kenneth Manheimer" . "Ken Manheimer") |
("Paul Eggert" "eggert") |
90 |
("Kenichi HANDA" . "Kenichi Handa") |
("Paul Reilly" "(pmr@legacy.pajato.com)") |
91 |
("Jay Adams" . "Jay R. Adams") |
("Pavel Jan,Bm(Bk" "Pavel Jan,Am(Bk Ml.") |
92 |
("Joe Arceneaux" . "Josef Arceneaux") |
("Per Abrahamsen" "Per Abhiddenware") |
93 |
("K. Berry" . "Karl Berry") |
("Peter S. Galbraith" "Peter S Galbraith") |
94 |
("Michael Ernst" . "Michael D. Ernst") |
("Richard M. Stallman" "Richard M. Stallman,,," "Richard Stallman" |
95 |
("Dave Gillespie" . "David Gillespie") |
"rms" "rms@gnu.org") |
96 |
("Shane Hartman" . "K. Shane Hartman") |
("Robert J. Chassell" "Bob Chassell") |
97 |
("Francesco Potorti`" . "Francesco Potorti") |
("Roland B. Roberts" "Roland B Roberts" "Roland Roberts") |
98 |
("Roland Roberts" . "Roland B. Roberts") |
("Rui-Tao Dong" "Rui-Tao Dong ~{6-Hpln~}") |
99 |
("David Smith" . "David M. Smith") |
("Sam Steingold" "Sam Shteingold") |
100 |
|
("Stephen A. Wood" "(saw@cebaf.gov)") |
101 |
|
("Steven L. Baur" "SL Baur" "Steven L Baur") |
102 |
|
("Takaaki Ota" "Tak Ota") |
103 |
|
("Torbj,Av(Brn Axelsson" "Torbjvrn Axelsson") |
104 |
|
("Torbj,Av(Brn Einarsson" "Torbj.*rn Einarsson") |
105 |
|
("Toru Tomabechi" "Toru Tomabechi,") |
106 |
|
("Vincent Del Vecchio" "Vince Del Vecchio") |
107 |
|
("Wlodzimierz Bzyl" "W.*dek Bzyl") |
108 |
|
("Yutaka NIIBE" "NIIBE Yutaka") |
109 |
) |
) |
110 |
"Alist of author aliases. |
"Alist of author aliases. |
111 |
|
|
112 |
Each entry is of the form (REGEXP . ALIAS). If an author's name |
Each entry is of the form (REALNAME REGEXP...). If an author's name |
113 |
matches REGEXP, use ALIAS instead. The special alias \"ignore\" means |
matches one of the REGEXPs, use REALNAME instead. |
114 |
ignore that author.") |
If REALNAME is nil, ignore that author.") |
115 |
|
|
116 |
|
|
117 |
(defvar authors-public-domain-files |
(defvar authors-public-domain-files |
139 |
|
|
140 |
|
|
141 |
(defconst authors-fixed-entries |
(defconst authors-fixed-entries |
142 |
'(("Joe Arceneax" :wrote "xrdb.c") |
'(("Richard M. Stallman" :wrote "[The original GNU emacs and numerous files]") |
143 |
|
("Joseph Arceneaux" :wrote "xrdb.c") |
144 |
("Blitz Product Development Corporation" :wrote "ispell.el") |
("Blitz Product Development Corporation" :wrote "ispell.el") |
145 |
("Frank Bresz" :wrote "diff.el") |
("Frank Bresz" :wrote "diff.el") |
146 |
("David M. Brown" :wrote "array.el") |
("David M. Brown" :wrote "array.el") |
243 |
"Actions taken from the original, manually (un)maintained AUTHORS file.") |
"Actions taken from the original, manually (un)maintained AUTHORS file.") |
244 |
|
|
245 |
|
|
246 |
|
(defconst authors-valid-file-names |
247 |
|
'("aclocal.m4" |
248 |
|
"makedist.bat") |
249 |
|
"File names which are valid, but no longer exists (or cannot be |
250 |
|
found) in the repository.") |
251 |
|
|
252 |
|
(defconst authors-renamed-files-alist |
253 |
|
'(("nt.c" . "w32.c") ("nt.h" . "w32.h") |
254 |
|
("ntheap.c" . "w32heap.c") ("ntheap.h" . "w32heap.h") |
255 |
|
("ntinevt.c" . "w32inevt.c") ("ntinevt.h" . "w32inevt.h") |
256 |
|
("ntproc.c" . "w32proc.c") |
257 |
|
("w32console.c" . "w32term.c") |
258 |
|
("unexnt.c" . "unexw32.c") |
259 |
|
("s/windowsnt.h" . "s/ms-w32.h") |
260 |
|
("config.emacs" . "configure") |
261 |
|
("GETTING.GNU.SOFTWARE" . "FTP") |
262 |
|
) |
263 |
|
"Alist of files which have been renamed during their lifetime. |
264 |
|
Elements are (OLDNAME . NEWNAME).") |
265 |
|
|
266 |
|
(defconst authors-renamed-files-regexps |
267 |
|
'(("^m/m-\\(.*\\.h\\)$" . "m/\\1") |
268 |
|
("^m-\\(.*\\.h\\)$" . "\\1") |
269 |
|
("^s/s-\\(.*\\.h\\)$" . "s/\\1") |
270 |
|
("^s-\\(.*\\.h\\)$" . "\\1") |
271 |
|
("^s/[-.a-zA-Z0-9_]+\\.h$" . t) |
272 |
|
("\\(.*\\)\\.cmd$" . "\\1.bat") |
273 |
|
("\\.bat$" . t) |
274 |
|
("\\.[ch]$" . t) |
275 |
|
("\\.el$" . t) |
276 |
|
("\\.ps$" . t) |
277 |
|
("\\.texi?$" . t) |
278 |
|
("\\.texinfo$" . t) |
279 |
|
("\\.xml?$" . t) |
280 |
|
("\\.x[pb]m$" . t) |
281 |
|
("\\.[xp]bm$" . t) |
282 |
|
("^paths\\." . t) |
283 |
|
("^install\\." . t) |
284 |
|
) |
285 |
|
"List regexps and rewriting rules for renamed files. |
286 |
|
Elements are (REGEXP . REPLACE). If REPLACE is a string, the file |
287 |
|
name matching REGEXP is replaced by REPLACE using `replace-string'. |
288 |
|
Otherwise, the file name is accepted as is.") |
289 |
|
|
290 |
|
(defvar authors-checked-files-alist) |
291 |
|
(defvar authors-invalid-file-names) |
292 |
|
|
293 |
|
(defun authors-canonical-file-name (file log-file pos author) |
294 |
|
"Return canonical file name for FILE found in LOG-FILE at POS for AUTHOR. |
295 |
|
Checks whether FILE is a valid (existing) file name, has been renamed, |
296 |
|
or is on the list of removed files. Returns the non-diretory part of |
297 |
|
the file name." |
298 |
|
(let ((entry (assoc file authors-checked-files-alist)) |
299 |
|
relname |
300 |
|
valid) |
301 |
|
(if entry |
302 |
|
(cdr entry) |
303 |
|
(setq relname (file-name-nondirectory file)) |
304 |
|
(if (or (member relname authors-valid-file-names) |
305 |
|
(file-exists-p file) |
306 |
|
(file-exists-p relname) |
307 |
|
(file-exists-p (concat "etc/" relname))) |
308 |
|
(setq valid relname) |
309 |
|
(setq valid (assoc file authors-renamed-files-alist)) |
310 |
|
(if valid |
311 |
|
(setq valid (cdr valid)) |
312 |
|
(let ((rules authors-renamed-files-regexps)) |
313 |
|
(while rules |
314 |
|
(if (string-match (car (car rules)) file) |
315 |
|
(setq valid (if (stringp (cdr (car rules))) |
316 |
|
(file-name-nondirectory |
317 |
|
(replace-match (cdr (car rules)) t nil file)) |
318 |
|
relname) |
319 |
|
rules nil)) |
320 |
|
(setq rules (cdr rules)))))) |
321 |
|
(setq authors-checked-files-alist |
322 |
|
(cons (cons file valid) authors-checked-files-alist)) |
323 |
|
(unless valid |
324 |
|
(setq authors-invalid-file-names |
325 |
|
(cons (format "%s:%d: unrecognized `%s' for %s" |
326 |
|
log-file |
327 |
|
(1+ (count-lines (point-min) pos)) |
328 |
|
file author) |
329 |
|
authors-invalid-file-names))) |
330 |
|
valid))) |
331 |
|
|
332 |
(defun authors-add-fixed-entries (table) |
(defun authors-add-fixed-entries (table) |
333 |
"Add actions from `authors-fixed-entries' to TABLE." |
"Add actions from `authors-fixed-entries' to TABLE." |
334 |
(dolist (entry authors-fixed-entries) |
(dolist (entry authors-fixed-entries) |
339 |
(setq action item) |
(setq action item) |
340 |
(authors-add author item action table)))))) |
(authors-add author item action table)))))) |
341 |
|
|
342 |
|
|
343 |
(defun authors-obsolete-file-p (file) |
(defun authors-obsolete-file-p (file) |
344 |
"Return non-nil if FILE is obsolete. |
"Return non-nil if FILE is obsolete. |
345 |
FILE is considered obsolete if it matches on of the regular expressions |
FILE is considered obsolete if it matches one of the regular expressions |
346 |
from `authors-obsolete-files-regexps'." |
from `authors-obsolete-files-regexps'." |
347 |
(let (obsolete-p |
(let (obsolete-p |
348 |
(regexps authors-obsolete-files-regexps)) |
(regexps authors-obsolete-files-regexps)) |
360 |
(unless (or (authors-obsolete-file-p file) |
(unless (or (authors-obsolete-file-p file) |
361 |
(equal author "")) |
(equal author "")) |
362 |
(let* ((value (gethash author table)) |
(let* ((value (gethash author table)) |
363 |
(entry (assoc file value))) |
(entry (assoc file value)) |
364 |
|
slot) |
365 |
(if (null entry) |
(if (null entry) |
366 |
(puthash author (cons (list file action) value) table) |
(puthash author (cons (list file (cons action 1)) value) table) |
367 |
(unless (memq action entry) |
(if (setq slot (assoc action (cdr entry))) |
368 |
(nconc entry (list action))))))) |
(setcdr slot (1+ (cdr slot))) |
369 |
|
(nconc entry (list (cons action 1)))))))) |
370 |
|
|
371 |
|
|
372 |
(defun authors-process-lines (program &rest args) |
(defun authors-process-lines (program &rest args) |
391 |
"Return a canonicalized form of AUTHOR, an author name. |
"Return a canonicalized form of AUTHOR, an author name. |
392 |
If AUTHOR has an alias, use that. Remove email addresses. Capitalize |
If AUTHOR has an alias, use that. Remove email addresses. Capitalize |
393 |
words in the author's name." |
words in the author's name." |
394 |
(let ((aliases authors-aliases)) |
(let* ((aliases authors-aliases) |
395 |
|
regexps realname) |
396 |
(while aliases |
(while aliases |
397 |
(when (string-match (car (car aliases)) author) |
(setq realname (car (car aliases)) |
398 |
(setq author (cdr (car aliases)) |
regexps (cdr (car aliases)) |
399 |
aliases nil)) |
aliases (cdr aliases)) |
400 |
(setq aliases (cdr aliases)))) |
(while regexps |
401 |
(setq author (replace-regexp-in-string "[ \t]*[(<].*$" "" author)) |
(if (string-match (car regexps) author) |
402 |
(setq author (replace-regexp-in-string "^[ \t]+" "" author)) |
(setq author realname |
403 |
(setq author (replace-regexp-in-string "[ \t]+$" "" author)) |
regexps nil |
404 |
(capitalize author)) |
aliases nil) |
405 |
|
(setq regexps (cdr regexps)))))) |
406 |
|
(when author |
407 |
|
(setq author (replace-regexp-in-string "[ \t]*[(<].*$" "" author)) |
408 |
|
(setq author (replace-regexp-in-string "^[ \t]+" "" author)) |
409 |
|
(setq author (replace-regexp-in-string "[ \t]+$" "" author)) |
410 |
|
(capitalize author))) |
411 |
|
|
412 |
|
|
413 |
(defun authors-scan-change-log (file table) |
(defun authors-scan-change-log (log-file table) |
414 |
"Scan change log FILE for author information. |
"Scan change log LOG-FILE for author information. |
415 |
|
|
416 |
For each change mentioned in the log, add an entry to hash table TABLE |
For each change mentioned in the log, add an entry to hash table TABLE |
417 |
under the author's canonical name. |
under the author's canonical name. |
418 |
|
|
419 |
Keys of TABLE are author names. Values are alists of entries (FILE |
Keys of TABLE are author names. Values are alists of entries (FILE |
420 |
ACTION...). FILE is one file the author worked on. The rest of the |
\(ACTION . COUNT) ...). FILE is one file the author worked on. The |
421 |
entry is a list of keyword symbols describing what he did with the |
rest of the entry is a list of keyword symbols describing what he did |
422 |
file. |
with the file and the number of each action. |
423 |
|
|
424 |
:wrote means the author wrote the file |
:wrote means the author wrote the file |
425 |
:changed means he changed the file." |
:changed means he changed the file COUNT times." |
426 |
|
|
427 |
(let* ((enable-local-variables t) |
(let* ((enable-local-variables t) |
428 |
(enable-local-eval t) |
(enable-local-eval t) |
429 |
(existing-buffer (get-file-buffer file)) |
(existing-buffer (get-file-buffer log-file)) |
430 |
(buffer (find-file-noselect file)) |
(buffer (find-file-noselect log-file)) |
431 |
author) |
author file pos) |
432 |
(save-excursion |
(save-excursion |
433 |
(set-buffer buffer) |
(set-buffer buffer) |
434 |
(save-restriction |
(save-restriction |
436 |
(goto-char (point-min)) |
(goto-char (point-min)) |
437 |
(while (re-search-forward "^[0-9]\\|^[ \t]+\\* " nil t) |
(while (re-search-forward "^[0-9]\\|^[ \t]+\\* " nil t) |
438 |
(beginning-of-line) |
(beginning-of-line) |
439 |
|
(setq pos (point)) |
440 |
(cond ((looking-at "^[0-9]+-[0-9]+-[0-9]+") |
(cond ((looking-at "^[0-9]+-[0-9]+-[0-9]+") |
441 |
(skip-chars-forward " \t+:0-9-") |
(skip-chars-forward " \t+:0-9-") |
442 |
(setq author (buffer-substring-no-properties |
(setq author (buffer-substring-no-properties |
458 |
(setq line (replace-regexp-in-string "[[(<{].*$" "" line)) |
(setq line (replace-regexp-in-string "[[(<{].*$" "" line)) |
459 |
(setq line (replace-regexp-in-string "," "" line)) |
(setq line (replace-regexp-in-string "," "" line)) |
460 |
(dolist (file (split-string line)) |
(dolist (file (split-string line)) |
461 |
(setq file (file-name-nondirectory file)) |
(when (setq file (authors-canonical-file-name file log-file pos author)) |
462 |
;(message "%s changed %s" author file) |
;;(message "%s changed %s" author file) |
463 |
(authors-add author file :changed table))) |
(authors-add author file :changed table)))) |
464 |
(forward-line 1))))))) |
(forward-line 1))))))) |
465 |
(unless existing-buffer |
(unless existing-buffer |
466 |
(kill-buffer buffer)))) |
(kill-buffer buffer)))) |
503 |
(setq list (cdr list))) |
(setq list (cdr list))) |
504 |
public-domain-p)) |
public-domain-p)) |
505 |
|
|
506 |
|
(defvar authors-author-list) |
507 |
|
|
508 |
(defun authors-print (author changes) |
(defun authors-add-to-author-list (author changes) |
509 |
"Insert information about AUTHOR's work on Emacs into the current buffer. |
"Insert information about AUTHOR's work on Emacs into `authors-author-list'. |
510 |
CHANGES is an alist of entries (FILE ACTION...), as produced by |
CHANGES is an alist of entries (FILE (ACTION . COUNT) ...), as produced by |
511 |
`authors-scan-change-log'." |
`authors-scan-change-log'. |
512 |
(unless (equal author "Ignore") |
The element added to `authors-author-list' is (AUTHOR WROTE CHANGED), where |
513 |
(let ((nchanged 0)) |
WROTE and CHANGED are lists of the files written and changed by AUTHOR." |
514 |
(dolist (change changes) |
(when author |
515 |
(let ((actions (cdr change)) |
(let ((nchanged 0) |
516 |
(file (car change))) |
wrote-list |
517 |
(if (memq :wrote actions) |
changed-list) |
|
(progn |
|
|
(insert author " (wrote) " file) |
|
|
(when (authors-public-domain-p file) |
|
|
(insert " (public domain)")) |
|
|
(insert "\n")) |
|
|
(setq nchanged (1+ nchanged))))) |
|
|
(if (> nchanged authors-many-files) |
|
|
(insert author " (changed) [more than " |
|
|
(int-to-string authors-many-files) " files]\n") |
|
518 |
(dolist (change changes) |
(dolist (change changes) |
519 |
(let ((actions (cdr change)) |
(let ((actions (cdr change)) |
520 |
(file (car change))) |
(file (car change)) |
521 |
(unless (memq :wrote actions) |
slot) |
522 |
(insert author " (changed) " file "\n")))))))) |
(if (assq :wrote actions) |
523 |
|
(setq wrote-list |
524 |
|
(cons |
525 |
|
(if (authors-public-domain-p file) |
526 |
|
(concat file " (public domain)") |
527 |
|
file) |
528 |
|
wrote-list)) |
529 |
|
(setq changed-list |
530 |
|
(cons (cons file (cdr (assq :changed actions))) |
531 |
|
changed-list))))) |
532 |
|
(if wrote-list |
533 |
|
(setq wrote-list (sort wrote-list 'string-lessp))) |
534 |
|
(when changed-list |
535 |
|
(setq changed-list (sort changed-list |
536 |
|
(lambda (a b) |
537 |
|
(if (= (cdr a) (cdr b)) |
538 |
|
(string-lessp (car a) (car b)) |
539 |
|
(> (cdr a) (cdr b)))))) |
540 |
|
(setq nchanged (length changed-list)) |
541 |
|
(setq changed-list (mapcar 'car changed-list))) |
542 |
|
(if (> (- nchanged authors-many-files) 2) |
543 |
|
(setcdr (nthcdr authors-many-files changed-list) |
544 |
|
(list (format "and %d other files" (- nchanged authors-many-files))))) |
545 |
|
(setq authors-author-list |
546 |
|
(cons (list author wrote-list changed-list) |
547 |
|
authors-author-list))))) |
548 |
|
|
549 |
(defun authors (root) |
(defun authors (root) |
550 |
"Extract author information from change logs and Lisp source files. |
"Extract author information from change logs and Lisp source files. |
551 |
ROOT is the root directory under which to find the files. If called |
ROOT is the root directory under which to find the files. If called |
552 |
interactively, ROOT is read from the minibuffer. Result is a |
interactively, ROOT is read from the minibuffer. |
553 |
buffer *Authors* containing authorship information." |
Result is a buffer *Authors* containing authorship information, and a |
554 |
|
buffer *Authors Errors* containing references to unknown files." |
555 |
(interactive "DEmacs source directory: ") |
(interactive "DEmacs source directory: ") |
556 |
(setq root (expand-file-name root)) |
(setq root (expand-file-name root)) |
557 |
(let ((logs (authors-process-lines "find" root "-name" "ChangeLog*")) |
(let ((logs (authors-process-lines "find" root "-name" "ChangeLog*")) |
558 |
(table (make-hash-table :test 'equal)) |
(table (make-hash-table :test 'equal)) |
559 |
(buffer-name "*Authors*")) |
(buffer-name "*Authors*") |
560 |
|
authors-checked-files-alist |
561 |
|
authors-invalid-file-names) |
562 |
(authors-add-fixed-entries table) |
(authors-add-fixed-entries table) |
563 |
(unless (file-exists-p (expand-file-name "src/emacs.c" root)) |
(unless (file-exists-p (expand-file-name "src/emacs.c" root)) |
564 |
(error "Not the root directory of Emacs: %s" root)) |
(error "Not the root directory of Emacs: %s" root)) |
571 |
(dolist (file els) |
(dolist (file els) |
572 |
(message "Scanning %s..." file) |
(message "Scanning %s..." file) |
573 |
(authors-scan-el file table))) |
(authors-scan-el file table))) |
574 |
|
(message "Generating buffer %s..." buffer-name) |
575 |
(set-buffer (get-buffer-create buffer-name)) |
(set-buffer (get-buffer-create buffer-name)) |
576 |
(erase-buffer) |
(erase-buffer) |
577 |
(set-buffer-file-coding-system 'iso-2022-7bit) |
(set-buffer-file-coding-system authors-coding-system) |
578 |
(maphash #'authors-print table) |
(insert |
579 |
(sort-lines nil (point-min) (point-max)) |
"Many people have contributed code included in the Free Software |
580 |
(insert "\nLocal" " Variables:\ncoding: iso-2022-7bit\nEnd:\n") |
Foundation's distribution of GNU Emacs. To show our appreciation for |
581 |
|
their public spirit, we list here in alphabetical order a condensed |
582 |
|
list of their contributions.\n") |
583 |
|
(let (authors-author-list a) |
584 |
|
(maphash #'authors-add-to-author-list table) |
585 |
|
(setq authors-author-list |
586 |
|
(sort authors-author-list |
587 |
|
(lambda (a b) (string-lessp (car a) (car b))))) |
588 |
|
(dolist (a authors-author-list) |
589 |
|
(let ((author (car a)) |
590 |
|
(wrote (nth 1 a)) |
591 |
|
(changed (nth 2 a)) |
592 |
|
file) |
593 |
|
(insert "\n" author ": ") |
594 |
|
(when wrote |
595 |
|
(insert "wrote") |
596 |
|
(dolist (file wrote) |
597 |
|
(if (> (+ (current-column) (length file)) 72) |
598 |
|
(insert "\n ")) |
599 |
|
(insert " " file)) |
600 |
|
(insert "\n")) |
601 |
|
(when changed |
602 |
|
(if wrote |
603 |
|
(insert "and ")) |
604 |
|
(insert "changed") |
605 |
|
(dolist (file changed) |
606 |
|
(if (> (+ (current-column) (length file)) 72) |
607 |
|
(insert "\n ")) |
608 |
|
(insert " " file)) |
609 |
|
(insert "\n"))))) |
610 |
|
(insert "\nLocal" " Variables:\ncoding: " |
611 |
|
(symbol-name authors-coding-system) "\nEnd:\n") |
612 |
|
(message "Generating buffer %s... done" buffer-name) |
613 |
(unless noninteractive |
(unless noninteractive |
614 |
|
(when authors-invalid-file-names |
615 |
|
(with-current-buffer (get-buffer-create "*Authors Errors*") |
616 |
|
(erase-buffer) |
617 |
|
(set-buffer-file-coding-system authors-coding-system) |
618 |
|
(insert "Unrecognized file entries found:\n\n") |
619 |
|
(mapcar (lambda (f) (if (not (string-match "^[A-Za-z]+$" f)) (insert f "\n"))) |
620 |
|
(sort authors-invalid-file-names 'string-lessp)) |
621 |
|
(goto-char (point-min)) |
622 |
|
(compilation-mode) |
623 |
|
(message "Errors were found. See buffer %s" (buffer-name)))) |
624 |
(pop-to-buffer buffer-name)))) |
(pop-to-buffer buffer-name)))) |
625 |
|
|
626 |
|
|