update.
[elisp/apel.git] / install.el
1 ;;; install.el --- Emacs Lisp package install utility
2
3 ;; Copyright (C) 1996,1997,1998,1999 Free Software Foundation, Inc.
4
5 ;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
6 ;; Created: 1996/08/18
7 ;; Keywords: install, byte-compile, directory detection
8
9 ;; This file is part of APEL (A Portable Emacs Library).
10
11 ;; This program is free software; you can redistribute it and/or
12 ;; modify it under the terms of the GNU General Public License as
13 ;; published by the Free Software Foundation; either version 2, or (at
14 ;; your option) any later version.
15
16 ;; This program is distributed in the hope that it will be useful, but
17 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 ;; General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING.  If not, write to
23 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
25
26 ;;; Code:
27
28 ;; for historical reason, we do (require 'emu) in this file.
29 ;; but you should do (require 'emu) explicitly if you use functions and/or
30 ;; variables defined in emu module.
31 (require 'emu)
32 (require 'path-util)                    ; default-load-path
33
34 ;; verbatim copy of `defun-maybe' from poe.el, and
35 ;; `make-directory-internal' and `make-directory' from poe-18.el
36 (defmacro defun-maybe (name &rest everything-else)
37   "Define NAME as a function if NAME is not defined.
38 See also the function `defun'."
39   (or (and (fboundp name)
40            (not (get name 'defun-maybe)))
41       (` (or (fboundp (quote (, name)))
42              (prog1
43                  (defun (, name) (,@ everything-else))
44                (put (quote (, name)) 'defun-maybe t))))))
45
46 (defun-maybe make-directory-internal (dirname)
47   "Create a directory. One argument, a file name string."
48   (let ((dir (expand-file-name dirname)))
49     (if (file-exists-p dir)
50         (error "Creating directory: %s is already exist" dir)
51       (call-process "mkdir" nil nil nil dir))))
52
53 (defun-maybe make-directory (dir &optional parents)
54   "Create the directory DIR and any nonexistent parent dirs.
55 The second (optional) argument PARENTS says whether
56 to create parent directories if they don't exist."
57   (let ((len (length dir))
58         (p 0) p1 path)
59     (catch 'tag
60       (while (and (< p len) (string-match "[^/]*/?" dir p))
61         (setq p1 (match-end 0))
62         (if (= p1 len)
63             (throw 'tag nil))
64         (setq path (substring dir 0 p1))
65         (if (not (file-directory-p path))
66             (cond ((file-exists-p path)
67                    (error "Creating directory: %s is not directory" path))
68                   ((null parents)
69                    (error "Creating directory: %s is not exist" path))
70                   (t
71                    (make-directory-internal path))))
72         (setq p p1)))
73     (make-directory-internal dir)))
74
75
76 ;;; @ compile Emacs Lisp files
77 ;;;
78
79 (defun compile-elisp-module (module &optional path every-time)
80   (setq module (expand-file-name (symbol-name module) path))
81   (let ((el-file (concat module ".el"))
82         (elc-file (concat module ".elc")))
83     (if (or every-time
84             (file-newer-than-file-p el-file elc-file))
85         (byte-compile-file el-file))))
86
87 (defun compile-elisp-modules (modules &optional path every-time)
88   (mapcar (function
89            (lambda (module)
90              (compile-elisp-module module path every-time)))
91           modules))
92
93
94 ;;; @ install files
95 ;;;
96
97 (defvar install-overwritten-file-modes (+ (* 64 6)(* 8 4) 4))
98
99 (defun install-file (file src dest &optional move overwrite just-print)
100   (if just-print
101       (princ (format "%s -> %s\n" file dest))
102     (let ((src-file (expand-file-name file src)))
103       (if (file-exists-p src-file)
104           (let ((full-path (expand-file-name file dest)))
105             (if (and (file-exists-p full-path) overwrite)
106                 (delete-file full-path))
107             (copy-file src-file full-path t t)
108             (if move
109                 (catch 'tag
110                   (while (and (file-exists-p src-file)
111                               (file-writable-p src-file))
112                     (condition-case err
113                         (progn
114                           (delete-file src-file)
115                           (throw 'tag nil))
116                       (error (princ (format "%s\n" (nth 1 err))))))))
117             (princ (format "%s -> %s\n" file dest)))))))
118
119 (defun install-files (files src dest &optional move overwrite just-print)
120   (or (file-exists-p dest)
121       (make-directory dest t))
122   (mapcar (function
123            (lambda (file)
124              (install-file file src dest move overwrite just-print)))
125           files))
126
127
128 ;;; @@ install Emacs Lisp files
129 ;;;
130
131 (defun install-elisp-module (module src dest &optional just-print)
132   (let (el-file elc-file)
133     (let ((name (symbol-name module)))
134       (setq el-file (concat name ".el"))
135       (setq elc-file (concat name ".elc")))
136     (let ((src-file (expand-file-name el-file src)))
137       (if (not (file-exists-p src-file))
138           nil 
139         (if just-print
140             (princ (format "%s -> %s\n" el-file dest))
141           (let ((full-path (expand-file-name el-file dest)))
142             (if (file-exists-p full-path)
143                 (delete-file full-path))
144             (copy-file src-file full-path t t)
145             (princ (format "%s -> %s\n" el-file dest)))))
146       (setq src-file (expand-file-name elc-file src))
147       (if (not (file-exists-p src-file))
148           nil 
149         (if just-print
150             (princ (format "%s -> %s\n" elc-file dest))
151           (let ((full-path (expand-file-name elc-file dest)))
152             (if (file-exists-p full-path)
153                 (delete-file full-path))
154             (copy-file src-file full-path t t)
155             (catch 'tag
156               (while (file-exists-p src-file)
157                 (condition-case err
158                     (progn
159                       (delete-file src-file)
160                       (throw 'tag nil))
161                   (error (princ (format "%s\n" (nth 1 err)))))))
162             (princ (format "%s -> %s\n" elc-file dest))))))))
163
164 (defun install-elisp-modules (modules src dest &optional just-print)
165   (or (file-exists-p dest)
166       (make-directory dest t))
167   (mapcar (function
168            (lambda (module)
169              (install-elisp-module module src dest just-print)))
170           modules))
171
172
173 ;;; @ detect install path
174 ;;;
175
176 ;; install to shared directory (maybe "/usr/local")
177 (defvar install-prefix
178   (if (or (<= emacs-major-version 18)   ; running-emacs-18
179           (featurep 'xemacs)            ; running-xemacs
180           (and (boundp 'system-configuration-options) ; 19.29 or later
181                (string= system-configuration-options "NT"))) ; for Meadow
182       (expand-file-name "../../.." exec-directory)
183     (expand-file-name "../../../.." data-directory)))
184
185 (defvar install-elisp-prefix
186   (if (>= emacs-major-version 19)
187       "site-lisp"
188     "local.lisp"))
189
190 (defun install-detect-elisp-directory (&optional prefix elisp-prefix
191                                                  allow-version-specific)
192   (or prefix
193       (setq prefix install-prefix))
194   (or elisp-prefix
195       (setq elisp-prefix install-elisp-prefix))
196   (or
197    (catch 'tag
198      (let ((rest default-load-path)
199            (pat (concat "^"
200                         (expand-file-name (concat ".*/" elisp-prefix) prefix)
201                         "/?$")))
202        (while rest
203          (if (string-match pat (car rest))
204              (if (or allow-version-specific
205                      (not (string-match (format "/%d\\.%d"
206                                                 emacs-major-version
207                                                 emacs-minor-version)
208                                         (car rest))))
209                  (throw 'tag (car rest))))
210          (setq rest (cdr rest)))))
211    (expand-file-name (concat
212                       (if (and          ; running-emacs-19_29-or-later
213                            (not (featurep 'xemacs))
214                            (or (>= emacs-major-version 20)
215                                (and (= emacs-major-version 19)
216                                     (>= emacs-minor-version 29))))
217                           "share/"
218                         "lib/")
219                       (cond ((boundp 'NEMACS) "nemacs/")
220                             ((boundp 'MULE)   "mule/")
221                             ((featurep 'xemacs) ; running-xemacs
222                              (if (featurep 'mule)
223                                  "xmule/"
224                                "xemacs/"))
225                             (t "emacs/"))
226                       elisp-prefix)
227                      prefix)))
228
229 (defvar install-default-elisp-directory
230   (install-detect-elisp-directory))
231
232
233 ;;; @ end
234 ;;;
235
236 (provide 'install)
237
238 ;;; install.el ends here