├── .travis.yml ├── CMakeLists.txt ├── COPYRIGHT ├── README.md ├── cmake ├── dist.cmake └── lua.cmake ├── dist.info ├── dist ├── config.lua.in ├── dep.lua ├── fetch.lua ├── init.lua ├── log.lua ├── manifest.lua ├── package.lua ├── persist.lua └── sys.lua ├── doc ├── index.html ├── luadoc.css └── modules │ ├── dist.dep.html │ ├── dist.fetch.html │ ├── dist.html │ ├── dist.log.html │ ├── dist.manifest.html │ ├── dist.package.html │ ├── dist.persist.html │ └── dist.sys.html └── luadist /.travis.yml: -------------------------------------------------------------------------------- 1 | # 2 | # LuaDist Travis-CI Hook 3 | # 4 | 5 | # Since CMake is not directly supported we use erlang VMs 6 | language: erlang 7 | 8 | # Try using multiple Lua Implementations 9 | env: 10 | - LUA="" # Use automatic dependencies 11 | - LUA="luajit" # Try with LuaJIT 12 | # - CMAKE="-DCMAKE_VARIABLE=value" 13 | # - LUA="lua-5.1.5" 14 | 15 | # Allow luajit to fail 16 | matrix: 17 | allow_failures: 18 | - env: LUA="luajit" 19 | 20 | # We need CMake and LuaDist 21 | install: 22 | - export MODULE=`basename $PWD` 23 | - sudo apt-get install cmake 24 | - git clone git://github.com/LuaDist/bootstrap.git _luadist 25 | - cd _luadist 26 | - git submodule update --init 27 | - ./bootstrap 28 | - export LUADIST=$PWD/_install/bin/luadist 29 | - cd $HOME 30 | 31 | # Use LuaDist to deploy the module 32 | script: 33 | - $LUADIST _test install $LUA $MODULE-scm $CMAKE -verbose=true -debug=true -test=true 34 | 35 | # Execute additional tests or commands 36 | #after_script: 37 | # - [run additional test commans] 38 | 39 | # Only watch the master branch 40 | branches: 41 | only: 42 | - master 43 | 44 | # Notify the LuaDist Dev group if needed 45 | notifications: 46 | recipients: 47 | - luadist-dev@googlegroups.com 48 | email: 49 | on_success: change 50 | on_failure: always -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2012 LuaDist. 2 | # Created by Peter Drahoš 3 | # Redistribution and use of this file is allowed according to the terms of the MIT license. 4 | # For details see the COPYRIGHT file distributed with LuaDist. 5 | # Please note that the package source code is licensed under its own license. 6 | 7 | # C type needed for correct library suffix and prefix detection 8 | project ( luadist C ) 9 | cmake_minimum_required ( VERSION 2.6 ) 10 | include ( cmake/dist.cmake ) 11 | include ( lua ) 12 | 13 | ## LuaDist settings 14 | # Host specific setup 15 | set ( DETECTED_TYPE ${CMAKE_SYSTEM_PROCESSOR} ) 16 | set ( DETECTED_ARCH ${CMAKE_SYSTEM_NAME} ) 17 | 18 | if ( CYGWIN ) 19 | # Make sure Cygwin uses correct arch and type. 20 | set ( DETECTED_TYPE x86 ) 21 | set ( DETECTED_ARCH Cygwin ) 22 | elseif ( MSVC ) 23 | set ( DETECTED_TYPE MSVC32 ) 24 | endif () 25 | 26 | set ( DIST_VERSION 1.2 ) 27 | set ( DIST_TYPE ${DETECTED_TYPE} CACHE STRING "Host system type. PLEASE CHECK!" FORCE ) 28 | set ( DIST_ARCH ${DETECTED_ARCH} CACHE STRING "Host system architecture. PLEASE CHECK!" FORCE ) 29 | 30 | set ( DIST_LUA_LIBRARY "/${INSTALL_LIB}/${CMAKE_SHARED_LIBRARY_PREFIX}lua${CMAKE_SHARED_LIBRARY_SUFFIX}" ) 31 | if ( WIN32 OR CYGWIN ) 32 | # On Windows use the import library 33 | set ( DIST_LUA_LIBRARY "/${INSTALL_LIB}/${CMAKE_IMPORT_LIBRARY_PREFIX}lua${CMAKE_IMPORT_LIBRARY_SUFFIX}" ) 34 | endif () 35 | 36 | configure_file ( dist/config.lua.in ${CMAKE_CURRENT_BINARY_DIR}/dist/config.lua @ONLY ) 37 | 38 | install_lua_executable ( luadist luadist ) 39 | install_lua_module ( dist.init dist/init.lua ) 40 | install_lua_module ( dist.dep dist/dep.lua ) 41 | install_lua_module ( dist.fetch dist/fetch.lua ) 42 | install_lua_module ( dist.log dist/log.lua ) 43 | install_lua_module ( dist.manifest dist/manifest.lua ) 44 | install_lua_module ( dist.package dist/package.lua ) 45 | install_lua_module ( dist.persist dist/persist.lua ) 46 | install_lua_module ( dist.sys dist/sys.lua ) 47 | install_lua_module ( dist.config ${CMAKE_CURRENT_BINARY_DIR}/dist/config.lua ) 48 | 49 | install_data ( COPYRIGHT README.md ) 50 | install_doc ( doc/ ) 51 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | LuaDist License 2 | --------------- 3 | 4 | LuaDist is licensed under the terms of the MIT license reproduced below. 5 | This means that LuaDist is free software and can be used for both academic 6 | and commercial purposes at absolutely no cost. 7 | 8 | Modules and Lua bindings contained in "dist" packages have their 9 | individual copyright. 10 | 11 | =============================================================================== 12 | 13 | Copyright (C) 2007-2010 LuaDist. 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy 16 | of this software and associated documentation files (the "Software"), to deal 17 | in the Software without restriction, including without limitation the rights 18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | copies of the Software, and to permit persons to whom the Software is 20 | furnished to do so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in 23 | all copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 31 | THE SOFTWARE. 32 | 33 | =============================================================================== 34 | 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | LuaDist - Automated CMake based distribution for the Lua programming language 2 | ============= 3 | 4 | [![Build Status](https://secure.travis-ci.org/LuaDist/luadist.png?branch=master)](http://travis-ci.org/LuaDist/luadist) 5 | 6 | LuaDist is a CMake-based multi-platform standalone Lua distribution 7 | providing a build environment and module management. For more information 8 | please visit http://www.luadist.org. 9 | 10 | Availability 11 | ------------ 12 | 13 | LuaDist is freely available for both academic and commercial purposes under 14 | MIT license. See COPYRIGHT for details. Please see individual packages for 15 | their license. 16 | 17 | Installation 18 | ------------ 19 | 20 | LuaDist relies on CMake (www.cmake.org) for building. The build process 21 | consists of two stages. First stage in the CMake based bootstrap that will 22 | build and install all needed components. Second stage uses the bootstrap 23 | environment to build and install the final release. This process is needed to 24 | ensure LuaDist remains self update-able and endorses its correct deployment 25 | structure. 26 | 27 | To build LuaDist please use the provided [Bootstrap](http://github.com/LuaDist/bootstrap) repository. Alternatively look up updated install instructions on www.luadist.org 28 | 29 | Running 30 | ------- 31 | 32 | LuaDist installs to a standalone directory and should be able to execute on 33 | most systems supported systems without the need to set up any environment. 34 | 35 | To invoke the luadist CLI simply use: 36 | 37 | ```bash 38 | $ cd luadist/bin 39 | $ ./luadist 40 | ``` 41 | 42 | Any other binaries distributed using LuaDist can also be invoked directly 43 | 44 | ```bash 45 | $ cd luadist/bin 46 | $ ./luac 47 | $ ./lua 48 | ``` 49 | 50 | For advanced use please consult the [Project Wiki](https://github.com/LuaDist/Repository/wiki) 51 | 52 | Compatibility 53 | ------------- 54 | 55 | LuaDist was designed to support Unix/Linux, Mac and Windows 56 | installs. 57 | 58 | Following systems are supported: 59 | Linux, x86, x86_64 (Ubuntu tested) 60 | OS X, Intel, x86, x86_64 (10.7) 61 | Windows 7, MinGW compiler, 32bit 62 | Windows 7, Cygwin, 32bit 63 | 64 | Authors 65 | ------- 66 | 67 | Peter Drahoš 68 | Peter Kapec 69 | David Manura 70 | Jozef Lang 71 | Matej Lipták 72 | 73 | NOTE: LuaDist installable components "dists" contain their copyright and 74 | legal information. Authors of the contents of these components are not 75 | related to the LuaDist project. 76 | 77 | Thanks 78 | ------ 79 | 80 | We would like to thank the following people who directly or indirectly 81 | contributed to the project. 82 | 83 | Roberto Ierusalimschy 84 | Waldemar Celes 85 | Luiz Henrique de Figueiredo 86 | Mike Pall 87 | Hisham Muhamad 88 | Karl M. Syrings 89 | David Manura 90 | André Carregal 91 | Tomás Guisasola 92 | Diego Nehab 93 | All "dist" authors and maintainers. 94 | 95 | Thank You. 96 | -------------------------------------------------------------------------------- /cmake/dist.cmake: -------------------------------------------------------------------------------- 1 | # LuaDist CMake utility library. 2 | # Provides sane project defaults and macros common to LuaDist CMake builds. 3 | # 4 | # Copyright (C) 2007-2012 LuaDist. 5 | # by David Manura, Peter Drahoš 6 | # Redistribution and use of this file is allowed according to the terms of the MIT license. 7 | # For details see the COPYRIGHT file distributed with LuaDist. 8 | # Please note that the package source code is licensed under its own license. 9 | 10 | ## Extract information from dist.info 11 | if ( NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/dist.info ) 12 | message ( FATAL_ERROR 13 | "Missing dist.info file (${CMAKE_CURRENT_SOURCE_DIR}/dist.info)." ) 14 | endif () 15 | file ( READ ${CMAKE_CURRENT_SOURCE_DIR}/dist.info DIST_INFO ) 16 | if ( "${DIST_INFO}" STREQUAL "" ) 17 | message ( FATAL_ERROR "Failed to load dist.info." ) 18 | endif () 19 | # Reads field `name` from dist.info string `DIST_INFO` into variable `var`. 20 | macro ( _parse_dist_field name var ) 21 | string ( REGEX REPLACE ".*${name}[ \t]?=[ \t]?[\"']([^\"']+)[\"'].*" "\\1" 22 | ${var} "${DIST_INFO}" ) 23 | if ( ${var} STREQUAL DIST_INFO ) 24 | message ( FATAL_ERROR "Failed to extract \"${var}\" from dist.info" ) 25 | endif () 26 | endmacro () 27 | # 28 | _parse_dist_field ( name DIST_NAME ) 29 | _parse_dist_field ( version DIST_VERSION ) 30 | _parse_dist_field ( license DIST_LICENSE ) 31 | _parse_dist_field ( author DIST_AUTHOR ) 32 | _parse_dist_field ( maintainer DIST_MAINTAINER ) 33 | _parse_dist_field ( url DIST_URL ) 34 | _parse_dist_field ( desc DIST_DESC ) 35 | message ( "DIST_NAME: ${DIST_NAME}") 36 | message ( "DIST_VERSION: ${DIST_VERSION}") 37 | message ( "DIST_AUTHOR: ${DIST_LICENSE}") 38 | message ( "DIST_AUTHOR: ${DIST_AUTHOR}") 39 | message ( "DIST_MAINTAINER: ${DIST_MAINTAINER}") 40 | message ( "DIST_URL: ${DIST_URL}") 41 | message ( "DIST_DESC: ${DIST_DESC}") 42 | string ( REGEX REPLACE ".*depends[ \t]?=[ \t]?[\"']([^\"']+)[\"'].*" "\\1" 43 | DIST_DEPENDS ${DIST_INFO} ) 44 | if ( DIST_DEPENDS STREQUAL DIST_INFO ) 45 | set ( DIST_DEPENDS "" ) 46 | endif () 47 | message ( "DIST_DEPENDS: ${DIST_DEPENDS}") 48 | ## 2DO: Parse DIST_DEPENDS and try to install Dependencies with automatically using externalproject_add 49 | 50 | 51 | ## INSTALL DEFAULTS (Relative to CMAKE_INSTALL_PREFIX) 52 | # Primary paths 53 | set ( INSTALL_BIN bin CACHE PATH "Where to install binaries to." ) 54 | set ( INSTALL_LIB lib CACHE PATH "Where to install libraries to." ) 55 | set ( INSTALL_INC include CACHE PATH "Where to install headers to." ) 56 | set ( INSTALL_ETC etc CACHE PATH "Where to store configuration files" ) 57 | set ( INSTALL_SHARE share CACHE PATH "Directory for shared data." ) 58 | 59 | # Secondary paths 60 | option ( INSTALL_VERSION 61 | "Install runtime libraries and executables with version information." OFF) 62 | set ( INSTALL_DATA ${INSTALL_SHARE}/${DIST_NAME} CACHE PATH 63 | "Directory the package can store documentation, tests or other data in.") 64 | set ( INSTALL_DOC ${INSTALL_DATA}/doc CACHE PATH 65 | "Recommended directory to install documentation into.") 66 | set ( INSTALL_EXAMPLE ${INSTALL_DATA}/example CACHE PATH 67 | "Recommended directory to install examples into.") 68 | set ( INSTALL_TEST ${INSTALL_DATA}/test CACHE PATH 69 | "Recommended directory to install tests into.") 70 | set ( INSTALL_FOO ${INSTALL_DATA}/etc CACHE PATH 71 | "Where to install additional files") 72 | 73 | # Tweaks and other defaults 74 | # Setting CMAKE to use loose block and search for find modules in source directory 75 | set ( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true ) 76 | set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH} ) 77 | option ( BUILD_SHARED_LIBS "Build shared libraries" ON ) 78 | 79 | # In MSVC, prevent warnings that can occur when using standard libraries. 80 | if ( MSVC ) 81 | add_definitions ( -D_CRT_SECURE_NO_WARNINGS ) 82 | endif () 83 | 84 | # RPath and relative linking 85 | option ( USE_RPATH "Use relative linking." ON) 86 | if ( USE_RPATH ) 87 | string ( REGEX REPLACE "[^!/]+" ".." UP_DIR ${INSTALL_BIN} ) 88 | set ( CMAKE_SKIP_BUILD_RPATH FALSE CACHE STRING "" FORCE ) 89 | set ( CMAKE_BUILD_WITH_INSTALL_RPATH FALSE CACHE STRING "" FORCE ) 90 | set ( CMAKE_INSTALL_RPATH $ORIGIN/${UP_DIR}/${INSTALL_LIB} 91 | CACHE STRING "" FORCE ) 92 | set ( CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE CACHE STRING "" FORCE ) 93 | set ( CMAKE_INSTALL_NAME_DIR @executable_path/${UP_DIR}/${INSTALL_LIB} 94 | CACHE STRING "" FORCE ) 95 | endif () 96 | 97 | ## MACROS 98 | # Parser macro 99 | macro ( parse_arguments prefix arg_names option_names) 100 | set ( DEFAULT_ARGS ) 101 | foreach ( arg_name ${arg_names} ) 102 | set ( ${prefix}_${arg_name} ) 103 | endforeach () 104 | foreach ( option ${option_names} ) 105 | set ( ${prefix}_${option} FALSE ) 106 | endforeach () 107 | 108 | set ( current_arg_name DEFAULT_ARGS ) 109 | set ( current_arg_list ) 110 | foreach ( arg ${ARGN} ) 111 | set ( larg_names ${arg_names} ) 112 | list ( FIND larg_names "${arg}" is_arg_name ) 113 | if ( is_arg_name GREATER -1 ) 114 | set ( ${prefix}_${current_arg_name} ${current_arg_list} ) 115 | set ( current_arg_name ${arg} ) 116 | set ( current_arg_list ) 117 | else () 118 | set ( loption_names ${option_names} ) 119 | list ( FIND loption_names "${arg}" is_option ) 120 | if ( is_option GREATER -1 ) 121 | set ( ${prefix}_${arg} TRUE ) 122 | else () 123 | set ( current_arg_list ${current_arg_list} ${arg} ) 124 | endif () 125 | endif () 126 | endforeach () 127 | set ( ${prefix}_${current_arg_name} ${current_arg_list} ) 128 | endmacro () 129 | 130 | 131 | # install_executable ( executable_targets ) 132 | # Installs any executables generated using "add_executable". 133 | # USE: install_executable ( lua ) 134 | # NOTE: subdirectories are NOT supported 135 | set ( CPACK_COMPONENT_RUNTIME_DISPLAY_NAME "${DIST_NAME} Runtime" ) 136 | set ( CPACK_COMPONENT_RUNTIME_DESCRIPTION 137 | "Executables and runtime libraries. Installed into ${INSTALL_BIN}." ) 138 | macro ( install_executable ) 139 | foreach ( _file ${ARGN} ) 140 | if ( INSTALL_VERSION ) 141 | set_target_properties ( ${_file} PROPERTIES VERSION ${DIST_VERSION} 142 | SOVERSION ${DIST_VERSION} ) 143 | endif () 144 | install ( TARGETS ${_file} RUNTIME DESTINATION ${INSTALL_BIN} 145 | COMPONENT Runtime ) 146 | endforeach() 147 | endmacro () 148 | 149 | # install_library ( library_targets ) 150 | # Installs any libraries generated using "add_library" into apropriate places. 151 | # USE: install_library ( libexpat ) 152 | # NOTE: subdirectories are NOT supported 153 | set ( CPACK_COMPONENT_LIBRARY_DISPLAY_NAME "${DIST_NAME} Development Libraries" ) 154 | set ( CPACK_COMPONENT_LIBRARY_DESCRIPTION 155 | "Static and import libraries needed for development. Installed into ${INSTALL_LIB} or ${INSTALL_BIN}." ) 156 | macro ( install_library ) 157 | foreach ( _file ${ARGN} ) 158 | if ( INSTALL_VERSION ) 159 | set_target_properties ( ${_file} PROPERTIES VERSION ${DIST_VERSION} 160 | SOVERSION ${DIST_VERSION} ) 161 | endif () 162 | install ( TARGETS ${_file} 163 | RUNTIME DESTINATION ${INSTALL_BIN} COMPONENT Runtime 164 | LIBRARY DESTINATION ${INSTALL_LIB} COMPONENT Runtime 165 | ARCHIVE DESTINATION ${INSTALL_LIB} COMPONENT Library ) 166 | endforeach() 167 | endmacro () 168 | 169 | # helper function for various install_* functions, for PATTERN/REGEX args. 170 | macro ( _complete_install_args ) 171 | if ( NOT("${_ARG_PATTERN}" STREQUAL "") ) 172 | set ( _ARG_PATTERN PATTERN ${_ARG_PATTERN} ) 173 | endif () 174 | if ( NOT("${_ARG_REGEX}" STREQUAL "") ) 175 | set ( _ARG_REGEX REGEX ${_ARG_REGEX} ) 176 | endif () 177 | endmacro () 178 | 179 | # install_header ( files/directories [INTO destination] ) 180 | # Install a directories or files into header destination. 181 | # USE: install_header ( lua.h luaconf.h ) or install_header ( GL ) 182 | # USE: install_header ( mylib.h INTO mylib ) 183 | # For directories, supports optional PATTERN/REGEX arguments like install(). 184 | set ( CPACK_COMPONENT_HEADER_DISPLAY_NAME "${DIST_NAME} Development Headers" ) 185 | set ( CPACK_COMPONENT_HEADER_DESCRIPTION 186 | "Headers needed for development. Installed into ${INSTALL_INC}." ) 187 | macro ( install_header ) 188 | parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} ) 189 | _complete_install_args() 190 | foreach ( _file ${_ARG_DEFAULT_ARGS} ) 191 | if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" ) 192 | install ( DIRECTORY ${_file} DESTINATION ${INSTALL_INC}/${_ARG_INTO} 193 | COMPONENT Header ${_ARG_PATTERN} ${_ARG_REGEX} ) 194 | else () 195 | install ( FILES ${_file} DESTINATION ${INSTALL_INC}/${_ARG_INTO} 196 | COMPONENT Header ) 197 | endif () 198 | endforeach() 199 | endmacro () 200 | 201 | # install_data ( files/directories [INTO destination] ) 202 | # This installs additional data files or directories. 203 | # USE: install_data ( extra data.dat ) 204 | # USE: install_data ( image1.png image2.png INTO images ) 205 | # For directories, supports optional PATTERN/REGEX arguments like install(). 206 | set ( CPACK_COMPONENT_DATA_DISPLAY_NAME "${DIST_NAME} Data" ) 207 | set ( CPACK_COMPONENT_DATA_DESCRIPTION 208 | "Application data. Installed into ${INSTALL_DATA}." ) 209 | macro ( install_data ) 210 | parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} ) 211 | _complete_install_args() 212 | foreach ( _file ${_ARG_DEFAULT_ARGS} ) 213 | if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" ) 214 | install ( DIRECTORY ${_file} 215 | DESTINATION ${INSTALL_DATA}/${_ARG_INTO} 216 | COMPONENT Data ${_ARG_PATTERN} ${_ARG_REGEX} ) 217 | else () 218 | install ( FILES ${_file} DESTINATION ${INSTALL_DATA}/${_ARG_INTO} 219 | COMPONENT Data ) 220 | endif () 221 | endforeach() 222 | endmacro () 223 | 224 | # INSTALL_DOC ( files/directories [INTO destination] ) 225 | # This installs documentation content 226 | # USE: install_doc ( doc/ doc.pdf ) 227 | # USE: install_doc ( index.html INTO html ) 228 | # For directories, supports optional PATTERN/REGEX arguments like install(). 229 | set ( CPACK_COMPONENT_DOCUMENTATION_DISPLAY_NAME "${DIST_NAME} Documentation" ) 230 | set ( CPACK_COMPONENT_DOCUMENTATION_DESCRIPTION 231 | "Application documentation. Installed into ${INSTALL_DOC}." ) 232 | macro ( install_doc ) 233 | parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} ) 234 | _complete_install_args() 235 | foreach ( _file ${_ARG_DEFAULT_ARGS} ) 236 | if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" ) 237 | install ( DIRECTORY ${_file} DESTINATION ${INSTALL_DOC}/${_ARG_INTO} 238 | COMPONENT Documentation ${_ARG_PATTERN} ${_ARG_REGEX} ) 239 | else () 240 | install ( FILES ${_file} DESTINATION ${INSTALL_DOC}/${_ARG_INTO} 241 | COMPONENT Documentation ) 242 | endif () 243 | endforeach() 244 | endmacro () 245 | 246 | # install_example ( files/directories [INTO destination] ) 247 | # This installs additional examples 248 | # USE: install_example ( examples/ exampleA ) 249 | # USE: install_example ( super_example super_data INTO super) 250 | # For directories, supports optional PATTERN/REGEX argument like install(). 251 | set ( CPACK_COMPONENT_EXAMPLE_DISPLAY_NAME "${DIST_NAME} Examples" ) 252 | set ( CPACK_COMPONENT_EXAMPLE_DESCRIPTION 253 | "Examples and their associated data. Installed into ${INSTALL_EXAMPLE}." ) 254 | macro ( install_example ) 255 | parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} ) 256 | _complete_install_args() 257 | foreach ( _file ${_ARG_DEFAULT_ARGS} ) 258 | if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" ) 259 | install ( DIRECTORY ${_file} DESTINATION ${INSTALL_EXAMPLE}/${_ARG_INTO} 260 | COMPONENT Example ${_ARG_PATTERN} ${_ARG_REGEX} ) 261 | else () 262 | install ( FILES ${_file} DESTINATION ${INSTALL_EXAMPLE}/${_ARG_INTO} 263 | COMPONENT Example ) 264 | endif () 265 | endforeach() 266 | endmacro () 267 | 268 | # install_test ( files/directories [INTO destination] ) 269 | # This installs tests and test files, DOES NOT EXECUTE TESTS 270 | # USE: install_test ( my_test data.sql ) 271 | # USE: install_test ( feature_x_test INTO x ) 272 | # For directories, supports optional PATTERN/REGEX argument like install(). 273 | set ( CPACK_COMPONENT_TEST_DISPLAY_NAME "${DIST_NAME} Tests" ) 274 | set ( CPACK_COMPONENT_TEST_DESCRIPTION 275 | "Tests and associated data. Installed into ${INSTALL_TEST}." ) 276 | macro ( install_test ) 277 | parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} ) 278 | _complete_install_args() 279 | foreach ( _file ${_ARG_DEFAULT_ARGS} ) 280 | if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" ) 281 | install ( DIRECTORY ${_file} DESTINATION ${INSTALL_TEST}/${_ARG_INTO} 282 | COMPONENT Test ${_ARG_PATTERN} ${_ARG_REGEX} ) 283 | else () 284 | install ( FILES ${_file} DESTINATION ${INSTALL_TEST}/${_ARG_INTO} 285 | COMPONENT Test ) 286 | endif () 287 | endforeach() 288 | endmacro () 289 | 290 | # install_foo ( files/directories [INTO destination] ) 291 | # This installs optional or otherwise unneeded content 292 | # USE: install_foo ( etc/ example.doc ) 293 | # USE: install_foo ( icon.png logo.png INTO icons) 294 | # For directories, supports optional PATTERN/REGEX argument like install(). 295 | set ( CPACK_COMPONENT_OTHER_DISPLAY_NAME "${DIST_NAME} Unspecified Content" ) 296 | set ( CPACK_COMPONENT_OTHER_DESCRIPTION 297 | "Other unspecified content. Installed into ${INSTALL_FOO}." ) 298 | macro ( install_foo ) 299 | parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} ) 300 | _complete_install_args() 301 | foreach ( _file ${_ARG_DEFAULT_ARGS} ) 302 | if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" ) 303 | install ( DIRECTORY ${_file} DESTINATION ${INSTALL_FOO}/${_ARG_INTO} 304 | COMPONENT Other ${_ARG_PATTERN} ${_ARG_REGEX} ) 305 | else () 306 | install ( FILES ${_file} DESTINATION ${INSTALL_FOO}/${_ARG_INTO} 307 | COMPONENT Other ) 308 | endif () 309 | endforeach() 310 | endmacro () 311 | 312 | ## CTest defaults 313 | 314 | ## CPack defaults 315 | set ( CPACK_GENERATOR "ZIP" ) 316 | set ( CPACK_STRIP_FILES TRUE ) 317 | set ( CPACK_PACKAGE_NAME "${DIST_NAME}" ) 318 | set ( CPACK_PACKAGE_VERSION "${DIST_VERSION}") 319 | set ( CPACK_PACKAGE_VENDOR "LuaDist" ) 320 | set ( CPACK_COMPONENTS_ALL Runtime Library Header Data Documentation Example Other ) 321 | include ( CPack ) 322 | -------------------------------------------------------------------------------- /cmake/lua.cmake: -------------------------------------------------------------------------------- 1 | # LuaDist CMake utility library for Lua. 2 | # 3 | # Copyright (C) 2007-2012 LuaDist. 4 | # by David Manura, Peter Drahos 5 | # Redistribution and use of this file is allowed according to the terms of the MIT license. 6 | # For details see the COPYRIGHT file distributed with LuaDist. 7 | # Please note that the package source code is licensed under its own license. 8 | 9 | set ( INSTALL_LMOD ${INSTALL_LIB}/lua 10 | CACHE PATH "Directory to install Lua modules." ) 11 | set ( INSTALL_CMOD ${INSTALL_LIB}/lua 12 | CACHE PATH "Directory to install Lua binary modules." ) 13 | 14 | option ( SKIP_LUA_WRAPPER 15 | "Do not build and install Lua executable wrappers." OFF) 16 | 17 | # List of (Lua module name, file path) pairs. 18 | # Used internally by add_lua_test. Built by add_lua_module. 19 | set ( _lua_modules ) 20 | 21 | # utility function: appends path `path` to path `basepath`, properly 22 | # handling cases when `path` may be relative or absolute. 23 | macro ( _append_path basepath path result ) 24 | if ( IS_ABSOLUTE "${path}" ) 25 | set ( ${result} "${path}" ) 26 | else () 27 | set ( ${result} "${basepath}/${path}" ) 28 | endif () 29 | endmacro () 30 | 31 | # install_lua_executable ( target source ) 32 | # Automatically generate a binary wrapper for lua application and install it 33 | # The wrapper and the source of the application will be placed into /bin 34 | # If the application source did not have .lua suffix then it will be added 35 | # USE: lua_executable ( sputnik src/sputnik.lua ) 36 | macro ( install_lua_executable _name _source ) 37 | get_filename_component ( _source_name ${_source} NAME_WE ) 38 | if ( NOT SKIP_LUA_WRAPPER ) 39 | enable_language ( C ) 40 | 41 | find_package ( Lua51 REQUIRED ) 42 | include_directories ( ${LUA_INCLUDE_DIR} ) 43 | 44 | set ( _wrapper ${CMAKE_CURRENT_BINARY_DIR}/${_name}.c ) 45 | set ( _code 46 | "// Not so simple executable wrapper for Lua apps 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | 53 | lua_State *L\; 54 | 55 | static int getargs (lua_State *L, char **argv, int n) { 56 | int narg\; 57 | int i\; 58 | int argc = 0\; 59 | while (argv[argc]) argc++\; 60 | narg = argc - (n + 1)\; 61 | luaL_checkstack(L, narg + 3, \"too many arguments to script\")\; 62 | for (i=n+1\; i < argc\; i++) 63 | lua_pushstring(L, argv[i])\; 64 | lua_createtable(L, narg, n + 1)\; 65 | for (i=0\; i < argc\; i++) { 66 | lua_pushstring(L, argv[i])\; 67 | lua_rawseti(L, -2, i - n)\; 68 | } 69 | return narg\; 70 | } 71 | 72 | static void lstop (lua_State *L, lua_Debug *ar) { 73 | (void)ar\; 74 | lua_sethook(L, NULL, 0, 0)\; 75 | luaL_error(L, \"interrupted!\")\; 76 | } 77 | 78 | static void laction (int i) { 79 | signal(i, SIG_DFL)\; 80 | lua_sethook(L, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1)\; 81 | } 82 | 83 | static void l_message (const char *pname, const char *msg) { 84 | if (pname) fprintf(stderr, \"%s: \", pname)\; 85 | fprintf(stderr, \"%s\\n\", msg)\; 86 | fflush(stderr)\; 87 | } 88 | 89 | static int report (lua_State *L, int status) { 90 | if (status && !lua_isnil(L, -1)) { 91 | const char *msg = lua_tostring(L, -1)\; 92 | if (msg == NULL) msg = \"(error object is not a string)\"\; 93 | l_message(\"${_source_name}\", msg)\; 94 | lua_pop(L, 1)\; 95 | } 96 | return status\; 97 | } 98 | 99 | static int traceback (lua_State *L) { 100 | if (!lua_isstring(L, 1)) 101 | return 1\; 102 | lua_getfield(L, LUA_GLOBALSINDEX, \"debug\")\; 103 | if (!lua_istable(L, -1)) { 104 | lua_pop(L, 1)\; 105 | return 1\; 106 | } 107 | lua_getfield(L, -1, \"traceback\")\; 108 | if (!lua_isfunction(L, -1)) { 109 | lua_pop(L, 2)\; 110 | return 1\; 111 | } 112 | lua_pushvalue(L, 1)\; 113 | lua_pushinteger(L, 2)\; 114 | lua_call(L, 2, 1)\; 115 | return 1\; 116 | } 117 | 118 | static int docall (lua_State *L, int narg, int clear) { 119 | int status\; 120 | int base = lua_gettop(L) - narg\; 121 | lua_pushcfunction(L, traceback)\; 122 | lua_insert(L, base)\; 123 | signal(SIGINT, laction)\; 124 | status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base)\; 125 | signal(SIGINT, SIG_DFL)\; 126 | lua_remove(L, base)\; 127 | if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0)\; 128 | return status\; 129 | } 130 | 131 | int main (int argc, char **argv) { 132 | L=lua_open()\; 133 | lua_gc(L, LUA_GCSTOP, 0)\; 134 | luaL_openlibs(L)\; 135 | lua_gc(L, LUA_GCRESTART, 0)\; 136 | int narg = getargs(L, argv, 0)\; 137 | lua_setglobal(L, \"arg\")\; 138 | 139 | // Script 140 | char script[500] = \"./${_source_name}.lua\"\; 141 | lua_getglobal(L, \"_PROGDIR\")\; 142 | if (lua_isstring(L, -1)) { 143 | sprintf( script, \"%s/${_source_name}.lua\", lua_tostring(L, -1))\; 144 | } 145 | lua_pop(L, 1)\; 146 | 147 | // Run 148 | int status = luaL_loadfile(L, script)\; 149 | lua_insert(L, -(narg+1))\; 150 | if (status == 0) 151 | status = docall(L, narg, 0)\; 152 | else 153 | lua_pop(L, narg)\; 154 | 155 | report(L, status)\; 156 | lua_close(L)\; 157 | return status\; 158 | }; 159 | ") 160 | file ( WRITE ${_wrapper} ${_code} ) 161 | add_executable ( ${_name} ${_wrapper} ) 162 | target_link_libraries ( ${_name} ${LUA_LIBRARY} ) 163 | install ( TARGETS ${_name} DESTINATION ${INSTALL_BIN} ) 164 | endif() 165 | install ( PROGRAMS ${_source} DESTINATION ${INSTALL_BIN} 166 | RENAME ${_source_name}.lua ) 167 | endmacro () 168 | 169 | macro ( _lua_module_helper is_install _name ) 170 | parse_arguments ( _MODULE "LINK;ALL_IN_ONE" "" ${ARGN} ) 171 | # _target is CMake-compatible target name for module (e.g. socket_core). 172 | # _module is relative path of target (e.g. socket/core), 173 | # without extension (e.g. .lua/.so/.dll). 174 | # _MODULE_SRC is list of module source files (e.g. .lua and .c files). 175 | # _MODULE_NAMES is list of module names (e.g. socket.core). 176 | if ( _MODULE_ALL_IN_ONE ) 177 | string ( REGEX REPLACE "\\..*" "" _target "${_name}" ) 178 | string ( REGEX REPLACE "\\..*" "" _module "${_name}" ) 179 | set ( _target "${_target}_all_in_one") 180 | set ( _MODULE_SRC ${_MODULE_ALL_IN_ONE} ) 181 | set ( _MODULE_NAMES ${_name} ${_MODULE_DEFAULT_ARGS} ) 182 | else () 183 | string ( REPLACE "." "_" _target "${_name}" ) 184 | string ( REPLACE "." "/" _module "${_name}" ) 185 | set ( _MODULE_SRC ${_MODULE_DEFAULT_ARGS} ) 186 | set ( _MODULE_NAMES ${_name} ) 187 | endif () 188 | if ( NOT _MODULE_SRC ) 189 | message ( FATAL_ERROR "no module sources specified" ) 190 | endif () 191 | list ( GET _MODULE_SRC 0 _first_source ) 192 | 193 | get_filename_component ( _ext ${_first_source} EXT ) 194 | if ( _ext STREQUAL ".lua" ) # Lua source module 195 | list ( LENGTH _MODULE_SRC _len ) 196 | if ( _len GREATER 1 ) 197 | message ( FATAL_ERROR "more than one source file specified" ) 198 | endif () 199 | 200 | set ( _module "${_module}.lua" ) 201 | 202 | get_filename_component ( _module_dir ${_module} PATH ) 203 | get_filename_component ( _module_filename ${_module} NAME ) 204 | _append_path ( "${CMAKE_CURRENT_SOURCE_DIR}" "${_first_source}" _module_path ) 205 | list ( APPEND _lua_modules "${_name}" "${_module_path}" ) 206 | 207 | if ( ${is_install} ) 208 | install ( FILES ${_first_source} DESTINATION ${INSTALL_LMOD}/${_module_dir} 209 | RENAME ${_module_filename} ) 210 | endif () 211 | else () # Lua C binary module 212 | enable_language ( C ) 213 | find_package ( Lua51 REQUIRED ) 214 | include_directories ( ${LUA_INCLUDE_DIR} ) 215 | 216 | set ( _module "${_module}${CMAKE_SHARED_MODULE_SUFFIX}" ) 217 | 218 | get_filename_component ( _module_dir ${_module} PATH ) 219 | get_filename_component ( _module_filenamebase ${_module} NAME_WE ) 220 | foreach ( _thisname ${_MODULE_NAMES} ) 221 | list ( APPEND _lua_modules "${_thisname}" 222 | "${CMAKE_CURRENT_BINARY_DIR}/\${CMAKE_CFG_INTDIR}/${_module}" ) 223 | endforeach () 224 | 225 | add_library( ${_target} MODULE ${_MODULE_SRC}) 226 | target_link_libraries ( ${_target} ${LUA_LIBRARY} ${_MODULE_LINK} ) 227 | set_target_properties ( ${_target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY 228 | "${_module_dir}" PREFIX "" OUTPUT_NAME "${_module_filenamebase}" ) 229 | if ( ${is_install} ) 230 | install ( TARGETS ${_target} DESTINATION ${INSTALL_CMOD}/${_module_dir}) 231 | endif () 232 | endif () 233 | endmacro () 234 | 235 | # add_lua_module 236 | # Builds a Lua source module into a destination locatable by Lua 237 | # require syntax. 238 | # Binary modules are also supported where this function takes sources and 239 | # libraries to compile separated by LINK keyword. 240 | # USE: add_lua_module ( socket.http src/http.lua ) 241 | # USE2: add_lua_module ( mime.core src/mime.c ) 242 | # USE3: add_lua_module ( socket.core ${SRC_SOCKET} LINK ${LIB_SOCKET} ) 243 | # USE4: add_lua_module ( ssl.context ssl.core ALL_IN_ONE src/context.c src/ssl.c ) 244 | # This form builds an "all-in-one" module (e.g. ssl.so or ssl.dll containing 245 | # both modules ssl.context and ssl.core). The CMake target name will be 246 | # ssl_all_in_one. 247 | # Also sets variable _module_path (relative path where module typically 248 | # would be installed). 249 | macro ( add_lua_module ) 250 | _lua_module_helper ( 0 ${ARGN} ) 251 | endmacro () 252 | 253 | 254 | # install_lua_module 255 | # This is the same as `add_lua_module` but also installs the module. 256 | # USE: install_lua_module ( socket.http src/http.lua ) 257 | # USE2: install_lua_module ( mime.core src/mime.c ) 258 | # USE3: install_lua_module ( socket.core ${SRC_SOCKET} LINK ${LIB_SOCKET} ) 259 | macro ( install_lua_module ) 260 | _lua_module_helper ( 1 ${ARGN} ) 261 | endmacro () 262 | 263 | # Builds string representing Lua table mapping Lua modules names to file 264 | # paths. Used internally. 265 | macro ( _make_module_table _outvar ) 266 | set ( ${_outvar} ) 267 | list ( LENGTH _lua_modules _n ) 268 | if ( ${_n} GREATER 0 ) # avoids cmake complaint 269 | foreach ( _i RANGE 1 ${_n} 2 ) 270 | list ( GET _lua_modules ${_i} _path ) 271 | math ( EXPR _ii ${_i}-1 ) 272 | list ( GET _lua_modules ${_ii} _name ) 273 | set ( ${_outvar} "${_table} ['${_name}'] = '${_path}'\;\n") 274 | endforeach () 275 | endif () 276 | set ( ${_outvar} 277 | "local modules = { 278 | ${_table}}" ) 279 | endmacro () 280 | 281 | # add_lua_test ( _testfile [ WORKING_DIRECTORY _working_dir ] ) 282 | # Runs Lua script `_testfile` under CTest tester. 283 | # Optional named argument `WORKING_DIRECTORY` is current working directory to 284 | # run test under (defaults to ${CMAKE_CURRENT_BINARY_DIR}). 285 | # Both paths, if relative, are relative to ${CMAKE_CURRENT_SOURCE_DIR}. 286 | # Any modules previously defined with install_lua_module are automatically 287 | # preloaded (via package.preload) prior to running the test script. 288 | # Under LuaDist, set test=true in config.lua to enable testing. 289 | # USE: add_lua_test ( test/test1.lua [args...] [WORKING_DIRECTORY dir]) 290 | macro ( add_lua_test _testfile ) 291 | if ( NOT SKIP_TESTING ) 292 | parse_arguments ( _ARG "WORKING_DIRECTORY" "" ${ARGN} ) 293 | include ( CTest ) 294 | find_program ( LUA NAMES lua lua.bat ) 295 | get_filename_component ( TESTFILEABS ${_testfile} ABSOLUTE ) 296 | get_filename_component ( TESTFILENAME ${_testfile} NAME ) 297 | get_filename_component ( TESTFILEBASE ${_testfile} NAME_WE ) 298 | 299 | # Write wrapper script. 300 | # Note: One simple way to allow the script to find modules is 301 | # to just put them in package.preload. 302 | set ( TESTWRAPPER ${CMAKE_CURRENT_BINARY_DIR}/${TESTFILENAME} ) 303 | _make_module_table ( _table ) 304 | set ( TESTWRAPPERSOURCE 305 | "local CMAKE_CFG_INTDIR = ... or '.' 306 | ${_table} 307 | local function preload_modules(modules) 308 | for name, path in pairs(modules) do 309 | if path:match'%.lua' then 310 | package.preload[name] = assert(loadfile(path)) 311 | else 312 | local name = name:gsub('.*%-', '') -- remove any hyphen prefix 313 | local symbol = 'luaopen_' .. name:gsub('%.', '_') 314 | --improve: generalize to support all-in-one loader? 315 | local path = path:gsub('%$%{CMAKE_CFG_INTDIR%}', CMAKE_CFG_INTDIR) 316 | package.preload[name] = assert(package.loadlib(path, symbol)) 317 | end 318 | end 319 | end 320 | preload_modules(modules) 321 | arg[0] = '${TESTFILEABS}' 322 | table.remove(arg, 1) 323 | return assert(loadfile '${TESTFILEABS}')(unpack(arg)) 324 | " ) 325 | if ( _ARG_WORKING_DIRECTORY ) 326 | get_filename_component ( 327 | TESTCURRENTDIRABS ${_ARG_WORKING_DIRECTORY} ABSOLUTE ) 328 | # note: CMake 2.6 (unlike 2.8) lacks WORKING_DIRECTORY parameter. 329 | set ( _pre ${CMAKE_COMMAND} -E chdir "${TESTCURRENTDIRABS}" ) 330 | endif () 331 | file ( WRITE ${TESTWRAPPER} ${TESTWRAPPERSOURCE}) 332 | add_test ( NAME ${TESTFILEBASE} COMMAND ${_pre} ${LUA} 333 | ${TESTWRAPPER} "${CMAKE_CFG_INTDIR}" 334 | ${_ARG_DEFAULT_ARGS} ) 335 | endif () 336 | # see also http://gdcm.svn.sourceforge.net/viewvc/gdcm/Sandbox/CMakeModules/UsePythonTest.cmake 337 | # Note: ${CMAKE_CFG_INTDIR} is a command-line argument to allow proper 338 | # expansion by the native build tool. 339 | endmacro () 340 | 341 | 342 | # Converts Lua source file `_source` to binary string embedded in C source 343 | # file `_target`. Optionally compiles Lua source to byte code (not available 344 | # under LuaJIT2, which doesn't have a bytecode loader). Additionally, Lua 345 | # versions of bin2c [1] and luac [2] may be passed respectively as additional 346 | # arguments. 347 | # 348 | # [1] http://lua-users.org/wiki/BinToCee 349 | # [2] http://lua-users.org/wiki/LuaCompilerInLua 350 | function ( add_lua_bin2c _target _source ) 351 | find_program ( LUA NAMES lua lua.bat ) 352 | execute_process ( COMMAND ${LUA} -e "string.dump(function()end)" 353 | RESULT_VARIABLE _LUA_DUMP_RESULT ERROR_QUIET ) 354 | if ( NOT ${_LUA_DUMP_RESULT} ) 355 | SET ( HAVE_LUA_DUMP true ) 356 | endif () 357 | message ( "-- string.dump=${HAVE_LUA_DUMP}" ) 358 | 359 | if ( ARGV2 ) 360 | get_filename_component ( BIN2C ${ARGV2} ABSOLUTE ) 361 | set ( BIN2C ${LUA} ${BIN2C} ) 362 | else () 363 | find_program ( BIN2C NAMES bin2c bin2c.bat ) 364 | endif () 365 | if ( HAVE_LUA_DUMP ) 366 | if ( ARGV3 ) 367 | get_filename_component ( LUAC ${ARGV3} ABSOLUTE ) 368 | set ( LUAC ${LUA} ${LUAC} ) 369 | else () 370 | find_program ( LUAC NAMES luac luac.bat ) 371 | endif () 372 | endif ( HAVE_LUA_DUMP ) 373 | message ( "-- bin2c=${BIN2C}" ) 374 | message ( "-- luac=${LUAC}" ) 375 | 376 | get_filename_component ( SOURCEABS ${_source} ABSOLUTE ) 377 | if ( HAVE_LUA_DUMP ) 378 | get_filename_component ( SOURCEBASE ${_source} NAME_WE ) 379 | add_custom_command ( 380 | OUTPUT ${_target} DEPENDS ${_source} 381 | COMMAND ${LUAC} -o ${CMAKE_CURRENT_BINARY_DIR}/${SOURCEBASE}.lo 382 | ${SOURCEABS} 383 | COMMAND ${BIN2C} ${CMAKE_CURRENT_BINARY_DIR}/${SOURCEBASE}.lo 384 | ">${_target}" ) 385 | else () 386 | add_custom_command ( 387 | OUTPUT ${_target} DEPENDS ${SOURCEABS} 388 | COMMAND ${BIN2C} ${_source} ">${_target}" ) 389 | endif () 390 | endfunction() 391 | -------------------------------------------------------------------------------- /dist.info: -------------------------------------------------------------------------------- 1 | --- This file is part of LuaDist project 2 | 3 | name = "luadist" 4 | version = "1.2.5" 5 | 6 | desc = "Simple Lua Module Development, Distribution and Deployment Tool." 7 | maintainer = "Peter Drahoš" 8 | author = "Peter Drahoš, Peter Kapec, David Manura" 9 | license = "MIT/X11" 10 | url = "http://www.luadist.org" 11 | 12 | depends = { 13 | "lua ~> 5.1", 14 | "md5 >= 1.1", 15 | "luasocket >= 2.0.2", 16 | "luafilesystem >= 1.4.1", 17 | "luasec >= 0.4", 18 | "unzip >= 6.0" 19 | } 20 | 21 | -------------------------------------------------------------------------------- /dist/config.lua.in: -------------------------------------------------------------------------------- 1 | --- LuaDist configuration 2 | -- The contents of this file is automaticaly generated. 3 | -- Feel free to edit to suit your needs. 4 | 5 | local write = io.write 6 | local flush = io.flush 7 | local getenv = os.getenv 8 | 9 | -- Look for _PROGDIR by default 10 | local path = _PROGDIR 11 | if path then path = path:gsub("\\", "/") .. "/.." end 12 | 13 | module ("dist.config") 14 | 15 | -- LuaDist Install Identification 16 | version = "@DIST_VERSION@" -- Current LuaDist version 17 | arch = "@DIST_ARCH@" -- Host architecture 18 | type = "@DIST_TYPE@" -- Host type 19 | 20 | -- Behavior 21 | binary = true -- Use binary dists. 22 | source = true -- Use source dists (requires CMake and MinGW/gcc/VS to be installed). 23 | test = false -- Run tests before install. 24 | verbose = false -- Print verbose output. 25 | debug = false -- Start debug mod. Will keep temporary directories too. 26 | proxy = false -- HTTP proxy to use. False for none, otherwise the proxy address. 27 | timeout = 10 -- HTTP fetch timeout (seconds) 28 | cache = 5*60 -- Cache timeout (seconds) 29 | 30 | --- Packages provided by host 31 | -- If you install any packages manually or using your host OS installer you can add the name-version 32 | -- here, LuaDist will NOT install these modules and will search for the libraries in the host 33 | provides = { 34 | -- "unzip-6.0" -- Is available on OSX and most Unix/Linux based installs. 35 | } 36 | 37 | -- Paths 38 | root = path or getenv("DIST_ROOT") or "/" 39 | temp = root .. "/tmp" -- Full path temp 40 | log = temp .. "/luadist.log" -- Log file 41 | dists = "share/luadist/dists" 42 | 43 | -- URLs of repositories to search for dists. http:// or file:// URLs are cecognized atm. 44 | repo = { 45 | --- Examples 46 | -- "file:///home/joe/my_dists" -- Private Local Repository Unix 47 | -- "file://C:/MyDists" -- Private Local Repository Windows 48 | -- "http://myserver.tld/repo" -- Private Online Repository 49 | 50 | --- Use local repo to speed things up when re-deploying 51 | -- "file://" .. root .. "/dist", 52 | 53 | --- Official repo 54 | "https://raw.github.com/LuaDist/Repository/master/" 55 | } 56 | 57 | --- !!! Do not edit below unless you know what you are doing. !!! 58 | -- Additional CMake variables to pass to build 59 | variables = { 60 | --- Install defaults 61 | INSTALL_BIN = "@INSTALL_BIN@", 62 | INSTALL_LIB = "@INSTALL_LIB@", 63 | INSTALL_INC = "@INSTALL_INC@", 64 | INSTALL_ETC = "@INSTALL_ETC@", 65 | INSTALL_LMOD = "@INSTALL_LMOD@", 66 | INSTALL_CMOD = "@INSTALL_CMOD@", 67 | 68 | --- LuaDist specific variables 69 | DIST_VERSION = version, 70 | DIST_ARCH = arch, 71 | DIST_TYPE = type, 72 | 73 | -- CMake specific setup 74 | CMAKE_GENERATOR = "@CMAKE_GENERATOR@", 75 | CMAKE_BUILD_TYPE = "@CMAKE_BUILD_TYPE@", 76 | 77 | -- RPath functionality 78 | CMAKE_SKIP_BUILD_RPATH = "@CMAKE_SKIP_BUILD_RPATH@", 79 | CMAKE_BUILD_WITH_INSTALL_RPATH = "@CMAKE_BUILD_WITH_INSTALL_RPATH@", 80 | CMAKE_INSTALL_RPATH = "@CMAKE_INSTALL_RPATH@", 81 | CMAKE_INSTALL_RPATH_USE_LINK_PATH = "@CMAKE_INSTALL_RPATH_USE_LINK_PATH@", 82 | CMAKE_INSTALL_NAME_DIR = "@CMAKE_INSTALL_NAME_DIR@", 83 | 84 | -- OSX specific 85 | CMAKE_OSX_ARCHITECTURES = "@CMAKE_OSX_ARCHITECTURES@", 86 | 87 | -- Fixes and overrides 88 | LUA_LIBRARY = root .. "@DIST_LUA_LIBRARY@", 89 | } 90 | 91 | -- Commands to use for building. (CMake 2.8+) 92 | cmake = "cmake" 93 | cmakeDebug = "cmake -DCMAKE_VERBOSE_MAKEFILE=true -DCMAKE_BUILD_TYPE=Debug" 94 | ctest = "ctest" 95 | ctestDebug = "ctest" 96 | make = "cmake --build . --target install --clean-first" 97 | makeDebug = "cmake --build . --target install --clean-first" 98 | 99 | -- Add -j option to make in case of unix makefiles to speed up builds 100 | if (variables.CMAKE_GENERATOR == "Unix Makefiles") then 101 | make = make .. " -- -j6" 102 | makeDebug = makeDebug .. " -- -j6" 103 | end 104 | 105 | -- On Windows with MinGW use the SHELL trick to force mingw32-make to build in parallel 106 | -- Note: No numbers behind -j needed 107 | if (variables.CMAKE_GENERATOR == "MinGW Makefiles") then 108 | make = "set SHELL=cmd.exe && " .. make .. " -- -j" 109 | makeDebug = "set SHELL=cmd.exe && " .. makeDebug .. " -- -j" 110 | end 111 | 112 | -- Function used to display messages, warnings and errors 113 | message = function(...) 114 | write(...) 115 | write("\n") 116 | flush() 117 | end 118 | -------------------------------------------------------------------------------- /dist/dep.lua: -------------------------------------------------------------------------------- 1 | --- LuaDist dependency functions 2 | -- Peter Drahoš, LuaDist Project, 2010 3 | -- Original Code borrowed from LuaRocks Project 4 | 5 | --- Dependency handling functions. 6 | -- Dependencies are represented in LuaDist through strings with 7 | -- a dist name followed by a comma-separated list of constraints. 8 | -- Each constraint consists of an operator and a version number. 9 | -- In this string format, version numbers are represented as 10 | -- naturally as possible, like they are used by upstream projects 11 | -- (e.g. "2.0beta3"). Internally, LuaDist converts them to a purely 12 | -- numeric representation, allowing comparison following some 13 | -- "common sense" heuristics. The precise specification of the 14 | -- comparison criteria is the source code of this module, but the 15 | -- test/test_deps.lua file included with LuaDist provides some 16 | -- insights on what these criteria are. 17 | 18 | module ("dist.dep", package.seeall) 19 | 20 | local distr = require "dist" 21 | local log = require "dist.log" 22 | local manif = require "dist.manifest" 23 | 24 | local operators = { 25 | ["=="] = "==", 26 | ["~="] = "~=", 27 | [">"] = ">", 28 | ["<"] = "<", 29 | [">="] = ">=", 30 | ["<="] = "<=", 31 | ["~>"] = "~>", 32 | -- plus some convenience translations 33 | [""] = "==", 34 | ["-"] = "==", 35 | ["="] = "==", 36 | ["!="] = "~=" 37 | } 38 | 39 | local deltas = { 40 | scm = -100, 41 | rc = -1000, 42 | pre = -10000, 43 | beta = -100000, 44 | alpha = -1000000, 45 | work = -10000000, 46 | } 47 | 48 | local version_mt = { 49 | --- Equality comparison for versions. 50 | -- All version numbers must be equal. 51 | -- If both versions have revision numbers, they must be equal; 52 | -- otherwise the revision number is ignored. 53 | -- @param v1 table: version table to compare. 54 | -- @param v2 table: version table to compare. 55 | -- @return boolean: true if they are considered equivalent. 56 | __eq = function(v1, v2) 57 | if #v1 ~= #v2 then 58 | return false 59 | end 60 | for i = 1, #v1 do 61 | if v1[i] ~= v2[i] then 62 | return false 63 | end 64 | end 65 | if v1.revision and v2.revision then 66 | return (v1.revision == v2.revision) 67 | end 68 | return true 69 | end, 70 | --- Size comparison for versions. 71 | -- All version numbers are compared. 72 | -- If both versions have revision numbers, they are compared; 73 | -- otherwise the revision number is ignored. 74 | -- @param v1 table: version table to compare. 75 | -- @param v2 table: version table to compare. 76 | -- @return boolean: true if v1 is considered lower than v2. 77 | __lt = function(v1, v2) 78 | for i = 1, math.max(#v1, #v2) do 79 | local v1i, v2i = v1[i] or 0, v2[i] or 0 80 | if v1i ~= v2i then 81 | return (v1i < v2i) 82 | end 83 | end 84 | if v1.revision and v2.revision then 85 | return (v1.revision < v2.revision) 86 | end 87 | return false 88 | end 89 | } 90 | 91 | local version_cache = {} 92 | setmetatable(version_cache, { 93 | __mode = "kv" 94 | }) 95 | 96 | --- Parse a version string, converting to table format. 97 | -- A version table contains all components of the version string 98 | -- converted to numeric format, stored in the array part of the table. 99 | -- If the version contains a revision, it is stored numerically 100 | -- in the 'revision' field. The original string representation of 101 | -- the string is preserved in the 'string' field. 102 | -- Returned version tables use a metatable 103 | -- allowing later comparison through relational operators. 104 | -- @param vstring string: A version number in string format. 105 | -- @return table or nil: A version table or nil 106 | -- if the input string contains invalid characters. 107 | function parseVersion(vstring) 108 | if not vstring then return nil end 109 | assert(type(vstring) == "string") 110 | 111 | local cached = version_cache[vstring] 112 | if cached then 113 | return cached 114 | end 115 | 116 | local version = {} 117 | local i = 1 118 | 119 | local function add_token(number) 120 | version[i] = version[i] and version[i] + number/100000 or number 121 | i = i + 1 122 | end 123 | 124 | -- trim leading and trailing spaces 125 | vstring = vstring:match("^%s*(.*)%s*$") 126 | version.string = vstring 127 | -- store revision separately if any 128 | local main, revision = vstring:match("(.*)%-(%d+)$") 129 | if revision then 130 | vstring = main 131 | version.revision = tonumber(revision) 132 | end 133 | while #vstring > 0 do 134 | -- extract a number 135 | local token, rest = vstring:match("^(%d+)[%.%-%_]*(.*)") 136 | if token then 137 | add_token(tonumber(token)) 138 | else 139 | -- extract a word 140 | token, rest = vstring:match("^(%a+)[%.%-%_]*(.*)") 141 | if not token then 142 | return nil 143 | end 144 | local last = #version 145 | version[i] = deltas[token] or (token:byte() / 1000) 146 | end 147 | vstring = rest 148 | end 149 | setmetatable(version, version_mt) 150 | version_cache[vstring] = version 151 | return version 152 | end 153 | 154 | --- Utility function to compare version numbers given as strings. 155 | -- @param a string: one version. 156 | -- @param b string: another version. 157 | -- @return boolean: True if a > b. 158 | function compareVersions(a, b) 159 | return parseVersion(a) > parseVersion(b) 160 | end 161 | 162 | --- Consumes a constraint from a string, converting it to table format. 163 | -- For example, a string ">= 1.0, > 2.0" is converted to a table in the 164 | -- format {op = ">=", version={1,0}} and the rest, "> 2.0", is returned 165 | -- back to the caller. 166 | -- @param input string: A list of constraints in string format. 167 | -- @return (table, string) or nil: A table representing the same 168 | -- constraints and the string with the unused input, or nil if the 169 | -- input string is invalid. 170 | local function parseConstraint(input) 171 | assert(type(input) == "string") 172 | 173 | local op, version, rest = input:match("^([<>=~!]*)%s*([%w%.%_%-]+)[%s,]*(.*)") 174 | op = operators[op] 175 | version = parseVersion(version) 176 | if not op or not version then return nil end 177 | return { op = op, version = version }, rest 178 | end 179 | 180 | --- Convert a list of constraints from string to table format. 181 | -- For example, a string ">= 1.0, < 2.0" is converted to a table in the format 182 | -- {{op = ">=", version={1,0}}, {op = "<", version={2,0}}}. 183 | -- Version tables use a metatable allowing later comparison through 184 | -- relational operators. 185 | -- @param input string: A list of constraints in string format. 186 | -- @return table or nil: A table representing the same constraints, 187 | -- or nil if the input string is invalid. 188 | function parseConstraints(input) 189 | assert(type(input) == "string") 190 | 191 | local constraints, constraint = {}, nil 192 | while #input > 0 do 193 | constraint, input = parseConstraint(input) 194 | if constraint then 195 | table.insert(constraints, constraint) 196 | else 197 | return nil 198 | end 199 | end 200 | return constraints 201 | end 202 | 203 | --- A more lenient check for equivalence between versions. 204 | -- This returns true if the requested components of a version 205 | -- match and ignore the ones that were not given. For example, 206 | -- when requesting "2", then "2", "2.1", "2.3.5-9"... all match. 207 | -- When requesting "2.1", then "2.1", "2.1.3" match, but "2.2" 208 | -- doesn't. 209 | -- @param version string or table: Version to be tested; may be 210 | -- in string format or already parsed into a table. 211 | -- @param requested string or table: Version requested; may be 212 | -- in string format or already parsed into a table. 213 | -- @return boolean: True if the tested version matches the requested 214 | -- version, false otherwise. 215 | local function partialMatch(version, requested) 216 | assert(type(version) == "string" or type(version) == "table") 217 | assert(type(requested) == "string" or type(version) == "table") 218 | 219 | if type(version) ~= "table" then version = parseVersion(version) end 220 | if type(requested) ~= "table" then requested = parseVersion(requested) end 221 | if not version or not requested then return false end 222 | 223 | for i = 1, #requested do 224 | if requested[i] ~= version[i] then return false end 225 | end 226 | if requested.revision then 227 | return requested.revision == version.revision 228 | end 229 | return true 230 | end 231 | 232 | --- Check if a version satisfies a set of constraints. 233 | -- @param version table: A version in table format 234 | -- @param constraints table: An array of constraints in table format. 235 | -- @return boolean: True if version satisfies all constraints, 236 | -- false otherwise. 237 | function matchConstraints(version, constraints) 238 | assert(type(version) == "table") 239 | assert(type(constraints) == "table") 240 | local ok = true 241 | setmetatable(version, version_mt) 242 | for _, constr in pairs(constraints) do 243 | local constr_version = constr.version 244 | setmetatable(constr.version, version_mt) 245 | if constr.op == "==" then ok = version == constr_version 246 | elseif constr.op == "~=" then ok = version ~= constr_version 247 | elseif constr.op == ">" then ok = version > constr_version 248 | elseif constr.op == "<" then ok = version < constr_version 249 | elseif constr.op == ">=" then ok = version >= constr_version 250 | elseif constr.op == "<=" then ok = version <= constr_version 251 | elseif constr.op == "~>" then ok = partialMatch(version, constr_version) 252 | end 253 | if not ok then break end 254 | end 255 | return ok 256 | end 257 | 258 | --- Check if a version string is satisfied by a constraint string. 259 | -- @param version string: A version in string format 260 | -- @param constraints string: Constraints in string format. 261 | -- @return boolean: True if version satisfies all constraints, 262 | -- false otherwise. 263 | function constrain(version, constraints) 264 | local const = parseConstraints(constraints) 265 | local ver = parseVersion(version) 266 | if const and ver then 267 | return matchConstraints(ver, const) 268 | end 269 | return nil, "Error parsing versions." 270 | end 271 | 272 | --- Split dist name into name and constraints. 273 | -- @param name string: A string containing name and version constraints eg. "lua-5.1.4" or "luajit >= 1.0 < 2.0" 274 | -- @return string, string: Returns separated name and constraints 275 | function split(name) 276 | local cut = string.find(name, "[%s-=<>~]+%d") or string.find(name, "[%s-=<>~]+scm") 277 | if cut then 278 | -- Cut the string and remove - from version if needed. 279 | return string.sub(name, 0, cut-1), string.gsub(string.sub(name, cut), "^[-%s]", "") 280 | end 281 | return name, nil 282 | end 283 | 284 | -------------------------------------------------------------------------------- /dist/fetch.lua: -------------------------------------------------------------------------------- 1 | --- LuaDist URL fetch functions 2 | -- Peter Drahoš, LuaDist Project, 2010 3 | 4 | --- This module is responsible for downloading contents using URIs. 5 | -- It should handle at least HTTP and FILE URIs as well as system paths transparently. 6 | -- 2DO: support for more protocols if demanded. 7 | -- Two functions are provided. Notice that http requests are cached. 8 | -- download - To download dists. 9 | -- get - To directly obtain manifests. 10 | 11 | module ("dist.fetch", package.seeall) 12 | 13 | local config = require "dist.config" 14 | local sys = require "dist.sys" 15 | local log = require "dist.log" 16 | 17 | -- Download contents directly from HTTP source to file 18 | local function downloadHTTP(src, file) 19 | local ltn12 = require "ltn12" 20 | local http = require "socket.http" 21 | 22 | local request = { 23 | url = src, 24 | headers = { 25 | USERAGENT = "LuaDist", 26 | TIMEOUT = config.timeout, 27 | }, 28 | sink = ltn12.sink.file(assert(io.open(file, "wb"))), 29 | redirect = true, 30 | } 31 | if config.proxy then request.proxy = config.proxy end 32 | 33 | local ok, err = http.request(request) 34 | if not ok then return nil, "Failed to get contents of " .. src .. " error: " .. err end 35 | return true 36 | end 37 | 38 | -- Download contents directly from HTTP source to file 39 | local function downloadHTTPS(src, file) 40 | local ltn12 = require "ltn12" 41 | local https = require "ssl.https" 42 | 43 | local request = { 44 | url = src, 45 | headers = { 46 | USERAGENT = "LuaDist", 47 | TIMEOUT = config.timeout, 48 | }, 49 | protocol = "tlsv1", 50 | options = "all", 51 | verify = "none", 52 | sink = ltn12.sink.file(assert(io.open(file, "wb"))), 53 | } 54 | 55 | local ok, err = https.request(request) 56 | if not ok then return nil, "Failed to get contents of " .. src .. " error: " .. err end 57 | return true 58 | end 59 | 60 | --- Fetch file from URI into destination. 61 | -- @param src string: URI to fetch file from. Accepts paths too. 62 | -- @param dest string: Destination dir, if not provided temporary dir will be used. 63 | -- @return path, log: Path the file was downloaded and the resulting log message. 64 | function download(src, dest) 65 | assert(type(src) == "string", "fetch.download: Argument 'src' is not a string.") 66 | assert(not dest or type(dest) == "string", "fecth.download: Argument 'dest' is not a string.") 67 | 68 | -- Dont waste time 69 | if src == dest then return true end 70 | 71 | -- Make sure all paths are absolute and set 72 | dest = sys.path(dest) or config.temp 73 | src = sys.path(src) 74 | 75 | -- Test destination existstence 76 | local ok, err = sys.isDir(dest) 77 | if not ok then return nil, "Destination " .. dest .. " is not a directory." end 78 | 79 | -- Construct destination filename 80 | local name = src:match("([^/]+)$") 81 | dest = sys.path(dest, name) 82 | part = dest .. ".part" 83 | 84 | -- Test if the file is local 85 | local file = sys.path((src:gsub("^file://",""))) 86 | if sys.isFile(file) then 87 | local ok, err = sys.copy(file, dest) 88 | if not ok then return nil, "Failed to coply local file " .. file .. " to " .. dest end 89 | return dest, "Succesfuly copied " .. file .. " to " .. dest 90 | elseif src:match("^file://") then 91 | return nil, "Failed to get contents of " .. src .. " error: not found" 92 | end -- else uncertain 93 | 94 | -- Cache check 95 | if config.cache then 96 | local md5 = require "md5" 97 | local lfs = require "lfs" 98 | 99 | local path = sys.path(config.temp, "luadist_cache") 100 | local cache = sys.path(path, md5.sumhexa(src)) 101 | 102 | if ((lfs.attributes(cache, "modification") or 0) + config.cache) > os.time() then 103 | sys.copy(cache, dest) 104 | return dest, "Retrieved from cache." 105 | end 106 | end 107 | 108 | -- Depeding on the protocol try obtaining the source 109 | local ok, err 110 | if (src:match("http://")) then ok, err = downloadHTTP(src, part) end 111 | if (src:match("https://")) then ok, err = downloadHTTPS(src, part) end 112 | 113 | if not ok then return nil, err end 114 | sys.move(part, dest) 115 | 116 | -- Save cache 117 | if config.cache then 118 | local md5 = require "md5" 119 | 120 | local path = sys.path(config.temp, "luadist_cache") 121 | local cache = sys.path(path, md5.sumhexa(src)) 122 | sys.makeDir(path) 123 | sys.copy(dest, cache) 124 | end 125 | 126 | if not ok then return nil, "Failed to get contents of " .. src .. " error: " .. err end 127 | return dest, "Succesfuly downloaded " .. src .. " to " .. dest 128 | end 129 | 130 | -- Obtain contents directly from HTTP source 131 | local function getHTTP(src) 132 | local ltn12 = require "ltn12" 133 | local http = require "socket.http" 134 | 135 | local contents = {} 136 | local request = { 137 | url = src, 138 | headers = { 139 | USERAGENT = "LuaDist", 140 | TIMEOUT = config.timeout, 141 | }, 142 | sink = ltn12.sink.table(contents), 143 | redirect = true, 144 | } 145 | if config.proxy then request.proxy = config.proxy end 146 | 147 | local ok, err = http.request(request) 148 | if not ok then return nil, "Failed to get contents of " .. src .. " error: " .. err end 149 | return table.concat(contents) 150 | end 151 | 152 | -- Obtain contents directly from HTTP source 153 | local function getHTTPS(src) 154 | local ltn12 = require "ltn12" 155 | local https = require "ssl.https" 156 | 157 | local contents = {} 158 | local request = { 159 | url = src, 160 | headers = { 161 | USERAGENT = "LuaDist", 162 | TIMEOUT = config.timeout, 163 | }, 164 | protocol = "tlsv1", 165 | options = "all", 166 | verify = "none", 167 | sink = ltn12.sink.table(contents), 168 | } 169 | 170 | local ok, err = https.request(request) 171 | 172 | if not ok then return nil, "Failed to get contents of " .. src .. " error: " .. err end 173 | return table.concat(contents) 174 | end 175 | 176 | --- Directly get file contents from URI using luasocket. 177 | -- @param src string: URI to fetch file from. Accepts paths too. 178 | -- @return text, log: Contents of the URL file or nil and log message. 179 | function get(src) 180 | assert(type(src) == "string", "fetch.get: Argument 'src' is not a string.") 181 | 182 | -- Test if file is local 183 | local file = sys.path((src:gsub("^file://",""))) 184 | if sys.isFile(file) then 185 | local handle = io.open(file, "rb") 186 | if not handle then return nil, "Failed to get contents of " .. file end 187 | local ret = handle:read("*all") 188 | handle:close() 189 | return ret, "Succesfuly obtained contents of " .. file 190 | elseif src:match("^file://") then 191 | return nil, "Failed to get contents of " .. src .. " error: not found" 192 | end -- else uncertain 193 | 194 | -- Cache check 195 | if config.cache then 196 | local md5 = require "md5" 197 | local lfs = require "lfs" 198 | 199 | local path = sys.path(config.temp, "luadist_cache") 200 | local cache = sys.path(path, md5.sumhexa(src)) 201 | 202 | if ((lfs.attributes(cache, "modification") or 0) + config.cache) > os.time() then 203 | local file = io.open(cache, "rb") 204 | if file then 205 | local data = file:read("*all") 206 | file:close() 207 | return data, "Retrieved from cache." 208 | end 209 | end 210 | end 211 | 212 | -- Depeding on the protocol try obtaining the source 213 | local data, err 214 | if (src:match("http://")) then data, err = getHTTP(src) end 215 | if (src:match("https://")) then data, err = getHTTPS(src) end 216 | 217 | if (not data) then return nil, err end 218 | 219 | -- Save cache 220 | if config.cache then 221 | local md5 = require "md5" 222 | 223 | local path = sys.path(config.temp, "luadist_cache") 224 | local cache = sys.path(path, md5.sumhexa(src)) 225 | sys.makeDir(path) 226 | local file = io.open(cache, "wb") 227 | if file then 228 | file:write(data) 229 | file:close() 230 | end 231 | end 232 | 233 | return data, "Succesfuly obtained contents of " .. src 234 | end 235 | -------------------------------------------------------------------------------- /dist/log.lua: -------------------------------------------------------------------------------- 1 | --- LuaDist simple message logger 2 | -- Peter Drahoš, Peter Kapec, LuaDist Project, 2010 3 | 4 | --- Very simple log system. 5 | -- 2DO: change to LuaLogging on next version. 6 | -- write - write a log line 7 | -- message - write and optionally display a message 8 | 9 | module ("dist.log", package.seeall) 10 | 11 | local lfs = require "lfs" 12 | local config = require "dist.config" 13 | 14 | -- Profile to store info in 15 | lfs.mkdir(config.temp) 16 | local log = assert(io.open(config.log, "a"), "Could not create log file!") 17 | 18 | --- Display and log a message 19 | function message(...) 20 | if config.message then config.message(...) end 21 | return write(...) 22 | end 23 | 24 | --- Write a line to log 25 | function write(...) 26 | 27 | local args = ... 28 | if type(...) == "string" then args = { ... } end 29 | if type(args) ~= "table" then return nil end 30 | 31 | log:write(os.date("%c", os.time()) .. ":: ") 32 | for i = 1, #args do 33 | log:write(tostring(args[i]) .. " ") 34 | end 35 | log:write("\n") 36 | log:flush() 37 | end 38 | -------------------------------------------------------------------------------- /dist/manifest.lua: -------------------------------------------------------------------------------- 1 | --- LuaDist manifest specific functions including checks 2 | -- Peter Drahoš, Peter Kapec, LuaDist Project, 2010 3 | 4 | --- The purpose of this module is to check and collect dist manifests. 5 | -- There are three functions provided: 6 | -- make - Generates manifest for local directory 7 | -- get - Gets sorted manifest from URI, this uses make for local paths. For remote directories it requires dist.manifest file to be present. 8 | -- info - Loads and/or corrects and checks dist.info contents 9 | -- Dists and manifests are simply arrays of collected dist.info files. 10 | 11 | module ("dist.manifest", package.seeall) 12 | 13 | local log = require "dist.log" 14 | local fetch = require "dist.fetch" 15 | local persist = require "dist.persist" 16 | local sys = require "dist.sys" 17 | local config = require "dist.config" 18 | local dep = require "dist.dep" 19 | 20 | local function couldBeDistFile(path) 21 | return (path:match"%.dist$" or path:match"%.zip$") and 22 | sys.isFile(path) 23 | end 24 | 25 | --- Collect and sort dists in a directory. 26 | -- @param dir string: Directory to get manifest from. 27 | -- @return dists, log: Dists in the directory and log message. 28 | function make(dir) 29 | assert(type(dir) == "string", "manifest.make: argument 'dir' not a string.") 30 | 31 | -- Collection 32 | local dists 33 | 34 | for id, file in pairs(sys.dir(dir) or {}) do 35 | local path = sys.path(dir, file) 36 | -- Try to load dist.info in case the file is expanded dist directory, then try loading it from the file using unzip 37 | local dist = 38 | persist.load(sys.path(path, "dist.info")) or 39 | couldBeDistFile(path) and 40 | persist.loadText(sys.getZipFile(path, "*/dist.info") or "fail") 41 | -- note: couldBeDistFile test avoids calling unnecessarily calling 42 | -- getZipFile, which requires io.popen and unzip, which may be 43 | -- unavailable in the bootstrapping Lua. 44 | 45 | -- We have identified a dist 46 | if dist then 47 | -- Test it 48 | local dist, err = info(dist) 49 | if dist then 50 | -- Collect the dist 51 | dists = dists or {} 52 | dist.path = file 53 | table.insert(dists, dist) 54 | else 55 | -- Log warnings 56 | log.message("Warning, skipped malformed dist.info for file: ", file, "err:", err) 57 | end 58 | -- Recursively traverse subdirectory 59 | elseif sys.isDir(path) then 60 | local ret = make(path) 61 | for _,v in pairs(ret or {}) do 62 | dists = dists or {} 63 | v.path = file .. "/" .. v.path 64 | table.insert(dists, v) 65 | end 66 | end 67 | end 68 | if not dists then return nil, "No dists found in directory " .. dir end 69 | return dists, "Generated manifest for directory" .. dir 70 | end 71 | 72 | --- Get or generate repository contents from URI. 73 | -- @param url string: URL to load the dist.manifest from. In case file:// is used generate the manifest. 74 | -- @return dists, log: Returns true on success and nil and error message on failure. 75 | function get(src, variables) 76 | assert(type(src) == "string", "manifest:get, argument 'url' is not a string." ) 77 | 78 | -- If the src is local then make the manifest 79 | local dir = src:gsub("^file://","") 80 | local dists 81 | 82 | -- If src points to a unpacked dist 83 | if sys.isFile(sys.path(src, "dist.info")) then 84 | local dist = info(sys.path(src, "dist.info")) 85 | if dist then dists = { dist } end 86 | -- If src points to a dir 87 | elseif sys.isDir(dir) then 88 | dists = make(dir) 89 | -- Try collecting from manifest, assuming non-local reporitory 90 | else 91 | local manifest = fetch.get(sys.path(src, "dist.manifest")) 92 | if not manifest then return nil, "Could not obtain manifest for " .. src end 93 | dists = persist.loadText(manifest) 94 | end 95 | 96 | -- Sort by name and version 97 | if not dists then return nil, "No suitable dists found in " .. src end 98 | 99 | -- Check every dist 100 | local checked 101 | for i = 1, #dists do 102 | local dist, err = info(dists[i]) 103 | if dist then 104 | -- Dist is ok 105 | checked = checked or {} 106 | if not string.match(dist.path, "^https?://") then 107 | dist.path = sys.path(src:gsub("file://",""), dist.path) 108 | end 109 | table.insert(checked, dist) 110 | else 111 | -- Malformed dist 112 | local name = tostring(dist.name) .. " " .. tostring(dist.version) 113 | log.message("Warning, skipped malformed dist.info (" .. name .. ") from:", src, "err:", err) 114 | end 115 | end 116 | if not checked then return nil, "No suitable dists found in " .. src end 117 | 118 | table.sort(checked, function(a, b) 119 | -- If names match 120 | if a.name == b.name then 121 | -- When versions match 122 | if a.version == b.version then 123 | -- Prefer Universal arch 124 | if a.arch == b.arch then 125 | -- Prefer source arch 126 | if a.type == "source" then return false end 127 | end 128 | if a.arch == "Universal" then return false end 129 | end 130 | return dep.compareVersions(a.version ,b.version) 131 | end 132 | return a.name < b.name 133 | end) 134 | return checked, "Succesfuly obtained dists from " .. src 135 | end 136 | 137 | --- Check names in table, used in info checks. 138 | -- @param table: Table to check names in. 139 | -- @return ok, err: Returns true if everything is ok. In case of error nil and the malformed entry is returned. 140 | local function checkNames(table) 141 | for k, v in pairs(table) do 142 | if type(v) == "string" then 143 | local name, const = dep.split(v) 144 | if not name then return nil, v end 145 | elseif type(v) == "table" then 146 | return checkNames(v) 147 | else 148 | return nil, "unknown entry" 149 | end 150 | end 151 | return true 152 | end 153 | 154 | --- Load and check info from file or check info table 155 | -- @param dist string or table: Path to dist.info or info table to check. 156 | -- @return info, log: Table containing loaded and checked info or nil and log message. 157 | function info(dist) 158 | assert(type(dist) == "string" or type(dist) == "table", "manifest:info, argument 'dist' is not a string or table." ) 159 | 160 | -- Load the info if needed from a file 161 | if type(dist) == "string" then 162 | dist = persist.load(dist) 163 | if not dist then return nil, "manifest.info: Failed loading dist.info from", dist end 164 | return info(dist), "manifest.info: Succesfully loaded dist.info from", dist 165 | end 166 | 167 | -- Add arch-type if not present 168 | dist.arch = dist.arch or "Universal" 169 | dist.type = dist.type or "source" 170 | 171 | 172 | -- Check the info entries 173 | if type(dist.name) ~= "string" then return nil, "Info does not contain valid name." end 174 | if not dist.name:match("[%l%d%.%:%_%-]+") then return nil, "Info info entry 'name' contains invalid characters" end 175 | if type(dist.version) ~= "string" then return nil, "Info does not contain valid version." end 176 | if not dist.version:match("[%l%d%.%:%_%-]+") then return nil, "Info entry 'version' contains invalid characters" end 177 | if type(dist.arch) ~= "string" then return nil, "Info does not contain valid architecture." end 178 | if not dist.arch:match("[%a%d]") then return nil, "Info entry 'arch' contains invalid characters." end 179 | if type(dist.type) ~= "string" then return nil, "Info does not contain valid type." end 180 | if not dist.type:match("[%a%d]") then return nil, "Info entry 'type' contains invalid characters." end 181 | 182 | -- Optional 183 | if dist.desc and type(dist.desc) ~= "string" then return nil, "Info does not contain valid description." end 184 | if dist.author and type(dist.author) ~= "string" then return nil, "Info does not contain valid author." end 185 | if dist.maintainer and type(dist.maintainer) ~= "string" then return nil, "Info does not contain valid maintainer." end 186 | if dist.url and type(dist.url) ~= "string" then return nil, "Info does not contain valid url." end 187 | if dist.license and type(dist.license) ~= "string" then return nil, "Info does not contain valid license." end 188 | if dist.depends and type(dist.depends) ~= "table" then return nil, "Info does not contain valid dependencies." end 189 | 190 | -- Check dependency format, swap for arch type specific id needed 191 | local ok, err = checkNames(dist.depends or {}) 192 | if not ok then return nil, "Dependencies contain malformed entry: " .. err end 193 | 194 | -- Same for conflicts 195 | local ok, err = checkNames(dist.conflicts or {}) 196 | if not ok then return nil, "Conflicts contain malformed entry: " .. err end 197 | 198 | -- And provides 199 | local ok, err = checkNames(dist.provides or {}) 200 | if not ok then return nil, "Provides contain malformed entry: " .. err end 201 | 202 | -- Return, no log since it would spam the log file alot 203 | return dist, "Contents of dist is valid." 204 | end 205 | -------------------------------------------------------------------------------- /dist/package.lua: -------------------------------------------------------------------------------- 1 | --- LuaDist package specific functions 2 | -- Peter Drahoš, Peter Kapec, LuaDist Project, 2010 3 | 4 | --- Package handling functions. 5 | -- This module deals with packages, these are unpacked dists in LuaDist terminology 6 | -- The following functions are provided: 7 | -- unpack - fetch and unpack a dist 8 | -- build - compile a source dist 9 | -- deploy - install a dist into deployment 10 | -- pack - create dist from package 11 | -- delete - delete package 12 | 13 | module ("dist.package", package.seeall) 14 | 15 | local config = require "dist.config" 16 | local fetch = require "dist.fetch" 17 | local persist = require "dist.persist" 18 | local sys = require "dist.sys" 19 | local manif = require "dist.manifest" 20 | local log = require "dist.log" 21 | 22 | --- Fetch and unpack zip/dist from URL into dest directory. 23 | -- @param url string: Local packed dist or URL to fetch dist from. 24 | -- @param dest string: Destination to unpack contents into, nil for temp directory. 25 | -- @return path, log: Unpacked dist path or nil and log. 26 | function unpack(url, dest) 27 | -- Make sure dest is set up properly 28 | dest = sys.path(dest) or config.temp 29 | 30 | -- Check types 31 | assert(type(url)=="string", "package.unpack: Argument 'url' is not a string.") 32 | assert(type(dest)=="string", "package.unpack: Argument 'dest' is not a string.") 33 | 34 | -- Setup destination 35 | local name = url:match("([^/]+)%.[^%.]+$") 36 | if not name then return nil, "Could not determine dist name from " .. url end 37 | local pkg = sys.path(dest, name) 38 | local dist = pkg .. ".dist" 39 | 40 | -- If the files already exist 41 | if sys.exists(pkg) then return pkg, "Skipped unpack, destination " .. dest .. " exists." end 42 | 43 | -- Download if needed 44 | if not sys.exists(dist) then 45 | -- Download from URL or local path. Fetch handles this 46 | dist = fetch.download(url) 47 | if not dist then return nil, "Failed to download " .. url end 48 | end 49 | 50 | -- Unzip 51 | local ok = sys.unzip(dist, pkg) 52 | if not ok then return nil, "Failed to unzip " .. dist .. " to " .. pkg end 53 | 54 | -- Cleanup 55 | if not config.debug then sys.delete(dist) end 56 | 57 | return pkg, "Unpacked " .. url .. " to " .. pkg 58 | end 59 | 60 | --- Build, deploy and test a source dist using CMake. 61 | -- @param dist string: Directory of the source dist to build. 62 | -- @param variables: Table containing optional CMake parameters. 63 | -- @return path, log: Returns temporary directory the dist was build into and log message. 64 | function build(dist, depl, variables) 65 | -- Make sure deployment is always set up 66 | depl = sys.path(depl) or config.root 67 | 68 | assert(type(dist)=="string", "package.build: Arument 'dist' is not a string.") 69 | assert(type(depl)=="string", "package.build: Argument 'depl' is not a string.") 70 | assert(type(variables)=="table", "package.build: Argument 'variables' is not a table.") 71 | 72 | -- Load dist info 73 | local info = manif.info(sys.path(dist, "dist.info")) 74 | if not info then return nil, "Directory " .. dist .. " does not contain valid dist.info." end 75 | 76 | -- Prepare temporary directory and build directory 77 | local install = sys.path(config.temp,info.name .. "-" .. info.version .. "-" .. config.arch .. "-" .. config.type) 78 | local build = sys.path(config.temp,info.name .. "-" .. info.version .. "-CMake-build") 79 | sys.makeDir(install) 80 | sys.makeDir(build) 81 | 82 | -- Prepare CMackeCache 83 | variables["CMAKE_INSTALL_PREFIX"] = install 84 | 85 | local cache = assert(io.open(build..'/cache.cmake', "w"), "Could not create cache file.") 86 | for k,v in pairs(variables) do 87 | cache:write('SET('..k..' "' .. tostring(v) ..'" CACHE STRING "" FORCE)\n') 88 | end 89 | cache:close() 90 | 91 | -- Determine build commands 92 | local make = config.make 93 | local cmake = config.cmake 94 | local ctest = config.ctest 95 | if config.debug then 96 | make = config.makeDebug 97 | cmake = config.cmakeDebug 98 | ctest = config.ctestDebug 99 | end 100 | 101 | -- Build 102 | local ok = sys.execute("cd " .. sys.Q(build) .. " && " .. cmake .. " -C cache.cmake " .. sys.Q(dist)) 103 | if not ok then return nil, "CMake failed pre-cmake script in directory " .. build end 104 | local ok = sys.execute("cd " .. sys.Q(build) .. " && " .. make) 105 | if not ok then return nil, "CMake failed building in directory " .. build end 106 | if config.test then 107 | local ok = sys.execute("cd " .. sys.Q(build) .. " && " .. ctest) 108 | if not ok then return nil, "CMake failed test in directory " .. build end 109 | end 110 | 111 | -- Save info 112 | info.arch = config.arch 113 | info.type = config.type 114 | local ok = persist.save(sys.path(install, "dist.info"), info ) 115 | if not ok then return nil, "Cannot wite dist.info to" .. fullDist end 116 | 117 | -- Deploy the dist 118 | local ok, err = deploy(install, depl) 119 | if not ok then return nil, err end 120 | 121 | -- Clean up 122 | if not config.debug then sys.delete(build) sys.delete(install) end 123 | 124 | return install, "Successfully built dist in " .. install 125 | end 126 | 127 | --- Deploy dist into deployment directory. 128 | -- @param dist string: Directory of the dist to deploy. 129 | -- @param depl string: Deployment directory nil for default. 130 | -- @return ok, log: Returns true on success and log message. 131 | function deploy(dist, depl) 132 | -- Make sure deployment is always set up 133 | depl = sys.path(depl) or config.root 134 | 135 | assert(type(dist)=="string", "package.deploy: Argument 'dist' is not a string.") 136 | assert(type(depl)=="string", "package.deploy: Argument 'depl' is not a string.") 137 | 138 | -- Load dist info 139 | local info = manif.info(sys.path(dist, "dist.info")) 140 | if not info then return nil, "Directory " .. dist .. " does not contain valid dist.info" end 141 | 142 | -- Relative and full path to dist deployment 143 | local distRel = config.dists .. "/" .. info.name .. "-" .. info.version 144 | local distPath = sys.path(depl, distRel) 145 | 146 | -- If we are deploying a dist into itself 147 | if distPath == dist then return 148 | true, "Skipping, already deployed" 149 | end 150 | 151 | -- Copy to install dir 152 | sys.makeDir(depl) 153 | sys.makeDir(distPath) 154 | 155 | -- Collect files to process 156 | local files = sys.list(dist) 157 | 158 | -- Simple copy deployment 159 | for i = 1, #files do 160 | local file = files[i] 161 | if file~="dist.info" then 162 | local path = sys.path(dist, file) 163 | -- Create directory in depl 164 | if sys.isDir(path) then 165 | local ok, err = sys.makeDir(sys.path(depl, file)) 166 | if not ok then return nil, "Failed to install " .. dist .. "/" .. file .. " to " .. depl end 167 | -- Copy files to depl 168 | else 169 | local ok, err = sys.copy(sys.path(dist, file), sys.path(depl, file)) 170 | if not ok then return nil, "Failed to install " .. dist .. "/" .. file .. " to " .. depl end 171 | end 172 | end 173 | end 174 | 175 | -- Modify and save dist.info 176 | info.files = files 177 | 178 | local ok = persist.save(sys.path(distPath, "dist.info"), info) 179 | if not ok then return nil, "Cannot wite dist.info to" .. distPath end 180 | 181 | return true, "Successfully deployed dist to " .. depl 182 | end 183 | 184 | --- Pack a package to create a dist. 185 | -- @param dist string: deployed dist to pack. 186 | -- @param depl string: deployment dir to pack from. 187 | -- @param dir string: Optional destination for the dist, current directory will be used by default. 188 | -- @return ok, log: Returns success and log message. 189 | function pack(dist, depl, dir) 190 | depl = depl or dist 191 | assert(type(dist)=="string", "package.pack: Argument 'dist' is not a string.") 192 | assert(not dir or type(dir)=="string", "package.pack: Argument 'dir' is no a string.") 193 | if not dir then dir = sys.curDir() end 194 | 195 | -- Get the manifest of the dist 196 | local info = manif.info(sys.path(dist, "dist.info")) 197 | if not info then return nil, "Dist does not contain valid dist.info in " .. dist end 198 | 199 | -- Create temporary folder 200 | local pkg = info.name .. "-" .. info.version .. "-" .. info.arch .. "-" .. info.type 201 | if info.arch == "Universal" and info.type == "source" then 202 | pkg = info.name .. "-" .. info.version 203 | end 204 | 205 | local tmp = sys.path(config.temp, pkg) 206 | sys.makeDir(tmp) 207 | 208 | -- Copy dist files into temporary folder 209 | local files = info.files or sys.list(dist) 210 | if not files then return nil, "Failed to collect files for dist in " .. dist end 211 | 212 | for i = 1, #files do 213 | local file = files[i] 214 | if sys.isDir(sys.path(depl, file)) then 215 | sys.makeDir(sys.path(tmp, file)) 216 | elseif file ~= "dist.info" then 217 | local ok = sys.copy(sys.path(depl, file), sys.path(tmp, file)) 218 | if not ok then return nil, "Pack failed to copy file " .. file end 219 | end 220 | end 221 | 222 | -- Clean obsolete dist.info entries 223 | info.path = nil 224 | info.files = nil 225 | local ok, err = persist.save(sys.path(tmp, "dist.info"), info) 226 | if not ok then return nil, "Could not update dist.info." end 227 | 228 | -- Zip dist files in the temporary folder. The zip will be placed into LuaDist/tmp folder 229 | -- This cleans up .git .svn and Mac .DS_Store files. 230 | local ok = sys.zip(config.temp, pkg .. ".dist", pkg, '-x "*.git*" -x "*.svn*" -x "*~" -x "*.DS_Store*"') 231 | if not ok then return nil, "Failed to compress files in" .. pkg end 232 | local ok = sys.move(tmp .. ".dist", dir .. "/") -- Adding the "/" gets around ambiguity issues on Windows. 233 | if not ok then return nil, "Could not move dist to target directory " .. dir end 234 | 235 | -- Remove the temporary folder 236 | if not config.debug then sys.delete(tmp) end 237 | return true, "Sucessfully packed dist " .. dist .. " to " .. dir 238 | end 239 | 240 | --- Delete a deployed dist. 241 | -- @param dist string: dist to delete. 242 | -- @param depl string: deployment dir to delete from. 243 | -- @return ok, log: Returns success and nlog message. 244 | function delete(dist, depl) 245 | assert(type(dist)=="string", "package.delete: Argument 'dist' is not a string.") 246 | assert(type(dist)=="string", "package.delete: Argument 'depl' is not a string.") 247 | 248 | -- Get the manifest of the dist 249 | local info = manif.info(sys.path(dist, "dist.info")) 250 | if not info then return nil, "Dist does not contain valid dist.info in " .. dist end 251 | 252 | -- Delete installed files 253 | local files = info.files 254 | if not files then return nil, "Failed to collect files for dist in " .. dist end 255 | 256 | -- Remove list backwards to empty dirs 1st. 257 | for i = #files, 1, -1 do 258 | local file = sys.path(depl, files[i]) 259 | -- Delete deployed file 260 | if sys.isFile(file) then 261 | sys.delete(file) 262 | end 263 | -- Delete empty directories 264 | if sys.isDir(file) then 265 | local contents = sys.dir(file) 266 | if #contents == 0 then 267 | sys.delete(file) 268 | end 269 | end 270 | end 271 | 272 | -- Delete dist directory 273 | local ok = sys.delete(dist) 274 | if not ok then return nil, "Deleting dist files failed in " .. dist end 275 | 276 | return true, "Successfully removed dist " .. dist 277 | end 278 | -------------------------------------------------------------------------------- /dist/persist.lua: -------------------------------------------------------------------------------- 1 | --- LuaDist simple persistance functions 2 | -- Peter Drahoš, LuaDist Project, 2010 3 | -- Original Code borrowed from LuaRocks Project 4 | 5 | --- Persistency table serializarion. 6 | --- 2DO: If a better persistency dist with good readability becomes available change this code 7 | -- This module contains functions that deal with serialization and loading of tables. 8 | -- loadText - text 2 table 9 | -- load - file 2 table 10 | -- saveText - table 2 text 11 | -- save - table 2 file 12 | -- saveManifest - variant of save for manifests 13 | 14 | module ("dist.persist", package.seeall) 15 | 16 | local sys = require "dist.sys" 17 | 18 | --- Serialize a table into text. 19 | -- @param tbl table: Table to serialize. 20 | -- @param d number: Intendation lenght. 21 | -- @return out string: Serialized text. 22 | local function serialize(o, d) 23 | local out = "" 24 | if not d then d = 0 end 25 | 26 | if type(o) == "number" then 27 | out = out .. tostring(o) 28 | elseif type(o) == "table" then 29 | out = out .."{\n" 30 | for k,v in pairs(o) do 31 | for f = 1,d do out = out .."\t" end 32 | 33 | if type(k) ~="number" then 34 | out = out .."\t['" ..tostring(k) .."'] = " 35 | end 36 | 37 | for f = 1,d do out = out .."\t" end 38 | out = out .. serialize(v, d + 1) 39 | if type(v) ~= "table" then out = out ..",\n" end 40 | end 41 | for f = 1,d do out = out .."\t" end 42 | out = out .."},\n" 43 | else 44 | out = out .. '[[' .. tostring(o) .. ']]' 45 | end 46 | return out 47 | end 48 | 49 | --- Load table from text. 50 | -- @param text string: Text to load table from. 51 | -- @return table, log: Returns table on success, nil on failure and log message. 52 | function loadText(text) 53 | assert(type(text) == "string", "persist.loadText: Argument 'text' is not a string.") 54 | 55 | local chunk, err = loadstring(text) 56 | if not chunk then return false, "Failed to parse text " .. err end 57 | 58 | local result = {} 59 | 60 | setfenv(chunk, result) 61 | local ok, ret, err = pcall(chunk) 62 | if not ok then return false, ret end 63 | return ret or result, "Sucessfully loaded table from text" 64 | end 65 | 66 | --- Load table from file. 67 | -- @param filename string: File to load table from 68 | -- @return table, log: Returns table on success, nil on failure and log message. 69 | function load(filename) 70 | assert(type(filename) == "string", "persist.load: Argument 'filename' is not a string.") 71 | 72 | local chunk, err = loadfile(filename) 73 | if not chunk then return false, "Cannot load from file " .. filename end 74 | 75 | local result = {} 76 | 77 | setfenv(chunk, result) 78 | local ok, ret, err = pcall(chunk) 79 | if not ok then return false, ret end 80 | return ret or result, "Sucessfully loaded table from file " .. filename 81 | end 82 | 83 | --- Save table to string. Used for dist.info. 84 | -- @param tbl table: Table to save. 85 | -- @return out string: Serialized text. 86 | function saveText(tbl) 87 | assert(type(tbl) == "table", "persist.save: Argument 'tbl' is not a table.") 88 | 89 | local out = "" 90 | for k, v in pairs(tbl) do 91 | -- Small fix for non alphanumeric strings (i know it looks ugly) 92 | if not k:match("[^%w_]*$") then k = "_G['" .. k .. "']" end 93 | if type(v) == 'table' then 94 | -- little trick so top-level table won't have commas, but sub-tables will have 95 | out = out .. k .. " = " .. serialize(v):gsub(',\n$', '\n') .."\n" 96 | else 97 | out = out .. k ..' = "' .. tostring(v):gsub('"','\\"') ..'"\n' 98 | end 99 | end 100 | return out 101 | end 102 | 103 | --- Special serialization formating for manifests. 104 | -- @param filename string: Path to save manifest to 105 | -- @return ok, log: Returns true on success, nil on failure and log message. 106 | function saveManifest(filename, dists) 107 | assert(type(filename) == "string", "persist.saveManifest: Argument 'filename' is not a string.") 108 | assert(type(dists) == "table", "persist.saveManifest: Argument 'dists' is not a table.") 109 | 110 | local out = io.open(filename, "w") 111 | if not out then return false, "Cannot write to file " .. filename end 112 | 113 | out:write("return "); 114 | out:write(serialize(dists).."true") 115 | out:close() 116 | return true, "Successfully saved manifest to " .. filename 117 | end 118 | 119 | --- Save table to file. 120 | -- @param filename string: File to save table to. 121 | -- @param tbl table: Table to save. 122 | -- @return ok, log: Returns true on success, nil on failure and log message. 123 | function save(filename, tbl) 124 | assert(type(filename) == "string", "persist.save: Argument 'filename' is not a string.") 125 | assert(type(tbl) == "table", "persist.save: Argument 'tbl' is not a table.") 126 | 127 | local out = io.open(filename, "w") 128 | if not out then return false, "Cannot write to file" .. filename end 129 | out:write(saveText(tbl) or "") 130 | out:close() 131 | return true, "Successfully saved table to " .. filename 132 | end 133 | -------------------------------------------------------------------------------- /dist/sys.lua: -------------------------------------------------------------------------------- 1 | --- LuaDist UNIX and Windows system functions 2 | -- Peter Drahoš, LuaDist Project, 2010 3 | -- Original Code contributed to and then borrowed back from the LuaRocks Project 4 | 5 | --- Host system dependent commands. 6 | -- Override the default UNIX commands if needed for your platform. 7 | -- Commands currently depend on popen and unzip being available. For future releases we would like 8 | -- to use lua packages handling the compression issues. Additionally some filesystem functionality 9 | -- not available in luafilesystem is emulated here. 10 | 11 | module ("dist.sys", package.seeall) 12 | 13 | local log = require "dist.log" 14 | local config = require "dist.config" 15 | local lfs = require "lfs" 16 | 17 | --- Quote argument for shell processing. 18 | -- Adds single quotes and escapes. 19 | -- @param arg string: Unquoted argument. 20 | -- @return string: Quoted argument. 21 | function Q(arg) 22 | assert(type(arg) == "string", "Q argument 'arg' is not a string.") 23 | 24 | return "'" .. arg:gsub("\\", "\\\\"):gsub("'", "'\\''") .. "'" 25 | end 26 | 27 | --- Compose full system path or part of url 28 | -- @args string: Path components 29 | -- @return string: Path string 30 | function path(...) 31 | local args = ... 32 | --if not args then return curDir() end 33 | if type(...) == "string" then args = { ... } end 34 | if type(args) ~= "table" then return nil end 35 | 36 | if args[1]:match("^[%a:]*[/\\]") then 37 | return table.concat(args,"/") 38 | end 39 | return curDir() .. "/" .. table.concat(args,"/") 40 | end 41 | 42 | --- Run the given system command. 43 | -- The command is executed in the current directory in the dir stack. 44 | -- @param cmd string: No quoting/escaping is applied to the command. 45 | -- @return boolean: True if command succeeds, false otherwise. 46 | function executeString(cmd) 47 | assert(type(cmd) == "string", "sys.executeString: Argument 'cmd' is not a string.") 48 | 49 | -- Command log 50 | local execPath = path(config.temp, "execute.log") 51 | 52 | -- Hande std output 53 | local run = cmd 54 | if not ( config.verbose or config.debug) then 55 | run = run .. " >" .. execPath .. " 2>&1" 56 | end 57 | 58 | -- Run the command 59 | local ok = os.execute( run ) 60 | 61 | -- Append the execution log to the log 62 | local execFile, err = io.open( execPath, "r") 63 | if execFile then 64 | assert(execFile, "sys.executeString: Cannot create log.") 65 | log.write("Command: " .. cmd .. "\n" .. execFile:read("*all") .. "\n") 66 | execFile:close() 67 | if not config.debug then os.remove(execPath) end 68 | end 69 | 70 | if ok~=0 then return nil, "Failed running command: " .. cmd end 71 | return true, "Sucessfully executed command: " .. cmd 72 | end 73 | 74 | --- Run the given system command, quoting its arguments. 75 | -- The command is executed in the current directory in the dir stack. 76 | -- @param command string: The command to be executed. No quoting/escaping need to be applied. 77 | -- @param ... strings: containing additional arguments, which are quoted. 78 | -- @return ok, log: true on success, false on failure and log message. 79 | function execute(command, ...) 80 | assert(type(command) == "string", "execute argument 'command' is not a string.") 81 | 82 | for k, arg in ipairs({...}) do 83 | assert(type(arg) == "string", "execute argument #" .. tostring(k+1) .. "is not a string.") 84 | command = command .. " " .. Q(arg) 85 | end 86 | return executeString(command) 87 | end 88 | 89 | --- Create a directory. 90 | -- @param dir string: Path to create. 91 | -- @return ok, log: true on success, false on failure and log message. 92 | -- Succeeds if already exists. 93 | function makeDir(dir) 94 | assert(type(dir)=="string", "sys.makeDir: Argument 'dir' is not a string.") 95 | dir = path(dir) 96 | 97 | if isDir(dir) then return true end -- done 98 | 99 | -- Find out if the base dir exists, if not make it 100 | local base = dir:gsub("/[^/]*$","") 101 | if base == "" then base = "/" end 102 | -- Recursion! 103 | if not isDir(base) then makeDir(base) end 104 | 105 | -- Make directory 106 | local ok = lfs.mkdir(dir) 107 | if not ok then return nil, "Cannot create directory: " .. dir end 108 | return true, "Created directory: " .. dir 109 | end 110 | 111 | --- Force delete a file, even if it is open. 112 | -- If the file can't be deleted because it is currently open, this function 113 | -- will try to rename the file to a temporary file in the same directory. 114 | -- Windows in particular doesn't allow running executables to be deleted, but 115 | -- it does allow them to be renamed. Cygwin 1.7 (unlike 1.5) does allow such 116 | -- deletion but internally implements it via a mechanism like this. For 117 | -- futher details, see 118 | -- http://sourceforge.net/mailarchive/message.php?msg_name=bc4ed2190909261323i7c6280bfp6e7be6f70c713b0c%40mail.gmail.com 119 | -- 120 | -- @param src - file name 121 | function forceDelete(src) 122 | os.remove(src) -- note: ignore fail 123 | 124 | if exists(src) then -- still exists, try move instead 125 | local tempfile 126 | local MAX_TRIES = 10 127 | for i=1,MAX_TRIES do 128 | local test = src .. ".luadist-temporary-" .. i 129 | os.remove(test) -- note: ignore fail 130 | if not exists(test) then 131 | tempfile = test 132 | break 133 | end 134 | end 135 | if not tempfile then 136 | return nil, "Failed removing temporary files: " .. tempfile .. "*" 137 | end 138 | local ok, err = os.rename(src, tempfile) 139 | if not ok then 140 | return nil, "Failed renaming file: " .. err 141 | end 142 | end 143 | return true 144 | end 145 | 146 | --- Move a file from one location to another. 147 | -- @param src string: Pathname of source. 148 | -- @param dest string: Pathname of destination. 149 | -- @return ok, log: true on success, false on failure and log message. 150 | function move(src, dest) 151 | assert(type(src)=="string", "sys.move: Argument 'src' is not a string.") 152 | assert(type(dest)=="string", "sys.move: Argument 'dest' is not a string.") 153 | 154 | local ok, err = execute("mv -f", src, dest) 155 | if not ok then return nil, "Failed moving source: " .. src .. " to: " .. dest .. " error: " .. err end 156 | return true, "Moved source: " .. src .. " to: " .. dest 157 | end 158 | 159 | --- Recursive copy a file or directory. 160 | -- @param src string: Pathname of source 161 | -- @param dest string: Pathname of destination. 162 | -- @param copy_contents boolean: if true, copies contents of 163 | -- directory src into directory dest, creating dest 164 | -- and parents of dest if they don't exist. (false if omitted) 165 | -- @return ok, log: true on success, false on failure and log message. 166 | function copy(src, dest, copy_contents) 167 | assert(type(src)=="string", "copy argument 'src' is not a string.") 168 | assert(type(dest)=="string", "copy argument 'dest' is not a string.") 169 | 170 | if copy_contents and not isDir(dest) then 171 | local ok, err = makeDir(dest) 172 | if not ok then return nil, err end 173 | end 174 | 175 | local ok, err 176 | if copy_contents then 177 | ok, err = execute("cp -R -f -H " .. Q(src) .. [[/*]], dest) 178 | else 179 | ok, err = execute("cp -R -f -H ", src, dest) 180 | end 181 | if not ok then return nil, "Failed copying " .. src .. " to " .. dest .. ".\n" .. err end 182 | return true 183 | end 184 | 185 | --- little helper function to get file depth (for directories its +1) 186 | local function pathLen(dir) 187 | local _, len = dir:gsub("[^\\/]+","") 188 | return len - 1 189 | end 190 | 191 | --- Delete a file or a directory and all its contents. 192 | -- For safety, this only accepts absolute paths. 193 | -- @param dir string: Pathname of the file or directory to delete 194 | -- @return ok, log: true on success, false on failure and log message. Returns success if already deleted. 195 | function delete(dir) 196 | assert(type(dir)=="string" and dir:match("^[%a:]*[/\\]"), "delete argument 'dir' is not a string or a full path.") 197 | if not exists(dir) then return true end 198 | return executeString("rm -rf " .. Q(dir)) 199 | end 200 | 201 | --- List the contents of a directory. 202 | -- @param path string: directory to list if not specified the current directory will be used. 203 | -- @return table: an array of strings with the filenames representing the contents of a directory. 204 | function dir(dir) 205 | assert(not dir or type(dir) == "string", "dir argument 'dir' is not a string.") 206 | dir = dir or curDir() 207 | if not isDir(dir) then return nil, "Could not find directory " .. dir .. "." end 208 | local files = {} 209 | for file in lfs.dir(dir) do 210 | if not file:match("^%.") then table.insert(files, file) end 211 | end 212 | return files 213 | end 214 | 215 | --- Get current directory. 216 | -- @return string: current direcotry. 217 | function curDir() 218 | local dir, err = lfs.currentdir() 219 | if not dir then return nil, err end 220 | return dir:gsub("\\","/") -- Everyone loves win32 221 | end 222 | 223 | --- Test for existance of a file. 224 | -- @param path string: filename to test 225 | -- @return ok, log: true on success, false on failure and log message. 226 | function exists(dir) 227 | assert(type(dir)=="string", "exists argument 'dir' is not a string.") 228 | return lfs.attributes(dir) 229 | end 230 | 231 | --- Test is pathname is a directory. 232 | -- @param path string: pathname to test 233 | -- @return ok, log: true on success, false on failure and log message. 234 | function isDir(dir) 235 | assert(type(dir)=="string", "isDir argument 'dir' is not a string.") 236 | local attr, err = lfs.attributes(dir) 237 | if not attr then return nil, "Failed to obtain attributes for " .. dir .. "." end 238 | return attr.mode == "directory" 239 | end 240 | 241 | --- Test is pathname is a file. 242 | -- @param path string: pathname to test 243 | -- @return ok, log: true on success, false on failure and log message. 244 | function isFile(dir) 245 | assert(type(dir)=="string", "isFile argument 'dir' is not a string.") 246 | local attr, err = lfs.attributes(dir) 247 | if not attr then return nil, "Failed to obtain attributes for " .. dir .. "." end 248 | return attr.mode == "file" 249 | end 250 | 251 | --- Recursively list the contents of a directory. 252 | -- @param path string: directory to list if not specified the current directory will be used 253 | -- @return table: an array of strings representing the contents of the directory structure 254 | function list(dir) 255 | assert(type(dir)=="string", "list argument 'path' is not a string.") 256 | if not isDir(dir) then return nil, "Directory " .. dir .. " does not exist." end 257 | 258 | local files = {} 259 | 260 | local function collect (subdir) 261 | subdir = subdir or "" 262 | for file in lfs.dir(path(dir, subdir)) do 263 | if not file:match("^%.") then 264 | table.insert(files, subdir .. file) 265 | if isDir(path(dir, subdir .. file)) then collect(subdir .. "/" .. file .. "/") end 266 | end 267 | end 268 | end 269 | collect() 270 | return files 271 | end 272 | 273 | --- Compress files in a .zip archive. 274 | -- @param zipfile string: pathname of .zip archive to be created. 275 | -- @param ... Filenames to be stored in the archive are given as additional arguments. 276 | -- @return ok, log: true on success, false on failure and log message. 277 | function zip(workdir, zipfile, ...) 278 | assert (type(workdir)=="string", "zip argument 'workdir' is not a string.") 279 | assert (type(zipfile)=="string", "zip argument 'zipfile' is not a string.") 280 | return execute("cd " .. Q(workdir) .. " && "..config.root.."/bin/zip -r", zipfile, ...) or 281 | execute("cd " .. Q(workdir) .. " && zip -r", zipfile, ...) 282 | end 283 | 284 | --- Unpack an archive. 285 | -- Extract the contents of an archive, detecting its format by filename extension. 286 | -- @param archive string: Filename of archive. 287 | -- @return ok, log: true on success, false on failure and log message. 288 | function unzip(archive, dest) 289 | assert(type(archive) == "string", "unpack argument 'archive' is not a string.") 290 | assert(type(dest) == "string", "unpack agrument 'dest' is not a string.") 291 | local ok 292 | if archive:match("%.zip$") or archive:match("%.dist$") then 293 | ok = executeString(config.root.."/bin/unzip " .. Q(archive) .. " -d " .. Q(dest)) or 294 | executeString("unzip " .. Q(archive) .. " -d " .. Q(dest)) 295 | end 296 | if not ok then 297 | return false, "Failed extracting." 298 | end 299 | return dest 300 | end 301 | 302 | --- Extract file contents of a file from archive 303 | -- @param zipfile string: pathname of .zip/.dist archive to read from. 304 | -- @param file string: file to get contents of. 305 | -- @return contents, err: returns contents of file or false and error message. 306 | -- Requires io.popen (2DO: work when io.popen not available?) 307 | function getZipFile(zipfile, file) 308 | assert(type(zipfile) == "string", "unpack argument 'zipfile' is not a string.") 309 | assert(type(file) == "string", "unpack agrument 'file' is not a string.") 310 | 311 | -- Try to get contents 312 | local f, err = io.popen(config.root.."/bin/unzip -cp " .. Q(zipfile) .. " " .. Q(file)) or 313 | io.popen("unzip -cp " .. Q(zipfile) .. " " .. Q(file)) 314 | if not f then return false, "Failed to extract " .. file .. " from " .. zipfile end 315 | 316 | -- Read result 317 | local content = f:read("*a") 318 | f:close() 319 | if content == "" then return false, "Failed to extract " .. file .. " from " .. zipfile end 320 | return content 321 | end 322 | 323 | --- Override different functions for Windows 324 | if config.arch == "Windows" then 325 | 326 | --- Quote argument for shell processing (Windows). 327 | -- Adds single quotes and escapes. 328 | -- @param arg string: Unquoted argument. 329 | -- @return string: Quoted argument. 330 | function Q(arg) 331 | assert(type(arg) == "string", "Q argument 'arg' is not a string.") 332 | -- Quote DIR for Windows 333 | if arg:match("^[\.a-zA-Z]?:?[\\/]") then 334 | return '"' .. arg:gsub("//","\\"):gsub("/", "\\"):gsub('"', '\\"') .. '"' 335 | end 336 | -- URLs and anything else 337 | return '"' .. arg:gsub('"', '\\"') .. '"' 338 | end 339 | 340 | --- Move a file from one location to another (Windows). 341 | -- @param src string: Pathname of source. 342 | -- @param dest string: Pathname of destination. 343 | -- @return ok, log: true on success, false on failure and log message. 344 | function move(src, dest) 345 | assert(type(src)=="string", "sys.move: Argument 'src' is not a string.") 346 | assert(type(dest)=="string", "sys.move: Argument 'dest' is not a string.") 347 | 348 | -- note: copy+delete may be more reliable than move (e.g. copy across drives). 349 | -- [improve: cleanup on failure?] 350 | local ok, err = copy(src, dest) 351 | if ok then 352 | ok, err = delete(src) 353 | end 354 | if not ok then return nil, "Failed moving source: " .. src .. " to: " .. dest .. " error: " .. err end 355 | return true, "Moved source: " .. src .. " to: " .. dest 356 | end 357 | 358 | --- Recursive copy a file or directory (Windows). 359 | -- @param src string: Pathname of source 360 | -- @param dest string: Pathname of destination. 361 | -- If `src` is a directory, copies contents of `src` into contents of 362 | -- directory `dest`. Otherwise, both must represent files. 363 | -- @return ok, log: true on success, false on failure and log message. 364 | function copy(src, dest) 365 | assert(type(src)=="string", "copy argument 'src' is not a string.") 366 | assert(type(dest)=="string", "copy argument 'dest' is not a string.") 367 | 368 | -- Avoid ambiguous behavior: file <-> directory 369 | --2DO - Improve? 370 | if isFile(src) then 371 | if isDir(dest) then 372 | return nil, "ambiguous request to copy file " .. src .. " to directory " .. dest 373 | end 374 | elseif isDir(src) then 375 | if isFile(dest) then 376 | return nil, "ambiguous request to copy directory " .. src .. " to file " .. dest 377 | end 378 | end 379 | 380 | --2DO: The below will cause problems if src and dest are the same. 381 | 382 | -- For any destination files that will be overwritten, 383 | -- force delete them to avoid conflicts from open files 384 | -- in subsequent copy. 385 | if isDir(src) then 386 | local srcfiles = list(src) 387 | for i = 1, #srcfiles do 388 | local destfile = path(dest, srcfiles[i]) 389 | if isFile(destfile) then 390 | local ok, err = forceDelete(destfile) 391 | if not ok then return nil, "Failed removing file: " .. destfile .. " " .. err end 392 | end 393 | end 394 | elseif isFile(src) then 395 | local ok, err = forceDelete(dest) 396 | if not ok then return nil, "Failed removing file: " .. dest .. " " .. err end 397 | end 398 | 399 | local ok, err 400 | if isDir(src) then 401 | -- note: "xcopy /E /I /Y" copies contents of `src` into contents 402 | -- of `dest` and creates all leading directories of `dest` if needed. 403 | ok, err = execute("xcopy /I /E /Y " .. Q(src), dest) 404 | else 405 | ok, err = execute("copy /Y", src, dest) 406 | end 407 | if not ok then return nil, "Failed copying " .. src .. " to " .. dest .. ".\n" .. err end 408 | -- note: The /Q flag on xcopy is not fully quiet; it prints 409 | -- "1 File(s) copied". Copy lacks a /Q flag. 410 | 411 | return true 412 | end 413 | 414 | --- Delete a file or a directory and all its contents (Windows). 415 | -- For safety, this only accepts absolute paths. 416 | -- @param dir string: Pathname of the file or directory to delete 417 | -- @return ok, log: true on success, false on failure and log message. 418 | -- Returns success if already deleted. 419 | function delete(dir) 420 | assert(type(dir)=="string" and dir:match("^[%a:]*[/\\]"), "delete argument 'dir' is not a string or a full path.") 421 | -- Note: `del /S` recursively deletes files but not directories. 422 | -- `rmdir /S` recursively deletes files and directories but does not 423 | -- work if its parameter is a file. 424 | if not exists(dir) then 425 | return true 426 | elseif isDir(dir) then 427 | local ok, err = executeString("rmdir /S /Q " .. Q(dir)) 428 | if not ok then 429 | return nil, "Could not recursively delete directory " .. dir .. " . " .. err 430 | end 431 | else 432 | local ok, err = os.remove(dir) 433 | if not ok then 434 | return nil, "Could not delete file " .. dir .. " . " .. err 435 | end 436 | end 437 | return true 438 | end 439 | end 440 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | Reference 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 |
14 | 15 |
16 |
17 |
18 | 19 |
20 | 21 | 81 | 82 |
83 | 84 | 85 | 86 |

