Skip to content

Commit abe87bc

Browse files
committed
Rework installer paths
1 parent b2b07a6 commit abe87bc

File tree

3 files changed

+110
-120
lines changed

3 files changed

+110
-120
lines changed

common-lisp-jupyter.asd

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#:cl-indentify
1414
#:closer-mop
1515
#:dissect
16-
; This should be `(:feature (:not :clasp) :ironclad)` but some distributions still don't have
16+
; This should be `(:feature (:not :clasp) :ironclad)` but some implementations still don't have
1717
; ASDF 3
1818
#-clasp :eclector
1919
#-clasp :ironclad
@@ -25,6 +25,7 @@
2525
#:trivial-garbage
2626
#:trivial-gray-streams
2727
#:trivial-mimes
28+
#:trivial-features
2829
#:shasht)
2930
:components
3031
((:module res

src/cl-jupyter/installer.lisp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
(append (list (or implementation
7676
(first (uiop:raw-command-line-arguments))
7777
(format nil "~(~A~)" (uiop:implementation-type)))
78-
+load-flag+ (namestring (jupyter:installer-path instance :root :program :bundle))
78+
+load-flag+ (namestring (jupyter:installer-path instance :bundle))
7979
+eval-flag+ (if (find-package :quicklisp)
8080
"(ql:quickload :common-lisp-jupyter)"
8181
"(asdf:load-system :common-lisp-jupyter)"))
@@ -105,7 +105,7 @@
105105
'("{connection_file}"))))
106106

107107

108-
(defun install (&key bin-path implementation system bundle local prefix root
108+
(defun install (&key bin-path implementation system bundle local prefix jupyter program
109109
(load-system t))
110110
"Install Common Lisp kernel based on the current implementation.
111111
- `bin-path` specifies path to LISP binary.
@@ -114,7 +114,7 @@
114114
- `bundle` creates a quicklisp bundle for system installations.
115115
- `local` toggles `/usr/local/share versus` `/usr/share` for system installations.
116116
- `prefix` key specifies directory prefix for packaging.
117-
- `root` key specifies the root under which the Jupyter folder is found. Is automatically determined if not provided."
117+
- `jupyter` key specifies the root under which the Jupyter folder is found. Is automatically determined if not provided."
118118
(jupyter:install
119119
(make-instance
120120
(cond
@@ -146,14 +146,15 @@
146146
(lisp-implementation-type)))
147147
+language+)
148148
:prefix prefix
149-
:root root)))
149+
:jupyter-path jupyter
150+
:program-path program)))
150151

151152

152-
(defun install-image (&key implementation prefix root)
153+
(defun install-image (&key implementation prefix jupyter program)
153154
"Install Common Lisp kernel based on image of current implementation.
154155
- `implementation` toggles including implementation details in kernel name.
155156
- `prefix` key specifies directory prefix for packaging.
156-
- `root` key specifies the root under which the Jupyter folder is found. Is automatically determined if not provided."
157+
- `jupyter` key specifies the root under which the Jupyter folder is found. Is automatically determined if not provided."
157158
(jupyter:install
158159
(make-instance 'user-image-installer
159160
:display-name
@@ -169,7 +170,8 @@
169170
(lisp-implementation-type)))
170171
+language+)
171172
:prefix prefix
172-
:root root)))
173+
:jupyter-path jupyter
174+
:program-path program)))
173175

174176

175177
(defun install-roswell (&key implementation)

src/installer.lisp

Lines changed: 99 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,16 @@
4747
:initform nil
4848
:accessor installer-resources
4949
:documentation "List of paths of resource files such as icons.")
50-
(root
51-
:initarg :root
50+
(jupyter-path
51+
:initarg :jupyter-path
5252
:initform nil
53-
:accessor installer-root
54-
:documentation "The root directory under which the Jupyter folder is found. If nil then it will be determined automatically.")
53+
:accessor installer-jupyter-path
54+
:documentation "The Jupyter directory. If nil then it will be determined automatically.")
55+
(program-path
56+
:initarg :program-path
57+
:initform nil
58+
:accessor installer-program-path
59+
:documentation "The program directory. If nil then it will be determined automatically.")
5560
(systems
5661
:initarg :systems
5762
:initform nil
@@ -75,105 +80,84 @@
7580
()
7681
(:documentation "User image installer class."))
7782

