772e7e5d1ca40f3703ae23865cc387e093d589e3
[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 (defvar emacs-major-version (string-to-int emacs-version))
35 (defvar emacs-minor-version
36   (string-to-int
37    (substring emacs-version
38               (string-match (format "%d\\." emacs-major-version)
39                             emacs-version))))
40
41 ;; verbatim copy of `defun-maybe' from poe.el, and
42 ;; `make-directory-internal' and `make-directory' from poe-18.el
43 (defmacro defun-maybe (name &rest everything-else)
44   "Define NAME as a function if NAME is not defined.
45 See also the function `defun'."
46   (or (and (fboundp name)
47            (not (get name 'defun-maybe)))
48       (` (or (fboundp (quote (, name)))
49              (prog1
50                  (defun (, name) (,@ everything-else))
51                (put (quote (, name)) 'defun-maybe t))))))
52
53 (defun-maybe make-directory-internal (dirname)
54   "Create a directory. One argument, a file name string."
55   (let ((dir (expand-file-name dirname)))
56     (if (file-exists-p dir)
57         (error "Creating directory: %s is already exist" dir)
58       (call-process "mkdir" nil nil nil dir))))
59
60 (defun-maybe make-directory (dir &optional parents)
61   "Create the directory DIR and any nonexistent parent dirs.
62 The second (optional) argument PARENTS says whether
63 to create parent directories if they don't exist."
64   (let ((len (length dir))
65         (p 0) p1 path)
66     (catch 'tag
67       (while (and (< p len) (string-match "[^/]*/?" dir p))
68         (setq p1 (match-end 0))
69         (if (= p1 len)
70             (throw 'tag nil))
71         (setq path (substring dir 0 p1))
72         (if (not (file-directory-p path))
73             (cond ((file-exists-p path)
74                    (error "Creating directory: %s is not directory" path))
75                   ((null parents)
76                    (error "Creating directory: %s is not exist" path))
77                   (t
78                    (make-directory-internal path))))
79         (setq p p1)))
80     (make-directory-internal dir)))
81
82
83 ;;; @ compile Emacs Lisp files
84 ;;;
85
86 (defun compile-elisp-module (module &optional path every-time)
87   (setq module (expand-file-name (symbol-name module) path))
88   (let ((el-file (concat module ".el"))
89         (elc-file (concat module ".elc")))
90     (if (or every-time
91             (file-newer-than-file-p el-file elc-file))
92         (byte-compile-file el-file))))
93
94 (defun compile-elisp-modules (modules &optional path every-time)
95   (mapcar (function
96            (lambda (module)
97              (compile-elisp-module module path every-time)))
98           modules))
99
100
101 ;;; @ install files
102 ;;;
103
104 (defvar install-overwritten-file-modes (+ (* 64 6)(* 8 4) 4))
105
106 (defun install-file (file src dest &optional move overwrite just-print)
107   (if just-print
108       (princ (format "%s -> %s\n" file dest))
109     (let ((src-file (expand-file-name file src)))
110       (if (file-exists-p src-file)
111           (let ((full-path (expand-file-name file dest)))
112             (if (and (file-exists-p full-path) overwrite)
113                 (delete-file full-path))
114             (copy-file src-file full-path t t)
115             (if move
116                 (catch 'tag
117                   (while (and (file-exists-p src-file)
118                               (file-writable-p src-file))
119                     (condition-case err
120                         (progn
121                           (delete-file src-file)
122                           (throw 'tag nil))
123                       (error (princ (format "%s\n" (nth 1 err))))))))
124             (princ (format "%s -> %s\n" file dest)))))))
125
126 (defun install-files (files src dest &optional move overwrite just-print)
127   (or (file-exists-p dest)
128       (make-directory dest t))
129   (mapcar (function
130            (lambda (file)
131              (install-file file src dest move overwrite just-print)))
132           files))
133
134
135 ;;; @@ install Emacs Lisp files
136 ;;;
137
138 (defun install-elisp-module (module src dest &optional just-print)
139   (let (el-file elc-file)
140     (let ((name (symbol-name module)))
141       (setq el-file (concat name ".el"))
142       (setq elc-file (concat name ".elc")))
143     (let ((src-file (expand-file-name el-file src)))
144       (if (not (file-exists-p src-file))
145           nil 
146         (if just-print
147             (princ (format "%s -> %s\n" el-file dest))
148           (let ((full-path (expand-file-name el-file dest)))
149             (if (file-exists-p full-path)
150                 (delete-file full-path))
151             (copy-file src-file full-path t t)
152             (princ (format "%s -> %s\n" el-file dest)))))
153       (setq src-file (expand-file-name elc-file src))
154       (if (not (file-exists-p src-file))
155           nil 
156         (if just-print
157             (princ (format "%s -> %s\n" elc-file dest))
158           (let ((full-path (expand-file-name elc-file dest)))
159             (if (file-exists-p full-path)
160                 (delete-file full-path))
161             (copy-file src-file full-path t t)
162             (catch 'tag
163               (while (file-exists-p src-file)
164                 (condition-case err
165                     (progn
166                       (delete-file src-file)
167                       (throw 'tag nil))
168                   (error (princ (format "%s\n" (nth 1 err)))))))
169             (princ (format "%s -> %s\n" elc-file dest))))))))
170
171 (defun install-elisp-modules (modules src dest &optional just-print)
172   (or (file-exists-p dest)
173       (make-directory dest t))
174   (mapcar (function
175            (lambda (module)
176              (install-elisp-module module src dest just-print)))
177           modules))
178
179
180 ;;; @ detect install path
181 ;;;
182
183 ;; install to shared directory (maybe "/usr/local")
184 (defvar install-prefix
185   (if (or (<= emacs-major-version 18)   ; running-emacs-18
186           (featurep 'xemacs)            ; running-xemacs
187           (and (boundp 'system-configuration-options) ; 19.29 or later
188                (string= system-configuration-options "NT"))) ; for Meadow
189       (expand-file-name "../../.." exec-directory)
190     (expand-file-name "../../../.." data-directory)))
191
192 (defvar install-elisp-prefix
193   (if (>= emacs-major-version 19)
194       "site-lisp"
195     "local.lisp"))
196
197 (defun install-detect-elisp-directory (&optional prefix elisp-prefix
198                                                  allow-version-specific)
199   (or prefix
200       (setq prefix install-prefix))
201   (or elisp-prefix
202       (setq elisp-prefix install-elisp-prefix))
203   (or
204    (catch 'tag
205      (let ((rest default-load-path)
206            (pat (concat "^"
207                         (expand-file-name (concat ".*/" elisp-prefix) prefix)
208                         "/?$")))
209        (while rest
210          (if (string-match pat (car rest))
211              (if (or allow-version-specific
212                      (not (string-match (format "/%d\\.%d"
213                                                 emacs-major-version
214                                                 emacs-minor-version)
215                                         (car rest))))
216                  (throw 'tag (car rest))))
217          (setq rest (cdr rest)))))
218    (expand-file-name (concat
219                       (if (and          ; running-emacs-19_29-or-later
220                            (not (featurep 'xemacs))
221                            (or (>= emacs-major-version 20)
222                                (and (= emacs-major-version 19)
223                                     (>= emacs-minor-version 29))))
224                           "share/"
225                         "lib/")
226                       (cond ((boundp 'NEMACS) "nemacs/")
227                             ((boundp 'MULE)   "mule/")
228                             ((featurep 'xemacs) ; running-xemacs
229                              (if (featurep 'mule)
230                                  "xmule/"
231                                "xemacs/"))
232                             (t "emacs/"))
233                       elisp-prefix)
234                      prefix)))
235
236 (defvar install-default-elisp-directory
237   (install-detect-elisp-directory))
238
239
240 ;;; @ end
241 ;;;
242
243 (provide 'install)
244
245 ;;; install.el ends here