Modules

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 |
distThis file contains the basic functions of LuaDist.
dist.depDependency handling functions.
dist.fetchThis module is responsible for downloading contents using URIs.
dist.logVery simple log system.
dist.manifestThe purpose of this module is to check and collect dist manifests.
dist.packagePackage handling functions.
dist.persistPersistency table serializarion.
dist.sysHost system dependent commands.
131 | 132 | 133 | 134 | 135 | 136 | 137 |
138 | 139 |
140 | 141 |
142 |

Valid XHTML 1.0!

143 |
144 | 145 |
146 | 147 | 148 | -------------------------------------------------------------------------------- /doc/luadoc.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin-left: 1em; 3 | margin-right: 1em; 4 | font-family: arial, helvetica, geneva, sans-serif; 5 | background-color:#ffffff; margin:0px; 6 | } 7 | 8 | code { 9 | font-family: "Andale Mono", monospace; 10 | } 11 | 12 | tt { 13 | font-family: "Andale Mono", monospace; 14 | } 15 | 16 | body, td, th { font-size: 11pt; } 17 | 18 | h1, h2, h3, h4 { margin-left: 0em; } 19 | 20 | textarea, pre, tt { font-size:10pt; } 21 | body, td, th { color:#000000; } 22 | small { font-size:0.85em; } 23 | h1 { font-size:1.5em; } 24 | h2 { font-size:1.25em; } 25 | h3 { font-size:1.15em; } 26 | h4 { font-size:1.06em; } 27 | 28 | a:link { font-weight:bold; color: #004080; text-decoration: none; } 29 | a:visited { font-weight:bold; color: #006699; text-decoration: none; } 30 | a:link:hover { text-decoration:underline; } 31 | hr { color:#cccccc } 32 | img { border-width: 0px; } 33 | 34 | 35 | h3 { padding-top: 1em; } 36 | 37 | p { margin-left: 1em; } 38 | 39 | p.name { 40 | font-family: "Andale Mono", monospace; 41 | padding-top: 1em; 42 | margin-left: 0em; 43 | } 44 | 45 | blockquote { margin-left: 3em; } 46 | 47 | pre.example { 48 | background-color: rgb(245, 245, 245); 49 | border-top-width: 1px; 50 | border-right-width: 1px; 51 | border-bottom-width: 1px; 52 | border-left-width: 1px; 53 | border-top-style: solid; 54 | border-right-style: solid; 55 | border-bottom-style: solid; 56 | border-left-style: solid; 57 | border-top-color: silver; 58 | border-right-color: silver; 59 | border-bottom-color: silver; 60 | border-left-color: silver; 61 | padding: 1em; 62 | margin-left: 1em; 63 | margin-right: 1em; 64 | font-family: "Andale Mono", monospace; 65 | font-size: smaller; 66 | } 67 | 68 | 69 | hr { 70 | margin-left: 0em; 71 | background: #00007f; 72 | border: 0px; 73 | height: 1px; 74 | } 75 | 76 | ul { list-style-type: disc; } 77 | 78 | table.index { border: 1px #00007f; } 79 | table.index td { text-align: left; vertical-align: top; } 80 | table.index ul { padding-top: 0em; margin-top: 0em; } 81 | 82 | table { 83 | border: 1px solid black; 84 | border-collapse: collapse; 85 | margin-left: auto; 86 | margin-right: auto; 87 | } 88 | th { 89 | border: 1px solid black; 90 | padding: 0.5em; 91 | } 92 | td { 93 | border: 1px solid black; 94 | padding: 0.5em; 95 | } 96 | div.header, div.footer { margin-left: 0em; } 97 | 98 | #container 99 | { 100 | margin-left: 1em; 101 | margin-right: 1em; 102 | background-color: #f0f0f0; 103 | } 104 | 105 | #product 106 | { 107 | text-align: center; 108 | border-bottom: 1px solid #cccccc; 109 | background-color: #ffffff; 110 | } 111 | 112 | #product big { 113 | font-size: 2em; 114 | } 115 | 116 | #product_logo 117 | { 118 | } 119 | 120 | #product_name 121 | { 122 | } 123 | 124 | #product_description 125 | { 126 | } 127 | 128 | #main 129 | { 130 | background-color: #f0f0f0; 131 | border-left: 2px solid #cccccc; 132 | } 133 | 134 | #navigation 135 | { 136 | float: left; 137 | width: 18em; 138 | margin: 0; 139 | vertical-align: top; 140 | background-color: #f0f0f0; 141 | overflow:visible; 142 | } 143 | 144 | #navigation h1 { 145 | background-color:#e7e7e7; 146 | font-size:1.1em; 147 | color:#000000; 148 | text-align:left; 149 | margin:0px; 150 | padding:0.2em; 151 | border-top:1px solid #dddddd; 152 | border-bottom:1px solid #dddddd; 153 | } 154 | 155 | #navigation ul 156 | { 157 | font-size:1em; 158 | list-style-type: none; 159 | padding: 0; 160 | margin: 1px; 161 | } 162 | 163 | #navigation li 164 | { 165 | text-indent: -1em; 166 | margin: 0em 0em 0em 0.5em; 167 | display: block; 168 | padding: 3px 0px 0px 12px; 169 | } 170 | 171 | #navigation li li a 172 | { 173 | padding: 0px 3px 0px -1em; 174 | } 175 | 176 | #content 177 | { 178 | margin-left: 18em; 179 | padding: 1em; 180 | border-left: 2px solid #cccccc; 181 | border-right: 2px solid #cccccc; 182 | background-color: #ffffff; 183 | } 184 | 185 | #about 186 | { 187 | clear: both; 188 | margin: 0; 189 | padding: 5px; 190 | border-top: 2px solid #cccccc; 191 | background-color: #ffffff; 192 | } 193 | 194 | @media print { 195 | body { 196 | font: 12pt "Times New Roman", "TimeNR", Times, serif; 197 | } 198 | a { font-weight:bold; color: #004080; text-decoration: underline; } 199 | 200 | #main { background-color: #ffffff; border-left: 0px; } 201 | #container { margin-left: 2%; margin-right: 2%; background-color: #ffffff; } 202 | 203 | #content { margin-left: 0px; padding: 1em; border-left: 0px; border-right: 0px; background-color: #ffffff; } 204 | 205 | #navigation { display: none; 206 | } 207 | pre.example { 208 | font-family: "Andale Mono", monospace; 209 | font-size: 10pt; 210 | page-break-inside: avoid; 211 | } 212 | } 213 | 214 | table.module_list td 215 | { 216 | border-width: 1px; 217 | padding: 3px; 218 | border-style: solid; 219 | border-color: #cccccc; 220 | } 221 | table.module_list td.name { background-color: #f0f0f0; } 222 | table.module_list td.summary { width: 100%; } 223 | 224 | table.file_list 225 | { 226 | border-width: 1px; 227 | border-style: solid; 228 | border-color: #cccccc; 229 | border-collapse: collapse; 230 | } 231 | table.file_list td 232 | { 233 | border-width: 1px; 234 | padding: 3px; 235 | border-style: solid; 236 | border-color: #cccccc; 237 | } 238 | table.file_list td.name { background-color: #f0f0f0; } 239 | table.file_list td.summary { width: 100%; } 240 | 241 | 242 | table.function_list 243 | { 244 | border-width: 1px; 245 | border-style: solid; 246 | border-color: #cccccc; 247 | border-collapse: collapse; 248 | } 249 | table.function_list td 250 | { 251 | border-width: 1px; 252 | padding: 3px; 253 | border-style: solid; 254 | border-color: #cccccc; 255 | } 256 | table.function_list td.name { background-color: #f0f0f0; } 257 | table.function_list td.summary { width: 100%; } 258 | 259 | 260 | table.table_list 261 | { 262 | border-width: 1px; 263 | border-style: solid; 264 | border-color: #cccccc; 265 | border-collapse: collapse; 266 | } 267 | table.table_list td 268 | { 269 | border-width: 1px; 270 | padding: 3px; 271 | border-style: solid; 272 | border-color: #cccccc; 273 | } 274 | table.table_list td.name { background-color: #f0f0f0; } 275 | table.table_list td.summary { width: 100%; } 276 | 277 | dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;} 278 | dl.function dd {padding-bottom: 1em;} 279 | dl.function h3 {padding: 0; margin: 0; font-size: medium;} 280 | 281 | dl.table dt {border-top: 1px solid #ccc; padding-top: 1em;} 282 | dl.table dd {padding-bottom: 1em;} 283 | dl.table h3 {padding: 0; margin: 0; font-size: medium;} 284 | 285 | #TODO: make module_list, file_list, function_list, table_list inherit from a list 286 | 287 | -------------------------------------------------------------------------------- /doc/modules/dist.dep.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | Reference 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 |
14 | 15 |
16 |
17 |
18 | 19 |
20 | 21 | 79 | 80 |
81 | 82 |

