Mercurial > emacs
annotate lisp/emacs-lisp/shadow.el @ 42811:cf0c0ef57504
*** empty log message ***
| author | Jason Rumney <jasonr@gnu.org> |
|---|---|
| date | Thu, 17 Jan 2002 19:29:24 +0000 |
| parents | b174db545cfd |
| children | 621fbfd0bf87 |
| rev | line source |
|---|---|
|
38436
b174db545cfd
Some fixes to follow coding conventions.
Pavel Jan?k <Pavel@Janik.cz>
parents:
22170
diff
changeset
|
1 ;;; shadow.el --- locate Emacs Lisp file shadowings |
| 14058 | 2 |
| 3 ;; Copyright (C) 1995 Free Software Foundation, Inc. | |
| 4 | |
| 5 ;; Author: Terry Jones <terry@santafe.edu> | |
| 6 ;; Keywords: lisp | |
| 7 ;; Created: 15 December 1995 | |
| 8 | |
| 9 ;; This file is part of GNU Emacs. | |
| 10 | |
| 11 ;; GNU Emacs is free software; you can redistribute it and/or modify | |
| 12 ;; it under the terms of the GNU General Public License as published by | |
| 13 ;; the Free Software Foundation; either version 2, or (at your option) | |
| 14 ;; any later version. | |
| 15 | |
| 16 ;; GNU Emacs is distributed in the hope that it will be useful, | |
| 17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 19 ;; GNU General Public License for more details. | |
| 20 | |
| 21 ;; You should have received a copy of the GNU General Public License | |
| 14169 | 22 ;; along with GNU Emacs; see the file COPYING. If not, write to the |
| 23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
| 24 ;; Boston, MA 02111-1307, USA. | |
| 14058 | 25 |
| 26 ;;; Commentary: | |
| 14169 | 27 |
| 14058 | 28 ;; The functions in this file detect (`find-emacs-lisp-shadows') |
| 29 ;; and display (`list-load-path-shadows') potential load-path | |
| 30 ;; problems that arise when Emacs Lisp files "shadow" each other. | |
| 31 ;; | |
| 32 ;; For example, a file XXX.el early in one's load-path will shadow | |
| 33 ;; a file with the same name in a later load-path directory. When | |
| 34 ;; this is unintentional, it may result in problems that could have | |
| 35 ;; been easily avoided. This occurs often (to me) when installing a | |
| 36 ;; new version of emacs and something in the site-lisp directory | |
| 37 ;; has been updated and added to the emacs distribution. The old | |
| 38 ;; version, now outdated, shadows the new one. This is obviously | |
| 39 ;; undesirable. | |
| 40 ;; | |
| 41 ;; The `list-load-path-shadows' function was run when you installed | |
| 42 ;; this version of emacs. To run it by hand in emacs: | |
| 43 ;; | |
| 44 ;; M-x load-library RET shadow RET | |
| 45 ;; M-x list-load-path-shadows | |
| 46 ;; | |
| 47 ;; or run it non-interactively via: | |
| 48 ;; | |
| 49 ;; emacs -batch -l shadow.el -f list-load-path-shadows | |
| 50 ;; | |
| 51 ;; Thanks to Francesco Potorti` <pot@cnuce.cnr.it> for suggestions, | |
| 52 ;; rewritings & speedups. | |
| 53 | |
| 54 ;;; Code: | |
| 55 | |
| 21365 | 56 (defgroup shadow nil |
| 57 "Locate Emacs Lisp file shadowings." | |
| 58 :prefix "shadows-" | |
| 59 :group 'lisp) | |
| 60 | |
| 61 (defcustom shadows-compare-text-p nil | |
| 19982 | 62 "*If non-nil, then shadowing files are reported only if their text differs. |
| 21365 | 63 This is slower, but filters out some innocuous shadowing." |
| 64 :type 'boolean | |
| 65 :group 'shadow) | |
| 19982 | 66 |
| 14058 | 67 (defun find-emacs-lisp-shadows (&optional path) |
| 68 "Return a list of Emacs Lisp files that create shadows. | |
| 69 This function does the work for `list-load-path-shadows'. | |
| 70 | |
| 71 We traverse PATH looking for shadows, and return a \(possibly empty\) | |
| 72 even-length list of files. A file in this list at position 2i shadows | |
| 73 the file in position 2i+1. Emacs Lisp file suffixes \(.el and .elc\) | |
| 74 are stripped from the file names in the list. | |
| 75 | |
| 76 See the documentation for `list-load-path-shadows' for further information." | |
| 77 | |
| 78 (or path (setq path load-path)) | |
| 79 | |
| 80 (let (true-names ; List of dirs considered. | |
| 81 shadows ; List of shadowings, to be returned. | |
| 82 files ; File names ever seen, with dirs. | |
| 83 dir ; The dir being currently scanned. | |
| 84 curr-files ; This dir's Emacs Lisp files. | |
| 85 orig-dir ; Where the file was first seen. | |
| 86 files-seen-this-dir ; Files seen so far in this dir. | |
| 87 file) ; The current file. | |
| 88 | |
| 89 | |
| 90 (while path | |
| 91 | |
| 19982 | 92 (setq dir (directory-file-name (file-truename (or (car path) ".")))) |
| 14058 | 93 (if (member dir true-names) |
| 94 ;; We have already considered this PATH redundant directory. | |
| 95 ;; Show the redundancy if we are interactiver, unless the PATH | |
| 96 ;; dir is nil or "." (these redundant directories are just a | |
| 97 ;; result of the current working directory, and are therefore | |
| 98 ;; not always redundant). | |
| 99 (or noninteractive | |
| 100 (and (car path) | |
| 101 (not (string= (car path) ".")) | |
|
15736
73a325c414a5
(list-load-path-shadows): Fix ambiguous wording.
Karl Heuer <kwzh@gnu.org>
parents:
14348
diff
changeset
|
102 (message "Ignoring redundant directory %s" (car path)))) |
| 19982 | 103 |
| 14058 | 104 (setq true-names (append true-names (list dir))) |
| 19982 | 105 (setq dir (directory-file-name (or (car path) "."))) |
| 14058 | 106 (setq curr-files (if (file-accessible-directory-p dir) |
| 19982 | 107 (directory-files dir nil ".\\.elc?$" t))) |
| 14058 | 108 (and curr-files |
| 109 (not noninteractive) | |
|
15736
73a325c414a5
(list-load-path-shadows): Fix ambiguous wording.
Karl Heuer <kwzh@gnu.org>
parents:
14348
diff
changeset
|
110 (message "Checking %d files in %s..." (length curr-files) dir)) |
| 19982 | 111 |
| 14058 | 112 (setq files-seen-this-dir nil) |
| 113 | |
| 114 (while curr-files | |
| 115 | |
| 116 (setq file (car curr-files)) | |
| 117 (setq file (substring | |
| 118 file 0 (if (string= (substring file -1) "c") -4 -3))) | |
| 119 | |
|
19226
c160218de690
(find-emacs-lisp-shadows): Don't mention `subdirs.el'.
Richard M. Stallman <rms@gnu.org>
parents:
15756
diff
changeset
|
120 ;; FILE now contains the current file name, with no suffix. |
|
c160218de690
(find-emacs-lisp-shadows): Don't mention `subdirs.el'.
Richard M. Stallman <rms@gnu.org>
parents:
15756
diff
changeset
|
121 (unless (or (member file files-seen-this-dir) |
|
c160218de690
(find-emacs-lisp-shadows): Don't mention `subdirs.el'.
Richard M. Stallman <rms@gnu.org>
parents:
15756
diff
changeset
|
122 ;; Ignore these files. |
|
c160218de690
(find-emacs-lisp-shadows): Don't mention `subdirs.el'.
Richard M. Stallman <rms@gnu.org>
parents:
15756
diff
changeset
|
123 (member file '("subdirs"))) |
| 14058 | 124 ;; File has not been seen yet in this directory. |
| 125 ;; This test prevents us declaring that XXX.el shadows | |
| 126 ;; XXX.elc (or vice-versa) when they are in the same directory. | |
| 127 (setq files-seen-this-dir (cons file files-seen-this-dir)) | |
| 128 | |
| 129 (if (setq orig-dir (assoc file files)) | |
| 130 ;; This file was seen before, we have a shadowing. | |
| 19982 | 131 ;; Report it unless the files are identical. |
| 132 (let ((base1 (concat (cdr orig-dir) "/" file)) | |
| 133 (base2 (concat dir "/" file))) | |
| 134 (if (not (and shadows-compare-text-p | |
| 135 (shadow-same-file-or-nonexistent | |
| 136 (concat base1 ".el") (concat base2 ".el")) | |
| 137 ;; This is a bit strict, but safe. | |
| 138 (shadow-same-file-or-nonexistent | |
| 139 (concat base1 ".elc") (concat base2 ".elc")))) | |
| 22170 | 140 (setq shadows |
| 141 (append shadows (list base1 base2))))) | |
| 14058 | 142 |
| 143 ;; Not seen before, add it to the list of seen files. | |
| 144 (setq files (cons (cons file dir) files)))) | |
| 145 | |
| 146 (setq curr-files (cdr curr-files)))) | |
| 147 (setq path (cdr path))) | |
| 148 | |
| 149 ;; Return the list of shadowings. | |
| 150 shadows)) | |
| 151 | |
| 19982 | 152 ;; Return true if neither file exists, or if both exist and have identical |
| 153 ;; contents. | |
| 154 (defun shadow-same-file-or-nonexistent (f1 f2) | |
| 155 (let ((exists1 (file-exists-p f1)) | |
| 156 (exists2 (file-exists-p f2))) | |
| 157 (or (and (not exists1) (not exists2)) | |
| 158 (and exists1 exists2 | |
| 159 (or (equal (file-truename f1) (file-truename f2)) | |
| 160 ;; As a quick test, avoiding spawning a process, compare file | |
| 161 ;; sizes. | |
| 162 (and (= (nth 7 (file-attributes f1)) | |
| 163 (nth 7 (file-attributes f2))) | |
| 164 (zerop (call-process "cmp" nil nil nil "-s" f1 f2)))))))) | |
| 14058 | 165 |
| 166 ;;;###autoload | |
| 167 (defun list-load-path-shadows () | |
|
15756
30e9db641e6f
(list-load-path-shadows): Doc fix.
Richard M. Stallman <rms@gnu.org>
parents:
15736
diff
changeset
|
168 "Display a list of Emacs Lisp files that shadow other files. |
| 14058 | 169 |
| 170 This function lists potential load-path problems. Directories in the | |
| 171 `load-path' variable are searched, in order, for Emacs Lisp | |
|
15756
30e9db641e6f
(list-load-path-shadows): Doc fix.
Richard M. Stallman <rms@gnu.org>
parents:
15736
diff
changeset
|
172 files. When a previously encountered file name is found again, a |
|
30e9db641e6f
(list-load-path-shadows): Doc fix.
Richard M. Stallman <rms@gnu.org>
parents:
15736
diff
changeset
|
173 message is displayed indicating that the later file is \"hidden\" by |
| 14058 | 174 the earlier. |
| 175 | |
| 176 For example, suppose `load-path' is set to | |
| 177 | |
| 178 \(\"/usr/gnu/emacs/site-lisp\" \"/usr/gnu/emacs/share/emacs/19.30/lisp\"\) | |
| 179 | |
| 180 and that each of these directories contains a file called XXX.el. Then | |
| 181 XXX.el in the site-lisp directory is referred to by all of: | |
| 182 \(require 'XXX\), \(autoload .... \"XXX\"\), \(load-library \"XXX\"\) etc. | |
| 183 | |
| 184 The first XXX.el file prevents emacs from seeing the second \(unless | |
| 185 the second is loaded explicitly via load-file\). | |
| 186 | |
| 187 When not intended, such shadowings can be the source of subtle | |
| 188 problems. For example, the above situation may have arisen because the | |
| 189 XXX package was not distributed with versions of emacs prior to | |
| 190 19.30. An emacs maintainer downloaded XXX from elsewhere and installed | |
| 191 it. Later, XXX was updated and included in the emacs distribution. | |
| 192 Unless the emacs maintainer checks for this, the new version of XXX | |
| 193 will be hidden behind the old \(which may no longer work with the new | |
| 194 emacs version\). | |
| 195 | |
| 196 This function performs these checks and flags all possible | |
| 197 shadowings. Because a .el file may exist without a corresponding .elc | |
| 198 \(or vice-versa\), these suffixes are essentially ignored. A file | |
| 199 XXX.elc in an early directory \(that does not contain XXX.el\) is | |
| 200 considered to shadow a later file XXX.el, and vice-versa. | |
| 201 | |
| 202 When run interactively, the shadowings \(if any\) are displayed in a | |
| 203 buffer called `*Shadows*'. Shadowings are located by calling the | |
| 204 \(non-interactive\) companion function, `find-emacs-lisp-shadows'." | |
| 205 | |
| 206 (interactive) | |
|
19313
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
207 (let* ((path (copy-sequence load-path)) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
208 (tem path) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
209 toplevs) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
210 ;; If we can find simple.el in two places, |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
211 (while tem |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
212 (if (file-exists-p (expand-file-name "simple.el" (car tem))) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
213 (setq toplevs (cons (car tem) toplevs))) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
214 (setq tem (cdr tem))) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
215 (if (> (length toplevs) 1) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
216 ;; Cut off our copy of load-path right before |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
217 ;; the second directory which has simple.el in it. |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
218 ;; This avoids loads of duplications between the source dir |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
219 ;; and the dir where these files were copied by installation. |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
220 (let ((break (nth (- (length toplevs) 2) toplevs))) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
221 (setq tem path) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
222 (while tem |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
223 (if (eq (nth 1 tem) break) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
224 (progn |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
225 (setcdr tem nil) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
226 (setq tem nil))) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
227 (setq tem (cdr tem))))) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
228 |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
229 (let* ((shadows (find-emacs-lisp-shadows path)) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
230 (n (/ (length shadows) 2)) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
231 (msg (format "%s Emacs Lisp load-path shadowing%s found" |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
232 (if (zerop n) "No" (concat "\n" (number-to-string n))) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
233 (if (= n 1) " was" "s were")))) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
234 (if (interactive-p) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
235 (save-excursion |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
236 ;; We are interactive. |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
237 ;; Create the *Shadows* buffer and display shadowings there. |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
238 (let ((output-buffer (get-buffer-create "*Shadows*"))) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
239 (display-buffer output-buffer) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
240 (set-buffer output-buffer) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
241 (erase-buffer) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
242 (while shadows |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
243 (insert (format "%s hides %s\n" (car shadows) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
244 (car (cdr shadows)))) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
245 (setq shadows (cdr (cdr shadows)))) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
246 (insert msg "\n"))) |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
247 ;; We are non-interactive, print shadows via message. |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
248 (when shadows |
|
04175c55c49b
(list-load-path-shadows): Exclude, from the path we search, all but
Richard M. Stallman <rms@gnu.org>
parents:
19226
diff
changeset
|
249 (message "This site has duplicate Lisp libraries with the same name. |
|
19226
c160218de690
(find-emacs-lisp-shadows): Don't mention `subdirs.el'.
Richard M. Stallman <rms@gnu.org>
parents:
15756
diff
changeset
|
250 If a locally-installed Lisp library overrides a library in the Emacs release, |
|
c160218de690
(find-emacs-lisp-shadows): Don't mention `subdirs.el'.
Richard M. Stallman <rms@gnu.org>
parents:
15756
diff
changeset
|
251 that can cause trouble, and you should probably remove the locally-installed |
|
21927
8332fee2c358
(list-load-path-shadows): Don't say
Richard M. Stallman <rms@gnu.org>
parents:
21365
diff
changeset
|
252 version unless you know what you are doing.\n") |
|
8332fee2c358
(list-load-path-shadows): Don't say
Richard M. Stallman <rms@gnu.org>
parents:
21365
diff
changeset
|
253 (while shadows |
|
8332fee2c358
(list-load-path-shadows): Don't say
Richard M. Stallman <rms@gnu.org>
parents:
21365
diff
changeset
|
254 (message "%s hides %s" (car shadows) (car (cdr shadows))) |
|
8332fee2c358
(list-load-path-shadows): Don't say
Richard M. Stallman <rms@gnu.org>
parents:
21365
diff
changeset
|
255 (setq shadows (cdr (cdr shadows)))) |
|
8332fee2c358
(list-load-path-shadows): Don't say
Richard M. Stallman <rms@gnu.org>
parents:
21365
diff
changeset
|
256 (message "%s" msg)))))) |
| 14058 | 257 |
| 258 (provide 'shadow) | |
| 259 | |
| 260 ;;; shadow.el ends here |
