aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKim F. Storm2003-01-29 00:13:11 +0000
committerKim F. Storm2003-01-29 00:13:11 +0000
commitf39caf4436726a314bef9c472d456bec027daa23 (patch)
tree426eb1aa22c58d82efb1bbd84339279c9bdfb6fc
parent88c717201f5d8e7f59b4654482250d4ce69cecc3 (diff)
downloademacs-f39caf4436726a314bef9c472d456bec027daa23.tar.gz
emacs-f39caf4436726a314bef9c472d456bec027daa23.zip
New format of AUTHORS file; list each
author name once followed by contributed and changed files. Improve selection of entries to include in list, and generate list of unrecognized entries indicating syntax errors in ChangeLog files. (authors-coding-system): New variable. (authors-many-files): Update doc string. (authors-aliases): Change format. Now one entry with multiple aliases per author. (authors-valid-file-names, authors-renamed-files-alist) (authors-renamed-files-regexps): New variables. (authors-canonical-file-name): New function. Validates that file exists or occurs in one of the above lists. Record unrecognized file names in global authors-invalid-file-names list. (authors-add): Change to record per-change counts. (authors-canonical-author-name): Handle new format of authors-aliases list. (authors-scan-change-log): Rename FILE arg to LOG-FILE. Change doc string to describe new entry format. Only add author entries for valid file names. (authors-print): Replace by authors-add-to-author-list. (authors-add-to-author-list): New function which reorders per-file entries and adds them to global authors-author-list. (authors): Instead of authors-print to insert in *Authors* buffer, use authors-add-to-author-list to reorder the list and then insert result in *Authors* buffer with new format. Generate *Authors Errors* compilation-mode buffer listing unrecognized ChangeLog entries.
-rw-r--r--lisp/emacs-lisp/authors.el421
1 files changed, 295 insertions, 126 deletions
diff --git a/lisp/emacs-lisp/authors.el b/lisp/emacs-lisp/authors.el
index c7c1da5e491..166c16bf86f 100644
--- a/lisp/emacs-lisp/authors.el
+++ b/lisp/emacs-lisp/authors.el
@@ -1,9 +1,9 @@
1;;; authors.el --- utility for maintaining Emacs' AUTHORS file -*-coding: iso-2022-7bit;-*- 1;;; authors.el --- utility for maintaining Emacs' AUTHORS file -*-coding: iso-2022-7bit;-*-
2 2
3;; Copyright (C) 2000 Free Software Foundation, Inc. 3;; Copyright (C) 2000, 2003 Free Software Foundation, Inc.
4 4
5;; Author: Gerd Moellmann <gerd@gnu.org> 5;; Author: Gerd Moellmann <gerd@gnu.org>
6;; Maintainer: FSF 6;; Maintainer: Kim F. Storm <storm@cua.dk>
7;; Keywords: maint 7;; Keywords: maint
8 8
9;; This file is part of GNU Emacs. 9;; This file is part of GNU Emacs.
@@ -30,78 +30,88 @@
30 30
31;;; Code: 31;;; Code:
32 32
33(defvar authors-coding-system 'iso-2022-7bit
34 "Coding system used in the AUTHORS file.")
35
33(defconst authors-many-files 20 36(defconst authors-many-files 20
34 "Maximum number of files for which to print individual information. 37 "Maximum number of files for which to print individual information.
35If an author has modified more files, only a single entry is 38If an author has modified more files, only the names of the most
36printed telling how many files he changed, instead of listing each 39frequently modified files are printed and a count of the additional
37file individually.") 40files.")
38 41
39(defconst authors-aliases 42(defconst authors-aliases
40 '(("eliz" . "Eli Zaretskii") 43 '(
41 ("Richard Stallman" . "Richard M. Stallman") 44 ("Andrew Innes" "Andrw Innes")
42 ("Richard M. Stallman,,," . "Richard M. Stallman") 45 ("Barry A. Warsaw" "Barry A. Warsaw, Century Computing, Inc."
43 ("rms@gnu.org" . "Richard M. Stallman") 46 "Barry A. Warsaw, ITB" "Barry Warsaw")
44 ("NIIBE Yutaka" . "Yutaka NIIBE") 47 ("Bj,Av(Brn Torkelsson" "Bjorn Torkelsson")
45 ("(saw@cebaf.gov)" . "Stephen A. Wood") 48 ("Brian Fox" "Brian J. Fox")
46 ("(pmr@legacy.pajato.com)" . "Paul Reilly") 49 ("Christoph Wedler" "Christoph.Wedler@sap.com")
47 ("(Eric Youngdale at youngdale@v6550c.nrl.navy.mil)" . "Eric Youngdale") 50 ("Daniel Pfeiffer" "<Daniel.Pfeiffer@Informatik.START.db.de>"
48 ("<Daniel.Pfeiffer@Informatik.START.db.de>" . "Daniel Pfeiffer") 51 "<Daniel.Pfeiffer@Informatik.START.dbp.de>")
49 ("<Daniel.Pfeiffer@Informatik.START.dbp.de>" . "Daniel Pfeiffer") 52 ("David Gillespie" "Dave Gillespie")
50 ("(afs@hplb.hpl.hp.com)" . "ignore") 53 ("David K,Ae(Bgedal" "David K..edal")
51 ("<Use-Author-Address-Header@\\[127.1\\]>" . "ignore") 54 ("David M. Koppelman" "David M. Koppelman, Koppel@Ee.Lsu.Edu")
52 ("Code Extracted" . "ignore") 55 ("David M. Smith" "David Smith")
53 ("Fsf" . "ignore") 56 ("Edward M. Reingold" "Ed Reingold" "Edward M Reingold"
54 ("David M. Koppelman, Koppel@Ee.Lsu.Edu" . "David M. Koppelman") 57 "Reingold Edward M")
55 ("jka@ece.cmu.edu" . "Jay K. Adams") 58 ("Eli Zaretskii" "eliz")
56 ("Per Abhiddenware; you can redistribute it and/or modify" . "Per Abrahamsen") 59 ("Eric M. Ludlam" "Eric Ludlam")
57 ("Andrw Innes" . "Andrew Innes") 60 ("Eric S. Raymond" "Eric Raymond")
58 ("Barry Warsaw" . "Barry A. Warsaw") 61 ("Eric Youngdale" "(Eric Youngdale at youngdale@v6550c.nrl.navy.mil)")
59 ("Barry A. Warsaw, Century Computing, Inc." . "Barry A. Warsaw") 62 ("Fran,Ag(Bois Pinard" "Francois Pinard")
60 ("Barry A. Warsaw, ITB" . "Barry A. Warsaw") 63 ("Francesco Potorti" "Francesco Potorti`")
61 ("Ken'ichi Handa" . "Kenichi Handa") 64 ("Frederic Pierresteguy" "Fred Pierresteguy")
62 ("Bob Chassell" . "Robert J. Chassell") 65 ("Geoff Voelker" "voelker")
63 ("SL Baur" . "Steven L. Baur") 66 ("Hallvard B. Furuseth" "Hallvard B Furuseth")
64 ("Steven L Baur" . "Steven L. Baur") 67 (nil "(afs@hplb.hpl.hp.com)")
65 ("eggert" . "Paul Eggert") 68 (nil "<Use-Author-Address-Header@\\[127.1\\]>")
66 ("voelker" . "Geoff Voelker") 69 (nil "Code Extracted")
67 ("rms" . "Richard M. Stallman") 70 (nil "Fsf")
68 ("Edward M Reingold" . "Edward M. Reingold") 71 (nil "ISO-2022-JP")
69 ("Eric Ludlam" . "Eric M. Ludlam") 72 ("Jaeyoun Chung" "Jae-youn Chung" "Jae-you Chung" "Chung Jae-youn")
70 ("Eric Raymond" . "Eric S. Raymond") 73 ("Jan Dj,Ad(Brv" "Jan D." "Jan Djarv")
71 ("Francois Pinard" . "Fran,Ag(Bois Pinard") 74 ("Jay K. Adams" "jka@ece.cmu.edu")
72 ("Fred Pierresteguy" . "Frederic Pierresteguy") 75 ("Jay R. Adams" "Jay Adams")
73 ("Hallvard B Furuseth" . "Hallvard B. Furuseth") 76 ("Jens-Ulrik Holger Petersen" "Jens-Ulrik Petersen")
74 ("ISO-2022-JP" . "ignore") 77 ("Jonathan I. Kamens" "Jonathan Kamens")
75 ("Jens-Ulrik Petersen" . "Jens-Ulrik Holger Petersen") 78 ("Joseph Arceneaux" "Joe Arceneaux")
76 ("Christoph.Wedler@sap.com" . "Christoph Wedler") 79 ("K. Shane Hartman" "Shane Hartman")
77 ("Jonathan Kamens" . "Jonathan I. Kamens") 80 ("Kai Gro,A_(Bjohann" "Kai Grossjohann" "Kai Gro,b_(Bjohann"
78 ("Kim Storm" . "Kim F. Storm") 81 "Kai.Grossjohann@Cs.Uni-Dortmund.De")
79 ("Marcus Daniels" . "Marcus G. Daniels") 82 ("Karl Berry" "K. Berry")
80 ("Michael I Bushnell" . "Michael I. Bushnell") 83 ("Ken Manheimer" "Kenneth Manheimer")
81 ("Michael I. Bushnell, P/Bsg" . "Michael I. Bushnell") 84 ("Kenichi Handa" "Ken'ichi Handa" "Kenichi HANDA")
82 ("Reingold Edward M" . "Edward M. Reingold") 85 ("Kim F. Storm" "Kim Storm")
83 ("Roland B Roberts" . "Roland B. Roberts") 86 ("Marcus G. Daniels" "Marcus Daniels")
84 ("Sam Shteingold" . "Sam Steingold") 87 ("Michael D. Ernst" "Michael Ernst")
85 ("W{\L}Odek Bzyl" . "Wlodzimierz Bzyl") 88 ("Michael I. Bushnell" "Michael I Bushnell" "Michael I. Bushnell, P/Bsg")
86 ("Kenneth Manheimer" . "Ken Manheimer") 89 ("Paul Eggert" "eggert")
87 ("Kenichi HANDA" . "Kenichi Handa") 90 ("Paul Reilly" "(pmr@legacy.pajato.com)")
88 ("Jay Adams" . "Jay R. Adams") 91 ("Pavel Jan,Bm(Bk" "Pavel Jan,Am(Bk Ml.")
89 ("Joe Arceneaux" . "Joseph Arceneaux") 92 ("Per Abrahamsen" "Per Abhiddenware")
90 ("K. Berry" . "Karl Berry") 93 ("Peter S. Galbraith" "Peter S Galbraith")
91 ("Michael Ernst" . "Michael D. Ernst") 94 ("Richard M. Stallman" "Richard M. Stallman,,," "Richard Stallman"
92 ("Dave Gillespie" . "David Gillespie") 95 "rms" "rms@gnu.org")
93 ("Shane Hartman" . "K. Shane Hartman") 96 ("Robert J. Chassell" "Bob Chassell")
94 ("Francesco Potorti`" . "Francesco Potorti") 97 ("Roland B. Roberts" "Roland B Roberts" "Roland Roberts")
95 ("Roland Roberts" . "Roland B. Roberts") 98 ("Rui-Tao Dong" "Rui-Tao Dong ~{6-Hpln~}")
96 ("David Smith" . "David M. Smith") 99 ("Sam Steingold" "Sam Shteingold")
97 ("Jan Djarv" . "Jan Dj,Ad(Brv") 100 ("Stephen A. Wood" "(saw@cebaf.gov)")
98 ("Jan D." . "Jan Dj,Ad(Brv") 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")
99 ) 109 )
100 "Alist of author aliases. 110 "Alist of author aliases.
101 111
102Each entry is of the form (REGEXP . ALIAS). If an author's name 112Each entry is of the form (REALNAME REGEXP...). If an author's name
103matches REGEXP, use ALIAS instead. The special alias \"ignore\" means 113matches one of the REGEXPs, use REALNAME instead.
104ignore that author.") 114If REALNAME is nil, ignore that author.")
105 115
106 116
107(defvar authors-public-domain-files 117(defvar authors-public-domain-files
@@ -129,7 +139,8 @@ listed.")
129 139
130 140
131(defconst authors-fixed-entries 141(defconst authors-fixed-entries
132 '(("Joseph Arceneaux" :wrote "xrdb.c") 142 '(("Richard M. Stallman" :wrote "[The original GNU emacs and numerous files]")
143 ("Joseph Arceneaux" :wrote "xrdb.c")
133 ("Blitz Product Development Corporation" :wrote "ispell.el") 144 ("Blitz Product Development Corporation" :wrote "ispell.el")
134 ("Frank Bresz" :wrote "diff.el") 145 ("Frank Bresz" :wrote "diff.el")
135 ("David M. Brown" :wrote "array.el") 146 ("David M. Brown" :wrote "array.el")
@@ -232,6 +243,92 @@ listed.")
232 "Actions taken from the original, manually (un)maintained AUTHORS file.") 243 "Actions taken from the original, manually (un)maintained AUTHORS file.")
233 244
234 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
250found) 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.
264Elements 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.
286Elements are (REGEXP . REPLACE). If REPLACE is a string, the file
287name matching REGEXP is replaced by REPLACE using `replace-string'.
288Otherwise, 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.
295Checks whether FILE is a valid (existing) file name, has been renamed,
296or is on the list of removed files. Returns the non-diretory part of
297the 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
235(defun authors-add-fixed-entries (table) 332(defun authors-add-fixed-entries (table)
236 "Add actions from `authors-fixed-entries' to TABLE." 333 "Add actions from `authors-fixed-entries' to TABLE."
237 (dolist (entry authors-fixed-entries) 334 (dolist (entry authors-fixed-entries)
@@ -263,11 +360,13 @@ author and what he did in hash table TABLE. See the description of
263 (unless (or (authors-obsolete-file-p file) 360 (unless (or (authors-obsolete-file-p file)
264 (equal author "")) 361 (equal author ""))
265 (let* ((value (gethash author table)) 362 (let* ((value (gethash author table))
266 (entry (assoc file value))) 363 (entry (assoc file value))
364 slot)
267 (if (null entry) 365 (if (null entry)
268 (puthash author (cons (list file action) value) table) 366 (puthash author (cons (list file (cons action 1)) value) table)
269 (unless (memq action entry) 367 (if (setq slot (assoc action (cdr entry)))
270 (nconc entry (list action))))))) 368 (setcdr slot (1+ (cdr slot)))
369 (nconc entry (list (cons action 1))))))))
271 370
272 371
273(defun authors-process-lines (program &rest args) 372(defun authors-process-lines (program &rest args)
@@ -292,37 +391,44 @@ Signal an error if the program returns with a non-zero exit status."
292 "Return a canonicalized form of AUTHOR, an author name. 391 "Return a canonicalized form of AUTHOR, an author name.
293If AUTHOR has an alias, use that. Remove email addresses. Capitalize 392If AUTHOR has an alias, use that. Remove email addresses. Capitalize
294words in the author's name." 393words in the author's name."
295 (let ((aliases authors-aliases)) 394 (let* ((aliases authors-aliases)
395 regexps realname)
296 (while aliases 396 (while aliases
297 (when (string-match (car (car aliases)) author) 397 (setq realname (car (car aliases))
298 (setq author (cdr (car aliases)) 398 regexps (cdr (car aliases))
299 aliases nil)) 399 aliases (cdr aliases))
300 (setq aliases (cdr aliases)))) 400 (while regexps
301 (setq author (replace-regexp-in-string "[ \t]*[(<].*$" "" author)) 401 (if (string-match (car regexps) author)
302 (setq author (replace-regexp-in-string "^[ \t]+" "" author)) 402 (setq author realname
303 (setq author (replace-regexp-in-string "[ \t]+$" "" author)) 403 regexps nil
304 (capitalize author)) 404 aliases nil)
305 405 (setq regexps (cdr regexps))))))
306 406 (when author
307(defun authors-scan-change-log (file table) 407 (setq author (replace-regexp-in-string "[ \t]*[(<].*$" "" author))
308 "Scan change log FILE for author information. 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 (log-file table)
414 "Scan change log LOG-FILE for author information.
309 415
310For each change mentioned in the log, add an entry to hash table TABLE 416For each change mentioned in the log, add an entry to hash table TABLE
311under the author's canonical name. 417under the author's canonical name.
312 418
313Keys of TABLE are author names. Values are alists of entries (FILE 419Keys of TABLE are author names. Values are alists of entries (FILE
314ACTION...). FILE is one file the author worked on. The rest of the 420\(ACTION . COUNT) ...). FILE is one file the author worked on. The
315entry is a list of keyword symbols describing what he did with the 421rest of the entry is a list of keyword symbols describing what he did
316file. 422with the file and the number of each action.
317 423
318:wrote means the author wrote the file 424:wrote means the author wrote the file
319:changed means he changed the file." 425:changed means he changed the file COUNT times."
320 426
321 (let* ((enable-local-variables t) 427 (let* ((enable-local-variables t)
322 (enable-local-eval t) 428 (enable-local-eval t)
323 (existing-buffer (get-file-buffer file)) 429 (existing-buffer (get-file-buffer log-file))
324 (buffer (find-file-noselect file)) 430 (buffer (find-file-noselect log-file))
325 author) 431 author file pos)
326 (save-excursion 432 (save-excursion
327 (set-buffer buffer) 433 (set-buffer buffer)
328 (save-restriction 434 (save-restriction
@@ -330,6 +436,7 @@ file.
330 (goto-char (point-min)) 436 (goto-char (point-min))
331 (while (re-search-forward "^[0-9]\\|^[ \t]+\\* " nil t) 437 (while (re-search-forward "^[0-9]\\|^[ \t]+\\* " nil t)
332 (beginning-of-line) 438 (beginning-of-line)
439 (setq pos (point))
333 (cond ((looking-at "^[0-9]+-[0-9]+-[0-9]+") 440 (cond ((looking-at "^[0-9]+-[0-9]+-[0-9]+")
334 (skip-chars-forward " \t+:0-9-") 441 (skip-chars-forward " \t+:0-9-")
335 (setq author (buffer-substring-no-properties 442 (setq author (buffer-substring-no-properties
@@ -351,9 +458,9 @@ file.
351 (setq line (replace-regexp-in-string "[[(<{].*$" "" line)) 458 (setq line (replace-regexp-in-string "[[(<{].*$" "" line))
352 (setq line (replace-regexp-in-string "," "" line)) 459 (setq line (replace-regexp-in-string "," "" line))
353 (dolist (file (split-string line)) 460 (dolist (file (split-string line))
354 (setq file (file-name-nondirectory file)) 461 (when (setq file (authors-canonical-file-name file log-file pos author))
355 ;(message "%s changed %s" author file) 462 ;;(message "%s changed %s" author file)
356 (authors-add author file :changed table))) 463 (authors-add author file :changed table))))
357 (forward-line 1))))))) 464 (forward-line 1)))))))
358 (unless existing-buffer 465 (unless existing-buffer
359 (kill-buffer buffer)))) 466 (kill-buffer buffer))))
@@ -396,43 +503,62 @@ TABLE is a hash table to add author information to."
396 (setq list (cdr list))) 503 (setq list (cdr list)))
397 public-domain-p)) 504 public-domain-p))
398 505
399 506(defvar authors-author-list)
400(defun authors-print (author changes) 507
401 "Insert information about AUTHOR's work on Emacs into the current buffer. 508(defun authors-add-to-author-list (author changes)
402CHANGES is an alist of entries (FILE ACTION...), as produced by 509 "Insert information about AUTHOR's work on Emacs into `authors-author-list'.
403`authors-scan-change-log'." 510CHANGES is an alist of entries (FILE (ACTION . COUNT) ...), as produced by
404 (unless (equal author "Ignore") 511`authors-scan-change-log'.
405 (let ((nchanged 0)) 512The element added to `authors-author-list' is (AUTHOR WROTE CHANGED), where
406 (dolist (change changes) 513WROTE and CHANGED are lists of the files written and changed by AUTHOR."
407 (let ((actions (cdr change)) 514 (when author
408 (file (car change))) 515 (let ((nchanged 0)
409 (if (memq :wrote actions) 516 wrote-list
410 (progn 517 changed-list)
411 (insert author " (wrote) " file)
412 (when (authors-public-domain-p file)
413 (insert " (public domain)"))
414 (insert "\n"))
415 (setq nchanged (1+ nchanged)))))
416 (if (> nchanged authors-many-files)
417 (insert author " (changed) [more than "
418 (int-to-string authors-many-files) " files]\n")
419 (dolist (change changes) 518 (dolist (change changes)
420 (let ((actions (cdr change)) 519 (let ((actions (cdr change))
421 (file (car change))) 520 (file (car change))
422 (unless (memq :wrote actions) 521 slot)
423 (insert author " (changed) " file "\n")))))))) 522 (if (assq :wrote actions)
424 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)))))
425 548
426(defun authors (root) 549(defun authors (root)
427 "Extract author information from change logs and Lisp source files. 550 "Extract author information from change logs and Lisp source files.
428ROOT is the root directory under which to find the files. If called 551ROOT is the root directory under which to find the files. If called
429interactively, ROOT is read from the minibuffer. Result is a 552interactively, ROOT is read from the minibuffer.
430buffer *Authors* containing authorship information." 553Result is a buffer *Authors* containing authorship information, and a
554buffer *Authors Errors* containing references to unknown files."
431 (interactive "DEmacs source directory: ") 555 (interactive "DEmacs source directory: ")
432 (setq root (expand-file-name root)) 556 (setq root (expand-file-name root))
433 (let ((logs (authors-process-lines "find" root "-name" "ChangeLog*")) 557 (let ((logs (authors-process-lines "find" root "-name" "ChangeLog*"))
434 (table (make-hash-table :test 'equal)) 558 (table (make-hash-table :test 'equal))
435 (buffer-name "*Authors*")) 559 (buffer-name "*Authors*")
560 authors-checked-files-alist
561 authors-invalid-file-names)
436 (authors-add-fixed-entries table) 562 (authors-add-fixed-entries table)
437 (unless (file-exists-p (expand-file-name "src/emacs.c" root)) 563 (unless (file-exists-p (expand-file-name "src/emacs.c" root))
438 (error "Not the root directory of Emacs: %s" root)) 564 (error "Not the root directory of Emacs: %s" root))
@@ -445,13 +571,56 @@ buffer *Authors* containing authorship information."
445 (dolist (file els) 571 (dolist (file els)
446 (message "Scanning %s..." file) 572 (message "Scanning %s..." file)
447 (authors-scan-el file table))) 573 (authors-scan-el file table)))
574 (message "Generating buffer %s..." buffer-name)
448 (set-buffer (get-buffer-create buffer-name)) 575 (set-buffer (get-buffer-create buffer-name))
449 (erase-buffer) 576 (erase-buffer)
450 (set-buffer-file-coding-system 'iso-2022-7bit) 577 (set-buffer-file-coding-system authors-coding-system)
451 (maphash #'authors-print table) 578 (insert
452 (sort-lines nil (point-min) (point-max)) 579"Many people have contributed code included in the Free Software
453 (insert "\nLocal" " Variables:\ncoding: iso-2022-7bit\nEnd:\n") 580Foundation's distribution of GNU Emacs. To show our appreciation for
581their public spirit, we list here in alphabetical order a condensed
582list 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)
454 (unless noninteractive 613 (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))))
455 (pop-to-buffer buffer-name)))) 624 (pop-to-buffer buffer-name))))
456 625
457 626