luarocks-2.0.9/ 0000755 0001750 0000144 00000000000 11757524232 012545 5 ustar hisham users luarocks-2.0.9/COPYING_lua 0000644 0001750 0000144 00000002770 11757524226 014452 0 ustar hisham users Lua License
-----------
Lua is licensed under the terms of the MIT license reproduced below.
This means that Lua is free software and can be used for both academic
and commercial purposes at absolutely no cost.
For details and rationale, see http://www.lua.org/license.html .
===============================================================================
Copyright (C) 1994-2008 Lua.org, PUC-Rio.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================================================
(end of COPYRIGHT)
luarocks-2.0.9/test/ 0000755 0001750 0000144 00000000000 11757524227 013530 5 ustar hisham users luarocks-2.0.9/test/test_require.lua 0000755 0001750 0000144 00000001017 11757524227 016750 0 ustar hisham users #!/usr/bin/env lua
local luarocks = require("luarocks.require")
luarocks.set_context("cgilua", "cvs-2")
print(package.path)
print(package.cpath)
local socket = require("socket")
if not socket then os.exit(1) end
print(socket, socket._VERSION)
local socket2 = require("socket")
if not socket2 then os.exit(1) end
print(socket2, socket2._VERSION)
local mime = require("mime")
if not mime then os.exit(1) end
print(mime, mime._VERSION)
local socket = require("lfs")
if not lfs then os.exit(1) end
print(lfs, lfs._VERSION)
luarocks-2.0.9/test/run_tests.sh 0000755 0001750 0000144 00000003124 11757524227 016115 0 ustar hisham users #!/bin/bash
if [ -e ./run_tests.sh ]
then
cd ../src
elif [ -d src ]
then
cd src
elif ! [ -d luarocks ]
then
echo "Go to the src directory and run this."
exit 1
fi
if [ ! -d ../rocks ]
then
echo "Downloading entire rocks repository for tests"
cd ..
cp -a ~/.cache/luarocks/rocks .
cd src
fi
rocks=(
`ls ../rocks/*.src.rock | grep -v luacom`
)
bin/luarocks-admin make-manifest ../rocks || exit 1
[ "$1" ] && rocks=("$1")
TRY() {
"$@" || {
echo "Failed running: $@"
exit 1
}
}
list_search() {
bin/luarocks list $name | grep $version
}
for rock in "${rocks[@]}"
do
base=`basename $rock`
baserockspec=`basename $rock .rockspec`
basesrcrock=`basename $rock .src.rock`
if [ "$base" != "$baserockspec" ]
then
base=$baserockspec
name=`echo $base | sed 's/\(.*\)-[^-]*-[^-]*$/\1/'`
version=`echo $base | sed 's/.*-\([^-]*-[^-]*\)$/\1/'`
TRY bin/luarocks pack $rock
TRY bin/luarocks build $base.src.rock
TRY rm $base.src.rock
else
base=$basesrcrock
name=`echo $base | sed 's/\(.*\)-[^-]*-[^-]*$/\1/'`
version=`echo $base | sed 's/.*-\([^-]*-[^-]*\)$/\1/'`
TRY bin/luarocks build $rock
fi
TRY bin/luarocks pack $name $version
TRY bin/luarocks install $base.*.rock
TRY rm $base.*.rock
TRY list_search $name $version
bin/luarocks remove $name $version
# TODO: differentiate between error and dependency block.
done
if bin/luarocks install nonexistant | grep "No results"
then echo "OK, got expected error."
else exit 1
fi
TRY ../test/test_deps.lua
TRY ../test/test_require.lua
luarocks-2.0.9/test/test_deps.lua 0000644 0001750 0000144 00000004204 11757524227 016225 0 ustar hisham users #!/usr/bin/env lua
deps = require "luarocks.deps"
print(deps.show_dep(deps.parse_dep("lfs 2.1.9pre5"), true))
print(deps.show_dep(deps.parse_dep("cgilua cvs-2"), true))
print(deps.show_dep(deps.parse_dep("foobar 0.0.1beta"), true))
print(deps.show_dep(deps.parse_dep("foobar 0.0.1a"), true))
print(deps.show_dep(deps.parse_dep("foobar 1"), true))
print(deps.show_dep(deps.parse_dep("foobar 2.0"), true))
print(deps.show_dep(deps.parse_dep("foobar 3.5a4"), true))
print(deps.show_dep(deps.parse_dep("foobar 1.1pre2"), true))
print(deps.show_dep(deps.parse_dep("foobar 2.0-beta3"), true))
print(deps.show_dep(deps.parse_dep("foobar 5.3"), true))
print(deps.show_dep(deps.parse_dep("foobar 3.5rc2"), true))
print(deps.show_dep(deps.parse_dep("foobar 4.19p"), true))
print()
comparisons = {
-- first second eq le
{"Vista", "XP", false, true},
{"XP", "3.1", false, true},
{"1.0", "1.0", true, false},
{"2.2.10", "2.2-10", false, false},
{"2.2", "2.2-10", true, false},
{"1.0beta1", "1.0rc3", false, true},
{"2.0beta3", "2.0", false, true},
{"2.0beta", "2.0beta2", false, true},
{"2.0beta4", "2.0beta3", false, false},
{"2.1alpha1", "2.0beta1", false, false},
{"1.5p3", "1.5.1", false, true},
{"1.1.3", "1.1.3a", false, true},
{"1.5a100", "1.5b1", false, true},
{"2.0alpha100", "2.0beta1", false, true},
{"2.0.0beta3", "2.0beta2", false, false},
{"2.0-1", "2.0-2", false, true},
{"2.0-2", "2.0-1", false, false},
--[[
-- Corner cases I don't wish to handle by now.
{"2.0.0beta2", "2.0beta2", true, true},
{"2.0.0beta2", "2.0beta3", false, true},
]]
}
local v1, v2
err = false
function result(test, expected)
if test == expected then
print(test, "OK")
else
print(test, "ERROR", deps.show_version(v1, true), deps.show_version(v2, true))
err = true
end
end
for _, c in ipairs(comparisons) do
v1, v2 = deps.parse_version(c[1]), deps.parse_version(c[2])
print(c[1].." == "..c[2].." ?")
result(v1 == v2, c[3])
print(c[1].." < "..c[2].." ?")
result(v1 < v2, c[4])
end
if err then os.exit(1) end
luarocks-2.0.9/config.ld 0000644 0001750 0000144 00000000217 11757524226 014336 0 ustar hisham users file = "src/luarocks"
project = "LuaRocks"
dir = "docs/ldoc"
description = [[
LuaRocks - a deployment and management system for Lua modules
]]
luarocks-2.0.9/configure 0000755 0001750 0000144 00000024320 11757524226 014460 0 ustar hisham users #!/bin/sh
# A basic configure script for LuaRocks.
# Not doing any fancy shell stuff here to keep good compatibility.
# Defaults
PREFIX="/usr/local"
SYSCONFDIR="$PREFIX/etc/luarocks"
ROCKS_TREE="$PREFIX"
LUA_SUFFIX=""
LUA_DIR="/usr"
LUA_BINDIR="/usr/bin"
LUA_INCDIR="/usr/include"
LUA_LIBDIR="/usr/lib"
LUA_VERSION="5.1"
# ----------------------------------------------------------------------------
# FUNCTION DEFINITIONS
# ----------------------------------------------------------------------------
# Help
show_help() {
cat </dev/null 2>/dev/null`
then
echo
echo '*WARNING*: the "~" sign is not expanded in flags.'
echo 'If you mean the home directory, use $HOME instead.'
echo
fi
case "$key" in
--help)
show_help
exit 0
;;
--prefix)
[ -n "$value" ] || die "Missing value in flag $key."
PREFIX="$value"
PREFIX_SET=yes
;;
--sysconfdir)
[ -n "$value" ] || die "Missing value in flag $key."
SYSCONFDIR="$value"
SYSCONFDIR_SET=yes
;;
--rocks-tree)
[ -n "$value" ] || die "Missing value in flag $key."
ROCKS_TREE="$value"
ROCKS_TREE_SET=yes
;;
--force-config)
FORCE_CONFIG=yes
;;
--lua-suffix)
[ -n "$value" ] || die "Missing value in flag $key."
LUA_SUFFIX="$value"
LUA_SUFFIX_SET=yes
;;
--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_SET=yes
;;
--with-lua)
[ -n "$value" ] || die "Missing value in flag $key."
LUA_DIR="$value"
LUA_DIR_SET=yes
;;
--with-lua-include)
[ -n "$value" ] || die "Missing value in flag $key."
LUA_INCDIR="$value"
LUA_INCDIR_SET=yes
;;
--with-lua-lib)
[ -n "$value" ] || die "Missing value in flag $key."
LUA_LIBDIR="$value"
LUA_LIBDIR_SET=yes
;;
--with-downloader)
[ -n "$value" ] || die "Missing value in flag $key."
case "$value" in
wget|curl) LUAROCKS_DOWNLOADER="$value" ;;
*) die "Invalid option: $value. See --help." ;;
esac
LUAROCKS_DOWNLOADER_SET=yes
;;
--with-md5-checker)
[ -n "$value" ] || die "Missing value in flag $key."
case "$value" in
md5sum|openssl|md5) LUAROCKS_MD5CHECKER="$value" ;;
*) die "Invalid option: $value. See --help." ;;
esac
LUAROCKS_MD5CHECKER_SET=yes
;;
*)
die "Error: Unknown flag: $1"
;;
esac
shift
done
if [ "$PREFIX_SET" = "yes" -a ! "$SYSCONFDIR_SET" = "yes" ]
then
if [ "$PREFIX" = "/usr" ]
then SYSCONFDIR=/etc/luarocks
else SYSCONFDIR=$PREFIX/etc/luarocks
fi
fi
if [ "$PREFIX_SET" = "yes" -a ! "$ROCKS_TREE_SET" = "yes" ]
then
ROCKS_TREE=$PREFIX
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" ]
then
echo "Lua version detected: $detected_lua"
if [ "$LUA_VERSION_SET" != "yes" ]
then
LUA_VERSION=$detected_lua
elif [ "$LUA_VERSION" != "$detected_lua" ]
then
die "This clashes with the value of --with-lua-version. Please check your configuration."
fi
fi
}
search_interpreter() {
LUA_SUFFIX="$1"
if [ "$LUA_DIR_SET" = "yes" ]
then
if [ -f "$LUA_DIR/bin/lua$suffix" ]
then
find_lua="$LUA_DIR/bin"
fi
else
find_lua=`find_program lua$suffix`
fi
if [ -n "$find_lua" ]
then
echo "Lua interpreter found: $find_lua/lua$suffix..."
detect_lua_version "$find_lua/lua$suffix"
return 0
fi
return 1
}
if [ "$LUA_SUFFIX_SET" != "yes" ]
then
if [ "$LUA_VERSION_SET" = "yes" -a "$LUA_VERSION" = "5.1" ]
then
suffixes="5.1 51"
elif [ "$LUA_VERSION_SET" = "yes" -a "$LUA_VERSION" = "5.2" ]
then
suffixes="5.2 52"
else
suffixes="5.2 52 5.1 51"
fi
for suffix in "" `echo $suffixes` ""
do
search_interpreter "$suffix" && break
done
fi
if [ "$LUA_VERSION" = "5.2" ]
then
echo "******************************"
echo "WARNING: Lua 5.2 support is still experimental."
echo "Bug reports, patches and pull requests are welcome"
echo "at the GitHub project:"
echo "http://github.com/keplerproject/luarocks"
echo "and the mailing list:"
echo "https://lists.sourceforge.net/lists/listinfo/luarocks-developers"
echo "******************************"
fi
if [ "$LUA_DIR_SET" != "yes" ]
then
echo_n "Looking for Lua... "
if [ ! -n "$find_lua" ]
then
find_lua=`find_program lua$LUA_SUFFIX`
fi
if [ -n "$find_lua" ]
then
LUA_DIR=`dirname $find_lua`
LUA_BINDIR="$find_lua"
echo "lua$LUA_SUFFIX found in \$PATH: $find_lua"
else
echo "lua$LUA_SUFFIX not found in \$PATH."
die "You may want to use the flags --with-lua and/or --lua-suffix. See --help."
fi
fi
if [ "$LUA_INCDIR_SET" != "yes" ]
then
LUA_INCDIR="$LUA_DIR/include"
fi
if [ "$LUA_LIBDIR_SET" != "yes" ]
then
LUA_LIBDIR="$LUA_DIR/lib"
fi
if [ "$LUA_DIR_SET" = "yes" ]
then
LUA_BINDIR="$LUA_DIR/bin"
fi
echo_n "Checking Lua includes... "
lua_h="$LUA_INCDIR/lua.h"
if [ -f "$lua_h" ]
then
echo "lua.h found in $lua_h"
else
LUA_INCDIR="$LUA_INCDIR/lua/$LUA_VERSION"
d_lua_h="$LUA_INCDIR/lua.h"
if [ -f "$d_lua_h" ]
then
echo "lua.h found in $d_lua_h (Debian/Ubuntu)"
else
echo "lua.h not found (looked in $lua_h)"
die "You may want to use the flag --with-lua-include. See --help."
fi
fi
if [ "$LUAROCKS_DOWNLOADER_SET" != "yes" ]
then
find_helper "downloader helper program" wget curl fetch
LUAROCKS_DOWNLOADER=$HELPER
fi
if [ "$LUAROCKS_MD5CHECKER_SET" != "yes" ]
then
find_helper "MD5 checksum calculator" md5sum openssl md5
LUAROCKS_MD5CHECKER=$HELPER
fi
echo_n "Configuring for system... "
if uname -s
then
LUAROCKS_UNAME_S=`uname -s`
else
die "Could not determine operating system. 'uname -s' failed."
fi
echo_n "Configuring for architecture... "
if uname -m
then
LUAROCKS_UNAME_M=`uname -m`
else
die "Could not determine processor architecture. 'uname -m' failed."
fi
if [ -f config.unix ]; then
rm -f config.unix
fi
# Write config
echo "Writing configuration..."
echo
rm -f built
cat < config.unix
# This file was automatically generated by the configure script.
# Run "./configure --help" for details.
LUA_VERSION=$LUA_VERSION
PREFIX=$PREFIX
SYSCONFDIR=$SYSCONFDIR
ROCKS_TREE=$ROCKS_TREE
LUA_SUFFIX=$LUA_SUFFIX
LUA_DIR=$LUA_DIR
LUA_INCDIR=$LUA_INCDIR
LUA_LIBDIR=$LUA_LIBDIR
LUA_BINDIR=$LUA_BINDIR
FORCE_CONFIG=$FORCE_CONFIG
LUAROCKS_UNAME_M=$LUAROCKS_UNAME_M
LUAROCKS_UNAME_S=$LUAROCKS_UNAME_S
LUAROCKS_DOWNLOADER=$LUAROCKS_DOWNLOADER
LUAROCKS_MD5CHECKER=$LUAROCKS_MD5CHECKER
EOF
echo "Installation prefix: $PREFIX"
echo "LuaRocks configuration directory: $SYSCONFDIR"
echo "Using Lua from: $LUA_DIR"
make clean > /dev/null 2> /dev/null
echo
echo "Done. You can now run 'make' to build."
echo
luarocks-2.0.9/rockspec 0000644 0001750 0000144 00000002043 11757524226 014303 0 ustar hisham users package = "LuaRocks"
local VER = "2.0.9"
local REV = "1"
version = VER.."-"..REV
description = {
summary = "A deployment and management system for Lua modules.",
detailed = [[
LuaRocks allows you to install Lua modules as self-contained
packages called "rocks", which also contain version dependency
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 that when a module is
required, the correct version is loaded. LuaRocks supports both
local and remote repositories, and multiple local rocks trees.
]],
license = "MIT/X11",
homepage = "http://www.luarocks.org",
maintainer = "Hisham Muhammad"
}
dependencies = {
"lua ~> 5.1"
}
source = {
url = "http://luarocks.org/releases/luarocks-"..VER..".tar.gz",
}
build = {
type = "make",
install_target = "install_rock",
build_pass=false,
install_variables = {
BINDIR="$(BINDIR)",
LUADIR="$(LUADIR)"
}
}
luarocks-2.0.9/COPYING_7z 0000644 0001750 0000144 00000003607 11757524226 014231 0 ustar hisham users 7-Zip
~~~~~
License for use and distribution
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7-Zip Copyright (C) 1999-2010 Igor Pavlov.
Licenses for files are:
1) 7z.dll: GNU LGPL + unRAR restriction
2) All other files: GNU LGPL
The GNU LGPL + unRAR restriction means that you must follow both
GNU LGPL rules and unRAR restriction rules.
Note:
You can use 7-Zip on any computer, including a computer in a commercial
organization. You don't need to register or pay for 7-Zip.
GNU LGPL information
--------------------
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You can receive a copy of the GNU Lesser General Public License from
http://www.gnu.org/
unRAR restriction
-----------------
The decompression engine for RAR archives was developed using source
code of unRAR program.
All copyrights to original unRAR code are owned by Alexander Roshal.
The license for original unRAR code has the following restriction:
The unRAR sources cannot be used to re-create the RAR compression algorithm,
which is proprietary. Distribution of modified unRAR sources in separate form
or as a part of other software is permitted, provided that it is clearly
stated in the documentation and source comments that the code may
not be used to develop a RAR (WinRAR) compatible archiver.
--
Igor Pavlov
luarocks-2.0.9/Makefile 0000644 0001750 0000144 00000012246 11757524226 014215 0 ustar hisham users # $Id: Makefile,v 1.30 2008/08/18 14:07:35 hisham Exp $
include config.unix
DESTDIR =
PREFIX ?= /usr/local
ROCKS_TREE ?= $(PREFIX)
SYSCONFDIR ?= $(PREFIX)/etc/luarocks
BINDIR ?= $(PREFIX)/bin
LUADIR ?= $(PREFIX)/share/lua/$(LUA_VERSION)/
LUA_DIR ?= /usr/local
LUA_BINDIR ?= $(LUA_DIR)/bin
BIN_FILES = luarocks luarocks-admin
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 rep.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 \
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 add.lua refresh_cache.lua loader.lua \
admin_remove.lua fetch/hg.lua fetch/git_file.lua new_version.lua
CONFIG_FILE = $(SYSCONFDIR)/config.lua
all: built
src/luarocks/site_config.lua: config.unix
rm -f src/luarocks/site_config.lua
echo 'module("luarocks.site_config")' >> src/luarocks/site_config.lua
if [ -n "$(PREFIX)" ] ;\
then \
echo "LUAROCKS_PREFIX=[[$(PREFIX)]]" >> src/luarocks/site_config.lua ;\
fi
if [ -n "$(LUA_INCDIR)" ] ;\
then \
echo "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 ;\
fi
if [ -n "$(LUA_BINDIR)" ] ;\
then \
echo "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 ;\
fi
if [ -n "$(SYSCONFDIR)" ] ;\
then \
echo "LUAROCKS_SYSCONFIG=[[$(SYSCONFDIR)/config.lua]]" >> src/luarocks/site_config.lua ;\
fi
if [ -n "$(ROCKS_TREE)" ] ;\
then \
echo "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 ;\
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
dev:
$(MAKE) build_bins LUADIR=$(PWD)/src
build_bins: cleanup_bins
for f in $(BIN_FILES) ;\
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 ;\
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
cd src && luadoc -d ../doc/luadoc --nofiles luarocks/*.lua
check_makefile:
echo $(BIN_FILES) | tr " " "\n" | sort > makefile_list.txt
( cd src/bin && ls -d * ) | grep -v "CVS" | sort > luarocks_dir.txt
echo $(LUAROCKS_FILES) | tr " " "\n" | sort >> makefile_list.txt
( cd src/luarocks && find * -name "*.lua" ) | sort >> luarocks_dir.txt
diff makefile_list.txt luarocks_dir.txt
rm -f makefile_list.txt luarocks_dir.txt
@echo
@echo "Makefile is sane."
@echo
cleanup_bins:
for f in $(BIN_FILES) ;\
do \
mv src/bin/$$f src/bin/$$f.bak ;\
sed "s,^#!.*lua.*,#!/usr/bin/env lua,;/^package.path/d" < src/bin/$$f.bak > src/bin/$$f ;\
chmod +x src/bin/$$f ;\
rm -f src/bin/$$f.bak ;\
done
clean: cleanup_bins
rm -f src/luarocks/site_config.lua
rm -f built
install_bins: built
mkdir -p "$(DESTDIR)$(BINDIR)"
cd src/bin && cp $(BIN_FILES) "$(DESTDIR)$(BINDIR)"
install_luas: built
mkdir -p "$(DESTDIR)$(LUADIR)/luarocks"
cd src/luarocks && for f in $(LUAROCKS_FILES); do d="$(DESTDIR)$(LUADIR)/luarocks"/`dirname "$$f"`; mkdir -p "$$d"; cp "$$f" "$$d"; done
install_site_config: built
mkdir -p "$(DESTDIR)$(LUADIR)/luarocks"
cd src/luarocks && cp site_config.lua "$(DESTDIR)$(LUADIR)/luarocks"
write_sysconfig: built
mkdir -p "$(DESTDIR)$(ROCKS_TREE)"
if [ ! -f "$(DESTDIR)$(CONFIG_FILE)" ] ;\
then \
mkdir -p `dirname "$(DESTDIR)$(CONFIG_FILE)"` ;\
echo 'rocks_servers = {' >> "$(DESTDIR)$(CONFIG_FILE)" ;\
echo ' [[http://luarocks.org/repositories/rocks]]' >> "$(DESTDIR)$(CONFIG_FILE)" ;\
echo '}' >> "$(DESTDIR)$(CONFIG_FILE)" ;\
echo 'rocks_trees = {' >> "$(DESTDIR)$(CONFIG_FILE)" ;\
if [ ! -n "$(FORCE_CONFIG)" ] ;\
then \
echo ' home..[[/.luarocks]],' >> "$(DESTDIR)$(CONFIG_FILE)" ;\
fi ;\
echo ' [[$(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
install_rock: install_bins install_luas
luarocks-2.0.9/README.md 0000644 0001750 0000144 00000002042 11757524226 014025 0 ustar hisham users This is LuaRocks, a deployment and management system for Lua modules.
Main website: [luarocks.org](http://www.luarocks.org)
LuaRocks 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 that when a module is required, the correct version is loaded. LuaRocks supports both local and
[remote][3] repositories, and multiple local rocks trees. You can [download][4] and install LuaRocks
on [Unix][5] and [Windows][6].
LuaRocks is free software and uses the same [license][7] as Lua 5.1.
[1]: http://luarocks.org/en/Types_of_rocks
[2]: http://luarocks.org/en/Dependencies
[3]: http://luarocks.org/en/Rocks_repositories
[4]: http://luarocks.org/en/Download
[5]: http://luarocks.org/en/Installation_instructions_for_Unix
[6]: http://luarocks.org/en/Installation_instructions_for_Windows
[7]: http://luarocks.org/en/License
luarocks-2.0.9/COPYING 0000644 0001750 0000144 00000004600 11757524226 013603 0 ustar hisham users 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.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
luarocks-2.0.9/src/ 0000755 0001750 0000144 00000000000 11757524226 013337 5 ustar hisham users luarocks-2.0.9/src/luarocks/ 0000755 0001750 0000144 00000000000 11757524227 015163 5 ustar hisham users luarocks-2.0.9/src/luarocks/unpack.lua 0000644 0001750 0000144 00000012542 11757524227 017153 0 ustar hisham users
--- Module implementing the LuaRocks "unpack" command.
-- Unpack the contents of a rock.
module("luarocks.unpack", package.seeall)
local fetch = require("luarocks.fetch")
local fs = require("luarocks.fs")
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 = "{| []}"
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.
]]
--- Load a rockspec file to the given directory, fetches the source
-- files specified in the rockspec, and unpack them inside the directory.
-- @param rockspec_file string: The URL for a rockspec file.
-- @param dir_name string: The directory where to store and unpack files.
-- @return table or (nil, string): the loaded rockspec table or
-- nil and an error message.
local function unpack_rockspec(rockspec_file, dir_name)
assert(type(rockspec_file) == "string")
assert(type(dir_name) == "string")
local rockspec, err = fetch.load_rockspec(rockspec_file)
if not rockspec then
return nil, "Failed loading rockspec "..rockspec_file..": "..err
end
fs.change_dir(dir_name)
local ok, sources_dir = fetch.fetch_sources(rockspec, true, ".")
if not ok then
return nil, sources_dir
end
fs.change_dir(dir_name)
build.apply_patches(rockspec)
fs.pop_dir()
return rockspec
end
--- Load a .rock file to the given directory and unpack it inside it.
-- @param rock_file string: The URL for a .rock file.
-- @param dir_name string: The directory where to unpack.
-- @param kind string: the kind of rock file, as in the second-level
-- extension in the rock filename (eg. "src", "all", "linux-x86")
-- @return table or (nil, string): the loaded rockspec table or
-- nil and an error message.
local function unpack_rock(rock_file, dir_name, kind)
assert(type(rock_file) == "string")
assert(type(dir_name) == "string")
local ok, err, errcode = fetch.fetch_and_unpack_rock(rock_file, dir_name)
if not ok then
return nil, "Failed unzipping rock "..rock_file, errcode
end
fs.change_dir(dir_name)
local rockspec_file = dir_name..".rockspec"
local rockspec, err = fetch.load_rockspec(rockspec_file)
if not rockspec then
return nil, "Failed loading rockspec "..rockspec_file..": "..err
end
if kind == "src" then
if rockspec.source.file then
local ok, err = fs.unpack_archive(rockspec.source.file)
if not ok then
return nil, err
end
fs.change_dir(rockspec.source.dir)
build.apply_patches(rockspec)
fs.pop_dir()
end
end
return rockspec
end
--- Create a directory and perform the necessary actions so that
-- the sources for the rock and its rockspec are unpacked inside it,
-- laid out properly so that the 'make' command is able to build the module.
-- @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)
assert(type(file) == "string")
local base_name = dir.base_name(file)
local dir_name, kind, extension = base_name:match("(.*)%.([^.]+)%.(rock)$")
if not extension then
dir_name, extension = base_name:match("(.*)%.(rockspec)$")
kind = "rockspec"
end
if not extension then
return nil, file.." does not seem to be a valid filename."
end
if (fs.exists(dir_name)) then
return nil, "Directory "..dir_name.." already exists."
end
fs.make_dir(dir_name)
local rollback = util.schedule_function(fs.delete, fs.absolute_name(dir_name))
local rockspec, err
if extension == "rock" then
rockspec, err = unpack_rock(file, dir_name, kind)
elseif extension == "rockspec" then
rockspec, err = unpack_rockspec(file, dir_name)
end
if not rockspec then
return nil, err
end
if kind == "src" or kind == "rockspec" then
if rockspec.source.dir ~= "." then
local ok = fs.copy(rockspec.local_filename, rockspec.source.dir)
if not ok then
return nil, "Failed copying unpacked rockspec into unpacked source directory."
end
end
util.printout()
util.printout("Done. You may now enter directory ")
util.printout(dir.path(dir_name, rockspec.source.dir))
util.printout("and type 'luarocks make' to build.")
end
util.remove_scheduled_function(rollback)
return true
end
--- Driver function for the "unpack" command.
-- @param name string: may be a rock filename, for unpacking a
-- rock file or the name of a rock to be fetched and unpacked.
-- @param version string or nil: if the name of a package is given, a
-- version may also be passed.
-- @return boolean or (nil, string): true if successful or nil followed
-- by an error message.
function run(...)
local flags, name, version = util.parse_flags(...)
assert(type(version) == "string" or not version)
if type(name) ~= "string" then
return nil, "Argument missing, see help."
end
if name:match(".*%.rock") or name:match(".*%.rockspec") then
return run_unpacker(name)
else
local search = require("luarocks.search")
return search.act_on_src_or_rockspec(run_unpacker, name, version)
end
end
luarocks-2.0.9/src/luarocks/loader.lua 0000644 0001750 0000144 00000021143 11757524227 017135 0 ustar hisham users
--- A module which installs a Lua package loader that is LuaRocks-aware.
-- This loader uses dependency information from the LuaRocks tree to load
-- correct versions of modules. It does this by constructing a "context"
-- 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
module("luarocks.loader")
local path = require("luarocks.path")
local manif_core = require("luarocks.manif_core")
local deps = require("luarocks.deps")
local cfg = require("luarocks.cfg")
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
local function load_rocks_trees()
local any_ok = false
local trees = {}
for _, tree in pairs(cfg.rocks_trees) do
local manifest, err = manif_core.load_local_manifest(path.rocks_dir(tree))
if manifest then
any_ok = true
table.insert(trees, {tree=tree, manifest=manifest})
end
end
if not any_ok then
rocks_trees = false
return false
end
rocks_trees = trees
return true
end
--- Process the dependencies of a package to determine its dependency
-- 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)
-- assert(type(name) == "string")
-- assert(type(version) == "string")
if context[name] then
return
end
context[name] = version
if not rocks_trees and not load_rocks_trees() then
return nil
end
local providers = {}
for _, tree in pairs(rocks_trees) do
local manifest = tree.manifest
local pkgdeps
if manifest.dependencies and manifest.dependencies[name] then
pkgdeps = manifest.dependencies[name][version]
end
if not pkgdeps then
return nil
end
for _, dep in ipairs(pkgdeps) do
local pkg, constraints = dep.name, dep.constraints
for _, tree in pairs(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)
end
end
end
end
end
end
end
--- Internal sorting function.
-- @param a table: A provider table.
-- @param b table: Another provider table.
-- @return boolean: True if the version of a is greater than that of b.
local function sort_versions(a,b)
return a.version > b.version
end
--- Request module to be loaded through other loaders,
-- once the proper name of the module has been determined.
-- For example, in case the module "socket.core" has been requested
-- to the LuaRocks loader and it determined based on context that
-- the version 2.0.2 needs to be loaded and it is not the current
-- version, the module requested for the other loaders will be
-- "socket.core_2_0_2".
-- @param module The module name requested by the user, such as "socket.core"
-- @param name The rock name, such as "luasocket"
-- @param version The rock version, such as "2.0.2-1"
-- @param module_name The actual module name, such as "socket.core" or "socket.core_2_0_2".
-- @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) }
if type(results[1]) == "function" then
return unpack(results)
end
end
end
return nil, "Failed loading module "..module.." in LuaRocks rock "..name.." "..version
end
--- Search for a module in the rocks trees
-- @param module string: module name (eg. "socket.core")
-- @param filter_module_name function(string, string, string, string, number):
-- a function that takes the module name (eg "socket.core"), the rock name
-- (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).
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
return nil
end
local providers = {}
for _, tree in pairs(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)..")")
end
module_name = filter_module_name(module_name, name, version, tree.tree, i)
if 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})
end
end
end
if next(providers) then
table.sort(providers, sort_versions)
local first = providers[1]
return first.name, first.version.string, first.module_name
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).
local function pick_module(module)
return
select_module(module, function(module_name, name, version, tree, i)
if i > 1 then
module_name = path.versioned_name(module_name, "", name, version)
end
module_name = path.path_to_module(module_name)
return module_name
end)
end
--- Return the pathname of the file that would be loaded 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"),
-- filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so")
function which(module)
local name, version, module_name =
select_module(module, function(module_name, name, version, tree, i)
local deploy_dir
if module_name:match("%.lua$") then
deploy_dir = path.deploy_lua_dir(tree)
module_name = deploy_dir.."/"..module_name
else
deploy_dir = path.deploy_lib_dir(tree)
module_name = deploy_dir.."/"..module_name
end
if i > 1 then
module_name = path.versioned_name(module_name, deploy_dir, name, version)
end
return module_name
end)
return module_name
end
--- Package loader for LuaRocks support.
-- A module is searched in installed rocks that match the
-- current LuaRocks context. If module is not part of the
-- context, or if a context has not yet been set, the module
-- in the package with the highest version is used.
-- @param module string: The module name, like in plain require().
-- @return table: The module table (typically), like in plain
-- require(). See require()
-- in the Lua reference manual for details.
function luarocks_loader(module)
local name, version, module_name = pick_module(module)
if not name then
return nil, "No LuaRocks module found for "..module
else
add_context(name, version)
return call_other_loaders(module, name, version, module_name)
end
end
table.insert(global_env.package.loaders, 1, luarocks_loader)
luarocks-2.0.9/src/luarocks/download.lua 0000644 0001750 0000144 00000005732 11757524226 017503 0 ustar hisham users
--- Module implementing the luarocks "download" command.
-- Download a rock from the repository.
module("luarocks.download", package.seeall)
local util = require("luarocks.util")
local path = require("luarocks.path")
local fetch = require("luarocks.fetch")
local search = require("luarocks.search")
help_summary = "Download a specific rock file from a rocks server."
help_arguments = "[--all] [--arch= | --source | --rockspec] [ []]"
help = [[
--all Download all files if there are multiple matches.
--source Download .src.rock if available.
--rockspec Download .rockspec if available.
--arch= Download rock for a specific architecture.
]]
function download(arch, name, version, all)
local results, err
local query = search.make_query(name, version)
if arch then query.arch = arch end
if all then
if name == "" then query.exact_name = false end
results, err = search.search_repos(query)
else
results, err = search.find_suitable_rock(query)
end
if type(results) == "string" then
local file = fetch.fetch_url(results)
return file
elseif type(results) == "table" and next(results) then
if all then
local all_ok = true
local any_err = ""
for name, result in pairs(results) do
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)
if not ok then
all_ok = false
any_err = any_err .. "\n" .. err
end
end
end
end
return all_ok, any_err
else
util.printerr("Multiple search results were returned.")
util.printout()
util.printout("Search results:")
util.printout("---------------")
search.print_results(results)
return nil, "Please narrow your query or use --all."
end
end
return nil, "Could not find a result named "..name..(version and " "..version or "").."."
end
--- Driver function for the "download" command.
-- @param name string: a rock name.
-- @param version string or nil: if the name of a package is given, a
-- version may also be passed.
-- @return boolean or (nil, string): true if successful or nil followed
-- by an error message.
function run(...)
local flags, name, version = util.parse_flags(...)
assert(type(version) == "string" or not version)
if type(name) ~= "string" and not flags["all"] then
return nil, "Argument missing, see help."
end
if not name then name, version = "", "" end
local arch
if flags["source"] then
arch = "src"
elseif flags["rockspec"] then
arch = "rockspec"
elseif flags["arch"] then
arch = flags["arch"]
end
local dl, err = download(arch, name, version, flags["all"])
return dl and true, err
end
luarocks-2.0.9/src/luarocks/fetch.lua 0000644 0001750 0000144 00000030427 11757524226 016764 0 ustar hisham users
--- Functions related to fetching and loading local and remote files.
module("luarocks.fetch", package.seeall)
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local type_check = require("luarocks.type_check")
local path = require("luarocks.path")
local deps = require("luarocks.deps")
local persist = require("luarocks.persist")
local util = require("luarocks.util")
local cfg = require("luarocks.cfg")
--- 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.
-- If a local pathname is given, it is returned as a result.
-- @param url string: a local pathname or a remote URL.
-- @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 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)
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)
if not ok then
return nil, "Failed downloading "..url..(err and " - "..err or ""), "network"
end
return dir.path(fs.current_dir(), filename or dir.base_name(url))
else
return nil, "Unsupported protocol "..protocol
end
end
--- For remote URLs, create a temporary directory and download URL inside it.
-- This temporary directory will be deleted on program termination.
-- For local URLs, just return the local pathname and its directory.
-- @param url string: URL to be downloaded
-- @param tmpname string: name pattern to use for avoiding conflicts
-- when creating temporary directory.
-- @param filename string or nil: local filename of URL to be downloaded,
-- in case it can't be inferred from the URL.
-- @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)
assert(type(url) == "string")
assert(type(tmpname) == "string")
assert(type(filename) == "string" or not filename)
filename = filename or dir.base_name(url)
local protocol, pathname = dir.split_url(url)
if protocol == "file" then
if fs.exists(pathname) then
return pathname, dir.dir_name(fs.absolute_name(pathname))
else
return nil, "File not found: "..pathname
end
else
local temp_dir = fs.make_temp_dir(tmpname)
if not temp_dir then
return nil, "Failed creating temporary directory."
end
util.schedule_function(fs.delete, temp_dir)
fs.change_dir(temp_dir)
local file, err, errcode = fetch_url(url, filename)
fs.pop_dir()
if not file then
return nil, "Error fetching file: "..err, errcode
end
return file, temp_dir
end
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.
-- @param rock_file string: URL or filename of the rock.
-- @param dest string or nil: if given, directory will be used as
-- 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)
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)
if not rock_file then
return nil, "Could not fetch rock file: " .. err, errcode
end
rock_file = fs.absolute_name(rock_file)
local unpack_dir
if dest then
unpack_dir = dest
fs.make_dir(unpack_dir)
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)
if not ok then
return nil, "Failed unpacking rock file: " .. rock_file
end
fs.pop_dir()
return unpack_dir
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.
-- @return table or (nil, string): A table representing the rockspec
-- or nil followed by an error message.
function load_local_rockspec(filename)
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
local ok, err = type_check.type_check_rockspec(rockspec)
if not ok then
return nil, filename..": "..err
end
if rockspec.rockspec_format then
if deps.compare_versions(rockspec.rockspec_format, type_check.rockspec_format) then
return nil, "Rockspec format "..rockspec.rockspec_format.." is not supported, please upgrade LuaRocks."
end
end
util.platform_overrides(rockspec.build)
util.platform_overrides(rockspec.dependencies)
util.platform_overrides(rockspec.external_dependencies)
util.platform_overrides(rockspec.source)
util.platform_overrides(rockspec.hooks)
local basename = dir.base_name(filename)
if basename == "rockspec" then
rockspec.name = rockspec.package:lower()
else
rockspec.name = basename:match("(.*)-[^-]*-[0-9]*")
if not rockspec.name then
return nil, "Expected filename in format 'name-version-revision.rockspec'."
end
end
local protocol, pathname = dir.split_url(rockspec.source.url)
if protocol == "http" or protocol == "https" or protocol == "ftp" or protocol == "file" then
rockspec.source.file = rockspec.source.file or dir.base_name(rockspec.source.url)
end
rockspec.source.protocol, rockspec.source.pathname = protocol, pathname
-- Temporary compatibility
if rockspec.source.cvs_module then rockspec.source.module = rockspec.source.cvs_module end
if rockspec.source.cvs_tag then rockspec.source.tag = rockspec.source.cvs_tag end
local name_version = rockspec.package:lower() .. "-" .. rockspec.version
if basename ~= "rockspec" and basename ~= name_version .. ".rockspec" then
return nil, "Inconsistency between rockspec filename ("..basename..") and its contents ("..name_version..".rockspec)."
end
rockspec.local_filename = filename
local filebase = rockspec.source.file or rockspec.source.url
local base = dir.base_name(filebase)
base = base:gsub("%.[^.]*$", ""):gsub("%.tar$", "")
rockspec.source.dir = rockspec.source.dir
or rockspec.source.module
or ((filebase:match(".lua$") or filebase:match(".c$")) and ".")
or base
if rockspec.dependencies then
for i = 1, #rockspec.dependencies do
local parsed = deps.parse_dep(rockspec.dependencies[i])
if not parsed then
return nil, "Parse error processing dependency '"..rockspec.dependencies[i].."'"
end
rockspec.dependencies[i] = parsed
end
else
rockspec.dependencies = {}
end
local ok, err = path.configure_paths(rockspec)
if err then
return nil, "Error verifying paths: "..err
end
return rockspec
end
--- Load a local or remote rockspec into a table.
-- This is the entry point for the LuaRocks tools.
-- Only the LuaRocks runtime loader should use
-- load_local_rockspec directly.
-- @param filename string: Local or remote filename of a rockspec.
-- @param location string or nil: Where to download. If not given,
-- 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)
assert(type(filename) == "string")
local name
local basename = dir.base_name(filename)
if basename == "rockspec" then
name = "rockspec"
else
name = basename:match("(.*)%.rockspec")
if not name and not basename == "rockspec" 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)
fs.pop_dir()
else
filename, err, errcode = fetch_url_at_temp_dir(filename,"luarocks-rockspec-"..name)
end
if not filename then
return nil, err, errcode
end
return 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.
-- @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)
assert(type(rockspec) == "table")
assert(type(extract) == "boolean")
assert(type(dest_dir) == "string" or not dest_dir)
local url = rockspec.source.url
local name = rockspec.name.."-"..rockspec.version
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)
fs.pop_dir()
store_dir = dest_dir
else
source_file, store_dir, errcode = 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."
end
end
if extract then
fs.change_dir(store_dir)
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
end
fs.pop_dir()
end
return source_file, store_dir
end
--- Download sources for building a rock, calling the appropriate protocol method.
-- @param rockspec table: The rockspec table
-- @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.
-- @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)
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
proto = require("luarocks.fetch")
else
ok, proto = pcall(require, "luarocks.fetch."..protocol:gsub("[+-]", "_"))
if not ok then
return nil, "Unknown protocol "..protocol
end
end
if cfg.only_sources_from
and rockspec.source.pathname
and #rockspec.source.pathname > 0 then
if #cfg.only_sources_from == 0 then
return nil, "Can't download "..rockspec.source.url.." -- download from remote servers disabled"
elseif rockspec.source.pathname:find(cfg.only_sources_from, 1, true) ~= 1 then
return nil, "Can't download "..rockspec.source.url.." -- only downloading from "..cfg.only_sources_from
end
end
return proto.get_sources(rockspec, extract, dest_dir)
end
luarocks-2.0.9/src/luarocks/rep.lua 0000644 0001750 0000144 00000025463 11757524227 016466 0 ustar hisham users
--- Functions for managing the repository on disk.
module("luarocks.rep", package.seeall)
local fs = require("luarocks.fs")
local path = require("luarocks.path")
local cfg = require("luarocks.cfg")
local util = require("luarocks.util")
local dir = require("luarocks.dir")
local manif = require("luarocks.manif")
local deps = require("luarocks.deps")
--- Get all installed versions of a package.
-- @param name string: a package name.
-- @return table or nil: An array of strings listing installed
-- versions of a package, or nil if none is available.
function get_versions(name)
assert(type(name) == "string")
local dirs = fs.list_dir(path.versions_dir(name))
return (dirs and #dirs > 0) and dirs or nil
end
--- Check if a package exists in a local repository.
-- Version numbers are compared as exact string comparison.
-- @param name string: name of package
-- @param version string: package version in string format
-- @return boolean: true if a package is installed,
-- false otherwise.
function is_installed(name, version)
assert(type(name) == "string")
assert(type(version) == "string")
return fs.is_dir(path.install_dir(name, version))
end
local function recurse_rock_manifest_tree(file_tree, action)
assert(type(file_tree) == "table")
assert(type(action) == "function")
local function do_recurse_rock_manifest_tree(tree, parent_path, parent_module)
for file, sub in pairs(tree) do
if type(sub) == "table" then
local ok, err = do_recurse_rock_manifest_tree(sub, parent_path..file.."/", parent_module..file..".")
if not ok then return nil, err end
else
local ok, err = action(parent_path, parent_module, file)
if not ok then return nil, err end
end
end
return true
end
return do_recurse_rock_manifest_tree(file_tree, "", "")
end
local function store_package_data(result, name, sub, prefix)
assert(type(result) == "table")
assert(type(name) == "string")
assert(type(sub) == "table" or type(sub) == "string")
assert(type(prefix) == "string")
if type(sub) == "table" then
for sname, ssub in pairs(sub) do
store_package_data(result, sname, ssub, prefix..name.."/")
end
elseif type(sub) == "string" then
local pathname = prefix..name
result[path.path_to_module(pathname)] = pathname
end
end
local function store_package_data(result, name, file_tree)
if not file_tree then return end
return recurse_rock_manifest_tree(file_tree,
function(parent_path, parent_module, file)
local pathname = parent_path..file
result[path.path_to_module(pathname)] = pathname
return true
end
)
end
--- Obtain a list of modules within an installed package.
-- @param package string: The package name; for example "luasocket"
-- @param version string: The exact version number including revision;
-- for example "2.0.1-1".
-- @return table: A table of modules where keys are module identifiers
-- 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)
assert(type(package) == "string")
assert(type(version) == "string")
local result = {}
local rock_manifest = manif.load_rock_manifest(package, version)
store_package_data(result, package, rock_manifest.lib)
store_package_data(result, package, rock_manifest.lua)
return result
end
--- Obtain a list of command-line scripts within an installed package.
-- @param package string: The package name; for example "luasocket"
-- @param version string: The exact version number including revision;
-- for example "2.0.1-1".
-- @return table: A table of items where keys are command names
-- 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)
assert(type(package) == "string")
assert(type(version) == "string")
local result = {}
local rock_manifest = manif.load_rock_manifest(package, version)
store_package_data(result, package, rock_manifest.bin)
return result
end
--- Check if a rock contains binary executables.
-- @param name string: name of an installed rock
-- @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)
assert(type(name) == "string")
assert(type(version) == "string")
local rock_manifest = manif.load_rock_manifest(name, version)
if rock_manifest.bin then
for name, md5 in pairs(rock_manifest.bin) do
-- TODO verify that it is the same file. If it isn't, find the actual command.
if fs.is_actual_binary(dir.path(cfg.deploy_bin_dir, name)) then
return true
end
end
end
return false
end
function run_hook(rockspec, hook_name)
assert(type(rockspec) == "table")
assert(type(hook_name) == "string")
local hooks = rockspec.hooks
if not hooks then
return true
end
if not hooks.substituted_variables then
util.variable_substitutions(hooks, rockspec.variables)
hooks.substituted_variables = true
end
local hook = hooks[hook_name]
if hook then
util.printout(hook)
if not fs.execute(hook) then
return nil, "Failed running "..hook_name.." hook."
end
end
return true
end
local function install_binary(source, target)
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)
else
ok, err = fs.copy_binary(source, target)
end
if file then file:close() end
return ok, err
end
local function resolve_conflict(target, deploy_dir, name, version)
local cname, cversion = manif.find_current_provider(target)
if not cname then
return nil, cversion
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))
fs.move(target, versioned)
return target
else
return path.versioned_name(target, deploy_dir, name, version)
end
end
function should_wrap_bin_scripts(rockspec)
assert(type(rockspec) == "table")
if cfg.wrap_bin_scripts ~= nil then
return cfg.wrap_bin_scripts
end
if rockspec.deploy and rockspec.deploy.wrap_bin_scripts == false then
return false
end
return true
end
function deploy_files(name, version, wrap_bin_scripts)
assert(type(name) == "string")
assert(type(version) == "string")
assert(type(wrap_bin_scripts) == "boolean")
local function deploy_file_tree(file_tree, source_dir, deploy_dir, move_fn)
if not move_fn then
move_fn = fs.move
end
return recurse_rock_manifest_tree(file_tree,
function(parent_path, parent_module, file)
local source = dir.path(source_dir, parent_path, file)
local target = dir.path(deploy_dir, parent_path, file)
local ok, err
if fs.exists(target) then
local new_target, err = resolve_conflict(target, deploy_dir, name, version)
if err == "untracked" then
fs.delete(target)
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 = move_fn(source, target)
fs.remove_dir_tree_if_empty(dir.dir_name(source))
if not ok then return nil, err end
return true
end
)
end
local rock_manifest = manif.load_rock_manifest(name, version)
local ok, err = true
if rock_manifest.bin then
local move_bin_fn = wrap_bin_scripts and install_binary or fs.copy_binary
ok, err = deploy_file_tree(rock_manifest.bin, path.bin_dir(name, version), cfg.deploy_bin_dir, move_bin_fn)
end
if ok and rock_manifest.lua then
ok, err = deploy_file_tree(rock_manifest.lua, path.lua_dir(name, version), cfg.deploy_lua_dir)
end
if ok and rock_manifest.lib then
ok, err = deploy_file_tree(rock_manifest.lib, path.lib_dir(name, version), cfg.deploy_lib_dir)
end
return ok, err
end
--- Delete a package from the local repository.
-- Version numbers are compared as exact string comparison.
-- @param name string: name of package
-- @param version string: package version in string format
function delete_version(name, version)
assert(type(name) == "string")
assert(type(version) == "string")
local function delete_deployed_file_tree(file_tree, deploy_dir)
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)
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)
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
fs.remove_dir_tree_if_empty(dir.dir_name(target))
if not ok then return nil, "Failed deleting "..target end
end
return true
end
)
end
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
local ok, err = true
if rock_manifest.bin then
ok, err = delete_deployed_file_tree(rock_manifest.bin, cfg.deploy_bin_dir)
end
if ok and rock_manifest.lua then
ok, err = delete_deployed_file_tree(rock_manifest.lua, cfg.deploy_lua_dir)
end
if ok and rock_manifest.lib then
ok, err = delete_deployed_file_tree(rock_manifest.lib, cfg.deploy_lib_dir)
end
if err then return nil, err end
fs.delete(path.install_dir(name, version))
if not get_versions(name) then
fs.delete(dir.path(cfg.rocks_dir, name))
end
return true
end
luarocks-2.0.9/src/luarocks/list.lua 0000644 0001750 0000144 00000002147 11757524227 016645 0 ustar hisham users
--- Module implementing the LuaRocks "list" command.
-- Lists currently installed rocks.
module("luarocks.list", package.seeall)
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 = [[
is a substring of a rock name to filter by.
]]
--- Driver function for "list" command.
-- @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(...)
local flags, filter, version = util.parse_flags(...)
local results = {}
local query = search.make_query(filter and filter:lower() or "", version)
query.exact_name = false
for _, tree in ipairs(cfg.rocks_trees) do
search.manifest_search(results, path.rocks_dir(tree), query)
end
util.printout()
util.printout("Installed rocks:")
util.printout("----------------")
util.printout()
search.print_results(results, false)
return true
end
luarocks-2.0.9/src/luarocks/fetch/ 0000755 0001750 0000144 00000000000 11757524226 016253 5 ustar hisham users luarocks-2.0.9/src/luarocks/fetch/git_file.lua 0000644 0001750 0000144 00000001434 11757524226 020542 0 ustar hisham users
--- Fetch back-end for retrieving sources from local Git repositories.
module("luarocks.fetch.git_file", package.seeall)
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 get_sources(rockspec, extract, dest_dir)
rockspec.source.url = rockspec.source.url:gsub("^git.file://", "")
return git.get_sources(rockspec, extract, dest_dir)
end
luarocks-2.0.9/src/luarocks/fetch/svn.lua 0000644 0001750 0000144 00000003234 11757524226 017566 0 ustar hisham users
--- Fetch back-end for retrieving sources from Subversion.
module("luarocks.fetch.svn", package.seeall)
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local util = require("luarocks.util")
--- Download sources for building a rock, using Subversion.
-- @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 get_sources(rockspec, extract, dest_dir)
assert(type(rockspec) == "table")
assert(type(dest_dir) == "string" or not dest_dir)
local svn_cmd = rockspec.variables.SVN
local name_version = rockspec.name .. "-" .. rockspec.version
local module = rockspec.source.module or dir.base_name(rockspec.source.url)
local url = rockspec.source.url:gsub("^svn://", "")
local command = {svn_cmd, "checkout", url, module}
if rockspec.source.tag then
table.insert(command, 5, "-r")
table.insert(command, 6, rockspec.source.tag)
end
local store_dir
if not dest_dir then
store_dir = fs.make_temp_dir(name_version)
if not store_dir then
return nil, "Failed creating temporary directory."
end
util.schedule_function(fs.delete, store_dir)
else
store_dir = dest_dir
end
fs.change_dir(store_dir)
if not fs.execute(unpack(command)) then
return nil, "Failed fetching files from Subversion."
end
fs.pop_dir()
return module, store_dir
end
luarocks-2.0.9/src/luarocks/fetch/cvs.lua 0000644 0001750 0000144 00000003116 11757524226 017552 0 ustar hisham users
--- Fetch back-end for retrieving sources from CVS.
module("luarocks.fetch.cvs", package.seeall)
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local util = require("luarocks.util")
--- Download sources for building a rock, using CVS.
-- @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 get_sources(rockspec, extract, dest_dir)
assert(type(rockspec) == "table")
assert(type(dest_dir) == "string" or not dest_dir)
local name_version = rockspec.name .. "-" .. rockspec.version
local module = rockspec.source.module or dir.base_name(rockspec.source.url)
local command = {rockspec.variables.CVS, "-d"..rockspec.source.pathname, "export", module}
if rockspec.source.tag then
table.insert(command, 4, "-r")
table.insert(command, 5, rockspec.source.tag)
end
local store_dir
if not dest_dir then
store_dir = fs.make_temp_dir(name_version)
if not store_dir then
return nil, "Failed creating temporary directory."
end
util.schedule_function(fs.delete, store_dir)
else
store_dir = dest_dir
end
fs.change_dir(store_dir)
if not fs.execute(unpack(command)) then
return nil, "Failed fetching files from CVS."
end
fs.pop_dir()
return module, store_dir
end
luarocks-2.0.9/src/luarocks/fetch/sscm.lua 0000644 0001750 0000144 00000003474 11757524226 017733 0 ustar hisham users
--- Fetch back-end for retrieving sources from Surround SCM Server
module("luarocks.fetch.sscm", package.seeall)
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
--- Download sources via Surround SCM Server for building a rock.
-- @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 get_sources(rockspec, extract, dest_dir)
assert(type(rockspec) == "table")
assert(type(dest_dir) == "string" or not dest_dir)
local sscm_cmd = rockspec.variables.SSCM
local module = rockspec.source.module or dir.base_name(rockspec.source.url)
local branch, repository = string.match(rockspec.source.pathname, "^([^/]*)/(.*)")
if not branch or not repository then
return nil, "Error retrieving branch and repository from rockspec."
end
-- Search for working directory.
local working_dir
local tmp = io.popen(string.format(sscm_cmd..[[ property "/" -d -b%s -p%s]], branch, repository))
for line in tmp:lines() do
--%c because a chr(13) comes in the end.
working_dir = string.match(line, "Working directory:[%s]*(.*)%c$")
if working_dir then break end
end
tmp:close()
if not working_dir then
return nil, "Error retrieving working directory from SSCM."
end
if not fs.execute(sscm_cmd, "get", "*", "-e" , "-r", "-b"..branch, "-p"..repository, "-tmodify", "-wreplace") then
return nil, "Failed fetching files from SSCM."
end
-- FIXME: This function does not honor the dest_dir parameter.
return module, working_dir
end
luarocks-2.0.9/src/luarocks/fetch/git.lua 0000644 0001750 0000144 00000003607 11757524226 017547 0 ustar hisham users
--- Fetch back-end for retrieving sources from GIT.
module("luarocks.fetch.git", package.seeall)
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local util = require("luarocks.util")
--- Download sources for building a rock, using git.
-- @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 get_sources(rockspec, extract, dest_dir)
assert(type(rockspec) == "table")
assert(type(dest_dir) == "string" or not dest_dir)
local git_cmd = rockspec.variables.GIT
local name_version = rockspec.name .. "-" .. rockspec.version
local module = dir.base_name(rockspec.source.url)
-- Strip off .git from base name if present
module = module:gsub("%.git$", "")
local command = {git_cmd, "clone", "--depth=1", rockspec.source.url, module}
local tag_or_branch = rockspec.source.tag or rockspec.source.branch
if tag_or_branch then
table.insert(command, 4, "--branch=" .. tag_or_branch)
end
local store_dir
if not dest_dir then
store_dir = fs.make_temp_dir(name_version)
if not store_dir then
return nil, "Failed creating temporary directory."
end
util.schedule_function(fs.delete, store_dir)
else
store_dir = dest_dir
end
store_dir = fs.absolute_name(store_dir)
fs.change_dir(store_dir)
if not fs.execute(unpack(command)) then
return nil, "Failed cloning git repository."
end
fs.change_dir(module)
fs.delete(dir.path(store_dir, module, ".git"))
fs.delete(dir.path(store_dir, module, ".gitignore"))
fs.pop_dir()
fs.pop_dir()
return module, store_dir
end
luarocks-2.0.9/src/luarocks/fetch/hg.lua 0000644 0001750 0000144 00000003462 11757524226 017361 0 ustar hisham users
--- Fetch back-end for retrieving sources from HG.
module("luarocks.fetch.hg", package.seeall)
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local util = require("luarocks.util")
--- Download sources for building a rock, using hg.
-- @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 get_sources(rockspec, extract, dest_dir)
assert(type(rockspec) == "table")
assert(type(dest_dir) == "string" or not dest_dir)
local hg_cmd = rockspec.variables.HG
local name_version = rockspec.name .. "-" .. rockspec.version
-- Strip off special hg:// protocol type
local url = rockspec.source.url:gsub("^hg://", "")
local module = dir.base_name(url)
local command = {hg_cmd, "clone", url, module}
local tag_or_branch = rockspec.source.tag or rockspec.source.branch
if tag_or_branch then
command = {hg_cmd, "clone", "--rev", url, module}
end
local store_dir
if not dest_dir then
store_dir = fs.make_temp_dir(name_version)
if not store_dir then
return nil, "Failed creating temporary directory."
end
util.schedule_function(fs.delete, store_dir)
else
store_dir = dest_dir
end
fs.change_dir(store_dir)
if not fs.execute(unpack(command)) then
return nil, "Failed cloning hg repository."
end
fs.change_dir(module)
fs.delete(dir.path(store_dir, module, ".hg"))
fs.delete(dir.path(store_dir, module, ".hgignore"))
fs.pop_dir()
fs.pop_dir()
return module, store_dir
end
luarocks-2.0.9/src/luarocks/dir.lua 0000644 0001750 0000144 00000004124 11757524226 016444 0 ustar hisham users
--- Generic utilities for handling pathnames.
module("luarocks.dir", package.seeall)
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)
assert(type(pathname) == "string")
local base = pathname:gsub("[/\\]*$", ""):match(".*[/\\]([^/\\]*)")
return base or pathname
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
-- no directory separators in input, "" is returned.
function dir_name(pathname)
assert(type(pathname) == "string")
return (pathname:gsub("/*$", ""):match("(.*/)[^/]*")) or ""
end
function strip_base_dir(pathname)
return pathname:gsub("^[^/]*/", "")
end
--- Describe a path in a cross-platform way.
-- Use this function to avoid platform-specific directory
-- separators in other modules. If the first item contains a
-- protocol descriptor (e.g. "http:"), paths are always constituted
-- with forward slashes.
-- @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("/*$", "")
if items[i] == "" then
table.remove(items, i)
else
i = i + 1
end
end
return table.concat(items, "/")
end
--- Split protocol and path from an URL or local pathname.
-- URLs should be in the "protocol://path" format.
-- 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)
assert(type(url) == "string")
local protocol, pathname = url:match("^([^:]*)://(.*)")
if not protocol then
protocol = "file"
pathname = url
end
return protocol, pathname
end
luarocks-2.0.9/src/luarocks/help.lua 0000644 0001750 0000144 00000007260 11757524227 016623 0 ustar hisham users
--- Module implementing the LuaRocks "help" command.
-- This is a generic help display module, which
-- 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)
local util = require("luarocks.util")
local cfg = require("luarocks.cfg")
help_summary = "Help on commands. Type '"..program_name.." help ' for more."
help_arguments = "[]"
help = [[
is the command to show help for.
]]
local function print_banner()
util.printout("\nLuaRocks "..cfg.program_version..", a module deployment system for Lua")
end
local function print_section(section)
util.printout("\n"..section)
end
local function get_status(status)
if status then
return "ok"
elseif status == false then
return "not found"
else
return "failed"
end
end
--- Driver function for the "help" command.
-- @param command string or nil: command to show help for; if not
-- 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(...)
local flags, command = util.parse_flags(...)
if not command then
local sys_file, sys_ok, home_file, home_ok = cfg.which_config()
print_banner()
print_section("NAME")
util.printout("\t"..program_name..[[ - ]]..program_description)
print_section("SYNOPSIS")
util.printout("\t"..program_name..[[ [--from= | --only-from=] [--to=] [VAR=VALUE]... [] ]])
print_section("GENERAL OPTIONS")
util.printout([[
These apply to all commands, as appropriate:
--server= Fetch rocks/rockspecs from this server
(takes priority over config file)
--only-server= Fetch rocks/rockspecs from this server only
(overrides any entries in the config file)
--only-sources= Restrict downloads to paths matching the
given URL.
--tree= Which tree to operate on.
--local Use the tree in the user's home directory.]])
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]
util.printout("", name)
util.printout("\t", command.help_summary)
end
print_section("CONFIGURATION")
util.printout([[
System configuration file: ]]..sys_file .. " (" .. get_status(sys_ok) ..[[)
User configuration file: ]]..home_file .. " (" .. get_status(home_ok) ..")\n")
else
command = command:gsub("-", "_")
if commands[command] then
local arguments = commands[command].help_arguments or ""
print_banner()
print_section("NAME")
util.printout("\t"..program_name.." "..command.." - "..commands[command].help_summary)
print_section("SYNOPSIS")
util.printout("\t"..program_name.." "..command.." "..arguments)
print_section("DESCRIPTION")
util.printout("",(commands[command].help:gsub("\n","\n\t"):gsub("\n\t$","")))
print_section("SEE ALSO")
util.printout("","'luarocks help' for general options and configuration.\n")
else
return nil, "Unknown command '"..command.."'"
end
end
return true
end
luarocks-2.0.9/src/luarocks/make_manifest.lua 0000644 0001750 0000144 00000002052 11757524227 020470 0 ustar hisham users
--- Module implementing the luarocks-admin "make_manifest" command.
-- Compile a manifest file for a repository.
module("luarocks.make_manifest", package.seeall)
local manif = require("luarocks.manif")
local index = require("luarocks.index")
local cfg = require("luarocks.cfg")
local util = require("luarocks.util")
help_summary = "Compile a manifest file for a repository."
help = [[
, if given, is a local repository pathname.
]]
--- Driver function for "make_manifest" command.
-- @param repo string or nil: Pathname of a local repository. If not given,
-- 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(repo)
assert(type(repo) == "string" or not repo)
repo = repo or cfg.rocks_dir
util.printout("Making manifest for "..repo)
local ok, err = manif.make_manifest(repo)
if ok then
util.printout("Generating index.html for "..repo)
index.make_index(repo)
end
return ok, err
end
luarocks-2.0.9/src/luarocks/add.lua 0000644 0001750 0000144 00000007335 11757524226 016425 0 ustar hisham users
--- Module implementing the luarocks-admin "add" command.
-- Adds a rock or rockspec to a rocks server.
module("luarocks.add", package.seeall)
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=] [--no-refresh] {|...}"
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
from the configuration file is used instead.
The flag --no-refresh indicates the local cache should not be refreshed
prior to generation of the updated manifest.
]]
local function add_files_to_server(refresh, rockfiles, server, upload_server)
assert(type(refresh) == "boolean" or not refresh)
assert(type(rockfiles) == "table")
assert(type(server) == "string")
assert(type(upload_server) == "table" or not upload_server)
local download_url, login_url = cache.get_server_urls(server, upload_server)
local at = fs.current_dir()
local refresh_fn = refresh and cache.refresh_local_cache or cache.split_server_url
local local_cache, protocol, server_path, user, password = refresh_fn(server, download_url, cfg.upload_user, cfg.upload_password)
if not local_cache then
return nil, protocol
end
if protocol == "file" then
return nil, "Server "..server.." is not recognized, check your configuration."
end
if not login_url then
login_url = protocol.."://"..server_path
end
fs.change_dir(at)
local files = {}
for i, rockfile in ipairs(rockfiles) do
if fs.exists(rockfile) then
util.printout("Copying file "..rockfile.." to "..local_cache.."...")
local absolute = fs.absolute_name(rockfile)
fs.copy(absolute, local_cache)
table.insert(files, dir.base_name(absolute))
else
util.printerr("File "..rockfile.." not found")
end
end
if #files == 0 then
return nil, "No files found"
end
fs.change_dir(local_cache)
util.printout("Updating manifest...")
manif.make_manifest(local_cache)
util.printout("Updating index.html...")
index.make_index(local_cache)
local login_info = ""
if user then login_info = " -u "..user end
if password then login_info = login_info..":"..password end
if not login_url:match("/$") then
login_url = login_url .. "/"
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.."/"
elseif upload_server and upload_server.sftp then
local part1, part2 = upload_server.sftp:match("^([^/]*)/(.*)$")
cmd = cfg.variables.SCP.." manifest index.html "..table.concat(files, " ").." "..user.."@"..part1..":/"..part2
else
cmd = cfg.variables.CURL.." "..login_info.." -T '{manifest,index.html,"..table.concat(files, ",").."}' "..login_url
end
util.printout(cmd)
fs.execute(cmd)
return true
end
function run(...)
local files = { util.parse_flags(...) }
local flags = table.remove(files, 1)
if #files < 1 then
return nil, "Argument missing, see help."
end
local server, server_table = cache.get_upload_server(flags["server"])
if not server then return nil, server_table end
return add_files_to_server(not flags["no-refresh"], files, server, server_table)
end
luarocks-2.0.9/src/luarocks/admin_remove.lua 0000644 0001750 0000144 00000005656 11757524226 020346 0 ustar hisham users
--- Module implementing the luarocks-admin "remove" command.
-- Removes a rock or rockspec from a rocks server.
module("luarocks.admin_remove", package.seeall)
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=] [--no-refresh] {|...}"
help = [[
Arguments are local files, which may be rockspecs or rocks.
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.
The flag --no-refresh indicates the local cache should not be refreshed
prior to generation of the updated manifest.
]]
local function remove_files_from_server(refresh, rockfiles, server, upload_server)
assert(type(refresh) == "boolean" or not refresh)
assert(type(rockfiles) == "table")
assert(type(server) == "string")
assert(type(upload_server) == "table" or not upload_server)
local download_url, login_url = cache.get_server_urls(server, upload_server)
local at = fs.current_dir()
local refresh_fn = refresh and cache.refresh_local_cache or cache.split_server_url
local local_cache, protocol, server_path, user, password = refresh_fn(server, download_url, cfg.upload_user, cfg.upload_password)
if not local_cache then
return nil, protocol
end
if protocol ~= "rsync" then
return nil, "This command requires 'rsync', check your configuration."
end
fs.change_dir(at)
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
nr_files = nr_files + 1
else
util.printerr("Failed removing "..file)
end
end
if nr_files == 0 then
return nil, "No files removed."
end
fs.change_dir(local_cache)
util.printout("Updating manifest...")
manif.make_manifest(local_cache)
util.printout("Updating index.html...")
index.make_index(local_cache)
local srv, path = server_path:match("([^/]+)(/.+)")
local cmd = "rsync -Oavz --delete -e ssh "..local_cache.."/ "..user.."@"..srv..":"..path.."/"
util.printout(cmd)
fs.execute(cmd)
return true
end
function run(...)
local files = { util.parse_flags(...) }
local flags = table.remove(files, 1)
if #files < 1 then
return nil, "Argument missing, see help."
end
local server, server_table = cache.get_upload_server(flags["server"])
if not server then return nil, server_table end
return remove_files_from_server(not flags["no-refresh"], files, server, server_table)
end
luarocks-2.0.9/src/luarocks/util.lua 0000644 0001750 0000144 00000031730 11757524227 016647 0 ustar hisham users
--- Assorted utilities for managing tables, plus a scheduler for rollback functions.
-- Does not requires modules directly (only as locals
-- 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 scheduled_functions = {}
--- Schedule a function to be executed upon program termination.
-- This is useful for actions such as deleting temporary directories
-- or failure rollbacks.
-- @param f function: Function to be executed.
-- @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, ...)
assert(type(f) == "function")
local item = { fn = f, args = {...} }
table.insert(scheduled_functions, item)
return item
end
--- Unschedule a function.
-- 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)
for k, v in pairs(scheduled_functions) do
if v == item then
table.remove(scheduled_functions, k)
return
end
end
end
--- Execute scheduled functions.
-- Some calls create temporary files and/or directories and register
-- 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()
local fs = require("luarocks.fs")
fs.change_dir_to_root()
for i = #scheduled_functions, 1, -1 do
local item = scheduled_functions[i]
item.fn(unpack(item.args))
end
end
--- Extract flags from an arguments list.
-- Given string arguments, extract flag arguments into a flags set.
-- 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(...)
local args = {...}
local flags = {}
for i = #args, 1, -1 do
local flag = args[i]:match("^%-%-(.*)")
if flag then
local var,val = flag:match("([a-z_%-]*)=(.*)")
if val then
flags[var] = val
else
flags[flag] = true
end
table.remove(args, i)
end
end
return flags, unpack(args)
end
--- Merges contents of src on top of dst's contents.
-- @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)
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)
else
dst[k] = v
end
else
dst[k] = v
end
end
end
--- Perform platform-specific overrides on a table.
-- Overrides values of table with the contents of the appropriate
-- subset of its "platforms" field. The "platforms" field should
-- be a table containing subtables keyed with strings representing
-- platform names. Names that match the contents of the global
-- cfg.platforms setting are used. For example, if
-- cfg.platforms= {"foo"}, then the fields of
-- tbl.platforms.foo will overwrite those of tbl with the same
-- names. For table values, the operation is performed recursively
-- (tbl.platforms.foo.x.y.z overrides tbl.x.y.z; other contents of
-- 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)
assert(type(tbl) == "table" or not tbl)
local cfg = require("luarocks.cfg")
if not tbl then return end
if tbl.platforms then
for _, platform in ipairs(cfg.platforms) do
local platform_tbl = tbl.platforms[platform]
if platform_tbl then
deep_merge(tbl, platform_tbl)
end
end
end
tbl.platforms = nil
end
local var_format_pattern = "%$%((%a[%a%d_]+)%)"
--- Create a new shallow copy of a table: a new table with
-- the same keys and values. Keys point to the same objects as
-- the original table (ie, does not copy recursively).
-- @param tbl table: the input table
-- @return table: a new table with the same contents.
local function make_shallow_copy(tbl)
local copy = {}
for k,v in pairs(tbl) do
copy[k] = v
end
return copy
end
-- Check if a set of needed variables are referenced
-- somewhere in a list of definitions, warning the user
-- about any unused ones. Each key in needed_set should
-- appear as a $(XYZ) variable at least once as a
-- substring of some value of var_defs.
-- @param var_defs: a table with string keys and string
-- values, containing variable definitions.
-- @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)
needed_set = make_shallow_copy(needed_set)
for var,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))
end
end
-- Output any entries that might remain in $(XYZ) format,
-- warning the user that substitutions have failed.
-- @param line string: the input string
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)
any_failed = true
end
end
return any_failed
end
--- Perform make-style variable substitutions on string values of a table.
-- For every string value tbl.x which contains a substring of the format
-- "$(XYZ)" will have this substring replaced by vars["XYZ"], if that field
-- exists in vars. Only string values are processed; this function
-- does not scan subtables recursively.
-- @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)
assert(type(tbl) == "table")
assert(type(vars) == "table")
local updated = {}
for k, v in pairs(tbl) do
if type(v) == "string" then
updated[k] = v:gsub(var_format_pattern, vars)
if warn_failed_matches(updated[k]) then
updated[k] = updated[k]:gsub(var_format_pattern, "")
end
end
end
for k, v in pairs(updated) do
tbl[k] = v
end
end
--- Return an array of keys of a table.
-- @param tbl table: The input table.
-- @return table: The array of keys.
function keys(tbl)
local ks = {}
for k,_ in pairs(tbl) do
table.insert(ks, k)
end
return ks
end
local function default_sort(a, b)
local ta = type(a)
local tb = type(b)
if ta == "number" and tb == "number" then
return a < b
elseif ta == "number" then
return true
elseif tb == "number" then
return false
else
return tostring(a) < tostring(b)
end
end
-- The iterator function used internally by util.sortedpairs.
-- @param tbl table: The table to be iterated.
-- @param sort_function function or nil: An optional comparison function
-- to be used by table.sort when sorting keys.
-- @see sortedpairs
local function sortedpairs_iterator(tbl, sort_function)
local ks = 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
coroutine.yield(k, tbl[k])
end
else
local order = sort_function
local done = {}
for _, k in ipairs(order) do
local sub_order
if type(k) == "table" then
sub_order = k[2]
k = k[1]
end
if tbl[k] then
done[k] = true
coroutine.yield(k, tbl[k], sub_order)
end
end
table.sort(ks, default_sort)
for _, k in ipairs(ks) do
if not done[k] then
coroutine.yield(k, tbl[k])
end
end
end
end
--- A table iterator generator that returns elements sorted by key,
-- to be used in "for" loops.
-- @param tbl table: The table to be iterated.
-- @param sort_function function or table or nil: An optional comparison function
-- to be used by table.sort when sorting keys, or an array listing an explicit order
-- for keys. If a value itself is an array, it is taken so that the first element
-- 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)
return coroutine.wrap(function() sortedpairs_iterator(tbl, sort_function) end)
end
function starts_with(s, prefix)
return s:sub(1,#prefix) == prefix
end
--- Print a line to standard output
function printout(...)
io.stdout:write(table.concat({...},"\t"))
io.stdout:write("\n")
end
--- Print a line to standard error
function 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)
end
-- from http://lua-users.org/wiki/SplitJoin
-- by PhilippeLhoste
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
--[[
Author: Julio Manuel Fernandez-Diaz
Date: January 12, 2007
(For Lua 5.1)
Formats tables with cycles recursively to any depth.
The output is returned as a string.
References to other tables are shown as values.
Self references are indicated.
The string returned is "Lua code", which can be procesed
(in the case in which indent is composed by spaces or "--").
Userdata and function keys and values are shown as strings,
which logically are exactly not equivalent to the original code.
This routine can serve for pretty formating tables with
proper indentations, apart from printing them:
io.write(table.show(t, "t")) -- a typical use
Heavily based on "Saving tables with cycles", PIL2, p. 113.
Arguments:
t is the table.
name is the name of the table (optional)
indent is a first indentation (optional).
--]]
function show_table(t, name, indent)
local cart -- a container
local autoref -- for self references
local function isemptytable(t) return next(t) == nil end
local function basicSerialize (o)
local so = tostring(o)
if type(o) == "function" then
local info = debug.getinfo(o, "S")
-- info.name is nil because o is not a calling level
if info.what == "C" then
return ("%q"):format(so .. ", C function")
else
-- the information is defined through lines
return ("%q"):format(so .. ", defined in (" .. info.linedefined .. "-" .. info.lastlinedefined .. ")" .. info.source)
end
elseif type(o) == "number" then
return so
else
return ("%q"):format(so)
end
end
local function addtocart (value, name, indent, saved, field)
indent = indent or ""
saved = saved or {}
field = field or name
cart = cart .. indent .. field
if type(value) ~= "table" then
cart = cart .. " = " .. basicSerialize(value) .. ";\n"
else
if saved[value] then
cart = cart .. " = {}; -- " .. saved[value] .. " (self reference)\n"
autoref = autoref .. name .. " = " .. saved[value] .. ";\n"
else
saved[value] = name
--if tablecount(value) == 0 then
if isemptytable(value) then
cart = cart .. " = {};\n"
else
cart = cart .. " = {\n"
for k, v in pairs(value) do
k = basicSerialize(k)
local fname = ("%s[%s]"):format(name, k)
field = ("[%s]"):format(k)
-- three spaces between levels
addtocart(v, fname, indent .. " ", saved, field)
end
cart = cart .. indent .. "};\n"
end
end
end
end
name = name or "__unnamed__"
if type(t) ~= "table" then
return name .. " = " .. basicSerialize(t)
end
cart, autoref = "", ""
addtocart(t, name, indent)
return cart .. autoref
end
luarocks-2.0.9/src/luarocks/pack.lua 0000644 0001750 0000144 00000015363 11757524227 016614 0 ustar hisham users
--- Module implementing the LuaRocks "pack" command.
-- Creates a rock, packing sources or binaries.
module("luarocks.pack", package.seeall)
local path = require("luarocks.path")
local rep = require("luarocks.rep")
local fetch = require("luarocks.fetch")
local fs = require("luarocks.fs")
local cfg = require("luarocks.cfg")
local util = require("luarocks.util")
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 = "{| []}"
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
argument.
]]
--- Create a source rock.
-- Packages a rockspec and its required source files in a rock
-- file with the .src.rock extension, which can later be built and
-- installed with the "build" command.
-- @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)
assert(type(rockspec_file) == "string")
local rockspec, err = fetch.load_rockspec(rockspec_file)
if err then
return nil, "Error loading rockspec: "..err
end
rockspec_file = rockspec.local_filename
local name_version = rockspec.name .. "-" .. rockspec.version
local rock_file = fs.absolute_name(name_version .. ".src.rock")
local source_file, source_dir = fetch.fetch_sources(rockspec, false)
if not source_file then
return nil, source_dir
end
fs.change_dir(source_dir)
fs.delete(rock_file)
fs.copy(rockspec_file, source_dir)
if not fs.zip(rock_file, dir.base_name(rockspec_file), dir.base_name(source_file)) then
return nil, "Failed packing "..rock_file
end
fs.pop_dir()
return rock_file
end
local function copy_back_files(name, version, file_tree, deploy_dir, pack_dir)
fs.make_dir(pack_dir)
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)
else
local versioned = path.versioned_name(source, deploy_dir, name, version)
if fs.exists(versioned) then
fs.copy(versioned, target)
else
fs.copy(source, target)
end
end
end
return true
end
-- @param name string: Name of package to pack.
-- @param version string or nil: A version number may also be passed.
-- @return string or (nil, string): The filename of the resulting
-- .src.rock file; or nil and an error message.
local function do_pack_binary_rock(name, version)
assert(type(name) == "string")
assert(type(version) == "string" or not version)
local query = search.make_query(name, version)
query.exact_name = true
local results = {}
search.manifest_search(results, cfg.rocks_dir, query)
if not next(results) then
return nil, "'"..name.."' does not seem to be an installed rock."
end
local versions = results[name]
if not version then
local first = next(versions)
if next(versions, first) then
return nil, "Please specify which version of '"..name.."' to pack."
end
version = first
end
if not version:match("[^-]+%-%d+") then
return nil, "Expected version "..version.." in version-revision format."
end
local info = versions[version][1]
local root = path.root_dir(info.repo)
local prefix = path.install_dir(name, version, root)
if not fs.exists(prefix) then
return nil, "'"..name.." "..version.."' does not seem to be an installed rock."
end
local rock_manifest = manif.load_rock_manifest(name, version, root)
if not rock_manifest then
return nil, "rock_manifest file not found for "..name.." "..version.." - not a LuaRocks 2 tree?"
end
local name_version = name .. "-" .. version
local rock_file = fs.absolute_name(name_version .. "."..cfg.arch..".rock")
local temp_dir = fs.make_temp_dir("pack")
fs.copy_contents(prefix, temp_dir)
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"))
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"))
end
fs.change_dir(temp_dir)
if not is_binary and not rep.has_binaries(name, version) then
rock_file = rock_file:gsub("%."..cfg.arch:gsub("%-","%%-").."%.", ".all.")
end
fs.delete(rock_file)
if not fs.zip(rock_file, unpack(fs.list_dir())) then
return nil, "Failed packing "..rock_file
end
fs.pop_dir()
fs.delete(temp_dir)
return rock_file
end
function 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
-- alternative would require refactoring parts of luarocks.build and
-- luarocks.pack, which would save a few file operations: the idea would be
-- 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))
if not temp_dir then
return nil, "Failed creating temporary directory."
end
util.schedule_function(fs.delete, temp_dir)
path.use_tree(temp_dir)
local ok, err = cmd(...)
if not ok then
return nil, err
end
local rname, rversion = path.parse_name(name)
if not rname then
rname, rversion = name, version
end
return do_pack_binary_rock(rname, rversion)
end
--- Driver function for the "pack" command.
-- @param arg string: may be a rockspec file, for creating a source rock,
-- or the name of an installed package, for creating a binary rock.
-- @param version string or nil: if the name of a package is given, a
-- version may also be passed.
-- @return boolean or (nil, string): true if successful or nil followed
-- by an error message.
function run(...)
local flags, arg, version = util.parse_flags(...)
assert(type(version) == "string" or not version)
if type(arg) ~= "string" then
return nil, "Argument missing, see help."
end
local file, err
if arg:match(".*%.rockspec") then
file, err = pack_source_rock(arg)
else
file, err = do_pack_binary_rock(arg, version)
end
if err then
return nil, err
else
util.printout("Packed: "..file)
return true
end
end
luarocks-2.0.9/src/luarocks/path.lua 0000644 0001750 0000144 00000026475 11757524227 016640 0 ustar hisham users
--- 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)
local dir = require("luarocks.dir")
local cfg = require("luarocks.cfg")
local util = require("luarocks.util")
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)
assert(type(rock_name) == "string")
local base_name = dir.base_name(rock_name)
return base_name:match("(.*)%.[^.]*.rock") .. ".rockspec"
end
function rocks_dir(tree)
if type(tree) == "string" then
return dir.path(tree, "lib", "luarocks", "rocks")
else
assert(type(tree) == "table")
return tree.rocks_dir or dir.path(tree.root, "lib", "luarocks", "rocks")
end
end
function root_dir(rocks_dir)
assert(type(rocks_dir) == "string")
local suffix = dir.path("lib", "luarocks", "rocks")
return rocks_dir:match("(.*)" .. suffix .. "$")
end
function deploy_bin_dir(tree)
if type(tree) == "string" then
return dir.path(tree, "bin")
else
assert(type(tree) == "table")
return tree.bin_dir or dir.path(tree.root, "bin")
end
end
function deploy_lua_dir(tree)
if type(tree) == "string" then
return dir.path(tree, cfg.lua_modules_path)
else
assert(type(tree) == "table")
return tree.lua_dir or dir.path(tree.root, cfg.lua_modules_path)
end
end
function deploy_lib_dir(tree)
if type(tree) == "string" then
return dir.path(tree, cfg.lib_modules_path)
else
assert(type(tree) == "table")
return tree.lib_dir or dir.path(tree.root, cfg.lib_modules_path)
end
end
function manifest_file(tree)
if type(tree) == "string" then
return dir.path(tree, "lib", "luarocks", "rocks", "manifest")
else
assert(type(tree) == "table")
return (tree.rocks_dir and dir.path(tree.rocks_dir, "manifest")) or dir.path(tree.root, "lib", "luarocks", "rocks", "manifest")
end
end
--- Get the directory for all versions of a package in a tree.
-- @param name string: The package name.
-- @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)
assert(type(name) == "string")
tree = tree or cfg.root_dir
return dir.path(rocks_dir(tree), name)
end
--- Get the local installation directory (prefix) for a package.
-- @param name string: The package name.
-- @param version string: The package version.
-- @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)
assert(type(name) == "string")
assert(type(version) == "string")
tree = tree or cfg.root_dir
return dir.path(rocks_dir(tree), name, version)
end
--- Get the local filename of the rockspec of an installed rock.
-- @param name string: The package name.
-- @param version string: The package version.
-- @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)
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")
end
--- Get the local filename of the rock_manifest file of an installed rock.
-- @param name string: The package name.
-- @param version string: The package version.
-- @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)
assert(type(name) == "string")
assert(type(version) == "string")
tree = tree or cfg.root_dir
return dir.path(rocks_dir(tree), name, version, "rock_manifest")
end
--- Get the local installation directory for C libraries of a package.
-- @param name string: The package name.
-- @param version string: The package version.
-- @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)
assert(type(name) == "string")
assert(type(version) == "string")
tree = tree or cfg.root_dir
return dir.path(rocks_dir(tree), name, version, "lib")
end
--- Get the local installation directory for Lua modules of a package.
-- @param name string: The package name.
-- @param version string: The package version.
-- @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)
assert(type(name) == "string")
assert(type(version) == "string")
tree = tree or cfg.root_dir
return dir.path(rocks_dir(tree), name, version, "lua")
end
--- Get the local installation directory for documentation of a package.
-- @param name string: The package name.
-- @param version string: The package version.
-- @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)
assert(type(name) == "string")
assert(type(version) == "string")
tree = tree or cfg.root_dir
return dir.path(rocks_dir(tree), name, version, "doc")
end
--- Get the local installation directory for configuration files of a package.
-- @param name string: The package name.
-- @param version string: The package version.
-- @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)
assert(type(name) == "string")
assert(type(version) == "string")
tree = tree or cfg.root_dir
return dir.path(rocks_dir(tree), name, version, "conf")
end
--- Get the local installation directory for command-line scripts
-- of a package.
-- @param name string: The package name.
-- @param version string: The package version.
-- @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)
assert(type(name) == "string")
assert(type(version) == "string")
tree = tree or cfg.root_dir
return dir.path(rocks_dir(tree), name, version, "bin")
end
--- Extract name, version and arch of a rock filename,
-- or name, version and "rockspec" from a rockspec name.
-- @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)
assert(type(file_name) == "string")
if file_name:match("%.rock$") then
return dir.base_name(file_name):match("(.*)-([^-]+-%d+)%.([^.]+)%.rock$")
else
return dir.base_name(file_name):match("(.*)-([^-]+-%d+)%.(rockspec)")
end
end
--- Make a rockspec or rock URL.
-- @param pathname string: Base URL or pathname.
-- @param name string: Package name.
-- @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)
assert(type(pathname) == "string")
assert(type(name) == "string")
assert(type(version) == "string")
assert(type(arch) == "string")
local filename = name.."-"..version
if arch == "installed" then
filename = dir.path(name, version, filename..".rockspec")
elseif arch == "rockspec" then
filename = filename..".rockspec"
else
filename = filename.."."..arch..".rock"
end
return dir.path(pathname, filename)
end
--- Convert a pathname to a module identifier.
-- In Unix, for example, a path "foo/bar/baz.lua" is converted to
-- "foo.bar.baz"; "bla/init.lua" returns "bla"; "foo.so" returns "foo".
-- @param file string: Pathname of module
-- @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)
assert(type(file) == "string")
local name = file:match("(.*)%."..cfg.lua_extension.."$")
if name then
name = name:gsub(dir.separator, ".")
local init = name:match("(.*)%.init$")
if init then
name = init
end
else
name = file:match("(.*)%."..cfg.lib_extension.."$")
if name then
name = name:gsub(dir.separator, ".")
end
end
if not name then name = file end
name = name:gsub("^%.+", ""):gsub("%.+$", "")
return name
end
--- Obtain the directory name where a module should be stored.
-- 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)
assert(type(mod) == "string")
return (mod:gsub("[^.]*$", ""):gsub("%.", dir.separator))
end
--- Set up path-related variables for a given rock.
-- 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)
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)
rockspec.variables = vars
end
function versioned_name(file, prefix, name, version)
assert(type(file) == "string")
assert(type(name) == "string")
assert(type(version) == "string")
local rest = file:sub(#prefix+1):gsub("^/*", "")
local name_version = (name.."_"..version):gsub("%-", "_"):gsub("%.", "_")
return dir.path(prefix, name_version.."-"..rest)
end
function 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)
end
--- Driver function for "path" command.
-- @return boolean This function always succeeds.
function run(...)
util.printout(cfg.export_lua_path:format(package.path))
util.printout(cfg.export_lua_cpath:format(package.cpath))
return true
end
luarocks-2.0.9/src/luarocks/fs.lua 0000644 0001750 0000144 00000002105 11757524226 016273 0 ustar hisham users
--- Proxy module for filesystem and platform abstractions.
-- All code using "fs" code should require "luarocks.fs",
-- and not the various platform-specific implementations.
-- However, see the documentation of the implementation
-- for the API reference.
local pairs = pairs
module("luarocks.fs", package.seeall)
local cfg = require("luarocks.cfg")
local function load_fns(fs_table)
for name, fn in pairs(fs_table) do
if not _M[name] then
_M[name] = fn
end
end
end
-- Load platform-specific functions
local loaded_platform = nil
for _, platform in ipairs(cfg.platforms) do
local ok, fs_plat = pcall(require, "luarocks.fs."..platform)
if ok and fs_plat then
loaded_platform = platform
load_fns(fs_plat)
break
end
end
-- Load platform-independent pure-Lua functionality
local fs_lua = require("luarocks.fs.lua")
load_fns(fs_lua)
-- Load platform-specific fallbacks for missing Lua modules
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
luarocks-2.0.9/src/luarocks/fs/ 0000755 0001750 0000144 00000000000 11757524227 015573 5 ustar hisham users luarocks-2.0.9/src/luarocks/fs/unix.lua 0000644 0001750 0000144 00000005515 11757524227 017267 0 ustar hisham users
--- 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)
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())
--- Return an absolute pathname from a potentially relative one.
-- @param pathname string: pathname to convert.
-- @param relative_to string or nil: path to prepend when making
-- 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)
assert(type(pathname) == "string")
assert(type(relative_to) == "string" or not relative_to)
relative_to = relative_to or fs.current_dir()
if pathname:sub(1,1) == "/" then
return pathname
else
return relative_to .. "/" .. pathname
end
end
--- Create a wrapper to make a script executable from the command-line.
-- @param file string: Pathname of script to be made executable.
-- @param dest string: Directory where to put the wrapper.
-- @return boolean or (nil, string): True if succeeded, or nil and
-- an error message.
function wrap_script(file, dest)
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 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 "'..file..'" "$@"\n')
wrapper:close()
if fs.chmod(wrapname, "0755") then
return true
else
return nil, "Could not make "..wrapname.." executable."
end
end
--- Check if a file (typically inside path.bin_dir) is an actual binary
-- or a Lua wrapper.
-- @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)
if filename:match("%.lua$") then
return false
end
local file = io.open(filename)
if not file then
return true
end
local first = file:read(2)
file:close()
if not first then
util.printerr("Warning: could not read "..filename)
return true
end
return first ~= "#!"
end
function copy_binary(filename, dest)
return fs.copy(filename, dest, "0755")
end
luarocks-2.0.9/src/luarocks/fs/win32.lua 0000644 0001750 0000144 00000006757 11757524227 017257 0 ustar hisham users --- 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)
local fs = require("luarocks.fs")
local cfg = require("luarocks.cfg")
local dir = require("luarocks.dir")
--- Quote argument for shell processing. Fixes paths on Windows.
-- Adds single quotes and escapes.
-- @param arg string: Unquoted argument.
-- @return string: Quoted argument.
function Q(arg)
assert(type(arg) == "string")
-- Quote DIR for Windows
if arg:match("^[%.a-zA-Z]?:?[\\/]") then
return '"' .. arg:gsub("/", "\\"):gsub('"', '\\"') .. '"'
end
-- URLs and anything else
return '"' .. arg:gsub('"', '\\"') .. '"'
end
--- Return an absolute pathname from a potentially relative one.
-- @param pathname string: pathname to convert.
-- @param relative_to string or nil: path to prepend when making
-- 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)
assert(type(pathname) == "string")
assert(type(relative_to) == "string" or not relative_to)
relative_to = relative_to or fs.current_dir()
-- FIXME I'm not sure this first \\ should be there at all.
-- What are the Windows rules for drive letters?
if pathname:match("^[\\.a-zA-Z]?:?[\\/]") then
return pathname
else
return relative_to .. "/" .. pathname
end
end
--- Create a wrapper to make a script executable from the command-line.
-- @param file string: Pathname of script to be made executable.
-- @param dest string: Directory where to put the wrapper.
-- @return boolean or (nil, string): True if succeeded, or nil and
-- an error message.
function wrap_script(file, dest)
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 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 "'..file..'" %*\n')
wrapper:write("endlocal\n")
wrapper:close()
return true
end
function is_actual_binary(name)
name = name:lower()
if name:match("%.bat$") or name:match("%.exe$") then
return true
end
return false
end
function 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)
if base:match(exe_pattern) then
base = base:gsub(exe_pattern, ".lua")
local helpname = dest.."/"..base
local helper = io.open(helpname, "w")
if not helper then
return nil, "Could not open "..helpname.." for writing."
end
helper:write('package.path=\"'..package.path:gsub("\\","\\\\")..';\"..package.path\n')
helper:write('package.cpath=\"'..package.path:gsub("\\","\\\\")..';\"..package.cpath\n')
helper:close()
end
return true
end
function chmod(filename, mode)
return true
end
function get_permissions(filename)
return ""
end
luarocks-2.0.9/src/luarocks/fs/unix/ 0000755 0001750 0000144 00000000000 11757524227 016556 5 ustar hisham users luarocks-2.0.9/src/luarocks/fs/unix/tools.lua 0000644 0001750 0000144 00000024463 11757524227 020432 0 ustar hisham users
--- fs operations implemented with third-party tools for Unix platform abstractions.
module("luarocks.fs.unix.tools", package.seeall)
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local cfg = require("luarocks.cfg")
local dir_stack = {}
local vars = cfg.variables
--- Run the given command.
-- The command is executed in the current directory in the directory stack.
-- @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 actual_cmd = "cd " .. fs.Q(fs.current_dir()) .. " && " .. cmd
local code = os.execute(actual_cmd)
if code == 0 or code == true then
return true
else
return false
end
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()
for _, directory in ipairs(dir_stack) do
current = fs.absolute_name(directory, current)
end
return current
end
--- Change the current directory.
-- Uses the module's internal directory stack. This does not have exact
-- 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)
assert(type(directory) == "string")
table.insert(dir_stack, directory)
end
--- Change directory to root.
-- Allows leaving a directory (e.g. for deleting it) in
-- a crossplatform way.
function change_dir_to_root()
table.insert(dir_stack, "/")
end
--- Change working directory to the previous in the directory stack.
function pop_dir()
local directory = table.remove(dir_stack)
return directory ~= nil
end
--- Create a directory if it does not already exist.
-- If any of the higher levels in the path name does 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)
assert(directory)
return fs.execute(vars.MKDIR.." -p", 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_if_empty(directory)
assert(directory)
fs.execute_string(vars.RMDIR.." "..fs.Q(directory).." 1> /dev/null 2> /dev/null")
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)
assert(directory)
fs.execute_string(vars.RMDIR.." -p "..fs.Q(directory).." 1> /dev/null 2> /dev/null")
end
--- Copy a file.
-- @param src string: Pathname of source
-- @param dest string: Pathname of destination
-- @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)
assert(src and dest)
if fs.execute(vars.CP, src, dest) then
if perm then
if fs.is_dir(dest) then
dest = dir.path(dest, dir.base_name(src))
end
if fs.chmod(dest, perm) then
return true
else
return false, "Failed setting permissions of "..dest
end
end
return true
else
return false, "Failed copying "..src.." to "..dest
end
end
--- Recursively copy the contents of a directory.
-- @param src string: Pathname of source
-- @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)
assert(src and dest)
if fs.execute_string(vars.CP.." -pPR "..fs.Q(src).."/* "..fs.Q(dest).." 1> /dev/null 2>/dev/null") then
return true
else
return false, "Failed copying "..src.." to "..dest
end
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)
assert(arg)
assert(arg:sub(1,1) == "/")
return fs.execute_string(vars.RM.." -rf " .. fs.Q(arg) .. " 1> /dev/null 2>/dev/null")
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("cd "..fs.Q(at).." && "..vars.LS)
for file in pipe:lines() do
table.insert(result, file)
end
pipe:close()
return result
end
--- Recursively scan the contents of a directory.
-- @param at string or nil: directory to scan (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 find(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("cd "..fs.Q(at).." && "..vars.FIND.." * 2>/dev/null")
for file in pipe:lines() do
table.insert(result, file)
end
pipe:close()
return result
end
--- Compress files in a .zip archive.
-- @param zipfile string: pathname of .zip archive to be created.
-- @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.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)
assert(zipfile)
return fs.execute(vars.UNZIP, zipfile)
end
--- Test for existance of a file.
-- @param file string: filename to test
-- @return boolean: true if file exists, false otherwise.
function exists(file)
assert(file)
return fs.execute(vars.TEST, "-r", file)
end
--- Test is file/directory is writable.
-- @param file string: filename to test
-- @return boolean: true if file exists, false otherwise.
function is_writable(file)
assert(file)
return fs.execute(vars.TEST, "-w", file)
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)
assert(file)
return fs.execute(vars.TEST, "-d", file)
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)
assert(file)
return fs.execute(vars.TEST, "-f", file)
end
--- 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)
assert(type(url) == "string")
assert(type(filename) == "string" or not filename)
if cfg.downloader == "wget" then
local wget_cmd = vars.WGET.." --no-check-certificate --no-cache --user-agent="..cfg.user_agent.." --quiet --continue "
if filename then
return fs.execute(wget_cmd.." --output-document ", filename, url)
else
return fs.execute(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.." "..fs.Q(url).." 2> /dev/null 1> "..fs.Q(filename))
end
end
function chmod(pathname, mode)
if mode then
return fs.execute(vars.CHMOD, mode, pathname)
else
return false
end
end
--- Apply a patch.
-- @param patchname string: The filename of the patch.
function apply_patch(patchname)
return fs.execute(vars.PATCH.." -p1 -f -i ", patchname)
end
--- Unpack an archive.
-- Extract the contents of an archive, detecting its format by
-- 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)
assert(type(archive) == "string")
local ok
if archive:match("%.tar%.gz$") or archive:match("%.tgz$") then
-- ok = fs.execute("tar zxvpf ", archive)
ok = fs.execute_string(vars.GUNZIP.." -c "..archive.."|"..vars.TAR.." -xf -")
elseif archive:match("%.tar%.bz2$") then
-- ok = fs.execute("tar jxvpf ", archive)
ok = fs.execute_string(vars.BUNZIP2.." -c "..archive.."|tar -xf -")
elseif archive:match("%.zip$") then
ok = fs.execute(vars.UNZIP, archive)
elseif archive:match("%.lua$") or archive:match("%.c$") then
-- Ignore .lua and .c files; they don't need to be extracted.
return true
else
local ext = archive:match(".*(%..*)")
return false, "Unrecognized filename extension "..(ext or "")
end
if not ok then
return false, "Failed extracting "..archive
end
return true
end
local md5_cmd = {
md5sum = vars.MD5SUM,
openssl = vars.OPENSSL.." md5",
md5 = 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)
local cmd = md5_cmd[cfg.md5checker]
if not cmd then return nil end
local pipe = io.popen(cmd.." "..fs.absolute_name(file))
local computed = pipe:read("*a")
pipe:close()
if not computed then return nil end
return computed:match("("..("%x"):rep(32)..")")
end
function get_permissions(filename)
local pipe = io.popen(vars.STAT.." "..vars.STATFLAG.." "..fs.Q(filename))
local ret = pipe:read("*l")
pipe:close()
return ret
end
luarocks-2.0.9/src/luarocks/fs/win32/ 0000755 0001750 0000144 00000000000 11757524227 016535 5 ustar hisham users luarocks-2.0.9/src/luarocks/fs/win32/tools.lua 0000644 0001750 0000144 00000025157 11757524227 020412 0 ustar hisham users
--- 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)
local fs = require("luarocks.fs")
local cfg = require("luarocks.cfg")
local dir = require("luarocks.dir")
local dir_stack = {}
local vars = cfg.variables
--- Strip the last extension of a filename.
-- Example: "foo.tar.gz" becomes "foo.tar".
-- If filename has no dots, returns it unchanged.
-- @param filename string: The file name to strip.
-- @return string: The stripped name.
local function strip_extension(filename)
assert(type(filename) == "string")
return (filename:gsub("%.[^.]+$", "")) or filename
end
local function command_at(directory, cmd)
local drive = directory:match("^([A-Za-z]:)")
cmd = "cd " .. fs.Q(directory) .. " & " .. cmd
if drive then
cmd = drive .. " & " .. cmd
end
return cmd
end
--- Test for existance of a file.
-- @param file string: filename to test
-- @return boolean: true if file exists, false otherwise.
function exists(file)
assert(file)
return fs.execute("if not exist " .. fs.Q(file) ..
" invalidcommandname 2>NUL 1>NUL")
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()
for _, directory in ipairs(dir_stack) do
current = fs.absolute_name(directory, current)
end
return current
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)
assert(file)
return fs.execute(vars.TEST.." -f", file)
end
local md5_cmd = {
md5sum = vars.MD5SUM,
openssl = vars.OPENSSL.." md5",
md5 = 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)
local cmd = md5_cmd[cfg.md5checker]
if not cmd then return nil end
local pipe = io.popen(cmd.." "..fs.absolute_name(file))
local computed = pipe:read("*a")
pipe:close()
if not computed then return nil end
return computed:match("("..("%x"):rep(32)..")")
end
--- Change the current directory.
-- Uses the module's internal directory stack. This does not have exact
-- 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)
assert(type(directory) == "string")
table.insert(dir_stack, directory)
end
--- Change directory to root.
-- Allows leaving a directory (e.g. for deleting it) in
-- a crossplatform way.
function change_dir_to_root()
table.insert(dir_stack, "/")
end
--- Change working directory to the previous in the directory stack.
function pop_dir()
local directory = table.remove(dir_stack)
return directory ~= nil
end
--- Run the given command.
-- The command is executed in the current directory in the directory stack.
-- @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))
if code == 0 or code == true then
return true
else
return false
end
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_dir(file)
assert(file)
return fs.execute(vars.TEST.." -d " .. fs.Q(file) .. " 2>NUL 1>NUL")
end
--- Create a directory if it does not already exist.
-- If any of the higher levels in the path name does 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)
assert(directory)
fs.execute(vars.MKDIR.." "..fs.Q(directory).." 1> NUL 2> NUL")
return 1
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)
assert(directory)
fs.execute_string(vars.RMDIR.." "..fs.Q(directory).." 1> NUL 2> NUL")
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)
assert(directory)
fs.execute_string(vars.RMDIR.." "..fs.Q(directory).." 1> NUL 2> NUL")
end
--- Copy a file.
-- @param src string: Pathname of source
-- @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)
assert(src and dest)
if dest:match("[/\\]$") then dest = dest:sub(1, -2) end
if fs.execute(vars.CP, src, dest) then
return true
else
return false, "Failed copying "..src.." to "..dest
end
end
--- Recursively copy the contents of a directory.
-- @param src string: Pathname of source
-- @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)
assert(src and dest)
if fs.execute_string(vars.CP.." -a "..src.."\\*.* "..fs.Q(dest).." 1> NUL 2> NUL") then
return true
else
return false, "Failed copying "..src.." to "..dest
end
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)
assert(arg)
assert(arg:match("^[\a-zA-Z]?:?[\\/]"))
fs.execute(vars.CHMOD.." a+rw -R ", arg)
return fs.execute_string(vars.RM.." -rf " .. fs.Q(arg) .. " 1> NUL 2> NUL")
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))
for file in pipe:lines() do
table.insert(result, file)
end
pipe:close()
return result
end
--- Recursively scan the contents of a directory.
-- @param at string or nil: directory to scan (will be the current
-- 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)
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.FIND.." 2> NUL"))
for file in pipe:lines() do
-- Windows find is a bit different
local first_two = file:sub(1,2)
if first_two == ".\\" or first_two == "./" then file=file:sub(3) end
if file ~= "." then
table.insert(result, (file:gsub("\\", "/")))
end
end
return result
end
--- 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)
assert(type(url) == "string")
assert(type(filename) == "string" or not filename)
if cfg.downloader == "wget" then
local wget_cmd = vars.WGET.." --no-check-certificate --no-cache --user-agent="..cfg.user_agent.." --quiet --continue "
if filename then
return fs.execute(wget_cmd.." --output-document ", filename, url)
else
return fs.execute(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.." "..fs.Q(url).." 2> NUL 1> "..fs.Q(filename))
end
end
--- Compress files in a .zip archive.
-- @param zipfile string: pathname of .zip archive to be created.
-- @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, ...)
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)
assert(zipfile)
return fs.execute(vars.SEVENZ.." x", zipfile)
end
--- Uncompress gzip file.
-- @param archive string: Filename of archive.
-- @return boolean : success status
local function gunzip(archive)
return fs.execute(vars.SEVENZ.." x", archive)
end
--- Unpack an archive.
-- Extract the contents of an archive, detecting its format by
-- 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)
assert(type(archive) == "string")
local ok
local sevenzx = vars.SEVENZ.." x"
if archive:match("%.tar%.gz$") then
ok = gunzip(archive)
if ok then
ok = fs.execute(sevenzx, strip_extension(archive))
end
elseif archive:match("%.tgz$") then
ok = gunzip(archive)
if ok then
ok = fs.execute(sevenzx, strip_extension(archive)..".tar")
end
elseif archive:match("%.tar%.bz2$") then
ok = fs.execute(sevenzx, archive)
if ok then
ok = fs.execute(sevenzx, strip_extension(archive))
end
elseif archive:match("%.zip$") then
ok = fs.execute(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
else
local ext = archive:match(".*(%..*)")
return false, "Unrecognized filename extension "..(ext or "")
end
if not ok then
return false, "Failed extracting "..archive
end
return true
end
luarocks-2.0.9/src/luarocks/fs/lua.lua 0000644 0001750 0000144 00000047517 11757524227 017075 0 ustar hisham users
--- Native Lua implementation of filesystem and platform abstractions,
-- using LuaFileSystem, LZLib, MD5 and LuaCurl.
module("luarocks.fs.lua", package.seeall)
local fs = require("luarocks.fs")
local cfg = require("luarocks.cfg")
local dir = require("luarocks.dir")
local util = require("luarocks.util")
local path = require("luarocks.path")
local socket_ok, http = pcall(require, "socket.http")
local _, ftp = pcall(require, "socket.ftp")
local zip_ok, lrzip = pcall(require, "luarocks.tools.zip")
local unzip_ok, luazip = pcall(require, "zip"); _G.zip = nil
local lfs_ok, lfs = pcall(require, "lfs")
local md5_ok, md5 = pcall(require, "md5")
local posix_ok, posix = pcall(require, "posix")
local tar = require("luarocks.tools.tar")
local patch = require("luarocks.tools.patch")
local dir_stack = {}
math.randomseed(os.time())
dir_separator = "/"
--- Quote argument for shell processing.
-- Adds single quotes and escapes.
-- @param arg string: Unquoted argument.
-- @return string: Quoted argument.
function Q(arg)
assert(type(arg) == "string")
-- FIXME Unix-specific
return "'" .. arg:gsub("\\", "\\\\"):gsub("'", "'\\''") .. "'"
end
local function normalize(name)
return name:gsub("\\", "/"):gsub("/$", "")
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 is_writable(file)
assert(file)
file = normalize(file)
local result
if fs.is_dir(file) then
local file2 = dir.path(file, '.tmpluarockstestwritable')
local fh = io.open(file2, 'wb')
result = fh ~= nil
if fh then fh:close() 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
--- 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)
assert(type(name) == "string")
name = 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
return temp_dir
else
return nil
end
end
--- Run the given command, quoting its arguments.
-- The command is executed in the current directory in the dir stack.
-- @param command string: The command to be executed. No quoting/escaping
-- is applied.
-- @param ... Strings containing additional arguments, which are quoted.
-- @return boolean: true if command succeeds (status code 0), false
-- otherwise.
function execute(command, ...)
assert(type(command) == "string")
for _, arg in ipairs({...}) do
assert(type(arg) == "string")
command = command .. " " .. fs.Q(arg)
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
-- or if it could not perform the check for any reason.
function check_md5(file, md5sum)
file = normalize(file)
local computed = fs.get_md5(file)
if not computed then
return false
end
if computed:match("^"..md5sum) then
return true
else
return false
end
end
---------------------------------------------------------------------
-- LuaFileSystem functions
---------------------------------------------------------------------
if lfs_ok then
--- Run the given command.
-- The command is executed in the current directory in the dir stack.
-- @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(cmd)
if code == 0 or code == true then
return true
else
return false
end
end
--- Obtain current directory.
-- Uses the module's internal dir stack.
-- @return string: the absolute pathname of the current directory.
function current_dir()
return lfs.currentdir()
end
--- Change the current directory.
-- Uses the module's internal dir stack. This does not have exact
-- 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)
table.insert(dir_stack, lfs.currentdir())
d = normalize(d)
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()
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()
local d = table.remove(dir_stack)
if d then
lfs.chdir(d)
return true
else
return false
end
end
--- Create a directory if it does not already exist.
-- If any of the higher levels in the path name does 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)
assert(type(directory) == "string")
directory = normalize(directory)
local path = nil
if directory:sub(2, 2) == ":" then
path = directory:sub(1, 2)
directory = directory:sub(4)
else
if directory:match("^/") then
path = ""
end
end
for d in directory:gmatch("([^"..dir.separator.."]+)"..dir.separator.."*") do
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
end
elseif mode ~= "directory" then
return false
end
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 d string: pathname of directory to remove.
function remove_dir_if_empty(d)
assert(d)
d = normalize(d)
lfs.rmdir(d)
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 d string: pathname of directory to remove.
function remove_dir_tree_if_empty(d)
assert(d)
d = normalize(d)
for i=1,10 do
lfs.rmdir(d)
d = dir.dir_name(d)
end
end
--- Copy a file.
-- @param src string: Pathname of source
-- @param dest string: Pathname of destination
-- @param perms string or nil: Permissions for destination file,
-- 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)
assert(src and dest)
src = normalize(src)
dest = normalize(dest)
local destmode = lfs.attributes(dest, "mode")
if destmode == "directory" then
dest = dir.path(dest, dir.base_name(src))
end
if not perms then perms = fs.get_permissions(src) end
local src_h, err = io.open(src, "rb")
if not src_h then return nil, err end
local dest_h, err = io.open(dest, "wb+")
if not dest_h then src_h:close() return nil, err end
while true do
local block = src_h:read(8192)
if not block then break end
dest_h:write(block)
end
src_h:close()
dest_h:close()
fs.chmod(dest, perms)
return true
end
--- Implementation function for recursive copy of directory contents.
-- Assumes paths are normalized.
-- @param src string: Pathname of source
-- @param dest string: Pathname of destination
-- @return boolean or (boolean, string): true on success, false on failure
local function recursive_copy(src, dest)
local srcmode = lfs.attributes(src, "mode")
if srcmode == "file" then
local ok = fs.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)
for file in lfs.dir(src) do
if file ~= "." and file ~= ".." then
local ok = recursive_copy(dir.path(src, file), subdir)
if not ok then return false end
end
end
end
return true
end
--- Recursively copy the contents of a directory.
-- @param src string: Pathname of source
-- @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)
assert(src and dest)
src = normalize(src)
dest = normalize(dest)
assert(lfs.attributes(src, "mode") == "directory")
for file in lfs.dir(src) do
if file ~= "." and file ~= ".." then
local ok = recursive_copy(dir.path(src, file), dest)
if not ok then
return false, "Failed copying "..src.." to "..dest
end
end
end
return true
end
--- Implementation function for recursive removal of directories.
-- Assumes paths are normalized.
-- @param name string: Pathname of file
-- @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
for file in lfs.dir(name) do
if file ~= "." and file ~= ".." then
local ok, err = recursive_delete(dir.path(name, file))
if not ok then return nil, err end
end
end
local ok, err = lfs.rmdir(name)
if not ok then return nil, err end
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)
name = normalize(name)
return recursive_delete(name) or false
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 = normalize(at)
if not fs.is_dir(at) then
return {}
end
local result = {}
for file in lfs.dir(at) do
if file ~= "." and file ~= ".." then
table.insert(result, file)
end
end
return result
end
--- Implementation function for recursive find.
-- Assumes paths are normalized.
-- @param cwd string: Current working directory in recursion.
-- @param prefix string: Auxiliary prefix string to form pathname.
-- @param result table: Array of strings where results are collected.
local function recursive_find(cwd, prefix, result)
for file in lfs.dir(cwd) do
if file ~= "." and file ~= ".." then
local item = prefix .. file
table.insert(result, item)
local pathname = dir.path(cwd, file)
if lfs.attributes(pathname, "mode") == "directory" then
recursive_find(pathname, item..dir_separator, result)
end
end
end
end
--- Recursively scan the contents of a directory.
-- @param at string or nil: directory to scan (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 find(at)
assert(type(at) == "string" or not at)
if not at then
at = fs.current_dir()
end
at = normalize(at)
if not fs.is_dir(at) then
return {}
end
local result = {}
recursive_find(at, "", result)
return result
end
--- Test for existance of a file.
-- @param file string: filename to test
-- @return boolean: true if file exists, false otherwise.
function exists(file)
assert(file)
file = normalize(file)
return type(lfs.attributes(file)) == "table"
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)
assert(file)
file = normalize(file)
return lfs.attributes(file, "mode") == "directory"
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)
assert(file)
file = normalize(file)
return lfs.attributes(file, "mode") == "file"
end
function set_time(file, time)
file = normalize(file)
return lfs.touch(file, time)
end
end
---------------------------------------------------------------------
-- LuaZip functions
---------------------------------------------------------------------
if zip_ok then
function zip(zipfile, ...)
return lrzip.zip(zipfile, ...)
end
end
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)
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))
else
local rf, err = zipfile:open(file.filename)
if not rf then zipfile:close(); return nil, err end
local contents = rf:read("*a")
rf:close()
local wf, err = io.open(dir.path(fs.current_dir(), file.filename), "wb")
if not wf then zipfile:close(); return nil, err end
wf:write(contents)
wf:close()
end
file = files()
until not file
zipfile:close()
return true
end
end
---------------------------------------------------------------------
-- LuaSocket functions
---------------------------------------------------------------------
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 result = {}
local res, status, headers, err = http.request { url = url, proxy = cfg.proxy, redirect = false, sink = ltn12.sink.table(result) }
if not res then
return nil, status
elseif status == 301 or status == 302 then
local location = headers.location
if location then
local protocol, rest = dir.split_url(location)
if redirect_protocols[protocol] then
if not loop_control then
loop_control = {}
elseif loop_control[location] then
return nil, "Redirection loop -- broken URL?"
end
loop_control[url] = true
return http_request(location, redirect_protocols[protocol], loop_control)
else
return nil, "URL redirected to unsupported protocol - install luasec to get HTTPS support."
end
end
return nil, err
elseif status ~= 200 then
return nil, err
else
return table.concat(result)
end
end
--- 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)
assert(type(url) == "string")
assert(type(filename) == "string" or not filename)
filename = dir.path(fs.current_dir(), filename or dir.base_name(url))
local content, err
if util.starts_with(url, "http:") then
content, err = http_request(url, http)
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)
else
err = "Unsupported protocol - install luasec to get HTTPS support."
end
else
err = "Unsupported protocol"
end
if not content then
return false, tostring(err)
end
local file = io.open(filename, "wb")
if not file then return false end
file:write(content)
file:close()
return true
end
end
---------------------------------------------------------------------
-- MD5 functions
---------------------------------------------------------------------
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)
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
end
end
---------------------------------------------------------------------
-- POSIX functions
---------------------------------------------------------------------
if posix_ok then
local octal_to_rwx = {
["0"] = "---",
["1"] = "--x",
["2"] = "-w-",
["3"] = "-wx",
["4"] = "r--",
["5"] = "r-x",
["6"] = "rw-",
["7"] = "rwx",
}
function chmod(file, mode)
-- LuaPosix (as of 5.1.15) does not support octal notation...
if mode:sub(1,1) == "0" then
local new_mode = {}
for c in mode:sub(2):gmatch(".") do
table.insert(new_mode, octal_to_rwx[c])
end
mode = table.concat(new_mode)
end
local err = posix.chmod(file, mode)
return err == 0
end
function get_permissions(file)
return posix.stat(file, "mode")
end
end
---------------------------------------------------------------------
-- Other functions
---------------------------------------------------------------------
--- 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)
local p, all_ok = patch.read_patch(patchname, patchdata)
if not all_ok then
return nil, "Failed reading patch "..patchname
end
if p then
return patch.apply_patch(p, 1)
end
end
--- Move a file.
-- @param src string: Pathname of source
-- @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)
assert(src and dest)
if fs.exists(dest) and not fs.is_dir(dest) then
return false, "File already exists: "..dest
end
local ok, err = fs.copy(src, dest)
if not ok then
return false, err
end
ok = fs.delete(src)
if not ok then
return false, "Failed move: could not delete "..src.." after copy."
end
return true
end
--- Check if user has write permissions for the command.
-- Assumes the configuration variables under cfg have been previously set up.
-- @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)
local root_dir = path.root_dir(cfg.rocks_dir)
local ok = true
local err = ""
for _, dir in ipairs { cfg.rocks_dir, root_dir, dir.dir_name(root_dir) } do
if fs.exists(dir) and not fs.is_writable(dir) then
ok = false
err = "Your user does not have write permissions in " .. dir
break
end
end
if ok then
return true
else
if flags["local"] then
err = err .. " \n-- please check your permissions."
else
err = err .. " \n-- you may want to run as a privileged user or use your local tree with --local."
end
return nil, err
end
end
luarocks-2.0.9/src/luarocks/command_line.lua 0000644 0001750 0000144 00000011471 11757524226 020316 0 ustar hisham users
--- Functions for command-line scripts.
module("luarocks.command_line", package.seeall)
local util = require("luarocks.util")
local cfg = require("luarocks.cfg")
local fs = require("luarocks.fs")
local path = require("luarocks.path")
local dir = require("luarocks.dir")
--- Display an error message and exit.
-- @param message string: The error message.
local function die(message)
assert(type(message) == "string")
local ok, err = pcall(util.run_scheduled_functions)
if not ok then
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)
end
local function is_writable(tree)
if type(tree) == "string" then
return fs.make_dir(tree) and fs.is_writable(tree)
else
writable = true
for k, v in pairs(tree) do
writable = writable and fs.make_dir(v) and fs.is_writable(v)
end
return writable
end
end
--- Main command-line processor.
-- Parses input arguments and calls the appropriate driver function
-- to execute the action requested on the command-line, forwarding
-- to it any additional arguments passed by the user.
-- Uses the global table "commands", which contains
-- the loaded modules representing commands.
-- @param ... string: Arguments given on the command-line.
function run_command(...)
local args = {...}
local cmdline_vars = {}
for i = #args, 1, -1 do
local arg = args[i]
if arg:match("^[^-][^=]*=") then
local var, val = arg:match("^([A-Z_][A-Z0-9_]*)=(.*)")
if val then
cmdline_vars[var] = val
table.remove(args, i)
else
die("Invalid assignment: "..arg)
end
end
end
local nonflags = { util.parse_flags(unpack(args)) }
local flags = table.remove(nonflags, 1)
if flags["from"] then flags["server"] = flags["from"] end
if flags["only-from"] then flags["only-server"] = flags["only-from"] end
if flags["only-sources-from"] then flags["only-sources"] = flags["only-sources-from"] end
if flags["to"] then flags["tree"] = flags["to"] end
cfg.flags = flags
local command
if flags["version"] then
util.printout(program_name.." "..cfg.program_version)
util.printout(program_description)
util.printout()
os.exit(0)
elseif flags["help"] or #nonflags == 0 then
command = "help"
args = nonflags
else
command = nonflags[1]
for i, arg in ipairs(args) do
if arg == command then
table.remove(args, i)
break
end
end
end
command = command:gsub("-", "_")
if flags["extensions"] then
cfg.use_extensions = true
local type_check = require("luarocks.type_check")
type_check.load_extensions()
end
if cfg.local_by_default then
flags["local"] = true
end
if flags["tree"] then
if flags["tree"] == true then
die("Argument error: use --tree=")
end
local root_dir = fs.absolute_name(flags["tree"])
path.use_tree(root_dir)
elseif flags["local"] then
path.use_tree(cfg.home_tree)
else
local trees = cfg.rocks_trees
path.use_tree(trees[#trees])
end
if type(cfg.root_dir) == "string" then
cfg.root_dir = cfg.root_dir:gsub("/+$", "")
else
cfg.root_dir.root = cfg.root_dir.root:gsub("/+$", "")
end
cfg.rocks_dir = cfg.rocks_dir:gsub("/+$", "")
cfg.deploy_bin_dir = cfg.deploy_bin_dir:gsub("/+$", "")
cfg.deploy_lua_dir = cfg.deploy_lua_dir:gsub("/+$", "")
cfg.deploy_lib_dir = cfg.deploy_lib_dir:gsub("/+$", "")
cfg.variables.ROCKS_TREE = cfg.rocks_dir
cfg.variables.SCRIPTS_DIR = cfg.deploy_bin_dir
if flags["server"] then
if flags["server"] == true then
die("Argument error: use --server=")
end
local protocol, path = dir.split_url(flags["server"])
table.insert(cfg.rocks_servers, 1, protocol.."://"..path)
end
if flags["only-server"] then
if flags["only-server"] == true then
die("Argument error: use --only-server=")
end
cfg.rocks_servers = { flags["only-server"] }
end
if flags["only-sources"] then
cfg.only_sources_from = flags["only-sources"]
end
if command ~= "help" then
for k, v in pairs(cmdline_vars) do
cfg.variables[k] = v
end
end
if commands[command] then
local xp, ok, err = xpcall(function() return commands[command].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)
end
else
die("Unknown command: "..command)
end
util.run_scheduled_functions()
end
luarocks-2.0.9/src/luarocks/deps.lua 0000644 0001750 0000144 00000056607 11757524226 016636 0 ustar hisham users
--- Dependency handling functions.
-- Dependencies are represented in LuaRocks through strings with
-- a package name followed by a comma-separated list of constraints.
-- Each constraint consists of an operator and a version number.
-- In this string format, version numbers are represented as
-- naturally as possible, like they are used by upstream projects
-- (e.g. "2.0beta3"). Internally, LuaRocks converts them to a purely
-- numeric representation, allowing comparison following some
-- "common sense" heuristics. The precise specification of the
-- comparison criteria is the source code of this module, but the
-- test/test_deps.lua file included with LuaRocks provides some
-- insights on what these criteria are.
module("luarocks.deps", package.seeall)
local cfg = require("luarocks.cfg")
local manif_core = require("luarocks.manif_core")
local path = require("luarocks.path")
local dir = require("luarocks.dir")
local util = require("luarocks.util")
local operators = {
["=="] = "==",
["~="] = "~=",
[">"] = ">",
["<"] = "<",
[">="] = ">=",
["<="] = "<=",
["~>"] = "~>",
-- plus some convenience translations
[""] = "==",
["="] = "==",
["!="] = "~="
}
local deltas = {
scm = 1000,
cvs = 1000,
rc = -1000,
pre = -10000,
beta = -100000,
alpha = -1000000
}
local version_mt = {
--- Equality comparison for versions.
-- All version numbers must be equal.
-- If both versions have revision numbers, they must be equal;
-- otherwise the revision number is ignored.
-- @param v1 table: version table to compare.
-- @param v2 table: version table to compare.
-- @return boolean: true if they are considered equivalent.
__eq = function(v1, v2)
if #v1 ~= #v2 then
return false
end
for i = 1, #v1 do
if v1[i] ~= v2[i] then
return false
end
end
if v1.revision and v2.revision then
return (v1.revision == v2.revision)
end
return true
end,
--- Size comparison for versions.
-- All version numbers are compared.
-- If both versions have revision numbers, they are compared;
-- otherwise the revision number is ignored.
-- @param v1 table: version table to compare.
-- @param v2 table: version table to compare.
-- @return boolean: true if v1 is considered lower than v2.
__lt = function(v1, v2)
for i = 1, math.max(#v1, #v2) do
local v1i, v2i = v1[i] or 0, v2[i] or 0
if v1i ~= v2i then
return (v1i < v2i)
end
end
if v1.revision and v2.revision then
return (v1.revision < v2.revision)
end
return false
end
}
local version_cache = {}
setmetatable(version_cache, {
__mode = "kv"
})
--- Parse a version string, converting to table format.
-- A version table contains all components of the version string
-- converted to numeric format, stored in the array part of the table.
-- If the version contains a revision, it is stored numerically
-- in the 'revision' field. The original string representation of
-- the string is preserved in the 'string' field.
-- Returned version tables use a metatable
-- allowing later comparison through relational operators.
-- @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)
if not vstring then return nil end
assert(type(vstring) == "string")
local cached = version_cache[vstring]
if cached then
return cached
end
local version = {}
local i = 1
local function add_token(number)
version[i] = version[i] and version[i] + number/100000 or number
i = i + 1
end
-- trim leading and trailing spaces
vstring = vstring:match("^%s*(.*)%s*$")
version.string = vstring
-- store revision separately if any
local main, revision = vstring:match("(.*)%-(%d+)$")
if revision then
vstring = main
version.revision = tonumber(revision)
end
while #vstring > 0 do
-- extract a number
local token, rest = vstring:match("^(%d+)[%.%-%_]*(.*)")
if token then
add_token(tonumber(token))
else
-- extract a word
token, rest = vstring:match("^(%a+)[%.%-%_]*(.*)")
if not token then
util.printerr("Warning: version number '"..vstring.."' could not be parsed.")
version[i] = 0
break
end
local last = #version
version[i] = deltas[token] or (token:byte() / 1000)
end
vstring = rest
end
setmetatable(version, version_mt)
version_cache[vstring] = version
return version
end
--- Utility function to compare version numbers given as strings.
-- @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)
end
--- Consumes a constraint from a string, converting it to table format.
-- For example, a string ">= 1.0, > 2.0" is converted to a table in the
-- format {op = ">=", version={1,0}} and the rest, "> 2.0", is returned
-- back to the caller.
-- @param input string: A list of constraints in string format.
-- @return (table, string) or nil: A table representing the same
-- constraints and the string with the unused input, or nil if the
-- input string is invalid.
local function parse_constraint(input)
assert(type(input) == "string")
local no_upgrade, op, version, rest = input:match("^(@?)([<>=~!]*)%s*([%w%.%_%-]+)[%s,]*(.*)")
op = operators[op]
version = parse_version(version)
if not op or not version then return nil end
return { op = op, version = version, no_upgrade = no_upgrade=="@" and true or nil }, rest
end
--- Convert a list of constraints from string to table format.
-- For example, a string ">= 1.0, < 2.0" is converted to a table in the format
-- {{op = ">=", version={1,0}}, {op = "<", version={2,0}}}.
-- Version tables use a metatable allowing later comparison through
-- relational operators.
-- @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)
assert(type(input) == "string")
local constraints, constraint = {}, nil
while #input > 0 do
constraint, input = parse_constraint(input)
if constraint then
table.insert(constraints, constraint)
else
return nil
end
end
return constraints
end
--- Convert a dependency from string to table format.
-- For example, a string "foo >= 1.0, < 2.0"
-- is converted to a table in the format
-- {name = "foo", constraints = {{op = ">=", version={1,0}},
-- {op = "<", version={2,0}}}}. Version tables use a metatable
-- allowing later comparison through relational operators.
-- @param dep string: A dependency in string format
-- 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)
assert(type(dep) == "string")
local name, rest = dep:match("^%s*([a-zA-Z][a-zA-Z0-9%.%-%_]*)%s*(.*)")
if not name then return nil end
local constraints = parse_constraints(rest)
if not constraints then return nil end
return { name = name, constraints = constraints }
end
--- Convert a version table to a string.
-- @param v table: The version table
-- @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)
assert(type(v) == "table")
assert(type(internal) == "boolean" or not internal)
return (internal
and table.concat(v, ":")..(v.revision and tostring(v.revision) or "")
or v.string)
end
--- Convert a dependency in table format to a string.
-- @param dep table: The dependency in table format
-- @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)
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))
end
return dep.name.." "..table.concat(pretty, ", ")
end
--- A more lenient check for equivalence between versions.
-- This returns true if the requested components of a version
-- match and ignore the ones that were not given. For example,
-- when requesting "2", then "2", "2.1", "2.3.5-9"... all match.
-- When requesting "2.1", then "2.1", "2.1.3" match, but "2.2"
-- doesn't.
-- @param version string or table: Version to be tested; may be
-- in string format or already parsed into a table.
-- @param requested string or table: Version requested; may be
-- in string format or already parsed into a table.
-- @return boolean: True if the tested version matches the requested
-- version, false otherwise.
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 not version or not requested then return false end
for i, ri in ipairs(requested) do
local vi = version[i] or 0
if ri ~= vi then return false end
end
if requested.revision then
return requested.revision == version.revision
end
return true
end
--- Check if a version satisfies a set of constraints.
-- @param version table: A version in table format
-- @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)
assert(type(version) == "table")
assert(type(constraints) == "table")
local ok = true
setmetatable(version, version_mt)
for _, constr in pairs(constraints) do
local constr_version = constr.version
setmetatable(constr.version, version_mt)
if constr.op == "==" then ok = version == constr_version
elseif constr.op == "~=" then ok = version ~= constr_version
elseif constr.op == ">" then ok = version > constr_version
elseif constr.op == "<" then ok = version < constr_version
elseif constr.op == ">=" then ok = version >= constr_version
elseif constr.op == "<=" then ok = version <= constr_version
elseif constr.op == "~>" then ok = partial_match(version, constr_version)
end
if not ok then break end
end
return ok
end
--- Attempt to match a dependency to an installed rock.
-- @param dep table: A dependency parsed in table format.
-- @param blacklist table: Versions that can't be accepted. Table where keys
-- are program versions and values are 'true'.
-- @return table or nil: A table containing fields 'name' and 'version'
-- representing an installed rock which matches the given dependency,
-- or nil if it could not be matched.
local function match_dep(dep, blacklist)
assert(type(dep) == "table")
local versions
if dep.name == "lua" then
versions = { cfg.lua_version }
else
versions = manif_core.get_versions(dep.name)
end
if not versions then
return nil
end
if blacklist then
local i = 1
while versions[i] do
if blacklist[versions[i]] then
table.remove(versions, i)
else
i = i + 1
end
end
end
local candidates = {}
for _, vstring in ipairs(versions) do
local version = parse_version(vstring)
if match_constraints(version, dep.constraints) then
table.insert(candidates, version)
end
end
if #candidates == 0 then
return nil
else
table.sort(candidates)
return {
name = dep.name,
version = candidates[#candidates].string
}
end
end
--- Attempt to match dependencies of a rockspec to installed rocks.
-- @param rockspec table: The rockspec loaded as a table.
-- @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
-- 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)
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)
if found then
if dep.name ~= "lua" then
matched[dep] = found
end
else
if dep.constraints[1] and dep.constraints[1].no_upgrade then
no_upgrade[dep.name] = dep
else
missing[dep.name] = dep
end
end
end
return matched, missing, no_upgrade
end
--- Return a set of values of a table.
-- @param tbl table: The input table.
-- @return table: The array of keys.
local function values_set(tbl)
local set = {}
for _, v in pairs(tbl) do
set[v] = true
end
return set
end
--- Check dependencies of a rock and attempt to install any missing ones.
-- Packages are installed using the LuaRocks "install" command.
-- Aborts the program if a dependency could not be fulfilled.
-- @param rockspec table: A rockspec in table format.
-- @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)
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)
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
return nil, "This rockspec for "..rockspec.package.." does not support "..plat.." platforms."
end
else
if platforms_set[plat] then
supported = true
else
if supported == nil then
supported = false
end
end
end
end
if supported == false then
local plats = table.concat(cfg.platforms, ", ")
return nil, "This rockspec for "..rockspec.package.." does not support "..plats.." platforms."
end
end
local matched, missing, no_upgrade = match_deps(rockspec)
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))
end
if next(missing) then
for _, dep in pairs(missing) do
util.printerr(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("automatically. Please upgrade "..dep.name.." with")
util.printerr(" luarocks install "..dep.name)
util.printerr("or choose an older version of "..rockspec.name.." with")
util.printerr(" luarocks search "..rockspec.name)
end
return nil, "Failed matching dependencies."
end
if next(missing) then
util.printerr()
util.printerr("Missing dependencies for "..rockspec.name..":")
for _, dep in pairs(missing) do
util.printerr(show_dep(dep))
end
util.printerr()
for _, dep in pairs(missing) do
-- Double-check in case dependency was filled during recursion.
if not match_dep(dep) then
local rock = search.find_suitable_rock(dep)
if not rock then
return nil, "Could not satisfy dependency: "..show_dep(dep)
end
local ok, err, errcode = install.run(rock)
if not ok then
return nil, "Failed installing dependency: "..rock.." - "..err, errcode
end
end
end
end
return true
end
--- Set up path-related variables for external dependencies.
-- For each key in the external_dependencies table in the
-- rockspec file, four variables are created: _DIR, _BINDIR,
-- _INCDIR and _LIBDIR. These are not overwritten
-- if already set (e.g. by the LuaRocks config file or through the
-- command-line). Values in the external_dependencies table
-- are tables that may contain a "header" or a "library" field,
-- with filenames to be tested for existence.
-- @param rockspec table: The rockspec table.
-- @param mode string: if "build" is given, checks all files;
-- 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)
assert(type(rockspec) == "table")
local fs = require("luarocks.fs")
local vars = rockspec.variables
local patterns = cfg.external_deps_patterns
local subdirs = cfg.external_deps_subdirs
if mode == "install" then
patterns = cfg.runtime_external_deps_patterns
subdirs = cfg.runtime_external_deps_subdirs
end
if rockspec.external_dependencies then
for name, files in pairs(rockspec.external_dependencies) do
local ok = true
local failed_file = nil
local failed_dirname = nil
for _, extdir in ipairs(cfg.external_deps_dirs) do
ok = true
local prefix = vars[name.."_DIR"]
local dirs = {
BINDIR = { subdir = subdirs.bin, testfile = "program", pattern = patterns.bin },
INCDIR = { subdir = subdirs.include, testfile = "header", pattern = patterns.include },
LIBDIR = { subdir = subdirs.lib, testfile = "library", pattern = patterns.lib }
}
if mode == "install" then
dirs.INCDIR = nil
end
if not prefix then
prefix = extdir
end
if type(prefix) == "table" then
if prefix.bin then
dirs.BINDIR.subdir = prefix.bin
end
if prefix.include then
if dirs.INCDIR then
dirs.INCDIR.subdir = prefix.include
end
end
if prefix.lib then
dirs.LIBDIR.subdir = prefix.lib
end
prefix = prefix.prefix
end
for dirname, dirdata in pairs(dirs) do
dirdata.dir = vars[name.."_"..dirname] or dir.path(prefix, dirdata.subdir)
local file = files[dirdata.testfile]
if file then
local files = {}
if not file:match("%.") then
for _, pattern in ipairs(dirdata.pattern) do
table.insert(files, (pattern:gsub("?", file)))
end
else
table.insert(files, file)
end
local found = false
failed_file = nil
for _, f in pairs(files) do
-- small convenience hack
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
end
end
else
found = fs.is_file(dir.path(dirdata.dir, f))
end
if found then
break
else
if failed_file then
failed_file = failed_file .. ", or " .. f
else
failed_file = f
end
end
end
if not found then
ok = false
failed_dirname = dirname
break
end
end
end
if ok then
for dirname, dirdata in pairs(dirs) do
vars[name.."_"..dirname] = dirdata.dir
end
vars[name.."_DIR"] = prefix
break
end
end
if not ok then
return nil, "Could not find expected file "..failed_file.." for "..name.." -- you may have to install "..name.." in your system and/or pass "..name.."_DIR or "..name.."_"..failed_dirname.." to the luarocks command. Example: luarocks install "..rockspec.name.." "..name.."_DIR=/usr/local", "dependency"
end
end
end
return true
end
--- Recursively scan dependencies, to build a transitive closure of all
-- dependent packages.
-- @param results table: The results table being built.
-- @param missing table: The table of missing dependencies being recursively built.
-- @param manifest table: The manifest table containing dependencies.
-- @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)
assert(type(results) == "table")
assert(type(missing) == "table")
assert(type(manifest) == "table")
assert(type(name) == "string")
assert(type(version) == "string")
local fetch = require("luarocks.fetch")
local err
if results[name] then
return results, missing
end
if not manifest.dependencies then manifest.dependencies = {} end
local dependencies = manifest.dependencies
if not dependencies[name] then dependencies[name] = {} end
local dependencies_name = dependencies[name]
local deplist = dependencies_name[version]
local rockspec, err
if not deplist then
rockspec, err = fetch.load_local_rockspec(path.rockspec_file(name, version))
if err then
missing[name.." "..version] = err
return results, missing
end
dependencies_name[version] = rockspec.dependencies
else
rockspec = { dependencies = deplist }
end
local matched, failures = match_deps(rockspec)
for _, match in pairs(matched) do
results, missing = scan_deps(results, missing, manifest, match.name, match.version)
end
if next(failures) then
for _, failure in pairs(failures) do
missing[show_dep(failure)] = "failed"
end
end
results[name] = version
return results, missing
end
luarocks-2.0.9/src/luarocks/refresh_cache.lua 0000644 0001750 0000144 00000001662 11757524227 020454 0 ustar hisham users
--- Module implementing the luarocks-admin "refresh_cache" command.
module("luarocks.refresh_cache", package.seeall)
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=]"
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(...)
local flags = util.parse_flags(...)
local server, upload_server = cache.get_upload_server(flags["server"])
if not server then return nil, upload_server end
local download_url = cache.get_server_urls(server, upload_server)
local ok, err = cache.refresh_local_cache(server, download_url, cfg.upload_user, cfg.upload_password)
if not ok then
return nil, err
else
return true
end
end
luarocks-2.0.9/src/luarocks/cfg.lua 0000644 0001750 0000144 00000034265 11757524226 016436 0 ustar hisham users
--- Configuration for LuaRocks.
-- Tries to load the user's configuration file and
-- defines defaults for unset values. See the
-- config
-- file format documentation for details.
--
-- End-users shouldn't edit this file. They can override any defaults
-- set in this file using their system-wide $LUAROCKS_SYSCONFIG file
-- (see luarocks.site_config) or their user-specific configuration file
-- (~/.luarocks/config.lua on Unix or %APPDATA%/luarocks/config.lua on
-- Windows).
local rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs, package, type, assert, _VERSION =
rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs, package, type, assert, _VERSION
module("luarocks.cfg")
-- Load site-local global configurations
local ok, site_config = pcall(require, "luarocks.site_config")
if not ok then
io.stderr:write("Site-local luarocks/site_config.lua file not found. Incomplete installation?\n")
site_config = {}
end
_M.site_config = site_config
lua_version = _VERSION:sub(5)
program_version = "2.0.8"
user_agent = "LuaRocks/"..program_version
local persist = require("luarocks.persist")
local popen_ok, popen_result = pcall(io.popen, "")
if popen_ok then
if popen_result then
popen_result:close()
end
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)
end
-- System detection:
local detected = {}
local system,proc
-- A proper installation of LuaRocks will hardcode the system
-- and proc values with site_config.LUAROCKS_UNAME_S and site_config.LUAROCKS_UNAME_M,
-- so that this detection does not run every time. When it is
-- performed, we use the Unix way to identify the system,
-- even on Windows (assuming UnxUtils or Cygwin).
system = site_config.LUAROCKS_UNAME_S or io.popen("uname -s"):read("*l")
proc = site_config.LUAROCKS_UNAME_M or io.popen("uname -m"):read("*l")
if proc:match("i[%d]86") then
proc = "x86"
elseif proc:match("amd64") or proc:match("x86_64") then
proc = "x86_64"
elseif proc:match("Power Macintosh") then
proc = "powerpc"
end
if system == "FreeBSD" then
detected.unix = true
detected.freebsd = true
detected.bsd = true
elseif system == "OpenBSD" then
detected.unix = true
detected.openbsd = true
detected.bsd = true
elseif system == "Darwin" then
detected.unix = true
detected.macosx = true
detected.bsd = true
elseif system == "Linux" then
detected.unix = true
detected.linux = true
elseif system == "SunOS" then
detected.unix = true
detected.solaris = true
elseif system and system:match("^CYGWIN") then
detected.unix = true
detected.cygwin = true
elseif system and system:match("^Windows") then
detected.windows = true
elseif system and system:match("^MINGW") then
detected.mingw32 = true
else
detected.unix = true
-- Fall back to Unix in unknown systems.
end
-- Path configuration:
local sys_config_file, home_config_file
local sys_config_ok, home_config_ok = false, false
if detected.windows or detected.mingw32 then
home = os.getenv("APPDATA") or "c:"
sys_config_file = site_config.LUAROCKS_SYSCONFIG or "c:/luarocks/config.lua"
home_config_file = home.."/luarocks/config.lua"
home_tree = home.."/luarocks/"
else
home = os.getenv("HOME") or ""
sys_config_file = site_config.LUAROCKS_SYSCONFIG or "/etc/luarocks/config.lua"
home_config_file = home.."/.luarocks/config.lua"
home_tree = home.."/.luarocks/"
end
variables = {}
rocks_trees = {}
local ok, err = persist.load_into_table(sys_config_file, _M)
if ok then
sys_config_ok = true
else -- nil or false
sys_config_ok = ok
if err and ok == nil then
io.stderr:write(err.."\n")
end
end
if not site_config.LUAROCKS_FORCE_CONFIG then
home_config_file = os.getenv("LUAROCKS_CONFIG") or home_config_file
local home_overrides, err = persist.load_into_table(home_config_file, { home = home })
if home_overrides then
home_config_ok = true
local util = require("luarocks.util")
if home_overrides.rocks_trees then
_M.rocks_trees = nil
end
if home_overrides.rocks_servers then
_M.rocks_servers = nil
end
util.deep_merge(_M, home_overrides)
else -- nil or false
home_config_ok = home_overrides
if err and home_config_ok == nil then
io.stderr:write(err.."\n")
end
end
end
if not next(rocks_trees) then
if home_tree then
table.insert(rocks_trees, home_tree)
end
if site_config.LUAROCKS_ROCKS_TREE then
table.insert(rocks_trees, site_config.LUAROCKS_ROCKS_TREE)
end
end
-- Configure defaults:
local root = rocks_trees[#rocks_trees]
local defaults = {
local_by_default = false,
use_extensions = false,
accept_unknown_fields = false,
lua_modules_path = "/share/lua/"..lua_version,
lib_modules_path = "/lib/lua/"..lua_version,
arch = "unknown",
lib_extension = "unknown",
obj_extension = "unknown",
rocks_servers = {
"http://www.luarocks.org/repositories/rocks"
},
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",
variables = {
MAKE = "make",
CC = "cc",
LD = "ld",
CVS = "cvs",
GIT = "git",
SSCM = "sscm",
SVN = "svn",
HG = "hg",
RSYNC = "rsync",
WGET = "wget",
SCP = "scp",
CURL = "curl",
PWD = "pwd",
MKDIR = "mkdir",
RMDIR = "rmdir",
CP = "cp",
LS = "ls",
RM = "rm",
FIND = "find",
TEST = "test",
CHMOD = "chmod",
PATCH = "patch",
ZIP = "zip",
UNZIP = "unzip",
GUNZIP = "gunzip",
BUNZIP2 = "bunzip2",
TAR = "tar",
MD5SUM = "md5sum",
OPENSSL = "openssl",
MD5 = "md5",
STAT = "stat",
CMAKE = "cmake",
SEVENZ = "7z",
STATFLAG = "-c '%a'",
},
external_deps_subdirs = {
bin = "bin",
lib = "lib",
include = "include"
},
runtime_external_deps_subdirs = {
bin = "bin",
lib = "lib",
include = "include"
},
}
if detected.windows then
home_config_file = home_config_file:gsub("\\","/")
defaults.arch = "win32-"..proc
defaults.platforms = {"win32", "windows" }
defaults.lib_extension = "dll"
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.cmake_generator = "MinGW Makefiles"
defaults.makefile = "Makefile.win"
defaults.variables.MAKE = "nmake" -- TODO: Split Windows flavors between mingw and msvc
defaults.variables.CC = "cl"
defaults.variables.RC = "rc"
defaults.variables.WRAPPER = site_config.LUAROCKS_PREFIX .. "\\2.0\\rclauncher.obj"
defaults.variables.LD = "link"
defaults.variables.MT = "mt"
defaults.variables.LUALIB = "lua"..lua_version..".lib"
defaults.variables.CFLAGS = "/MD /O2"
defaults.variables.LIBFLAG = "/dll"
defaults.variables.LUALIB = "lua"..lua_version..".lib"
defaults.external_deps_patterns = {
bin = { "?.exe", "?.bat" },
lib = { "?.lib", "?.dll", "lib?.dll" },
include = { "?.h" }
}
defaults.runtime_external_deps_patterns = {
bin = { "?.exe", "?.bat" },
lib = { "?.dll", "lib?.dll" },
include = { "?.h" }
}
defaults.export_lua_path = "SET LUA_PATH=%s"
defaults.export_lua_cpath = "SET LUA_CPATH=%s"
defaults.local_cache = home.."/cache/luarocks"
end
if detected.mingw32 then
home_config_file = home_config_file:gsub("\\","/")
defaults.arch = "win32-"..proc
defaults.platforms = { "win32", "mingw32" }
defaults.lib_extension = "dll"
defaults.external_lib_extension = "dll"
defaults.obj_extension = "o"
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.cmake_generator = "MinGW Makefiles"
defaults.make = "mingw32-make" -- TODO: Split Windows flavors between mingw and msvc
defaults.makefile = "Makefile.win"
defaults.variables.CC = "mingw32-gcc"
defaults.variables.RC = "windres"
defaults.variables.WRAPPER = site_config.LUAROCKS_PREFIX .. "\\2.0\\rclauncher.o"
defaults.variables.LD = "mingw32-gcc"
defaults.variables.CFLAGS = "-O2"
defaults.variables.LIBFLAG = "-shared"
defaults.external_deps_patterns = {
bin = { "?.exe", "?.bat" },
lib = { "?.lib", "?.dll", "lib?.dll" },
include = { "?.h" }
}
defaults.runtime_external_deps_patterns = {
bin = { "?.exe", "?.bat" },
lib = { "?.dll", "lib?.dll" },
include = { "?.h" }
}
defaults.export_lua_path = "SET LUA_PATH=%s"
defaults.export_lua_cpath = "SET LUA_CPATH=%s"
defaults.local_cache = home.."/cache/luarocks"
end
if detected.unix then
defaults.lib_extension = "so"
defaults.external_lib_extension = "so"
defaults.obj_extension = "o"
defaults.external_deps_dirs = { "/usr/local", "/usr" }
defaults.variables.LUA_BINDIR = site_config.LUA_BINDIR or "/usr/local/bin"
defaults.variables.LUA_INCDIR = site_config.LUA_INCDIR or "/usr/local/include"
defaults.variables.LUA_LIBDIR = site_config.LUA_LIBDIR or "/usr/local/lib"
defaults.variables.CFLAGS = "-O2"
defaults.cmake_generator = "Unix Makefiles"
defaults.platforms = { "unix" }
defaults.variables.LIBFLAG = "-shared"
defaults.external_deps_patterns = {
bin = { "?" },
lib = { "lib?.a", "lib?.so", "lib?.so.*" },
include = { "?.h" }
}
defaults.runtime_external_deps_patterns = {
bin = { "?" },
lib = { "lib?.so", "lib?.so.*" },
include = { "?.h" }
}
defaults.export_lua_path = "export LUA_PATH='%s'"
defaults.export_lua_cpath = "export LUA_CPATH='%s'"
defaults.local_cache = home.."/.cache/luarocks"
if not defaults.variables.CFLAGS:match("-fPIC") then
defaults.variables.CFLAGS = defaults.variables.CFLAGS.." -fPIC"
end
end
if detected.cygwin then
defaults.lib_extension = "so" -- can be overridden in the config file for mingw builds
defaults.arch = "cygwin-"..proc
defaults.platforms = {"unix", "cygwin"}
defaults.cmake_generator = "Unix Makefiles"
defaults.variables.CC = "echo -llua | xargs gcc"
defaults.variables.LD = "echo -llua | xargs gcc"
defaults.variables.LIBFLAG = "-shared"
end
if detected.bsd then
defaults.variables.STATFLAG = "-f '%Op'"
end
if detected.macosx then
defaults.external_lib_extension = "dylib"
defaults.arch = "macosx-"..proc
defaults.platforms = {"unix", "bsd", "macosx"}
defaults.variables.CC = "export MACOSX_DEPLOYMENT_TARGET=10.3; gcc"
defaults.variables.LD = "export MACOSX_DEPLOYMENT_TARGET=10.3; gcc"
defaults.variables.LIBFLAG = "-bundle -undefined dynamic_lookup -all_load"
defaults.variables.STATFLAG = "-f '%A'"
end
if detected.linux then
defaults.arch = "linux-"..proc
defaults.platforms = {"unix", "linux"}
defaults.variables.CC = "gcc"
defaults.variables.LD = "gcc"
defaults.variables.LIBFLAG = "-shared"
end
if detected.freebsd then
defaults.arch = "freebsd-"..proc
defaults.platforms = {"unix", "bsd", "freebsd"}
defaults.variables.MAKE = "gmake"
defaults.variables.CC = "gcc"
defaults.variables.LD = "gcc"
defaults.variables.LIBFLAG = "-shared"
end
if detected.openbsd then
defaults.arch = "openbsd-"..proc
defaults.platforms = {"unix", "bsd", "openbsd"}
end
if detected.solaris then
defaults.arch = "solaris-"..proc
defaults.platforms = {"unix", "solaris"}
defaults.variables.MAKE = "gmake"
defaults.variables.CC = "gcc"
defaults.variables.LD = "gcc"
end
-- Expose some more values detected by LuaRocks for use by rockspec authors.
defaults.variables.LUA = defaults.lua_interpreter
defaults.variables.LIB_EXTENSION = defaults.lib_extension
defaults.variables.OBJ_EXTENSION = defaults.obj_extension
defaults.variables.LUAROCKS_PREFIX = site_config.LUAROCKS_PREFIX
-- Use defaults:
-- Populate values from 'defaults.variables' in 'variables' if they were not
-- already set by user.
if not _M.variables then
_M.variables = {}
end
for k,v in pairs(defaults.variables) do
if not _M.variables[k] then
_M.variables[k] = v
end
end
-- For values not set in the config file, use values from the 'defaults' table.
local cfg_mt = {
__index = function(t, k)
local default = defaults[k]
if default then
rawset(t, k, default)
end
return default
end
}
setmetatable(_M, cfg_mt)
for _,tree in ipairs(rocks_trees) do
if type(tree) == "string" then
package.path = tree..lua_modules_path.."/?.lua;"..tree..lua_modules_path.."/?/init.lua;"..package.path
package.cpath = tree..lib_modules_path.."/?."..lib_extension..";"..package.cpath
else
package.path = (tree.lua_dir or tree.root..lua_modules_path).."/?.lua;"..
(tree.lua_dir or tree.root..lua_modules_path).."/?/init.lua;"..package.path
package.cpath = (tree.lib_dir or tree.root..lib_modules_path).."/?."..lib_extension..";"..package.cpath
end
end
function which_config()
return sys_config_file, sys_config_ok, home_config_file, home_config_ok
end
--- 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)
assert(type(query) == "string")
for _, platform in ipairs(platforms) do
if platform == query then
return true
end
end
end
luarocks-2.0.9/src/luarocks/require.lua 0000644 0001750 0000144 00000000314 11757524227 017340 0 ustar hisham users --- 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
luarocks-2.0.9/src/luarocks/new_version.lua 0000644 0001750 0000144 00000010647 11757524227 020234 0 ustar hisham users
--- 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)
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")
help_summary = "Auto-write a rockspec for a new version of a rock."
help_arguments = "{|} [] []"
help = [[
This is a utility function that writes a new rockspec, updating data
from a previous one.
If a package name is given, it downloads the latest rockspec from the
default server. If a rockspec is given, it uses it instead.
If the version number is not given, it only increments the revision
number of the given (or downloaded) rockspec.
If a URL is given, it replaces the one from the old rockspec with the
given URL. If a URL is not given and a new version is given, it tries
to guess the new URL by replacing occurrences of the version number
in the URL or tag. It also tries to download the new URL to determine
the new MD5 checksum.
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
end
local old_field = tbl[field]
local new_field = tbl[field]:gsub(old, new)
if new_field ~= old_field then
util.printout("Guessing new '"..field.."' field as "..new_field)
tbl[field] = new_field
return true
end
return false
end
local function check_url_and_update_md5(out_rs, out_name)
out_rs.source.md5 = nil
local file, temp_dir = fetch.fetch_url_at_temp_dir(out_rs.source.url, "luarocks-new-version-"..out_name)
if file then
util.printout("File successfully downloaded. Updating MD5 checksum...")
out_rs.source.md5 = fs.get_md5(file)
else
util.printerr("Warning: invalid URL - "..temp_dir)
end
end
function run(...)
local flags, input, version, url = util.parse_flags(...)
if not input then
return nil, "Missing arguments: expected program or rockspec. See help."
end
assert(type(input) == "string")
local filename = input
if not input:match(".rockspec$") then
local err
filename, err = download.download("rockspec", input)
if not input then
return nil, err
end
end
local valid_rs, err = fetch.load_rockspec(filename)
if not valid_rs then
return nil, err
end
local old_ver, old_rev = valid_rs.version:match("(.*)%-(%d+)$")
local new_ver, new_rev
if version then
new_ver, new_rev = version:match("(.*)%-(%d+)$")
new_rev = tonumber(new_rev)
if not new_rev then
new_ver = version
new_rev = 1
end
else
new_ver = old_ver
new_rev = tonumber(old_rev) + 1
end
local out_rs = persist.load_into_table(filename)
local out_name = out_rs.package:lower()
out_rs.version = new_ver.."-"..new_rev
if url then
out_rs.source.url = url
check_url_and_update_md5(out_rs, out_name)
else
if new_ver ~= old_ver then
local ok = try_replace(out_rs.source, "url", old_ver, new_ver)
if ok then
check_url_and_update_md5(out_rs, out_name)
else
ok = try_replace(out_rs.source, "tag", old_ver, new_ver)
if not ok then
return nil, "Failed to determine the location of the new version."
end
end
end
end
if out_rs.build and out_rs.build.type == "module" then
out_rs.build.type = "builtin"
end
local out_filename = out_name.."-"..new_ver.."-"..new_rev..".rockspec"
persist.save_from_table(out_filename, out_rs, order)
util.printout("Wrote "..out_filename)
local valid_out_rs, err = fetch.load_local_rockspec(out_filename)
if not valid_out_rs then
return nil, "Failed loading generated rockspec: "..err
end
return true
end
luarocks-2.0.9/src/luarocks/manif.lua 0000644 0001750 0000144 00000031561 11757524227 016766 0 ustar hisham users
--- 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)
local manif_core = require("luarocks.manif_core")
local persist = require("luarocks.persist")
local fetch = require("luarocks.fetch")
local dir = require("luarocks.dir")
local fs = require("luarocks.fs")
local search = require("luarocks.search")
local util = require("luarocks.util")
local cfg = require("luarocks.cfg")
local path = require("luarocks.path")
local rep = require("luarocks.rep")
local deps = require("luarocks.deps")
rock_manifest_cache = {}
--- Commit a table to disk in given local path.
-- @param where string: The directory where the table should be saved.
-- @param name string: The filename.
-- @param tbl table: The table to be saved.
-- @return boolean or (nil, string): true if successful, or nil and a
-- message in case of errors.
local function save_table(where, name, tbl)
assert(type(where) == "string")
assert(type(name) == "string")
assert(type(tbl) == "table")
local filename = dir.path(where, name)
return persist.save_from_table(filename, tbl)
end
function 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
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
return rock_manifest.rock_manifest
end
function make_rock_manifest(name, version)
local install_dir = path.install_dir(name, version)
local rock_manifest = path.rock_manifest_file(name, version)
local tree = {}
for _, file in ipairs(fs.find(install_dir)) do
local full_path = dir.path(install_dir, file)
local walk = tree
local last
local last_name
for name in file:gmatch("[^/]+") do
local next = walk[name]
if not next then
next = {}
walk[name] = next
end
last = walk
last_name = name
walk = next
end
if fs.is_file(full_path) then
last[last_name] = fs.get_md5(full_path)
end
end
local rock_manifest = { rock_manifest=tree }
rock_manifest_cache[name.."/"..version] = rock_manifest
save_table(install_dir, "rock_manifest", rock_manifest )
end
--- Load a local or remote manifest describing a repository.
-- All functions that use manifest tables assume they were obtained
-- through either this function or load_local_manifest.
-- @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)
assert(type(repo_url) == "string")
if manif_core.manifest_cache[repo_url] then
return manif_core.manifest_cache[repo_url]
end
local protocol, pathname = dir.split_url(repo_url)
if protocol == "file" then
pathname = dir.path(pathname, "manifest")
else
local url = dir.path(repo_url, "manifest")
local name = repo_url:gsub("[/:]","_")
local file, err, errcode = fetch.fetch_url_at_temp_dir(url, "luarocks-manifest-"..name)
if not file then
return nil, "Failed fetching manifest for "..repo_url..(err and " - "..err or ""), errcode
end
pathname = file
end
return manif_core.manifest_loader(pathname, repo_url)
end
--- Output a table listing items of a package.
-- @param itemsfn function: a function for obtaining items of a package.
-- pkg and version will be passed to it; it should return a table with
-- items as keys.
-- @param pkg string: package name
-- @param version string: package version
-- @param tbl table: the package matching table: keys should be item names
-- and values arrays of strings with packages names in "name/version" format.
local function store_package_items(itemsfn, pkg, version, tbl)
assert(type(itemsfn) == "function")
assert(type(pkg) == "string")
assert(type(version) == "string")
assert(type(tbl) == "table")
local pkg_version = pkg.."/"..version
local result = {}
for item, path in pairs(itemsfn(pkg, version)) do
result[item] = path
if not tbl[item] then
tbl[item] = {}
end
table.insert(tbl[item], pkg_version)
end
return result
end
--- Sort function for ordering rock identifiers in a manifest's
-- modules table. Rocks are ordered alphabetically by name, and then
-- by version which greater first.
-- @param a string: Version to compare.
-- @param b string: Version to compare.
-- @return boolean: The comparison result, according to the
-- rule outlined above.
local function sort_pkgs(a, b)
assert(type(a) == "string")
assert(type(b) == "string")
local na, va = a:match("(.*)/(.*)$")
local nb, vb = b:match("(.*)/(.*)$")
return (na == nb) and deps.compare_versions(va, vb) or na < nb
end
--- Sort items of a package matching table by version number (higher versions first).
-- @param tbl table: the package matching table: keys should be strings
-- and values arrays of strings with packages names in "name/version" format.
local function sort_package_matching_table(tbl)
assert(type(tbl) == "table")
if next(tbl) then
for item, pkgs in pairs(tbl) do
if #pkgs > 1 then
table.sort(pkgs, sort_pkgs)
-- Remove duplicates from the sorted array.
local prev = nil
local i = 1
while pkgs[i] do
local curr = pkgs[i]
if curr == prev then
table.remove(pkgs, i)
else
prev = curr
i = i + 1
end
end
end
end
end
end
--- Process the dependencies of a manifest table to determine its dependency
-- chains for loading modules. The manifest dependencies information is filled
-- and any dependency inconsistencies or missing dependencies are reported to
-- standard error.
-- @param manifest table: a manifest table.
local function update_dependencies(manifest)
for pkg, versions in pairs(manifest.repository) do
for version, repos in pairs(versions) do
local current = pkg.." "..version
for _, repo in ipairs(repos) do
if repo.arch == "installed" then
local missing
repo.dependencies, missing = deps.scan_deps({}, {}, manifest, pkg, version)
repo.dependencies[pkg] = nil
if missing then
for miss, err in pairs(missing) do
if miss == current then
util.printerr("Tree inconsistency detected: "..current.." has no rockspec. "..err)
else
util.printerr("Missing dependency for "..pkg.." "..version..": "..miss)
end
end
end
end
end
end
end
end
--- Store search results in a manifest table.
-- @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.
-- @return boolean or (nil, string): true in case of success, or nil followed by an error message.
local function store_results(results, manifest)
assert(type(results) == "table")
assert(type(manifest) == "table")
for name, versions in pairs(results) do
local pkgtable = manifest.repository[name] or {}
for version, entries in pairs(versions) do
local versiontable = {}
for _, entry in ipairs(entries) do
local entrytable = {}
entrytable.arch = entry.arch
if entry.arch == "installed" then
local rock_manifest = 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
entrytable.modules = store_package_items(rep.package_modules, name, version, manifest.modules)
entrytable.commands = store_package_items(rep.package_commands, name, version, manifest.commands)
end
table.insert(versiontable, entrytable)
end
pkgtable[version] = versiontable
end
manifest.repository[name] = pkgtable
end
update_dependencies(manifest)
sort_package_matching_table(manifest.modules)
sort_package_matching_table(manifest.commands)
return true
end
--- Scan a LuaRocks repository and output a manifest file.
-- A file called 'manifest' will be written in the root of the given
-- repository directory.
-- @param repo A local repository directory.
-- @return boolean or (nil, string): True if manifest was generated,
-- or nil and an error message.
function make_manifest(repo)
assert(type(repo) == "string")
if not fs.is_dir(repo) then
return nil, "Cannot access repository at "..repo
end
local query = search.make_query("")
query.exact_name = false
query.arch = "any"
local results = search.disk_search(repo, query)
local manifest = { repository = {}, modules = {}, commands = {} }
manif_core.manifest_cache[repo] = manifest
local ok, err = store_results(results, manifest)
if not ok then return nil, err end
return save_table(repo, "manifest", manifest)
end
--- Load a manifest file from a local repository and add to the repository
-- information with regard to the given name and version.
-- A file called 'manifest' will be written in the root of the given
-- repository directory.
-- @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.
-- @return boolean or (nil, string): True if manifest was generated,
-- or nil and an error message.
function update_manifest(name, version, repo)
assert(type(name) == "string")
assert(type(version) == "string")
repo = path.rocks_dir(repo or cfg.root_dir)
util.printout("Updating manifest for "..repo)
local manifest, err = load_manifest(repo)
if not manifest then
util.printerr("No existing manifest. Attempting to rebuild...")
local ok, err = make_manifest(repo)
if not ok then
return nil, err
end
manifest, err = load_manifest(repo)
if not manifest then
return nil, err
end
end
local results = {[name] = {[version] = {{arch = "installed", repo = repo}}}}
local ok, err = store_results(results, manifest)
if not ok then return nil, err end
return save_table(repo, "manifest", manifest)
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?"
end
local deploy_bin = path.deploy_bin_dir(root)
local deploy_lua = path.deploy_lua_dir(root)
local deploy_lib = path.deploy_lib_dir(root)
local key, manifest_tbl
if util.starts_with(file, deploy_lua) then
manifest_tbl = manifest.modules
key = path.path_to_module(file:sub(#deploy_lua+1):gsub("\\", "/"))
elseif util.starts_with(file, deploy_lib) then
manifest_tbl = manifest.modules
key = path.path_to_module(file:sub(#deploy_lib+1):gsub("\\", "/"))
elseif util.starts_with(file, deploy_bin) then
manifest_tbl = manifest.commands
key = file:sub(#deploy_bin+1):gsub("^[\\/]*", "")
else
assert(false, "Assertion failed: '"..file.."' is not a deployed file.")
end
local providers = manifest_tbl[key]
if not providers then
return nil, "untracked"
end
return providers
end
--- Given a path of a deployed file, figure out which rock name and version
-- correspond to it in the tree manifest.
-- @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)
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)
local providers, err = find_providers(file, root)
if not providers then return nil, err end
if providers[2] then
return providers[2]:match("([^/]*)/([^/]*)")
else
return nil
end
end
luarocks-2.0.9/src/luarocks/remove.lua 0000644 0001750 0000144 00000011764 11757524227 017174 0 ustar hisham users
--- Module implementing the LuaRocks "remove" command.
-- Uninstalls rocks.
module("luarocks.remove", package.seeall)
local search = require("luarocks.search")
local deps = require("luarocks.deps")
local fetch = require("luarocks.fetch")
local rep = require("luarocks.rep")
local path = require("luarocks.path")
local util = require("luarocks.util")
local cfg = require("luarocks.cfg")
local manif = require("luarocks.manif")
local fs = require("luarocks.fs")
help_summary = "Uninstall a rock."
help_arguments = "[--force] []"
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.
]]
--- Obtain a list of packages that depend on the given set of packages
-- (where all packages of the set are versions of one program).
-- @param name string: the name of a program
-- @param versions array of string: the versions to be deleted.
-- @return array of string: an empty table if no packages depend on any
-- of the given list, or an array of strings in "name/version" format.
local function check_dependents(name, versions)
local dependents = {}
local blacklist = {}
blacklist[name] = {}
for version, _ in pairs(versions) do
blacklist[name][version] = true
end
local local_rocks = {}
local query_all = search.make_query("")
query_all.exact_name = false
search.manifest_search(local_rocks, cfg.rocks_dir, query_all)
local_rocks[name] = nil
for rock_name, rock_versions in pairs(local_rocks) do
for rock_version, _ in pairs(rock_versions) do
local rockspec, err = fetch.load_rockspec(path.rockspec_file(rock_name, rock_version))
if rockspec then
local _, missing = deps.match_deps(rockspec, blacklist)
if missing[name] then
table.insert(dependents, { name = rock_name, version = rock_version })
end
end
end
end
return dependents
end
--- Delete given versions of a program.
-- @param name string: the name of a program
-- @param versions array of string: the versions to be deleted.
-- @return boolean or (nil, string): true on success or nil and an error message.
local function delete_versions(name, versions)
for version, _ in pairs(versions) do
util.printout("Removing "..name.." "..version.."...")
local ok, err = rep.delete_version(name, version)
if not ok then return nil, err end
end
return true
end
--- Driver function for the "remove" command.
-- @param name string: name of a rock. If a version is given, refer to
-- 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(...)
local flags, name, version = util.parse_flags(...)
if type(name) ~= "string" then
return nil, "Argument missing, see help."
end
local ok, err = fs.check_command_permissions(flags)
if not ok then return nil, err end
local results = {}
search.manifest_search(results, cfg.rocks_dir, search.make_query(name, version))
local versions = results[name]
if not versions then
return nil, "Could not find rock '"..name..(version and " "..version or "").."' in local tree."
else
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)
if #dependents == 0 or flags["force"] then
if #dependents > 0 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)
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 all 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
end
util.printout("Removal successful.")
return true
end
luarocks-2.0.9/src/luarocks/show.lua 0000644 0001750 0000144 00000011344 11757524227 016651 0 ustar hisham users
--- Module implementing the LuaRocks "show" command.
-- Shows information about an installed rock.
module("luarocks.show", package.seeall)
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."
help = [[
is an existing package name.
Without any flags, show all module information.
With these flags, return only the desired information:
--home home page of project
--modules all modules provided by this package as used by require()
--deps packages this package depends on
--rockspec the full path of the rockspec file
--mversion the package version
--tree local tree where rock is installed
--rock-dir data directory of the installed rock
]]
local function keys_as_string(t, sep)
return table.concat(util.keys(t), sep or " ")
end
local function word_wrap(line)
local width = tonumber(os.getenv("COLUMNS")) or 80
if width > 80 then width = 80 end
if #line > width then
local brk = width
while brk > 0 and line:sub(brk, brk) ~= " " do
brk = brk - 1
end
if brk > 0 then
return line:sub(1, brk-1) .. "\n" .. word_wrap(line:sub(brk+1))
end
end
return line
end
local function format_text(text)
text = text:gsub("^%s*",""):gsub("%s$", ""):gsub("\n[ \t]+","\n"):gsub("([^\n])\n([^\n])","%1 %2")
local paragraphs = util.split_string(text, "\n\n")
for n, line in ipairs(paragraphs) do
paragraphs[n] = word_wrap(line)
end
return (table.concat(paragraphs, "\n\n"):gsub("%s$", ""))
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, see help."
end
local results = {}
local query = search.make_query(name, version)
query.exact_name = true
local tree_map = {}
for _, tree in ipairs(cfg.rocks_trees) do
local rocks_dir = path.rocks_dir(tree)
tree_map[rocks_dir] = tree
search.manifest_search(results, rocks_dir, query)
end
if not next(results) then --
return nil,"cannot find package "..name.."\nUse 'list' to find installed rocks"
end
local version,repo_url
local package, versions = util.sortedpairs(results)()
--question: what do we do about multiple versions? This should
--give us the latest version on the last repo (which is usually the global one)
for vs, repos in util.sortedpairs(versions, deps.compare_versions) do
if not version then version = vs end
for _, rp in ipairs(repos) do repo_url = rp.repo end
end
local repo = tree_map[repo_url]
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)
if not rockspec then return nil,err end
local descript = rockspec.description or {}
local manifest, err = manif.load_manifest(repo_url)
if not manifest then return nil,err end
local minfo = manifest.repository[name][version][1]
if flags["tree"] then util.printout(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["deps"] then util.printout(keys_as_string(minfo.dependencies))
elseif flags["rockspec"] then util.printout(rockspec_file)
elseif flags["mversion"] then util.printout(version)
else
util.printout()
util.printout(rockspec.package.." "..rockspec.version.." - "..(descript.summary or ""))
util.printout()
if descript.detailed then
util.printout(format_text(descript.detailed))
util.printout()
end
if descript.license then
util.printout("License: ", descript.license)
end
if descript.homepage then
util.printout("Homepage: ", descript.homepage)
end
util.printout("Installed in: ", repo)
if next(minfo.modules) then
util.printout()
util.printout("Modules:")
util.printout("\t"..keys_as_string(minfo.modules, "\n\t"))
end
if next(minfo.dependencies) then
util.printout()
util.printout("Depends on:")
util.printout("\t"..keys_as_string(minfo.dependencies, "\n\t"))
end
util.printout()
end
return true
end
luarocks-2.0.9/src/luarocks/make.lua 0000644 0001750 0000144 00000005136 11757524227 016610 0 ustar hisham users
--- Module implementing the LuaRocks "make" command.
-- 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)
local build = require("luarocks.build")
local fs = require("luarocks.fs")
local util = require("luarocks.util")
local cfg = require("luarocks.cfg")
local fetch = require("luarocks.fetch")
local pack = require("luarocks.pack")
help_summary = "Compile package in current directory using a rockspec."
help_arguments = "[--pack-binary-rock] []"
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,
look for a rockspec in the current directory. If more than one
is found, you must specify which to use, through the command-line.
This command is useful as a tool for debugging rockspecs.
To install rocks, you'll normally want to use the "install" and
"build" commands. See the help on those for details.
If --pack-binary-rock is passed, the rock is not installed;
instead, a .rock file with the contents of compilation is produced
in the current directory.
]]
--- 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(...)
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
if file:match("rockspec$") then
if rockspec then
return nil, "Please specify which rockspec file to use."
else
rockspec = file
end
end
end
if not rockspec then
return nil, "Argument missing: please specify a rockspec to use on current directory."
end
end
if not rockspec:match("rockspec$") then
return nil, "Invalid argument: 'make' takes a rockspec as a parameter. See help."
end
if flags["pack-binary-rock"] then
local rspec, err, errcode = fetch.load_rockspec(rockspec)
if not rspec then
return nil, err
end
return pack.pack_binary_rock(rspec.name, rspec.version, build.build_rockspec, rockspec, false, true, flags["nodeps"])
else
local ok, err = fs.check_command_permissions(flags)
if not ok then return nil, err end
return build.build_rockspec(rockspec, false, true)
end
end
luarocks-2.0.9/src/luarocks/persist.lua 0000644 0001750 0000144 00000011307 11757524227 017361 0 ustar hisham users
--- Utility module for loading files into tables and
-- 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)
local util = require("luarocks.util")
--- Load a Lua file containing assignments, storing them in a table.
-- The global environment is not propagated to the loaded file.
-- @param filename string: the name of the file.
-- @param tbl table or nil: if given, this table is used to store
-- 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)
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
chunk, err = loadfile(filename)
if chunk then
setfenv(chunk, result)
ran, err = pcall(chunk)
end
else -- Lua 5.2
chunk, err = loadfile(filename, "t", result)
if chunk then
ran, err = pcall(chunk)
end
end
if not chunk then
if err:sub(1,5) ~= filename:sub(1,5) then
return false, err
end
return nil, "Error loading file: "..err
end
if not ran then
return nil, "Error running file: "..err
end
return result
end
local write_table
--- Write a value as Lua code, invoking write_table.
-- This function handles only numbers, strings and tables
-- are keys (tables are handled recursively).
-- @param out userdata: a file object, open for writing.
-- @param v: the value to be written.
-- @param level number: the indentation level
-- @param sub_order table: optional prioritization table
-- @see write_table
local function write_value(out, v, level, sub_order)
if type(v) == "table" then
write_table(out, v, level + 1, sub_order)
elseif type(v) == "string" then
if v:match("\n") then
local open, close = "[[", "]]"
local equals = 0
while v:find(open,1,true) or v:find(close,1,true) do
equals = equals + 1
local eqs = ("="):rep(equals)
open, close = "["..eqs.."[", "]"..eqs.."]"
end
out:write(open.."\n"..v..close)
else
out:write("\""..v:gsub("\"", "\\\"").."\"")
end
else
out:write(tostring(v))
end
end
--- Write a table as Lua code representing a table to disk
-- (that is, in curly brackets notation).
-- This function handles only numbers, strings and tables
-- are keys (tables are handled recursively).
-- @param out userdata: a file object, open for writing.
-- @param tbl table: the table to be written.
-- @param level number: the indentation level
-- @param field_order table: optional prioritization table
write_table = function(out, tbl, level, field_order)
out:write("{")
local sep = "\n"
local indentation = " "
local indent = true
local i = 1
for k, v, sub_order in util.sortedpairs(tbl, field_order) do
out:write(sep)
if indent then
for n = 1,level do out:write(indentation) end
end
sep = ",\n"
indent = true
if type(k) == "number" then
if k ~= i then
out:write("["..tostring(k).."]=")
else
i = i + 1
end
indent = false
sep = ", "
elseif type(k) == "table" then
out:write("[")
write_table(out, k, level + 1)
out:write("] = ")
else
if k:match("^[a-zA-Z_][a-zA-Z0-9_]*$") then
out:write(k.." = ")
else
out:write("['"..k:gsub("'", "\\'").."'] = ")
end
end
write_value(out, v, level, sub_order)
end
if sep ~= "\n" then
out:write("\n")
for n = 1,level-1 do out:write(indentation) end
end
out:write("}")
end
--- Save the contents of a table in a file.
-- Each element of the table is saved as a global assignment.
-- Only numbers, strings and tables (containing numbers, strings
-- or other recursively processed tables) are supported.
-- @param filename string: the output filename
-- @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 boolean or (nil, string): true if successful, or nil and a
-- message in case of errors.
function save_from_table(filename, tbl, field_order)
local out = io.open(filename, "w")
if not out then
return nil, "Cannot create file at "..filename
end
for k, v, sub_order in util.sortedpairs(tbl, field_order) do
out:write(k.." = ")
write_value(out, v, 0, sub_order)
out:write("\n")
end
out:close()
return true
end
luarocks-2.0.9/src/luarocks/manif_core.lua 0000644 0001750 0000144 00000004511 11757524227 017771 0 ustar hisham users
--- Core functions for querying manifest files.
-- This module requires no specific 'fs' functionality.
module("luarocks.manif_core", package.seeall)
local persist = require("luarocks.persist")
local type_check = require("luarocks.type_check")
local dir = require("luarocks.dir")
local util = require("luarocks.util")
local cfg = require("luarocks.cfg")
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)
local manifest, err = persist.load_into_table(file)
if not manifest then
return nil, "Failed loading manifest for "..repo_url..": "..err
end
if not quick then
local ok, err = type_check.type_check_manifest(manifest)
if not ok then
return nil, "Error checking manifest: "..err
end
end
manifest_cache[repo_url] = manifest
return manifest
end
--- Load a local manifest describing a repository.
-- All functions that use manifest tables assume they were obtained
-- through either this function or load_manifest.
-- @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)
assert(type(repo_url) == "string")
if manifest_cache[repo_url] then
return manifest_cache[repo_url]
end
local pathname = dir.path(repo_url, "manifest")
return manifest_loader(pathname, repo_url, true)
end
--- Get all versions of a package listed in a manifest file.
-- @param name string: a package name.
-- @param manifest table or nil: a manifest table; if not given, the
-- default local manifest table is used.
-- @return table: An array of strings listing installed
-- versions of a package.
function get_versions(name, manifest)
assert(type(name) == "string")
assert(type(manifest) == "table" or not manifest)
if not manifest then
manifest = load_local_manifest(cfg.rocks_dir)
if not manifest then
return {}
end
end
local item = manifest.repository[name]
if item then
return util.keys(item)
end
return {}
end
luarocks-2.0.9/src/luarocks/build.lua 0000644 0001750 0000144 00000026442 11757524226 016774 0 ustar hisham users
--- Module implementing the LuaRocks "build" command.
-- Builds a rock, compiling its C parts if any.
module("luarocks.build", package.seeall)
local pack = require("luarocks.pack")
local path = require("luarocks.path")
local util = require("luarocks.util")
local rep = require("luarocks.rep")
local fetch = require("luarocks.fetch")
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local deps = require("luarocks.deps")
local manif = require("luarocks.manif")
local cfg = require("luarocks.cfg")
help_summary = "Build/compile a rock."
help_arguments = "[--pack-binary-rock] {|| []}"
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.
If --pack-binary-rock is passed, the rock is not installed;
instead, a .rock file with the contents of compilation is produced
in the current directory.
]]
--- Install files to a given location.
-- Takes a table where the array part is a list of filenames to be copied.
-- In the hash part, other keys, if is_module_path is set, are identifiers
-- in Lua module format, to indicate which subdirectory the file should be
-- copied to. For example, install_files({["foo.bar"] = "src/bar.lua"}, "boo")
-- will copy src/bar.lua to boo/foo.
-- @param files table or nil: A table containing a list of files to copy in
-- the format described above. If nil is passed, this function is a no-op.
-- Directories should be delimited by forward slashes as in internet URLs.
-- @param location string: The base directory files should be copied to.
-- @param is_module_path boolean: True if string keys in files should be
-- interpreted as dotted module paths.
-- @return boolean or (nil, string): True if succeeded or
-- nil and an error message.
local function install_files(files, location, is_module_path)
assert(type(files) == "table" or not files)
assert(type(location) == "string")
if files then
for k, file in pairs(files) do
local dest = location
if type(k) == "string" then
if is_module_path then
dest = dir.path(location, path.module_to_path(k))
fs.make_dir(dest)
else
dest = dir.path(location, dir.dir_name(k))
fs.make_dir(dest)
dest = dir.path(dest, dir.base_name(k))
end
else
fs.make_dir(dest)
end
local ok = fs.copy(dir.path(file), dest)
if not ok then
return nil, "Failed copying "..file
end
end
end
return true
end
--- Write to the current directory the contents of a table,
-- where each key is a file name and its value is the file content.
-- @param files table: The table of files to be written.
local function extract_from_rockspec(files)
for name, content in pairs(files) do
local fd = io.open(dir.path(fs.current_dir(), name), "w+")
fd:write(content)
fd:close()
end
end
--- Applies patches inlined in the build.patches section
-- and extracts files inlined in the build.extra_files section
-- of a rockspec.
-- @param rockspec table: A rockspec table.
-- @return boolean or (nil, string): True if succeeded or
-- nil and an error message.
function apply_patches(rockspec)
assert(type(rockspec) == "table")
local build = rockspec.build
if build.extra_files then
extract_from_rockspec(build.extra_files)
end
if build.patches then
extract_from_rockspec(build.patches)
for patch, patchdata in util.sortedpairs(build.patches) do
util.printout("Applying patch "..patch.."...")
local ok, err = fs.apply_patch(tostring(patch), patchdata)
if not ok then
return nil, "Failed applying patch "..patch
end
end
end
return true
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,
-- false if the rockspec was obtained from inside a source rock.
-- @param minimal_mode boolean: true if there's no need to fetch,
-- unpack or change dir (this is used by "luarocks make"). Implies
-- need_to_fetch = false.
-- @param no_deps boolean: true if dependency check needs to be skipped
-- @return boolean or (nil, string, [string]): True if succeeded or
-- nil and an error message followed by an error code.
function build_rockspec(rockspec_file, need_to_fetch, minimal_mode, no_deps)
assert(type(rockspec_file) == "string")
assert(type(need_to_fetch) == "boolean")
local rockspec, err, errcode = fetch.load_rockspec(rockspec_file)
if err then
return nil, err, errcode
elseif not rockspec.build then
return nil, "Rockspec error: build table not specified"
elseif not rockspec.build.type then
return nil, "Rockspec error: build type not specified"
end
if no_deps then
util.printerr("Warning: skipping dependency checks.")
else
local ok, err, errcode = deps.fulfill_dependencies(rockspec)
if err then
return nil, err, errcode
end
end
ok, err, errcode = deps.check_external_deps(rockspec, "build")
if err then
return nil, err, errcode
end
local name, version = rockspec.name, rockspec.version
if rep.is_installed(name, version) then
rep.delete_version(name, version)
end
if not minimal_mode then
local _, source_dir
if need_to_fetch then
ok, source_dir, errcode = fetch.fetch_sources(rockspec, true)
if not ok then
return nil, source_dir, errcode
end
fs.change_dir(source_dir)
elseif rockspec.source.file then
local ok, err = fs.unpack_archive(rockspec.source.file)
if not ok then
return nil, err
end
end
fs.change_dir(rockspec.source.dir)
end
local dirs = {
lua = { name = path.lua_dir(name, version), is_module_path = true },
lib = { name = path.lib_dir(name, version), is_module_path = true },
conf = { name = path.conf_dir(name, version), is_module_path = false },
bin = { name = path.bin_dir(name, version), is_module_path = false },
}
for _, d in pairs(dirs) do
fs.make_dir(d.name)
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
if not minimal_mode then
ok, err = apply_patches(rockspec)
if err then
return nil, err
end
end
if build.type ~= "none" then
-- Temporary compatibility
if build.type == "module" then
util.printout("Do not use 'module' as a build type. Use 'builtin' instead.")
build.type = "builtin"
end
local build_type
ok, build_type = pcall(require, "luarocks.build." .. build.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
end
ok, err = build_type.run(rockspec)
if not ok then
return nil, "Build error: " .. err
end
end
if build.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)
if not ok then
return nil, err
end
end
end
local copy_directories = build.copy_directories or {"doc"}
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)
end
end
for _, d in pairs(dirs) do
fs.remove_dir_if_empty(d.name)
end
fs.pop_dir()
fs.copy(rockspec.local_filename, path.rockspec_file(name, version))
if need_to_fetch then
fs.pop_dir()
end
ok, err = manif.make_rock_manifest(name, version)
if err then return nil, err end
ok, err = rep.deploy_files(name, version, rep.should_wrap_bin_scripts(rockspec))
if err then return nil, err end
util.remove_scheduled_function(rollback)
rollback = util.schedule_function(function()
rep.delete_version(name, version)
end)
ok, err = rep.run_hook(rockspec, "post_install")
if err then return nil, err end
ok, err = manif.update_manifest(name, version)
if err then return nil, err end
local license = ""
if rockspec.description and rockspec.description.license then
license = ("(license: "..rockspec.description.license..")")
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.remove_scheduled_function(rollback)
return true
end
--- Build and install a rock.
-- @param rock_file string: local or remote filename of a rock.
-- @param need_to_fetch boolean: true if sources need to be fetched,
-- false if the rockspec was obtained from inside a source rock.
-- @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, no_deps)
assert(type(rock_file) == "string")
assert(type(need_to_fetch) == "boolean")
local unpack_dir, err, errcode = fetch.fetch_and_unpack_rock(rock_file)
if not unpack_dir then
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, no_deps)
fs.pop_dir()
return ok, err, errcode
end
local function do_build(name, version, no_deps)
if name:match("%.rockspec$") then
return build_rockspec(name, true, false, no_deps)
elseif name:match("%.src%.rock$") then
return build_rock(name, false, no_deps)
elseif name:match("%.all%.rock$") then
local install = require("luarocks.install")
return install.install_binary_rock(name, no_deps)
elseif name:match("%.rock$") then
return build_rock(name, true, no_deps)
elseif not name:match(dir.separator) then
local search = require("luarocks.search")
return search.act_on_src_or_rockspec(run, name:lower(), version, no_deps and "--nodeps")
end
return nil, "Don't know what to do with "..name
end
--- Driver function for "build" command.
-- @param name string: A local or remote rockspec or rock file.
-- If a package name is given, forwards the request to "search" and,
-- 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(...)
local flags, name, version = util.parse_flags(...)
if type(name) ~= "string" then
return nil, "Argument missing, see help."
end
assert(type(version) == "string" or not version)
if flags["pack-binary-rock"] then
return pack.pack_binary_rock(name, version, do_build, name, version, flags["nodeps"])
else
local ok, err = fs.check_command_permissions(flags)
if not ok then return nil, err end
return do_build(name, version, flags["nodeps"])
end
end
luarocks-2.0.9/src/luarocks/search.lua 0000644 0001750 0000144 00000034741 11757524227 017144 0 ustar hisham users
--- Module implementing the LuaRocks "search" command.
-- Queries LuaRocks servers.
module("luarocks.search", package.seeall)
local dir = require("luarocks.dir")
local path = require("luarocks.path")
local manif = require("luarocks.manif")
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] { [] | --all }"
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
with the "install" command without requiring a C toolchain).
--all List all contents of the server that are suitable to
this platform, do not filter by name.
]]
--- Convert the arch field of a query table to table format.
-- @param query table: A query table.
local function query_arch_as_table(query)
local format = type(query.arch)
if format == "table" then
return
elseif format == "nil" then
local accept = {}
accept["src"] = true
accept["all"] = true
accept["rockspec"] = true
accept["installed"] = true
accept[cfg.arch] = true
query.arch = accept
elseif format == "string" then
local accept = {}
for a in query.arch:gmatch("[%w_-]+") do
accept[a] = true
end
query.arch = accept
end
end
--- Store a search result (a rock or rockspec) in the results table.
-- @param results table: The results table, where keys are package names and
-- versions are tables matching version strings to an array of servers.
-- @param name string: Package name.
-- @param version string: Package version.
-- @param arch string: Architecture of rock ("all", "src" or platform
-- identifier), "rockspec" or "installed"
-- @param repo string: Pathname of a local repository of URL of
-- rocks server.
local function store_result(results, name, version, arch, repo)
assert(type(results) == "table")
assert(type(name) == "string")
assert(type(version) == "string")
assert(type(arch) == "string")
assert(type(repo) == "string")
if not results[name] then results[name] = {} end
if not results[name][version] then results[name][version] = {} end
table.insert(results[name][version], {
arch = arch,
repo = repo
})
end
--- Test the name field of a query.
-- If query has a boolean field exact_name set to false,
-- then substring match is performed; otherwise, exact string
-- comparison is done.
-- @param query table: A query in dependency table format.
-- @param name string: A package name.
-- @return boolean: True if names match, false otherwise.
local function match_name(query, name)
assert(type(query) == "table")
assert(type(name) == "string")
if query.exact_name == false then
return name:find(query.name, 0, true) and true or false
else
return name == query.name
end
end
--- Store a match in a results table if version matches query.
-- Name, version, arch and repository path are stored in a given
-- table, optionally checking if version and arch (if given) match
-- a query.
-- @param results table: The results table, where keys are package names and
-- versions are tables matching version strings to an array of servers.
-- @param repo string: URL or pathname of the repository.
-- @param name string: The name of the package being tested.
-- @param version string: The version of the package being tested.
-- @param arch string: The arch of the package being tested.
-- @param query table: A table describing the query in dependency
-- format (for example, {name = "filesystem", exact_name = false,
-- constraints = {op = "~>", version = {1,0}}}, arch = "rockspec").
-- If the arch field is omitted, the local architecture (cfg.arch)
-- is used. The special value "any" is also recognized, returning all
-- matches regardless of architecture.
local function store_if_match(results, repo, name, version, arch, query)
if match_name(query, name) then
if query.arch[arch] or query.arch["any"] then
if deps.match_constraints(deps.parse_version(version), query.constraints) then
store_result(results, name, version, arch, repo)
end
end
end
end
--- Perform search on a local repository.
-- @param repo string: The pathname of the local repository.
-- @param query table: A table describing the query in dependency
-- format (for example, {name = "filesystem", exact_name = false,
-- constraints = {op = "~>", version = {1,0}}}, arch = "rockspec").
-- If the arch field is omitted, the local architecture (cfg.arch)
-- is used. The special value "any" is also recognized, returning all
-- matches regardless of architecture.
-- @param results table or nil: If given, this table will store the
-- results; if not given, a new table will be created.
-- @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)
assert(type(repo) == "string")
assert(type(query) == "table")
assert(type(results) == "table" or not results)
local fs = require("luarocks.fs")
if not results then
results = {}
end
query_arch_as_table(query)
for _, name in pairs(fs.list_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 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
end
--- Perform search on a rocks server.
-- @param results table: The results table, where keys are package names and
-- versions are tables matching version strings to an array of servers.
-- @param repo string: The URL of the rocks server.
-- @param query table: A table describing the query in dependency
-- format (for example, {name = "filesystem", exact_name = false,
-- constraints = {op = "~>", version = {1,0}}}, arch = "rockspec").
-- If the arch field is omitted, the local architecture (cfg.arch)
-- 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)
assert(type(results) == "table")
assert(type(repo) == "string")
assert(type(query) == "table")
query_arch_as_table(query)
local manifest, err = manif.load_manifest(repo)
if not manifest then
return nil, "Failed loading manifest: "..err
end
for name, versions in pairs(manifest.repository) do
for version, items in pairs(versions) do
for _, item in ipairs(items) do
store_if_match(results, repo, name, version, item.arch, query)
end
end
end
return true
end
--- Search on all configured rocks servers.
-- @param query table: A dependency query.
-- @return table or (nil, string): 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.
-- In case of errors, nil and and error message are returned.
function search_repos(query)
assert(type(query) == "table")
local results = {}
for _, repo in ipairs(cfg.rocks_servers) do
local protocol, pathname = dir.split_url(repo)
if protocol == "file" then
repo = pathname
end
local ok, err = manifest_search(results, repo, query)
if not ok then
util.warning("Failed searching manifest: "..err)
end
end
return results
end
--- Prepare a query in dependency table format.
-- @param name string: The query name.
-- @param version string or nil:
-- @return table: A query in table format
function make_query(name, version)
assert(type(name) == "string")
assert(type(version) == "string" or not version)
local query = {
name = name,
constraints = {}
}
if version then
table.insert(query.constraints, { op = "==", version = deps.parse_version(version)})
end
return query
end
--- Get the URL for the latest in a set of versions.
-- @param name string: The package name to be used in the URL.
-- @param versions table: An array of version informations, as stored
-- in search results tables.
-- @return string or nil: the URL for the latest version if one could
-- be picked, or nil.
local function pick_latest_version(name, versions)
assert(type(name) == "string")
assert(type(versions) == "table")
local vtables = {}
for v, _ in pairs(versions) do
table.insert(vtables, deps.parse_version(v))
end
table.sort(vtables)
local version = vtables[#vtables].string
local items = versions[version]
if items then
local pick = 1
for i, item in ipairs(items) do
if (item.arch == 'src' and items[pick].arch == 'rockspec')
or (item.arch ~= 'src' and item.arch ~= 'rockspec') then
pick = i
end
end
return path.make_url(items[pick].repo, name, version, items[pick].arch)
end
return nil
end
--- Attempt to get a single URL for a given search.
-- @param query table: A dependency query.
-- @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)
assert(type(query) == "table")
local results, err = search_repos(query)
if not results then
return nil, err
end
local first = next(results)
if not first then
return nil, "No results matching query were found."
elseif not next(results, first) then
return pick_latest_version(query.name, results[first])
else
return results
end
end
--- Print a list of rocks/rockspecs on standard output.
-- @param results table: A table where keys are package names and versions
-- are tables matching version strings to an array of rocks servers.
-- @param show_repo boolean or nil: Whether to show repository
-- @param long boolean or nil: Whether to show module files
-- information or not. Default is true.
function print_results(results, show_repo, long)
assert(type(results) == "table")
assert(type(show_repo) == "boolean" or not show_repo)
-- Force display of repo location for the time being
show_repo = true -- show_repo == nil and true or show_repo
for package, versions in util.sortedpairs(results) do
util.printout(package)
for version, repos in util.sortedpairs(versions, deps.compare_versions) do
if show_repo then
for _, repo in ipairs(repos) do
util.printout(" "..version.." ("..repo.arch..") - "..repo.repo)
end
else
util.printout(" "..version)
end
end
util.printout()
end
end
--- Splits a list of search results into two lists, one for "source" results
-- to be used with the "build" command, and one for "binary" results to be
-- used with the "install" command.
-- @param results table: A search results table.
-- @return (table, table): Two tables, one for source and one for binary
-- results.
local function split_source_and_binary_results(results)
local sources, binaries = {}, {}
for name, versions in pairs(results) do
for version, repos in pairs(versions) do
for _, repo in ipairs(repos) do
local where = sources
if repo.arch == "all" or repo.arch == cfg.arch then
where = binaries
end
store_result(where, name, version, repo.arch, repo.repo)
end
end
end
return sources, binaries
end
--- Given a name and optionally a version, try to find in the rocks
-- servers a single .src.rock or .rockspec file that satisfies
-- the request, and run the given function on it; or display to the
-- user possibilities if it couldn't narrow down a single match.
-- @param action function: A function that takes a .src.rock or
-- .rockspec URL as a parameter.
-- @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, ...)
assert(type(action) == "function")
assert(type(name) == "string")
assert(type(version) == "string" or not version)
local query = make_query(name, version)
query.arch = "src|rockspec"
local results, err = find_suitable_rock(query)
if type(results) == "string" then
return action(results, ...)
elseif type(results) == "table" and next(results) then
util.printout("Multiple search results were returned.")
util.printout()
util.printout("Search results:")
util.printout("---------------")
print_results(results)
return nil, "Please narrow your query."
else
return nil, "Could not find a result named "..name..(version and " "..version or "").."."
end
end
--- Driver function for "search" command.
-- @param name string: A substring of a rock name to search.
-- @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(...)
local flags, name, version = util.parse_flags(...)
if flags["all"] then
name, version = "", nil
end
if type(name) ~= "string" and not flags["all"] then
return nil, "Enter name and version or use --all; see help."
end
local query = make_query(name:lower(), version)
query.exact_name = false
local results, err = search_repos(query)
if not results then
return nil, err
end
util.printout()
util.printout("Search results:")
util.printout("===============")
util.printout()
local sources, binaries = split_source_and_binary_results(results)
if next(sources) and not flags["binary"] then
util.printout("Rockspecs and source rocks:")
util.printout("---------------------------")
util.printout()
print_results(sources, true)
end
if next(binaries) and not flags["source"] then
util.printout("Binary and pure-Lua rocks:")
util.printout("--------------------------")
util.printout()
print_results(binaries, true)
end
return true
end
luarocks-2.0.9/src/luarocks/cache.lua 0000644 0001750 0000144 00000005600 11757524226 016731 0 ustar hisham users
--- Module handling the LuaRocks local cache.
-- Adds a rock or rockspec to a rocks server.
module("luarocks.cache", package.seeall)
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)
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."
end
return server, cfg.upload_servers and cfg.upload_servers[server]
end
function get_server_urls(server, upload_server)
local download_url = server
local login_url = nil
if upload_server then
if upload_server.rsync then download_url = "rsync://"..upload_server.rsync
elseif upload_server.http then download_url = "http://"..upload_server.http
elseif upload_server.ftp then download_url = "ftp://"..upload_server.ftp
end
if upload_server.ftp then login_url = "ftp://"..upload_server.ftp
elseif upload_server.sftp then login_url = "sftp://"..upload_server.sftp
end
end
return download_url, login_url
end
function split_server_url(server, url, user, password)
local protocol, server_path = dir.split_url(url)
if server_path:match("@") then
local credentials
credentials, server_path = server_path:match("([^@]*)@(.*)")
if credentials:match(":") then
user, password = credentials:match("([^:]*):(.*)")
else
user = credentials
end
end
local local_cache
if cfg.local_cache then
local_cache = cfg.local_cache .. "/" .. server
end
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)
fs.make_dir(cfg.local_cache)
local tmp_cache = false
if not local_cache then
local_cache = fs.make_temp_dir("local_cache")
tmp_cache = true
end
local ok = fs.make_dir(local_cache)
if not ok then
return nil, "Failed creating local cache dir."
end
fs.change_dir(local_cache)
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.."/")
else
local login_info = ""
if user then login_info = " --user="..user end
if password then login_info = login_info .. " --password="..password end
ok = fs.execute(cfg.variables.WGET.." --no-cache -q -m -np -nd "..protocol.."://"..server_path..login_info)
end
if not ok then
return nil, "Failed downloading cache."
end
return local_cache, protocol, server_path, user, password
end
luarocks-2.0.9/src/luarocks/tools/ 0000755 0001750 0000144 00000000000 11757524227 016323 5 ustar hisham users luarocks-2.0.9/src/luarocks/tools/zip.lua 0000644 0001750 0000144 00000020224 11757524227 017630 0 ustar hisham users
--- A Lua implementation of .zip file archiving (used for creating .rock files),
-- using only lua-zlib.
module("luarocks.tools.zip", package.seeall)
local zlib = require("zlib")
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local function number_to_bytestring(number, nbytes)
local out = {}
for i = 1, nbytes do
local byte = number % 256
table.insert(out, string.char(byte))
number = (number - byte) / 256
end
return table.concat(out)
end
--- Begin a new file to be stored inside the zipfile.
-- @param self handle of the zipfile being written.
-- @param filename filenome of the file to be added to the zipfile.
-- @return true if succeeded, nil in case of failure.
local function zipwriter_open_new_file_in_zip(self, filename)
if self.in_open_file then
self:close_file_in_zip()
return nil
end
local lfh = {}
self.local_file_header = lfh
lfh.last_mod_file_time = 0 -- TODO
lfh.last_mod_file_date = 0 -- TODO
lfh.crc32 = 0 -- initial value
lfh.compressed_size = 0 -- unknown yet
lfh.uncompressed_size = 0 -- unknown yet
lfh.file_name_length = #filename
lfh.extra_field_length = 0
lfh.file_name = filename:gsub("\\", "/")
lfh.external_attr = 0 -- TODO properly store permissions
self.in_open_file = true
self.data = {}
return true
end
--- Write data to the file currently being stored in the zipfile.
-- @param self handle of the zipfile being written.
-- @param buf string containing data to be written.
-- @return true if succeeded, nil in case of failure.
local function zipwriter_write_file_in_zip(self, buf)
if not self.in_open_file then
return nil
end
local lfh = self.local_file_header
local cbuf = zlib.compress(buf):sub(3, -5)
lfh.crc32 = zlib.crc32(lfh.crc32, buf)
lfh.compressed_size = lfh.compressed_size + #cbuf
lfh.uncompressed_size = lfh.uncompressed_size + #buf
table.insert(self.data, cbuf)
return true
end
--- Complete the writing of a file stored in the zipfile.
-- @param self handle of the zipfile being written.
-- @return true if succeeded, nil in case of failure.
local function zipwriter_close_file_in_zip(self)
local zh = self.ziphandle
if not self.in_open_file then
return nil
end
-- Local file header
local lfh = self.local_file_header
lfh.offset = zh:seek()
zh:write(number_to_bytestring(0x04034b50, 4)) -- signature
zh:write(number_to_bytestring(20, 2)) -- version needed to extract: 2.0
zh:write(number_to_bytestring(0, 2)) -- general purpose bit flag
zh:write(number_to_bytestring(8, 2)) -- compression method: deflate
zh:write(number_to_bytestring(lfh.last_mod_file_time, 2))
zh:write(number_to_bytestring(lfh.last_mod_file_date, 2))
zh:write(number_to_bytestring(lfh.crc32, 4))
zh:write(number_to_bytestring(lfh.compressed_size, 4))
zh:write(number_to_bytestring(lfh.uncompressed_size, 4))
zh:write(number_to_bytestring(lfh.file_name_length, 2))
zh:write(number_to_bytestring(lfh.extra_field_length, 2))
zh:write(lfh.file_name)
-- File data
for _, cbuf in ipairs(self.data) do
zh:write(cbuf)
end
-- Data descriptor
zh:write(number_to_bytestring(lfh.crc32, 4))
zh:write(number_to_bytestring(lfh.compressed_size, 4))
zh:write(number_to_bytestring(lfh.uncompressed_size, 4))
table.insert(self.files, lfh)
self.in_open_file = false
return true
end
-- @return boolean or (boolean, string): true on success,
-- false and an error message on failure.
local function zipwriter_add(self, file)
local fin
local ok, err = self:open_new_file_in_zip(file)
if not ok then
err = "error in opening "..file.." in zipfile"
else
fin = io.open(fs.absolute_name(file), "rb")
if not fin then
ok = false
err = "error opening "..file.." for reading"
end
end
if ok then
local buf = fin:read("*a")
if not buf then
err = "error reading "..file
ok = false
else
ok = self:write_file_in_zip(buf)
if not ok then
err = "error in writing "..file.." in the zipfile"
end
end
end
if fin then
fin:close()
end
if ok then
ok = self:close_file_in_zip()
if not ok then
err = "error in writing "..file.." in the zipfile"
end
end
return ok == true, err
end
--- Complete the writing of the zipfile.
-- @param self handle of the zipfile being written.
-- @return true if succeeded, nil in case of failure.
local function zipwriter_close(self)
local zh = self.ziphandle
local central_directory_offset = zh:seek()
local size_of_central_directory = 0
-- Central directory structure
for _, lfh in ipairs(self.files) do
zh:write(number_to_bytestring(0x02014b50, 4)) -- signature
zh:write(number_to_bytestring(3, 2)) -- version made by: UNIX
zh:write(number_to_bytestring(20, 2)) -- version needed to extract: 2.0
zh:write(number_to_bytestring(0, 2)) -- general purpose bit flag
zh:write(number_to_bytestring(8, 2)) -- compression method: deflate
zh:write(number_to_bytestring(lfh.last_mod_file_time, 2))
zh:write(number_to_bytestring(lfh.last_mod_file_date, 2))
zh:write(number_to_bytestring(lfh.crc32, 4))
zh:write(number_to_bytestring(lfh.compressed_size, 4))
zh:write(number_to_bytestring(lfh.uncompressed_size, 4))
zh:write(number_to_bytestring(lfh.file_name_length, 2))
zh:write(number_to_bytestring(lfh.extra_field_length, 2))
zh:write(number_to_bytestring(0, 2)) -- file comment length
zh:write(number_to_bytestring(0, 2)) -- disk number start
zh:write(number_to_bytestring(0, 2)) -- internal file attributes
zh:write(number_to_bytestring(lfh.external_attr, 4)) -- external file attributes
zh:write(number_to_bytestring(lfh.offset, 4)) -- relative offset of local header
zh:write(lfh.file_name)
size_of_central_directory = size_of_central_directory + 46 + lfh.file_name_length
end
-- End of central directory record
zh:write(number_to_bytestring(0x06054b50, 4)) -- signature
zh:write(number_to_bytestring(0, 2)) -- number of this disk
zh:write(number_to_bytestring(0, 2)) -- number of disk with start of central directory
zh:write(number_to_bytestring(#self.files, 2)) -- total number of entries in the central dir on this disk
zh:write(number_to_bytestring(#self.files, 2)) -- total number of entries in the central dir
zh:write(number_to_bytestring(size_of_central_directory, 4))
zh:write(number_to_bytestring(central_directory_offset, 4))
zh:write(number_to_bytestring(0, 2)) -- zip file comment length
zh:close()
return true
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)
local zw = {}
zw.ziphandle = io.open(fs.absolute_name(name), "wb")
if not zw.ziphandle then
return nil
end
zw.files = {}
zw.in_open_file = false
zw.add = zipwriter_add
zw.close = zipwriter_close
zw.open_new_file_in_zip = zipwriter_open_new_file_in_zip
zw.write_file_in_zip = zipwriter_write_file_in_zip
zw.close_file_in_zip = zipwriter_close_file_in_zip
return zw
end
--- Compress files in a .zip archive.
-- @param zipfile string: pathname of .zip archive to be created.
-- @param ... Filenames to be stored in the archive are given as
-- 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)
if not zw then
return nil, "error opening "..zipfile
end
local ok, err
for _, file in pairs({...}) do
if fs.is_dir(file) then
for _, entry in pairs(fs.find(file)) do
local fullname = dir.path(file, entry)
if fs.is_file(fullname) then
ok, err = zw:add(fullname)
if not ok then break end
end
end
else
ok, err = zw:add(file)
if not ok then break end
end
end
local ok = zw:close()
if not ok then
return false, "error closing "..zipfile
end
return ok, err
end
luarocks-2.0.9/src/luarocks/tools/patch.lua 0000644 0001750 0000144 00000053454 11757524227 020140 0 ustar hisham users --- Patch utility to apply unified diffs.
--
-- http://lua-users.org/wiki/LuaPatch
--
-- (c) 2008 David Manura, Licensed under the same terms as Lua (MIT license).
-- 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/ .
module("luarocks.tools.patch", package.seeall)
local fs = require("luarocks.fs")
local version = '0.1'
local io = io
local os = os
local string = string
local table = table
local format = string.format
-- logging
local debugmode = false
local function debug(s) end
local function info(s) end
local function warning(s) io.stderr:write(s .. '\n') end
-- Returns boolean whether string s2 starts with string s.
local function startswith(s, s2)
return s:sub(1, #s2) == s2
end
-- Returns boolean whether string s2 ends with string s.
local function endswith(s, s2)
return #s >= #s2 and s:sub(#s-#s2+1) == s2
end
-- Returns string s after filtering out any new-line characters from end.
local function endlstrip(s)
return s:gsub('[\r\n]+$', '')
end
-- Returns shallow copy of table t.
local function table_copy(t)
local t2 = {}
for k,v in pairs(t) do t2[k] = v end
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
if fh then fh:close() end
return result
end
local function isfile() return true end --FIX?
local function read_file(filename)
local fh, err, oserr = io.open(filename, 'rb')
if not fh then return fh, err, oserr end
local data, err, oserr = fh:read'*a'
fh:close()
if not data then return nil, err, oserr end
return data
end
local function write_file(filename, data)
local fh, err, oserr = io.open(filename 'wb')
if not fh then return fh, err, oserr end
local status, err, oserr = fh:write(data)
fh:close()
if not status then return nil, err, oserr end
return true
end
local function file_copy(src, dest)
local data, err, oserr = read_file(src)
if not data then return data, err, oserr end
local status, err, oserr = write_file(dest)
if not status then return status, err, oserr end
return true
end
local function string_as_file(s)
return {
at = 0,
str = s,
len = #s,
eof = false,
read = function(self, n)
if self.eof then return nil end
local chunk = self.str:sub(self.at, self.at+n)
self.at = self.at + n
if self.at > self.len then
self.eof = true
end
return chunk
end,
close = function(self)
self.eof = true
end,
}
end
--
-- file_lines(f) is similar to f:lines() for file f.
-- The main difference is that read_lines includes
-- new-line character sequences ("\n", "\r\n", "\r"),
-- if any, at the end of each line. Embedded "\0" are also handled.
-- Caution: The newline behavior can depend on whether f is opened
-- in binary or ASCII mode.
-- (file_lines - version 20080913)
--
local function file_lines(f)
local CHUNK_SIZE = 1024
local buffer = ""
local pos_beg = 1
return function()
local pos, chars
while 1 do
pos, chars = buffer:match('()([\r\n].)', pos_beg)
if pos or not f then
break
elseif f then
local chunk = f:read(CHUNK_SIZE)
if chunk then
buffer = buffer:sub(pos_beg) .. chunk
pos_beg = 1
else
f = nil
end
end
end
if not pos then
pos = #buffer
elseif chars == '\r\n' then
pos = pos + 1
end
local line = buffer:sub(pos_beg, pos)
pos_beg = pos + 1
if #line > 0 then
return line
end
end
end
local function match_linerange(line)
local m1, m2, m3, m4 = line:match("^@@ %-(%d+),(%d+) %+(%d+),(%d+)")
if not m1 then m1, m3, m4 = line:match("^@@ %-(%d+) %+(%d+),(%d+)") end
if not m1 then m1, m2, m3 = line:match("^@@ %-(%d+),(%d+) %+(%d+)") end
if not m1 then m1, m3 = line:match("^@@ %-(%d+) %+(%d+)") end
return m1, m2, m3, m4
end
function read_patch(filename, data)
-- define possible file regions that will direct the parser flow
local state = 'header'
-- 'header' - comments before the patch body
-- 'filenames' - lines starting with --- and +++
-- 'hunkhead' - @@ -R +R @@ sequence
-- 'hunkbody'
-- 'hunkskip' - skipping invalid hunk mode
local all_ok = true
local lineends = {lf=0, crlf=0, cr=0}
local files = {source={}, target={}, hunks={}, fileends={}, hunkends={}}
local nextfileno = 0
local nexthunkno = 0 --: even if index starts with 0 user messages
-- number hunks from 1
-- hunkinfo holds parsed values, hunkactual - calculated
local hunkinfo = {
startsrc=nil, linessrc=nil, starttgt=nil, linestgt=nil,
invalid=false, text={}
}
local hunkactual = {linessrc=nil, linestgt=nil}
info(format("reading patch %s", filename))
local fp
if data then
fp = string_as_file(data)
else
fp = filename == '-' and io.stdin or assert(io.open(filename, "rb"))
end
local lineno = 0
for line in file_lines(fp) do
lineno = lineno + 1
if state == 'header' then
if startswith(line, "--- ") then
state = 'filenames'
end
-- state is 'header' or 'filenames'
end
if state == 'hunkbody' then
-- skip hunkskip and hunkbody code until definition of hunkhead read
-- process line first
if line:match"^[- +\\]" or line:match"^[\r\n]*$" then
-- gather stats about line endings
local he = files.hunkends[nextfileno]
if endswith(line, "\r\n") then
he.crlf = he.crlf + 1
elseif endswith(line, "\n") then
he.lf = he.lf + 1
elseif endswith(line, "\r") then
he.cr = he.cr + 1
end
if startswith(line, "-") then
hunkactual.linessrc = hunkactual.linessrc + 1
elseif startswith(line, "+") then
hunkactual.linestgt = hunkactual.linestgt + 1
elseif startswith(line, "\\") then
-- nothing
else
hunkactual.linessrc = hunkactual.linessrc + 1
hunkactual.linestgt = hunkactual.linestgt + 1
end
table.insert(hunkinfo.text, line)
-- todo: handle \ No newline cases
else
warning(format("invalid hunk no.%d at %d for target file %s",
nexthunkno, lineno, files.target[nextfileno]))
-- add hunk status node
table.insert(files.hunks[nextfileno], table_copy(hunkinfo))
files.hunks[nextfileno][nexthunkno].invalid = true
all_ok = false
state = 'hunkskip'
end
-- check exit conditions
if hunkactual.linessrc > hunkinfo.linessrc or
hunkactual.linestgt > hunkinfo.linestgt
then
warning(format("extra hunk no.%d lines at %d for target %s",
nexthunkno, lineno, files.target[nextfileno]))
-- add hunk status node
table.insert(files.hunks[nextfileno], table_copy(hunkinfo))
files.hunks[nextfileno][nexthunkno].invalid = true
state = 'hunkskip'
elseif hunkinfo.linessrc == hunkactual.linessrc and
hunkinfo.linestgt == hunkactual.linestgt
then
table.insert(files.hunks[nextfileno], table_copy(hunkinfo))
state = 'hunkskip'
-- detect mixed window/unix line ends
local ends = files.hunkends[nextfileno]
if (ends.cr~=0 and 1 or 0) + (ends.crlf~=0 and 1 or 0) +
(ends.lf~=0 and 1 or 0) > 1
then
warning(format("inconsistent line ends in patch hunks for %s",
files.source[nextfileno]))
end
if debugmode then
local debuglines = {crlf=ends.crlf, lf=ends.lf, cr=ends.cr,
file=files.target[nextfileno], hunk=nexthunkno}
debug(format("crlf: %(crlf)d lf: %(lf)d cr: %(cr)d\t " ..
"- file: %(file)s hunk: %(hunk)d", debuglines))
end
end
-- state is 'hunkbody' or 'hunkskip'
end
if state == 'hunkskip' then
if match_linerange(line) then
state = 'hunkhead'
elseif startswith(line, "--- ") then
state = 'filenames'
if debugmode and #files.source > 0 then
debug(format("- %2d hunks for %s", #files.hunks[nextfileno],
files.source[nextfileno]))
end
end
-- state is 'hunkskip', 'hunkhead', or 'filenames'
end
local advance
if state == 'filenames' then
if startswith(line, "--- ") then
if array_contains(files.source, nextfileno) then
all_ok = false
warning(format("skipping invalid patch for %s",
files.source[nextfileno+1]))
table.remove(files.source, nextfileno+1)
-- double source filename line is encountered
-- attempt to restart from this second line
end
-- Accept a space as a terminator, like GNU patch does.
-- Breaks patches containing filenames with spaces...
-- FIXME Figure out what does GNU patch do in those cases.
local match = line:match("^--- ([^\t ]+)")
if not match then
all_ok = false
warning(format("skipping invalid filename at line %d", lineno+1))
state = 'header'
else
table.insert(files.source, match)
end
elseif not startswith(line, "+++ ") then
if array_contains(files.source, nextfileno) then
all_ok = false
warning(format("skipping invalid patch with no target for %s",
files.source[nextfileno+1]))
table.remove(files.source, nextfileno+1)
else
-- this should be unreachable
warning("skipping invalid target patch")
end
state = 'header'
else
if array_contains(files.target, nextfileno) then
all_ok = false
warning(format("skipping invalid patch - double target at line %d",
lineno+1))
table.remove(files.source, nextfileno+1)
table.remove(files.target, nextfileno+1)
nextfileno = nextfileno - 1
-- double target filename line is encountered
-- switch back to header state
state = 'header'
else
-- Accept a space as a terminator, like GNU patch does.
-- Breaks patches containing filenames with spaces...
-- FIXME Figure out what does GNU patch do in those cases.
local re_filename = "^%+%+%+ ([^ \t]+)"
local match = line:match(re_filename)
if not match then
all_ok = false
warning(format(
"skipping invalid patch - no target filename at line %d",
lineno+1))
state = 'header'
else
table.insert(files.target, match)
nextfileno = nextfileno + 1
nexthunkno = 0
table.insert(files.hunks, {})
table.insert(files.hunkends, table_copy(lineends))
table.insert(files.fileends, table_copy(lineends))
state = 'hunkhead'
advance = true
end
end
end
-- state is 'filenames', 'header', or ('hunkhead' with advance)
end
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
all_ok = false
warning(format("skipping invalid patch with no hunks for file %s",
files.target[nextfileno]))
end
state = 'header'
else
hunkinfo.startsrc = tonumber(m1)
hunkinfo.linessrc = tonumber(m2 or 1)
hunkinfo.starttgt = tonumber(m3)
hunkinfo.linestgt = tonumber(m4 or 1)
hunkinfo.invalid = false
hunkinfo.text = {}
hunkactual.linessrc = 0
hunkactual.linestgt = 0
state = 'hunkbody'
nexthunkno = nexthunkno + 1
end
-- state is 'header' or 'hunkbody'
end
end
if state ~= 'hunkskip' then
warning(format("patch file incomplete - %s", filename))
all_ok = false
-- os.exit(?)
else
-- duplicated message when an eof is reached
if debugmode and #files.source > 0 then
debug(format("- %2d hunks for %s", #files.hunks[nextfileno],
files.source[nextfileno]))
end
end
local sum = 0; for _,hset in ipairs(files.hunks) do sum = sum + #hset end
info(format("total files: %d total hunks: %d", #files.source, sum))
fp:close()
return files, all_ok
end
local function find_hunk(file, h, hno)
for fuzz=0,2 do
local lineno = h.startsrc
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
if startswith(hline, " ") or startswith(hline, "-") then
local line = file[lineno]
lineno = lineno + 1
if not line or #line == 0 then
found = false
break
end
if endlstrip(line) ~= endlstrip(hline:sub(2)) then
found = false
break
end
end
end
end
if found then
local offset = location - h.startsrc - fuzz
if offset ~= 0 then
warning(format("Hunk %d found at offset %d%s...", hno, offset, fuzz == 0 and "" or format(" (fuzz %d)", fuzz)))
end
h.startsrc = location
h.starttgt = h.starttgt + offset
for i=1,fuzz do
table.remove(h.text, 1)
table.remove(h.text, #h.text)
end
return true
end
lineno = i
end
end
return false
end
local function load_file(filename)
local fp = assert(io.open(filename))
local file = {}
local readline = file_lines(fp)
while true do
local line = readline()
if not line then break end
table.insert(file, line)
end
fp:close()
return file
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
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'
end
for hno, h in ipairs(hunks) do
-- skip to line just before hunk starts
if #file < h.starttgt then
error 'nomatch'
end
lineno = h.starttgt
for _, hline in ipairs(h.text) do
-- todo: \ No newline at the end of file
if not startswith(hline, "-") and not startswith(hline, "\\") then
local line = file[lineno]
lineno = lineno + 1
if #line == 0 then
error 'nomatch'
end
if endlstrip(line) ~= endlstrip(hline:sub(2)) then
warning(format("file is not patched - failed hunk: %d", hno))
error 'nomatch'
end
end
end
end
end)
if err == 'nomatch' then
matched = false
end
-- todo: display failed hunk, i.e. expected/found
return matched
end
local function patch_hunks(srcname, tgtname, hunks)
local src = assert(io.open(srcname, "rb"))
local tgt = assert(io.open(tgtname, "wb"))
local src_readline = file_lines(src)
-- todo: detect linefeeds early - in apply_files routine
-- to handle cases when patch starts right from the first
-- line and no lines are processed. At the moment substituted
-- lineends may not be the same at the start and at the end
-- of patching. Also issue a warning about mixed lineends
local srclineno = 1
local lineends = {['\n']=0, ['\r\n']=0, ['\r']=0}
for hno, h in ipairs(hunks) do
debug(format("processing hunk %d for file %s", hno, tgtname))
-- skip to line just before hunk starts
while srclineno < h.startsrc do
local line = src_readline()
-- Python 'U' mode works only with text files
if endswith(line, "\r\n") then
lineends["\r\n"] = lineends["\r\n"] + 1
elseif endswith(line, "\n") then
lineends["\n"] = lineends["\n"] + 1
elseif endswith(line, "\r") then
lineends["\r"] = lineends["\r"] + 1
end
tgt:write(line)
srclineno = srclineno + 1
end
for _,hline in ipairs(h.text) do
-- todo: check \ No newline at the end of file
if startswith(hline, "-") or startswith(hline, "\\") then
src_readline()
srclineno = srclineno + 1
else
if not startswith(hline, "+") then
src_readline()
srclineno = srclineno + 1
end
local line2write = hline:sub(2)
-- detect if line ends are consistent in source file
local sum = 0
for k,v in pairs(lineends) do if v > 0 then sum=sum+1 end end
if sum == 1 then
local newline
for k,v in pairs(lineends) do if v ~= 0 then newline = k end end
tgt:write(endlstrip(line2write) .. newline)
else -- newlines are mixed or unknown
tgt:write(line2write)
end
end
end
end
for line in src_readline do
tgt:write(line)
end
tgt:close()
src:close()
return true
end
local function strip_dirs(filename, strip)
if strip == nil then return filename end
for i=1,strip do
filename=filename:gsub("^[^/]*/", "")
end
return filename
end
function apply_patch(patch, strip)
local all_ok = true
local total = #patch.source
for fileno, filename in ipairs(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 = 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",
filename, f2patch))
all_ok = false
continue = true
end
end
if not continue and not isfile(f2patch) then
warning(format("not a file - %s", f2patch))
all_ok = false
continue = true
end
if not continue then
filename = f2patch
info(format("processing %d/%d:\t %s", fileno, total, filename))
-- validate before patching
local hunks = patch.hunks[fileno]
local file = load_file(filename)
local hunkno = 1
local hunk = hunks[hunkno]
local hunkfind = {}
local hunkreplace = {}
local validhunks = 0
local canpatch = false
local hunklineno
local isbreak
local lineno = 0
find_hunks(file, hunks)
for _, line in ipairs(file) do
lineno = lineno + 1
local continue
if not hunk or lineno < hunk.startsrc then
continue = true
elseif lineno == hunk.startsrc then
hunkfind = {}
for _,x in ipairs(hunk.text) do
if x:sub(1,1) == ' ' or x:sub(1,1) == '-' then
hunkfind[#hunkfind+1] = endlstrip(x:sub(2))
end end
hunkreplace = {}
for _,x in ipairs(hunk.text) do
if x:sub(1,1) == ' ' or x:sub(1,1) == '+' then
hunkreplace[#hunkreplace+1] = endlstrip(x:sub(2))
end end
--pprint(hunkreplace)
hunklineno = 1
-- todo \ No newline at end of file
end
-- check hunks in source file
if not continue and lineno < hunk.startsrc + #hunkfind - 1 then
if endlstrip(line) == hunkfind[hunklineno] then
hunklineno = hunklineno + 1
else
debug(format("hunk no.%d doesn't match source file %s",
hunkno, filename))
-- file may be already patched, but check other hunks anyway
hunkno = hunkno + 1
if hunkno <= #hunks then
hunk = hunks[hunkno]
continue = true
else
isbreak = true; break
end
end
end
-- check if processed line is the last line
if not continue and lineno == hunk.startsrc + #hunkfind - 1 then
debug(format("file %s hunk no.%d -- is ready to be patched",
filename, hunkno))
hunkno = hunkno + 1
validhunks = validhunks + 1
if hunkno <= #hunks then
hunk = hunks[hunkno]
else
if validhunks == #hunks then
-- patch file
canpatch = true
isbreak = true; break
end
end
end
end
if not isbreak then
if hunkno <= #hunks then
warning(format("premature end of source file %s at hunk %d",
filename, hunkno))
all_ok = false
end
end
if validhunks < #hunks then
if check_patched(file, hunks) then
warning(format("already patched %s", filename))
else
warning(format("source file is different - %s", filename))
all_ok = false
end
end
if canpatch then
local backupname = filename .. ".orig"
if exists(backupname) then
warning(format("can't backup original file to %s - aborting",
backupname))
all_ok = false
else
assert(os.rename(filename, backupname))
if patch_hunks(backupname, filename, hunks) then
warning(format("successfully patched %s", filename))
assert(os.remove(backupname))
else
warning(format("error patching file %s", filename))
assert(file_copy(filename, filename .. ".invalid"))
warning(format("invalid version is saved to %s",
filename .. ".invalid"))
-- todo: proper rejects
assert(os.rename(backupname, filename))
all_ok = false
end
end
end
end -- if not continue
end -- for
-- todo: check for premature eof
return all_ok
end
luarocks-2.0.9/src/luarocks/tools/tar.lua 0000644 0001750 0000144 00000011077 11757524227 017622 0 ustar hisham users
--- A pure-Lua implementation of untar (unpacking .tar archives)
module("luarocks.tools.tar", package.seeall)
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local util = require("luarocks.util")
local blocksize = 512
local function get_typeflag(flag)
if flag == "0" or flag == "\0" then return "file"
elseif flag == "1" then return "link"
elseif flag == "2" then return "symlink" -- "reserved" in POSIX, "symlink" in GNU
elseif flag == "3" then return "character"
elseif flag == "4" then return "block"
elseif flag == "5" then return "directory"
elseif flag == "6" then return "fifo"
elseif flag == "7" then return "contiguous" -- "reserved" in POSIX, "contiguous" in GNU
elseif flag == "x" then return "next file"
elseif flag == "g" then return "global extended header"
elseif flag == "L" then return "long name"
elseif flag == "K" then return "long link name"
end
return "unknown"
end
local function octal_to_number(octal)
local exp = 0
local number = 0
for i = #octal,1,-1 do
local digit = tonumber(octal:sub(i,i))
if not digit then break end
number = number + (digit * 8^exp)
exp = exp + 1
end
return number
end
local function checksum_header(block)
local sum = 256
for i = 1,148 do
sum = sum + block:byte(i)
end
for i = 157,500 do
sum = sum + block:byte(i)
end
return sum
end
local function nullterm(s)
return s:match("^[^%z]*")
end
local function read_header_block(block)
local header = {}
header.name = nullterm(block:sub(1,100))
header.mode = nullterm(block:sub(101,108))
header.uid = octal_to_number(nullterm(block:sub(109,116)))
header.gid = octal_to_number(nullterm(block:sub(117,124)))
header.size = octal_to_number(nullterm(block:sub(125,136)))
header.mtime = octal_to_number(nullterm(block:sub(137,148)))
header.chksum = octal_to_number(nullterm(block:sub(149,156)))
header.typeflag = get_typeflag(block:sub(157,157))
header.linkname = nullterm(block:sub(158,257))
header.magic = block:sub(258,263)
header.version = block:sub(264,265)
header.uname = nullterm(block:sub(266,297))
header.gname = nullterm(block:sub(298,329))
header.devmajor = octal_to_number(nullterm(block:sub(330,337)))
header.devminor = octal_to_number(nullterm(block:sub(338,345)))
header.prefix = block:sub(346,500)
if header.magic ~= "ustar " and header.magic ~= "ustar\0" then
return false, "Invalid header magic "..header.magic
end
if header.version ~= "00" and header.version ~= " \0" then
return false, "Unknown version "..header.version
end
if not checksum_header(block) == header.chksum then
return false, "Failed header checksum"
end
return header
end
function untar(filename, destdir)
assert(type(filename) == "string")
assert(type(destdir) == "string")
local tar_handle = io.open(filename, "r")
if not tar_handle then return nil, "Error opening file "..filename end
local long_name, long_link_name
while true do
local block
repeat
block = tar_handle:read(blocksize)
until (not block) or checksum_header(block) > 256
if not block then break end
local header, err = read_header_block(block)
if not header then
util.printerr(err)
end
local file_data = tar_handle:read(math.ceil(header.size / blocksize) * blocksize):sub(1,header.size)
if header.typeflag == "long name" then
long_name = nullterm(file_data)
elseif header.typeflag == "long link name" then
long_link_name = nullterm(file_data)
else
if long_name then
header.name = long_name
long_name = nil
end
if long_link_name then
header.name = long_link_name
long_link_name = nil
end
end
local pathname = dir.path(destdir, header.name)
if header.typeflag == "directory" then
fs.make_dir(pathname)
elseif header.typeflag == "file" then
local dirname = dir.dir_name(pathname)
if dirname ~= "" then
fs.make_dir(dirname)
end
local file_handle = io.open(pathname, "wb")
file_handle:write(file_data)
file_handle:close()
fs.set_time(pathname, header.mtime)
if fs.chmod then
fs.chmod(pathname, header.mode)
end
end
--[[
for k,v in pairs(header) do
util.printout("[\""..tostring(k).."\"] = "..(type(v)=="number" and v or "\""..v:gsub("%z", "\\0").."\""))
end
util.printout()
--]]
end
return true
end
luarocks-2.0.9/src/luarocks/index.lua 0000644 0001750 0000144 00000012027 11757524227 016777 0 ustar hisham users
--- Module which builds the index.html page to be used in rocks servers.
module("luarocks.index", package.seeall)
local util = require("luarocks.util")
local fs = require("luarocks.fs")
local deps = require("luarocks.deps")
local persist = require("luarocks.persist")
local dir = require("luarocks.dir")
local manif = require("luarocks.manif")
local ext_url_target = ' target="_blank"'
local index_header = [[
Available rocks
Available rocks
Lua modules available from this location for use with LuaRocks:
]]
local index_package_start = [[
$package - $summary
$detailed
$externaldependencies
latest sources $homepage | License: $license
|
]]
local index_package_end = [[
|
|
]]
local index_footer = [[
manifest file
]]
function format_external_dependencies(rockspec)
if rockspec.external_dependencies then
local deplist = {}
local listed_set = {}
local plats = nil
for name, desc in util.sortedpairs(rockspec.external_dependencies) do
if name ~= "platforms" then
table.insert(deplist, name:lower())
listed_set[name] = true
else
plats = desc
end
end
if plats then
for plat, entries in util.sortedpairs(plats) do
for name, desc in util.sortedpairs(entries) do
if not listed_set[name] then
table.insert(deplist, name:lower() .. " (on "..plat..")")
end
end
end
end
return 'External dependencies: ' .. table.concat(deplist, ', ').. '
'
else
return ""
end
end
function make_index(repo)
if not fs.is_dir(repo) then
return nil, "Cannot access repository at "..repo
end
local manifest = manif.load_manifest(repo)
local out = io.open(dir.path(repo, "index.html"), "w")
out:write(index_header)
for package, version_list in util.sortedpairs(manifest.repository) do
local latest_rockspec = nil
local output = index_package_start
for version, data in util.sortedpairs(version_list, deps.compare_versions) do
local versions = {}
output = output..version..': '
table.sort(data, function(a,b) return a.arch < b.arch end)
for _, item in ipairs(data) do
local link = ''..item.arch..''
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)
else
link = link:gsub("$url", ("%s-%s.%s.rock"):format(package, version, item.arch))
end
table.insert(versions, link)
end
output = output .. table.concat(versions, ', ') .. '
'
end
output = output .. index_package_end
if latest_rockspec then
local rockspec = persist.load_into_table(dir.path(repo, latest_rockspec))
local descript = rockspec.description or {}
local vars = {
anchor = package,
package = rockspec.package,
original = rockspec.source.url,
summary = descript.summary or "",
detailed = descript.detailed or "",
license = descript.license or "N/A",
homepage = descript.homepage and ('| project homepage') or "",
externaldependencies = format_external_dependencies(rockspec)
}
vars.detailed = vars.detailed:gsub("\n\n", "
"):gsub("%s+", " ")
vars.detailed = vars.detailed:gsub("(https?://[a-zA-Z0-9%.%%-_%+%[%]=%?&/$@;:]+)", '%1')
output = output:gsub("$(%w+)", vars)
else
output = output:gsub("$anchor", package)
output = output:gsub("$package", package)
output = output:gsub("$(%w+)", "")
end
out:write(output)
end
out:write(index_footer)
out:close()
end
luarocks-2.0.9/src/luarocks/type_check.lua 0000644 0001750 0000144 00000017514 11757524227 020014 0 ustar hisham users
--- Type-checking functions.
-- Functions and definitions for doing a basic lint check on files
-- loaded by LuaRocks.
module("luarocks.type_check", package.seeall)
local cfg = require("luarocks.cfg")
rockspec_format = "1.0"
rockspec_types = {
rockspec_format = "string",
MUST_package = "string",
MUST_version = "[%w.]+-[%d]+",
description = {
summary = "string",
detailed = "string",
homepage = "string",
license = "string",
maintainer = "string"
},
dependencies = {
platforms = {},
ANY = "string"
},
supported_platforms = {
ANY = "string"
},
external_dependencies = {
platforms = {},
ANY = {
program = "string",
header = "string",
library = "string"
}
},
MUST_source = {
platforms = {},
MUST_url = "string",
md5 = "string",
file = "string",
dir = "string",
tag = "string",
branch = "string",
module = "string",
cvs_tag = "string",
cvs_module = "string"
},
build = {
platforms = {},
type = "string",
install = {
lua = {
MORE = true
},
lib = {
MORE = true
},
conf = {
MORE = true
},
bin = {
MORE = true
}
},
copy_directories = {
ANY = "string"
},
MORE = true
},
hooks = {
platforms = {},
post_install = "string"
}
}
function load_extensions()
rockspec_format = "1.1"
rockspec_types.deploy = {
wrap_bin_scripts = true,
}
end
if cfg.use_extensions then
load_extensions()
end
rockspec_types.build.platforms.ANY = rockspec_types.build
rockspec_types.dependencies.platforms.ANY = rockspec_types.dependencies
rockspec_types.external_dependencies.platforms.ANY = rockspec_types.external_dependencies
rockspec_types.MUST_source.platforms.ANY = rockspec_types.MUST_source
rockspec_types.hooks.platforms.ANY = rockspec_types.hooks
manifest_types = {
MUST_repository = {
-- packages
ANY = {
-- versions
ANY = {
-- items
ANY = {
MUST_arch = "string",
modules = { ANY = "string" },
commands = { ANY = "string" },
dependencies = { ANY = "string" },
-- TODO: to be extended with more metadata.
}
}
}
},
MUST_modules = {
-- modules
ANY = {
-- providers
ANY = "string"
}
},
MUST_commands = {
-- modules
ANY = {
-- commands
ANY = "string"
}
},
dependencies = {
-- each module
ANY = {
-- each version
ANY = {
-- each dependency
ANY = {
name = "string",
constraints = {
ANY = {
no_upgrade = "boolean",
op = "string",
version = {
string = "string",
ANY = 0,
}
}
}
}
}
}
}
}
local type_check_table
--- Type check an object.
-- The object is compared against an archetypical value
-- matching the expected type -- the actual values don't matter,
-- only their types. Tables are type checked recursively.
-- @param name any: The object name (for error messages).
-- @param item any: The object being checked.
-- @param expected any: The reference object. In case of a table,
-- its is structured as a type reference table.
-- @param context string: A string indicating the "context" where the
-- error occurred (such as the name of the table the item is a part of),
-- to be used by error messages.
-- @return boolean or (nil, string): true if type checking
-- succeeded, or nil and an error message if it failed.
-- @see type_check_table
local function type_check_item(name, item, expected, context)
name = tostring(name)
local item_type = type(item)
local expected_type = type(expected)
if expected_type == "number" then
if not tonumber(item) then
return nil, "Type mismatch on field "..context..name..": expected a number"
end
elseif expected_type == "string" then
if not tostring(item) then
return nil, "Type mismatch on field "..context..name..": expected a value convertible to string"
end
if expected ~= "string" then
if not item:match("^"..expected.."$") then
return nil, "Type mismatch on field "..context..name..": invalid value "..item
end
end
elseif expected_type == "table" then
if item_type ~= expected_type then
return nil, "Type mismatch on field "..context..name..": expected a table"
else
return type_check_table(item, expected, context..name..".")
end
elseif item_type ~= expected_type then
return nil, "Type mismatch on field "..context..name..": expected a "..expected_type
end
return true
end
--- Type check the contents of a table.
-- The table's contents are compared against a reference table,
-- which contains the recognized fields, with archetypical values
-- matching the expected types -- the actual values of items in the
-- reference table don't matter, only their types (ie, for field x
-- in tbl that is correctly typed, type(tbl.x) == type(types.x)).
-- If the reference table contains a field called MORE, then
-- unknown fields in the checked table are accepted.
-- If it contains a field called ANY, then its type will be
-- used to check any unknown fields. If a field is prefixed
-- with MUST_, it is mandatory; its absence from the table is
-- a type error.
-- Tables are type checked recursively.
-- @param tbl table: The table to be type checked.
-- @param types table: The reference table, containing
-- values for recognized fields in the checked table.
-- @param context string: A string indicating the "context" where the
-- error occurred (such as the name of the table the item is a part of),
-- to be used by error messages.
-- @return boolean or (nil, string): true if type checking
-- succeeded, or nil and an error message if it failed.
type_check_table = function(tbl, types, context)
assert(type(tbl) == "table")
assert(type(types) == "table")
for k, v in pairs(tbl) do
local t = types[k] or (type(k) == "string" and types["MUST_"..k]) or types.ANY
if t then
local ok, err = type_check_item(k, v, t, context)
if not ok then return nil, err end
elseif types.MORE then
-- Accept unknown field
else
if not cfg.accept_unknown_fields then
return nil, "Unknown field "..k
end
end
end
for k, v in pairs(types) do
local mandatory_key = k:match("^MUST_(.+)")
if mandatory_key then
if not tbl[mandatory_key] then
return nil, "Mandatory field "..context..mandatory_key.." is missing."
end
end
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)
assert(type(rockspec) == "table")
if rockspec.rockspec_format then
-- relies on global state
load_extensions()
end
return type_check_table(rockspec, rockspec_types, "")
end
--- Type check a manifest table.
-- Verify the correctness of elements from a
-- manifest 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_manifest(manifest)
assert(type(manifest) == "table")
return type_check_table(manifest, manifest_types, "")
end
luarocks-2.0.9/src/luarocks/build/ 0000755 0001750 0000144 00000000000 11757524226 016261 5 ustar hisham users luarocks-2.0.9/src/luarocks/build/command.lua 0000644 0001750 0000144 00000001652 11757524226 020406 0 ustar hisham users
--- Build back-end for raw listing of commands in rockspec files.
module("luarocks.build.command", package.seeall)
local fs = require("luarocks.fs")
local util = require("luarocks.util")
--- Driver function for the "command" build back-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)
assert(type(rockspec) == "table")
local build = rockspec.build
util.variable_substitutions(build, rockspec.variables)
if build.build_command then
util.printout(build.build_command)
if not fs.execute(build.build_command) then
return nil, "Failed building."
end
end
if build.install_command then
util.printout(build.install_command)
if not fs.execute(build.install_command) then
return nil, "Failed installing."
end
end
return true
end
luarocks-2.0.9/src/luarocks/build/cmake.lua 0000644 0001750 0000144 00000003203 11757524226 020042 0 ustar hisham users
--- Build back-end for CMake-based modules.
module("luarocks.build.cmake", package.seeall)
local fs = require("luarocks.fs")
local util = require("luarocks.util")
local cfg = require("luarocks.cfg")
--- Driver function for the "cmake" build back-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)
assert(type(rockspec) == "table")
local build = rockspec.build
local variables = build.variables or {}
-- Pass Env variables
variables.CMAKE_MODULE_PATH=os.getenv("CMAKE_MODULE_PATH")
variables.CMAKE_LIBRARY_PATH=os.getenv("CMAKE_LIBRARY_PATH")
variables.CMAKE_INCLUDE_PATH=os.getenv("CMAKE_INCLUDE_PATH")
util.variable_substitutions(variables, rockspec.variables)
-- 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()
end
-- Execute cmake with variables.
local args = ""
if cfg.cmake_generator then
args = args .. ' -G"'..cfg.cmake_generator.. '"'
end
for k,v in pairs(variables) do
args = args .. ' -D' ..k.. '="' ..v.. '"'
end
if not fs.execute(rockspec.variables.CMAKE.." . " ..args) then
return nil, "Failed cmake."
end
if not fs.execute(rockspec.variables.MAKE.." -fMakefile") then
return nil, "Failed building."
end
if not fs.execute(rockspec.variables.MAKE.." -fMakefile install") then
return nil, "Failed installing."
end
return true
end
luarocks-2.0.9/src/luarocks/build/make.lua 0000644 0001750 0000144 00000006476 11757524226 017716 0 ustar hisham users
--- Build back-end for using Makefile-based packages.
module("luarocks.build.make", package.seeall)
local fs = require("luarocks.fs")
local util = require("luarocks.util")
local cfg = require("luarocks.cfg")
--- Call "make" with given target and variables
-- @param make_cmd string: the make command to be used (typically
-- configured through variables.MAKE in the config files, or
-- the appropriate platform-specific default).
-- @param pass boolean: If true, run make; if false, do nothing.
-- @param target string: The make target; an empty string indicates
-- the default target.
-- @param variables table: A table containing string-string key-value
-- pairs representing variable assignments to be passed to make.
-- @return boolean: false if any errors occurred, true otherwise.
local function make_pass(make_cmd, pass, target, variables)
assert(type(pass) == "boolean")
assert(type(target) == "string")
assert(type(variables) == "table")
local assignments = {}
for k,v in pairs(variables) do
table.insert(assignments, k.."="..v)
end
if pass then
return fs.execute(make_cmd.." "..target, unpack(assignments))
else
return true
end
end
--- Driver function for the "make" build back-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)
assert(type(rockspec) == "table")
local build = rockspec.build
if build.build_pass == nil then build.build_pass = true end
if build.install_pass == nil then build.install_pass = true end
build.build_variables = build.build_variables or {}
build.install_variables = build.install_variables or {}
build.build_target = build.build_target or ""
build.install_target = build.install_target or "install"
local makefile = build.makefile or cfg.makefile
if makefile then
-- Assumes all make's accept -f. True for POSIX make, GNU make and Microsoft nmake.
build.build_target = "-f "..makefile.." "..build.build_target
build.install_target = "-f "..makefile.." "..build.install_target
end
if build.variables then
for var, val in pairs(build.variables) do
build.build_variables[var] = val
build.install_variables[var] = val
end
end
util.warn_if_not_used(build.build_variables, { CFLAGS=true }, "variable %s was not passed in build_variables")
util.variable_substitutions(build.build_variables, rockspec.variables)
util.variable_substitutions(build.install_variables, rockspec.variables)
local auto_variables = { "CC" }
for _, variable in pairs(auto_variables) do
if not build.build_variables[variable] then
build.build_variables[variable] = rockspec.variables[variable]
end
if not build.install_variables[variable] then
build.install_variables[variable] = rockspec.variables[variable]
end
end
-- backwards compatibility
local make_cmd = cfg.make or rockspec.variables.MAKE
local ok = make_pass(make_cmd, build.build_pass, build.build_target, build.build_variables)
if not ok then
return nil, "Failed building."
end
ok = make_pass(make_cmd, build.install_pass, build.install_target, build.install_variables)
if not ok then
return nil, "Failed installing."
end
return true
end
luarocks-2.0.9/src/luarocks/build/builtin.lua 0000644 0001750 0000144 00000023425 11757524226 020440 0 ustar hisham users
--- A builtin build system: back-end to provide a portable way of building C-based Lua modules.
module("luarocks.build.builtin", package.seeall)
local fs = require("luarocks.fs")
local path = require("luarocks.path")
local util = require("luarocks.util")
local cfg = require("luarocks.cfg")
local dir = require("luarocks.dir")
--- Run a command displaying its execution on standard output.
-- @return boolean: true if command succeeds (status code 0), false
-- otherwise.
local function execute(...)
io.stdout:write(table.concat({...}, " ").."\n")
return fs.execute(...)
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)
local rcfile = io.open(rcfilename, "w")
if not rcfile then
error("Could not open "..rcfilename.." for writing.")
end
rcfile:write("STRINGTABLE\r\nBEGIN\r\n")
local i = 1
for line in io.lines(luafilename) do
if not line:match("^#!") then
rcfile:write(i .. " \"")
line = line:gsub("\\", "\\\\"):gsub('"', '""'):gsub("[\r\n]+", "")
rcfile:write(line .. "\\r\\n\"\r\n")
i = i + 1
end
end
rcfile:write("END\r\n")
rcfile:close()
end
--- Driver function for the builtin build back-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)
assert(type(rockspec) == "table")
local compile_object, compile_library, compile_wrapper_binary
local build = rockspec.build
local variables = rockspec.variables
local function add_flags(extras, flag, flags)
if flags then
if type(flags) ~= "table" then
flags = { tostring(flags) }
end
util.variable_substitutions(flags, variables)
for _, v in ipairs(flags) do
table.insert(extras, flag:format(v))
end
end
end
if cfg.is_platform("mingw32") then
compile_object = function(object, source, defines, incdirs)
local extras = {}
add_flags(extras, "-D%s", defines)
add_flags(extras, "-I%s", incdirs)
return execute(variables.CC.." "..variables.CFLAGS, "-c", "-o", object, "-I"..variables.LUA_INCDIR, source, unpack(extras))
end
compile_library = function(library, objects, libraries, libdirs, name)
local extras = { unpack(objects) }
add_flags(extras, "-L%s", libdirs)
add_flags(extras, "%s.lib", libraries)
extras[#extras+1] = dir.path(variables.LUA_LIBDIR, variables.LUALIB)
extras[#extras+1] = "-l" .. (variables.MSVCRT or "msvcr80")
local ok = execute(variables.LD.." "..variables.LIBFLAG, "-o", library, unpack(extras))
return ok
end
compile_wrapper_binary = function(fullname, name)
local fullbasename = fullname:gsub("%.lua$", ""):gsub("/", "\\")
local basename = name:gsub("%.lua$", ""):gsub("/", "\\")
local rcname = basename..".rc"
local resname = basename..".o"
local wrapname = basename..".exe"
make_rc(fullname, fullbasename..".rc")
local ok = execute(variables.RC, "-o", resname, rcname)
if not ok then return ok end
ok = execute(variables.LD, "-o", wrapname, resname, variables.WRAPPER,
dir.path(variables.LUA_LIBDIR, variables.LUALIB), "-l" .. (variables.MSVCRT or "msvcr80"), "-luser32")
return ok, wrapname
end
elseif cfg.is_platform("win32") then
compile_object = function(object, source, defines, incdirs)
local extras = {}
add_flags(extras, "-D%s", defines)
add_flags(extras, "-I%s", incdirs)
return execute(variables.CC.." "..variables.CFLAGS, "-c", "-Fo"..object, "-I"..variables.LUA_INCDIR, source, unpack(extras))
end
compile_library = function(library, objects, libraries, libdirs, name)
local extras = { unpack(objects) }
add_flags(extras, "-libpath:%s", libdirs)
add_flags(extras, "%s.lib", libraries)
local basename = dir.base_name(library):gsub(".[^.]*$", "")
local deffile = basename .. ".def"
local def = io.open(dir.path(fs.current_dir(), deffile), "w+")
def:write("EXPORTS\n")
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"
if ok and fs.exists(manifestfile) then
ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:"..basename..".dll;2")
end
return ok
end
compile_wrapper_binary = function(fullname, name)
local fullbasename = fullname:gsub("%.lua$", ""):gsub("/", "\\")
local basename = name:gsub("%.lua$", ""):gsub("/", "\\")
local rcname = basename..".rc"
local resname = basename..".res"
local wrapname = basename..".exe"
make_rc(fullname, fullbasename..".rc")
local ok = execute(variables.RC, "-r", "-fo"..resname, rcname)
if not ok then return ok end
ok = execute(variables.LD, "-out:"..wrapname, resname, variables.WRAPPER,
dir.path(variables.LUA_LIBDIR, variables.LUALIB), "user32.lib")
local manifestfile = wrapname..".manifest"
if ok and fs.exists(manifestfile) then
ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:"..wrapname..";1")
end
return ok, wrapname
end
else
compile_object = function(object, source, defines, incdirs)
local extras = {}
add_flags(extras, "-D%s", defines)
add_flags(extras, "-I%s", incdirs)
return execute(variables.CC.." "..variables.CFLAGS, "-I"..variables.LUA_INCDIR, "-c", source, "-o", object, unpack(extras))
end
compile_library = function (library, objects, libraries, libdirs)
local extras = { unpack(objects) }
add_flags(extras, "-L%s", libdirs)
add_flags(extras, "-l%s", libraries)
if cfg.is_platform("cygwin") then
add_flags(extras, "-l%s", {"lua"})
end
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
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)
-- 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
if build.install and build.install.bin then
for i, name in ipairs(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
ok, name = compile_wrapper_binary(fullname, name)
if ok then
build.install.bin[i] = 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
if info:match("init%.lua$") and not name:match("%.init$") then
moddir = path.module_to_path(name..".init")
end
local dest = dir.path(luadir, moddir)
built_modules[info] = dest
else
info = {info}
end
end
if type(info) == "table" then
local objects = {}
local sources = info.sources
if info[1] then sources = info end
if type(sources) == "string" then sources = {sources} end
for _, source in ipairs(sources) do
local object = source:gsub(".[^.]*$", "."..cfg.obj_extension)
if not object then
object = source.."."..cfg.obj_extension
end
ok = compile_object(object, source, info.defines, info.incdirs)
if not ok then
err = "Failed compiling object "..object
break
end
table.insert(objects, object)
end
if not ok then break end
local module_name = dir.path(moddir, name:match("([^.]*)$").."."..cfg.lib_extension):gsub("//", "/")
if moddir ~= "" then
fs.make_dir(moddir)
end
local dest = dir.path(libdir, moddir)
built_modules[module_name] = dest
ok = compile_library(module_name, objects, info.libraries, info.libdirs, name)
if not ok then
err = "Failed compiling module "..module_name
break
end
end
end
for name, dest in pairs(built_modules) do
fs.make_dir(dest)
ok = fs.copy(name, dest)
if not ok then
err = "Failed installing "..name.." in "..dest
break
end
end
if ok then
if fs.is_dir("lua") then
ok = fs.copy_contents("lua", luadir)
if not ok then err = "Failed copying contents of 'lua' directory." end
end
end
if ok then
return true
else
return nil, err
end
end
luarocks-2.0.9/src/luarocks/install.lua 0000644 0001750 0000144 00000012330 11757524227 017333 0 ustar hisham users
--- Module implementing the LuaRocks "install" command.
-- Installs binary rocks.
module("luarocks.install", package.seeall)
local path = require("luarocks.path")
local rep = require("luarocks.rep")
local fetch = require("luarocks.fetch")
local util = require("luarocks.util")
local fs = require("luarocks.fs")
local deps = require("luarocks.deps")
local manif = require("luarocks.manif")
local cfg = require("luarocks.cfg")
help_summary = "Install a rock."
help_arguments = "{| []}"
help = [[
Argument may be the name of a rock to be fetched from a repository
or a filename of a locally available rock.
]]
--- Install a binary rock.
-- @param rock_file string: local or remote filename of a rock.
-- @param no_deps boolean: true if dependency check needs to be skipped
-- @return boolean or (nil, string, [string]): True if succeeded or
-- nil and an error message and an optional error code.
function install_binary_rock(rock_file, no_deps)
assert(type(rock_file) == "string")
local name, version, arch = path.parse_name(rock_file)
if not name then
return nil, "Filename "..rock_file.." does not match format 'name-version-revision.arch.rock'."
end
if arch ~= "all" and arch ~= cfg.arch then
return nil, "Incompatible architecture "..arch, "arch"
end
if rep.is_installed(name, version) then
rep.delete_version(name, version)
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 ok, err, errcode = fetch.fetch_and_unpack_rock(rock_file, path.install_dir(name, version))
if not ok then return nil, err, errcode end
local rockspec, err, errcode = fetch.load_rockspec(path.rockspec_file(name, version))
if err then
return nil, "Failed loading rockspec for installed package: "..err, errcode
end
if no_deps then
util.printerr("Warning: skipping dependency checks.")
else
ok, err, errcode = deps.check_external_deps(rockspec, "install")
if err then return nil, err, errcode end
end
-- For compatibility with .rock files built with LuaRocks 1
if not fs.exists(path.rock_manifest_file(name, version)) then
ok, err = manif.make_rock_manifest(name, version)
if err then return nil, err end
end
if not no_deps then
ok, err, errcode = deps.fulfill_dependencies(rockspec)
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 = rep.deploy_files(name, version, rep.should_wrap_bin_scripts(rockspec))
if err then return nil, err end
util.remove_scheduled_function(rollback)
rollback = util.schedule_function(function()
rep.delete_version(name, version)
end)
ok, err = rep.run_hook(rockspec, "post_install")
if err then return nil, err end
ok, err = manif.update_manifest(name, version)
if err then return nil, err end
local license = ""
if rockspec.description.license then
license = ("(license: "..rockspec.description.license..")")
end
local root_dir = path.root_dir(cfg.rocks_dir)
util.printout()
util.printout(name.." "..version.." is now installed in "..root_dir.." "..license)
util.remove_scheduled_function(rollback)
return true
end
--- Driver function for the "install" command.
-- @param name string: name of a binary rock. If an URL or pathname
-- to a binary rock is given, fetches and installs it. If a rockspec or a
-- source rock is given, forwards the request to the "build" command.
-- If a package name is given, forwards the request to "search" and,
-- 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(...)
local flags, name, version = util.parse_flags(...)
if type(name) ~= "string" then
return nil, "Argument missing, see help."
end
local ok, err = fs.check_command_permissions(flags)
if not ok then return nil, err 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, flags["local"] and "--local")
elseif name:match("%.rock$") then
return install_binary_rock(name, flags["nodeps"])
else
local search = require("luarocks.search")
local results, err = search.find_suitable_rock(search.make_query(name:lower(), version))
if err then
return nil, err
elseif type(results) == "string" then
local url = results
util.printout("Installing "..url.."...")
return run(url)
else
util.printout()
util.printerr("Could not determine which rock to install.")
util.printout()
util.printout("Search results:")
util.printout("---------------")
search.print_results(results)
return nil, (next(results) and "Please narrow your query." or "No results found.")
end
end
end
luarocks-2.0.9/src/luarocks/validate.lua 0000644 0001750 0000144 00000011157 11757524227 017464 0 ustar hisham users
--- Sandboxed test of build/install of all packages in a repository (unfinished and disabled).
module("luarocks.validate", package.seeall)
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local path = require("luarocks.path")
local cfg = require("luarocks.cfg")
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."
help = [[
, if given, is a local repository pathname.
]]
local function save_settings(repo)
local protocol, path = dir.split_url(repo)
table.insert(cfg.rocks_servers, 1, protocol.."://"..path)
return {
root_dir = cfg.root_dir,
rocks_dir = cfg.rocks_dir,
deploy_bin_dir = cfg.deploy_bin_dir,
deploy_lua_dir = cfg.deploy_lua_dir,
deploy_lib_dir = cfg.deploy_lib_dir,
}
end
local function restore_settings(settings)
cfg.root_dir = settings.root_dir
cfg.rocks_dir = settings.rocks_dir
cfg.deploy_bin_dir = settings.deploy_bin_dir
cfg.deploy_lua_dir = settings.deploy_lua_dir
cfg.deploy_lib_dir = settings.deploy_lib_dir
cfg.variables.ROCKS_TREE = settings.rocks_dir
cfg.variables.SCRIPTS_DIR = settings.deploy_bin_dir
table.remove(cfg.rocks_servers, 1)
end
local function prepare_sandbox(file)
local root_dir = fs.make_temp_dir(file):gsub("/+$", "")
cfg.root_dir = root_dir
cfg.rocks_dir = path.rocks_dir(root_dir)
cfg.deploy_bin_dir = path.deploy_bin_dir(root_dir)
cfg.variables.ROCKS_TREE = cfg.rocks_dir
cfg.variables.SCRIPTS_DIR = cfg.deploy_bin_dir
return root_dir
end
local function validate_rockspec(file)
local ok, err, errcode = build.build_rockspec(file, true)
if not ok then
util.printerr(err)
end
return ok, err, errcode
end
local function validate_src_rock(file)
local ok, err, errcode = build.build_rock(file, false)
if not ok then
util.printerr(err)
end
return ok, err, errcode
end
local function validate_rock(file)
local ok, err, errcode = install.install_binary_rock(file)
if not ok then
util.printerr(err)
end
return ok, err, errcode
end
local function validate(repo, flags)
local results = {
ok = {}
}
local settings = save_settings(repo)
local sandbox
if flags["quick"] then
sandbox = prepare_sandbox("luarocks_validate")
end
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
if file == "manifest" or file == "index.html" then
break -- continue for
end
local pathname = fs.absolute_name(dir.path(repo, file))
if not flags["quick"] then
sandbox = prepare_sandbox(file)
end
local ok, err, errcode
util.printout()
util.printout("Verifying "..pathname)
if file:match("%.rockspec$") then
ok, err, errcode = validate_rockspec(pathname)
elseif file:match("%.src%.rock$") then
ok, err, errcode = validate_src_rock(pathname)
elseif file:match("%.rock$") then
ok, err, errcode = validate_rock(pathname)
end
if ok then
table.insert(results.ok, {file=file} )
else
if not errcode then
errcode = "misc"
end
if not results[errcode] then
results[errcode] = {}
end
table.insert(results[errcode], {file=file, err=err} )
end
util.run_scheduled_functions()
if not flags["quick"] then
fs.delete(sandbox)
end
repeat until not fs.pop_dir()
end end
if flags["quick"] then
fs.delete(sandbox)
end
restore_settings(settings)
util.printout()
util.printout("Results:")
util.printout("--------")
util.printout("OK: "..tostring(#results.ok))
for _, entry in ipairs(results.ok) do
util.printout(entry.file)
end
for errcode, errors in pairs(results) do
if errcode ~= "ok" then
util.printout()
util.printout(errcode.." errors: "..tostring(#errors))
for _, entry in ipairs(errors) do
util.printout(entry.file, entry.err)
end
end
end
util.printout()
util.printout("Summary:")
util.printout("--------")
local total = 0
for errcode, errors in pairs(results) do
util.printout(errcode..": "..tostring(#errors))
total = total + #errors
end
util.printout("Total: "..total)
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
luarocks-2.0.9/src/bin/ 0000755 0001750 0000144 00000000000 11757524232 014104 5 ustar hisham users luarocks-2.0.9/src/bin/luarocks 0000755 0001750 0000144 00000001417 11757524226 015663 0 ustar hisham users #!/usr/bin/env lua
local command_line = require("luarocks.command_line")
program_name = "luarocks"
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")
command_line.run_command(...)
luarocks-2.0.9/src/bin/luarocks-admin 0000755 0001750 0000144 00000000731 11757524226 016747 0 ustar hisham users #!/usr/bin/env lua
local command_line = require("luarocks.command_line")
program_name = "luarocks-admin"
program_description = "LuaRocks repository administration interface"
commands = {
}
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(...)