1 | ;;;; TODO: move to a utility package |
---|
2 | (in-package :abcl/build) |
---|
3 | |
---|
4 | ;;; TODO remove |
---|
5 | (defun localize-executable-name (name) |
---|
6 | (let* ((p (if (pathnamep name) |
---|
7 | name |
---|
8 | (pathname name))) |
---|
9 | (type (pathname-type p))) |
---|
10 | (make-pathname :defaults p |
---|
11 | :type |
---|
12 | (if (uiop:os-windows-p) |
---|
13 | (when (null type) |
---|
14 | "exe") |
---|
15 | type)))) |
---|
16 | |
---|
17 | (defun possible-executable-names (name |
---|
18 | &key (suffixes '("exe" "cmd" "bat") suffixes-p)) |
---|
19 | (let* ((p (if (pathnamep name) |
---|
20 | name |
---|
21 | (pathname name))) |
---|
22 | (type (pathname-type p))) |
---|
23 | (declare (ignore type)) |
---|
24 | (unless (or (uiop:os-windows-p) suffixes-p) |
---|
25 | (return-from possible-executable-names |
---|
26 | (listify name))) |
---|
27 | (loop |
---|
28 | :for suffix :in suffixes |
---|
29 | :with result = (list p) |
---|
30 | :doing (push (make-pathname :defaults p :type suffix) |
---|
31 | result) |
---|
32 | :finally (return (nreverse result))))) |
---|
33 | |
---|
34 | (defun introspect-path-for (executable) |
---|
35 | (let ((which-command (if (uiop:os-windows-p) |
---|
36 | "where" |
---|
37 | "which"))) |
---|
38 | (when (ignore-errors |
---|
39 | (uiop:run-program (list which-command which-command) :output :string)) |
---|
40 | (dolist (p (possible-executable-names executable)) |
---|
41 | (let ((raw-result |
---|
42 | (ignore-errors (uiop:run-program |
---|
43 | (list which-command |
---|
44 | (namestring p)) |
---|
45 | :output :string)))) |
---|
46 | (when raw-result |
---|
47 | (let ((result (first (split-string raw-result #\Newline)))) |
---|
48 | (return-from introspect-path-for |
---|
49 | (values |
---|
50 | result |
---|
51 | (pathname result)))))))))) |
---|
52 | |
---|
53 | (defun probe-for-executable (directory executable) |
---|
54 | (dolist (executable (possible-executable-names executable)) |
---|
55 | (let ((pathname |
---|
56 | (probe-file |
---|
57 | (merge-pathnames executable directory)))) |
---|
58 | (when pathname |
---|
59 | (return-from probe-for-executable |
---|
60 | pathname))))) |
---|
61 | |
---|
62 | (defun split-string (string split-char) |
---|
63 | (loop :for i = 0 :then (1+ j) |
---|
64 | :as j = (position split-char string :test #'string-equal :start i) |
---|
65 | :collect (subseq string i j) |
---|
66 | :while j)) |
---|
67 | |
---|
68 | (defun stringify (thing) |
---|
69 | (cond |
---|
70 | ((pathnamep thing) |
---|
71 | (namestring thing)) |
---|
72 | ((stringp thing) |
---|
73 | thing) |
---|
74 | (t |
---|
75 | (error "Don't know how stringify ~a." thing)))) |
---|
76 | |
---|
77 | (defun listify (thing) |
---|
78 | (if (consp thing) |
---|
79 | thing |
---|
80 | (list thing))) |
---|
81 | |
---|
82 | (defun some-directory-containing (executable) |
---|
83 | ;; search path |
---|
84 | (let ((in-path (introspect-path-for executable))) |
---|
85 | (when in-path |
---|
86 | (return-from some-directory-containing |
---|
87 | in-path)) |
---|
88 | (dolist (d (if (uiop:os-windows-p) |
---|
89 | '(#p"c:/Program Files/") ;; TODO localize me! |
---|
90 | '(#p"/usr/local/bin/" #p"/opt/local/bin/" #p"/usr/bin/"))) |
---|
91 | (let* ((e (localize-executable-name |
---|
92 | (merge-pathnames executable d))) |
---|
93 | (p (probe-file e))) |
---|
94 | (when p |
---|
95 | (return-from some-directory-containing p)))))) |
---|
96 | |
---|
97 | (defun copy-directory-recursively (from to) |
---|
98 | (flet ((normalize-to-directory (p) |
---|
99 | (when (or (not (pathnamep p)) |
---|
100 | (not (and (null (pathname-name p)) |
---|
101 | (null (pathname-type p))))) |
---|
102 | (setf p (make-pathname :defaults p |
---|
103 | :name nil :type nil))) |
---|
104 | p)) |
---|
105 | (normalize-to-directory from) |
---|
106 | (normalize-to-directory to) |
---|
107 | (let ((wildcard (merge-pathnames "**/*" from))) |
---|
108 | (loop :for source :in (directory wildcard) |
---|
109 | :for relative = (enough-namestring source from) |
---|
110 | :for destination = (merge-pathnames relative to) |
---|
111 | :doing |
---|
112 | (progn |
---|
113 | (ensure-directories-exist destination) |
---|
114 | (when (or (pathname-name destination) |
---|
115 | (pathname-type destination)) |
---|
116 | (uiop:copy-file source destination))))))) |
---|
117 | |
---|
118 | |
---|
119 | |
---|
120 | |
---|
121 | |
---|
122 | |
---|
123 | |
---|
124 | |
---|