- added user-specific defaults (stored in file ~/.scsh-pkg-defaults),
- added "exclude" option, to exclude some files, - parse layouts *after* processing the options, - changed "display-error-and-exit" to not use "format" anymore.
This commit is contained in:
parent
47391a548d
commit
06427ff520
|
@ -1,5 +1,5 @@
|
||||||
;;; Installation library for scsh modules.
|
;;; Installation library for scsh modules.
|
||||||
;;; $Id: install-lib.scm,v 1.11 2004/02/20 08:22:07 michel-schinz Exp $
|
;;; $Id: install-lib.scm,v 1.12 2004/02/23 20:11:40 michel-schinz Exp $
|
||||||
|
|
||||||
;; TODO
|
;; TODO
|
||||||
;; - add a "--debug" option
|
;; - add a "--debug" option
|
||||||
|
@ -128,6 +128,14 @@
|
||||||
(define (alist-replace key datum alist)
|
(define (alist-replace key datum alist)
|
||||||
(alist-cons key datum (alist-delete key alist)))
|
(alist-cons key datum (alist-delete key alist)))
|
||||||
|
|
||||||
|
;; Add all mappings from ALIST-2 to ALIST-1. If a key is mapped in
|
||||||
|
;; both lists, the mapping in the first list takes precedence.
|
||||||
|
(define (alist-combine alist-1 alist-2)
|
||||||
|
(fold (lambda (key/value result)
|
||||||
|
(if (assoc (car key/value) result) result (cons key/value result)))
|
||||||
|
alist-1
|
||||||
|
alist-2))
|
||||||
|
|
||||||
;; Return the value associated with KEY in ALIST. If none exists,
|
;; Return the value associated with KEY in ALIST. If none exists,
|
||||||
;; return DEFAULT, or signal an error if no DEFAULT was given.
|
;; return DEFAULT, or signal an error if no DEFAULT was given.
|
||||||
(define (alist-get key alist . rest)
|
(define (alist-get key alist . rest)
|
||||||
|
@ -251,14 +259,6 @@
|
||||||
(return #f))))
|
(return #f))))
|
||||||
(split-defs str)))))))
|
(split-defs str)))))))
|
||||||
|
|
||||||
;; Combine layouts L1 and L2 by adding to L1 all the additional
|
|
||||||
;; mappings found in L2.
|
|
||||||
(define (combine-layouts l1 l2)
|
|
||||||
(fold (lambda (key/value layout)
|
|
||||||
(if (assoc (car key/value) layout) layout (cons key/value layout)))
|
|
||||||
l1
|
|
||||||
l2))
|
|
||||||
|
|
||||||
;; Return an absolute version of LAYOUT by prepending PREFIX to all
|
;; Return an absolute version of LAYOUT by prepending PREFIX to all
|
||||||
;; its components (which must be relative).
|
;; its components (which must be relative).
|
||||||
(define (absolute-layout layout prefix)
|
(define (absolute-layout layout prefix)
|
||||||
|
@ -280,11 +280,11 @@
|
||||||
(doc . ,(absolute-file-name "doc" base))))
|
(doc . ,(absolute-file-name "doc" base))))
|
||||||
|
|
||||||
(define (scsh-layout-1 platform pkg)
|
(define (scsh-layout-1 platform pkg)
|
||||||
(combine-layouts '((active . "."))
|
(alist-combine '((active . "."))
|
||||||
(scsh-layout platform (package-full-name pkg))))
|
(scsh-layout platform (package-full-name pkg))))
|
||||||
|
|
||||||
(define (scsh-layout-2 platform pkg)
|
(define (scsh-layout-2 platform pkg)
|
||||||
(combine-layouts
|
(alist-combine
|
||||||
'((active . "active"))
|
'((active . "active"))
|
||||||
(scsh-layout platform
|
(scsh-layout platform
|
||||||
(path-list->file-name
|
(path-list->file-name
|
||||||
|
@ -308,6 +308,13 @@
|
||||||
("scsh-alt" . ,scsh-layout-2)
|
("scsh-alt" . ,scsh-layout-2)
|
||||||
("fhs" . ,fhs-layout)))
|
("fhs" . ,fhs-layout)))
|
||||||
|
|
||||||
|
;; If NAME-OR-LAYOUT refers to a predefined layout, return it.
|
||||||
|
;; Otherwise, if NAME-OR-LAYOUT is a valid layout definition, parse
|
||||||
|
;; and return it. Otherwise, return false.
|
||||||
|
(define (resolve-layout name-or-layout)
|
||||||
|
(or (alist-get name-or-layout predefined-layouts #f)
|
||||||
|
(parse-layout name-or-layout)))
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;; Packages
|
;; Packages
|
||||||
;;
|
;;
|
||||||
|
@ -481,18 +488,21 @@
|
||||||
(cdr name-or-pair)
|
(cdr name-or-pair)
|
||||||
name-or-pair)))
|
name-or-pair)))
|
||||||
(target (absolute-file-name target-name target-dir)))
|
(target (absolute-file-name target-name target-dir)))
|
||||||
(create-directory&parents target-dir perms-fn)
|
(if (not ((get-option-value 'exclude) source))
|
||||||
(cond ((or (file-regular? source) (file-symlink? source))
|
(begin
|
||||||
(-copy-file source target))
|
(create-directory&parents target-dir perms-fn)
|
||||||
((file-directory? source)
|
(cond ((or (file-regular? source) (file-symlink? source))
|
||||||
(-create-directory target (file-mode source))
|
(-copy-file source target))
|
||||||
(install-directory-contents% layout
|
((file-directory? source)
|
||||||
source
|
(-create-directory target (file-mode source))
|
||||||
location
|
(install-directory-contents% layout
|
||||||
(absolute-file-name target-name
|
source
|
||||||
target-rel-dir)
|
location
|
||||||
perms-fn))
|
(absolute-file-name
|
||||||
(else (error "cannot install file-system object" source)))))
|
target-name
|
||||||
|
target-rel-dir)
|
||||||
|
perms-fn))
|
||||||
|
(else (error "cannot install file-system object" source)))))))
|
||||||
|
|
||||||
(define (install-directory-contents% layout
|
(define (install-directory-contents% layout
|
||||||
name
|
name
|
||||||
|
@ -575,7 +585,7 @@
|
||||||
(let* ((prefix (alist-get 'prefix options-values))
|
(let* ((prefix (alist-get 'prefix options-values))
|
||||||
(dest-dir (alist-get 'dest-dir options-values))
|
(dest-dir (alist-get 'dest-dir options-values))
|
||||||
(dest-prefix (and prefix (re-root-file-name prefix dest-dir)))
|
(dest-prefix (and prefix (re-root-file-name prefix dest-dir)))
|
||||||
(layout-fn (alist-get 'layout options-values))
|
(layout-fn (resolve-layout (alist-get 'layout options-values)))
|
||||||
(layout-to (alist-get 'layout-to options-values))
|
(layout-to (alist-get 'layout-to options-values))
|
||||||
(build (alist-get 'build options-values))
|
(build (alist-get 'build options-values))
|
||||||
(non-shared-only? (alist-get 'non-shared-only options-values))
|
(non-shared-only? (alist-get 'non-shared-only options-values))
|
||||||
|
@ -616,10 +626,10 @@
|
||||||
;; Error handling
|
;; Error handling
|
||||||
;;
|
;;
|
||||||
|
|
||||||
;; Display MSG (a format string with ARGS as arguments) on the error
|
;; Display all the MSGS on the error port, then exit with an error
|
||||||
;; port, then exit with an error code of 1.
|
;; code of 1.
|
||||||
(define (display-error-and-exit msg . args)
|
(define (display-error-and-exit . msgs)
|
||||||
(apply format (current-error-port) (string-append "Error: " msg) args)
|
(for-each display (cons "Error: " msgs))
|
||||||
(newline)
|
(newline)
|
||||||
(exit 1))
|
(exit 1))
|
||||||
|
|
||||||
|
@ -669,15 +679,15 @@ END
|
||||||
pkg-opts)
|
pkg-opts)
|
||||||
(set! usage (string-output-port-output usage-port))))
|
(set! usage (string-output-port-output usage-port))))
|
||||||
|
|
||||||
;; Display the usage string, then MSG (a format string with ARGS as
|
;; Display the usage string, then all MSGS on the standard output
|
||||||
;; arguments) on the standard output port, then exit with an error
|
;; port, then exit with an error code of 1.
|
||||||
;; code of 1.
|
(define (display-usage-and-exit . msgs)
|
||||||
(define (display-usage-and-exit msg . args)
|
|
||||||
(format #t
|
(format #t
|
||||||
usage
|
usage
|
||||||
(car (command-line))
|
(car (command-line))
|
||||||
(string-join (map car predefined-layouts) ", "))
|
(string-join (map car predefined-layouts) ", "))
|
||||||
(if msg (begin (apply format #t msg args) (newline)))
|
(for-each display msgs)
|
||||||
|
(newline)
|
||||||
(exit 1))
|
(exit 1))
|
||||||
|
|
||||||
;;
|
;;
|
||||||
|
@ -689,7 +699,7 @@ END
|
||||||
(cond ((string=? s "yes") #t)
|
(cond ((string=? s "yes") #t)
|
||||||
((string=? s "no") #f)
|
((string=? s "no") #f)
|
||||||
(else (display-error-and-exit
|
(else (display-error-and-exit
|
||||||
"unknown boolean value '~a'. Use 'yes' or 'no'." s))))
|
"unknown boolean value '"s"'. Use 'yes' or 'no'."))))
|
||||||
|
|
||||||
(define (show-boolean b)
|
(define (show-boolean b)
|
||||||
(if b "yes" "no"))
|
(if b "yes" "no"))
|
||||||
|
@ -714,17 +724,10 @@ END
|
||||||
(alist-replace key #t alist)))))
|
(alist-replace key #t alist)))))
|
||||||
(list
|
(list
|
||||||
(option '(#\h "help") #f #f
|
(option '(#\h "help") #f #f
|
||||||
(lambda args (display-usage-and-exit #f)))
|
(lambda args (display-usage-and-exit)))
|
||||||
(option '("prefix") #t #f (alist-arg-updater 'prefix))
|
(option '("prefix") #t #f (alist-arg-updater 'prefix))
|
||||||
(option '("dest-dir") #t #f (alist-arg-updater 'dest-dir))
|
(option '("dest-dir") #t #f (alist-arg-updater 'dest-dir))
|
||||||
(option '("layout") #t #f
|
(option '("layout") #t #f (alist-arg-updater 'layout))
|
||||||
(lambda (opt name arg alist)
|
|
||||||
(alist-replace 'layout
|
|
||||||
(cond ((assoc arg predefined-layouts) => cdr)
|
|
||||||
((parse-layout arg) => identity)
|
|
||||||
(else (display-error-and-exit
|
|
||||||
"invalid layout ~a" arg)))
|
|
||||||
alist)))
|
|
||||||
(option '("layout-from") #t #f
|
(option '("layout-from") #t #f
|
||||||
(lambda (opt name arg alist)
|
(lambda (opt name arg alist)
|
||||||
(alist-replace 'layout
|
(alist-replace 'layout
|
||||||
|
@ -740,43 +743,70 @@ END
|
||||||
(option '("verbose") #f #f (alist-boolean-updater 'verbose))
|
(option '("verbose") #f #f (alist-boolean-updater 'verbose))
|
||||||
(option '("force") #f #f (alist-boolean-updater 'force)))))
|
(option '("force") #f #f (alist-boolean-updater 'force)))))
|
||||||
|
|
||||||
|
(define no-user-defaults-option "--no-user-defaults")
|
||||||
|
|
||||||
|
(define (parse-options args options defaults)
|
||||||
|
(args-fold args
|
||||||
|
options
|
||||||
|
(lambda (option name . rest)
|
||||||
|
(display-usage-and-exit "Unknown option "name))
|
||||||
|
(lambda (operand . rest)
|
||||||
|
(display-usage-and-exit "Don't know what to do with " operand))
|
||||||
|
defaults))
|
||||||
|
|
||||||
|
;; Return user-specific defaults.
|
||||||
|
(define (read-user-defaults)
|
||||||
|
(let ((file (expand-file-name "~/.scsh-pkg-defaults.scm")))
|
||||||
|
(if (file-exists? file)
|
||||||
|
(call-with-input-file file
|
||||||
|
(lambda (port)
|
||||||
|
(let ((defaults (read port)))
|
||||||
|
(if (or (eof-object? defaults))
|
||||||
|
(display-error-and-exit "no valid defaults found in "file))
|
||||||
|
(if (not (eof-object? (read port)))
|
||||||
|
(display-error-and-exit
|
||||||
|
"more than one expression found in "file))
|
||||||
|
(eval (list 'quasiquote defaults) (interaction-environment)))))
|
||||||
|
'())))
|
||||||
|
|
||||||
(define options-defaults
|
(define options-defaults
|
||||||
`((prefix . #f)
|
`((prefix . #f)
|
||||||
(dest-dir . "/")
|
(dest-dir . "/")
|
||||||
(layout . ,scsh-layout-1)
|
(layout . "scsh")
|
||||||
(layout-to . #f)
|
(layout-to . #f)
|
||||||
(build . ,(host))
|
(build . ,(host))
|
||||||
(non-shared-only . #f)
|
(non-shared-only . #f)
|
||||||
(inactive . #f)
|
(inactive . #f)
|
||||||
(dry-run . #f)
|
(dry-run . #f)
|
||||||
(verbose . #f)
|
(verbose . #f)
|
||||||
(force . #f)))
|
(force . #f)
|
||||||
|
(exclude . ,(lambda args #f))))
|
||||||
(define (parse-options args options defaults)
|
|
||||||
(args-fold args
|
|
||||||
options
|
|
||||||
(lambda (option name . rest)
|
|
||||||
(display-usage-and-exit "Unknown option ~a" name))
|
|
||||||
(lambda (operand . rest)
|
|
||||||
(display-usage-and-exit "Don't know what to do with ~a"
|
|
||||||
operand))
|
|
||||||
defaults))
|
|
||||||
|
|
||||||
(define (install-main cmd-line)
|
(define (install-main cmd-line)
|
||||||
(if (not (file-exists? package-definition-file))
|
(if (not (file-exists? package-definition-file))
|
||||||
(display-error-and-exit "cannot find package definition file (~a)"
|
(display-error-and-exit "cannot find package definition file"
|
||||||
package-definition-file))
|
"("package-definition-file")"))
|
||||||
(let* ((packages (load-packages))
|
(let* ((packages (load-packages))
|
||||||
(all-pkg-opts (all-package-options packages)))
|
(all-pkg-opts (all-package-options packages)))
|
||||||
(if (not (null? all-pkg-opts))
|
(if (not (null? all-pkg-opts))
|
||||||
(complete-usage! all-pkg-opts))
|
(complete-usage! all-pkg-opts))
|
||||||
(let* ((all-opts (append options (map pkg-opt->option all-pkg-opts)))
|
(let* ((all-opts (append options (map pkg-opt->option all-pkg-opts)))
|
||||||
(all-dfts (append options-defaults
|
(all-dfts (append (alist-combine
|
||||||
|
(if (member no-user-defaults-option cmd-line)
|
||||||
|
'()
|
||||||
|
(read-user-defaults))
|
||||||
|
options-defaults)
|
||||||
(map pkg-opt-key&default all-pkg-opts)))
|
(map pkg-opt-key&default all-pkg-opts)))
|
||||||
(options-values (parse-options (cdr cmd-line) all-opts all-dfts))
|
(options-values (parse-options (delete no-user-defaults-option
|
||||||
(prefix (alist-get 'prefix options-values)))
|
(cdr cmd-line))
|
||||||
|
all-opts
|
||||||
|
all-dfts))
|
||||||
|
(prefix (alist-get 'prefix options-values))
|
||||||
|
(layout (alist-get 'layout options-values)))
|
||||||
(if (not prefix)
|
(if (not prefix)
|
||||||
(display-error-and-exit "no prefix specified (use --prefix option)"))
|
(display-error-and-exit "no prefix specified (use --prefix option)"))
|
||||||
(if (not (file-name-absolute? prefix))
|
(if (not (file-name-absolute? prefix))
|
||||||
(display-error-and-exit "prefix must be an absolute path"))
|
(display-error-and-exit "prefix must be an absolute path"))
|
||||||
|
(if (not (resolve-layout layout))
|
||||||
|
(display-error-and-exit "invalid layout "layout))
|
||||||
(install-packages packages options-values))))
|
(install-packages packages options-values))))
|
||||||
|
|
Loading…
Reference in New Issue