-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcenv.scm
executable file
·130 lines (111 loc) · 4.2 KB
/
cenv.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/env csi -script
(import (chicken file)
(chicken file posix)
(chicken irregex)
(chicken pathname)
(chicken platform)
(chicken process)
(chicken process-context))
;; kinda silly
(define (parse-args #!optional (args (command-line-arguments)))
(when (null? args)
(usage))
(let ((verb (car args))
(rest (cdr args)))
`((command . ,(executable-pathname))
(verb . ,(string->symbol verb))
(args . ,rest))))
(define (usage)
(print "usage: " (program-name) " init <dir>")
(exit 1))
(define (dispatch)
(let ((args (parse-args)))
(let ((verb (alist-ref 'verb args)))
(case verb
((init)
(let ((args (alist-ref 'args args)))
(when (null? args)
(usage))
(cenv-init-repository (car args))))
(else
(usage))))))
(define (template str alist)
(irregex-replace/all "{{([A-Za-z0-9_-]+)}}"
str
(lambda (m)
(let ((key (string->symbol (irregex-match-substring m 1))))
(or (alist-ref key alist)
(error 'template "missing value for key" key))))))
;; realpath is available as C_realpath but only if we compile.
(define (realpath x)
(normalize-pathname
(if (absolute-pathname? x)
x
(make-pathname (current-directory) x))))
(define (last x)
(if (pair? (cdr x))
(last (cdr x))
(car x)))
;; We precompute our env dir, the chicken prefix, and the chicken system repo; so we
;; cannot relocate, but it makes things simpler.
;; We may want to ignore any CHICKEN_REPOSITORY_PATH set in the calling environment;
;; we currently honor it, which is of debatable utility.
(define center-data #<<EOF
#!/bin/bash
export CHICKEN_PREFIX="{{prefix}}"
export CHICKEN_ENV="{{env}}"
export CHICKEN_INSTALL_PREFIX=$CHICKEN_ENV
export CHICKEN_INSTALL_REPOSITORY=$CHICKEN_INSTALL_PREFIX/lib
export PATH=$CHICKEN_INSTALL_PREFIX/bin:$CHICKEN_PREFIX/bin:$PATH
export CHICKEN_REPOSITORY_PATH="$CHICKEN_INSTALL_REPOSITORY:{{sys-repo}}"
# chicken-doc repo defaults to being in system shared dir when unset;
# preserve this behavior for local envs.
if [ -z "${CHICKEN_DOC_REPOSITORY+x}" ]; then
export CHICKEN_DOC_REPOSITORY=$CHICKEN_INSTALL_PREFIX/share/chicken-doc
fi
EOF
)
(define cexec-data #<<EOF
#!/bin/sh
. {{env}}/bin/center
exec "$@"
EOF
)
(define chicken-prefix
;; Note: If we compile, we can obtain prefix via foreign-variable, but
;; it is not exposed by default. Otherwise, we just assume chicken-home
;; is the default and reverse engineer the prefix.
(let ((m (irregex-match "(.+)/share/chicken" (chicken-home))))
(if m
(irregex-match-substring m 1)
(error "Unable to determine chicken prefix from " (chicken-home)))))
(define (create-cexec dirname)
(let ((cexec (string-append dirname "/bin/cexec")))
(with-output-to-file cexec
(lambda () (print (template cexec-data
`((env . ,(realpath dirname)))))))
(set! (file-permissions cexec) #o0755))) ; ignores umask, probably
(define (create-center dirname)
(let ((center (string-append dirname "/bin/center")))
(with-output-to-file center
(lambda () (print (template center-data
`((prefix . ,chicken-prefix)
(env . ,(realpath dirname))
(sys-repo . ,(last (repository-path))))))))
(set! (file-permissions center) #o0644)))
(define (test-cenv dirname)
;; This is available in CHICKEN_REPOSITORY_PATH after entering environment,
;; but double-check that it works by running csi via cexec.
(print "New repository path:")
(system* (string-append (string-append dirname "/bin/cexec ")
"csi -R chicken.platform -p '(repository-path)'")))
(define (cenv-init-repository dirname)
(print "Using CHICKEN " (chicken-version) " in " chicken-prefix)
(print "Initializing repository in " dirname)
(for-each (cut create-directory <> #t)
(map (cut string-append dirname <>)
'("/bin" "/lib" "/share")))
(create-center dirname)
(create-cexec dirname)
(test-cenv dirname))
(dispatch)