78-
(defgeneric installer-path-part (instance part)
79-
(:documentation "Get a specific part of an installer path. part is a keyword symbol specifying which part."))
80-
81-
(defmethod installer-path-part (instance (part (eql :prefix)))
82-
"Get the directory prefix if it exists."
83-
(with-slots (prefix) instance
84-
(if prefix
85-
(merge-pathnames
86-
(uiop:relativize-pathname-directory (installer-path-part instance :root))
87-
(truename prefix))
88-
(installer-path-part instance :root))))
89-
90-
(defmethod installer-path-part ((instance system-installer) (type (eql :root)))
91-
"Get the root directory for a system installation."
92-
(cond
93-
((installer-root instance)
94-
(installer-root instance))
95-
((uiop:os-windows-p) ; Use %PROGRAMDATA% on Windows
96-
(uiop:getenv-absolute-directory "PROGRAMDATA"))
97-
((installer-local instance) ; /usr/local/share/
98-
(make-pathname :directory '(:absolute "usr" "local" "share")))
99-
(t ; /usr/share/
100-
(make-pathname :directory '(:absolute "usr" "share")))))
101-
102-
(defmethod installer-path-part ((instance user-installer) (type (eql :root)))
103-
"Get the root directory for a user installation"
104-
(cond
105-
((installer-root instance)
106-
(installer-root instance))
107-
((uiop:os-macosx-p) ; use $HOME/Library/ on Mac
108-
(merge-pathnames (make-pathname :directory '(:relative "Library"))
109-
(uiop:getenv-pathname "HOME" :ensure-directory t)))
110-
((uiop:os-windows-p) ; Use %APPDATA% on Windows
111-
(uiop:get-folder-path :appdata))
112-
(t ; Use XDG_DATA_HOME on all other platforms
113-
(uiop:xdg-data-home))))
114-
115-
(defmethod installer-path-part (instance (part (eql :kernel)))
116-
"Get the kernel directory."
117-
(make-pathname
118-
:directory
119-
(list
120-
:relative
121-
; Just in case HFS+ is case-sensitive
122-
(if (uiop:os-macosx-p) "Jupyter" "jupyter")
123-
"kernels"
124-
(installer-kernel-name instance))))
125-
126-
(defmethod installer-path-part (instance (part (eql :program)))
127-
"Get the program directory."
128-
(make-pathname
129-
:directory
130-
(list
131-
:relative
132-
(format nil "~A-jupyter" (installer-kernel-name instance)))))
133-
134-
(defmethod installer-path-part (instance (part (eql :spec)))
135-
"Get the kernel spec file name."
136-
(make-pathname :name "kernel" :type "json"))
137-
138-
(defmethod installer-path-part (instance (part (eql :image)))
139-
"Get the image file name."
140-
(make-pathname :name "image" :type (when (uiop:os-windows-p) "exe")))
141-
142-
(defmethod installer-path-part (instance (part (eql :bundle)))
143-
"Get the Quicklisp bundle file name."
144-
(make-pathname :name "bundle" :type "lisp"))
145-
146-
(defmethod installer-path-part (instance (part (eql :local-projects)))
147-
"Get the local-projects directory."
148-
(make-pathname
149-
:directory (list :relative "local-projects")))
150-
151-
(defmethod installer-path-part (instance (part string))
152-
"If the part is a string then just return it."
153-
part)
154-
155-
(defmethod installer-path-part (instance (part pathname))
156-
"If the part is already a pathname then just return it."
157-
part)
158-
159-
(defun installer-path (instance &rest parts)
160-
"Resolve each of the path parts then combine all into a single path using merge-pathnames."
161-
(reduce
162-
(lambda (previous part)
163-
(merge-pathnames
164-
(installer-path-part instance part)
165-
previous))
166-
parts
167-
:initial-value (make-pathname)))
83+
(defgeneric installer-path (instance name))
84+
85+
(defmethod installer-path (instance (name (eql :spec)))
86+
(merge-pathnames (make-pathname :name "kernel" :type "json")
87+
(installer-path instance :kernel)))
88+
89+
(defmethod installer-path (instance (name (eql :kernel)))
90+
(merge-pathnames (make-pathname :directory (list :relative
91+
"kernels"
92+
(installer-kernel-name instance)))
93+
(installer-path instance :jupyter)))
94+
95+
(defun add-prefix (instance path)
96+
(if (installer-prefix instance)
97+
(merge-pathnames (uiop:relativize-pathname-directory path)
98+
(truename (installer-prefix instance)))
99+
path))
100+
101+
(defmethod installer-path ((instance system-installer) (name (eql :root)))
102+
#+windows
103+
(uiop:getenv-absolute-directory "PROGRAMDATA")
104+
#-windows
105+
(make-pathname :directory (if (installer-local instance)
106+
'(:absolute "usr" "local" "share")
107+
'(:absolute "usr" "share"))))
108+
109+
(defmethod installer-path ((instance user-installer) (name (eql :root)))
110+
#+darwin
111+
(merge-pathnames (make-pathname :directory '(:relative "Library"))
112+
(uiop:getenv-pathname "HOME" :ensure-directory t))
113+
#+windows
114+
(uiop:get-folder-path :appdata)
115+
#-(or darwin windows)
116+
(uiop:xdg-data-home))
117+
118+
(defmethod installer-path ((instance system-installer) (name (eql :jupyter)))
119+
(add-prefix instance
120+
(or (installer-jupyter-path instance)
121+
(merge-pathnames (make-pathname :directory '(:relative "jupyter"))
122+
(installer-path instance :root)))))
123+
124+
(defmethod installer-path ((instance user-installer) (name (eql :jupyter)))
125+
(add-prefix instance
126+
(or (installer-jupyter-path instance)
127+
(merge-pathnames (make-pathname :directory '(:relative #+darwin "Jupyter"
128+
#-darwin "jupyter"))
129+
(installer-path instance :root)))))
130+
131+
(defmethod installer-path (instance (name (eql :program)))
132+
(add-prefix instance
133+
(or (installer-program-path instance)
134+
(merge-pathnames (make-pathname :directory (list :relative
135+
(format nil "~A-jupyter"
136+
(installer-kernel-name instance))))
137+
(installer-path instance :root)))))
138+
139+
(defmethod installer-path (instance (name (eql :image)))
140+
(merge-pathnames (make-pathname :name "image" :type #+windows "exe" #-windows :unspecific)
141+
(installer-path instance :program)))
142+
143+
(defmethod installer-path (instance (name (eql :bundle)))
144+
(merge-pathnames (make-pathname :name "bundle" :type "lisp")
145+
(installer-path instance :program)))
146+
147+
(defmethod installer-path (instance (name (eql :local-projects)))
148+
(merge-pathnames (make-pathname :directory (list :relative "local-projects"))
149+
(installer-path instance :program)))
150+
151+
(defmethod installer-path (instance (name pathname))
152+
name)
168153

169154
(defgeneric command-line (instance)
170155
(:documentation "Get the command line for an installer instance."))
171156

172157
(defmethod command-line ((instance user-image-installer))
173158
"Get the command for a user image installer."
174-
(list
175-
(namestring (installer-path instance :root :program :image))
176-
"{connection_file}"))
159+
(list (namestring (installer-path instance :image))
160+
"{connection_file}"))
177161

178162
(defgeneric copy-component (component dest)
179163
(:documentation "Copy a specific ASDF component to the destination."))
@@ -206,31 +190,33 @@
206190

207191
(defun install-local-systems (instance)
208192
"Install the local systems into local-projects."
209-
(let ((dest (installer-path instance :prefix :program :local-projects)))
210-
(format t "Installing local systems to ~A~%" dest)
211-
(dolist (system-sym (installer-local-systems instance))
212-
(alexandria:when-let ((system (asdf:find-system system-sym)))
213-
(copy-component system dest)))))
193+
(when (installer-local-systems instance)
194+
(let ((dest (installer-path instance :local-projects)))
195+
(format t "Installing local systems to ~A~%" dest)
196+
(ensure-directories-exist dest)
197+
(dolist (system-sym (installer-local-systems instance))
198+
(alexandria:when-let ((system (asdf:find-system system-sym)))
199+
(copy-component system dest))))))
214200

215201
(defun install-bundle (instance)
216202
"Install the Quicklisp bundle."
217-
(let ((dest (installer-path instance :prefix :program)))
203+
(let ((dest (installer-path instance :program)))
218204
(format t "Installing Quicklisp bundle to ~A~%" dest)
205+
(ensure-directories-exist dest)
219206
(funcall (fdefinition (find-symbol "BUNDLE-SYSTEMS" 'ql))
220207
(installer-systems instance) :to dest)))
221208

222209
(defun install-directories (instance)
223210
"Create all needed directories."
224211
(format t "Creating directories.~%")
225-
(alexandria:when-let ((prefix (installer-prefix instance)))
226-
(ensure-directories-exist prefix))
227-
(ensure-directories-exist (installer-path instance :prefix :kernel))
228-
(ensure-directories-exist (installer-path instance :prefix :program)))
212+
(alexandria:when-let ((installer-prefix (installer-prefix instance)))
213+
(ensure-directories-exist installer-prefix))
214+
(ensure-directories-exist (installer-path instance :kernel)))
229215

230216
(defun install-spec (instance)
231217
"Install the kernel spec file."
232218
(with-slots (display-name language) instance
233-
(let ((spec-path (installer-path instance :prefix :kernel :spec)))
219+
(let ((spec-path (installer-path instance :spec)))
234220
(format t "Installing kernel spec file ~A~%" spec-path)
235221
(with-open-file (stream spec-path :direction :output :if-exists :supersede)
236222
(shasht:write-json
@@ -244,11 +230,12 @@
244230
:empty-object))
245231
stream)))))
246232

247-
(defun install-resources (instance)
233+
(defun install-resources (instance &aux (kernel-path (installer-path instance :kernel)))
248234
"Install all kernel resources."
249-
(format t "Installing kernel resources to ~A.~%" (installer-path instance :prefix :kernel))
235+
(format t "Installing kernel resources to ~A.~%" kernel-path)
250236
(dolist (src (installer-resources instance))
251-
(alexandria:copy-file src (installer-path instance :prefix :kernel (file-namestring src)))))
237+
(alexandria:copy-file src (merge-pathnames (file-namestring src)
238+
kernel-path))))
252239

253240
(defgeneric install (instance)
254241
(:documentation "Install a kernel based on an installer instance."))
@@ -261,7 +248,7 @@
261248

262249
(defmethod install ((instance user-image-installer))
263250
"Create an image for the user image based kernels."
264-
(let ((prefixed-image-path (installer-path instance :prefix :program :image))
251+
(let ((prefixed-image-path (installer-path instance :image))
265252
(class (installer-class instance)))
266253
(setq uiop:*image-entry-point*
267254
`(lambda ()

0 commit comments

Comments
 (0)