Module dist.dep

83 | 84 |

Dependency handling functions. Dependencies are represented in LuaDist through strings with a dist name followed by a comma-separated list of constraints. Each constraint consists of an operator and a version number. In this string format, version numbers are represented as naturally as possible, like they are used by upstream projects (e.g. "2.0beta3"). Internally, LuaDist converts them to a purely numeric representation, allowing comparison following some "common sense" heuristics. The precise specification of the comparison criteria is the source code of this module, but the test/test_deps.lua file included with LuaDist provides some insights on what these criteria are.

85 | 86 | 87 | 88 | 89 | 90 |

Functions

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 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 |
__eq (v1, v2)Equality comparison for versions.
__lt (v1, v2)Size comparison for versions.
compareVersions (a, b)Utility function to compare version numbers given as strings.
constrain (version, constraints)Check if a version string is satisfied by a constraint string.
matchConstraints (version, constraints)Check if a version satisfies a set of constraints.
parseConstraint (input)Consumes a constraint from a string, converting it to table format.
parseConstraints (input)Convert a list of constraints from string to table format.
parseVersion (vstring)Parse a version string, converting to table format.
partialMatch (version, requested)A more lenient check for equivalence between versions.
split (name)Split dist name into name and constraints.
144 | 145 | 146 | 147 | 148 | 149 | 150 |
151 |
152 | 153 | 154 | 155 |

