├── LICENSE ├── README.md ├── meta.ils ├── repo.ils ├── scf.ils ├── spam.ils └── spkg.ils /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SKILL Package Manager (SPAM) 2 | 3 | SPAM is a package management system for Cadence SKILL. 4 | 5 | ## Dependencies 6 | 7 | Following utilities must be installed: 8 | + wget 9 | + unzip 10 | 11 | SPAM has only been tested under Cadence Design Framework: 12 | + virtuoso version 6.1.7-64b 01/24/2018 13 | + SKILL 35.00 14 | 15 | ## Getting Started 16 | 17 | Download spam 18 | ```bash 19 | $ git clone https://github.com/rbzentrum/SPAM.git ~/.cadence/spam 20 | ``` 21 | into a directory of your choosing, for example ```~/.cadence/spam/```. 22 | 23 | Make sure environment variables ```SPAMHOMEPATH``` and ```SPAMPROJPATH``` are set either with 24 | ```bash 25 | $ export SPAMHOMEPATH=~/.cadence/spam 26 | $ export SPAMPROJPATH=/path/to/project 27 | ``` 28 | or in your ```.cdsinit``` 29 | ```scheme 30 | (setShellEnvVar "SPAMHOMEPATH" "~/.cadence/spam") 31 | (setShellEnvVar "SPAMPROJPATH" "/path/to/project") 32 | ``` 33 | and load ```spam.ils```. 34 | ```scheme 35 | (load "spam.ils") 36 | ``` 37 | 38 | ## Adding Repositories 39 | 40 | The repository definition for github is given in ```repo.ils```, 41 | just add others or private repositories in the same way to that list. 42 | Alternatively you can call ```spmDefineRepo``` at runtime: 43 | ```scheme 44 | (spmDefineRepo 45 | t_name 46 | t_metaUrl 47 | u_urlGenerator 48 | ) => r_repo 49 | ``` 50 | and add this ```r_repo``` object to ```(get SPAM 'repositories)```. 51 | 52 | ## Function Reference 53 | 54 | ### spamSearch 55 | ```scheme 56 | (spamSearch 57 | t_query 58 | ) => t | nil 59 | ``` 60 | Searches for packages with the names given by the string 't_query'. 61 | 62 | ### spamInstall 63 | ```scheme 64 | (spamInstall 65 | t_name 66 | [ t_name ] 67 | ... 68 | ) => t | nil 69 | ``` 70 | Installs the packages given by the strings 't_name'. 71 | If the installation was successful, t is returned. 72 | 73 | ### spamRemove 74 | ```scheme 75 | (spamRemove 76 | t_name 77 | [ t_name ] 78 | ... 79 | ) => t | nil 80 | ``` 81 | Removes the packages with the names given by the strings 't_name'. 82 | 83 | ### spamUpdate 84 | ```scheme 85 | (spamUpdate 86 | [t_name] 87 | ... 88 | ) => t | nil 89 | ``` 90 | Updates a given list of packages (t_name). 91 | If no packages are specified the meta database will be updated. 92 | 93 | ### spamInfo 94 | ```scheme 95 | (spamInfo 96 | t_name 97 | ) => t | nil 98 | ``` 99 | Prints information about the given package with name 't_name'. 100 | 101 | ### spamUse 102 | ```scheme 103 | (spamUse 104 | t_name 105 | [ t_name ] 106 | ... 107 | ) => t | nil 108 | ``` 109 | Includes the given packages in the given order into the current toplevel. 110 | -------------------------------------------------------------------------------- /meta.ils: -------------------------------------------------------------------------------- 1 | (list 2 | (spmDefinePkg "SPAM" "rbzentrum" "spam" "0.0.1" 3 | ?authors (list "Yannick Uhlmann") 4 | ?description (strcat "A package management system for Cadence SKILL.") 5 | ?url "https://github.com/rbzentrum/SPAM" 6 | ?dependencies nil 7 | ?requires (list 111) 8 | ?license (list nil 9 | 'name "MIT" 10 | 'text (strcat 11 | "MIT License\n" 12 | "Copyright (c) 2017 \n" 13 | "Permission is hereby granted, free of charge, to any person obtaining a copy\n" 14 | "of this software and associated documentation files (the \"Software\"), to deal\n" 15 | "in the Software without restriction, including without limitation the rights\n" 16 | "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n" 17 | "copies of the Software, and to permit persons to whom the Software is\n" 18 | "furnished to do so, subject to the following conditions:\n" 19 | "The above copyright notice and this permission notice shall be included in all\n" 20 | "copies or substantial portions of the Software.\n" 21 | "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n" 22 | "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n" 23 | "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n" 24 | "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n" 25 | "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n" 26 | "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n" 27 | "SOFTWARE.\n") 28 | 'url "https://raw.githubusercontent.com/rbzentrum/SAM/master/LICENSE") 29 | ?entry "spam.ils" 30 | ?environment nil 31 | ?repository "github") 32 | 33 | (spmDefinePkg "SAM" "rbzentrum" "spam" "1.0" 34 | ?authors (list "Florian Leber" "Tobias Wolfert") 35 | ?description (strcat "The SKILL Application Manager (SAM), " 36 | "is a new tool for Cadence Virtuoso that assists SKILL programmers " 37 | "in software development. This tool allows a very user-friendly " 38 | "organization and execution of source code. ") 39 | ?url "https://github.com/rbzentrum/SAM" 40 | ?dependencies nil 41 | ?requires (list 111) 42 | ?license (list nil 43 | 'name "MIT" 44 | 'text (strcat 45 | "MIT License\n" 46 | "Copyright (c) 2017 \n" 47 | "Permission is hereby granted, free of charge, to any person obtaining a copy\n" 48 | "of this software and associated documentation files (the \"Software\"), to deal\n" 49 | "in the Software without restriction, including without limitation the rights\n" 50 | "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n" 51 | "copies of the Software, and to permit persons to whom the Software is\n" 52 | "furnished to do so, subject to the following conditions:\n" 53 | "The above copyright notice and this permission notice shall be included in all\n" 54 | "copies or substantial portions of the Software.\n" 55 | "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n" 56 | "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n" 57 | "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n" 58 | "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n" 59 | "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n" 60 | "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n" 61 | "SOFTWARE.\n") 62 | 'url "https://raw.githubusercontent.com/rbzentrum/SAM/master/LICENSE") 63 | ?entry ".saminit" 64 | ?environment nil 65 | ?repository "github") 66 | 67 | (spmDefinePkg "SKILLFFI" "rbzentrum" "spam" "0.1.0" 68 | ?authors '("Yannick Uhlmann") 69 | ?description (strcat "With the Foreign Function Interface (FFI) for SKILL C-Type Libraries " 70 | "can be loaded and used within the SKILL environment.") 71 | ?url "https://rbzentrum.de/" 72 | ?dependencies nil 73 | ?requires (list 111) 74 | ?license (list nil 75 | 'name "MIT" 76 | 'text (strcat 77 | "MIT License\n\n 78 | Copyright (c) 2018\n\n 79 | Permission is hereby granted, free of charge, to any person obtaining a copy\n 80 | of this software and associated documentation files (the \"Software\"), to deal\n 81 | in the Software without restriction, including without limitation the rights\n 82 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n 83 | copies of the Software, and to permit persons to whom the Software is\n 84 | furnished to do so, subject to the following conditions:\n\n 85 | The above copyright notice and this permission notice shall be included in all\n 86 | copies or substantial portions of the Software.\n\n 87 | THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n 88 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n 89 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n 90 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n 91 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n 92 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n 93 | SOFTWARE.\n") 94 | 'url "LICENSE URL") 95 | ?entry "ffi.ils" 96 | ?environment (list "FFIPATH") 97 | ?repository "github") 98 | 99 | (spmDefinePkg "ml2tikz" "rbzentrum" "spam" "1.0.0" 100 | ?authors '("Matthias Schweikardt") 101 | ?description (strcat "Cadence SKILL function, which can be used to create a tikzpicture of a maskLayout." 102 | "This is especially useful for theses, publications and presentation.") 103 | ?url "https://rbzentrum.de/" 104 | ?dependencies nil 105 | ?requires (list 111) 106 | ?license (list nil 107 | 'name "MIT" 108 | 'text (strcat 109 | "MIT License\n\n 110 | Copyright (c) 2018\n\n 111 | Permission is hereby granted, free of charge, to any person obtaining a copy\n 112 | of this software and associated documentation files (the \"Software\"), to deal\n 113 | in the Software without restriction, including without limitation the rights\n 114 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n 115 | copies of the Software, and to permit persons to whom the Software is\n 116 | furnished to do so, subject to the following conditions:\n\n 117 | The above copyright notice and this permission notice shall be included in all\n 118 | copies or substantial portions of the Software.\n\n 119 | THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n 120 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n 121 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n 122 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n 123 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n 124 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n 125 | SOFTWARE.\n") 126 | 'url "LICENSE URL") 127 | ?entry "ml2tikz.il" 128 | ?environment nil 129 | ?repository "github") 130 | 131 | (spmDefinePkg "libvc" "rbzentrum" "spam" "1.0.0" 132 | ?authors '("Yannick Uhlmann") 133 | ?description (strcat "his library acts as the C++ counterpart to ipcSkillProcess.") 134 | ?url "https://rbzentrum.de/" 135 | ?dependencies nil 136 | ?requires (list 111) 137 | ?license (list nil 138 | 'name "MIT" 139 | 'text (strcat 140 | "MIT License\n\n 141 | Copyright (c) 2018\n\n 142 | Permission is hereby granted, free of charge, to any person obtaining a copy\n 143 | of this software and associated documentation files (the \"Software\"), to deal\n 144 | in the Software without restriction, including without limitation the rights\n 145 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n 146 | copies of the Software, and to permit persons to whom the Software is\n 147 | furnished to do so, subject to the following conditions:\n\n 148 | The above copyright notice and this permission notice shall be included in all\n 149 | copies or substantial portions of the Software.\n\n 150 | THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n 151 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n 152 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n 153 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n 154 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n 155 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n 156 | SOFTWARE.\n") 157 | 'url "LICENSE URL") 158 | ?entry "example.ils" 159 | ?environment nil 160 | ?repository "github") 161 | ) 162 | -------------------------------------------------------------------------------- /repo.ils: -------------------------------------------------------------------------------- 1 | (list 2 | (spmDefineRepo 3 | "github" 4 | "https://raw.githubusercontent.com/rbzentrum/SPAM/master/meta.ils" 5 | (lambda (t_name t_group t_branch) 6 | (strcat "https://github.com/" t_group "/" t_name "/archive/" t_branch ".zip")) 7 | ) 8 | ) 9 | -------------------------------------------------------------------------------- /scf.ils: -------------------------------------------------------------------------------- 1 | /*============================================================* 2 | * 3 | * SKILL Common Functions 4 | * 5 | * Purpose: Collection of common SKILL functions suitable for use in any project. 6 | * 7 | * Author: Yannick Uhlmann 8 | * Email: yannick.uhlmann@reutlingen-university.de 9 | * 10 | * Revision: 0.0.1 (2019-01-18) 11 | * 12 | * Copyright 2019 Reutlingen University (Germany) 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 15 | * and associated documentation files (the "Software"), to deal in the Software without restriction, 16 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, 17 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 18 | * furnished to do so, subject to the following conditions: 19 | * 20 | * The above copyright notice and this permission notice shall be included in all copies or substantial 21 | * portions of the Software. 22 | * 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 24 | * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 25 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 27 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | * 29 | *=============================================================*/ 30 | 31 | ; Define Scheme style boolean values 32 | (define \#f nil) 33 | (define \#t t) 34 | 35 | ; last :: (list) => element 36 | ; Parameters: l_collection can be any list. 37 | ; Return: The last element of the list, 38 | ; effectively the reverse of car. 39 | (defun lastElem (l_collection) 40 | (cond 41 | ((null (cdr l_collection)) (car l_collection)) 42 | (t (lastElem (cdr l_collection)))) 43 | ) 44 | 45 | ; init :: (list) => list 46 | ; Parameters: l_collection can be any list. 47 | ; Return: The same list except the last element, 48 | ; effectively the reverse of cdr. 49 | (defun init (l_collection) 50 | (cond 51 | ((eq (car l_collection) (lastElem l_collection)) nil) 52 | (t (cons (car l_collection) (init (cdr l_collection))))) 53 | ) 54 | 55 | ; reduce :: (function value list) => value 56 | ; Parameters: su_predicate :: (value value) => value, 57 | ; takes 2 parameters, the current item in the collection and the accumulator. 58 | ; g_init is any start value for the accumulator, can be nil or 0 59 | ; l_collection is the collection to be reduced 60 | ; Return: The accumulator from the final interation. 61 | (defun reduce (su_predicate g_init l_collection) 62 | (cond 63 | ((null l_collection) g_init) 64 | (t (funcall su_predicate (car l_collection) (reduce su_predicate g_init (cdr l_collection))))) 65 | ) 66 | 67 | ; filter :: (function list) => list 68 | ; Parameters: su_predicate :: (value) => bool, used to filter the list 69 | ; l_collection will be filtered 70 | ; Return: A filtered list 71 | (defun filter (su_predicate l_collection) 72 | (cond 73 | ((null l_collection) '()) 74 | ((funcall su_predicate (car l_collection)) 75 | (cons (car l_collection) (filter su_predicate (cdr l_collection)))) 76 | (t (filter su_predicate (cdr l_collection)))) 77 | ) 78 | 79 | ; transform :: (function list) => list 80 | ; Paramters: su_predicate :: (value) => value, takes 1 element of the list and applys a function to it 81 | ; l_collection will be transformed 82 | ; Return: A transofrmed list 83 | (defun transform (su_predicate l_collection) 84 | (cond 85 | ((null l_collection) '()) 86 | (t (cons (funcall su_predicate (car l_collection)) (transform su_predicate (cdr l_collection))))) 87 | ) 88 | 89 | ; hsrtExtractFileName :: (string) => list 90 | ; Parameters: t_path is a path as a string. 91 | ; Returns: A list containing the file name and extension. 92 | (defun hsrtExtractFileName (t_path) 93 | (let ((t_fn (parseString (lastElem (parseString t_path "/")) "."))) 94 | (list (reduce 'strcat "" (init t_fn)) (lastElem t_fn))) 95 | ) 96 | 97 | ; hsrtReadFile :: (inport string) => string 98 | ; Parameters: p_file the inport from which is read 99 | ; l_content previously read lines 100 | ; Return: A single string with the files contents 101 | (defun hsrtReadFile (p_file @optional (l_content '())) 102 | (let (line) 103 | (cond 104 | ((null (gets line p_file)) (close p_file) l_content) 105 | (t (hsrtReadFile p_file (reduce 'cons (list line) l_content)))) 106 | ) 107 | ) 108 | 109 | ; hsrtEscape :: (string pattern ) => string 110 | ; Parameters: t_string is containes characters to be escaped. 111 | ; t_pattern is the string or character that needs to be escaped 112 | ; Return: The string with the given pattern escaped 113 | (defun hsrtEscape (t_string t_pattern) 114 | (cond 115 | ((eq (strcmp t_pattern "%") 0) 116 | (buildString (parseString t_string t_pattern) (symbolToString '\%\%))) 117 | ((eq (strcmp t_pattern "\"") 0) 118 | nil) 119 | (t 120 | (buildString (parseString t_string t_pattern) 121 | (evalstring (sprintf nil "\"\\%s\"" t_pattern))))) 122 | ) 123 | 124 | ; hsrtEvalFile :: (string) => any 125 | ; Parameters: t_path is the path to a .il/.ils file 126 | ; Return: Evaluation of the last expression in the file 127 | (defun hsrtEvalFile (t_path) 128 | (let ((p_in (infile t_path))) 129 | (cond 130 | (p_in (let ((x_eval (eval (read p_in)))) 131 | (close p_in) 132 | x_eval)) 133 | (t (warn "HSRT - Could not read file %s" t_path)))) 134 | ) 135 | 136 | ; hsrtReadCid :: (processId string) => string 137 | ; Parameters: id of child process o_pid, returned from ipc call 138 | ; string for recursive adding 139 | ; Return: accumulated string until pid termination 140 | (defun hsrtReadCid (o_pid @optional (t_read "")) 141 | (let ((t_data (ipcReadProcess o_pid 1))) 142 | (if t_data 143 | (hsrtReadCid o_pid (strcat t_read t_data)) 144 | t_read)) 145 | ) 146 | 147 | ; hsrtWriteCid :: (processId string) = > string 148 | ; Parameters: PID of child process, started with ipcBeginProcess call 149 | ; string of data to write to given PID 150 | ; Return: Response from PID 151 | (defun hsrtWriteCid (o_pid t_data) 152 | (when (ipcWriteProcess o_pid t_data) 153 | (ipcReadProcess o_pid 1)) 154 | ) 155 | 156 | ; defconst :: (symbol value) => value 157 | ; Parameters: s_name is the symbol name of the variable 158 | ; x_value is an arbitrary value which is assigned to the variable 159 | ; Return: The value assigned to s_name 160 | (defun defconst (s_name g_value) 161 | (define s_name g_value) 162 | (setVarWriteProtect s_name) 163 | (symeval s_name) 164 | ) 165 | 166 | ; cowsay :: (string) => bool 167 | ; Parameters: t_say is the text, the cow says 168 | ; Return: Whatever printf returns 169 | (defun cowsay (t_say) 170 | (printf (hsrtReadCid (ipcBeginProcess (strcat "echo " t_say " | cowsay")))) 171 | ) 172 | 173 | ; figlet :: (string) => bool 174 | ; Parameters: t_text is the text, printed with figlet 175 | ; Return: Whatever printf returns 176 | (defun figlet (t_text) 177 | (printf (hsrtReadCid (ipcBeginProcess (strcat "echo " t_text " | figlet")))) 178 | ) 179 | -------------------------------------------------------------------------------- /spam.ils: -------------------------------------------------------------------------------- 1 | ; SKILL Package Manager (SPAM) 2 | ; 3 | ; Purpose: The SKILL Package Manager (SPAM), is a package 4 | ; management system for Cadence Virtuoso to streamline 5 | ; the installation and distribution of SKILL code. 6 | ; With this, developers may easily obtain 7 | ; and use SKILL code provided by others. 8 | ; Users are able to install extensions and other 9 | ; software written in SKILL to enhance their 10 | ; Cadence Design Environment. 11 | ; 12 | ; Author: Yannick Uhlmann 13 | ; Email: yannick.uhlmann@reutlingen-university.de 14 | ; 15 | ; Revision: 0.0.1 (2018-11-07) 16 | ; 17 | ; Copyright 2018 Reutlingen University (Germany) 18 | ; 19 | ; Permission is hereby granted, free of charge, to any person obtaining a copy of this software 20 | ; and associated documentation files (the "Software"), to deal in the Software without restriction, 21 | ; including without limitation the rights to use, copy, modify, merge, publish, distribute, 22 | ; sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 23 | ; furnished to do so, subject to the following conditions: 24 | ; 25 | ; The above copyright notice and this permission notice shall be included in all copies or substantial 26 | ; portions of the Software. 27 | ; 28 | ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 29 | ; NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 30 | ; IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 31 | ; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 32 | ; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 33 | 34 | (define spamHelp (lambda (@optional (cmd nil)) 35 | (cond 36 | ((or (equal cmd 'spamSearch) (equal cmd 'search)) 37 | (printf "\n(spamSearch\n\tt_query\n)\n=> t | nil\n\n") 38 | (printf "Searches for packages with the names given by the string 't_query'.\n")) 39 | ((or (equal cmd 'spamInstall) (equal cmd 'install)) 40 | (printf "\n(spamInstall\n\tpackages ...\n)\n=> t | nil\n\n") 41 | (printf "Installs the packages given by the strings 'packages'. ") 42 | (printf "If the installation was successful, t is returned.\n")) 43 | ((or (equal cmd 'spamRemove) (equal cmd 'remove)) 44 | (printf "\n(spamRemove\n\tpackages\n)\n=> t | nil\n\n") 45 | (printf "Removes the packages with the names given by the strings 'packages.\n")) 46 | ((or (equal cmd 'spamUpdate) (equal cmd 'update)) 47 | (printf "\n(spamUpdate\n\t[packages]\n)\n=> t | nil\n\n") 48 | (printf "Updates a given list of packages.") 49 | (printf "If no packages are specified, every installed package will be updated.\n")) 50 | ((or (equal cmd 'spamInfo) (equal cmd 'info)) 51 | (printf "\n(spamInfo\n\tt_name\n)\n=> t | nil\n\n") 52 | (printf "Prints information about the given package 't_name'.\n")) 53 | ((or (equal cmd 'spamUse) (equal cmd 'use)) 54 | (printf "\n(spamUse\n\tpackages\n)\n=> t | nil\n\n") 55 | (printf "Includes the given packages into the current toplevel") 56 | (printf "in the given order.\n")) 57 | (t 58 | (printf "\n\"%s\" is not a SPAM function, searching SKILL API...\n" cmd) 59 | (evalstring (strcat "(help " (symbolToString cmd) ")")))) 60 | )) 61 | 62 | (define spamSearch (lambda (@optional (t_query nil)) 63 | (if t_query 64 | (let ((l_matching (filter 65 | (lambda (name) 66 | (nindex (lowerCase name) (lowerCase t_query))) 67 | (arrayref (get SPAM 'packages) ?))) 68 | (l_packages (transform 69 | (lambda (name) 70 | (arrayref (get SPAM 'packages) name)) 71 | (arrayref (get SPAM 'packages) ?))) 72 | (u_printpkg (lambda (pkg) 73 | (printf "%s(%s) :\t\t%s\n" 74 | (get pkg 'name) 75 | (get pkg 'repository) 76 | (get pkg 'description))))) 77 | (printf "\n================ Matching Package Name ======================\n") 78 | (transform 79 | (lambda (name) 80 | (let ((pkg (arrayref (get SPAM 'packages) name))) 81 | (u_printpkg pkg))) 82 | l_matching) 83 | (printf "\n============= Matching Package Description ==================\n") 84 | (transform 85 | (lambda (pkg) 86 | (if (nindex (lowerCase (get pkg 'description)) (lowerCase t_query)) 87 | (u_printpkg pkg))) 88 | (filter 89 | (lambda (pkg) 90 | (not (lindex l_matching (get pkg 'name)))) 91 | l_packages)) 92 | (printf "\n=============================================================\n")) 93 | (spamHelp 'spamSearch)) 94 | )) 95 | 96 | (define spmUrlAlive (lambda (t_url) 97 | (shell (strcat "wget -q --no-check-certificate --spider " t_url)) 98 | )) 99 | 100 | (define spmPkgUrl (lambda (t_pkg) 101 | (let ((r_repo (arrayref (get SPAM 'repositories) 102 | (get (arrayref (get SPAM 'packages) t_pkg) 'repository)))) 103 | (if r_repo 104 | ((get r_repo 'generate) 105 | t_pkg 106 | (get (arrayref (get SPAM 'packages) t_pkg) 'group) 107 | (get (arrayref (get SPAM 'packages) t_pkg) 'branch)) 108 | (error "SPAM - Could not generate URL for %s." t_pkg))) 109 | )) 110 | 111 | (define spmDownload (lambda (t_name) 112 | (let ((t_branch (get (arrayref (get SPAM 'packages) t_name) 'branch))) 113 | (if t_branch 114 | (let ((t_url (spmPkgUrl t_name)) 115 | (t_pkg (strcat t_name "-" t_branch ".zip"))) 116 | (if (spmUrlAlive t_url) 117 | (let 118 | ((cid_dl (hsrtReadCid (ipcBeginProcess 119 | (strcat "cd " (get SPAM 'path) "; " 120 | "wget -q --no-check-certificate -O " t_pkg 121 | " " t_url))))) 122 | (cond 123 | ((null cid_dl) 124 | (error "SPAM - Failed to download %s!" t_name)) 125 | (t 126 | (printf "SPAM - Successfully downloaded %s!\n" t_name) 127 | t_pkg))) 128 | (error "SPAM - Could not find package %s with url %s" t_name t_url))) 129 | (error "SPAM - Could not find branch %N for %s." t_branch t_name))) 130 | )) 131 | 132 | (define spmResolve (lambda (t_name @optional (l_resolved '())) 133 | (let ((l_deps (get (arrayref (get SPAM 'packages) t_name) 'depends))) 134 | (if (not (null l_deps)) 135 | (cons t_name (reduce 136 | (lambda (dep res) 137 | (if (not (member dep l_resolved)) 138 | (append (spmResolve dep (append res l_resolved)) res))) 139 | '() l_deps)) 140 | (list t_name))) 141 | )) 142 | 143 | (define spamInstall (lambda (@rest packages) 144 | (if (greaterp (length packages) 0) 145 | (let ((l_tree (reverse 146 | (reduce 147 | (lambda (pkg res) 148 | (append (spmResolve pkg res) res)) 149 | '() packages)))) 150 | (printf "SPAM - Resolving dependecies... \n") 151 | (printf "SPAM - Installing") 152 | (transform 153 | (lambda (t_name) (printf " -> %s" t_name)) 154 | l_tree) 155 | (printf "\n") 156 | (if (transform 157 | (lambda (t_pkg) 158 | (if t_pkg 159 | (spkgInstall (strcat (get SPAM 'path) "/" t_pkg) (get SPAM 'path)) 160 | (error "SPAM - One or more packages could not be installed!"))) 161 | (transform 'spmDownload l_tree)) 162 | (shell (strcat "rm " (get SPAM 'path) "/*.zip")) 163 | (error "SPAM - Error during installation, operation aborted.")) 164 | ) 165 | (spamHelp 'spamInstall)) 166 | )) 167 | 168 | (define spmPkgPath (lambda (t_name) 169 | (strcat (get SPAM 'path) "/" t_name "-" 170 | (get (arrayref 171 | (get SPAM 'packages) t_name) 'branch)) 172 | )) 173 | 174 | (define spmMetaPath (lambda (t_repo) 175 | (strcat (get SPAM 'path) "/" t_repo "_meta.ils") 176 | )) 177 | 178 | (define spmUninstall (lambda (t_name) 179 | (let 180 | ((t_path (spmPkgPath t_name))) 181 | (cond 182 | ((isDir t_path) 183 | (if (shell (strcat "rm -rf " t_path)) 184 | (printf "SPAM - Removed %s\n" t_name) 185 | (error "SPAM - Failed to remove %s" t_name))) 186 | (t (warn "SPAM - Package %s isn't even installed, nothing to remove" t_name)))) 187 | )) 188 | 189 | (define spamRemove (lambda (@rest packages) 190 | (if (greaterp (length packages) 0) 191 | (let () 192 | (printf "SPAM - Removing packages, be aware that this may break dependent packages.\n") 193 | (if (member nil (transform 'spmUninstall packages)) 194 | (warn "SPAM - One or more packages could not be removed!") 195 | (printf "SPAM - Successfully uninstalled packages!\n"))) 196 | (spamHelp 'spamRemove)) 197 | )) 198 | 199 | (define spmSyncMeta (lambda (t_repo) 200 | (let ((t_meta (get (arrayref (get SPAM 'repositories) t_repo) 'meta))) 201 | (if (spmUrlAlive t_meta) 202 | (let ((cid_dl (hsrtReadCid (ipcBeginProcess 203 | (strcat "cd " (get SPAM 'path) "; " 204 | "wget -q --no-check-certificate -O " (strcat t_repo "_meta.ils") 205 | " " t_meta))))) 206 | (cond 207 | ((null cid_dl) 208 | (error "SPAM - Failed to update %s's meta data!" t_repo)) 209 | (t 210 | (transform 211 | (lambda (pkg) 212 | (setarray (get SPAM 'packages) (get pkg 'name) pkg)) 213 | (hsrtEvalFile (spmMetaPath t_repo))) 214 | (printf "SPAM - Successfully Updated %s's meta database.\n" t_repo)))) 215 | (warn "SPAM - Could not update %s's meta data with %s" t_repo t_meta))) 216 | )) 217 | 218 | (define spmPkgVersion (lambda (t_pkg) 219 | (let ((r_pkg (hsrtEvalFile (strcat (spmPkgPath t_pkg) "/package.ils")))) 220 | (get r_pkg 'version)) 221 | )) 222 | 223 | (define spmPkgInstalled (lambda (t_name) 224 | (isFile (strcat (spmPkgPath t_name) "/package.ils")) 225 | )) 226 | 227 | (define spmPkgUpToDate (lambda (t_name) 228 | (let ((localV (transform 229 | 'evalstring 230 | (parseString (spmPkgVersion t_name) "."))) 231 | (remoteV (transform 232 | 'evalstring 233 | (parseString (get (arrayref (get SPAM 'packages) t_name) 'version) ".")))) 234 | (reduce 235 | (lambda (v l) 236 | (let ((local (car v)) (remote (cadr v))) 237 | (if l 238 | (geqp local remote) 239 | (greaterp local remote)))) 240 | t (mapcar 'list localV remoteV))) 241 | )) 242 | 243 | (define spamUpdate (lambda (@rest packages) 244 | (if (greaterp (length packages) 0) 245 | (let () 246 | ;(when ((get SPAM 'metaExpired) 7) 247 | ; (spamUpdate)) 248 | (transform 249 | (lambda (pkg) 250 | (let ((t_path (spmPkgPath pkg)) 251 | (r_repo (arrayref (get SPAM 'repositories) 252 | (get (arrayref (get SPAM 'packages) pkg) 'repository)))) 253 | (cond 254 | ((and (isDir t_path) 255 | (spmPkgInstalled pkg) 256 | (spmUrlAlive (spmPkgUrl pkg))) 257 | (if (spmPkgUpToDate pkg) 258 | (printf "SPAM - Package %s is already up to date.\n" pkg) 259 | (let ((t_src (spmDownload pkg))) 260 | (spmUninstall pkg) 261 | (spkgInstall (strcat (get SPAM 'path) "/" t_src) 262 | (get SPAM 'path)) 263 | (shell (strcat "rm " (get SPAM 'path) "/*.zip"))))) 264 | (t (error "SPAM - Could not update %s!" pkg))))) 265 | packages)) 266 | (transform 267 | 'spmSyncMeta 268 | (get (get SPAM 'repositories) '?))) 269 | )) 270 | 271 | (define spamInfo (lambda (@optional (t_name nil)) 272 | (if t_name 273 | (let ((r_pkg (arrayref (get SPAM 'packages) t_name))) 274 | (cond 275 | ((not (null r_pkg)) 276 | (printf "Name: %s\n" t_name) 277 | (printf "Branch: %s\n" (or (get r_pkg 'branch) "Not Specified")) 278 | (printf "Version: %s\n" (or (get r_pkg 'version) "Not Specified")) 279 | (printf "Environment: %s\n" (or (buildString (get r_pkg 'environment) ", ") 280 | "Not Specified")) 281 | (printf "Required Lincenses: %s\n" (or (buildString (transform 282 | (lambda (lic) 283 | (sprintf nil "%n" lic)) 284 | (get r_pkg 'requires)) ", ") 285 | "Not Specified")) 286 | (printf "Description: %s\n\n" (or (get r_pkg 'description) "Not Specified"))) 287 | (t (warn "SPAM - No matching packages to list.\n")))) 288 | (spamHelp 'spamInfo)) 289 | )) 290 | 291 | (define spamUse (lambda (@rest packages) 292 | (if (greaterp (length packages) 0) 293 | (transform 294 | (lambda (t_name) 295 | (let ((r_pkg (arrayref (get SPAM 'packages) t_name))) 296 | (load (strcat (spmPkgPath t_name) "/" 297 | (get r_pkg 'entry))))) 298 | packages) 299 | (spamHelp 'spamUse)) 300 | )) 301 | 302 | (define spmReadLicenseFile (lambda (p_licenseFile @optional (l_licenses '())) 303 | (let (licenseLine) 304 | (if (gets licenseLine p_licenseFile) 305 | (if (nindex licenseLine " : ") 306 | (spmReadLicenseFile p_licenseFile (cons (car (parseString licenseLine ":")) l_licenses)) 307 | (spmReadLicenseFile p_licenseFile l_licenses)) 308 | (transform (lambda (l) (car (parseString l " "))) l_licenses)) 309 | ) 310 | )) 311 | 312 | (define spmDefineRepo (lambda (t_name t_meta u_generator) 313 | (setarray (get SPAM 'repositories) t_name 314 | (make_SREPO ?name t_name 315 | ?meta t_meta 316 | ?generate u_generator 317 | ?expire 7)) 318 | )) 319 | 320 | (define spmDefinePkg (lambda (t_name t_group t_branch t_version 321 | @key (authors (list "FIXME NAME")) 322 | (description "FIXME: add description.") 323 | (requires (list 111)) 324 | (url "https://example.com/FIXME") 325 | (license (list nil 'name "MIT" 'text "LICENSE TEXT" 'url "LICENSE URL")) 326 | (dependencies (list (list "rbzentrum/spam" "master"))) 327 | (entry (strcat t_name ".il")) 328 | (environment nil) 329 | (repository "github")) 330 | ;(setarray (get SPAM 'packages) t_name 331 | (make_SPKG ?name t_name 332 | ?group t_group 333 | ?branch t_branch 334 | ?version t_version 335 | ?authors authors 336 | ?description description 337 | ?requires requires 338 | ?url url 339 | ?license license 340 | ?depends dependencies 341 | ?entry entry 342 | ?environment environment 343 | ?repository repository) 344 | ;) 345 | )) 346 | 347 | (define spmReload (lambda () 348 | (load (strcat (getShellEnvVar "SPAMHOMEPATH") "/spam.ils")))) 349 | 350 | (define SPAM (list nil 351 | 'home nil 352 | 'path nil 353 | 'repositories (makeTable "SKILL Package Repository DB") 354 | 'packages (makeTable "SKILL Packages Meta DB") 355 | 'licenses (lambda (@optional 356 | (p_file (infile (strcat (getShellEnvVar "ICHOME") "/share/license/products.dfII")))) 357 | (transform 358 | (lambda (line) (car (parseString line " "))) 359 | (filter (lambda (line) (nindex line " : ")) 360 | (hsrtReadFile p_file)))) 361 | 'license (lambda () 362 | (transform 363 | 'printf 364 | (hsrtReadFile (infile (strcat (get SPAM 'home) "/LICENSE"))))) 365 | 'install spamInstall 366 | 'use spamUse 367 | 'update spamUpdate 368 | 'remove spamRemove 369 | 'search spamSearch 370 | 'help spamHelp 371 | 'metaExpired (lambda (n_days) 372 | (greaterp n_days (quotient 373 | (difference 374 | (stringToTime (getCurrentTime)) 375 | (fileTimeModified (strcat (get SPAM 'path) "/meta.ils"))) 376 | 60 60 24))) 377 | 'reload (lambda () 378 | (load (strcat (get SPAM 'home) "/spam.ils"))) 379 | )) 380 | 381 | (defstruct SREPO name meta generate expire) 382 | 383 | (let ((t_home (getShellEnvVar "SPAMHOMEPATH")) 384 | (t_project (getShellEnvVar "SPAMPROJPATH"))) 385 | (printf "Loading spam.ils\n") 386 | (cond 387 | ((and t_home (isDir t_home)) 388 | (putprop SPAM t_home 'home) 389 | (load (strcat t_home "/scf.ils")) 390 | (load (strcat t_home "/spkg.ils")) 391 | (if (and t_project (isDir t_project)) 392 | (let ((t_pkgPath (strcat t_project "/skill_packages"))) 393 | (unless (isDir t_pkgPath) (createDir t_pkgPath)) 394 | (putprop SPAM t_pkgPath 'path) 395 | (unless (isFile (strcat t_pkgPath "/meta.ils")) 396 | (shell (strcat "cp " t_home "/meta.ils " t_pkgPath))) 397 | (unless (isFile (strcat t_pkgPath "/repo.ils")) 398 | (shell (strcat "cp " t_home "/repo.ils " t_pkgPath))) 399 | (load (if (isFile (strcat t_project "/repo.ils")) 400 | (strcat t_project "/repo.ils") 401 | (strcat t_home "/repo.ils"))) 402 | (spamUpdate) 403 | (transform 404 | (lambda (repo) 405 | (let ((l_meta (hsrtEvalFile (spmMetaPath repo)))) 406 | (transform 407 | (lambda (pkg) 408 | (setarray (get SPAM 'packages) (get pkg 'name) pkg)) 409 | (or l_meta 410 | (hsrtEvalFile (if (isFile (strcat t_pkgPath "/meta.ils")) 411 | (strcat t_pkgPath "/meta.ils") 412 | (strcat t_home "/meta.ils"))))))) 413 | (get (get SPAM 'repositories) ?))) 414 | (error "SPAM" "Env Var 'SPAMPROJPATH' must be set."))) 415 | (t (error "SPAM" "Env Var 'SPAMHOMEPATH' must be set."))) 416 | ) 417 | -------------------------------------------------------------------------------- /spkg.ils: -------------------------------------------------------------------------------- 1 | ;; SKILL Package (SPKG) 2 | ;; 3 | ;; Purpose: The SKILL Package (SPKG) is a packaging format 4 | ;; for modularized SKILL code distribution. 5 | ;; 6 | ;; Author: Yannick Uhlmann 7 | ;; Email: yannick.uhlmann@reutlingen-university.de 8 | ;; 9 | ;; Revision: 0.0.1 (2018-11-07) 10 | ;; 11 | ;; Copyright 2018 Reutlingen University (Germany) 12 | ;; 13 | ;; Permission is hereby granted, free of charge, to any person obtaining a copy of this software 14 | ;; and associated documentation files (the "Software"), to deal in the Software without restriction, 15 | ;; including without limitation the rights to use, copy, modify, merge, publish, distribute, 16 | ;; sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 17 | ;; furnished to do so, subject to the following conditions: 18 | ;; 19 | ;; The above copyright notice and this permission notice shall be included in all copies or substantial 20 | ;; portions of the Software. 21 | ;; 22 | ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 23 | ;; NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24 | ;; IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | ;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | ;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | (defstruct SPKG 29 | name 30 | group 31 | branch 32 | version 33 | authors 34 | description 35 | url 36 | requires 37 | license 38 | depends 39 | installed 40 | entry 41 | environment 42 | repository 43 | ) 44 | 45 | (defun spkgCreateManifest (r_pkg) 46 | (strcat 47 | "(spmDefinePkg \"" (get r_pkg 'name) "\" \"" 48 | (get r_pkg 'group) "\" \"" 49 | (get r_pkg 'branch) "\" \"" 50 | (get r_pkg 'version) "\"\n" 51 | (reduce 52 | (lambda (field data) 53 | (sprintf nil "%s\t?%s %N\n" data field (get r_pkg field))) 54 | "" 55 | (filter 56 | (lambda (field) 57 | (unless (or (eq field 'name) 58 | (eq field 'group) 59 | (eq field 'branch)) 60 | field)) 61 | (get r_pkg '?))) 62 | ")") 63 | ) 64 | 65 | (defun spkgCreate (t_path r_pkg) 66 | (if (and (isDir t_path) (isFile (strcat t_path "/" (get r_pkg 'entry)))) 67 | (let ((p_out (outfile (strcat t_path "/package.ils")))) 68 | (if p_out 69 | (let ((t_pkg (strcat (get r_pkg 'name) "-" (get r_pkg 'branch))) 70 | (t_manifest (spkgCreateManifest r_pkg))) 71 | (fprintf p_out "%s" t_manifest) 72 | (unless (eq t_pkg (lastElem (parseString t_path "/"))) 73 | (shell (strcat "cd " t_path "/../; ln -s " t_path " " t_pkg))) 74 | (shell (strcat "cd " t_path "/../; zip " t_pkg 75 | " -qr " t_pkg "/ -x " t_pkg "/.git/**\\*")) 76 | (unless (eq t_pkg (lastElem (parseString t_path "/"))) 77 | (shell (strcat "cd " t_path "/../; unlink " t_pkg))) 78 | (close p_out) 79 | (simplifyFilename (strcat t_path "/../" t_pkg ".zip"))) 80 | (error "SPKG - Inaccessible entry point!"))) 81 | (error "SPKG - Invalid direcotry %s" t_path)) 82 | ) 83 | 84 | (defun spkgContent (t_path) 85 | (if (and (isFile t_path) (isReadable t_path)) 86 | (let ((t_query (hsrtReadCid (ipcBeginProcess (strcat "unzip -v " t_path))))) 87 | (printf (hsrtEscape t_query "%"))) 88 | (error "SPKG - Content: '%s' is not a valid Path to a SKILL Package" t_path)) 89 | ) 90 | 91 | (defun spkgManifest (t_path) 92 | (if (and (isFile t_path) (isReadable t_path)) 93 | (evalstring (hsrtReadCid (ipcBeginProcess 94 | (strcat "unzip -qqp " t_path 95 | " " (car (hsrtExtractFileName t_path)) 96 | "/package.ils | cat"))) 'ils) 97 | (error "SPKG - Manifest: '%s' is not a valid Path to a SKILL Package" t_path)) 98 | ) 99 | 100 | (defun spkgQuery (t_path) 101 | (if (and (isFile t_path) (isReadable t_path)) 102 | (let ((r_manifest (spkgManifest t_path))) 103 | (printf 104 | (reduce 105 | (lambda (field query) 106 | (sprintf query "%s%s: %N\n" query 107 | (symbolToString field) 108 | (get r_manifest field))) 109 | "" (get r_manifest '?)))) 110 | (error "SPKG - Query: '%s' is not a valid Path to a SKILL Package" t_path)) 111 | ) 112 | 113 | (defun spkgInstall (t_src @optional (t_dst (pwd))) 114 | (if (and (isFile t_src) (isReadable t_src)) 115 | (let ((t_dir (simplifyFilename (strcat t_dst 116 | "/" (get (spkgManifest t_src) 'name) 117 | "-" (get (spkgManifest t_src) 'branch))))) 118 | (if (shell (strcat "cd " t_dst "; unzip -qq " t_src)) 119 | (if (isFile (strcat t_dir "/install.ils")) 120 | (let ((u_installer (hsrtEvalFile (strcat t_dir "/install.ils")))) 121 | (cond 122 | ((equal (typep u_installer) 'funobj) 123 | (funcall u_installer t_dir)) 124 | (u_installer t) 125 | (t nil))) 126 | t) 127 | (error "SPAM - Error when unzipping %s." t_src))) 128 | (error "SPKG - Installation failed, invalid source: '%s'" t_src)) 129 | ) 130 | --------------------------------------------------------------------------------