bundle.lisp - clic - Clic is an command line interactive client for gopher written in Common LISP (HTM) git clone git://bitreich.org/clic/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/clic/ (DIR) Log (DIR) Files (DIR) Refs (DIR) Tags (DIR) README (DIR) LICENSE --- bundle.lisp (6978B) --- 1 (cl:in-package #:cl-user) 2 3 (eval-when (:compile-toplevel :load-toplevel :execute) 4 (require "asdf") 5 (unless (find-package '#:asdf) 6 (error "ASDF could not be required"))) 7 8 (let ((indicator '#:ql-bundle-v1) 9 (searcher-name '#:ql-bundle-searcher) 10 (base (make-pathname :name nil :type nil 11 :defaults #. (or *compile-file-truename* 12 *load-truename*)))) 13 (labels ((file-lines (file) 14 (with-open-file (stream file) 15 (loop for line = (read-line stream nil) 16 while line 17 collect line))) 18 (relative (pathname) 19 (merge-pathnames pathname base)) 20 (pathname-timestamp (pathname) 21 #+clisp 22 (nth-value 2 (ext:probe-pathname pathname)) 23 #-clisp 24 (file-write-date pathname)) 25 (system-table (table pathnames) 26 (dolist (pathname pathnames table) 27 (setf (gethash (pathname-name pathname) table) 28 (relative pathname)))) 29 30 (initialize-bundled-systems-table (table data-source) 31 (system-table table 32 (mapcar (lambda (line) 33 (merge-pathnames line data-source)) 34 (file-lines data-source)))) 35 36 (local-projects-system-pathnames (data-source) 37 (let ((files (directory (merge-pathnames "**/*.asd" 38 data-source)))) 39 (stable-sort (sort files #'string< :key #'namestring) 40 #'< 41 :key (lambda (file) 42 (length (namestring file)))))) 43 (initialize-local-projects-table (table data-source) 44 (system-table table (local-projects-system-pathnames data-source))) 45 46 (make-table (&key data-source init-function) 47 (let ((table (make-hash-table :test 'equalp))) 48 (setf (gethash "/data-source" table) 49 data-source 50 (gethash "/timestamp" table) 51 (pathname-timestamp data-source) 52 (gethash "/init" table) 53 init-function) 54 table)) 55 56 (tcall (table key &rest args) 57 (let ((fun (gethash key table))) 58 (unless (and fun (functionp fun)) 59 (error "Unknown function key ~S" key)) 60 (apply fun args))) 61 (created-timestamp (table) 62 (gethash "/timestamp" table)) 63 (data-source-timestamp (table) 64 (pathname-timestamp (data-source table))) 65 (data-source (table) 66 (gethash "/data-source" table)) 67 68 (stalep (table) 69 ;; FIXME: Handle newly missing data sources? 70 (< (created-timestamp table) 71 (data-source-timestamp table))) 72 (meta-key-p (key) 73 (and (stringp key) 74 (< 0 (length key)) 75 (char= (char key 0) #\/))) 76 (clear (table) 77 ;; Don't clear "/foo" keys 78 (maphash (lambda (key value) 79 (declare (ignore value)) 80 (unless (meta-key-p key) 81 (remhash key table))) 82 table)) 83 (initialize (table) 84 (tcall table "/init" table (data-source table)) 85 (setf (gethash "/timestamp" table) 86 (pathname-timestamp (data-source table))) 87 table) 88 (update (table) 89 (clear table) 90 (initialize table)) 91 (lookup (system-name table) 92 (when (stalep table) 93 (update table)) 94 (values (gethash system-name table))) 95 96 (search-function (system-name) 97 (let ((tables (get searcher-name indicator))) 98 (dolist (table tables) 99 (let* ((result (lookup system-name table)) 100 (probed (and result (probe-file result)))) 101 (when probed 102 (return probed)))))) 103 104 (make-bundled-systems-table () 105 (initialize 106 (make-table :data-source (relative "system-index.txt") 107 :init-function #'initialize-bundled-systems-table))) 108 (make-bundled-local-projects-systems-table () 109 (let ((data-source (relative "bundled-local-projects/system-index.txt"))) 110 (when (probe-file data-source) 111 (initialize 112 (make-table :data-source data-source 113 :init-function #'initialize-bundled-systems-table))))) 114 (make-local-projects-table () 115 (initialize 116 (make-table :data-source (relative "local-projects/") 117 :init-function #'initialize-local-projects-table))) 118 119 (=matching-data-sources (tables) 120 (let ((data-sources (mapcar #'data-source tables))) 121 (lambda (table) 122 (member (data-source table) data-sources 123 :test #'equalp)))) 124 125 (check-for-existing-searcher (searchers) 126 (block done 127 (dolist (searcher searchers) 128 (when (symbolp searcher) 129 (let ((plist (symbol-plist searcher))) 130 (loop for key in plist by #'cddr 131 when 132 (and (symbolp key) (string= key indicator)) 133 do 134 (setf indicator key) 135 (setf searcher-name searcher) 136 (return-from done t))))))) 137 138 (clear-asdf (table) 139 (maphash (lambda (system-name pathname) 140 (declare (ignore pathname)) 141 (asdf:clear-system system-name)) 142 table))) 143 144 (let ((existing (check-for-existing-searcher 145 asdf:*system-definition-search-functions*))) 146 (let* ((local (make-local-projects-table)) 147 (bundled-local-projects 148 (make-bundled-local-projects-systems-table)) 149 (bundled (make-bundled-systems-table)) 150 (new-tables (remove nil (list local 151 bundled-local-projects 152 bundled))) 153 (existing-tables (get searcher-name indicator)) 154 (filter (=matching-data-sources new-tables))) 155 (setf (get searcher-name indicator) 156 (append new-tables (delete-if filter existing-tables))) 157 (map nil #'clear-asdf new-tables)) 158 (unless existing 159 (setf (symbol-function searcher-name) #'search-function) 160 (push searcher-name asdf:*system-definition-search-functions*))) 161 t))