Functions

156 |
157 | 158 | 159 | 160 |
__eq (v1, v2)
161 |
162 | Equality comparison for versions. All version numbers must be equal. If both versions have revision numbers, they must be equal; otherwise the revision number is ignored. 163 | 164 | 165 |

Parameters

166 |
    167 | 168 |
  • 169 | v1: table: version table to compare. 170 |
  • 171 | 172 |
  • 173 | v2: table: version table to compare. 174 |
  • 175 | 176 |
177 | 178 | 179 | 180 | 181 | 182 | 183 |

Return value:

184 | boolean: true if they are considered equivalent. 185 | 186 | 187 | 188 |
189 | 190 | 191 | 192 | 193 |
__lt (v1, v2)
194 |
195 | Size comparison for versions. All version numbers are compared. If both versions have revision numbers, they are compared; otherwise the revision number is ignored. 196 | 197 | 198 |

Parameters

199 |
    200 | 201 |
  • 202 | v1: table: version table to compare. 203 |
  • 204 | 205 |
  • 206 | v2: table: version table to compare. 207 |
  • 208 | 209 |
210 | 211 | 212 | 213 | 214 | 215 | 216 |

Return value:

217 | boolean: true if v1 is considered lower than v2. 218 | 219 | 220 | 221 |
222 | 223 | 224 | 225 | 226 |
compareVersions (a, b)
227 |
228 | Utility function to compare version numbers given as strings. 229 | 230 | 231 |

