Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/torch/luajit-rocks.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRonan Collobert <locronan@fb.com>2014-09-11 01:44:48 +0400
committerRonan Collobert <locronan@fb.com>2014-09-11 01:44:48 +0400
commit31690a82a01bf8a336699e6a278f85d5a420561f (patch)
treeda900b500d7d71a8d6a77f88537e7078758d1e6a
parent009a990f201a9b57c768cd96a97466d044d122b1 (diff)
Squashed 'luarocks/' changes from c7a3685..b563ebd
b563ebd Make error message more specific. Closes #213. 2b93947 Switch to HTTPS by default. Closes #240. 8dffe73 Ensure luarocks.loader sees package paths. This should fix a bug reported by @tomasguisasola on 2014-07-07. fa6863a Apply portability fixes suggested by @ignacio. b66bc07 Latest FreeBSD doesn't include gcc :( 878fbf5 Merge pull request #231 from rrthomas/master 107fe26 Correct inaccuracy in documentation. The logic for determining the default local repository can get complicated (see luarocks/command_line.lua and luarocks/path.lua), so saying cfg.root_dir wouldn't be quite precise either. So let's avoid the issue. Closes #278. 9e58a22 Add --with-lua-bin and improve documentation of --with-lua 23739a7 Fix build issue by not depending on ordering. 7374302 Enable API debug when in verbose mode. 5707a24 Fix documentation 3abde0d Turn failure into success in test. Oh, excellent, with the new fallback code in fs.download, this doesn't fail anymore! 570e29f Merge branch 'master' of https://github.com/keplerproject/luarocks c318a9a HTTPS support for downloading and uploading rocks. HTTPS is set as default for uploading. HTTP is still default for downloading to keep dependencies low and because the HTTPS code is new; might be changed in the future. See #273 and #240. 54733d5 Merge pull request #271 from Tieske/master fbd5d29 slightly more readable output with many dependencies ee69f76 Add luafr.org moonrocks mirror 4ab6969 Dehardcode the separator for PATH variables, fixing behavior on Unix. f8c6ac1 Fix Windows package generator; cleanup dot files. 015aa52 Merge pull request #263 from siffiejoe/220windowsfix be35795 fixed install.bat for new luarocks version dc9d2da Transition to MoonRocks. Add `luarocks upload` command for uploading into MoonRocks. 1788d0b Fix chmod argument order. 0d9bc9e Merge branch 'master' of https://github.com/keplerproject/luarocks 4f66cbd Fix curl --connect-timeout option following #261. a9bd5ca Merge pull request #261 from apuertolas/curl-fix 3eeb977 Fix curl --connect-timeout option 9db13c5 Merge pull request #259 from Tieske/new_installer_options a100950 Adds /LUAMOD and /CMOD options to Windows installer ceab1a6 Merge pull request #256 from Tieske/reorg_win 1dd5293 Reorganized Windows specific files. Now installer can work directly from the repository 9f1a6be Merge pull request #253 from Tieske/fix_path_order 4396b50 Set timeout in LuaSocket/LuaSec based implementation as well. Be more forgiving with thi cfg.connection_timeout setting. Add --timeout flag, as discussed in #249. dca1783 Merge branch 'master' of https://github.com/keplerproject/luarocks 2501f31 Merge pull request #249 from Tieske/conn_timeout 17437fd fixes #251 - order of path; user vs system tree corrected. - bin directories of all trees included, instead of current tree 635e7e9 added `--tries=1` to wget to prevent 20 tries (=20 timeouts) e6243d2 initial commit including a network timeout for wget and curl based downloads 63820f8 Add -k flag so that curl behavior matches that of wget. Also, make win32 and unix code more similar (we're almost to the point where we could have a single implementation for both!) 999e27d Merge pull request #246 from Tieske/fixed_interpreter 6f12f25 run LR itself on the Lua interpreter found during install, not on the interpreter first in the system path. Lining up with the unix shell scripts. 489b990 Add -f flag to curl, to improve error handling, as suggested in #244. 0842090 Use a test matrix in Travis 7e06313 Merge pull request #243 from siffiejoe/lua53 eba0f64 prepare luarocks for lua 5.3 00b5631 Run Travis-CI testsuite on Lua 5.1 and Lua 5.2! 33eb354 Fix regression introduced by demodularization process 58b7f5d Merge pull request #242 from mpeterv/lua52_compat 99c664c Fixed remaining unpack issues 8498916 Merge branch 'master' of https://github.com/keplerproject/luarocks into lua52_compat d9c7991 Fixed some issues with table.unpack 397659c Split luarocks.path the library and `luarocks path` the command. As suggested in #232. 37e3884 Removed module calls from installation scripts 878f56e Unmoduled core modules with package.loaded trick + fixed locals shadowing module table be3a351 Minor consistency improvement in util.lua cb08cbe Unmoduled per-platform fs implementations 232317a Fixed strange things in deps modules + fixed a bug with luarocks.fs.lua.get_md5 235124b Unmoduled luarocks.util b63e863 Unmoduled CLI-related modules which used some globals 066269a In luarocks.utils, require deps only inside functions a3ee3e9 Split luarocks.path module 3af05c7 Un-module bundled deps 3aa7e7a Bring the Unix implementation up to par with the Windows one! 0e8c964 Fix help, as pointed out by @ignacio 96a3f27 Merge branch 'master' of github.com:keplerproject/luarocks 548de23 Merge pull request #239 from mpeterv/remove_unused_variables 427b40d Removed some unused variables 2181a1b Revert change that broke rocks.moonscript.org — it would skip servers that have no .zip manifest in them. 63793e2 Merge pull request #237 from Tieske/no_exe_wrapper 9ab0707 check is_lua by compiling the file ab3f1a0 remove exe wrappers, just batch files on windows 2bcc5e5 Merge pull request #236 from fperrad/patch-1 7e2fd86 filter message when deps_mode="none" ef20bb1 Merge pull request #235 from siffiejoe/unzip 659f811 use correct path for is_dir check 1fe7650 handle implict subdirectories when unpacking with LuaZip b14d3f9 Flag -c is running too slow. 5ae1d1f Fix issue when source.dir got misdetected if URL ends with character 'c'! How many years did this go undetected? 16a34ad Remove repeated entry 506a539 Merge pull request #233 from neomantra/http_request_err b5259bc Added nil check for tsfd in http_request() 2f23df7 Upgrade luacov 916f3b9 Add test for missing external deps. Improves coverage. A bug was uncovered writing this! e6ebf47 When a server times out, stop using it and move down the mirrors list. fdf5465 Refactor and improve logic for detecting base directory. 330ee40 Install default doc files if the rockspec does not include any. 0033902 Have separate fs.dir and fs.list_dir functions. The first returns an iterator, the second one a table. 343fbd5 Merge branch 'master' of github.com:keplerproject/luarocks a3b0f72 Make `luarocks doc` return something meaningful even for rocks that are not installed. 2219ac8 Merge pull request #230 from fperrad/patch-1 73850de remove dead local variable wrap_bin_scripts 735f794 Add more tests. 981a8c9 Merge branch 'master' of github.com:keplerproject/luarocks 6e65663 Fix logic to report errors when loading config.lua. Closes #228. Please reopen if problem persists. a4a9795 Merge pull request #227 from Tieske/install_fix 340ebd5 remove rocksserver settings from windows installer 93f69e6 Merge pull request #226 from Tieske/branch_option fd1d38a added help info to build and make commands 097d81a Merge pull request #224 from Tieske/help_update f36d651 Merge pull request #225 from Tieske/md5_fix d0aab1f updated the `--branch` option to work through updating the rockspec `source.branch` field Additionally a fix for the `git` module, to use command quoting 2078f83 adds a --branch=<branchname> option. The branchename is passed as BRANCH to the rockspec environment 7e4e9d0 unquoted path fails when spaces are in the filename 1029726 mention --verbose option in help 78be496 Why was this here? :) bd471f7 Merge pull request #223 from ignacio/patch-2 cb05319 Use \n as separator to keys_as_string a69f6dc Fix documentation. Thanks @ignacio! c0d695a show --modules will output one module per line 3049878 Add git+http fetch module to be used in case of "git clone http://..." URLs. c358d9b This constant needs to be global. 5d0f26d Merge branch 'master' of github.com:keplerproject/luarocks c58ba1d Merge pull request #222 from Tieske/fic_doc e867e18 bugfix doc on windows - path with spaces could not be opened - missing parameter for 'start' b78aa96 Catch undeclared globals in rockspecs 77f68c7 Merge branch 'master' of github.com:keplerproject/luarocks 1e0af10 Merge branch 'master' of https://github.com/keplerproject/luarocks 60323b4 minor update 17f1c5d Merge pull request #216 from siffiejoe/master 488dcab Merge pull request #220 from ignacio/patch-2 bbf9214 Misplaced quote in resulting luarocks.bat file d6b97cf Prepare to release version 2.1.2 04d071b Use --homepage, which is less ambiguous. 0402bce Check if unzip failed a147020 Don't quote URL on Windows. Doesn't seem to work: https://twitter.com/pchapuis/status/414119212739604480 6235923 Quote URLs. I wonder if it works properly with `start` on Windows. 2c21fec Fix bug when docs are missing bac6b52 Enhancements for `luarocks doc` UI 5592cbc Add doc command 9f8ab8c Factor out function for use by luarocks.doc 3168502 Add textile 5a8f454 Modifications based on suggestions by @agladysh f50cde9 Add fs.browser command cd0054d Remove spurious commented code 64e386e Add default web browsers 74a46a3 First go on `luarocks doc` 7c3c9c8 Merge pull request #219 from Tieske/master 9fb2a23 bugfix: /CONFIG option to follow install location, so /P will have effect on config location as well. b7ac940 Merge pull request #218 from Tieske/master e073a4b bugfix: /CONFIG not honored because of typo 4ec1388 Looks like I ran the test suite locally in the wrong branch fec24d3 Add missing commit of luarocks-admin command changes cc232cb Merge branch 'master' of github.com:keplerproject/luarocks 757539b Performance improvements ee2ff69 Merge pull request #217 from Tieske/master 3d42a34 don't print process info when help is displayed 2e3b220 fixed test for empty variable in configure script 2511c83 Add help on --deps-mode 2e48fb3 Merge branch 'master' of github.com:keplerproject/luarocks 16c2c97 Improvements to the write_rockspec command. Let's make this more and more automagical over time. :) a30a946 Merge pull request #214 from Tieske/purge_permission d269a3c Fix: Purge command did not check permission for the tree to operate on f4b271c Merge branch 'master' of github.com:keplerproject/luarocks 8927752 Licensing cleanup 5abe779 Merge pull request #212 from Tieske/text_fix 983362f some textual updates 1ab1f45 Merge pull request #211 from Tieske/exitcodes 57c4c60 updated comments for exitcodes batch wrapper script (luarocks.bat) updated to auto-elevate if permission was denied e4760c8 specify error exitcodes, specifically 'permission denied'. 33e0ec7 updated default system tree location to 'program files', so it is protected with admin rights. Implemented a /SELFCONTAINED installation option that makes a single directory installation cd2b895 Merge pull request #209 from Tieske/help_output b220473 normalize paths in help output 3bc775b Make sure value of tree is propagated correctly to commands. 786b6a1 Merge branch 'master' of github.com:keplerproject/luarocks b45af8b Try versioned "lua" names before the unversioned one. Should improve on behavior mentioned at http://stackoverflow.com/questions/20321560/how-do-install-libraries-for-both-lua5-2-and-5-1-using-luarocks/20359102?noredirect=1#comment30696438_20359102 a0064f4 Merge pull request #206 from Tieske/verbose_flag 0bcdb08 Merge pull request #207 from Tieske/normpath ccc851f Merge pull request #208 from Tieske/treeorder 82e065c fixed wrong tree order in config file; order was user - system. Now corrected to system - user. So installations default to system tree. c056337 take urls into account besides local paths df91dc7 Normalizes paths displayed from `search` module, used for searching and listing installed rocks c04e89b adds flag `--verbose` as equivalent for config file `verbose = true` c05ebc0 Merge pull request #205 from Tieske/context_menu_fix 52cd32a fixed bug where context menu options did not support paths containing spaces 6b398ff Fix display of error message in loader. 13a249a Fix regressions caused by #194. Thank you, integrated testing! f169343 Let's not use "built-in" terminology in this case: avoid confusion with the "builtin" build mode. e13d4e0 Use same loop for both arrays dfce483 Let's be more conservative about this for now. 9133c69 Merge pull request #194 from rtsisyk/gh-177-option-for-builtin-packages 30b5ae3 Merge pull request #188 from echiesse/master e70f8ed Merge pull request #204 from Tieske/win_named_tree 12e6e26 1. bug fix for installing on x64 systems in "program files (x86)" (parentheses around x86 gave some escaping problems) 2. Adds named trees created by windows installer in the config file. 1cc2c90 Add check that will be used to ensure no rocks without licenses are uploaded. Closes #202. c34e7ba Prioritize "scm" over "cvs". This was underspecified before. e0fc42d Make default rocks_trees named as well. 0f172cb Fix some tests that only run locally. 3f67e81 Add named trees, as suggested by @Tieske, plus tests. 138d823 More tests 7a9bd56 Test environment improvements 346a73b Propagate failure of MD5 correctly. Closes #184. 5ca108f Merge pull request #200 from fab13n/master 949c05e Add Travis-CI badge to the README file 87e35e9 Use LuaCov 0.4 fb08ed2 Major updates, hopefully speeding up things. Preload necessary rocks and rockspecs and create a local server. Cache LuaSocket compilation for tests that need it. 58aabb2 Merge branch 'master' of github.com:keplerproject/luarocks e37937d Make the download command work with the file:// protocol ca0cf62 Fixed an improper error message f154f7e Merge pull request #197 from Tieske/proper_win_defaults f93e614 stopped copying dll files becasue reason is unknown added note on %appdata% value d0a6f0b Going crazy! c7c9ee2 Just one more... 9f05a48 skip more rsync stuff 8f3f740 skip rsync stuff 8bf1272 I'm still trying, Travis! I'm still trying! a620ec6 skip this one ce84268 Drop the X11 dependency 69d80ee Let's use the unstable LuaSec for now. Pinged Bruno about it. 6f2e95c Ah, Ubuntu... 50332f6 Fixes for Travis-CI aafefa8 Add .travis.yml... let's see what happens! 8fde71c Merge branch 'master' of github.com:keplerproject/luarocks 7734e61 Improve error message 42396f9 Fix incorrect condition in test 4e94b65 Merge branch 'master' of https://github.com/keplerproject/luarocks into proper_win_defaults 4f9ee18 Merge pull request #198 from Tieske/unquoted_path_fix 716a8a5 bugfix: unquoted path 16af248 Does the windows installation with Windowish defaults Adds a prompt before installing, and a switch /Q to ignore that example added to help text to explain a self contained installation registry information is now loaded without prompts 5f08796 Merge pull request #195 from Tieske/fix_order 52b6e37 Commandline options where silently ignored if config.lua already existed. Now a backup is made and the options are written. Additional paths to the local tree are now listed after installing aeff145 Windows installer required /P argument to be first or would overwrite other values cleanup temp batch file in case of elevation c1342e2 Merge pull request #193 from Tieske/no_powershell 948a070 If PowerShell is not available, a proper message is now displayed when installing on Windows without admin priviledges 94cde99 Merge pull request #192 from Tieske/debug_output 03cc920 refactored debug output. Now all is set by using `verbose = true` in the config file instead of manually uncommenting code. Also moved to platform independent code, from Windows only 62c7402 Merge pull request #191 from Tieske/refactor_priv 5d8a42b simplified priviledge test on Windows 8a2ede6 Merge branch 'master' of https://github.com/echiesse/luarocks 8d1973d Fixed the error of not embedding the manifest in DLLs compiled by Visual Studio 2008 in the case where the DLL is part of a module (inside a subdirectory). LusRocks was not correctly building modules with directory structure (like luasql.postgres) when compiling for win32. ef05a02 Add a configuration option to specify manually installed rocks. 3cd6318 Merge pull request #190 from Tieske/adminrights_installer aeed3ed The installer will automatically request admin priviledges to allow proper installation in protected locations. A new switch /NOADMIN is added to explicitly prevent this, and allow installation in unprotected locations when the user doesn't have admin rights. 50e6d37 Merge pull request #183 from Tieske/command_quoting 222c3c4 Merge branch 'master' of https://github.com/keplerproject/luarocks into command_quoting 2d946ff Merge pull request #189 from Tieske/fix_permission_check 45c2342 removed unintended code 4c650b9 fixes permission checks on Windows with VirtualStore redirection fdbb7ed Corrigido erro de não fazer o embed do manifest em dlls compiladas pelo Visual Studio 2008 no caso de a dll fazer parte de um módulo (estar em um subdiretório). O LuaRocks não fazia corretamente o build de módulo que tivessem estrutura de diretório (como luasql.postgres). 7f11f5f Merge branch 'master' of https://github.com/keplerproject/luarocks into command_quoting 722c03a fixed double quotes in io.popen commands 827bdfd Merge pull request #186 from Tieske/bad_underscore 579ad25 fixed type. Fixes #185 a1f62e6 Add --force flag. Should be useful for François Perrad's work on the BuildRoot infrastructure for LuaRocks. 64ca4ac Make sure manifest unzips properly, to avoid stale manifests. de9c982 Fix `luarocks path` now that luarocks.cfg no longer edits package.path 3844927 Merge branch 'master' of https://github.com/keplerproject/luarocks into command_quoting 217a435 update get_md5() and check_md5() to also return an error message if it fails unquoted arguments of get_md5 command to prevent failure, needs further updating 370a294 fixes LR install in location with spaces, quoting LR commands NOTE: seems to be broken now, bug not found yet 3168eaa Merge branch 'master' of github.com:keplerproject/luarocks 66bf838 Remove incompatibility in the sed command, as reported in the Lua mailing list. 0521c3d Merge pull request #181 from Tieske/win_install_checkpath 1078610 Merge pull request #179 from akfidjeland/bugfix-deps-mode-order 0643c2c Merge branch 'master' of github.com:keplerproject/luarocks e05effd Allow the wrapper scripts to keep working even if LuaRocks is uninstalled (or if one is building them to run in another box without LuaRocks, for example, in cross-compiling scenarios). 4e4e1d2 Merge branch 'master' of github.com:Tieske/luarocks into win_install_checkpath f06853c Merge pull request #182 from Tieske/fix_quotes 64bf574 added quoting to os command, failed with paths containing spaces d3a6420 Merge branch 'master' of github.com:keplerproject/luarocks 8863788 Merge changes proposed by @siffiejoe in #172. (Sorry about the clumsiness of not doing a proper merge.) f0f3f13 fix: registry import with filename containing spaces 7e520a5 Merge branch 'master' of github.com:Tieske/luarocks into win_install_checkpath bdcde87 Merge pull request #180 from Tieske/win_space_arguments a726e45 Several updates: 1) will search the system path for Lua interpreter if no location is found. Only then the ancient defaults will be checked. 2) if /LUA is provided, it will only look there, and fail if not found instead of falling back to the defaults 3) if no interpreter found, it is not automatically installed. Only with explicit /L switch the included interpreter is installed 26817ad minor text update 4299979 fixed issue with double quoted arguments 7bd1a65 fixed command line parameters with spaces reorganized help description fixed whitespace 14d06b0 map_trees deals with both string and table trees 143cc28 Merge branch 'master' of github.com:keplerproject/luarocks ffb82c3 Merge branch 'master' of github.com:keplerproject/luarocks df33f22 Symlinks shouldn't refer to DESTDIR. Patch submitted by Dmitri Paduchikh. 84c13db Merge pull request #175 from rtsisyk/gh-174 9c13a68 Fix #174: An extra parenthesis in build/cmake.lua f3fae7c Prepare for release 2.1.1 88e21b5 Improve coverage -- now at 80.06% 1ab2ca9 Fix handling of arguments. 98ef4bf Remove redundant function. d82cc27 Merge branch 'master' of github.com:keplerproject/luarocks 86d183e Don't loop in case of circular dependencies 33baf1f Fix inverted logic in recent commit. c815ed2 Merge pull request #171 from siffiejoe/lua-path-windows 5c36bba added extra path for luarocks modules on windows 54fd912 Add escaping of ]] preventing code injection as contributed by @siffiejoe. See #154, #167. 76b1780 update info 6149392 Remove binaries which are no longer needed. See #167. eb97343 Remove spurious \ from pattern ed118e5 Should fix build on Windows. See #167. Also, speeds up operations on Windows considerably. abac98a Use a more idiomatic Windows path for the local caches 23a7eae Accidentally ate a space, sorry! 4c96734 Add option to make 7z overwrite zip files, matching unzip behavior on Unix. Flag suggested by @siffiejoe. Should fix problems mentioned in #167. a1bc8ec Cache remote manifest files locally and hit server with a HEAD request to check timestamp. 7559598 Fix behavior on nonexisting files, and while we're at it make it more efficient and less prone to race conditions. e868215 Make make-manifest more fool-proof, for values of "fool" equalling Hisham e5610e7 Add documentation. a9f9050 Cleanup temporary fields that escaped; catch an argument error. 15cc0d6 Improve coverage -- now at 79.65% 30c2877 Fix infinite loop! 88c6b10 Improvements for write_rockspec 08e694e Merge pull request #166 from siffiejoe/win32-escapes 8adef07 remove non-portable Qb from lua.lua c557cda special handling for chdir and root directory ef06536 better shell escaping on windows f728b1b Improved quoting in script wrappers. Add util.LQ function for Lua quoting. As discussed in #154. 18b2024 No need to quote backslashes in single-quoted strings. As referenced by @siffiejoe in #154. a3c1394 Merge pull request #165 from Tieske/pe-parser f9a2409 Escape doublebrackets in paths that go to wrappers. b6990a6 Merge branch 'master' of github.com:keplerproject/luarocks faf6740 Merge pull request #154 from siffiejoe/linux-multiarch 58c7d8d minimize path and cpath modification in wrapper scripts 504f70f wrapper scripts don't mess with env-vars of subprocesses 309ad25 Merge remote-tracking branch 'upstream/master' into linux-multiarch 67d8a8a Fix version test. Thanks @siffiejoe for the heads up! 57bde51 Some tests require a local sshd server. Add a small check and message to myself, to avoid running the whole thing only to have it fail at the very end. 5b69973 Add reference to write_rockspec.lua in Makefile e11e2f8 Merge branch 'master' of github.com:keplerproject/luarocks c0a59c5 minor fix! ee42f74 Added new command 'luarocks write_rockspec', which writes a template for a new rockspec. 23214ad included pe-parser module (no longer objdump.exe, which is removed), updated installer to check architecture (32/64) interpreter was compiled for (instead of system architecture). Runtime detection should now also properly work on 64bit binaries. e6e0e57 Merge remote-tracking branch 'upstream/master' into linux-multiarch 68878f0 Merge pull request #164 from Tieske/interpreter_short_version 8c675a1 fix paths for 5.2, escaping in installer and fix wrapper scripts aafea84 Merge remote-tracking branch 'upstream/master' into linux-multiarch ff7c4d7 Merge pull request #163 from Tieske/interpreter_short_version 41a84a7 modified architecture detection as per http://support.microsoft.com/kb/556009 83aa8df fix for 5.2 path variable 54be99f added platform detection 32/64bit 8580df1 make installer find interpreter by short versioned name, eg. lua52.exe instead of lua5.2.exe c026b15 Fix hardcoded reference to git b11a31c fixed quotes in wrapper scripts on windows be6664e Lua 5.2 paths in wrapper scripts on windows 44a397f Merge pull request #159 from Tieske/missed_ones d03c7ef ditch some more output 82f11eb Merge remote-tracking branch 'upstream/master' into linux-multiarch df1e8d9 A simpler approach for reducing output clutter. Closes #158. 216f360 changed multiarch detection and site_config variables 0455050 Merge remote-tracking branch 'upstream/master' into linux-multiarch 99bf419 Merge pull request #157 from Tieske/cleanup_reg_files 289366d Merge pull request #156 from Tieske/Win_installer_5v2 a988293 update installer to work on Lua 5.2 fc9d5bb adding Lua 5.2 paths to wrapper scripts 4745a6e support for tables in (runtime_)external_deps_subdirs.* f63fa84 Merge remote-tracking branch 'upstream/master' into linux-multiarch 4a3c087 Merge branch 'master' of github.com:keplerproject/luarocks 606c29d Remove trailing space from dir_name; do not rely on setfenv to check for Lua 5.1, this breaks users of 'strict' globals checker 9fd7004 detect native multiarch directory on linux a55309e Merge pull request #153 from Tieske/master 5eb08d9 Added a utility batch file to pack LR on windows 794a45d Merge pull request #152 from ignacio/install_wrong_cpath f8b5432 When you supply an existing Lua installation, the suggested value for LUA_CPATH is wrong. 890e7bb factor out rsync flags to make them consistent 9d3d6e5 Make sure .git is not rsync'd 612024d Whitelist bit32 as a pre-satisfied dependency when running Lua 5.2. 2e999a1 Fix regressions in test suite 24ce781 Fix unpacking of rockspecs b2a9fa9 Inform Lua version in use in help screen 031e8aa Fix help of remove ff226c6 Use zipped manifests. Makes LR a bit faster! 4f565f3 remove reg files no longer needed after install 666faa4 Merge pull request #150 from Tieske/master ff54c88 include winbinaries in new location d9e8c2c Merge pull request #145 from Tieske/move_win_binaries 644c0b0 Merge pull request #149 from Tieske/remove_output 3d55785 downloading caused some output to appear, by wget.exe, this fix removes that output f06cddb normalize directory before creating a directory path. Fixes #140 a5a94c6 Merge branch 'master' of https://github.com/keplerproject/luarocks into move_win_binaries 5e1bc7d Since we're using our own mkdir, use mkdir -p to create subdirectories. Should suffice for #140 but needs testing. 186db3f Fix typo. (Ouch, how did that get in? My local environment must have pulled luarocks.cfg from somewhere else. Need to check that.) 6cab773 moved windows binaries into a 'bin' subdirectory. fabfd9c Call helper binaries using full path on Windows. Closes #127. Closes #140. 268efd3 Add --force=fast mode that does not report on dependency issues, as suggested by @agladysh. Closes #144. d4ff96d Fix regression when installing modules in subdirectories. Closes #143. 42e1e4b Make LR stop complaining when the 'doc' directory is missing. Also, handle missing directories explicitly specified in copy_directories as errors. Closes #142. 8cb0bc4 accept numbers as first character of a rock name in a dependency 4744dc4 Should fix installation of parallel LuaRocks versions when using 'make bootstrap' on both. Thanks to Philipp Janda for the test case! a4f62cb minor updates to the testing.sh script c480542 Use list from http://stackoverflow.com/a/15853231/1793220 when detecting mingw libraries. Closes #139. 86ad431 oops, remove debug message :) 0b8605f Make behavior more intuitive when the key in a modules or build.install.lua section asks to rename a module. I personally think it's a bad practice, but the syntax implies this is possible and the previous behavior is surely worse than the new one. See http://stackoverflow.com/questions/18314068/does-luarocks-rockspec-use-only-file-names-for-module-sub-names 951cb2b Make anchors more easily accessible from web browsers 7882ea4 Make sure fs.change_dir is always checked and results in proper errors. 772410c Make sure fs.make_dir is always checked and results in proper errors. git-subtree-dir: luarocks git-subtree-split: b563ebd276fbcb6a49f2d60380d8ec51b40b54a2
-rw-r--r--.travis.yml10
-rw-r--r--COPYING29
-rw-r--r--COPYING_win16
-rw-r--r--Makefile83
-rw-r--r--README.md9
-rwxr-xr-xconfigure73
-rw-r--r--install.bat684
-rwxr-xr-xmakedist5
-rw-r--r--rockspec2
-rwxr-xr-xsrc/bin/luarocks40
-rwxr-xr-xsrc/bin/luarocks-admin15
-rw-r--r--src/luarocks/add.lua32
-rw-r--r--src/luarocks/admin_remove.lua28
-rw-r--r--src/luarocks/build.lua154
-rw-r--r--src/luarocks/build/builtin.lua70
-rw-r--r--src/luarocks/build/cmake.lua15
-rw-r--r--src/luarocks/build/command.lua7
-rw-r--r--src/luarocks/build/make.lua9
-rw-r--r--src/luarocks/cache.lua29
-rw-r--r--src/luarocks/cfg.lua261
-rw-r--r--src/luarocks/command_line.lua76
-rw-r--r--src/luarocks/deps.lua141
-rw-r--r--src/luarocks/dir.lua49
-rw-r--r--src/luarocks/doc.lua156
-rw-r--r--src/luarocks/download.lua39
-rw-r--r--src/luarocks/fetch.lua150
-rw-r--r--src/luarocks/fetch/cvs.lua12
-rw-r--r--src/luarocks/fetch/git.lua27
-rw-r--r--src/luarocks/fetch/git_file.lua7
-rw-r--r--src/luarocks/fetch/git_http.lua27
-rw-r--r--src/luarocks/fetch/hg.lua15
-rw-r--r--src/luarocks/fetch/sscm.lua7
-rw-r--r--src/luarocks/fetch/svn.lua15
-rw-r--r--src/luarocks/fs.lua39
-rw-r--r--src/luarocks/fs/lua.lua340
-rw-r--r--src/luarocks/fs/unix.lua35
-rw-r--r--src/luarocks/fs/unix/tools.lua161
-rw-r--r--src/luarocks/fs/win32.lua130
-rw-r--r--src/luarocks/fs/win32/tools.lua213
-rw-r--r--src/luarocks/help.lua57
-rw-r--r--src/luarocks/index.lua47
-rw-r--r--src/luarocks/install.lua35
-rw-r--r--src/luarocks/lint.lua28
-rw-r--r--src/luarocks/list.lua14
-rw-r--r--src/luarocks/loader.lua84
-rw-r--r--src/luarocks/make.lua27
-rw-r--r--src/luarocks/make_manifest.lua23
-rw-r--r--src/luarocks/manif.lua200
-rw-r--r--src/luarocks/manif_core.lua27
-rw-r--r--src/luarocks/new_version.lua43
-rw-r--r--src/luarocks/pack.lua42
-rw-r--r--src/luarocks/path.lua152
-rw-r--r--src/luarocks/path_cmd.lua73
-rw-r--r--src/luarocks/persist.lua28
-rw-r--r--src/luarocks/purge.lua21
-rw-r--r--src/luarocks/refresh_cache.lua14
-rw-r--r--src/luarocks/remove.lua87
-rw-r--r--src/luarocks/repos.lua98
-rw-r--r--src/luarocks/require.lua6
-rw-r--r--src/luarocks/search.lua98
-rw-r--r--src/luarocks/show.lua59
-rw-r--r--src/luarocks/tools/patch.lua40
-rw-r--r--src/luarocks/tools/tar.lua13
-rw-r--r--src/luarocks/tools/zip.lua11
-rw-r--r--src/luarocks/type_check.lua57
-rw-r--r--src/luarocks/unpack.lua43
-rw-r--r--src/luarocks/upload.lua92
-rw-r--r--src/luarocks/upload/api.lua270
-rw-r--r--src/luarocks/upload/multipart.lua112
-rw-r--r--src/luarocks/util.lua117
-rw-r--r--src/luarocks/validate.lua26
-rw-r--r--src/luarocks/write_rockspec.lua340
-rw-r--r--test/testfiles/missing_external-0.1-1.rockspec24
-rwxr-xr-xtest/testing.sh353
-rw-r--r--win32/LuaRocks.reg.lua (renamed from win32/bin/create_reg_file.lua)0
-rw-r--r--win32/LuaRocks.reg.template (renamed from win32/bin/LuaRocks.reg.template)0
-rw-r--r--win32/bin/chmod.exebin81920 -> 0 bytes
-rw-r--r--win32/bin/objdump.exebin2247694 -> 0 bytes
-rwxr-xr-xwin32/bin/rm.exebin109056 -> 0 bytes
-rw-r--r--win32/lua.ico (renamed from win32/bin/lua.ico)bin22486 -> 22486 bytes
-rw-r--r--win32/luarocksw.bat (renamed from win32/bin/luarocksw.bat)4
-rw-r--r--win32/pe-parser.lua546
-rw-r--r--win32/rclauncher.c (renamed from win32/bin/rclauncher.c)0
-rw-r--r--win32/tools/7z.dll (renamed from win32/bin/7z.dll)bin858624 -> 858624 bytes
-rw-r--r--win32/tools/7z.exe (renamed from win32/bin/7z.exe)bin161792 -> 161792 bytes
-rw-r--r--[-rwxr-xr-x]win32/tools/cp.exe (renamed from win32/bin/cp.exe)bin130048 -> 130048 bytes
-rw-r--r--[-rwxr-xr-x]win32/tools/find.exe (renamed from win32/bin/find.exe)bin160256 -> 160256 bytes
-rw-r--r--win32/tools/libeay32.dll (renamed from win32/bin/libeay32.dll)bin1177600 -> 1177600 bytes
-rw-r--r--win32/tools/libiconv2.dll (renamed from win32/bin/libiconv2.dll)bin1008128 -> 1008128 bytes
-rw-r--r--win32/tools/libintl3.dll (renamed from win32/bin/libintl3.dll)bin103424 -> 103424 bytes
-rw-r--r--win32/tools/libssl32.dll (renamed from win32/bin/libssl32.dll)bin232960 -> 232960 bytes
-rw-r--r--[-rwxr-xr-x]win32/tools/ls.exe (renamed from win32/bin/ls.exe)bin180736 -> 180736 bytes
-rw-r--r--win32/tools/md5sum.exe (renamed from win32/bin/md5sum.exe)bin41984 -> 41984 bytes
-rw-r--r--[-rwxr-xr-x]win32/tools/mkdir.exe (renamed from win32/bin/mkdir.exe)bin32768 -> 32768 bytes
-rw-r--r--[-rwxr-xr-x]win32/tools/mv.exe (renamed from win32/bin/mv.exe)bin138752 -> 138752 bytes
-rw-r--r--[-rwxr-xr-x]win32/tools/pwd.exe (renamed from win32/bin/pwd.exe)bin61440 -> 61440 bytes
-rw-r--r--[-rwxr-xr-x]win32/tools/rmdir.exe (renamed from win32/bin/rmdir.exe)bin25088 -> 25088 bytes
-rw-r--r--[-rwxr-xr-x]win32/tools/test.exe (renamed from win32/bin/test.exe)bin62976 -> 62976 bytes
-rw-r--r--[-rwxr-xr-x]win32/tools/uname.exe (renamed from win32/bin/uname.exe)bin33792 -> 33792 bytes
-rw-r--r--win32/tools/wget.exe (renamed from win32/bin/wget.exe)bin449024 -> 449024 bytes
100 files changed, 4880 insertions, 1641 deletions
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..cf2b1e6
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,10 @@
+language: c
+
+compiler: gcc
+
+env:
+ matrix:
+ - LUA_VER=5.1.5
+ - LUA_VER=5.2.3
+
+script: cd test && ./testing.sh --travis --lua $LUA_VER
diff --git a/COPYING b/COPYING
index 4311883..34a3de3 100644
--- a/COPYING
+++ b/COPYING
@@ -1,31 +1,4 @@
-LuaRocks is free software: it can be used for both academic and commercial
-purposes at absolutely no cost. There are no royalties or GNU-like "copyleft"
-restrictions. LuaRocks qualifies as Open Source software. Its licenses are
-compatible with the GPL. LuaRocks is not in the public domain and the Kepler
-Project keeps its copyright. The legal details are below.
-
-The spirit of the license is that you are free to use LuaRocks for any purpose
-at no cost without having to ask us. The only requirement is that if you do
-use LuaRocks, then you should give us credit by including the appropriate
-copyright notice somewhere in your product or its documentation.
-
-7z.exe and 7z.dll are covered by another license, please see COPYING.7z for
-details.
-
-find.exe, mv.exe, rm.exe, wget.exe, ls.exe, pwd.exe, rmdir.exe, chmod.exe,
-md5sum.exe, test.exe, cp.exe, mkdir.exe, and uname.exe are part of UnxUtils,
-check http://unxutils.sourceforge.net/ for license information.
-
-Files under win32/lua5.1, except for Microsoft.VC80.CRT.manifest and msv*.*,
-are covered by another license, please see COPYING.lua for details.
-
-Microsoft.VC80.CRT.manifest, msvcm80.dll, msvcp80.dll, msvcr80.dll are part
-of the Microsoft Visual C++ 2005 SP1 Redistributable Package (x86) and
-are Copyright Microsoft, Inc. 2007.
-
-------------------------------------------------------------------------------
-
-Copyright 2007-2010 Kepler Project.
+Copyright 2007-2014 Kepler Project.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/COPYING_win b/COPYING_win
new file mode 100644
index 0000000..3413b8c
--- /dev/null
+++ b/COPYING_win
@@ -0,0 +1,16 @@
+
+This package includes additional Windows components which are under the
+following licenses:
+
+* For 7z.exe and 7z.dll, please see COPYING_7z for details.
+
+* find.exe, mv.exe, wget.exe, ls.exe, pwd.exe, rmdir.exe, md5sum.exe,
+ test.exe, cp.exe, mkdir.exe, and uname.exe are part of UnxUtils, check
+ http://unxutils.sourceforge.net/ for license information.
+
+* Files under win32/lua5.1, except for Microsoft.VC80.CRT.manifest and msv*.*,
+ are covered by another license, please see COPYING_lua for details.
+
+* Microsoft.VC80.CRT.manifest, msvcm80.dll, msvcp80.dll, msvcr80.dll are part
+ of the Microsoft Visual C++ 2005 SP1 Redistributable Package (x86) and are
+ Copyright Microsoft, Inc. 2007.
diff --git a/Makefile b/Makefile
index be83c01..1f9d0e2 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,10 @@
-# $Id: Makefile,v 1.30 2008/08/18 14:07:35 hisham Exp $
include config.unix
+.PHONY: all build dev build_bins luadoc check_makefile cleanup_bins clean \
+ install_bins install_luas install_site_config write_sysconfig \
+ install bootstrap install_rock
+
DESTDIR =
PREFIX ?= /usr/local
ROCKS_TREE ?= $(PREFIX)
@@ -16,14 +19,18 @@ LUAROCKS_FILES = fs/unix/tools.lua fs/unix.lua fs/win32/tools.lua fs/win32.lua \
fs/lua.lua persist.lua list.lua require.lua repos.lua dir.lua make_manifest.lua \
command_line.lua install.lua build/command.lua build/cmake.lua build/make.lua \
build/builtin.lua fetch/cvs.lua fetch/git.lua fetch/sscm.lua tools/patch.lua \
-fetch/svn.lua tools/zip.lua tools/tar.lua pack.lua type_check.lua make.lua path.lua \
+fetch/svn.lua tools/zip.lua tools/tar.lua pack.lua type_check.lua make.lua \
remove.lua fs.lua manif.lua add.lua deps.lua build.lua search.lua show.lua \
manif_core.lua fetch.lua unpack.lua validate.lua cfg.lua download.lua \
help.lua util.lua index.lua cache.lua refresh_cache.lua loader.lua \
-admin_remove.lua fetch/hg.lua fetch/git_file.lua new_version.lua lint.lua purge.lua
+admin_remove.lua fetch/hg.lua fetch/git_file.lua new_version.lua lint.lua \
+purge.lua path.lua path_cmd.lua write_rockspec.lua doc.lua upload.lua \
+upload/api.lua upload/multipart.lua fetch/git_http.lua
CONFIG_FILE = $(SYSCONFDIR)/config-$(LUA_VERSION).lua
+SAFEPWD=`echo "$$PWD" | sed -e 's/\([][]\)\1/]]..'\''\1\1'\''..[[/g'`
+
all:
@echo "- Type 'make build' and 'make install':"
@echo " to install to $(PREFIX) as usual."
@@ -31,55 +38,64 @@ all:
@echo " to install LuaRocks in $(PREFIX) as a rock."
@echo
-build: built
+build: src/luarocks/site_config.lua build_bins
+ @echo
+ @echo "Done. Type 'make install' to install into $(PREFIX)."
+ @echo
src/luarocks/site_config.lua: config.unix
rm -f src/luarocks/site_config.lua
- echo 'module("luarocks.site_config")' >> src/luarocks/site_config.lua
+ echo 'local site_config = {}' >> src/luarocks/site_config.lua
if [ -n "$(PREFIX)" ] ;\
then \
- echo "LUAROCKS_PREFIX=[[$(PREFIX)]]" >> src/luarocks/site_config.lua ;\
+ echo "site_config.LUAROCKS_PREFIX=[[$(PREFIX)]]" >> src/luarocks/site_config.lua ;\
fi
if [ -n "$(LUA_INCDIR)" ] ;\
then \
- echo "LUA_INCDIR=[[$(LUA_INCDIR)]]" >> src/luarocks/site_config.lua ;\
+ echo "site_config.LUA_INCDIR=[[$(LUA_INCDIR)]]" >> src/luarocks/site_config.lua ;\
fi
if [ -n "$(LUA_LIBDIR)" ] ;\
then \
- echo "LUA_LIBDIR=[[$(LUA_LIBDIR)]]" >> src/luarocks/site_config.lua ;\
+ echo "site_config.LUA_LIBDIR=[[$(LUA_LIBDIR)]]" >> src/luarocks/site_config.lua ;\
fi
if [ -n "$(LUA_BINDIR)" ] ;\
then \
- echo "LUA_BINDIR=[[$(LUA_BINDIR)]]" >> src/luarocks/site_config.lua ;\
+ echo "site_config.LUA_BINDIR=[[$(LUA_BINDIR)]]" >> src/luarocks/site_config.lua ;\
fi
if [ -n "$(LUA_SUFFIX)" ] ;\
then \
- echo "LUA_INTERPRETER=[[lua$(LUA_SUFFIX)]]" >> src/luarocks/site_config.lua ;\
+ echo "site_config.LUA_INTERPRETER=[[lua$(LUA_SUFFIX)]]" >> src/luarocks/site_config.lua ;\
fi
if [ -n "$(SYSCONFDIR)" ] ;\
then \
- echo "LUAROCKS_SYSCONFDIR=[[$(SYSCONFDIR)]]" >> src/luarocks/site_config.lua ;\
+ echo "site_config.LUAROCKS_SYSCONFDIR=[[$(SYSCONFDIR)]]" >> src/luarocks/site_config.lua ;\
fi
if [ -n "$(ROCKS_TREE)" ] ;\
then \
- echo "LUAROCKS_ROCKS_TREE=[[$(ROCKS_TREE)]]" >> src/luarocks/site_config.lua ;\
+ echo "site_config.LUAROCKS_ROCKS_TREE=[[$(ROCKS_TREE)]]" >> src/luarocks/site_config.lua ;\
fi
if [ -n "$(FORCE_CONFIG)" ] ;\
then \
- echo "LUAROCKS_FORCE_CONFIG=true" >> src/luarocks/site_config.lua ;\
+ echo "site_config.LUAROCKS_FORCE_CONFIG=true" >> src/luarocks/site_config.lua ;\
fi
if [ -n "$(LUAROCKS_ROCKS_SUBDIR)" ] ;\
then \
- echo "LUAROCKS_ROCKS_SUBDIR=[[$(LUAROCKS_ROCKS_SUBDIR)]]" >> src/luarocks/site_config.lua ;\
+ echo "site_config.LUAROCKS_ROCKS_SUBDIR=[[$(LUAROCKS_ROCKS_SUBDIR)]]" >> src/luarocks/site_config.lua ;\
fi
if [ "$(LUA_DIR_SET)" = "yes" ] ;\
then \
- echo "LUA_DIR_SET=true" >> src/luarocks/site_config.lua ;\
+ echo "site_config.LUA_DIR_SET=true" >> src/luarocks/site_config.lua ;\
fi
- echo "LUAROCKS_UNAME_S=[[$(LUAROCKS_UNAME_S)]]" >> src/luarocks/site_config.lua
- echo "LUAROCKS_UNAME_M=[[$(LUAROCKS_UNAME_M)]]" >> src/luarocks/site_config.lua
- echo "LUAROCKS_DOWNLOADER=[[$(LUAROCKS_DOWNLOADER)]]" >> src/luarocks/site_config.lua
- echo "LUAROCKS_MD5CHECKER=[[$(LUAROCKS_MD5CHECKER)]]" >> src/luarocks/site_config.lua
+ echo "site_config.LUAROCKS_UNAME_S=[[$(LUAROCKS_UNAME_S)]]" >> src/luarocks/site_config.lua
+ echo "site_config.LUAROCKS_UNAME_M=[[$(LUAROCKS_UNAME_M)]]" >> src/luarocks/site_config.lua
+ echo "site_config.LUAROCKS_DOWNLOADER=[[$(LUAROCKS_DOWNLOADER)]]" >> src/luarocks/site_config.lua
+ echo "site_config.LUAROCKS_MD5CHECKER=[[$(LUAROCKS_MD5CHECKER)]]" >> src/luarocks/site_config.lua
+ if [ -n "$(MULTIARCH_SUBDIR)" ] ;\
+ then \
+ echo 'site_config.LUAROCKS_EXTERNAL_DEPS_SUBDIRS={ bin="bin", lib={ "lib", [[$(MULTIARCH_SUBDIR)]] }, include="include" }' >> src/luarocks/site_config.lua ;\
+ echo 'site_config.LUAROCKS_RUNTIME_EXTERNAL_DEPS_SUBDIRS={ bin="bin", lib={ "lib", [[$(MULTIARCH_SUBDIR)]] }, include="include" }' >> src/luarocks/site_config.lua ;\
+ fi
+ echo "return site_config" >> src/luarocks/site_config.lua
dev:
$(MAKE) build_bins LUADIR=$(PWD)/src
@@ -89,18 +105,12 @@ build_bins: cleanup_bins
do \
sed "1d" src/bin/$$f > src/bin/$$f.bak ;\
echo "#!$(LUA_BINDIR)/lua$(LUA_SUFFIX)" > src/bin/$$f ;\
- echo "package.path = [[$(LUADIR)/?.lua;$(LUADIR)/?/init.lua;]]..package.path" >> src/bin/$$f ;\
+ echo "package.path = [[$(LUADIR)/?.lua;]]..package.path" | sed "s,//,/,g" >> src/bin/$$f ;\
cat src/bin/$$f.bak >> src/bin/$$f ;\
chmod +x src/bin/$$f ;\
rm -f src/bin/$$f.bak ;\
done
-built: src/luarocks/site_config.lua build_bins
- touch built
- @echo
- @echo "Done. Type 'make install' to install into $(PREFIX)."
- @echo
-
luadoc:
rm -rf doc/luadoc
mkdir -p doc/luadoc
@@ -128,17 +138,16 @@ cleanup_bins:
clean: cleanup_bins
rm -f src/luarocks/site_config.lua
- rm -f built
-install_bins: built
+install_bins:
mkdir -p "$(DESTDIR)$(BINDIR)"
cd src/bin && for f in $(BIN_FILES); \
do \
cp "$$f" "$(DESTDIR)$(BINDIR)/$$f-$(LUA_VERSION)"; \
- ln -nfs "$(DESTDIR)$(BINDIR)/$$f-$(LUA_VERSION)" "$(DESTDIR)$(BINDIR)/$$f"; \
+ ln -nfs "$$f-$(LUA_VERSION)" "$(DESTDIR)$(BINDIR)/$$f"; \
done
-install_luas: built
+install_luas:
mkdir -p "$(DESTDIR)$(LUADIR)/luarocks"
cd src/luarocks && for f in $(LUAROCKS_FILES); \
do \
@@ -147,11 +156,11 @@ install_luas: built
cp "$$f" "$$d" || exit 1; \
done
-install_site_config: built
+install_site_config: src/luarocks/site_config.lua
mkdir -p "$(DESTDIR)$(LUADIR)/luarocks"
- cd src/luarocks && cp site_config.lua "$(DESTDIR)$(LUADIR)/luarocks"
+ cp src/luarocks/site_config.lua "$(DESTDIR)$(LUADIR)/luarocks"
-write_sysconfig: built
+write_sysconfig:
mkdir -p "$(DESTDIR)$(ROCKS_TREE)"
if [ ! -f "$(DESTDIR)$(CONFIG_FILE)" ] ;\
then \
@@ -159,15 +168,15 @@ write_sysconfig: built
echo 'rocks_trees = {' >> "$(DESTDIR)$(CONFIG_FILE)" ;\
if [ ! -n "$(FORCE_CONFIG)" ] ;\
then \
- echo ' home..[[/.luarocks]],' >> "$(DESTDIR)$(CONFIG_FILE)" ;\
+ echo ' { name = [[user]], root = home..[[/.luarocks]] },' >> "$(DESTDIR)$(CONFIG_FILE)" ;\
fi ;\
- echo ' [[$(ROCKS_TREE)]]' >> "$(DESTDIR)$(CONFIG_FILE)" ;\
+ echo ' { name = [[system]], root = [[$(ROCKS_TREE)]] }' >> "$(DESTDIR)$(CONFIG_FILE)" ;\
echo '}' >> "$(DESTDIR)$(CONFIG_FILE)" ;\
fi
install: install_bins install_luas install_site_config write_sysconfig
-bootstrap: src/luarocks/site_config.lua install_site_config write_sysconfig
- LUA_PATH="$$PWD/src/?.lua;$$LUA_PATH" src/bin/luarocks make rockspec --tree="$(PREFIX)"
+bootstrap: src/luarocks/site_config.lua install_site_config write_sysconfig cleanup_bins
+ '$(LUA_BINDIR)/lua$(LUA_SUFFIX)' -e "package.path=[[$(SAFEPWD)/src/?.lua;]]..package.path" src/bin/luarocks make rockspec --tree="$(PREFIX)"
install_rock: install_bins install_luas
diff --git a/README.md b/README.md
index 87345a2..c779c3d 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,13 @@
-This is LuaRocks, a deployment and management system for Lua modules.
+LuaRocks
+========
+
+A package manager for Lua modules.
+
+[![Build Status](https://travis-ci.org/keplerproject/luarocks.png?branch=master)](https://travis-ci.org/keplerproject/luarocks)
Main website: [luarocks.org](http://www.luarocks.org)
-LuaRocks allows you to install Lua modules as self-contained packages called
+It allows you to install Lua modules as self-contained packages called
[*rocks*][1], which also contain version [dependency][2] information. This
information is used both during installation, so that when one rock is
requested all rocks it depends on are installed as well, and at run time, so
diff --git a/configure b/configure
index a5aa1f4..a7b8529 100755
--- a/configure
+++ b/configure
@@ -14,6 +14,7 @@ LUA_BINDIR="/usr/bin"
LUA_INCDIR="/usr/include"
LUA_LIBDIR="/usr/lib"
LUA_VERSION="5.1"
+MULTIARCH_SUBDIR=""
# ----------------------------------------------------------------------------
# FUNCTION DEFINITIONS
@@ -35,21 +36,24 @@ Where to install files installed by rocks, to make the accessible to Lua and
your \$PATH. Beware of clashes between files installed by LuaRocks and by your
system's package manager.
---rocks-tree=FILE Root of the local tree of installed rocks.
+--rocks-tree=DIR Root of the local tree of installed rocks.
Default is \$PREFIX
---lua-version=VERSION Use specific Lua version: 5.1 or 5.2
+--lua-version=VERSION Use specific Lua version: 5.1, 5.2, or 5.3
Default is "$LUA_VERSION"
--lua-suffix=SUFFIX Versioning suffix to use in Lua filenames.
Default is "$LUA_SUFFIX" (lua$LUA_SUFFIX...)
--with-lua=PREFIX Use Lua from given prefix.
- Default is $LUA_DIR
+ Default is auto-detected (the parent directory of \$LUA_BINDIR).
+--with-lua-bin=DIR You can also specify Lua's bin dir.
+ Default is the directory of the auto-detected Lua interpreter,
+ or \$LUA_DIR/bin if --with-lua is used.
--with-lua-include=DIR You can also specify Lua's includes dir.
Default is \$LUA_DIR/include
--with-lua-lib=DIR You can also specify Lua's libraries dir.
Default is \$LUA_DIR/lib
--with-downloader=TOOL Which tool to use as a downloader.
- Valid options are: wget, curl.
+ Valid options are: curl, wget.
Default is to auto-detect.
--with-md5-checker=TOOL Which tool to use as a downloader.
Valid options are: md5sum, openssl
@@ -176,7 +180,7 @@ do
--lua-version)
[ -n "$value" ] || die "Missing value in flag $key."
LUA_VERSION="$value"
- [ "$LUA_VERSION" = "5.1" -o "$LUA_VERSION" = "5.2" ] || die "Invalid Lua version in flag $key."
+ [ "$LUA_VERSION" = "5.1" -o "$LUA_VERSION" = "5.2" -o "$LUA_VERSION" = "5.3" ] || die "Invalid Lua version in flag $key."
LUA_VERSION_SET=yes
;;
--with-lua)
@@ -184,6 +188,11 @@ do
LUA_DIR="$value"
LUA_DIR_SET=yes
;;
+ --with-lua-bin)
+ [ -n "$value" ] || die "Missing value in flag $key."
+ LUA_BINDIR="$value"
+ LUA_BINDIR_SET=yes
+ ;;
--with-lua-include)
[ -n "$value" ] || die "Missing value in flag $key."
LUA_INCDIR="$value"
@@ -233,7 +242,7 @@ fi
detect_lua_version() {
detected_lua=`$1 -e 'print(_VERSION:sub(5))' 2> /dev/null`
- if [ "$detected_lua" = "5.1" -o "$detected_lua" = "5.2" ]
+ if [ "$detected_lua" = "5.1" -o "$detected_lua" = "5.2" -o "$detected_lua" = "5.3" ]
then
echo "Lua version detected: $detected_lua"
if [ "$LUA_VERSION_SET" != "yes" ]
@@ -248,7 +257,10 @@ detect_lua_version() {
search_interpreter() {
LUA_SUFFIX="$1"
- if [ "$LUA_DIR_SET" = "yes" ]
+ if [ "$LUA_BINDIR_SET" = "yes" ]
+ then
+ find_lua="$LUA_BINDIR"
+ elif [ "$LUA_DIR_SET" = "yes" ]
then
if [ -f "$LUA_DIR/bin/lua$suffix" ]
then
@@ -259,7 +271,7 @@ search_interpreter() {
fi
if [ -n "$find_lua" ]
then
- echo "Lua interpreter found: $find_lua/lua$suffix..."
+ echo "Lua interpreter: $find_lua/lua$suffix..."
detect_lua_version "$find_lua/lua$suffix"
return 0
fi
@@ -270,14 +282,17 @@ if [ "$LUA_SUFFIX_SET" != "yes" ]
then
if [ "$LUA_VERSION_SET" = "yes" -a "$LUA_VERSION" = "5.1" ]
then
- suffixes="5.1 51"
+ suffixes="5.1 51 -5.1 -51"
elif [ "$LUA_VERSION_SET" = "yes" -a "$LUA_VERSION" = "5.2" ]
then
- suffixes="5.2 52"
+ suffixes="5.2 52 -5.2 -52"
+ elif [ "$LUA_VERSION_SET" = "yes" -a "$LUA_VERSION" = "5.3" ]
+ then
+ suffixes="5.3 53 -5.3 -53"
else
- suffixes="5.2 52 5.1 51"
+ suffixes="5.3 53 -5.3 -53 5.2 52 -5.2 -52 5.1 51 -5.1 -51"
fi
- for suffix in "" `echo $suffixes` ""
+ for suffix in `echo $suffixes` ""
do
search_interpreter "$suffix" && break
done
@@ -285,9 +300,9 @@ fi
if [ "$LUA_DIR_SET" != "yes" ]
then
- echo_n "Looking for Lua... "
- if [ ! -n "$find_lua" ]
+ if [ -z "$find_lua" ]
then
+ echo_n "Looking for Lua... "
find_lua=`find_program lua$LUA_SUFFIX`
fi
@@ -312,7 +327,7 @@ then
LUA_LIBDIR="$LUA_DIR/lib"
fi
-if [ "$LUA_DIR_SET" = "yes" ]
+if [ "$LUA_DIR_SET" = "yes" -a "$LUA_BINDIR_SET" != "yes" ]
then
LUA_BINDIR="$LUA_DIR/bin"
fi
@@ -345,7 +360,7 @@ fi
if [ "$LUAROCKS_DOWNLOADER_SET" != "yes" ]
then
- find_helper "downloader helper program" wget curl fetch
+ find_helper "downloader helper program" curl wget fetch
LUAROCKS_DOWNLOADER=$HELPER
fi
@@ -370,12 +385,14 @@ else
die "Could not determine processor architecture. 'uname -m' failed."
fi
-if [ "$LUA_VERSION" = "5.2" ]
-then
- LUA_OTHER_VERSION=5.1
-else
- LUA_OTHER_VERSION=5.2
-fi
+for v in 5.1 5.2 5.3; do
+ if [ "$v" != "$LUA_VERSION" ]; then
+ if [ -e "$PREFIX/share/lua/$v/luarocks/site_config.lua" ]; then
+ LUA_OTHER_VERSION="$v"
+ break
+ fi
+ fi
+done
LUAROCKS_ROCKS_SUBDIR=/lib/luarocks/rocks
if [ "$VERSIONED_ROCKS_DIR" = "yes" ]
@@ -387,7 +404,7 @@ then
echo "Existing installation detected."
LUAROCKS_ROCKS_SUBDIR=`grep "LUAROCKS_ROCKS_SUBDIR" "$PREFIX/share/lua/$LUA_VERSION/luarocks/site_config.lua" | sed 's,.*=\[\[\(.*\)\]\],\1,'`
echo "Using previously configured rocks dir: $PREFIX$LUAROCKS_ROCKS_SUBDIR"
-elif [ -e "$PREFIX/share/lua/$LUA_OTHER_VERSION/luarocks/site_config.lua" ]
+elif [ -n "$LUA_OTHER_VERSION" ]
then
echo "Existing installation detected for other Lua version ($LUA_OTHER_VERSION)."
LUAROCKS_ROCKS_SUBDIR=$LUAROCKS_ROCKS_SUBDIR-$LUA_VERSION
@@ -396,6 +413,15 @@ else
echo "Using unversioned rocks dir: $PREFIX$LUAROCKS_ROCKS_SUBDIR"
fi
+if [ "$LUAROCKS_UNAME_S" = Linux ]
+then
+ GCC_ARCH=`gcc -print-multiarch 2>/dev/null`
+ if [ -n "$GCC_ARCH" -a -d "/usr/lib/$GCC_ARCH" ]
+ then
+ MULTIARCH_SUBDIR="lib/$GCC_ARCH"
+ fi
+fi
+
if [ -f config.unix ]; then
rm -f config.unix
fi
@@ -426,6 +452,7 @@ LUAROCKS_UNAME_S=$LUAROCKS_UNAME_S
LUAROCKS_DOWNLOADER=$LUAROCKS_DOWNLOADER
LUAROCKS_MD5CHECKER=$LUAROCKS_MD5CHECKER
LUAROCKS_ROCKS_SUBDIR=$LUAROCKS_ROCKS_SUBDIR
+MULTIARCH_SUBDIR=$MULTIARCH_SUBDIR
EOF
diff --git a/install.bat b/install.bat
index 15f2607..52d2135 100644
--- a/install.bat
+++ b/install.bat
@@ -1,14 +1,17 @@
rem=rem --[[
@setlocal& set luafile="%~f0" & if exist "%~f0.bat" set luafile="%~f0.bat"
-@lua5.1\bin\lua5.1.exe %luafile% %*& exit /b ]]
+@win32\lua5.1\bin\lua5.1.exe %luafile% %*& exit /b ]]
local vars = {}
-vars.PREFIX = [[C:\LuaRocks]]
-vars.VERSION = "2.1"
-vars.SYSCONFDIR = [[C:\LuaRocks]]
-vars.ROCKS_TREE = [[C:\LuaRocks]]
-vars.SCRIPTS_DIR = nil
+
+vars.PREFIX = nil
+vars.VERSION = "2.2"
+vars.SYSCONFDIR = nil
+vars.TREE_ROOT = nil
+vars.TREE_BIN = nil
+vars.TREE_LMODULE = nil
+vars.TREE_CMODULE = nil
vars.LUA_INTERPRETER = nil
vars.LUA_PREFIX = nil
vars.LUA_BINDIR = nil
@@ -16,20 +19,29 @@ vars.LUA_INCDIR = nil
vars.LUA_LIBDIR = nil
vars.LUA_LIBNAME = nil
vars.LUA_VERSION = "5.1"
-vars.LUA_SHORTV = nil
-vars.LUA_LIB_NAMES = "lua5.1.lib lua51.dll liblua.dll.a"
+vars.LUA_SHORTV = nil -- "51"
+-- MinGW does not generate .lib, nor needs it to link, but MSVC does
+-- so .lib must be listed first to ensure they are found first if present.
+-- To prevent MSVC trying to link to a .dll, which won't work.
+vars.LUA_LIB_NAMES = "lua5.1.lib lua51.lib lua5.1.dll lua51.dll liblua.dll.a"
vars.LUA_RUNTIME = nil
+vars.UNAME_M = nil
-local P_SET = false
local FORCE = false
local FORCE_CONFIG = false
local INSTALL_LUA = false
local USE_MINGW = false
-local REGISTRY = false
+local REGISTRY = true
+local NOADMIN = false
+local PROMPT = true
+local SELFCONTAINED = false
---
-- Some helpers
--
+
+local pe = assert(loadfile(".\\win32\\pe-parser.lua"))()
+
local function die(message)
if message then print(message) end
print()
@@ -37,19 +49,64 @@ local function die(message)
os.exit(1)
end
+function split_string(str, delim, maxNb)
+ -- Eliminate bad cases...
+ if string.find(str, delim) == nil then
+ return { str }
+ end
+ if maxNb == nil or maxNb < 1 then
+ maxNb = 0 -- No limit
+ end
+ local result = {}
+ local pat = "(.-)" .. delim .. "()"
+ local nb = 0
+ local lastPos
+ for part, pos in string.gmatch(str, pat) do
+ nb = nb + 1
+ result[nb] = part
+ lastPos = pos
+ if nb == maxNb then break end
+ end
+ -- Handle the last field
+ if nb ~= maxNb then
+ result[nb + 1] = string.sub(str, lastPos)
+ end
+ return result
+end
+
+
local function exec(cmd)
--print(cmd)
local status = os.execute(cmd)
- return status == 0
+ return (status == 0 or status == true) -- compat 5.1/5.2
end
local function exists(filename)
- local cmd = [[.\bin\test -e "]]..filename..[["]]
+ local cmd = [[.\win32\tools\test -e "]]..filename..[["]]
return exec(cmd)
end
local function mkdir (dir)
- return exec([[.\bin\mkdir -p "]]..dir..[[" >NUL]])
+ return exec([[.\win32\tools\mkdir -p "]]..dir..[[" >NUL]])
+end
+
+-- does the current user have admin priviledges ( = elevated)
+local function permission()
+ return exec("net session >NUL 2>&1") -- fails if not admin
+end
+
+-- rename file (full path) to backup (name only), appending number if required
+-- returns the new name (name only)
+local function backup(filename, backupname)
+ local path = filename:match("(.+)%\\.-$").."\\"
+ local nname = backupname
+ local i = 0
+ while exists(path..nname) do
+ i = i + 1
+ nname = backupname..tostring(i)
+ end
+ exec([[REN "]]..filename..[[" "]]..nname..[[" > NUL]])
+ return nname
end
-- interpolate string with values from 'vars' table
@@ -61,44 +118,69 @@ local function print_help()
print(S[[
Installs LuaRocks.
-/P [dir] (REQUIRED) Where to install.
- Note that version; $VERSION, will be
- appended to this path.
-/CONFIG [dir] Location where the config file should be installed.
- Default is same place of installation
-/TREE [dir] Root of the local tree of installed rocks.
- Default is same place of installation
-/SCRIPTS [dir] Where to install scripts installed by rocks.
- Default is TREE/bin.
+/P [dir] Where to install LuaRocks.
+ Note that version; $VERSION, will be appended to this
+ path, so "/P c:\luarocks\" will install in
+ "c:\luarocks\$VERSION\"
+ Default is %PROGRAMFILES%\LuaRocks
-/LV [version] Lua version to use; either 5.1 or 5.2.
+Configuring the destinations:
+/TREE [dir] Root of the local tree of installed rocks.
+ Default is %PROGRAMFILES%\LuaRocks\systree
+/SCRIPTS [dir] Where to install commandline scripts installed by
+ rocks. Default is {TREE}\bin.
+/LUAMOD [dir] Where to install Lua modules installed by rocks.
+ Default is {TREE}\share\lua\{LV}.
+/CMOD [dir] Where to install c modules installed by rocks.
+ Default is {TREE}\lib\lua\{LV}.
+/CONFIG [dir] Location where the config file should be installed.
+ Default is to follow /P option
+/SELFCONTAINED Creates a self contained installation in a single
+ directory given by /P.
+ Sets the /TREE and /CONFIG options to the same
+ location as /P. And does not load registry info
+ with option /NOREG. The only option NOT self
+ contained is the user rock tree, so don't use that
+ if you create a self contained installation.
+
+Configuring the Lua interpreter:
+/LV [version] Lua version to use; either 5.1, 5.2, or 5.3.
Default is 5.1
-/L Install LuaRocks' own copy of Lua even if detected,
- this will always be a 5.1 installation.
- (/LUA, /INC, /LIB, /BIN cannot be used with /L)
/LUA [dir] Location where Lua is installed - e.g. c:\lua\5.1\
+ If not provided, the installer will search the system
+ path and some default locations for a valid Lua
+ installation.
This is the base directory, the installer will look
for subdirectories bin, lib, include. Alternatively
these can be specified explicitly using the /INC,
/LIB, and /BIN options.
/INC [dir] Location of Lua includes - e.g. c:\lua\5.1\include
If provided overrides sub directory found using /LUA.
-/LIB [dir] Location of Lua libraries -e.g. c:\lua\5.1\lib
+/LIB [dir] Location of Lua libraries (.dll/.lib) - e.g. c:\lua\5.1\lib
If provided overrides sub directory found using /LUA.
/BIN [dir] Location of Lua executables - e.g. c:\lua\5.1\bin
If provided overrides sub directory found using /LUA.
+/L Install LuaRocks' own copy of Lua even if detected,
+ this will always be a 5.1 installation.
+ (/LUA, /INC, /LIB, /BIN cannot be used with /L)
+Compiler configuration:
/MW Use mingw as build system instead of MSVC
+Other options:
/FORCECONFIG Use a single config location. Do not use the
LUAROCKS_CONFIG variable or the user's home directory.
Useful to avoid conflicts when LuaRocks
is embedded within an application.
-
/F Remove installation directory if it already exists.
-
-/R Load registry information to register '.rockspec'
+/NOREG Do not load registry info to register '.rockspec'
extension with LuaRocks commands (right-click).
+/NOADMIN The installer requires admin priviledges. If not
+ available it will elevate a new process. Use this
+ switch to prevent elevation, but make sure the
+ destination paths are all accessible for the current
+ user.
+/Q Do not prompt for confirmation of settings
]])
end
@@ -114,15 +196,16 @@ local function parse_options(args)
os.exit(0)
elseif name == "/P" then
vars.PREFIX = option.value
- vars.SYSCONFDIR = option.value
- vars.ROCKS_TREE = option.value
- P_SET = true
elseif name == "/CONFIG" then
vars.SYSCONFDIR = option.value
elseif name == "/TREE" then
- vars.ROCKS_TREE = option.value
+ vars.TREE_ROOT = option.value
elseif name == "/SCRIPTS" then
- vars.SCRIPTS_DIR = option.value
+ vars.TREE_BIN = option.value
+ elseif name == "/LUAMOD" then
+ vars.TREE_LMODULE = option.value
+ elseif name == "/CMOD" then
+ vars.TREE_CMODULE = option.value
elseif name == "/LV" then
vars.LUA_VERSION = option.value
elseif name == "/L" then
@@ -141,8 +224,14 @@ local function parse_options(args)
FORCE_CONFIG = true
elseif name == "/F" then
FORCE = true
- elseif name == "/R" then
- REGISTRY = true
+ elseif name == "/SELFCONTAINED" then
+ SELFCONTAINED = true
+ elseif name == "/NOREG" then
+ REGISTRY = false
+ elseif name == "/NOADMIN" then
+ NOADMIN = true
+ elseif name == "/Q" then
+ PROMPT = false
else
die("Unrecognized option: " .. name)
end
@@ -151,8 +240,13 @@ end
-- check for combination/required flags
local function check_flags()
- if not P_SET then
- die("Missing required parameter /P")
+ if SELFCONTAINED then
+ if not vars.PREFIX then
+ die("Option /P is required when using /SELFCONTAINED")
+ end
+ if vars.SYSCONFDIR or vars.TREE_ROOT or vars.TREE_BIN or vars.TREE_LMODULE or vars.TREE_CMODULE then
+ die("Cannot combine /TREE, /SCRIPTS, /LUAMOD, /CMOD, or /CONFIG with /SELFCONTAINED")
+ end
end
if INSTALL_LUA then
if vars.LUA_INCDIR or vars.LUA_BINDIR or vars.LUA_LIBDIR or vars.LUA_PREFIX then
@@ -165,8 +259,10 @@ local function check_flags()
if vars.LUA_VERSION ~= "5.1" then
if vars.LUA_VERSION == "5.2" then
vars.LUA_LIB_NAMES = vars.LUA_LIB_NAMES:gsub("5([%.]?)1", "5%12")
+ elseif vars.LUA_VERSION == "5.3" then
+ vars.LUA_LIB_NAMES = vars.LUA_LIB_NAMES:gsub("5([%.]?)1", "5%13")
else
- die("Bad argument: /LV must either be 5.1 or 5.2")
+ die("Bad argument: /LV must either be 5.1, 5.2, or 5.3")
end
end
end
@@ -176,10 +272,15 @@ end
-- ***********************************************************
local function look_for_interpreter (directory)
if vars.LUA_BINDIR then
+ -- if LUA_BINDIR is specified, it must be there, otherwise we fail
if exists( S"$LUA_BINDIR\\lua$LUA_VERSION.exe" ) then
vars.LUA_INTERPRETER = S"lua$LUA_VERSION.exe"
print(S" Found $LUA_BINDIR\\$LUA_INTERPRETER")
return true
+ elseif exists( S"$LUA_BINDIR\\lua$LUA_SHORTV.exe" ) then
+ vars.LUA_INTERPRETER = S"lua$LUA_SHORTV.exe"
+ print(S" Found $LUA_BINDIR\\$LUA_INTERPRETER")
+ return true
elseif exists(S"$LUA_BINDIR\\lua.exe") then
vars.LUA_INTERPRETER = "lua.exe"
print(S" Found $LUA_BINDIR\\$LUA_INTERPRETER")
@@ -189,7 +290,7 @@ local function look_for_interpreter (directory)
print(S" Found $LUA_BINDIR\\$LUA_INTERPRETER")
return true
end
- die(S"Lua executable lua.exe, luajit.exe or lua$LUA_VERSION.exe not found in $LUA_BINDIR")
+ die(S"Lua executable lua.exe, luajit.exe, lua$LUA_SHORTV.exe or lua$LUA_VERSION.exe not found in $LUA_BINDIR")
end
for _, e in ipairs{ [[\]], [[\bin\]] } do
@@ -199,6 +300,12 @@ local function look_for_interpreter (directory)
print(" Found ."..e..vars.LUA_INTERPRETER)
return true
+ elseif exists(directory..e.."\\lua"..vars.LUA_SHORTV..".exe") then
+ vars.LUA_INTERPRETER = S"lua$LUA_SHORTV.exe"
+ vars.LUA_BINDIR = directory .. e
+ print(" Found ."..e..vars.LUA_INTERPRETER)
+ return true
+
elseif exists(directory..e.."\\lua.exe") then
vars.LUA_INTERPRETER = "lua.exe"
vars.LUA_BINDIR = directory..e
@@ -264,76 +371,62 @@ local function look_for_headers (directory)
return false
end
--- Checks a binary file for the runtime dll used by it. If nu runtime is found, it returns an
--- array of dll's is depends upon.
--- result: string = runtime used, table = list of dll's depended upon, nil = nothing found.
-local function get_file_runtime(p,f) -- path, filename
- local infile = p.."\\"..f
- local outfile = "output.txt"
- local content
- -- analyze binary
- if exec([[.\bin\objdump -x "]]..infile..[[" > ]]..outfile..[[ 2<&1]]) then
- -- read temp file
- local fh = io.open(outfile)
- content = fh:read("*a")
- fh:close()
- end
- -- delete temp file
- os.remove(outfile)
- if not content then
- print(" Failed to analyze "..infile.." for the runtime used")
- return nil
- end
-
- -- lookup
- content = content:upper()
- local result = content:match('DLL NAME%: (MSVCR%d*)%.DLL')
- if not result then
- result = content:match('DLL NAME%: (MSVCRT)%.DLL')
- end
-
- if result then
- print(" "..f.." uses "..tostring(result)..".DLL as runtime")
- else
- print(" No runtime found for "..f)
- -- so; create a list of dll's this file is depending upon, next level of the tree
- result = {}
- for name in content:gmatch("DLL NAME%: (.-%.DLL)") do
- --print("found dll:", name)
- table.insert(result, name)
- end
- end
- return result
-end
local function get_runtime()
- -- first check interpreter
- vars.LUA_RUNTIME = get_file_runtime(vars.LUA_BINDIR, vars.LUA_INTERPRETER)
- if type(vars.LUA_RUNTIME) == "table" then
- -- a table with dll's depended upon was returned, check this list
- -- note: we only check 1 level deep
- for _,dll in ipairs(vars.LUA_RUNTIME) do
- local t = get_file_runtime(vars.LUA_BINDIR, dll)
- if type(t) == "string" then
- -- found it
- vars.LUA_RUNTIME = t
- break
- end
- end
- end
+ local f
+ vars.LUA_RUNTIME, f = pe.msvcrt(vars.LUA_BINDIR.."\\"..vars.LUA_INTERPRETER)
if type(vars.LUA_RUNTIME) ~= "string" then
-- analysis failed, issue a warning
vars.LUA_RUNTIME = "MSVCR80"
print("*** WARNING ***: could not analyse the runtime used, defaulting to "..vars.LUA_RUNTIME)
+ else
+ print(" "..f.." uses "..vars.LUA_RUNTIME..".DLL as runtime")
end
return true
end
+local function get_architecture()
+ -- detect processor arch interpreter was compiled for
+ local proc = (pe.parse(vars.LUA_BINDIR.."\\"..vars.LUA_INTERPRETER) or {}).Machine
+ if not proc then
+ die("Could not detect processor architecture used in "..vars.LUA_INTERPRETER)
+ end
+ proc = pe.const.Machine[proc] -- collect name from constant value
+ if proc == "IMAGE_FILE_MACHINE_I386" then
+ proc = "x86"
+ else
+ proc = "x86_64"
+ end
+ return proc
+end
+
local function look_for_lua_install ()
print("Looking for Lua interpreter")
- local directories = { [[c:\lua5.1.2]], [[c:\lua]], [[c:\kepler\1.1]] }
+ local directories
if vars.LUA_PREFIX then
- table.insert(directories, 1, vars.LUA_PREFIX)
+ directories = { vars.LUA_PREFIX }
+ else
+ -- no prefix given, so use path
+ directories = (os.getenv("PATH",";") or "")
+ local i = 1
+ while i ~= 0 do directories, i = directories:gsub(";;",";") end --remove all doubles
+ directories = split_string(directories,";")
+ -- if a path element ends with "\bin\" then remove it, as the searcher will check there anyway
+ for i, val in ipairs(directories) do
+ -- remove trailing backslash
+ while val:sub(-1,-1) == "\\" and val:sub(-2,-1) ~= ":\\" do
+ val = val:sub(1,-2)
+ end
+ -- remove trailing 'bin'
+ if val:upper():sub(-4,-1) == "\\BIN" or val:upper():sub(-4,-1) == ":BIN" then
+ val = val:sub(1,-5)
+ end
+ directories[i] = val
+ end
+ -- finaly add some other default paths
+ table.insert(directories, [[c:\lua5.1.2]])
+ table.insert(directories, [[c:\lua]])
+ table.insert(directories, [[c:\kepler\1.1]])
end
if vars.LUA_BINDIR and vars.LUA_LIBDIR and vars.LUA_INCDIR then
if look_for_interpreter(vars.LUA_BINDIR) and
@@ -342,7 +435,7 @@ local function look_for_lua_install ()
then
if get_runtime() then
print("Runtime check completed, now testing interpreter...")
- if exec(S[[$LUA_BINDIR\$LUA_INTERPRETER -v 2>NUL]]) then
+ if exec(S[["$LUA_BINDIR\$LUA_INTERPRETER" -v 2>NUL]]) then
print(" Ok")
return true
end
@@ -363,7 +456,7 @@ local function look_for_lua_install ()
print("Headers found, checking runtime to use...")
if get_runtime() then
print("Runtime check completed, now testing interpreter...")
- if exec(S[[$LUA_BINDIR\$LUA_INTERPRETER -v 2>NUL]]) then
+ if exec(S[["$LUA_BINDIR\$LUA_INTERPRETER" -v 2>NUL]]) then
print(" Ok")
return true
end
@@ -377,7 +470,11 @@ local function look_for_lua_install ()
return false
end
----
+
+-- ***********************************************************
+-- Installer script start
+-- ***********************************************************
+
-- Poor man's command-line parsing
local config = {}
local with_arg = { -- options followed by an argument, others are flags
@@ -385,16 +482,46 @@ local with_arg = { -- options followed by an argument, others are flags
["/CONFIG"] = true,
["/TREE"] = true,
["/SCRIPTS"] = true,
+ ["/LUAMOD"] = true,
+ ["/CMOD"] = true,
["/LV"] = true,
["/LUA"] = true,
["/INC"] = true,
["/BIN"] = true,
["/LIB"] = true,
}
+-- reconstruct argument values with spaces and double quotes
+-- this will be damaged by the batch construction at the start of this file
+local oarg = arg -- retain old table
+if #arg > 0 then
+ farg = table.concat(arg, " ") .. " "
+ arg = {}
+ farg = farg:gsub('%"', "")
+ local i = 0
+ while #farg>0 do
+ i = i + 1
+ if (farg:sub(1,1) ~= "/") and ((arg[i-1] or ""):sub(1,1) ~= "/") then
+ i = i - 1 -- continued previous arg
+ if i == 0 then i = 1 end
+ end
+ if arg[i] then
+ arg[i] = arg[i] .. " "
+ else
+ arg[i] = ""
+ end
+ local v,r = farg:match("^(.-)%s(.*)$")
+ arg[i], farg = arg[i]..v, r
+ while farg:sub(1,1) == " " do farg = farg:sub(2,-1) end -- remove prefix spaces
+ end
+end
+for k,v in pairs(oarg) do if k < 1 then arg[k] = v end end -- copy 0 and negative indexes
+oarg = nil
+
+-- build config option table with name and value elements
local i = 1
while i <= #arg do
local opt = arg[i]
- if with_arg[opt] then
+ if with_arg[opt:upper()] then
local value = arg[i + 1]
if not value then
die("Missing value for option "..opt)
@@ -410,8 +537,46 @@ end
print(S"LuaRocks $VERSION.x installer.\n")
parse_options(config)
+
+print([[
+
+========================
+== Checking system... ==
+========================
+
+]])
+
check_flags()
+if not permission() then
+ if not NOADMIN then
+ -- must elevate the process with admin priviledges
+ if not exec("PowerShell /? >NUL 2>&1") then
+ -- powershell is not available, so error out
+ die("No administrative priviledges detected and cannot auto-elevate. Please run with admin priviledges or use the /NOADMIN switch")
+ end
+ print("Need admin priviledges, now elevating a new process to continue installing...")
+ local runner = os.getenv("TEMP").."\\".."LuaRocks_Installer.bat"
+ local f = io.open(runner, "w")
+ f:write("@echo off\n")
+ f:write("CHDIR /D "..arg[0]:match("(.+)%\\.-$").."\n") -- return to current dir, elevation changes current path
+ f:write('"'..arg[-1]..'" "'..table.concat(arg, '" "', 0)..'"\n')
+ f:write("ECHO Press any key to close this window...\n")
+ f:write("PAUSE > NUL\n")
+ f:write('DEL "'..runner..'"') -- temp batch file deletes itself
+ f:close()
+ -- run the created temp batch file in elevated mode
+ exec("PowerShell -Command (New-Object -com 'Shell.Application').ShellExecute('"..runner.."', '', '', 'runas')\n")
+ print("Now exiting unpriviledged installer")
+ os.exit() -- exit here, the newly created elevated process will do the installing
+ else
+ print("Attempting to install without admin priviledges...")
+ end
+else
+ print("Admin priviledges available for installing")
+end
+
+vars.PREFIX = vars.PREFIX or os.getenv("PROGRAMFILES")..[[\LuaRocks]]
vars.FULL_PREFIX = S"$PREFIX\\$VERSION"
vars.BINDIR = vars.FULL_PREFIX
vars.LIBDIR = vars.FULL_PREFIX
@@ -419,33 +584,72 @@ vars.LUADIR = S"$FULL_PREFIX\\lua"
vars.INCDIR = S"$FULL_PREFIX\\include"
vars.LUA_SHORTV = vars.LUA_VERSION:gsub("%.", "")
-if not look_for_lua_install() then
- print("Could not find Lua. Will install its own copy.")
- print("See /? for options for specifying the location of Lua.")
+if INSTALL_LUA then
if vars.LUA_VERSION ~= "5.1" then
- die("Cannot install own copy because no 5.2 version is bundled")
+ die("Cannot install own copy of Lua because only 5.1 is bundled")
end
- INSTALL_LUA = true
vars.LUA_INTERPRETER = "lua5.1"
vars.LUA_BINDIR = vars.BINDIR
vars.LUA_LIBDIR = vars.LIBDIR
vars.LUA_INCDIR = vars.INCDIR
vars.LUA_LIBNAME = "lua5.1.lib"
- vars.LUA_RUNTIME = "MSVCR80"
+ vars.LUA_RUNTIME = "MSVCR80"
+ vars.UNAME_M = "x86"
else
- print(S[[
+ if not look_for_lua_install() then
+ die("Could not find Lua. See /? for options for specifying the location of Lua, or installing a bundled copy of Lua 5.1.")
+ end
+ vars.UNAME_M = get_architecture() -- can only do when installation was found
+end
+
+local datapath
+if vars.UNAME_M == "x86" then
+ datapath = os.getenv("PROGRAMFILES") .. [[\LuaRocks]]
+else
+ -- our target interpreter is 64bit, so the tree (with binaries) should go into 64bit program files
+ datapath = os.getenv("ProgramW6432") .. [[\LuaRocks]]
+end
+vars.SYSCONFDIR = vars.SYSCONFDIR or vars.PREFIX
+vars.TREE_ROOT = vars.TREE_ROOT or datapath..[[\systree]]
+if SELFCONTAINED then
+ vars.SYSCONFDIR = vars.PREFIX
+ vars.TREE_ROOT = vars.PREFIX..[[\systree]]
+ REGISTRY = false
+end
+
+print(S[[
+
+==========================
+== System check results ==
+==========================
Will configure LuaRocks with the following paths:
-LuaRocks : $FULL_PREFIX
-Lua interpreter: $LUA_BINDIR\$LUA_INTERPRETER
-Lua binaries : $LUA_BINDIR
-Lua libraries : $LUA_LIBDIR
-Lua includes : $LUA_INCDIR
-Binaries will be linked against: $LUA_LIBNAME with runtime $LUA_RUNTIME
+LuaRocks : $FULL_PREFIX
+Config file : $SYSCONFDIR\config.lua
+Rocktree : $TREE_ROOT
+
+Lua interpreter : $LUA_BINDIR\$LUA_INTERPRETER
+ binaries : $LUA_BINDIR
+ libraries : $LUA_LIBDIR
+ includes : $LUA_INCDIR
+ architecture: $UNAME_M
+ binary link : $LUA_LIBNAME with runtime $LUA_RUNTIME.dll
]])
+
+if PROMPT then
+ print("Press <ENTER> to start installing, or press <CTRL>+<C> to abort. Use install /? for installation options.")
+ io.read()
end
+print([[
+
+============================
+== Installing LuaRocks... ==
+============================
+
+]])
+
-- ***********************************************************
-- Install LuaRocks files
-- ***********************************************************
@@ -474,13 +678,22 @@ if INSTALL_LUA then
if not exists(vars.LUA_INCDIR) then
mkdir(vars.LUA_INCDIR)
end
- exec(S[[COPY lua5.1\bin\*.* "$LUA_BINDIR" >NUL]])
- exec(S[[COPY lua5.1\include\*.* "$LUA_INCDIR" >NUL]])
+ exec(S[[COPY win32\lua5.1\bin\*.* "$LUA_BINDIR" >NUL]])
+ exec(S[[COPY win32\lua5.1\include\*.* "$LUA_INCDIR" >NUL]])
print(S"Installed the LuaRocks bundled Lua interpreter in $LUA_BINDIR")
end
-- Copy the LuaRocks binaries
-if not exec(S[[COPY bin\*.* "$BINDIR" >NUL]]) then
+if not exists(S[[$BINDIR\tools]]) then
+ if not mkdir(S[[$BINDIR\tools]]) then
+ die()
+ end
+end
+if not exec(S[[COPY win32\tools\*.* "$BINDIR\tools" >NUL]]) then
+ die()
+end
+-- Copy LR bin helper files
+if not exec(S[[COPY win32\*.* "$BINDIR" >NUL]]) then
die()
end
-- Copy the LuaRocks lua source files
@@ -507,61 +720,104 @@ for _, c in ipairs{"luarocks", "luarocks-admin"} do
f:write(S[[
@ECHO OFF
SETLOCAL
-SET LUA_PATH=$LUADIR\?.lua;$LUADIR\?\init.lua;%LUA_PATH%
-SET PATH=$BINDIR\;%PATH%
-"$LUA_INTERPRETER" "$BINDIR\]]..c..[[.lua" %*
+SET "LUA_PATH=$LUADIR\?.lua;$LUADIR\?\init.lua;%LUA_PATH%"
+IF NOT "%LUA_PATH_5_2%"=="" (
+ SET "LUA_PATH_5_2=$LUADIR\?.lua;$LUADIR\?\init.lua;%LUA_PATH_5_2%"
+)
+IF NOT "%LUA_PATH_5_3%"=="" (
+ SET "LUA_PATH_5_3=$LUADIR\?.lua;$LUADIR\?\init.lua;%LUA_PATH_5_3%"
+)
+SET "PATH=$BINDIR;%PATH%"
+"$LUA_BINDIR\$LUA_INTERPRETER" "$BINDIR\]]..c..[[.lua" %*
+IF NOT "%ERRORLEVEL%"=="2" GOTO EXITLR
+
+REM Permission denied error, try and auto elevate...
+REM already an admin? (checking to prevent loops)
+NET SESSION >NUL 2>&1
+IF "%ERRORLEVEL%"=="0" GOTO EXITLR
+
+REM Do we have PowerShell available?
+PowerShell /? >NUL 2>&1
+IF NOT "%ERRORLEVEL%"=="0" GOTO EXITLR
+
+:GETTEMPNAME
+SET TMPFILE=%TEMP%\LuaRocks-Elevator-%RANDOM%.bat
+IF EXIST "%TMPFILE%" GOTO :GETTEMPNAME
+
+ECHO @ECHO OFF > "%TMPFILE%"
+ECHO CHDIR /D %CD% >> "%TMPFILE%"
+ECHO ECHO %0 %* >> "%TMPFILE%"
+ECHO ECHO. >> "%TMPFILE%"
+ECHO CALL %0 %* >> "%TMPFILE%"
+ECHO ECHO. >> "%TMPFILE%"
+ECHO ECHO Press any key to close this window... >> "%TMPFILE%"
+ECHO PAUSE ^> NUL >> "%TMPFILE%"
+ECHO DEL "%TMPFILE%" >> "%TMPFILE%"
+
+ECHO Now retrying as a priviledged user...
+PowerShell -Command (New-Object -com 'Shell.Application').ShellExecute('%TMPFILE%', '', '', 'runas')
+
+:EXITLR
ENDLOCAL
]])
f:close()
print(S"Created LuaRocks command: $BINDIR\\"..c..".bat")
end
+
+-- part below was commented out as its purpose was unclear
+-- see https://github.com/keplerproject/luarocks/pull/197#issuecomment-30176548
+
-- configure 'scripts' directory
-if vars.SCRIPTS_DIR then
- mkdir(vars.SCRIPTS_DIR)
- if not USE_MINGW then
- -- definitly not for MinGW because of conflicting runtimes
- -- but is it ok to do it for others???
- exec(S[[COPY lua5.1\bin\*.dll "$SCRIPTS_DIR" >NUL]])
- end
-else
- if not USE_MINGW then
- mkdir(S[[$ROCKS_TREE\bin]])
- -- definitly not for MinGW because of conflicting runtimes
- -- but is it ok to do it for others???
- exec(S[[COPY lua5.1\bin\*.dll "$ROCKS_TREE"\bin >NUL]])
- end
-end
+-- if vars.TREE_BIN then
+-- mkdir(vars.TREE_BIN)
+-- if not USE_MINGW then
+-- -- definitly not for MinGW because of conflicting runtimes
+-- -- but is it ok to do it for others???
+-- exec(S[[COPY lua5.1\bin\*.dll "$TREE_BIN" >NUL]])
+-- end
+-- else
+-- if not USE_MINGW then
+-- mkdir(S[[$TREE_ROOT\bin]])
+-- -- definitly not for MinGW because of conflicting runtimes
+-- -- but is it ok to do it for others???
+-- exec(S[[COPY lua5.1\bin\*.dll "$TREE_ROOT"\bin >NUL]])
+-- end
+-- end
+-- ***********************************************************
+-- Configure LuaRocks
+-- ***********************************************************
print()
print("Configuring LuaRocks...")
+
-- Create a site-config file
if exists(S[[$LUADIR\luarocks\site_config.lua]]) then
exec(S[[RENAME "$LUADIR\luarocks\site_config.lua" site_config.lua.bak]])
end
local f = io.open(vars.LUADIR.."\\luarocks\\site_config.lua", "w")
f:write(S[=[
-module("luarocks.site_config")
-LUA_INCDIR=[[$LUA_INCDIR]]
-LUA_LIBDIR=[[$LUA_LIBDIR]]
-LUA_BINDIR=[[$LUA_BINDIR]]
-LUA_INTERPRETER=[[$LUA_INTERPRETER]]
+local site_config = {}
+site_config.LUA_INCDIR=[[$LUA_INCDIR]]
+site_config.LUA_LIBDIR=[[$LUA_LIBDIR]]
+site_config.LUA_BINDIR=[[$LUA_BINDIR]]
+site_config.LUA_INTERPRETER=[[$LUA_INTERPRETER]]
]=])
if USE_MINGW then
- f:write("LUAROCKS_UNAME_S=[[MINGW]]\n")
+ f:write("site_config.LUAROCKS_UNAME_S=[[MINGW]]\n")
else
- f:write("LUAROCKS_UNAME_S=[[WindowsNT]]\n")
+ f:write("site_config.LUAROCKS_UNAME_S=[[WindowsNT]]\n")
end
f:write(S[=[
-LUAROCKS_UNAME_M=[[x86]]
-LUAROCKS_SYSCONFIG=[[$SYSCONFDIR\config.lua]]
-LUAROCKS_ROCKS_TREE=[[$ROCKS_TREE]]
-LUAROCKS_PREFIX=[[$PREFIX]]
-LUAROCKS_DOWNLOADER=[[wget]]
-LUAROCKS_MD5CHECKER=[[md5sum]]
+site_config.LUAROCKS_UNAME_M=[[$UNAME_M]]
+site_config.LUAROCKS_SYSCONFIG=[[$SYSCONFDIR\config.lua]]
+site_config.LUAROCKS_ROCKS_TREE=[[$TREE_ROOT]]
+site_config.LUAROCKS_PREFIX=[[$PREFIX]]
+site_config.LUAROCKS_DOWNLOADER=[[wget]]
+site_config.LUAROCKS_MD5CHECKER=[[md5sum]]
]=])
if FORCE_CONFIG then
- f:write("local LUAROCKS_FORCE_CONFIG=true\n")
+ f:write("site_config.LUAROCKS_FORCE_CONFIG=true\n")
end
if exists(vars.LUADIR.."\\luarocks\\site_config.lua.bak") then
for line in io.lines(vars.LUADIR.."\\luarocks\\site_config.lua.bak", "r") do
@@ -570,6 +826,7 @@ if exists(vars.LUADIR.."\\luarocks\\site_config.lua.bak") then
end
exec(S[[DEL /F /Q "$LUADIR\luarocks\site_config.lua.bak"]])
end
+f:write("return site_config\n")
f:close()
print(S[[Created LuaRocks site-config file: $LUADIR\luarocks\site_config.lua]])
@@ -578,50 +835,65 @@ vars.CONFIG_FILE = vars.SYSCONFDIR.."\\config.lua"
if not exists(vars.SYSCONFDIR) then
mkdir(vars.SYSCONFDIR)
end
-if not exists(vars.CONFIG_FILE) then
- local f = io.open(vars.CONFIG_FILE, "w")
- f:write([=[
-rocks_servers = {
- [[http://luarocks.org/repositories/rocks]]
-}
+if exists(vars.CONFIG_FILE) then
+ local nname = backup(vars.CONFIG_FILE, "config.bak")
+ print("***************")
+ print(S"*** WARNING *** LuaRocks config file already exists: '$CONFIG_FILE'. The old file has been renamed to '"..nname.."'")
+ print("***************")
+end
+local f = io.open(vars.CONFIG_FILE, "w")
+f:write([=[
rocks_trees = {
]=])
- if FORCE_CONFIG then
- f:write(" home..[[/luarocks]],\n")
- end
- f:write(S" [[$ROCKS_TREE]]\n")
- f:write("}\n")
- if vars.SCRIPTS_DIR then
- f:write(S"scripts_dir=[[$SCRIPTS_DIR]]\n")
- end
- f:write("variables = {\n")
- if USE_MINGW and vars.LUA_RUNTIME == "MSVCRT" then
- f:write(" MSVCRT = 'm', -- make MinGW use MSVCRT.DLL as runtime\n")
- else
- f:write(" MSVCRT = '"..vars.LUA_RUNTIME.."',\n")
- end
- f:write(S" LUALIB = '$LUA_LIBNAME'\n")
- f:write("}\n")
- f:close()
- print(S"Created LuaRocks config file: $CONFIG_FILE")
+if FORCE_CONFIG then
+ f:write(" home..[[/luarocks]],\n")
+end
+f:write(S" { name = [[user]],\n")
+f:write(S" root = home..[[/luarocks]],\n")
+f:write(S" },\n")
+f:write(S" { name = [[system]],\n")
+f:write(S" root = [[$TREE_ROOT]],\n")
+if vars.TREE_BIN then
+ f:write(S" bin_dir = [[$TREE_BIN]],\n")
+end
+if vars.TREE_CMODULE then
+ f:write(S" lib_dir = [[$TREE_CMODULE]],\n")
+end
+if vars.TREE_LMODULE then
+ f:write(S" lua_dir = [[$TREE_LMODULE]],\n")
+end
+f:write(S" },\n")
+f:write("}\n")
+f:write("variables = {\n")
+if USE_MINGW and vars.LUA_RUNTIME == "MSVCRT" then
+ f:write(" MSVCRT = 'm', -- make MinGW use MSVCRT.DLL as runtime\n")
else
- print(S"LuaRocks config file already exists: $CONFIG_FILE")
+ f:write(" MSVCRT = '"..vars.LUA_RUNTIME.."',\n")
end
+f:write(S" LUALIB = '$LUA_LIBNAME'\n")
+f:write("}\n")
+f:write("verbose = false -- set to 'true' to enable verbose output\n")
+f:close()
+
+print(S"Created LuaRocks config file: $CONFIG_FILE")
+
print()
print("Creating rocktrees...")
-if not exists(vars.ROCKS_TREE) then
- mkdir(vars.ROCKS_TREE)
- print(S[[Created rocktree: "$ROCKS_TREE"]])
+if not exists(vars.TREE_ROOT) then
+ mkdir(vars.TREE_ROOT)
+ print(S[[Created system rocktree : "$TREE_ROOT"]])
else
- print(S[[Rocktree exists: "$ROCKS_TREE"]])
+ print(S[[System rocktree exists : "$TREE_ROOT"]])
end
-local APPDATA = os.getenv("APPDATA")
-if not exists(APPDATA.."\\luarocks") then
- mkdir(APPDATA.."\\luarocks")
- print([[Created rocktree: "]]..APPDATA..[[\luarocks"]])
+
+vars.APPDATA = os.getenv("APPDATA")
+vars.LOCAL_TREE = vars.APPDATA..[[\LuaRocks]]
+if not exists(vars.LOCAL_TREE) then
+ mkdir(vars.LOCAL_TREE)
+ print(S[[Created local user rocktree: "$LOCAL_TREE"]])
else
- print([[Rocktree exists: "]]..APPDATA..[[\luarocks"]])
+ print(S[[Local user rocktree exists : "$LOCAL_TREE"]])
end
-- Load registry information
@@ -629,21 +901,49 @@ if REGISTRY then
-- expand template with correct path information
print()
print([[Loading registry information for ".rockspec" files]])
- exec( S[[lua5.1\bin\lua5.1.exe "$FULL_PREFIX\create_reg_file.lua" "$FULL_PREFIX\LuaRocks.reg.template"]] )
- exec( S"$FULL_PREFIX\\LuaRocks.reg" )
+ exec( S[[win32\lua5.1\bin\lua5.1.exe "$FULL_PREFIX\LuaRocks.reg.lua" "$FULL_PREFIX\LuaRocks.reg.template"]] )
+ exec( S[[regedit /S "$FULL_PREFIX\\LuaRocks.reg"]] )
end
-- ***********************************************************
--- Exit handlers
+-- Cleanup
-- ***********************************************************
+-- remove regsitry related files, no longer needed
+exec( S[[del "$FULL_PREFIX\LuaRocks.reg.*" >NUL]] )
+-- remove pe-parser module
+exec( S[[del "$FULL_PREFIX\pe-parser.lua" >NUL]] )
+-- ***********************************************************
+-- Exit handlers
+-- ***********************************************************
+vars.TREE_BIN = vars.TREE_BIN or vars.TREE_ROOT..[[\bin]]
+vars.TREE_LMODULE = vars.TREE_LMODULE or vars.TREE_ROOT..[[\share\lua\]]..vars.LUA_VERSION
+vars.TREE_CMODULE = vars.TREE_CMODULE or vars.TREE_ROOT..[[\lib\lua\]]..vars.LUA_VERSION
print(S[[
-*** LuaRocks is installed! ***
- You may want to add the following elements to your paths;
-PATH : $LUA_BINDIR;$FULL_PREFIX
-LUA_PATH : $ROCKS_TREE\share\lua\$LUA_VERSION\?.lua;$ROCKS_TREE\share\lua\$LUA_VERSION\?\init.lua
-LUA_CPATH: $LUA_LIBDIR\lua\$LUA_VERSION\?.dll
+============================
+== LuaRocks is installed! ==
+============================
+
+
+You may want to add the following elements to your paths;
+Lua interpreter;
+ PATH : $LUA_BINDIR
+ PATHEXT : .LUA
+LuaRocks;
+ PATH : $FULL_PREFIX
+ LUA_PATH : $FULL_PREFIX\lua\?.lua;$FULL_PREFIX\lua\?\init.lua
+Local user rocktree (Note: %APPDATA% is user dependent);
+ PATH : %APPDATA%\LuaRocks\bin
+ LUA_PATH : %APPDATA%\LuaRocks\share\lua\$LUA_VERSION\?.lua;%APPDATA%\LuaRocks\share\lua\$LUA_VERSION\?\init.lua
+ LUA_CPATH: %APPDATA%\LuaRocks\lib\lua\$LUA_VERSION\?.dll
+System rocktree
+ PATH : $TREE_BIN
+ LUA_PATH : $TREE_LMODULE\?.lua;$TREE_LMODULE\?\init.lua
+ LUA_CPATH: $TREE_CMODULE\?.dll
+
+Note that the %APPDATA% element in the paths above is user specific and it MUST be replaced by its actual value.
+For the current user that value is: $APPDATA.
]])
os.exit(0)
diff --git a/makedist b/makedist
index 9b3308e..141f670 100755
--- a/makedist
+++ b/makedist
@@ -61,15 +61,14 @@ mkdir "release-windows"
mv "$out" "release-windows/$out-win32"
cd "release-unix/$out"
-rm -rf makedist install.bat COPYING.lua COPYING.7z win32 lfw
+rm -rf makedist install.bat COPYING_lua COPYING_7z COPYING_win win32 lfw .travis.yml .gitignore
cd ..
tar czvpf ../"$out.tar.gz" "$out"
cd ..
rm -rf "release-unix"
cd "release-windows/$out-win32"
-cp -va win32/* .
-rm -rf makedist Makefile configure lfw win32
+rm -rf makedist Makefile configure lfw .travis.yml .gitignore
cd ..
zip -r ../"$out-win32.zip" "$out-win32"
cd ..
diff --git a/rockspec b/rockspec
index 69f253b..16ac635 100644
--- a/rockspec
+++ b/rockspec
@@ -1,5 +1,5 @@
package = "LuaRocks"
-local VER = "2.1.0"
+local VER = "2.2.0beta1"
local REV = "1"
version = VER.."-"..REV
diff --git a/src/bin/luarocks b/src/bin/luarocks
index b64051d..d2f3c22 100755
--- a/src/bin/luarocks
+++ b/src/bin/luarocks
@@ -1,24 +1,32 @@
#!/usr/bin/env lua
+-- this should be loaded first.
+local cfg = require("luarocks.cfg")
+
+local loader = require("luarocks.loader")
local command_line = require("luarocks.command_line")
program_description = "LuaRocks main command-line interface"
-commands = {}
-commands.help = require("luarocks.help")
-commands.pack = require("luarocks.pack")
-commands.unpack = require("luarocks.unpack")
-commands.build = require("luarocks.build")
-commands.install = require("luarocks.install")
-commands.search = require("luarocks.search")
-commands.list = require("luarocks.list")
-commands.remove = require("luarocks.remove")
-commands.make = require("luarocks.make")
-commands.download = require("luarocks.download")
-commands.path = require("luarocks.path")
-commands.show = require("luarocks.show")
-commands.new_version = require("luarocks.new_version")
-commands.lint = require("luarocks.lint")
-commands.purge = require("luarocks.purge")
+commands = {
+ help = "luarocks.help",
+ pack = "luarocks.pack",
+ unpack = "luarocks.unpack",
+ build = "luarocks.build",
+ install = "luarocks.install",
+ search = "luarocks.search",
+ list = "luarocks.list",
+ remove = "luarocks.remove",
+ make = "luarocks.make",
+ download = "luarocks.download",
+ path = "luarocks.path_cmd",
+ show = "luarocks.show",
+ new_version = "luarocks.new_version",
+ lint = "luarocks.lint",
+ write_rockspec = "luarocks.write_rockspec",
+ purge = "luarocks.purge",
+ doc = "luarocks.doc",
+ upload = "luarocks.upload",
+}
command_line.run_command(...)
diff --git a/src/bin/luarocks-admin b/src/bin/luarocks-admin
index 4c5613c..2890d1f 100755
--- a/src/bin/luarocks-admin
+++ b/src/bin/luarocks-admin
@@ -1,16 +1,19 @@
#!/usr/bin/env lua
+-- this should be loaded first.
+local cfg = require("luarocks.cfg")
+
+local loader = require("luarocks.loader")
local command_line = require("luarocks.command_line")
program_description = "LuaRocks repository administration interface"
commands = {
+ help = "luarocks.help",
+ make_manifest = "luarocks.make_manifest",
+ add = "luarocks.add",
+ remove = "luarocks.admin_remove",
+ refresh_cache = "luarocks.refresh_cache",
}
-commands.help = require("luarocks.help")
-commands.make_manifest = require("luarocks.make_manifest")
-commands.add = require("luarocks.add")
-commands.remove = require("luarocks.admin_remove")
-commands.refresh_cache = require("luarocks.refresh_cache")
-
command_line.run_command(...)
diff --git a/src/luarocks/add.lua b/src/luarocks/add.lua
index d7c293e..fc913c9 100644
--- a/src/luarocks/add.lua
+++ b/src/luarocks/add.lua
@@ -1,20 +1,21 @@
--- Module implementing the luarocks-admin "add" command.
-- Adds a rock or rockspec to a rocks server.
-module("luarocks.add", package.seeall)
+--module("luarocks.add", package.seeall)
+local add = {}
+package.loaded["luarocks.add"] = add
local cfg = require("luarocks.cfg")
local util = require("luarocks.util")
-local fetch = require("luarocks.fetch")
local dir = require("luarocks.dir")
local manif = require("luarocks.manif")
local index = require("luarocks.index")
local fs = require("luarocks.fs")
local cache = require("luarocks.cache")
-help_summary = "Add a rock or rockspec to a rocks server."
-help_arguments = "[--server=<server>] [--no-refresh] {<rockspec>|<rock>...}"
-help = [[
+add.help_summary = "Add a rock or rockspec to a rocks server."
+add.help_arguments = "[--server=<server>] [--no-refresh] {<rockspec>|<rock>...}"
+add.help = [[
Arguments are local files, which may be rockspecs or rocks.
The flag --server indicates which server to use.
If not given, the default server set in the upload_server variable
@@ -45,7 +46,8 @@ local function add_files_to_server(refresh, rockfiles, server, upload_server)
login_url = protocol.."://"..server_path
end
- fs.change_dir(at)
+ local ok, err = fs.change_dir(at)
+ if not ok then return nil, err end
local files = {}
for i, rockfile in ipairs(rockfiles) do
@@ -62,10 +64,14 @@ local function add_files_to_server(refresh, rockfiles, server, upload_server)
return nil, "No files found"
end
- fs.change_dir(local_cache)
+ local ok, err = fs.change_dir(local_cache)
+ if not ok then return nil, err end
util.printout("Updating manifest...")
manif.make_manifest(local_cache, "one", true)
+
+ manif.zip_manifests()
+
util.printout("Updating index.html...")
index.make_index(local_cache)
@@ -78,15 +84,17 @@ local function add_files_to_server(refresh, rockfiles, server, upload_server)
table.insert(files, "index.html")
table.insert(files, "manifest")
- table.insert(files, "manifest-5.1")
- table.insert(files, "manifest-5.2")
+ for ver in util.lua_versions() do
+ table.insert(files, "manifest-"..ver)
+ table.insert(files, "manifest-"..ver..".zip")
+ end
-- TODO abstract away explicit 'curl' call
local cmd
if protocol == "rsync" then
local srv, path = server_path:match("([^/]+)(/.+)")
- cmd = cfg.variables.RSYNC.." --exclude=.git -Oavz -e ssh "..local_cache.."/ "..user.."@"..srv..":"..path.."/"
+ cmd = cfg.variables.RSYNC.." "..cfg.variables.RSYNCFLAGS.." -e ssh "..local_cache.."/ "..user.."@"..srv..":"..path.."/"
elseif upload_server and upload_server.sftp then
local part1, part2 = upload_server.sftp:match("^([^/]*)/(.*)$")
cmd = cfg.variables.SCP.." "..table.concat(files, " ").." "..user.."@"..part1..":/"..part2
@@ -100,7 +108,7 @@ local function add_files_to_server(refresh, rockfiles, server, upload_server)
return true
end
-function run(...)
+function add.run(...)
local files = { util.parse_flags(...) }
local flags = table.remove(files, 1)
if #files < 1 then
@@ -111,3 +119,5 @@ function run(...)
return add_files_to_server(not flags["no-refresh"], files, server, server_table)
end
+
+return add
diff --git a/src/luarocks/admin_remove.lua b/src/luarocks/admin_remove.lua
index 83b57fc..839121d 100644
--- a/src/luarocks/admin_remove.lua
+++ b/src/luarocks/admin_remove.lua
@@ -1,22 +1,23 @@
--- Module implementing the luarocks-admin "remove" command.
-- Removes a rock or rockspec from a rocks server.
-module("luarocks.admin_remove", package.seeall)
+--module("luarocks.admin_remove", package.seeall)
+local admin_remove = {}
+package.loaded["luarocks.admin_remove"] = admin_remove
local cfg = require("luarocks.cfg")
local util = require("luarocks.util")
-local fetch = require("luarocks.fetch")
local dir = require("luarocks.dir")
local manif = require("luarocks.manif")
local index = require("luarocks.index")
local fs = require("luarocks.fs")
local cache = require("luarocks.cache")
-help_summary = "Remove a rock or rockspec from a rocks server."
-help_arguments = "[--from=<server>] [--no-refresh] {<rockspec>|<rock>...}"
-help = [[
+admin_remove.help_summary = "Remove a rock or rockspec from a rocks server."
+admin_remove.help_arguments = "[--server=<server>] [--no-refresh] {<rockspec>|<rock>...}"
+admin_remove.help = [[
Arguments are local files, which may be rockspecs or rocks.
-The flag --from indicates which server to use.
+The flag --server indicates which server to use.
If not given, the default server set in the upload_server variable
from the configuration file is used instead.
The flag --no-refresh indicates the local cache should not be refreshed
@@ -41,14 +42,16 @@ local function remove_files_from_server(refresh, rockfiles, server, upload_serve
return nil, "This command requires 'rsync', check your configuration."
end
- fs.change_dir(at)
+ local ok, err = fs.change_dir(at)
+ if not ok then return nil, err end
local nr_files = 0
for i, rockfile in ipairs(rockfiles) do
local basename = dir.base_name(rockfile)
local file = dir.path(local_cache, basename)
util.printout("Removing file "..file.."...")
- if fs.delete(file) then
+ fs.delete(file)
+ if not fs.exists(file) then
nr_files = nr_files + 1
else
util.printerr("Failed removing "..file)
@@ -58,7 +61,8 @@ local function remove_files_from_server(refresh, rockfiles, server, upload_serve
return nil, "No files removed."
end
- fs.change_dir(local_cache)
+ local ok, err = fs.change_dir(local_cache)
+ if not ok then return nil, err end
util.printout("Updating manifest...")
manif.make_manifest(local_cache, "one", true)
@@ -66,7 +70,7 @@ local function remove_files_from_server(refresh, rockfiles, server, upload_serve
index.make_index(local_cache)
local srv, path = server_path:match("([^/]+)(/.+)")
- local cmd = "rsync -Oavz --delete -e ssh "..local_cache.."/ "..user.."@"..srv..":"..path.."/"
+ local cmd = cfg.variables.RSYNC.." "..cfg.variables.RSYNCFLAGS.." --delete -e ssh "..local_cache.."/ "..user.."@"..srv..":"..path.."/"
util.printout(cmd)
fs.execute(cmd)
@@ -74,7 +78,7 @@ local function remove_files_from_server(refresh, rockfiles, server, upload_serve
return true
end
-function run(...)
+function admin_remove.run(...)
local files = { util.parse_flags(...) }
local flags = table.remove(files, 1)
if #files < 1 then
@@ -85,3 +89,5 @@ function run(...)
return remove_files_from_server(not flags["no-refresh"], files, server, server_table)
end
+
+return admin_remove
diff --git a/src/luarocks/build.lua b/src/luarocks/build.lua
index dbe450a..01bfa9d 100644
--- a/src/luarocks/build.lua
+++ b/src/luarocks/build.lua
@@ -1,7 +1,9 @@
--- Module implementing the LuaRocks "build" command.
-- Builds a rock, compiling its C parts if any.
-module("luarocks.build", package.seeall)
+--module("luarocks.build", package.seeall)
+local build = {}
+package.loaded["luarocks.build"] = build
local pack = require("luarocks.pack")
local path = require("luarocks.path")
@@ -12,13 +14,12 @@ local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local deps = require("luarocks.deps")
local manif = require("luarocks.manif")
-local search = require("luarocks.search")
local remove = require("luarocks.remove")
local cfg = require("luarocks.cfg")
-help_summary = "Build/compile a rock."
-help_arguments = "[--pack-binary-rock] [--keep] {<rockspec>|<rock>|<name> [<version>]}"
-help = [[
+build.help_summary = "Build/compile a rock."
+build.help_arguments = "[--pack-binary-rock] [--keep] {<rockspec>|<rock>|<name> [<version>]}"
+build.help = [[
Build and install a rock, compiling its C parts if any.
Argument may be a rockspec file, a source rock file
or the name of a rock to be fetched from a repository.
@@ -31,7 +32,12 @@ or the name of a rock to be fetched from a repository.
rock after building a new one. This behavior can
be made permanent by setting keep_other_versions=true
in the configuration file.
-]]
+
+--branch=<name> Override the `source.branch` field in the loaded
+ rockspec. Allows to specify a different branch to
+ fetch. Particularly for SCM rocks.
+
+]]..util.deps_mode_help()
--- Install files to a given location.
-- Takes a table where the array part is a list of filenames to be copied.
@@ -53,19 +59,31 @@ local function install_files(files, location, is_module_path)
if files then
for k, file in pairs(files) do
local dest = location
+ local filename = dir.base_name(file)
if type(k) == "string" then
+ local modname = k
if is_module_path then
- dest = dir.path(location, path.module_to_path(k))
- fs.make_dir(dest)
+ dest = dir.path(location, path.module_to_path(modname))
+ local ok, err = fs.make_dir(dest)
+ if not ok then return nil, err end
+ if filename:match("%.lua$") then
+ local basename = modname:match("([^.]+)$")
+ local baseinfo = filename:gsub("%.lua$", "")
+ if basename ~= baseinfo then
+ filename = basename..".lua"
+ end
+ end
else
- dest = dir.path(location, dir.dir_name(k))
- fs.make_dir(dest)
- dest = dir.path(dest, dir.base_name(k))
+ dest = dir.path(location, dir.dir_name(modname))
+ local ok, err = fs.make_dir(dest)
+ if not ok then return nil, err end
+ filename = dir.base_name(modname)
end
else
- fs.make_dir(dest)
+ local ok, err = fs.make_dir(dest)
+ if not ok then return nil, err end
end
- local ok = fs.copy(dir.path(file), dest)
+ local ok = fs.copy(dir.path(file), dir.path(dest, filename))
if not ok then
return nil, "Failed copying "..file
end
@@ -91,16 +109,16 @@ end
-- @param rockspec table: A rockspec table.
-- @return boolean or (nil, string): True if succeeded or
-- nil and an error message.
-function apply_patches(rockspec)
+function build.apply_patches(rockspec)
assert(type(rockspec) == "table")
- local build = rockspec.build
- if build.extra_files then
- extract_from_rockspec(build.extra_files)
+ local build_spec = rockspec.build
+ if build_spec.extra_files then
+ extract_from_rockspec(build_spec.extra_files)
end
- if build.patches then
- extract_from_rockspec(build.patches)
- for patch, patchdata in util.sortedpairs(build.patches) do
+ if build_spec.patches then
+ extract_from_rockspec(build_spec.patches)
+ for patch, patchdata in util.sortedpairs(build_spec.patches) do
util.printout("Applying patch "..patch.."...")
local ok, err = fs.apply_patch(tostring(patch), patchdata)
if not ok then
@@ -111,6 +129,24 @@ function apply_patches(rockspec)
return true
end
+local function install_default_docs(name, version)
+ local patterns = { "readme", "license", "copying" }
+ local dest = dir.path(path.install_dir(name, version), "doc")
+ local has_dir = false
+ for name in fs.dir() do
+ for _, pattern in ipairs(patterns) do
+ if name:lower():match("^"..pattern) then
+ if not has_dir then
+ fs.make_dir(dest)
+ has_dir = true
+ end
+ fs.copy(name, dest)
+ break
+ end
+ end
+ end
+end
+
--- Build and install a rock given a rockspec.
-- @param rockspec_file string: local or remote filename of a rockspec.
-- @param need_to_fetch boolean: true if sources need to be fetched,
@@ -123,7 +159,7 @@ end
-- "none" for no trees.
-- @return (string, string) or (nil, string, [string]): Name and version of
-- installed rock if succeeded or nil and an error message followed by an error code.
-function build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_mode)
+function build.build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_mode)
assert(type(rockspec_file) == "string")
assert(type(need_to_fetch) == "boolean")
@@ -145,7 +181,7 @@ function build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_mode)
end
end
- ok, err, errcode = deps.check_external_deps(rockspec, "build")
+ local ok, err, errcode = deps.check_external_deps(rockspec, "build")
if err then
return nil, err, errcode
end
@@ -162,7 +198,8 @@ function build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_mode)
if not ok then
return nil, source_dir, errcode
end
- fs.change_dir(source_dir)
+ local ok, err = fs.change_dir(source_dir)
+ if not ok then return nil, err end
elseif rockspec.source.file then
local ok, err = fs.unpack_archive(rockspec.source.file)
if not ok then
@@ -180,38 +217,39 @@ function build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_mode)
}
for _, d in pairs(dirs) do
- fs.make_dir(d.name)
+ local ok, err = fs.make_dir(d.name)
+ if not ok then return nil, err end
end
local rollback = util.schedule_function(function()
fs.delete(path.install_dir(name, version))
fs.remove_dir_if_empty(path.versions_dir(name))
end)
- local build = rockspec.build
+ local build_spec = rockspec.build
if not minimal_mode then
- ok, err = apply_patches(rockspec)
+ ok, err = build.apply_patches(rockspec)
if err then
return nil, err
end
end
- if build.type ~= "none" then
+ if build_spec.type ~= "none" then
-- Temporary compatibility
- if build.type == "module" then
+ if build_spec.type == "module" then
util.printout("Do not use 'module' as a build type. Use 'builtin' instead.")
- build.type = "builtin"
+ build_spec.type = "builtin"
end
- if cfg.accepted_build_types and util.array_contains(cfg.accepted_build_types, build.type) then
- return nil, "This rockspec uses the '"..build.type.."' build type, which is blocked by the 'accepted_build_types' setting in your LuaRocks configuration."
+ if cfg.accepted_build_types and util.array_contains(cfg.accepted_build_types, build_spec.type) then
+ return nil, "This rockspec uses the '"..build_spec.type.."' build type, which is blocked by the 'accepted_build_types' setting in your LuaRocks configuration."
end
local build_type
- ok, build_type = pcall(require, "luarocks.build." .. build.type)
+ ok, build_type = pcall(require, "luarocks.build." .. build_spec.type)
if not ok or not type(build_type) == "table" then
- return nil, "Failed initializing build back-end for build type '"..build.type.."': "..build_type
+ return nil, "Failed initializing build back-end for build type '"..build_spec.type.."': "..build_type
end
ok, err = build_type.run(rockspec)
@@ -220,27 +258,40 @@ function build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_mode)
end
end
- if build.install then
+ if build_spec.install then
for id, install_dir in pairs(dirs) do
- ok, err = install_files(build.install[id], install_dir.name, install_dir.is_module_path)
+ ok, err = install_files(build_spec.install[id], install_dir.name, install_dir.is_module_path)
if not ok then
return nil, err
end
end
end
- local copy_directories = build.copy_directories or {"doc"}
+ local copy_directories = build_spec.copy_directories
+ local copying_default = false
+ if not copy_directories then
+ copy_directories = {"doc"}
+ copying_default = true
+ end
+ local any_docs = false
for _, copy_dir in pairs(copy_directories) do
if fs.is_dir(copy_dir) then
local dest = dir.path(path.install_dir(name, version), copy_dir)
fs.make_dir(dest)
fs.copy_contents(copy_dir, dest)
+ any_docs = true
else
- util.warning("Directory '"..copy_dir.."' not found")
+ if not copying_default then
+ return nil, "Directory '"..copy_dir.."' not found"
+ end
end
end
-
+
+ if not any_docs then
+ install_default_docs(name, version)
+ end
+
for _, d in pairs(dirs) do
fs.remove_dir_if_empty(d.name)
end
@@ -275,8 +326,8 @@ function build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_mode)
end
local root_dir = path.root_dir(cfg.rocks_dir)
- util.printout()
util.printout(name.." "..version.." is now built and installed in "..root_dir.." "..license)
+ util.printout()
util.remove_scheduled_function(rollback)
return name, version
@@ -291,7 +342,7 @@ end
-- "order" for all trees with priority >= the current default, "none" for no trees.
-- @return boolean or (nil, string, [string]): True if build was successful,
-- or false and an error message and an optional error code.
-function build_rock(rock_file, need_to_fetch, deps_mode)
+function build.build_rock(rock_file, need_to_fetch, deps_mode)
assert(type(rock_file) == "string")
assert(type(need_to_fetch) == "boolean")
@@ -300,25 +351,26 @@ function build_rock(rock_file, need_to_fetch, deps_mode)
return nil, err, errcode
end
local rockspec_file = path.rockspec_name_from_rock(rock_file)
- fs.change_dir(unpack_dir)
- local ok, err, errcode = build_rockspec(rockspec_file, need_to_fetch, false, deps_mode)
+ local ok, err = fs.change_dir(unpack_dir)
+ if not ok then return nil, err end
+ local ok, err, errcode = build.build_rockspec(rockspec_file, need_to_fetch, false, deps_mode)
fs.pop_dir()
return ok, err, errcode
end
local function do_build(name, version, deps_mode)
if name:match("%.rockspec$") then
- return build_rockspec(name, true, false, deps_mode)
+ return build.build_rockspec(name, true, false, deps_mode)
elseif name:match("%.src%.rock$") then
- return build_rock(name, false, deps_mode)
+ return build.build_rock(name, false, deps_mode)
elseif name:match("%.all%.rock$") then
local install = require("luarocks.install")
return install.install_binary_rock(name, deps_mode)
elseif name:match("%.rock$") then
- return build_rock(name, true, deps_mode)
+ return build.build_rock(name, true, deps_mode)
elseif not name:match(dir.separator) then
local search = require("luarocks.search")
- return search.act_on_src_or_rockspec(run, name:lower(), version, deps.deps_mode_to_flag(deps_mode))
+ return search.act_on_src_or_rockspec(build.run, name:lower(), version, deps.deps_mode_to_flag(deps_mode))
end
return nil, "Don't know what to do with "..name
end
@@ -329,9 +381,9 @@ end
-- if returned a result, installs the matching rock.
-- @param version string: When passing a package name, a version number may
-- also be given.
--- @return boolean or (nil, string): True if build was successful; nil and an
--- error message otherwise.
-function run(...)
+-- @return boolean or (nil, string, exitcode): True if build was successful; nil and an
+-- error message otherwise. exitcode is optionally returned.
+function build.run(...)
local flags, name, version = util.parse_flags(...)
if type(name) ~= "string" then
return nil, "Argument missing. "..util.see_help("build")
@@ -342,7 +394,7 @@ function run(...)
return pack.pack_binary_rock(name, version, do_build, name, version, deps.get_deps_mode(flags))
else
local ok, err = fs.check_command_permissions(flags)
- if not ok then return nil, err end
+ if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end
ok, err = do_build(name, version, deps.get_deps_mode(flags))
if not ok then return nil, err end
local name, version = ok, err
@@ -353,3 +405,5 @@ function run(...)
return name, version
end
end
+
+return build
diff --git a/src/luarocks/build/builtin.lua b/src/luarocks/build/builtin.lua
index 9d97d58..47aa71f 100644
--- a/src/luarocks/build/builtin.lua
+++ b/src/luarocks/build/builtin.lua
@@ -1,6 +1,9 @@
--- A builtin build system: back-end to provide a portable way of building C-based Lua modules.
-module("luarocks.build.builtin", package.seeall)
+--module("luarocks.build.builtin", package.seeall)
+local builtin = {}
+
+local unpack = unpack or table.unpack
local fs = require("luarocks.fs")
local path = require("luarocks.path")
@@ -19,6 +22,7 @@ end
--- Makes an RC file with an embedded Lua script, for building .exes on Windows
-- @return nil if could open files, error otherwise
local function make_rc(luafilename, rcfilename)
+ --TODO EXEWRAPPER
local rcfile = io.open(rcfilename, "w")
if not rcfile then
error("Could not open "..rcfilename.." for writing.")
@@ -44,9 +48,9 @@ end
-- @param rockspec table: the loaded rockspec.
-- @return boolean or (nil, string): true if no errors ocurred,
-- nil and an error message otherwise.
-function run(rockspec)
+function builtin.run(rockspec)
assert(type(rockspec) == "table")
- local compile_object, compile_library, compile_wrapper_binary
+ local compile_object, compile_library, compile_wrapper_binary --TODO EXEWRAPPER
local build = rockspec.build
local variables = rockspec.variables
@@ -80,6 +84,7 @@ function run(rockspec)
return ok
end
compile_wrapper_binary = function(fullname, name)
+ --TODO EXEWRAPPER
local fullbasename = fullname:gsub("%.lua$", ""):gsub("/", "\\")
local basename = name:gsub("%.lua$", ""):gsub("/", "\\")
local rcname = basename..".rc"
@@ -112,13 +117,20 @@ function run(rockspec)
def:write("luaopen_"..name:gsub("%.", "_").."\n")
def:close()
local ok = execute(variables.LD, "-dll", "-def:"..deffile, "-out:"..library, dir.path(variables.LUA_LIBDIR, variables.LUALIB), unpack(extras))
- local manifestfile = basename..".dll.manifest"
+ local basedir = ""
+ if name:find("%.") ~= nil then
+ basedir = name:gsub("%.%w+$", "\\")
+ basedir = basedir:gsub("%.", "\\")
+ end
+ local manifestfile = basedir .. basename..".dll.manifest"
+
if ok and fs.exists(manifestfile) then
- ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:"..basename..".dll;2")
+ ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:"..basedir..basename..".dll;2")
end
return ok
end
compile_wrapper_binary = function(fullname, name)
+ --TODO EXEWRAPPER
local fullbasename = fullname:gsub("%.lua$", ""):gsub("/", "\\")
local basename = name:gsub("%.lua$", ""):gsub("/", "\\")
local object = basename..".obj"
@@ -159,47 +171,48 @@ function run(rockspec)
return execute(variables.LD.." "..variables.LIBFLAG, "-o", library, "-L"..variables.LUA_LIBDIR, unpack(extras))
end
compile_wrapper_binary = function(fullname, name) return true, name end
+ --TODO EXEWRAPPER
end
local ok = true
- local err = "Build error"
local built_modules = {}
local luadir = path.lua_dir(rockspec.name, rockspec.version)
local libdir = path.lib_dir(rockspec.name, rockspec.version)
- local docdir = path.doc_dir(rockspec.name, rockspec.version)
+ --TODO EXEWRAPPER
-- On Windows, compiles an .exe for each Lua file in build.install.bin, and
-- replaces the filename with the .exe name. Strips the .lua extension if it exists,
- -- otherwise just appends .exe to the name
+ -- otherwise just appends .exe to the name. Only if `cfg.exewrapper = true`
if build.install and build.install.bin then
- for i, name in ipairs(build.install.bin) do
+ for key, name in pairs(build.install.bin) do
local fullname = dir.path(fs.current_dir(), name)
- local match = name:match("%.lua$")
- local basename = name:gsub("%.lua$", "")
- local file
- if not match then
- file = io.open(fullname)
- end
- if match or (file and file:read():match("#!.*lua.*")) then
+ if cfg.exewrapper and fs.is_lua(fullname) then
ok, name = compile_wrapper_binary(fullname, name)
if ok then
- build.install.bin[i] = name
+ build.install.bin[key] = name
else
- if file then file:close() end
return nil, "Build error in wrapper binaries"
end
end
- if file then file:close() end
end
end
+
+
for name, info in pairs(build.modules) do
local moddir = path.module_to_path(name)
if type(info) == "string" then
local ext = info:match(".([^.]+)$")
if ext == "lua" then
+ local filename = dir.base_name(info)
if info:match("init%.lua$") and not name:match("%.init$") then
moddir = path.module_to_path(name..".init")
+ else
+ local basename = name:match("([^.]+)$")
+ local baseinfo = filename:gsub("%.lua$", "")
+ if basename ~= baseinfo then
+ filename = basename..".lua"
+ end
end
- local dest = dir.path(luadir, moddir)
+ local dest = dir.path(luadir, moddir, filename)
built_modules[info] = dest
else
info = {info}
@@ -222,12 +235,13 @@ function run(rockspec)
table.insert(objects, object)
end
if not ok then break end
- local module_name = dir.path(moddir, name:match("([^.]*)$").."."..util.matchquote(cfg.lib_extension)):gsub("//", "/")
+ local module_name = name:match("([^.]*)$").."."..util.matchquote(cfg.lib_extension)
if moddir ~= "" then
- fs.make_dir(moddir)
+ module_name = dir.path(moddir, module_name)
+ local ok, err = fs.make_dir(moddir)
+ if not ok then return nil, err end
end
- local dest = dir.path(libdir, moddir)
- built_modules[module_name] = dest
+ built_modules[module_name] = dir.path(libdir, module_name)
ok = compile_library(module_name, objects, info.libraries, info.libdirs, name)
if not ok then
return nil, "Failed compiling module "..module_name
@@ -235,17 +249,19 @@ function run(rockspec)
end
end
for name, dest in pairs(built_modules) do
- fs.make_dir(dest)
+ fs.make_dir(dir.dir_name(dest))
ok = fs.copy(name, dest)
if not ok then
return nil, "Failed installing "..name.." in "..dest
end
end
if fs.is_dir("lua") then
- ok, err = fs.copy_contents("lua", luadir)
- if not ok then
+ local ok, err = fs.copy_contents("lua", luadir)
+ if not ok then
return nil, "Failed copying contents of 'lua' directory: "..err
end
end
return true
end
+
+return builtin
diff --git a/src/luarocks/build/cmake.lua b/src/luarocks/build/cmake.lua
index 82f4ff5..ed2af3f 100644
--- a/src/luarocks/build/cmake.lua
+++ b/src/luarocks/build/cmake.lua
@@ -1,6 +1,7 @@
--- Build back-end for CMake-based modules.
-module("luarocks.build.cmake", package.seeall)
+--module("luarocks.build.cmake", package.seeall)
+local cmake = {}
local fs = require("luarocks.fs")
local util = require("luarocks.util")
@@ -10,7 +11,7 @@ local cfg = require("luarocks.cfg")
-- @param rockspec table: the loaded rockspec.
-- @return boolean or (nil, string): true if no errors ocurred,
-- nil and an error message otherwise.
-function run(rockspec)
+function cmake.run(rockspec)
assert(type(rockspec) == "table")
local build = rockspec.build
local variables = build.variables or {}
@@ -22,15 +23,15 @@ function run(rockspec)
util.variable_substitutions(variables, rockspec.variables)
- if not fs.execute_string(fs.quiet(rockspec.variables.CMAKE.." --help")) then
+ if not fs.execute_quiet(rockspec.variables.CMAKE, "--help") then
return nil, "'"..rockspec.variables.CMAKE.."' program not found. Is cmake installed? You may want to edit variables.CMAKE"
end
-- If inline cmake is present create CMakeLists.txt from it.
if type(build.cmake) == "string" then
- local cmake = assert(io.open(fs.current_dir().."/CMakeLists.txt", "w"))
- cmake:write(build.cmake)
- cmake:close()
+ local cmake_handler = assert(io.open(fs.current_dir().."/CMakeLists.txt", "w"))
+ cmake_handler:write(build.cmake)
+ cmake_handler:close()
end
@@ -56,3 +57,5 @@ function run(rockspec)
end
return true
end
+
+return cmake
diff --git a/src/luarocks/build/command.lua b/src/luarocks/build/command.lua
index aeec0da..650e323 100644
--- a/src/luarocks/build/command.lua
+++ b/src/luarocks/build/command.lua
@@ -1,6 +1,7 @@
--- Build back-end for raw listing of commands in rockspec files.
-module("luarocks.build.command", package.seeall)
+--module("luarocks.build.command", package.seeall)
+local command = {}
local fs = require("luarocks.fs")
local util = require("luarocks.util")
@@ -9,7 +10,7 @@ local util = require("luarocks.util")
-- @param rockspec table: the loaded rockspec.
-- @return boolean or (nil, string): true if no errors ocurred,
-- nil and an error message otherwise.
-function run(rockspec)
+function command.run(rockspec)
assert(type(rockspec) == "table")
local build = rockspec.build
@@ -30,3 +31,5 @@ function run(rockspec)
end
return true
end
+
+return command
diff --git a/src/luarocks/build/make.lua b/src/luarocks/build/make.lua
index c4b2157..0da183e 100644
--- a/src/luarocks/build/make.lua
+++ b/src/luarocks/build/make.lua
@@ -1,6 +1,9 @@
--- Build back-end for using Makefile-based packages.
-module("luarocks.build.make", package.seeall)
+--module("luarocks.build.make", package.seeall)
+local make = {}
+
+local unpack = unpack or table.unpack
local fs = require("luarocks.fs")
local util = require("luarocks.util")
@@ -36,7 +39,7 @@ end
-- @param rockspec table: the loaded rockspec.
-- @return boolean or (nil, string): true if no errors ocurred,
-- nil and an error message otherwise.
-function run(rockspec)
+function make.run(rockspec)
assert(type(rockspec) == "table")
local build = rockspec.build
@@ -90,3 +93,5 @@ function run(rockspec)
end
return true
end
+
+return make
diff --git a/src/luarocks/cache.lua b/src/luarocks/cache.lua
index 21185c1..dbea840 100644
--- a/src/luarocks/cache.lua
+++ b/src/luarocks/cache.lua
@@ -1,14 +1,16 @@
--- Module handling the LuaRocks local cache.
-- Adds a rock or rockspec to a rocks server.
-module("luarocks.cache", package.seeall)
+--module("luarocks.cache", package.seeall)
+local cache = {}
+package.loaded["luarocks.cache"] = cache
local fs = require("luarocks.fs")
local cfg = require("luarocks.cfg")
local dir = require("luarocks.dir")
local util = require("luarocks.util")
-function get_upload_server(server)
+function cache.get_upload_server(server)
if not server then server = cfg.upload_server end
if not server then
return nil, "No server specified and no default configured with upload_server."
@@ -16,7 +18,7 @@ function get_upload_server(server)
return server, cfg.upload_servers and cfg.upload_servers[server]
end
-function get_server_urls(server, upload_server)
+function cache.get_server_urls(server, upload_server)
local download_url = server
local login_url = nil
if upload_server then
@@ -32,7 +34,7 @@ function get_server_urls(server, upload_server)
return download_url, login_url
end
-function split_server_url(server, url, user, password)
+function cache.split_server_url(server, url, user, password)
local protocol, server_path = dir.split_url(url)
if server_path:match("@") then
local credentials
@@ -50,28 +52,31 @@ function split_server_url(server, url, user, password)
return local_cache, protocol, server_path, user, password
end
-function refresh_local_cache(server, url, user, password)
- local local_cache, protocol, server_path, user, password = split_server_url(server, url, user, password)
+function cache.refresh_local_cache(server, url, user, password)
+ local local_cache, protocol, server_path, user, password = cache.split_server_url(server, url, user, password)
- fs.make_dir(cfg.local_cache)
+ local ok, err = fs.make_dir(cfg.local_cache)
+ if not ok then return nil, err end
local tmp_cache = false
if not local_cache then
- local_cache = fs.make_temp_dir("local_cache")
+ local err
+ local_cache, err = fs.make_temp_dir("local_cache")
tmp_cache = true
end
- local ok = fs.make_dir(local_cache)
+ local ok, err = fs.make_dir(local_cache)
if not ok then
- return nil, "Failed creating local cache dir."
+ return nil, "Failed creating local cache dir: "..err
end
fs.change_dir(local_cache)
+ if not ok then return nil, err end
util.printout("Refreshing cache "..local_cache.."...")
-- TODO abstract away explicit 'wget' call
local ok = false
if protocol == "rsync" then
local srv, path = server_path:match("([^/]+)(/.+)")
- ok = fs.execute(cfg.variables.RSYNC.." -avz -e ssh "..user.."@"..srv..":"..path.."/ "..local_cache.."/")
+ ok = fs.execute(cfg.variables.RSYNC.." "..cfg.variables.RSYNCFLAGS.." -e ssh "..user.."@"..srv..":"..path.."/ "..local_cache.."/")
else
local login_info = ""
if user then login_info = " --user="..user end
@@ -83,3 +88,5 @@ function refresh_local_cache(server, url, user, password)
end
return local_cache, protocol, server_path, user, password
end
+
+return cache
diff --git a/src/luarocks/cfg.lua b/src/luarocks/cfg.lua
index 5d918b1..b2acfcc 100644
--- a/src/luarocks/cfg.lua
+++ b/src/luarocks/cfg.lua
@@ -13,10 +13,14 @@
local rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs, package, tonumber, type, assert, _VERSION =
rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs, package, tonumber, type, assert, _VERSION
-module("luarocks.cfg")
+--module("luarocks.cfg")
+local cfg = {}
+package.loaded["luarocks.cfg"] = cfg
-lua_version = _VERSION:sub(5)
-local version_suffix = lua_version:gsub("%.", "_")
+local util = require("luarocks.util")
+
+cfg.lua_version = _VERSION:sub(5)
+local version_suffix = cfg.lua_version:gsub("%.", "_")
-- Load site-local global configurations
local ok, site_config = pcall(require, "luarocks.site_config_"..version_suffix)
@@ -28,12 +32,28 @@ if not ok then
site_config = {}
end
-_M.site_config = site_config
+cfg.site_config = site_config
-program_version = "2.1.0"
+cfg.program_version = "2.2.0beta1"
+cfg.major_version = cfg.program_version:match("([^.]%.[^.])")
local persist = require("luarocks.persist")
+cfg.errorcodes = setmetatable({
+ OK = 0,
+ UNSPECIFIED = 1,
+ PERMISSIONDENIED = 2,
+},{
+ __index = function(t, key)
+ local val = rawget(t, key)
+ if not val then
+ error("'"..tostring(key).."' is not a valid errorcode", 2)
+ end
+ return val
+ end
+})
+
+
local popen_ok, popen_result = pcall(io.popen, "")
if popen_ok then
if popen_result then
@@ -42,7 +62,7 @@ if popen_ok then
else
io.stderr:write("Your version of Lua does not support io.popen,\n")
io.stderr:write("which is required by LuaRocks. Please check your Lua installation.\n")
- os.exit(1)
+ os.exit(cfg.errorcodes.UNSPECIFIED)
end
-- System detection:
@@ -105,31 +125,32 @@ end
local sys_config_file, home_config_file
local sys_config_dir, home_config_dir
local sys_config_ok, home_config_ok = false, false
+local extra_luarocks_module_dir
sys_config_dir = site_config.LUAROCKS_SYSCONFDIR
if detected.windows then
- home = os.getenv("APPDATA") or "c:"
+ cfg.home = os.getenv("APPDATA") or "c:"
sys_config_dir = sys_config_dir or "c:/luarocks"
- home_config_dir = home.."/luarocks"
- home_tree = home.."/luarocks/"
+ home_config_dir = cfg.home.."/luarocks"
+ cfg.home_tree = cfg.home.."/luarocks/"
else
- home = os.getenv("HOME") or ""
+ cfg.home = os.getenv("HOME") or ""
sys_config_dir = sys_config_dir or "/etc/luarocks"
- home_config_dir = home.."/.luarocks"
- home_tree = home.."/.luarocks/"
+ home_config_dir = cfg.home.."/.luarocks"
+ cfg.home_tree = cfg.home.."/.luarocks/"
end
-variables = {}
-rocks_trees = {}
+cfg.variables = {}
+cfg.rocks_trees = {}
-sys_config_file = site_config.LUAROCKS_SYSCONFIG or sys_config_dir.."/config-"..lua_version..".lua"
+sys_config_file = site_config.LUAROCKS_SYSCONFIG or sys_config_dir.."/config-"..cfg.lua_version..".lua"
local err
-sys_config_ok, err = persist.load_into_table(sys_config_file, _M)
+sys_config_ok, err = persist.load_into_table(sys_config_file, cfg)
if not sys_config_ok then
sys_config_file = sys_config_dir.."/config.lua"
- sys_config_ok, err = persist.load_into_table(sys_config_file, _M)
+ sys_config_ok, err = persist.load_into_table(sys_config_file, cfg)
end
-if err and ok == nil then
+if err and sys_config_ok == nil then
io.stderr:write(err.."\n")
end
@@ -137,25 +158,24 @@ if not site_config.LUAROCKS_FORCE_CONFIG then
local home_overrides, err
home_config_file = os.getenv("LUAROCKS_CONFIG_" .. version_suffix) or os.getenv("LUAROCKS_CONFIG")
if home_config_file then
- home_overrides, err = persist.load_into_table(home_config_file, { home = home, lua_version = lua_version })
+ home_overrides, err = persist.load_into_table(home_config_file, { home = cfg.home, lua_version = cfg.lua_version })
else
- home_config_file = home_config_dir.."/config-"..lua_version..".lua"
- home_overrides, err = persist.load_into_table(home_config_file, { home = home, lua_version = lua_version })
+ home_config_file = home_config_dir.."/config-"..cfg.lua_version..".lua"
+ home_overrides, err = persist.load_into_table(home_config_file, { home = cfg.home, lua_version = cfg.lua_version })
if not home_overrides then
home_config_file = home_config_dir.."/config.lua"
- home_overrides, err = persist.load_into_table(home_config_file, { home = home, lua_version = lua_version })
+ home_overrides, err = persist.load_into_table(home_config_file, { home = cfg.home, lua_version = cfg.lua_version })
end
end
if home_overrides then
home_config_ok = true
- local util = require("luarocks.util")
if home_overrides.rocks_trees then
- _M.rocks_trees = nil
+ cfg.rocks_trees = nil
end
if home_overrides.rocks_servers then
- _M.rocks_servers = nil
+ cfg.rocks_servers = nil
end
- util.deep_merge(_M, home_overrides)
+ util.deep_merge(cfg, home_overrides)
else -- nil or false
home_config_ok = home_overrides
if err and home_config_ok == nil then
@@ -164,18 +184,18 @@ if not site_config.LUAROCKS_FORCE_CONFIG then
end
end
-if not next(rocks_trees) then
- if home_tree then
- table.insert(rocks_trees, home_tree)
+if not next(cfg.rocks_trees) then
+ if cfg.home_tree then
+ table.insert(cfg.rocks_trees, { name = "user", root = cfg.home_tree } )
end
if site_config.LUAROCKS_ROCKS_TREE then
- table.insert(rocks_trees, site_config.LUAROCKS_ROCKS_TREE)
+ table.insert(cfg.rocks_trees, { name = "system", root = site_config.LUAROCKS_ROCKS_TREE } )
end
end
-- Configure defaults:
-local root = rocks_trees[#rocks_trees]
+local root = cfg.rocks_trees[#cfg.rocks_trees]
local defaults = {
local_by_default = false,
@@ -185,8 +205,8 @@ local defaults = {
hooks_enabled = true,
deps_mode = "one",
- lua_modules_path = "/share/lua/"..lua_version,
- lib_modules_path = "/lib/lua/"..lua_version,
+ lua_modules_path = "/share/lua/"..cfg.lua_version,
+ lib_modules_path = "/lib/lua/"..cfg.lua_version,
rocks_subdir = site_config.LUAROCKS_ROCKS_SUBDIR or "/lib/luarocks/rocks",
arch = "unknown",
@@ -195,18 +215,25 @@ local defaults = {
rocks_servers = {
{
- "http://www.luarocks.org/repositories/rocks",
- "http://luarocks.giga.puc-rio.br/",
- "http://luafr.org/luarocks/rocks",
- "http://liblua.so/luarocks/repositories/rocks",
+ "https://rocks.moonscript.org",
+ "https://raw.githubusercontent.com/rocks-moonscript-org/moonrocks-mirror/master/",
+ "http://luafr.org/moonrocks/",
"http://luarocks.logiceditor.com/rocks",
}
},
+ disabled_servers = {},
+
+ upload = {
+ server = "https://rocks.moonscript.org",
+ tool_version = "0.0.1",
+ api_version = "1",
+ },
lua_extension = "lua",
lua_interpreter = site_config.LUA_INTERPRETER or "lua",
downloader = site_config.LUAROCKS_DOWNLOADER or "wget",
md5checker = site_config.LUAROCKS_MD5CHECKER or "md5sum",
+ connection_timeout = 30, -- 0 = no timeout
variables = {
MAKE = "make",
@@ -249,22 +276,28 @@ local defaults = {
CMAKE = "cmake",
SEVENZ = "7z",
+ RSYNCFLAGS = "--exclude=.git -Oavz",
STATFLAG = "-c '%a'",
},
- external_deps_subdirs = {
+ external_deps_subdirs = site_config.LUAROCKS_EXTERNAL_DEPS_SUBDIRS or {
bin = "bin",
lib = "lib",
include = "include"
},
- runtime_external_deps_subdirs = {
+ runtime_external_deps_subdirs = site_config.LUAROCKS_RUNTIME_EXTERNAL_DEPS_SUBDIRS or {
bin = "bin",
lib = "lib",
include = "include"
},
+
+ rocks_provided = {}
}
if detected.windows then
+ local full_prefix = site_config.LUAROCKS_PREFIX.."\\"..cfg.major_version
+ extra_luarocks_module_dir = full_prefix.."\\lua\\?.lua"
+
home_config_file = home_config_file and home_config_file:gsub("\\","/")
defaults.fs_use_modules = false
defaults.arch = "win32-"..proc
@@ -273,21 +306,29 @@ if detected.windows then
defaults.external_lib_extension = "dll"
defaults.obj_extension = "obj"
defaults.external_deps_dirs = { "c:/external/" }
- defaults.variables.LUA_BINDIR = site_config.LUA_BINDIR and site_config.LUA_BINDIR:gsub("\\", "/") or "c:/lua"..lua_version.."/bin"
- defaults.variables.LUA_INCDIR = site_config.LUA_INCDIR and site_config.LUA_INCDIR:gsub("\\", "/") or "c:/lua"..lua_version.."/include"
- defaults.variables.LUA_LIBDIR = site_config.LUA_LIBDIR and site_config.LUA_LIBDIR:gsub("\\", "/") or "c:/lua"..lua_version.."/lib"
+ defaults.variables.LUA_BINDIR = site_config.LUA_BINDIR and site_config.LUA_BINDIR:gsub("\\", "/") or "c:/lua"..cfg.lua_version.."/bin"
+ defaults.variables.LUA_INCDIR = site_config.LUA_INCDIR and site_config.LUA_INCDIR:gsub("\\", "/") or "c:/lua"..cfg.lua_version.."/include"
+ defaults.variables.LUA_LIBDIR = site_config.LUA_LIBDIR and site_config.LUA_LIBDIR:gsub("\\", "/") or "c:/lua"..cfg.lua_version.."/lib"
defaults.cmake_generator = "MinGW Makefiles"
defaults.makefile = "Makefile.win"
defaults.variables.MAKE = "nmake"
defaults.variables.CC = "cl"
defaults.variables.RC = "rc"
- defaults.variables.WRAPPER = site_config.LUAROCKS_PREFIX .. "\\2.0\\rclauncher.c"
+ defaults.variables.WRAPPER = full_prefix.."\\rclauncher.c"
defaults.variables.LD = "link"
defaults.variables.MT = "mt"
- defaults.variables.LUALIB = "lua"..lua_version..".lib"
+ defaults.variables.LUALIB = "lua"..cfg.lua_version..".lib"
defaults.variables.CFLAGS = "/MD /O2"
defaults.variables.LIBFLAG = "/dll"
- defaults.variables.LUALIB = "lua"..lua_version..".lib"
+
+ local bins = { "SEVENZ", "CP", "FIND", "LS", "MD5SUM",
+ "MKDIR", "MV", "PWD", "RMDIR", "TEST", "UNAME", "WGET" }
+ for _, var in ipairs(bins) do
+ if defaults.variables[var] then
+ defaults.variables[var] = full_prefix.."\\tools\\"..defaults.variables[var]
+ end
+ end
+
defaults.external_deps_patterns = {
bin = { "?.exe", "?.bat" },
lib = { "?.lib", "?.dll", "lib?.dll" },
@@ -302,7 +343,15 @@ if detected.windows then
defaults.export_path_separator = ";"
defaults.export_lua_path = "SET LUA_PATH=%s"
defaults.export_lua_cpath = "SET LUA_CPATH=%s"
- defaults.local_cache = home.."/cache/luarocks"
+ defaults.wrapper_suffix = ".bat"
+
+ local localappdata = os.getenv("LOCALAPPDATA")
+ if not localappdata then
+ -- for Windows versions below Vista
+ localappdata = os.getenv("USERPROFILE").."/Local Settings/Application Data"
+ end
+ defaults.local_cache = localappdata.."/LuaRocks/Cache"
+ defaults.web_browser = "start"
end
if detected.mingw32 then
@@ -312,10 +361,22 @@ if detected.mingw32 then
defaults.variables.MAKE = "mingw32-make"
defaults.variables.CC = "mingw32-gcc"
defaults.variables.RC = "windres"
- defaults.variables.WRAPPER = site_config.LUAROCKS_PREFIX .. "\\2.0\\rclauncher.c"
defaults.variables.LD = "mingw32-gcc"
defaults.variables.CFLAGS = "-O2"
defaults.variables.LIBFLAG = "-shared"
+ defaults.external_deps_patterns = {
+ bin = { "?.exe", "?.bat" },
+ -- mingw lookup list from http://stackoverflow.com/a/15853231/1793220
+ -- ...should we keep ?.lib at the end? It's not in the above list.
+ lib = { "lib?.dll.a", "?.dll.a", "lib?.a", "cyg?.dll", "lib?.dll", "?.dll", "?.lib" },
+ include = { "?.h" }
+ }
+ defaults.runtime_external_deps_patterns = {
+ bin = { "?.exe", "?.bat" },
+ lib = { "cyg?.dll", "?.dll", "lib?.dll" },
+ include = { "?.h" }
+ }
+
end
if detected.unix then
@@ -347,10 +408,12 @@ if detected.unix then
defaults.export_path_separator = ":"
defaults.export_lua_path = "export LUA_PATH='%s'"
defaults.export_lua_cpath = "export LUA_CPATH='%s'"
- defaults.local_cache = home.."/.cache/luarocks"
+ defaults.wrapper_suffix = ""
+ defaults.local_cache = cfg.home.."/.cache/luarocks"
if not defaults.variables.CFLAGS:match("-fPIC") then
defaults.variables.CFLAGS = defaults.variables.CFLAGS.." -fPIC"
end
+ defaults.web_browser = "xdg-open"
end
if detected.cygwin then
@@ -384,6 +447,7 @@ if detected.macosx then
end
defaults.variables.CC = "export MACOSX_DEPLOYMENT_TARGET=10."..version.."; gcc"
defaults.variables.LD = "export MACOSX_DEPLOYMENT_TARGET=10."..version.."; gcc"
+ defaults.web_browser = "open"
end
if detected.linux then
@@ -394,6 +458,9 @@ end
if detected.freebsd then
defaults.arch = "freebsd-"..proc
defaults.platforms = {"unix", "bsd", "freebsd"}
+ defaults.gcc_rpath = false
+ defaults.variables.CC = "cc"
+ defaults.variables.LD = "cc"
end
if detected.openbsd then
@@ -418,16 +485,38 @@ defaults.variables.OBJ_EXTENSION = defaults.obj_extension
defaults.variables.LUAROCKS_PREFIX = site_config.LUAROCKS_PREFIX
defaults.variables.LUA = site_config.LUA_DIR_SET and (defaults.variables.LUA_BINDIR.."/"..defaults.lua_interpreter) or defaults.lua_interpreter
--- Use defaults:
+-- Add built-in modules to rocks_provided
+defaults.rocks_provided["lua"] = cfg.lua_version.."-1"
+
+if cfg.lua_version >= "5.2" then
+ -- Lua 5.2+
+ defaults.rocks_provided["bit32"] = cfg.lua_version.."-1"
+end
+
+if cfg.lua_version >= "5.3" then
+ -- Lua 5.3+
+ defaults.rocks_provided["utf8"] = cfg.lua_version.."-1"
+end
--- Populate values from 'defaults.variables' in 'variables' if they were not
--- already set by user.
-if not _M.variables then
- _M.variables = {}
+if package.loaded.jit then
+ -- LuaJIT
+ local lj_version = package.loaded.jit.version:match("LuaJIT (.*)"):gsub("%-","")
+ --defaults.rocks_provided["luajit"] = lj_version.."-1"
+ defaults.rocks_provided["luabitop"] = lj_version.."-1"
end
-for k,v in pairs(defaults.variables) do
- if not _M.variables[k] then
- _M.variables[k] = v
+
+-- Use defaults:
+
+-- Populate some arrays with values from their 'defaults' counterparts
+-- if they were not already set by user.
+for _, entry in ipairs({"variables", "rocks_provided"}) do
+ if not cfg[entry] then
+ cfg[entry] = {}
+ end
+ for k,v in pairs(defaults[entry]) do
+ if not cfg[entry][k] then
+ cfg[entry][k] = v
+ end
end
end
@@ -441,44 +530,60 @@ local cfg_mt = {
return default
end
}
-setmetatable(_M, cfg_mt)
-
-function package_paths()
- local new_path, new_cpath = {}, {}
- for _,tree in ipairs(rocks_trees) do
- if type(tree) == "string" then
- table.insert(new_path, 1, tree..lua_modules_path.."/?.lua;"..tree..lua_modules_path.."/?/init.lua")
- table.insert(new_cpath, 1, tree..lib_modules_path.."/?."..lib_extension)
- else
- table.insert(new_path, 1, (tree.lua_dir or tree.root..lua_modules_path).."/?.lua;"..
- (tree.lua_dir or tree.root..lua_modules_path).."/?/init.lua")
- table.insert(new_cpath, 1, (tree.lib_dir or tree.root..lib_modules_path).."/?."..lib_extension)
- end
+setmetatable(cfg, cfg_mt)
+
+function cfg.make_paths_from_tree(tree)
+ local lua_path, lib_path, bin_path
+ if type(tree) == "string" then
+ lua_path = tree..cfg.lua_modules_path
+ lib_path = tree..cfg.lib_modules_path
+ bin_path = tree.."/bin"
+ else
+ lua_path = tree.lua_dir or tree.root..cfg.lua_modules_path
+ lib_path = tree.lib_dir or tree.root..cfg.lib_modules_path
+ bin_path = tree.bin_dir or tree.root.."/bin"
end
- return table.concat(new_path, ";"), table.concat(new_cpath, ";")
+ return lua_path, lib_path, bin_path
end
-do
- local new_path, new_cpath = package_paths()
- package.path = new_path..";"..package.path
- package.cpath = new_cpath..";"..package.cpath
+function cfg.package_paths()
+ local new_path, new_cpath, new_bin = {}, {}, {}
+ for _,tree in ipairs(cfg.rocks_trees) do
+ local lua_path, lib_path, bin_path = cfg.make_paths_from_tree(tree)
+ table.insert(new_path, lua_path.."/?.lua")
+ table.insert(new_path, lua_path.."/?/init.lua")
+ table.insert(new_cpath, lib_path.."/?."..cfg.lib_extension)
+ table.insert(new_bin, bin_path)
+ end
+ if extra_luarocks_module_dir then
+ table.insert(new_path, extra_luarocks_module_dir)
+ end
+ return table.concat(new_path, ";"), table.concat(new_cpath, ";"), table.concat(new_bin, cfg.export_path_separator)
+end
+
+function cfg.init_package_paths()
+ local lr_path, lr_cpath, lr_bin = cfg.package_paths()
+ package.path = util.remove_path_dupes(package.path .. ";" .. lr_path, ";")
+ package.cpath = util.remove_path_dupes(package.cpath .. ";" .. lr_cpath, ";")
end
-function which_config()
+function cfg.which_config()
return sys_config_file, sys_config_ok, home_config_file, home_config_ok
end
-user_agent = "LuaRocks/"..program_version.." "..arch
+cfg.user_agent = "LuaRocks/"..cfg.program_version.." "..cfg.arch
--- Check if platform was detected
-- @param query string: The platform name to check.
-- @return boolean: true if LuaRocks is currently running on queried platform.
-function is_platform(query)
+function cfg.is_platform(query)
assert(type(query) == "string")
- for _, platform in ipairs(platforms) do
+ for _, platform in ipairs(cfg.platforms) do
if platform == query then
return true
end
end
end
+
+return cfg
diff --git a/src/luarocks/command_line.lua b/src/luarocks/command_line.lua
index d16ef8e..cc2e168 100644
--- a/src/luarocks/command_line.lua
+++ b/src/luarocks/command_line.lua
@@ -1,6 +1,9 @@
--- Functions for command-line scripts.
-module("luarocks.command_line", package.seeall)
+--module("luarocks.command_line", package.seeall)
+local command_line = {}
+
+local unpack = unpack or table.unpack
local util = require("luarocks.util")
local cfg = require("luarocks.cfg")
@@ -12,7 +15,8 @@ local program = util.this_program("luarocks")
--- Display an error message and exit.
-- @param message string: The error message.
-local function die(message)
+-- @param exitcode number: the exitcode to use
+local function die(message, exitcode)
assert(type(message) == "string")
local ok, err = pcall(util.run_scheduled_functions)
@@ -20,7 +24,19 @@ local function die(message)
util.printerr("\nLuaRocks "..cfg.program_version.." internal bug (please report at luarocks-developers@lists.sourceforge.net):\n"..err)
end
util.printerr("\nError: "..message)
- os.exit(1)
+ os.exit(exitcode or cfg.errorcodes.UNSPECIFIED)
+end
+
+local function replace_tree(flags, args, tree)
+ tree = dir.normalize(tree)
+ flags["tree"] = tree
+ for i = 1, #args do
+ if args[i]:match("%-%-tree=") then
+ args[i] = "--tree="..tree
+ break
+ end
+ end
+ path.use_tree(tree)
end
--- Main command-line processor.
@@ -30,7 +46,7 @@ end
-- Uses the global table "commands", which contains
-- the loaded modules representing commands.
-- @param ... string: Arguments given on the command-line.
-function run_command(...)
+function command_line.run_command(...)
local args = {...}
local cmdline_vars = {}
for i = #args, 1, -1 do
@@ -61,11 +77,26 @@ function run_command(...)
local command
+ if flags["verbose"] then -- setting it in the config file will kick-in earlier in the process
+ cfg.verbose = true
+ local fs = require("luarocks.fs")
+ fs.verbose()
+ end
+
+ if flags["timeout"] then -- setting it in the config file will kick-in earlier in the process
+ local timeout = tonumber(flags["timeout"])
+ if timeout then
+ cfg.connection_timeout = timeout
+ else
+ die "Argument error: --timeout expects a numeric argument."
+ end
+ end
+
if flags["version"] then
util.printout(program.." "..cfg.program_version)
util.printout(program_description)
util.printout()
- os.exit(0)
+ os.exit(cfg.errorcodes.OK)
elseif flags["help"] or #nonflags == 0 then
command = "help"
args = nonflags
@@ -94,15 +125,35 @@ function run_command(...)
die("Invalid entry for --deps-mode.")
end
+ if flags["branch"] then
+ if flags["branch"] == true or flags["branch"] == "" then
+ die("Argument error: use --branch=<branch-name>")
+ end
+ cfg.branch = flags["branch"]
+ end
+
if flags["tree"] then
if flags["tree"] == true or flags["tree"] == "" then
die("Argument error: use --tree=<path>")
end
- local fs = require("luarocks.fs")
- local root_dir = fs.absolute_name(flags["tree"])
- path.use_tree(root_dir)
+ local named = false
+ for _, tree in ipairs(cfg.rocks_trees) do
+ if type(tree) == "table" and flags["tree"] == tree.name then
+ if not tree.root then
+ die("Configuration error: tree '"..tree.name.."' has no 'root' field.")
+ end
+ replace_tree(flags, args, tree.root)
+ named = true
+ break
+ end
+ end
+ if not named then
+ local fs = require("luarocks.fs")
+ local root_dir = fs.absolute_name(flags["tree"])
+ replace_tree(flags, args, root_dir)
+ end
elseif flags["local"] then
- path.use_tree(cfg.home_tree)
+ replace_tree(flags, args, cfg.home_tree)
else
local trees = cfg.rocks_trees
path.use_tree(trees[#trees])
@@ -153,16 +204,19 @@ function run_command(...)
-- I'm not changing this now to avoid messing with the run()
-- interface, which I know some people use (even though
-- I never published it as a public API...)
- local xp, ok, err = xpcall(function() return commands[command].run(unpack(args)) end, function(err)
+ local cmd = require(commands[command])
+ local xp, ok, err, exitcode = xpcall(function() return cmd.run(unpack(args)) end, function(err)
die(debug.traceback("LuaRocks "..cfg.program_version
.." bug (please report at luarocks-developers@lists.sourceforge.net).\n"
..err, 2))
end)
if xp and (not ok) then
- die(err)
+ die(err, exitcode)
end
else
die("Unknown command: "..command)
end
util.run_scheduled_functions()
end
+
+return command_line
diff --git a/src/luarocks/deps.lua b/src/luarocks/deps.lua
index 5ac822c..3f75f9b 100644
--- a/src/luarocks/deps.lua
+++ b/src/luarocks/deps.lua
@@ -11,7 +11,9 @@
-- comparison criteria is the source code of this module, but the
-- test/test_deps.lua file included with LuaRocks provides some
-- insights on what these criteria are.
-module("luarocks.deps", package.seeall)
+--module("luarocks.deps", package.seeall)
+local deps = {}
+package.loaded["luarocks.deps"] = deps
local cfg = require("luarocks.cfg")
local manif_core = require("luarocks.manif_core")
@@ -34,7 +36,7 @@ local operators = {
}
local deltas = {
- scm = 1000,
+ scm = 1100,
cvs = 1000,
rc = -1000,
pre = -10000,
@@ -101,7 +103,7 @@ setmetatable(version_cache, {
-- @param vstring string: A version number in string format.
-- @return table or nil: A version table or nil
-- if the input string contains invalid characters.
-function parse_version(vstring)
+function deps.parse_version(vstring)
if not vstring then return nil end
assert(type(vstring) == "string")
@@ -140,7 +142,6 @@ function parse_version(vstring)
version[i] = 0
break
end
- local last = #version
version[i] = deltas[token] or (token:byte() / 1000)
end
vstring = rest
@@ -154,8 +155,8 @@ end
-- @param a string: one version.
-- @param b string: another version.
-- @return boolean: True if a > b.
-function compare_versions(a, b)
- return parse_version(a) > parse_version(b)
+function deps.compare_versions(a, b)
+ return deps.parse_version(a) > deps.parse_version(b)
end
--- Consumes a constraint from a string, converting it to table format.
@@ -171,7 +172,7 @@ local function parse_constraint(input)
local no_upgrade, op, version, rest = input:match("^(@?)([<>=~!]*)%s*([%w%.%_%-]+)[%s,]*(.*)")
local _op = operators[op]
- version = parse_version(version)
+ version = deps.parse_version(version)
if not _op then
return nil, "Encountered bad constraint operator: '"..tostring(op).."' in '"..input.."'"
end
@@ -189,7 +190,7 @@ end
-- @param input string: A list of constraints in string format.
-- @return table or nil: A table representing the same constraints,
-- or nil if the input string is invalid.
-function parse_constraints(input)
+function deps.parse_constraints(input)
assert(type(input) == "string")
local constraints, constraint, oinput = {}, nil, input
@@ -214,12 +215,12 @@ end
-- as entered in rockspec files.
-- @return table or nil: A table representing the same dependency relation,
-- or nil if the input string is invalid.
-function parse_dep(dep)
+function deps.parse_dep(dep)
assert(type(dep) == "string")
- local name, rest = dep:match("^%s*([a-zA-Z][a-zA-Z0-9%.%-%_]*)%s*(.*)")
+ local name, rest = dep:match("^%s*([a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*(.*)")
if not name then return nil, "failed to extract dependency name from '"..tostring(dep).."'" end
- local constraints, err = parse_constraints(rest)
+ local constraints, err = deps.parse_constraints(rest)
if not constraints then return nil, err end
return { name = name, constraints = constraints }
end
@@ -229,7 +230,7 @@ end
-- @param internal boolean or nil: Whether to display versions in their
-- internal representation format or how they were specified.
-- @return string: The dependency information pretty-printed as a string.
-function show_version(v, internal)
+function deps.show_version(v, internal)
assert(type(v) == "table")
assert(type(internal) == "boolean" or not internal)
@@ -243,13 +244,13 @@ end
-- @param internal boolean or nil: Whether to display versions in their
-- internal representation format or how they were specified.
-- @return string: The dependency information pretty-printed as a string.
-function show_dep(dep, internal)
+function deps.show_dep(dep, internal)
assert(type(dep) == "table")
assert(type(internal) == "boolean" or not internal)
local pretty = {}
for _, c in ipairs(dep.constraints) do
- table.insert(pretty, c.op .. " " .. show_version(c.version, internal))
+ table.insert(pretty, c.op .. " " .. deps.show_version(c.version, internal))
end
return dep.name.." "..table.concat(pretty, ", ")
end
@@ -270,8 +271,8 @@ local function partial_match(version, requested)
assert(type(version) == "string" or type(version) == "table")
assert(type(requested) == "string" or type(version) == "table")
- if type(version) ~= "table" then version = parse_version(version) end
- if type(requested) ~= "table" then requested = parse_version(requested) end
+ if type(version) ~= "table" then version = deps.parse_version(version) end
+ if type(requested) ~= "table" then requested = deps.parse_version(requested) end
if not version or not requested then return false end
for i, ri in ipairs(requested) do
@@ -289,14 +290,14 @@ end
-- @param constraints table: An array of constraints in table format.
-- @return boolean: True if version satisfies all constraints,
-- false otherwise.
-function match_constraints(version, constraints)
+function deps.match_constraints(version, constraints)
assert(type(version) == "table")
assert(type(constraints) == "table")
local ok = true
setmetatable(version, version_mt)
for _, constr in pairs(constraints) do
if type(constr.version) == "string" then
- constr.version = parse_version(constr.version)
+ constr.version = deps.parse_version(constr.version)
end
local constr_version, constr_op = constr.version, constr.op
setmetatable(constr_version, version_mt)
@@ -323,9 +324,10 @@ end
local function match_dep(dep, blacklist, deps_mode)
assert(type(dep) == "table")
- local versions
- if dep.name == "lua" then
- versions = { cfg.lua_version }
+ local versions = cfg.rocks_provided[dep.name]
+ if cfg.rocks_provided[dep.name] then
+ -- provided rocks have higher priority than manifest's rocks
+ versions = { cfg.rocks_provided[dep.name] }
else
versions = manif_core.get_versions(dep.name, deps_mode)
end
@@ -344,8 +346,8 @@ local function match_dep(dep, blacklist, deps_mode)
end
local candidates = {}
for _, vstring in ipairs(versions) do
- local version = parse_version(vstring)
- if match_constraints(version, dep.constraints) then
+ local version = deps.parse_version(vstring)
+ if deps.match_constraints(version, dep.constraints) then
table.insert(candidates, version)
end
end
@@ -365,19 +367,21 @@ end
-- @param blacklist table or nil: Program versions to not use as valid matches.
-- Table where keys are program names and values are tables where keys
-- are program versions and values are 'true'.
--- @return table, table: A table where keys are dependencies parsed
+-- @return table, table, table: A table where keys are dependencies parsed
-- in table format and values are tables containing fields 'name' and
--- version' representing matches, and a table of missing dependencies
--- parsed as tables.
-function match_deps(rockspec, blacklist, deps_mode)
+-- version' representing matches; a table of missing dependencies
+-- parsed as tables; and a table of "no-upgrade" missing dependencies
+-- (to be used in plugin modules so that a plugin does not force upgrade of
+-- its parent application).
+function deps.match_deps(rockspec, blacklist, deps_mode)
assert(type(rockspec) == "table")
assert(type(blacklist) == "table" or not blacklist)
local matched, missing, no_upgrade = {}, {}, {}
-
+
for _, dep in ipairs(rockspec.dependencies) do
local found = match_dep(dep, blacklist and blacklist[dep.name] or nil, deps_mode)
if found then
- if dep.name ~= "lua" then
+ if not cfg.rocks_provided[dep.name] then
matched[dep] = found
end
else
@@ -409,24 +413,24 @@ end
-- @return boolean or (nil, string, [string]): True if no errors occurred, or
-- nil and an error message if any test failed, followed by an optional
-- error code.
-function fulfill_dependencies(rockspec, deps_mode)
+function deps.fulfill_dependencies(rockspec, deps_mode)
local search = require("luarocks.search")
local install = require("luarocks.install")
if rockspec.supported_platforms then
- if not platforms_set then
- platforms_set = values_set(cfg.platforms)
+ if not deps.platforms_set then
+ deps.platforms_set = values_set(cfg.platforms)
end
local supported = nil
for _, plat in pairs(rockspec.supported_platforms) do
local neg, plat = plat:match("^(!?)(.*)")
if neg == "!" then
- if platforms_set[plat] then
+ if deps.platforms_set[plat] then
return nil, "This rockspec for "..rockspec.package.." does not support "..plat.." platforms."
end
else
- if platforms_set[plat] then
+ if deps.platforms_set[plat] then
supported = true
else
if supported == nil then
@@ -441,22 +445,22 @@ function fulfill_dependencies(rockspec, deps_mode)
end
end
- local matched, missing, no_upgrade = match_deps(rockspec, nil, deps_mode)
+ local _, missing, no_upgrade = deps.match_deps(rockspec, nil, deps_mode)
if next(no_upgrade) then
util.printerr("Missing dependencies for "..rockspec.name.." "..rockspec.version..":")
for _, dep in pairs(no_upgrade) do
- util.printerr(show_dep(dep))
+ util.printerr(deps.show_dep(dep))
end
if next(missing) then
for _, dep in pairs(missing) do
- util.printerr(show_dep(dep))
+ util.printerr(deps.show_dep(dep))
end
end
util.printerr()
for _, dep in pairs(no_upgrade) do
util.printerr("This version of "..rockspec.name.." is designed for use with")
- util.printerr(show_dep(dep)..", but is configured to avoid upgrading it")
+ util.printerr(deps.show_dep(dep)..", but is configured to avoid upgrading it")
util.printerr("automatically. Please upgrade "..dep.name.." with")
util.printerr(" luarocks install "..dep.name)
util.printerr("or choose an older version of "..rockspec.name.." with")
@@ -469,7 +473,7 @@ function fulfill_dependencies(rockspec, deps_mode)
util.printerr()
util.printerr("Missing dependencies for "..rockspec.name..":")
for _, dep in pairs(missing) do
- util.printerr(show_dep(dep))
+ util.printerr(deps.show_dep(dep))
end
util.printerr()
@@ -478,7 +482,7 @@ function fulfill_dependencies(rockspec, deps_mode)
if not match_dep(dep, nil, deps_mode) then
local rock = search.find_suitable_rock(dep)
if not rock then
- return nil, "Could not satisfy dependency: "..show_dep(dep)
+ return nil, "Could not satisfy dependency: "..deps.show_dep(dep)
end
local ok, err, errcode = install.run(rock)
if not ok then
@@ -528,7 +532,7 @@ end
-- if "install" is given, do not scan for headers.
-- @return boolean or (nil, string): True if no errors occurred, or
-- nil and an error message if any test failed.
-function check_external_deps(rockspec, mode)
+function deps.check_external_deps(rockspec, mode)
assert(type(rockspec) == "table")
local fs = require("luarocks.fs")
@@ -574,7 +578,19 @@ function check_external_deps(rockspec, mode)
prefix = prefix.prefix
end
for dirname, dirdata in pairs(dirs) do
- dirdata.dir = vars[name.."_"..dirname] or dir.path(prefix, dirdata.subdir)
+ local paths
+ local path_var_value = vars[name.."_"..dirname]
+ if path_var_value then
+ paths = { path_var_value }
+ elseif type(dirdata.subdir) == "table" then
+ paths = {}
+ for i,v in ipairs(dirdata.subdir) do
+ paths[i] = dir.path(prefix, v)
+ end
+ else
+ paths = { dir.path(prefix, dirdata.subdir) }
+ end
+ dirdata.dir = paths[1]
local file = files[dirdata.testfile]
if file then
local files = {}
@@ -596,16 +612,22 @@ function check_external_deps(rockspec, mode)
if f:match("%.so$") or f:match("%.dylib$") or f:match("%.dll$") then
f = f:gsub("%.[^.]+$", "."..cfg.external_lib_extension)
end
- if f:match("%*") then
- local replaced = f:gsub("%.", "%%."):gsub("%*", ".*")
- for _, entry in ipairs(fs.list_dir(dirdata.dir)) do
- if entry:match(replaced) then
- found = true
- break
+ for _, d in ipairs(paths) do
+ if f:match("%*") then
+ local replaced = f:gsub("%.", "%%."):gsub("%*", ".*")
+ for entry in fs.dir(d) do
+ if entry:match(replaced) then
+ found = true
+ break
+ end
end
+ else
+ found = fs.is_file(dir.path(d, f))
+ end
+ if found then
+ dirdata.dir = d
+ break
end
- else
- found = fs.is_file(dir.path(dirdata.dir, f))
end
if found then
break
@@ -648,7 +670,7 @@ end
-- @param name string: Package name.
-- @param version string: Package version.
-- @return (table, table): The results and a table of missing dependencies.
-function scan_deps(results, missing, manifest, name, version, deps_mode)
+function deps.scan_deps(results, missing, manifest, name, version, deps_mode)
assert(type(results) == "table")
assert(type(missing) == "table")
assert(type(manifest) == "table")
@@ -668,7 +690,7 @@ function scan_deps(results, missing, manifest, name, version, deps_mode)
local deplist = dependencies_name[version]
local rockspec, err
if not deplist then
- rockspec, err = fetch.load_local_rockspec(path.rockspec_file(name, version))
+ rockspec, err = fetch.load_local_rockspec(path.rockspec_file(name, version), false)
if err then
missing[name.." "..version] = err
return results, missing
@@ -677,13 +699,14 @@ function scan_deps(results, missing, manifest, name, version, deps_mode)
else
rockspec = { dependencies = deplist }
end
- local matched, failures = match_deps(rockspec, nil, deps_mode)
+ local matched, failures = deps.match_deps(rockspec, nil, deps_mode)
+ results[name] = results
for _, match in pairs(matched) do
- results, missing = scan_deps(results, missing, manifest, match.name, match.version, deps_mode)
+ results, missing = deps.scan_deps(results, missing, manifest, match.name, match.version, deps_mode)
end
if next(failures) then
for _, failure in pairs(failures) do
- missing[show_dep(failure)] = "failed"
+ missing[deps.show_dep(failure)] = "failed"
end
end
results[name] = version
@@ -697,11 +720,11 @@ local valid_deps_modes = {
none = true,
}
-function check_deps_mode_flag(flag)
+function deps.check_deps_mode_flag(flag)
return valid_deps_modes[flag]
end
-function get_deps_mode(flags)
+function deps.get_deps_mode(flags)
if flags["deps-mode"] then
return flags["deps-mode"]
else
@@ -709,6 +732,8 @@ function get_deps_mode(flags)
end
end
-function deps_mode_to_flag(deps_mode)
+function deps.deps_mode_to_flag(deps_mode)
return "--deps-mode="..deps_mode
end
+
+return deps
diff --git a/src/luarocks/dir.lua b/src/luarocks/dir.lua
index b496c96..2ef9881 100644
--- a/src/luarocks/dir.lua
+++ b/src/luarocks/dir.lua
@@ -1,14 +1,16 @@
--- Generic utilities for handling pathnames.
-module("luarocks.dir", package.seeall)
+--module("luarocks.dir", package.seeall)
+local dir = {}
+package.loaded["luarocks.dir"] = dir
-separator = "/"
+dir.separator = "/"
--- Strip the path off a path+filename.
-- @param pathname string: A path+name, such as "/a/b/c"
-- or "\a\b\c".
-- @return string: The filename without its path, such as "c".
-function base_name(pathname)
+function dir.base_name(pathname)
assert(type(pathname) == "string")
local base = pathname:gsub("[/\\]*$", ""):match(".*[/\\]([^/\\]*)")
@@ -17,13 +19,12 @@ end
--- Strip the name off a path+filename.
-- @param pathname string: A path+name, such as "/a/b/c".
--- @return string: The filename without its path, such as "/a/b/".
--- For entries such as "/a/b/", "/a/" is returned. If there are
+-- @return string: The filename without its path, such as "/a/b".
+-- For entries such as "/a/b/", "/a" is returned. If there are
-- no directory separators in input, "" is returned.
-function dir_name(pathname)
+function dir.dir_name(pathname)
assert(type(pathname) == "string")
-
- return (pathname:gsub("/*$", ""):match("(.*/)[^/]*")) or ""
+ return (pathname:gsub("/*$", ""):match("(.*)[/]+[^/]*")) or ""
end
--- Describe a path in a cross-platform way.
@@ -35,18 +36,12 @@ end
-- @param ... strings representing directories
-- @return string: a string with a platform-specific representation
-- of the path.
-function path(...)
- local items = {...}
- local i = 1
- while items[i] do
- items[i] = items[i]:gsub("(.+)/+$", "%1")
- if items[i] == "" then
- table.remove(items, i)
- else
- i = i + 1
- end
+function dir.path(...)
+ local t = {...}
+ while t[1] == "" do
+ table.remove(t, 1)
end
- return (table.concat(items, "/"):gsub("(.+)/+$", "%1"))
+ return (table.concat(t, "/"):gsub("([^:])/+", "%1/"):gsub("^/+", "/"):gsub("/*$", ""))
end
--- Split protocol and path from an URL or local pathname.
@@ -54,7 +49,7 @@ end
-- For local pathnames, "file" is returned as the protocol.
-- @param url string: an URL or a local pathname.
-- @return string, string: the protocol, and the pathname without the protocol.
-function split_url(url)
+function dir.split_url(url)
assert(type(url) == "string")
local protocol, pathname = url:match("^([^:]*)://(.*)")
@@ -65,6 +60,16 @@ function split_url(url)
return protocol, pathname
end
-function normalize(name)
- return name:gsub("\\", "/"):gsub("(.)/*$", "%1")
+--- Normalize a url or local path.
+-- URLs should be in the "protocol://path" format. System independent
+-- forward slashes are used, removing trailing and double slashes
+-- @param url string: an URL or a local pathname.
+-- @return string: Normalized result.
+function dir.normalize(name)
+ local protocol, pathname = dir.split_url(name)
+ pathname = pathname:gsub("\\", "/"):gsub("(.)/*$", "%1"):gsub("//", "/")
+ if protocol ~= "file" then pathname = protocol .."://"..pathname end
+ return pathname
end
+
+return dir
diff --git a/src/luarocks/doc.lua b/src/luarocks/doc.lua
new file mode 100644
index 0000000..6dee106
--- /dev/null
+++ b/src/luarocks/doc.lua
@@ -0,0 +1,156 @@
+
+--- Module implementing the LuaRocks "doc" command.
+-- Shows documentation for an installed rock.
+--module("luarocks.doc", package.seeall)
+local doc = {}
+package.loaded["luarocks.doc"] = doc
+
+local util = require("luarocks.util")
+local show = require("luarocks.show")
+local path = require("luarocks.path")
+local dir = require("luarocks.dir")
+local fetch = require("luarocks.fetch")
+local fs = require("luarocks.fs")
+local download = require("luarocks.download")
+
+doc.help_summary = "Shows documentation for an installed rock."
+
+doc.help = [[
+<argument> is an existing package name.
+Without any flags, tries to load the documentation
+using a series of heuristics.
+With these flags, return only the desired information:
+
+--homepage Open the home page of project.
+--list List documentation files only.
+
+For more information about a rock, see the 'show' command.
+]]
+
+local function show_homepage(homepage, name, version)
+ if not homepage then
+ return nil, "No 'homepage' field in rockspec for "..name.." "..version
+ end
+ util.printout("Opening "..homepage.." ...")
+ fs.browser(homepage)
+ return true
+end
+
+local function try_to_open_homepage(name, version)
+ local temp_dir, err = fs.make_temp_dir("doc-"..name.."-"..(version or ""))
+ if not temp_dir then
+ return nil, "Failed creating temporary directory: "..err
+ end
+ util.schedule_function(fs.delete, temp_dir)
+ local ok, err = fs.change_dir(temp_dir)
+ if not ok then return nil, err end
+ local filename, err = download.download("rockspec", name, version)
+ if not filename then return nil, err end
+ local rockspec, err = fetch.load_local_rockspec(filename)
+ if not rockspec then return nil, err end
+ fs.pop_dir()
+ local descript = rockspec.description or {}
+ if not descript.homepage then return nil, "No homepage defined for "..name end
+ return show_homepage(descript.homepage, name, version)
+end
+
+--- Driver function for "doc" command.
+-- @param name or nil: an existing package name.
+-- @param version string or nil: a version may also be passed.
+-- @return boolean: True if succeeded, nil on errors.
+function doc.run(...)
+ local flags, name, version = util.parse_flags(...)
+ if not name then
+ return nil, "Argument missing. "..util.see_help("doc")
+ end
+
+ local iname, iversion, repo = show.pick_installed_rock(name, version, flags["tree"])
+ if not iname then
+ util.printout(name..(version and " "..version or "").." is not installed. Looking for it in the rocks servers...")
+ return try_to_open_homepage(name, version)
+ end
+ name, version = iname, iversion
+
+ local rockspec, err = fetch.load_local_rockspec(path.rockspec_file(name, version, repo))
+ if not rockspec then return nil,err end
+ local descript = rockspec.description or {}
+
+ if flags["homepage"] then
+ return show_homepage(descript.homepage, name, version)
+ end
+
+ local directory = path.install_dir(name,version,repo)
+
+ local docdir
+ local directories = { "doc", "docs" }
+ for _, d in ipairs(directories) do
+ local dirname = dir.path(directory, d)
+ if fs.is_dir(dirname) then
+ docdir = dirname
+ break
+ end
+ end
+ if not docdir then
+ if descript.homepage and not flags["list"] then
+ util.printout("Local documentation directory not found -- opening "..descript.homepage.." ...")
+ fs.browser(descript.homepage)
+ return true
+ end
+ return nil, "Documentation directory not found for "..name.." "..version
+ end
+
+ docdir = dir.normalize(docdir):gsub("/+", "/")
+ local files = fs.find(docdir)
+ local htmlpatt = "%.html?$"
+ local extensions = { htmlpatt, "%.md$", "%.txt$", "%.textile$", "" }
+ local basenames = { "index", "readme", "manual" }
+
+ local porcelain = flags["porcelain"]
+ if #files > 0 then
+ util.title("Documentation files for "..name.." "..version, porcelain)
+ if porcelain then
+ for _, file in ipairs(files) do
+ util.printout(docdir.."/"..file)
+ end
+ else
+ util.printout(docdir.."/")
+ for _, file in ipairs(files) do
+ util.printout("\t"..file)
+ end
+ end
+ end
+
+ if flags["list"] then
+ return true
+ end
+
+ for _, extension in ipairs(extensions) do
+ for _, basename in ipairs(basenames) do
+ local filename = basename..extension
+ local found
+ for _, file in ipairs(files) do
+ if file:lower():match(filename) and ((not found) or #file < #found) then
+ found = file
+ end
+ end
+ if found then
+ local pathname = dir.path(docdir, found)
+ util.printout()
+ util.printout("Opening "..pathname.." ...")
+ util.printout()
+ local ok = fs.browser(pathname)
+ if not ok and not pathname:match(htmlpatt) then
+ local fd = io.open(pathname, "r")
+ util.printout(fd:read("*a"))
+ fd:close()
+ end
+ return true
+ end
+ end
+ end
+
+ return true
+end
+
+
+return doc
diff --git a/src/luarocks/download.lua b/src/luarocks/download.lua
index 0012cb1..74ed40e 100644
--- a/src/luarocks/download.lua
+++ b/src/luarocks/download.lua
@@ -1,24 +1,42 @@
--- Module implementing the luarocks "download" command.
-- Download a rock from the repository.
-module("luarocks.download", package.seeall)
+--module("luarocks.download", package.seeall)
+local download = {}
+package.loaded["luarocks.download"] = download
local util = require("luarocks.util")
local path = require("luarocks.path")
local fetch = require("luarocks.fetch")
local search = require("luarocks.search")
+local fs = require("luarocks.fs")
+local dir = require("luarocks.dir")
-help_summary = "Download a specific rock file from a rocks server."
-help_arguments = "[--all] [--arch=<arch> | --source | --rockspec] [<name> [<version>]]"
+download.help_summary = "Download a specific rock file from a rocks server."
+download.help_arguments = "[--all] [--arch=<arch> | --source | --rockspec] [<name> [<version>]]"
-help = [[
+download.help = [[
--all Download all files if there are multiple matches.
--source Download .src.rock if available.
--rockspec Download .rockspec if available.
--arch=<arch> Download rock for a specific architecture.
]]
-function download(arch, name, version, all)
+local function get_file(filename)
+ local protocol, pathname = dir.split_url(filename)
+ if protocol == "file" then
+ local ok, err = fs.copy(pathname, fs.current_dir())
+ if ok then
+ return pathname
+ else
+ return nil, err
+ end
+ else
+ return fetch.fetch_url(filename)
+ end
+end
+
+function download.download(arch, name, version, all)
local results, err
local query = search.make_query(name, version)
if arch then query.arch = arch end
@@ -29,8 +47,7 @@ function download(arch, name, version, all)
results, err = search.find_suitable_rock(query)
end
if type(results) == "string" then
- local file = fetch.fetch_url(results)
- return file
+ return get_file(results)
elseif type(results) == "table" and next(results) then
if all then
local all_ok = true
@@ -39,7 +56,7 @@ function download(arch, name, version, all)
for version, versions in pairs(result) do
for _,items in pairs(versions) do
local filename = path.make_url(items.repo, name, version, items.arch)
- local ok, err = fetch.fetch_url(filename)
+ local ok, err = get_file(filename)
if not ok then
all_ok = false
any_err = any_err .. "\n" .. err
@@ -64,7 +81,7 @@ end
-- version may also be passed.
-- @return boolean or (nil, string): true if successful or nil followed
-- by an error message.
-function run(...)
+function download.run(...)
local flags, name, version = util.parse_flags(...)
assert(type(version) == "string" or not version)
@@ -83,6 +100,8 @@ function run(...)
arch = flags["arch"]
end
- local dl, err = download(arch, name, version, flags["all"])
+ local dl, err = download.download(arch, name, version, flags["all"])
return dl and true, err
end
+
+return download
diff --git a/src/luarocks/fetch.lua b/src/luarocks/fetch.lua
index bfdbace..980c8fe 100644
--- a/src/luarocks/fetch.lua
+++ b/src/luarocks/fetch.lua
@@ -1,6 +1,8 @@
--- Functions related to fetching and loading local and remote files.
-module("luarocks.fetch", package.seeall)
+--module("luarocks.fetch", package.seeall)
+local fetch = {}
+package.loaded["luarocks.fetch"] = fetch
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
@@ -11,6 +13,10 @@ local persist = require("luarocks.persist")
local util = require("luarocks.util")
local cfg = require("luarocks.cfg")
+function fetch.is_basic_protocol(protocol, remote)
+ return protocol == "http" or protocol == "https" or protocol == "ftp" or (not remote and protocol == "file")
+end
+
--- Fetch a local or remote file.
-- Make a remote or local URL/pathname local, fetching the file if necessary.
-- Other "fetch" and "load" functions use this function to obtain files.
@@ -23,19 +29,19 @@ local cfg = require("luarocks.cfg")
-- @return string or (nil, string, [string]): the absolute local pathname for the
-- fetched file, or nil and a message in case of errors, followed by
-- an optional error code.
-function fetch_url(url, filename)
+function fetch.fetch_url(url, filename, cache)
assert(type(url) == "string")
assert(type(filename) == "string" or not filename)
local protocol, pathname = dir.split_url(url)
if protocol == "file" then
return fs.absolute_name(pathname)
- elseif protocol == "http" or protocol == "ftp" or protocol == "https" then
- local ok, err = fs.download(url, filename)
+ elseif fetch.is_basic_protocol(protocol, true) then
+ local ok, filename = fs.download(url, filename, cache)
if not ok then
- return nil, "Failed downloading "..url..(err and " - "..err or ""), "network"
+ return nil, "Failed downloading "..url..(filename and " - "..filename or ""), "network"
end
- return dir.path(fs.current_dir(), filename or dir.base_name(url))
+ return filename
else
return nil, "Unsupported protocol "..protocol
end
@@ -52,7 +58,7 @@ end
-- @return (string, string) or (nil, string, [string]): absolute local pathname of
-- the fetched file and temporary directory name; or nil and an error message
-- followed by an optional error code
-function fetch_url_at_temp_dir(url, tmpname, filename)
+function fetch.fetch_url_at_temp_dir(url, tmpname, filename)
assert(type(url) == "string")
assert(type(tmpname) == "string")
assert(type(filename) == "string" or not filename)
@@ -66,13 +72,14 @@ function fetch_url_at_temp_dir(url, tmpname, filename)
return nil, "File not found: "..pathname
end
else
- local temp_dir = fs.make_temp_dir(tmpname)
+ local temp_dir, err = fs.make_temp_dir(tmpname)
if not temp_dir then
- return nil, "Failed creating temporary directory."
+ return nil, "Failed creating temporary directory "..tmpname..": "..err
end
util.schedule_function(fs.delete, temp_dir)
- fs.change_dir(temp_dir)
- local file, err, errcode = fetch_url(url, filename)
+ local ok, err = fs.change_dir(temp_dir)
+ if not ok then return nil, err end
+ local file, err, errcode = fetch.fetch_url(url, filename)
fs.pop_dir()
if not file then
return nil, "Error fetching file: "..err, errcode
@@ -81,6 +88,44 @@ function fetch_url_at_temp_dir(url, tmpname, filename)
end
end
+-- Determine base directory of a fetched URL by extracting its
+-- archive and looking for a directory in the root.
+-- @param file string: absolute local pathname of the fetched file
+-- @param temp_dir string: temporary directory in which URL was fetched.
+-- @param src_url string: URL to use when inferring base directory.
+-- @param src_dir string or nil: expected base directory (inferred
+-- from src_url if not given).
+-- @return (string, string) or (string, nil) or (nil, string):
+-- The inferred base directory and the one actually found (which may
+-- be nil if not found), or nil followed by an error message.
+-- The inferred dir is returned first to avoid confusion with errors,
+-- because it is never nil.
+function fetch.find_base_dir(file, temp_dir, src_url, src_dir)
+ local ok, err = fs.change_dir(temp_dir)
+ if not ok then return nil, err end
+ fs.unpack_archive(file)
+ local inferred_dir = src_dir or fetch.url_to_base_dir(src_url)
+ local found_dir = nil
+ if fs.exists(inferred_dir) then
+ found_dir = inferred_dir
+ else
+ util.printerr("Directory "..inferred_dir.." not found")
+ local files = fs.list_dir()
+ if files then
+ table.sort(files)
+ for i,filename in ipairs(files) do
+ if fs.is_dir(filename) then
+ util.printerr("Found "..filename)
+ found_dir = filename
+ break
+ end
+ end
+ end
+ end
+ fs.pop_dir()
+ return inferred_dir, found_dir
+end
+
--- Obtain a rock and unpack it.
-- If a directory is not given, a temporary directory will be created,
-- which will be deleted on program termination.
@@ -89,13 +134,13 @@ end
-- a permanent destination.
-- @return string or (nil, string, [string]): the directory containing the contents
-- of the unpacked rock.
-function fetch_and_unpack_rock(rock_file, dest)
+function fetch.fetch_and_unpack_rock(rock_file, dest)
assert(type(rock_file) == "string")
assert(type(dest) == "string" or not dest)
local name = dir.base_name(rock_file):match("(.*)%.[^.]*%.rock")
- local rock_file, err, errcode = fetch_url_at_temp_dir(rock_file,"luarocks-rock-"..name)
+ local rock_file, err, errcode = fetch.fetch_url_at_temp_dir(rock_file,"luarocks-rock-"..name)
if not rock_file then
return nil, "Could not fetch rock file: " .. err, errcode
end
@@ -104,15 +149,19 @@ function fetch_and_unpack_rock(rock_file, dest)
local unpack_dir
if dest then
unpack_dir = dest
- fs.make_dir(unpack_dir)
+ local ok, err = fs.make_dir(unpack_dir)
+ if not ok then
+ return nil, "Failed unpacking rock file: " .. err
+ end
else
unpack_dir = fs.make_temp_dir(name)
end
if not dest then
util.schedule_function(fs.delete, unpack_dir)
end
- fs.change_dir(unpack_dir)
- local ok = fs.unzip(rock_file)
+ local ok, err = fs.change_dir(unpack_dir)
+ if not ok then return nil, err end
+ ok = fs.unzip(rock_file)
if not ok then
return nil, "Failed unpacking rock file: " .. rock_file
end
@@ -120,7 +169,7 @@ function fetch_and_unpack_rock(rock_file, dest)
return unpack_dir
end
-function url_to_base_dir(url)
+function fetch.url_to_base_dir(url)
local base = dir.base_name(url)
return base:gsub("%.[^.]*$", ""):gsub("%.tar$", "")
end
@@ -128,19 +177,28 @@ end
--- Back-end function that actually loads the local rockspec.
-- Performs some validation and postprocessing of the rockspec contents.
-- @param filename string: The local filename of the rockspec file.
+-- @param quick boolean: if true, skips some steps when loading
+-- rockspec.
-- @return table or (nil, string): A table representing the rockspec
-- or nil followed by an error message.
-function load_local_rockspec(filename)
+function fetch.load_local_rockspec(filename, quick)
assert(type(filename) == "string")
filename = fs.absolute_name(filename)
local rockspec, err = persist.load_into_table(filename)
if not rockspec then
return nil, "Could not load rockspec file "..filename.." ("..err..")"
end
+ if cfg.branch and (type(rockspec.source) == "table") then
+ rockspec.source.branch = cfg.branch
+ end
+ local globals = err
- local ok, err = type_check.type_check_rockspec(rockspec)
- if not ok then
- return nil, filename..": "..err
+ local ok, err = true, nil
+ if not quick then
+ ok, err = type_check.type_check_rockspec(rockspec, globals)
+ if not ok then
+ return nil, filename..": "..err
+ end
end
if rockspec.rockspec_format then
@@ -166,7 +224,7 @@ function load_local_rockspec(filename)
end
local protocol, pathname = dir.split_url(rockspec.source.url)
- if protocol == "http" or protocol == "https" or protocol == "ftp" or protocol == "file" then
+ if fetch.is_basic_protocol(protocol) then
rockspec.source.file = rockspec.source.file or dir.base_name(rockspec.source.url)
end
rockspec.source.protocol, rockspec.source.pathname = protocol, pathname
@@ -182,10 +240,10 @@ function load_local_rockspec(filename)
rockspec.local_filename = filename
local filebase = rockspec.source.file or rockspec.source.url
- local base = url_to_base_dir(filebase)
+ local base = fetch.url_to_base_dir(filebase)
rockspec.source.dir = rockspec.source.dir
or rockspec.source.module
- or ((filebase:match(".lua$") or filebase:match(".c$")) and ".")
+ or ((filebase:match("%.lua$") or filebase:match("%.c$")) and ".")
or base
if rockspec.dependencies then
for i = 1, #rockspec.dependencies do
@@ -198,9 +256,8 @@ function load_local_rockspec(filename)
else
rockspec.dependencies = {}
end
- local ok, err = path.configure_paths(rockspec)
- if err then
- return nil, "Error verifying paths: "..err
+ if not quick then
+ path.configure_paths(rockspec)
end
return rockspec
@@ -215,7 +272,7 @@ end
-- a temporary dir is created.
-- @return table or (nil, string, [string]): A table representing the rockspec
-- or nil followed by an error message and optional error code.
-function load_rockspec(filename, location)
+function fetch.load_rockspec(filename, location)
assert(type(filename) == "string")
local name
@@ -224,35 +281,37 @@ function load_rockspec(filename, location)
name = "rockspec"
else
name = basename:match("(.*)%.rockspec")
- if not name and not basename == "rockspec" then
+ if not name then
return nil, "Filename '"..filename.."' does not look like a rockspec."
end
end
local err, errcode
if location then
- fs.change_dir(location)
- filename, err = fetch_url(filename)
+ local ok, err = fs.change_dir(location)
+ if not ok then return nil, err end
+ filename, err = fetch.fetch_url(filename)
fs.pop_dir()
else
- filename, err, errcode = fetch_url_at_temp_dir(filename,"luarocks-rockspec-"..name)
+ filename, err, errcode = fetch.fetch_url_at_temp_dir(filename,"luarocks-rockspec-"..name)
end
if not filename then
return nil, err, errcode
end
- return load_local_rockspec(filename)
+ return fetch.load_local_rockspec(filename)
end
--- Download sources for building a rock using the basic URL downloader.
-- @param rockspec table: The rockspec table
-- @param extract boolean: Whether to extract the sources from
-- the fetched source tarball or not.
--- @param dest_dir string or nil: If set, will extract to the given directory.
+-- @param dest_dir string or nil: If set, will extract to the given directory;
+-- if not given, will extract to a temporary directory.
-- @return (string, string) or (nil, string, [string]): The absolute pathname of
-- the fetched source tarball and the temporary directory created to
-- store it; or nil and an error message and optional error code.
-function get_sources(rockspec, extract, dest_dir)
+function fetch.get_sources(rockspec, extract, dest_dir)
assert(type(rockspec) == "table")
assert(type(extract) == "boolean")
assert(type(dest_dir) == "string" or not dest_dir)
@@ -262,26 +321,28 @@ function get_sources(rockspec, extract, dest_dir)
local filename = rockspec.source.file
local source_file, store_dir, err, errcode
if dest_dir then
- fs.change_dir(dest_dir)
- source_file, err, errcode = fetch_url(url, filename)
+ local ok, err = fs.change_dir(dest_dir)
+ if not ok then return nil, err, "dest_dir" end
+ source_file, err, errcode = fetch.fetch_url(url, filename)
fs.pop_dir()
store_dir = dest_dir
else
- source_file, store_dir, errcode = fetch_url_at_temp_dir(url, "luarocks-source-"..name, filename)
+ source_file, store_dir, errcode = fetch.fetch_url_at_temp_dir(url, "luarocks-source-"..name, filename)
end
if not source_file then
return nil, err or store_dir, errcode
end
if rockspec.source.md5 then
if not fs.check_md5(source_file, rockspec.source.md5) then
- return nil, "MD5 check for "..filename.." has failed."
+ return nil, "MD5 check for "..filename.." has failed.", "md5"
end
end
if extract then
- fs.change_dir(store_dir)
+ local ok, err = fs.change_dir(store_dir)
+ if not ok then return nil, err end
fs.unpack_archive(rockspec.source.file)
if not fs.exists(rockspec.source.dir) then
- return nil, "Directory "..rockspec.source.dir.." not found inside archive "..rockspec.source.file
+ return nil, "Directory "..rockspec.source.dir.." not found inside archive "..rockspec.source.file, "source.dir", source_file, store_dir
end
fs.pop_dir()
end
@@ -293,17 +354,18 @@ end
-- @param extract boolean: When downloading compressed formats, whether to extract
-- the sources from the fetched archive or not.
-- @param dest_dir string or nil: If set, will extract to the given directory.
+-- if not given, will extract to a temporary directory.
-- @return (string, string) or (nil, string): The absolute pathname of
-- the fetched source tarball and the temporary directory created to
-- store it; or nil and an error message.
-function fetch_sources(rockspec, extract, dest_dir)
+function fetch.fetch_sources(rockspec, extract, dest_dir)
assert(type(rockspec) == "table")
assert(type(extract) == "boolean")
assert(type(dest_dir) == "string" or not dest_dir)
local protocol = rockspec.source.protocol
local ok, proto
- if protocol == "http" or protocol == "https" or protocol == "ftp" or protocol == "file" then
+ if fetch.is_basic_protocol(protocol) then
proto = require("luarocks.fetch")
else
ok, proto = pcall(require, "luarocks.fetch."..protocol:gsub("[+-]", "_"))
@@ -323,3 +385,5 @@ function fetch_sources(rockspec, extract, dest_dir)
end
return proto.get_sources(rockspec, extract, dest_dir)
end
+
+return fetch
diff --git a/src/luarocks/fetch/cvs.lua b/src/luarocks/fetch/cvs.lua
index a622cdc..cc9fd65 100644
--- a/src/luarocks/fetch/cvs.lua
+++ b/src/luarocks/fetch/cvs.lua
@@ -1,6 +1,9 @@
--- Fetch back-end for retrieving sources from CVS.
-module("luarocks.fetch.cvs", package.seeall)
+--module("luarocks.fetch.cvs", package.seeall)
+local cvs = {}
+
+local unpack = unpack or table.unpack
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
@@ -13,7 +16,7 @@ local util = require("luarocks.util")
-- @return (string, string) or (nil, string): The absolute pathname of
-- the fetched source tarball and the temporary directory created to
-- store it; or nil and an error message.
-function get_sources(rockspec, extract, dest_dir)
+function cvs.get_sources(rockspec, extract, dest_dir)
assert(type(rockspec) == "table")
assert(type(dest_dir) == "string" or not dest_dir)
@@ -34,7 +37,8 @@ function get_sources(rockspec, extract, dest_dir)
else
store_dir = dest_dir
end
- fs.change_dir(store_dir)
+ local ok, err = fs.change_dir(store_dir)
+ if not ok then return nil, err end
if not fs.execute(unpack(command)) then
return nil, "Failed fetching files from CVS."
end
@@ -42,3 +46,5 @@ function get_sources(rockspec, extract, dest_dir)
return module, store_dir
end
+
+return cvs
diff --git a/src/luarocks/fetch/git.lua b/src/luarocks/fetch/git.lua
index e7c8943..53fd444 100644
--- a/src/luarocks/fetch/git.lua
+++ b/src/luarocks/fetch/git.lua
@@ -1,6 +1,9 @@
--- Fetch back-end for retrieving sources from GIT.
-module("luarocks.fetch.git", package.seeall)
+--module("luarocks.fetch.git", package.seeall)
+local git = {}
+
+local unpack = unpack or table.unpack
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
@@ -11,13 +14,13 @@ local util = require("luarocks.util")
-- clone by tag then we'll have to issue a subsequent command to check out the
-- given tag.
-- @return boolean: Whether Git can clone by tag.
-local function git_can_clone_by_tag()
- local version_string = io.popen('git --version'):read()
+local function git_can_clone_by_tag(git_cmd)
+ local version_string = io.popen(fs.Q(git_cmd)..' --version'):read()
local major, minor, tiny = version_string:match('(%d-)%.(%d+)%.?(%d*)')
major, minor, tiny = tonumber(major), tonumber(minor), tonumber(tiny) or 0
local value = major > 1 or (major == 1 and (minor > 7 or (minor == 7 and tiny >= 10)))
git_can_clone_by_tag = function() return value end
- return git_can_clone_by_tag()
+ return value
end
--- Download sources for building a rock, using git.
@@ -27,7 +30,7 @@ end
-- @return (string, string) or (nil, string): The absolute pathname of
-- the fetched source tarball and the temporary directory created to
-- store it; or nil and an error message.
-function get_sources(rockspec, extract, dest_dir)
+function git.get_sources(rockspec, extract, dest_dir, depth)
assert(type(rockspec) == "table")
assert(type(dest_dir) == "string" or not dest_dir)
@@ -48,15 +51,16 @@ function get_sources(rockspec, extract, dest_dir)
store_dir = dest_dir
end
store_dir = fs.absolute_name(store_dir)
- fs.change_dir(store_dir)
+ local ok, err = fs.change_dir(store_dir)
+ if not ok then return nil, err end
- local command = {git_cmd, "clone", "--depth=1", rockspec.source.url, module}
+ local command = {fs.Q(git_cmd), "clone", depth or "--depth=1", rockspec.source.url, module}
local tag_or_branch = rockspec.source.tag or rockspec.source.branch
-- If the tag or branch is explicitly set to "master" in the rockspec, then
-- we can avoid passing it to Git since it's the default.
if tag_or_branch == "master" then tag_or_branch = nil end
if tag_or_branch then
- if git_can_clone_by_tag() then
+ if git_can_clone_by_tag(git_cmd) then
-- The argument to `--branch` can actually be a branch or a tag as of
-- Git 1.7.10.
table.insert(command, 4, "--branch=" .. tag_or_branch)
@@ -65,9 +69,10 @@ function get_sources(rockspec, extract, dest_dir)
if not fs.execute(unpack(command)) then
return nil, "Failed cloning git repository."
end
- fs.change_dir(module)
+ ok, err = fs.change_dir(module)
+ if not ok then return nil, err end
if tag_or_branch and not git_can_clone_by_tag() then
- local checkout_command = {git_cmd, "checkout", tag_or_branch}
+ local checkout_command = {fs.Q(git_cmd), "checkout", tag_or_branch}
if not fs.execute(unpack(checkout_command)) then
return nil, 'Failed to check out the "' .. tag_or_branch ..'" tag or branch.'
end
@@ -79,3 +84,5 @@ function get_sources(rockspec, extract, dest_dir)
fs.pop_dir()
return module, store_dir
end
+
+return git
diff --git a/src/luarocks/fetch/git_file.lua b/src/luarocks/fetch/git_file.lua
index 1b18d0f..0144bc2 100644
--- a/src/luarocks/fetch/git_file.lua
+++ b/src/luarocks/fetch/git_file.lua
@@ -1,6 +1,7 @@
--- Fetch back-end for retrieving sources from local Git repositories.
-module("luarocks.fetch.git_file", package.seeall)
+--module("luarocks.fetch.git_file", package.seeall)
+local git_file = {}
local git = require("luarocks.fetch.git")
@@ -11,7 +12,9 @@ local git = require("luarocks.fetch.git")
-- @return (string, string) or (nil, string): The absolute pathname of
-- the fetched source tarball and the temporary directory created to
-- store it; or nil and an error message.
-function get_sources(rockspec, extract, dest_dir)
+function git_file.get_sources(rockspec, extract, dest_dir)
rockspec.source.url = rockspec.source.url:gsub("^git.file://", "")
return git.get_sources(rockspec, extract, dest_dir)
end
+
+return git_file
diff --git a/src/luarocks/fetch/git_http.lua b/src/luarocks/fetch/git_http.lua
new file mode 100644
index 0000000..4ecd481
--- /dev/null
+++ b/src/luarocks/fetch/git_http.lua
@@ -0,0 +1,27 @@
+
+--- Fetch back-end for retrieving sources from Git repositories
+-- that use http:// transport. For example, for fetching a repository
+-- that requires the following command line:
+-- `git clone http://example.com/foo.git`
+-- you can use this in the rockspec:
+-- source = { url = "git+http://example.com/foo.git" }
+-- Prefer using the normal git:// fetch mode as it is more widely
+-- available in older versions of LuaRocks.
+--module("luarocks.fetch.git_http", package.seeall)
+local git_http = {}
+
+local git = require("luarocks.fetch.git")
+
+--- Fetch sources for building a rock from a local Git repository.
+-- @param rockspec table: The rockspec table
+-- @param extract boolean: Unused in this module (required for API purposes.)
+-- @param dest_dir string or nil: If set, will extract to the given directory.
+-- @return (string, string) or (nil, string): The absolute pathname of
+-- the fetched source tarball and the temporary directory created to
+-- store it; or nil and an error message.
+function git_http.get_sources(rockspec, extract, dest_dir)
+ rockspec.source.url = rockspec.source.url:gsub("^git.", "")
+ return git.get_sources(rockspec, extract, dest_dir, "--")
+end
+
+return git_http
diff --git a/src/luarocks/fetch/hg.lua b/src/luarocks/fetch/hg.lua
index a08520a..b2ba56e 100644
--- a/src/luarocks/fetch/hg.lua
+++ b/src/luarocks/fetch/hg.lua
@@ -1,6 +1,9 @@
--- Fetch back-end for retrieving sources from HG.
-module("luarocks.fetch.hg", package.seeall)
+--module("luarocks.fetch.hg", package.seeall)
+local hg = {}
+
+local unpack = unpack or table.unpack
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
@@ -13,7 +16,7 @@ local util = require("luarocks.util")
-- @return (string, string) or (nil, string): The absolute pathname of
-- the fetched source tarball and the temporary directory created to
-- store it; or nil and an error message.
-function get_sources(rockspec, extract, dest_dir)
+function hg.get_sources(rockspec, extract, dest_dir)
assert(type(rockspec) == "table")
assert(type(dest_dir) == "string" or not dest_dir)
@@ -39,11 +42,13 @@ function get_sources(rockspec, extract, dest_dir)
else
store_dir = dest_dir
end
- fs.change_dir(store_dir)
+ local ok, err = fs.change_dir(store_dir)
+ if not ok then return nil, err end
if not fs.execute(unpack(command)) then
return nil, "Failed cloning hg repository."
end
- fs.change_dir(module)
+ ok, err = fs.change_dir(module)
+ if not ok then return nil, err end
fs.delete(dir.path(store_dir, module, ".hg"))
fs.delete(dir.path(store_dir, module, ".hgignore"))
@@ -52,3 +57,5 @@ function get_sources(rockspec, extract, dest_dir)
return module, store_dir
end
+
+return hg
diff --git a/src/luarocks/fetch/sscm.lua b/src/luarocks/fetch/sscm.lua
index e52e801..53ae86a 100644
--- a/src/luarocks/fetch/sscm.lua
+++ b/src/luarocks/fetch/sscm.lua
@@ -1,6 +1,7 @@
--- Fetch back-end for retrieving sources from Surround SCM Server
-module("luarocks.fetch.sscm", package.seeall)
+--module("luarocks.fetch.sscm", package.seeall)
+local sscm = {}
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
@@ -12,7 +13,7 @@ local dir = require("luarocks.dir")
-- @return (string, string) or (nil, string): The absolute pathname of
-- the fetched source tarball and the temporary directory created to
-- store it; or nil and an error message.
-function get_sources(rockspec, extract, dest_dir)
+function sscm.get_sources(rockspec, extract, dest_dir)
assert(type(rockspec) == "table")
assert(type(dest_dir) == "string" or not dest_dir)
@@ -40,3 +41,5 @@ function get_sources(rockspec, extract, dest_dir)
-- FIXME: This function does not honor the dest_dir parameter.
return module, working_dir
end
+
+return sscm
diff --git a/src/luarocks/fetch/svn.lua b/src/luarocks/fetch/svn.lua
index a4e952d..abeacf9 100644
--- a/src/luarocks/fetch/svn.lua
+++ b/src/luarocks/fetch/svn.lua
@@ -1,6 +1,9 @@
--- Fetch back-end for retrieving sources from Subversion.
-module("luarocks.fetch.svn", package.seeall)
+--module("luarocks.fetch.svn", package.seeall)
+local svn = {}
+
+local unpack = unpack or table.unpack
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
@@ -13,7 +16,7 @@ local util = require("luarocks.util")
-- @return (string, string) or (nil, string): The absolute pathname of
-- the fetched source tarball and the temporary directory created to
-- store it; or nil and an error message.
-function get_sources(rockspec, extract, dest_dir)
+function svn.get_sources(rockspec, extract, dest_dir)
assert(type(rockspec) == "table")
assert(type(dest_dir) == "string" or not dest_dir)
@@ -36,11 +39,13 @@ function get_sources(rockspec, extract, dest_dir)
else
store_dir = dest_dir
end
- fs.change_dir(store_dir)
+ local ok, err = fs.change_dir(store_dir)
+ if not ok then return nil, err end
if not fs.execute(unpack(command)) then
return nil, "Failed fetching files from Subversion."
end
- fs.change_dir(module)
+ ok, err = fs.change_dir(module)
+ if not ok then return nil, err end
for _, d in ipairs(fs.find(".")) do
if dir.base_name(d) == ".svn" then
fs.delete(dir.path(store_dir, module, d))
@@ -51,3 +56,5 @@ function get_sources(rockspec, extract, dest_dir)
return module, store_dir
end
+
+return svn
diff --git a/src/luarocks/fs.lua b/src/luarocks/fs.lua
index 467b194..72e11c0 100644
--- a/src/luarocks/fs.lua
+++ b/src/luarocks/fs.lua
@@ -7,14 +7,45 @@
local pairs = pairs
-module("luarocks.fs", package.seeall)
+--module("luarocks.fs", package.seeall)
+local fs = {}
+package.loaded["luarocks.fs"] = fs
local cfg = require("luarocks.cfg")
+local pack = table.pack or function(...) return { n = select("#", ...), ... } end
+local unpack = table.unpack or unpack
+
+local old_popen, old_exec
+fs.verbose = function() -- patch io.popen and os.execute to display commands in verbose mode
+ if old_popen or old_exec then return end
+ old_popen = io.popen
+ io.popen = function(one, two)
+ if two == nil then
+ print("\nio.popen: ", one)
+ else
+ print("\nio.popen: ", one, "Mode:", two)
+ end
+ return old_popen(one, two)
+ end
+
+ old_exec = os.execute
+ os.execute = function(cmd)
+ print("\nos.execute: ", cmd)
+ local code = pack(old_exec(cmd))
+ print("Results: "..tostring(code.n))
+ for i = 1,code.n do
+ print(" "..tostring(i).." ("..type(code[i]).."): "..tostring(code[i]))
+ end
+ return unpack(code, 1, code.n)
+ end
+end
+if cfg.verbose then fs.verbose() end
+
local function load_fns(fs_table)
for name, fn in pairs(fs_table) do
- if not _M[name] then
- _M[name] = fn
+ if not fs[name] then
+ fs[name] = fn
end
end
end
@@ -38,3 +69,5 @@ load_fns(fs_lua)
local ok, fs_plat_tools = pcall(require, "luarocks.fs."..loaded_platform..".tools")
if ok and fs_plat_tools then load_fns(fs_plat_tools) end
+
+return fs
diff --git a/src/luarocks/fs/lua.lua b/src/luarocks/fs/lua.lua
index 36b3369..b261905 100644
--- a/src/luarocks/fs/lua.lua
+++ b/src/luarocks/fs/lua.lua
@@ -1,7 +1,8 @@
--- Native Lua implementation of filesystem and platform abstractions,
-- using LuaFileSystem, LZLib, MD5 and LuaCurl.
-module("luarocks.fs.lua", package.seeall)
+-- module("luarocks.fs.lua")
+local fs_lua = {}
local fs = require("luarocks.fs")
@@ -29,17 +30,17 @@ local dir_stack = {}
math.randomseed(os.time())
-dir_separator = "/"
+local dir_separator = "/"
--- Quote argument for shell processing.
-- Adds single quotes and escapes.
-- @param arg string: Unquoted argument.
-- @return string: Quoted argument.
-function Q(arg)
+function fs_lua.Q(arg)
assert(type(arg) == "string")
-- FIXME Unix-specific
- return "'" .. arg:gsub("\\", "\\\\"):gsub("'", "'\\''") .. "'"
+ return "'" .. arg:gsub("'", "'\\''") .. "'"
end
--- Test is file/dir is writable.
@@ -48,7 +49,7 @@ end
-- for checking the result of subsequent operations.
-- @param file string: filename to test
-- @return boolean: true if file exists, false otherwise.
-function is_writable(file)
+function fs_lua.is_writable(file)
assert(file)
file = dir.normalize(file)
local result
@@ -69,17 +70,27 @@ end
--- Create a temporary directory.
-- @param name string: name pattern to use for avoiding conflicts
-- when creating temporary directory.
--- @return string or nil: name of temporary directory or nil on failure.
-function make_temp_dir(name)
+-- @return string or (nil, string): name of temporary directory or (nil, error message) on failure.
+function fs_lua.make_temp_dir(name)
assert(type(name) == "string")
name = dir.normalize(name)
local temp_dir = (os.getenv("TMP") or "/tmp") .. "/luarocks_" .. name:gsub(dir.separator, "_") .. "-" .. tostring(math.floor(math.random() * 10000))
- if fs.make_dir(temp_dir) then
+ local ok, err = fs.make_dir(temp_dir)
+ if ok then
return temp_dir
else
- return nil
+ return nil, err
+ end
+end
+
+local function quote_args(command, ...)
+ local out = { command }
+ for _, arg in ipairs({...}) do
+ assert(type(arg) == "string")
+ out[#out+1] = fs.Q(arg)
end
+ return table.concat(out, " ")
end
--- Run the given command, quoting its arguments.
@@ -89,34 +100,75 @@ end
-- @param ... Strings containing additional arguments, which are quoted.
-- @return boolean: true if command succeeds (status code 0), false
-- otherwise.
-function execute(command, ...)
+function fs_lua.execute(command, ...)
assert(type(command) == "string")
+ return fs.execute_string(quote_args(command, ...))
+end
- for _, arg in ipairs({...}) do
- assert(type(arg) == "string")
- command = command .. " " .. fs.Q(arg)
+--- Run the given command, quoting its arguments, silencing its output.
+-- The command is executed in the current directory in the dir stack.
+-- Silencing is omitted if 'verbose' mode is enabled.
+-- @param command string: The command to be executed. No quoting/escaping
+-- is applied.
+-- @param ... Strings containing additional arguments, which will be quoted.
+-- @return boolean: true if command succeeds (status code 0), false
+-- otherwise.
+function fs_lua.execute_quiet(command, ...)
+ assert(type(command) == "string")
+ if cfg.verbose then -- omit silencing output
+ return fs.execute_string(quote_args(command, ...))
+ else
+ return fs.execute_string(fs.quiet(quote_args(command, ...)))
end
- return fs.execute_string(command)
end
--- Check the MD5 checksum for a file.
-- @param file string: The file to be checked.
-- @param md5sum string: The string with the expected MD5 checksum.
--- @return boolean: true if the MD5 checksum for 'file' equals 'md5sum', false if not
+-- @return boolean: true if the MD5 checksum for 'file' equals 'md5sum', false + msg if not
-- or if it could not perform the check for any reason.
-function check_md5(file, md5sum)
+function fs_lua.check_md5(file, md5sum)
file = dir.normalize(file)
- local computed = fs.get_md5(file)
+ local computed, msg = fs.get_md5(file)
if not computed then
- return false
+ return false, msg
end
if computed:match("^"..md5sum) then
return true
else
- return false
+ return false, "Mismatch MD5 hash for file "..file
end
end
+--- List the contents of a directory.
+-- @param at string or nil: directory to list (will be the current
+-- directory if none is given).
+-- @return table: an array of strings with the filenames representing
+-- the contents of a directory.
+function fs_lua.list_dir(at)
+ local result = {}
+ for file in fs.dir(at) do
+ result[#result+1] = file
+ end
+ return result
+end
+
+--- Iterate over the contents of a directory.
+-- @param at string or nil: directory to list (will be the current
+-- directory if none is given).
+-- @return function: an iterator function suitable for use with
+-- the for statement.
+function fs_lua.dir(at)
+ if not at then
+ at = fs.current_dir()
+ end
+ at = dir.normalize(at)
+ if not fs.is_dir(at) then
+ return function() end
+ end
+ return coroutine.wrap(function() fs.dir_iterator(at) end)
+end
+
---------------------------------------------------------------------
-- LuaFileSystem functions
---------------------------------------------------------------------
@@ -128,20 +180,15 @@ if lfs_ok then
-- @param cmd string: No quoting/escaping is applied to the command.
-- @return boolean: true if command succeeds (status code 0), false
-- otherwise.
-function execute_string(cmd)
- if cfg.verbose then print("Executing: "..cmd) end
+function fs_lua.execute_string(cmd)
local code = os.execute(cmd)
- if code == 0 or code == true then
- return true
- else
- return false
- end
+ return (code == 0 or code == true)
end
--- Obtain current directory.
-- Uses the module's internal dir stack.
-- @return string: the absolute pathname of the current directory.
-function current_dir()
+function fs_lua.current_dir()
return lfs.currentdir()
end
@@ -150,23 +197,23 @@ end
-- semantics of chdir, as it does not handle errors the same way,
-- but works well for our purposes for now.
-- @param d string: The directory to switch to.
-function change_dir(d)
+function fs_lua.change_dir(d)
table.insert(dir_stack, lfs.currentdir())
d = dir.normalize(d)
- lfs.chdir(d)
+ return lfs.chdir(d)
end
--- Change directory to root.
-- Allows leaving a directory (e.g. for deleting it) in
-- a crossplatform way.
-function change_dir_to_root()
+function fs_lua.change_dir_to_root()
table.insert(dir_stack, lfs.currentdir())
lfs.chdir("/") -- works on Windows too
end
--- Change working directory to the previous in the dir stack.
-- @return true if a pop ocurred, false if the stack was empty.
-function pop_dir()
+function fs_lua.pop_dir()
local d = table.remove(dir_stack)
if d then
lfs.chdir(d)
@@ -177,11 +224,11 @@ function pop_dir()
end
--- Create a directory if it does not already exist.
--- If any of the higher levels in the path name does not exist
+-- If any of the higher levels in the path name do not exist
-- too, they are created as well.
-- @param directory string: pathname of directory to create.
--- @return boolean: true on success, false on failure.
-function make_dir(directory)
+-- @return boolean or (boolean, string): true on success or (false, error message) on failure.
+function fs_lua.make_dir(directory)
assert(type(directory) == "string")
directory = dir.normalize(directory)
local path = nil
@@ -197,11 +244,12 @@ function make_dir(directory)
path = path and path .. dir.separator .. d or d
local mode = lfs.attributes(path, "mode")
if not mode then
- if not lfs.mkdir(path) then
- return false
+ local ok, err = lfs.mkdir(path)
+ if not ok then
+ return false, err
end
elseif mode ~= "directory" then
- return false
+ return false, path.." is not a directory"
end
end
return true
@@ -211,7 +259,7 @@ end
-- Does not return errors (for example, if directory is not empty or
-- if already does not exist)
-- @param d string: pathname of directory to remove.
-function remove_dir_if_empty(d)
+function fs_lua.remove_dir_if_empty(d)
assert(d)
d = dir.normalize(d)
lfs.rmdir(d)
@@ -221,7 +269,7 @@ end
-- Does not return errors (for example, if directory is not empty or
-- if already does not exist)
-- @param d string: pathname of directory to remove.
-function remove_dir_tree_if_empty(d)
+function fs_lua.remove_dir_tree_if_empty(d)
assert(d)
d = dir.normalize(d)
for i=1,10 do
@@ -237,7 +285,7 @@ end
-- or nil to use the source filename permissions
-- @return boolean or (boolean, string): true on success, false on failure,
-- plus an error message.
-function copy(src, dest, perms)
+function fs_lua.copy(src, dest, perms)
assert(src and dest)
src = dir.normalize(src)
dest = dir.normalize(dest)
@@ -274,7 +322,8 @@ local function recursive_copy(src, dest)
if not ok then return false end
elseif srcmode == "directory" then
local subdir = dir.path(dest, dir.base_name(src))
- fs.make_dir(subdir)
+ local ok, err = fs.make_dir(subdir)
+ if not ok then return nil, err end
for file in lfs.dir(src) do
if file ~= "." and file ~= ".." then
local ok = recursive_copy(dir.path(src, file), subdir)
@@ -290,7 +339,7 @@ end
-- @param dest string: Pathname of destination
-- @return boolean or (boolean, string): true on success, false on failure,
-- plus an error message.
-function copy_contents(src, dest)
+function fs_lua.copy_contents(src, dest)
assert(src and dest)
src = dir.normalize(src)
dest = dir.normalize(dest)
@@ -313,11 +362,9 @@ end
-- @return boolean or (boolean, string): true on success,
-- or nil and an error message on failure.
local function recursive_delete(name)
- local mode = lfs.attributes(name, "mode")
-
- if mode == "file" then
- return os.remove(name)
- elseif mode == "directory" then
+ local ok = os.remove(name)
+ if ok then return true end
+ local pok, ok, err = pcall(function()
for file in lfs.dir(name) do
if file ~= "." and file ~= ".." then
local ok, err = recursive_delete(dir.path(name, file))
@@ -325,40 +372,33 @@ local function recursive_delete(name)
end
end
local ok, err = lfs.rmdir(name)
- if not ok then return nil, err end
+ return ok, (not ok) and err
+ end)
+ if pok then
+ return ok, err
+ else
+ return pok, ok
end
- return true
end
--- Delete a file or a directory and all its contents.
-- @param name string: Pathname of source
--- @return boolean: true on success, false on failure.
-function delete(name)
+-- @return nil
+function fs_lua.delete(name)
name = dir.normalize(name)
- return recursive_delete(name) or false
+ recursive_delete(name)
end
---- List the contents of a directory.
--- @param at string or nil: directory to list (will be the current
--- directory if none is given).
--- @return table: an array of strings with the filenames representing
--- the contents of a directory.
-function list_dir(at)
- assert(type(at) == "string" or not at)
- if not at then
- at = fs.current_dir()
- end
- at = dir.normalize(at)
- if not fs.is_dir(at) then
- return {}
- end
- local result = {}
+--- Internal implementation function for fs.dir.
+-- Yields a filename on each iteration.
+-- @param at string: directory to list
+-- @return nil
+function fs_lua.dir_iterator(at)
for file in lfs.dir(at) do
if file ~= "." and file ~= ".." then
- table.insert(result, file)
+ coroutine.yield(file)
end
end
- return result
end
--- Implementation function for recursive find.
@@ -384,7 +424,7 @@ end
-- directory if none is given).
-- @return table: an array of strings with the filenames representing
-- the contents of a directory.
-function find(at)
+function fs_lua.find(at)
assert(type(at) == "string" or not at)
if not at then
at = fs.current_dir()
@@ -401,7 +441,7 @@ end
--- Test for existance of a file.
-- @param file string: filename to test
-- @return boolean: true if file exists, false otherwise.
-function exists(file)
+function fs_lua.exists(file)
assert(file)
file = dir.normalize(file)
return type(lfs.attributes(file)) == "table"
@@ -410,7 +450,7 @@ end
--- Test is pathname is a directory.
-- @param file string: pathname to test
-- @return boolean: true if it is a directory, false otherwise.
-function is_dir(file)
+function fs_lua.is_dir(file)
assert(file)
file = dir.normalize(file)
return lfs.attributes(file, "mode") == "directory"
@@ -419,13 +459,13 @@ end
--- Test is pathname is a regular file.
-- @param file string: pathname to test
-- @return boolean: true if it is a file, false otherwise.
-function is_file(file)
+function fs_lua.is_file(file)
assert(file)
file = dir.normalize(file)
return lfs.attributes(file, "mode") == "file"
end
-function set_time(file, time)
+function fs_lua.set_time(file, time)
file = dir.normalize(file)
return lfs.touch(file, time)
end
@@ -438,7 +478,7 @@ end
if zip_ok then
-function zip(zipfile, ...)
+function fs_lua.zip(zipfile, ...)
return lrzip.zip(zipfile, ...)
end
@@ -448,15 +488,24 @@ if unzip_ok then
--- Uncompress files from a .zip archive.
-- @param zipfile string: pathname of .zip archive to be extracted.
-- @return boolean: true on success, false on failure.
-function unzip(zipfile)
+function fs_lua.unzip(zipfile)
local zipfile, err = luazip.open(zipfile)
if not zipfile then return nil, err end
local files = zipfile:files()
local file = files()
repeat
if file.filename:sub(#file.filename) == "/" then
- fs.make_dir(dir.path(fs.current_dir(), file.filename))
+ local ok, err = fs.make_dir(dir.path(fs.current_dir(), file.filename))
+ if not ok then return nil, err end
else
+ local base = dir.dir_name(file.filename)
+ if base ~= "" then
+ base = dir.path(fs.current_dir(), base)
+ if not fs.is_dir(base) then
+ local ok, err = fs.make_dir(base)
+ if not ok then return nil, err end
+ end
+ end
local rf, err = zipfile:open(file.filename)
if not rf then zipfile:close(); return nil, err end
local contents = rf:read("*a")
@@ -482,12 +531,13 @@ if socket_ok then
local ltn12 = require("ltn12")
local luasec_ok, https = pcall(require, "ssl.https")
+
local redirect_protocols = {
http = http,
https = luasec_ok and https,
}
-local function http_request(url, http, loop_control)
+local function request(url, method, http, loop_control)
local result = {}
local proxy = cfg.proxy
@@ -497,15 +547,36 @@ local function http_request(url, http, loop_control)
proxy = "http://" .. proxy
end
+ if cfg.show_downloads then
+ io.write(method.." "..url.." ...\n")
+ end
+ local dots = 0
+ if cfg.connection_timeout and cfg.connection_timeout > 0 then
+ http.TIMEOUT = cfg.connection_timeout
+ end
local res, status, headers, err = http.request {
url = url,
proxy = proxy,
+ method = method,
redirect = false,
sink = ltn12.sink.table(result),
+ step = cfg.show_downloads and function(...)
+ io.write(".")
+ io.flush()
+ dots = dots + 1
+ if dots == 70 then
+ io.write("\n")
+ dots = 0
+ end
+ return ltn12.pump.step(...)
+ end,
headers = {
["user-agent"] = cfg.user_agent.." via LuaSocket"
},
}
+ if cfg.show_downloads then
+ io.write("\n")
+ end
if not res then
return nil, status
elseif status == 301 or status == 302 then
@@ -519,46 +590,89 @@ local function http_request(url, http, loop_control)
return nil, "Redirection loop -- broken URL?"
end
loop_control[url] = true
- return http_request(location, redirect_protocols[protocol], loop_control)
+ return request(location, method, redirect_protocols[protocol], loop_control)
else
- return nil, "URL redirected to unsupported protocol - install luasec to get HTTPS support."
+ return nil, "URL redirected to unsupported protocol - install luasec to get HTTPS support.", "https"
end
end
return nil, err
elseif status ~= 200 then
return nil, err
else
+ return result, status, headers, err
+ end
+end
+
+local function http_request(url, http, cached)
+ if cached then
+ local tsfd = io.open(cached..".timestamp", "r")
+ if tsfd then
+ local timestamp = tsfd:read("*a")
+ tsfd:close()
+ local result, status, headers, err = request(url, "HEAD", http)
+ if status == 200 and headers["last-modified"] == timestamp then
+ return true
+ end
+ if not result then
+ return nil, status, headers
+ end
+ end
+ end
+ local result, status, headers, err = request(url, "GET", http)
+ if result then
+ if cached and headers["last-modified"] then
+ local tsfd = io.open(cached..".timestamp", "w")
+ if tsfd then
+ tsfd:write(headers["last-modified"])
+ tsfd:close()
+ end
+ end
return table.concat(result)
+ else
+ return nil, status, headers
end
end
+local downloader_warning = false
+
--- Download a remote file.
-- @param url string: URL to be fetched.
-- @param filename string or nil: this function attempts to detect the
-- resulting local filename of the remote file as the basename of the URL;
-- if that is not correct (due to a redirection, for example), the local
-- filename can be given explicitly as this second argument.
--- @return boolean: true on success, false on failure.
-function download(url, filename)
+-- @return (boolean, string): true and the filename on success,
+-- false and the error message on failure.
+function fs_lua.download(url, filename, cache)
assert(type(url) == "string")
assert(type(filename) == "string" or not filename)
- filename = dir.path(fs.current_dir(), filename or dir.base_name(url))
+ filename = fs.absolute_name(filename or dir.base_name(url))
- local content, err
+ local content, err, https_err
if util.starts_with(url, "http:") then
- content, err = http_request(url, http)
+ content, err, https_err = http_request(url, http, cache and filename)
elseif util.starts_with(url, "ftp:") then
content, err = ftp.get(url)
elseif util.starts_with(url, "https:") then
if luasec_ok then
- content, err = http_request(url, https)
+ content, err = http_request(url, https, cache and filename)
else
- err = "Unsupported protocol - install luasec to get HTTPS support."
+ https_err = true
end
else
err = "Unsupported protocol"
end
+ if https_err then
+ if not downloader_warning then
+ util.printerr("Warning: falling back to "..cfg.downloader.." - install luasec to get native HTTPS support")
+ downloader_warning = true
+ end
+ return fs.use_downloader(url, filename, cache)
+ end
+ if cache and content == true then
+ return true, filename
+ end
if not content then
return false, tostring(err)
end
@@ -566,7 +680,13 @@ function download(url, filename)
if not file then return false end
file:write(content)
file:close()
- return true
+ return true, filename
+end
+
+else --...if socket_ok == false then
+
+function fs_lua.download(url, filename, cache)
+ return fs.use_downloader(url, filename, cache)
end
end
@@ -578,14 +698,15 @@ if md5_ok then
--- Get the MD5 checksum for a file.
-- @param file string: The file to be computed.
--- @return string: The MD5 checksum
-function get_md5(file)
+-- @return string: The MD5 checksum or nil + error
+function fs_lua.get_md5(file)
file = fs.absolute_name(file)
- local file = io.open(file, "rb")
- if not file then return false end
- local computed = md5.sumhexa(file:read("*a"))
- file:close()
- return computed
+ local file_handler = io.open(file, "rb")
+ if not file_handler then return nil, "Failed to open file for reading: "..file end
+ local computed = md5.sumhexa(file_handler:read("*a"))
+ file_handler:close()
+ if computed then return computed end
+ return nil, "Failed to compute MD5 hash for file "..file
end
end
@@ -607,7 +728,7 @@ local octal_to_rwx = {
["7"] = "rwx",
}
-function chmod(file, mode)
+function fs_lua.chmod(file, mode)
-- LuaPosix (as of 5.1.15) does not support octal notation...
if mode:sub(1,1) == "0" then
local new_mode = {}
@@ -620,7 +741,7 @@ function chmod(file, mode)
return err == 0
end
-function get_permissions(file)
+function fs_lua.get_permissions(file)
return posix.stat(file, "mode")
end
@@ -633,7 +754,7 @@ end
--- Apply a patch.
-- @param patchname string: The filename of the patch.
-- @param patchdata string or nil: The actual patch as a string.
-function apply_patch(patchname, patchdata)
+function fs_lua.apply_patch(patchname, patchdata)
local p, all_ok = patch.read_patch(patchname, patchdata)
if not all_ok then
return nil, "Failed reading patch "..patchname
@@ -648,7 +769,7 @@ end
-- @param dest string: Pathname of destination
-- @return boolean or (boolean, string): true on success, false on failure,
-- plus an error message.
-function move(src, dest)
+function fs_lua.move(src, dest)
assert(src and dest)
if fs.exists(dest) and not fs.is_dir(dest) then
return false, "File already exists: "..dest
@@ -657,8 +778,8 @@ function move(src, dest)
if not ok then
return false, err
end
- ok = fs.delete(src)
- if not ok then
+ fs.delete(src)
+ if fs.exists(src) then
return false, "Failed move: could not delete "..src.." after copy."
end
return true
@@ -669,7 +790,7 @@ end
-- @param flags table: the flags table passed to run() drivers.
-- @return boolean or (boolean, string): true on success, false on failure,
-- plus an error message.
-function check_command_permissions(flags)
+function fs_lua.check_command_permissions(flags)
local root_dir = path.root_dir(cfg.rocks_dir)
local ok = true
local err = ""
@@ -696,3 +817,18 @@ function check_command_permissions(flags)
return nil, err
end
end
+
+--- Check whether a file is a Lua script
+-- When the file can be succesfully compiled by the configured
+-- Lua interpreter, it's considered to be a valid Lua file.
+-- @param name filename of file to check
+-- @return boolean true, if it is a Lua script, false otherwise
+function fs_lua.is_lua(name)
+ name = name:gsub([[%\]],"/") -- normalize on fw slash to prevent escaping issues
+ local lua = fs.Q(dir.path(cfg.variables["LUA_BINDIR"], cfg.lua_interpreter)) -- get lua interpreter configured
+ -- execute on configured interpreter, might not be the same as the interpreter LR is run on
+ local result = fs.execute_string(lua..[[ -e "if loadfile(']]..name..[[') then os.exit() else os.exit(1) end"]])
+ return (result == true)
+end
+
+return fs_lua
diff --git a/src/luarocks/fs/unix.lua b/src/luarocks/fs/unix.lua
index cccbbd3..6ad5a67 100644
--- a/src/luarocks/fs/unix.lua
+++ b/src/luarocks/fs/unix.lua
@@ -1,16 +1,12 @@
--- Unix implementation of filesystem and platform abstractions.
-
-local assert, type, table, io, package, math, os, ipairs =
- assert, type, table, io, package, math, os, ipairs
-
-module("luarocks.fs.unix", package.seeall)
+--module("luarocks.fs.unix", package.seeall)
+local unix = {}
local fs = require("luarocks.fs")
local cfg = require("luarocks.cfg")
local dir = require("luarocks.dir")
-local fs = require("luarocks.fs")
local util = require("luarocks.util")
math.randomseed(os.time())
@@ -18,7 +14,7 @@ math.randomseed(os.time())
--- Annotate command string for quiet execution.
-- @param cmd string: A command-line string.
-- @return string: The command-line, with silencing annotation.
-function quiet(cmd)
+function unix.quiet(cmd)
return cmd.." 1> /dev/null 2> /dev/null"
end
@@ -28,7 +24,7 @@ end
-- pathname absolute, or the current dir in the dir stack if
-- not given.
-- @return string: The pathname converted to absolute.
-function absolute_name(pathname, relative_to)
+function unix.absolute_name(pathname, relative_to)
assert(type(pathname) == "string")
assert(type(relative_to) == "string" or not relative_to)
@@ -47,21 +43,22 @@ end
-- @param version string: rock version to be used in loader context.
-- @return boolean or (nil, string): True if succeeded, or nil and
-- an error message.
-function wrap_script(file, dest, name, version)
+function unix.wrap_script(file, dest, name, version)
assert(type(file) == "string")
assert(type(dest) == "string")
local base = dir.base_name(file)
local wrapname = fs.is_dir(dest) and dest.."/"..base or dest
+ local lpath, lcpath = cfg.package_paths()
local wrapper = io.open(wrapname, "w")
if not wrapper then
return nil, "Could not open "..wrapname.." for writing."
end
wrapper:write("#!/bin/sh\n\n")
- wrapper:write('LUA_PATH="'..package.path..';$LUA_PATH"\n')
- wrapper:write('LUA_CPATH="'..package.cpath..';$LUA_CPATH"\n')
- wrapper:write('export LUA_PATH LUA_CPATH\n')
- wrapper:write('exec "'..dir.path(cfg.variables["LUA_BINDIR"], cfg.lua_interpreter)..'" -lluarocks.loader -e\'luarocks.loader.add_context([['..name..']],[['..version..']])\' "'..file..'" "$@"\n')
+ local lua = dir.path(cfg.variables["LUA_BINDIR"], cfg.lua_interpreter)
+ local ppaths = "package.path="..util.LQ(lpath..";").."..package.path; package.cpath="..util.LQ(lcpath..";").."..package.cpath"
+ local addctx = "local k,l,_=pcall(require,"..util.LQ("luarocks.loader")..") _=k and l.add_context("..util.LQ(name)..","..util.LQ(version)..")"
+ wrapper:write('exec '..fs.Q(lua)..' -e '..fs.Q(ppaths)..' -e '..fs.Q(addctx)..' '..fs.Q(file)..' "$@"\n')
wrapper:close()
if fs.chmod(wrapname, "0755") then
return true
@@ -75,7 +72,7 @@ end
-- @param filename string: the file name with full path.
-- @return boolean: returns true if file is an actual binary
-- (or if it couldn't check) or false if it is a Lua wrapper.
-function is_actual_binary(filename)
+function unix.is_actual_binary(filename)
if filename:match("%.lua$") then
return false
end
@@ -92,7 +89,7 @@ function is_actual_binary(filename)
return first ~= "#!"
end
-function copy_binary(filename, dest)
+function unix.copy_binary(filename, dest)
return fs.copy(filename, dest, "0755")
end
@@ -106,6 +103,12 @@ end
-- which will replace old_file.
-- @return boolean or (nil, string): True if succeeded, or nil and
-- an error message.
-function replace_file(old_file, new_file)
+function unix.replace_file(old_file, new_file)
return os.rename(new_file, old_file)
end
+
+function unix.tmpname()
+ return os.tmpname()
+end
+
+return unix
diff --git a/src/luarocks/fs/unix/tools.lua b/src/luarocks/fs/unix/tools.lua
index 3b853be..f36e815 100644
--- a/src/luarocks/fs/unix/tools.lua
+++ b/src/luarocks/fs/unix/tools.lua
@@ -1,6 +1,7 @@
--- fs operations implemented with third-party tools for Unix platform abstractions.
-module("luarocks.fs.unix.tools", package.seeall)
+--module("luarocks.fs.unix.tools", package.seeall)
+local tools = {}
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
@@ -17,10 +18,14 @@ end
--- Obtain current directory.
-- Uses the module's internal directory stack.
-- @return string: the absolute pathname of the current directory.
-function current_dir()
- local pipe = io.popen(vars.PWD)
- local current = pipe:read("*l")
- pipe:close()
+function tools.current_dir()
+ local current = cfg.cache_pwd
+ if not current then
+ local pipe = io.popen(fs.Q(vars.PWD))
+ current = pipe:read("*l")
+ pipe:close()
+ cfg.cache_pwd = current
+ end
for _, directory in ipairs(dir_stack) do
current = fs.absolute_name(directory, current)
end
@@ -32,8 +37,8 @@ end
-- @param cmd string: No quoting/escaping is applied to the command.
-- @return boolean: true if command succeeds (status code 0), false
-- otherwise.
-function execute_string(cmd)
- local code = os.execute(command_at(fs.current_dir(), cmd))
+function tools.execute_string(cmd)
+ local code, err = os.execute(command_at(fs.current_dir(), cmd))
if code == 0 or code == true then
return true
else
@@ -46,20 +51,24 @@ end
-- semantics of chdir, as it does not handle errors the same way,
-- but works well for our purposes for now.
-- @param directory string: The directory to switch to.
-function change_dir(directory)
+function tools.change_dir(directory)
assert(type(directory) == "string")
- table.insert(dir_stack, directory)
+ if fs.is_dir(directory) then
+ table.insert(dir_stack, directory)
+ return true
+ end
+ return nil, "directory not found: "..directory
end
--- Change directory to root.
-- Allows leaving a directory (e.g. for deleting it) in
-- a crossplatform way.
-function change_dir_to_root()
+function tools.change_dir_to_root()
table.insert(dir_stack, "/")
end
--- Change working directory to the previous in the directory stack.
-function pop_dir()
+function tools.pop_dir()
local directory = table.remove(dir_stack)
return directory ~= nil
end
@@ -69,27 +78,31 @@ end
-- too, they are created as well.
-- @param directory string: pathname of directory to create.
-- @return boolean: true on success, false on failure.
-function make_dir(directory)
+function tools.make_dir(directory)
assert(directory)
- return fs.execute(vars.MKDIR.." -p", directory)
+ local ok, err = fs.execute(vars.MKDIR.." -p", directory)
+ if not ok then
+ err = "failed making directory "..directory
+ end
+ return ok, err
end
--- Remove a directory if it is empty.
-- Does not return errors (for example, if directory is not empty or
-- if already does not exist)
-- @param directory string: pathname of directory to remove.
-function remove_dir_if_empty(directory)
+function tools.remove_dir_if_empty(directory)
assert(directory)
- fs.execute_string(fs.quiet(vars.RMDIR.." "..fs.Q(directory)))
+ fs.execute_quiet(vars.RMDIR, directory)
end
--- Remove a directory if it is empty.
-- Does not return errors (for example, if directory is not empty or
-- if already does not exist)
-- @param directory string: pathname of directory to remove.
-function remove_dir_tree_if_empty(directory)
+function tools.remove_dir_tree_if_empty(directory)
assert(directory)
- fs.execute_string(fs.quiet(vars.RMDIR.." -p "..fs.Q(directory)))
+ fs.execute_quiet(vars.RMDIR, "-p", directory)
end
--- Copy a file.
@@ -98,7 +111,7 @@ end
-- @param perm string or nil: Permissions for destination file,
-- @return boolean or (boolean, string): true on success, false on failure,
-- plus an error message.
-function copy(src, dest, perm)
+function tools.copy(src, dest, perm)
assert(src and dest)
if fs.execute(vars.CP, src, dest) then
if perm then
@@ -122,9 +135,9 @@ end
-- @param dest string: Pathname of destination
-- @return boolean or (boolean, string): true on success, false on failure,
-- plus an error message.
-function copy_contents(src, dest)
+function tools.copy_contents(src, dest)
assert(src and dest)
- if fs.execute_string(fs.quiet(vars.CP.." -pPR "..fs.Q(src).."/* "..fs.Q(dest))) then
+ if fs.execute_quiet(vars.CP.." -pPR "..fs.Q(src).."/* "..fs.Q(dest)) then
return true
else
return false, "Failed copying "..src.." to "..dest
@@ -133,33 +146,25 @@ end
--- Delete a file or a directory and all its contents.
-- For safety, this only accepts absolute paths.
-- @param arg string: Pathname of source
--- @return boolean: true on success, false on failure.
-function delete(arg)
+-- @return nil
+function tools.delete(arg)
assert(arg)
assert(arg:sub(1,1) == "/")
- return fs.execute_string(fs.quiet(vars.RM.." -rf " .. fs.Q(arg)))
+ fs.execute_quiet(vars.RM, "-rf", arg)
end
---- List the contents of a directory.
--- @param at string or nil: directory to list (will be the current
--- directory if none is given).
--- @return table: an array of strings with the filenames representing
--- the contents of a directory.
-function list_dir(at)
- assert(type(at) == "string" or not at)
- if not at then
- at = fs.current_dir()
- end
- if not fs.is_dir(at) then
- return {}
- end
- local result = {}
+--- Internal implementation function for fs.dir.
+-- Yields a filename on each iteration.
+-- @param at string: directory to list
+-- @return nil
+function tools.dir_iterator(at)
local pipe = io.popen(command_at(at, vars.LS))
for file in pipe:lines() do
- table.insert(result, file)
+ if file ~= "." and file ~= ".." then
+ coroutine.yield(file)
+ end
end
pipe:close()
- return result
end
--- Recursively scan the contents of a directory.
@@ -167,7 +172,7 @@ end
-- directory if none is given).
-- @return table: an array of strings with the filenames representing
-- the contents of a directory.
-function find(at)
+function tools.find(at)
assert(type(at) == "string" or not at)
if not at then
at = fs.current_dir()
@@ -189,22 +194,22 @@ end
-- @param ... Filenames to be stored in the archive are given as
-- additional arguments.
-- @return boolean: true on success, false on failure.
-function zip(zipfile, ...)
+function tools.zip(zipfile, ...)
return fs.execute(vars.ZIP.." -r", zipfile, ...)
end
--- Uncompress files from a .zip archive.
-- @param zipfile string: pathname of .zip archive to be extracted.
-- @return boolean: true on success, false on failure.
-function unzip(zipfile)
+function tools.unzip(zipfile)
assert(zipfile)
- return fs.execute(vars.UNZIP, zipfile)
+ return fs.execute_quiet(vars.UNZIP, zipfile)
end
--- Test is file/directory exists
-- @param file string: filename to test
-- @return boolean: true if file exists, false otherwise.
-function exists(file)
+function tools.exists(file)
assert(file)
return fs.execute(vars.TEST, "-e", file)
end
@@ -212,7 +217,7 @@ end
--- Test is pathname is a directory.
-- @param file string: pathname to test
-- @return boolean: true if it is a directory, false otherwise.
-function is_dir(file)
+function tools.is_dir(file)
assert(file)
return fs.execute(vars.TEST, "-d", file)
end
@@ -220,7 +225,7 @@ end
--- Test is pathname is a regular file.
-- @param file string: pathname to test
-- @return boolean: true if it is a regular file, false otherwise.
-function is_file(file)
+function tools.is_file(file)
assert(file)
return fs.execute(vars.TEST, "-f", file)
end
@@ -231,25 +236,46 @@ end
-- resulting local filename of the remote file as the basename of the URL;
-- if that is not correct (due to a redirection, for example), the local
-- filename can be given explicitly as this second argument.
--- @return boolean: true on success, false on failure.
-function download(url, filename)
+-- @return (boolean, string): true and the filename on success,
+-- false and the error message on failure.
+function tools.use_downloader(url, filename, cache)
assert(type(url) == "string")
assert(type(filename) == "string" or not filename)
+ filename = fs.absolute_name(filename or dir.base_name(url))
+
+ local ok
if cfg.downloader == "wget" then
- local wget_cmd = vars.WGET.." --no-check-certificate --no-cache --user-agent='"..cfg.user_agent.." via wget' --quiet --continue "
- if filename then
- return fs.execute(wget_cmd.." --output-document ", filename, url)
+ local wget_cmd = fs.Q(vars.WGET).." --no-check-certificate --no-cache --user-agent='"..cfg.user_agent.." via wget' --quiet "
+ if cfg.connection_timeout and cfg.connection_timeout > 0 then
+ wget_cmd = wget_cmd .. "--timeout="..tonumber(cfg.connection_timeout).." --tries=1 "
+ end
+ if cache then
+ -- --timestamping is incompatible with --output-document,
+ -- but that's not a problem for our use cases.
+ fs.change_dir(dir.dir_name(filename))
+ ok = fs.execute_quiet(wget_cmd.." --timestamping ", url)
+ fs.pop_dir()
+ elseif filename then
+ ok = fs.execute_quiet(wget_cmd.." --output-document ", filename, url)
else
- return fs.execute(wget_cmd, url)
+ ok = fs.execute_quiet(wget_cmd, url)
end
elseif cfg.downloader == "curl" then
- filename = filename or dir.base_name(url)
- return fs.execute_string(vars.CURL.." -L --user-agent '"..cfg.user_agent.." via curl' "..fs.Q(url).." 2> /dev/null 1> "..fs.Q(filename))
+ local curl_cmd = fs.Q(vars.CURL).." -f -k -L --user-agent '"..cfg.user_agent.." via curl' "
+ if cfg.connection_timeout and cfg.connection_timeout > 0 then
+ curl_cmd = curl_cmd .. "--connect-timeout "..tonumber(cfg.connection_timeout).." "
+ end
+ ok = fs.execute_string(curl_cmd..fs.Q(url).." 2> /dev/null 1> "..fs.Q(filename))
+ end
+ if ok then
+ return true, filename
+ else
+ return false
end
end
-function chmod(pathname, mode)
+function tools.chmod(pathname, mode)
if mode then
return fs.execute(vars.CHMOD, mode, pathname)
else
@@ -259,7 +285,7 @@ end
--- Apply a patch.
-- @param patchname string: The filename of the patch.
-function apply_patch(patchname)
+function tools.apply_patch(patchname)
return fs.execute(vars.PATCH.." -p1 -f -i ", patchname)
end
@@ -268,7 +294,7 @@ end
-- filename extension.
-- @param archive string: Filename of archive.
-- @return boolean or (boolean, string): true on success, false and an error message on failure.
-function unpack_archive(archive)
+function tools.unpack_archive(archive)
assert(type(archive) == "string")
local ok
@@ -300,19 +326,28 @@ local md5_cmd = {
--- Get the MD5 checksum for a file.
-- @param file string: The file to be computed.
-- @return string: The MD5 checksum
-function get_md5(file)
+function tools.get_md5(file)
local cmd = md5_cmd[cfg.md5checker]
- if not cmd then return nil end
- local pipe = io.popen(cmd.." "..fs.absolute_name(file))
+ if not cmd then return nil, "no MD5 checker command configured" end
+ local pipe = io.popen(cmd.." "..fs.Q(fs.absolute_name(file)))
local computed = pipe:read("*a")
pipe:close()
- if not computed then return nil end
- return computed:match("("..("%x"):rep(32)..")")
+ if computed then
+ computed = computed:match("("..("%x"):rep(32)..")")
+ end
+ if computed then return computed end
+ return nil, "Failed to compute MD5 hash for file "..tostring(fs.absolute_name(file))
end
-function get_permissions(filename)
+function tools.get_permissions(filename)
local pipe = io.popen(vars.STAT.." "..vars.STATFLAG.." "..fs.Q(filename))
local ret = pipe:read("*l")
pipe:close()
return ret
end
+
+function tools.browser(url)
+ return fs.execute(cfg.web_browser, url)
+end
+
+return tools
diff --git a/src/luarocks/fs/win32.lua b/src/luarocks/fs/win32.lua
index 2b5bb95..12d86d1 100644
--- a/src/luarocks/fs/win32.lua
+++ b/src/luarocks/fs/win32.lua
@@ -1,32 +1,84 @@
--- Windows implementation of filesystem and platform abstractions.
-- Download http://unxutils.sourceforge.net/ for Windows GNU utilities
-- used by this module.
-module("luarocks.fs.win32", package.seeall)
+--module("luarocks.fs.win32", package.seeall)
+local win32 = {}
local fs = require("luarocks.fs")
local cfg = require("luarocks.cfg")
local dir = require("luarocks.dir")
+local util = require("luarocks.util")
+
+-- Monkey patch io.popen and os.execute to make sure quoting
+-- works as expected.
+-- See http://lua-users.org/lists/lua-l/2013-11/msg00367.html
+local _prefix = "type NUL && "
+local _popen, _execute = io.popen, os.execute
+io.popen = function(cmd, ...) return _popen(_prefix..cmd, ...) end
+os.execute = function(cmd, ...) return _execute(_prefix..cmd, ...) end
+
--- Annotate command string for quiet execution.
-- @param cmd string: A command-line string.
-- @return string: The command-line, with silencing annotation.
-function quiet(cmd)
+function win32.quiet(cmd)
return cmd.." 2> NUL 1> NUL"
end
+
+local win_escape_chars = {
+ ["%"] = "%%",
+ ['"'] = '\\"',
+}
+
+local function q_escaper(bs, q)
+ return ("\\"):rep(2*#bs-1) .. (q or "\\")
+end
+
+local function p_escaper(bs)
+ return bs .. bs .. '"%"'
+end
+
--- Quote argument for shell processing. Fixes paths on Windows.
--- Adds single quotes and escapes.
+-- Adds double quotes and escapes.
-- @param arg string: Unquoted argument.
-- @return string: Quoted argument.
-function Q(arg)
+function win32.Q(arg)
assert(type(arg) == "string")
-- Quote DIR for Windows
- if arg:match("^[%.a-zA-Z]?:?[\\/]") then
- return '"' .. arg:gsub("/", "\\"):gsub('"', '\\"') .. '"'
- end
+ if arg:match("^[%.a-zA-Z]?:?[\\/]") then
+ arg = arg:gsub("/", "\\")
+ end
+ if arg == "\\" then
+ return '\\' -- CHDIR needs special handling for root dir
+ end
-- URLs and anything else
- return '"' .. arg:gsub('"', '\\"') .. '"'
+ arg = arg:gsub('(\\+)(")', q_escaper)
+ arg = arg:gsub('(\\+)$', q_escaper)
+ arg = arg:gsub('"', win_escape_chars)
+ arg = arg:gsub('(\\*)%%', p_escaper)
+ return '"' .. arg .. '"'
+end
+
+--- Quote argument for shell processing in batch files.
+-- Adds double quotes and escapes.
+-- @param arg string: Unquoted argument.
+-- @return string: Quoted argument.
+function win32.Qb(arg)
+ assert(type(arg) == "string")
+ -- Quote DIR for Windows
+ if arg:match("^[%.a-zA-Z]?:?[\\/]") then
+ arg = arg:gsub("/", "\\")
+ end
+ if arg == "\\" then
+ return '\\' -- CHDIR needs special handling for root dir
+ end
+ -- URLs and anything else
+ arg = arg:gsub('(\\+)(")', q_escaper)
+ arg = arg:gsub('(\\+)$', q_escaper)
+ arg = arg:gsub('[%%"]', win_escape_chars)
+ return '"' .. arg .. '"'
end
--- Return an absolute pathname from a potentially relative one.
@@ -35,7 +87,7 @@ end
-- pathname absolute, or the current dir in the dir stack if
-- not given.
-- @return string: The pathname converted to absolute.
-function absolute_name(pathname, relative_to)
+function win32.absolute_name(pathname, relative_to)
assert(type(pathname) == "string")
assert(type(relative_to) == "string" or not relative_to)
@@ -56,28 +108,28 @@ end
-- @param version string: rock version to be used in loader context.
-- @return boolean or (nil, string): True if succeeded, or nil and
-- an error message.
-function wrap_script(file, dest, name, version)
+function win32.wrap_script(file, dest, name, version)
assert(type(file) == "string")
assert(type(dest) == "string")
local base = dir.base_name(file)
local wrapname = fs.is_dir(dest) and dest.."/"..base or dest
wrapname = wrapname..".bat"
+ local lpath, lcpath = cfg.package_paths()
local wrapper = io.open(wrapname, "w")
if not wrapper then
return nil, "Could not open "..wrapname.." for writing."
end
wrapper:write("@echo off\n")
- wrapper:write("setlocal\n")
- wrapper:write('set LUA_PATH='..package.path..";%LUA_PATH%\n")
- wrapper:write('set LUA_CPATH='..package.cpath..";%LUA_CPATH%\n")
- wrapper:write('"'..dir.path(cfg.variables["LUA_BINDIR"], cfg.lua_interpreter)..'" -lluarocks.loader -e\'luarocks.loader.add_context([['..name..']],[['..version..']])\' "'..file..'" %*\n')
- wrapper:write("endlocal\n")
+ local lua = dir.path(cfg.variables["LUA_BINDIR"], cfg.lua_interpreter)
+ local ppaths = "package.path="..util.LQ(lpath..";").."..package.path; package.cpath="..util.LQ(lcpath..";").."..package.cpath"
+ local addctx = "local k,l,_=pcall(require,"..util.LQ("luarocks.loader")..") _=k and l.add_context("..util.LQ(name)..","..util.LQ(version)..")"
+ wrapper:write(fs.Qb(lua)..' -e '..fs.Qb(ppaths)..' -e '..fs.Qb(addctx)..' '..fs.Qb(file)..' %*\n')
wrapper:close()
return true
end
-function is_actual_binary(name)
+function win32.is_actual_binary(name)
name = name:lower()
if name:match("%.bat$") or name:match("%.exe$") then
return true
@@ -85,14 +137,14 @@ function is_actual_binary(name)
return false
end
-function copy_binary(filename, dest)
+function win32.copy_binary(filename, dest)
local ok, err = fs.copy(filename, dest)
if not ok then
return nil, err
end
local exe_pattern = "%.[Ee][Xx][Ee]$"
local base = dir.base_name(filename)
- local dest = dir.dir_name(dest)
+ dest = dir.dir_name(dest)
if base:match(exe_pattern) then
base = base:gsub(exe_pattern, ".lua")
local helpname = dest.."/"..base
@@ -107,11 +159,11 @@ function copy_binary(filename, dest)
return true
end
-function chmod(filename, mode)
+function win32.chmod(filename, mode)
return true
end
-function get_permissions(filename)
+function win32.get_permissions(filename)
return ""
end
@@ -126,8 +178,44 @@ end
-- which will replace old_file.
-- @return boolean or (nil, string): True if succeeded, or nil and
-- an error message.
-function replace_file(old_file, new_file)
+function win32.replace_file(old_file, new_file)
os.remove(old_file)
return os.rename(new_file, old_file)
end
+--- Test is file/dir is writable.
+-- Warning: testing if a file/dir is writable does not guarantee
+-- that it will remain writable and therefore it is no replacement
+-- for checking the result of subsequent operations.
+-- @param file string: filename to test
+-- @return boolean: true if file exists, false otherwise.
+function win32.is_writable(file)
+ assert(file)
+ file = dir.normalize(file)
+ local result
+ local tmpname = 'tmpluarockstestwritable.deleteme'
+ if fs.is_dir(file) then
+ local file2 = dir.path(file, tmpname)
+ local fh = io.open(file2, 'wb')
+ result = fh ~= nil
+ if fh then fh:close() end
+ if result then
+ -- the above test might give a false positive when writing to
+ -- c:\program files\ because of VirtualStore redirection on Vista and up
+ -- So check whether it's really there
+ result = fs.exists(file2)
+ end
+ os.remove(file2)
+ else
+ local fh = io.open(file, 'r+b')
+ result = fh ~= nil
+ if fh then fh:close() end
+ end
+ return result
+end
+
+function win32.tmpname()
+ return os.getenv("TMP")..os.tmpname()
+end
+
+return win32
diff --git a/src/luarocks/fs/win32/tools.lua b/src/luarocks/fs/win32/tools.lua
index 1af1dd9..f970f36 100644
--- a/src/luarocks/fs/win32/tools.lua
+++ b/src/luarocks/fs/win32/tools.lua
@@ -2,7 +2,8 @@
--- fs operations implemented with third-party tools for Windows platform abstractions.
-- Download http://unxutils.sourceforge.net/ for Windows GNU utilities
-- used by this module.
-module("luarocks.fs.win32.tools", package.seeall)
+--module("luarocks.fs.win32.tools", package.seeall)
+local tools = {}
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
@@ -12,10 +13,6 @@ local dir_stack = {}
local vars = cfg.variables
-local function pack(...)
- return { n = select("#", ...), ... }
-end
-
--- Strip the last extension of a filename.
-- Example: "foo.tar.gz" becomes "foo.tar".
-- If filename has no dots, returns it unchanged.
@@ -39,10 +36,14 @@ end
--- Obtain current directory.
-- Uses the module's internal directory stack.
-- @return string: the absolute pathname of the current directory.
-function current_dir()
- local pipe = io.popen(vars.PWD)
- local current = pipe:read("*l")
- pipe:close()
+function tools.current_dir()
+ local current = cfg.cache_pwd
+ if not current then
+ local pipe = io.popen(fs.Q(vars.PWD))
+ current = pipe:read("*l")
+ pipe:close()
+ cfg.cache_pwd = current
+ end
for _, directory in ipairs(dir_stack) do
current = fs.absolute_name(directory, current)
end
@@ -54,18 +55,10 @@ end
-- @param cmd string: No quoting/escaping is applied to the command.
-- @return boolean: true if command succeeds (status code 0), false
-- otherwise.
-function execute_string(cmd)
+function tools.execute_string(cmd)
cmd = command_at(fs.current_dir(), cmd)
- if cfg.verbose then print("Executing: "..tostring(cmd)) end
- local code = pack(os.execute(cmd))
- if cfg.verbose then
- print("Results: "..tostring(code.n))
- for i = 1,code.n do
- print(" "..tostring(i).." ("..type(code[i]).."): "..tostring(code[i]))
- end
- print()
- end
- if code[1] == 0 or code[1] == true then
+ local code = os.execute(cmd)
+ if code == 0 or code == true then
return true
else
return false
@@ -77,20 +70,25 @@ end
-- semantics of chdir, as it does not handle errors the same way,
-- but works well for our purposes for now.
-- @param directory string: The directory to switch to.
-function change_dir(directory)
+-- @return boolean or (nil, string): true if successful, (nil, error message) if failed.
+function tools.change_dir(directory)
assert(type(directory) == "string")
- table.insert(dir_stack, directory)
+ if fs.is_dir(directory) then
+ table.insert(dir_stack, directory)
+ return true
+ end
+ return nil, "directory not found: "..directory
end
--- Change directory to root.
-- Allows leaving a directory (e.g. for deleting it) in
-- a crossplatform way.
-function change_dir_to_root()
+function tools.change_dir_to_root()
table.insert(dir_stack, "/")
end
--- Change working directory to the previous in the directory stack.
-function pop_dir()
+function tools.pop_dir()
local directory = table.remove(dir_stack)
return directory ~= nil
end
@@ -100,28 +98,32 @@ end
-- too, they are created as well.
-- @param directory string: pathname of directory to create.
-- @return boolean: true on success, false on failure.
-function make_dir(directory)
+function tools.make_dir(directory)
assert(directory)
- fs.execute(fs.quiet(vars.MKDIR.." "..fs.Q(directory)))
- return 1
+ directory = dir.normalize(directory)
+ fs.execute_quiet(fs.Q(vars.MKDIR).." -p ", directory)
+ if not fs.is_dir(directory) then
+ return false, "failed making directory "..directory
+ end
+ return true
end
--- Remove a directory if it is empty.
-- Does not return errors (for example, if directory is not empty or
-- if already does not exist)
-- @param directory string: pathname of directory to remove.
-function remove_dir_if_empty(directory)
+function tools.remove_dir_if_empty(directory)
assert(directory)
- fs.execute_string(fs.quiet(vars.RMDIR.." "..fs.Q(directory)))
+ fs.execute_quiet(fs.Q(vars.RMDIR), directory)
end
--- Remove a directory if it is empty.
-- Does not return errors (for example, if directory is not empty or
-- if already does not exist)
-- @param directory string: pathname of directory to remove.
-function remove_dir_tree_if_empty(directory)
+function tools.remove_dir_tree_if_empty(directory)
assert(directory)
- fs.execute_string(fs.quiet(vars.RMDIR.." "..fs.Q(directory)))
+ fs.execute_quiet(fs.Q(vars.RMDIR), directory)
end
--- Copy a file.
@@ -129,10 +131,11 @@ end
-- @param dest string: Pathname of destination
-- @return boolean or (boolean, string): true on success, false on failure,
-- plus an error message.
-function copy(src, dest)
+function tools.copy(src, dest)
assert(src and dest)
if dest:match("[/\\]$") then dest = dest:sub(1, -2) end
- if fs.execute(vars.CP, src, dest) then
+ local ok = fs.execute(fs.Q(vars.CP), src, dest)
+ if ok then
return true
else
return false, "Failed copying "..src.." to "..dest
@@ -144,9 +147,9 @@ end
-- @param dest string: Pathname of destination
-- @return boolean or (boolean, string): true on success, false on failure,
-- plus an error message.
-function copy_contents(src, dest)
+function tools.copy_contents(src, dest)
assert(src and dest)
- if fs.execute_string(fs.quiet(vars.CP.." -dR "..src.."\\*.* "..fs.Q(dest))) then
+ if fs.execute_quiet(fs.Q(vars.CP).." -dR "..src.."\\*.* "..fs.Q(dest)) then
return true
else
return false, "Failed copying "..src.." to "..dest
@@ -156,35 +159,25 @@ end
--- Delete a file or a directory and all its contents.
-- For safety, this only accepts absolute paths.
-- @param arg string: Pathname of source
--- @return boolean: true on success, false on failure.
-function delete(arg)
+-- @return nil
+function tools.delete(arg)
assert(arg)
- assert(arg:match("^[\a-zA-Z]?:?[\\/]"))
- fs.execute(vars.CHMOD.." a+rw -R ", arg)
- return fs.execute_string(fs.quiet(vars.RM.." -rf " .. fs.Q(arg)))
+ assert(arg:match("^[a-zA-Z]?:?[\\/]"))
+ fs.execute_quiet("if exist "..fs.Q(arg.."\\").." ( RMDIR /S /Q "..fs.Q(arg).." ) else ( DEL /Q /F "..fs.Q(arg).." )")
end
---- List the contents of a directory.
--- @param at string or nil: directory to list (will be the current
--- directory if none is given).
--- @return table: an array of strings with the filenames representing
--- the contents of a directory.
-function list_dir(at)
- assert(type(at) == "string" or not at)
- if not at then
- at = fs.current_dir()
- end
- if not fs.is_dir(at) then
- return {}
- end
- local result = {}
- local pipe = io.popen(command_at(at, vars.LS))
+--- Internal implementation function for fs.dir.
+-- Yields a filename on each iteration.
+-- @param at string: directory to list
+-- @return nil
+function tools.dir_iterator(at)
+ local pipe = io.popen(command_at(at, fs.Q(vars.LS)))
for file in pipe:lines() do
- table.insert(result, file)
+ if file ~= "." and file ~= ".." then
+ coroutine.yield(file)
+ end
end
pipe:close()
-
- return result
end
--- Recursively scan the contents of a directory.
@@ -192,7 +185,7 @@ end
-- directory if none is given).
-- @return table: an array of strings with the filenames representing
-- the contents of a directory. Paths are returned with forward slashes.
-function find(at)
+function tools.find(at)
assert(type(at) == "string" or not at)
if not at then
at = fs.current_dir()
@@ -201,7 +194,7 @@ function find(at)
return {}
end
local result = {}
- local pipe = io.popen(command_at(at, vars.FIND.." 2> NUL"))
+ local pipe = io.popen(command_at(at, fs.Q(vars.FIND).." 2> NUL"))
for file in pipe:lines() do
-- Windows find is a bit different
local first_two = file:sub(1,2)
@@ -219,32 +212,32 @@ end
-- @param ... Filenames to be stored in the archive are given as
-- additional arguments.
-- @return boolean: true on success, false on failure.
-function zip(zipfile, ...)
- return fs.execute(vars.SEVENZ.." a -tzip", zipfile, ...)
+function tools.zip(zipfile, ...)
+ return fs.execute_quiet(fs.Q(vars.SEVENZ).." -aoa a -tzip", zipfile, ...)
end
--- Uncompress files from a .zip archive.
-- @param zipfile string: pathname of .zip archive to be extracted.
-- @return boolean: true on success, false on failure.
-function unzip(zipfile)
+function tools.unzip(zipfile)
assert(zipfile)
- return fs.execute(vars.SEVENZ.." x", zipfile)
+ return fs.execute_quiet(fs.Q(vars.SEVENZ).." -aoa x", zipfile)
end
--- Test is pathname is a directory.
-- @param file string: pathname to test
-- @return boolean: true if it is a directory, false otherwise.
-function is_dir(file)
+function tools.is_dir(file)
assert(file)
- return fs.execute(fs.quiet(vars.TEST.." -d " .. fs.Q(file)))
+ return fs.execute_quiet("if not exist " .. fs.Q(file.."\\").." invalidcommandname")
end
--- Test is pathname is a regular file.
-- @param file string: pathname to test
-- @return boolean: true if it is a regular file, false otherwise.
-function is_file(file)
+function tools.is_file(file)
assert(file)
- return fs.execute(vars.TEST.." -f", file)
+ return fs.execute(fs.Q(vars.TEST).." -f", file)
end
--- Download a remote file.
@@ -253,21 +246,42 @@ end
-- resulting local filename of the remote file as the basename of the URL;
-- if that is not correct (due to a redirection, for example), the local
-- filename can be given explicitly as this second argument.
--- @return boolean: true on success, false on failure.
-function download(url, filename)
+-- @return (boolean, string): true and the filename on success,
+-- false and the error message on failure.
+function tools.use_downloader(url, filename, cache)
assert(type(url) == "string")
assert(type(filename) == "string" or not filename)
+ filename = fs.absolute_name(filename or dir.base_name(url))
+
+ local ok
if cfg.downloader == "wget" then
- local wget_cmd = vars.WGET.." --no-check-certificate --no-cache --user-agent=\""..cfg.user_agent.." via wget\" --quiet --continue "
- if filename then
- return fs.execute(wget_cmd.." --output-document ", filename, url)
+ local wget_cmd = fs.Q(vars.WGET).." --no-check-certificate --no-cache --user-agent=\""..cfg.user_agent.." via wget\" --quiet "
+ if cfg.connection_timeout and cfg.connection_timeout > 0 then
+ wget_cmd = wget_cmd .. "--timeout="..tonumber(cfg.connection_timeout).." --tries=1 "
+ end
+ if cache then
+ -- --timestamping is incompatible with --output-document,
+ -- but that's not a problem for our use cases.
+ fs.change_dir(dir.dir_name(filename))
+ ok = fs.execute_quiet(wget_cmd.." --timestamping ", url)
+ fs.pop_dir()
+ elseif filename then
+ ok = fs.execute_quiet(wget_cmd.." --output-document ", filename, url)
else
- return fs.execute(wget_cmd, url)
+ ok = fs.execute_quiet(wget_cmd, url)
end
elseif cfg.downloader == "curl" then
- filename = filename or dir.base_name(url)
- return fs.execute_string(vars.CURL.." -L --user-agent \""..cfg.user_agent.." via curl\" "..fs.Q(url).." 2> NUL 1> "..fs.Q(filename))
+ local curl_cmd = vars.CURL.." -f -k -L --user-agent \""..cfg.user_agent.." via curl\" "
+ if cfg.connection_timeout and cfg.connection_timeout > 0 then
+ curl_cmd = curl_cmd .. "--connect-timeout "..tonumber(cfg.connection_timeout).." "
+ end
+ ok = fs.execute_string(curl_cmd..fs.Q(url).." 2> NUL 1> "..fs.Q(filename))
+ end
+ if ok then
+ return true, filename
+ else
+ return false
end
end
@@ -275,7 +289,7 @@ end
-- @param archive string: Filename of archive.
-- @return boolean : success status
local function gunzip(archive)
- return fs.execute(vars.SEVENZ.." x", archive)
+ return fs.execute_quiet(fs.Q(vars.SEVENZ).." -aoa x", archive)
end
--- Unpack an archive.
@@ -283,28 +297,28 @@ end
-- filename extension.
-- @param archive string: Filename of archive.
-- @return boolean or (boolean, string): true on success, false and an error message on failure.
-function unpack_archive(archive)
+function tools.unpack_archive(archive)
assert(type(archive) == "string")
local ok
- local sevenzx = vars.SEVENZ.." x"
+ local sevenzx = fs.Q(vars.SEVENZ).." -aoa x"
if archive:match("%.tar%.gz$") then
ok = gunzip(archive)
if ok then
- ok = fs.execute(sevenzx, strip_extension(archive))
+ ok = fs.execute_quiet(sevenzx, strip_extension(archive))
end
elseif archive:match("%.tgz$") then
ok = gunzip(archive)
if ok then
- ok = fs.execute(sevenzx, strip_extension(archive)..".tar")
+ ok = fs.execute_quiet(sevenzx, strip_extension(archive)..".tar")
end
elseif archive:match("%.tar%.bz2$") then
- ok = fs.execute(sevenzx, archive)
+ ok = fs.execute_quiet(sevenzx, archive)
if ok then
- ok = fs.execute(sevenzx, strip_extension(archive))
+ ok = fs.execute_quiet(sevenzx, strip_extension(archive))
end
elseif archive:match("%.zip$") then
- ok = fs.execute(sevenzx, archive)
+ ok = fs.execute_quiet(sevenzx, archive)
elseif archive:match("%.lua$") or archive:match("%.c$") then
-- Ignore .lua and .c files; they don't need to be extracted.
return true
@@ -319,28 +333,37 @@ function unpack_archive(archive)
end
local md5_cmd = {
- md5sum = vars.MD5SUM,
- openssl = vars.OPENSSL.." md5",
- md5 = vars.MD5,
+ md5sum = fs.Q(vars.MD5SUM),
+ openssl = fs.Q(vars.OPENSSL).." md5",
+ md5 = fs.Q(vars.MD5),
}
--- Get the MD5 checksum for a file.
-- @param file string: The file to be computed.
--- @return string: The MD5 checksum
-function get_md5(file)
+-- @return string: The MD5 checksum or nil + message
+function tools.get_md5(file)
local cmd = md5_cmd[cfg.md5checker]
- if not cmd then return nil end
- local pipe = io.popen(cmd.." "..fs.absolute_name(file))
+ if not cmd then return nil, "no MD5 checker command configured" end
+ local pipe = io.popen(cmd.." "..fs.Q(fs.absolute_name(file)))
local computed = pipe:read("*a")
pipe:close()
- if not computed then return nil end
- return computed:match("("..("%x"):rep(32)..")")
+ if computed then
+ computed = computed:match("("..("%x"):rep(32)..")")
+ end
+ if computed then return computed end
+ return nil, "Failed to compute MD5 hash for file "..tostring(fs.absolute_name(file))
end
--- Test for existance of a file.
-- @param file string: filename to test
-- @return boolean: true if file exists, false otherwise.
-function exists(file)
+function tools.exists(file)
assert(file)
- return fs.execute(fs.quiet("if not exist " .. fs.Q(file) .. " invalidcommandname"))
+ return fs.execute_quiet("if not exist " .. fs.Q(file) .. " invalidcommandname")
+end
+
+function tools.browser(url)
+ return fs.execute(cfg.web_browser..' "Starting docs..." '..fs.Q(url))
end
+
+return tools
diff --git a/src/luarocks/help.lua b/src/luarocks/help.lua
index 2944dfd..0a15550 100644
--- a/src/luarocks/help.lua
+++ b/src/luarocks/help.lua
@@ -4,17 +4,19 @@
-- uses a global table called "commands" to find commands
-- to show help for; each command should be represented by a
-- table containing "help" and "help_summary" fields.
-module("luarocks.help", package.seeall)
+--module("luarocks.help", package.seeall)
+local help = {}
local util = require("luarocks.util")
local cfg = require("luarocks.cfg")
+local dir = require("luarocks.dir")
local program = util.this_program("luarocks")
-help_summary = "Help on commands. Type '"..program.." help <command>' for more."
+help.help_summary = "Help on commands. Type '"..program.." help <command>' for more."
-help_arguments = "[<command>]"
-help = [[
+help.help_arguments = "[<command>]"
+help.help = [[
<command> is the command to show help for.
]]
@@ -41,7 +43,7 @@ end
-- given, help summaries for all commands are shown.
-- @return boolean or (nil, string): true if there were no errors
-- or nil and an error message if an invalid command was requested.
-function run(...)
+function help.run(...)
local flags, command = util.parse_flags(...)
if not command then
@@ -63,40 +65,51 @@ function run(...)
given URL.
--tree=<tree> Which tree to operate on.
--local Use the tree in the user's home directory.
- To enable it, see ']]..program..[[ help path'.]])
+ To enable it, see ']]..program..[[ help path'.
+ --verbose Display verbose output of commands executed.
+ --timeout=<seconds> Timeout on network operations, in seconds.
+ 0 means no timeout (wait forever).
+ Default is ]]..cfg.connection_timeout..[[.]])
print_section("VARIABLES")
util.printout([[
Variables from the "variables" table of the configuration file
can be overriden with VAR=VALUE assignments.]])
print_section("COMMANDS")
- local names = {}
- for name, command in pairs(commands) do
- table.insert(names, name)
- end
- table.sort(names)
- for _, name in ipairs(names) do
- local command = commands[name]
+ for name, command in util.sortedpairs(commands) do
+ local cmd = require(command)
util.printout("", name)
- util.printout("\t", command.help_summary)
+ util.printout("\t", cmd.help_summary)
end
print_section("CONFIGURATION")
- util.printout("\tSystem configuration file: ".. sys_file .. " (" .. get_status(sys_ok) ..")")
+ util.printout("\tLua version: " .. cfg.lua_version)
+ util.printout("\tConfiguration files:")
+ util.printout("\t\tSystem: ".. dir.normalize(sys_file) .. " (" .. get_status(sys_ok) ..")")
if home_file then
- util.printout("\tUser configuration file: ".. home_file .. " (" .. get_status(home_ok) ..")\n")
+ util.printout("\t\tUser : ".. dir.normalize(home_file) .. " (" .. get_status(home_ok) ..")\n")
else
- util.printout("\tUser configuration file disabled in this LuaRocks installation.\n")
+ util.printout("\t\tUser : disabled in this LuaRocks installation.\n")
+ end
+ util.printout("\tRocks trees in use: ")
+ for _, tree in ipairs(cfg.rocks_trees) do
+ if type(tree) == "string" then
+ util.printout("\t\t"..dir.normalize(tree))
+ else
+ local name = tree.name and " (\""..tree.name.."\")" or ""
+ util.printout("\t\t"..dir.normalize(tree.root)..name)
+ end
end
else
command = command:gsub("-", "_")
- if commands[command] then
- local arguments = commands[command].help_arguments or "<argument>"
+ local cmd = require(commands[command])
+ if cmd then
+ local arguments = cmd.help_arguments or "<argument>"
print_banner()
print_section("NAME")
- util.printout("\t"..program.." "..command.." - "..commands[command].help_summary)
+ util.printout("\t"..program.." "..command.." - "..cmd.help_summary)
print_section("SYNOPSIS")
util.printout("\t"..program.." "..command.." "..arguments)
print_section("DESCRIPTION")
- util.printout("",(commands[command].help:gsub("\n","\n\t"):gsub("\n\t$","")))
+ util.printout("",(cmd.help:gsub("\n","\n\t"):gsub("\n\t$","")))
print_section("SEE ALSO")
util.printout("","'"..program.." help' for general options and configuration.\n")
else
@@ -105,3 +118,5 @@ function run(...)
end
return true
end
+
+return help
diff --git a/src/luarocks/index.lua b/src/luarocks/index.lua
index e1391cc..116bdfd 100644
--- a/src/luarocks/index.lua
+++ b/src/luarocks/index.lua
@@ -1,6 +1,8 @@
--- Module which builds the index.html page to be used in rocks servers.
-module("luarocks.index", package.seeall)
+--module("luarocks.index", package.seeall)
+local index = {}
+package.loaded["luarocks.index"] = index
local util = require("luarocks.util")
local fs = require("luarocks.fs")
@@ -27,6 +29,9 @@ a {
color: #0000c0;
text-decoration: none;
}
+a.pkg {
+ color: black;
+}
a:hover {
text-decoration: underline;
}
@@ -63,9 +68,9 @@ Lua modules available from this location for use with <a href="http://www.luaroc
<table class="main">
]]
-local index_package_start = [[
+local index_package_begin = [[
<td class="package">
-<p><a name="$anchor"></a><b>$package</b> - $summary<br/>
+<p><a name="$anchor"></a><a href="#$anchor" class="pkg"><b>$package</b></a> - $summary<br/>
</p><blockquote><p>$detailed<br/>
$externaldependencies
<font size="-1"><a href="$original">latest sources</a> $homepage | License: $license</font></p>
@@ -78,16 +83,21 @@ local index_package_end = [[
<tr><td colspan="2" class="spacer"></td></tr>
]]
-local index_footer = [[
+local index_footer_begin = [[
</table>
<p class="manifest">
-<a href="manifest">manifest file</a> &bull; <a href="manifest-5.1">Lua 5.1 manifest file</a> &bull; <a href="manifest-5.2">Lua 5.2 manifest file</a>
+<a href="manifest">manifest file</a>
+]]
+local index_manifest_ver = [[
+&bull; <a href="manifest-$VER">Lua $VER manifest file</a> (<a href="manifest-$VER.zip">zip</a>)
+]]
+local index_footer_end = [[
</p>
</body>
</html>
]]
-function format_external_dependencies(rockspec)
+function index.format_external_dependencies(rockspec)
if rockspec.external_dependencies then
local deplist = {}
local listed_set = {}
@@ -115,7 +125,7 @@ function format_external_dependencies(rockspec)
end
end
-function make_index(repo)
+function index.make_index(repo)
if not fs.is_dir(repo) then
return nil, "Cannot access repository at "..repo
end
@@ -125,21 +135,20 @@ function make_index(repo)
out:write(index_header)
for package, version_list in util.sortedpairs(manifest.repository) do
local latest_rockspec = nil
- local output = index_package_start
+ local output = index_package_begin
for version, data in util.sortedpairs(version_list, deps.compare_versions) do
local versions = {}
output = output..version..':&nbsp;'
table.sort(data, function(a,b) return a.arch < b.arch end)
for _, item in ipairs(data) do
- local link = '<a href="$url">'..item.arch..'</a>'
+ local file
if item.arch == 'rockspec' then
- local rs = ("%s-%s.rockspec"):format(package, version)
- if not latest_rockspec then latest_rockspec = rs end
- link = link:gsub("$url", rs)
+ file = ("%s-%s.rockspec"):format(package, version)
+ if not latest_rockspec then latest_rockspec = file end
else
- link = link:gsub("$url", ("%s-%s.%s.rock"):format(package, version, item.arch))
+ file = ("%s-%s.%s.rock"):format(package, version, item.arch)
end
- table.insert(versions, link)
+ table.insert(versions, '<a href="'..file..'">'..item.arch..'</a>')
end
output = output .. table.concat(versions, ',&nbsp;') .. '<br/>'
end
@@ -155,7 +164,7 @@ function make_index(repo)
detailed = descript.detailed or "",
license = descript.license or "N/A",
homepage = descript.homepage and ('| <a href="'..descript.homepage..'"'..ext_url_target..'>project homepage</a>') or "",
- externaldependencies = format_external_dependencies(rockspec)
+ externaldependencies = index.format_external_dependencies(rockspec)
}
vars.detailed = vars.detailed:gsub("\n\n", "</p><p>"):gsub("%s+", " ")
vars.detailed = vars.detailed:gsub("(https?://[a-zA-Z0-9%.%%-_%+%[%]=%?&/$@;:]+)", '<a href="%1"'..ext_url_target..'>%1</a>')
@@ -167,6 +176,12 @@ function make_index(repo)
end
out:write(output)
end
- out:write(index_footer)
+ out:write(index_footer_begin)
+ for ver in util.lua_versions() do
+ out:write((index_manifest_ver:gsub("$VER", ver)))
+ end
+ out:write(index_footer_end)
out:close()
end
+
+return index
diff --git a/src/luarocks/install.lua b/src/luarocks/install.lua
index c181d61..7678c0c 100644
--- a/src/luarocks/install.lua
+++ b/src/luarocks/install.lua
@@ -1,7 +1,8 @@
-
--- Module implementing the LuaRocks "install" command.
-- Installs binary rocks.
-module("luarocks.install", package.seeall)
+--module("luarocks.install", package.seeall)
+local install = {}
+package.loaded["luarocks.install"] = install
local path = require("luarocks.path")
local repos = require("luarocks.repos")
@@ -13,11 +14,11 @@ local manif = require("luarocks.manif")
local remove = require("luarocks.remove")
local cfg = require("luarocks.cfg")
-help_summary = "Install a rock."
+install.help_summary = "Install a rock."
-help_arguments = "{<rock>|<name> [<version>]}"
+install.help_arguments = "{<rock>|<name> [<version>]}"
-help = [[
+install.help = [[
Argument may be the name of a rock to be fetched from a repository
or a filename of a locally available rock.
@@ -25,7 +26,8 @@ or a filename of a locally available rock.
rock after installing a new one. This behavior can
be made permanent by setting keep_other_versions=true
in the configuration file.
-]]
+]]..util.deps_mode_help()
+
--- Install a binary rock.
-- @param rock_file string: local or remote filename of a rock.
@@ -34,7 +36,7 @@ or a filename of a locally available rock.
-- "order" for all trees with priority >= the current default, "none" for no trees.
-- @return (string, string) or (nil, string, [string]): Name and version of
-- installed rock if succeeded or nil and an error message followed by an error code.
-function install_binary_rock(rock_file, deps_mode)
+function install.install_binary_rock(rock_file, deps_mode)
assert(type(rock_file) == "string")
local name, version, arch = path.parse_name(rock_file)
@@ -80,11 +82,6 @@ function install_binary_rock(rock_file, deps_mode)
if err then return nil, err, errcode end
end
- local wrap_bin_scripts = true
- if rockspec.deploy and rockspec.deploy.wrap_bin_scripts == false then
- wrap_bin_scripts = false
- end
-
ok, err = repos.deploy_files(name, version, repos.should_wrap_bin_scripts(rockspec))
if err then return nil, err end
@@ -120,23 +117,23 @@ end
-- if returned a result, installs the matching rock.
-- @param version string: When passing a package name, a version number
-- may also be given.
--- @return boolean or (nil, string): True if installation was
--- successful, nil and an error message otherwise.
-function run(...)
+-- @return boolean or (nil, string, exitcode): True if installation was
+-- successful, nil and an error message otherwise. exitcode is optionally returned.
+function install.run(...)
local flags, name, version = util.parse_flags(...)
if type(name) ~= "string" then
return nil, "Argument missing. "..util.see_help("install")
end
local ok, err = fs.check_command_permissions(flags)
- if not ok then return nil, err end
+ if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end
if name:match("%.rockspec$") or name:match("%.src%.rock$") then
util.printout("Using "..name.."... switching to 'build' mode")
local build = require("luarocks.build")
return build.run(name, util.forward_flags(flags, "local", "keep", "deps-mode"))
elseif name:match("%.rock$") then
- ok, err = install_binary_rock(name, deps.get_deps_mode(flags))
+ ok, err = install.install_binary_rock(name, deps.get_deps_mode(flags))
if not ok then return nil, err end
local name, version = ok, err
if (not flags["keep"]) and not cfg.keep_other_versions then
@@ -152,7 +149,7 @@ function run(...)
elseif type(results) == "string" then
local url = results
util.printout("Installing "..url.."...")
- return run(url, util.forward_flags(flags))
+ return install.run(url, util.forward_flags(flags))
else
util.printout()
util.printerr("Could not determine which rock to install.")
@@ -162,3 +159,5 @@ function run(...)
end
end
end
+
+return install
diff --git a/src/luarocks/lint.lua b/src/luarocks/lint.lua
index 62ced64..091c8de 100644
--- a/src/luarocks/lint.lua
+++ b/src/luarocks/lint.lua
@@ -1,22 +1,24 @@
--- Module implementing the LuaRocks "lint" command.
-- Utility function that checks syntax of the rockspec.
-module("luarocks.lint", package.seeall)
+--module("luarocks.lint", package.seeall)
+local lint = {}
+package.loaded["luarocks.lint"] = lint
local util = require("luarocks.util")
local download = require("luarocks.download")
local fetch = require("luarocks.fetch")
-help_summary = "Check syntax of a rockspec."
-help_arguments = "<rockspec>"
-help = [[
+lint.help_summary = "Check syntax of a rockspec."
+lint.help_arguments = "<rockspec>"
+lint.help = [[
This is a utility function that checks the syntax of a rockspec.
It returns success or failure if the text of a rockspec is
syntactically correct.
]]
-function run(...)
+function lint.run(...)
local flags, input = util.parse_flags(...)
if not input then
@@ -37,5 +39,19 @@ function run(...)
return nil, "Failed loading rockspec: "..err
end
- return true
+ local ok = true
+
+ -- This should have been done in the type checker,
+ -- but it would break compatibility of other commands.
+ -- Making 'lint' alone be stricter shouldn't be a problem,
+ -- because extra-strict checks is what lint-type commands
+ -- are all about.
+ if not rs.description.license then
+ util.printerr("Rockspec has no license field.")
+ ok = false
+ end
+
+ return ok, ok or filename.." failed consistency checks."
end
+
+return lint
diff --git a/src/luarocks/list.lua b/src/luarocks/list.lua
index 6081ed4..319909d 100644
--- a/src/luarocks/list.lua
+++ b/src/luarocks/list.lua
@@ -1,16 +1,18 @@
--- Module implementing the LuaRocks "list" command.
-- Lists currently installed rocks.
-module("luarocks.list", package.seeall)
+--module("luarocks.list", package.seeall)
+local list = {}
+package.loaded["luarocks.list"] = list
local search = require("luarocks.search")
local cfg = require("luarocks.cfg")
local util = require("luarocks.util")
local path = require("luarocks.path")
-help_summary = "Lists currently installed rocks."
-help_arguments = "[--porcelain] <filter>"
-help = [[
+list.help_summary = "Lists currently installed rocks."
+list.help_arguments = "[--porcelain] <filter>"
+list.help = [[
<filter> is a substring of a rock name to filter by.
--porcelain Produce machine-friendly output.
@@ -20,7 +22,7 @@ help = [[
-- @param filter string or nil: A substring of a rock name to filter by.
-- @param version string or nil: a version may also be passed.
-- @return boolean: True if succeeded, nil on errors.
-function run(...)
+function list.run(...)
local flags, filter, version = util.parse_flags(...)
local results = {}
local query = search.make_query(filter and filter:lower() or "", version)
@@ -36,3 +38,5 @@ function run(...)
search.print_results(results, flags["porcelain"])
return true
end
+
+return list
diff --git a/src/luarocks/loader.lua b/src/luarocks/loader.lua
index a116766..1eaa672 100644
--- a/src/luarocks/loader.lua
+++ b/src/luarocks/loader.lua
@@ -5,23 +5,28 @@
-- table in the environment, which records which versions of packages were
-- used to load previous modules, so that the loader chooses versions
-- that are declared to be compatible with the ones loaded earlier.
-local global_env = _G
-local package, require, ipairs, pairs, table, type, next, unpack =
- package, require, ipairs, pairs, table, type, next, unpack
+local loaders = package.loaders or package.searchers
+local package, require, ipairs, pairs, table, type, next, tostring, error =
+ package, require, ipairs, pairs, table, type, next, tostring, error
+local unpack = unpack or table.unpack
-module("luarocks.loader")
+--module("luarocks.loader")
+local loader = {}
+package.loaded["luarocks.loader"] = loader
+
+local cfg = require("luarocks.cfg")
+cfg.init_package_paths()
local path = require("luarocks.path")
local manif_core = require("luarocks.manif_core")
local deps = require("luarocks.deps")
-local cfg = require("luarocks.cfg")
-context = {}
+loader.context = {}
-- Contains a table when rocks trees are loaded,
-- or 'false' to indicate rocks trees failed to load.
-- 'nil' indicates rocks trees were not attempted to be loaded yet.
-rocks_trees = nil
+loader.rocks_trees = nil
local function load_rocks_trees()
local any_ok = false
@@ -34,10 +39,10 @@ local function load_rocks_trees()
end
end
if not any_ok then
- rocks_trees = false
+ loader.rocks_trees = false
return false
end
- rocks_trees = trees
+ loader.rocks_trees = trees
return true
end
@@ -45,21 +50,20 @@ end
-- chain for loading modules.
-- @param name string: The name of an installed rock.
-- @param version string: The version of the rock, in string format
-function add_context(name, version)
+function loader.add_context(name, version)
-- assert(type(name) == "string")
-- assert(type(version) == "string")
- if context[name] then
+ if loader.context[name] then
return
end
- context[name] = version
+ loader.context[name] = version
- if not rocks_trees and not load_rocks_trees() then
+ if not loader.rocks_trees and not load_rocks_trees() then
return nil
end
- local providers = {}
- for _, tree in ipairs(rocks_trees) do
+ for _, tree in ipairs(loader.rocks_trees) do
local manifest = tree.manifest
local pkgdeps
@@ -72,12 +76,12 @@ function add_context(name, version)
for _, dep in ipairs(pkgdeps) do
local pkg, constraints = dep.name, dep.constraints
- for _, tree in ipairs(rocks_trees) do
+ for _, tree in ipairs(loader.rocks_trees) do
local entries = tree.manifest.repository[pkg]
if entries then
for version, pkgs in pairs(entries) do
if (not constraints) or deps.match_constraints(deps.parse_version(version), constraints) then
- add_context(pkg, version)
+ loader.add_context(pkg, version)
end
end
end
@@ -108,9 +112,9 @@ end
-- @return table or (nil, string): The module table as returned by some other loader,
-- or nil followed by an error message if no other loader managed to load the module.
local function call_other_loaders(module, name, version, module_name)
- for i, loader in pairs(package.loaders) do
- if loader ~= luarocks_loader then
- local results = { loader(module_name) }
+ for i, a_loader in ipairs(loaders) do
+ if a_loader ~= loader.luarocks_loader then
+ local results = { a_loader(module_name) }
if type(results[1]) == "function" then
return unpack(results)
end
@@ -126,34 +130,35 @@ end
-- (eg "luasocket"), the version (eg "2.0.2-1"), the path of the rocks tree
-- (eg "/usr/local"), and the numeric index of the matching entry, so the
-- filter function can know if the matching module was the first entry or not.
--- @return string, string, string: name of the rock containing the module
--- (eg. "luasocket"), version of the rock (eg. "2.0.2-1"),
--- name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is
--- stored versioned).
+-- @return string, string, string, (string or table):
+-- * name of the rock containing the module (eg. "luasocket")
+-- * version of the rock (eg. "2.0.2-1")
+-- * name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is stored versioned).
+-- * tree of the module (string or table in `rocks_trees` format)
local function select_module(module, filter_module_name)
--assert(type(module) == "string")
--assert(type(filter_module_name) == "function")
- if not rocks_trees and not load_rocks_trees() then
+ if not loader.rocks_trees and not load_rocks_trees() then
return nil
end
local providers = {}
- for _, tree in ipairs(rocks_trees) do
+ for _, tree in ipairs(loader.rocks_trees) do
local entries = tree.manifest.modules[module]
if entries then
for i, entry in ipairs(entries) do
local name, version = entry:match("^([^/]*)/(.*)$")
local module_name = tree.manifest.repository[name][version][1].modules[module]
if type(module_name) ~= "string" then
- error("Invalid format in manifest file (invalid data for "..tostring(name).." "..tostring(version)..")")
+ error("Invalid data in manifest file for module "..tostring(module).." (invalid data for "..tostring(name).." "..tostring(version)..")")
end
module_name = filter_module_name(module_name, name, version, tree.tree, i)
- if context[name] == version then
+ if loader.context[name] == version then
return name, version, module_name
end
version = deps.parse_version(version)
- table.insert(providers, {name = name, version = version, module_name = module_name})
+ table.insert(providers, {name = name, version = version, module_name = module_name, tree = tree})
end
end
end
@@ -161,16 +166,17 @@ local function select_module(module, filter_module_name)
if next(providers) then
table.sort(providers, sort_versions)
local first = providers[1]
- return first.name, first.version.string, first.module_name
+ return first.name, first.version.string, first.module_name, first.tree
end
end
--- Search for a module
-- @param module string: module name (eg. "socket.core")
--- @return string, string, string: name of the rock containing the module
--- (eg. "luasocket"), version of the rock (eg. "2.0.2-1"),
--- name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is
--- stored versioned).
+-- @return string, string, string, (string or table):
+-- * name of the rock containing the module (eg. "luasocket")
+-- * version of the rock (eg. "2.0.2-1")
+-- * name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is stored versioned).
+-- * tree of the module (string or table in `rocks_trees` format)
local function pick_module(module)
return
select_module(module, function(module_name, name, version, tree, i)
@@ -185,7 +191,7 @@ end
--- Return the pathname of the file that would be loaded for a module.
-- @param module string: module name (eg. "socket.core")
-- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so")
-function which(module)
+function loader.which(module)
local name, version, module_name = select_module(module, path.which_i)
return module_name
end
@@ -199,14 +205,16 @@ end
-- @return table: The module table (typically), like in plain
-- require(). See <a href="http://www.lua.org/manual/5.1/manual.html#pdf-require">require()</a>
-- in the Lua reference manual for details.
-function luarocks_loader(module)
+function loader.luarocks_loader(module)
local name, version, module_name = pick_module(module)
if not name then
return "No LuaRocks module found for "..module
else
- add_context(name, version)
+ loader.add_context(name, version)
return call_other_loaders(module, name, version, module_name)
end
end
-table.insert(global_env.package.loaders, 1, luarocks_loader)
+table.insert(loaders, 1, loader.luarocks_loader)
+
+return loader
diff --git a/src/luarocks/make.lua b/src/luarocks/make.lua
index eef49d0..1dfe647 100644
--- a/src/luarocks/make.lua
+++ b/src/luarocks/make.lua
@@ -3,7 +3,9 @@
-- Builds sources in the current directory, but unlike "build",
-- it does not fetch sources, etc., assuming everything is
-- available in the current directory.
-module("luarocks.make", package.seeall)
+--module("luarocks.make", package.seeall)
+local make = {}
+package.loaded["luarocks.make"] = make
local build = require("luarocks.build")
local fs = require("luarocks.fs")
@@ -14,9 +16,9 @@ local pack = require("luarocks.pack")
local remove = require("luarocks.remove")
local deps = require("luarocks.deps")
-help_summary = "Compile package in current directory using a rockspec."
-help_arguments = "[--pack-binary-rock] [<rockspec>]"
-help = [[
+make.help_summary = "Compile package in current directory using a rockspec."
+make.help_arguments = "[--pack-binary-rock] [<rockspec>]"
+make.help = [[
Builds sources in the current directory, but unlike "build",
it does not fetch sources, etc., assuming everything is
available in the current directory. If no argument is given,
@@ -36,19 +38,22 @@ To install rocks, you'll normally want to use the "install" and
be made permanent by setting keep_other_versions=true
in the configuration file.
+--branch=<name> Override the `source.branch` field in the loaded
+ rockspec. Allows to specify a different branch to
+ fetch. Particularly for SCM rocks.
+
]]
--- Driver function for "make" command.
-- @param name string: A local rockspec.
--- @return boolean or (nil, string): True if build was successful; nil and an
--- error message otherwise.
-function run(...)
+-- @return boolean or (nil, string, exitcode): True if build was successful; nil and an
+-- error message otherwise. exitcode is optionally returned.
+function make.run(...)
local flags, rockspec = util.parse_flags(...)
assert(type(rockspec) == "string" or not rockspec)
if not rockspec then
- local files = fs.list_dir(fs.current_dir())
- for _, file in pairs(files) do
+ for file in fs.dir() do
if file:match("rockspec$") then
if rockspec then
return nil, "Please specify which rockspec file to use."
@@ -73,7 +78,7 @@ function run(...)
return pack.pack_binary_rock(rspec.name, rspec.version, build.build_rockspec, rockspec, false, true, deps.get_deps_mode(flags))
else
local ok, err = fs.check_command_permissions(flags)
- if not ok then return nil, err end
+ if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end
ok, err = build.build_rockspec(rockspec, false, true, deps.get_deps_mode(flags))
if not ok then return nil, err end
local name, version = ok, err
@@ -84,3 +89,5 @@ function run(...)
return name, version
end
end
+
+return make
diff --git a/src/luarocks/make_manifest.lua b/src/luarocks/make_manifest.lua
index a698f83..b6e65bf 100644
--- a/src/luarocks/make_manifest.lua
+++ b/src/luarocks/make_manifest.lua
@@ -1,17 +1,21 @@
--- Module implementing the luarocks-admin "make_manifest" command.
-- Compile a manifest file for a repository.
-module("luarocks.make_manifest", package.seeall)
+--module("luarocks.make_manifest", package.seeall)
+local make_manifest = {}
+package.loaded["luarocks.make_manifest"] = make_manifest
local manif = require("luarocks.manif")
local index = require("luarocks.index")
local cfg = require("luarocks.cfg")
local util = require("luarocks.util")
local deps = require("luarocks.deps")
+local fs = require("luarocks.fs")
+local dir = require("luarocks.dir")
-help_summary = "Compile a manifest file for a repository."
+make_manifest.help_summary = "Compile a manifest file for a repository."
-help = [[
+make_manifest.help = [[
<argument>, if given, is a local repository pathname.
--local-tree If given, do not write versioned versions of the manifest file.
@@ -23,7 +27,7 @@ help = [[
-- the default local repository configured as cfg.rocks_dir is used.
-- @return boolean or (nil, string): True if manifest was generated,
-- or nil and an error message.
-function run(...)
+function make_manifest.run(...)
local flags, repo = util.parse_flags(...)
assert(type(repo) == "string" or not repo)
@@ -31,10 +35,21 @@ function run(...)
util.printout("Making manifest for "..repo)
+ if repo:match("/lib/luarocks") and not flags["local-tree"] then
+ util.warning("This looks like a local rocks tree, but you did not pass --local-tree.")
+ end
+
local ok, err = manif.make_manifest(repo, deps.get_deps_mode(flags), not flags["local-tree"])
if ok and not flags["local-tree"] then
util.printout("Generating index.html for "..repo)
index.make_index(repo)
end
+ if flags["local-tree"] then
+ for luaver in util.lua_versions() do
+ fs.delete(dir.path(repo, "manifest-"..luaver))
+ end
+ end
return ok, err
end
+
+return make_manifest
diff --git a/src/luarocks/manif.lua b/src/luarocks/manif.lua
index c17da71..f53f8dc 100644
--- a/src/luarocks/manif.lua
+++ b/src/luarocks/manif.lua
@@ -1,9 +1,10 @@
-
--- Module for handling manifest files and tables.
-- Manifest files describe the contents of a LuaRocks tree or server.
-- They are loaded into manifest tables, which are then used for
-- performing searches, matching dependencies, etc.
-module("luarocks.manif", package.seeall)
+--module("luarocks.manif", package.seeall)
+local manif = {}
+package.loaded["luarocks.manif"] = manif
local manif_core = require("luarocks.manif_core")
local persist = require("luarocks.persist")
@@ -17,7 +18,7 @@ local path = require("luarocks.path")
local repos = require("luarocks.repos")
local deps = require("luarocks.deps")
-rock_manifest_cache = {}
+manif.rock_manifest_cache = {}
--- Commit a table to disk in given local path.
-- @param where string: The directory where the table should be saved.
@@ -38,22 +39,22 @@ local function save_table(where, name, tbl)
return ok, err
end
-function load_rock_manifest(name, version, root)
+function manif.load_rock_manifest(name, version, root)
assert(type(name) == "string")
assert(type(version) == "string")
local name_version = name.."/"..version
- if rock_manifest_cache[name_version] then
- return rock_manifest_cache[name_version].rock_manifest
+ if manif.rock_manifest_cache[name_version] then
+ return manif.rock_manifest_cache[name_version].rock_manifest
end
local pathname = path.rock_manifest_file(name, version, root)
local rock_manifest = persist.load_into_table(pathname)
if not rock_manifest then return nil end
- rock_manifest_cache[name_version] = rock_manifest
+ manif.rock_manifest_cache[name_version] = rock_manifest
return rock_manifest.rock_manifest
end
-function make_rock_manifest(name, version)
+function manif.make_rock_manifest(name, version)
local install_dir = path.install_dir(name, version)
local rock_manifest = path.rock_manifest_file(name, version)
local tree = {}
@@ -73,18 +74,27 @@ function make_rock_manifest(name, version)
walk = next
end
if fs.is_file(full_path) then
- last[last_name] = fs.get_md5(full_path)
+ local sum, err = fs.get_md5(full_path)
+ if not sum then
+ return nil, "Failed producing checksum: "..tostring(err)
+ end
+ last[last_name] = sum
end
end
- local rock_manifest = { rock_manifest=tree }
- rock_manifest_cache[name.."/"..version] = rock_manifest
+ rock_manifest = { rock_manifest=tree }
+ manif.rock_manifest_cache[name.."/"..version] = rock_manifest
save_table(install_dir, "rock_manifest", rock_manifest )
end
local function fetch_manifest_from(repo_url, filename)
local url = dir.path(repo_url, filename)
local name = repo_url:gsub("[/:]","_")
- local file, err, errcode = fetch.fetch_url_at_temp_dir(url, "luarocks-manifest-"..name)
+ local cache_dir = dir.path(cfg.local_cache, name)
+ local ok = fs.make_dir(cache_dir)
+ if not ok then
+ return nil, "Failed creating temporary cache directory "..cache_dir
+ end
+ local file, err, errcode = fetch.fetch_url(url, dir.path(cache_dir, filename), true)
if not file then
return nil, "Failed fetching manifest for "..repo_url..(err and " - "..err or ""), errcode
end
@@ -97,32 +107,54 @@ end
-- @param repo_url string: URL or pathname for the repository.
-- @return table or (nil, string, [string]): A table representing the manifest,
-- or nil followed by an error message and an optional error code.
-function load_manifest(repo_url)
+function manif.load_manifest(repo_url)
assert(type(repo_url) == "string")
if manif_core.manifest_cache[repo_url] then
return manif_core.manifest_cache[repo_url]
end
-
- local vmanifest = "manifest-"..cfg.lua_version
-
- local protocol, pathname = dir.split_url(repo_url)
+
+ local filenames = {
+ "manifest-"..cfg.lua_version..".zip",
+ "manifest-"..cfg.lua_version,
+ "manifest",
+ }
+
+ local protocol, repodir = dir.split_url(repo_url)
+ local pathname
if protocol == "file" then
- local file = dir.path(pathname, vmanifest)
- if fs.exists(file) then
- pathname = file
- else
- pathname = dir.path(pathname, "manifest")
+ for _, filename in ipairs(filenames) do
+ pathname = dir.path(repodir, filename)
+ if fs.exists(pathname) then
+ break
+ end
end
else
- local file, err = fetch_manifest_from(repo_url, vmanifest)
- if not file then
- file, err = fetch_manifest_from(repo_url, "manifest")
+ local err, errcode
+ for _, filename in ipairs(filenames) do
+ pathname, err, errcode = fetch_manifest_from(repo_url, filename)
+ if pathname then
+ break
+ end
end
- if not file then
- return nil, err
+ if not pathname then
+ return nil, err, errcode
+ end
+ end
+ if pathname:match(".*%.zip$") then
+ pathname = fs.absolute_name(pathname)
+ local dir = dir.dir_name(pathname)
+ fs.change_dir(dir)
+ local nozip = pathname:match("(.*)%.zip$")
+ fs.delete(nozip)
+ local ok = fs.unzip(pathname)
+ fs.pop_dir()
+ if not ok then
+ fs.delete(pathname)
+ fs.delete(pathname..".timestamp")
+ return nil, "Failed extracting manifest file"
end
- pathname = file
+ pathname = nozip
end
return manif_core.manifest_loader(pathname, repo_url)
end
@@ -206,18 +238,11 @@ end
-- @param deps_mode string: Dependency mode: "one" for the current default tree,
-- "all" for all trees, "order" for all trees with priority >= the current default,
-- "none" for no trees.
--- @param repodir string: directory of repository being scanned
--- @param filter_lua string or nil: filter by Lua version
--- @param cache table: temporary rockspec cache table
-local function update_dependencies(manifest, deps_mode, repodir, filter_lua, cache)
+local function update_dependencies(manifest, deps_mode)
assert(type(manifest) == "table")
assert(type(deps_mode) == "string")
- cache = cache or {}
- local lua_version = filter_lua and deps.parse_version(filter_lua)
-
for pkg, versions in pairs(manifest.repository) do
- local to_remove = {}
for version, repositories in pairs(versions) do
local current = pkg.." "..version
for _, repo in ipairs(repositories) do
@@ -229,16 +254,39 @@ local function update_dependencies(manifest, deps_mode, repodir, filter_lua, cac
for miss, err in pairs(missing) do
if miss == current then
util.printerr("Tree inconsistency detected: "..current.." has no rockspec. "..err)
- else
+ elseif deps_mode ~= "none" then
util.printerr("Missing dependency for "..pkg.." "..version..": "..miss)
end
end
end
- elseif filter_lua and repo.arch == "rockspec" then
+ end
+ end
+ end
+ end
+end
+
+--- Filter manifest table by Lua version, removing rockspecs whose Lua version
+-- does not match.
+-- @param manifest table: a manifest table.
+-- @param lua_version string or nil: filter by Lua version
+-- @param repodir string: directory of repository being scanned
+-- @param cache table: temporary rockspec cache table
+local function filter_by_lua_version(manifest, lua_version, repodir, cache)
+ assert(type(manifest) == "table")
+ assert(type(repodir) == "string")
+ assert((not cache) or type(cache) == "table")
+
+ cache = cache or {}
+ lua_version = deps.parse_version(lua_version)
+ for pkg, versions in pairs(manifest.repository) do
+ local to_remove = {}
+ for version, repositories in pairs(versions) do
+ for _, repo in ipairs(repositories) do
+ if repo.arch == "rockspec" then
local pathname = dir.path(repodir, pkg.."-"..version..".rockspec")
local rockspec, err = cache[pathname]
if not rockspec then
- rockspec, err = fetch.load_local_rockspec(pathname)
+ rockspec, err = fetch.load_local_rockspec(pathname, true)
end
if rockspec then
cache[pathname] = rockspec
@@ -258,9 +306,9 @@ local function update_dependencies(manifest, deps_mode, repodir, filter_lua, cac
end
if next(to_remove) then
for _, incompat in ipairs(to_remove) do
- manifest.repository[pkg][incompat] = nil
+ versions[incompat] = nil
end
- if not next(manifest.repository[pkg]) then
+ if not next(versions) then
manifest.repository[pkg] = nil
end
end
@@ -271,17 +319,12 @@ end
-- @param results table: The search results as returned by search.disk_search.
-- @param manifest table: A manifest table (must contain repository, modules, commands tables).
-- It will be altered to include the search results.
--- @param deps_mode string: Dependency mode: "one" for the current default tree,
--- "all" for all trees, "order" for all trees with priority >= the current default,
--- "none" for no trees.
--- @param repo string: directory of repository
--- @param filter_lua string or nil: filter by Lua version
--- @param cache table: temporary rockspec cache table
+-- @param dep_handler: dependency handler function
-- @return boolean or (nil, string): true in case of success, or nil followed by an error message.
-local function store_results(results, manifest, deps_mode, repo, filter_lua, cache)
+local function store_results(results, manifest, dep_handler)
assert(type(results) == "table")
assert(type(manifest) == "table")
- assert(type(deps_mode) == "string")
+ assert((not dep_handler) or type(dep_handler) == "function")
for name, versions in pairs(results) do
local pkgtable = manifest.repository[name] or {}
@@ -291,7 +334,7 @@ local function store_results(results, manifest, deps_mode, repo, filter_lua, cac
local entrytable = {}
entrytable.arch = entry.arch
if entry.arch == "installed" then
- local rock_manifest = load_rock_manifest(name, version)
+ local rock_manifest = manif.load_rock_manifest(name, version)
if not rock_manifest then
return nil, "rock_manifest file not found for "..name.." "..version.." - not a LuaRocks 2 tree?"
end
@@ -304,7 +347,9 @@ local function store_results(results, manifest, deps_mode, repo, filter_lua, cac
end
manifest.repository[name] = pkgtable
end
- update_dependencies(manifest, deps_mode, repo, filter_lua, cache)
+ if dep_handler then
+ dep_handler(manifest)
+ end
sort_package_matching_table(manifest.modules)
sort_package_matching_table(manifest.commands)
return true
@@ -320,7 +365,7 @@ end
-- @param versioned boolean: if versioned versions of the manifest should be created.
-- @return boolean or (nil, string): True if manifest was generated,
-- or nil and an error message.
-function make_manifest(repo, deps_mode, versioned)
+function manif.make_manifest(repo, deps_mode, remote)
assert(type(repo) == "string")
assert(type(deps_mode) == "string")
@@ -338,14 +383,23 @@ function make_manifest(repo, deps_mode, versioned)
manif_core.manifest_cache[repo] = manifest
- local cache = {}
- local ok, err = store_results(results, manifest, deps_mode, repo, nil, cache)
+ local dep_handler = nil
+ if not remote then
+ dep_handler = function(manifest)
+ update_dependencies(manifest, deps_mode)
+ end
+ end
+ local ok, err = store_results(results, manifest, dep_handler)
if not ok then return nil, err end
- if versioned then
- for _, luaver in ipairs({"5.1", "5.2"}) do
+ if remote then
+ local cache = {}
+ for luaver in util.lua_versions() do
local vmanifest = { repository = {}, modules = {}, commands = {} }
- local ok, err = store_results(results, vmanifest, deps_mode, repo, luaver, cache)
+ local dep_handler = function(manifest)
+ filter_by_lua_version(manifest, luaver, repo, cache)
+ end
+ local ok, err = store_results(results, vmanifest, dep_handler)
save_table(repo, "manifest-"..luaver, vmanifest)
end
end
@@ -360,13 +414,13 @@ end
-- @param name string: Name of a package from the repository.
-- @param version string: Version of a package from the repository.
-- @param repo string or nil: Pathname of a local repository. If not given,
--- the default local repository configured as cfg.rocks_dir is used.
+-- the default local repository is used.
-- @param deps_mode string: Dependency mode: "one" for the current default tree,
-- "all" for all trees, "order" for all trees with priority >= the current default,
-- "none" for using the default dependency mode from the configuration.
-- @return boolean or (nil, string): True if manifest was generated,
-- or nil and an error message.
-function update_manifest(name, version, repo, deps_mode)
+function manif.update_manifest(name, version, repo, deps_mode)
assert(type(name) == "string")
assert(type(version) == "string")
repo = path.rocks_dir(repo or cfg.root_dir)
@@ -376,14 +430,14 @@ function update_manifest(name, version, repo, deps_mode)
util.printout("Updating manifest for "..repo)
- local manifest, err = load_manifest(repo)
+ local manifest, err = manif.load_manifest(repo)
if not manifest then
util.printerr("No existing manifest. Attempting to rebuild...")
- local ok, err = make_manifest(repo, deps_mode)
+ local ok, err = manif.make_manifest(repo, deps_mode)
if not ok then
return nil, err
end
- manifest, err = load_manifest(repo)
+ manifest, err = manif.load_manifest(repo)
if not manifest then
return nil, err
end
@@ -391,19 +445,31 @@ function update_manifest(name, version, repo, deps_mode)
local results = {[name] = {[version] = {{arch = "installed", repo = repo}}}}
- local ok, err = store_results(results, manifest, deps_mode, repo)
+ local dep_handler = function(manifest)
+ update_dependencies(manifest, deps_mode)
+ end
+ local ok, err = store_results(results, manifest, dep_handler)
if not ok then return nil, err end
return save_table(repo, "manifest", manifest)
end
+function manif.zip_manifests()
+ for ver in util.lua_versions() do
+ local file = "manifest-"..ver
+ local zip = file..".zip"
+ fs.delete(dir.path(fs.current_dir(), zip))
+ fs.zip(zip, file)
+ end
+end
+
local function find_providers(file, root)
assert(type(file) == "string")
root = root or cfg.root_dir
local manifest, err = manif_core.load_local_manifest(path.rocks_dir(root))
if not manifest then
- return nil, err .. " -- corrupted local rocks tree?"
+ return nil, "untracked"
end
local deploy_bin = path.deploy_bin_dir(root)
local deploy_lua = path.deploy_lua_dir(root)
@@ -435,13 +501,13 @@ end
-- @param file string: The full path of a deployed file.
-- @param root string or nil: A local root dir for a rocks tree. If not given, the default is used.
-- @return string, string: name and version of the provider rock.
-function find_current_provider(file, root)
+function manif.find_current_provider(file, root)
local providers, err = find_providers(file, root)
if not providers then return nil, err end
return providers[1]:match("([^/]*)/([^/]*)")
end
-function find_next_provider(file, root)
+function manif.find_next_provider(file, root)
local providers, err = find_providers(file, root)
if not providers then return nil, err end
if providers[2] then
@@ -450,3 +516,5 @@ function find_next_provider(file, root)
return nil
end
end
+
+return manif
diff --git a/src/luarocks/manif_core.lua b/src/luarocks/manif_core.lua
index 6424a1e..1a2c111 100644
--- a/src/luarocks/manif_core.lua
+++ b/src/luarocks/manif_core.lua
@@ -1,7 +1,9 @@
--- Core functions for querying manifest files.
-- This module requires no specific 'fs' functionality.
-module("luarocks.manif_core", package.seeall)
+--module("luarocks.manif_core", package.seeall)
+local manif_core = {}
+package.loaded["luarocks.manif_core"] = manif_core
local persist = require("luarocks.persist")
local type_check = require("luarocks.type_check")
@@ -10,26 +12,27 @@ local util = require("luarocks.util")
local cfg = require("luarocks.cfg")
local path = require("luarocks.path")
-manifest_cache = {}
+manif_core.manifest_cache = {}
--- Back-end function that actually loads the manifest
-- and stores it in the manifest cache.
-- @param file string: The local filename of the manifest file.
-- @param repo_url string: The repository identifier.
-- @param quick boolean: If given, skips type checking.
-function manifest_loader(file, repo_url, quick)
+function manif_core.manifest_loader(file, repo_url, quick)
local manifest, err = persist.load_into_table(file)
if not manifest then
return nil, "Failed loading manifest for "..repo_url..": "..err
end
+ local globals = err
if not quick then
- local ok, err = type_check.type_check_manifest(manifest)
+ local ok, err = type_check.type_check_manifest(manifest, globals)
if not ok then
return nil, "Error checking manifest: "..err
end
end
- manifest_cache[repo_url] = manifest
+ manif_core.manifest_cache[repo_url] = manifest
return manifest
end
@@ -39,16 +42,16 @@ end
-- @param repo_url string: URL or pathname for the repository.
-- @return table or (nil, string): A table representing the manifest,
-- or nil followed by an error message.
-function load_local_manifest(repo_url)
+function manif_core.load_local_manifest(repo_url)
assert(type(repo_url) == "string")
- if manifest_cache[repo_url] then
- return manifest_cache[repo_url]
+ if manif_core.manifest_cache[repo_url] then
+ return manif_core.manifest_cache[repo_url]
end
local pathname = dir.path(repo_url, "manifest")
- return manifest_loader(pathname, repo_url, true)
+ return manif_core.manifest_loader(pathname, repo_url, true)
end
--- Get all versions of a package listed in a manifest file.
@@ -59,13 +62,13 @@ end
-- or "all", to use all trees.
-- @return table: An array of strings listing installed
-- versions of a package.
-function get_versions(name, deps_mode)
+function manif_core.get_versions(name, deps_mode)
assert(type(name) == "string")
assert(type(deps_mode) == "string")
local manifest = {}
path.map_trees(deps_mode, function(tree)
- local loaded = load_local_manifest(path.rocks_dir(tree))
+ local loaded = manif_core.load_local_manifest(path.rocks_dir(tree))
if loaded then
util.deep_merge(manifest, loaded)
end
@@ -77,3 +80,5 @@ function get_versions(name, deps_mode)
end
return {}
end
+
+return manif_core
diff --git a/src/luarocks/new_version.lua b/src/luarocks/new_version.lua
index cb17032..9ef0cfb 100644
--- a/src/luarocks/new_version.lua
+++ b/src/luarocks/new_version.lua
@@ -1,19 +1,20 @@
--- Module implementing the LuaRocks "new_version" command.
-- Utility function that writes a new rockspec, updating data from a previous one.
-module("luarocks.new_version", package.seeall)
+--module("luarocks.new_version", package.seeall)
+local new_version = {}
+package.loaded["luarocks.new_version"] = new_version
local util = require("luarocks.util")
-local cfg = require("luarocks.cfg")
local download = require("luarocks.download")
local fetch = require("luarocks.fetch")
local persist = require("luarocks.persist")
-local dir = require("luarocks.dir")
local fs = require("luarocks.fs")
+local type_check = require("luarocks.type_check")
-help_summary = "Auto-write a rockspec for a new version of a rock."
-help_arguments = "{<package>|<rockspec>} [<new_version>] [<new_url>]"
-help = [[
+new_version.help_summary = "Auto-write a rockspec for a new version of a rock."
+new_version.help_arguments = "{<package>|<rockspec>} [<new_version>] [<new_url>]"
+new_version.help = [[
This is a utility function that writes a new rockspec, updating data
from a previous one.
@@ -33,13 +34,6 @@ WARNING: it writes the new rockspec to the current directory,
overwriting the file if it already exists.
]]
-local order = {"rockspec_format", "package", "version",
- { "source", { "url", "tag", "branch", "md5" } },
- { "description", {"summary", "detailed", "homepage", "license" } },
- "supported_platforms", "dependencies", "external_dependencies",
- { "build", {"type", "modules", "copy_directories", "platforms"} },
- "hooks"}
-
local function try_replace(tbl, field, old, new)
if not tbl[field] then
return false
@@ -64,18 +58,13 @@ local function check_url_and_update_md5(out_rs, out_name)
end
util.printout("File successfully downloaded. Updating MD5 checksum...")
out_rs.source.md5 = fs.get_md5(file)
- fs.change_dir(temp_dir)
- fs.unpack_archive(file)
- local base_dir = out_rs.source.dir or fetch.url_to_base_dir(out_rs.source.url)
- if not fs.exists(base_dir) then
- util.printerr("Directory "..base_dir.." not found")
- local files = fs.list_dir()
- if files[1] and fs.is_dir(files[1]) then
- util.printerr("Found "..files[1])
- out_rs.source.dir = files[1]
- end
+ local inferred_dir, found_dir = fetch.find_base_dir(file, temp_dir, out_rs.source.url, out_rs.source.dir)
+ if not inferred_dir then
+ return nil, found_dir
+ end
+ if found_dir and found_dir ~= inferred_dir then
+ out_rs.source.dir = found_dir
end
- fs.pop_dir()
return out_rs.source.md5 ~= old_md5
end
@@ -115,7 +104,7 @@ local function update_source_section(out_rs, out_name, url, old_ver, new_ver)
return true
end
-function run(...)
+function new_version.run(...)
local flags, input, version, url = util.parse_flags(...)
if not input then
return nil, "Missing arguments: expected program or rockspec. "..util.see_help("new_version")
@@ -165,7 +154,7 @@ function run(...)
local out_filename = out_name.."-"..new_rockver.."-"..new_rev..".rockspec"
- persist.save_from_table(out_filename, out_rs, order)
+ persist.save_from_table(out_filename, out_rs, type_check.rockspec_order)
util.printout("Wrote "..out_filename)
@@ -176,3 +165,5 @@ function run(...)
return true
end
+
+return new_version
diff --git a/src/luarocks/pack.lua b/src/luarocks/pack.lua
index 583932e..c73d66a 100644
--- a/src/luarocks/pack.lua
+++ b/src/luarocks/pack.lua
@@ -1,7 +1,11 @@
--- Module implementing the LuaRocks "pack" command.
-- Creates a rock, packing sources or binaries.
-module("luarocks.pack", package.seeall)
+--module("luarocks.pack", package.seeall)
+local pack = {}
+package.loaded["luarocks.pack"] = pack
+
+local unpack = unpack or table.unpack
local path = require("luarocks.path")
local repos = require("luarocks.repos")
@@ -13,9 +17,9 @@ local dir = require("luarocks.dir")
local manif = require("luarocks.manif")
local search = require("luarocks.search")
-help_summary = "Create a rock, packing sources or binaries."
-help_arguments = "{<rockspec>|<name> [<version>]}"
-help = [[
+pack.help_summary = "Create a rock, packing sources or binaries."
+pack.help_arguments = "{<rockspec>|<name> [<version>]}"
+pack.help = [[
Argument may be a rockspec file, for creating a source rock,
or the name of an installed package, for creating a binary rock.
In the latter case, the app version may be given as a second
@@ -29,7 +33,7 @@ argument.
-- @param rockspec_file string: An URL or pathname for a rockspec file.
-- @return string or (nil, string): The filename of the resulting
-- .src.rock file; or nil and an error message.
-local function pack_source_rock(rockspec_file)
+function pack.pack_source_rock(rockspec_file)
assert(type(rockspec_file) == "string")
local rockspec, err = fetch.load_rockspec(rockspec_file)
@@ -45,7 +49,8 @@ local function pack_source_rock(rockspec_file)
if not source_file then
return nil, source_dir
end
- fs.change_dir(source_dir)
+ local ok, err = fs.change_dir(source_dir)
+ if not ok then return nil, err end
fs.delete(rock_file)
fs.copy(rockspec_file, source_dir)
@@ -58,12 +63,14 @@ local function pack_source_rock(rockspec_file)
end
local function copy_back_files(name, version, file_tree, deploy_dir, pack_dir)
- fs.make_dir(pack_dir)
+ local ok, err = fs.make_dir(pack_dir)
+ if not ok then return nil, err end
for file, sub in pairs(file_tree) do
local source = dir.path(deploy_dir, file)
local target = dir.path(pack_dir, file)
if type(sub) == "table" then
local ok, err = copy_back_files(name, version, sub, source, target)
+ if not ok then return nil, err end
else
local versioned = path.versioned_name(source, deploy_dir, name, version)
if fs.exists(versioned) then
@@ -128,14 +135,17 @@ local function do_pack_binary_rock(name, version)
local is_binary = false
if rock_manifest.lib then
- copy_back_files(name, version, rock_manifest.lib, path.deploy_lib_dir(root), dir.path(temp_dir, "lib"))
+ local ok, err = copy_back_files(name, version, rock_manifest.lib, path.deploy_lib_dir(root), dir.path(temp_dir, "lib"))
+ if not ok then return nil, "Failed copying back files: " .. err end
is_binary = true
end
if rock_manifest.lua then
- copy_back_files(name, version, rock_manifest.lua, path.deploy_lua_dir(root), dir.path(temp_dir, "lua"))
+ local ok, err = copy_back_files(name, version, rock_manifest.lua, path.deploy_lua_dir(root), dir.path(temp_dir, "lua"))
+ if not ok then return nil, "Failed copying back files: " .. err end
end
- fs.change_dir(temp_dir)
+ local ok, err = fs.change_dir(temp_dir)
+ if not ok then return nil, err end
if not is_binary and not repos.has_binaries(name, version) then
rock_file = rock_file:gsub("%."..cfg.arch:gsub("%-","%%-").."%.", ".all.")
end
@@ -148,7 +158,7 @@ local function do_pack_binary_rock(name, version)
return rock_file
end
-function pack_binary_rock(name, version, cmd, ...)
+function pack.pack_binary_rock(name, version, cmd, ...)
-- The --pack-binary-rock option for "luarocks build" basically performs
-- "luarocks build" on a temporary tree and then "luarocks pack". The
@@ -157,9 +167,9 @@ function pack_binary_rock(name, version, cmd, ...)
-- to shave off the final deploy steps from the build phase and the initial
-- collect steps from the pack phase.
- local temp_dir = fs.make_temp_dir("luarocks-build-pack-"..dir.base_name(name))
+ local temp_dir, err = fs.make_temp_dir("luarocks-build-pack-"..dir.base_name(name))
if not temp_dir then
- return nil, "Failed creating temporary directory."
+ return nil, "Failed creating temporary directory: "..err
end
util.schedule_function(fs.delete, temp_dir)
@@ -182,7 +192,7 @@ end
-- version may also be passed.
-- @return boolean or (nil, string): true if successful or nil followed
-- by an error message.
-function run(...)
+function pack.run(...)
local flags, arg, version = util.parse_flags(...)
assert(type(version) == "string" or not version)
if type(arg) ~= "string" then
@@ -191,7 +201,7 @@ function run(...)
local file, err
if arg:match(".*%.rockspec") then
- file, err = pack_source_rock(arg)
+ file, err = pack.pack_source_rock(arg)
else
file, err = do_pack_binary_rock(arg, version)
end
@@ -202,3 +212,5 @@ function run(...)
return true
end
end
+
+return pack
diff --git a/src/luarocks/path.lua b/src/luarocks/path.lua
index 7af81c0..598e51d 100644
--- a/src/luarocks/path.lua
+++ b/src/luarocks/path.lua
@@ -2,31 +2,23 @@
--- LuaRocks-specific path handling functions.
-- All paths are configured in this module, making it a single
-- point where the layout of the local installation is defined in LuaRocks.
-module("luarocks.path", package.seeall)
+--module("luarocks.path", package.seeall)
+local path = {}
local dir = require("luarocks.dir")
local cfg = require("luarocks.cfg")
local util = require("luarocks.util")
-local deps = require("luarocks.deps")
-
-help_summary = "Return the currently configured package path."
-help_arguments = ""
-help = [[
-Returns the package path currently configured for this installation
-of LuaRocks, formatted as shell commands to update LUA_PATH and
-LUA_CPATH. (On Unix systems, you may run: eval `luarocks path`)
-]]
--- Infer rockspec filename from a rock filename.
-- @param rock_name string: Pathname of a rock file.
-- @return string: Filename of the rockspec, without path.
-function rockspec_name_from_rock(rock_name)
+function path.rockspec_name_from_rock(rock_name)
assert(type(rock_name) == "string")
local base_name = dir.base_name(rock_name)
return base_name:match("(.*)%.[^.]*.rock") .. ".rockspec"
end
-function rocks_dir(tree)
+function path.rocks_dir(tree)
if type(tree) == "string" then
return dir.path(tree, cfg.rocks_subdir)
else
@@ -35,12 +27,12 @@ function rocks_dir(tree)
end
end
-function root_dir(rocks_dir)
+function path.root_dir(rocks_dir)
assert(type(rocks_dir) == "string")
return rocks_dir:match("(.*)" .. util.matchquote(cfg.rocks_subdir) .. ".*$")
end
-function rocks_tree_to_string(tree)
+function path.rocks_tree_to_string(tree)
if type(tree) == "string" then
return tree
else
@@ -49,7 +41,7 @@ function rocks_tree_to_string(tree)
end
end
-function deploy_bin_dir(tree)
+function path.deploy_bin_dir(tree)
if type(tree) == "string" then
return dir.path(tree, "bin")
else
@@ -58,7 +50,7 @@ function deploy_bin_dir(tree)
end
end
-function deploy_lua_dir(tree)
+function path.deploy_lua_dir(tree)
if type(tree) == "string" then
return dir.path(tree, cfg.lua_modules_path)
else
@@ -67,7 +59,7 @@ function deploy_lua_dir(tree)
end
end
-function deploy_lib_dir(tree)
+function path.deploy_lib_dir(tree)
if type(tree) == "string" then
return dir.path(tree, cfg.lib_modules_path)
else
@@ -76,7 +68,7 @@ function deploy_lib_dir(tree)
end
end
-function manifest_file(tree)
+function path.manifest_file(tree)
if type(tree) == "string" then
return dir.path(tree, cfg.rocks_subdir, "manifest")
else
@@ -90,10 +82,10 @@ end
-- @return string: The resulting path -- does not guarantee that
-- @param tree string or nil: If given, specifies the local tree to use.
-- the package (and by extension, the path) exists.
-function versions_dir(name, tree)
+function path.versions_dir(name, tree)
assert(type(name) == "string")
tree = tree or cfg.root_dir
- return dir.path(rocks_dir(tree), name)
+ return dir.path(path.rocks_dir(tree), name)
end
--- Get the local installation directory (prefix) for a package.
@@ -102,11 +94,11 @@ end
-- @param tree string or nil: If given, specifies the local tree to use.
-- @return string: The resulting path -- does not guarantee that
-- the package (and by extension, the path) exists.
-function install_dir(name, version, tree)
+function path.install_dir(name, version, tree)
assert(type(name) == "string")
assert(type(version) == "string")
tree = tree or cfg.root_dir
- return dir.path(rocks_dir(tree), name, version)
+ return dir.path(path.rocks_dir(tree), name, version)
end
--- Get the local filename of the rockspec of an installed rock.
@@ -115,11 +107,11 @@ end
-- @param tree string or nil: If given, specifies the local tree to use.
-- @return string: The resulting path -- does not guarantee that
-- the package (and by extension, the file) exists.
-function rockspec_file(name, version, tree)
+function path.rockspec_file(name, version, tree)
assert(type(name) == "string")
assert(type(version) == "string")
tree = tree or cfg.root_dir
- return dir.path(rocks_dir(tree), name, version, name.."-"..version..".rockspec")
+ return dir.path(path.rocks_dir(tree), name, version, name.."-"..version..".rockspec")
end
--- Get the local filename of the rock_manifest file of an installed rock.
@@ -128,11 +120,11 @@ end
-- @param tree string or nil: If given, specifies the local tree to use.
-- @return string: The resulting path -- does not guarantee that
-- the package (and by extension, the file) exists.
-function rock_manifest_file(name, version, tree)
+function path.rock_manifest_file(name, version, tree)
assert(type(name) == "string")
assert(type(version) == "string")
tree = tree or cfg.root_dir
- return dir.path(rocks_dir(tree), name, version, "rock_manifest")
+ return dir.path(path.rocks_dir(tree), name, version, "rock_manifest")
end
--- Get the local installation directory for C libraries of a package.
@@ -141,11 +133,11 @@ end
-- @param tree string or nil: If given, specifies the local tree to use.
-- @return string: The resulting path -- does not guarantee that
-- the package (and by extension, the path) exists.
-function lib_dir(name, version, tree)
+function path.lib_dir(name, version, tree)
assert(type(name) == "string")
assert(type(version) == "string")
tree = tree or cfg.root_dir
- return dir.path(rocks_dir(tree), name, version, "lib")
+ return dir.path(path.rocks_dir(tree), name, version, "lib")
end
--- Get the local installation directory for Lua modules of a package.
@@ -154,11 +146,11 @@ end
-- @param tree string or nil: If given, specifies the local tree to use.
-- @return string: The resulting path -- does not guarantee that
-- the package (and by extension, the path) exists.
-function lua_dir(name, version, tree)
+function path.lua_dir(name, version, tree)
assert(type(name) == "string")
assert(type(version) == "string")
tree = tree or cfg.root_dir
- return dir.path(rocks_dir(tree), name, version, "lua")
+ return dir.path(path.rocks_dir(tree), name, version, "lua")
end
--- Get the local installation directory for documentation of a package.
@@ -167,11 +159,11 @@ end
-- @param tree string or nil: If given, specifies the local tree to use.
-- @return string: The resulting path -- does not guarantee that
-- the package (and by extension, the path) exists.
-function doc_dir(name, version, tree)
+function path.doc_dir(name, version, tree)
assert(type(name) == "string")
assert(type(version) == "string")
tree = tree or cfg.root_dir
- return dir.path(rocks_dir(tree), name, version, "doc")
+ return dir.path(path.rocks_dir(tree), name, version, "doc")
end
--- Get the local installation directory for configuration files of a package.
@@ -180,11 +172,11 @@ end
-- @param tree string or nil: If given, specifies the local tree to use.
-- @return string: The resulting path -- does not guarantee that
-- the package (and by extension, the path) exists.
-function conf_dir(name, version, tree)
+function path.conf_dir(name, version, tree)
assert(type(name) == "string")
assert(type(version) == "string")
tree = tree or cfg.root_dir
- return dir.path(rocks_dir(tree), name, version, "conf")
+ return dir.path(path.rocks_dir(tree), name, version, "conf")
end
--- Get the local installation directory for command-line scripts
@@ -194,11 +186,11 @@ end
-- @param tree string or nil: If given, specifies the local tree to use.
-- @return string: The resulting path -- does not guarantee that
-- the package (and by extension, the path) exists.
-function bin_dir(name, version, tree)
+function path.bin_dir(name, version, tree)
assert(type(name) == "string")
assert(type(version) == "string")
tree = tree or cfg.root_dir
- return dir.path(rocks_dir(tree), name, version, "bin")
+ return dir.path(path.rocks_dir(tree), name, version, "bin")
end
--- Extract name, version and arch of a rock filename,
@@ -206,7 +198,7 @@ end
-- @param file_name string: pathname of a rock or rockspec
-- @return (string, string, string) or nil: name, version and arch
-- or nil if name could not be parsed
-function parse_name(file_name)
+function path.parse_name(file_name)
assert(type(file_name) == "string")
if file_name:match("%.rock$") then
return dir.base_name(file_name):match("(.*)-([^-]+-%d+)%.([^.]+)%.rock$")
@@ -221,7 +213,7 @@ end
-- @param version string: Package version.
-- @param arch string: Architecture identifier, or "rockspec" or "installed".
-- @return string: A URL or pathname following LuaRocks naming conventions.
-function make_url(pathname, name, version, arch)
+function path.make_url(pathname, name, version, arch)
assert(type(pathname) == "string")
assert(type(name) == "string")
assert(type(version) == "string")
@@ -245,7 +237,7 @@ end
-- @return string: The module identifier, or nil if given path is
-- not a conformant module path (the function does not check if the
-- path actually exists).
-function path_to_module(file)
+function path.path_to_module(file)
assert(type(file) == "string")
local name = file:match("(.*)%."..cfg.lua_extension.."$")
@@ -270,7 +262,7 @@ end
-- For example, on Unix, "foo.bar.baz" will return "foo/bar".
-- @param mod string: A module name in Lua dot-separated format.
-- @return string: A directory name using the platform's separator.
-function module_to_path(mod)
+function path.module_to_path(mod)
assert(type(mod) == "string")
return (mod:gsub("[^.]*$", ""):gsub("%.", dir.separator))
end
@@ -279,23 +271,29 @@ end
-- Create a "variables" table in the rockspec table, containing
-- adjusted variables according to the configuration file.
-- @param rockspec table: The rockspec table.
-function configure_paths(rockspec)
+function path.configure_paths(rockspec)
assert(type(rockspec) == "table")
local vars = {}
for k,v in pairs(cfg.variables) do
vars[k] = v
end
local name, version = rockspec.name, rockspec.version
- vars.PREFIX = install_dir(name, version)
- vars.LUADIR = lua_dir(name, version)
- vars.LIBDIR = lib_dir(name, version)
- vars.CONFDIR = conf_dir(name, version)
- vars.BINDIR = bin_dir(name, version)
- vars.DOCDIR = doc_dir(name, version)
+ vars.PREFIX = path.install_dir(name, version)
+ vars.LUADIR = path.lua_dir(name, version)
+ vars.LIBDIR = path.lib_dir(name, version)
+ vars.CONFDIR = path.conf_dir(name, version)
+ vars.BINDIR = path.bin_dir(name, version)
+ vars.DOCDIR = path.doc_dir(name, version)
rockspec.variables = vars
end
-function versioned_name(file, prefix, name, version)
+--- Produce a versioned version of a filename.
+-- @param file string: filename (must start with prefix)
+-- @param prefix string: Path prefix for file
+-- @param name string: Rock name
+-- @param version string: Rock version
+-- @return string: a pathname with the same directory parts and a versioned basename.
+function path.versioned_name(file, prefix, name, version)
assert(type(file) == "string")
assert(type(name) == "string")
assert(type(version) == "string")
@@ -305,12 +303,12 @@ function versioned_name(file, prefix, name, version)
return dir.path(prefix, name_version.."-"..rest)
end
-function use_tree(tree)
+function path.use_tree(tree)
cfg.root_dir = tree
- cfg.rocks_dir = rocks_dir(tree)
- cfg.deploy_bin_dir = deploy_bin_dir(tree)
- cfg.deploy_lua_dir = deploy_lua_dir(tree)
- cfg.deploy_lib_dir = deploy_lib_dir(tree)
+ cfg.rocks_dir = path.rocks_dir(tree)
+ cfg.deploy_bin_dir = path.deploy_bin_dir(tree)
+ cfg.deploy_lua_dir = path.deploy_lua_dir(tree)
+ cfg.deploy_lib_dir = path.deploy_lib_dir(tree)
end
--- Apply a given function to the active rocks trees based on chosen dependency mode.
@@ -320,7 +318,7 @@ end
-- @param fn function: function to be applied, with the tree dir (string) as the first
-- argument and the remaining varargs of map_trees as the following arguments.
-- @return a table with all results of invocations of fn collected.
-function map_trees(deps_mode, fn, ...)
+function path.map_trees(deps_mode, fn, ...)
local result = {}
if deps_mode == "one" then
table.insert(result, (fn(cfg.root_dir, ...)) or 0)
@@ -330,7 +328,7 @@ function map_trees(deps_mode, fn, ...)
use = true
end
for _, tree in ipairs(cfg.rocks_trees) do
- if dir.normalize(tree) == dir.normalize(cfg.root_dir) then
+ if dir.normalize(path.rocks_tree_to_string(tree)) == dir.normalize(path.rocks_tree_to_string(cfg.root_dir)) then
use = true
end
if use then
@@ -349,17 +347,17 @@ end
-- @param i number: the index, 1 if version is the current default, > 1 otherwise.
-- This is done this way for use by select_module in luarocks.loader.
-- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so")
-function which_i(module_name, name, version, tree, i)
+function path.which_i(module_name, name, version, tree, i)
local deploy_dir
if module_name:match("%.lua$") then
- deploy_dir = deploy_lua_dir(tree)
+ deploy_dir = path.deploy_lua_dir(tree)
module_name = dir.path(deploy_dir, module_name)
else
- deploy_dir = deploy_lib_dir(tree)
+ deploy_dir = path.deploy_lib_dir(tree)
module_name = dir.path(deploy_dir, module_name)
end
if i > 1 then
- module_name = versioned_name(module_name, deploy_dir, name, version)
+ module_name = path.versioned_name(module_name, deploy_dir, name, version)
end
return module_name
end
@@ -373,45 +371,15 @@ end
-- @param tree string: repository path (eg. "/usr/local")
-- @param manifest table: the manifest table for the tree.
-- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so")
-function which(module_name, filename, name, version, tree, manifest)
+function path.which(module_name, filename, name, version, tree, manifest)
local versions = manifest.modules[module_name]
assert(versions)
for i, name_version in ipairs(versions) do
if name_version == name.."/"..version then
- return which_i(filename, name, version, tree, i):gsub("//", "/")
+ return path.which_i(filename, name, version, tree, i):gsub("//", "/")
end
end
assert(false)
end
---- Driver function for "path" command.
--- @return boolean This function always succeeds.
-function run(...)
- local flags = util.parse_flags(...)
- local deps_mode = deps.get_deps_mode(flags)
-
- local lr_path, lr_cpath = cfg.package_paths()
- local bin_dirs = map_trees(deps_mode, deploy_bin_dir)
-
- if flags["lr-path"] then
- util.printout(util.remove_path_dupes(lr_path, ';'))
- return true
- elseif flags["lr-cpath"] then
- util.printout(util.remove_path_dupes(lr_cpath, ';'))
- return true
- elseif flags["lr-bin"] then
- local lr_bin = util.remove_path_dupes(table.concat(bin_dirs, cfg.export_path_separator), cfg.export_path_separator)
- util.printout(util.remove_path_dupes(lr_bin, ';'))
- return true
- end
-
- util.printout(cfg.export_lua_path:format(util.remove_path_dupes(package.path, ';')))
- util.printout(cfg.export_lua_cpath:format(util.remove_path_dupes(package.cpath, ';')))
- if flags["bin"] then
- table.insert(bin_dirs, 1, os.getenv("PATH"))
- local lr_bin = util.remove_path_dupes(table.concat(bin_dirs, cfg.export_path_separator), cfg.export_path_separator)
- util.printout(cfg.export_path:format(lr_bin))
- end
- return true
-end
-
+return path
diff --git a/src/luarocks/path_cmd.lua b/src/luarocks/path_cmd.lua
new file mode 100644
index 0000000..95532f9
--- /dev/null
+++ b/src/luarocks/path_cmd.lua
@@ -0,0 +1,73 @@
+
+--- @module luarocks.path_cmd
+-- Driver for the `luarocks path` command.
+local path_cmd = {}
+
+local util = require("luarocks.util")
+local deps = require("luarocks.deps")
+local cfg = require("luarocks.cfg")
+local path = require("luarocks.path")
+
+path_cmd.help_summary = "Return the currently configured package path."
+path_cmd.help_arguments = ""
+path_cmd.help = [[
+Returns the package path currently configured for this installation
+of LuaRocks, formatted as shell commands to update LUA_PATH and LUA_CPATH.
+
+--bin Adds the system path to the output
+
+--append Appends the paths to the existing paths. Default is to prefix
+ the LR paths to the existing paths.
+
+--lr-path Exports the Lua path (not formatted as shell command)
+
+--lr-cpath Exports the Lua cpath (not formatted as shell command)
+
+--lr-bin Exports the system path (not formatted as shell command)
+
+
+On Unix systems, you may run:
+ eval `luarocks path`
+And on Windows:
+ luarocks path > "%temp%\_lrp.bat" && call "%temp%\_lrp.bat" && del "%temp%\_lrp.bat"
+]]
+
+--- Driver function for "path" command.
+-- @return boolean This function always succeeds.
+function path_cmd.run(...)
+ local flags = util.parse_flags(...)
+ local deps_mode = deps.get_deps_mode(flags)
+
+ local lr_path, lr_cpath, lr_bin = cfg.package_paths()
+ local path_sep = cfg.export_path_separator
+
+ if flags["lr-path"] then
+ util.printout(util.remove_path_dupes(lr_path, ';'))
+ return true
+ elseif flags["lr-cpath"] then
+ util.printout(util.remove_path_dupes(lr_cpath, ';'))
+ return true
+ elseif flags["lr-bin"] then
+ util.printout(util.remove_path_dupes(lr_bin, path_sep))
+ return true
+ end
+
+ if flags["append"] then
+ lr_path = package.path .. ";" .. lr_path
+ lr_cpath = package.cpath .. ";" .. lr_cpath
+ lr_bin = os.getenv("PATH") .. path_sep .. lr_bin
+ else
+ lr_path = lr_path.. ";" .. package.path
+ lr_cpath = lr_cpath .. ";" .. package.cpath
+ lr_bin = lr_bin .. path_sep .. os.getenv("PATH")
+ end
+
+ util.printout(cfg.export_lua_path:format(util.remove_path_dupes(lr_path, ';')))
+ util.printout(cfg.export_lua_cpath:format(util.remove_path_dupes(lr_cpath, ';')))
+ if flags["bin"] then
+ util.printout(cfg.export_path:format(util.remove_path_dupes(lr_bin, path_sep)))
+ end
+ return true
+end
+
+return path_cmd
diff --git a/src/luarocks/persist.lua b/src/luarocks/persist.lua
index 208aee0..9d601a4 100644
--- a/src/luarocks/persist.lua
+++ b/src/luarocks/persist.lua
@@ -3,7 +3,9 @@
-- saving tables into files.
-- Implemented separately to avoid interdependencies,
-- as it is used in the bootstrapping stage of the cfg module.
-module("luarocks.persist", package.seeall)
+--module("luarocks.persist", package.seeall)
+local persist = {}
+package.loaded["luarocks.persist"] = persist
local util = require("luarocks.util")
@@ -14,13 +16,22 @@ local util = require("luarocks.util")
-- loaded values.
-- @return table or (nil, string): a table with the file's assignments
-- as fields, or nil and a message in case of errors.
-function load_into_table(filename, tbl)
+function persist.load_into_table(filename, tbl)
assert(type(filename) == "string")
assert(type(tbl) == "table" or not tbl)
local result, chunk, ran, err
- local result = tbl or {}
- if setfenv then -- Lua 5.1
+ result = tbl or {}
+ local globals = {}
+ local globals_mt = {
+ __index = function(t, n)
+ globals[n] = true
+ return rawget(t, n)
+ end
+ }
+ local save_mt = getmetatable(result)
+ setmetatable(result, globals_mt)
+ if _VERSION == "Lua 5.1" then -- Lua 5.1
chunk, err = loadfile(filename)
if chunk then
setfenv(chunk, result)
@@ -32,6 +43,7 @@ function load_into_table(filename, tbl)
ran, err = pcall(chunk)
end
end
+ setmetatable(result, save_mt)
if not chunk then
if err:sub(1,5) ~= filename:sub(1,5) then
@@ -42,7 +54,7 @@ function load_into_table(filename, tbl)
if not ran then
return nil, "Error running file: "..err
end
- return result
+ return result, globals
end
local write_table
@@ -146,7 +158,7 @@ end
-- @param tbl table: the table containing the data to be written
-- @param field_order table: an optional array indicating the order of top-level fields.
-- @return string
-function save_from_table_to_string(tbl, field_order)
+function persist.save_from_table_to_string(tbl, field_order)
local out = {buffer = {}}
function out:write(data) table.insert(self.buffer, data) end
write_table(out, tbl, field_order)
@@ -162,7 +174,7 @@ end
-- @param field_order table: an optional array indicating the order of top-level fields.
-- @return boolean or (nil, string): true if successful, or nil and a
-- message in case of errors.
-function save_from_table(filename, tbl, field_order)
+function persist.save_from_table(filename, tbl, field_order)
local out = io.open(filename, "w")
if not out then
return nil, "Cannot create file at "..filename
@@ -171,3 +183,5 @@ function save_from_table(filename, tbl, field_order)
out:close()
return true
end
+
+return persist
diff --git a/src/luarocks/purge.lua b/src/luarocks/purge.lua
index e76a82e..ba9b870 100644
--- a/src/luarocks/purge.lua
+++ b/src/luarocks/purge.lua
@@ -1,7 +1,9 @@
--- Module implementing the LuaRocks "purge" command.
-- Remove all rocks from a given tree.
-module("luarocks.purge", package.seeall)
+--module("luarocks.purge", package.seeall)
+local purge = {}
+package.loaded["luarocks.purge"] = purge
local util = require("luarocks.util")
local fs = require("luarocks.fs")
@@ -13,9 +15,9 @@ local manif = require("luarocks.manif")
local cfg = require("luarocks.cfg")
local remove = require("luarocks.remove")
-help_summary = "Remove all installed rocks from a tree."
-help_arguments = "--tree=<tree> [--old-versions]"
-help = [[
+purge.help_summary = "Remove all installed rocks from a tree."
+purge.help_arguments = "--tree=<tree> [--old-versions]"
+purge.help = [[
This command removes rocks en masse from a given tree.
By default, it removes all rocks from a tree.
@@ -29,7 +31,7 @@ assume a default tree.
overridden with the flag --force.
]]
-function run(...)
+function purge.run(...)
local flags = util.parse_flags(...)
local tree = flags["tree"]
@@ -41,6 +43,13 @@ function run(...)
local results = {}
local query = search.make_query("")
query.exact_name = false
+ if not fs.is_dir(tree) then
+ return nil, "Directory not found: "..tree
+ end
+
+ local ok, err = fs.check_command_permissions(flags)
+ if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end
+
search.manifest_search(results, path.rocks_dir(tree), query)
local sort = function(a,b) return deps.compare_versions(b,a) end
@@ -68,3 +77,5 @@ function run(...)
end
return manif.make_manifest(cfg.rocks_dir, "one")
end
+
+return purge
diff --git a/src/luarocks/refresh_cache.lua b/src/luarocks/refresh_cache.lua
index 8073037..193e599 100644
--- a/src/luarocks/refresh_cache.lua
+++ b/src/luarocks/refresh_cache.lua
@@ -1,20 +1,22 @@
--- Module implementing the luarocks-admin "refresh_cache" command.
-module("luarocks.refresh_cache", package.seeall)
+--module("luarocks.refresh_cache", package.seeall)
+local refresh_cache = {}
+package.loaded["luarocks.refresh_cache"] = refresh_cache
local util = require("luarocks.util")
local cfg = require("luarocks.cfg")
local cache = require("luarocks.cache")
-help_summary = "Refresh local cache of a remote rocks server."
-help_arguments = "[--from=<server>]"
-help = [[
+refresh_cache.help_summary = "Refresh local cache of a remote rocks server."
+refresh_cache.help_arguments = "[--from=<server>]"
+refresh_cache.help = [[
The flag --from indicates which server to use.
If not given, the default server set in the upload_server variable
from the configuration file is used instead.
]]
-function run(...)
+function refresh_cache.run(...)
local flags = util.parse_flags(...)
local server, upload_server = cache.get_upload_server(flags["server"])
if not server then return nil, upload_server end
@@ -28,3 +30,5 @@ function run(...)
end
end
+
+return refresh_cache
diff --git a/src/luarocks/remove.lua b/src/luarocks/remove.lua
index 9681641..e1cd44f 100644
--- a/src/luarocks/remove.lua
+++ b/src/luarocks/remove.lua
@@ -1,7 +1,9 @@
--- Module implementing the LuaRocks "remove" command.
-- Uninstalls rocks.
-module("luarocks.remove", package.seeall)
+--module("luarocks.remove", package.seeall)
+local remove = {}
+package.loaded["luarocks.remove"] = remove
local search = require("luarocks.search")
local deps = require("luarocks.deps")
@@ -13,14 +15,17 @@ local cfg = require("luarocks.cfg")
local manif = require("luarocks.manif")
local fs = require("luarocks.fs")
-help_summary = "Uninstall a rock."
-help_arguments = "[--force] <name> [<version>]"
-help = [[
+remove.help_summary = "Uninstall a rock."
+remove.help_arguments = "[--force[=fast]] <name> [<version>]"
+remove.help = [[
Argument is the name of a rock to be uninstalled.
If a version is not given, try to remove all versions at once.
Will only perform the removal if it does not break dependencies.
To override this check and force the removal, use --force.
-]]
+To perform a forced removal without reporting dependency issues,
+use --force=fast.
+
+]]..util.deps_mode_help()
--- Obtain a list of packages that depend on the given set of packages
-- (where all packages of the set are versions of one program).
@@ -69,54 +74,58 @@ local function delete_versions(name, versions)
return true
end
-function remove_search_results(results, name, deps_mode, force)
+function remove.remove_search_results(results, name, deps_mode, force)
local versions = results[name]
local version = next(versions)
local second = next(versions, version)
- util.printout("Checking stability of dependencies on the absence of")
- util.printout(name.." "..table.concat(util.keys(versions), ", ").."...")
- util.printout()
-
- local dependents = check_dependents(name, versions, deps_mode)
+ local dependents = {}
+ if force ~= "fast" then
+ util.printout("Checking stability of dependencies on the absence of")
+ util.printout(name.." "..table.concat(util.keys(versions), ", ").."...")
+ util.printout()
+ dependents = check_dependents(name, versions, deps_mode)
+ end
- if #dependents == 0 or force then
- if #dependents > 0 then
+ if #dependents > 0 then
+ if force then
util.printerr("The following packages may be broken by this forced removal:")
for _, dependent in ipairs(dependents) do
util.printerr(dependent.name.." "..dependent.version)
end
util.printerr()
- end
- local ok, err = delete_versions(name, versions)
- if not ok then return nil, err end
- ok, err = manif.make_manifest(cfg.rocks_dir, deps_mode)
- if not ok then return nil, err end
- else
- if not second then
- util.printerr("Will not remove "..name.." "..version..".")
- util.printerr("Removing it would break dependencies for: ")
else
- util.printerr("Will not remove installed versions of "..name..".")
- util.printerr("Removing them would break dependencies for: ")
- end
- for _, dependent in ipairs(dependents) do
- util.printerr(dependent.name.." "..dependent.version)
+ if not second then
+ util.printerr("Will not remove "..name.." "..version..".")
+ util.printerr("Removing it would break dependencies for: ")
+ else
+ util.printerr("Will not remove installed versions of "..name..".")
+ util.printerr("Removing them would break dependencies for: ")
+ end
+ for _, dependent in ipairs(dependents) do
+ util.printerr(dependent.name.." "..dependent.version)
+ end
+ util.printerr()
+ util.printerr("Use --force to force removal (warning: this may break modules).")
+ return nil, "Failed removing."
end
- util.printerr()
- util.printerr("Use --force to force removal (warning: this may break modules).")
- return nil, "Failed removing."
end
+
+ local ok, err = delete_versions(name, versions)
+ if not ok then return nil, err end
+ ok, err = manif.make_manifest(cfg.rocks_dir, deps_mode)
+ if not ok then return nil, err end
+
util.printout("Removal successful.")
return true
end
-function remove_other_versions(name, version, force)
+function remove.remove_other_versions(name, version, force)
local results = {}
search.manifest_search(results, cfg.rocks_dir, { name = name, exact_name = true, constraints = {{ op = "~=", version = version}} })
if results[name] then
- return remove_search_results(results, name, cfg.deps_mode, force)
+ return remove.remove_search_results(results, name, cfg.deps_mode, force)
end
return true
end
@@ -126,9 +135,9 @@ end
-- a specific version; otherwise, try to remove all versions.
-- @param version string: When passing a package name, a version number
-- may also be given.
--- @return boolean or (nil, string): True if removal was
--- successful, nil and an error message otherwise.
-function run(...)
+-- @return boolean or (nil, string, exitcode): True if removal was
+-- successful, nil and an error message otherwise. exitcode is optionally returned.
+function remove.run(...)
local flags, name, version = util.parse_flags(...)
if type(name) ~= "string" then
@@ -138,7 +147,7 @@ function run(...)
local deps_mode = flags["deps-mode"] or cfg.deps_mode
local ok, err = fs.check_command_permissions(flags)
- if not ok then return nil, err end
+ if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end
local rock_type = name:match("%.(rock)$") or name:match("%.(rockspec)$")
local filename = name
@@ -150,8 +159,10 @@ function run(...)
local results = {}
search.manifest_search(results, cfg.rocks_dir, search.make_query(name, version))
if not results[name] then
- return nil, "Could not find rock '"..name..(version and " "..version or "").."' in local tree."
+ return nil, "Could not find rock '"..name..(version and " "..version or "").."' in "..cfg.root_dir
end
- return remove_search_results(results, name, deps_mode, flags["force"])
+ return remove.remove_search_results(results, name, deps_mode, flags["force"])
end
+
+return remove
diff --git a/src/luarocks/repos.lua b/src/luarocks/repos.lua
index b7e64d4..1745659 100644
--- a/src/luarocks/repos.lua
+++ b/src/luarocks/repos.lua
@@ -1,6 +1,8 @@
--- Functions for managing the repository on disk.
-module("luarocks.repos", package.seeall)
+--module("luarocks.repos", package.seeall)
+local repos = {}
+package.loaded["luarocks.repos"] = repos
local fs = require("luarocks.fs")
local path = require("luarocks.path")
@@ -27,7 +29,7 @@ end
-- @param version string: package version in string format
-- @return boolean: true if a package is installed,
-- false otherwise.
-function is_installed(name, version)
+function repos.is_installed(name, version)
assert(type(name) == "string")
assert(type(version) == "string")
@@ -72,7 +74,7 @@ end
-- in "foo.bar" format and values are pathnames in architecture-dependent
-- "foo/bar.so" format. If no modules are found or if package or version
-- are invalid, an empty table is returned.
-function package_modules(package, version)
+function repos.package_modules(package, version)
assert(type(package) == "string")
assert(type(version) == "string")
@@ -91,7 +93,7 @@ end
-- as strings and values are pathnames in architecture-dependent
-- ".../bin/foo" format. If no modules are found or if package or version
-- are invalid, an empty table is returned.
-function package_commands(package, version)
+function repos.package_commands(package, version)
assert(type(package) == "string")
assert(type(version) == "string")
@@ -107,7 +109,7 @@ end
-- @param version string: version of an installed rock
-- @return boolean: returns true if rock contains platform-specific
-- binary executables, or false if it is a pure-Lua rock.
-function has_binaries(name, version)
+function repos.has_binaries(name, version)
assert(type(name) == "string")
assert(type(version) == "string")
@@ -123,7 +125,7 @@ function has_binaries(name, version)
return false
end
-function run_hook(rockspec, hook_name)
+function repos.run_hook(rockspec, hook_name)
assert(type(rockspec) == "table")
assert(type(hook_name) == "string")
@@ -153,19 +155,13 @@ end
local function install_binary(source, target, name, version)
assert(type(source) == "string")
assert(type(target) == "string")
-
- local match = source:match("%.lua$")
- local file, ok, err
- if not match then
- file = io.open(source)
- end
- if match or (file and file:read():match("^#!.*lua.*")) then
- ok, err = fs.wrap_script(source, target, name, version)
+
+ if fs.is_lua(source) then
+ repos.ok, repos.err = fs.wrap_script(source, target, name, version)
else
- ok, err = fs.copy_binary(source, target)
+ repos.ok, repos.err = fs.copy_binary(source, target)
end
- if file then file:close() end
- return ok, err
+ return repos.ok, repos.err
end
local function resolve_conflict(target, deploy_dir, name, version)
@@ -175,7 +171,8 @@ local function resolve_conflict(target, deploy_dir, name, version)
end
if name ~= cname or deps.compare_versions(version, cversion) then
local versioned = path.versioned_name(target, deploy_dir, cname, cversion)
- fs.make_dir(dir.dir_name(versioned))
+ local ok, err = fs.make_dir(dir.dir_name(versioned))
+ if not ok then return nil, err end
fs.move(target, versioned)
return target
else
@@ -183,7 +180,7 @@ local function resolve_conflict(target, deploy_dir, name, version)
end
end
-function should_wrap_bin_scripts(rockspec)
+function repos.should_wrap_bin_scripts(rockspec)
assert(type(rockspec) == "table")
if cfg.wrap_bin_scripts ~= nil then
@@ -195,7 +192,7 @@ function should_wrap_bin_scripts(rockspec)
return true
end
-function deploy_files(name, version, wrap_bin_scripts)
+function repos.deploy_files(name, version, wrap_bin_scripts)
assert(type(name) == "string")
assert(type(version) == "string")
assert(type(wrap_bin_scripts) == "boolean")
@@ -213,14 +210,20 @@ function deploy_files(name, version, wrap_bin_scripts)
if fs.exists(target) then
local new_target, err = resolve_conflict(target, deploy_dir, name, version)
if err == "untracked" then
- fs.delete(target)
+ local backup = target
+ repeat
+ backup = backup.."~"
+ until not fs.exists(backup) -- slight race condition here, but shouldn't be a problem.
+ util.printerr("Warning: "..target.." is not tracked by this installation of LuaRocks. Moving it to "..backup)
+ fs.move(target, backup)
elseif err then
return nil, err.." Cannot install new version."
else
target = new_target
end
end
- fs.make_dir(dir.dir_name(target))
+ ok, err = fs.make_dir(dir.dir_name(target))
+ if not ok then return nil, err end
ok, err = move_fn(source, target, name, version)
fs.remove_dir_tree_if_empty(dir.dir_name(source))
if not ok then return nil, err end
@@ -245,6 +248,21 @@ function deploy_files(name, version, wrap_bin_scripts)
return ok, err
end
+local function delete_suffixed(filename, suffix)
+ local filenames = { filename }
+ if suffix and suffix ~= "" then filenames = { filename..suffix, filename } end
+ for _, name in ipairs(filenames) do
+ if fs.exists(name) then
+ fs.delete(name)
+ if fs.exists(name) then
+ return nil, "Failed deleting "..name, "fail"
+ end
+ return true, name
+ end
+ end
+ return false, "File not found", "not found"
+end
+
--- Delete a package from the local repository.
-- Version numbers are compared as exact string comparison.
-- @param name string: name of package
@@ -253,32 +271,32 @@ end
-- of another version that provides the same module that
-- was deleted. This is used during 'purge', as every module
-- will be eventually deleted.
-function delete_version(name, version, quick)
+function repos.delete_version(name, version, quick)
assert(type(name) == "string")
assert(type(version) == "string")
- local function delete_deployed_file_tree(file_tree, deploy_dir)
+ local function delete_deployed_file_tree(file_tree, deploy_dir, suffix)
return recurse_rock_manifest_tree(file_tree,
function(parent_path, parent_module, file)
local target = dir.path(deploy_dir, parent_path, file)
local versioned = path.versioned_name(target, deploy_dir, name, version)
- if fs.exists(versioned) then
- local ok = fs.delete(versioned)
+ local ok, name, err = delete_suffixed(versioned, suffix)
+ if ok then
fs.remove_dir_tree_if_empty(dir.dir_name(versioned))
- if not ok then return nil, "Failed deleting "..versioned end
- else
- local ok = fs.delete(target)
- if not quick then
- local next_name, next_version = manif.find_next_provider(target)
- if next_name then
- local versioned = path.versioned_name(target, deploy_dir, next_name, next_version)
- fs.move(versioned, target)
- fs.remove_dir_tree_if_empty(dir.dir_name(versioned))
- end
+ return true
+ end
+ if err == "fail" then return nil, name end
+ ok, name, err = delete_suffixed(target, suffix)
+ if err == "fail" then return nil, name end
+ if not quick then
+ local next_name, next_version = manif.find_next_provider(target)
+ if next_name then
+ local versioned = path.versioned_name(name, deploy_dir, next_name, next_version)
+ fs.move(versioned, name)
+ fs.remove_dir_tree_if_empty(dir.dir_name(versioned))
end
- fs.remove_dir_tree_if_empty(dir.dir_name(target))
- if not ok then return nil, "Failed deleting "..target end
end
+ fs.remove_dir_tree_if_empty(dir.dir_name(target))
return true
end
)
@@ -291,7 +309,7 @@ function delete_version(name, version, quick)
local ok, err = true
if rock_manifest.bin then
- ok, err = delete_deployed_file_tree(rock_manifest.bin, cfg.deploy_bin_dir)
+ ok, err = delete_deployed_file_tree(rock_manifest.bin, cfg.deploy_bin_dir, cfg.wrapper_suffix)
end
if ok and rock_manifest.lua then
ok, err = delete_deployed_file_tree(rock_manifest.lua, cfg.deploy_lua_dir)
@@ -307,3 +325,5 @@ function delete_version(name, version, quick)
end
return true
end
+
+return repos
diff --git a/src/luarocks/require.lua b/src/luarocks/require.lua
index 9917770..902bd1a 100644
--- a/src/luarocks/require.lua
+++ b/src/luarocks/require.lua
@@ -1,6 +1,2 @@
--- Retained for compatibility reasons only. Use luarocks.loader instead.
-local require, pairs = require, pairs
-module("luarocks.require")
-for k,v in pairs(require("luarocks.loader")) do
- _M[k] = v
-end
+return require("luarocks.loader")
diff --git a/src/luarocks/search.lua b/src/luarocks/search.lua
index 1fc1f9a..5343938 100644
--- a/src/luarocks/search.lua
+++ b/src/luarocks/search.lua
@@ -1,7 +1,9 @@
--- Module implementing the LuaRocks "search" command.
-- Queries LuaRocks servers.
-module("luarocks.search", package.seeall)
+--module("luarocks.search", package.seeall)
+local search = {}
+package.loaded["luarocks.search"] = search
local dir = require("luarocks.dir")
local path = require("luarocks.path")
@@ -10,9 +12,9 @@ local deps = require("luarocks.deps")
local cfg = require("luarocks.cfg")
local util = require("luarocks.util")
-help_summary = "Query the LuaRocks servers."
-help_arguments = "[--source] [--binary] { <name> [<version>] | --all }"
-help = [[
+search.help_summary = "Query the LuaRocks servers."
+search.help_arguments = "[--source] [--binary] { <name> [<version>] | --all }"
+search.help = [[
--source Return only rockspecs and source rocks,
to be used with the "build" command.
--binary Return only pure Lua and binary rocks (rocks that can be used
@@ -124,7 +126,7 @@ end
-- @param table: The results table, where keys are package names and
-- versions are tables matching version strings to an array of servers.
-- If a table was given in the "results" parameter, that is the result value.
-function disk_search(repo, query, results)
+function search.disk_search(repo, query, results)
assert(type(repo) == "string")
assert(type(query) == "table")
assert(type(results) == "table" or not results)
@@ -136,17 +138,18 @@ function disk_search(repo, query, results)
end
query_arch_as_table(query)
- for _, name in pairs(fs.list_dir(repo)) do
+ for name in fs.dir(repo) do
local pathname = dir.path(repo, name)
local rname, rversion, rarch = path.parse_name(name)
- if fs.is_dir(pathname) then
- for _, version in pairs(fs.list_dir(pathname)) do
+
+ if rname and (pathname:match(".rockspec$") or pathname:match(".rock$")) then
+ store_if_match(results, repo, rname, rversion, rarch, query)
+ elseif fs.is_dir(pathname) then
+ for version in fs.dir(pathname) do
if version:match("-%d+$") then
store_if_match(results, repo, name, version, "installed", query)
end
end
- elseif rname then
- store_if_match(results, repo, rname, rversion, rarch, query)
end
end
return results
@@ -163,15 +166,15 @@ end
-- is used. The special value "any" is also recognized, returning all
-- matches regardless of architecture.
-- @return true or, in case of errors, nil and an error message.
-function manifest_search(results, repo, query)
+function search.manifest_search(results, repo, query)
assert(type(results) == "table")
assert(type(repo) == "string")
assert(type(query) == "table")
query_arch_as_table(query)
- local manifest, err = manif.load_manifest(repo)
+ local manifest, err, errcode = manif.load_manifest(repo)
if not manifest then
- return nil, "Failed loading manifest: "..err
+ return nil, err, errcode
end
for name, versions in pairs(manifest.repository) do
for version, items in pairs(versions) do
@@ -188,27 +191,37 @@ end
-- @return table: A table where keys are package names
-- and values are tables matching version strings to an array of
-- rocks servers; if no results are found, an empty table is returned.
-function search_repos(query)
+function search.search_repos(query)
assert(type(query) == "table")
local results = {}
for _, repo in ipairs(cfg.rocks_servers) do
- if type(repo) == "string" then
- repo = { repo }
- end
- for _, mirror in ipairs(repo) do
- local protocol, pathname = dir.split_url(mirror)
- if protocol == "file" then
- mirror = pathname
+ if not cfg.disabled_servers[repo] then
+ if type(repo) == "string" then
+ repo = { repo }
end
- local ok, err = manifest_search(results, mirror, query)
- if ok then
- break
- else
- util.warning("Failed searching manifest: "..err)
+ for _, mirror in ipairs(repo) do
+ local protocol, pathname = dir.split_url(mirror)
+ if protocol == "file" then
+ mirror = pathname
+ end
+ local ok, err, errcode = search.manifest_search(results, mirror, query)
+ if errcode == "network" then
+ cfg.disabled_servers[repo] = true
+ end
+ if ok then
+ break
+ else
+ util.warning("Failed searching manifest: "..err)
+ end
end
end
end
+ -- search through rocks in cfg.rocks_provided
+ local provided_repo = "provided by VM or rocks_provided"
+ for name, versions in pairs(cfg.rocks_provided) do
+ store_if_match(results, provided_repo, name, versions, "installed", query)
+ end
return results
end
@@ -216,7 +229,7 @@ end
-- @param name string: The query name.
-- @param version string or nil:
-- @return table: A query in table format
-function make_query(name, version)
+function search.make_query(name, version)
assert(type(name) == "string")
assert(type(version) == "string" or not version)
@@ -265,14 +278,20 @@ end
-- @return string or table or (nil, string): URL for matching rock if
-- a single one was found, a table of candidates if it could not narrow to
-- a single result, or nil followed by an error message.
-function find_suitable_rock(query)
+function search.find_suitable_rock(query)
assert(type(query) == "table")
- local results = search_repos(query)
+ local results = search.search_repos(query)
local first = next(results)
if not first then
return nil, "No results matching query were found."
elseif not next(results, first) then
+ if cfg.rocks_provided[query.name] ~= nil then
+ -- do not install versions that listed in cfg.rocks_provided
+ return nil, "Rock "..query.name..
+ " "..cfg.rocks_provided[query.name]..
+ " was found but it is provided by VM or 'rocks_provided' in the config file."
+ end
return pick_latest_version(query.name, results[first])
else
return results
@@ -283,7 +302,7 @@ end
-- @param results table: A table where keys are package names and versions
-- are tables matching version strings to an array of rocks servers.
-- @param porcelain boolean or nil: A flag to force machine-friendly output.
-function print_results(results, porcelain)
+function search.print_results(results, porcelain)
assert(type(results) == "table")
assert(type(porcelain) == "boolean" or not porcelain)
@@ -293,6 +312,7 @@ function print_results(results, porcelain)
end
for version, repos in util.sortedpairs(versions, deps.compare_versions) do
for _, repo in ipairs(repos) do
+ repo.repo = dir.normalize(repo.repo)
if porcelain then
util.printout(package, version, repo.arch, repo.repo)
else
@@ -337,14 +357,14 @@ end
-- @param name string: A rock name
-- @param version string or nil: A version number may also be given.
-- @return The result of the action function, or nil and an error message.
-function act_on_src_or_rockspec(action, name, version, ...)
+function search.act_on_src_or_rockspec(action, name, version, ...)
assert(type(action) == "function")
assert(type(name) == "string")
assert(type(version) == "string" or not version)
- local query = make_query(name, version)
+ local query = search.make_query(name, version)
query.arch = "src|rockspec"
- local results, err = find_suitable_rock(query)
+ local results, err = search.find_suitable_rock(query)
if type(results) == "string" then
return action(results, ...)
else
@@ -357,7 +377,7 @@ end
-- @param version string or nil: a version may also be passed.
-- @return boolean or (nil, string): True if build was successful; nil and an
-- error message otherwise.
-function run(...)
+function search.run(...)
local flags, name, version = util.parse_flags(...)
if flags["all"] then
@@ -368,19 +388,21 @@ function run(...)
return nil, "Enter name and version or use --all. "..util.see_help("search")
end
- local query = make_query(name:lower(), version)
+ local query = search.make_query(name:lower(), version)
query.exact_name = false
- local results, err = search_repos(query)
+ local results, err = search.search_repos(query)
local porcelain = flags["porcelain"]
util.title("Search results:", porcelain, "=")
local sources, binaries = split_source_and_binary_results(results)
if next(sources) and not flags["binary"] then
util.title("Rockspecs and source rocks:", porcelain)
- print_results(sources, porcelain)
+ search.print_results(sources, porcelain)
end
if next(binaries) and not flags["source"] then
util.title("Binary and pure-Lua rocks:", porcelain)
- print_results(binaries, porcelain)
+ search.print_results(binaries, porcelain)
end
return true
end
+
+return search
diff --git a/src/luarocks/show.lua b/src/luarocks/show.lua
index 536085a..3243c0c 100644
--- a/src/luarocks/show.lua
+++ b/src/luarocks/show.lua
@@ -1,19 +1,19 @@
-
--- Module implementing the LuaRocks "show" command.
-- Shows information about an installed rock.
-module("luarocks.show", package.seeall)
+--module("luarocks.show", package.seeall)
+local show = {}
+package.loaded["luarocks.show"] = show
local search = require("luarocks.search")
local cfg = require("luarocks.cfg")
local util = require("luarocks.util")
local path = require("luarocks.path")
-local dir = require("luarocks.dir")
local deps = require("luarocks.deps")
local fetch = require("luarocks.fetch")
local manif = require("luarocks.manif")
-help_summary = "Shows information about an installed rock."
+show.help_summary = "Shows information about an installed rock."
-help = [[
+show.help = [[
<argument> is an existing package name.
Without any flags, show all module information.
With these flags, return only the desired information:
@@ -55,33 +55,14 @@ local function format_text(text)
return (table.concat(paragraphs, "\n\n"):gsub("%s$", ""))
end
-local function module_name(mod, filename, name, version, repo, manifest)
- local base_dir
- if filename:match("%.lua$") then
- base_dir = path.deploy_lua_dir(repo)
- else
- base_dir = path.deploy_lib_dir(repo)
- end
-
- return dir.path(base_dir, filename)
-end
-
---- Driver function for "show" command.
--- @param name or nil: an existing package name.
--- @param version string or nil: a version may also be passed.
--- @return boolean: True if succeeded, nil on errors.
-function run(...)
- local flags, name, version = util.parse_flags(...)
- if not name then
- return nil, "Argument missing. "..util.see_help("show")
- end
+function show.pick_installed_rock(name, version, tree)
local results = {}
local query = search.make_query(name, version)
query.exact_name = true
local tree_map = {}
local trees = cfg.rocks_trees
- if flags["tree"] then
- trees = { flags["tree"] }
+ if tree then
+ trees = { tree }
end
for _, tree in ipairs(trees) do
local rocks_dir = path.rocks_dir(tree)
@@ -103,8 +84,26 @@ function run(...)
for _, rp in ipairs(repositories) do repo_url = rp.repo end
end
-
local repo = tree_map[repo_url]
+ return name, version, repo, repo_url
+end
+
+--- Driver function for "show" command.
+-- @param name or nil: an existing package name.
+-- @param version string or nil: a version may also be passed.
+-- @return boolean: True if succeeded, nil on errors.
+function show.run(...)
+ local flags, name, version = util.parse_flags(...)
+ if not name then
+ return nil, "Argument missing. "..util.see_help("show")
+ end
+
+ local repo, repo_url
+ name, version, repo, repo_url = show.pick_installed_rock(name, version, flags["tree"])
+ if not name then
+ return nil, version
+ end
+
local directory = path.install_dir(name,version,repo)
local rockspec_file = path.rockspec_file(name, version, repo)
local rockspec, err = fetch.load_local_rockspec(rockspec_file)
@@ -118,7 +117,7 @@ function run(...)
if flags["rock-tree"] then util.printout(path.rocks_tree_to_string(repo))
elseif flags["rock-dir"] then util.printout(directory)
elseif flags["home"] then util.printout(descript.homepage)
- elseif flags["modules"] then util.printout(keys_as_string(minfo.modules))
+ elseif flags["modules"] then util.printout(keys_as_string(minfo.modules, "\n"))
elseif flags["deps"] then util.printout(keys_as_string(minfo.dependencies))
elseif flags["rockspec"] then util.printout(rockspec_file)
elseif flags["mversion"] then util.printout(version)
@@ -154,3 +153,5 @@ function run(...)
return true
end
+
+return show
diff --git a/src/luarocks/tools/patch.lua b/src/luarocks/tools/patch.lua
index baaacfc..8df3093 100644
--- a/src/luarocks/tools/patch.lua
+++ b/src/luarocks/tools/patch.lua
@@ -6,12 +6,13 @@
-- Code is heavilly based on the Python-based patch.py version 8.06-1
-- Copyright (c) 2008 rainforce.org, MIT License
-- Project home: http://code.google.com/p/python-patch/ .
+-- Version 0.1
-module("luarocks.tools.patch", package.seeall)
+--module("luarocks.tools.patch", package.seeall)
+local patch = {}
local fs = require("luarocks.fs")
-
-local version = '0.1'
+local util = require("luarocks.util")
local io = io
local os = os
@@ -47,12 +48,6 @@ local function table_copy(t)
return t2
end
--- Returns boolean whether array t contains value v.
-local function array_contains(t, v)
- for _,v2 in ipairs(t) do if v == v2 then return true end end
- return false
-end
-
local function exists(filename)
local fh = io.open(filename)
local result = fh ~= nil
@@ -158,7 +153,7 @@ local function match_linerange(line)
return m1, m2, m3, m4
end
-function read_patch(filename, data)
+function patch.read_patch(filename, data)
-- define possible file regions that will direct the parser flow
local state = 'header'
-- 'header' - comments before the patch body
@@ -284,7 +279,7 @@ function read_patch(filename, data)
local advance
if state == 'filenames' then
if startswith(line, "--- ") then
- if array_contains(files.source, nextfileno) then
+ if util.array_contains(files.source, nextfileno) then
all_ok = false
warning(format("skipping invalid patch for %s",
files.source[nextfileno+1]))
@@ -304,7 +299,7 @@ function read_patch(filename, data)
table.insert(files.source, match)
end
elseif not startswith(line, "+++ ") then
- if array_contains(files.source, nextfileno) then
+ if util.array_contains(files.source, nextfileno) then
all_ok = false
warning(format("skipping invalid patch with no target for %s",
files.source[nextfileno+1]))
@@ -315,7 +310,7 @@ function read_patch(filename, data)
end
state = 'header'
else
- if array_contains(files.target, nextfileno) then
+ if util.array_contains(files.target, nextfileno) then
all_ok = false
warning(format("skipping invalid patch - double target at line %d",
lineno+1))
@@ -354,7 +349,7 @@ function read_patch(filename, data)
if not advance and state == 'hunkhead' then
local m1, m2, m3, m4 = match_linerange(line)
if not m1 then
- if not array_contains(files.hunks, nextfileno-1) then
+ if not util.array_contains(files.hunks, nextfileno-1) then
all_ok = false
warning(format("skipping invalid patch with no hunks for file %s",
files.target[nextfileno]))
@@ -401,7 +396,6 @@ local function find_hunk(file, h, hno)
for i=0,#file do
local found = true
local location = lineno
- local total = #h.text - fuzz
for l, hline in ipairs(h.text) do
if l > fuzz then
-- todo: \ No newline at the end of file
@@ -452,9 +446,6 @@ local function load_file(filename)
end
local function find_hunks(file, hunks)
- local matched = true
- local lineno = 1
- local hno = nil
for hno, h in ipairs(hunks) do
find_hunk(file, h, hno)
end
@@ -463,7 +454,6 @@ end
local function check_patched(file, hunks)
local matched = true
local lineno = 1
- local hno = nil
local ok, err = pcall(function()
if #file == 0 then
error 'nomatch'
@@ -569,15 +559,15 @@ local function strip_dirs(filename, strip)
return filename
end
-function apply_patch(patch, strip)
+function patch.apply_patch(the_patch, strip)
local all_ok = true
- local total = #patch.source
- for fileno, filename in ipairs(patch.source) do
+ local total = #the_patch.source
+ for fileno, filename in ipairs(the_patch.source) do
filename = strip_dirs(filename, strip)
local continue
local f2patch = filename
if not exists(f2patch) then
- f2patch = strip_dirs(patch.target[fileno], strip)
+ f2patch = strip_dirs(the_patch.target[fileno], strip)
f2patch = fs.absolute_name(f2patch)
if not exists(f2patch) then --FIX:if f2patch nil
warning(format("source/target file does not exist\n--- %s\n+++ %s",
@@ -598,7 +588,7 @@ function apply_patch(patch, strip)
info(format("processing %d/%d:\t %s", fileno, total, filename))
-- validate before patching
- local hunks = patch.hunks[fileno]
+ local hunks = the_patch.hunks[fileno]
local file = load_file(filename)
local hunkno = 1
local hunk = hunks[hunkno]
@@ -710,3 +700,5 @@ function apply_patch(patch, strip)
-- todo: check for premature eof
return all_ok
end
+
+return patch
diff --git a/src/luarocks/tools/tar.lua b/src/luarocks/tools/tar.lua
index ba01a41..03f7de3 100644
--- a/src/luarocks/tools/tar.lua
+++ b/src/luarocks/tools/tar.lua
@@ -1,6 +1,7 @@
--- A pure-Lua implementation of untar (unpacking .tar archives)
-module("luarocks.tools.tar", package.seeall)
+--module("luarocks.tools.tar", package.seeall)
+local tar = {}
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
@@ -82,7 +83,7 @@ local function read_header_block(block)
return header
end
-function untar(filename, destdir)
+function tar.untar(filename, destdir)
assert(type(filename) == "string")
assert(type(destdir) == "string")
@@ -119,11 +120,13 @@ function untar(filename, destdir)
end
local pathname = dir.path(destdir, header.name)
if header.typeflag == "directory" then
- fs.make_dir(pathname)
+ local ok, err = fs.make_dir(pathname)
+ if not ok then return nil, err end
elseif header.typeflag == "file" then
local dirname = dir.dir_name(pathname)
if dirname ~= "" then
- fs.make_dir(dirname)
+ local ok, err = fs.make_dir(dirname)
+ if not ok then return nil, err end
end
local file_handle = io.open(pathname, "wb")
file_handle:write(file_data)
@@ -142,3 +145,5 @@ function untar(filename, destdir)
end
return true
end
+
+return tar
diff --git a/src/luarocks/tools/zip.lua b/src/luarocks/tools/zip.lua
index 35428d9..40cc089 100644
--- a/src/luarocks/tools/zip.lua
+++ b/src/luarocks/tools/zip.lua
@@ -1,7 +1,8 @@
--- A Lua implementation of .zip file archiving (used for creating .rock files),
-- using only lua-zlib.
-module("luarocks.tools.zip", package.seeall)
+--module("luarocks.tools.zip", package.seeall)
+local zip = {}
local zlib = require("zlib")
local fs = require("luarocks.fs")
@@ -188,7 +189,7 @@ end
--- Return a zip handle open for writing.
-- @param name filename of the zipfile to be created.
-- @return a zip handle, or nil in case of error.
-function new_zipwriter(name)
+function zip.new_zipwriter(name)
local zw = {}
@@ -214,8 +215,8 @@ end
-- additional arguments.
-- @return boolean or (boolean, string): true on success,
-- false and an error message on failure.
-function zip(zipfile, ...)
- local zw = new_zipwriter(zipfile)
+function zip.zip(zipfile, ...)
+ local zw = zip.new_zipwriter(zipfile)
if not zw then
return nil, "error opening "..zipfile
end
@@ -243,3 +244,5 @@ function zip(zipfile, ...)
return ok, err
end
+
+return zip
diff --git a/src/luarocks/type_check.lua b/src/luarocks/type_check.lua
index 28e6e7b..a78c484 100644
--- a/src/luarocks/type_check.lua
+++ b/src/luarocks/type_check.lua
@@ -1,14 +1,15 @@
-
--- Type-checking functions.
-- Functions and definitions for doing a basic lint check on files
-- loaded by LuaRocks.
-module("luarocks.type_check", package.seeall)
+--module("luarocks.type_check", package.seeall)
+local type_check = {}
+package.loaded["luarocks.type_check"] = type_check
local cfg = require("luarocks.cfg")
-rockspec_format = "1.0"
+type_check.rockspec_format = "1.0"
-rockspec_types = {
+local rockspec_types = {
rockspec_format = "string",
MUST_package = "string",
MUST_version = "[%w.]+-[%d]+",
@@ -74,15 +75,22 @@ rockspec_types = {
}
}
-function load_extensions()
- rockspec_format = "1.1"
+type_check.rockspec_order = {"rockspec_format", "package", "version",
+ { "source", { "url", "tag", "branch", "md5" } },
+ { "description", {"summary", "detailed", "homepage", "license" } },
+ "supported_platforms", "dependencies", "external_dependencies",
+ { "build", {"type", "modules", "copy_directories", "platforms"} },
+ "hooks"}
+
+function type_check.load_extensions()
+ type_check.rockspec_format = "1.1"
rockspec_types.deploy = {
wrap_bin_scripts = true,
}
end
if cfg.use_extensions then
- load_extensions()
+ type_check.load_extensions()
end
rockspec_types.build.platforms.ANY = rockspec_types.build
@@ -91,7 +99,7 @@ rockspec_types.external_dependencies.platforms.ANY = rockspec_types.external_dep
rockspec_types.MUST_source.platforms.ANY = rockspec_types.MUST_source
rockspec_types.hooks.platforms.ANY = rockspec_types.hooks
-manifest_types = {
+local manifest_types = {
MUST_repository = {
-- packages
ANY = {
@@ -176,8 +184,10 @@ local function type_check_item(name, item, expected, context)
return nil, "Type mismatch on field "..context..name..": expected a string"
end
if expected ~= "string" then
- if not item:match("^"..expected.."$") then
- return nil, "Type mismatch on field "..context..name..": invalid value "..item
+ if item_type ~= "string" then
+ return nil, "Type mismatch on field "..context..name..": expected a string, got a "..type(item)
+ elseif not item:match("^"..expected.."$") then
+ return nil, "Type mismatch on field "..context..name..": invalid value "..item.." does not match '"..expected.."'"
end
end
elseif expected_type == "table" then
@@ -240,18 +250,35 @@ type_check_table = function(tbl, types, context)
return true
end
+local function check_undeclared_globals(globals, types)
+ local undeclared = {}
+ for glob, _ in pairs(globals) do
+ if not (types[glob] or types["MUST_"..glob]) then
+ table.insert(undeclared, glob)
+ end
+ end
+ if #undeclared == 1 then
+ return nil, "Unknown variable: "..undeclared[1]
+ elseif #undeclared > 1 then
+ return nil, "Unknown variables: "..table.concat(undeclared, ", ")
+ end
+ return true
+end
+
--- Type check a rockspec table.
-- Verify the correctness of elements from a
-- rockspec table, reporting on unknown fields and type
-- mismatches.
-- @return boolean or (nil, string): true if type checking
-- succeeded, or nil and an error message if it failed.
-function type_check_rockspec(rockspec)
+function type_check.type_check_rockspec(rockspec, globals)
assert(type(rockspec) == "table")
if rockspec.rockspec_format then
-- relies on global state
- load_extensions()
+ type_check.load_extensions()
end
+ local ok, err = check_undeclared_globals(globals, rockspec_types)
+ if not ok then return nil, err end
return type_check_table(rockspec, rockspec_types, "")
end
@@ -261,7 +288,11 @@ end
-- mismatches.
-- @return boolean or (nil, string): true if type checking
-- succeeded, or nil and an error message if it failed.
-function type_check_manifest(manifest)
+function type_check.type_check_manifest(manifest, globals)
assert(type(manifest) == "table")
+ local ok, err = check_undeclared_globals(globals, manifest_types)
+ if not ok then return nil, err end
return type_check_table(manifest, manifest_types, "")
end
+
+return type_check
diff --git a/src/luarocks/unpack.lua b/src/luarocks/unpack.lua
index 6715381..9204e26 100644
--- a/src/luarocks/unpack.lua
+++ b/src/luarocks/unpack.lua
@@ -1,7 +1,9 @@
--- Module implementing the LuaRocks "unpack" command.
-- Unpack the contents of a rock.
-module("luarocks.unpack", package.seeall)
+--module("luarocks.unpack", package.seeall)
+local unpack = {}
+package.loaded["luarocks.unpack"] = unpack
local fetch = require("luarocks.fetch")
local fs = require("luarocks.fs")
@@ -9,12 +11,14 @@ local util = require("luarocks.util")
local build = require("luarocks.build")
local dir = require("luarocks.dir")
-help_summary = "Unpack the contents of a rock."
-help_arguments = "{<rock>|<name> [<version>]}"
-help = [[
+unpack.help_summary = "Unpack the contents of a rock."
+unpack.help_arguments = "[--force] {<rock>|<name> [<version>]}"
+unpack.help = [[
Unpacks the contents of a rock in a newly created directory.
Argument may be a rock file, or the name of a rock in a rocks server.
In the latter case, the app version may be given as a second argument.
+
+--force Unpack files even if the output directory already exists.
]]
--- Load a rockspec file to the given directory, fetches the source
@@ -31,14 +35,17 @@ local function unpack_rockspec(rockspec_file, dir_name)
if not rockspec then
return nil, "Failed loading rockspec "..rockspec_file..": "..err
end
- fs.change_dir(dir_name)
+ local ok, err = fs.change_dir(dir_name)
+ if not ok then return nil, err end
local ok, sources_dir = fetch.fetch_sources(rockspec, true, ".")
if not ok then
return nil, sources_dir
end
- fs.change_dir(dir_name)
+ ok, err = fs.change_dir(sources_dir)
+ if not ok then return nil, err end
build.apply_patches(rockspec)
fs.pop_dir()
+ fs.pop_dir()
return rockspec
end
@@ -57,7 +64,8 @@ local function unpack_rock(rock_file, dir_name, kind)
if not ok then
return nil, "Failed unzipping rock "..rock_file, errcode
end
- fs.change_dir(dir_name)
+ ok, err = fs.change_dir(dir_name)
+ if not ok then return nil, err end
local rockspec_file = dir_name..".rockspec"
local rockspec, err = fetch.load_rockspec(rockspec_file)
if not rockspec then
@@ -69,7 +77,8 @@ local function unpack_rock(rock_file, dir_name, kind)
if not ok then
return nil, err
end
- fs.change_dir(rockspec.source.dir)
+ ok, err = fs.change_dir(rockspec.source.dir)
+ if not ok then return nil, err end
build.apply_patches(rockspec)
fs.pop_dir()
end
@@ -83,7 +92,7 @@ end
-- @param file string: A rockspec or .rock URL.
-- @return boolean or (nil, string): true if successful or nil followed
-- by an error message.
-local function run_unpacker(file)
+local function run_unpacker(file, force)
assert(type(file) == "string")
local base_name = dir.base_name(file)
@@ -95,11 +104,15 @@ local function run_unpacker(file)
if not extension then
return nil, file.." does not seem to be a valid filename."
end
-
- if (fs.exists(dir_name)) then
+
+ local exists = fs.exists(dir_name)
+ if exists and not force then
return nil, "Directory "..dir_name.." already exists."
end
- fs.make_dir(dir_name)
+ if not exists then
+ local ok, err = fs.make_dir(dir_name)
+ if not ok then return nil, err end
+ end
local rollback = util.schedule_function(fs.delete, fs.absolute_name(dir_name))
local rockspec, err
@@ -134,7 +147,7 @@ end
-- version may also be passed.
-- @return boolean or (nil, string): true if successful or nil followed
-- by an error message.
-function run(...)
+function unpack.run(...)
local flags, name, version = util.parse_flags(...)
assert(type(version) == "string" or not version)
@@ -143,9 +156,11 @@ function run(...)
end
if name:match(".*%.rock") or name:match(".*%.rockspec") then
- return run_unpacker(name)
+ return run_unpacker(name, flags["force"])
else
local search = require("luarocks.search")
return search.act_on_src_or_rockspec(run_unpacker, name, version)
end
end
+
+return unpack
diff --git a/src/luarocks/upload.lua b/src/luarocks/upload.lua
new file mode 100644
index 0000000..d87313a
--- /dev/null
+++ b/src/luarocks/upload.lua
@@ -0,0 +1,92 @@
+
+local upload = {}
+
+local util = require("luarocks.util")
+local fetch = require("luarocks.fetch")
+local pack = require("luarocks.pack")
+local cfg = require("luarocks.cfg")
+local Api = require("luarocks.upload.api")
+
+upload.help_summary = "Upload a rockspec to the public rocks repository."
+upload.help_arguments = "[--skip-pack] [--api-key=<key>] [--force] <rockspec>"
+upload.help = [[
+<rockspec> Pack a source rock file (.src.rock extension),
+ upload rockspec and source rock to server.
+--skip-pack Do not pack and send source rock.
+--api-key=<key> Give it an API key. It will be stored for subsequent uses.
+--force Replace existing rockspec if the same revision of
+ a module already exists. This should be used only
+ in case of upload mistakes: when updating a rockspec,
+ increment the revision number instead.
+]]
+
+function upload.run(...)
+ local flags, fname = util.parse_flags(...)
+ if not fname then
+ return nil, "Missing rockspec. "..util.see_help("upload")
+ end
+
+ local api, err = Api.new(flags)
+ if not api then
+ return nil, err
+ end
+ if cfg.verbose then
+ api.debug = true
+ end
+
+ local rockspec, err, errcode = fetch.load_rockspec(fname)
+ if err then
+ return nil, err, errcode
+ end
+
+ util.printout("Sending " .. tostring(fname) .. " ...")
+ local res, err = api:method("check_rockspec", {
+ package = rockspec.package,
+ version = rockspec.version
+ })
+ if not res then return nil, err end
+
+ if not res.module then
+ util.printout("Will create new module (" .. tostring(rockspec.package) .. ")")
+ end
+ if res.version and not flags["force"] then
+ return nil, "Revision "..rockspec.version.." already exists on the server. "..util.see_help("upload")
+ end
+
+ local rock_fname
+ if not flags["skip-pack"] then
+ util.printout("Packing " .. tostring(rockspec.package))
+ rock_fname, err = pack.pack_source_rock(fname)
+ if not rock_fname then
+ return nil, err
+ end
+ end
+
+ local multipart = require("luarocks.upload.multipart")
+
+ res, err = api:method("upload", nil, {
+ rockspec_file = multipart.new_file(fname)
+ })
+ if not res then return nil, err end
+
+ if res.is_new and #res.manifests == 0 then
+ util.printerr("Warning: module not added to root manifest due to name taken.")
+ end
+
+ local module_url = res.module_url
+
+ if rock_fname then
+ util.printout(("Sending " .. tostring(rock_fname) .. " ..."))
+ res, err = api:method("upload_rock/" .. tostring(res.version.id), nil, {
+ rock_file = multipart.new_file(rock_fname)
+ })
+ if not res then return nil, err end
+ end
+
+ util.printout()
+ util.printout("Done: " .. tostring(module_url))
+ util.printout()
+ return true
+end
+
+return upload
diff --git a/src/luarocks/upload/api.lua b/src/luarocks/upload/api.lua
new file mode 100644
index 0000000..c588335
--- /dev/null
+++ b/src/luarocks/upload/api.lua
@@ -0,0 +1,270 @@
+
+local api = {}
+
+local cfg = require("luarocks.cfg")
+local fs = require("luarocks.fs")
+local util = require("luarocks.util")
+local persist = require("luarocks.persist")
+local multipart = require("luarocks.upload.multipart")
+
+local Api = {}
+
+local function upload_config_file()
+ local _, _, home_conf, home_ok = cfg.which_config()
+ if not home_conf then
+ return nil
+ end
+ return (home_conf:gsub("/[^/]+$", "/upload_config.lua"))
+end
+
+function Api:load_config()
+ local upload_conf = upload_config_file()
+ print(upload_conf)
+ if not upload_conf then return nil end
+ local cfg, err = persist.load_into_table(upload_conf)
+ return cfg
+end
+
+function Api:save_config()
+ -- Test configuration before saving it.
+ local res, err = self:raw_method("status")
+ if not res then
+ return nil, err
+ end
+ if res.errors then
+ util.printerr("Server says: " .. tostring(res.errors[1]))
+ return
+ end
+ local upload_conf = upload_config_file()
+ if not upload_conf then return nil end
+ persist.save_from_table(upload_conf, self.config)
+ fs.chmod(upload_conf, "0600")
+end
+
+function Api:check_version()
+ if not self._server_tool_version then
+ local tool_version = cfg.upload.tool_version
+ local res, err = self:request(tostring(self.config.server) .. "/api/tool_version", {
+ current = tool_version
+ })
+ if not res then
+ return nil, err
+ end
+ if not res.version then
+ return nil, "failed to fetch tool version"
+ end
+ self._server_tool_version = res.version
+ if res.force_update then
+ return nil, "Your upload client is too out of date to continue, please upgrade LuaRocks."
+ end
+ if res.version ~= tool_version then
+ util.printerr("Warning: Your LuaRocks is out of date, consider upgrading.")
+ end
+ end
+ return true
+end
+
+function Api:method(...)
+ local res, err = self:raw_method(...)
+ if not res then
+ return nil, err
+ end
+ if res.errors then
+ if res.errors[1] == "Invalid key" then
+ return nil, res.errors[1] .. " (use the --api-key flag to change)"
+ end
+ local msg = table.concat(res.errors, ", ")
+ return nil, "API Failed: " .. msg
+ end
+ return res
+end
+
+function Api:raw_method(path, ...)
+ self:check_version()
+ local url = tostring(self.config.server) .. "/api/" .. tostring(cfg.upload.api_version) .. "/" .. tostring(self.config.key) .. "/" .. tostring(path)
+ return self:request(url, ...)
+end
+
+local function encode_query_string(t, sep)
+ if sep == nil then
+ sep = "&"
+ end
+ local i = 0
+ local buf = { }
+ for k, v in pairs(t) do
+ if type(k) == "number" and type(v) == "table" then
+ k, v = v[1], v[2]
+ end
+ buf[i + 1] = multipart.url_escape(k)
+ buf[i + 2] = "="
+ buf[i + 3] = multipart.url_escape(v)
+ buf[i + 4] = sep
+ i = i + 4
+ end
+ buf[i] = nil
+ return table.concat(buf)
+end
+
+-- An ode to the multitude of JSON libraries out there...
+local function require_json()
+ for _, lib in ipairs({ "cjson", "dkjson", "json" }) do
+ local json_ok, json = pcall(require, lib)
+ if json_ok then
+ return json_ok, json
+ end
+ end
+ return nil
+end
+
+local ltn12_ok, ltn12 = pcall(require, "ltn12")
+if not ltn12_ok then -- If not using LuaSocket and/or LuaSec...
+
+function Api:request(url, params, post_params)
+ local vars = cfg.variables
+ local json_ok, json = require_json()
+ if not json_ok then return nil, "A JSON library is required for this command." end
+
+ if cfg.downloader == "wget" then
+ local curl_ok = fs.execute_quiet(vars.CURL, "--version")
+ if not curl_ok then
+ return nil, "Missing network helper program 'curl'.\nMake sure 'curl' is installed and available from your path."
+ end
+ end
+
+ if not self.config.key then
+ return nil, "Must have API key before performing any actions."
+ end
+ local body
+ local headers = {}
+ if params and next(params) then
+ url = url .. ("?" .. encode_query_string(params))
+ end
+ local method = "GET"
+ local out
+ local tmpfile = fs.tmpname()
+ if post_params then
+ method = "POST"
+ local curl_cmd = fs.Q(vars.CURL).." -f -k -L --silent --user-agent \""..cfg.user_agent.." via curl\" "
+ for k,v in pairs(post_params) do
+ local var = v
+ if type(v) == "table" then
+ var = "@"..v.fname
+ end
+ curl_cmd = curl_cmd .. "--form \""..k.."="..var.."\" "
+ end
+ if cfg.connection_timeout and cfg.connection_timeout > 0 then
+ curl_cmd = curl_cmd .. "--connect-timeout "..tonumber(cfg.connection_timeout).." "
+ end
+ ok = fs.execute_string(curl_cmd..fs.Q(url).." -o "..fs.Q(tmpfile))
+ else
+ local ok, err = fs.download(url, tmpfile)
+ if not ok then
+ return nil, "API failure: " .. tostring(err) .. " - " .. tostring(url)
+ end
+ end
+
+ local tmpfd = io.open(tmpfile)
+ if not tmpfd then
+ os.remove(tmpfile)
+ return nil, "API failure reading temporary file - " .. tostring(url)
+ end
+ out = tmpfd:read("*a")
+ tmpfd:close()
+ os.remove(tmpfile)
+
+ if self.debug then
+ util.printout("[" .. tostring(method) .. " via curl] " .. tostring(url) .. " ... ")
+ end
+
+ return json.decode(out)
+end
+
+else -- use LuaSocket and LuaSec
+
+local warned_luasec = false
+
+function Api:request(url, params, post_params)
+ local json_ok, json = require_json()
+ if not json_ok then return nil, "A JSON library is required for this command." end
+ local server = tostring(self.config.server)
+ local http_ok, http
+ local via = "luasocket"
+ if server:match("^https://") then
+ http_ok, http = pcall(require, "ssl.https")
+ if http_ok then
+ via = "luasec"
+ else
+ if not warned_luasec then
+ util.printerr("LuaSec is not available; using plain HTTP. Install 'luasec' to enable HTTPS.")
+ warned_luasec = true
+ end
+ http_ok, http = pcall(require, "socket.http")
+ server = server:gsub("^https", "http")
+ url = url:gsub("^https", "http")
+ via = "luasocket"
+ end
+ else
+ http_ok, http = pcall(require, "socket.http")
+ end
+ if not http_ok then
+ return nil, "Failed loading socket library!"
+ end
+
+ if not self.config.key then
+ return nil, "Must have API key before performing any actions."
+ end
+ local body
+ local headers = {}
+ if params and next(params) then
+ url = url .. ("?" .. encode_query_string(params))
+ end
+ if post_params then
+ local boundary
+ body, boundary = multipart.encode(post_params)
+ headers["Content-length"] = #body
+ headers["Content-type"] = "multipart/form-data; boundary=" .. tostring(boundary)
+ end
+ local method = post_params and "POST" or "GET"
+ if self.debug then
+ util.printout("[" .. tostring(method) .. " via "..via.."] " .. tostring(url) .. " ... ")
+ end
+ local out = {}
+ local _, status = http.request({
+ url = url,
+ headers = headers,
+ method = method,
+ sink = ltn12.sink.table(out),
+ source = body and ltn12.source.string(body)
+ })
+ if self.debug then
+ util.printout(tostring(status))
+ end
+ if status ~= 200 then
+ return nil, "API returned " .. tostring(status) .. " - " .. tostring(url)
+ end
+ return json.decode(table.concat(out))
+end
+
+end
+
+function api.new(flags, name)
+ local self = {}
+ setmetatable(self, { __index = Api })
+ self.config = self:load_config() or {}
+ self.config.server = flags["server"] or self.config.server or cfg.upload.server
+ self.config.version = self.config.version or cfg.upload.version
+ self.config.key = flags["api-key"] or self.config.key
+ self.debug = flags["debug"]
+ if not self.config.key then
+ return nil, "You need an API key to upload rocks.\n" ..
+ "Navigate to "..self.config.server.."/settings to get a key\n" ..
+ "and then pass it through the --api-key=<key> flag."
+ end
+ if flags["api-key"] then
+ self:save_config()
+ end
+ return self
+end
+
+return api
+
diff --git a/src/luarocks/upload/multipart.lua b/src/luarocks/upload/multipart.lua
new file mode 100644
index 0000000..5677657
--- /dev/null
+++ b/src/luarocks/upload/multipart.lua
@@ -0,0 +1,112 @@
+
+local multipart = {}
+
+local File = {}
+
+local unpack = unpack or table.unpack
+
+math.randomseed(os.time())
+
+-- socket.url.escape(s) from LuaSocket 3.0rc1
+function multipart.url_escape(s)
+ return (string.gsub(s, "([^A-Za-z0-9_])", function(c)
+ return string.format("%%%02x", string.byte(c))
+ end))
+end
+
+function File:mime()
+ if not self.mimetype then
+ local mimetypes_ok, mimetypes = pcall(require, "mimetypes")
+ if mimetypes_ok then
+ self.mimetype = mimetypes.guess(self.fname)
+ else
+ self.mimetype = "application/octet-stream"
+ end
+ end
+ return self.mimetype
+end
+
+function File:content()
+ local fd = io.open(self.fname)
+ if not fd then
+ return nil, "Failed to open file: "..self.fname
+ end
+ local data = fd:read("*a")
+ fd:close()
+ return data
+end
+
+local function rand_string(len)
+ local shuffled = {}
+ for i = 1, len do
+ local r = math.random(97, 122)
+ if math.random() >= 0.5 then
+ r = r - 32
+ end
+ shuffled[i] = r
+ end
+ return string.char(unpack(shuffled))
+end
+
+-- multipart encodes params
+-- returns encoded string,boundary
+-- params is an a table of tuple tables:
+-- params = {
+-- {key1, value2},
+-- {key2, value2},
+-- key3: value3
+-- }
+function multipart.encode(params)
+ local tuples = { }
+ for i = 1, #params do
+ tuples[i] = params[i]
+ end
+ for k,v in pairs(params) do
+ if type(k) == "string" then
+ table.insert(tuples, {k, v})
+ end
+ end
+ local chunks = {}
+ for _, tuple in ipairs(tuples) do
+ local k,v = unpack(tuple)
+ k = multipart.url_escape(k)
+ local buffer = { 'Content-Disposition: form-data; name="' .. k .. '"' }
+ local content
+ if type(v) == "table" and v.__class == File then
+ buffer[1] = buffer[1] .. ('; filename="' .. v.fname:gsub(".*/", "") .. '"')
+ table.insert(buffer, "Content-type: " .. v:mime())
+ content = v:content()
+ else
+ content = v
+ end
+ table.insert(buffer, "")
+ table.insert(buffer, content)
+ table.insert(chunks, table.concat(buffer, "\r\n"))
+ end
+ local boundary
+ while not boundary do
+ boundary = "Boundary" .. rand_string(16)
+ for _, chunk in ipairs(chunks) do
+ if chunk:find(boundary) then
+ boundary = nil
+ break
+ end
+ end
+ end
+ local inner = "\r\n--" .. boundary .. "\r\n"
+ return table.concat({ "--", boundary, "\r\n",
+ table.concat(chunks, inner),
+ "\r\n", "--", boundary, "--", "\r\n" }), boundary
+end
+
+function multipart.new_file(fname, mime)
+ local self = {}
+ setmetatable(self, { __index = File })
+ self.__class = File
+ self.fname = fname
+ self.mimetype = mime
+ return self
+end
+
+return multipart
+
diff --git a/src/luarocks/util.lua b/src/luarocks/util.lua
index ba20acf..8772883 100644
--- a/src/luarocks/util.lua
+++ b/src/luarocks/util.lua
@@ -4,9 +4,10 @@
-- inside specific functions) to avoid interdependencies,
-- as this is used in the bootstrapping stage of luarocks.cfg.
-local global_env = _G
+--module("luarocks.util", package.seeall)
+local util = {}
-module("luarocks.util", package.seeall)
+local unpack = unpack or table.unpack
local scheduled_functions = {}
local debug = require("debug")
@@ -18,7 +19,7 @@ local debug = require("debug")
-- @param ... arguments to be passed to function.
-- @return table: A token representing the scheduled execution,
-- which can be used to remove the item later from the list.
-function schedule_function(f, ...)
+function util.schedule_function(f, ...)
assert(type(f) == "function")
local item = { fn = f, args = {...} }
@@ -30,7 +31,7 @@ end
-- This is useful for cancelling a rollback of a completed operation.
-- @param item table: The token representing the scheduled function that was
-- returned from the schedule_function call.
-function remove_scheduled_function(item)
+function util.remove_scheduled_function(item)
for k, v in pairs(scheduled_functions) do
if v == item then
table.remove(scheduled_functions, k)
@@ -44,7 +45,7 @@ end
-- corresponding cleanup functions. Calling this function will run
-- these function, erasing temporaries.
-- Functions are executed in the inverse order they were scheduled.
-function run_scheduled_functions()
+function util.run_scheduled_functions()
local fs = require("luarocks.fs")
fs.change_dir_to_root()
for i = #scheduled_functions, 1, -1 do
@@ -58,7 +59,7 @@ end
-- so it does not include beginning- and end-of-string markers (^$)
-- @param s string: The input string
-- @return string: The equivalent pattern
-function matchquote(s)
+function util.matchquote(s)
return (s:gsub("[?%-+*%[%].%%()$^]","%%%1"))
end
@@ -67,7 +68,7 @@ end
-- For example, given "foo", "--tux=beep", "--bla", "bar", "--baz",
-- it would return the following:
-- {["bla"] = true, ["tux"] = "beep", ["baz"] = true}, "foo", "bar".
-function parse_flags(...)
+function util.parse_flags(...)
local args = {...}
local flags = {}
for i = #args, 1, -1 do
@@ -92,7 +93,7 @@ end
-- in the flags table. If no flags are passed as varargs, the
-- entire flags table is forwarded.
-- @return string... A variable number of strings
-function forward_flags(flags, ...)
+function util.forward_flags(flags, ...)
assert(type(flags) == "table")
local out = {}
local filter = select('#', ...)
@@ -121,14 +122,14 @@ end
-- @param dst Destination table, which will receive src's contents.
-- @param src Table which provides new contents to dst.
-- @see platform_overrides
-function deep_merge(dst, src)
+function util.deep_merge(dst, src)
for k, v in pairs(src) do
if type(v) == "table" then
if not dst[k] then
dst[k] = {}
end
if type(dst[k]) == "table" then
- deep_merge(dst[k], v)
+ util.deep_merge(dst[k], v)
else
dst[k] = v
end
@@ -151,7 +152,7 @@ end
-- tbl.x are preserved).
-- @param tbl table or nil: Table which may contain a "platforms" field;
-- if it doesn't (or if nil is passed), this function does nothing.
-function platform_overrides(tbl)
+function util.platform_overrides(tbl)
assert(type(tbl) == "table" or not tbl)
local cfg = require("luarocks.cfg")
@@ -162,7 +163,7 @@ function platform_overrides(tbl)
for _, platform in ipairs(cfg.platforms) do
local platform_tbl = tbl.platforms[platform]
if platform_tbl then
- deep_merge(tbl, platform_tbl)
+ util.deep_merge(tbl, platform_tbl)
end
end
end
@@ -194,15 +195,15 @@ end
-- @param needed_set: a set where keys are the names of
-- needed variables.
-- @param msg string: the warning message to display.
-function warn_if_not_used(var_defs, needed_set, msg)
+function util.warn_if_not_used(var_defs, needed_set, msg)
needed_set = make_shallow_copy(needed_set)
- for var,val in pairs(var_defs) do
+ for _, val in pairs(var_defs) do
for used in val:gmatch(var_format_pattern) do
needed_set[used] = nil
end
end
- for var,_ in pairs(needed_set) do
- warning(msg:format(var))
+ for var, _ in pairs(needed_set) do
+ util.warning(msg:format(var))
end
end
@@ -213,7 +214,7 @@ local function warn_failed_matches(line)
local any_failed = false
if line:match(var_format_pattern) then
for unmatched in line:gmatch(var_format_pattern) do
- warning("unmatched variable " .. unmatched)
+ util.warning("unmatched variable " .. unmatched)
any_failed = true
end
end
@@ -228,7 +229,7 @@ end
-- @param tbl table: Table to have its string values modified.
-- @param vars table: Table containing string-string key-value pairs
-- representing variables to replace in the strings values of tbl.
-function variable_substitutions(tbl, vars)
+function util.variable_substitutions(tbl, vars)
assert(type(tbl) == "table")
assert(type(vars) == "table")
@@ -249,7 +250,7 @@ end
--- Return an array of keys of a table.
-- @param tbl table: The input table.
-- @return table: The array of keys.
-function keys(tbl)
+function util.keys(tbl)
local ks = {}
for k,_ in pairs(tbl) do
table.insert(ks, k)
@@ -277,7 +278,7 @@ end
-- to be used by table.sort when sorting keys.
-- @see sortedpairs
local function sortedpairs_iterator(tbl, sort_function)
- local ks = keys(tbl)
+ local ks = util.keys(tbl)
if not sort_function or type(sort_function) == "function" then
table.sort(ks, sort_function or default_sort)
for _, k in ipairs(ks) do
@@ -315,41 +316,50 @@ end
-- is a string representing the field name, and the second element is a priority table
-- for that key.
-- @return function: the iterator function.
-function sortedpairs(tbl, sort_function)
+function util.sortedpairs(tbl, sort_function)
return coroutine.wrap(function() sortedpairs_iterator(tbl, sort_function) end)
end
-function starts_with(s, prefix)
+function util.lua_versions()
+ local versions = { "5.1", "5.2", "5.3" }
+ local i = 0
+ return function()
+ i = i + 1
+ return versions[i]
+ end
+end
+
+function util.starts_with(s, prefix)
return s:sub(1,#prefix) == prefix
end
--- Print a line to standard output
-function printout(...)
+function util.printout(...)
io.stdout:write(table.concat({...},"\t"))
io.stdout:write("\n")
end
--- Print a line to standard error
-function printerr(...)
+function util.printerr(...)
io.stderr:write(table.concat({...},"\t"))
io.stderr:write("\n")
end
--- Display a warning message.
-- @param msg string: the warning message
-function warning(msg)
- printerr("Warning: "..msg)
+function util.warning(msg)
+ util.printerr("Warning: "..msg)
end
-function title(msg, porcelain, underline)
+function util.title(msg, porcelain, underline)
if porcelain then return end
- printout()
- printout(msg)
- printout((underline or "-"):rep(#msg))
- printout()
+ util.printout()
+ util.printout(msg)
+ util.printout((underline or "-"):rep(#msg))
+ util.printout()
end
-function this_program(default)
+function util.this_program(default)
local i = 1
local last, cur = default, default
while i do
@@ -362,13 +372,32 @@ function this_program(default)
return last:sub(2)
end
-function see_help(command, program)
- return "See '"..this_program(program or "luarocks")..' help '..command.."'."
+function util.deps_mode_help(program)
+ local cfg = require("luarocks.cfg")
+ return [[
+--deps-mode=<mode> How to handle dependencies. Four modes are supported:
+ * all - use all trees from the rocks_trees list
+ for finding dependencies
+ * one - use only the current tree (possibly set
+ with --tree)
+ * order - use trees based on order (use the current
+ tree and all trees below it on the rocks_trees list)
+ * none - ignore dependencies altogether.
+ The default mode may be set with the deps_mode entry
+ in the configuration file.
+ The current default is "]]..cfg.deps_mode..[[".
+ Type ']]..util.this_program(program or "luarocks")..[[' with no arguments to see
+ your list of rocks trees.
+]]
+end
+
+function util.see_help(command, program)
+ return "See '"..util.this_program(program or "luarocks")..' help'..(command and " "..command or "").."'."
end
-- from http://lua-users.org/wiki/SplitJoin
-- by PhilippeLhoste
-function split_string(str, delim, maxNb)
+function util.split_string(str, delim, maxNb)
-- Eliminate bad cases...
if string.find(str, delim) == nil then
return { str }
@@ -397,12 +426,13 @@ end
-- Example: given ("a;b;c;a;b;d", ";"), returns "a;b;c;d".
-- @param list string: A path string (from $PATH or package.path)
-- @param sep string: The separator
-function remove_path_dupes(list, sep)
+function util.remove_path_dupes(list, sep)
assert(type(list) == "string")
assert(type(sep) == "string")
- local parts = split_string(list, sep)
+ local parts = util.split_string(list, sep)
local final, entries = {}, {}
for _, part in ipairs(parts) do
+ part = part:gsub("//", "/")
if not entries[part] then
table.insert(final, part)
entries[part] = true
@@ -428,7 +458,7 @@ end
-- @param name string: is the name of the table (optional)
-- @param indent string: is a first indentation (optional).
-- @return string: the pretty-printed table
-function show_table(t, name, indent)
+function util.show_table(t, name, indent)
local cart -- a container
local autoref -- for self references
@@ -494,7 +524,7 @@ function show_table(t, name, indent)
return cart .. autoref
end
-function array_contains(tbl, value)
+function util.array_contains(tbl, value)
for _, v in ipairs(tbl) do
if v == value then
return true
@@ -502,3 +532,12 @@ function array_contains(tbl, value)
end
return false
end
+
+-- Quote Lua string, analogous to fs.Q.
+-- @param s A string, such as "hello"
+-- @return string: A quoted string, such as '"hello"'
+function util.LQ(s)
+ return ("%q"):format(s)
+end
+
+return util
diff --git a/src/luarocks/validate.lua b/src/luarocks/validate.lua
index 1e1e69e..e6e09c3 100644
--- a/src/luarocks/validate.lua
+++ b/src/luarocks/validate.lua
@@ -1,6 +1,8 @@
--- Sandboxed test of build/install of all packages in a repository (unfinished and disabled).
-module("luarocks.validate", package.seeall)
+--module("luarocks.validate", package.seeall)
+local validate = {}
+package.loaded["luarocks.validate"] = validate
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
@@ -10,9 +12,9 @@ local build = require("luarocks.build")
local install = require("luarocks.install")
local util = require("luarocks.util")
-help_summary = "Sandboxed test of build/install of all packages in a repository."
+validate.help_summary = "Sandboxed test of build/install of all packages in a repository."
-help = [[
+validate.help = [[
<argument>, if given, is a local repository pathname.
]]
@@ -73,7 +75,12 @@ local function validate_rock(file)
return ok, err, errcode
end
-local function validate(repo, flags)
+function validate.run(...)
+ local flags, repo = util.parse_flags(...)
+ repo = repo or cfg.rocks_dir
+
+ util.printout("Verifying contents of "..repo)
+
local results = {
ok = {}
}
@@ -85,7 +92,7 @@ local function validate(repo, flags)
if not fs.exists(repo) then
return nil, repo.." is not a local repository."
end
- for _, file in pairs(fs.list_dir(repo)) do for _=1,1 do
+ for file in fs.dir(repo) do for _=1,1 do
if file == "manifest" or file == "index.html" then
break -- continue for
end
@@ -149,12 +156,5 @@ local function validate(repo, flags)
return true
end
-function run(...)
- local flags, repo = util.parse_flags(...)
- repo = repo or cfg.rocks_dir
-
- util.printout("Verifying contents of "..repo)
-
- return validate(repo, flags)
-end
+return validate
diff --git a/src/luarocks/write_rockspec.lua b/src/luarocks/write_rockspec.lua
new file mode 100644
index 0000000..403cbc8
--- /dev/null
+++ b/src/luarocks/write_rockspec.lua
@@ -0,0 +1,340 @@
+
+--module("luarocks.write_rockspec", package.seeall)
+local write_rockspec = {}
+package.loaded["luarocks.write_rockspec"] = write_rockspec
+
+local dir = require("luarocks.dir")
+local fetch = require("luarocks.fetch")
+local fs = require("luarocks.fs")
+local path = require("luarocks.path")
+local persist = require("luarocks.persist")
+local type_check = require("luarocks.type_check")
+local util = require("luarocks.util")
+
+write_rockspec.help_summary = "Write a template for a rockspec file."
+write_rockspec.help_arguments = "[--output=<file> ...] [<name>] [<version>] {<url>|<path>}"
+write_rockspec.help = [[
+This command writes an initial version of a rockspec file,
+based on an URL or a local path. You may use a relative path such as '.'.
+If a local path is given, name and version arguments are mandatory.
+For URLs, LuaRocks will attempt to infer name and version if not given.
+
+If a repository URL is given with no version, it creates an 'scm' rock.
+
+Note that the generated file is a _starting point_ for writing a
+rockspec, and is not guaranteed to be complete or correct.
+
+--output=<file> Write the rockspec with the given filename.
+ If not given, a file is written in the current
+ directory with a filename based on given name and version.
+--license="<string>" A license string, such as "MIT/X11" or "GNU GPL v3".
+--summary="<txt>" A short one-line description summary.
+--detailed="<txt>" A longer description string.
+--homepage=<url> Project homepage.
+--lua-version=<ver> Supported Lua versions. Accepted values are "5.1", "5.2",
+ "5.3", "5.1,5.2", "5.2,5.3", or "5.1,5.2,5.3".
+--tag=<tag> Tag to use. Will attempt to extract version number from it.
+--lib=<lib>[,<lib>] A comma-separated list of libraries that C files need to
+ link to.
+]]
+
+local function open_file(name)
+ return io.open(dir.path(fs.current_dir(), name), "r")
+end
+
+local function get_url(rockspec)
+ local file, temp_dir, err_code, err_file, err_temp_dir = fetch.fetch_sources(rockspec, false)
+ if err_code == "source.dir" then
+ file, temp_dir = err_file, err_temp_dir
+ elseif not file then
+ util.warning("Could not fetch sources - "..temp_dir)
+ return false
+ end
+ util.printout("File successfully downloaded. Making checksum and checking base dir...")
+ if fetch.is_basic_protocol(rockspec.source.protocol) then
+ rockspec.source.md5 = fs.get_md5(file)
+ end
+ local inferred_dir, found_dir = fetch.find_base_dir(file, temp_dir, rockspec.source.url)
+ return true, found_dir or inferred_dir, temp_dir
+end
+
+local function configure_lua_version(rockspec, luaver)
+ if luaver == "5.1" then
+ table.insert(rockspec.dependencies, "lua ~> 5.1")
+ elseif luaver == "5.2" then
+ table.insert(rockspec.dependencies, "lua ~> 5.2")
+ elseif luaver == "5.3" then
+ table.insert(rockspec.dependencies, "lua ~> 5.3")
+ elseif luaver == "5.1,5.2" then
+ table.insert(rockspec.dependencies, "lua >= 5.1, < 5.3")
+ elseif luaver == "5.2,5.3" then
+ table.insert(rockspec.dependencies, "lua >= 5.2, < 5.4")
+ elseif luaver == "5.1,5.2,5.3" then
+ table.insert(rockspec.dependencies, "lua >= 5.1, < 5.4")
+ else
+ util.warning("Please specify supported Lua version with --lua-version=<ver>. "..util.see_help("write_rockspec"))
+ end
+end
+
+local function detect_description(rockspec)
+ local fd = open_file("README.md") or open_file("README")
+ if not fd then return end
+ local data = fd:read("*a")
+ fd:close()
+ local paragraph = data:match("\n\n([^%[].-)\n\n")
+ if not paragraph then paragraph = data:match("\n\n(.*)") end
+ if paragraph then
+ if #paragraph < 80 then
+ rockspec.description.summary = paragraph:gsub("\n", "")
+ rockspec.description.detailed = paragraph
+ else
+ local summary = paragraph:gsub("\n", " "):match("([^.]*%.) ")
+ if summary then
+ rockspec.description.summary = summary:gsub("\n", "")
+ end
+ rockspec.description.detailed = paragraph
+ end
+ end
+end
+
+local function detect_mit_license(data)
+ local strip_copyright = (data:gsub("Copyright [^\n]*\n", ""))
+ local sum = 0
+ for i = 1, #strip_copyright do
+ local num = string.byte(strip_copyright:sub(i,i))
+ if num > 32 and num <= 128 then
+ sum = sum + num
+ end
+ end
+ return sum == 78656
+end
+
+local function show_license(rockspec)
+ local fd = open_file("COPYING") or open_file("LICENSE") or open_file("MIT-LICENSE.txt")
+ if not fd then return nil end
+ local data = fd:read("*a")
+ fd:close()
+ local is_mit = detect_mit_license(data)
+ util.title("License for "..rockspec.package..":")
+ util.printout(data)
+ util.printout()
+ return is_mit
+end
+
+local function get_cmod_name(file)
+ local fd = open_file(file)
+ if not fd then return nil end
+ local data = fd:read("*a")
+ fd:close()
+ return (data:match("int%s+luaopen_([a-zA-Z0-9_]+)"))
+end
+
+local luamod_blacklist = {
+ test = true,
+ tests = true,
+}
+
+local function fill_as_builtin(rockspec, libs)
+ rockspec.build.type = "builtin"
+ rockspec.build.modules = {}
+ local prefix = ""
+
+ for _, parent in ipairs({"src", "lua"}) do
+ if fs.is_dir(parent) then
+ fs.change_dir(parent)
+ prefix = parent.."/"
+ break
+ end
+ end
+
+ local incdirs, libdirs
+ if libs then
+ incdirs, libdirs = {}, {}
+ for _, lib in ipairs(libs) do
+ local upper = lib:upper()
+ incdirs[#incdirs+1] = "$("..upper.."_INCDIR)"
+ libdirs[#libdirs+1] = "$("..upper.."_LIBDIR)"
+ end
+ end
+
+ for _, file in ipairs(fs.find()) do
+ local luamod = file:match("(.*)%.lua$")
+ if luamod and not luamod_blacklist[luamod] then
+ rockspec.build.modules[path.path_to_module(file)] = prefix..file
+ else
+ local cmod = file:match("(.*)%.c$")
+ if cmod then
+ local modname = get_cmod_name(file) or path.path_to_module(file:gsub("%.c$", ".lua"))
+ rockspec.build.modules[modname] = {
+ sources = prefix..file,
+ libraries = libs,
+ incdirs = incdirs,
+ libdirs = libdirs,
+ }
+ end
+ end
+ end
+
+ for _, directory in ipairs({ "doc", "docs", "samples", "tests" }) do
+ if fs.is_dir(directory) then
+ if not rockspec.build.copy_directories then
+ rockspec.build.copy_directories = {}
+ end
+ table.insert(rockspec.build.copy_directories, directory)
+ end
+ end
+
+ if prefix ~= "" then
+ fs.pop_dir()
+ end
+end
+
+local function rockspec_cleanup(rockspec)
+ rockspec.source.file = nil
+ rockspec.source.protocol = nil
+ rockspec.variables = nil
+ rockspec.name = nil
+end
+
+function write_rockspec.run(...)
+ local flags, name, version, url_or_dir = util.parse_flags(...)
+
+ if not name then
+ return nil, "Missing arguments. "..util.see_help("write_rockspec")
+ end
+
+ if name and not version then
+ url_or_dir = name
+ name = nil
+ elseif not url_or_dir then
+ url_or_dir = version
+ end
+
+ if flags["tag"] == true then
+ return nil, "Incorrect usage: --tag requires an argument. "..util.see_help("write_rockspec")
+ end
+
+ if flags["tag"] then
+ if not version then
+ version = flags["tag"]:gsub("^v", "")
+ end
+ end
+
+ local protocol, pathname = dir.split_url(url_or_dir)
+ if not fetch.is_basic_protocol(protocol) then
+ if not name then
+ name = dir.base_name(url_or_dir):gsub("%.[^.]+$", "")
+ end
+ if not version then
+ version = "scm"
+ end
+ elseif protocol ~= "file" then
+ local filename = dir.base_name(url_or_dir)
+ local newname, newversion = filename:match("(.*)-([^-]+)")
+ if (not name) and newname then
+ name = newname
+ end
+ if (not version) and newversion then
+ version = newversion:gsub(".[a-z]+$", ""):gsub(".tar$", "")
+ end
+ if not (name and version) then
+ return nil, "Missing name and version arguments. "..util.see_help("write_rockspec")
+ end
+ elseif not version then
+ return nil, "Missing name and version arguments. "..util.see_help("write_rockspec")
+ end
+
+ local filename = flags["output"] or dir.path(fs.current_dir(), name:lower().."-"..version.."-1.rockspec")
+
+ if not flags["homepage"] and url_or_dir:match("^git://github.com") then
+ flags["homepage"] = "http://"..url_or_dir:match("^[^:]+://(.*)")
+ end
+
+ local rockspec = {
+ package = name,
+ name = name:lower(),
+ version = version.."-1",
+ source = {
+ url = "*** please add URL for source tarball, zip or repository here ***",
+ tag = flags["tag"],
+ },
+ description = {
+ summary = flags["summary"] or "*** please specify description summary ***",
+ detailed = flags["detailed"] or "*** please enter a detailed description ***",
+ homepage = flags["homepage"] or "*** please enter a project homepage ***",
+ license = flags["license"] or "*** please specify a license ***",
+ },
+ dependencies = {},
+ build = {},
+ }
+ path.configure_paths(rockspec)
+ rockspec.source.protocol = protocol
+
+ configure_lua_version(rockspec, flags["lua-version"])
+
+ local local_dir = url_or_dir
+
+ if url_or_dir:match("://") then
+ rockspec.source.url = url_or_dir
+ rockspec.source.file = dir.base_name(url_or_dir)
+ rockspec.source.dir = "dummy"
+ if not fetch.is_basic_protocol(rockspec.source.protocol) then
+ if version ~= "scm" then
+ rockspec.source.tag = flags["tag"] or "v" .. version
+ end
+ end
+ rockspec.source.dir = nil
+ local ok, base_dir, temp_dir = get_url(rockspec)
+ if ok then
+ if base_dir ~= dir.base_name(url_or_dir) then
+ rockspec.source.dir = base_dir
+ end
+ end
+ if base_dir then
+ local_dir = dir.path(temp_dir, base_dir)
+ else
+ local_dir = nil
+ end
+ end
+
+ if not local_dir then
+ local_dir = "."
+ end
+
+ local libs = nil
+ if flags["lib"] then
+ libs = {}
+ rockspec.external_dependencies = {}
+ for lib in flags["lib"]:gmatch("([^,]+)") do
+ table.insert(libs, lib)
+ rockspec.external_dependencies[lib:upper()] = {
+ library = lib
+ }
+ end
+ end
+
+ local ok, err = fs.change_dir(local_dir)
+ if not ok then return nil, "Failed reaching files from project - error entering directory "..local_dir end
+
+ detect_description(rockspec)
+
+ local is_mit = show_license(rockspec)
+
+ if is_mit and not flags["license"] then
+ rockspec.description.license = "MIT"
+ end
+
+ fill_as_builtin(rockspec, libs)
+
+ rockspec_cleanup(rockspec)
+
+ persist.save_from_table(filename, rockspec, type_check.rockspec_order)
+
+ util.printout()
+ util.printout("Wrote template at "..filename.." -- you should now edit and finish it.")
+ util.printout()
+
+ return true
+end
+
+return write_rockspec
diff --git a/test/testfiles/missing_external-0.1-1.rockspec b/test/testfiles/missing_external-0.1-1.rockspec
new file mode 100644
index 0000000..5f8e621
--- /dev/null
+++ b/test/testfiles/missing_external-0.1-1.rockspec
@@ -0,0 +1,24 @@
+package = "missing_external"
+version = "0.1-1"
+source = {
+ -- any valid URL
+ url = "https://raw.github.com/keplerproject/luarocks/master/src/luarocks/build.lua"
+}
+description = {
+ summary = "Missing external dependency",
+}
+external_dependencies = {
+ INEXISTENT = {
+ library = "inexistentlib*",
+ header = "inexistentheader*.h",
+ }
+}
+dependencies = {
+ "lua >= 5.1"
+}
+build = {
+ type = "builtin",
+ modules = {
+ build = "build.lua"
+ }
+}
diff --git a/test/testing.sh b/test/testing.sh
index c06bd27..b0d95c3 100755
--- a/test/testing.sh
+++ b/test/testing.sh
@@ -1,4 +1,4 @@
-#!/bin/sh -e
+#!/bin/bash -e
# Setup #########################################
@@ -7,13 +7,45 @@
exit 1
}
+if [ -z "$*" ]
+then
+ ps aux | grep -q '[s]shd' || {
+ echo "Run sudo /bin/sshd in order to perform all tests."
+ exit 1
+ }
+fi
+
+if [ "$1" == "--travis" ]
+then
+ travis=true
+ shift
+fi
+
+luaversion=5.1.5
+
+if [ "$1" == "--lua" ]
+then
+ shift
+ luaversion=$1
+ shift
+fi
+
testing_dir="$PWD"
-testing_tree="$testing_dir/testing"
-testing_sys_tree="$testing_dir/testing_sys"
-testing_tree_copy="$testing_dir/testing_copy"
-testing_sys_tree_copy="$testing_dir/testing_sys_copy"
-testing_cache="$testing_dir/testing_cache"
+testing_tree="$testing_dir/testing-$luaversion"
+testing_sys_tree="$testing_dir/testing_sys-$luaversion"
+testing_tree_copy="$testing_dir/testing_copy-$luaversion"
+testing_sys_tree_copy="$testing_dir/testing_sys_copy-$luaversion"
+testing_cache="$testing_dir/testing_cache-$luaversion"
+testing_server="$testing_dir/testing_server-$luaversion"
+
+
+if [ "$1" == "--clean" ]
+then
+ shift
+ rm -rf "$testing_cache"
+ rm -rf "$testing_server"
+fi
[ "$1" ] || rm -f luacov.stats.out
rm -f luacov.report.out
@@ -23,12 +55,25 @@ rm -rf "$testing_tree"
rm -rf "$testing_sys_tree"
rm -rf "$testing_tree_copy"
rm -rf "$testing_sys_tree_copy"
-rm -rf "$testing_cache"
+rm -rf "$testing_dir/testing_config.lua"
+rm -rf "$testing_dir/testing_config_show_downloads.lua"
+rm -rf "$testing_dir/testing_config_sftp.lua"
+rm -rf "$testing_dir/luacov.config"
+
+mkdir -p "$testing_cache"
+
+[ "$1" = "clean" ] && {
+ rm -f luacov.stats.out
+ exit 0
+}
cat <<EOF > $testing_dir/testing_config.lua
rocks_trees = {
"$testing_tree",
- "$testing_sys_tree",
+ { name = "system", root = "$testing_sys_tree" },
+}
+rocks_servers = {
+ "$testing_server"
}
local_cache = "$testing_cache"
upload_server = "testing"
@@ -38,7 +83,23 @@ upload_servers = {
rsync = "localhost/tmp/luarocks_testing",
},
}
+external_deps_dirs = {
+ "/usr/local",
+ "/usr",
+ -- These are used for a test that fails, so it
+ -- can point to invalid paths:
+ {
+ prefix = "/opt",
+ bin = "bin",
+ include = "include",
+ lib = { "lib", "lib64" },
+ }
+}
EOF
+(
+ cat $testing_dir/testing_config.lua
+ echo "show_downloads = true"
+) > $testing_dir/testing_config_show_downloads.lua
cat <<EOF > $testing_dir/testing_config_sftp.lua
rocks_trees = {
"$testing_tree",
@@ -76,23 +137,123 @@ export LUAROCKS_CONFIG="$testing_dir/testing_config.lua"
export LUA_PATH=
export LUA_CPATH=
-luadir="/Programs/Lua/Current"
+if [ "$travis" ]
+then
+ luadir=/tmp/lua-$luaversion
+ pushd /tmp
+ if [ ! -e "$luadir/bin/lua" ]
+ then
+ mkdir -p lua
+ echo "Downloading lua $luaversion..."
+ wget "http://www.lua.org/ftp/lua-$luaversion.tar.gz" &> /dev/null
+ tar zxpf "lua-$luaversion.tar.gz"
+ cd "lua-$luaversion"
+ echo "Building lua $luaversion..."
+ make linux INSTALL_TOP="$luadir" &> /dev/null
+ make install INSTALL_TOP="$luadir" &> /dev/null
+ fi
+ popd
+else
+ luadir="/Programs/Lua/Current"
+fi
+
+if [ `uname -m` = i686 ]
+then
+ platform="linux-x86"
+else
+ platform="linux-x86_64"
+fi
+
lua="$luadir/bin/lua"
+version_luasocket=3.0rc1
+verrev_luasocket=${version_luasocket}-1
+srcdir_luasocket=luasocket-3.0-rc1
+
+version_cprint=0.1
+verrev_cprint=0.1-1
+
+version_luacov=0.5
+verrev_luacov=0.5-1
+version_lxsh=0.8.6
+version_validate_args=1.5.4
+verrev_validate_args=1.5.4-1
+verrev_lxsh=${version_lxsh}-2
+
+luasec=luasec
+
cd ..
./configure --with-lua="$luadir"
make clean
make src/luarocks/site_config.lua
make dev
cd src
-
-echo $LUA_PATH
-
-luarocks_nocov="$lua $PWD/bin/luarocks"
-luarocks="$lua -erequire('luacov.runner')('$testing_dir/luacov.config') $PWD/bin/luarocks"
-luarocks_admin="$lua -erequire('luacov.runner')('$testing_dir/luacov.config') $PWD/bin/luarocks-admin"
-
-$luarocks_nocov download luacov
+basedir=$PWD
+run_lua() {
+ if [ "$1" = "--noecho" ]; then shift; noecho=1; else noecho=0; fi
+ if [ "$1" = "--nocov" ]; then shift; nocov=1; else nocov=0; fi
+ if [ "$noecho" = 0 ]
+ then
+ echo $*
+ fi
+ cmd=$1
+ shift
+ if [ "$nocov" = 0 ]
+ then
+ "$lua" -e"require('luacov.runner')('$testing_dir/luacov.config')" "$basedir/bin/$cmd" "$@"
+ else
+ "$lua" "$basedir/bin/$cmd" "$@"
+ fi
+}
+luarocks="run_lua luarocks"
+luarocks_nocov="run_lua --nocov luarocks"
+luarocks_noecho="run_lua --noecho luarocks"
+luarocks_noecho_nocov="run_lua --noecho --nocov luarocks"
+luarocks_admin="run_lua luarocks-admin"
+luarocks_admin_nocov="run_lua --nocov luarocks-admin"
+
+###################################################
+
+mkdir -p "$testing_server"
+(
+ cd "$testing_server"
+ luarocks_repo="http://luarocks.org/repositories/rocks"
+ luarocks_scm_repo="http://luarocks.org/repositories/rocks-scm"
+ get() { [ -e `basename "$1"` ] || wget -c "$1"; }
+ get "$luarocks_repo/luacov-${verrev_luacov}.src.rock"
+ get "$luarocks_repo/luacov-${verrev_luacov}.rockspec"
+ get "$luarocks_repo/luadoc-3.0.1-1.src.rock"
+ get "$luarocks_repo/lualogging-1.3.0-1.src.rock"
+ get "$luarocks_repo/luasocket-${verrev_luasocket}.src.rock"
+ get "$luarocks_repo/luasocket-${verrev_luasocket}.rockspec"
+ get "$luarocks_repo/luafilesystem-1.6.2-1.src.rock"
+ get "$luarocks_repo/stdlib-35-1.src.rock"
+ get "$luarocks_repo/luarepl-0.4-1.src.rock"
+ get "$luarocks_repo/validate-args-1.5.4-1.rockspec"
+ get "$luarocks_scm_repo/luasec-scm-1.rockspec"
+ get "$luarocks_repo/luabitop-1.0.2-1.rockspec"
+ get "$luarocks_repo/lpty-1.0.1-1.src.rock"
+ get "$luarocks_repo/cprint-${verrev_cprint}.src.rock"
+ get "$luarocks_repo/cprint-${verrev_cprint}.rockspec"
+ get "$luarocks_repo/wsapi-1.6-1.src.rock"
+ get "$luarocks_repo/lxsh-${verrev_lxsh}.src.rock"
+ get "$luarocks_repo/abelhas-1.0-1.rockspec"
+ get "$luarocks_repo/lzlib-0.4.work3-1.src.rock"
+ get "$luarocks_repo/lpeg-0.12-1.src.rock"
+ get "$luarocks_repo/luaposix-31-1.src.rock"
+ get "$luarocks_repo/md5-1.2-1.src.rock"
+ get "$luarocks_repo/lrandom-20120430.51-1.src.rock"
+ get "$luarocks_repo/lrandom-20120430.52-1.src.rock"
+ get "$luarocks_repo/lrandom-20120430.51-1.rockspec"
+ get "$luarocks_repo/lrandom-20120430.52-1.rockspec"
+)
+$luarocks_admin_nocov make_manifest "$testing_server"
+
+###################################################
+
+checksum_path() {
+ ( cd "$1"; find . -printf "%s %p\n" | md5sum )
+}
build_environment() {
rm -rf "$testing_tree"
@@ -101,21 +262,55 @@ build_environment() {
rm -rf "$testing_sys_tree_copy"
mkdir -p "$testing_tree"
mkdir -p "$testing_sys_tree"
+ $luarocks_admin_nocov make_manifest "$testing_cache"
for package in "$@"
do
- $luarocks_nocov build --tree="$testing_sys_tree" $package
+ $luarocks_nocov install --only-server="$testing_cache" --tree="$testing_sys_tree" $package || {
+ $luarocks_nocov build --tree="$testing_sys_tree" $package
+ $luarocks_nocov pack --tree="$testing_sys_tree" $package; mv $package-*.rock "$testing_cache"
+ }
done
- eval `$luarocks_nocov path --bin`
+ eval `$luarocks_noecho_nocov path --bin`
cp -a "$testing_tree" "$testing_tree_copy"
cp -a "$testing_sys_tree" "$testing_sys_tree_copy"
+ testing_tree_copy_md5=`checksum_path "$testing_tree_copy"`
+ testing_sys_tree_copy_md5=`checksum_path "$testing_sys_tree_copy"`
}
reset_environment() {
- rm -rf "$testing_tree"
- rm -rf "$testing_sys_tree"
- cp -a "$testing_tree_copy" "$testing_tree"
- cp -a "$testing_sys_tree_copy" "$testing_sys_tree"
+ testing_tree_md5=`checksum_path "$testing_tree"`
+ testing_sys_tree_md5=`checksum_path "$testing_sys_tree"`
+ if [ "$testing_tree_md5" != "$testing_tree_copy_md5" ]
+ then
+ rm -rf "$testing_tree"
+ cp -a "$testing_tree_copy" "$testing_tree"
+ fi
+ if [ "$testing_sys_tree_md5" != "$testing_sys_tree_copy_md5" ]
+ then
+ rm -rf "$testing_sys_tree"
+ cp -a "$testing_sys_tree_copy" "$testing_sys_tree"
+ fi
+}
+
+need() {
+ echo "Obtaining $1 $2..."
+ if $luarocks show $1 &> /dev/null
+ then
+ echo "Already available"
+ return
+ fi
+ platrock="$1-$2.$platform.rock"
+ if [ ! -e "$testing_cache/$platrock" ]
+ then
+ echo "Building $1 $2..."
+ $luarocks_nocov build --pack-binary-rock $1 $2
+ mv "$platrock" "$testing_cache"
+ fi
+ echo "Installing $1 $2..."
+ $luarocks_nocov install "$testing_cache/$platrock"
+ return
}
+need_luasocket() { need luasocket $verrev_luasocket; }
# Tests #########################################
@@ -134,7 +329,10 @@ fail_lint_noarg() { $luarocks lint; }
fail_search_noarg() { $luarocks search; }
fail_show_noarg() { $luarocks show; }
fail_unpack_noarg() { $luarocks unpack; }
+fail_remove_noarg() { $luarocks remove; }
+fail_doc_noarg() { $luarocks doc; }
fail_new_version_noarg() { $luarocks new_version; }
+fail_write_rockspec_noarg() { $luarocks write_rockspec; }
fail_build_invalid() { $luarocks build invalid; }
fail_download_invalid() { $luarocks download invalid; }
@@ -146,77 +344,103 @@ fail_new_version_invalid() { $luarocks new_version invalid; }
fail_make_norockspec() { $luarocks make; }
fail_build_blank_arg() { $luarocks build --tree="" lpeg; }
-test_build_withpatch() { $luarocks build luadoc; }
-test_build_diffversion() { $luarocks build luacov 0.1; }
+test_build_withpatch() { need_luasocket; $luarocks build luadoc; }
+test_build_diffversion() { $luarocks build luacov ${version_luacov}; }
test_build_command() { $luarocks build stdlib; }
test_build_install_bin() { $luarocks build luarepl; }
-fail_build_nohttps() { $luarocks install luasocket && $luarocks download --rockspec validate-args 1.5.4 && $luarocks build ./validate-args-1.5.4-1.rockspec && rm ./validate-args-1.5.4-1.rockspec; }
-test_build_https() { $luarocks download --rockspec validate-args 1.5.4 && $luarocks install luasec && $luarocks build ./validate-args-1.5.4-1.rockspec && rm ./validate-args-1.5.4-1.rockspec; }
-test_build_supported_platforms() { $luarocks build xctrl; }
+test_build_nohttps() { need_luasocket; $luarocks download --rockspec validate-args ${verrev_validate_args} && $luarocks build ./validate-args-${version_validate_args}-1.rockspec && rm ./validate-args-${version_validate_args}-1.rockspec; }
+test_build_https() { need_luasocket; $luarocks download --rockspec validate-args ${verrev_validate_args} && $luarocks install $luasec && $luarocks build ./validate-args-${verrev_validate_args}.rockspec && rm ./validate-args-${verrev_validate_args}.rockspec; }
+test_build_supported_platforms() { $luarocks build lpty; }
+fail_build_missing_external() { $luarocks build "$testing_dir/testfiles/missing_external-0.1-1.rockspec" INEXISTENT_INCDIR="/invalid/dir"; }
+
+test_build_deps_partial_match() { $luarocks build lrandom; }
+test_build_show_downloads() { export LUAROCKS_CONFIG="$testing_dir/testing_config_show_downloads.lua" && $luarocks build alien; export LUAROCKS_CONFIG="$testing_dir/testing_config.lua"; }
test_download_all() { $luarocks download --all validate-args && rm validate-args-*; }
-test_download_rockspecversion() { $luarocks download --rockspec validate-args 1.5.4 && rm validate-args-*; }
+test_download_rockspecversion() { $luarocks download --rockspec validate-args ${verrev_validate_args} && rm validate-args-*; }
test_help() { $luarocks help; }
-test_install_binaryrock() { $luarocks build luasocket && $luarocks pack luasocket && $luarocks install ./luasocket-2.0.2-5.linux-x86.rock && rm ./luasocket-2.0.2-5.linux-x86.rock; }
+test_install_binaryrock() { $luarocks build --pack-binary-rock cprint && $luarocks install ./cprint-${verrev_cprint}.${platform}.rock && rm ./cprint-${verrev_cprint}.${platform}.rock; }
test_install_with_bin() { $luarocks install wsapi; }
+fail_install_notazipfile() { $luarocks install "$testing_dir/testfiles/not_a_zipfile-1.0-1.src.rock"; }
-test_lint_ok() { $luarocks download --rockspec validate-args 1.5.4 && $luarocks lint ./validate-args-1.5.4-1.rockspec && rm ./validate-args-1.5.4-1.rockspec; }
+test_lint_ok() { $luarocks download --rockspec validate-args ${verrev_validate_args} && $luarocks lint ./validate-args-${verrev_validate_args}.rockspec && rm ./validate-args-${verrev_validate_args}.rockspec; }
+fail_lint_type_mismatch_string() { $luarocks lint "$testing_dir/testfiles/type_mismatch_string-1.0-1.rockspec"; }
+fail_lint_type_mismatch_version() { $luarocks lint "$testing_dir/testfiles/type_mismatch_version-1.0-1.rockspec"; }
+fail_lint_type_mismatch_table() { $luarocks lint "$testing_dir/testfiles/type_mismatch_table-1.0-1.rockspec"; }
test_list() { $luarocks list; }
test_list_porcelain() { $luarocks list --porcelain; }
-test_make() { rm -rf ./luasocket-2.0.2-5 && $luarocks download --src luasocket && $luarocks unpack ./luasocket-2.0.2-5.src.rock && cd luasocket-2.0.2-5/luasocket-2.0.2 && $luarocks make && cd ../.. && rm -rf ./luasocket-2.0.2-5; }
-test_make_pack_binary_rock() { rm -rf ./lxsh-0.8.6-1 && $luarocks download --src lxsh 0.8.6-1 && $luarocks unpack ./lxsh-0.8.6-1.src.rock && cd lxsh-0.8.6-1/lxsh-0.8.6-1 && $luarocks make --deps-mode=none --pack-binary-rock && [ -e ./lxsh-0.8.6-1.all.rock ] && cd ../.. && rm -rf ./lxsh-0.8.6-1; }
+test_make_with_rockspec() { rm -rf ./luasocket-${verrev_luasocket} && $luarocks download --src luasocket && $luarocks unpack ./luasocket-${verrev_luasocket}.src.rock && cd luasocket-${verrev_luasocket}/${srcdir_luasocket} && $luarocks make luasocket-${verrev_luasocket}.rockspec && cd ../.. && rm -rf ./luasocket-${verrev_luasocket}; }
+test_make_default_rockspec() { rm -rf ./lxsh-${verrev_lxsh} && $luarocks download --src lxsh ${verrev_lxsh} && $luarocks unpack ./lxsh-${verrev_lxsh}.src.rock && cd lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1 && $luarocks make && cd ../.. && rm -rf ./lxsh-${verrev_lxsh}; }
+test_make_pack_binary_rock() { rm -rf ./lxsh-${verrev_lxsh} && $luarocks download --src lxsh ${verrev_lxsh} && $luarocks unpack ./lxsh-${verrev_lxsh}.src.rock && cd lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1 && $luarocks make --deps-mode=none --pack-binary-rock && [ -e ./lxsh-${verrev_lxsh}.all.rock ] && cd ../.. && rm -rf ./lxsh-${verrev_lxsh}; }
+fail_make_which_rockspec() { rm -rf ./luasocket-${verrev_luasocket} && $luarocks download --src luasocket && $luarocks unpack ./luasocket-${verrev_luasocket}.src.rock && cd luasocket-${verrev_luasocket}/${srcdir_luasocket} && $luarocks make && cd ../.. && rm -rf ./luasocket-${verrev_luasocket}; }
-test_new_version() { $luarocks download --rockspec luacov 0.1 && $luarocks new_version ./luacov-0.1-1.rockspec 0.2 && rm ./luacov-0.*; }
+test_new_version() { $luarocks download --rockspec luacov ${version_luacov} && $luarocks new_version ./luacov-${version_luacov}-1.rockspec 0.2 && rm ./luacov-0.*; }
+test_new_version_url() { $luarocks download --rockspec abelhas 1.0 && $luarocks new_version ./abelhas-1.0-1.rockspec 1.1 https://github.com/downloads/ittner/abelhas/abelhas-1.1.tar.gz && rm ./abelhas-*; }
test_pack() { $luarocks list && $luarocks pack luacov && rm ./luacov-*.rock; }
-test_pack_src() { $luarocks download --rockspec luasocket && $luarocks pack ./luasocket-2.0.2-5.rockspec && rm ./luasocket-2.0.2-*.rock; }
+test_pack_src() { $luarocks install $luasec && $luarocks download --rockspec luasocket && $luarocks pack ./luasocket-${verrev_luasocket}.rockspec && rm ./luasocket-${version_luasocket}-*.rock; }
test_path() { $luarocks path --bin; }
+test_path_lr_path() { $luarocks path --lr-path; }
+test_path_lr_cpath() { $luarocks path --lr-cpath; }
+test_path_lr_bin() { $luarocks path --lr-bin; }
fail_purge_missing_tree() { $luarocks purge --tree="$testing_tree"; }
test_purge() { $luarocks purge --tree="$testing_sys_tree"; }
-test_remove() { $luarocks build luacov 0.1 && $luarocks remove luacov 0.1; }
-#fail_remove_deps() { $luarocks build luadoc && $luarocks remove luasocket; }
+test_remove() { $luarocks build luacov ${version_luacov} && $luarocks remove luacov ${version_luacov}; }
+test_remove_force() { need_luasocket; $luarocks build lualogging && $luarocks remove --force luasocket; }
+fail_remove_deps() { need_luasocket; $luarocks build lualogging && $luarocks remove luasocket; }
+fail_remove_invalid_name() { $luarocks remove invalid.rock; }
test_search_found() { $luarocks search zlib; }
test_search_missing() { $luarocks search missing_rock; }
test_show() { $luarocks show luacov; }
test_show_modules() { $luarocks show --modules luacov; }
-test_show_depends() { $luarocks install luasec && $luarocks show luasec; }
-test_show_oldversion() { $luarocks install luacov 0.1 && $luarocks show luacov 0.1; }
+test_show_depends() { need_luasocket; $luarocks install $luasec && $luarocks show luasec; }
+test_show_oldversion() { $luarocks install luacov ${version_luacov} && $luarocks show luacov ${version_luacov}; }
-test_unpack_download() { rm -rf ./luasocket-2.0.2-5 && $luarocks unpack luasocket && rm -rf ./luasocket-2.0.2-5; }
-test_unpack_src() { rm -rf ./luasocket-2.0.2-5 && $luarocks download --src luasocket && $luarocks unpack ./luasocket-2.0.2-5.src.rock && rm -rf ./luasocket-2.0.2-5; }
-test_unpack_rockspec() { rm -rf ./luasocket-2.0.2-5 && $luarocks download --rockspec luasocket && $luarocks unpack ./luasocket-2.0.2-5.rockspec && rm -rf ./luasocket-2.0.2-5; }
-test_unpack_binary() { rm -rf ./luasocket-2.0.2-5 && $luarocks build luasocket && $luarocks pack luasocket && $luarocks unpack ./luasocket-2.0.2-5.linux-x86.rock && rm -rf ./luasocket-2.0.2-5; }
+test_unpack_download() { rm -rf ./cprint-${verrev_cprint} && $luarocks unpack cprint && rm -rf ./cprint-${verrev_cprint}; }
+test_unpack_src() { rm -rf ./cprint-${verrev_cprint} && $luarocks download --src cprint && $luarocks unpack ./cprint-${verrev_cprint}.src.rock && rm -rf ./cprint-${verrev_cprint}; }
+test_unpack_rockspec() { rm -rf ./cprint-${verrev_cprint} && $luarocks download --rockspec cprint && $luarocks unpack ./cprint-${verrev_cprint}.rockspec && rm -rf ./cprint-${verrev_cprint}; }
+test_unpack_binary() { rm -rf ./cprint-${verrev_cprint} && $luarocks build cprint && $luarocks pack cprint && $luarocks unpack ./cprint-${verrev_cprint}.${platform}.rock && rm -rf ./cprint-${verrev_cprint}; }
test_admin_help() { $luarocks_admin help; }
test_admin_make_manifest() { $luarocks_admin make_manifest; }
-test_admin_add_rsync() { $luarocks_admin --server=testing add ./luasocket-2.0.2-5.src.rock; }
-test_admin_add_sftp() { export LUAROCKS_CONFIG="$testing_dir/testing_config_sftp.lua" && $luarocks_admin --server=testing add ./luasocket-2.0.2-5.src.rock; export LUAROCKS_CONFIG="$testing_dir/testing_config.lua"; }
+test_admin_add_rsync() { if [ "$travis" ]; then return; fi; $luarocks_admin --server=testing add "$testing_server/luasocket-${verrev_luasocket}.src.rock"; }
+test_admin_add_sftp() { if [ "$travis" ]; then return; fi; export LUAROCKS_CONFIG="$testing_dir/testing_config_sftp.lua" && $luarocks_admin --server=testing add ./luasocket-${verrev_luasocket}.src.rock; export LUAROCKS_CONFIG="$testing_dir/testing_config.lua"; }
fail_admin_add_missing() { $luarocks_admin --server=testing add; }
-fail_admin_invalidserver() { $luarocks_admin --server=invalid add ./luasocket-2.0.2-5.src.rock; }
-fail_admin_invalidrock() { $luarocks_admin --server=testing add invalid; }
-test_admin_refresh_cache() { $luarocks_admin --server=testing refresh_cache; }
-test_admin_remove() { $luarocks_admin --server=testing remove luasocket; }
+fail_admin_invalidserver() { $luarocks_admin --server=invalid add "$testing_server/luasocket-${verrev_luasocket}.src.rock"; }
+fail_admin_invalidrock() { if [ "$travis" ]; then return 1; fi; $luarocks_admin --server=testing add invalid; }
+test_admin_refresh_cache() { if [ "$travis" ]; then return; fi; $luarocks_admin --server=testing refresh_cache; }
+test_admin_remove() { if [ "$travis" ]; then return; fi; $luarocks_admin --server=testing remove luasocket-${verrev_luasocket}.src.rock; }
fail_admin_remove_missing() { $luarocks_admin --server=testing remove; }
fail_deps_mode_invalid_arg() { $luarocks remove luacov --deps-mode; }
-test_deps_mode_one() { $luarocks build --tree="$testing_sys_tree" lpeg && $luarocks list && $luarocks build --deps-mode=one --tree="$testing_tree" lxsh && [ `$luarocks list --tree="$testing_tree" --porcelain lpeg | wc -l` = 1 ]; }
-test_deps_mode_order() { $luarocks build --tree="$testing_sys_tree" lpeg && $luarocks build --deps-mode=order --tree="$testing_tree" lxsh && [ `$luarocks list --tree="$testing_tree" --porcelain lpeg | wc -l` = 0 ]; }
-test_deps_mode_order_sys() { $luarocks build --tree="$testing_tree" lpeg && $luarocks build --deps-mode=order --tree="$testing_sys_tree" lxsh && [ `$luarocks list --tree="$testing_sys_tree" --porcelain lpeg | wc -l` = 1 ]; }
-test_deps_mode_all_sys() { $luarocks build --tree="$testing_tree" lpeg && $luarocks build --deps-mode=all --tree="$testing_sys_tree" lxsh && [ `$luarocks list --tree="$testing_sys_tree" --porcelain lpeg | wc -l` = 0 ]; }
-test_deps_mode_none() { $luarocks build --tree="$testing_tree" --deps-mode=none lxsh; [ `$luarocks list --tree="$testing_tree" --porcelain lpeg | wc -l` = 0 ]; }
-test_deps_mode_nodeps_alias() { $luarocks build --tree="$testing_tree" --nodeps lxsh; [ `$luarocks list --tree="$testing_tree" --porcelain lpeg | wc -l` = 0 ]; }
-test_deps_mode_make_order() { $luarocks build --tree="$testing_sys_tree" lpeg && rm -rf ./lxsh-0.8.6-1 && $luarocks download --src lxsh 0.8.6-1 && $luarocks unpack ./lxsh-0.8.6-1.src.rock && cd lxsh-0.8.6-1/lxsh-0.8.6-1 && $luarocks make --tree="$testing_tree" --deps-mode=order && cd ../.. && [ `$luarocks list --tree="$testing_tree" --porcelain lpeg | wc -l` = 0 ] && rm -rf ./lxsh-0.8.6-1; }
-test_deps_mode_make_order_sys() { $luarocks build --tree="$testing_tree" lpeg && rm -rf ./lxsh-0.8.6-1 && $luarocks download --src lxsh 0.8.6-1 && $luarocks unpack ./lxsh-0.8.6-1.src.rock && cd lxsh-0.8.6-1/lxsh-0.8.6-1 && $luarocks make --tree="$testing_sys_tree" --deps-mode=order && cd ../.. && [ `$luarocks list --tree="$testing_tree" --porcelain lpeg | wc -l` = 1 ] && rm -rf ./lxsh-0.8.6-1; }
+test_deps_mode_one() { $luarocks build --tree="system" lpeg && $luarocks list && $luarocks build --deps-mode=one --tree="$testing_tree" lxsh && [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 1 ]; }
+test_deps_mode_order() { $luarocks build --tree="system" lpeg && $luarocks build --deps-mode=order --tree="$testing_tree" lxsh && $luarocks_noecho list --tree="$testing_tree" --porcelain lpeg && [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 0 ]; }
+test_deps_mode_order_sys() { $luarocks build --tree="$testing_tree" lpeg && $luarocks build --deps-mode=order --tree="$testing_sys_tree" lxsh && [ `$luarocks_noecho list --tree="$testing_sys_tree" --porcelain lpeg | wc -l` = 1 ]; }
+test_deps_mode_all_sys() { $luarocks build --tree="$testing_tree" lpeg && $luarocks build --deps-mode=all --tree="$testing_sys_tree" lxsh && [ `$luarocks_noecho list --tree="$testing_sys_tree" --porcelain lpeg | wc -l` = 0 ]; }
+test_deps_mode_none() { $luarocks build --tree="$testing_tree" --deps-mode=none lxsh; [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 0 ]; }
+test_deps_mode_nodeps_alias() { $luarocks build --tree="$testing_tree" --nodeps lxsh; [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 0 ]; }
+test_deps_mode_make_order() { $luarocks build --tree="$testing_sys_tree" lpeg && rm -rf ./lxsh-${verrev_lxsh} && $luarocks download --src lxsh ${verrev_lxsh} && $luarocks unpack ./lxsh-${verrev_lxsh}.src.rock && cd lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1 && $luarocks make --tree="$testing_tree" --deps-mode=order && cd ../.. && [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 0 ] && rm -rf ./lxsh-${verrev_lxsh}; }
+test_deps_mode_make_order_sys() { $luarocks build --tree="$testing_tree" lpeg && rm -rf ./lxsh-${verrev_lxsh} && $luarocks download --src lxsh ${verrev_lxsh} && $luarocks unpack ./lxsh-${verrev_lxsh}.src.rock && cd lxsh-${verrev_lxsh}/lxsh-${version_lxsh}-1 && $luarocks make --tree="$testing_sys_tree" --deps-mode=order && cd ../.. && [ `$luarocks_noecho list --tree="$testing_tree" --porcelain lpeg | wc -l` = 1 ] && rm -rf ./lxsh-${verrev_lxsh}; }
+
+test_write_rockspec() { $luarocks write_rockspec git://github.com/keplerproject/luarocks; }
+test_write_rockspec_lib() { $luarocks write_rockspec git://github.com/mbalmer/luafcgi --lib=fcgi --license="3-clause BSD" --lua-version=5.1,5.2; }
+test_write_rockspec_fullargs() { $luarocks write_rockspec git://github.com/keplerproject/luarocks --lua-version=5.1,5.2 --license="MIT/X11" --homepage="http://www.luarocks.org" --summary="A package manager for Lua modules"; }
+fail_write_rockspec_args() { $luarocks write_rockspec invalid; }
+fail_write_rockspec_args_url() { $luarocks write_rockspec http://example.com/invalid.zip; }
+test_write_rockspec_http() { $luarocks write_rockspec http://luarocks.org/releases/luarocks-2.1.0.tar.gz --lua-version=5.1; }
+test_write_rockspec_basedir() { $luarocks write_rockspec https://github.com/downloads/Olivine-Labs/luassert/luassert-1.2.tar.gz --lua-version=5.1; }
+
+test_doc() { $luarocks install luarepl; $luarocks doc luarepl; }
# Driver #########################################
@@ -232,7 +456,6 @@ run_tests() {
else echo "FAIL: Unexpected failure."; exit 1
fi
done
-
grep "^fail_$1.*(" < $testing_dir/testing.sh | cut -d'(' -f1 | while read test
do
echo "-------------------------------------------"
@@ -247,11 +470,17 @@ run_tests() {
}
run_with_minimal_environment() {
+ echo "==========================================="
+ echo "Running with minimal environment"
+ echo "==========================================="
build_environment luacov
run_tests $1
}
run_with_full_environment() {
+ echo "==========================================="
+ echo "Running with full environment"
+ echo "==========================================="
build_environment luacov luafilesystem luasocket luabitop luaposix md5 lzlib
run_tests $1
}
@@ -266,4 +495,10 @@ run_all_tests $1
$testing_sys_tree/bin/luacov -c $testing_dir/luacov.config src/luarocks src/bin
-cat $testing_dir/luacov.report.out
+if [ "$travis" ]
+then
+ grep "Summary" -B1 -A1000 $testing_dir/luacov.report.out
+else
+ cat "$testing_dir/luacov.report.out"
+fi
+
diff --git a/win32/bin/create_reg_file.lua b/win32/LuaRocks.reg.lua
index 2eb7583..2eb7583 100644
--- a/win32/bin/create_reg_file.lua
+++ b/win32/LuaRocks.reg.lua
diff --git a/win32/bin/LuaRocks.reg.template b/win32/LuaRocks.reg.template
index 82cc180..82cc180 100644
--- a/win32/bin/LuaRocks.reg.template
+++ b/win32/LuaRocks.reg.template
diff --git a/win32/bin/chmod.exe b/win32/bin/chmod.exe
deleted file mode 100644
index 9655cfd..0000000
--- a/win32/bin/chmod.exe
+++ /dev/null
Binary files differ
diff --git a/win32/bin/objdump.exe b/win32/bin/objdump.exe
deleted file mode 100644
index 4429d10..0000000
--- a/win32/bin/objdump.exe
+++ /dev/null
Binary files differ
diff --git a/win32/bin/rm.exe b/win32/bin/rm.exe
deleted file mode 100755
index 8e79306..0000000
--- a/win32/bin/rm.exe
+++ /dev/null
Binary files differ
diff --git a/win32/bin/lua.ico b/win32/lua.ico
index 56dc4fe..56dc4fe 100644
--- a/win32/bin/lua.ico
+++ b/win32/lua.ico
Binary files differ
diff --git a/win32/bin/luarocksw.bat b/win32/luarocksw.bat
index 313508d..8ac0292 100644
--- a/win32/bin/luarocksw.bat
+++ b/win32/luarocksw.bat
@@ -34,14 +34,14 @@ if [%1]==[removeall] goto REMOVEALL
REM execute LuaRocks and wait for results
echo executing: luarocks %*
-call %MYPATH%luarocks %*
+call "%MYPATH%luarocks" %*
pause
goto END
:REMOVEALL
for /f "delims=-" %%a in ("%~n2") do (
echo executing: luarocks remove %%a
- %MYPATH%luarocks remove "%%a"
+ "%MYPATH%luarocks" remove "%%a"
pause
goto END
)
diff --git a/win32/pe-parser.lua b/win32/pe-parser.lua
new file mode 100644
index 0000000..30bb839
--- /dev/null
+++ b/win32/pe-parser.lua
@@ -0,0 +1,546 @@
+---------------------------------------------------------------------------------------
+-- Lua module to parse a Portable Executable (.exe , .dll, etc.) file and extract metadata.
+--
+-- Version 0.1, [copyright (c) 2013 - Thijs Schreijer](http://www.thijsschreijer.nl)
+-- @name pe-parser
+-- @class module
+
+local M = {}
+
+--- Table with named constants/flag-constants.
+-- Named elements can be looked up by their name in the `const` table. The sub tables are index by value.
+-- For flag fields the name is extended with `_flags`.
+-- @usage -- lookup descriptive name for the myobj.Magic value
+-- local desc = pe.const.Magic(myobj.Magic)
+--
+-- -- get list of flag names, indexed by flag values, for the Characteristics field
+-- local flag_list = pe.const.Characteristics_flags
+M.const = {
+ Magic = {
+ ["10b"] = "PE32",
+ ["20b"] = "PE32+",
+ },
+ Machine = {
+ ["0"] = "IMAGE_FILE_MACHINE_UNKNOWN",
+ ["1d3"] = "IMAGE_FILE_MACHINE_AM33",
+ ["8664"] = "IMAGE_FILE_MACHINE_AMD64",
+ ["1c0"] = "IMAGE_FILE_MACHINE_ARM",
+ ["1c4"] = "IMAGE_FILE_MACHINE_ARMNT",
+ ["aa64"] = "IMAGE_FILE_MACHINE_ARM64",
+ ["ebc"] = "IMAGE_FILE_MACHINE_EBC",
+ ["14c"] = "IMAGE_FILE_MACHINE_I386",
+ ["200"] = "IMAGE_FILE_MACHINE_IA64",
+ ["9041"] = "IMAGE_FILE_MACHINE_M32R",
+ ["266"] = "IMAGE_FILE_MACHINE_MIPS16",
+ ["366"] = "IMAGE_FILE_MACHINE_MIPSFPU",
+ ["466"] = "IMAGE_FILE_MACHINE_MIPSFPU16",
+ ["1f0"] = "IMAGE_FILE_MACHINE_POWERPC",
+ ["1f1"] = "IMAGE_FILE_MACHINE_POWERPCFP",
+ ["166"] = "IMAGE_FILE_MACHINE_R4000",
+ ["1a2"] = "IMAGE_FILE_MACHINE_SH3",
+ ["1a3"] = "IMAGE_FILE_MACHINE_SH3DSP",
+ ["1a6"] = "IMAGE_FILE_MACHINE_SH4",
+ ["1a8"] = "IMAGE_FILE_MACHINE_SH5",
+ ["1c2"] = "IMAGE_FILE_MACHINE_THUMB",
+ ["169"] = "IMAGE_FILE_MACHINE_WCEMIPSV2",
+ },
+ Characteristics_flags = {
+ ["1"] = "IMAGE_FILE_RELOCS_STRIPPED",
+ ["2"] = "IMAGE_FILE_EXECUTABLE_IMAGE",
+ ["4"] = "IMAGE_FILE_LINE_NUMS_STRIPPED",
+ ["8"] = "IMAGE_FILE_LOCAL_SYMS_STRIPPED",
+ ["10"] = "IMAGE_FILE_AGGRESSIVE_WS_TRIM",
+ ["20"] = "IMAGE_FILE_LARGE_ADDRESS_AWARE",
+ ["40"] = "Reserved for future use",
+ ["80"] = "IMAGE_FILE_BYTES_REVERSED_LO",
+ ["100"] = "IMAGE_FILE_32BIT_MACHINE",
+ ["200"] = "IMAGE_FILE_DEBUG_STRIPPED",
+ ["400"] = "IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP",
+ ["800"] = "IMAGE_FILE_NET_RUN_FROM_SWAP",
+ ["1000"] = "IMAGE_FILE_SYSTEM",
+ ["2000"] = "IMAGE_FILE_DLL",
+ ["4000"] = "IMAGE_FILE_UP_SYSTEM_ONLY",
+ ["8000"] = "IMAGE_FILE_BYTES_REVERSED_HI",
+ },
+ Subsystem = {
+ ["0"] = "IMAGE_SUBSYSTEM_UNKNOWN",
+ ["1"] = "IMAGE_SUBSYSTEM_NATIVE",
+ ["2"] = "IMAGE_SUBSYSTEM_WINDOWS_GUI",
+ ["3"] = "IMAGE_SUBSYSTEM_WINDOWS_CUI",
+ ["7"] = "IMAGE_SUBSYSTEM_POSIX_CUI",
+ ["9"] = "IMAGE_SUBSYSTEM_WINDOWS_CE_GUI",
+ ["a"] = "IMAGE_SUBSYSTEM_EFI_APPLICATION",
+ ["b"] = "IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER",
+ ["c"] = "IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER",
+ ["d"] = "IMAGE_SUBSYSTEM_EFI_ROM",
+ ["e"] = "IMAGE_SUBSYSTEM_XBOX",
+ },
+ DllCharacteristics_flags = {
+ ["40"] = "IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE",
+ ["80"] = "IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY",
+ ["100"] = "IMAGE_DLL_CHARACTERISTICS_NX_COMPAT",
+ ["200"] = "IMAGE_DLLCHARACTERISTICS_NO_ISOLATION",
+ ["400"] = "IMAGE_DLLCHARACTERISTICS_NO_SEH",
+ ["800"] = "IMAGE_DLLCHARACTERISTICS_NO_BIND",
+ ["2000"] = "IMAGE_DLLCHARACTERISTICS_WDM_DRIVER",
+ ["8000"] = "IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE",
+ },
+ Sections = {
+ Characteristics_flags = {
+ ["8"] = "IMAGE_SCN_TYPE_NO_PAD",
+ ["20"] = "IMAGE_SCN_CNT_CODE",
+ ["40"] = "IMAGE_SCN_CNT_INITIALIZED_DATA",
+ ["80"] = "IMAGE_SCN_CNT_UNINITIALIZED_ DATA",
+ ["100"] = "IMAGE_SCN_LNK_OTHER",
+ ["200"] = "IMAGE_SCN_LNK_INFO",
+ ["800"] = "IMAGE_SCN_LNK_REMOVE",
+ ["1000"] = "IMAGE_SCN_LNK_COMDAT",
+ ["8000"] = "IMAGE_SCN_GPREL",
+ ["20000"] = "IMAGE_SCN_MEM_PURGEABLE",
+ ["20000"] = "IMAGE_SCN_MEM_16BIT",
+ ["40000"] = "IMAGE_SCN_MEM_LOCKED",
+ ["80000"] = "IMAGE_SCN_MEM_PRELOAD",
+ ["100000"] = "IMAGE_SCN_ALIGN_1BYTES",
+ ["200000"] = "IMAGE_SCN_ALIGN_2BYTES",
+ ["300000"] = "IMAGE_SCN_ALIGN_4BYTES",
+ ["400000"] = "IMAGE_SCN_ALIGN_8BYTES",
+ ["500000"] = "IMAGE_SCN_ALIGN_16BYTES",
+ ["600000"] = "IMAGE_SCN_ALIGN_32BYTES",
+ ["700000"] = "IMAGE_SCN_ALIGN_64BYTES",
+ ["800000"] = "IMAGE_SCN_ALIGN_128BYTES",
+ ["900000"] = "IMAGE_SCN_ALIGN_256BYTES",
+ ["a00000"] = "IMAGE_SCN_ALIGN_512BYTES",
+ ["b00000"] = "IMAGE_SCN_ALIGN_1024BYTES",
+ ["c00000"] = "IMAGE_SCN_ALIGN_2048BYTES",
+ ["d00000"] = "IMAGE_SCN_ALIGN_4096BYTES",
+ ["e00000"] = "IMAGE_SCN_ALIGN_8192BYTES",
+ ["1000000"] = "IMAGE_SCN_LNK_NRELOC_OVFL",
+ ["2000000"] = "IMAGE_SCN_MEM_DISCARDABLE",
+ ["4000000"] = "IMAGE_SCN_MEM_NOT_CACHED",
+ ["8000000"] = "IMAGE_SCN_MEM_NOT_PAGED",
+ ["10000000"] = "IMAGE_SCN_MEM_SHARED",
+ ["20000000"] = "IMAGE_SCN_MEM_EXECUTE",
+ ["40000000"] = "IMAGE_SCN_MEM_READ",
+ ["80000000"] = "IMAGE_SCN_MEM_WRITE",
+ },
+ },
+
+}
+
+
+--- convert integer to HEX representation
+-- @param IN the number to convert to hex
+-- @param len the size to return, any result smaller will be prefixed by "0"s
+-- @return string containing hex representation
+function M.toHex(IN, len)
+ local B,K,OUT,I,D=16,"0123456789abcdef","",0
+ while IN>0 do
+ I=I+1
+ IN,D=math.floor(IN/B),math.fmod(IN,B)+1
+ OUT=string.sub(K,D,D)..OUT
+ end
+ len = len or string.len(OUT)
+ if len<1 then len = 1 end
+ return (string.rep("0",len) .. OUT):sub(-len,-1)
+end
+
+--- convert HEX to integer
+-- @param IN the string to convert to dec
+-- @return number in dec format
+function M.toDec(IN)
+ assert(type(IN)=="string")
+ local OUT = 0
+ IN = IN:lower()
+ while #IN > 0 do
+ local b = string.find("0123456789abcdef",IN:sub(1,1))
+ OUT = OUT * 16 + (b-1)
+ IN = IN:sub(2,-1)
+ end
+ return OUT
+end
+
+local function get_int(str)
+ -- convert a byte-sequence to an integer
+ assert(str)
+ local r = 0
+ for i = #str, 1, -1 do
+ r = r*256 + string.byte(str,i,i)
+ end
+ return r
+end
+
+local function get_hex(str)
+ -- convert a byte-sequence to a hex string
+ assert(str)
+ local r = ""
+ for i = #str, 1, -1 do
+ r = r .. M.toHex(string.byte(str,i,i),2)
+ end
+ while (#r > 1) and (r:sub(1,1) == "0") do
+ r = r:sub(2, -1)
+ end
+ return r
+end
+
+local function get_list(list, f, add_to)
+ -- list: list of tables with 'size' and 'name' and is_str
+ -- f: file to read from
+ -- add_to: table to add results to (optional)
+ local r = add_to or {}
+ for i, t in ipairs(list) do
+ assert(r[t.name] == nil, "Value for '"..t.name.."' already set")
+ local val,err = f:read(t.size) -- read specified size in bytes
+ val = val or "\0"
+ if t.is_str then -- entry is marked as a string value, read as such
+ for i = 1, #val do
+ if val:sub(i,i) == "\0" then
+ r[t.name] = val:sub(1,i-1)
+ break
+ end
+ end
+ r[t.name] = r[t.name] or val
+ else -- entry not marked, so always read as hex value
+ r[t.name] = get_hex(val)
+ end
+ end
+ return r
+end
+
+--- Calculates the fileoffset of a given RVA.
+-- This function is also available as a method on the parsed output table
+-- @param obj a parsed object (return value from `parse`)
+-- @param RVA an RVA value to convert to a fileoffset (either number or hex-string)
+-- @return fileoffset of the given RVA (number)
+M.get_fileoffset = function(obj, RVA)
+ -- given an object with a section table, and an RVA, it returns
+ -- the fileoffset for the data
+ if type(RVA)=="string" then RVA = M.toDec(RVA) end
+ local section
+ for i, s in ipairs(obj.Sections) do
+ if M.toDec(s.VirtualAddress) <= RVA and M.toDec(s.VirtualAddress) + M.toDec(s.VirtualSize) >= RVA then
+ section = s
+ break
+ end
+ end
+ if not section then return nil, "No match RVA with Section list, RVA out of bounds" end
+ return RVA - M.toDec(section.VirtualAddress) + M.toDec(section.PointerToRawData)
+end
+
+local function readstring(f)
+ -- reads a null-terminated string from the current file posistion
+ local name = ""
+ while true do
+ local c = f:read(1)
+ if c == "\0" then break end
+ name = name .. c
+ end
+ return name
+end
+
+--- Parses a file and extracts the information.
+-- All numbers are delivered as "string" types containing hex values, see `toHex` and `toDec` conversion functions.
+-- @return table with data, or nil + error
+-- @usage local pe = require("pe-parser")
+-- local obj = pe.parse("c:\lua\lua.exe")
+-- obj:dump()
+M.parse = function(target)
+
+ local list = { -- list of known architectures
+ [332] = "x86", -- IMAGE_FILE_MACHINE_I386
+ [512] = "x86_64", -- IMAGE_FILE_MACHINE_IA64
+ [34404] = "x86_64", -- IMAGE_FILE_MACHINE_AMD64
+ }
+
+ local f, err = io.open(target, "rb")
+ if not f then return nil, err end
+
+ local MZ = f:read(2)
+ if MZ ~= "MZ" then
+ f:close()
+ return nil, "Not a valid image"
+ end
+
+ f:seek("set", 60) -- position of PE header position
+ local peoffset = get_int(f:read(4)) -- read position of PE header
+
+ f:seek("set", peoffset) -- move to position of PE header
+ local out = get_list({
+ { size = 4,
+ name = "PEheader",
+ is_str = true },
+ { size = 2,
+ name = "Machine" },
+ { size = 2,
+ name = "NumberOfSections"},
+ { size = 4,
+ name = "TimeDateStamp" },
+ { size = 4,
+ name = "PointerToSymbolTable"},
+ { size = 4,
+ name = "NumberOfSymbols"},
+ { size = 2,
+ name = "SizeOfOptionalHeader"},
+ { size = 2,
+ name = "Characteristics"},
+ }, f)
+
+ if out.PEheader ~= "PE" then
+ f:close()
+ return nil, "Invalid PE header"
+ end
+ out.PEheader = nil -- remove it, has no value
+ out.dump = M.dump -- export dump function as a method
+
+ if M.toDec(out.SizeOfOptionalHeader) > 0 then
+ -- parse optional header; standard
+ get_list({
+ { size = 2,
+ name = "Magic" },
+ { size = 1,
+ name = "MajorLinkerVersion"},
+ { size = 1,
+ name = "MinorLinkerVersion"},
+ { size = 4,
+ name = "SizeOfCode"},
+ { size = 4,
+ name = "SizeOfInitializedData"},
+ { size = 4,
+ name = "SizeOfUninitializedData"},
+ { size = 4,
+ name = "AddressOfEntryPoint"},
+ { size = 4,
+ name = "BaseOfCode"},
+ }, f, out)
+ local plus = (out.Magic == "20b")
+ if not plus then -- plain PE32, not PE32+
+ get_list({
+ { size = 4,
+ name = "BaseOfData" },
+ }, f, out)
+ end
+ -- parse optional header; windows-fields
+ local plussize = 4
+ if plus then plussize = 8 end
+ get_list({
+ { size = plussize,
+ name = "ImageBase"},
+ { size = 4,
+ name = "SectionAlignment"},
+ { size = 4,
+ name = "FileAlignment"},
+ { size = 2,
+ name = "MajorOperatingSystemVersion"},
+ { size = 2,
+ name = "MinorOperatingSystemVersion"},
+ { size = 2,
+ name = "MajorImageVersion"},
+ { size = 2,
+ name = "MinorImageVersion"},
+ { size = 2,
+ name = "MajorSubsystemVersion"},
+ { size = 2,
+ name = "MinorSubsystemVersion"},
+ { size = 4,
+ name = "Win32VersionValue"},
+ { size = 4,
+ name = "SizeOfImage"},
+ { size = 4,
+ name = "SizeOfHeaders"},
+ { size = 4,
+ name = "CheckSum"},
+ { size = 2,
+ name = "Subsystem"},
+ { size = 2,
+ name = "DllCharacteristics"},
+ { size = plussize,
+ name = "SizeOfStackReserve"},
+ { size = plussize,
+ name = "SizeOfStackCommit"},
+ { size = plussize,
+ name = "SizeOfHeapReserve"},
+ { size = plussize,
+ name = "SizeOfHeapCommit"},
+ { size = 4,
+ name = "LoaderFlags"},
+ { size = 4,
+ name = "NumberOfRvaAndSizes"},
+ }, f, out)
+ -- Read data directory entries
+ for i = 1, M.toDec(out.NumberOfRvaAndSizes) do
+ out.DataDirectory = out.DataDirectory or {}
+ out.DataDirectory[i] = get_list({
+ { size = 4,
+ name = "VirtualAddress"},
+ { size = 4,
+ name = "Size"},
+ }, f)
+ end
+ for i, name in ipairs{"ExportTable", "ImportTable", "ResourceTable",
+ "ExceptionTable", "CertificateTable", "BaseRelocationTable",
+ "Debug", "Architecture", "GlobalPtr", "TLSTable",
+ "LoadConfigTable", "BoundImport", "IAT",
+ "DelayImportDescriptor", "CLRRuntimeHeader", "Reserved"} do
+ out.DataDirectory[name] = out.DataDirectory[i]
+ if out.DataDirectory[name] then out.DataDirectory[name].name = name end
+ end
+ end
+
+ -- parse section table
+ for i = 1, M.toDec(out.NumberOfSections) do
+ out.Sections = out.Sections or {}
+ out.Sections[i] = get_list({
+ { size = 8,
+ name = "Name",
+ is_str = true},
+ { size = 4,
+ name = "VirtualSize"},
+ { size = 4,
+ name = "VirtualAddress"},
+ { size = 4,
+ name = "SizeOfRawData"},
+ { size = 4,
+ name = "PointerToRawData"},
+ { size = 4,
+ name = "PointerToRelocations"},
+ { size = 4,
+ name = "PointerToLinenumbers"},
+ { size = 2,
+ name = "NumberOfRelocations"},
+ { size = 2,
+ name = "NumberOfLinenumbers"},
+ { size = 4,
+ name = "Characteristics"},
+ }, f)
+ end
+ -- we now have section data, so add RVA convertion method
+ out.get_fileoffset = M.get_fileoffset
+
+ -- get the import table
+ f:seek("set", out:get_fileoffset(out.DataDirectory.ImportTable.VirtualAddress))
+ local done = false
+ local cnt = 1
+ while not done do
+ local dll = get_list({
+ { size = 4,
+ name = "ImportLookupTableRVA"},
+ { size = 4,
+ name = "TimeDateStamp"},
+ { size = 4,
+ name = "ForwarderChain"},
+ { size = 4,
+ name = "NameRVA"},
+ { size = 4,
+ name = "ImportAddressTableRVA"},
+ }, f)
+ if M.toDec(dll.NameRVA) == 0 then
+ -- this is the final NULL entry, so we're done
+ done = true
+ else
+ -- store the import entry
+ out.DataDirectory.ImportTable[cnt] = dll
+ cnt = cnt + 1
+ end
+ end
+ -- resolve imported DLL names
+ for i, dll in ipairs(out.DataDirectory.ImportTable) do
+ f:seek("set", out:get_fileoffset(dll.NameRVA))
+ dll.Name = readstring(f)
+ end
+
+ f:close()
+ return out
+end
+
+-- pad a string (prefix) to a specific length
+local function pad(str, l, chr)
+ chr = chr or " "
+ l = l or 0
+ return string.rep(chr,l-#str)..str
+end
+
+--- Dumps the output parsed.
+-- This function is also available as a method on the parsed output table
+M.dump = function(obj)
+ local l = 0
+ for k,v in pairs(obj) do if #k > l then l = #k end end
+
+ for k,v in pairs(obj) do
+ if (M.const[k] and type(v)=="string") then
+ -- look up named value
+ print(k..string.rep(" ", l - #k + 1)..": "..M.const[k][v])
+ elseif M.const[k.."_flags"] then
+ -- flags should be listed
+ print(k..string.rep(" ", l - #k + 1)..": "..v.." (flag field)")
+ else
+ -- regular values
+ if type(v) == "number" then
+ print(k..string.rep(" ", l - #k + 1)..": "..v.." (dec)")
+ else
+ if (type(v)=="string") and (k ~= "DataDirectory") and (k ~= "Sections") then
+ print(k..string.rep(" ", l - #k + 1)..": "..v)
+ end
+ end
+ end
+ end
+
+ if obj.DataDirectory then
+ print("DataDirectory (RVA, size):")
+ for i, v in ipairs(obj.DataDirectory) do
+ print(" Entry "..M.toHex(i-1).." "..pad(v.VirtualAddress,8,"0").." "..pad(v.Size,8,"0").." "..v.name)
+ end
+ end
+
+ if obj.Sections then
+ print("Sections:")
+ print("idx name RVA VSize Offset RawSize")
+ for i, v in ipairs(obj.Sections) do
+ print(" "..i.." "..v.Name.. string.rep(" ",9-#v.Name)..pad(v.VirtualAddress,8,"0").." "..pad(v.VirtualSize,8,"0").." "..pad(v.PointerToRawData,8,"0").." "..pad(v.SizeOfRawData,8,"0"))
+ end
+ end
+
+ print("Imports:")
+ for i, dll in ipairs(obj.DataDirectory.ImportTable) do
+ print(" "..dll.Name)
+ end
+end
+
+--- Checks the msvcrt dll the binary was linked against.
+-- Mixing and matching dlls only works when they all are using the same runtime, if
+-- not unexpected errors will probably occur.
+-- Checks the binary provided and then traverses all imported dlls to find the msvcrt
+-- used (it will only look for the dlls in the same directory).
+-- @param infile binary file to check
+-- @return msvcrt name (uppercase, without extension) + file where the reference was found, or nil + error
+function M.msvcrt(infile)
+ local path, file = infile:match("(.+)\\(.+)$")
+ if not path then
+ path = ""
+ file = infile
+ else
+ path=path .. "\\"
+ end
+ local obj, err = M.parse(path..file)
+ if not obj then return obj, err end
+
+ for i, dll in ipairs(obj.DataDirectory.ImportTable) do
+ dll = dll.Name:upper()
+ local result = dll:match('(MSVCR%d*)%.DLL')
+ if not result then
+ result = dll:match('(MSVCRT)%.DLL')
+ end
+ -- success, found it return name + binary where it was found
+ if result then return result, infile end
+ end
+
+ -- not found, so traverse all imported dll's
+ for i, dll in ipairs(obj.DataDirectory.ImportTable) do
+ local rt, ref = M.msvcrt(path..dll.Name)
+ if rt then
+ return rt, ref -- found it
+ end
+ end
+
+ return nil, "No msvcrt found"
+end
+
+return M
diff --git a/win32/bin/rclauncher.c b/win32/rclauncher.c
index 77459f4..77459f4 100644
--- a/win32/bin/rclauncher.c
+++ b/win32/rclauncher.c
diff --git a/win32/bin/7z.dll b/win32/tools/7z.dll
index c0ff7fb..c0ff7fb 100644
--- a/win32/bin/7z.dll
+++ b/win32/tools/7z.dll
Binary files differ
diff --git a/win32/bin/7z.exe b/win32/tools/7z.exe
index 5e3d6f9..5e3d6f9 100644
--- a/win32/bin/7z.exe
+++ b/win32/tools/7z.exe
Binary files differ
diff --git a/win32/bin/cp.exe b/win32/tools/cp.exe
index 0ef4fe8..0ef4fe8 100755..100644
--- a/win32/bin/cp.exe
+++ b/win32/tools/cp.exe
Binary files differ
diff --git a/win32/bin/find.exe b/win32/tools/find.exe
index 85192fb..85192fb 100755..100644
--- a/win32/bin/find.exe
+++ b/win32/tools/find.exe
Binary files differ
diff --git a/win32/bin/libeay32.dll b/win32/tools/libeay32.dll
index 8d31f86..8d31f86 100644
--- a/win32/bin/libeay32.dll
+++ b/win32/tools/libeay32.dll
Binary files differ
diff --git a/win32/bin/libiconv2.dll b/win32/tools/libiconv2.dll
index 544dd92..544dd92 100644
--- a/win32/bin/libiconv2.dll
+++ b/win32/tools/libiconv2.dll
Binary files differ
diff --git a/win32/bin/libintl3.dll b/win32/tools/libintl3.dll
index ec11e6b..ec11e6b 100644
--- a/win32/bin/libintl3.dll
+++ b/win32/tools/libintl3.dll
Binary files differ
diff --git a/win32/bin/libssl32.dll b/win32/tools/libssl32.dll
index a30ff0e..a30ff0e 100644
--- a/win32/bin/libssl32.dll
+++ b/win32/tools/libssl32.dll
Binary files differ
diff --git a/win32/bin/ls.exe b/win32/tools/ls.exe
index 96ff2e5..96ff2e5 100755..100644
--- a/win32/bin/ls.exe
+++ b/win32/tools/ls.exe
Binary files differ
diff --git a/win32/bin/md5sum.exe b/win32/tools/md5sum.exe
index 4ae9f74..4ae9f74 100644
--- a/win32/bin/md5sum.exe
+++ b/win32/tools/md5sum.exe
Binary files differ
diff --git a/win32/bin/mkdir.exe b/win32/tools/mkdir.exe
index 83e57d9..83e57d9 100755..100644
--- a/win32/bin/mkdir.exe
+++ b/win32/tools/mkdir.exe
Binary files differ
diff --git a/win32/bin/mv.exe b/win32/tools/mv.exe
index 9fb65bb..9fb65bb 100755..100644
--- a/win32/bin/mv.exe
+++ b/win32/tools/mv.exe
Binary files differ
diff --git a/win32/bin/pwd.exe b/win32/tools/pwd.exe
index 7dd114d..7dd114d 100755..100644
--- a/win32/bin/pwd.exe
+++ b/win32/tools/pwd.exe
Binary files differ
diff --git a/win32/bin/rmdir.exe b/win32/tools/rmdir.exe
index 6a85c3c..6a85c3c 100755..100644
--- a/win32/bin/rmdir.exe
+++ b/win32/tools/rmdir.exe
Binary files differ
diff --git a/win32/bin/test.exe b/win32/tools/test.exe
index 94c95f9..94c95f9 100755..100644
--- a/win32/bin/test.exe
+++ b/win32/tools/test.exe
Binary files differ
diff --git a/win32/bin/uname.exe b/win32/tools/uname.exe
index 3e2f4cf..3e2f4cf 100755..100644
--- a/win32/bin/uname.exe
+++ b/win32/tools/uname.exe
Binary files differ
diff --git a/win32/bin/wget.exe b/win32/tools/wget.exe
index 54b372e..54b372e 100644
--- a/win32/bin/wget.exe
+++ b/win32/tools/wget.exe
Binary files differ