Parameters

232 |
    233 | 234 |
  • 235 | a: string: one version. 236 |
  • 237 | 238 |
  • 239 | b: string: another version. 240 |
  • 241 | 242 |
243 | 244 | 245 | 246 | 247 | 248 | 249 |

Return value:

250 | boolean: True if a > b. 251 | 252 | 253 | 254 |
255 | 256 | 257 | 258 | 259 |
constrain (version, constraints)
260 |
261 | Check if a version string is satisfied by a constraint string. 262 | 263 | 264 |

Parameters

265 |
    266 | 267 |
  • 268 | version: string: A version in string format 269 |
  • 270 | 271 |
  • 272 | constraints: string: Constraints in string format. 273 |
  • 274 | 275 |
276 | 277 | 278 | 279 | 280 | 281 | 282 |

Return value:

283 | boolean: True if version satisfies all constraints, false otherwise. 284 | 285 | 286 | 287 |
288 | 289 | 290 | 291 | 292 |
matchConstraints (version, constraints)
293 |
294 | Check if a version satisfies a set of constraints. 295 | 296 | 297 |

Parameters

298 |
    299 | 300 |
  • 301 | version: table: A version in table format 302 |
  • 303 | 304 |
  • 305 | constraints: table: An array of constraints in table format. 306 |
  • 307 | 308 |
309 | 310 | 311 | 312 | 313 | 314 | 315 |

Return value:

316 | boolean: True if version satisfies all constraints, false otherwise. 317 | 318 | 319 | 320 |
321 | 322 | 323 | 324 | 325 |
parseConstraint (input)
326 |
327 | Consumes a constraint from a string, converting it to table format. For example, a string ">= 1.0, > 2.0" is converted to a table in the format {op = ">=", version={1,0}} and the rest, "> 2.0", is returned back to the caller. 328 | 329 | 330 |

Parameters

331 |
    332 | 333 |
  • 334 | input: string: A list of constraints in string format. 335 |
  • 336 | 337 |
338 | 339 | 340 | 341 | 342 | 343 | 344 |

Return value:

345 | (table, string) or nil: A table representing the same constraints and the string with the unused input, or nil if the input string is invalid. 346 | 347 | 348 | 349 |
350 | 351 | 352 | 353 | 354 |
parseConstraints (input)
355 |
356 | Convert a list of constraints from string to table format. For example, a string ">= 1.0, < 2.0" is converted to a table in the format {{op = ">=", version={1,0}}, {op = "<", version={2,0}}}. Version tables use a metatable allowing later comparison through relational operators. 357 | 358 | 359 |

Parameters

360 |
    361 | 362 |
  • 363 | input: string: A list of constraints in string format. 364 |
  • 365 | 366 |
367 | 368 | 369 | 370 | 371 | 372 | 373 |

Return value:

374 | table or nil: A table representing the same constraints, or nil if the input string is invalid. 375 | 376 | 377 | 378 |
379 | 380 | 381 | 382 | 383 |
parseVersion (vstring)
384 |
385 | Parse a version string, converting to table format. A version table contains all components of the version string converted to numeric format, stored in the array part of the table. If the version contains a revision, it is stored numerically in the 'revision' field. The original string representation of the string is preserved in the 'string' field. Returned version tables use a metatable allowing later comparison through relational operators. 386 | 387 | 388 |

Parameters

389 |
    390 | 391 |
  • 392 | vstring: string: A version number in string format. 393 |
  • 394 | 395 |
396 | 397 | 398 | 399 | 400 | 401 | 402 |

Return value:

403 | table or nil: A version table or nil if the input string contains invalid characters. 404 | 405 | 406 | 407 |
408 | 409 | 410 | 411 | 412 |
partialMatch (version, requested)
413 |
414 | A more lenient check for equivalence between versions. This returns true if the requested components of a version match and ignore the ones that were not given. For example, when requesting "2", then "2", "2.1", "2.3.5-9"... all match. When requesting "2.1", then "2.1", "2.1.3" match, but "2.2" doesn't. 415 | 416 | 417 |

Parameters

418 |
    419 | 420 |
  • 421 | version: string or table: Version to be tested; may be in string format or already parsed into a table. 422 |
  • 423 | 424 |
  • 425 | requested: string or table: Version requested; may be in string format or already parsed into a table. 426 |
  • 427 | 428 |
429 | 430 | 431 | 432 | 433 | 434 | 435 |

Return value:

436 | boolean: True if the tested version matches the requested version, false otherwise. 437 | 438 | 439 | 440 |
441 | 442 | 443 | 444 | 445 |
split (name)
446 |
447 | Split dist name into name and constraints. 448 | 449 | 450 |

Parameters

451 |
    452 | 453 |
  • 454 | name: string: A string containing name and version constraints eg. "lua-5.1.4" or "luajit >= 1.0 < 2.0" 455 |
  • 456 | 457 |
458 | 459 | 460 | 461 | 462 | 463 | 464 |

Return value:

465 | string, string: Returns separated name and constraints 466 | 467 | 468 | 469 |
470 | 471 | 472 |
473 | 474 | 475 | 476 | 477 | 478 | 479 |
480 | 481 |
482 | 483 |
484 |

Valid XHTML 1.0!

485 |
486 | 487 |
488 | 489 | 490 | -------------------------------------------------------------------------------- /doc/modules/dist.fetch.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | Reference 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 |
14 | 15 |
16 |
17 |
18 | 19 |
20 | 21 | 79 | 80 |
81 | 82 |

Module dist.fetch

83 | 84 |

This module is responsible for downloading contents using URIs. It should handle at least HTTP and FILE URIs as well as system paths transparently. 2DO: support for more protocols if demanded. Two functions are provided. Notice that http requests are cached. download - To download dists. get - To directly obtain manifests.

85 | 86 | 87 | 88 | 89 | 90 |

Functions

91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 |
download (src, dest)Fetch file from URI into destination.
get (src)Directly get file contents from URI using luasocket.
104 | 105 | 106 | 107 | 108 | 109 | 110 |
111 |
112 | 113 | 114 | 115 |

Functions

116 |
117 | 118 | 119 | 120 |
download (src, dest)
121 |
122 | Fetch file from URI into destination. 123 | 124 | 125 |

Parameters

126 |
    127 | 128 |
  • 129 | src: string: URI to fetch file from. Accepts paths too. 130 |
  • 131 | 132 |
  • 133 | dest: string: Destination dir, if not provided temporary dir will be used. 134 |
  • 135 | 136 |
137 | 138 | 139 | 140 | 141 | 142 | 143 |

Return value:

144 | path, log: Path the file was downloaded and the resulting log message. 145 | 146 | 147 | 148 |
149 | 150 | 151 | 152 | 153 |
get (src)
154 |
155 | Directly get file contents from URI using luasocket. 156 | 157 | 158 |

Parameters

159 |
    160 | 161 |
  • 162 | src: string: URI to fetch file from. Accepts paths too. 163 |
  • 164 | 165 |
166 | 167 | 168 | 169 | 170 | 171 | 172 |

Return value:

173 | text, log: Contents of the URL file or nil and log message. 174 | 175 | 176 | 177 |
178 | 179 | 180 |
181 | 182 | 183 | 184 | 185 | 186 | 187 |
188 | 189 |
190 | 191 |
192 |

Valid XHTML 1.0!

193 |
194 | 195 |
196 | 197 | 198 | -------------------------------------------------------------------------------- /doc/modules/dist.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | Reference 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 |
14 | 15 |
16 |
17 |
18 | 19 |
20 | 21 | 79 | 80 |
81 | 82 |

Module dist

83 | 84 |

This file contains the basic functions of LuaDist. Feel free to use this exposed API in your projects if you need to deploy something automatically. Please note that everything may change in future releases. Terminology used: _dist_ - General reference to "package" in LuaDist, often synonymous with _info_. _info_ - Meta-data describing a _dist_. Collected from dist.info files inside dist archives. _manifest_ - A collection of sorted _info_ entries in a table. Sorted alphabetically by name and by version descending. _name_ - Refers to a string containing dist name and version constraints. Eg. "lua-5.1.4" or "luajit>=2" _deployment_ - A directory containing dists installed using LuaDist.

85 | 86 | 87 | 88 | 89 | 90 |

Functions

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 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 |
deploy (src, deployment, variables)Deploy a dist directly from source.
filterManifest (list, constraints)Filter dist manifests using constraint functions.
findDists (names, manifest, name)Find dists in manifest by name.
getDeployed (deployment)Get all deployed dists in the target dir, this will also list dists provided by other dists.
getDeployment ()Get deployment directory.
getDeps (names, manifest)Collect dependencies.
getInstalled (deployment)Get all installed dists from deployment directory.
getManifest (repositories)Get contents of repository or a list of repositories.
install (names, deployment, manifest, variables, name)Install dist by name.
pack (names, deployment, dest, dist)Pack a deployed dist.
remove (names, deployment, dist)Remove a deployed dist.
149 | 150 | 151 | 152 | 153 | 154 | 155 |
156 |
157 | 158 | 159 | 160 |

Functions

161 |
162 | 163 | 164 | 165 |
deploy (src, deployment, variables)
166 |
167 | Deploy a dist directly from source. _deploy_ will install; and in case of source dists, build a dist from source path. Deployment will automatically fetch from remote URLs and unpack dist or zip files into deploymemt. Variables can contain additional CMake variables to be used when building source dists. 168 | 169 | 170 |

Parameters

171 |
    172 | 173 |
  • 174 | src: string: Path to the dist directory to make/deploy or nil to use current directory. 175 |
  • 176 | 177 |
  • 178 | deployment: string: Deployment directory to install the dist into. If nil LuaDist directory is used. 179 |
  • 180 | 181 |
  • 182 | variables: table: Table of key value pairs that can be used to set additional CMake variables for source dists. 183 |
  • 184 | 185 |
186 | 187 | 188 | 189 | 190 | 191 | 192 |

Return value:

193 | ok, log: Returns true on success. nil on error and log message. 194 | 195 | 196 | 197 |
198 | 199 | 200 | 201 | 202 |
filterManifest (list, constraints)
203 |
204 | Filter dist manifests using constraint functions. _filterManifest_ is used to remove dists from dist manifests that don't satisfy conditions. Conditions are specified using a table of functions. Functions are named after the attribute they check and return true if an argument satisfies its condition. When constraint are not defined a default set of constraints is used. These constraints filter out dists not suitable for the architecture LuaDist is running on. More specifically, only dists of arch "Universal" or of arch equal to cfg.arch and of type "all" or type equal to cfg.type are preserved. Additionally when source dists are enabled in configuration this will include dists of type equal to "source". In case no manifest is specified _filterManifest_ will automatically collect dist manifests from default repositories using _getManifest_. 205 | 206 | 207 |

Parameters

208 |
    209 | 210 |
  • 211 | list: table: Dist list or manifest to filter. By default all dists collected from cfg.repo will be filtered. 212 |
  • 213 | 214 |
  • 215 | constraints: table: Table of constraint function. Key determines what dist attribute is checked while the value is the actual constraint test written as a function. By default dists are filtered for correct arch-type. 216 |
  • 217 | 218 |
219 | 220 | 221 | 222 | 223 | 224 | 225 |

Return value:

226 | manifest: Table containing collections of filtered dists. 227 | 228 | 229 | 230 |
231 | 232 | 233 | 234 | 235 |
findDists (names, manifest, name)
236 |
237 | Find dists in manifest by name. _findDists_ will find all dists in manifest that satisfy conditions in the name string. Name contains dist name to search for and a set of optional version constraints. For example searching for "lua-5.1.4" will find all dists of name "lua" and version "5.1.4". Searching for version ranges is done using sets of constraints eg. "luajit >= 2.0 < 3.0". For more information, limitations and use of the constraint system please see LuaDist documentation. 238 | 239 | 240 |

Parameters

241 |
    242 | 243 |
  • 244 | names: 245 |
  • 246 | 247 |
  • 248 | manifest: string: Dist manifest to search through. 249 |
  • 250 | 251 |
  • 252 | name: string: String specifying the dist to find, version constraints can be used. Case sensitive. 253 |
  • 254 | 255 |
256 | 257 | 258 | 259 | 260 | 261 | 262 |

Return value:

263 | dist, log: List of matching dists. Returns nil on error and log message. 264 | 265 | 266 | 267 |
268 | 269 | 270 | 271 | 272 |
getDeployed (deployment)
273 |
274 | Get all deployed dists in the target dir, this will also list dists provided by other dists. _getDeployed_ will collect all deployed dists inside a deployment directory. This inludes entries that simulate provided dists which act as dependency satisfaction for dists during installation. Integration with host package managers can be achieved by providing a list of modules already installed directly to the host system. The list can be edited directly by the user in configuration. 275 | 276 | 277 |

Parameters

278 |
    279 | 280 |
  • 281 | deployment: string: Path to deployment directory. If not specified the deployment LuaDist is running in will be used. 282 |
  • 283 | 284 |
285 | 286 | 287 | 288 | 289 | 290 | 291 |

Return value:

292 | manifest: Table containing collections of deployed dists. 293 | 294 | 295 | 296 |
297 | 298 | 299 | 300 | 301 |
getDeployment ()
302 |
303 | Get deployment directory. 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 |

Return value:

312 | path: Full path to the LuaDist install directory 313 | 314 | 315 | 316 |
317 | 318 | 319 | 320 | 321 |
getDeps (names, manifest)
322 |
323 | Collect dependencies. _getDeps_ is the magic function where dependency resolving happens. This function handles multiple names for which it computes the best possible set of dists that satisfy all the names. It consideres provided dists, conflicts and dependencies of each candidate dist and avoids dependency loops. It may not be very elegant or efficient, contributions welcome. The algorithm relies on sequential satisfaction of names. For each name it tries to determine best possible candidate and tries to install its dependencies and rest of the names list. If dependencies fail another candidate is checked untill all names check out or candidates run out. Provides are faked by injecting dists into manifest and replaced before return. 324 | 325 | 326 |

Parameters

327 |
    328 | 329 |
  • 330 | names: string or table: Names to compute dependencies for. 331 |
  • 332 | 333 |
  • 334 | manifest: table: Manifest of dists to select dependencies from, needs to be sorted. 335 |
  • 336 | 337 |
338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 |
347 | 348 | 349 | 350 | 351 |
getInstalled (deployment)
352 |
353 | Get all installed dists from deployment directory. _getInstalled_ will collect all installed dists inside a deployment directory. These represent installed dists; provided dists are not included, see _getDeployed_ if you need a provided dists too. 354 | 355 | 356 |

Parameters

357 |
    358 | 359 |
  • 360 | deployment: string: Path to deployment directory. If not specified the deployment LuaDist is running in will be used. 361 |
  • 362 | 363 |
364 | 365 | 366 | 367 | 368 | 369 | 370 |

Return value:

371 | manifest: Table containing collections of installed dists. 372 | 373 | 374 | 375 |
376 | 377 | 378 | 379 | 380 |
getManifest (repositories)
381 |
382 | Get contents of repository or a list of repositories. _getManifest_ is used to fetch or generate collections of dist.info entries from URIs, system paths and on-line repositories. Returned dist manifests are not filtered and may not be appropriate for installation, see _filterManifest_ for this purpose. Dist information is gathered by collecting dist.info entries from dist.manifest file in case an URL to on-line repository is given. System paths are searched for dist.info files on demand and do extracted dists can be used for local repositories, this is handy for bootstrap and development of multiple interconnected dists. Zip archives and dists are peeked into on demand and in case it contains dist.info entry its added to the manifest. In case of multiple repositories, first repository always has priority. Dists are ordered by repository, name and version. Every item is checked, malformed entries are removed. 383 | 384 | 385 |

Parameters

386 |
    387 | 388 |
  • 389 | repositories: string or table: Path or URL of a repository or repositories. By default cfg.repo is used if argument is not defined. 390 |
  • 391 | 392 |
393 | 394 | 395 | 396 | 397 | 398 | 399 |

Return value:

400 | manifest: Table containing collections of available dists. 401 | 402 | 403 | 404 |
405 | 406 | 407 | 408 | 409 |
install (names, deployment, manifest, variables, name)
410 |
411 | Install dist by name. _install_ is capable to install dists from various sources and of both source and binary type. Sources can be accumulated into install lists in which case LuaDist will install the sources in sequence. Sources supported by the command currently include: name, path and URL to .dist and .zip, path to unpacked dist and dist.info table. 412 | 413 | 414 |

Parameters

415 |
    416 | 417 |
  • 418 | names: 419 |
  • 420 | 421 |
  • 422 | deployment: string: Deployment directory to install into. Leave undefined for current deployment directory. 423 |
  • 424 | 425 |
  • 426 | manifest: table: Manifest of dists used to search for sources and resolve dependencies. Leave undefined for default repositories. 427 |
  • 428 | 429 |
  • 430 | variables: table: Table of key value pairs that can be used to set additional CMake variables for source dists. 431 |
  • 432 | 433 |
  • 434 | name: string: Package to install identified by name which can include version constraints. Case sensitive. 435 |
  • 436 | 437 |
438 | 439 | 440 | 441 | 442 | 443 | 444 |

Return value:

445 | ok, log: Returns true on success. nil on error and log message. 446 | 447 | 448 | 449 |
450 | 451 | 452 | 453 | 454 |
pack (names, deployment, dest, dist)
455 |
456 | Pack a deployed dist. _pack_ will pack specified dist from deployment deployment and generate .dist archives in dest. When no name is specified all dists will be packed. 457 | 458 | 459 |

Parameters

460 |
    461 | 462 |
  • 463 | names: 464 |
  • 465 | 466 |
  • 467 | deployment: string: Deployment directory to uninstall from, nil for default LuaDist directory. 468 |
  • 469 | 470 |
  • 471 | dest: string: Optional destination for the result 472 |
  • 473 | 474 |
  • 475 | dist: string or table: Dist name or info to uninstall. 476 |
  • 477 | 478 |
479 | 480 | 481 | 482 | 483 | 484 | 485 |

Return value:

486 | ok, log: Returns true on success. nil on error and log message. 487 | 488 | 489 | 490 |
491 | 492 | 493 | 494 | 495 |
remove (names, deployment, dist)
496 |
497 | Remove a deployed dist. _remove_ will delete specified dist from deployment. When no name is specified, the whole deployment directory will be removed. WARNING: Calling "luadist remove" will instruct LuaDist to commit suicide. 498 | 499 | 500 |

Parameters

501 |
    502 | 503 |
  • 504 | names: 505 |
  • 506 | 507 |
  • 508 | deployment: string: Deployment directory to uninstall from, nil for default LuaDist directory. 509 |
  • 510 | 511 |
  • 512 | dist: string or table: Dist name or info to uninstall. 513 |
  • 514 | 515 |
516 | 517 | 518 | 519 | 520 | 521 | 522 |

Return value:

523 | ok, log: Returns true on success. nil on error and log message. 524 | 525 | 526 | 527 |
528 | 529 | 530 |
531 | 532 | 533 | 534 | 535 | 536 | 537 |
538 | 539 |
540 | 541 |
542 |

Valid XHTML 1.0!

543 |
544 | 545 |
546 | 547 | 548 | -------------------------------------------------------------------------------- /doc/modules/dist.log.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | Reference 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 |
14 | 15 |
16 |
17 |
18 | 19 |
20 | 21 | 79 | 80 |
81 | 82 |

Module dist.log

83 | 84 |

Very simple log system. 2DO: change to LuaLogging on next version. write - write a log line message - write and optionally display a message

85 | 86 | 87 | 88 | 89 | 90 |

Functions

91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 |
message (...)Display and log a message
write (...)Write a line to log
104 | 105 | 106 | 107 | 108 | 109 | 110 |
111 |
112 | 113 | 114 | 115 |

Functions

116 |
117 | 118 | 119 | 120 |
message (...)
121 |
122 | Display and log a message 123 | 124 | 125 |

Parameters

126 |
    127 | 128 |
  • 129 | ...: 130 |
  • 131 | 132 |
133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 |
142 | 143 | 144 | 145 | 146 |
write (...)
147 |
148 | Write a line to log 149 | 150 | 151 |

Parameters

152 |
    153 | 154 |
  • 155 | ...: 156 |
  • 157 | 158 |
159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 |
168 | 169 | 170 |
171 | 172 | 173 | 174 | 175 | 176 | 177 |
178 | 179 |
180 | 181 |
182 |

Valid XHTML 1.0!

183 |
184 | 185 |
186 | 187 | 188 | -------------------------------------------------------------------------------- /doc/modules/dist.manifest.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | Reference 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 |
14 | 15 |
16 |
17 |
18 | 19 |
20 | 21 | 79 | 80 |
81 | 82 |

Module dist.manifest

83 | 84 |

The purpose of this module is to check and collect dist manifests. There are three functions provided: make - Generates manifest for local directory get - Gets sorted manifest from URI, this uses make for local paths. For remote directories it requires dist.manifest file to be present. info - Loads and/or corrects and checks dist.info contents Dists and manifests are simply arrays of collected dist.info files.

85 | 86 | 87 | 88 | 89 | 90 |

Functions

91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 |
get (src, variables, url)Get or generate repository contents from URI.
info (dist)Load and check info from file or check info table
make (dir)Collect and sort dists in a directory.
109 | 110 | 111 | 112 | 113 | 114 | 115 |
116 |
117 | 118 | 119 | 120 |

Functions

121 |
122 | 123 | 124 | 125 |
get (src, variables, url)
126 |
127 | Get or generate repository contents from URI. 128 | 129 | 130 |

Parameters

131 |
    132 | 133 |
  • 134 | src: 135 |
  • 136 | 137 |
  • 138 | variables: 139 |
  • 140 | 141 |
  • 142 | url: string: URL to load the dist.manifest from. In case file:// is used generate the manifest. 143 |
  • 144 | 145 |
146 | 147 | 148 | 149 | 150 | 151 | 152 |

Return value:

153 | dists, log: Returns true on success and nil and error message on failure. 154 | 155 | 156 | 157 |
158 | 159 | 160 | 161 | 162 |
info (dist)
163 |
164 | Load and check info from file or check info table 165 | 166 | 167 |

Parameters

168 |
    169 | 170 |
  • 171 | dist: string or table: Path to dist.info or info table to check. 172 |
  • 173 | 174 |
175 | 176 | 177 | 178 | 179 | 180 | 181 |

Return value:

182 | info, log: Table containing loaded and checked info or nil and log message. 183 | 184 | 185 | 186 |
187 | 188 | 189 | 190 | 191 |
make (dir)
192 |
193 | Collect and sort dists in a directory. 194 | 195 | 196 |

Parameters

197 |
    198 | 199 |
  • 200 | dir: string: Directory to get manifest from. 201 |
  • 202 | 203 |
204 | 205 | 206 | 207 | 208 | 209 | 210 |

Return value:

211 | dists, log: Dists in the directory and log message. 212 | 213 | 214 | 215 |
216 | 217 | 218 |
219 | 220 | 221 | 222 | 223 | 224 | 225 |
226 | 227 |
228 | 229 |
230 |

Valid XHTML 1.0!

231 |
232 | 233 |
234 | 235 | 236 | -------------------------------------------------------------------------------- /doc/modules/dist.package.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | Reference 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 |
14 | 15 |
16 |
17 |
18 | 19 |
20 | 21 | 79 | 80 |
81 | 82 |

Module dist.package

83 | 84 |

Package handling functions. This module deals with packages, these are unpacked dists in LuaDist terminology The following functions are provided: unpack - fetch and unpack a dist build - compile a source dist deploy - install a dist into deployment dir and/or fix links. pack - create dist from package delete - delete package

85 | 86 | 87 | 88 | 89 | 90 |

Functions

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 |
build (dist, depl, variables)Build, deploy and test a source dist using CMake.
delete (dist, depl)Delete a deployed dist.
deploy (dist, depl)Deploy dist into deployment directory.
pack (dist, depl, dir)Pack a package to create a dist.
unpack (url, dest)Fetch and unpack zip/dist from URL into dest directory.
119 | 120 | 121 | 122 | 123 | 124 | 125 |
126 |
127 | 128 | 129 | 130 |

Functions

131 |
132 | 133 | 134 | 135 |
build (dist, depl, variables)
136 |
137 | Build, deploy and test a source dist using CMake. 138 | 139 | 140 |

Parameters

141 |
    142 | 143 |
  • 144 | dist: string: Directory of the source dist to build. 145 |
  • 146 | 147 |
  • 148 | depl: 149 |
  • 150 | 151 |
  • 152 | variables: 153 |
  • 154 | 155 |
156 | 157 | 158 | 159 | 160 | 161 | 162 |

Return value:

163 | path, log: Returns temporary directory the dist was build into and log message. 164 | 165 | 166 | 167 |
168 | 169 | 170 | 171 | 172 |
delete (dist, depl)
173 |
174 | Delete a deployed dist. 175 | 176 | 177 |

Parameters

178 |
    179 | 180 |
  • 181 | dist: string: dist to delete. 182 |
  • 183 | 184 |
  • 185 | depl: string: deployment dir to delete from. 186 |
  • 187 | 188 |
189 | 190 | 191 | 192 | 193 | 194 | 195 |

Return value:

196 | ok, log: Returns success and nlog message. 197 | 198 | 199 | 200 |
201 | 202 | 203 | 204 | 205 |
deploy (dist, depl)
206 |
207 | Deploy dist into deployment directory. 208 | 209 | 210 |

Parameters

211 |
    212 | 213 |
  • 214 | dist: string: Directory of the dist to deploy. 215 |
  • 216 | 217 |
  • 218 | depl: string: Deployment directory nil for default. 219 |
  • 220 | 221 |
222 | 223 | 224 | 225 | 226 | 227 | 228 |

Return value:

229 | ok, log: Returns true on success and log message. 230 | 231 | 232 | 233 |
234 | 235 | 236 | 237 | 238 |
pack (dist, depl, dir)
239 |
240 | Pack a package to create a dist. 241 | 242 | 243 |

Parameters

244 |
    245 | 246 |
  • 247 | dist: string: deployed dist to pack. 248 |
  • 249 | 250 |
  • 251 | depl: string: deployment dir to pack from. 252 |
  • 253 | 254 |
  • 255 | dir: string: Optional destination for the dist, current directory will be used by default. 256 |
  • 257 | 258 |
259 | 260 | 261 | 262 | 263 | 264 | 265 |

Return value:

266 | ok, log: Returns success and log message. 267 | 268 | 269 | 270 |
271 | 272 | 273 | 274 | 275 |
unpack (url, dest)
276 |
277 | Fetch and unpack zip/dist from URL into dest directory. 278 | 279 | 280 |

Parameters

281 |
    282 | 283 |
  • 284 | url: string: Local packed dist or URL to fetch dist from. 285 |
  • 286 | 287 |
  • 288 | dest: string: Destination to unpack contents into, nil for temp directory. 289 |
  • 290 | 291 |
292 | 293 | 294 | 295 | 296 | 297 | 298 |

Return value:

299 | path, log: Unpacked dist path or nil and log. 300 | 301 | 302 | 303 |
304 | 305 | 306 |
307 | 308 | 309 | 310 | 311 | 312 | 313 |
314 | 315 |
316 | 317 |
318 |

Valid XHTML 1.0!

319 |
320 | 321 |
322 | 323 | 324 | -------------------------------------------------------------------------------- /doc/modules/dist.persist.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | Reference 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 |
14 | 15 |
16 |
17 |
18 | 19 |
20 | 21 | 79 | 80 |
81 | 82 |

Module dist.persist

83 | 84 |

Persistency table serializarion. 2DO: If a better persistency dist with good readability becomes available change this code This module contains functions that deal with serialization and loading of tables. loadText - text 2 table load - file 2 table saveText - table 2 text save - table 2 file saveManifest - variant of save for manifests

85 | 86 | 87 | 88 | 89 | 90 |

Functions

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 |
load (filename)Load table from file.
loadText (text)Load table from text.
save (filename, tbl)Save table to file.
saveManifest (filename, dists)Special serialization formating for manifests.
saveText (tbl)Save table to string.
serialize (o, d, tbl)Serialize a table into text.
124 | 125 | 126 | 127 | 128 | 129 | 130 |
131 |
132 | 133 | 134 | 135 |

Functions

136 |
137 | 138 | 139 | 140 |
load (filename)
141 |
142 | Load table from file. 143 | 144 | 145 |

Parameters

146 |
    147 | 148 |
  • 149 | filename: string: File to load table from 150 |
  • 151 | 152 |
153 | 154 | 155 | 156 | 157 | 158 | 159 |

Return value:

160 | table, log: Returns table on success, nil on failure and log message. 161 | 162 | 163 | 164 |
165 | 166 | 167 | 168 | 169 |
loadText (text)
170 |
171 | Load table from text. 172 | 173 | 174 |

Parameters

175 |
    176 | 177 |
  • 178 | text: string: Text to load table from. 179 |
  • 180 | 181 |
182 | 183 | 184 | 185 | 186 | 187 | 188 |

Return value:

189 | table, log: Returns table on success, nil on failure and log message. 190 | 191 | 192 | 193 |
194 | 195 | 196 | 197 | 198 |
save (filename, tbl)
199 |
200 | Save table to file. 201 | 202 | 203 |

Parameters

204 |
    205 | 206 |
  • 207 | filename: string: File to save table to. 208 |
  • 209 | 210 |
  • 211 | tbl: table: Table to save. 212 |
  • 213 | 214 |
215 | 216 | 217 | 218 | 219 | 220 | 221 |

Return value:

222 | ok, log: Returns true on success, nil on failure and log message. 223 | 224 | 225 | 226 |
227 | 228 | 229 | 230 | 231 |
saveManifest (filename, dists)
232 |
233 | Special serialization formating for manifests. 234 | 235 | 236 |

Parameters

237 |
    238 | 239 |
  • 240 | filename: string: Path to save manifest to 241 |
  • 242 | 243 |
  • 244 | dists: 245 |
  • 246 | 247 |
248 | 249 | 250 | 251 | 252 | 253 | 254 |

Return value:

255 | ok, log: Returns true on success, nil on failure and log message. 256 | 257 | 258 | 259 |
260 | 261 | 262 | 263 | 264 |
saveText (tbl)
265 |
266 | Save table to string. Used for dist.info. 267 | 268 | 269 |

Parameters

270 |
    271 | 272 |
  • 273 | tbl: table: Table to save. 274 |
  • 275 | 276 |
277 | 278 | 279 | 280 | 281 | 282 | 283 |

Return value:

284 | out string: Serialized text. 285 | 286 | 287 | 288 |
289 | 290 | 291 | 292 | 293 |
serialize (o, d, tbl)
294 |
295 | Serialize a table into text. 296 | 297 | 298 |

Parameters

299 |
    300 | 301 |
  • 302 | o: 303 |
  • 304 | 305 |
  • 306 | d: number: Intendation lenght. 307 |
  • 308 | 309 |
  • 310 | tbl: table: Table to serialize. 311 |
  • 312 | 313 |
314 | 315 | 316 | 317 | 318 | 319 | 320 |

Return value:

321 | out string: Serialized text. 322 | 323 | 324 | 325 |
326 | 327 | 328 |
329 | 330 | 331 | 332 | 333 | 334 | 335 |
336 | 337 |
338 | 339 |
340 |

Valid XHTML 1.0!

341 |
342 | 343 |
344 | 345 | 346 | -------------------------------------------------------------------------------- /doc/modules/dist.sys.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | Reference 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 |
14 | 15 |
16 |
17 |
18 | 19 |
20 | 21 | 79 | 80 |
81 | 82 |

Module dist.sys

83 | 84 |

Host system dependent commands. Override the default UNIX commands if needed for your platform. Commands currently depend on popen and unzip being available. For future releases we would like to use lua packages handling the compression issues. Additionally some filesystem functionality not available in luafilesystem is emulated here.

85 | 86 | 87 | 88 | 89 | 90 |

Functions

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 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 |
Q (arg)Quote argument for shell processing (Windows).
Q (arg)Quote argument for shell processing (Windows).
copy (src, dest)Recursive copy a file or directory (Windows).
copy (src, dest)Recursive copy a file or directory (Windows).
curDir ()Get current directory.
delete (dir)Delete a file or a directory and all its contents (Windows).
delete (dir)Delete a file or a directory and all its contents (Windows).
dir (dir, path)List the contents of a directory.
execute (command, ...)Run the given system command, quoting its arguments.
executeString (cmd)Run the given system command.
exists (dir, path)Test for existance of a file.
forceDelete (src)Force delete a file, even if it is open.
getZipFile (zipfile, file)Extract file contents of a file from archive
isDir (dir, path)Test is pathname is a directory.
isFile (dir, path)Test is pathname is a file.
list (dir, path)Recursively list the contents of a directory.
makeDir (dir)Create a directory.
makeStart (dest)Create environment startup script (Windows).
makeStart (dest)Create environment startup script (Windows).
move (src, dest)Move a file from one location to another (Windows).
move (src, dest)Move a file from one location to another (Windows).
path (...)Compose full system path or part of url
pathLen (dir)little helper function to get file depth (for directories its +1)
relLink (src, dest, from)Relatively Link file or directory contents to destination.
unzip (archive, dest)Unpack an archive.
zip (workdir, zipfile, ...)Compress files in a .zip archive.
224 | 225 | 226 | 227 | 228 | 229 | 230 |
231 |
232 | 233 | 234 | 235 |

Functions

236 |
237 | 238 | 239 | 240 |
Q (arg)
241 |
242 | Quote argument for shell processing (Windows). Adds single quotes and escapes. 243 | 244 | 245 |

Parameters

246 |
    247 | 248 |
  • 249 | arg: string: Unquoted argument. 250 |
  • 251 | 252 |
253 | 254 | 255 | 256 | 257 | 258 | 259 |

Return value:

260 | string: Quoted argument. 261 | 262 | 263 | 264 |
265 | 266 | 267 | 268 | 269 |
Q (arg)
270 |
271 | Quote argument for shell processing (Windows). Adds single quotes and escapes. 272 | 273 | 274 |

Parameters

275 |
    276 | 277 |
  • 278 | arg: string: Unquoted argument. 279 |
  • 280 | 281 |
282 | 283 | 284 | 285 | 286 | 287 | 288 |

Return value:

289 | string: Quoted argument. 290 | 291 | 292 | 293 |
294 | 295 | 296 | 297 | 298 |
copy (src, dest)
299 |
300 | Recursive copy a file or directory (Windows). 301 | 302 | 303 |

Parameters

304 |
    305 | 306 |
  • 307 | src: string: Pathname of source 308 |
  • 309 | 310 |
  • 311 | dest: string: Pathname of destination. If `src` is a directory, copies contents of `src` into contents of directory `dest`. Otherwise, both must represent files. 312 |
  • 313 | 314 |
315 | 316 | 317 | 318 | 319 | 320 | 321 |

Return value:

322 | ok, log: true on success, false on failure and log message. 323 | 324 | 325 | 326 |
327 | 328 | 329 | 330 | 331 |
copy (src, dest)
332 |
333 | Recursive copy a file or directory (Windows). 334 | 335 | 336 |

Parameters

337 |
    338 | 339 |
  • 340 | src: string: Pathname of source 341 |
  • 342 | 343 |
  • 344 | dest: string: Pathname of destination. If `src` is a directory, copies contents of `src` into contents of directory `dest`. Otherwise, both must represent files. 345 |
  • 346 | 347 |
348 | 349 | 350 | 351 | 352 | 353 | 354 |

Return value:

355 | ok, log: true on success, false on failure and log message. 356 | 357 | 358 | 359 |
360 | 361 | 362 | 363 | 364 |
curDir ()
365 |
366 | Get current directory. 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 |

Return value:

375 | string: current direcotry. 376 | 377 | 378 | 379 |
380 | 381 | 382 | 383 | 384 |
delete (dir)
385 |
386 | Delete a file or a directory and all its contents (Windows). For safety, this only accepts absolute paths. 387 | 388 | 389 |

Parameters

390 |
    391 | 392 |
  • 393 | dir: string: Pathname of the file or directory to delete 394 |
  • 395 | 396 |
397 | 398 | 399 | 400 | 401 | 402 | 403 |

Return value:

404 | ok, log: true on success, false on failure and log message. Returns success if already deleted. 405 | 406 | 407 | 408 |
409 | 410 | 411 | 412 | 413 |
delete (dir)
414 |
415 | Delete a file or a directory and all its contents (Windows). For safety, this only accepts absolute paths. 416 | 417 | 418 |

Parameters

419 |
    420 | 421 |
  • 422 | dir: string: Pathname of the file or directory to delete 423 |
  • 424 | 425 |
426 | 427 | 428 | 429 | 430 | 431 | 432 |

Return value:

433 | ok, log: true on success, false on failure and log message. Returns success if already deleted. 434 | 435 | 436 | 437 |
438 | 439 | 440 | 441 | 442 |
dir (dir, path)
443 |
444 | List the contents of a directory. 445 | 446 | 447 |

Parameters

448 |
    449 | 450 |
  • 451 | dir: 452 |
  • 453 | 454 |
  • 455 | path: string: directory to list if not specified the current directory will be used. 456 |
  • 457 | 458 |
459 | 460 | 461 | 462 | 463 | 464 | 465 |

Return value:

466 | table: an array of strings with the filenames representing the contents of a directory. 467 | 468 | 469 | 470 |
471 | 472 | 473 | 474 | 475 |
execute (command, ...)
476 |
477 | Run the given system command, quoting its arguments. The command is executed in the current directory in the dir stack. 478 | 479 | 480 |

Parameters

481 |
    482 | 483 |
  • 484 | command: string: The command to be executed. No quoting/escaping need to be applied. 485 |
  • 486 | 487 |
  • 488 | ...: strings: containing additional arguments, which are quoted. 489 |
  • 490 | 491 |
492 | 493 | 494 | 495 | 496 | 497 | 498 |

Return value:

499 | ok, log: true on success, false on failure and log message. 500 | 501 | 502 | 503 |
504 | 505 | 506 | 507 | 508 |
executeString (cmd)
509 |
510 | Run the given system command. The command is executed in the current directory in the dir stack. 511 | 512 | 513 |

Parameters

514 |
    515 | 516 |
  • 517 | cmd: string: No quoting/escaping is applied to the command. 518 |
  • 519 | 520 |
521 | 522 | 523 | 524 | 525 | 526 | 527 |

Return value:

528 | boolean: True if command succeeds, false otherwise. 529 | 530 | 531 | 532 |
533 | 534 | 535 | 536 | 537 |
exists (dir, path)
538 |
539 | Test for existance of a file. 540 | 541 | 542 |

Parameters

543 |
    544 | 545 |
  • 546 | dir: 547 |
  • 548 | 549 |
  • 550 | path: string: filename to test 551 |
  • 552 | 553 |
554 | 555 | 556 | 557 | 558 | 559 | 560 |

Return value:

561 | ok, log: true on success, false on failure and log message. 562 | 563 | 564 | 565 |
566 | 567 | 568 | 569 | 570 |
forceDelete (src)
571 |
572 | Force delete a file, even if it is open. If the file can't be deleted because it is currently open, this function will try to rename the file to a temporary file in the same directory. Windows in particular doesn't allow running executables to be deleted, but it does allow them to be renamed. Cygwin 1.7 (unlike 1.5) does allow such deletion but internally implements it via a mechanism like this. For futher details, see http://sourceforge.net/mailarchive/message.php?msg_name=bc4ed2190909261323i7c6280bfp6e7be6f70c713b0c%40mail.gmail.com 573 | 574 | 575 |

Parameters

576 |
    577 | 578 |
  • 579 | src: - file name 580 |
  • 581 | 582 |
583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 |
592 | 593 | 594 | 595 | 596 |
getZipFile (zipfile, file)
597 |
598 | Extract file contents of a file from archive 599 | 600 | 601 |

Parameters

602 |
    603 | 604 |
  • 605 | zipfile: string: pathname of .zip/.dist archive to read from. 606 |
  • 607 | 608 |
  • 609 | file: string: file to get contents of. 610 |
  • 611 | 612 |
613 | 614 | 615 | 616 | 617 | 618 | 619 |

Return value:

620 | contents, err: returns contents of file or false and error message. Requires io.popen (2DO: work when io.popen not available?) 621 | 622 | 623 | 624 |
625 | 626 | 627 | 628 | 629 |
isDir (dir, path)
630 |
631 | Test is pathname is a directory. 632 | 633 | 634 |

Parameters

635 |
    636 | 637 |
  • 638 | dir: 639 |
  • 640 | 641 |
  • 642 | path: string: pathname to test 643 |
  • 644 | 645 |
646 | 647 | 648 | 649 | 650 | 651 | 652 |

Return value:

653 | ok, log: true on success, false on failure and log message. 654 | 655 | 656 | 657 |
658 | 659 | 660 | 661 | 662 |
isFile (dir, path)
663 |
664 | Test is pathname is a file. 665 | 666 | 667 |

Parameters

668 |
    669 | 670 |
  • 671 | dir: 672 |
  • 673 | 674 |
  • 675 | path: string: pathname to test 676 |
  • 677 | 678 |
679 | 680 | 681 | 682 | 683 | 684 | 685 |

Return value:

686 | ok, log: true on success, false on failure and log message. 687 | 688 | 689 | 690 |
691 | 692 | 693 | 694 | 695 |
list (dir, path)
696 |
697 | Recursively list the contents of a directory. 698 | 699 | 700 |

Parameters

701 |
    702 | 703 |
  • 704 | dir: 705 |
  • 706 | 707 |
  • 708 | path: string: directory to list if not specified the current directory will be used 709 |
  • 710 | 711 |
712 | 713 | 714 | 715 | 716 | 717 | 718 |

Return value:

719 | table: an array of strings representing the contents of the directory structure 720 | 721 | 722 | 723 |
724 | 725 | 726 | 727 | 728 |
makeDir (dir)
729 |
730 | Create a directory. 731 | 732 | 733 |

Parameters

734 |
    735 | 736 |
  • 737 | dir: string: Path to create. 738 |
  • 739 | 740 |
741 | 742 | 743 | 744 | 745 | 746 | 747 |

Return value:

748 | ok, log: true on success, false on failure and log message. Succeeds if already exists. 749 | 750 | 751 | 752 |
753 | 754 | 755 | 756 | 757 |
makeStart (dest)
758 |
759 | Create environment startup script (Windows). 760 | 761 | 762 |

Parameters

763 |
    764 | 765 |
  • 766 | dest: string: Dir to generate the file in. 767 |
  • 768 | 769 |
770 | 771 | 772 | 773 | 774 | 775 | 776 |

Return value:

777 | ok, log: true on success, false on failure and log message. 778 | 779 | 780 | 781 |
782 | 783 | 784 | 785 | 786 |
makeStart (dest)
787 |
788 | Create environment startup script (Windows). 789 | 790 | 791 |

Parameters

792 |
    793 | 794 |
  • 795 | dest: string: Dir to generate the file in. 796 |
  • 797 | 798 |
799 | 800 | 801 | 802 | 803 | 804 | 805 |

Return value:

806 | ok, log: true on success, false on failure and log message. 807 | 808 | 809 | 810 |
811 | 812 | 813 | 814 | 815 |
move (src, dest)
816 |
817 | Move a file from one location to another (Windows). 818 | 819 | 820 |

Parameters

821 |
    822 | 823 |
  • 824 | src: string: Pathname of source. 825 |
  • 826 | 827 |
  • 828 | dest: string: Pathname of destination. 829 |
  • 830 | 831 |
832 | 833 | 834 | 835 | 836 | 837 | 838 |

Return value:

839 | ok, log: true on success, false on failure and log message. 840 | 841 | 842 | 843 |
844 | 845 | 846 | 847 | 848 |
move (src, dest)
849 |
850 | Move a file from one location to another (Windows). 851 | 852 | 853 |

Parameters

854 |
    855 | 856 |
  • 857 | src: string: Pathname of source. 858 |
  • 859 | 860 |
  • 861 | dest: string: Pathname of destination. 862 |
  • 863 | 864 |
865 | 866 | 867 | 868 | 869 | 870 | 871 |

Return value:

872 | ok, log: true on success, false on failure and log message. 873 | 874 | 875 | 876 |
877 | 878 | 879 | 880 | 881 |
path (...)
882 |
883 | Compose full system path or part of url 884 | 885 | 886 |

Parameters

887 |
    888 | 889 |
  • 890 | ...: 891 |
  • 892 | 893 |
894 | 895 | 896 | 897 | 898 | 899 | 900 |

Return value:

901 | string: Path string 902 | 903 | 904 | 905 |
906 | 907 | 908 | 909 | 910 |
pathLen (dir)
911 |
912 | little helper function to get file depth (for directories its +1) 913 | 914 | 915 |

Parameters

916 |
    917 | 918 |
  • 919 | dir: 920 |
  • 921 | 922 |
923 | 924 | 925 | 926 | 927 | 928 | 929 | 930 | 931 |
932 | 933 | 934 | 935 | 936 |
relLink (src, dest, from)
937 |
938 | Relatively Link file or directory contents to destination. 939 | 940 | 941 |

Parameters

942 |
    943 | 944 |
  • 945 | src: string: Path or file to link. 946 |
  • 947 | 948 |
  • 949 | dest: string: Destination to link to. 950 |
  • 951 | 952 |
  • 953 | from: string: Directory to link from, by default curDir. 954 |
  • 955 | 956 |
957 | 958 | 959 | 960 | 961 | 962 | 963 |

Return value:

964 | ok, log: true on success, false on failure and log message. 965 | 966 | 967 | 968 |
969 | 970 | 971 | 972 | 973 |
unzip (archive, dest)
974 |
975 | Unpack an archive. Extract the contents of an archive, detecting its format by filename extension. 976 | 977 | 978 |

Parameters

979 |
    980 | 981 |
  • 982 | archive: string: Filename of archive. 983 |
  • 984 | 985 |
  • 986 | dest: 987 |
  • 988 | 989 |
990 | 991 | 992 | 993 | 994 | 995 | 996 |

Return value:

997 | ok, log: true on success, false on failure and log message. 998 | 999 | 1000 | 1001 |
1002 | 1003 | 1004 | 1005 | 1006 |
zip (workdir, zipfile, ...)
1007 |
1008 | Compress files in a .zip archive. 1009 | 1010 | 1011 |

Parameters

1012 |
    1013 | 1014 |
  • 1015 | workdir: 1016 |
  • 1017 | 1018 |
  • 1019 | zipfile: string: pathname of .zip archive to be created. 1020 |
  • 1021 | 1022 |
  • 1023 | ...: Filenames to be stored in the archive are given as additional arguments. 1024 |
  • 1025 | 1026 |
1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 1033 |

Return value:

1034 | ok, log: true on success, false on failure and log message. 1035 | 1036 | 1037 | 1038 |
1039 | 1040 | 1041 |
1042 | 1043 | 1044 | 1045 | 1046 | 1047 | 1048 |
1049 | 1050 |
1051 | 1052 |
1053 |

Valid XHTML 1.0!

1054 |
1055 | 1056 |
1057 | 1058 | 1059 | -------------------------------------------------------------------------------- /luadist: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Simple LuaDist CLI interface 3 | -- This script uses the exposed LuaDist APIs to provide commandline interface to LuaDist features. 4 | -- Peter Kapec, Peter Drahoš LuaDist Project, 2010 5 | 6 | local dist = require "dist" 7 | local config = require "dist.config" 8 | local sys = require "dist.sys" 9 | local persist = require "dist.persist" 10 | 11 | --- Display help 12 | local function help() 13 | print ([[ 14 | LuaDist ]] .. config.version .. [[ - Simple Lua Distribution and Module Deployment System 15 | Usage: luadist (depldir) [command] (names) (-variables) 16 | 17 | where [...] are required and (...) are optional: 18 | depldir - Optional path to the deployment directory LuaDist will operate on. 19 | command - Specifies the operation to be executed: 20 | help - Display detailed help about command. 21 | install - Install/Update Dists from repository. 22 | remove - Remove deployed Dists. 23 | pack - Pack deployed Dists. 24 | search - Search repositories for Dists. 25 | list - List deployed Dists. 26 | info - Show details about Dist from repository. 27 | manifest - Generate dist manifest file for repository. 28 | make - Build and deploy dist from path and URL. 29 | names - A list of names (case sensitive), each name can contain version constraints. 30 | variables - Configuration options or CMake settings to be passed into the build process. 31 | Examples: 32 | installing luasocket and md5 33 | > luadist install luasocket md5 34 | installing Lua 5.1.4 to its own deployment directory. 35 | > luadist ./example install lua-5.1.4 36 | switch to newest LuaJIT 1.x 37 | > luadist ./example remove lua 38 | > luadist ./example install luajit<2 39 | update luajit to latest version 40 | > luadist ./example install luajit 41 | 42 | For additional help invoke 43 | >luadist help command 44 | ]]) 45 | end 46 | 47 | --- Commands the CLI provides 48 | local commands 49 | commands = { 50 | -- Display help for any other command or luadist in general. 51 | ["help"] = { 52 | help = [[ 53 | Usage: luadist help (command) 54 | 55 | This will show detailed description about (command). 56 | ]], 57 | run = function (_, cmds) 58 | if #cmds == 0 then 59 | help() 60 | else 61 | for i = 1, #cmds do 62 | local command = cmds[i] 63 | if commands[command] then 64 | print(commands[command].help) 65 | else 66 | print("Unknown command: " .. command) 67 | end 68 | end 69 | end 70 | return 0 71 | end 72 | }, 73 | -- Install dist 74 | ["install"] = { 75 | help = [[ 76 | Usage: luadist (depldir) install (names) (-variables) 77 | 78 | The install command can install and update dists by their (names), each name can contain additional version constraints. 79 | When constraints are not specified then the newest found is installed. 80 | The optional (depldir) path is used to specify deployment directory, by default dists install directly into LuaDist. 81 | For source dists (-variables) can contain CMake arguments using CMake's -D format and must be properly quoted. 82 | Updating all deployed dists is possible by supplying no names to install. 83 | ]], 84 | run = function (depldir, names, variables) 85 | local ok, err = dist.install(names, depldir, manifest, variables) 86 | if not ok then print (err) return 1 end 87 | print("Installation succesfull.") 88 | return 0 89 | end 90 | }, 91 | ["test"] = { 92 | help = [[ 93 | Usage: luadist (report) test (names) (-variables) 94 | 95 | The test command can test installation of by their (names), each name can contain additional version constraints. 96 | When constraints are not specified then the newest found is installed. 97 | The optional (report) file is used to specify what type of report to generate, by default test will not generate a report file and will only print to console. 98 | For source dists (-variables) can contain CMake arguments using CMake's -D format and must be properly quoted. 99 | When a report file is supplied LuaDist will also generate packed binary dists from the test deployment, this is usefull when generating multiple binary dists from source. 100 | ]], 101 | run = function (report, names, variables) 102 | local function saveHtml(filename, reportTable) 103 | local report = {} 104 | -- beginning of HTML code 105 | report[#report + 1] = [[ 106 | 107 | 108 | Report - building packages in LuaDist 109 | 113 | 114 | 115 |

116 |

Results of building packages

117 |

118 | ]] 119 | 120 | for distName, distTable in pairs (reportTable) do 121 | -- first add dist name 122 | report[#report + 1] = "
    \n
  • " 123 | report[#report + 1] = distName 124 | report[#report + 1] = "
  • \n
      " 125 | 126 | for archName, archTable in pairs (distTable) do 127 | -- add architecture information 128 | report[#report + 1] = "\n
    • " 129 | report[#report + 1] = archName 130 | report[#report + 1] = "
    • " 131 | -- and for the architecture add results of test 132 | report[#report + 1] = "\n
        \n
      • Installation result: " 133 | 134 | -- if result is "FAILED ..." and not just "OK" 135 | if #archTable.result > 2 then 136 | report[#report + 1] = "" 137 | report[#report + 1] = archTable.result 138 | report[#report + 1] = "" 139 | else 140 | report[#report + 1] = archTable.result 141 | end 142 | 143 | -- add date of test to given architecture 144 | report[#report + 1] = "
      • \n
      • Date of test: " 145 | report[#report + 1] = os.date ("!%c", os.time (archTable.date)) 146 | report[#report + 1] = "
      • \n
      " 147 | end 148 | 149 | -- end of information about dist 150 | report[#report + 1] = "\n
    \n
\n
\n" 151 | end 152 | 153 | -- end of HTML code 154 | report[#report + 1] = "\n
\n" 155 | 156 | -- transform an array of strings into one long string 157 | report = table.concat (report) 158 | 159 | -- write the HTML code to a file 160 | local output = io.open (filename, "w") 161 | output:write (report) 162 | output:close () 163 | return true 164 | end 165 | 166 | -- Suppress standard output in tests 167 | config.message = nil 168 | 169 | -- Get requested dists and repo manifest 170 | local manifest = dist.filterManifest() 171 | local dists, err = dist.findDists(names, manifest) 172 | if not dists then print(err) return 1 end 173 | 174 | -- Temporary deployment dir 175 | local temp = sys.path(config.temp, "luadist-test") 176 | 177 | print ("\nTest results for " .. config.arch .. "-" .. config.type .. ":\n===========================\n") 178 | 179 | -- Generate the report 180 | local archType = config.arch .. "-" .. config.type 181 | 182 | local test = {} 183 | for i = 1, #dists do 184 | local info = dists[i] 185 | local name = info.name .. "-" .. info.version 186 | local depl = sys.path(temp, name) 187 | 188 | local entry = {} 189 | entry.date = os.date("!*t") 190 | 191 | io.write("\t" .. name) 192 | io.flush() 193 | -- try to install the module 194 | local ok, err = dist.install(name, depl, manifest, variables) 195 | if not ok then 196 | io.write(" FAILED: "..err.."\n") 197 | entry.result = "FAILED: "..err 198 | else 199 | io.write(" OK.\n") 200 | entry.result = "OK." 201 | if report then dist.pack(name, depl) end 202 | end 203 | io.flush() 204 | 205 | test[name] = { 206 | [archType] = entry 207 | } 208 | end 209 | 210 | -- Save report if needed 211 | if report then 212 | if report:match("html$") then 213 | saveHtml(report, test) 214 | else 215 | persist.saveManifest(report, test) 216 | end 217 | end 218 | 219 | -- Cleanup 220 | sys.delete(sys.path(temp)) 221 | 222 | return 0 223 | end 224 | }, 225 | -- Update dist 226 | ["remove"] = { 227 | help = [[ 228 | Usage: luadist (depldir) remove (names) 229 | 230 | The remove command will remove deployed dists specified by (names) from the deployment directory (depldir). 231 | When (depldir) is not specified, then the dist will be removed from LuaDist. 232 | When no names are supplied LuaDist will delete the deployment entirely. 233 | NOTE: LuaDist does not do any dist dependency breakage tests on remove! 234 | WARNING! Be careful when removing whole deployments. You may loose data and in worst case break your system. 235 | ]], 236 | run = function (depldir, names) 237 | local ok, err = dist.remove(names, depldir) 238 | if not ok then print (err) return 1 end 239 | print("Removal succesfull.") 240 | return 0 241 | end 242 | }, 243 | -- Pack dist 244 | ["pack"] = { 245 | help = [[ 246 | Usage: luadist (depldir) pack (names) 247 | 248 | The pack command will pack installed dist identified by (names) from the deployment directory (depldir). 249 | When (depldir) is not specified the dist will be packed from LuaDist. 250 | The resulting dist files will beplaced into current directory. 251 | When no names are supplied LuaDist will pack all dists in the deployment. 252 | ]], 253 | run = function (depldir, names) 254 | local ok, err = dist.pack(names, depldir) 255 | if not ok then print (err) return 1 end 256 | print("Pack successful.") 257 | return 0 258 | end 259 | }, 260 | -- Search for dist 261 | ["search"] = { 262 | help = [[ 263 | Usage: luadist search (names) 264 | 265 | The search command will search repositories for all dists satisfing manes. 266 | Wildcard character * can be used to search for. 267 | When no search arguments are specified then all available dists will be listed. 268 | Search results are filtered and display only dists that can be installed for the platform LuaDist is running on. 269 | ]], 270 | run = function (_, names) 271 | local dists = dist.findDists(names) 272 | if not dists then print("\nNo dists found!")return 1 end 273 | print("\nSearch result:\n===============\n") 274 | for i = 1, #dists do 275 | local dist = dists[i] 276 | print("\t" .. dist.name .. "-" .. dist.version, "(" .. dist.arch .. "-" .. dist.type .. ")") 277 | end 278 | return 0 279 | end 280 | }, 281 | -- List deployed dists 282 | ["list"] = { 283 | help = [[ 284 | Usage: luadist (depldir) list (names) 285 | 286 | The list command will list deployed dists containing any occurance of a string from (strings) in their name. 287 | When no list arguments are specified then all deployed dists will be listed. 288 | ]], 289 | run = function (depldir, names) 290 | local dists = dist.findDists(names, dist.getDeployed(depldir)) 291 | print("\nDeployed dists:\n===============\n") 292 | for i = 1, #dists do 293 | local dist = dists[i] 294 | if dist.provided then 295 | print("\t" .. dist.name .. "-" .. dist.version, "( provided by: " .. dist.provided .. ")") 296 | else 297 | print("\t" .. dist.name .. "-" .. dist.version, "(" .. dist.arch .. "-" .. dist.type .. ")") 298 | end 299 | end 300 | return 0 301 | end 302 | }, 303 | -- Generate manifest 304 | ["manifest"] = { 305 | help = [[ 306 | Usage: luadist (dir) manifest 307 | 308 | The manifest command will create a dist.manifest file for the directory (dir) or current directory. 309 | This file is used as generated static index of dists contained in remote URL repositories where LuaDist cannot fetch directory listings. 310 | When you plan to make an online repository make sure it contains and up to date manifest. 311 | ]], 312 | run = function (dir) 313 | local manifest, err = dist.getManifest(dir) 314 | if not manifest then return nil, "Could not generate manifest: " .. err end 315 | local ok, err = persist.saveManifest("dist.manifest", manifest) 316 | if not ok then return nil, "Could not save manifest: " .. err end 317 | print("Manifest generated.") 318 | return 0 319 | end 320 | }, 321 | -- Build a unpacked dist directory 322 | ["make"] = { 323 | help = [[ 324 | Usage: luadist (depldir) make (paths) (variables) 325 | 326 | The make command will make and deploy dists into (depldir) from local (paths) or current directory if no paths are specified. 327 | This command is usefull for development of dists or in cases where you want to force deployment of dists. 328 | Make sure (paths) contain valid dist.info files or point to .dist or .zip archives. 329 | Optional CMake (variables) can be passed to the build process when dealing with source dists using -D[CMakeVariable]= format. 330 | ]], 331 | run = function (depldir, paths, variables) 332 | local ok, err = dist.deploy(paths, depldir, variables) 333 | if not ok then print(err) return 1 end 334 | print("Make successful.") 335 | return 0 336 | end 337 | }, 338 | -- Display info about dist 339 | ["info"] = { 340 | help = [[ 341 | Usage: luadist info (names) 342 | 343 | Info command will print information about the dists identified by (name) from repository. 344 | In case names are satisfied by multiple dist versions, only the most recent version will be displayed. 345 | ]], 346 | run = function (depldir, names) 347 | local dists = dist.findDists(names) 348 | if not dists then print("No dists found!") return 1 end 349 | for i = 1, #dists do 350 | local info = dists[i] 351 | print("\n" .. info.name .. "-" .. info.version) 352 | print("Description: " .. (info.desc or "not-available")) 353 | print("Author: " .. (info.author or "not-available" )) 354 | print("Maintainer: " .. (info.maintainer or "not-available" )) 355 | print("Url: " .. (info.url or "not-available" )) 356 | print("License: " .. (info.license or "not-available" )) 357 | end 358 | return 0 359 | end 360 | }, 361 | } 362 | 363 | --- Handle commandline arguments 364 | local n, dir, command, names, variables = nil, nil, nil, {}, {} 365 | 366 | -- Determine deployment and command 367 | if not commands[arg[1]] and commands[arg[2]] then 368 | dir = arg[1] 369 | command = arg[2] 370 | n = 3 371 | elseif commands[arg[1]] then 372 | dir = dist.getDeployment() 373 | command = arg[1] 374 | n = 2 375 | else 376 | -- No Command, print help 377 | help() 378 | return 0 379 | end 380 | 381 | -- Helper split function for argument to table conversion 382 | function split(str, pat) 383 | local t, fpat, last_end = {}, "(.-)" .. pat, 1 384 | local s, e, cap = str:find(fpat, 1) 385 | while s do 386 | if s ~= 1 or cap ~= "" then 387 | table.insert(t,cap) 388 | end 389 | last_end = e+1 390 | s, e, cap = str:find(fpat, last_end) 391 | end 392 | if last_end <= #str then 393 | cap = str:sub(last_end) 394 | table.insert(t, cap) 395 | end 396 | return t 397 | end 398 | 399 | -- Collect settings, names and variables 400 | for i = n, #arg do 401 | -- Collect names 402 | if arg[i]:match("^%-") then 403 | -- Arguments 404 | if arg[i]:match("^%-D") then 405 | local cvar, value = arg[i]:match("^%-D(.-)=(.*)") 406 | variables[cvar] = value 407 | elseif arg[i]:match("^%-") then 408 | local var, value = arg[i]:match("^%-(.-)=(.*)") 409 | -- Compare to variables from config.lua and change type accordingly 410 | if config[var]~=nil then 411 | -- Change to number 412 | if type(config[var])=="number" then 413 | value = tonumber(value) 414 | end 415 | -- If its a boolean, everything else but "false" counts as true. 416 | if type(config[var])=="boolean" then 417 | if value == "false" or value == "0" or value == "off" then value = false else value = true end 418 | end 419 | -- If its a table 420 | if type(config[var])=="table" then 421 | value = split( value, "," ) 422 | end 423 | -- Set the value 424 | config[var] = value 425 | else 426 | print("Invalid configuration option!", arg[i], "\n") 427 | help() 428 | return 1 429 | end 430 | else 431 | print("Invalid argument!", arg[i], "\n") 432 | help() 433 | return 1 434 | end 435 | else 436 | table.insert(names, arg[i]) 437 | end 438 | end 439 | 440 | -- Run command 441 | os.exit(commands[command].run(dir, names, variables)) 442 | --------------------------------------------------------------------------------