fix: remove files added by mistake

This commit is contained in:
Lewis Russell 2024-07-03 17:22:18 +01:00
parent cc908326c9
commit 04e0644182
110 changed files with 0 additions and 23129 deletions

Binary file not shown.

Binary file not shown.

View file

@ -1,174 +0,0 @@
/*
** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
#ifndef lauxlib_h
#define lauxlib_h
#include <stddef.h>
#include <stdio.h>
#include "lua.h"
#if defined(LUA_COMPAT_GETN)
LUALIB_API int (luaL_getn) (lua_State *L, int t);
LUALIB_API void (luaL_setn) (lua_State *L, int t, int n);
#else
#define luaL_getn(L,i) ((int)lua_objlen(L, i))
#define luaL_setn(L,i,j) ((void)0) /* no op! */
#endif
#if defined(LUA_COMPAT_OPENLIB)
#define luaI_openlib luaL_openlib
#endif
/* extra error code for `luaL_load' */
#define LUA_ERRFILE (LUA_ERRERR+1)
typedef struct luaL_Reg {
const char *name;
lua_CFunction func;
} luaL_Reg;
LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname,
const luaL_Reg *l, int nup);
LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
const luaL_Reg *l);
LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);
LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,
size_t *l);
LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,
const char *def, size_t *l);
LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);
LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
lua_Integer def);
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
LUALIB_API void (luaL_where) (lua_State *L, int lvl);
LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
const char *const lst[]);
LUALIB_API int (luaL_ref) (lua_State *L, int t);
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);
LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,
const char *name);
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
LUALIB_API lua_State *(luaL_newstate) (void);
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
const char *r);
LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
const char *fname, int szhint);
/*
** ===============================================================
** some useful macros
** ===============================================================
*/
#define luaL_argcheck(L, cond,numarg,extramsg) \
((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
#define luaL_dofile(L, fn) \
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
#define luaL_dostring(L, s) \
(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
/*
** {======================================================
** Generic Buffer manipulation
** =======================================================
*/
typedef struct luaL_Buffer {
char *p; /* current position in buffer */
int lvl; /* number of strings in the stack (level) */
lua_State *L;
char buffer[LUAL_BUFFERSIZE];
} luaL_Buffer;
#define luaL_addchar(B,c) \
((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
(*(B)->p++ = (char)(c)))
/* compatibility only */
#define luaL_putchar(B,c) luaL_addchar(B,c)
#define luaL_addsize(B,n) ((B)->p += (n))
LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B);
LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
/* }====================================================== */
/* compatibility with ref system */
/* pre-defined references */
#define LUA_NOREF (-2)
#define LUA_REFNIL (-1)
#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
(lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))
#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref))
#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref))
#define luaL_reg luaL_Reg
#endif

View file

@ -1,388 +0,0 @@
/*
** $Id: lua.h,v 1.218.1.7 2012/01/13 20:36:20 roberto Exp $
** Lua - An Extensible Extension Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file
*/
#ifndef lua_h
#define lua_h
#include <stdarg.h>
#include <stddef.h>
#include "luaconf.h"
#define LUA_VERSION "Lua 5.1"
#define LUA_RELEASE "Lua 5.1.5"
#define LUA_VERSION_NUM 501
#define LUA_COPYRIGHT "Copyright (C) 1994-2012 Lua.org, PUC-Rio"
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
/* mark for precompiled code (`<esc>Lua') */
#define LUA_SIGNATURE "\033Lua"
/* option for multiple returns in `lua_pcall' and `lua_call' */
#define LUA_MULTRET (-1)
/*
** pseudo-indices
*/
#define LUA_REGISTRYINDEX (-10000)
#define LUA_ENVIRONINDEX (-10001)
#define LUA_GLOBALSINDEX (-10002)
#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
/* thread status; 0 is OK */
#define LUA_YIELD 1
#define LUA_ERRRUN 2
#define LUA_ERRSYNTAX 3
#define LUA_ERRMEM 4
#define LUA_ERRERR 5
typedef struct lua_State lua_State;
typedef int (*lua_CFunction) (lua_State *L);
/*
** functions that read/write blocks when loading/dumping Lua chunks
*/
typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);
/*
** prototype for memory-allocation functions
*/
typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
/*
** basic types
*/
#define LUA_TNONE (-1)
#define LUA_TNIL 0
#define LUA_TBOOLEAN 1
#define LUA_TLIGHTUSERDATA 2
#define LUA_TNUMBER 3
#define LUA_TSTRING 4
#define LUA_TTABLE 5
#define LUA_TFUNCTION 6
#define LUA_TUSERDATA 7
#define LUA_TTHREAD 8
/* minimum Lua stack available to a C function */
#define LUA_MINSTACK 20
/*
** generic extra include file
*/
#if defined(LUA_USER_H)
#include LUA_USER_H
#endif
/* type of numbers in Lua */
typedef LUA_NUMBER lua_Number;
/* type for integer functions */
typedef LUA_INTEGER lua_Integer;
/*
** state manipulation
*/
LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
LUA_API void (lua_close) (lua_State *L);
LUA_API lua_State *(lua_newthread) (lua_State *L);
LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
/*
** basic stack manipulation
*/
LUA_API int (lua_gettop) (lua_State *L);
LUA_API void (lua_settop) (lua_State *L, int idx);
LUA_API void (lua_pushvalue) (lua_State *L, int idx);
LUA_API void (lua_remove) (lua_State *L, int idx);
LUA_API void (lua_insert) (lua_State *L, int idx);
LUA_API void (lua_replace) (lua_State *L, int idx);
LUA_API int (lua_checkstack) (lua_State *L, int sz);
LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);
/*
** access functions (stack -> C)
*/
LUA_API int (lua_isnumber) (lua_State *L, int idx);
LUA_API int (lua_isstring) (lua_State *L, int idx);
LUA_API int (lua_iscfunction) (lua_State *L, int idx);
LUA_API int (lua_isuserdata) (lua_State *L, int idx);
LUA_API int (lua_type) (lua_State *L, int idx);
LUA_API const char *(lua_typename) (lua_State *L, int tp);
LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2);
LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2);
LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx);
LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx);
LUA_API int (lua_toboolean) (lua_State *L, int idx);
LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
LUA_API size_t (lua_objlen) (lua_State *L, int idx);
LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx);
LUA_API void *(lua_touserdata) (lua_State *L, int idx);
LUA_API lua_State *(lua_tothread) (lua_State *L, int idx);
LUA_API const void *(lua_topointer) (lua_State *L, int idx);
/*
** push functions (C -> stack)
*/
LUA_API void (lua_pushnil) (lua_State *L);
LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l);
LUA_API void (lua_pushstring) (lua_State *L, const char *s);
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
va_list argp);
LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
LUA_API void (lua_pushboolean) (lua_State *L, int b);
LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);
LUA_API int (lua_pushthread) (lua_State *L);
/*
** get functions (Lua -> stack)
*/
LUA_API void (lua_gettable) (lua_State *L, int idx);
LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k);
LUA_API void (lua_rawget) (lua_State *L, int idx);
LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n);
LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
LUA_API void (lua_getfenv) (lua_State *L, int idx);
/*
** set functions (stack -> Lua)
*/
LUA_API void (lua_settable) (lua_State *L, int idx);
LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
LUA_API void (lua_rawset) (lua_State *L, int idx);
LUA_API void (lua_rawseti) (lua_State *L, int idx, int n);
LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
LUA_API int (lua_setfenv) (lua_State *L, int idx);
/*
** `load' and `call' functions (load and run Lua code)
*/
LUA_API void (lua_call) (lua_State *L, int nargs, int nresults);
LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud);
LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
const char *chunkname);
LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
/*
** coroutine functions
*/
LUA_API int (lua_yield) (lua_State *L, int nresults);
LUA_API int (lua_resume) (lua_State *L, int narg);
LUA_API int (lua_status) (lua_State *L);
/*
** garbage-collection function and options
*/
#define LUA_GCSTOP 0
#define LUA_GCRESTART 1
#define LUA_GCCOLLECT 2
#define LUA_GCCOUNT 3
#define LUA_GCCOUNTB 4
#define LUA_GCSTEP 5
#define LUA_GCSETPAUSE 6
#define LUA_GCSETSTEPMUL 7
LUA_API int (lua_gc) (lua_State *L, int what, int data);
/*
** miscellaneous functions
*/
LUA_API int (lua_error) (lua_State *L);
LUA_API int (lua_next) (lua_State *L, int idx);
LUA_API void (lua_concat) (lua_State *L, int n);
LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
/*
** ===============================================================
** some useful macros
** ===============================================================
*/
#define lua_pop(L,n) lua_settop(L, -(n)-1)
#define lua_newtable(L) lua_createtable(L, 0, 0)
#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
#define lua_strlen(L,i) lua_objlen(L, (i))
#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
#define lua_pushliteral(L, s) \
lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s))
#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s))
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
/*
** compatibility macros and functions
*/
#define lua_open() luaL_newstate()
#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)
#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0)
#define lua_Chunkreader lua_Reader
#define lua_Chunkwriter lua_Writer
/* hack */
LUA_API void lua_setlevel (lua_State *from, lua_State *to);
/*
** {======================================================================
** Debug API
** =======================================================================
*/
/*
** Event codes
*/
#define LUA_HOOKCALL 0
#define LUA_HOOKRET 1
#define LUA_HOOKLINE 2
#define LUA_HOOKCOUNT 3
#define LUA_HOOKTAILRET 4
/*
** Event masks
*/
#define LUA_MASKCALL (1 << LUA_HOOKCALL)
#define LUA_MASKRET (1 << LUA_HOOKRET)
#define LUA_MASKLINE (1 << LUA_HOOKLINE)
#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
typedef struct lua_Debug lua_Debug; /* activation record */
/* Functions to be called by the debuger in specific events */
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n);
LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n);
LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);
LUA_API lua_Hook lua_gethook (lua_State *L);
LUA_API int lua_gethookmask (lua_State *L);
LUA_API int lua_gethookcount (lua_State *L);
struct lua_Debug {
int event;
const char *name; /* (n) */
const char *namewhat; /* (n) `global', `local', `field', `method' */
const char *what; /* (S) `Lua', `C', `main', `tail' */
const char *source; /* (S) */
int currentline; /* (l) */
int nups; /* (u) number of upvalues */
int linedefined; /* (S) */
int lastlinedefined; /* (S) */
char short_src[LUA_IDSIZE]; /* (S) */
/* private part */
int i_ci; /* active function */
};
/* }====================================================================== */
/******************************************************************************
* Copyright (C) 1994-2012 Lua.org, PUC-Rio. All rights reserved.
*
* 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.
******************************************************************************/
#endif

View file

@ -1,9 +0,0 @@
// lua.hpp
// Lua header files for C++
// <<extern "C">> not supplied automatically because Lua also compiles as C++
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}

View file

@ -1,763 +0,0 @@
/*
** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $
** Configuration file for Lua
** See Copyright Notice in lua.h
*/
#ifndef lconfig_h
#define lconfig_h
#include <limits.h>
#include <stddef.h>
/*
** ==================================================================
** Search for "@@" to find all configurable definitions.
** ===================================================================
*/
/*
@@ LUA_ANSI controls the use of non-ansi features.
** CHANGE it (define it) if you want Lua to avoid the use of any
** non-ansi feature or library.
*/
#if defined(__STRICT_ANSI__)
#define LUA_ANSI
#endif
#if !defined(LUA_ANSI) && defined(_WIN32)
#define LUA_WIN
#endif
#if defined(LUA_USE_LINUX)
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
#define LUA_USE_READLINE /* needs some extra libraries */
#endif
#if defined(LUA_USE_MACOSX)
#define LUA_USE_POSIX
#define LUA_DL_DYLD /* does not need extra library */
#endif
/*
@@ LUA_USE_POSIX includes all functionallity listed as X/Open System
@* Interfaces Extension (XSI).
** CHANGE it (define it) if your system is XSI compatible.
*/
#if defined(LUA_USE_POSIX)
#define LUA_USE_MKSTEMP
#define LUA_USE_ISATTY
#define LUA_USE_POPEN
#define LUA_USE_ULONGJMP
#endif
/*
@@ LUA_PATH and LUA_CPATH are the names of the environment variables that
@* Lua check to set its paths.
@@ LUA_INIT is the name of the environment variable that Lua
@* checks for initialization code.
** CHANGE them if you want different names.
*/
#define LUA_PATH "LUA_PATH"
#define LUA_CPATH "LUA_CPATH"
#define LUA_INIT "LUA_INIT"
/*
@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for
@* Lua libraries.
@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for
@* C libraries.
** CHANGE them if your machine has a non-conventional directory
** hierarchy or if you want to install your libraries in
** non-conventional directories.
*/
#if defined(_WIN32)
/*
** In Windows, any exclamation mark ('!') in the path is replaced by the
** path of the directory of the executable file of the current process.
*/
#define LUA_LDIR "!\\lua\\"
#define LUA_CDIR "!\\"
#define LUA_PATH_DEFAULT \
".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua"
#define LUA_CPATH_DEFAULT \
".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
#else
#define LUA_ROOT "/usr/local/"
#define LUA_LDIR LUA_ROOT "share/lua/5.1/"
#define LUA_CDIR LUA_ROOT "lib/lua/5.1/"
#define LUA_PATH_DEFAULT \
"./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua"
#define LUA_CPATH_DEFAULT \
"./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so"
#endif
/*
@@ LUA_DIRSEP is the directory separator (for submodules).
** CHANGE it if your machine does not use "/" as the directory separator
** and is not Windows. (On Windows Lua automatically uses "\".)
*/
#if defined(_WIN32)
#define LUA_DIRSEP "\\"
#else
#define LUA_DIRSEP "/"
#endif
/*
@@ LUA_PATHSEP is the character that separates templates in a path.
@@ LUA_PATH_MARK is the string that marks the substitution points in a
@* template.
@@ LUA_EXECDIR in a Windows path is replaced by the executable's
@* directory.
@@ LUA_IGMARK is a mark to ignore all before it when bulding the
@* luaopen_ function name.
** CHANGE them if for some reason your system cannot use those
** characters. (E.g., if one of those characters is a common character
** in file/directory names.) Probably you do not need to change them.
*/
#define LUA_PATHSEP ";"
#define LUA_PATH_MARK "?"
#define LUA_EXECDIR "!"
#define LUA_IGMARK "-"
/*
@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
** machines, ptrdiff_t gives a good choice between int or long.)
*/
#define LUA_INTEGER ptrdiff_t
/*
@@ LUA_API is a mark for all core API functions.
@@ LUALIB_API is a mark for all standard library functions.
** CHANGE them if you need to define those functions in some special way.
** For instance, if you want to create one Windows DLL with the core and
** the libraries, you may want to use the following definition (define
** LUA_BUILD_AS_DLL to get it).
*/
#if defined(LUA_BUILD_AS_DLL)
#if defined(LUA_CORE) || defined(LUA_LIB)
#define LUA_API __declspec(dllexport)
#else
#define LUA_API __declspec(dllimport)
#endif
#else
#define LUA_API extern
#endif
/* more often than not the libs go together with the core */
#define LUALIB_API LUA_API
/*
@@ LUAI_FUNC is a mark for all extern functions that are not to be
@* exported to outside modules.
@@ LUAI_DATA is a mark for all extern (const) variables that are not to
@* be exported to outside modules.
** CHANGE them if you need to mark them in some special way. Elf/gcc
** (versions 3.2 and later) mark them as "hidden" to optimize access
** when Lua is compiled as a shared library.
*/
#if defined(luaall_c)
#define LUAI_FUNC static
#define LUAI_DATA /* empty */
#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
defined(__ELF__)
#define LUAI_FUNC __attribute__((visibility("hidden"))) extern
#define LUAI_DATA LUAI_FUNC
#else
#define LUAI_FUNC extern
#define LUAI_DATA extern
#endif
/*
@@ LUA_QL describes how error messages quote program elements.
** CHANGE it if you want a different appearance.
*/
#define LUA_QL(x) "'" x "'"
#define LUA_QS LUA_QL("%s")
/*
@@ LUA_IDSIZE gives the maximum size for the description of the source
@* of a function in debug information.
** CHANGE it if you want a different size.
*/
#define LUA_IDSIZE 60
/*
** {==================================================================
** Stand-alone configuration
** ===================================================================
*/
#if defined(lua_c) || defined(luaall_c)
/*
@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that
@* is, whether we're running lua interactively).
** CHANGE it if you have a better definition for non-POSIX/non-Windows
** systems.
*/
#if defined(LUA_USE_ISATTY)
#include <unistd.h>
#define lua_stdin_is_tty() isatty(0)
#elif defined(LUA_WIN)
#include <io.h>
#include <stdio.h>
#define lua_stdin_is_tty() _isatty(_fileno(stdin))
#else
#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
#endif
/*
@@ LUA_PROMPT is the default prompt used by stand-alone Lua.
@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua.
** CHANGE them if you want different prompts. (You can also change the
** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.)
*/
#define LUA_PROMPT "> "
#define LUA_PROMPT2 ">> "
/*
@@ LUA_PROGNAME is the default name for the stand-alone Lua program.
** CHANGE it if your stand-alone interpreter has a different name and
** your system is not able to detect that name automatically.
*/
#define LUA_PROGNAME "lua"
/*
@@ LUA_MAXINPUT is the maximum length for an input line in the
@* stand-alone interpreter.
** CHANGE it if you need longer lines.
*/
#define LUA_MAXINPUT 512
/*
@@ lua_readline defines how to show a prompt and then read a line from
@* the standard input.
@@ lua_saveline defines how to "save" a read line in a "history".
@@ lua_freeline defines how to free a line read by lua_readline.
** CHANGE them if you want to improve this functionality (e.g., by using
** GNU readline and history facilities).
*/
#if defined(LUA_USE_READLINE)
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
#define lua_saveline(L,idx) \
if (lua_strlen(L,idx) > 0) /* non-empty line? */ \
add_history(lua_tostring(L, idx)); /* add it to history */
#define lua_freeline(L,b) ((void)L, free(b))
#else
#define lua_readline(L,b,p) \
((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
#define lua_saveline(L,idx) { (void)L; (void)idx; }
#define lua_freeline(L,b) { (void)L; (void)b; }
#endif
#endif
/* }================================================================== */
/*
@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles
@* as a percentage.
** CHANGE it if you want the GC to run faster or slower (higher values
** mean larger pauses which mean slower collection.) You can also change
** this value dynamically.
*/
#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */
/*
@@ LUAI_GCMUL defines the default speed of garbage collection relative to
@* memory allocation as a percentage.
** CHANGE it if you want to change the granularity of the garbage
** collection. (Higher values mean coarser collections. 0 represents
** infinity, where each step performs a full collection.) You can also
** change this value dynamically.
*/
#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */
/*
@@ LUA_COMPAT_GETN controls compatibility with old getn behavior.
** CHANGE it (define it) if you want exact compatibility with the
** behavior of setn/getn in Lua 5.0.
*/
#undef LUA_COMPAT_GETN
/*
@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib.
** CHANGE it to undefined as soon as you do not need a global 'loadlib'
** function (the function is still available as 'package.loadlib').
*/
#undef LUA_COMPAT_LOADLIB
/*
@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature.
** CHANGE it to undefined as soon as your programs use only '...' to
** access vararg parameters (instead of the old 'arg' table).
*/
#define LUA_COMPAT_VARARG
/*
@@ LUA_COMPAT_MOD controls compatibility with old math.mod function.
** CHANGE it to undefined as soon as your programs use 'math.fmod' or
** the new '%' operator instead of 'math.mod'.
*/
#define LUA_COMPAT_MOD
/*
@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting
@* facility.
** CHANGE it to 2 if you want the old behaviour, or undefine it to turn
** off the advisory error when nesting [[...]].
*/
#define LUA_COMPAT_LSTR 1
/*
@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name.
** CHANGE it to undefined as soon as you rename 'string.gfind' to
** 'string.gmatch'.
*/
#define LUA_COMPAT_GFIND
/*
@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib'
@* behavior.
** CHANGE it to undefined as soon as you replace to 'luaL_register'
** your uses of 'luaL_openlib'
*/
#define LUA_COMPAT_OPENLIB
/*
@@ luai_apicheck is the assert macro used by the Lua-C API.
** CHANGE luai_apicheck if you want Lua to perform some checks in the
** parameters it gets from API calls. This may slow down the interpreter
** a bit, but may be quite useful when debugging C code that interfaces
** with Lua. A useful redefinition is to use assert.h.
*/
#if defined(LUA_USE_APICHECK)
#include <assert.h>
#define luai_apicheck(L,o) { (void)L; assert(o); }
#else
#define luai_apicheck(L,o) { (void)L; }
#endif
/*
@@ LUAI_BITSINT defines the number of bits in an int.
** CHANGE here if Lua cannot automatically detect the number of bits of
** your machine. Probably you do not need to change this.
*/
/* avoid overflows in comparison */
#if INT_MAX-20 < 32760
#define LUAI_BITSINT 16
#elif INT_MAX > 2147483640L
/* int has at least 32 bits */
#define LUAI_BITSINT 32
#else
#error "you must define LUA_BITSINT with number of bits in an integer"
#endif
/*
@@ LUAI_UINT32 is an unsigned integer with at least 32 bits.
@@ LUAI_INT32 is an signed integer with at least 32 bits.
@@ LUAI_UMEM is an unsigned integer big enough to count the total
@* memory used by Lua.
@@ LUAI_MEM is a signed integer big enough to count the total memory
@* used by Lua.
** CHANGE here if for some weird reason the default definitions are not
** good enough for your machine. (The definitions in the 'else'
** part always works, but may waste space on machines with 64-bit
** longs.) Probably you do not need to change this.
*/
#if LUAI_BITSINT >= 32
#define LUAI_UINT32 unsigned int
#define LUAI_INT32 int
#define LUAI_MAXINT32 INT_MAX
#define LUAI_UMEM size_t
#define LUAI_MEM ptrdiff_t
#else
/* 16-bit ints */
#define LUAI_UINT32 unsigned long
#define LUAI_INT32 long
#define LUAI_MAXINT32 LONG_MAX
#define LUAI_UMEM unsigned long
#define LUAI_MEM long
#endif
/*
@@ LUAI_MAXCALLS limits the number of nested calls.
** CHANGE it if you need really deep recursive calls. This limit is
** arbitrary; its only purpose is to stop infinite recursion before
** exhausting memory.
*/
#define LUAI_MAXCALLS 20000
/*
@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function
@* can use.
** CHANGE it if you need lots of (Lua) stack space for your C
** functions. This limit is arbitrary; its only purpose is to stop C
** functions to consume unlimited stack space. (must be smaller than
** -LUA_REGISTRYINDEX)
*/
#define LUAI_MAXCSTACK 8000
/*
** {==================================================================
** CHANGE (to smaller values) the following definitions if your system
** has a small C stack. (Or you may want to change them to larger
** values if your system has a large C stack and these limits are
** too rigid for you.) Some of these constants control the size of
** stack-allocated arrays used by the compiler or the interpreter, while
** others limit the maximum number of recursive calls that the compiler
** or the interpreter can perform. Values too large may cause a C stack
** overflow for some forms of deep constructs.
** ===================================================================
*/
/*
@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and
@* syntactical nested non-terminals in a program.
*/
#define LUAI_MAXCCALLS 200
/*
@@ LUAI_MAXVARS is the maximum number of local variables per function
@* (must be smaller than 250).
*/
#define LUAI_MAXVARS 200
/*
@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function
@* (must be smaller than 250).
*/
#define LUAI_MAXUPVALUES 60
/*
@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
*/
#define LUAL_BUFFERSIZE BUFSIZ
/* }================================================================== */
/*
** {==================================================================
@@ LUA_NUMBER is the type of numbers in Lua.
** CHANGE the following definitions only if you want to build Lua
** with a number type different from double. You may also need to
** change lua_number2int & lua_number2integer.
** ===================================================================
*/
#define LUA_NUMBER_DOUBLE
#define LUA_NUMBER double
/*
@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
@* over a number.
*/
#define LUAI_UACNUMBER double
/*
@@ LUA_NUMBER_SCAN is the format for reading numbers.
@@ LUA_NUMBER_FMT is the format for writing numbers.
@@ lua_number2str converts a number to a string.
@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.
@@ lua_str2number converts a string to a number.
*/
#define LUA_NUMBER_SCAN "%lf"
#define LUA_NUMBER_FMT "%.14g"
#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
#define lua_str2number(s,p) strtod((s), (p))
/*
@@ The luai_num* macros define the primitive operations over numbers.
*/
#if defined(LUA_CORE)
#include <math.h>
#define luai_numadd(a,b) ((a)+(b))
#define luai_numsub(a,b) ((a)-(b))
#define luai_nummul(a,b) ((a)*(b))
#define luai_numdiv(a,b) ((a)/(b))
#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b))
#define luai_numpow(a,b) (pow(a,b))
#define luai_numunm(a) (-(a))
#define luai_numeq(a,b) ((a)==(b))
#define luai_numlt(a,b) ((a)<(b))
#define luai_numle(a,b) ((a)<=(b))
#define luai_numisnan(a) (!luai_numeq((a), (a)))
#endif
/*
@@ lua_number2int is a macro to convert lua_Number to int.
@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
** CHANGE them if you know a faster way to convert a lua_Number to
** int (with any rounding method and without throwing errors) in your
** system. In Pentium machines, a naive typecast from double to int
** in C is extremely slow, so any alternative is worth trying.
*/
/* On a Pentium, resort to a trick */
#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
(defined(__i386) || defined (_M_IX86) || defined(__i386__))
/* On a Microsoft compiler, use assembler */
#if defined(_MSC_VER)
#define lua_number2int(i,d) __asm fld d __asm fistp i
#define lua_number2integer(i,n) lua_number2int(i, n)
/* the next trick should work on any Pentium, but sometimes clashes
with a DirectX idiosyncrasy */
#else
union luai_Cast { double l_d; long l_l; };
#define lua_number2int(i,d) \
{ volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
#define lua_number2integer(i,n) lua_number2int(i, n)
#endif
/* this option always works, but may be slow */
#else
#define lua_number2int(i,d) ((i)=(int)(d))
#define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
#endif
/* }================================================================== */
/*
@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment.
** CHANGE it if your system requires alignments larger than double. (For
** instance, if your system supports long doubles and they must be
** aligned in 16-byte boundaries, then you should add long double in the
** union.) Probably you do not need to change this.
*/
#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; }
/*
@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling.
** CHANGE them if you prefer to use longjmp/setjmp even with C++
** or if want/don't to use _longjmp/_setjmp instead of regular
** longjmp/setjmp. By default, Lua handles errors with exceptions when
** compiling as C++ code, with _longjmp/_setjmp when asked to use them,
** and with longjmp/setjmp otherwise.
*/
#if defined(__cplusplus)
/* C++ exceptions */
#define LUAI_THROW(L,c) throw(c)
#define LUAI_TRY(L,c,a) try { a } catch(...) \
{ if ((c)->status == 0) (c)->status = -1; }
#define luai_jmpbuf int /* dummy variable */
#elif defined(LUA_USE_ULONGJMP)
/* in Unix, try _longjmp/_setjmp (more efficient) */
#define LUAI_THROW(L,c) _longjmp((c)->b, 1)
#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a }
#define luai_jmpbuf jmp_buf
#else
/* default handling with long jumps */
#define LUAI_THROW(L,c) longjmp((c)->b, 1)
#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a }
#define luai_jmpbuf jmp_buf
#endif
/*
@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern
@* can do during pattern-matching.
** CHANGE it if you need more captures. This limit is arbitrary.
*/
#define LUA_MAXCAPTURES 32
/*
@@ lua_tmpnam is the function that the OS library uses to create a
@* temporary name.
@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam.
** CHANGE them if you have an alternative to tmpnam (which is considered
** insecure) or if you want the original tmpnam anyway. By default, Lua
** uses tmpnam except when POSIX is available, where it uses mkstemp.
*/
#if defined(loslib_c) || defined(luaall_c)
#if defined(LUA_USE_MKSTEMP)
#include <unistd.h>
#define LUA_TMPNAMBUFSIZE 32
#define lua_tmpnam(b,e) { \
strcpy(b, "/tmp/lua_XXXXXX"); \
e = mkstemp(b); \
if (e != -1) close(e); \
e = (e == -1); }
#else
#define LUA_TMPNAMBUFSIZE L_tmpnam
#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); }
#endif
#endif
/*
@@ lua_popen spawns a new process connected to the current one through
@* the file streams.
** CHANGE it if you have a way to implement it in your system.
*/
#if defined(LUA_USE_POPEN)
#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m))
#define lua_pclose(L,file) ((void)L, (pclose(file) != -1))
#elif defined(LUA_WIN)
#define lua_popen(L,c,m) ((void)L, _popen(c,m))
#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1))
#else
#define lua_popen(L,c,m) ((void)((void)c, m), \
luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0)
#define lua_pclose(L,file) ((void)((void)L, file), 0)
#endif
/*
@@ LUA_DL_* define which dynamic-library system Lua should use.
** CHANGE here if Lua has problems choosing the appropriate
** dynamic-library system for your platform (either Windows' DLL, Mac's
** dyld, or Unix's dlopen). If your system is some kind of Unix, there
** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for
** it. To use dlopen you also need to adapt the src/Makefile (probably
** adding -ldl to the linker options), so Lua does not select it
** automatically. (When you change the makefile to add -ldl, you must
** also add -DLUA_USE_DLOPEN.)
** If you do not want any kind of dynamic library, undefine all these
** options.
** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD.
*/
#if defined(LUA_USE_DLOPEN)
#define LUA_DL_DLOPEN
#endif
#if defined(LUA_WIN)
#define LUA_DL_DLL
#endif
/*
@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State
@* (the data goes just *before* the lua_State pointer).
** CHANGE (define) this if you really need that. This value must be
** a multiple of the maximum alignment required for your machine.
*/
#define LUAI_EXTRASPACE 0
/*
@@ luai_userstate* allow user-specific actions on threads.
** CHANGE them if you defined LUAI_EXTRASPACE and need to do something
** extra when a thread is created/deleted/resumed/yielded.
*/
#define luai_userstateopen(L) ((void)L)
#define luai_userstateclose(L) ((void)L)
#define luai_userstatethread(L,L1) ((void)L)
#define luai_userstatefree(L) ((void)L)
#define luai_userstateresume(L,n) ((void)L)
#define luai_userstateyield(L,n) ((void)L)
/*
@@ LUA_INTFRMLEN is the length modifier for integer conversions
@* in 'string.format'.
@@ LUA_INTFRM_T is the integer type correspoding to the previous length
@* modifier.
** CHANGE them if your system supports long long or does not support long.
*/
#if defined(LUA_USELONGLONG)
#define LUA_INTFRMLEN "ll"
#define LUA_INTFRM_T long long
#else
#define LUA_INTFRMLEN "l"
#define LUA_INTFRM_T long
#endif
/* =================================================================== */
/*
** Local configuration. You can use this space to add your redefinitions
** without modifying the main part of the file.
*/
#endif

View file

@ -1,53 +0,0 @@
/*
** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $
** Lua standard libraries
** See Copyright Notice in lua.h
*/
#ifndef lualib_h
#define lualib_h
#include "lua.h"
/* Key to file-handle type */
#define LUA_FILEHANDLE "FILE*"
#define LUA_COLIBNAME "coroutine"
LUALIB_API int (luaopen_base) (lua_State *L);
#define LUA_TABLIBNAME "table"
LUALIB_API int (luaopen_table) (lua_State *L);
#define LUA_IOLIBNAME "io"
LUALIB_API int (luaopen_io) (lua_State *L);
#define LUA_OSLIBNAME "os"
LUALIB_API int (luaopen_os) (lua_State *L);
#define LUA_STRLIBNAME "string"
LUALIB_API int (luaopen_string) (lua_State *L);
#define LUA_MATHLIBNAME "math"
LUALIB_API int (luaopen_math) (lua_State *L);
#define LUA_DBLIBNAME "debug"
LUALIB_API int (luaopen_debug) (lua_State *L);
#define LUA_LOADLIBNAME "package"
LUALIB_API int (luaopen_package) (lua_State *L);
/* open all previous libraries */
LUALIB_API void (luaL_openlibs) (lua_State *L);
#ifndef lua_assert
#define lua_assert(x) ((void)0)
#endif
#endif

Binary file not shown.

View file

@ -1,163 +0,0 @@
.\" $Id: lua.man,v 1.11 2006/01/06 16:03:34 lhf Exp $
.TH LUA 1 "$Date: 2006/01/06 16:03:34 $"
.SH NAME
lua \- Lua interpreter
.SH SYNOPSIS
.B lua
[
.I options
]
[
.I script
[
.I args
]
]
.SH DESCRIPTION
.B lua
is the stand-alone Lua interpreter.
It loads and executes Lua programs,
either in textual source form or
in precompiled binary form.
(Precompiled binaries are output by
.BR luac ,
the Lua compiler.)
.B lua
can be used as a batch interpreter and also interactively.
.LP
The given
.I options
(see below)
are executed and then
the Lua program in file
.I script
is loaded and executed.
The given
.I args
are available to
.I script
as strings in a global table named
.BR arg .
If these arguments contain spaces or other characters special to the shell,
then they should be quoted
(but note that the quotes will be removed by the shell).
The arguments in
.B arg
start at 0,
which contains the string
.RI ' script '.
The index of the last argument is stored in
.BR arg.n .
The arguments given in the command line before
.IR script ,
including the name of the interpreter,
are available in negative indices in
.BR arg .
.LP
At the very start,
before even handling the command line,
.B lua
executes the contents of the environment variable
.BR LUA_INIT ,
if it is defined.
If the value of
.B LUA_INIT
is of the form
.RI '@ filename ',
then
.I filename
is executed.
Otherwise, the string is assumed to be a Lua statement and is executed.
.LP
Options start with
.B '\-'
and are described below.
You can use
.B "'\--'"
to signal the end of options.
.LP
If no arguments are given,
then
.B "\-v \-i"
is assumed when the standard input is a terminal;
otherwise,
.B "\-"
is assumed.
.LP
In interactive mode,
.B lua
prompts the user,
reads lines from the standard input,
and executes them as they are read.
If a line does not contain a complete statement,
then a secondary prompt is displayed and
lines are read until a complete statement is formed or
a syntax error is found.
So, one way to interrupt the reading of an incomplete statement is
to force a syntax error:
adding a
.B ';'
in the middle of a statement is a sure way of forcing a syntax error
(except inside multiline strings and comments; these must be closed explicitly).
If a line starts with
.BR '=' ,
then
.B lua
displays the values of all the expressions in the remainder of the
line. The expressions must be separated by commas.
The primary prompt is the value of the global variable
.BR _PROMPT ,
if this value is a string;
otherwise, the default prompt is used.
Similarly, the secondary prompt is the value of the global variable
.BR _PROMPT2 .
So,
to change the prompts,
set the corresponding variable to a string of your choice.
You can do that after calling the interpreter
or on the command line
(but in this case you have to be careful with quotes
if the prompt string contains a space; otherwise you may confuse the shell.)
The default prompts are "> " and ">> ".
.SH OPTIONS
.TP
.B \-
load and execute the standard input as a file,
that is,
not interactively,
even when the standard input is a terminal.
.TP
.BI \-e " stat"
execute statement
.IR stat .
You need to quote
.I stat
if it contains spaces, quotes,
or other characters special to the shell.
.TP
.B \-i
enter interactive mode after
.I script
is executed.
.TP
.BI \-l " name"
call
.BI require(' name ')
before executing
.IR script .
Typically used to load libraries.
.TP
.B \-v
show version information.
.SH "SEE ALSO"
.BR luac (1)
.br
http://www.lua.org/
.SH DIAGNOSTICS
Error messages should be self explanatory.
.SH AUTHORS
R. Ierusalimschy,
L. H. de Figueiredo,
and
W. Celes
.\" EOF

View file

@ -1,136 +0,0 @@
.\" $Id: luac.man,v 1.28 2006/01/06 16:03:34 lhf Exp $
.TH LUAC 1 "$Date: 2006/01/06 16:03:34 $"
.SH NAME
luac \- Lua compiler
.SH SYNOPSIS
.B luac
[
.I options
] [
.I filenames
]
.SH DESCRIPTION
.B luac
is the Lua compiler.
It translates programs written in the Lua programming language
into binary files that can be later loaded and executed.
.LP
The main advantages of precompiling chunks are:
faster loading,
protecting source code from accidental user changes,
and
off-line syntax checking.
.LP
Pre-compiling does not imply faster execution
because in Lua chunks are always compiled into bytecodes before being executed.
.B luac
simply allows those bytecodes to be saved in a file for later execution.
.LP
Pre-compiled chunks are not necessarily smaller than the corresponding source.
The main goal in pre-compiling is faster loading.
.LP
The binary files created by
.B luac
are portable only among architectures with the same word size and byte order.
.LP
.B luac
produces a single output file containing the bytecodes
for all source files given.
By default,
the output file is named
.BR luac.out ,
but you can change this with the
.B \-o
option.
.LP
In the command line,
you can mix
text files containing Lua source and
binary files containing precompiled chunks.
This is useful to combine several precompiled chunks,
even from different (but compatible) platforms,
into a single precompiled chunk.
.LP
You can use
.B "'\-'"
to indicate the standard input as a source file
and
.B "'\--'"
to signal the end of options
(that is,
all remaining arguments will be treated as files even if they start with
.BR "'\-'" ).
.LP
The internal format of the binary files produced by
.B luac
is likely to change when a new version of Lua is released.
So,
save the source files of all Lua programs that you precompile.
.LP
.SH OPTIONS
Options must be separate.
.TP
.B \-l
produce a listing of the compiled bytecode for Lua's virtual machine.
Listing bytecodes is useful to learn about Lua's virtual machine.
If no files are given, then
.B luac
loads
.B luac.out
and lists its contents.
.TP
.BI \-o " file"
output to
.IR file ,
instead of the default
.BR luac.out .
(You can use
.B "'\-'"
for standard output,
but not on platforms that open standard output in text mode.)
The output file may be a source file because
all files are loaded before the output file is written.
Be careful not to overwrite precious files.
.TP
.B \-p
load files but do not generate any output file.
Used mainly for syntax checking and for testing precompiled chunks:
corrupted files will probably generate errors when loaded.
Lua always performs a thorough integrity test on precompiled chunks.
Bytecode that passes this test is completely safe,
in the sense that it will not break the interpreter.
However,
there is no guarantee that such code does anything sensible.
(None can be given, because the halting problem is unsolvable.)
If no files are given, then
.B luac
loads
.B luac.out
and tests its contents.
No messages are displayed if the file passes the integrity test.
.TP
.B \-s
strip debug information before writing the output file.
This saves some space in very large chunks,
but if errors occur when running a stripped chunk,
then the error messages may not contain the full information they usually do.
For instance,
line numbers and names of local variables are lost.
.TP
.B \-v
show version information.
.SH FILES
.TP 15
.B luac.out
default output file
.SH "SEE ALSO"
.BR lua (1)
.br
http://www.lua.org/
.SH DIAGNOSTICS
Error messages should be self explanatory.
.SH AUTHORS
L. H. de Figueiredo,
R. Ierusalimschy and
W. Celes
.\" EOF

View file

@ -1,38 +0,0 @@
#!/home/runner/work/nvim-treesitter-context/nvim-treesitter-context/.lua/bin/lua
package.loaded["luarocks.core.hardcoded"] = { SYSCONFDIR = [[/home/runner/work/nvim-treesitter-context/nvim-treesitter-context/.luarocks/etc/luarocks]] }
package.path=[[/home/runner/work/nvim-treesitter-context/nvim-treesitter-context/.luarocks/share/lua/5.1/?.lua;]] .. package.path
local list = package.searchers or package.loaders; table.insert(list, 1, function(name) if name:match("^luarocks%.") then return loadfile([[/home/runner/work/nvim-treesitter-context/nvim-treesitter-context/.luarocks/share/lua/5.1/]] .. name:gsub([[%.]], [[/]]) .. [[.lua]]) end end)
-- Load cfg first so that the loader knows it is running inside LuaRocks
local cfg = require("luarocks.core.cfg")
local loader = require("luarocks.loader")
local cmd = require("luarocks.cmd")
local description = "LuaRocks main command-line interface"
local commands = {
init = "luarocks.cmd.init",
pack = "luarocks.cmd.pack",
unpack = "luarocks.cmd.unpack",
build = "luarocks.cmd.build",
install = "luarocks.cmd.install",
search = "luarocks.cmd.search",
list = "luarocks.cmd.list",
remove = "luarocks.cmd.remove",
make = "luarocks.cmd.make",
download = "luarocks.cmd.download",
path = "luarocks.cmd.path",
show = "luarocks.cmd.show",
new_version = "luarocks.cmd.new_version",
lint = "luarocks.cmd.lint",
write_rockspec = "luarocks.cmd.write_rockspec",
purge = "luarocks.cmd.purge",
doc = "luarocks.cmd.doc",
upload = "luarocks.cmd.upload",
config = "luarocks.cmd.config",
which = "luarocks.cmd.which",
test = "luarocks.cmd.test",
}
cmd.run_command(description, commands, "luarocks.cmd.external", ...)

View file

@ -1,21 +0,0 @@
#!/home/runner/work/nvim-treesitter-context/nvim-treesitter-context/.lua/bin/lua
package.loaded["luarocks.core.hardcoded"] = { SYSCONFDIR = [[/home/runner/work/nvim-treesitter-context/nvim-treesitter-context/.luarocks/etc/luarocks]] }
package.path=[[/home/runner/work/nvim-treesitter-context/nvim-treesitter-context/.luarocks/share/lua/5.1/?.lua;]] .. package.path
local list = package.searchers or package.loaders; table.insert(list, 1, function(name) if name:match("^luarocks%.") then return loadfile([[/home/runner/work/nvim-treesitter-context/nvim-treesitter-context/.luarocks/share/lua/5.1/]] .. name:gsub([[%.]], [[/]]) .. [[.lua]]) end end)
-- Load cfg first so that luarocks.loader knows it is running inside LuaRocks
local cfg = require("luarocks.core.cfg")
local loader = require("luarocks.loader")
local cmd = require("luarocks.cmd")
local description = "LuaRocks repository administration interface"
local commands = {
make_manifest = "luarocks.admin.cmd.make_manifest",
add = "luarocks.admin.cmd.add",
remove = "luarocks.admin.cmd.remove",
refresh_cache = "luarocks.admin.cmd.refresh_cache",
}
cmd.run_command(description, commands, "luarocks.admin.cmd.external", ...)

View file

@ -1,11 +0,0 @@
-- LuaRocks configuration
rocks_trees = {
{ name = "user", root = home .. "/.luarocks" };
{ name = "system", root = "/home/runner/work/nvim-treesitter-context/nvim-treesitter-context/.luarocks" };
}
lua_interpreter = "lua";
variables = {
LUA_DIR = "/home/runner/work/nvim-treesitter-context/nvim-treesitter-context/.lua";
LUA_BINDIR = "/home/runner/work/nvim-treesitter-context/nvim-treesitter-context/.lua/bin";
}

View file

@ -1,88 +0,0 @@
--- Module handling the LuaRocks local cache.
-- Adds a rock or rockspec to a rocks server.
local cache = {}
local fs = require("luarocks.fs")
local cfg = require("luarocks.core.cfg")
local dir = require("luarocks.dir")
local util = require("luarocks.util")
function cache.get_upload_server(server)
if not server then server = cfg.upload_server end
if not server then
return nil, "No server specified and no default configured with upload_server."
end
return server, cfg.upload_servers and cfg.upload_servers[server]
end
function cache.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 cache.split_server_url(url, user, password)
local protocol, server_path = dir.split_url(url)
if protocol == "file" then
server_path = fs.absolute_name(server_path)
elseif 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 = cfg.local_cache .. "/" .. server_path:gsub("[\\/]", "_")
return local_cache, protocol, server_path, user, password
end
local function download_cache(protocol, server_path, user, password)
os.remove("index.html")
-- TODO abstract away explicit 'wget' call
if protocol == "rsync" then
local srv, path = server_path:match("([^/]+)(/.+)")
return fs.execute(cfg.variables.RSYNC.." "..cfg.variables.RSYNCFLAGS.." -e ssh "..user.."@"..srv..":"..path.."/ ./")
elseif protocol == "file" then
return fs.copy_contents(server_path, ".")
else
local login_info = ""
if user then login_info = " --user="..user end
if password then login_info = login_info .. " --password="..password end
return fs.execute(cfg.variables.WGET.." --no-cache -q -m -np -nd "..protocol.."://"..server_path..login_info)
end
end
function cache.refresh_local_cache(url, given_user, given_password)
local local_cache, protocol, server_path, user, password = cache.split_server_url(url, given_user, given_password)
local ok, err = fs.make_dir(local_cache)
if not ok then
return nil, "Failed creating local cache dir: "..err
end
fs.change_dir(local_cache)
util.printout("Refreshing cache "..local_cache.."...")
ok = download_cache(protocol, server_path, user, password)
if not ok then
return nil, "Failed downloading cache."
end
return local_cache, protocol, server_path, user, password
end
return cache

View file

@ -1,134 +0,0 @@
--- Module implementing the luarocks-admin "add" command.
-- Adds a rock or rockspec to a rocks server.
local add = {}
local cfg = require("luarocks.core.cfg")
local util = require("luarocks.util")
local dir = require("luarocks.dir")
local writer = require("luarocks.manif.writer")
local fs = require("luarocks.fs")
local cache = require("luarocks.admin.cache")
local index = require("luarocks.admin.index")
function add.add_to_parser(parser)
local cmd = parser:command("add", "Add a rock or rockspec to a rocks server.", util.see_also())
cmd:argument("rock", "A local rockspec or rock file.")
:args("+")
cmd:option("--server", "The server to use. If not given, the default server "..
"set in the upload_server variable from the configuration file is used instead.")
:target("add_server")
cmd:flag("--no-refresh", "Do not refresh the local cache prior to "..
"generation of the updated manifest.")
cmd:flag("--index", "Produce an index.html file for the manifest. This "..
"flag is automatically set if an index.html file already exists.")
end
local function zip_manifests()
for ver in util.lua_versions() do
local file = "manifest-"..ver
local zip = file..".zip"
fs.delete(dir.path(fs.current_dir(), zip))
fs.zip(zip, file)
end
end
local function add_files_to_server(refresh, rockfiles, server, upload_server, do_index)
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(download_url, cfg.upload_user, cfg.upload_password)
if not local_cache then
return nil, protocol
end
if not login_url then
login_url = protocol.."://"..server_path
end
local ok, err = fs.change_dir(at)
if not ok then return nil, err end
local files = {}
for _, 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, "read")
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
local ok, err = fs.change_dir(local_cache)
if not ok then return nil, err end
util.printout("Updating manifest...")
writer.make_manifest(local_cache, "one", true)
zip_manifests()
if fs.exists("index.html") then
do_index = true
end
if do_index then
util.printout("Updating index.html...")
index.make_index(local_cache)
end
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
if do_index then
table.insert(files, "index.html")
end
table.insert(files, "manifest")
for ver in util.lua_versions() do
table.insert(files, "manifest-"..ver)
table.insert(files, "manifest-"..ver..".zip")
end
-- TODO abstract away explicit 'curl' call
local cmd
if protocol == "rsync" then
local srv, path = server_path:match("([^/]+)(/.+)")
cmd = cfg.variables.RSYNC.." "..cfg.variables.RSYNCFLAGS.." -e ssh "..local_cache.."/ "..user.."@"..srv..":"..path.."/"
elseif protocol == "file" then
return fs.copy_contents(local_cache, server_path)
elseif upload_server and upload_server.sftp then
local part1, part2 = upload_server.sftp:match("^([^/]*)/(.*)$")
cmd = cfg.variables.SCP.." "..table.concat(files, " ").." "..user.."@"..part1..":/"..part2
else
cmd = cfg.variables.CURL.." "..login_info.." -T '{"..table.concat(files, ",").."}' "..login_url
end
util.printout(cmd)
return fs.execute(cmd)
end
function add.command(args)
local server, server_table = cache.get_upload_server(args.add_server or args.server)
if not server then return nil, server_table end
return add_files_to_server(not args.no_refresh, args.rock, server, server_table, args.index)
end
return add

View file

@ -1,50 +0,0 @@
--- Module implementing the luarocks-admin "make_manifest" command.
-- Compile a manifest file for a repository.
local make_manifest = {}
local writer = require("luarocks.manif.writer")
local index = require("luarocks.admin.index")
local cfg = require("luarocks.core.cfg")
local util = require("luarocks.util")
local deps = require("luarocks.deps")
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
function make_manifest.add_to_parser(parser)
local cmd = parser:command("make_manifest", "Compile a manifest file for a repository.", util.see_also())
cmd:argument("repository", "Local repository pathname.")
:args("?")
cmd:flag("--local-tree", "If given, do not write versioned versions of the manifest file.\n"..
"Use this when rebuilding the manifest of a local rocks tree.")
util.deps_mode_option(cmd)
end
--- Driver function for "make_manifest" command.
-- @return boolean or (nil, string): True if manifest was generated,
-- or nil and an error message.
function make_manifest.command(args)
local repo = args.repository or cfg.rocks_dir
util.printout("Making manifest for "..repo)
if repo:match("/lib/luarocks") and not args.local_tree then
util.warning("This looks like a local rocks tree, but you did not pass --local-tree.")
end
local ok, err = writer.make_manifest(repo, deps.get_deps_mode(args), not args.local_tree)
if ok and not args.local_tree then
util.printout("Generating index.html for "..repo)
index.make_index(repo)
end
if args.local_tree then
for luaver in util.lua_versions() do
fs.delete(dir.path(repo, "manifest-"..luaver))
end
end
return ok, err
end
return make_manifest

View file

@ -1,31 +0,0 @@
--- Module implementing the luarocks-admin "refresh_cache" command.
local refresh_cache = {}
local cfg = require("luarocks.core.cfg")
local util = require("luarocks.util")
local cache = require("luarocks.admin.cache")
function refresh_cache.add_to_parser(parser)
local cmd = parser:command("refresh_cache", "Refresh local cache of a remote rocks server.", util.see_also())
cmd:option("--from", "The server to use. If not given, the default server "..
"set in the upload_server variable from the configuration file is used instead.")
:argname("<server>")
end
function refresh_cache.command(args)
local server, upload_server = cache.get_upload_server(args.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(download_url, cfg.upload_user, cfg.upload_password)
if not ok then
return nil, err
else
return true
end
end
return refresh_cache

View file

@ -1,87 +0,0 @@
--- Module implementing the luarocks-admin "remove" command.
-- Removes a rock or rockspec from a rocks server.
local admin_remove = {}
local cfg = require("luarocks.core.cfg")
local util = require("luarocks.util")
local dir = require("luarocks.dir")
local writer = require("luarocks.manif.writer")
local fs = require("luarocks.fs")
local cache = require("luarocks.admin.cache")
local index = require("luarocks.admin.index")
function admin_remove.add_to_parser(parser)
local cmd = parser:command("remove", "Remove a rock or rockspec from a rocks server.", util.see_also())
cmd:argument("rock", "A local rockspec or rock file.")
:args("+")
cmd:option("--server", "The server to use. If not given, the default server "..
"set in the upload_server variable from the configuration file is used instead.")
cmd:flag("--no-refresh", "Do not refresh the local cache prior to "..
"generation of the updated manifest.")
end
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(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
local ok, err = fs.change_dir(at)
if not ok then return nil, err end
local nr_files = 0
for _, rockfile in ipairs(rockfiles) do
local basename = dir.base_name(rockfile)
local file = dir.path(local_cache, basename)
util.printout("Removing file "..file.."...")
fs.delete(file)
if not fs.exists(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
local ok, err = fs.change_dir(local_cache)
if not ok then return nil, err end
util.printout("Updating manifest...")
writer.make_manifest(local_cache, "one", true)
util.printout("Updating index.html...")
index.make_index(local_cache)
local srv, path = server_path:match("([^/]+)(/.+)")
local cmd = cfg.variables.RSYNC.." "..cfg.variables.RSYNCFLAGS.." --delete -e ssh "..local_cache.."/ "..user.."@"..srv..":"..path.."/"
util.printout(cmd)
fs.execute(cmd)
return true
end
function admin_remove.command(args)
local server, server_table = cache.get_upload_server(args.server)
if not server then return nil, server_table end
return remove_files_from_server(not args.no_refresh, args.rock, server, server_table)
end
return admin_remove

View file

@ -1,185 +0,0 @@
--- Module which builds the index.html page to be used in rocks servers.
local index = {}
local util = require("luarocks.util")
local fs = require("luarocks.fs")
local vers = require("luarocks.core.vers")
local persist = require("luarocks.persist")
local dir = require("luarocks.dir")
local manif = require("luarocks.manif")
local ext_url_target = ' target="_blank"'
local index_header = [[
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Available rocks</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<style>
body {
background-color: white;
font-family: "bitstream vera sans", "verdana", "sans";
font-size: 14px;
}
a {
color: #0000c0;
text-decoration: none;
}
a.pkg {
color: black;
}
a:hover {
text-decoration: underline;
}
td.main {
border-style: none;
}
blockquote {
font-size: 12px;
}
td.package {
background-color: #f0f0f0;
vertical-align: top;
}
td.spacer {
height: 5px;
}
td.version {
background-color: #d0d0d0;
vertical-align: top;
text-align: left;
padding: 5px;
width: 100px;
}
p.manifest {
font-size: 8px;
}
</style>
</head>
<body>
<h1>Available rocks</h1>
<p>
Lua modules available from this location for use with <a href="http://www.luarocks.org">LuaRocks</a>:
</p>
<table class="main">
]]
local index_package_begin = [[
<td class="package">
<p><a name="$anchor"></a><a href="#$anchor" class="pkg"><b>$package</b></a> - $summary<br/>
</p><blockquote><p>$detailed<br/>
$externaldependencies
<font size="-1"><a href="$original">latest sources</a> $homepage | License: $license</font></p>
</blockquote></a></td>
<td class="version">
]]
local index_package_end = [[
</td></tr>
<tr><td colspan="2" class="spacer"></td></tr>
]]
local index_footer_begin = [[
</table>
<p class="manifest">
<a href="manifest">manifest file</a>
]]
local index_manifest_ver = [[
&bull; <a href="manifest-$VER">Lua $VER manifest file</a> (<a href="manifest-$VER.zip">zip</a>)
]]
local index_footer_end = [[
</p>
</body>
</html>
]]
function index.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 '<p><b>External dependencies:</b> ' .. table.concat(deplist, ',&nbsp;').. '</p>'
else
return ""
end
end
function index.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_begin
for version, data in util.sortedpairs(version_list, vers.compare_versions) do
local versions = {}
output = output..version..':&nbsp;'
table.sort(data, function(a,b) return a.arch < b.arch end)
for _, item in ipairs(data) do
local file
if item.arch == 'rockspec' then
file = ("%s-%s.rockspec"):format(package, version)
if not latest_rockspec then latest_rockspec = file end
else
file = ("%s-%s.%s.rock"):format(package, version, item.arch)
end
table.insert(versions, '<a href="'..file..'">'..item.arch..'</a>')
end
output = output .. table.concat(versions, ',&nbsp;') .. '<br/>'
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 ('| <a href="'..descript.homepage..'"'..ext_url_target..'>project homepage</a>') or "",
externaldependencies = index.format_external_dependencies(rockspec)
}
vars.detailed = vars.detailed:gsub("\n\n", "</p><p>"):gsub("%s+", " ")
vars.detailed = vars.detailed:gsub("(https?://[a-zA-Z0-9%.%%-_%+%[%]=%?&/$@;:]+)", '<a href="%1"'..ext_url_target..'>%1</a>')
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_begin)
for ver in util.lua_versions() do
out:write((index_manifest_ver:gsub("$VER", ver)))
end
out:write(index_footer_end)
out:close()
end
return index

File diff suppressed because it is too large Load diff

View file

@ -1,458 +0,0 @@
local build = {}
local path = require("luarocks.path")
local util = require("luarocks.util")
local fun = require("luarocks.fun")
local fetch = require("luarocks.fetch")
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local deps = require("luarocks.deps")
local cfg = require("luarocks.core.cfg")
local vers = require("luarocks.core.vers")
local repos = require("luarocks.repos")
local writer = require("luarocks.manif.writer")
local deplocks = require("luarocks.deplocks")
build.opts = util.opts_table("build.opts", {
need_to_fetch = "boolean",
minimal_mode = "boolean",
deps_mode = "string",
build_only_deps = "boolean",
namespace = "string?",
branch = "string?",
verify = "boolean",
check_lua_versions = "boolean",
pin = "boolean",
no_install = "boolean"
})
do
--- 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 build.apply_patches(rockspec)
assert(rockspec:type() == "rockspec")
if not (rockspec.build.extra_files or rockspec.build.patches) then
return true
end
local fd = io.open(fs.absolute_name(".luarocks.patches.applied"), "r")
if fd then
fd:close()
return true
end
if rockspec.build.extra_files then
extract_from_rockspec(rockspec.build.extra_files)
end
if rockspec.build.patches then
extract_from_rockspec(rockspec.build.patches)
for patch, patchdata in util.sortedpairs(rockspec.build.patches) do
util.printout("Applying patch "..patch.."...")
local create_delete = rockspec:format_is_at_least("3.0")
local ok, err = fs.apply_patch(tostring(patch), patchdata, create_delete)
if not ok then
return nil, "Failed applying patch "..patch
end
end
end
fd = io.open(fs.absolute_name(".luarocks.patches.applied"), "w")
if fd then
fd:close()
end
return true
end
end
local function check_macosx_deployment_target(rockspec)
local target = rockspec.build.macosx_deployment_target
local function patch_variable(var)
if rockspec.variables[var]:match("MACOSX_DEPLOYMENT_TARGET") then
rockspec.variables[var] = (rockspec.variables[var]):gsub("MACOSX_DEPLOYMENT_TARGET=[^ ]*", "MACOSX_DEPLOYMENT_TARGET="..target)
else
rockspec.variables[var] = "env MACOSX_DEPLOYMENT_TARGET="..target.." "..rockspec.variables[var]
end
end
if cfg.is_platform("macosx") and rockspec:format_is_at_least("3.0") and target then
local version = util.popen_read("sw_vers -productVersion")
if version:match("^%d+%.%d+%.%d+$") or version:match("^%d+%.%d+$") then
if vers.compare_versions(target, version) then
return nil, ("This rock requires Mac OSX %s, and you are running %s."):format(target, version)
end
end
patch_variable("CC")
patch_variable("LD")
end
return true
end
local function process_dependencies(rockspec, opts)
if not opts.build_only_deps then
local ok, err, errcode = deps.check_external_deps(rockspec, "build")
if err then
return nil, err, errcode
end
end
local ok, err, errcode = deps.check_lua_incdir(rockspec.variables)
if not ok then
return nil, err, errcode
end
if cfg.link_lua_explicitly then
local ok, err, errcode = deps.check_lua_libdir(rockspec.variables)
if not ok then
return nil, err, errcode
end
end
if opts.deps_mode == "none" then
return true
end
if not opts.build_only_deps then
if next(rockspec.build_dependencies) then
local ok, err, errcode = deps.fulfill_dependencies(rockspec, "build_dependencies", opts.deps_mode, opts.verify)
if err then
return nil, err, errcode
end
end
end
ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", opts.deps_mode, opts.verify)
if err then
return nil, err, errcode
end
return true
end
local function fetch_and_change_to_source_dir(rockspec, opts)
if opts.minimal_mode or opts.build_only_deps then
return true
end
if opts.need_to_fetch then
if opts.branch then
rockspec.source.branch = opts.branch
end
local ok, source_dir, errcode = fetch.fetch_sources(rockspec, true)
if not ok then
return nil, source_dir, errcode
end
local err
ok, err = fs.change_dir(source_dir)
if not ok then
return nil, err
end
elseif rockspec.source.file then
local ok, err = fs.unpack_archive(rockspec.source.file)
if not ok then
return nil, err
end
end
fs.change_dir(rockspec.source.dir)
return true
end
local function prepare_install_dirs(name, version)
local dirs = {
lua = { name = path.lua_dir(name, version), is_module_path = true, perms = "read" },
lib = { name = path.lib_dir(name, version), is_module_path = true, perms = "exec" },
bin = { name = path.bin_dir(name, version), is_module_path = false, perms = "exec" },
conf = { name = path.conf_dir(name, version), is_module_path = false, perms = "read" },
}
for _, d in pairs(dirs) do
local ok, err = fs.make_dir(d.name)
if not ok then
return nil, err
end
end
return dirs
end
local function run_build_driver(rockspec, no_install)
local btype = rockspec.build.type
if btype == "none" then
return true
end
-- Temporary compatibility
if btype == "module" then
util.printout("Do not use 'module' as a build type. Use 'builtin' instead.")
btype = "builtin"
rockspec.build.type = btype
end
if cfg.accepted_build_types and not fun.contains(cfg.accepted_build_types, btype) then
return nil, "This rockspec uses the '"..btype.."' build type, which is blocked by the 'accepted_build_types' setting in your LuaRocks configuration."
end
local pok, driver = pcall(require, "luarocks.build." .. btype)
if not pok or type(driver) ~= "table" then
return nil, "Failed initializing build back-end for build type '"..btype.."': "..driver
end
local ok, err = driver.run(rockspec, no_install)
if not ok then
return nil, "Build error: " .. err
end
return true
end
local install_files
do
--- 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.
-- @param perms string ("read" or "exec"): Permissions of the newly created
-- files installed.
-- Directories are always created with the default permissions.
-- @return boolean or (nil, string): True if succeeded or
-- nil and an error message.
local function install_to(files, location, is_module_path, perms)
assert(type(files) == "table" or not files)
assert(type(location) == "string")
if not files then
return true
end
for k, file in pairs(files) do
local dest = location
local filename = dir.base_name(file)
if type(k) == "string" then
local modname = k
if is_module_path then
dest = dir.path(location, path.module_to_path(modname))
local ok, err = fs.make_dir(dest)
if not ok then return nil, err end
if filename:match("%.lua$") then
local basename = modname:match("([^.]+)$")
filename = basename..".lua"
end
else
dest = dir.path(location, dir.dir_name(modname))
local ok, err = fs.make_dir(dest)
if not ok then return nil, err end
filename = dir.base_name(modname)
end
else
local ok, err = fs.make_dir(dest)
if not ok then return nil, err end
end
local ok = fs.copy(dir.path(file), dir.path(dest, filename), perms)
if not ok then
return nil, "Failed copying "..file
end
end
return true
end
local function install_default_docs(name, version)
local patterns = { "readme", "license", "copying", ".*%.md" }
local dest = dir.path(path.install_dir(name, version), "doc")
local has_dir = false
for file in fs.dir() do
for _, pattern in ipairs(patterns) do
if file:lower():match("^"..pattern) then
if not has_dir then
fs.make_dir(dest)
has_dir = true
end
fs.copy(file, dest, "read")
break
end
end
end
end
install_files = function(rockspec, dirs)
local name, version = rockspec.name, rockspec.version
if rockspec.build.install then
for k, d in pairs(dirs) do
local ok, err = install_to(rockspec.build.install[k], d.name, d.is_module_path, d.perms)
if not ok then return nil, err end
end
end
local copy_directories = rockspec.build.copy_directories
local copying_default = false
if not copy_directories then
copy_directories = {"doc"}
copying_default = true
end
local any_docs = false
for _, copy_dir in pairs(copy_directories) do
if fs.is_dir(copy_dir) then
local dest = dir.path(path.install_dir(name, version), copy_dir)
fs.make_dir(dest)
fs.copy_contents(copy_dir, dest)
any_docs = true
else
if not copying_default then
return nil, "Directory '"..copy_dir.."' not found"
end
end
end
if not any_docs then
install_default_docs(name, version)
end
return true
end
end
local function write_rock_dir_files(rockspec, opts)
local name, version = rockspec.name, rockspec.version
fs.copy(rockspec.local_abs_filename, path.rockspec_file(name, version), "read")
local deplock_file = deplocks.get_abs_filename(rockspec.name)
if deplock_file then
fs.copy(deplock_file, dir.path(path.install_dir(name, version), "luarocks.lock"), "read")
end
local ok, err = writer.make_rock_manifest(name, version)
if not ok then return nil, err end
ok, err = writer.make_namespace_file(name, version, opts.namespace)
if not ok then return nil, err end
return true
end
--- Build and install a rock given a rockspec.
-- @param opts table: build options table
-- @return (string, string) or (nil, string, [string]): Name and version of
-- installed rock if succeeded or nil and an error message followed by an error code.
function build.build_rockspec(rockspec, opts)
assert(rockspec:type() == "rockspec")
assert(opts:type() == "build.opts")
if not rockspec.build then
if rockspec:format_is_at_least("3.0") then
rockspec.build = {
type = "builtin"
}
else
return nil, "Rockspec error: build table not specified"
end
end
if not rockspec.build.type then
if rockspec:format_is_at_least("3.0") then
rockspec.build.type = "builtin"
else
return nil, "Rockspec error: build type not specified"
end
end
local ok, err = fetch_and_change_to_source_dir(rockspec, opts)
if not ok then return nil, err end
if opts.pin then
deplocks.init(rockspec.name, ".")
end
ok, err = process_dependencies(rockspec, opts)
if not ok then return nil, err end
local name, version = rockspec.name, rockspec.version
if opts.build_only_deps then
if opts.pin then
deplocks.write_file()
end
return name, version
end
local dirs, err
local rollback
if not opts.no_install then
if repos.is_installed(name, version) then
repos.delete_version(name, version, opts.deps_mode)
end
dirs, err = prepare_install_dirs(name, version)
if not dirs then return nil, err end
rollback = util.schedule_function(function()
fs.delete(path.install_dir(name, version))
fs.remove_dir_if_empty(path.versions_dir(name))
end)
end
ok, err = build.apply_patches(rockspec)
if not ok then return nil, err end
ok, err = check_macosx_deployment_target(rockspec)
if not ok then return nil, err end
ok, err = run_build_driver(rockspec, opts.no_install)
if not ok then return nil, err end
if opts.no_install then
fs.pop_dir()
if opts.need_to_fetch then
fs.pop_dir()
end
return name, version
end
ok, err = install_files(rockspec, dirs)
if not ok then return nil, err end
for _, d in pairs(dirs) do
fs.remove_dir_if_empty(d.name)
end
fs.pop_dir()
if opts.need_to_fetch then
fs.pop_dir()
end
if opts.pin then
deplocks.write_file()
end
ok, err = write_rock_dir_files(rockspec, opts)
if not ok then return nil, err end
ok, err = repos.deploy_files(name, version, repos.should_wrap_bin_scripts(rockspec), opts.deps_mode)
if not ok then return nil, err end
util.remove_scheduled_function(rollback)
rollback = util.schedule_function(function()
repos.delete_version(name, version, opts.deps_mode)
end)
ok, err = repos.run_hook(rockspec, "post_install")
if not ok then return nil, err end
util.announce_install(rockspec)
util.remove_scheduled_function(rollback)
return name, version
end
return build

View file

@ -1,367 +0,0 @@
--- A builtin build system: back-end to provide a portable way of building C-based Lua modules.
local builtin = {}
local unpack = unpack or table.unpack
local fs = require("luarocks.fs")
local path = require("luarocks.path")
local util = require("luarocks.util")
local cfg = require("luarocks.core.cfg")
local dir = require("luarocks.dir")
function builtin.autodetect_external_dependencies(build)
if not build or not build.modules then
return nil
end
local extdeps = {}
local any = false
for _, data in pairs(build.modules) do
if type(data) == "table" and data.libraries then
local libraries = data.libraries
if type(libraries) == "string" then
libraries = { libraries }
end
local incdirs = {}
local libdirs = {}
for _, lib in ipairs(libraries) do
local upper = lib:upper():gsub("%+", "P"):gsub("[^%w]", "_")
any = true
extdeps[upper] = { library = lib }
table.insert(incdirs, "$(" .. upper .. "_INCDIR)")
table.insert(libdirs, "$(" .. upper .. "_LIBDIR)")
end
if not data.incdirs then
data.incdirs = incdirs
end
if not data.libdirs then
data.libdirs = libdirs
end
end
end
return any and extdeps or nil
end
local function autoextract_libs(external_dependencies, variables)
if not external_dependencies then
return nil, nil, nil
end
local libs = {}
local incdirs = {}
local libdirs = {}
for name, data in pairs(external_dependencies) do
if data.library then
table.insert(libs, data.library)
table.insert(incdirs, variables[name .. "_INCDIR"])
table.insert(libdirs, variables[name .. "_LIBDIR"])
end
end
return libs, incdirs, libdirs
end
do
local function get_cmod_name(file)
local fd = io.open(dir.path(fs.current_dir(), file), "r")
if not fd then return nil end
local data = fd:read("*a")
fd:close()
return (data:match("int%s+luaopen_([a-zA-Z0-9_]+)"))
end
local skiplist = {
["spec"] = true,
[".luarocks"] = true,
["lua_modules"] = true,
["test.lua"] = true,
["tests.lua"] = true,
}
function builtin.autodetect_modules(libs, incdirs, libdirs)
local modules = {}
local install
local copy_directories
local prefix = ""
for _, parent in ipairs({"src", "lua", "lib"}) do
if fs.is_dir(parent) then
fs.change_dir(parent)
prefix = parent.."/"
break
end
end
for _, file in ipairs(fs.find()) do
local base = file:match("^([^\\/]*)")
if not skiplist[base] then
local luamod = file:match("(.*)%.lua$")
if luamod then
modules[path.path_to_module(file)] = prefix..file
else
local cmod = file:match("(.*)%.c$")
if cmod then
local modname = get_cmod_name(file) or path.path_to_module(file:gsub("%.c$", ".lua"))
modules[modname] = {
sources = prefix..file,
libraries = libs,
incdirs = incdirs,
libdirs = libdirs,
}
end
end
end
end
if prefix ~= "" then
fs.pop_dir()
end
local bindir = (fs.is_dir("src/bin") and "src/bin")
or (fs.is_dir("bin") and "bin")
if bindir then
install = { bin = {} }
for _, file in ipairs(fs.list_dir(bindir)) do
table.insert(install.bin, dir.path(bindir, file))
end
end
for _, directory in ipairs({ "doc", "docs", "samples", "tests" }) do
if fs.is_dir(directory) then
if not copy_directories then
copy_directories = {}
end
table.insert(copy_directories, directory)
end
end
return modules, install, copy_directories
end
end
--- 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
--- Driver function for the builtin build back-end.
-- @param rockspec table: the loaded rockspec.
-- @return boolean or (nil, string): true if no errors occurred,
-- nil and an error message otherwise.
function builtin.run(rockspec, no_install)
assert(rockspec:type() == "rockspec")
local compile_object, compile_library, compile_static_library
local build = rockspec.build
local variables = rockspec.variables
local checked_lua_h = false
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)
local extras = { unpack(objects) }
add_flags(extras, "-L%s", libdirs)
add_flags(extras, "-l%s", libraries)
extras[#extras+1] = dir.path(variables.LUA_LIBDIR, variables.LUALIB)
extras[#extras+1] = "-l" .. (variables.MSVCRT or "m")
local ok = execute(variables.LD.." "..variables.LIBFLAG, "-o", library, unpack(extras))
return ok
end
--[[ TODO disable static libs until we fix the conflict in the manifest, which will take extending the manifest format.
compile_static_library = function(library, objects, libraries, libdirs, name)
local ok = execute(variables.AR, "rc", library, unpack(objects))
if ok then
ok = execute(variables.RANLIB, library)
end
return ok
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+")
local exported_name = name:gsub("%.", "_")
exported_name = exported_name:match('^[^%-]+%-(.+)$') or exported_name
def:write("EXPORTS\n")
def:write("luaopen_"..exported_name.."\n")
def:close()
local ok = execute(variables.LD, "-dll", "-def:"..deffile, "-out:"..library, dir.path(variables.LUA_LIBDIR, variables.LUALIB), unpack(extras))
local basedir = ""
if name:find("%.") ~= nil then
basedir = name:gsub("%.%w+$", "\\")
basedir = basedir:gsub("%.", "\\")
end
local manifestfile = basedir .. basename..".dll.manifest"
if ok and fs.exists(manifestfile) then
ok = execute(variables.MT, "-manifest", manifestfile, "-outputresource:"..basedir..basename..".dll;2")
end
return ok
end
--[[ TODO disable static libs until we fix the conflict in the manifest, which will take extending the manifest format.
compile_static_library = function(library, objects, libraries, libdirs, name)
local ok = execute(variables.AR, "-out:"..library, unpack(objects))
return ok
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)
if cfg.gcc_rpath then
add_flags(extras, "-Wl,-rpath,%s", libdirs)
end
add_flags(extras, "-l%s", libraries)
if cfg.link_lua_explicitly then
extras[#extras+1] = "-L"..variables.LUA_LIBDIR
extras[#extras+1] = "-llua"
end
return execute(variables.LD.." "..variables.LIBFLAG, "-o", library, unpack(extras))
end
compile_static_library = function(library, objects, libraries, libdirs, name) -- luacheck: ignore 211
local ok = execute(variables.AR, "rc", library, unpack(objects))
if ok then
ok = execute(variables.RANLIB, library)
end
return ok
end
end
local ok, err
local lua_modules = {}
local lib_modules = {}
local luadir = path.lua_dir(rockspec.name, rockspec.version)
local libdir = path.lib_dir(rockspec.name, rockspec.version)
if not build.modules then
if rockspec:format_is_at_least("3.0") then
local libs, incdirs, libdirs = autoextract_libs(rockspec.external_dependencies, rockspec.variables)
local install, copy_directories
build.modules, install, copy_directories = builtin.autodetect_modules(libs, incdirs, libdirs)
build.install = build.install or install
build.copy_directories = build.copy_directories or copy_directories
else
return nil, "Missing build.modules table"
end
end
for name, info in pairs(build.modules) do
local moddir = path.module_to_path(name)
if type(info) == "string" then
local ext = info:match("%.([^.]+)$")
if ext == "lua" then
local filename = dir.base_name(info)
if filename == "init.lua" and not name:match("%.init$") then
moddir = path.module_to_path(name..".init")
else
local basename = name:match("([^.]+)$")
filename = basename..".lua"
end
local dest = dir.path(luadir, moddir, filename)
lua_modules[info] = dest
else
info = {info}
end
end
if type(info) == "table" then
if not checked_lua_h then
local lua_incdir, lua_h = variables.LUA_INCDIR, "lua.h"
if not fs.exists(dir.path(lua_incdir, lua_h)) then
return nil, "Lua header file "..lua_h.." not found (looked in "..lua_incdir.."). \n" ..
"You need to install the Lua development package for your system."
end
checked_lua_h = true
end
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
return nil, "Failed compiling object "..object
end
table.insert(objects, object)
end
local module_name = name:match("([^.]*)$").."."..util.matchquote(cfg.lib_extension)
if moddir ~= "" then
module_name = dir.path(moddir, module_name)
ok, err = fs.make_dir(moddir)
if not ok then return nil, err end
end
lib_modules[module_name] = dir.path(libdir, module_name)
ok = compile_library(module_name, objects, info.libraries, info.libdirs, name)
if not ok then
return nil, "Failed compiling module "..module_name
end
--[[ TODO disable static libs until we fix the conflict in the manifest, which will take extending the manifest format.
module_name = name:match("([^.]*)$").."."..util.matchquote(cfg.static_lib_extension)
if moddir ~= "" then
module_name = dir.path(moddir, module_name)
end
lib_modules[module_name] = dir.path(libdir, module_name)
ok = compile_static_library(module_name, objects, info.libraries, info.libdirs, name)
if not ok then
return nil, "Failed compiling static library "..module_name
end
]]
end
end
if not no_install then
for _, mods in ipairs({{ tbl = lua_modules, perms = "read" }, { tbl = lib_modules, perms = "exec" }}) do
for name, dest in pairs(mods.tbl) do
fs.make_dir(dir.dir_name(dest))
ok, err = fs.copy(name, dest, mods.perms)
if not ok then
return nil, "Failed installing "..name.." in "..dest..": "..err
end
end
end
if fs.is_dir("lua") then
ok, err = fs.copy_contents("lua", luadir)
if not ok then
return nil, "Failed copying contents of 'lua' directory: "..err
end
end
end
return true
end
return builtin

View file

@ -1,78 +0,0 @@
--- Build back-end for CMake-based modules.
local cmake = {}
local fs = require("luarocks.fs")
local util = require("luarocks.util")
local cfg = require("luarocks.core.cfg")
--- Driver function for the "cmake" build back-end.
-- @param rockspec table: the loaded rockspec.
-- @return boolean or (nil, string): true if no errors occurred,
-- nil and an error message otherwise.
function cmake.run(rockspec, no_install)
assert(rockspec:type() == "rockspec")
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)
local ok, err_msg = fs.is_tool_available(rockspec.variables.CMAKE, "CMake")
if not ok then
return nil, err_msg
end
-- If inline cmake is present create CMakeLists.txt from it.
if type(build.cmake) == "string" then
local cmake_handler = assert(io.open(fs.current_dir().."/CMakeLists.txt", "w"))
cmake_handler:write(build.cmake)
cmake_handler:close()
end
-- Execute cmake with variables.
local args = ""
-- Try to pick the best generator. With msvc and x64, CMake does not select it by default so we need to be explicit.
if cfg.cmake_generator then
args = args .. ' -G"'..cfg.cmake_generator.. '"'
elseif cfg.is_platform("windows") and cfg.target_cpu:match("x86_64$") then
args = args .. " -DCMAKE_GENERATOR_PLATFORM=x64"
end
for k,v in pairs(variables) do
args = args .. ' -D' ..k.. '="' ..tostring(v).. '"'
end
if not fs.execute_string(rockspec.variables.CMAKE.." -H. -Bbuild.luarocks "..args) then
return nil, "Failed cmake."
end
local do_build, do_install
if rockspec:format_is_at_least("3.0") then
do_build = (build.build_pass == nil) and true or build.build_pass
do_install = (build.install_pass == nil) and true or build.install_pass
else
do_build = true
do_install = true
end
if do_build then
if not fs.execute_string(rockspec.variables.CMAKE.." --build build.luarocks --config Release") then
return nil, "Failed building."
end
end
if do_install and not no_install then
if not fs.execute_string(rockspec.variables.CMAKE.." --build build.luarocks --target install --config Release") then
return nil, "Failed installing."
end
end
return true
end
return cmake

View file

@ -1,41 +0,0 @@
--- Build back-end for raw listing of commands in rockspec files.
local command = {}
local fs = require("luarocks.fs")
local util = require("luarocks.util")
local cfg = require("luarocks.core.cfg")
--- Driver function for the "command" build back-end.
-- @param rockspec table: the loaded rockspec.
-- @return boolean or (nil, string): true if no errors occurred,
-- nil and an error message otherwise.
function command.run(rockspec, not_install)
assert(rockspec:type() == "rockspec")
local build = rockspec.build
util.variable_substitutions(build, rockspec.variables)
local env = {
CC = cfg.variables.CC,
--LD = cfg.variables.LD,
--CFLAGS = cfg.variables.CFLAGS,
}
if build.build_command then
util.printout(build.build_command)
if not fs.execute_env(env, build.build_command) then
return nil, "Failed building."
end
end
if build.install_command and not not_install then
util.printout(build.install_command)
if not fs.execute_env(env, build.install_command) then
return nil, "Failed installing."
end
end
return true
end
return command

View file

@ -1,98 +0,0 @@
--- Build back-end for using Makefile-based packages.
local make = {}
local unpack = unpack or table.unpack
local fs = require("luarocks.fs")
local util = require("luarocks.util")
local cfg = require("luarocks.core.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 occurred,
-- nil and an error message otherwise.
function make.run(rockspec, not_install)
assert(rockspec:type() == "rockspec")
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
if not not_install then
ok = make_pass(make_cmd, build.install_pass, build.install_target, build.install_variables)
if not ok then
return nil, "Failed installing."
end
end
return true
end
return make

View file

@ -1,678 +0,0 @@
--- Functions for command-line scripts.
local cmd = {}
local manif = require("luarocks.manif")
local util = require("luarocks.util")
local path = require("luarocks.path")
local cfg = require("luarocks.core.cfg")
local dir = require("luarocks.dir")
local fun = require("luarocks.fun")
local fs = require("luarocks.fs")
local argparse = require("luarocks.argparse")
local unpack = table.unpack or unpack
local pack = table.pack or function(...) return { n = select("#", ...), ... } end
local hc_ok, hardcoded = pcall(require, "luarocks.core.hardcoded")
if not hc_ok then
hardcoded = {}
end
local program = util.this_program("luarocks")
cmd.errorcodes = {
OK = 0,
UNSPECIFIED = 1,
PERMISSIONDENIED = 2,
CONFIGFILE = 3,
CRASH = 99
}
local function check_popen()
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(cmd.errorcodes.UNSPECIFIED)
end
end
local process_tree_args
do
local function replace_tree(args, root, tree)
root = dir.normalize(root)
args.tree = root
path.use_tree(tree or root)
end
local function strip_trailing_slashes()
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("/+$", "")
end
process_tree_args = function(args, project_dir)
if args.global then
cfg.local_by_default = false
end
if args.tree then
local named = false
for _, tree in ipairs(cfg.rocks_trees) do
if type(tree) == "table" and args.tree == tree.name then
if not tree.root then
return nil, "Configuration error: tree '"..tree.name.."' has no 'root' field."
end
replace_tree(args, tree.root, tree)
named = true
break
end
end
if not named then
local root_dir = fs.absolute_name(args.tree)
replace_tree(args, root_dir)
end
elseif args["local"] then
if fs.is_superuser() then
return nil, "The --local flag is meant for operating in a user's home directory.\n"..
"You are running as a superuser, which is intended for system-wide operation.\n"..
"To force using the superuser's home, use --tree explicitly."
else
replace_tree(args, cfg.home_tree)
end
elseif args.project_tree then
local tree = args.project_tree
table.insert(cfg.rocks_trees, 1, { name = "project", root = tree } )
manif.load_rocks_tree_manifests()
path.use_tree(tree)
elseif cfg.local_by_default then
if cfg.home_tree then
replace_tree(args, cfg.home_tree)
end
elseif project_dir then
local project_tree = project_dir .. "/lua_modules"
table.insert(cfg.rocks_trees, 1, { name = "project", root = project_tree } )
manif.load_rocks_tree_manifests()
path.use_tree(project_tree)
else
local trees = cfg.rocks_trees
path.use_tree(trees[#trees])
end
strip_trailing_slashes()
cfg.variables.ROCKS_TREE = cfg.rocks_dir
cfg.variables.SCRIPTS_DIR = cfg.deploy_bin_dir
return true
end
end
local function process_server_args(args)
if args.server then
local protocol, pathname = dir.split_url(args.server)
table.insert(cfg.rocks_servers, 1, protocol.."://"..pathname)
end
if args.dev then
local append_dev = function(s) return dir.path(s, "dev") end
local dev_servers = fun.traverse(cfg.rocks_servers, append_dev)
cfg.rocks_servers = fun.concat(dev_servers, cfg.rocks_servers)
end
if args.only_server then
if args.dev then
return nil, "--only-server cannot be used with --dev"
end
if args.server then
return nil, "--only-server cannot be used with --server"
end
cfg.rocks_servers = { args.only_server }
end
return true
end
local function error_handler(err)
if not debug then
return err
end
local mode = "Arch.: " .. (cfg and cfg.arch or "unknown")
if package.config:sub(1, 1) == "\\" then
if cfg and cfg.fs_use_modules then
mode = mode .. " (fs_use_modules = true)"
end
end
if cfg and cfg.is_binary then
mode = mode .. " (binary)"
end
return debug.traceback("LuaRocks "..cfg.program_version..
" bug (please report at https://github.com/luarocks/luarocks/issues).\n"..
mode.."\n"..err, 2)
end
--- Display an error message and exit.
-- @param message string: The error message.
-- @param exitcode number: the exitcode to use
local function die(message, exitcode)
assert(type(message) == "string", "bad error, expected string, got: " .. type(message))
assert(exitcode == nil or type(exitcode) == "number", "bad error, expected number, got: " .. type(exitcode) .. " - " .. tostring(exitcode))
util.printerr("\nError: "..message)
local ok, err = xpcall(util.run_scheduled_functions, error_handler)
if not ok then
util.printerr("\nError: "..err)
exitcode = cmd.errorcodes.CRASH
end
os.exit(exitcode or cmd.errorcodes.UNSPECIFIED)
end
local function search_lua_in_path(lua_version, verbose)
local path_sep = (package.config:sub(1, 1) == "\\" and ";" or ":")
local all_tried = {}
for bindir in (os.getenv("PATH") or ""):gmatch("[^"..path_sep.."]+") do
local parentdir = dir.path((bindir:gsub("[\\/][^\\/]+[\\/]?$", "")))
local detected, tried = util.find_lua(parentdir, lua_version)
if detected then
return detected
else
table.insert(all_tried, tried)
end
bindir = dir.path(bindir)
detected = util.find_lua(bindir, lua_version)
if detected then
return detected
else
table.insert(all_tried, tried)
end
end
return nil, "Could not find " ..
(lua_version and "Lua " .. lua_version or "Lua") ..
" in PATH." ..
(verbose and " Tried:\n" .. table.concat(all_tried, "\n") or "")
end
local init_config
do
local detect_config_via_args
do
local function find_project_dir(project_tree)
if project_tree then
return project_tree:gsub("[/\\][^/\\]+$", ""), true
else
local try = "."
for _ = 1, 10 do -- FIXME detect when root dir was hit instead
if util.exists(try .. "/.luarocks") and util.exists(try .. "/lua_modules") then
return try, false
elseif util.exists(try .. "/.luarocks-no-project") then
break
end
try = try .. "/.."
end
end
return nil
end
local function find_default_lua_version(args, project_dir)
if hardcoded.FORCE_CONFIG then
return nil
end
local dirs = {}
if project_dir then
table.insert(dirs, dir.path(project_dir, ".luarocks"))
end
if cfg.homeconfdir then
table.insert(dirs, cfg.homeconfdir)
end
table.insert(dirs, cfg.sysconfdir)
for _, d in ipairs(dirs) do
local f = dir.path(d, "default-lua-version.lua")
local mod, err = loadfile(f, "t")
if mod then
local pok, ver = pcall(mod)
if pok and type(ver) == "string" and ver:match("%d+.%d+") then
if args.verbose then
util.printout("Defaulting to Lua " .. ver .. " based on " .. f .. " ...")
end
return ver
end
end
end
return nil
end
local function find_version_from_config(dirname)
return fun.find(util.lua_versions("descending"), function(v)
if util.exists(dir.path(dirname, ".luarocks", "config-"..v..".lua")) then
return v
end
end)
end
local function detect_lua_via_args(args, project_dir)
local lua_version = args.lua_version
or find_default_lua_version(args, project_dir)
or (project_dir and find_version_from_config(project_dir))
if args.lua_dir then
local detected, err = util.find_lua(args.lua_dir, lua_version)
if not detected then
local suggestion = (not args.lua_version)
and "\nYou may want to specify a different Lua version with --lua-version\n"
or ""
die(err .. suggestion)
end
return detected
end
if lua_version then
local detected = search_lua_in_path(lua_version)
if detected then
return detected
end
return {
lua_version = lua_version,
}
end
return {}
end
detect_config_via_args = function(args)
local project_dir, given = find_project_dir(args.project_tree)
local detected = detect_lua_via_args(args, project_dir)
if args.lua_version then
detected.given_lua_version = args.lua_version
end
if args.lua_dir then
detected.given_lua_dir = args.lua_dir
end
if given then
detected.given_project_dir = project_dir
end
detected.project_dir = project_dir
return detected
end
end
init_config = function(args)
local detected = detect_config_via_args(args)
local ok, err = cfg.init(detected, util.warning)
if not ok then
return nil, err
end
return (detected.lua_dir ~= nil)
end
end
local variables_help = [[
Variables:
Variables from the "variables" table of the configuration file can be
overridden with VAR=VALUE assignments.
]]
local function get_status(status)
return status and "ok" or "not found"
end
local function use_to_fix_location(key)
local buf = " ****************************************\n"
buf = buf .. " Use the command\n\n"
buf = buf .. " luarocks config " .. key .. " <dir>\n\n"
buf = buf .. " to fix the location\n"
buf = buf .. " ****************************************\n"
return buf
end
local function get_config_text(cfg) -- luacheck: ignore 431
local deps = require("luarocks.deps")
local libdir_ok = deps.check_lua_libdir(cfg.variables)
local incdir_ok = deps.check_lua_incdir(cfg.variables)
local bindir_ok = fs.exists(cfg.variables.LUA_BINDIR)
local luadir_ok = fs.exists(cfg.variables.LUA_DIR)
local lua_ok = fs.exists(cfg.variables.LUA)
local buf = "Configuration:\n"
buf = buf.." Lua:\n"
buf = buf.." Version : "..cfg.lua_version.."\n"
if cfg.luajit_version then
buf = buf.." LuaJIT : "..cfg.luajit_version.."\n"
end
buf = buf.." Interpreter: "..(cfg.variables.LUA or "").." ("..get_status(lua_ok)..")\n"
buf = buf.." LUA_DIR : "..(cfg.variables.LUA_DIR or "").." ("..get_status(luadir_ok)..")\n"
if not lua_ok then
buf = buf .. use_to_fix_location("lua_dir")
end
buf = buf.." LUA_BINDIR : "..(cfg.variables.LUA_BINDIR or "").." ("..get_status(bindir_ok)..")\n"
buf = buf.." LUA_INCDIR : "..(cfg.variables.LUA_INCDIR or "").." ("..get_status(incdir_ok)..")\n"
if lua_ok and not incdir_ok then
buf = buf .. use_to_fix_location("variables.LUA_INCDIR")
end
buf = buf.." LUA_LIBDIR : "..(cfg.variables.LUA_LIBDIR or "").." ("..get_status(libdir_ok)..")\n"
if lua_ok and not libdir_ok then
buf = buf .. use_to_fix_location("variables.LUA_LIBDIR")
end
buf = buf.."\n Configuration files:\n"
local conf = cfg.config_files
buf = buf.." System : "..fs.absolute_name(conf.system.file).." ("..get_status(conf.system.found)..")\n"
if conf.user.file then
buf = buf.." User : "..fs.absolute_name(conf.user.file).." ("..get_status(conf.user.found)..")\n"
else
buf = buf.." User : disabled in this LuaRocks installation.\n"
end
if conf.project then
buf = buf.." Project : "..fs.absolute_name(conf.project.file).." ("..get_status(conf.project.found)..")\n"
end
buf = buf.."\n Rocks trees in use: \n"
for _, tree in ipairs(cfg.rocks_trees) do
if type(tree) == "string" then
buf = buf.." "..fs.absolute_name(tree)
else
local name = tree.name and " (\""..tree.name.."\")" or ""
buf = buf.." "..fs.absolute_name(tree.root)..name
end
buf = buf .. "\n"
end
return buf
end
local function get_parser(description, cmd_modules)
local basename = dir.base_name(program)
local parser = argparse(
basename, "LuaRocks "..cfg.program_version..", the Lua package manager\n\n"..
program.." - "..description, variables_help.."Run '"..basename..
"' without any arguments to see the configuration.")
:help_max_width(80)
:add_help_command()
:add_complete_command({
help_max_width = 100,
summary = "Output a shell completion script.",
description = [[
Output a shell completion script.
Enabling completions for Bash:
Add the following line to your ~/.bashrc:
source <(]]..basename..[[ completion bash)
or save the completion script to the local completion directory:
]]..basename..[[ completion bash > ~/.local/share/bash-completion/completions/]]..basename..[[
Enabling completions for Zsh:
Save the completion script to a file in your $fpath.
You can add a new directory to your $fpath by adding e.g.
fpath=(~/.zfunc $fpath)
to your ~/.zshrc.
Then run:
]]..basename..[[ completion zsh > ~/.zfunc/_]]..basename..[[
Enabling completion for Fish:
Add the following line to your ~/.config/fish/config.fish:
]]..basename..[[ completion fish | source
or save the completion script to the local completion directory:
]]..basename..[[ completion fish > ~/.config/fish/completions/]]..basename..[[.fish
]]})
:command_target("command")
:require_command(false)
parser:flag("--version", "Show version info and exit.")
:action(function()
util.printout(program.." "..cfg.program_version)
util.printout(description)
util.printout()
os.exit(cmd.errorcodes.OK)
end)
parser:flag("--dev", "Enable the sub-repositories in rocks servers for "..
"rockspecs of in-development versions.")
parser:option("--server", "Fetch rocks/rockspecs from this server "..
"(takes priority over config file).")
:hidden_name("--from")
parser:option("--only-server", "Fetch rocks/rockspecs from this server only "..
"(overrides any entries in the config file).")
:argname("<server>")
:hidden_name("--only-from")
parser:option("--only-sources", "Restrict downloads to paths matching the given URL.")
:argname("<url>")
:hidden_name("--only-sources-from")
parser:option("--namespace", "Specify the rocks server namespace to use.")
:convert(string.lower)
parser:option("--lua-dir", "Which Lua installation to use.")
:argname("<prefix>")
parser:option("--lua-version", "Which Lua version to use.")
:argname("<ver>")
parser:option("--tree", "Which tree to operate on.")
:hidden_name("--to")
parser:flag("--local", "Use the tree in the user's home directory.\n"..
"To enable it, see '"..program.." help path'.")
parser:flag("--global", "Use the system tree when `local_by_default` is `true`.")
parser:flag("--verbose", "Display verbose output of commands executed.")
parser:option("--timeout", "Timeout on network operations, in seconds.\n"..
"0 means no timeout (wait forever). Default is "..
tostring(cfg.connection_timeout)..".")
:argname("<seconds>")
:convert(tonumber)
-- Used internally to force the use of a particular project tree
parser:option("--project-tree"):hidden(true)
for _, module in util.sortedpairs(cmd_modules) do
module.add_to_parser(parser)
end
return parser
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.
-- @param description string: Short summary description of the program.
-- @param commands table: contains the loaded modules representing commands.
-- @param external_namespace string: where to look for external commands.
-- @param ... string: Arguments given on the command-line.
function cmd.run_command(description, commands, external_namespace, ...)
check_popen()
-- Preliminary initialization
cfg.init()
fs.init()
for _, module_name in ipairs(fs.modules(external_namespace)) do
if not commands[module_name] then
commands[module_name] = external_namespace.."."..module_name
end
end
local cmd_modules = {}
for name, module in pairs(commands) do
local pok, mod = pcall(require, module)
if pok and type(mod) == "table" then
local original_command = mod.command
if original_command then
if not mod.add_to_parser then
mod.add_to_parser = function(parser)
parser:command(name, mod.help, util.see_also())
:summary(mod.help_summary)
:handle_options(false)
:argument("input")
:args("*")
end
mod.command = function(args)
return original_command(args, unpack(args.input))
end
end
cmd_modules[name] = mod
else
util.warning("command module " .. module .. " does not implement command(), skipping")
end
else
util.warning("failed to load command module " .. module)
end
end
local function process_cmdline_vars(...)
local args = pack(...)
local cmdline_vars = {}
local last = args.n
for i = 1, args.n do
if args[i] == "--" then
last = i - 1
break
end
end
for i = last, 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
return args, cmdline_vars
end
local args, cmdline_vars = process_cmdline_vars(...)
local parser = get_parser(description, cmd_modules)
args = parser:parse(args)
-- Compatibility for old flag
if args.nodeps then
args.deps_mode = "none"
end
if args.timeout then -- setting it in the config file will kick-in earlier in the process
cfg.connection_timeout = args.timeout
end
if args.command == "config" then
if args.key == "lua_version" and args.value then
args.lua_version = args.value
elseif args.key == "lua_dir" and args.value then
args.lua_dir = args.value
end
end
-----------------------------------------------------------------------------
local lua_found, err = init_config(args)
if err then
die(err)
end
-----------------------------------------------------------------------------
-- Now that the config is fully loaded, reinitialize fs using the full
-- feature set.
fs.init()
-- if the Lua interpreter wasn't explicitly found before cfg.init,
-- try again now.
local tried
if not lua_found then
if cfg.variables.LUA_DIR then
lua_found, tried = util.find_lua(cfg.variables.LUA_DIR, cfg.lua_version, args.verbose)
else
lua_found, tried = search_lua_in_path(cfg.lua_version, args.verbose)
end
end
if not lua_found and args.command ~= "config" and args.command ~= "help" then
util.warning(tried ..
"\nModules may not install with the correct configurations. " ..
"You may want to configure the path prefix to your build " ..
"of Lua " .. cfg.lua_version .. " using\n\n" ..
" luarocks config --local lua_dir <your-lua-prefix>\n")
end
cfg.lua_found = lua_found
if cfg.project_dir then
cfg.project_dir = fs.absolute_name(cfg.project_dir)
end
if args.verbose then
cfg.verbose = true
fs.verbose()
end
if (not fs.current_dir()) or fs.current_dir() == "" then
die("Current directory does not exist. Please run LuaRocks from an existing directory.")
end
local ok, err = process_tree_args(args, cfg.project_dir)
if not ok then
die(err)
end
ok, err = process_server_args(args)
if not ok then
die(err)
end
if args.only_sources then
cfg.only_sources_from = args.only_sources
end
for k, v in pairs(cmdline_vars) do
cfg.variables[k] = v
end
-- if running as superuser, use system cache dir
if fs.is_superuser() then
cfg.local_cache = dir.path(fs.system_cache_dir(), "luarocks")
end
if args.no_manifest then
cfg.no_manifest = true
end
if not args.command then
parser:epilog(variables_help..get_config_text(cfg))
util.printout()
util.printout(parser:get_help())
util.printout()
os.exit(cmd.errorcodes.OK)
end
local cmd_mod = cmd_modules[args.command]
local call_ok, ok, err, exitcode = xpcall(function()
return cmd_mod.command(args)
end, error_handler)
if not call_ok then
die(ok, cmd.errorcodes.CRASH)
elseif not ok then
die(err, exitcode)
end
util.run_scheduled_functions()
end
return cmd

View file

@ -1,183 +0,0 @@
--- Module implementing the LuaRocks "build" command.
-- Builds a rock, compiling its C parts if any.
local cmd_build = {}
local pack = require("luarocks.pack")
local path = require("luarocks.path")
local util = require("luarocks.util")
local fetch = require("luarocks.fetch")
local fs = require("luarocks.fs")
local deps = require("luarocks.deps")
local remove = require("luarocks.remove")
local cfg = require("luarocks.core.cfg")
local build = require("luarocks.build")
local writer = require("luarocks.manif.writer")
local search = require("luarocks.search")
local make = require("luarocks.cmd.make")
local cmd = require("luarocks.cmd")
function cmd_build.add_to_parser(parser)
local cmd = parser:command("build", "Build and install a rock, compiling its C parts if any.\n".. -- luacheck: ignore 431
"If the sources contain a luarocks.lock file, uses it as an authoritative source for "..
"exact version of dependencies.\n"..
"If no arguments are given, behaves as luarocks make.", util.see_also())
:summary("Build/compile a rock.")
cmd:argument("rock", "A rockspec file, a source rock file, or the name of "..
"a rock to be fetched from a repository.")
:args("?")
:action(util.namespaced_name_action)
cmd:argument("version", "Rock version.")
:args("?")
cmd:flag("--only-deps --deps-only", "Install only the dependencies of the rock.")
cmd:option("--branch", "Override the `source.branch` field in the loaded "..
"rockspec. Allows to specify a different branch to fetch. Particularly "..
'for "dev" rocks.')
:argname("<name>")
parser:flag("--pin", "Create a luarocks.lock file listing the exact "..
"versions of each dependency found for this rock (recursively), "..
"and store it in the rock's directory. "..
"Ignores any existing luarocks.lock file in the rock's sources.")
make.cmd_options(cmd)
end
--- Build and install a rock.
-- @param rock_filename string: local or remote filename of a rock.
-- @param opts table: build options
-- @return boolean or (nil, string, [string]): True if build was successful,
-- or false and an error message and an optional error code.
local function build_rock(rock_filename, opts)
assert(type(rock_filename) == "string")
assert(opts:type() == "build.opts")
local ok, err, errcode
local unpack_dir
unpack_dir, err, errcode = fetch.fetch_and_unpack_rock(rock_filename, nil, opts.verify)
if not unpack_dir then
return nil, err, errcode
end
local rockspec_filename = path.rockspec_name_from_rock(rock_filename)
ok, err = fs.change_dir(unpack_dir)
if not ok then return nil, err end
local rockspec
rockspec, err, errcode = fetch.load_rockspec(rockspec_filename)
if not rockspec then
return nil, err, errcode
end
ok, err, errcode = build.build_rockspec(rockspec, opts)
fs.pop_dir()
return ok, err, errcode
end
local function do_build(name, namespace, version, opts)
assert(type(name) == "string")
assert(type(namespace) == "string" or not namespace)
assert(version == nil or type(version) == "string")
assert(opts:type() == "build.opts")
local url, err
if name:match("%.rockspec$") or name:match("%.rock$") then
url = name
else
url, err = search.find_src_or_rockspec(name, namespace, version, opts.check_lua_versions)
if not url then
return nil, err
end
end
if url:match("%.rockspec$") then
local rockspec, err = fetch.load_rockspec(url, nil, opts.verify)
if not rockspec then
return nil, err
end
return build.build_rockspec(rockspec, opts)
end
if url:match("%.src%.rock$") then
opts.need_to_fetch = false
end
return build_rock(url, opts)
end
--- Driver function for "build" command.
-- If a package name is given, forwards the request to "search" and,
-- if returned a result, installs the matching rock.
-- When passing a package name, a version number may also be given.
-- @return boolean or (nil, string, exitcode): True if build was successful; nil and an
-- error message otherwise. exitcode is optionally returned.
function cmd_build.command(args)
if not args.rock then
return make.command(args)
end
local opts = build.opts({
need_to_fetch = true,
minimal_mode = false,
deps_mode = deps.get_deps_mode(args),
build_only_deps = not not (args.only_deps and not args.pack_binary_rock),
namespace = args.namespace,
branch = args.branch,
verify = not not args.verify,
check_lua_versions = not not args.check_lua_versions,
pin = not not args.pin,
no_install = false
})
if args.sign and not args.pack_binary_rock then
return nil, "In the build command, --sign is meant to be used only with --pack-binary-rock"
end
if args.pack_binary_rock then
return pack.pack_binary_rock(args.rock, args.namespace, args.version, args.sign, function()
local name, version = do_build(args.rock, args.namespace, args.version, opts)
if name and args.no_doc then
util.remove_doc_dir(name, version)
end
return name, version
end)
end
local ok, err = fs.check_command_permissions(args)
if not ok then
return nil, err, cmd.errorcodes.PERMISSIONDENIED
end
local name, version = do_build(args.rock, args.namespace, args.version, opts)
if not name then
return nil, version
end
if args.no_doc then
util.remove_doc_dir(name, version)
end
if opts.build_only_deps then
util.printout("Stopping after installing dependencies for " ..name.." "..version)
util.printout()
else
if (not args.keep) and not cfg.keep_other_versions then
local ok, err, warn = remove.remove_other_versions(name, version, args.force, args.force_fast)
if not ok then
return nil, err
elseif warn then
util.printerr(err)
end
end
end
if opts.deps_mode ~= "none" then
writer.check_dependencies(nil, deps.get_deps_mode(args))
end
return name, version
end
return cmd_build

View file

@ -1,326 +0,0 @@
--- Module implementing the LuaRocks "config" command.
-- Queries information about the LuaRocks configuration.
local config_cmd = {}
local persist = require("luarocks.persist")
local cfg = require("luarocks.core.cfg")
local util = require("luarocks.util")
local deps = require("luarocks.deps")
local dir = require("luarocks.dir")
local fs = require("luarocks.fs")
function config_cmd.add_to_parser(parser)
local cmd = parser:command("config", [[
Query information about the LuaRocks configuration.
* When given a configuration key, it prints the value of that key according to
the currently active configuration (taking into account all config files and
any command-line flags passed)
Examples:
luarocks config lua_interpreter
luarocks config variables.LUA_INCDIR
luarocks config lua_version
* When given a configuration key and a value, it overwrites the config file (see
the --scope option below to determine which) and replaces the value of the
given key with the given value.
* `lua_dir` is a special key as it checks for a valid Lua installation
(equivalent to --lua-dir) and sets several keys at once.
* `lua_version` is a special key as it changes the default Lua version
used by LuaRocks commands (equivalent to passing --lua-version).
Examples:
luarocks config variables.OPENSSL_DIR /usr/local/openssl
luarocks config lua_dir /usr/local
luarocks config lua_version 5.3
* When given a configuration key and --unset, it overwrites the config file (see
the --scope option below to determine which) and deletes that key from the
file.
Example: luarocks config variables.OPENSSL_DIR --unset
* When given no arguments, it prints the entire currently active configuration,
resulting from reading the config files from all scopes.
Example: luarocks config]], util.see_also([[
https://github.com/luarocks/luarocks/wiki/Config-file-format
for detailed information on the LuaRocks config file format.
]]))
:summary("Query information about the LuaRocks configuration.")
cmd:argument("key", "The configuration key.")
:args("?")
cmd:argument("value", "The configuration value.")
:args("?")
cmd:option("--scope", "The scope indicates which config file should be rewritten.\n"..
'* Using a wrapper created with `luarocks init`, the default is "project".\n'..
'* Using --local (or when `local_by_default` is `true`), the default is "user".\n'..
'* Otherwise, the default is "system".')
:choices({"system", "user", "project"})
cmd:flag("--unset", "Delete the key from the configuration file.")
cmd:flag("--json", "Output as JSON.")
-- Deprecated flags
cmd:flag("--lua-incdir"):hidden(true)
cmd:flag("--lua-libdir"):hidden(true)
cmd:flag("--lua-ver"):hidden(true)
cmd:flag("--system-config"):hidden(true)
cmd:flag("--user-config"):hidden(true)
cmd:flag("--rock-trees"):hidden(true)
end
local function config_file(conf)
print(dir.normalize(conf.file))
if conf.found then
return true
else
return nil, "file not found"
end
end
local cfg_skip = {
errorcodes = true,
flags = true,
platforms = true,
root_dir = true,
upload_servers = true,
}
local function should_skip(k, v)
return type(v) == "function" or cfg_skip[k]
end
local function cleanup(tbl)
local copy = {}
for k, v in pairs(tbl) do
if not should_skip(k, v) then
copy[k] = v
end
end
return copy
end
local function traverse_varstring(var, tbl, fn, missing_parent)
local k, r = var:match("^%[([0-9]+)%]%.(.*)$")
if k then
k = tonumber(k)
else
k, r = var:match("^([^.[]+)%.(.*)$")
if not k then
k, r = var:match("^([^[]+)(%[.*)$")
end
end
if k then
if not tbl[k] and missing_parent then
missing_parent(tbl, k)
end
if tbl[k] then
return traverse_varstring(r, tbl[k], fn, missing_parent)
else
return nil, "Unknown entry " .. k
end
end
local i = var:match("^%[([0-9]+)%]$")
if i then
var = tonumber(i)
end
return fn(tbl, var)
end
local function print_json(value)
local json_ok, json = util.require_json()
if not json_ok then
return nil, "A JSON library is required for this command. "..json
end
print(json.encode(value))
return true
end
local function print_entry(var, tbl, is_json)
return traverse_varstring(var, tbl, function(t, k)
if not t[k] then
return nil, "Unknown entry " .. k
end
local val = t[k]
if not should_skip(var, val) then
if is_json then
return print_json(val)
elseif type(val) == "string" then
print(val)
else
persist.write_value(io.stdout, val)
end
end
return true
end)
end
local function infer_type(var)
local typ
traverse_varstring(var, cfg, function(t, k)
if t[k] ~= nil then
typ = type(t[k])
end
end)
return typ
end
local function write_entries(keys, scope, do_unset)
if scope == "project" and not cfg.config_files.project then
return nil, "Current directory is not part of a project. You may want to run `luarocks init`."
end
local tbl, err = persist.load_config_file_if_basic(cfg.config_files[scope].file, cfg)
if not tbl then
return nil, err
end
for var, val in util.sortedpairs(keys) do
traverse_varstring(var, tbl, function(t, k)
if do_unset then
t[k] = nil
else
local typ = infer_type(var)
local v
if typ == "number" and tonumber(val) then
v = tonumber(val)
elseif typ == "boolean" and val == "true" then
v = true
elseif typ == "boolean" and val == "false" then
v = false
else
v = val
end
t[k] = v
keys[var] = v
end
return true
end, function(p, k)
p[k] = {}
end)
end
local ok, err = persist.save_from_table(cfg.config_files[scope].file, tbl)
if ok then
print(do_unset and "Removed" or "Wrote")
for var, val in util.sortedpairs(keys) do
if do_unset then
print(("\t%s"):format(var))
else
print(("\t%s = %q"):format(var, val))
end
end
print(do_unset and "from" or "to")
print("\t" .. cfg.config_files[scope].file)
return true
else
return nil, err
end
end
local function get_scope(args)
return args.scope
or (args["local"] and "user")
or (args.project_tree and "project")
or (cfg.local_by_default and "user")
or (fs.is_writable(cfg.config_files["system"].file and "system"))
or "user"
end
--- Driver function for "config" command.
-- @return boolean: True if succeeded, nil on errors.
function config_cmd.command(args)
deps.check_lua_incdir(cfg.variables, args.lua_version or cfg.lua_version)
deps.check_lua_libdir(cfg.variables, args.lua_version or cfg.lua_version)
-- deprecated flags
if args.lua_incdir then
print(cfg.variables.LUA_INCDIR)
return true
end
if args.lua_libdir then
print(cfg.variables.LUA_LIBDIR)
return true
end
if args.lua_ver then
print(cfg.lua_version)
return true
end
if args.system_config then
return config_file(cfg.config_files.system)
end
if args.user_config then
return config_file(cfg.config_files.user)
end
if args.rock_trees then
for _, tree in ipairs(cfg.rocks_trees) do
if type(tree) == "string" then
util.printout(dir.normalize(tree))
else
local name = tree.name and "\t"..tree.name or ""
util.printout(dir.normalize(tree.root)..name)
end
end
return true
end
if args.key == "lua_version" and args.value then
local scope = get_scope(args)
if scope == "project" and not cfg.config_files.project then
return nil, "Current directory is not part of a project. You may want to run `luarocks init`."
end
local prefix = dir.dir_name(cfg.config_files[scope].file)
local ok, err = persist.save_default_lua_version(prefix, args.value)
if not ok then
return nil, "could not set default Lua version: " .. err
end
print("Lua version will default to " .. args.value .. " in " .. prefix)
end
if args.key == "lua_dir" and args.value then
local scope = get_scope(args)
local keys = {
["variables.LUA_DIR"] = cfg.variables.LUA_DIR,
["variables.LUA_BINDIR"] = cfg.variables.LUA_BINDIR,
["variables.LUA_INCDIR"] = cfg.variables.LUA_INCDIR,
["variables.LUA_LIBDIR"] = cfg.variables.LUA_LIBDIR,
["lua_interpreter"] = cfg.lua_interpreter,
}
if args.lua_version then
local prefix = dir.dir_name(cfg.config_files[scope].file)
persist.save_default_lua_version(prefix, args.lua_version)
end
return write_entries(keys, scope, args.unset)
end
if args.key then
if args.value or args.unset then
local scope = get_scope(args)
return write_entries({ [args.key] = args.value or args.unset }, scope, args.unset)
else
return print_entry(args.key, cfg, args.json)
end
end
local cleancfg = cleanup(cfg)
if args.json then
return print_json(cleancfg)
else
print(persist.save_from_table_to_string(cleancfg))
return true
end
end
return config_cmd

View file

@ -1,153 +0,0 @@
--- Module implementing the LuaRocks "doc" command.
-- Shows documentation for an installed rock.
local doc = {}
local util = require("luarocks.util")
local queries = require("luarocks.queries")
local search = require("luarocks.search")
local path = require("luarocks.path")
local dir = require("luarocks.dir")
local fetch = require("luarocks.fetch")
local fs = require("luarocks.fs")
local download = require("luarocks.download")
function doc.add_to_parser(parser)
local cmd = parser:command("doc", "Show documentation for an installed rock.\n\n"..
"Without any flags, tries to load the documentation using a series of heuristics.\n"..
"With flags, return only the desired information.", util.see_also([[
For more information about a rock, see the 'show' command.
]]))
:summary("Show documentation for an installed rock.")
cmd:argument("rock", "Name of the rock.")
:action(util.namespaced_name_action)
cmd:argument("version", "Version of the rock.")
:args("?")
cmd:flag("--home", "Open the home page of project.")
cmd:flag("--list", "List documentation files only.")
cmd:flag("--porcelain", "Produce machine-friendly output.")
end
local function show_homepage(homepage, name, namespace, version)
if not homepage then
return nil, "No 'homepage' field in rockspec for "..util.format_rock_name(name, namespace, version)
end
util.printout("Opening "..homepage.." ...")
fs.browser(homepage)
return true
end
local function try_to_open_homepage(name, namespace, version)
local temp_dir, err = fs.make_temp_dir("doc-"..name.."-"..(version or ""))
if not temp_dir then
return nil, "Failed creating temporary directory: "..err
end
util.schedule_function(fs.delete, temp_dir)
local ok, err = fs.change_dir(temp_dir)
if not ok then return nil, err end
local filename, err = download.download("rockspec", name, namespace, version)
if not filename then return nil, err end
local rockspec, err = fetch.load_local_rockspec(filename)
if not rockspec then return nil, err end
fs.pop_dir()
local descript = rockspec.description or {}
return show_homepage(descript.homepage, name, namespace, version)
end
--- Driver function for "doc" command.
-- @return boolean: True if succeeded, nil on errors.
function doc.command(args)
local query = queries.new(args.rock, args.namespace, args.version)
local iname, iversion, repo = search.pick_installed_rock(query, args.tree)
if not iname then
local rock = util.format_rock_name(args.rock, args.namespace, args.version)
util.printout(rock.." is not installed. Looking for it in the rocks servers...")
return try_to_open_homepage(args.rock, args.namespace, args.version)
end
local name, version = iname, iversion
local rockspec, err = fetch.load_local_rockspec(path.rockspec_file(name, version, repo))
if not rockspec then return nil,err end
local descript = rockspec.description or {}
if args.home then
return show_homepage(descript.homepage, name, args.namespace, version)
end
local directory = path.install_dir(name, version, repo)
local docdir
local directories = { "doc", "docs" }
for _, d in ipairs(directories) do
local dirname = dir.path(directory, d)
if fs.is_dir(dirname) then
docdir = dirname
break
end
end
if not docdir then
if descript.homepage and not args.list then
util.printout("Local documentation directory not found -- opening "..descript.homepage.." ...")
fs.browser(descript.homepage)
return true
end
return nil, "Documentation directory not found for "..name.." "..version
end
docdir = dir.normalize(docdir):gsub("/+", "/")
local files = fs.find(docdir)
local htmlpatt = "%.html?$"
local extensions = { htmlpatt, "%.md$", "%.txt$", "%.textile$", "" }
local basenames = { "index", "readme", "manual" }
local porcelain = args.porcelain
if #files > 0 then
util.title("Documentation files for "..name.." "..version, porcelain)
if porcelain then
for _, file in ipairs(files) do
util.printout(docdir.."/"..file)
end
else
util.printout(docdir.."/")
for _, file in ipairs(files) do
util.printout("\t"..file)
end
end
end
if args.list then
return true
end
for _, extension in ipairs(extensions) do
for _, basename in ipairs(basenames) do
local filename = basename..extension
local found
for _, file in ipairs(files) do
if file:lower():match(filename) and ((not found) or #file < #found) then
found = file
end
end
if found then
local pathname = dir.path(docdir, found)
util.printout()
util.printout("Opening "..pathname.." ...")
util.printout()
local ok = fs.browser(pathname)
if not ok and not pathname:match(htmlpatt) then
local fd = io.open(pathname, "r")
util.printout(fd:read("*a"))
fd:close()
end
return true
end
end
end
return true
end
return doc

View file

@ -1,51 +0,0 @@
--- Module implementing the luarocks "download" command.
-- Download a rock from the repository.
local cmd_download = {}
local util = require("luarocks.util")
local download = require("luarocks.download")
function cmd_download.add_to_parser(parser)
local cmd = parser:command("download", "Download a specific rock file from a rocks server.", util.see_also())
cmd:argument("name", "Name of the rock.")
:args("?")
:action(util.namespaced_name_action)
cmd:argument("version", "Version of the rock.")
:args("?")
cmd:flag("--all", "Download all files if there are multiple matches.")
cmd:mutex(
cmd:flag("--source", "Download .src.rock if available."),
cmd:flag("--rockspec", "Download .rockspec if available."),
cmd:option("--arch", "Download rock for a specific architecture."))
cmd:flag("--check-lua-versions", "If the rock can't be found, check repository "..
"and report if it is available for another Lua version.")
end
--- Driver function for the "download" command.
-- @return boolean or (nil, string): true if successful or nil followed
-- by an error message.
function cmd_download.command(args)
if not args.name and not args.all then
return nil, "Argument missing. "..util.see_help("download")
end
args.name = args.name or ""
local arch
if args.source then
arch = "src"
elseif args.rockspec then
arch = "rockspec"
elseif args.arch then
arch = args.arch
end
local dl, err = download.download(arch, args.name, args.namespace, args.version, args.all, args.check_lua_versions)
return dl and true, err
end
return cmd_download

View file

@ -1,176 +0,0 @@
local init = {}
local cfg = require("luarocks.core.cfg")
local fs = require("luarocks.fs")
local path = require("luarocks.path")
local deps = require("luarocks.deps")
local dir = require("luarocks.dir")
local util = require("luarocks.util")
local persist = require("luarocks.persist")
local write_rockspec = require("luarocks.cmd.write_rockspec")
function init.add_to_parser(parser)
local cmd = parser:command("init", "Initialize a directory for a Lua project using LuaRocks.", util.see_also())
cmd:argument("name", "The project name.")
:args("?")
cmd:argument("version", "An optional project version.")
:args("?")
cmd:flag("--reset", "Delete .luarocks/config-5.x.lua and ./lua and generate new ones.")
cmd:group("Options for specifying rockspec data", write_rockspec.cmd_options(cmd))
end
local function write_gitignore(entries)
local gitignore = ""
local fd = io.open(".gitignore", "r")
if fd then
gitignore = fd:read("*a")
fd:close()
gitignore = "\n" .. gitignore .. "\n"
end
fd = io.open(".gitignore", gitignore and "a" or "w")
for _, entry in ipairs(entries) do
entry = "/" .. entry
if not gitignore:find("\n"..entry.."\n", 1, true) then
fd:write(entry.."\n")
end
end
fd:close()
end
--- Driver function for "init" command.
-- @return boolean: True if succeeded, nil on errors.
function init.command(args)
local pwd = fs.current_dir()
if not args.name then
args.name = dir.base_name(pwd)
if args.name == "/" then
return nil, "When running from the root directory, please specify the <name> argument"
end
end
util.title("Initializing project '" .. args.name .. "' for Lua " .. cfg.lua_version .. " ...")
util.printout("Checking your Lua installation ...")
if not cfg.lua_found then
return nil, "Lua installation is not found."
end
local ok, err = deps.check_lua_incdir(cfg.variables)
if not ok then
return nil, err
end
local has_rockspec = false
for file in fs.dir() do
if file:match("%.rockspec$") then
has_rockspec = true
break
end
end
if not has_rockspec then
args.version = args.version or "dev"
args.location = pwd
local ok, err = write_rockspec.command(args)
if not ok then
util.printerr(err)
end
end
local ext = cfg.wrapper_suffix
local luarocks_wrapper = "luarocks" .. ext
local lua_wrapper = "lua" .. ext
util.printout("Adding entries to .gitignore ...")
write_gitignore({ luarocks_wrapper, lua_wrapper, "lua_modules", ".luarocks" })
util.printout("Preparing ./.luarocks/ ...")
fs.make_dir(".luarocks")
local config_file = ".luarocks/config-" .. cfg.lua_version .. ".lua"
if args.reset then
fs.delete(lua_wrapper)
fs.delete(config_file)
end
local config_tbl, err = persist.load_config_file_if_basic(config_file, cfg)
if config_tbl then
local globals = {
"lua_interpreter",
}
for _, v in ipairs(globals) do
if cfg[v] then
config_tbl[v] = cfg[v]
end
end
local varnames = {
"LUA_DIR",
"LUA_INCDIR",
"LUA_LIBDIR",
"LUA_BINDIR",
"LUA_INTERPRETER",
}
for _, varname in ipairs(varnames) do
if cfg.variables[varname] then
config_tbl.variables = config_tbl.variables or {}
config_tbl.variables[varname] = cfg.variables[varname]
end
end
local ok, err = persist.save_from_table(config_file, config_tbl)
if ok then
util.printout("Wrote " .. config_file)
else
util.printout("Failed writing " .. config_file .. ": " .. err)
end
else
util.printout("Will not attempt to overwrite " .. config_file)
end
ok, err = persist.save_default_lua_version(".luarocks", cfg.lua_version)
if not ok then
util.printout("Failed setting default Lua version: " .. err)
end
util.printout("Preparing ./lua_modules/ ...")
fs.make_dir("lua_modules/lib/luarocks/rocks-" .. cfg.lua_version)
local tree = dir.path(pwd, "lua_modules")
luarocks_wrapper = dir.path(".", luarocks_wrapper)
if not fs.exists(luarocks_wrapper) then
util.printout("Preparing " .. luarocks_wrapper .. " ...")
fs.wrap_script(arg[0], "luarocks", "none", nil, nil, "--project-tree", tree)
else
util.printout(luarocks_wrapper .. " already exists. Not overwriting it!")
end
lua_wrapper = dir.path(".", lua_wrapper)
local write_lua_wrapper = true
if fs.exists(lua_wrapper) then
if not util.lua_is_wrapper(lua_wrapper) then
util.printout(lua_wrapper .. " already exists and does not look like a wrapper script. Not overwriting.")
write_lua_wrapper = false
end
end
if write_lua_wrapper then
local interp = dir.path(cfg.variables["LUA_BINDIR"], cfg.lua_interpreter)
if util.check_lua_version(interp, cfg.lua_version) then
util.printout("Preparing " .. lua_wrapper .. " for version " .. cfg.lua_version .. "...")
path.use_tree(tree)
fs.wrap_script(nil, "lua", "all")
else
util.warning("No Lua interpreter detected for version " .. cfg.lua_version .. ". Not creating " .. lua_wrapper)
end
end
return true
end
return init

View file

@ -1,254 +0,0 @@
--- Module implementing the LuaRocks "install" command.
-- Installs binary rocks.
local install = {}
local path = require("luarocks.path")
local repos = require("luarocks.repos")
local fetch = require("luarocks.fetch")
local util = require("luarocks.util")
local fs = require("luarocks.fs")
local deps = require("luarocks.deps")
local writer = require("luarocks.manif.writer")
local remove = require("luarocks.remove")
local search = require("luarocks.search")
local queries = require("luarocks.queries")
local cfg = require("luarocks.core.cfg")
local cmd = require("luarocks.cmd")
function install.add_to_parser(parser)
local cmd = parser:command("install", "Install a rock.", util.see_also()) -- luacheck: ignore 431
cmd:argument("rock", "The name of a rock to be fetched from a repository "..
"or a filename of a locally available rock.")
:action(util.namespaced_name_action)
cmd:argument("version", "Version of the rock.")
:args("?")
cmd:flag("--keep", "Do not remove previously installed versions of the "..
"rock after building a new one. This behavior can be made permanent by "..
"setting keep_other_versions=true in the configuration file.")
cmd:flag("--force", "If --keep is not specified, force removal of "..
"previously installed versions if it would break dependencies.")
cmd:flag("--force-fast", "Like --force, but performs a forced removal "..
"without reporting dependency issues.")
cmd:flag("--only-deps --deps-only", "Install only the dependencies of the rock.")
cmd:flag("--no-doc", "Install the rock without its documentation.")
cmd:flag("--verify", "Verify signature of the rockspec or src.rock being "..
"built. If the rockspec or src.rock is being downloaded, LuaRocks will "..
"attempt to download the signature as well. Otherwise, the signature "..
"file should be already available locally in the same directory.\n"..
"You need the signers public key in your local keyring for this "..
"option to work properly.")
cmd:flag("--check-lua-versions", "If the rock can't be found, check repository "..
"and report if it is available for another Lua version.")
util.deps_mode_option(cmd)
cmd:flag("--no-manifest", "Skip creating/updating the manifest")
-- luarocks build options
parser:flag("--pack-binary-rock"):hidden(true)
parser:option("--branch"):hidden(true)
parser:flag("--sign"):hidden(true)
end
install.opts = util.opts_table("install.opts", {
namespace = "string?",
keep = "boolean",
force = "boolean",
force_fast = "boolean",
no_doc = "boolean",
deps_mode = "string",
verify = "boolean",
})
--- Install a binary rock.
-- @param rock_file string: local or remote filename of a rock.
-- @param opts table: installation options
-- @return (string, string) or (nil, string, [string]): Name and version of
-- installed rock if succeeded or nil and an error message followed by an error code.
function install.install_binary_rock(rock_file, opts)
assert(type(rock_file) == "string")
assert(opts:type() == "install.opts")
local namespace = opts.namespace
local deps_mode = opts.deps_mode
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 repos.is_installed(name, version) then
repos.delete_version(name, version, opts.deps_mode)
end
local install_dir = path.install_dir(name, version)
local rollback = util.schedule_function(function()
fs.delete(install_dir)
fs.remove_dir_if_empty(path.versions_dir(name))
end)
local ok, err, errcode = fetch.fetch_and_unpack_rock(rock_file, install_dir, opts.verify)
if not ok then return nil, err, errcode end
local rockspec, err = fetch.load_rockspec(path.rockspec_file(name, version))
if err then
return nil, "Failed loading rockspec for installed package: "..err, errcode
end
if opts.deps_mode ~= "none" then
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 = writer.make_rock_manifest(name, version)
if err then return nil, err end
end
if namespace then
ok, err = writer.make_namespace_file(name, version, namespace)
if err then return nil, err end
end
if deps_mode ~= "none" then
ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", deps_mode, opts.verify, install_dir)
if err then return nil, err, errcode end
end
ok, err = repos.deploy_files(name, version, repos.should_wrap_bin_scripts(rockspec), deps_mode)
if err then return nil, err end
util.remove_scheduled_function(rollback)
rollback = util.schedule_function(function()
repos.delete_version(name, version, deps_mode)
end)
ok, err = repos.run_hook(rockspec, "post_install")
if err then return nil, err end
util.announce_install(rockspec)
util.remove_scheduled_function(rollback)
return name, version
end
--- Installs the dependencies of a binary rock.
-- @param rock_file string: local or remote filename of a rock.
-- @param opts table: installation options
-- @return (string, string) or (nil, string, [string]): Name and version of
-- the rock whose dependencies were installed if succeeded or nil and an error message
-- followed by an error code.
function install.install_binary_rock_deps(rock_file, opts)
assert(type(rock_file) == "string")
assert(opts:type() == "install.opts")
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
local install_dir = path.install_dir(name, version)
local ok, err, errcode = fetch.fetch_and_unpack_rock(rock_file, install_dir, opts.verify)
if not ok then return nil, err, errcode end
local rockspec, err = fetch.load_rockspec(path.rockspec_file(name, version))
if err then
return nil, "Failed loading rockspec for installed package: "..err, errcode
end
ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", opts.deps_mode, opts.verify, install_dir)
if err then return nil, err, errcode end
util.printout()
util.printout("Successfully installed dependencies for " ..name.." "..version)
return name, version
end
local function install_rock_file_deps(filename, opts)
assert(opts:type() == "install.opts")
local name, version = install.install_binary_rock_deps(filename, opts)
if not name then return nil, version end
writer.check_dependencies(nil, opts.deps_mode)
return name, version
end
local function install_rock_file(filename, opts)
assert(type(filename) == "string")
assert(opts:type() == "install.opts")
local name, version = install.install_binary_rock(filename, opts)
if not name then return nil, version end
if opts.no_doc then
util.remove_doc_dir(name, version)
end
if (not opts.keep) and not cfg.keep_other_versions then
local ok, err, warn = remove.remove_other_versions(name, version, opts.force, opts.force_fast)
if not ok then
return nil, err
elseif warn then
util.printerr(err)
end
end
writer.check_dependencies(nil, opts.deps_mode)
return name, version
end
--- Driver function for the "install" command.
-- 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.
-- @return boolean or (nil, string, exitcode): True if installation was
-- successful, nil and an error message otherwise. exitcode is optionally returned.
function install.command(args)
local ok, err = fs.check_command_permissions(args)
if not ok then return nil, err, cmd.errorcodes.PERMISSIONDENIED end
if args.rock:match("%.rockspec$") or args.rock:match("%.src%.rock$") then
local build = require("luarocks.cmd.build")
return build.command(args)
elseif args.rock:match("%.rock$") then
local deps_mode = deps.get_deps_mode(args)
local opts = install.opts({
namespace = args.namespace,
keep = not not args.keep,
force = not not args.force,
force_fast = not not args.force_fast,
no_doc = not not args.no_doc,
deps_mode = deps_mode,
verify = not not args.verify,
})
if args.only_deps then
return install_rock_file_deps(args.rock, opts)
else
return install_rock_file(args.rock, opts)
end
else
local url, err = search.find_rock_checking_lua_versions(
queries.new(args.rock, args.namespace, args.version),
args.check_lua_versions)
if not url then
return nil, err
end
util.printout("Installing "..url)
args.rock = url
return install.command(args)
end
end
return install

View file

@ -1,50 +0,0 @@
--- Module implementing the LuaRocks "lint" command.
-- Utility function that checks syntax of the rockspec.
local lint = {}
local util = require("luarocks.util")
local download = require("luarocks.download")
local fetch = require("luarocks.fetch")
function lint.add_to_parser(parser)
local cmd = parser:command("lint", "Check syntax of a rockspec.\n\n"..
"Returns success if the text of the rockspec is syntactically correct, else failure.",
util.see_also())
:summary("Check syntax of a rockspec.")
cmd:argument("rockspec", "The rockspec to check.")
end
function lint.command(args)
local filename = args.rockspec
if not filename:match(".rockspec$") then
local err
filename, err = download.download("rockspec", filename:lower())
if not filename then
return nil, err
end
end
local rs, err = fetch.load_local_rockspec(filename)
if not rs then
return nil, "Failed loading rockspec: "..err
end
local ok = true
-- This should have been done in the type checker,
-- but it would break compatibility of other commands.
-- Making 'lint' alone be stricter shouldn't be a problem,
-- because extra-strict checks is what lint-type commands
-- are all about.
if not rs.description.license then
util.printerr("Rockspec has no license field.")
ok = false
end
return ok, ok or filename.." failed consistency checks."
end
return lint

View file

@ -1,96 +0,0 @@
--- Module implementing the LuaRocks "list" command.
-- Lists currently installed rocks.
local list = {}
local search = require("luarocks.search")
local queries = require("luarocks.queries")
local vers = require("luarocks.core.vers")
local cfg = require("luarocks.core.cfg")
local util = require("luarocks.util")
local path = require("luarocks.path")
function list.add_to_parser(parser)
local cmd = parser:command("list", "List currently installed rocks.", util.see_also())
cmd:argument("filter", "A substring of a rock name to filter by.")
:args("?")
cmd:argument("version", "Rock version to filter by.")
:args("?")
cmd:flag("--outdated", "List only rocks for which there is a higher "..
"version available in the rocks server.")
cmd:flag("--porcelain", "Produce machine-friendly output.")
end
local function check_outdated(trees, query)
local results_installed = {}
for _, tree in ipairs(trees) do
search.local_manifest_search(results_installed, path.rocks_dir(tree), query)
end
local outdated = {}
for name, versions in util.sortedpairs(results_installed) do
versions = util.keys(versions)
table.sort(versions, vers.compare_versions)
local latest_installed = versions[1]
local query_available = queries.new(name:lower())
local results_available, err = search.search_repos(query_available)
if results_available[name] then
local available_versions = util.keys(results_available[name])
table.sort(available_versions, vers.compare_versions)
local latest_available = available_versions[1]
local latest_available_repo = results_available[name][latest_available][1].repo
if vers.compare_versions(latest_available, latest_installed) then
table.insert(outdated, { name = name, installed = latest_installed, available = latest_available, repo = latest_available_repo })
end
end
end
return outdated
end
local function list_outdated(trees, query, porcelain)
util.title("Outdated rocks:", porcelain)
local outdated = check_outdated(trees, query)
for _, item in ipairs(outdated) do
if porcelain then
util.printout(item.name, item.installed, item.available, item.repo)
else
util.printout(item.name)
util.printout(" "..item.installed.." < "..item.available.." at "..item.repo)
util.printout()
end
end
return true
end
--- Driver function for "list" command.
-- @return boolean: True if succeeded, nil on errors.
function list.command(args)
local query = queries.new(args.filter and args.filter:lower() or "", args.namespace, args.version, true)
local trees = cfg.rocks_trees
local title = "Rocks installed for Lua "..cfg.lua_version
if args.tree then
trees = { args.tree }
title = title .. " in " .. args.tree
end
if args.outdated then
return list_outdated(trees, query, args.porcelain)
end
local results = {}
for _, tree in ipairs(trees) do
local ok, err, errcode = search.local_manifest_search(results, path.rocks_dir(tree), query)
if not ok and errcode ~= "open" then
util.warning(err)
end
end
util.title(title, args.porcelain)
search.print_result_tree(results, args.porcelain)
return true
end
return list

View file

@ -1,158 +0,0 @@
--- 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.
local make = {}
local build = require("luarocks.build")
local fs = require("luarocks.fs")
local util = require("luarocks.util")
local cfg = require("luarocks.core.cfg")
local fetch = require("luarocks.fetch")
local pack = require("luarocks.pack")
local remove = require("luarocks.remove")
local deps = require("luarocks.deps")
local writer = require("luarocks.manif.writer")
local cmd = require("luarocks.cmd")
function make.cmd_options(parser)
parser:flag("--no-install", "Do not install the rock.")
parser:flag("--no-doc", "Install the rock without its documentation.")
parser:flag("--pack-binary-rock", "Do not install rock. Instead, produce a "..
".rock file with the contents of compilation in the current directory.")
parser:flag("--keep", "Do not remove previously installed versions of the "..
"rock after building a new one. This behavior can be made permanent by "..
"setting keep_other_versions=true in the configuration file.")
parser:flag("--force", "If --keep is not specified, force removal of "..
"previously installed versions if it would break dependencies.")
parser:flag("--force-fast", "Like --force, but performs a forced removal "..
"without reporting dependency issues.")
parser:flag("--verify", "Verify signature of the rockspec or src.rock being "..
"built. If the rockspec or src.rock is being downloaded, LuaRocks will "..
"attempt to download the signature as well. Otherwise, the signature "..
"file should be already available locally in the same directory.\n"..
"You need the signers public key in your local keyring for this "..
"option to work properly.")
parser:flag("--sign", "To be used with --pack-binary-rock. Also produce a "..
"signature file for the generated .rock file.")
parser:flag("--check-lua-versions", "If the rock can't be found, check repository "..
"and report if it is available for another Lua version.")
parser:flag("--pin", "Pin the exact dependencies used for the rockspec"..
"being built into a luarocks.lock file in the current directory.")
parser:flag("--no-manifest", "Skip creating/updating the manifest")
parser:flag("--only-deps --deps-only", "Install only the dependencies of the rock.")
util.deps_mode_option(parser)
end
function make.add_to_parser(parser)
-- luacheck: push ignore 431
local cmd = parser:command("make", [[
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, it looks for a rockspec in the current directory and in
"rockspec/" and "rockspecs/" subdirectories, picking the rockspec with newest
version or without version name. If rockspecs for different rocks are found or
there are several rockspecs without version, 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 the current directory contains a luarocks.lock file, it is used as the
authoritative source for exact version of dependencies. The --pin flag
overrides and recreates this file scanning dependency based on ranges.
]], util.see_also())
:summary("Compile package in current directory using a rockspec.")
-- luacheck: pop
cmd:argument("rockspec", "Rockspec for the rock to build.")
:args("?")
make.cmd_options(cmd)
end
--- Driver function for "make" command.
-- @return boolean or (nil, string, exitcode): True if build was successful; nil and an
-- error message otherwise. exitcode is optionally returned.
function make.command(args)
local rockspec_filename = args.rockspec
if not rockspec_filename then
local err
rockspec_filename, err = util.get_default_rockspec()
if not rockspec_filename then
return nil, err
end
end
if not rockspec_filename:match("rockspec$") then
return nil, "Invalid argument: 'make' takes a rockspec as a parameter. "..util.see_help("make")
end
local rockspec, err, errcode = fetch.load_rockspec(rockspec_filename)
if not rockspec then
return nil, err
end
local name, namespace = util.split_namespace(rockspec.name)
namespace = namespace or args.namespace
local opts = build.opts({
need_to_fetch = false,
minimal_mode = true,
deps_mode = deps.get_deps_mode(args),
build_only_deps = not not (args.only_deps and not args.pack_binary_rock),
namespace = namespace,
branch = args.branch,
verify = not not args.verify,
check_lua_versions = not not args.check_lua_versions,
pin = not not args.pin,
no_install = not not args.no_install
})
if args.sign and not args.pack_binary_rock then
return nil, "In the make command, --sign is meant to be used only with --pack-binary-rock"
end
if args.no_install then
return build.build_rockspec(rockspec, opts)
elseif args.pack_binary_rock then
return pack.pack_binary_rock(name, namespace, rockspec.version, args.sign, function()
local name, version = build.build_rockspec(rockspec, opts) -- luacheck: ignore 431
if name and args.no_doc then
util.remove_doc_dir(name, version)
end
return name, version
end)
else
local ok, err = fs.check_command_permissions(args)
if not ok then return nil, err, cmd.errorcodes.PERMISSIONDENIED end
ok, err = build.build_rockspec(rockspec, opts)
if not ok then return nil, err end
local name, version = ok, err -- luacheck: ignore 421
if opts.build_only_deps then
util.printout("Stopping after installing dependencies for " ..name.." "..version)
util.printout()
return name, version
end
if args.no_doc then
util.remove_doc_dir(name, version)
end
if (not args.keep) and not cfg.keep_other_versions then
local ok, err, warn = remove.remove_other_versions(name, version, args.force, args.force_fast)
if not ok then
return nil, err
elseif warn then
util.printerr(warn)
end
end
writer.check_dependencies(nil, deps.get_deps_mode(args))
return name, version
end
end
return make

View file

@ -1,228 +0,0 @@
--- Module implementing the LuaRocks "new_version" command.
-- Utility function that writes a new rockspec, updating data from a previous one.
local new_version = {}
local util = require("luarocks.util")
local download = require("luarocks.download")
local fetch = require("luarocks.fetch")
local persist = require("luarocks.persist")
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local type_rockspec = require("luarocks.type.rockspec")
function new_version.add_to_parser(parser)
local cmd = parser:command("new_version", [[
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 no argument is given, it
looks for a rockspec same way 'luarocks make' does.
If the version number is not given and tag is passed using --tag, it is used as
the version, with 'v' removed from beginning. Otherwise, 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; if the guessed
URL is invalid, the old URL is restored. It also tries to download the new URL
to determine the new MD5 checksum.
If a tag is given, it replaces the one from the old rockspec. If there is an old
tag but no new one passed, it is guessed in the same way URL is.
If a directory is not given, it defaults to the current directory.
WARNING: it writes the new rockspec to the given directory, overwriting the file
if it already exists.]], util.see_also())
:summary("Auto-write a rockspec for a new version of a rock.")
cmd:argument("rock", "Package name or rockspec.")
:args("?")
cmd:argument("new_version", "New version of the rock.")
:args("?")
cmd:argument("new_url", "New URL of the rock.")
:args("?")
cmd:option("--dir", "Output directory for the new rockspec.")
cmd:option("--tag", "New SCM tag.")
end
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
-- Try to download source file using URL from a rockspec.
-- If it specified MD5, update it.
-- @return (true, false) if MD5 was not specified or it stayed same,
-- (true, true) if MD5 changed, (nil, string) on error.
local function check_url_and_update_md5(out_rs, invalid_is_error)
local file, temp_dir = fetch.fetch_url_at_temp_dir(out_rs.source.url, "luarocks-new-version-"..out_rs.package)
if not file then
if invalid_is_error then
return nil, "invalid URL - "..temp_dir
end
util.warning("invalid URL - "..temp_dir)
return true, false
end
local inferred_dir, found_dir = fetch.find_base_dir(file, temp_dir, out_rs.source.url, out_rs.source.dir)
if not inferred_dir then
return nil, found_dir
end
if found_dir and found_dir ~= inferred_dir then
out_rs.source.dir = found_dir
end
if file then
if out_rs.source.md5 then
util.printout("File successfully downloaded. Updating MD5 checksum...")
local new_md5, err = fs.get_md5(file)
if not new_md5 then
return nil, err
end
local old_md5 = out_rs.source.md5
out_rs.source.md5 = new_md5
return true, new_md5 ~= old_md5
else
util.printout("File successfully downloaded.")
return true, false
end
end
end
local function update_source_section(out_rs, url, tag, old_ver, new_ver)
if tag then
out_rs.source.tag = tag
end
if url then
out_rs.source.url = url
return check_url_and_update_md5(out_rs)
end
if new_ver == old_ver then
return true
end
if out_rs.source.dir then
try_replace(out_rs.source, "dir", old_ver, new_ver)
end
if out_rs.source.file then
try_replace(out_rs.source, "file", old_ver, new_ver)
end
local old_url = out_rs.source.url
if try_replace(out_rs.source, "url", old_ver, new_ver) then
local ok, md5_changed = check_url_and_update_md5(out_rs, true)
if ok then
return ok, md5_changed
end
out_rs.source.url = old_url
end
if tag or try_replace(out_rs.source, "tag", old_ver, new_ver) then
return true
end
-- Couldn't replace anything significant, use the old URL.
local ok, md5_changed = check_url_and_update_md5(out_rs)
if not ok then
return nil, md5_changed
end
if md5_changed then
util.warning("URL is the same, but MD5 has changed. Old rockspec is broken.")
end
return true
end
function new_version.command(args)
if not args.rock then
local err
args.rock, err = util.get_default_rockspec()
if not args.rock then
return nil, err
end
end
local filename, err
if args.rock:match("rockspec$") then
filename, err = fetch.fetch_url(args.rock)
if not filename then
return nil, err
end
else
filename, err = download.download("rockspec", args.rock:lower())
if not filename 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 args.tag and not args.new_version then
args.new_version = args.tag:gsub("^v", "")
end
local out_dir
if args.dir then
out_dir = dir.normalize(args.dir)
end
if args.new_version then
new_ver, new_rev = args.new_version:match("(.*)%-(%d+)$")
new_rev = tonumber(new_rev)
if not new_rev then
new_ver = args.new_version
new_rev = 1
end
else
new_ver = old_ver
new_rev = tonumber(old_rev) + 1
end
local new_rockver = new_ver:gsub("-", "")
local out_rs, err = persist.load_into_table(filename)
local out_name = out_rs.package:lower()
out_rs.version = new_rockver.."-"..new_rev
local ok, err = update_source_section(out_rs, args.new_url, args.tag, old_ver, new_ver)
if not ok then return nil, err end
if out_rs.build and out_rs.build.type == "module" then
out_rs.build.type = "builtin"
end
local out_filename = out_name.."-"..new_rockver.."-"..new_rev..".rockspec"
if out_dir then
out_filename = dir.path(out_dir, out_filename)
fs.make_dir(out_dir)
end
persist.save_from_table(out_filename, out_rs, type_rockspec.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
return new_version

View file

@ -1,36 +0,0 @@
--- Module implementing the LuaRocks "pack" command.
-- Creates a rock, packing sources or binaries.
local cmd_pack = {}
local util = require("luarocks.util")
local pack = require("luarocks.pack")
local queries = require("luarocks.queries")
function cmd_pack.add_to_parser(parser)
local cmd = parser:command("pack", "Create a rock, packing sources or binaries.", util.see_also())
cmd:argument("rock", "A rockspec file, for creating a source rock, or the "..
"name of an installed package, for creating a binary rock.")
:action(util.namespaced_name_action)
cmd:argument("version", "A version may be given if the first argument is a rock name.")
:args("?")
cmd:flag("--sign", "Produce a signature file as well.")
end
--- Driver function for the "pack" command.
-- @return boolean or (nil, string): true if successful or nil followed
-- by an error message.
function cmd_pack.command(args)
local file, err
if args.rock:match(".*%.rockspec") then
file, err = pack.pack_source_rock(args.rock)
else
local query = queries.new(args.rock, args.namespace, args.version)
file, err = pack.pack_installed_rock(query, args.tree)
end
return pack.report_and_sign_local_file(file, err, args.sign)
end
return cmd_pack

View file

@ -1,70 +0,0 @@
--- @module luarocks.path_cmd
-- Driver for the `luarocks path` command.
local path_cmd = {}
local util = require("luarocks.util")
local cfg = require("luarocks.core.cfg")
local fs = require("luarocks.fs")
function path_cmd.add_to_parser(parser)
local cmd = parser:command("path", [[
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`
And on Windows:
luarocks path > "%temp%\_lrp.bat" && call "%temp%\_lrp.bat" && del "%temp%\_lrp.bat"]],
util.see_also())
:summary("Return the currently configured package path.")
cmd:flag("--no-bin", "Do not export the PATH variable.")
cmd:flag("--append", "Appends the paths to the existing paths. Default is "..
"to prefix the LR paths to the existing paths.")
cmd:flag("--lr-path", "Exports the Lua path (not formatted as shell command).")
cmd:flag("--lr-cpath", "Exports the Lua cpath (not formatted as shell command).")
cmd:flag("--lr-bin", "Exports the system path (not formatted as shell command).")
cmd:flag("--bin"):hidden(true)
end
--- Driver function for "path" command.
-- @return boolean This function always succeeds.
function path_cmd.command(args)
local lr_path, lr_cpath, lr_bin = cfg.package_paths(args.tree)
local path_sep = cfg.export_path_separator
if args.lr_path then
util.printout(util.cleanup_path(lr_path, ';', cfg.lua_version, true))
return true
elseif args.lr_cpath then
util.printout(util.cleanup_path(lr_cpath, ';', cfg.lua_version, true))
return true
elseif args.lr_bin then
util.printout(util.cleanup_path(lr_bin, path_sep, nil, true))
return true
end
local clean_path = util.cleanup_path(os.getenv("PATH") or "", path_sep, nil, true)
if args.append then
lr_path = package.path .. ";" .. lr_path
lr_cpath = package.cpath .. ";" .. lr_cpath
lr_bin = clean_path .. path_sep .. lr_bin
else
lr_path = lr_path.. ";" .. package.path
lr_cpath = lr_cpath .. ";" .. package.cpath
lr_bin = lr_bin .. path_sep .. clean_path
end
local lpath_var, lcpath_var = util.lua_path_variables()
util.printout(fs.export_cmd(lpath_var, util.cleanup_path(lr_path, ';', cfg.lua_version, args.append)))
util.printout(fs.export_cmd(lcpath_var, util.cleanup_path(lr_cpath, ';', cfg.lua_version, args.append)))
if not args.no_bin then
util.printout(fs.export_cmd("PATH", util.cleanup_path(lr_bin, path_sep, nil, args.append)))
end
return true
end
return path_cmd

View file

@ -1,84 +0,0 @@
--- Module implementing the LuaRocks "purge" command.
-- Remove all rocks from a given tree.
local purge = {}
local util = require("luarocks.util")
local fs = require("luarocks.fs")
local path = require("luarocks.path")
local search = require("luarocks.search")
local vers = require("luarocks.core.vers")
local repos = require("luarocks.repos")
local writer = require("luarocks.manif.writer")
local cfg = require("luarocks.core.cfg")
local remove = require("luarocks.remove")
local queries = require("luarocks.queries")
local cmd = require("luarocks.cmd")
function purge.add_to_parser(parser)
-- luacheck: push ignore 431
local cmd = parser:command("purge", [[
This command removes rocks en masse from a given tree.
By default, it removes all rocks from a tree.
The --tree option is mandatory: luarocks purge does not assume a default tree.]],
util.see_also())
:summary("Remove all installed rocks from a tree.")
-- luacheck: pop
cmd:flag("--old-versions", "Keep the highest-numbered version of each "..
"rock and remove the other ones. By default it only removes old "..
"versions if they are not needed as dependencies. This can be "..
"overridden with the flag --force.")
cmd:flag("--force", "If --old-versions is specified, force removal of "..
"previously installed versions if it would break dependencies.")
cmd:flag("--force-fast", "Like --force, but performs a forced removal "..
"without reporting dependency issues.")
end
function purge.command(args)
local tree = args.tree
if type(tree) ~= "string" then
return nil, "The --tree argument is mandatory. "..util.see_help("purge")
end
local results = {}
if not fs.is_dir(tree) then
return nil, "Directory not found: "..tree
end
local ok, err = fs.check_command_permissions(args)
if not ok then return nil, err, cmd.errorcodes.PERMISSIONDENIED end
search.local_manifest_search(results, path.rocks_dir(tree), queries.all())
local sort = function(a,b) return vers.compare_versions(b,a) end
if args.old_versions then
sort = vers.compare_versions
end
for package, versions in util.sortedpairs(results) do
for version, _ in util.sortedpairs(versions, sort) do
if args.old_versions then
util.printout("Keeping "..package.." "..version.."...")
local ok, err, warn = remove.remove_other_versions(package, version, args.force, args.force_fast)
if not ok then
util.printerr(err)
elseif warn then
util.printerr(err)
end
break
else
util.printout("Removing "..package.." "..version.."...")
local ok, err = repos.delete_version(package, version, "none", true)
if not ok then
util.printerr(err)
end
end
end
end
return writer.make_manifest(cfg.rocks_dir, "one")
end
return purge

View file

@ -1,75 +0,0 @@
--- Module implementing the LuaRocks "remove" command.
-- Uninstalls rocks.
local cmd_remove = {}
local remove = require("luarocks.remove")
local util = require("luarocks.util")
local cfg = require("luarocks.core.cfg")
local fs = require("luarocks.fs")
local search = require("luarocks.search")
local path = require("luarocks.path")
local deps = require("luarocks.deps")
local writer = require("luarocks.manif.writer")
local queries = require("luarocks.queries")
local cmd = require("luarocks.cmd")
function cmd_remove.add_to_parser(parser)
-- luacheck: push ignore 431
local cmd = parser:command("remove", [[
Uninstall a rock.
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 or --force-fast.]],
util.see_also())
:summary("Uninstall a rock.")
-- luacheck: pop
cmd:argument("rock", "Name of the rock to be uninstalled.")
:action(util.namespaced_name_action)
cmd:argument("version", "Version of the rock to uninstall.")
:args("?")
cmd:flag("--force", "Force removal if it would break dependencies.")
cmd:flag("--force-fast", "Perform a forced removal without reporting dependency issues.")
util.deps_mode_option(cmd)
end
--- Driver function for the "remove" command.
-- @return boolean or (nil, string, exitcode): True if removal was
-- successful, nil and an error message otherwise. exitcode is optionally returned.
function cmd_remove.command(args)
local name = args.rock
local deps_mode = deps.get_deps_mode(args)
local ok, err = fs.check_command_permissions(args)
if not ok then return nil, err, cmd.errorcodes.PERMISSIONDENIED end
local rock_type = name:match("%.(rock)$") or name:match("%.(rockspec)$")
local version = args.version
local filename = name
if rock_type then
name, version = path.parse_name(filename)
if not name then return nil, "Invalid "..rock_type.." filename: "..filename end
end
name = name:lower()
local results = {}
search.local_manifest_search(results, cfg.rocks_dir, queries.new(name, args.namespace, version))
if not results[name] then
local rock = util.format_rock_name(name, args.namespace, version)
return nil, "Could not find rock '"..rock.."' in "..path.rocks_tree_to_string(cfg.root_dir)
end
ok, err = remove.remove_search_results(results, name, deps_mode, args.force, args.force_fast)
if not ok then
return nil, err
end
writer.check_dependencies(nil, deps.get_deps_mode(args))
return true
end
return cmd_remove

View file

@ -1,84 +0,0 @@
--- Module implementing the LuaRocks "search" command.
-- Queries LuaRocks servers.
local cmd_search = {}
local cfg = require("luarocks.core.cfg")
local util = require("luarocks.util")
local search = require("luarocks.search")
local queries = require("luarocks.queries")
local results = require("luarocks.results")
function cmd_search.add_to_parser(parser)
local cmd = parser:command("search", "Query the LuaRocks servers.", util.see_also())
cmd:argument("name", "Name of the rock to search for.")
:args("?")
:action(util.namespaced_name_action)
cmd:argument("version", "Rock version to search for.")
:args("?")
cmd:flag("--source", "Return only rockspecs and source rocks, to be used "..
'with the "build" command.')
cmd:flag("--binary", "Return only pure Lua and binary rocks (rocks that "..
'can be used with the "install" command without requiring a C toolchain).')
cmd:flag("--all", "List all contents of the server that are suitable to "..
"this platform, do not filter by name.")
cmd:flag("--porcelain", "Return a machine readable format.")
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 result_tree 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(result_tree)
local sources, binaries = {}, {}
for name, versions in pairs(result_tree) do
for version, repositories in pairs(versions) do
for _, repo in ipairs(repositories) do
local where = sources
if repo.arch == "all" or repo.arch == cfg.arch then
where = binaries
end
local entry = results.new(name, version, repo.repo, repo.arch)
search.store_result(where, entry)
end
end
end
return sources, binaries
end
--- Driver function for "search" command.
-- @return boolean or (nil, string): True if build was successful; nil and an
-- error message otherwise.
function cmd_search.command(args)
local name = args.name
if args.all then
name, args.version = "", nil
end
if not args.name and not args.all then
return nil, "Enter name and version or use --all. "..util.see_help("search")
end
local query = queries.new(name, args.namespace, args.version, true)
local result_tree, err = search.search_repos(query)
local porcelain = args.porcelain
local full_name = util.format_rock_name(name, args.namespace, args.version)
util.title(full_name .. " - Search results for Lua "..cfg.lua_version..":", porcelain, "=")
local sources, binaries = split_source_and_binary_results(result_tree)
if next(sources) and not args.binary then
util.title("Rockspecs and source rocks:", porcelain)
search.print_result_tree(sources, porcelain)
end
if next(binaries) and not args.source then
util.title("Binary and pure-Lua rocks:", porcelain)
search.print_result_tree(binaries, porcelain)
end
return true
end
return cmd_search

View file

@ -1,315 +0,0 @@
--- Module implementing the LuaRocks "show" command.
-- Shows information about an installed rock.
local show = {}
local queries = require("luarocks.queries")
local search = require("luarocks.search")
local dir = require("luarocks.core.dir")
local fs = require("luarocks.fs")
local cfg = require("luarocks.core.cfg")
local util = require("luarocks.util")
local path = require("luarocks.path")
local fetch = require("luarocks.fetch")
local manif = require("luarocks.manif")
local repos = require("luarocks.repos")
function show.add_to_parser(parser)
local cmd = parser:command("show", [[
Show information about an installed rock.
Without any flags, show all module information.
With flags, return only the desired information.]], util.see_also())
:summary("Show information about an installed rock.")
cmd:argument("rock", "Name of an installed rock.")
:action(util.namespaced_name_action)
cmd:argument("version", "Rock version.")
:args("?")
cmd:flag("--home", "Show home page of project.")
cmd:flag("--modules", "Show all modules provided by the package as used by require().")
cmd:flag("--deps", "Show packages the package depends on.")
cmd:flag("--build-deps", "Show build-only dependencies for the package.")
cmd:flag("--test-deps", "Show dependencies for testing the package.")
cmd:flag("--rockspec", "Show the full path of the rockspec file.")
cmd:flag("--mversion", "Show the package version.")
cmd:flag("--rock-tree", "Show local tree where rock is installed.")
cmd:flag("--rock-namespace", "Show rock namespace.")
cmd:flag("--rock-dir", "Show data directory of the installed rock.")
cmd:flag("--rock-license", "Show rock license.")
cmd:flag("--issues", "Show URL for project's issue tracker.")
cmd:flag("--labels", "List the labels of the rock.")
cmd:flag("--porcelain", "Produce machine-friendly output.")
end
local friendly_template = [[
:
?namespace:${namespace}/${package} ${version} - ${summary}
!namespace:${package} ${version} - ${summary}
:
*detailed :${detailed}
?detailed :
?license :License: \t${license}
?homepage :Homepage: \t${homepage}
?issues :Issues: \t${issues}
?labels :Labels: \t${labels}
?location :Installed in: \t${location}
?commands :
?commands :Commands:
*commands :\t${name} (${file})
?modules :
?modules :Modules:
*modules :\t${name} (${file})
?bdeps :
?bdeps :Has build dependency on:
*bdeps :\t${name} (${label})
?tdeps :
?tdeps :Tests depend on:
*tdeps :\t${name} (${label})
?deps :
?deps :Depends on:
*deps :\t${name} (${label})
?ideps :
?ideps :Indirectly pulling:
*ideps :\t${name} (${label})
:
]]
local porcelain_template = [[
?namespace:namespace\t${namespace}
?package :package\t${package}
?version :version\t${version}
?summary :summary\t${summary}
*detailed :detailed\t${detailed}
?license :license\t${license}
?homepage :homepage\t${homepage}
?issues :issues\t${issues}
?labels :labels\t${labels}
?location :location\t${location}
*commands :command\t${name}\t${file}
*modules :module\t${name}\t${file}
*bdeps :build_dependency\t${name}\t${label}
*tdeps :test_dependency\t${name}\t${label}
*deps :dependency\t${name}\t${label}
*ideps :indirect_dependency\t${name}\t${label}
]]
local function keys_as_string(t, sep)
local keys = util.keys(t)
table.sort(keys)
return table.concat(keys, 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
local function installed_rock_label(dep, tree)
local installed, version
local rocks_provided = util.get_rocks_provided()
if rocks_provided[dep.name] then
installed, version = true, rocks_provided[dep.name]
else
installed, version = search.pick_installed_rock(dep, tree)
end
return installed and "using "..version or "missing"
end
local function render(template, data)
local out = {}
for cmd, var, line in template:gmatch("(.)([a-z]*)%s*:([^\n]*)\n") do
line = line:gsub("\\t", "\t")
local d = data[var]
if cmd == " " then
table.insert(out, line)
elseif cmd == "?" or cmd == "*" or cmd == "!" then
if (cmd == "!" and d == nil)
or (cmd ~= "!" and (type(d) == "string"
or (type(d) == "table" and next(d)))) then
local n = cmd == "*" and #d or 1
for i = 1, n do
local tbl = cmd == "*" and d[i] or data
if type(tbl) == "string" then
tbl = tbl:gsub("%%", "%%%%")
end
table.insert(out, (line:gsub("${([a-z]+)}", tbl)))
end
end
end
end
return table.concat(out, "\n")
end
local function adjust_path(name, version, basedir, pathname, suffix)
pathname = dir.path(basedir, pathname)
local vpathname = path.versioned_name(pathname, basedir, name, version)
return (fs.exists(vpathname)
and vpathname
or pathname) .. (suffix or "")
end
local function modules_to_list(name, version, repo)
local ret = {}
local rock_manifest = manif.load_rock_manifest(name, version, repo)
local lua_dir = path.deploy_lua_dir(repo)
local lib_dir = path.deploy_lib_dir(repo)
repos.recurse_rock_manifest_entry(rock_manifest.lua, function(pathname)
table.insert(ret, {
name = path.path_to_module(pathname),
file = adjust_path(name, version, lua_dir, pathname),
})
end)
repos.recurse_rock_manifest_entry(rock_manifest.lib, function(pathname)
table.insert(ret, {
name = path.path_to_module(pathname),
file = adjust_path(name, version, lib_dir, pathname),
})
end)
table.sort(ret, function(a, b)
if a.name == b.name then
return a.file < b.file
end
return a.name < b.name
end)
return ret
end
local function commands_to_list(name, version, repo)
local ret = {}
local rock_manifest = manif.load_rock_manifest(name, version, repo)
local bin_dir = path.deploy_bin_dir(repo)
repos.recurse_rock_manifest_entry(rock_manifest.bin, function(pathname)
pathname = adjust_path(name, version, bin_dir, pathname)
table.insert(ret, {
name = pathname,
file = adjust_path(name, version, bin_dir, pathname, cfg.wrapper_suffix),
})
end)
table.sort(ret, function(a, b)
if a.name == b.name then
return a.file < b.file
end
return a.name < b.name
end)
return ret
end
local function deps_to_list(dependencies, tree)
local ret = {}
for _, dep in ipairs(dependencies or {}) do
table.insert(ret, { name = tostring(dep), label = installed_rock_label(dep, tree) })
end
return ret
end
local function indirect_deps(mdeps, rdeps, tree)
local ret = {}
local direct_deps = {}
for _, dep in ipairs(rdeps) do
direct_deps[dep] = true
end
for dep_name in util.sortedpairs(mdeps or {}) do
if not direct_deps[dep_name] then
table.insert(ret, { name = tostring(dep_name), label = installed_rock_label(queries.new(dep_name), tree) })
end
end
return ret
end
local function show_rock(template, namespace, name, version, rockspec, repo, minfo, tree)
local desc = rockspec.description or {}
local data = {
namespace = namespace,
package = rockspec.package,
version = rockspec.version,
summary = desc.summary or "",
detailed = desc.detailed and util.split_string(format_text(desc.detailed), "\n"),
license = desc.license,
homepage = desc.homepage,
issues = desc.issues_url,
labels = desc.labels and table.concat(desc.labels, ", "),
location = path.rocks_tree_to_string(repo),
commands = commands_to_list(name, version, repo),
modules = modules_to_list(name, version, repo),
bdeps = deps_to_list(rockspec.build_dependencies, tree),
tdeps = deps_to_list(rockspec.test_dependencies, tree),
deps = deps_to_list(rockspec.dependencies, tree),
ideps = indirect_deps(minfo.dependencies, rockspec.dependencies, tree),
}
util.printout(render(template, data))
end
--- Driver function for "show" command.
-- @return boolean: True if succeeded, nil on errors.
function show.command(args)
local query = queries.new(args.rock, args.namespace, args.version, true)
local name, version, repo, repo_url = search.pick_installed_rock(query, args.tree)
if not name then
return nil, version
end
local tree = path.rocks_tree_to_string(repo)
local directory = path.install_dir(name, version, repo)
local namespace = path.read_namespace(name, version, tree)
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 args.rock_tree then util.printout(tree)
elseif args.rock_namespace then util.printout(namespace)
elseif args.rock_dir then util.printout(directory)
elseif args.home then util.printout(descript.homepage)
elseif args.rock_license then util.printout(descript.license)
elseif args.issues then util.printout(descript.issues_url)
elseif args.labels then util.printout(descript.labels and table.concat(descript.labels, "\n"))
elseif args.modules then util.printout(keys_as_string(minfo.modules, "\n"))
elseif args.deps then
for _, dep in ipairs(rockspec.dependencies) do
util.printout(tostring(dep))
end
elseif args.build_deps then
for _, dep in ipairs(rockspec.build_dependencies) do
util.printout(tostring(dep))
end
elseif args.test_deps then
for _, dep in ipairs(rockspec.test_dependencies) do
util.printout(tostring(dep))
end
elseif args.rockspec then util.printout(rockspec_file)
elseif args.mversion then util.printout(version)
elseif args.porcelain then
show_rock(porcelain_template, namespace, name, version, rockspec, repo, minfo, args.tree)
else
show_rock(friendly_template, namespace, name, version, rockspec, repo, minfo, args.tree)
end
return true
end
return show

View file

@ -1,48 +0,0 @@
--- Module implementing the LuaRocks "test" command.
-- Tests a rock, compiling its C parts if any.
local cmd_test = {}
local util = require("luarocks.util")
local test = require("luarocks.test")
function cmd_test.add_to_parser(parser)
local cmd = parser:command("test", [[
Run the test suite for the Lua project in the current directory.
If the first argument is a rockspec, it will use it to determine the parameters
for running tests; otherwise, it will attempt to detect the rockspec.
Any additional arguments are forwarded to the test suite.
To make sure that test suite flags are not interpreted as LuaRocks flags, use --
to separate LuaRocks arguments from test suite arguments.]],
util.see_also())
:summary("Run the test suite in the current directory.")
cmd:argument("rockspec", "Project rockspec.")
:args("?")
cmd:argument("args", "Test suite arguments.")
:args("*")
cmd:flag("--prepare", "Only install dependencies needed for testing only, but do not run the test")
cmd:option("--test-type", "Specify the test suite type manually if it was "..
"not specified in the rockspec and it could not be auto-detected.")
:argname("<type>")
end
function cmd_test.command(args)
if args.rockspec and args.rockspec:match("rockspec$") then
return test.run_test_suite(args.rockspec, args.test_type, args.args, args.prepare)
end
table.insert(args.args, 1, args.rockspec)
local rockspec, err = util.get_default_rockspec()
if not rockspec then
return nil, err
end
return test.run_test_suite(rockspec, args.test_type, args.args, args.prepare)
end
return cmd_test

View file

@ -1,168 +0,0 @@
--- Module implementing the LuaRocks "unpack" command.
-- Unpack the contents of a rock.
local unpack = {}
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")
local search = require("luarocks.search")
function unpack.add_to_parser(parser)
local cmd = parser:command("unpack", [[
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 rock version may be given as a second argument.]],
util.see_also())
:summary("Unpack the contents of a rock.")
cmd:argument("rock", "A rock file or the name of a rock.")
:action(util.namespaced_name_action)
cmd:argument("version", "Rock version.")
:args("?")
cmd:flag("--force", "Unpack files even if the output directory already exists.")
cmd:flag("--check-lua-versions", "If the rock can't be found, check repository "..
"and report if it is available for another Lua version.")
end
--- 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
local ok, err = fs.change_dir(dir_name)
if not ok then return nil, err end
local ok, sources_dir = fetch.fetch_sources(rockspec, true, ".")
if not ok then
return nil, sources_dir
end
ok, err = fs.change_dir(sources_dir)
if not ok then return nil, err end
ok, err = build.apply_patches(rockspec)
fs.pop_dir()
if not ok then return nil, err end
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, err, errcode
end
ok, err = fs.change_dir(dir_name)
if not ok then return nil, err end
local rockspec_file = dir_name..".rockspec"
local rockspec, err = fetch.load_rockspec(rockspec_file)
if not rockspec then
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
ok, err = fs.change_dir(rockspec.source.dir)
if not ok then return nil, err end
ok, err = build.apply_patches(rockspec)
fs.pop_dir()
if not ok then return nil, err end
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, force)
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
local exists = fs.exists(dir_name)
if exists and not force then
return nil, "Directory "..dir_name.." already exists."
end
if not exists then
local ok, err = fs.make_dir(dir_name)
if not ok then return nil, err end
end
local rollback = util.schedule_function(fs.delete, fs.absolute_name(dir_name))
local rockspec, err
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_abs_filename, rockspec.source.dir, "read")
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.
-- @return boolean or (nil, string): true if successful or nil followed
-- by an error message.
function unpack.command(args)
local url, err
if args.rock:match(".*%.rock") or args.rock:match(".*%.rockspec") then
url = args.rock
else
url, err = search.find_src_or_rockspec(args.rock, args.namespace, args.version, args.check_lua_versions)
if not url then
return nil, err
end
end
return run_unpacker(url, args.force)
end
return unpack

View file

@ -1,128 +0,0 @@
local upload = {}
local signing = require("luarocks.signing")
local util = require("luarocks.util")
local fetch = require("luarocks.fetch")
local pack = require("luarocks.pack")
local cfg = require("luarocks.core.cfg")
local Api = require("luarocks.upload.api")
function upload.add_to_parser(parser)
local cmd = parser:command("upload", "Pack a source rock file (.src.rock extension) "..
"and upload it and the rockspec to the public rocks repository.", util.see_also())
:summary("Upload a rockspec to the public rocks repository.")
cmd:argument("rockspec", "Rockspec for the rock to upload.")
cmd:argument("src-rock", "A corresponding .src.rock file; if not given it will be generated.")
:args("?")
cmd:flag("--skip-pack", "Do not pack and send source rock.")
cmd:option("--api-key", "Pass an API key. It will be stored for subsequent uses.")
:argname("<key>")
cmd:option("--temp-key", "Use the given a temporary API key in this "..
"invocation only. It will not be stored.")
:argname("<key>")
cmd:flag("--force", "Replace existing rockspec if the same revision of a "..
"module already exists. This should be used only in case of upload "..
"mistakes: when updating a rockspec, increment the revision number "..
"instead.")
cmd:flag("--sign", "Upload a signature file alongside each file as well.")
cmd:flag("--debug"):hidden(true)
end
local function is_dev_version(version)
return version:match("^dev") or version:match("^scm")
end
function upload.command(args)
local api, err = Api.new(args)
if not api then
return nil, err
end
if cfg.verbose then
api.debug = true
end
local rockspec, err, errcode = fetch.load_rockspec(args.rockspec)
if err then
return nil, err, errcode
end
util.printout("Sending " .. tostring(args.rockspec) .. " ...")
local res, err = api:method("check_rockspec", {
package = rockspec.package,
version = rockspec.version
})
if not res then return nil, err end
if not res.module then
util.printout("Will create new module (" .. tostring(rockspec.package) .. ")")
end
if res.version and not args.force then
return nil, "Revision "..rockspec.version.." already exists on the server. "..util.see_help("upload")
end
local sigfname
local rock_sigfname
if args.sign then
sigfname, err = signing.sign_file(args.rockspec)
if err then
return nil, "Failed signing rockspec: " .. err
end
util.printout("Signed rockspec: "..sigfname)
end
local rock_fname
if args.src_rock then
rock_fname = args.src_rock
elseif not args.skip_pack and not is_dev_version(rockspec.version) then
util.printout("Packing " .. tostring(rockspec.package))
rock_fname, err = pack.pack_source_rock(args.rockspec)
if not rock_fname then
return nil, err
end
end
if rock_fname and args.sign then
rock_sigfname, err = signing.sign_file(rock_fname)
if err then
return nil, "Failed signing rock: " .. err
end
util.printout("Signed packed rock: "..rock_sigfname)
end
local multipart = require("luarocks.upload.multipart")
res, err = api:method("upload", nil, {
rockspec_file = multipart.new_file(args.rockspec),
rockspec_sig = sigfname and multipart.new_file(sigfname),
})
if not res then return nil, err end
if res.is_new and #res.manifests == 0 then
util.printerr("Warning: module not added to root manifest due to name taken.")
end
local module_url = res.module_url
if rock_fname then
if (not res.version) or (not res.version.id) then
return nil, "Invalid response from server."
end
util.printout(("Sending " .. tostring(rock_fname) .. " ..."))
res, err = api:method("upload_rock/" .. ("%d"):format(res.version.id), nil, {
rock_file = multipart.new_file(rock_fname),
rock_sig = rock_sigfname and multipart.new_file(rock_sigfname),
})
if not res then return nil, err end
end
util.printout()
util.printout("Done: " .. tostring(module_url))
util.printout()
return true
end
return upload

View file

@ -1,48 +0,0 @@
--- @module luarocks.which_cmd
-- Driver for the `luarocks which` command.
local which_cmd = {}
local loader = require("luarocks.loader")
local cfg = require("luarocks.core.cfg")
local util = require("luarocks.util")
local fs = require("luarocks.fs")
function which_cmd.add_to_parser(parser)
local cmd = parser:command("which", 'Given a module name like "foo.bar", '..
"output which file would be loaded to resolve that module by "..
'luarocks.loader, like "/usr/local/lua/'..cfg.lua_version..'/foo/bar.lua".',
util.see_also())
:summary("Tell which file corresponds to a given module name.")
cmd:argument("modname", "Module name.")
end
--- Driver function for "which" command.
-- @return boolean This function terminates the interpreter.
function which_cmd.command(args)
local pathname, rock_name, rock_version = loader.which(args.modname)
if pathname then
util.printout(pathname)
util.printout("(provided by " .. tostring(rock_name) .. " " .. tostring(rock_version) .. ")")
return true
end
local modpath = args.modname:gsub("%.", "/")
for _, v in ipairs({"path", "cpath"}) do
for p in package[v]:gmatch("([^;]+)") do
local pathname = p:gsub("%?", modpath) -- luacheck: ignore 421
if fs.exists(pathname) then
util.printout(pathname)
util.printout("(found directly via package." .. v .. " -- not installed as a rock?)")
return true
end
end
end
return nil, "Module '" .. args.modname .. "' not found."
end
return which_cmd

View file

@ -1,408 +0,0 @@
local write_rockspec = {}
local builtin = require("luarocks.build.builtin")
local cfg = require("luarocks.core.cfg")
local dir = require("luarocks.dir")
local fetch = require("luarocks.fetch")
local fs = require("luarocks.fs")
local persist = require("luarocks.persist")
local rockspecs = require("luarocks.rockspecs")
local type_rockspec = require("luarocks.type.rockspec")
local util = require("luarocks.util")
local lua_versions = {
"5.1",
"5.2",
"5.3",
"5.4",
"5.1,5.2",
"5.2,5.3",
"5.3,5.4",
"5.1,5.2,5.3",
"5.2,5.3,5.4",
"5.1,5.2,5.3,5.4"
}
function write_rockspec.cmd_options(parser)
return parser:option("--output", "Write the rockspec with the given filename.\n"..
"If not given, a file is written in the current directory with a "..
"filename based on given name and version.")
:argname("<file>"),
parser:option("--license", 'A license string, such as "MIT/X11" or "GNU GPL v3".')
:argname("<string>"),
parser:option("--summary", "A short one-line description summary.")
:argname("<txt>"),
parser:option("--detailed", "A longer description string.")
:argname("<txt>"),
parser:option("--homepage", "Project homepage.")
:argname("<txt>"),
parser:option("--lua-versions", 'Supported Lua versions. Accepted values are: "'..
table.concat(lua_versions, '", "')..'".')
:argname("<ver>")
:choices(lua_versions),
parser:option("--rockspec-format", 'Rockspec format version, such as "1.0" or "1.1".')
:argname("<ver>"),
parser:option("--tag", "Tag to use. Will attempt to extract version number from it."),
parser:option("--lib", "A comma-separated list of libraries that C files need to link to.")
:argname("<libs>")
end
function write_rockspec.add_to_parser(parser)
local cmd = parser:command("write_rockspec", [[
This command writes an initial version of a rockspec file,
based on a name, a version, and a location (an URL or a local path).
If only two arguments are given, the first one is considered the name and the
second one is the location.
If only one argument is given, it must be the location.
If no arguments are given, current directory is used as the location.
LuaRocks will attempt to infer name and version if not given,
using 'dev' as a fallback default version.
Note that the generated file is a _starting point_ for writing a
rockspec, and is not guaranteed to be complete or correct. ]], util.see_also())
:summary("Write a template for a rockspec file.")
cmd:argument("name", "Name of the rock.")
:args("?")
cmd:argument("version", "Rock version.")
:args("?")
cmd:argument("location", "URL or path to the rock sources.")
:args("?")
write_rockspec.cmd_options(cmd)
end
local function open_file(name)
return io.open(dir.path(fs.current_dir(), name), "r")
end
local function fetch_url(rockspec)
local file, temp_dir, err_code, err_file, err_temp_dir = fetch.fetch_sources(rockspec, false)
if err_code == "source.dir" then
file, temp_dir = err_file, err_temp_dir
elseif not file then
util.warning("Could not fetch sources - "..temp_dir)
return false
end
util.printout("File successfully downloaded. Making checksum and checking base dir...")
if dir.is_basic_protocol(rockspec.source.protocol) then
rockspec.source.md5 = fs.get_md5(file)
end
local inferred_dir, found_dir = fetch.find_base_dir(file, temp_dir, rockspec.source.url)
return true, found_dir or inferred_dir, temp_dir
end
local lua_version_dep = {
["5.1"] = "lua ~> 5.1",
["5.2"] = "lua ~> 5.2",
["5.3"] = "lua ~> 5.3",
["5.4"] = "lua ~> 5.4",
["5.1,5.2"] = "lua >= 5.1, < 5.3",
["5.2,5.3"] = "lua >= 5.2, < 5.4",
["5.3,5.4"] = "lua >= 5.3, < 5.5",
["5.1,5.2,5.3"] = "lua >= 5.1, < 5.4",
["5.2,5.3,5.4"] = "lua >= 5.2, < 5.5",
["5.1,5.2,5.3,5.4"] = "lua >= 5.1, < 5.5",
}
local simple_scm_protocols = {
git = true,
["git+http"] = true,
["git+https"] = true,
["git+ssh"] = true,
hg = true,
["hg+http"] = true,
["hg+https"] = true,
["hg+ssh"] = true,
}
local detect_url
do
local function detect_url_from_command(program, args, directory)
local command = fs.Q(cfg.variables[program:upper()]).. " "..args
local pipe = io.popen(fs.command_at(directory, fs.quiet_stderr(command)))
if not pipe then return nil end
local url = pipe:read("*a"):match("^([^\r\n]+)")
pipe:close()
if not url then return nil end
if url:match("^[^@:/]+@[^@:/]+:.*$") then
local u, h, p = url:match("^([^@]+)@([^:]+):(.*)$")
url = program.."+ssh://"..u.."@"..h.."/"..p
elseif not util.starts_with(url, program.."://") then
url = program.."+"..url
end
if simple_scm_protocols[dir.split_url(url)] then
return url
end
end
local function detect_scm_url(directory)
return detect_url_from_command("git", "config --get remote.origin.url", directory) or
detect_url_from_command("hg", "paths default", directory)
end
detect_url = function(url_or_dir)
if url_or_dir:match("://") then
return url_or_dir
else
return detect_scm_url(url_or_dir) or "*** please add URL for source tarball, zip or repository here ***"
end
end
end
local function detect_homepage(url, homepage)
if homepage then
return homepage
end
local url_protocol, url_path = dir.split_url(url)
if simple_scm_protocols[url_protocol] then
for _, domain in ipairs({"github.com", "bitbucket.org", "gitlab.com"}) do
if util.starts_with(url_path, domain) then
return "https://"..url_path:gsub("%.git$", "")
end
end
end
return "*** please enter a project homepage ***"
end
local function detect_description()
local fd = open_file("README.md") or open_file("README")
if not fd then return end
local data = fd:read("*a")
fd:close()
local paragraph = data:match("\n\n([^%[].-)\n\n")
if not paragraph then paragraph = data:match("\n\n(.*)") end
local summary, detailed
if paragraph then
detailed = paragraph
if #paragraph < 80 then
summary = paragraph:gsub("\n", "")
else
summary = paragraph:gsub("\n", " "):match("([^.]*%.) ")
end
end
return summary, detailed
end
local licenses = {
[78656] = "MIT",
[49311] = "ISC",
}
local function detect_license(data)
local strip_copyright = (data:gsub("^Copyright [^\n]*\n", ""))
local sum = 0
for i = 1, #strip_copyright do
local num = string.byte(strip_copyright:sub(i,i))
if num > 32 and num <= 128 then
sum = sum + num
end
end
return licenses[sum]
end
local function check_license()
local fd = open_file("COPYING") or open_file("LICENSE") or open_file("MIT-LICENSE.txt")
if not fd then return nil end
local data = fd:read("*a")
fd:close()
local license = detect_license(data)
if license then
return license, data
end
return nil, data
end
local function fill_as_builtin(rockspec, libs)
rockspec.build.type = "builtin"
local incdirs, libdirs
if libs then
incdirs, libdirs = {}, {}
for _, lib in ipairs(libs) do
local upper = lib:upper()
incdirs[#incdirs+1] = "$("..upper.."_INCDIR)"
libdirs[#libdirs+1] = "$("..upper.."_LIBDIR)"
end
end
rockspec.build.modules, rockspec.build.install, rockspec.build.copy_directories = builtin.autodetect_modules(libs, incdirs, libdirs)
end
local function rockspec_cleanup(rockspec)
rockspec.source.file = nil
rockspec.source.protocol = nil
rockspec.source.identifier = nil
rockspec.source.dir = nil
rockspec.source.dir_set = nil
rockspec.source.pathname = nil
rockspec.variables = nil
rockspec.name = nil
rockspec.format_is_at_least = nil
rockspec.local_abs_filename = nil
rockspec.rocks_provided = nil
for _, list in ipairs({"dependencies", "build_dependencies", "test_dependencies"}) do
if rockspec[list] and not next(rockspec[list]) then
rockspec[list] = nil
end
end
for _, list in ipairs({"dependencies", "build_dependencies", "test_dependencies"}) do
if rockspec[list] then
for i, entry in ipairs(rockspec[list]) do
rockspec[list][i] = tostring(entry)
end
end
end
end
function write_rockspec.command(args)
local name, version = args.name, args.version
local location = args.location
if not name then
location = "."
elseif not version then
location = name
name = nil
elseif not location then
location = version
version = nil
end
if args.tag then
if not version then
version = args.tag:gsub("^v", "")
end
end
local protocol, pathname = dir.split_url(location)
if protocol == "file" then
if pathname == "." then
name = name or dir.base_name(fs.current_dir())
end
elseif dir.is_basic_protocol(protocol) then
local filename = dir.base_name(location)
local newname, newversion = filename:match("(.*)-([^-]+)")
if newname then
name = name or newname
version = version or newversion:gsub("%.[a-z]+$", ""):gsub("%.tar$", "")
end
else
name = name or dir.base_name(location):gsub("%.[^.]+$", "")
end
if not name then
return nil, "Could not infer rock name. "..util.see_help("write_rockspec")
end
version = version or "dev"
local filename = args.output or dir.path(fs.current_dir(), name:lower().."-"..version.."-1.rockspec")
local url = detect_url(location)
local homepage = detect_homepage(url, args.homepage)
local rockspec, err = rockspecs.from_persisted_table(filename, {
rockspec_format = args.rockspec_format,
package = name,
version = version.."-1",
source = {
url = url,
tag = args.tag,
},
description = {
summary = args.summary or "*** please specify description summary ***",
detailed = args.detailed or "*** please enter a detailed description ***",
homepage = homepage,
license = args.license or "*** please specify a license ***",
},
dependencies = {
lua_version_dep[args.lua_versions],
},
build = {},
})
assert(not err, err)
rockspec.source.protocol = protocol
if not next(rockspec.dependencies) then
util.warning("Please specify supported Lua versions with --lua-versions=<ver>. "..util.see_help("write_rockspec"))
end
local local_dir = location
if location:match("://") then
rockspec.source.file = dir.base_name(location)
if not dir.is_basic_protocol(rockspec.source.protocol) then
if version ~= "dev" then
rockspec.source.tag = args.tag or "v" .. version
end
end
rockspec.source.dir = nil
local ok, base_dir, temp_dir = fetch_url(rockspec)
if ok then
if base_dir ~= dir.base_name(location) then
rockspec.source.dir = base_dir
end
end
if base_dir then
local_dir = dir.path(temp_dir, base_dir)
else
local_dir = nil
end
end
if not local_dir then
local_dir = "."
end
local libs = nil
if args.lib then
libs = {}
rockspec.external_dependencies = {}
for lib in args.lib:gmatch("([^,]+)") do
table.insert(libs, lib)
rockspec.external_dependencies[lib:upper()] = {
library = lib
}
end
end
local ok, err = fs.change_dir(local_dir)
if not ok then return nil, "Failed reaching files from project - error entering directory "..local_dir end
if not (args.summary and args.detailed) then
local summary, detailed = detect_description()
rockspec.description.summary = args.summary or summary
rockspec.description.detailed = args.detailed or detailed
end
if not args.license then
local license, fulltext = check_license()
if license then
rockspec.description.license = license
elseif license then
util.title("Could not auto-detect type for project license:")
util.printout(fulltext)
util.printout()
util.title("Please fill in the source.license field manually or use --license.")
end
end
fill_as_builtin(rockspec, libs)
rockspec_cleanup(rockspec)
persist.save_from_table(filename, rockspec, type_rockspec.order)
util.printout()
util.printout("Wrote template at "..filename.." -- you should now edit and finish it.")
util.printout()
return true
end
return write_rockspec

View file

@ -1,878 +0,0 @@
--- Configuration for LuaRocks.
-- Tries to load the user's configuration file and
-- defines defaults for unset values. See the
-- <a href="http://luarocks.org/en/Config_file_format">config
-- file format documentation</a> for details.
--
-- End-users shouldn't edit this file. They can override any defaults
-- set in this file using their system-wide or user-specific configuration
-- files. Run `luarocks` with no arguments to see the locations of
-- these files in your platform.
local table, pairs, require, os, pcall, ipairs, package, type, assert =
table, pairs, require, os, pcall, ipairs, package, type, assert
local util = require("luarocks.core.util")
local persist = require("luarocks.core.persist")
local sysdetect = require("luarocks.core.sysdetect")
local vers = require("luarocks.core.vers")
--------------------------------------------------------------------------------
local program_version = "3.8.0"
local program_series = "3.8"
local major_version = (program_version:match("([^.]%.[^.])")) or program_series
local is_windows = package.config:sub(1,1) == "\\"
-- Set order for platform overrides.
-- More general platform identifiers should be listed first,
-- more specific ones later.
local platform_order = {
-- Unixes
"unix",
"bsd",
"solaris",
"netbsd",
"openbsd",
"freebsd",
"linux",
"macosx",
"cygwin",
"msys",
"haiku",
-- Windows
"windows",
"win32",
"mingw32",
"msys2_mingw_w64",
}
local function detect_sysconfdir()
if not debug then
return
end
local src = debug.getinfo(1, "S").source:gsub("\\", "/"):gsub("/+", "/")
if src:sub(1, 1) == "@" then
src = src:sub(2)
end
local basedir = src:match("^(.*)/luarocks/core/cfg.lua$")
if not basedir then
return
end
-- If installed in a Unix-like tree, use a Unix-like sysconfdir
local installdir = basedir:match("^(.*)/share/lua/[^/]*$")
if installdir then
if installdir == "/usr" then
return "/etc/luarocks"
end
return installdir .. "/etc/luarocks"
end
-- Otherwise, use base directory of sources
return basedir
end
local load_config_file
do
-- Create global environment for the config files;
local function env_for_config_file(cfg, platforms)
local e
e = {
home = cfg.home,
lua_version = cfg.lua_version,
platforms = util.make_shallow_copy(platforms),
processor = cfg.target_cpu, -- remains for compat reasons
target_cpu = cfg.target_cpu, -- replaces `processor`
os_getenv = os.getenv,
variables = cfg.variables or {},
dump_env = function()
-- debug function, calling it from a config file will show all
-- available globals to that config file
print(util.show_table(e, "global environment"))
end,
}
return e
end
-- Merge values from config files read into the `cfg` table
local function merge_overrides(cfg, overrides)
-- remove some stuff we do not want to integrate
overrides.os_getenv = nil
overrides.dump_env = nil
-- remove tables to be copied verbatim instead of deeply merged
if overrides.rocks_trees then cfg.rocks_trees = nil end
if overrides.rocks_servers then cfg.rocks_servers = nil end
-- perform actual merge
util.deep_merge(cfg, overrides)
end
local function update_platforms(platforms, overrides)
if overrides[1] then
for k, _ in pairs(platforms) do
platforms[k] = nil
end
for _, v in ipairs(overrides) do
platforms[v] = true
end
-- set some fallback default in case the user provides an incomplete configuration.
-- LuaRocks expects a set of defaults to be available.
if not (platforms.unix or platforms.windows) then
platforms[is_windows and "windows" or "unix"] = true
end
end
end
-- Load config file and merge its contents into the `cfg` module table.
-- @return filepath of successfully loaded file or nil if it failed
load_config_file = function(cfg, platforms, filepath)
local result, err, errcode = persist.load_into_table(filepath, env_for_config_file(cfg, platforms))
if (not result) and errcode ~= "open" then
-- errcode is either "load" or "run"; bad config file, so error out
return nil, err, "config"
end
if result then
-- success in loading and running, merge contents and exit
update_platforms(platforms, result.platforms)
result.platforms = nil
merge_overrides(cfg, result)
return filepath
end
return nil -- nothing was loaded
end
end
local platform_sets = {
freebsd = { unix = true, bsd = true, freebsd = true },
openbsd = { unix = true, bsd = true, openbsd = true },
solaris = { unix = true, solaris = true },
windows = { windows = true, win32 = true },
cygwin = { unix = true, cygwin = true },
macosx = { unix = true, bsd = true, macosx = true, macos = true },
netbsd = { unix = true, bsd = true, netbsd = true },
haiku = { unix = true, haiku = true },
linux = { unix = true, linux = true },
mingw = { windows = true, win32 = true, mingw32 = true, mingw = true },
msys = { unix = true, cygwin = true, msys = true },
msys2_mingw_w64 = { windows = true, win32 = true, mingw32 = true, mingw = true, msys = true, msys2_mingw_w64 = true },
}
local function make_platforms(system)
-- fallback to Unix in unknown systems
return platform_sets[system] or { unix = true }
end
--------------------------------------------------------------------------------
local function make_defaults(lua_version, target_cpu, platforms, home)
-- Configure defaults:
local defaults = {
lua_interpreter = "lua",
local_by_default = false,
accept_unknown_fields = false,
fs_use_modules = true,
hooks_enabled = true,
deps_mode = "one",
no_manifest = false,
check_certificates = false,
cache_timeout = 60,
cache_fail_timeout = 86400,
lua_modules_path = "/share/lua/"..lua_version,
lib_modules_path = "/lib/lua/"..lua_version,
rocks_subdir = "/lib/luarocks/rocks-"..lua_version,
arch = "unknown",
lib_extension = "unknown",
obj_extension = "unknown",
link_lua_explicitly = false,
rocks_servers = {
{
"https://luarocks.org",
"https://raw.githubusercontent.com/rocks-moonscript-org/moonrocks-mirror/master/",
"https://luafr.org/luarocks/",
"http://luarocks.logiceditor.com/rocks",
}
},
disabled_servers = {},
upload = {
server = "https://luarocks.org",
tool_version = "1.0.0",
api_version = "1",
},
lua_extension = "lua",
connection_timeout = 30, -- 0 = no timeout
variables = {
MAKE = "make",
CC = "cc",
LD = "ld",
AR = "ar",
RANLIB = "ranlib",
CVS = "cvs",
GIT = "git",
SSCM = "sscm",
SVN = "svn",
HG = "hg",
GPG = "gpg",
RSYNC = "rsync",
WGET = "wget",
SCP = "scp",
CURL = "curl",
PWD = "pwd",
MKDIR = "mkdir",
RMDIR = "rmdir",
CP = "cp",
LS = "ls",
RM = "rm",
FIND = "find",
CHMOD = "chmod",
ICACLS = "icacls",
MKTEMP = "mktemp",
ZIP = "zip",
UNZIP = "unzip -n",
GUNZIP = "gunzip",
BUNZIP2 = "bunzip2",
TAR = "tar",
MD5SUM = "md5sum",
OPENSSL = "openssl",
MD5 = "md5",
TOUCH = "touch",
CMAKE = "cmake",
SEVENZ = "7z",
RSYNCFLAGS = "--exclude=.git -Oavz",
CURLNOCERTFLAG = "",
WGETNOCERTFLAG = "",
},
external_deps_subdirs = {
bin = "bin",
lib = "lib",
include = "include"
},
runtime_external_deps_subdirs = {
bin = "bin",
lib = "lib",
include = "include"
},
}
if platforms.windows then
defaults.arch = "win32-"..target_cpu
defaults.lib_extension = "dll"
defaults.external_lib_extension = "dll"
defaults.static_lib_extension = "lib"
defaults.obj_extension = "obj"
defaults.external_deps_dirs = { "c:/external/", "c:/windows/system32" }
defaults.makefile = "Makefile.win"
defaults.variables.MAKE = "nmake"
defaults.variables.CC = "cl"
defaults.variables.RC = "rc"
defaults.variables.LD = "link"
defaults.variables.MT = "mt"
defaults.variables.AR = "lib"
defaults.variables.LUALIB = "lua"..lua_version..".lib"
defaults.variables.CFLAGS = "/nologo /MD /O2"
defaults.variables.LIBFLAG = "/nologo /dll"
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_path_separator = ";"
defaults.wrapper_suffix = ".bat"
local localappdata = os.getenv("LOCALAPPDATA")
if not localappdata then
-- for Windows versions below Vista
localappdata = (os.getenv("USERPROFILE") or "c:/Users/All Users").."/Local Settings/Application Data"
end
defaults.local_cache = localappdata.."/LuaRocks/Cache"
defaults.web_browser = "start"
defaults.external_deps_subdirs.lib = { "", "lib", "bin" }
defaults.runtime_external_deps_subdirs.lib = { "", "lib", "bin" }
defaults.link_lua_explicitly = true
defaults.fs_use_modules = false
end
if platforms.mingw32 then
defaults.obj_extension = "o"
defaults.static_lib_extension = "a"
defaults.external_deps_dirs = { "c:/external/", "c:/mingw", "c:/windows/system32" }
defaults.cmake_generator = "MinGW Makefiles"
defaults.variables.MAKE = "mingw32-make"
defaults.variables.CC = "mingw32-gcc"
defaults.variables.RC = "windres"
defaults.variables.LD = "mingw32-gcc"
defaults.variables.AR = "ar"
defaults.variables.RANLIB = "ranlib"
defaults.variables.CFLAGS = "-O2"
defaults.variables.LIBFLAG = "-shared"
defaults.makefile = "Makefile"
defaults.external_deps_patterns = {
bin = { "?.exe", "?.bat" },
-- mingw lookup list from http://stackoverflow.com/a/15853231/1793220
-- ...should we keep ?.lib at the end? It's not in the above list.
lib = { "lib?.dll.a", "?.dll.a", "lib?.a", "cyg?.dll", "lib?.dll", "?.dll", "?.lib" },
include = { "?.h" }
}
defaults.runtime_external_deps_patterns = {
bin = { "?.exe", "?.bat" },
lib = { "cyg?.dll", "?.dll", "lib?.dll" },
include = { "?.h" }
}
defaults.link_lua_explicitly = true
end
if platforms.unix then
defaults.lib_extension = "so"
defaults.static_lib_extension = "a"
defaults.external_lib_extension = "so"
defaults.obj_extension = "o"
defaults.external_deps_dirs = { "/usr/local", "/usr", "/" }
defaults.variables.CFLAGS = "-O2"
defaults.cmake_generator = "Unix Makefiles"
defaults.variables.CC = "gcc"
defaults.variables.LD = "gcc"
defaults.gcc_rpath = true
defaults.variables.LIBFLAG = "-shared"
defaults.variables.TEST = "test"
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_path_separator = ":"
defaults.wrapper_suffix = ""
local xdg_cache_home = os.getenv("XDG_CACHE_HOME") or home.."/.cache"
defaults.local_cache = xdg_cache_home.."/luarocks"
if not defaults.variables.CFLAGS:match("-fPIC") then
defaults.variables.CFLAGS = defaults.variables.CFLAGS.." -fPIC"
end
defaults.web_browser = "xdg-open"
end
if platforms.cygwin then
defaults.lib_extension = "so" -- can be overridden in the config file for mingw builds
defaults.arch = "cygwin-"..target_cpu
defaults.cmake_generator = "Unix Makefiles"
defaults.variables.CC = "echo -llua | xargs gcc"
defaults.variables.LD = "echo -llua | xargs gcc"
defaults.variables.LIBFLAG = "-shared"
defaults.link_lua_explicitly = true
end
if platforms.msys then
-- msys is basically cygwin made out of mingw, meaning the subsytem is unixish
-- enough, yet we can freely mix with native win32
defaults.external_deps_patterns = {
bin = { "?.exe", "?.bat", "?" },
lib = { "lib?.so", "lib?.so.*", "lib?.dll.a", "?.dll.a",
"lib?.a", "lib?.dll", "?.dll", "?.lib" },
include = { "?.h" }
}
defaults.runtime_external_deps_patterns = {
bin = { "?.exe", "?.bat" },
lib = { "lib?.so", "?.dll", "lib?.dll" },
include = { "?.h" }
}
if platforms.mingw then
-- MSYS2 can build Windows programs that depend on
-- msys-2.0.dll (based on Cygwin) but MSYS2 is also designed
-- for building native Windows programs by MinGW. These
-- programs don't depend on msys-2.0.dll.
local pipe = io.popen("cygpath --windows %MINGW_PREFIX%")
local mingw_prefix = pipe:read("*l")
pipe:close()
defaults.external_deps_dirs = { mingw_prefix, "c:/windows/system32" }
defaults.makefile = "Makefile"
defaults.cmake_generator = "MSYS Makefiles"
defaults.local_cache = home.."/.cache/luarocks"
defaults.variables.MAKE = "make"
defaults.variables.CC = "gcc"
defaults.variables.RC = "windres"
defaults.variables.LD = "gcc"
defaults.variables.MT = nil
defaults.variables.AR = "ar"
defaults.variables.RANLIB = "ranlib"
defaults.variables.LUALIB = "liblua"..lua_version..".dll.a"
defaults.variables.CFLAGS = "-O2 -fPIC"
defaults.variables.LIBFLAG = "-shared"
end
end
if platforms.bsd then
defaults.variables.MAKE = "gmake"
end
if platforms.macosx then
defaults.variables.MAKE = "make"
defaults.external_lib_extension = "dylib"
defaults.arch = "macosx-"..target_cpu
defaults.variables.LIBFLAG = "-bundle -undefined dynamic_lookup -all_load"
local version = util.popen_read("sw_vers -productVersion")
if not (version:match("^%d+%.%d+%.%d+$") or version:match("^%d+%.%d+$")) then
version = "10.3"
end
version = vers.parse_version(version)
if version >= vers.parse_version("10.10") then
version = vers.parse_version("10.8")
elseif version >= vers.parse_version("10.5") then
version = vers.parse_version("10.5")
else
defaults.gcc_rpath = false
end
defaults.variables.CC = "env MACOSX_DEPLOYMENT_TARGET="..tostring(version).." gcc"
defaults.variables.LD = "env MACOSX_DEPLOYMENT_TARGET="..tostring(version).." gcc"
defaults.web_browser = "open"
end
if platforms.linux then
defaults.arch = "linux-"..target_cpu
local gcc_arch = util.popen_read("gcc -print-multiarch 2>/dev/null")
if gcc_arch and gcc_arch ~= "" then
defaults.external_deps_subdirs.lib = { "lib", "lib/" .. gcc_arch, "lib64" }
defaults.runtime_external_deps_subdirs.lib = { "lib", "lib/" .. gcc_arch, "lib64" }
else
defaults.external_deps_subdirs.lib = { "lib", "lib64" }
defaults.runtime_external_deps_subdirs.lib = { "lib", "lib64" }
end
end
if platforms.freebsd then
defaults.arch = "freebsd-"..target_cpu
defaults.gcc_rpath = false
defaults.variables.CC = os.getenv("CC") or "cc"
defaults.variables.CFLAGS = os.getenv("CFLAGS") or defaults.variables.CFLAGS
defaults.variables.LD = defaults.variables.CC
defaults.variables.LIBFLAG = (os.getenv("LDFLAGS") or "").." -shared"
end
if platforms.openbsd then
defaults.arch = "openbsd-"..target_cpu
defaults.gcc_rpath = false
defaults.variables.CC = os.getenv("CC") or "cc"
defaults.variables.CFLAGS = os.getenv("CFLAGS") or defaults.variables.CFLAGS
defaults.variables.LD = defaults.variables.CC
defaults.variables.LIBFLAG = (os.getenv("LDFLAGS") or "").." -shared"
end
if platforms.netbsd then
defaults.arch = "netbsd-"..target_cpu
end
if platforms.solaris then
defaults.arch = "solaris-"..target_cpu
--defaults.platforms = {"unix", "solaris"}
defaults.variables.MAKE = "gmake"
end
-- Expose some more values detected by LuaRocks for use by rockspec authors.
defaults.variables.LIB_EXTENSION = defaults.lib_extension
defaults.variables.OBJ_EXTENSION = defaults.obj_extension
return defaults
end
local function use_defaults(cfg, defaults)
-- Populate variables with values from their 'defaults' counterparts
-- if they were not already set by user.
if not cfg.variables then
cfg.variables = {}
end
for k,v in pairs(defaults.variables) do
if not cfg.variables[k] then
cfg.variables[k] = v
end
end
util.deep_merge_under(cfg, defaults)
-- FIXME get rid of this
if not cfg.check_certificates then
cfg.variables.CURLNOCERTFLAG = "-k"
cfg.variables.WGETNOCERTFLAG = "--no-check-certificate"
end
end
local function get_first_arg()
if not arg then
return
end
local first_arg = arg[0]
local i = -1
while arg[i] do
first_arg = arg[i]
i = i -1
end
return first_arg
end
--------------------------------------------------------------------------------
local cfg = {}
--- Initializes the LuaRocks configuration for variables, paths
-- and OS detection.
-- @param detected table containing information detected about the
-- environment. All fields below are optional:
-- * lua_version (in x.y format, e.g. "5.3")
-- * lua_bindir (e.g. "/usr/local/bin")
-- * lua_dir (e.g. "/usr/local")
-- * lua_interpreter (e.g. "lua-5.3")
-- * project_dir (a string with the path of the project directory
-- when using per-project environments, as created with `luarocks init`)
-- @param warning a logging function for warnings that takes a string
-- @return true on success; nil and an error message on failure.
function cfg.init(detected, warning)
detected = detected or {}
local hc_ok, hardcoded = pcall(require, "luarocks.core.hardcoded")
if not hc_ok then
hardcoded = {}
end
local init = cfg.init
----------------------------------------
-- Reset the cfg table.
----------------------------------------
for k, _ in pairs(cfg) do
cfg[k] = nil
end
cfg.program_version = program_version
cfg.program_series = program_series
cfg.major_version = major_version
if hardcoded.IS_BINARY then
cfg.is_binary = true
end
-- Use detected values as defaults, overridable via config files or CLI args
local first_arg = get_first_arg()
cfg.lua_version = detected.lua_version or hardcoded.LUA_VERSION or _VERSION:sub(5)
cfg.lua_interpreter = detected.lua_interpreter or hardcoded.LUA_INTERPRETER or (first_arg and first_arg:gsub(".*[\\/]", "")) or (is_windows and "lua.exe" or "lua")
cfg.project_dir = (not hardcoded.FORCE_CONFIG) and detected.project_dir
do
local lua_bindir = detected.lua_bindir or hardcoded.LUA_BINDIR or (first_arg and first_arg:gsub("[\\/][^\\/]+$", ""))
local lua_dir = detected.lua_dir or hardcoded.LUA_DIR or (lua_bindir and lua_bindir:gsub("[\\/]bin$", ""))
cfg.variables = {
LUA_DIR = lua_dir,
LUA_BINDIR = lua_bindir,
LUA_LIBDIR = hardcoded.LUA_LIBDIR,
LUA_INCDIR = hardcoded.LUA_INCDIR,
}
end
cfg.init = init
----------------------------------------
-- System detection.
----------------------------------------
-- A proper build of LuaRocks will hardcode the system
-- and proc values with hardcoded.SYSTEM and hardcoded.PROCESSOR.
-- If that is not available, we try to identify the system.
local system, processor = sysdetect.detect()
if hardcoded.SYSTEM then
system = hardcoded.SYSTEM
end
if hardcoded.PROCESSOR then
processor = hardcoded.PROCESSOR
end
if system == "windows" then
if os.getenv("VCINSTALLDIR") then
-- running from the Development Command prompt for VS 2017
system = "windows"
else
local msystem = os.getenv("MSYSTEM")
if msystem == nil then
system = "mingw"
elseif msystem == "MSYS" then
system = "msys"
else
-- MINGW32 or MINGW64
system = "msys2_mingw_w64"
end
end
end
cfg.target_cpu = processor
local platforms = make_platforms(system)
----------------------------------------
-- Platform is determined.
-- Let's load the config files.
----------------------------------------
local sys_config_file
local home_config_file
local project_config_file
local config_file_name = "config-"..cfg.lua_version..".lua"
do
local sysconfdir = os.getenv("LUAROCKS_SYSCONFDIR") or hardcoded.SYSCONFDIR
if platforms.windows and not platforms.msys2_mingw_w64 then
cfg.home = os.getenv("APPDATA") or "c:"
cfg.home_tree = cfg.home.."/luarocks"
cfg.sysconfdir = sysconfdir or ((os.getenv("PROGRAMFILES") or "c:") .. "/luarocks")
else
cfg.home = os.getenv("HOME") or ""
cfg.home_tree = cfg.home.."/.luarocks"
cfg.sysconfdir = sysconfdir or detect_sysconfdir() or "/etc/luarocks"
end
end
-- Load system configuration file
sys_config_file = (cfg.sysconfdir .. "/" .. config_file_name):gsub("\\", "/")
local sys_config_ok, err = load_config_file(cfg, platforms, sys_config_file)
if err then
return nil, err, "config"
end
-- Load user configuration file (if allowed)
local home_config_ok
local project_config_ok
if not hardcoded.FORCE_CONFIG then
local env_var = "LUAROCKS_CONFIG_" .. cfg.lua_version:gsub("%.", "_")
local env_value = os.getenv(env_var)
if not env_value then
env_var = "LUAROCKS_CONFIG"
env_value = os.getenv(env_var)
end
-- first try environment provided file, so we can explicitly warn when it is missing
if env_value then
local env_ok, err = load_config_file(cfg, platforms, env_value)
if err then
return nil, err, "config"
elseif warning and not env_ok then
warning("Warning: could not load configuration file `"..env_value.."` given in environment variable "..env_var.."\n")
end
if env_ok then
home_config_ok = true
home_config_file = env_value
end
end
-- try XDG config home
if platforms.unix and not home_config_ok then
local xdg_config_home = os.getenv("XDG_CONFIG_HOME") or cfg.home .. "/.config"
cfg.homeconfdir = xdg_config_home .. "/luarocks"
home_config_file = (cfg.homeconfdir .. "/" .. config_file_name):gsub("\\", "/")
home_config_ok, err = load_config_file(cfg, platforms, home_config_file)
if err then
return nil, err, "config"
end
end
-- try the alternative defaults if there was no environment specified file or it didn't work
if not home_config_ok then
cfg.homeconfdir = cfg.home_tree
home_config_file = (cfg.homeconfdir .. "/" .. config_file_name):gsub("\\", "/")
home_config_ok, err = load_config_file(cfg, platforms, home_config_file)
if err then
return nil, err, "config"
end
end
-- finally, use the project-specific config file if any
if cfg.project_dir then
project_config_file = cfg.project_dir .. "/.luarocks/" .. config_file_name
project_config_ok, err = load_config_file(cfg, platforms, project_config_file)
if err then
return nil, err, "config"
end
end
end
----------------------------------------
-- Config files are loaded.
-- Let's finish up the cfg table.
----------------------------------------
-- Settings given via the CLI (i.e. --lua-dir) take precedence over config files.
cfg.project_dir = detected.given_project_dir or cfg.project_dir
cfg.lua_version = detected.given_lua_version or cfg.lua_version
if detected.given_lua_dir then
cfg.variables.LUA_DIR = detected.given_lua_dir
cfg.variables.LUA_BINDIR = detected.lua_bindir
cfg.variables.LUA_LIBDIR = nil
cfg.variables.LUA_INCDIR = nil
cfg.lua_interpreter = detected.lua_interpreter
end
-- Build a default list of rocks trees if not given
if cfg.rocks_trees == nil then
cfg.rocks_trees = {}
if cfg.home_tree then
table.insert(cfg.rocks_trees, { name = "user", root = cfg.home_tree } )
end
if hardcoded.PREFIX and hardcoded.PREFIX ~= cfg.home_tree then
table.insert(cfg.rocks_trees, { name = "system", root = hardcoded.PREFIX } )
end
end
local defaults = make_defaults(cfg.lua_version, processor, platforms, cfg.home)
if platforms.windows and hardcoded.WIN_TOOLS then
local tools = { "SEVENZ", "CP", "FIND", "LS", "MD5SUM", "PWD", "RMDIR", "WGET", "MKDIR" }
for _, tool in ipairs(tools) do
defaults.variables[tool] = '"' .. hardcoded.WIN_TOOLS .. "/" .. defaults.variables[tool] .. '.exe"'
end
else
defaults.fs_use_modules = true
end
use_defaults(cfg, defaults)
cfg.variables.LUA = cfg.variables.LUA or (cfg.variables.LUA_BINDIR and (cfg.variables.LUA_BINDIR .. "/" .. cfg.lua_interpreter):gsub("//", "/"))
cfg.user_agent = "LuaRocks/"..cfg.program_version.." "..cfg.arch
cfg.config_files = {
project = cfg.project_dir and {
file = project_config_file,
found = not not project_config_ok,
},
system = {
file = sys_config_file,
found = not not sys_config_ok,
},
user = {
file = home_config_file,
found = not not home_config_ok,
},
nearest = project_config_ok
and project_config_file
or (home_config_ok
and home_config_file
or sys_config_file),
}
cfg.cache = {}
----------------------------------------
-- Attributes of cfg are set.
-- Let's add some methods.
----------------------------------------
do
local function make_paths_from_tree(tree)
local lua_path, lib_path, bin_path
if type(tree) == "string" then
lua_path = tree..cfg.lua_modules_path
lib_path = tree..cfg.lib_modules_path
bin_path = tree.."/bin"
else
lua_path = tree.lua_dir or tree.root..cfg.lua_modules_path
lib_path = tree.lib_dir or tree.root..cfg.lib_modules_path
bin_path = tree.bin_dir or tree.root.."/bin"
end
return lua_path, lib_path, bin_path
end
function cfg.package_paths(current)
local new_path, new_cpath, new_bin = {}, {}, {}
local function add_tree_to_paths(tree)
local lua_path, lib_path, bin_path = make_paths_from_tree(tree)
table.insert(new_path, lua_path.."/?.lua")
table.insert(new_path, lua_path.."/?/init.lua")
table.insert(new_cpath, lib_path.."/?."..cfg.lib_extension)
table.insert(new_bin, bin_path)
end
if current then
add_tree_to_paths(current)
end
for _,tree in ipairs(cfg.rocks_trees) do
add_tree_to_paths(tree)
end
return table.concat(new_path, ";"), table.concat(new_cpath, ";"), table.concat(new_bin, cfg.export_path_separator)
end
end
function cfg.init_package_paths()
local lr_path, lr_cpath, lr_bin = cfg.package_paths()
package.path = util.cleanup_path(package.path .. ";" .. lr_path, ";", cfg.lua_version, true)
package.cpath = util.cleanup_path(package.cpath .. ";" .. lr_cpath, ";", cfg.lua_version, true)
end
--- Check if platform was detected
-- @param name string: The platform name to check.
-- @return boolean: true if LuaRocks is currently running on queried platform.
function cfg.is_platform(name)
assert(type(name) == "string")
return platforms[name]
end
-- @param direction (optional) "least-specific-first" (default) or "most-specific-first"
function cfg.each_platform(direction)
direction = direction or "least-specific-first"
local i, delta
if direction == "least-specific-first" then
i = 0
delta = 1
else
i = #platform_order + 1
delta = -1
end
return function()
local p
repeat
i = i + delta
p = platform_order[i]
until (not p) or platforms[p]
return p
end
end
function cfg.print_platforms()
local platform_keys = {}
for k,_ in pairs(platforms) do
table.insert(platform_keys, k)
end
table.sort(platform_keys)
return table.concat(platform_keys, ", ")
end
return true
end
return cfg

View file

@ -1,88 +0,0 @@
local dir = {}
local require = nil
--------------------------------------------------------------------------------
local function unquote(c)
local first, last = c:sub(1,1), c:sub(-1)
if (first == '"' and last == '"') or
(first == "'" and last == "'") then
return c:sub(2,-2)
end
return c
end
--- Describe a path in a cross-platform way.
-- Use this function to avoid platform-specific directory
-- separators in other modules. Removes trailing slashes from
-- each component given, to avoid repeated separators.
-- Separators inside strings are kept, to handle URLs containing
-- protocols.
-- @param ... strings representing directories
-- @return string: a string with a platform-specific representation
-- of the path.
function dir.path(...)
local t = {...}
while t[1] == "" do
table.remove(t, 1)
end
for i, c in ipairs(t) do
t[i] = unquote(c)
end
return (table.concat(t, "/"):gsub("([^:])/+", "%1/"):gsub("^/+", "/"):gsub("/*$", ""))
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 dir.split_url(url)
assert(type(url) == "string")
url = unquote(url)
local protocol, pathname = url:match("^([^:]*)://(.*)")
if not protocol then
protocol = "file"
pathname = url
end
return protocol, pathname
end
--- Normalize a url or local path.
-- URLs should be in the "protocol://path" format. System independent
-- forward slashes are used, removing trailing and double slashes
-- @param url string: an URL or a local pathname.
-- @return string: Normalized result.
function dir.normalize(name)
local protocol, pathname = dir.split_url(name)
pathname = pathname:gsub("\\", "/"):gsub("(.)/*$", "%1"):gsub("//", "/")
local pieces = {}
local drive = ""
if pathname:match("^.:") then
drive, pathname = pathname:match("^(.:)(.*)$")
end
for piece in pathname:gmatch("(.-)/") do
if piece == ".." then
local prev = pieces[#pieces]
if not prev or prev == ".." then
table.insert(pieces, "..")
elseif prev ~= "" then
table.remove(pieces)
end
elseif piece ~= "." then
table.insert(pieces, piece)
end
end
local basename = pathname:match("[^/]+$")
if basename then
table.insert(pieces, basename)
end
pathname = drive .. table.concat(pieces, "/")
if protocol ~= "file" then pathname = protocol .."://"..pathname end
return pathname
end
return dir

View file

@ -1,114 +0,0 @@
--- Core functions for querying manifest files.
local manif = {}
local persist = require("luarocks.core.persist")
local cfg = require("luarocks.core.cfg")
local dir = require("luarocks.core.dir")
local util = require("luarocks.core.util")
local vers = require("luarocks.core.vers")
local path = require("luarocks.core.path")
local require = nil
--------------------------------------------------------------------------------
-- Table with repository identifiers as keys and tables mapping
-- Lua versions to cached loaded manifests as values.
local manifest_cache = {}
--- Cache a loaded manifest.
-- @param repo_url string: The repository identifier.
-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
-- @param manifest table: the manifest to be cached.
function manif.cache_manifest(repo_url, lua_version, manifest)
lua_version = lua_version or cfg.lua_version
manifest_cache[repo_url] = manifest_cache[repo_url] or {}
manifest_cache[repo_url][lua_version] = manifest
end
--- Attempt to get cached loaded manifest.
-- @param repo_url string: The repository identifier.
-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
-- @return table or nil: loaded manifest or nil if cache is empty.
function manif.get_cached_manifest(repo_url, lua_version)
lua_version = lua_version or cfg.lua_version
return manifest_cache[repo_url] and manifest_cache[repo_url][lua_version]
end
--- 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 lua_version string: Lua version in "5.x" format, defaults to installed version.
-- @return table or (nil, string, string): the manifest or nil,
-- error message and error code ("open", "load", "run").
function manif.manifest_loader(file, repo_url, lua_version)
local manifest, err, errcode = persist.load_into_table(file)
if not manifest then
return nil, "Failed loading manifest for "..repo_url..": "..err, errcode
end
manif.cache_manifest(repo_url, lua_version, manifest)
return manifest, err, errcode
end
--- Load a local manifest describing a repository.
-- This is used by the luarocks.loader only.
-- @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 error code, see manifest_loader.
function manif.fast_load_local_manifest(repo_url)
assert(type(repo_url) == "string")
local cached_manifest = manif.get_cached_manifest(repo_url)
if cached_manifest then
return cached_manifest
end
local pathname = dir.path(repo_url, "manifest")
return manif.manifest_loader(pathname, repo_url, nil, true)
end
function manif.load_rocks_tree_manifests(deps_mode)
local trees = {}
path.map_trees(deps_mode, function(tree)
local manifest, err = manif.fast_load_local_manifest(path.rocks_dir(tree))
if manifest then
table.insert(trees, {tree=tree, manifest=manifest})
end
end)
return trees
end
function manif.scan_dependencies(name, version, tree_manifests, dest)
if dest[name] then
return
end
dest[name] = version
for _, tree in ipairs(tree_manifests) do
local manifest = tree.manifest
local pkgdeps
if manifest.dependencies and manifest.dependencies[name] then
pkgdeps = manifest.dependencies[name][version]
end
if pkgdeps then
for _, dep in ipairs(pkgdeps) do
local pkg, constraints = dep.name, dep.constraints
for _, t in ipairs(tree_manifests) do
local entries = t.manifest.repository[pkg]
if entries then
for ver, _ in util.sortedpairs(entries, vers.compare_versions) do
if (not constraints) or vers.match_constraints(vers.parse_version(ver), constraints) then
manif.scan_dependencies(pkg, ver, tree_manifests, dest)
end
end
end
end
end
return
end
end
end
return manif

View file

@ -1,150 +0,0 @@
--- Core LuaRocks-specific path handling functions.
local path = {}
local cfg = require("luarocks.core.cfg")
local dir = require("luarocks.core.dir")
local require = nil
--------------------------------------------------------------------------------
function path.rocks_dir(tree)
if tree == nil then
tree = cfg.root_dir
end
if type(tree) == "string" then
return dir.path(tree, cfg.rocks_subdir)
end
assert(type(tree) == "table")
return tree.rocks_dir or dir.path(tree.root, cfg.rocks_subdir)
end
--- Produce a versioned version of a filename.
-- @param file string: filename (must start with prefix)
-- @param prefix string: Path prefix for file
-- @param name string: Rock name
-- @param version string: Rock version
-- @return string: a pathname with the same directory parts and a versioned basename.
function path.versioned_name(file, prefix, name, version)
assert(type(file) == "string")
assert(type(name) == "string" and not name:match("/"))
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
--- 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.init"; "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.path_to_module(file)
assert(type(file) == "string")
local name = file:match("(.*)%."..cfg.lua_extension.."$")
if name then
name = name:gsub("/", ".")
else
name = file:match("(.*)%."..cfg.lib_extension.."$")
if name then
name = name:gsub("/", ".")
--[[ TODO disable static libs until we fix the conflict in the manifest, which will take extending the manifest format.
else
name = file:match("(.*)%."..cfg.static_lib_extension.."$")
if name then
name = name:gsub("/", ".")
end
]]
end
end
if not name then name = file end
name = name:gsub("^%.+", ""):gsub("%.+$", "")
return name
end
function path.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 path.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
local is_src_extension = { [".lua"] = true, [".tl"] = true, [".tld"] = true, [".moon"] = true }
--- Return the pathname of the file that would be loaded for a module, indexed.
-- @param file_name string: module file name as in manifest (eg. "socket/core.so")
-- @param name string: name of the package (eg. "luasocket")
-- @param version string: version number (eg. "2.0.2-1")
-- @param tree string: repository path (eg. "/usr/local")
-- @param i number: the index, 1 if version is the current default, > 1 otherwise.
-- This is done this way for use by select_module in luarocks.loader.
-- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so")
function path.which_i(file_name, name, version, tree, i)
local deploy_dir
local extension = file_name:match("%.[a-z]+$")
if is_src_extension[extension] then
deploy_dir = path.deploy_lua_dir(tree)
file_name = dir.path(deploy_dir, file_name)
else
deploy_dir = path.deploy_lib_dir(tree)
file_name = dir.path(deploy_dir, file_name)
end
if i > 1 then
file_name = path.versioned_name(file_name, deploy_dir, name, version)
end
return file_name
end
function path.rocks_tree_to_string(tree)
if type(tree) == "string" then
return tree
else
assert(type(tree) == "table")
return tree.root
end
end
--- Apply a given function to the active rocks trees based on chosen dependency mode.
-- @param deps_mode string: Dependency mode: "one" for the current default tree,
-- "all" for all trees, "order" for all trees with priority >= the current default,
-- "none" for no trees (this function becomes a nop).
-- @param fn function: function to be applied, with the tree dir (string) as the first
-- argument and the remaining varargs of map_trees as the following arguments.
-- @return a table with all results of invocations of fn collected.
function path.map_trees(deps_mode, fn, ...)
local result = {}
local current = cfg.root_dir or cfg.rocks_trees[1]
if deps_mode == "one" then
table.insert(result, (fn(current, ...)) or 0)
else
local use = false
if deps_mode == "all" then
use = true
end
for _, tree in ipairs(cfg.rocks_trees or {}) do
if dir.normalize(path.rocks_tree_to_string(tree)) == dir.normalize(path.rocks_tree_to_string(current)) then
use = true
end
if use then
table.insert(result, (fn(tree, ...)) or 0)
end
end
end
return result
end
return path

View file

@ -1,81 +0,0 @@
local persist = {}
local require = nil
--------------------------------------------------------------------------------
--- Load and run a Lua file in an environment.
-- @param filename string: the name of the file.
-- @param env table: the environment table.
-- @return (true, any) or (nil, string, string): true and the return value
-- of the file, or nil, an error message and an error code ("open", "load"
-- or "run") in case of errors.
function persist.run_file(filename, env)
local fd, err = io.open(filename)
if not fd then
return nil, err, "open"
end
local str, err = fd:read("*a")
fd:close()
if not str then
return nil, err, "open"
end
str = str:gsub("^#![^\n]*\n", "")
local chunk, ran
if _VERSION == "Lua 5.1" then -- Lua 5.1
chunk, err = loadstring(str, filename)
if chunk then
setfenv(chunk, env)
ran, err = pcall(chunk)
end
else -- Lua 5.2
chunk, err = load(str, filename, "t", env)
if chunk then
ran, err = pcall(chunk)
end
end
if not chunk then
return nil, "Error loading file: "..err, "load"
end
if not ran then
return nil, "Error running file: "..err, "run"
end
return true, err
end
--- 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, table) or (nil, string, string): a table with the file's assignments
-- as fields and set of undefined globals accessed in file,
-- or nil, an error message and an error code ("open"; couldn't open the file,
-- "load"; compile-time error, or "run"; run-time error)
-- in case of errors.
function persist.load_into_table(filename, tbl)
assert(type(filename) == "string")
assert(type(tbl) == "table" or not tbl)
local result = tbl or {}
local globals = {}
local globals_mt = {
__index = function(t, k)
globals[k] = true
end
}
local save_mt = getmetatable(result)
setmetatable(result, globals_mt)
local ok, err, errcode = persist.run_file(filename, result)
setmetatable(result, save_mt)
if not ok then
return nil, err, errcode
end
return result, globals
end
return persist

View file

@ -1,416 +0,0 @@
-- Detect the operating system and architecture without forking a subprocess.
--
-- We are not going for exhaustive list of every historical system here,
-- but aiming to cover every platform where LuaRocks is known to run.
-- If your system is not detected, patches are welcome!
local sysdetect = {}
local function hex(s)
return s:gsub("$(..)", function(x)
return string.char(tonumber(x, 16))
end)
end
local function read_int8(fd)
if io.type(fd) == "closed file" then
return nil
end
local s = fd:read(1)
if not s then
fd:close()
return nil
end
return s:byte()
end
local LITTLE = 1
-- local BIG = 2
local function bytes2number(s, endian)
local r = 0
if endian == LITTLE then
for i = #s, 1, -1 do
r = r*256 + s:byte(i,i)
end
else
for i = 1, #s do
r = r*256 + s:byte(i,i)
end
end
return r
end
local function read(fd, bytes, endian)
if io.type(fd) == "closed file" then
return nil
end
local s = fd:read(bytes)
if not s
then fd:close()
return nil
end
return bytes2number(s, endian)
end
local function read_int32le(fd)
return read(fd, 4, LITTLE)
end
--------------------------------------------------------------------------------
-- @section ELF
--------------------------------------------------------------------------------
local e_osabi = {
[0x00] = "sysv",
[0x01] = "hpux",
[0x02] = "netbsd",
[0x03] = "linux",
[0x04] = "hurd",
[0x06] = "solaris",
[0x07] = "aix",
[0x08] = "irix",
[0x09] = "freebsd",
[0x0c] = "openbsd",
}
local e_machines = {
[0x02] = "sparc",
[0x03] = "x86",
[0x08] = "mips",
[0x0f] = "hppa",
[0x12] = "sparcv8",
[0x14] = "ppc",
[0x15] = "ppc64",
[0x16] = "s390",
[0x28] = "arm",
[0x2a] = "superh",
[0x2b] = "sparcv9",
[0x32] = "ia_64",
[0x3E] = "x86_64",
[0xB6] = "alpha",
[0xB7] = "aarch64",
[0xF3] = "riscv64",
[0x9026] = "alpha",
}
local SHT_NOTE = 7
local function read_elf_section_headers(fd, hdr)
local endian = hdr.endian
local word = hdr.word
local strtab_offset
local sections = {}
for i = 0, hdr.e_shnum - 1 do
fd:seek("set", hdr.e_shoff + (i * hdr.e_shentsize))
local section = {}
section.sh_name_off = read(fd, 4, endian)
section.sh_type = read(fd, 4, endian)
section.sh_flags = read(fd, word, endian)
section.sh_addr = read(fd, word, endian)
section.sh_offset = read(fd, word, endian)
section.sh_size = read(fd, word, endian)
section.sh_link = read(fd, 4, endian)
section.sh_info = read(fd, 4, endian)
if section.sh_type == SHT_NOTE then
fd:seek("set", section.sh_offset)
section.namesz = read(fd, 4, endian)
section.descsz = read(fd, 4, endian)
section.type = read(fd, 4, endian)
section.namedata = fd:read(section.namesz):gsub("%z.*", "")
section.descdata = fd:read(section.descsz)
elseif i == hdr.e_shstrndx then
strtab_offset = section.sh_offset
end
table.insert(sections, section)
end
if strtab_offset then
for _, section in ipairs(sections) do
fd:seek("set", strtab_offset + section.sh_name_off)
section.name = fd:read(32):gsub("%z.*", "")
sections[section.name] = section
end
end
return sections
end
local function detect_elf_system(fd, hdr, sections)
local system = e_osabi[hdr.osabi]
local endian = hdr.endian
if system == "sysv" then
local abitag = sections[".note.ABI-tag"]
if abitag then
if abitag.namedata == "GNU" and abitag.type == 1
and abitag.descdata:sub(0, 4) == "\0\0\0\0" then
return "linux"
end
elseif sections[".SUNW_version"]
or sections[".SUNW_signature"] then
return "solaris"
elseif sections[".note.netbsd.ident"] then
return "netbsd"
elseif sections[".note.openbsd.ident"] then
return "openbsd"
end
local gnu_version_r = sections[".gnu.version_r"]
if gnu_version_r then
local dynstr = sections[".dynstr"].sh_offset
local idx = 0
for _ = 0, gnu_version_r.sh_info - 1 do
fd:seek("set", gnu_version_r.sh_offset + idx)
assert(read(fd, 2, endian)) -- vn_version
local vn_cnt = read(fd, 2, endian)
local vn_file = read(fd, 4, endian)
local vn_next = read(fd, 2, endian)
fd:seek("set", dynstr + vn_file)
local libname = fd:read(64):gsub("%z.*", "")
if hdr.e_type == 0x03 and libname == "libroot.so" then
return "haiku"
elseif libname:match("linux") then
return "linux"
end
idx = idx + (vn_next * (vn_cnt + 1))
end
end
local procfile = io.open("/proc/sys/kernel/ostype")
if procfile then
local version = procfile:read(6)
procfile:close()
if version == "Linux\n" then
return "linux"
end
end
end
return system
end
local function read_elf_header(fd)
local hdr = {}
hdr.bits = read_int8(fd)
hdr.endian = read_int8(fd)
hdr.elf_version = read_int8(fd)
if hdr.elf_version ~= 1 then
return nil
end
hdr.osabi = read_int8(fd)
if not hdr.osabi then
return nil
end
local endian = hdr.endian
fd:seek("set", 0x10)
hdr.e_type = read(fd, 2, endian)
local machine = read(fd, 2, endian)
local processor = e_machines[machine] or "unknown"
if endian == 1 and processor == "ppc64" then
processor = "ppc64le"
end
local elfversion = read(fd, 4, endian)
if elfversion ~= 1 then
return nil
end
local word = (hdr.bits == 1) and 4 or 8
hdr.word = word
hdr.e_entry = read(fd, word, endian)
hdr.e_phoff = read(fd, word, endian)
hdr.e_shoff = read(fd, word, endian)
hdr.e_flags = read(fd, 4, endian)
hdr.e_ehsize = read(fd, 2, endian)
hdr.e_phentsize = read(fd, 2, endian)
hdr.e_phnum = read(fd, 2, endian)
hdr.e_shentsize = read(fd, 2, endian)
hdr.e_shnum = read(fd, 2, endian)
hdr.e_shstrndx = read(fd, 2, endian)
return hdr, processor
end
local function detect_elf(fd)
local hdr, processor = read_elf_header(fd)
if not hdr then
return nil
end
local sections = read_elf_section_headers(fd, hdr)
local system = detect_elf_system(fd, hdr, sections)
return system, processor
end
--------------------------------------------------------------------------------
-- @section Mach Objects (Apple)
--------------------------------------------------------------------------------
local mach_l64 = {
[7] = "x86_64",
[12] = "aarch64",
}
local mach_b64 = {
[0] = "ppc64",
}
local mach_l32 = {
[7] = "x86",
[12] = "arm",
}
local mach_b32 = {
[0] = "ppc",
}
local function detect_mach(magic, fd)
if not magic then
return nil
end
if magic == hex("$CA$FE$BA$BE") then
-- fat binary, go for the first one
fd:seek("set", 0x12)
local offs = read_int8(fd)
if not offs then
return nil
end
fd:seek("set", offs * 256)
magic = fd:read(4)
return detect_mach(magic, fd)
end
local cputype = read_int8(fd)
if magic == hex("$CF$FA$ED$FE") then
return "macosx", mach_l64[cputype] or "unknown"
elseif magic == hex("$FE$ED$CF$FA") then
return "macosx", mach_b64[cputype] or "unknown"
elseif magic == hex("$CE$FA$ED$FE") then
return "macosx", mach_l32[cputype] or "unknown"
elseif magic == hex("$FE$ED$FA$CE") then
return "macosx", mach_b32[cputype] or "unknown"
end
end
--------------------------------------------------------------------------------
-- @section PE (Windows)
--------------------------------------------------------------------------------
local pe_machine = {
[0x8664] = "x86_64",
[0x01c0] = "arm",
[0x01c4] = "armv7l",
[0xaa64] = "arm64",
[0x014c] = "x86",
}
local function detect_pe(fd)
fd:seek("set", 60) -- position of PE header position
local peoffset = read_int32le(fd) -- read position of PE header
if not peoffset then
return nil
end
local system = "windows"
fd:seek("set", peoffset + 4) -- move to position of Machine section
local machine = read(fd, 2, LITTLE)
local processor = pe_machine[machine]
local rdata_pos = fd:read(736):match(".rdata%z%z............(....)")
if rdata_pos then
rdata_pos = bytes2number(rdata_pos, LITTLE)
fd:seek("set", rdata_pos)
local data = fd:read(512)
if data:match("cygwin") or data:match("cyggcc") then
system = "cygwin"
end
end
return system, processor or "unknown"
end
--------------------------------------------------------------------------------
-- @section API
--------------------------------------------------------------------------------
function sysdetect.detect_file(file)
assert(type(file) == "string")
local fd = io.open(file, "rb")
if not fd then
return nil
end
local magic = fd:read(4)
if magic == hex("$7FELF") then
return detect_elf(fd)
end
if magic == hex("MZ$90$00") then
return detect_pe(fd)
end
return detect_mach(magic, fd)
end
local cache_system
local cache_processor
function sysdetect.detect(input_file)
local dirsep = package.config:sub(1,1)
local files
if input_file then
files = { input_file }
else
if cache_system then
return cache_system, cache_processor
end
local PATHsep
local interp = arg and arg[-1]
if dirsep == "/" then
-- Unix
files = {
"/bin/sh", -- Unix: well-known POSIX path
"/proc/self/exe", -- Linux: this should always have a working binary
}
PATHsep = ":"
else
-- Windows
local systemroot = os.getenv("SystemRoot")
files = {
systemroot .. "\\system32\\notepad.exe", -- well-known Windows path
systemroot .. "\\explorer.exe", -- well-known Windows path
}
if interp and not interp:lower():match("exe$") then
interp = interp .. ".exe"
end
PATHsep = ";"
end
if interp then
if interp:match(dirsep) then
-- interpreter path is absolute
table.insert(files, interp)
else
for d in (os.getenv("PATH") or ""):gmatch("[^"..PATHsep.."]+") do
table.insert(files, d .. dirsep .. interp)
end
end
end
end
for _, f in ipairs(files) do
local system, processor = sysdetect.detect_file(f)
if system then
cache_system = system
cache_processor = processor
return system, processor
end
end
end
return sysdetect

View file

@ -1,331 +0,0 @@
local util = {}
local require = nil
--------------------------------------------------------------------------------
--- Run a process and read a its output.
-- Equivalent to io.popen(cmd):read("*l"), except that it
-- closes the fd right away.
-- @param cmd string: The command to execute
-- @param spec string: "*l" by default, to read a single line.
-- May be used to read more, passing, for instance, "*a".
-- @return string: the output of the program.
function util.popen_read(cmd, spec)
local dir_sep = package.config:sub(1, 1)
local tmpfile = (dir_sep == "\\")
and (os.getenv("TMP") .. "/luarocks-" .. tostring(math.floor(math.random() * 10000)))
or os.tmpname()
os.execute(cmd .. " > " .. tmpfile)
local fd = io.open(tmpfile, "rb")
if not fd then
os.remove(tmpfile)
return ""
end
local out = fd:read(spec or "*l")
fd:close()
os.remove(tmpfile)
return out or ""
end
--- 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.
function util.make_shallow_copy(tbl)
local copy = {}
for k,v in pairs(tbl) do
copy[k] = v
end
return copy
end
---
-- Formats tables with cycles recursively to any depth.
-- References to other tables are shown as values.
-- Self references are indicated.
-- The string returned is "Lua code", which can be processed
-- (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
-- Written by Julio Manuel Fernandez-Diaz,
-- Heavily based on "Saving tables with cycles", PIL2, p. 113.
-- @param t table: is the table.
-- @param tname string: is the name of the table (optional)
-- @param top_indent string: is a first indentation (optional).
-- @return string: the pretty-printed table
function util.show_table(t, tname, top_indent)
local cart -- a container
local autoref -- for self references
local function is_empty_table(tbl) return next(tbl) == nil end
local function basic_serialize(o)
local so = tostring(o)
if type(o) == "function" then
local info = debug and debug.getinfo(o, "S")
if not info then
return ("%q"):format(so)
end
-- 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 add_to_cart(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 .. " = " .. basic_serialize(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 is_empty_table(value) then
cart = cart .. " = {};\n"
else
cart = cart .. " = {\n"
for k, v in pairs(value) do
k = basic_serialize(k)
local fname = ("%s[%s]"):format(name, k)
field = ("[%s]"):format(k)
-- three spaces between levels
add_to_cart(v, fname, indent .. " ", saved, field)
end
cart = cart .. indent .. "};\n"
end
end
end
end
tname = tname or "__unnamed__"
if type(t) ~= "table" then
return tname .. " = " .. basic_serialize(t)
end
cart, autoref = "", ""
add_to_cart(t, tname, top_indent)
return cart .. autoref
end
--- Merges contents of src on top of dst's contents
-- (i.e. if an key from src already exists in dst, replace it).
-- @param dst Destination table, which will receive src's contents.
-- @param src Table which provides new contents to dst.
function util.deep_merge(dst, src)
for k, v in pairs(src) do
if type(v) == "table" then
if dst[k] == nil then
dst[k] = {}
end
if type(dst[k]) == "table" then
util.deep_merge(dst[k], v)
else
dst[k] = v
end
else
dst[k] = v
end
end
end
--- Merges contents of src below those of dst's contents
-- (i.e. if an key from src already exists in dst, do not replace it).
-- @param dst Destination table, which will receive src's contents.
-- @param src Table which provides new contents to dst.
function util.deep_merge_under(dst, src)
for k, v in pairs(src) do
if type(v) == "table" then
if dst[k] == nil then
dst[k] = {}
end
if type(dst[k]) == "table" then
util.deep_merge_under(dst[k], v)
end
elseif dst[k] == nil then
dst[k] = v
end
end
end
--- Clean up a path-style string ($PATH, $LUA_PATH/package.path, etc.),
-- removing repeated entries and making sure only the relevant
-- Lua version is used.
-- Example: given ("a;b;c;a;b;d", ";"), returns "a;b;c;d".
-- @param list string: A path string (from $PATH or package.path)
-- @param sep string: The separator
-- @param lua_version (optional) string: The Lua version to use.
-- @param keep_first (optional) if true, keep first occurrence in case
-- of duplicates; otherwise keep last occurrence. The default is false.
function util.cleanup_path(list, sep, lua_version, keep_first)
assert(type(list) == "string")
assert(type(sep) == "string")
local parts = util.split_string(list, sep)
local final, entries = {}, {}
local start, stop, step
if keep_first then
start, stop, step = 1, #parts, 1
else
start, stop, step = #parts, 1, -1
end
for i = start, stop, step do
local part = parts[i]:gsub("//", "/")
if lua_version then
part = part:gsub("/lua/([%d.]+)/", function(part_version)
if part_version:sub(1, #lua_version) ~= lua_version then
return "/lua/"..lua_version.."/"
end
end)
end
if not entries[part] then
local at = keep_first and #final+1 or 1
table.insert(final, at, part)
entries[part] = true
end
end
return table.concat(final, sep)
end
-- from http://lua-users.org/wiki/SplitJoin
-- by Philippe Lhoste
function util.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
--- Return an array of keys of a table.
-- @param tbl table: The input table.
-- @return table: The array of keys.
function util.keys(tbl)
local ks = {}
for k,_ in pairs(tbl) do
table.insert(ks, k)
end
return ks
end
--- Print a line to standard error
function util.printerr(...)
io.stderr:write(table.concat({...},"\t"))
io.stderr:write("\n")
end
--- Display a warning message.
-- @param msg string: the warning message
function util.warning(msg)
util.printerr("Warning: "..msg)
end
--- Simple sort function used as a default for util.sortedpairs.
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
--- 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, which is returned by the iterator as the third value after the key
-- and the value.
-- @return function: the iterator function.
function util.sortedpairs(tbl, sort_function)
sort_function = sort_function or default_sort
local keys = util.keys(tbl)
local sub_orders = {}
if type(sort_function) == "function" then
table.sort(keys, sort_function)
else
local order = sort_function
local ordered_keys = {}
local all_keys = keys
keys = {}
for _, order_entry in ipairs(order) do
local key, sub_order
if type(order_entry) == "table" then
key = order_entry[1]
sub_order = order_entry[2]
else
key = order_entry
end
if tbl[key] then
ordered_keys[key] = true
sub_orders[key] = sub_order
table.insert(keys, key)
end
end
table.sort(all_keys, default_sort)
for _, key in ipairs(all_keys) do
if not ordered_keys[key] then
table.insert(keys, key)
end
end
end
local i = 1
return function()
local key = keys[i]
i = i + 1
return key, tbl[key], sub_orders[key]
end
end
return util

View file

@ -1,207 +0,0 @@
local vers = {}
local util = require("luarocks.core.util")
local require = nil
--------------------------------------------------------------------------------
local deltas = {
dev = 120000000,
scm = 110000000,
cvs = 100000000,
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,
-- @param v1 table: version table to compare.
-- @param v2 table: version table to compare.
-- @return boolean: true if v1 is considered lower than or equal to v2.
__le = function(v1, v2)
return not (v2 < v1)
end,
--- Return version as a string.
-- @param v The version table.
-- @return The string representation.
__tostring = function(v)
return v.string
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 vers.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
local v = vstring:match("^%s*(.*)%s*$")
version.string = v
-- store revision separately if any
local main, revision = v:match("(.*)%-(%d+)$")
if revision then
v = main
version.revision = tonumber(revision)
end
while #v > 0 do
-- extract a number
local token, rest = v:match("^(%d+)[%.%-%_]*(.*)")
if token then
add_token(tonumber(token))
else
-- extract a word
token, rest = v:match("^(%a+)[%.%-%_]*(.*)")
if not token then
util.warning("version number '"..v.."' could not be parsed.")
version[i] = 0
break
end
version[i] = deltas[token] or (token:byte() / 1000)
end
v = 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 vers.compare_versions(a, b)
if a == b then
return false
end
return vers.parse_version(a) > vers.parse_version(b)
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 = vers.parse_version(version) end
if type(requested) ~= "table" then requested = vers.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 vers.match_constraints(version, constraints)
assert(type(version) == "table")
assert(type(constraints) == "table")
local ok = true
setmetatable(version, version_mt)
for _, constr in pairs(constraints) do
if type(constr.version) == "string" then
constr.version = vers.parse_version(constr.version)
end
local constr_version, constr_op = constr.version, constr.op
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
return vers

View file

@ -1,106 +0,0 @@
local deplocks = {}
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local util = require("luarocks.util")
local persist = require("luarocks.persist")
local deptable = {}
local deptable_mode = "start"
local deplock_abs_filename
local deplock_root_rock_name
function deplocks.init(root_rock_name, dirname)
if deptable_mode ~= "start" then
return
end
deptable_mode = "create"
local filename = dir.path(dirname, "luarocks.lock")
deplock_abs_filename = fs.absolute_name(filename)
deplock_root_rock_name = root_rock_name
deptable = {}
end
function deplocks.get_abs_filename(root_rock_name)
if root_rock_name == deplock_root_rock_name then
return deplock_abs_filename
end
end
function deplocks.load(root_rock_name, dirname)
if deptable_mode ~= "start" then
return true, nil
end
deptable_mode = "locked"
local filename = dir.path(dirname, "luarocks.lock")
local ok, result, errcode = persist.run_file(filename, {})
if errcode == "load" or errcode == "run" then
-- bad config file or depends on env, so error out
return nil, nil, "Could not read existing lockfile " .. filename
end
if errcode == "open" then
-- could not open, maybe file does not exist
return true, nil
end
deplock_abs_filename = fs.absolute_name(filename)
deplock_root_rock_name = root_rock_name
deptable = result
return true, filename
end
function deplocks.add(depskey, name, version)
if deptable_mode == "locked" then
return
end
local dk = deptable[depskey]
if not dk then
dk = {}
deptable[depskey] = dk
end
if not dk[name] then
dk[name] = version
end
end
function deplocks.get(depskey, name)
local dk = deptable[depskey]
if not dk then
return nil
end
return deptable[name]
end
function deplocks.write_file()
if deptable_mode ~= "create" then
return true
end
return persist.save_as_module(deplock_abs_filename, deptable)
end
-- a table-like interface to deplocks
function deplocks.proxy(depskey)
return setmetatable({}, {
__index = function(_, k)
return deplocks.get(depskey, k)
end,
__newindex = function(_, k, v)
return deplocks.add(depskey, k, v)
end,
})
end
function deplocks.each(depskey)
return util.sortedpairs(deptable[depskey] or {})
end
return deplocks

View file

@ -1,750 +0,0 @@
--- High-level dependency related functions.
local deps = {}
local cfg = require("luarocks.core.cfg")
local manif = require("luarocks.manif")
local path = require("luarocks.path")
local dir = require("luarocks.dir")
local fun = require("luarocks.fun")
local util = require("luarocks.util")
local vers = require("luarocks.core.vers")
local queries = require("luarocks.queries")
local builtin = require("luarocks.build.builtin")
local deplocks = require("luarocks.deplocks")
--- Generate a function that matches dep queries against the manifest,
-- taking into account rocks_provided, the list of versions to skip,
-- and the lockfile.
-- @param deps_mode "one", "none", "all" or "order"
-- @param rocks_provided a one-level table mapping names to versions,
-- listing rocks to consider provided by the VM
-- @param rocks_provided table: A table of auto-provided dependencies.
-- by this Lua implementation for the given dependency.
-- @param depskey key to use when matching the lockfile ("dependencies",
-- "build_dependencies", etc.)
-- @param skip_set a two-level table mapping names to versions to
-- boolean, listing rocks that should not be matched
-- @return function(dep): {string}, {string:string}, string, boolean
-- * array of matching versions
-- * map of versions to locations
-- * version matched via lockfile if any
-- * true if rock matched via rocks_provided
local function prepare_get_versions(deps_mode, rocks_provided, depskey, skip_set)
assert(type(deps_mode) == "string")
assert(type(rocks_provided) == "table")
assert(type(depskey) == "string")
assert(type(skip_set) == "table" or skip_set == nil)
return function(dep)
local versions, locations
local provided = rocks_provided[dep.name]
if provided then
-- Provided rocks have higher priority than manifest's rocks.
versions, locations = { provided }, {}
else
if deps_mode == "none" then
deps_mode = "one"
end
versions, locations = manif.get_versions(dep, deps_mode)
end
if skip_set and skip_set[dep.name] then
for i = #versions, 1, -1 do
local v = versions[i]
if skip_set[dep.name][v] then
table.remove(versions, i)
end
end
end
local lockversion = deplocks.get(depskey, dep.name)
return versions, locations, lockversion, provided ~= nil
end
end
--- Attempt to match a dependency to an installed rock.
-- @param get_versions a getter function obtained via prepare_get_versions
-- @return (string, string, table) or (nil, nil, table):
-- 1. latest installed version of the rock matching the dependency
-- 2. location where the installed version is installed
-- 3. the 'dep' query table
-- 4. true if provided via VM
-- or
-- 1. nil
-- 2. nil
-- 3. either 'dep' or an alternative query to be used
-- 4. false
local function match_dep(dep, get_versions)
assert(type(dep) == "table")
assert(type(get_versions) == "function")
local versions, locations, lockversion, provided = get_versions(dep)
local latest_version
local latest_vstring
for _, vstring in ipairs(versions) do
local version = vers.parse_version(vstring)
if vers.match_constraints(version, dep.constraints) then
if not latest_version or version > latest_version then
latest_version = version
latest_vstring = vstring
end
end
end
if lockversion and not locations[lockversion] then
local latest_matching_msg = ""
if latest_vstring and latest_vstring ~= lockversion then
latest_matching_msg = " (latest matching is " .. latest_vstring .. ")"
end
util.printout("Forcing " .. dep.name .. " to pinned version " .. lockversion .. latest_matching_msg)
return nil, nil, queries.new(dep.name, dep.namespace, lockversion)
end
return latest_vstring, locations[latest_vstring], dep, provided
end
local function match_all_deps(dependencies, get_versions)
assert(type(dependencies) == "table")
assert(type(get_versions) == "function")
local matched, missing, no_upgrade = {}, {}, {}
for _, dep in ipairs(dependencies) do
local found, _, provided
found, _, dep, provided = match_dep(dep, get_versions)
if found then
if not provided then
matched[dep] = {name = dep.name, version = 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
--- Attempt to match dependencies of a rockspec to installed rocks.
-- @param dependencies table: The table of dependencies.
-- @param rocks_provided table: The table of auto-provided dependencies.
-- @param skip_set 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'.
-- @param deps_mode string: Which trees to check dependencies for
-- @return table, table, table: A table where keys are dependencies parsed
-- in table format and values are tables containing fields 'name' and
-- version' representing matches; a table of missing dependencies
-- parsed as tables; and a table of "no-upgrade" missing dependencies
-- (to be used in plugin modules so that a plugin does not force upgrade of
-- its parent application).
function deps.match_deps(dependencies, rocks_provided, skip_set, deps_mode)
assert(type(dependencies) == "table")
assert(type(rocks_provided) == "table")
assert(type(skip_set) == "table" or skip_set == nil)
assert(type(deps_mode) == "string")
local get_versions = prepare_get_versions(deps_mode, rocks_provided, "dependencies", skip_set)
return match_all_deps(dependencies, get_versions)
end
local function rock_status(dep, get_versions)
assert(dep:type() == "query")
assert(type(get_versions) == "function")
local installed, _, _, provided = match_dep(dep, get_versions)
local installation_type = provided and "provided by VM" or "installed"
return installed and installed.." "..installation_type or "not installed"
end
--- Check depenendencies of a package and report any missing ones.
-- @param name string: package name.
-- @param version string: package version.
-- @param dependencies table: array of dependencies.
-- @param deps_mode string: Which trees to check dependencies for
-- @param rocks_provided table: A table of auto-dependencies provided
-- by this Lua implementation for the given dependency.
-- "one" for the current default tree, "all" for all trees,
-- "order" for all trees with priority >= the current default, "none" for no trees.
function deps.report_missing_dependencies(name, version, dependencies, deps_mode, rocks_provided)
assert(type(name) == "string")
assert(type(version) == "string")
assert(type(dependencies) == "table")
assert(type(deps_mode) == "string")
assert(type(rocks_provided) == "table")
if deps_mode == "none" then
return
end
local get_versions = prepare_get_versions(deps_mode, rocks_provided, "dependencies")
local first_missing_dep = true
for _, dep in ipairs(dependencies) do
local found, _
found, _, dep = match_dep(dep, get_versions)
if not found then
if first_missing_dep then
util.printout(("Missing dependencies for %s %s:"):format(name, version))
first_missing_dep = false
end
util.printout((" %s (%s)"):format(tostring(dep), rock_status(dep, get_versions)))
end
end
end
function deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey)
assert(dep:type() == "query")
assert(type(deps_mode) == "string" or deps_mode == nil)
assert(type(rocks_provided) == "table" or rocks_provided == nil)
assert(type(verify) == "boolean" or verify == nil)
assert(type(depskey) == "string")
deps_mode = deps_mode or "all"
rocks_provided = rocks_provided or {}
local get_versions = prepare_get_versions(deps_mode, rocks_provided, depskey)
local found, where
found, where, dep = match_dep(dep, get_versions)
if found then
local tree_manifests = manif.load_rocks_tree_manifests(deps_mode)
manif.scan_dependencies(dep.name, found, tree_manifests, deplocks.proxy(depskey))
return true, found, where
end
local search = require("luarocks.search")
local install = require("luarocks.cmd.install")
local url, search_err = search.find_suitable_rock(dep)
if not url then
return nil, "Could not satisfy dependency "..tostring(dep)..": "..search_err
end
util.printout("Installing "..url)
local install_args = {
rock = url,
deps_mode = deps_mode,
namespace = dep.namespace,
verify = verify,
}
local ok, install_err, errcode = install.command(install_args)
if not ok then
return nil, "Failed installing dependency: "..url.." - "..install_err, errcode
end
found, where = match_dep(dep, get_versions)
assert(found)
return true, found, where
end
local function check_supported_platforms(rockspec)
if rockspec.supported_platforms and next(rockspec.supported_platforms) then
local all_negative = true
local supported = false
for _, plat in pairs(rockspec.supported_platforms) do
local neg
neg, plat = plat:match("^(!?)(.*)")
if neg == "!" then
if cfg.is_platform(plat) then
return nil, "This rockspec for "..rockspec.package.." does not support "..plat.." platforms."
end
else
all_negative = false
if cfg.is_platform(plat) then
supported = true
break
end
end
end
if supported == false and not all_negative then
local plats = cfg.print_platforms()
return nil, "This rockspec for "..rockspec.package.." does not support "..plats.." platforms."
end
end
return true
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.
-- @param depskey string: Rockspec key to fetch to get dependency table
-- ("dependencies", "build_dependencies", etc.).
-- @param deps_mode string
-- @param verify boolean
-- @param deplock_dir string: dirname of the deplock file
-- @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 deps.fulfill_dependencies(rockspec, depskey, deps_mode, verify, deplock_dir)
assert(type(rockspec) == "table")
assert(type(depskey) == "string")
assert(type(deps_mode) == "string")
assert(type(verify) == "boolean" or verify == nil)
assert(type(deplock_dir) == "string" or deplock_dir == nil)
local name = rockspec.name
local version = rockspec.version
local rocks_provided = rockspec.rocks_provided
local ok, filename, err = deplocks.load(name, deplock_dir or ".")
if filename then
util.printout("Using dependencies pinned in lockfile: " .. filename)
local get_versions = prepare_get_versions("none", rocks_provided, depskey)
for dnsname, dversion in deplocks.each(depskey) do
local dname, dnamespace = util.split_namespace(dnsname)
local dep = queries.new(dname, dnamespace, dversion)
util.printout(("%s %s is pinned to %s (%s)"):format(
name, version, tostring(dep), rock_status(dep, get_versions)))
local ok, err = deps.fulfill_dependency(dep, "none", rocks_provided, verify, depskey)
if not ok then
return nil, err
end
end
util.printout()
return true
elseif err then
util.warning(err)
end
ok, err = check_supported_platforms(rockspec)
if not ok then
return nil, err
end
deps.report_missing_dependencies(name, version, rockspec[depskey], deps_mode, rocks_provided)
util.printout()
local get_versions = prepare_get_versions(deps_mode, rocks_provided, depskey)
for _, dep in ipairs(rockspec[depskey]) do
util.printout(("%s %s depends on %s (%s)"):format(
name, version, tostring(dep), rock_status(dep, get_versions)))
local ok, found_or_err, _, no_upgrade = deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey)
if ok then
deplocks.add(depskey, dep.name, found_or_err)
else
if no_upgrade then
util.printerr("This version of "..name.." is designed for use with")
util.printerr(tostring(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 look for a suitable version of "..name.." with")
util.printerr(" luarocks search "..name)
end
return nil, found_or_err
end
end
return true
end
--- If filename matches a pattern, return the capture.
-- For example, given "libfoo.so" and "lib?.so" is a pattern,
-- returns "foo" (which can then be used to build names
-- based on other patterns.
-- @param file string: a filename
-- @param pattern string: a pattern, where ? is to be matched by the filename.
-- @return string The pattern, if found, or nil.
local function deconstruct_pattern(file, pattern)
local depattern = "^"..(pattern:gsub("%.", "%%."):gsub("%*", ".*"):gsub("?", "(.*)")).."$"
return (file:match(depattern))
end
--- Construct all possible patterns for a name and add to the files array.
-- Run through the patterns array replacing all occurrences of "?"
-- with the given file name and store them in the files array.
-- @param file string A raw name (e.g. "foo")
-- @param array of string An array of patterns with "?" as the wildcard
-- (e.g. {"?.so", "lib?.so"})
-- @param files The array of constructed names
local function add_all_patterns(file, patterns, files)
for _, pattern in ipairs(patterns) do
table.insert(files, {#files + 1, (pattern:gsub("?", file))})
end
end
local function get_external_deps_dirs(mode)
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
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
return dirs
end
local function resolve_prefix(prefix, dirs)
if type(prefix) == "string" then
return prefix
elseif 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
return prefix.prefix
end
end
local function add_patterns_for_file(files, file, patterns)
-- If it doesn't look like it contains a filename extension
if not (file:match("%.[a-z]+$") or file:match("%.[a-z]+%.")) then
add_all_patterns(file, patterns, files)
else
for _, pattern in ipairs(patterns) do
local matched = deconstruct_pattern(file, pattern)
if matched then
add_all_patterns(matched, patterns, files)
end
end
table.insert(files, {#files + 1, file})
end
end
local function check_external_dependency_at(prefix, name, ext_files, vars, dirs, err_files, cache)
local fs = require("luarocks.fs")
cache = cache or {}
for dirname, dirdata in util.sortedpairs(dirs) do
local paths
local path_var_value = vars[name.."_"..dirname]
if path_var_value then
paths = { path_var_value }
elseif type(dirdata.subdir) == "table" then
paths = {}
for i,v in ipairs(dirdata.subdir) do
paths[i] = dir.path(prefix, v)
end
else
paths = { dir.path(prefix, dirdata.subdir) }
end
dirdata.dir = paths[1]
local file_or_files = ext_files[dirdata.testfile]
if file_or_files then
local files = {}
if type(file_or_files) == "string" then
add_patterns_for_file(files, file_or_files, dirdata.pattern)
elseif type(file_or_files) == "table" then
for _, f in ipairs(file_or_files) do
add_patterns_for_file(files, f, dirdata.pattern)
end
end
local found = false
table.sort(files, function(a, b)
if (not a[2]:match("%*")) and b[2]:match("%*") then
return true
elseif a[2]:match("%*") and (not b[2]:match("%*")) then
return false
else
return a[1] < b[1]
end
end)
for _, fa in ipairs(files) do
local f = fa[2]
-- small convenience hack
if f:match("%.so$") or f:match("%.dylib$") or f:match("%.dll$") then
f = f:gsub("%.[^.]+$", "."..cfg.external_lib_extension)
end
local pattern
if f:match("%*") then
pattern = "^" .. f:gsub("([-.+])", "%%%1"):gsub("%*", ".*") .. "$"
f = "matching "..f
end
for _, d in ipairs(paths) do
if pattern then
if not cache[d] then
cache[d] = fs.list_dir(d)
end
local match = string.match
for _, entry in ipairs(cache[d]) do
if match(entry, pattern) then
found = true
break
end
end
else
found = fs.is_file(dir.path(d, f))
end
if found then
dirdata.dir = d
dirdata.file = f
break
else
table.insert(err_files[dirdata.testfile], f.." in "..d)
end
end
if found then
break
end
end
if not found then
return nil, dirname, dirdata.testfile
end
end
end
for dirname, dirdata in pairs(dirs) do
vars[name.."_"..dirname] = dirdata.dir
vars[name.."_"..dirname.."_FILE"] = dirdata.file
end
vars[name.."_DIR"] = prefix
return true
end
local function check_external_dependency(name, ext_files, vars, mode, cache)
local ok
local err_dirname
local err_testfile
local err_files = {program = {}, header = {}, library = {}}
local dirs = get_external_deps_dirs(mode)
local prefixes
if vars[name .. "_DIR"] then
prefixes = { vars[name .. "_DIR"] }
elseif vars.DEPS_DIR then
prefixes = { vars.DEPS_DIR }
else
prefixes = cfg.external_deps_dirs
end
for _, prefix in ipairs(prefixes) do
prefix = resolve_prefix(prefix, dirs)
if cfg.is_platform("mingw32") and name == "LUA" then
dirs.LIBDIR.pattern = fun.filter(util.deep_copy(dirs.LIBDIR.pattern), function(s)
return not s:match("%.a$")
end)
elseif cfg.is_platform("windows") and name == "LUA" then
dirs.LIBDIR.pattern = fun.filter(util.deep_copy(dirs.LIBDIR.pattern), function(s)
return not s:match("%.dll$")
end)
end
ok, err_dirname, err_testfile = check_external_dependency_at(prefix, name, ext_files, vars, dirs, err_files, cache)
if ok then
return true
end
end
return nil, err_dirname, err_testfile, err_files
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: <key>_DIR, <key>_BINDIR,
-- <key>_INCDIR and <key>_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 deps.check_external_deps(rockspec, mode)
assert(rockspec:type() == "rockspec")
if not rockspec.external_dependencies then
rockspec.external_dependencies = builtin.autodetect_external_dependencies(rockspec.build)
end
if not rockspec.external_dependencies then
return true
end
for name, ext_files in util.sortedpairs(rockspec.external_dependencies) do
local ok, err_dirname, err_testfile, err_files = check_external_dependency(name, ext_files, rockspec.variables, mode)
if not ok then
local lines = {"Could not find "..err_testfile.." file for "..name}
local err_paths = {}
for _, err_file in ipairs(err_files[err_testfile]) do
if not err_paths[err_file] then
err_paths[err_file] = true
table.insert(lines, " No file "..err_file)
end
end
table.insert(lines, "You may have to install "..name.." in your system and/or pass "..name.."_DIR or "..name.."_"..err_dirname.." to the luarocks command.")
table.insert(lines, "Example: luarocks install "..rockspec.name.." "..name.."_DIR=/usr/local")
return nil, table.concat(lines, "\n"), "dependency"
end
end
return true
end
--- Recursively add satisfied dependencies of a package to a table,
-- to build a transitive closure of all dependent packages.
-- Additionally ensures that `dependencies` table of the manifest is up-to-date.
-- @param results table: The results table being built, maps package names to versions.
-- @param manifest table: The manifest table containing dependencies.
-- @param name string: Package name.
-- @param version string: Package version.
function deps.scan_deps(results, manifest, name, version, deps_mode)
assert(type(results) == "table")
assert(type(manifest) == "table")
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
local fetch = require("luarocks.fetch")
if results[name] then
return
end
if not manifest.dependencies then manifest.dependencies = {} end
local md = manifest.dependencies
if not md[name] then md[name] = {} end
local mdn = md[name]
local dependencies = mdn[version]
local rocks_provided
if not dependencies then
local rockspec, err = fetch.load_local_rockspec(path.rockspec_file(name, version), false)
if not rockspec then
util.printerr("Couldn't load rockspec for "..name.." "..version..": "..err)
return
end
dependencies = rockspec.dependencies
rocks_provided = rockspec.rocks_provided
mdn[version] = dependencies
else
rocks_provided = util.get_rocks_provided()
end
local get_versions = prepare_get_versions(deps_mode, rocks_provided, "dependencies")
local matched = match_all_deps(dependencies, get_versions)
results[name] = version
for _, match in pairs(matched) do
deps.scan_deps(results, manifest, match.name, match.version, deps_mode)
end
end
local function lua_h_exists(d, luaver)
local n = tonumber(luaver)
local major = math.floor(n)
local minor = (n - major) * 10
local luanum = math.floor(major * 100 + minor)
local lua_h = dir.path(d, "lua.h")
local fd = io.open(lua_h)
if fd then
local data = fd:read("*a")
fd:close()
if data:match("LUA_VERSION_NUM%s*" .. tostring(luanum)) then
return d
end
return nil, "Lua header mismatches configured version. You may need to install them or configure LUA_INCDIR.", "dependency"
end
return nil, "Failed finding Lua header files. You may need to install them or configure LUA_INCDIR.", "dependency"
end
local function find_lua_incdir(prefix, luaver, luajitver)
luajitver = luajitver and luajitver:gsub("%-.*", "")
local shortv = luaver:gsub("%.", "")
local incdirs = {
prefix .. "/include/lua/" .. luaver,
prefix .. "/include/lua" .. luaver,
prefix .. "/include/lua-" .. luaver,
prefix .. "/include/lua" .. shortv,
prefix .. "/include",
prefix,
luajitver and prefix .. "/include/luajit-" .. luajitver:match("^(%d+%.%d+)"),
}
for _, d in ipairs(incdirs) do
if lua_h_exists(d, luaver) then
return d
end
end
-- not found, will fallback to a default
return nil
end
function deps.check_lua_incdir(vars)
local ljv = util.get_luajit_version()
if vars.LUA_INCDIR then
return lua_h_exists(vars.LUA_INCDIR, cfg.lua_version)
end
if vars.LUA_DIR then
vars.LUA_INCDIR = find_lua_incdir(vars.LUA_DIR, cfg.lua_version, ljv)
if vars.LUA_INCDIR then
return true
end
end
return nil, "Failed finding Lua header files. You may need to install them or configure LUA_INCDIR.", "dependency"
end
function deps.check_lua_libdir(vars)
local fs = require("luarocks.fs")
local ljv = util.get_luajit_version()
if vars.LUA_LIBDIR and vars.LUALIB and fs.exists(dir.path(vars.LUA_LIBDIR, vars.LUALIB)) then
return true
end
local shortv = cfg.lua_version:gsub("%.", "")
local libnames = {
"lua" .. cfg.lua_version,
"lua" .. shortv,
"lua-" .. cfg.lua_version,
"lua-" .. shortv,
"lua",
}
if ljv then
table.insert(libnames, 1, "luajit-" .. cfg.lua_version)
end
local cache = {}
local save_LUA_INCDIR = vars.LUA_INCDIR
local ok = check_external_dependency("LUA", { library = libnames }, vars, "build", cache)
vars.LUA_INCDIR = save_LUA_INCDIR
if ok then
if fs.exists(dir.path(vars.LUA_LIBDIR, vars.LUA_LIBDIR_FILE)) then
vars.LUALIB = vars.LUA_LIBDIR_FILE
end
return true
end
return nil, "Failed finding Lua library. You may need to configure LUA_LIBDIR.", "dependency"
end
function deps.get_deps_mode(args)
return args.deps_mode or cfg.deps_mode
end
return deps

View file

@ -1,48 +0,0 @@
--- Generic utilities for handling pathnames.
local dir = {}
local core = require("luarocks.core.dir")
dir.path = core.path
dir.split_url = core.split_url
dir.normalize = core.normalize
--- 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 dir.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.dir_name(pathname)
assert(type(pathname) == "string")
return (pathname:gsub("/*$", ""):match("(.*)[/]+[^/]*")) or ""
end
--- Returns true if protocol does not require additional tools.
-- @param protocol The protocol name
function dir.is_basic_protocol(protocol)
return protocol == "http" or protocol == "https" or protocol == "ftp" or protocol == "file"
end
function dir.deduce_base_dir(url)
-- for extensions like foo.tar.gz, "gz" is stripped first
local known_exts = {}
for _, ext in ipairs{"zip", "git", "tgz", "tar", "gz", "bz2"} do
known_exts[ext] = ""
end
local base = dir.base_name(url)
return (base:gsub("%.([^.]*)$", known_exts):gsub("%.tar", ""))
end
return dir

View file

@ -1,68 +0,0 @@
local download = {}
local path = require("luarocks.path")
local fetch = require("luarocks.fetch")
local search = require("luarocks.search")
local queries = require("luarocks.queries")
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local util = require("luarocks.util")
local function get_file(filename)
local protocol, pathname = dir.split_url(filename)
if protocol == "file" then
local ok, err = fs.copy(pathname, fs.current_dir(), "read")
if ok then
return pathname
else
return nil, err
end
else
-- discard third result
local ok, err = fetch.fetch_url(filename)
return ok, err
end
end
function download.download(arch, name, namespace, version, all, check_lua_versions)
local substring = (all and name == "")
local query = queries.new(name, namespace, version, substring, arch)
local search_err
if all then
local results = search.search_repos(query)
local has_result = false
local all_ok = true
local any_err = ""
for name, result in pairs(results) do -- luacheck: ignore 422
for version, items in pairs(result) do -- luacheck: ignore 422
for _, item in ipairs(items) do
-- Ignore provided rocks.
if item.arch ~= "installed" then
has_result = true
local filename = path.make_url(item.repo, name, version, item.arch)
local ok, err = get_file(filename)
if not ok then
all_ok = false
any_err = any_err .. "\n" .. err
end
end
end
end
end
if has_result then
return all_ok, any_err
end
else
local url
url, search_err = search.find_rock_checking_lua_versions(query, check_lua_versions)
if url then
return get_file(url)
end
end
local rock = util.format_rock_name(name, namespace, version)
return nil, "Could not find a result named "..rock..(search_err and ": "..search_err or ".")
end
return download

View file

@ -1,537 +0,0 @@
--- Functions related to fetching and loading local and remote files.
local fetch = {}
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local rockspecs = require("luarocks.rockspecs")
local signing = require("luarocks.signing")
local persist = require("luarocks.persist")
local util = require("luarocks.util")
local cfg = require("luarocks.core.cfg")
--- Fetch a local or remote file, using a local cache directory.
-- 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 mirroring string: mirroring mode.
-- If set to "no_mirror", then rocks_servers mirror configuration is not used.
-- @return (string, nil, nil, boolean) or (nil, string, [string]):
-- in case of success:
-- * the absolute local pathname for the fetched file
-- * nil
-- * nil
-- * `true` if the file was fetched from cache
-- in case of failure:
-- * nil
-- * an error message
-- * an optional error code.
function fetch.fetch_caching(url, mirroring)
local repo_url, filename = url:match("^(.*)/([^/]+)$")
local name = repo_url:gsub("[/:]","_")
local cache_dir = dir.path(cfg.local_cache, name)
local ok = fs.make_dir(cache_dir)
if not ok then
cfg.local_cache = fs.make_temp_dir("local_cache")
cache_dir = dir.path(cfg.local_cache, name)
ok = fs.make_dir(cache_dir)
if not ok then
return nil, "Failed creating temporary cache directory "..cache_dir
end
end
local cachefile = dir.path(cache_dir, filename)
if cfg.aggressive_cache and (not name:match("^manifest")) and fs.exists(cachefile) then
return cachefile, nil, nil, true
end
local file, err, errcode, from_cache = fetch.fetch_url(url, cachefile, true, mirroring)
if not file then
return nil, err or "Failed downloading "..url, errcode
end
return file, nil, nil, from_cache
end
local function ensure_trailing_slash(url)
return (url:gsub("/*$", "/"))
end
local function is_url_relative_to_rocks_servers(url, servers)
for _, item in ipairs(servers) do
if type(item) == "table" then
for i, s in ipairs(item) do
local base = ensure_trailing_slash(s)
if string.find(url, base, 1, true) == 1 then
return i, url:sub(#base + 1), item
end
end
end
end
end
local function download_with_mirrors(url, filename, cache, servers)
local idx, rest, mirrors = is_url_relative_to_rocks_servers(url, servers)
if not idx then
-- URL is not from a rock server
return fs.download(url, filename, cache)
end
-- URL is from a rock server: try to download it falling back to mirrors.
local err = "\n"
for i = idx, #mirrors do
local try_url = ensure_trailing_slash(mirrors[i]) .. rest
if i > idx then
util.warning("Failed downloading. Attempting mirror at " .. try_url)
end
local ok, name, from_cache = fs.download(try_url, filename, cache)
if ok then
return ok, name, from_cache
else
err = err .. name .. "\n"
end
end
return nil, err
end
--- Fetch a local or remote file.
-- Make a remote or local URL/pathname local, fetching the file if necessary.
-- Other "fetch" and "load" functions use this function to obtain files.
-- 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.
-- @param cache boolean: compare remote timestamps via HTTP HEAD prior to
-- re-downloading the file.
-- @param mirroring string: mirroring mode.
-- If set to "no_mirror", then rocks_servers mirror configuration is not used.
-- @return (string, nil, nil, boolean) or (nil, string, [string]):
-- in case of success:
-- * the absolute local pathname for the fetched file
-- * nil
-- * nil
-- * `true` if the file was fetched from cache
-- in case of failure:
-- * nil
-- * an error message
-- * an optional error code.
function fetch.fetch_url(url, filename, cache, mirroring)
assert(type(url) == "string")
assert(type(filename) == "string" or not filename)
local protocol, pathname = dir.split_url(url)
if protocol == "file" then
local fullname = dir.normalize(fs.absolute_name(pathname))
if not fs.exists(fullname) then
local hint = (not pathname:match("^/"))
and (" - note that given path in rockspec is not absolute: " .. url)
or ""
return nil, "Local file not found: " .. fullname .. hint
end
filename = filename or dir.base_name(pathname)
local dstname = dir.normalize(fs.absolute_name(dir.path(".", filename)))
local ok, err
if fullname == dstname then
ok = true
else
ok, err = fs.copy(fullname, dstname)
end
if ok then
return dstname
else
return nil, "Failed copying local file " .. fullname .. " to " .. dstname .. ": " .. err
end
elseif dir.is_basic_protocol(protocol) then
local ok, name, from_cache
if mirroring ~= "no_mirror" then
ok, name, from_cache = download_with_mirrors(url, filename, cache, cfg.rocks_servers)
else
ok, name, from_cache = fs.download(url, filename, cache)
end
if not ok then
return nil, "Failed downloading "..url..(name and " - "..name or ""), "network"
end
return name, nil, nil, from_cache
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.fetch_url_at_temp_dir(url, tmpname, filename, cache)
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, err = fs.make_temp_dir(tmpname)
if not temp_dir then
return nil, "Failed creating temporary directory "..tmpname..": "..err
end
util.schedule_function(fs.delete, temp_dir)
local ok, err = fs.change_dir(temp_dir)
if not ok then return nil, err end
local file, err, errcode
if cache then
local cachefile
cachefile, err, errcode = fetch.fetch_caching(url)
if cachefile then
file = dir.path(temp_dir, filename)
fs.copy(cachefile, file)
end
else
file, err, errcode = fetch.fetch_url(url, filename, cache)
end
fs.pop_dir()
if not file then
return nil, "Error fetching file: "..err, errcode
end
return file, temp_dir
end
end
-- Determine base directory of a fetched URL by extracting its
-- archive and looking for a directory in the root.
-- @param file string: absolute local pathname of the fetched file
-- @param temp_dir string: temporary directory in which URL was fetched.
-- @param src_url string: URL to use when inferring base directory.
-- @param src_dir string or nil: expected base directory (inferred
-- from src_url if not given).
-- @return (string, string) or (string, nil) or (nil, string):
-- The inferred base directory and the one actually found (which may
-- be nil if not found), or nil followed by an error message.
-- The inferred dir is returned first to avoid confusion with errors,
-- because it is never nil.
function fetch.find_base_dir(file, temp_dir, src_url, src_dir)
local ok, err = fs.change_dir(temp_dir)
if not ok then return nil, err end
fs.unpack_archive(file)
local inferred_dir = src_dir or dir.deduce_base_dir(src_url)
local found_dir = nil
if fs.exists(inferred_dir) then
found_dir = inferred_dir
else
util.printerr("Directory "..inferred_dir.." not found")
local files = fs.list_dir()
if files then
table.sort(files)
for i,filename in ipairs(files) do
if fs.is_dir(filename) then
util.printerr("Found "..filename)
found_dir = filename
break
end
end
end
end
fs.pop_dir()
return inferred_dir, found_dir
end
local function fetch_and_verify_signature_for(url, filename, tmpdir)
local sig_url = signing.signature_url(url)
local sig_file, err, errcode = fetch.fetch_url_at_temp_dir(sig_url, tmpdir)
if not sig_file then
return nil, "Could not fetch signature file for verification: " .. err, errcode
end
local ok, err = signing.verify_signature(filename, sig_file)
if not ok then
return nil, "Failed signature verification: " .. err
end
return fs.absolute_name(sig_file)
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.
-- @param verify boolean: if true, download and verify signature for rockspec
-- @return string or (nil, string, [string]): the directory containing the contents
-- of the unpacked rock.
function fetch.fetch_and_unpack_rock(url, dest, verify)
assert(type(url) == "string")
assert(type(dest) == "string" or not dest)
local name = dir.base_name(url):match("(.*)%.[^.]*%.rock")
local tmpname = "luarocks-rock-" .. name
local rock_file, err, errcode = fetch.fetch_url_at_temp_dir(url, tmpname, nil, true)
if not rock_file then
return nil, "Could not fetch rock file: " .. err, errcode
end
local sig_file
if verify then
sig_file, err = fetch_and_verify_signature_for(url, rock_file, tmpname)
if err then
return nil, err
end
end
rock_file = fs.absolute_name(rock_file)
local unpack_dir
if dest then
unpack_dir = dest
local ok, err = fs.make_dir(unpack_dir)
if not ok then
return nil, "Failed unpacking rock file: " .. err
end
else
unpack_dir, err = fs.make_temp_dir(name)
if not unpack_dir then
return nil, "Failed creating temporary dir: " .. err
end
end
if not dest then
util.schedule_function(fs.delete, unpack_dir)
end
local ok, err = fs.change_dir(unpack_dir)
if not ok then return nil, err end
ok, err = fs.unzip(rock_file)
if not ok then
return nil, "Failed unpacking rock file: " .. rock_file .. ": " .. err
end
if sig_file then
ok, err = fs.copy(sig_file, ".")
if not ok then
return nil, "Failed copying signature file"
end
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 rel_filename string: The local filename of the rockspec file.
-- @param quick boolean: if true, skips some steps when loading
-- rockspec.
-- @return table or (nil, string): A table representing the rockspec
-- or nil followed by an error message.
function fetch.load_local_rockspec(rel_filename, quick)
assert(type(rel_filename) == "string")
local abs_filename = fs.absolute_name(rel_filename)
local basename = dir.base_name(abs_filename)
if basename ~= "rockspec" then
if not basename:match("(.*)%-[^-]*%-[0-9]*") then
return nil, "Expected filename in format 'name-version-revision.rockspec'."
end
end
local tbl, err = persist.load_into_table(abs_filename)
if not tbl then
return nil, "Could not load rockspec file "..abs_filename.." ("..err..")"
end
local rockspec, err = rockspecs.from_persisted_table(abs_filename, tbl, err, quick)
if not rockspec then
return nil, abs_filename .. ": " .. err
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
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.
-- @param verify boolean: if true, download and verify signature for rockspec
-- @return table or (nil, string, [string]): A table representing the rockspec
-- or nil followed by an error message and optional error code.
function fetch.load_rockspec(url, location, verify)
assert(type(url) == "string")
local name
local basename = dir.base_name(url)
if basename == "rockspec" then
name = "rockspec"
else
name = basename:match("(.*)%.rockspec")
if not name then
return nil, "Filename '"..url.."' does not look like a rockspec."
end
end
local tmpname = "luarocks-rockspec-"..name
local filename, err, errcode
if location then
local ok, err = fs.change_dir(location)
if not ok then return nil, err end
filename, err = fetch.fetch_url(url)
fs.pop_dir()
else
filename, err, errcode = fetch.fetch_url_at_temp_dir(url, tmpname, nil, true)
end
if not filename then
return nil, err, errcode
end
if verify then
local _, err = fetch_and_verify_signature_for(url, filename, tmpname)
if err then
return nil, err
end
end
return fetch.load_local_rockspec(filename)
end
--- Download sources for building a rock using the basic URL downloader.
-- @param rockspec table: The rockspec table
-- @param extract boolean: Whether to extract the sources from
-- the fetched source tarball or not.
-- @param dest_dir string or nil: If set, will extract to the given directory;
-- if not given, will extract to a temporary directory.
-- @return (string, string) or (nil, string, [string]): The absolute pathname of
-- the fetched source tarball and the temporary directory created to
-- store it; or nil and an error message and optional error code.
function fetch.get_sources(rockspec, extract, dest_dir)
assert(rockspec:type() == "rockspec")
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
local ok, err, errcode
if dest_dir then
ok, err = fs.change_dir(dest_dir)
if not ok then return nil, err, "dest_dir" end
source_file, err, errcode = fetch.fetch_url(url, filename)
fs.pop_dir()
store_dir = dest_dir
else
source_file, store_dir, errcode = fetch.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.", "md5"
end
end
if extract then
local ok, err = fs.change_dir(store_dir)
if not ok then return nil, err end
ok, err = fs.unpack_archive(rockspec.source.file)
if not ok then return nil, err end
if not fs.exists(rockspec.source.dir) then
-- If rockspec.source.dir can't be found, see if we only have one
-- directory in store_dir. If that's the case, assume it's what
-- we're looking for.
-- We only do this if the rockspec source.dir was not set, and only
-- with rockspecs newer than 3.0.
local file_count, found_dir = 0
if not rockspec.source.dir_set and rockspec:format_is_at_least("3.0") then
for file in fs.dir() do
file_count = file_count + 1
if fs.is_dir(file) then
found_dir = file
end
end
end
if file_count == 1 and found_dir then
rockspec.source.dir = found_dir
else
return nil, "Directory "..rockspec.source.dir.." not found inside archive "..rockspec.source.file, "source.dir", source_file, store_dir
end
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.
-- if not given, will extract to a temporary directory.
-- @return (string, string) or (nil, string): The absolute pathname of
-- the fetched source tarball and the temporary directory created to
-- store it; or nil and an error message.
function fetch.fetch_sources(rockspec, extract, dest_dir)
assert(rockspec:type() == "rockspec")
assert(type(extract) == "boolean")
assert(type(dest_dir) == "string" or not dest_dir)
-- auto-convert git://github.com URLs to use git+https
-- see https://github.blog/2021-09-01-improving-git-protocol-security-github/
if rockspec.source.url:match("^git://github%.com/")
or rockspec.source.url:match("^git://www%.github%.com/") then
rockspec.source.url = rockspec.source.url:gsub("^git://", "git+https://")
rockspec.source.protocol = "git+https"
end
local protocol = rockspec.source.protocol
local ok, proto
if dir.is_basic_protocol(protocol) then
proto = 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
return fetch

View file

@ -1,55 +0,0 @@
--- Fetch back-end for retrieving sources from CVS.
local cvs = {}
local unpack = unpack or table.unpack
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 cvs.get_sources(rockspec, extract, dest_dir)
assert(rockspec:type() == "rockspec")
assert(type(dest_dir) == "string" or not dest_dir)
local cvs_cmd = rockspec.variables.CVS
local ok, err_msg = fs.is_tool_available(cvs_cmd, "CVS")
if not ok then
return nil, err_msg
end
local name_version = rockspec.name .. "-" .. rockspec.version
local module = rockspec.source.module or dir.base_name(rockspec.source.url)
local command = {cvs_cmd, "-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
local ok, err = fs.change_dir(store_dir)
if not ok then return nil, err end
if not fs.execute(unpack(command)) then
return nil, "Failed fetching files from CVS."
end
fs.pop_dir()
return module, store_dir
end
return cvs

View file

@ -1,165 +0,0 @@
--- Fetch back-end for retrieving sources from GIT.
local git = {}
local unpack = unpack or table.unpack
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local vers = require("luarocks.core.vers")
local util = require("luarocks.util")
local cached_git_version
--- Get git version.
-- @param git_cmd string: name of git command.
-- @return table: git version as returned by luarocks.core.vers.parse_version.
local function git_version(git_cmd)
if not cached_git_version then
local version_line = io.popen(fs.Q(git_cmd)..' --version'):read()
local version_string = version_line:match('%d-%.%d+%.?%d*')
cached_git_version = vers.parse_version(version_string)
end
return cached_git_version
end
--- Check if git satisfies version requirement.
-- @param git_cmd string: name of git command.
-- @param version string: required version.
-- @return boolean: true if git matches version or is newer, false otherwise.
local function git_is_at_least(git_cmd, version)
return git_version(git_cmd) >= vers.parse_version(version)
end
--- Git >= 1.7.10 can clone a branch **or tag**, < 1.7.10 by branch only. We
-- need to know this in order to build the appropriate command; if we can't
-- clone by tag then we'll have to issue a subsequent command to check out the
-- given tag.
-- @param git_cmd string: name of git command.
-- @return boolean: Whether Git can clone by tag.
local function git_can_clone_by_tag(git_cmd)
return git_is_at_least(git_cmd, "1.7.10")
end
--- Git >= 1.8.4 can fetch submodules shallowly, saving bandwidth and time for
-- submodules with large history.
-- @param git_cmd string: name of git command.
-- @return boolean: Whether Git can fetch submodules shallowly.
local function git_supports_shallow_submodules(git_cmd)
return git_is_at_least(git_cmd, "1.8.4")
end
--- Git >= 2.10 can fetch submodules shallowly according to .gitmodules configuration, allowing more granularity.
-- @param git_cmd string: name of git command.
-- @return boolean: Whether Git can fetch submodules shallowly according to .gitmodules.
local function git_supports_shallow_recommendations(git_cmd)
return git_is_at_least(git_cmd, "2.10.0")
end
local function git_identifier(git_cmd, ver)
if not (ver:match("^dev%-%d+$") or ver:match("^scm%-%d+$")) then
return nil
end
local pd = io.popen(fs.command_at(fs.current_dir(), fs.Q(git_cmd).." log --pretty=format:%ai_%h -n 1"))
if not pd then
return nil
end
local date_hash = pd:read("*l")
pd:close()
if not date_hash then
return nil
end
local date, time, tz, hash = date_hash:match("([^%s]+) ([^%s]+) ([^%s]+)_([^%s]+)")
date = date:gsub("%-", "")
time = time:gsub(":", "")
return date .. "." .. time .. "." .. hash
end
--- 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 git.get_sources(rockspec, extract, dest_dir, depth)
assert(rockspec:type() == "rockspec")
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 ok, err_msg = fs.is_tool_available(git_cmd, "Git")
if not ok then
return nil, err_msg
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)
local ok, err = fs.change_dir(store_dir)
if not ok then return nil, err end
local command = {fs.Q(git_cmd), "clone", depth or "--depth=1", rockspec.source.url, module}
local tag_or_branch = rockspec.source.tag or rockspec.source.branch
-- If the tag or branch is explicitly set to "master" in the rockspec, then
-- we can avoid passing it to Git since it's the default.
if tag_or_branch == "master" then tag_or_branch = nil end
if tag_or_branch then
if git_can_clone_by_tag(git_cmd) then
-- The argument to `--branch` can actually be a branch or a tag as of
-- Git 1.7.10.
table.insert(command, 3, "--branch=" .. tag_or_branch)
end
end
if not fs.execute(unpack(command)) then
return nil, "Failed cloning git repository."
end
ok, err = fs.change_dir(module)
if not ok then return nil, err end
if tag_or_branch and not git_can_clone_by_tag() then
if not fs.execute(fs.Q(git_cmd), "checkout", tag_or_branch) then
return nil, 'Failed to check out the "' .. tag_or_branch ..'" tag or branch.'
end
end
-- Fetching git submodules is supported only when rockspec format is >= 3.0.
if rockspec:format_is_at_least("3.0") then
command = {fs.Q(git_cmd), "submodule", "update", "--init", "--recursive"}
if git_supports_shallow_recommendations(git_cmd) then
table.insert(command, 5, "--recommend-shallow")
elseif git_supports_shallow_submodules(git_cmd) then
-- Fetch only the last commit of each submodule.
table.insert(command, 5, "--depth=1")
end
if not fs.execute(unpack(command)) then
return nil, 'Failed to fetch submodules.'
end
end
if not rockspec.source.tag then
rockspec.source.identifier = git_identifier(git_cmd, rockspec.version)
end
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
return git

View file

@ -1,19 +0,0 @@
--- Fetch back-end for retrieving sources from local Git repositories.
local git_file = {}
local git = require("luarocks.fetch.git")
--- Fetch sources for building a rock from a local Git repository.
-- @param rockspec table: The rockspec table
-- @param extract boolean: Unused in this module (required for API purposes.)
-- @param dest_dir string or nil: If set, will extract to the given directory.
-- @return (string, string) or (nil, string): The absolute pathname of
-- the fetched source tarball and the temporary directory created to
-- store it; or nil and an error message.
function git_file.get_sources(rockspec, extract, dest_dir)
rockspec.source.url = rockspec.source.url:gsub("^git.file://", "")
return git.get_sources(rockspec, extract, dest_dir)
end
return git_file

View file

@ -1,26 +0,0 @@
--- Fetch back-end for retrieving sources from Git repositories
-- that use http:// transport. For example, for fetching a repository
-- that requires the following command line:
-- `git clone http://example.com/foo.git`
-- you can use this in the rockspec:
-- source = { url = "git+http://example.com/foo.git" }
-- Prefer using the normal git:// fetch mode as it is more widely
-- available in older versions of LuaRocks.
local git_http = {}
local git = require("luarocks.fetch.git")
--- Fetch sources for building a rock from a local Git repository.
-- @param rockspec table: The rockspec table
-- @param extract boolean: Unused in this module (required for API purposes.)
-- @param dest_dir string or nil: If set, will extract to the given directory.
-- @return (string, string) or (nil, string): The absolute pathname of
-- the fetched source tarball and the temporary directory created to
-- store it; or nil and an error message.
function git_http.get_sources(rockspec, extract, dest_dir)
rockspec.source.url = rockspec.source.url:gsub("^git.", "")
return git.get_sources(rockspec, extract, dest_dir, "--")
end
return git_http

View file

@ -1,7 +0,0 @@
--- Fetch back-end for retrieving sources from Git repositories
-- that use https:// transport. For example, for fetching a repository
-- that requires the following command line:
-- `git clone https://example.com/foo.git`
-- you can use this in the rockspec:
-- source = { url = "git+https://example.com/foo.git" }
return require "luarocks.fetch.git_http"

View file

@ -1,32 +0,0 @@
--- Fetch back-end for retrieving sources from Git repositories
-- that use ssh:// transport. For example, for fetching a repository
-- that requires the following command line:
-- `git clone ssh://git@example.com/path/foo.git
-- you can use this in the rockspec:
-- source = { url = "git+ssh://git@example.com/path/foo.git" }
-- It also handles scp-style ssh urls: git@example.com:path/foo.git,
-- but you have to prepend the "git+ssh://" and why not use the "newer"
-- style anyway?
local git_ssh = {}
local git = require("luarocks.fetch.git")
--- Fetch sources for building a rock from a local Git repository.
-- @param rockspec table: The rockspec table
-- @param extract boolean: Unused in this module (required for API purposes.)
-- @param dest_dir string or nil: If set, will extract to the given directory.
-- @return (string, string) or (nil, string): The absolute pathname of
-- the fetched source tarball and the temporary directory created to
-- store it; or nil and an error message.
function git_ssh.get_sources(rockspec, extract, dest_dir)
rockspec.source.url = rockspec.source.url:gsub("^git.", "")
-- Handle old-style scp-like git ssh urls
if rockspec.source.url:match("^ssh://[^/]+:[^%d]") then
rockspec.source.url = rockspec.source.url:gsub("^ssh://", "")
end
return git.get_sources(rockspec, extract, dest_dir, "--")
end
return git_ssh

View file

@ -1,65 +0,0 @@
--- Fetch back-end for retrieving sources from HG.
local hg = {}
local unpack = unpack or table.unpack
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 hg.get_sources(rockspec, extract, dest_dir)
assert(rockspec:type() == "rockspec")
assert(type(dest_dir) == "string" or not dest_dir)
local hg_cmd = rockspec.variables.HG
local ok, err_msg = fs.is_tool_available(hg_cmd, "Mercurial")
if not ok then
return nil, err_msg
end
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", tag_or_branch, 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
local ok, err = fs.change_dir(store_dir)
if not ok then return nil, err end
if not fs.execute(unpack(command)) then
return nil, "Failed cloning hg repository."
end
ok, err = fs.change_dir(module)
if not ok then return nil, err end
fs.delete(dir.path(store_dir, module, ".hg"))
fs.delete(dir.path(store_dir, module, ".hgignore"))
fs.pop_dir()
fs.pop_dir()
return module, store_dir
end
return hg

View file

@ -1,24 +0,0 @@
--- Fetch back-end for retrieving sources from hg repositories
-- that use http:// transport. For example, for fetching a repository
-- that requires the following command line:
-- `hg clone http://example.com/foo`
-- you can use this in the rockspec:
-- source = { url = "hg+http://example.com/foo" }
local hg_http = {}
local hg = require("luarocks.fetch.hg")
--- Download sources for building a rock, using hg over http.
-- @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 hg_http.get_sources(rockspec, extract, dest_dir)
rockspec.source.url = rockspec.source.url:gsub("^hg.", "")
return hg.get_sources(rockspec, extract, dest_dir)
end
return hg_http

View file

@ -1,8 +0,0 @@
--- Fetch back-end for retrieving sources from hg repositories
-- that use https:// transport. For example, for fetching a repository
-- that requires the following command line:
-- `hg clone https://example.com/foo`
-- you can use this in the rockspec:
-- source = { url = "hg+https://example.com/foo" }
return require "luarocks.fetch.hg_http"

View file

@ -1,8 +0,0 @@
--- Fetch back-end for retrieving sources from hg repositories
-- that use ssh:// transport. For example, for fetching a repository
-- that requires the following command line:
-- `hg clone ssh://example.com/foo`
-- you can use this in the rockspec:
-- source = { url = "hg+ssh://example.com/foo" }
return require "luarocks.fetch.hg_http"

View file

@ -1,44 +0,0 @@
--- Fetch back-end for retrieving sources from Surround SCM Server
local sscm = {}
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 sscm.get_sources(rockspec, extract, dest_dir)
assert(rockspec:type() == "rockspec")
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
return sscm

View file

@ -1,64 +0,0 @@
--- Fetch back-end for retrieving sources from Subversion.
local svn = {}
local unpack = unpack or table.unpack
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 svn.get_sources(rockspec, extract, dest_dir)
assert(rockspec:type() == "rockspec")
assert(type(dest_dir) == "string" or not dest_dir)
local svn_cmd = rockspec.variables.SVN
local ok, err_msg = fs.is_tool_available(svn_cmd, "Subversion", "--version")
if not ok then
return nil, err_msg
end
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
local ok, err = fs.change_dir(store_dir)
if not ok then return nil, err end
if not fs.execute(unpack(command)) then
return nil, "Failed fetching files from Subversion."
end
ok, err = fs.change_dir(module)
if not ok then return nil, err end
for _, d in ipairs(fs.find(".")) do
if dir.base_name(d) == ".svn" then
fs.delete(dir.path(store_dir, module, d))
end
end
fs.pop_dir()
fs.pop_dir()
return module, store_dir
end
return svn

View file

@ -1,140 +0,0 @@
--- 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
local fs = {}
-- To avoid a loop when loading the other fs modules.
package.loaded["luarocks.fs"] = fs
local cfg = require("luarocks.core.cfg")
local pack = table.pack or function(...) return { n = select("#", ...), ... } end
local unpack = table.unpack or unpack
math.randomseed(os.time())
local fs_is_verbose = false
do
local old_popen, old_execute
-- patch io.popen and os.execute to display commands in verbose mode
function fs.verbose()
fs_is_verbose = true
if old_popen or old_execute then return end
old_popen = io.popen
-- luacheck: push globals io os
io.popen = function(one, two)
if two == nil then
print("\nio.popen: ", one)
else
print("\nio.popen: ", one, "Mode:", two)
end
return old_popen(one, two)
end
old_execute = os.execute
os.execute = function(cmd)
-- redact api keys if present
print("\nos.execute: ", (cmd:gsub("(/api/[^/]+/)([^/]+)/", function(cap, key) return cap.."<redacted>/" end)) )
local code = pack(old_execute(cmd))
print("Results: "..tostring(code.n))
for i = 1,code.n do
print(" "..tostring(i).." ("..type(code[i]).."): "..tostring(code[i]))
end
return unpack(code, 1, code.n)
end
-- luacheck: pop
end
end
do
local function load_fns(fs_table, inits)
for name, fn in pairs(fs_table) do
if name ~= "init" and not fs[name] then
fs[name] = function(...)
if fs_is_verbose then
local args = pack(...)
for i=1, args.n do
local arg = args[i]
local pok, v = pcall(string.format, "%q", arg)
args[i] = pok and v or tostring(arg)
end
print("fs." .. name .. "(" .. table.concat(args, ", ") .. ")")
end
return fn(...)
end
end
end
if fs_table.init then
table.insert(inits, fs_table.init)
end
end
local function load_platform_fns(patt, inits)
local each_platform = cfg.each_platform
-- FIXME A quick hack for the experimental Windows build
if os.getenv("LUAROCKS_CROSS_COMPILING") then
each_platform = function()
local i = 0
local plats = { "linux", "unix" }
return function()
i = i + 1
return plats[i]
end
end
end
for platform in each_platform("most-specific-first") do
local ok, fs_plat = pcall(require, patt:format(platform))
if ok and fs_plat then
load_fns(fs_plat, inits)
end
end
end
function fs.init()
local inits = {}
if fs.current_dir then
-- unload luarocks fs so it can be reloaded using all modules
-- providing extra functionality in the current package paths
for k, _ in pairs(fs) do
if k ~= "init" and k ~= "verbose" then
fs[k] = nil
end
end
for m, _ in pairs(package.loaded) do
if m:match("luarocks%.fs%.") then
package.loaded[m] = nil
end
end
end
-- Load platform-specific functions
load_platform_fns("luarocks.fs.%s", inits)
-- Load platform-independent pure-Lua functionality
load_fns(require("luarocks.fs.lua"), inits)
-- Load platform-specific fallbacks for missing Lua modules
load_platform_fns("luarocks.fs.%s.tools", inits)
-- Load platform-independent external tool functionality
load_fns(require("luarocks.fs.tools"), inits)
-- Run platform-specific initializations after everything is loaded
for _, init in ipairs(inits) do
init()
end
end
end
return fs

View file

@ -1,11 +0,0 @@
--- FreeBSD implementation of filesystem and platform abstractions.
local freebsd = {}
local fs = require("luarocks.fs")
function freebsd.init()
fs.set_tool_available("zip", true)
fs.set_tool_available("unzip", true)
end
return freebsd

View file

@ -1,50 +0,0 @@
--- Linux-specific implementation of filesystem and platform abstractions.
local linux = {}
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
function linux.is_dir(file)
file = fs.absolute_name(file)
file = dir.normalize(file) .. "/."
local fd, _, code = io.open(file, "r")
if code == 2 then -- "No such file or directory"
return false
end
if code == 20 then -- "Not a directory", regardless of permissions
return false
end
if code == 13 then -- "Permission denied", but is a directory
return true
end
if fd then
local _, _, ecode = fd:read(1)
fd:close()
if ecode == 21 then -- "Is a directory"
return true
end
end
return false
end
function linux.is_file(file)
file = fs.absolute_name(file)
if fs.is_dir(file) then
return false
end
file = dir.normalize(file)
local fd, _, code = io.open(file, "r")
if code == 2 then -- "No such file or directory"
return false
end
if code == 13 then -- "Permission denied", but it exists
return true
end
if fd then
fd:close()
return true
end
return false
end
return linux

File diff suppressed because it is too large Load diff

View file

@ -1,50 +0,0 @@
--- macOS-specific implementation of filesystem and platform abstractions.
local macosx = {}
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
function macosx.is_dir(file)
file = fs.absolute_name(file)
file = dir.normalize(file) .. "/."
local fd, _, code = io.open(file, "r")
if code == 2 then -- "No such file or directory"
return false
end
if code == 20 then -- "Not a directory", regardless of permissions
return false
end
if code == 13 then -- "Permission denied", but is a directory
return true
end
if fd then
local _, _, ecode = fd:read(1)
fd:close()
if ecode == 21 then -- "Is a directory"
return true
end
end
return false
end
function macosx.is_file(file)
file = fs.absolute_name(file)
if fs.is_dir(file) then
return false
end
file = dir.normalize(file)
local fd, _, code = io.open(file, "r")
if code == 2 then -- "No such file or directory"
return false
end
if code == 13 then -- "Permission denied", but it exists
return true
end
if fd then
fd:close()
return true
end
return false
end
return macosx

View file

@ -1,14 +0,0 @@
--- NetBSD implementation of filesystem and platform abstractions.
local netbsd = {}
local fs = require("luarocks.fs")
function netbsd.init()
local uz=io.open("/usr/bin/unzip", "r")
if uz ~= nil then
io.close(uz)
fs.set_tool_available("unzip", true)
end
end
return netbsd

View file

@ -1,214 +0,0 @@
--- Common fs operations implemented with third-party tools.
local tools = {}
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local cfg = require("luarocks.core.cfg")
local vars = setmetatable({}, { __index = function(_,k) return cfg.variables[k] end })
local dir_stack = {}
do
local tool_cache = {}
local tool_options = {
downloader = {
desc = "downloader",
{ var = "WGET", name = "wget" },
{ var = "CURL", name = "curl" },
},
md5checker = {
desc = "MD5 checker",
{ var = "MD5SUM", name = "md5sum" },
{ var = "OPENSSL", name = "openssl", cmdarg = "md5", checkarg = "version" },
{ var = "MD5", name = "md5", checkarg = "-shello" },
},
}
function tools.which_tool(tooltype)
local tool = tool_cache[tooltype]
local names = {}
if not tool then
for _, opt in ipairs(tool_options[tooltype]) do
table.insert(names, opt.name)
if fs.is_tool_available(vars[opt.var], opt.name, opt.checkarg) then
tool = opt
tool_cache[tooltype] = opt
break
end
end
end
if not tool then
local tool_names = table.concat(names, ", ", 1, #names - 1) .. " or " .. names[#names]
return nil, "no " .. tool_options[tooltype].desc .. " tool available," .. " please install " .. tool_names .. " in your system"
end
return tool.name, vars[tool.var] .. (tool.cmdarg and " "..tool.cmdarg or "")
end
end
do
local cache_pwd
--- Obtain current directory.
-- Uses the module's internal directory stack.
-- @return string: the absolute pathname of the current directory.
function tools.current_dir()
local current = cache_pwd
if not current then
local pipe = io.popen(fs.quiet_stderr(vars.PWD))
current = pipe:read("*l")
pipe:close()
cache_pwd = current
end
for _, directory in ipairs(dir_stack) do
current = fs.absolute_name(directory, current)
end
return current
end
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.
-- @return boolean or (nil, string): true if successful, (nil, error message) if failed.
function tools.change_dir(directory)
assert(type(directory) == "string")
if fs.is_dir(directory) then
table.insert(dir_stack, directory)
return true
end
return nil, "directory not found: "..directory
end
--- Change directory to root.
-- Allows leaving a directory (e.g. for deleting it) in
-- a crossplatform way.
function tools.change_dir_to_root()
local curr_dir = fs.current_dir()
if not curr_dir or not fs.is_dir(curr_dir) then
return false
end
table.insert(dir_stack, "/")
return true
end
--- Change working directory to the previous in the directory stack.
function tools.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 tools.execute_string(cmd)
local current = fs.current_dir()
if not current then return false end
cmd = fs.command_at(current, cmd)
local code = os.execute(cmd)
if code == 0 or code == true then
return true
else
return false
end
end
--- Internal implementation function for fs.dir.
-- Yields a filename on each iteration.
-- @param at string: directory to list
-- @return nil
function tools.dir_iterator(at)
local pipe = io.popen(fs.command_at(at, vars.LS, true))
for file in pipe:lines() do
if file ~= "." and file ~= ".." then
coroutine.yield(file)
end
end
pipe:close()
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.
-- @param cache boolean: compare remote timestamps via HTTP HEAD prior to
-- re-downloading the file.
-- @return (boolean, string): true and the filename on success,
-- false and the error message on failure.
function tools.use_downloader(url, filename, cache)
assert(type(url) == "string")
assert(type(filename) == "string" or not filename)
filename = fs.absolute_name(filename or dir.base_name(url))
local downloader, err = fs.which_tool("downloader")
if not downloader then
return nil, err
end
local ok = false
if downloader == "wget" then
local wget_cmd = vars.WGET.." "..vars.WGETNOCERTFLAG.." --no-cache --user-agent=\""..cfg.user_agent.." via wget\" --quiet "
if cfg.connection_timeout and cfg.connection_timeout > 0 then
wget_cmd = wget_cmd .. "--timeout="..tostring(cfg.connection_timeout).." --tries=1 "
end
if cache then
-- --timestamping is incompatible with --output-document,
-- but that's not a problem for our use cases.
fs.delete(filename .. ".unixtime")
fs.change_dir(dir.dir_name(filename))
ok = fs.execute_quiet(wget_cmd.." --timestamping ", url)
fs.pop_dir()
elseif filename then
ok = fs.execute_quiet(wget_cmd.." --output-document ", filename, url)
else
ok = fs.execute_quiet(wget_cmd, url)
end
elseif downloader == "curl" then
local curl_cmd = vars.CURL.." "..vars.CURLNOCERTFLAG.." -f -L --user-agent \""..cfg.user_agent.." via curl\" "
if cfg.connection_timeout and cfg.connection_timeout > 0 then
curl_cmd = curl_cmd .. "--connect-timeout "..tostring(cfg.connection_timeout).." "
end
if cache then
curl_cmd = curl_cmd .. " -R -z \"" .. filename .. "\" "
end
ok = fs.execute_string(fs.quiet_stderr(curl_cmd..fs.Q(url).." --output "..fs.Q(filename)))
end
if ok then
return true, filename
else
os.remove(filename)
return false, "failed downloading " .. url
end
end
--- Get the MD5 checksum for a file.
-- @param file string: The file to be computed.
-- @return string: The MD5 checksum or nil + message
function tools.get_md5(file)
local ok, md5checker = fs.which_tool("md5checker")
if not ok then
return false, md5checker
end
local pipe = io.popen(md5checker.." "..fs.Q(fs.absolute_name(file)))
local computed = pipe:read("*l")
pipe:close()
if computed then
computed = computed:match("("..("%x"):rep(32)..")")
end
if computed then
return computed
else
return nil, "Failed to compute MD5 hash for file "..tostring(fs.absolute_name(file))
end
end
return tools

View file

@ -1,236 +0,0 @@
--- Unix implementation of filesystem and platform abstractions.
local unix = {}
local fs = require("luarocks.fs")
local cfg = require("luarocks.core.cfg")
local dir = require("luarocks.dir")
local path = require("luarocks.path")
local util = require("luarocks.util")
--- Annotate command string for quiet execution.
-- @param cmd string: A command-line string.
-- @return string: The command-line, with silencing annotation.
function unix.quiet(cmd)
return cmd.." 1> /dev/null 2> /dev/null"
end
--- Annotate command string for execution with quiet stderr.
-- @param cmd string: A command-line string.
-- @return string: The command-line, with stderr silencing annotation.
function unix.quiet_stderr(cmd)
return cmd.." 2> /dev/null"
end
--- Quote argument for shell processing.
-- Adds single quotes and escapes.
-- @param arg string: Unquoted argument.
-- @return string: Quoted argument.
function unix.Q(arg)
assert(type(arg) == "string")
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 unix.absolute_name(pathname, relative_to)
assert(type(pathname) == "string")
assert(type(relative_to) == "string" or not relative_to)
local unquoted = pathname:match("^['\"](.*)['\"]$")
if unquoted then
pathname = unquoted
end
relative_to = (relative_to or fs.current_dir()):gsub("/*$", "")
if pathname:sub(1,1) == "/" then
return pathname
else
return relative_to .. "/" .. pathname
end
end
--- Return the root directory for the given path.
-- In Unix, root is always "/".
-- @param pathname string: pathname to use.
-- @return string: The root of the given pathname.
function unix.root_of(_)
return "/"
end
--- Create a wrapper to make a script executable from the command-line.
-- @param script string: Pathname of script to be made executable.
-- @param target string: wrapper target pathname (without wrapper suffix).
-- @param name string: rock name to be used in loader context.
-- @param version string: rock version to be used in loader context.
-- @return boolean or (nil, string): True if succeeded, or nil and
-- an error message.
function unix.wrap_script(script, target, deps_mode, name, version, ...)
assert(type(script) == "string" or not script)
assert(type(target) == "string")
assert(type(deps_mode) == "string")
assert(type(name) == "string" or not name)
assert(type(version) == "string" or not version)
local wrapper = io.open(target, "w")
if not wrapper then
return nil, "Could not open "..target.." for writing."
end
local lpath, lcpath = path.package_paths(deps_mode)
local luainit = {
"package.path="..util.LQ(lpath..";").."..package.path",
"package.cpath="..util.LQ(lcpath..";").."..package.cpath",
}
local remove_interpreter = false
if target == "luarocks" or target == "luarocks-admin" then
if cfg.is_binary then
remove_interpreter = true
end
luainit = {
"package.path="..util.LQ(package.path),
"package.cpath="..util.LQ(package.cpath),
}
end
if name and version then
local addctx = "local k,l,_=pcall(require,"..util.LQ("luarocks.loader")..") _=k " ..
"and l.add_context("..util.LQ(name)..","..util.LQ(version)..")"
table.insert(luainit, addctx)
end
local argv = {
fs.Q(dir.path(cfg.variables["LUA_BINDIR"], cfg.lua_interpreter)),
"-e",
fs.Q(table.concat(luainit, ";")),
script and fs.Q(script) or [[$([ "$*" ] || echo -i)]],
...
}
if remove_interpreter then
table.remove(argv, 1)
table.remove(argv, 1)
table.remove(argv, 1)
end
wrapper:write("#!/bin/sh\n\n")
wrapper:write("LUAROCKS_SYSCONFDIR="..fs.Q(cfg.sysconfdir) .. " ")
wrapper:write("exec "..table.concat(argv, " ")..' "$@"\n')
wrapper:close()
if fs.set_permissions(target, "exec", "all") then
return true
else
return nil, "Could not make "..target.." 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 unix.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.warning("could not read "..filename)
return true
end
return first ~= "#!"
end
function unix.copy_binary(filename, dest)
return fs.copy(filename, dest, "exec")
end
--- Move a file on top of the other.
-- The new file ceases to exist under its original name,
-- and takes over the name of the old file.
-- On Unix this is done through a single rename operation.
-- @param old_file The name of the original file,
-- which will be the new name of new_file.
-- @param new_file The name of the new file,
-- which will replace old_file.
-- @return boolean or (nil, string): True if succeeded, or nil and
-- an error message.
function unix.replace_file(old_file, new_file)
return os.rename(new_file, old_file)
end
function unix.tmpname()
return os.tmpname()
end
function unix.current_user()
return os.getenv("USER")
end
function unix.is_superuser()
return os.getenv("USER") == "root"
end
function unix.export_cmd(var, val)
return ("export %s='%s'"):format(var, val)
end
local octal_to_rwx = {
["0"] = "---",
["1"] = "--x",
["2"] = "-w-",
["3"] = "-wx",
["4"] = "r--",
["5"] = "r-x",
["6"] = "rw-",
["7"] = "rwx",
}
local rwx_to_octal = {}
for octal, rwx in pairs(octal_to_rwx) do
rwx_to_octal[rwx] = octal
end
--- Moderate the given permissions based on the local umask
-- @param perms string: permissions to moderate
-- @return string: the moderated permissions
function unix._unix_moderate_permissions(perms)
local umask = fs._unix_umask()
local moderated_perms = ""
for i = 1, 3 do
local p_rwx = octal_to_rwx[perms:sub(i, i)]
local u_rwx = octal_to_rwx[umask:sub(i, i)]
local new_perm = ""
for j = 1, 3 do
local p_val = p_rwx:sub(j, j)
local u_val = u_rwx:sub(j, j)
if p_val == u_val then
new_perm = new_perm .. "-"
else
new_perm = new_perm .. p_val
end
end
moderated_perms = moderated_perms .. rwx_to_octal[new_perm]
end
return moderated_perms
end
function unix.system_cache_dir()
if fs.is_dir("/var/cache") then
return "/var/cache"
end
return dir.path(fs.system_temp_dir(), "cache")
end
return unix

View file

@ -1,300 +0,0 @@
--- fs operations implemented with third-party tools for Unix platform abstractions.
local tools = {}
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local cfg = require("luarocks.core.cfg")
local vars = setmetatable({}, { __index = function(_,k) return cfg.variables[k] end })
--- Adds prefix to command to make it run from a directory.
-- @param directory string: Path to a directory.
-- @param cmd string: A command-line string.
-- @return string: The command-line with prefix.
function tools.command_at(directory, cmd)
return "cd " .. fs.Q(fs.absolute_name(directory)) .. " && " .. cmd
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 tools.make_dir(directory)
assert(directory)
local ok, err = fs.execute(vars.MKDIR.." -p", directory)
if not ok then
err = "failed making directory "..directory
end
return ok, err
end
--- Remove a directory if it is empty.
-- Does not return errors (for example, if directory is not empty or
-- if already does not exist)
-- @param directory string: pathname of directory to remove.
function tools.remove_dir_if_empty(directory)
assert(directory)
fs.execute_quiet(vars.RMDIR, directory)
end
--- Remove a directory if it is empty.
-- Does not return errors (for example, if directory is not empty or
-- if already does not exist)
-- @param directory string: pathname of directory to remove.
function tools.remove_dir_tree_if_empty(directory)
assert(directory)
fs.execute_quiet(vars.RMDIR, "-p", directory)
end
--- Copy a file.
-- @param src string: Pathname of source
-- @param dest string: Pathname of destination
-- @param perm string ("read" or "exec") or nil: Permissions for destination
-- file or nil to use the source permissions
-- @return boolean or (boolean, string): true on success, false on failure,
-- plus an error message.
function tools.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.set_permissions(dest, perm, "all") 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 tools.copy_contents(src, dest)
assert(src and dest)
if fs.execute_quiet(vars.CP.." -pPR "..fs.Q(src).."/* "..fs.Q(dest)) 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 nil
function tools.delete(arg)
assert(arg)
assert(arg:sub(1,1) == "/")
fs.execute_quiet(vars.RM, "-rf", arg)
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 tools.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(fs.command_at(at, fs.quiet_stderr(vars.FIND.." *")))
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, nil and error message on failure.
function tools.zip(zipfile, ...)
local ok, err = fs.is_tool_available(vars.ZIP, "zip")
if not ok then
return nil, err
end
if fs.execute_quiet(vars.ZIP.." -r", zipfile, ...) then
return true
else
return nil, "failed compressing " .. zipfile
end
end
--- Uncompress files from a .zip archive.
-- @param zipfile string: pathname of .zip archive to be extracted.
-- @return boolean: true on success, nil and error message on failure.
function tools.unzip(zipfile)
assert(zipfile)
local ok, err = fs.is_tool_available(vars.UNZIP, "unzip", "--help")
if not ok then
return nil, err
end
if fs.execute_quiet(vars.UNZIP, zipfile) then
return true
else
return nil, "failed extracting " .. zipfile
end
end
local function uncompress(default_ext, program, infile, outfile)
assert(type(infile) == "string")
assert(outfile == nil or type(outfile) == "string")
if not outfile then
outfile = infile:gsub("%."..default_ext.."$", "")
end
if fs.execute(fs.Q(program).." -c "..fs.Q(infile).." > "..fs.Q(outfile)) then
return true
else
return nil, "failed extracting " .. infile
end
end
--- Uncompresses a .gz file.
-- @param infile string: pathname of .gz file to be extracted.
-- @param outfile string or nil: pathname of output file to be produced.
-- If not given, name is derived from input file.
-- @return boolean: true on success; nil and error message on failure.
function tools.gunzip(infile, outfile)
return uncompress("gz", "gunzip", infile, outfile)
end
--- Uncompresses a .bz2 file.
-- @param infile string: pathname of .bz2 file to be extracted.
-- @param outfile string or nil: pathname of output file to be produced.
-- If not given, name is derived from input file.
-- @return boolean: true on success; nil and error message on failure.
function tools.bunzip2(infile, outfile)
return uncompress("bz2", "bunzip2", infile, outfile)
end
do
local function rwx_to_octal(rwx)
return (rwx:match "r" and 4 or 0)
+ (rwx:match "w" and 2 or 0)
+ (rwx:match "x" and 1 or 0)
end
local umask_cache
function tools._unix_umask()
if umask_cache then
return umask_cache
end
local fd = assert(io.popen("umask -S"))
local umask = assert(fd:read("*a"))
fd:close()
local u, g, o = umask:match("u=([rwx]*),g=([rwx]*),o=([rwx]*)")
if not u then
error("invalid umask result")
end
umask_cache = string.format("%d%d%d",
7 - rwx_to_octal(u),
7 - rwx_to_octal(g),
7 - rwx_to_octal(o))
return umask_cache
end
end
--- Set permissions for file or directory
-- @param filename string: filename whose permissions are to be modified
-- @param mode string ("read" or "exec"): permissions to set
-- @param scope string ("user" or "all"): the user(s) to whom the permission applies
-- @return boolean or (boolean, string): true on success, false on failure,
-- plus an error message
function tools.set_permissions(filename, mode, scope)
assert(filename and mode and scope)
local perms
if mode == "read" and scope == "user" then
perms = fs._unix_moderate_permissions("600")
elseif mode == "exec" and scope == "user" then
perms = fs._unix_moderate_permissions("700")
elseif mode == "read" and scope == "all" then
perms = fs._unix_moderate_permissions("644")
elseif mode == "exec" and scope == "all" then
perms = fs._unix_moderate_permissions("755")
else
return false, "Invalid permission " .. mode .. " for " .. scope
end
return fs.execute(vars.CHMOD, perms, filename)
end
function tools.browser(url)
return fs.execute(cfg.web_browser, url)
end
-- Set access and modification times for a file.
-- @param filename File to set access and modification times for.
-- @param time may be a string or number containing the format returned
-- by os.time, or a table ready to be processed via os.time; if
-- nil, current time is assumed.
function tools.set_time(file, time)
assert(time == nil or type(time) == "table" or type(time) == "number")
file = dir.normalize(file)
local flag = ""
if type(time) == "number" then
time = os.date("*t", time)
end
if type(time) == "table" then
flag = ("-t %04d%02d%02d%02d%02d.%02d"):format(time.year, time.month, time.day, time.hour, time.min, time.sec)
end
return fs.execute(vars.TOUCH .. " " .. flag, file)
end
--- Create a temporary directory.
-- @param name_pattern string: name pattern to use for avoiding conflicts
-- when creating temporary directory.
-- @return string or (nil, string): name of temporary directory or (nil, error message) on failure.
function tools.make_temp_dir(name_pattern)
assert(type(name_pattern) == "string")
name_pattern = dir.normalize(name_pattern)
local template = (os.getenv("TMPDIR") or "/tmp") .. "/luarocks_" .. name_pattern:gsub("/", "_") .. "-XXXXXX"
local pipe = io.popen(vars.MKTEMP.." -d "..fs.Q(template))
local dirname = pipe:read("*l")
pipe:close()
if dirname and dirname:match("^/") then
return dirname
end
return nil, "Failed to create temporary directory "..tostring(dirname)
end
--- Test is file/directory exists
-- @param file string: filename to test
-- @return boolean: true if file exists, false otherwise.
function tools.exists(file)
assert(file)
return fs.execute(vars.TEST, "-e", 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 tools.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 tools.is_file(file)
assert(file)
return fs.execute(vars.TEST, "-f", file)
end
return tools

View file

@ -1,366 +0,0 @@
--- Windows implementation of filesystem and platform abstractions.
-- Download http://unxutils.sourceforge.net/ for Windows GNU utilities
-- used by this module.
local win32 = {}
local fs = require("luarocks.fs")
local cfg = require("luarocks.core.cfg")
local dir = require("luarocks.dir")
local path = require("luarocks.path")
local util = require("luarocks.util")
-- Monkey patch io.popen and os.execute to make sure quoting
-- works as expected.
-- See http://lua-users.org/lists/lua-l/2013-11/msg00367.html
local _prefix = "type NUL && "
local _popen, _execute = io.popen, os.execute
-- luacheck: push globals io os
io.popen = function(cmd, ...) return _popen(_prefix..cmd, ...) end
os.execute = function(cmd, ...) return _execute(_prefix..cmd, ...) end
-- luacheck: pop
--- Annotate command string for quiet execution.
-- @param cmd string: A command-line string.
-- @return string: The command-line, with silencing annotation.
function win32.quiet(cmd)
return cmd.." 2> NUL 1> NUL"
end
--- Annotate command string for execution with quiet stderr.
-- @param cmd string: A command-line string.
-- @return string: The command-line, with stderr silencing annotation.
function win32.quiet_stderr(cmd)
return cmd.." 2> NUL"
end
-- Split path into drive, root and the rest.
-- Example: "c:\\hello\\world" becomes "c:" "\\" "hello\\world"
-- if any part is missing from input, it becomes an empty string.
local function split_root(pathname)
local drive = ""
local root = ""
local rest
local unquoted = pathname:match("^['\"](.*)['\"]$")
if unquoted then
pathname = unquoted
end
if pathname:match("^.:") then
drive = pathname:sub(1, 2)
pathname = pathname:sub(3)
end
if pathname:match("^[\\/]") then
root = pathname:sub(1, 1)
rest = pathname:sub(2)
else
rest = pathname
end
return drive, root, rest
end
--- Quote argument for shell processing. Fixes paths on Windows.
-- Adds double quotes and escapes.
-- @param arg string: Unquoted argument.
-- @return string: Quoted argument.
function win32.Q(arg)
assert(type(arg) == "string")
-- Use Windows-specific directory separator for paths.
-- Paths should be converted to absolute by now.
local drive, root, rest = split_root(arg)
if root ~= "" then
arg = arg:gsub("/", "\\")
end
if arg == "\\" then
return '\\' -- CHDIR needs special handling for root dir
end
-- URLs and anything else
arg = arg:gsub('\\(\\*)"', '\\%1%1"')
arg = arg:gsub('\\+$', '%0%0')
arg = arg:gsub('"', '\\"')
arg = arg:gsub('(\\*)%%', '%1%1"%%"')
return '"' .. arg .. '"'
end
--- Quote argument for shell processing in batch files.
-- Adds double quotes and escapes.
-- @param arg string: Unquoted argument.
-- @return string: Quoted argument.
function win32.Qb(arg)
assert(type(arg) == "string")
-- Use Windows-specific directory separator for paths.
-- Paths should be converted to absolute by now.
local drive, root, rest = split_root(arg)
if root ~= "" then
arg = arg:gsub("/", "\\")
end
if arg == "\\" then
return '\\' -- CHDIR needs special handling for root dir
end
-- URLs and anything else
arg = arg:gsub('\\(\\*)"', '\\%1%1"')
arg = arg:gsub('\\+$', '%0%0')
arg = arg:gsub('"', '\\"')
arg = arg:gsub('%%', '%%%%')
return '"' .. arg .. '"'
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 win32.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()):gsub("[\\/]*$", "")
local drive, root, rest = split_root(pathname)
if root:match("[\\/]$") then
-- It's an absolute path already. Ensure is not quoted.
return drive .. root .. rest
else
-- It's a relative path, join it with base path.
-- This drops drive letter from paths like "C:foo".
return relative_to .. "/" .. rest
end
end
--- Return the root directory for the given path.
-- For example, for "c:\hello", returns "c:\"
-- @param pathname string: pathname to use.
-- @return string: The root of the given pathname.
function win32.root_of(pathname)
local drive, root, rest = split_root(fs.absolute_name(pathname))
return drive .. root
end
--- Create a wrapper to make a script executable from the command-line.
-- @param script string: Pathname of script to be made executable.
-- @param target string: wrapper target pathname (without wrapper suffix).
-- @param name string: rock name to be used in loader context.
-- @param version string: rock version to be used in loader context.
-- @return boolean or (nil, string): True if succeeded, or nil and
-- an error message.
function win32.wrap_script(script, target, deps_mode, name, version, ...)
assert(type(script) == "string" or not script)
assert(type(target) == "string")
assert(type(deps_mode) == "string")
assert(type(name) == "string" or not name)
assert(type(version) == "string" or not version)
local batname = target .. ".bat"
local wrapper = io.open(batname, "wb")
if not wrapper then
return nil, "Could not open "..batname.." for writing."
end
local lpath, lcpath = path.package_paths(deps_mode)
local luainit = {
"package.path="..util.LQ(lpath..";").."..package.path",
"package.cpath="..util.LQ(lcpath..";").."..package.cpath",
}
local remove_interpreter = false
if target == "luarocks" or target == "luarocks-admin" then
if cfg.is_binary then
remove_interpreter = true
end
luainit = {
"package.path="..util.LQ(package.path),
"package.cpath="..util.LQ(package.cpath),
}
end
if name and version then
local addctx = "local k,l,_=pcall(require,'luarocks.loader') _=k " ..
"and l.add_context('"..name.."','"..version.."')"
table.insert(luainit, addctx)
end
local argv = {
fs.Qb(dir.path(cfg.variables["LUA_BINDIR"], cfg.lua_interpreter)),
"-e",
fs.Qb(table.concat(luainit, ";")),
script and fs.Qb(script) or "%I%",
...
}
if remove_interpreter then
table.remove(argv, 1)
table.remove(argv, 1)
table.remove(argv, 1)
end
wrapper:write("@echo off\r\n")
wrapper:write("setlocal\r\n")
if not script then
wrapper:write([[IF "%*"=="" (set I=-i) ELSE (set I=)]] .. "\r\n")
end
wrapper:write("set "..fs.Qb("LUAROCKS_SYSCONFDIR="..cfg.sysconfdir) .. "\r\n")
wrapper:write(table.concat(argv, " ") .. " %*\r\n")
wrapper:write("exit /b %ERRORLEVEL%\r\n")
wrapper:close()
return true
end
function win32.is_actual_binary(name)
name = name:lower()
if name:match("%.bat$") or name:match("%.exe$") then
return true
end
return false
end
function win32.copy_binary(filename, dest)
local ok, err = fs.copy(filename, dest)
if not ok then
return nil, err
end
local exe_pattern = "%.[Ee][Xx][Ee]$"
local base = dir.base_name(filename)
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
--- Move a file on top of the other.
-- The new file ceases to exist under its original name,
-- and takes over the name of the old file.
-- On Windows this is done by removing the original file and
-- renaming the new file to its original name.
-- @param old_file The name of the original file,
-- which will be the new name of new_file.
-- @param new_file The name of the new file,
-- which will replace old_file.
-- @return boolean or (nil, string): True if succeeded, or nil and
-- an error message.
function win32.replace_file(old_file, new_file)
os.remove(old_file)
return os.rename(new_file, old_file)
end
function win32.is_dir(file)
file = fs.absolute_name(file)
file = dir.normalize(file)
local fd, _, code = io.open(file, "r")
if code == 13 then -- directories return "Permission denied"
fd, _, code = io.open(file .. "\\", "r")
if code == 2 then -- directories return 2, files return 22
return true
end
end
if fd then
fd:close()
end
return false
end
function win32.is_file(file)
file = fs.absolute_name(file)
file = dir.normalize(file)
local fd, _, code = io.open(file, "r")
if code == 13 then -- if "Permission denied"
fd, _, code = io.open(file .. "\\", "r")
if code == 2 then -- directories return 2, files return 22
return false
elseif code == 22 then
return true
end
end
if fd then
fd:close()
return true
end
return false
end
--- Test is file/dir is writable.
-- Warning: testing if a file/dir is writable does not guarantee
-- that it will remain writable and therefore it is no replacement
-- for checking the result of subsequent operations.
-- @param file string: filename to test
-- @return boolean: true if file exists, false otherwise.
function win32.is_writable(file)
assert(file)
file = dir.normalize(file)
local result
local tmpname = 'tmpluarockstestwritable.deleteme'
if fs.is_dir(file) then
local file2 = dir.path(file, tmpname)
local fh = io.open(file2, 'wb')
result = fh ~= nil
if fh then fh:close() end
if result then
-- the above test might give a false positive when writing to
-- c:\program files\ because of VirtualStore redirection on Vista and up
-- So check whether it's really there
result = fs.exists(file2)
end
os.remove(file2)
else
local fh = io.open(file, 'r+b')
result = fh ~= nil
if fh then fh:close() end
end
return result
end
--- Create a temporary directory.
-- @param name_pattern string: name pattern to use for avoiding conflicts
-- when creating temporary directory.
-- @return string or (nil, string): name of temporary directory or (nil, error message) on failure.
function win32.make_temp_dir(name_pattern)
assert(type(name_pattern) == "string")
name_pattern = dir.normalize(name_pattern)
local temp_dir = os.getenv("TMP") .. "/luarocks_" .. name_pattern:gsub("/", "_") .. "-" .. tostring(math.floor(math.random() * 10000))
local ok, err = fs.make_dir(temp_dir)
if ok then
return temp_dir
else
return nil, err
end
end
function win32.tmpname()
local name = os.tmpname()
local tmp = os.getenv("TMP")
if tmp and name:sub(1, #tmp) ~= tmp then
name = (tmp .. "\\" .. name):gsub("\\+", "\\")
end
return name
end
function win32.current_user()
return os.getenv("USERNAME")
end
function win32.is_superuser()
return false
end
function win32.export_cmd(var, val)
return ("SET %s=%s"):format(var, val)
end
function win32.system_cache_dir()
return dir.path(fs.system_temp_dir(), "cache")
end
return win32

View file

@ -1,311 +0,0 @@
--- fs operations implemented with third-party tools for Windows platform abstractions.
-- Download http://unxutils.sourceforge.net/ for Windows GNU utilities
-- used by this module.
local tools = {}
local fs = require("luarocks.fs")
local dir = require("luarocks.dir")
local cfg = require("luarocks.core.cfg")
local vars = setmetatable({}, { __index = function(_,k) return cfg.variables[k] end })
--- Adds prefix to command to make it run from a directory.
-- @param directory string: Path to a directory.
-- @param cmd string: A command-line string.
-- @param exit_on_error bool: Exits immediately if entering the directory failed.
-- @return string: The command-line with prefix.
function tools.command_at(directory, cmd, exit_on_error)
local drive = directory:match("^([A-Za-z]:)")
local op = " & "
if exit_on_error then
op = " && "
end
local cmd_prefixed = "cd " .. fs.Q(directory) .. op .. cmd
if drive then
cmd_prefixed = drive .. " & " .. cmd_prefixed
end
return cmd_prefixed
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 tools.make_dir(directory)
assert(directory)
directory = dir.normalize(directory)
fs.execute_quiet(vars.MKDIR.." -p ", directory)
if not fs.is_dir(directory) then
return false, "failed making directory "..directory
end
return true
end
--- Remove a directory if it is empty.
-- Does not return errors (for example, if directory is not empty or
-- if already does not exist)
-- @param directory string: pathname of directory to remove.
function tools.remove_dir_if_empty(directory)
assert(directory)
fs.execute_quiet(vars.RMDIR, directory)
end
--- Remove a directory if it is empty.
-- Does not return errors (for example, if directory is not empty or
-- if already does not exist)
-- @param directory string: pathname of directory to remove.
function tools.remove_dir_tree_if_empty(directory)
assert(directory)
fs.execute_quiet(vars.RMDIR, directory)
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 tools.copy(src, dest)
assert(src and dest)
if dest:match("[/\\]$") then dest = dest:sub(1, -2) end
local ok = fs.execute(vars.CP, src, dest)
if ok 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 tools.copy_contents(src, dest)
assert(src and dest)
if not fs.is_dir(src) then
return false, src .. " is not a directory"
end
if fs.make_dir(dest) and fs.execute_quiet(vars.CP, "-dR", src.."\\*.*", dest) 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 nil
function tools.delete(arg)
assert(arg)
assert(arg:match("^[a-zA-Z]?:?[\\/]"))
fs.execute_quiet("if exist "..fs.Q(arg.."\\*").." ( RMDIR /S /Q "..fs.Q(arg).." ) else ( DEL /Q /F "..fs.Q(arg).." )")
end
--- 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 tools.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(fs.command_at(at, fs.quiet_stderr(vars.FIND), true))
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
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, nil and error message on failure.
function tools.zip(zipfile, ...)
if fs.execute_quiet(vars.SEVENZ.." -aoa a -tzip", zipfile, ...) then
return true
else
return nil, "failed compressing " .. zipfile
end
end
--- Uncompress files from a .zip archive.
-- @param zipfile string: pathname of .zip archive to be extracted.
-- @return boolean: true on success, nil and error message on failure.
function tools.unzip(zipfile)
assert(zipfile)
if fs.execute_quiet(vars.SEVENZ.." -aoa x", zipfile) then
return true
else
return nil, "failed extracting " .. zipfile
end
end
local function sevenz(default_ext, infile, outfile)
assert(type(infile) == "string")
assert(outfile == nil or type(outfile) == "string")
local dropext = infile:gsub("%."..default_ext.."$", "")
local outdir = dir.dir_name(dropext)
infile = fs.absolute_name(infile)
local cmdline = vars.SEVENZ.." -aoa -t* -o"..fs.Q(outdir).." x "..fs.Q(infile)
local ok, err = fs.execute_quiet(cmdline)
if not ok then
return nil, "failed extracting " .. infile
end
if outfile then
outfile = fs.absolute_name(outfile)
dropext = fs.absolute_name(dropext)
ok, err = os.rename(dropext, outfile)
if not ok then
return nil, "failed creating new file " .. outfile
end
end
return true
end
--- Uncompresses a .gz file.
-- @param infile string: pathname of .gz file to be extracted.
-- @param outfile string or nil: pathname of output file to be produced.
-- If not given, name is derived from input file.
-- @return boolean: true on success; nil and error message on failure.
function tools.gunzip(infile, outfile)
return sevenz("gz", infile, outfile)
end
--- Uncompresses a .bz2 file.
-- @param infile string: pathname of .bz2 file to be extracted.
-- @param outfile string or nil: pathname of output file to be produced.
-- If not given, name is derived from input file.
-- @return boolean: true on success; nil and error message on failure.
function tools.bunzip2(infile, outfile)
return sevenz("bz2", infile, outfile)
end
--- Helper function for fs.set_permissions
-- @return table: an array of all system users
local function get_system_users()
local exclude = {
[""] = true,
["Name"] = true,
["\128\164\172\168\173\168\225\226\224\160\226\174\224"] = true, -- Administrator in cp866
["Administrator"] = true,
}
local result = {}
local fd = assert(io.popen("wmic UserAccount get name"))
for user in fd:lines() do
user = user:gsub("%s+$", "")
if not exclude[user] then
table.insert(result, user)
end
end
return result
end
--- Set permissions for file or directory
-- @param filename string: filename whose permissions are to be modified
-- @param mode string ("read" or "exec"): permission to set
-- @param scope string ("user" or "all"): the user(s) to whom the permission applies
-- @return boolean or (boolean, string): true on success, false on failure,
-- plus an error message
function tools.set_permissions(filename, mode, scope)
assert(filename and mode and scope)
if scope == "user" then
local perms
if mode == "read" then
perms = "(R,W,M)"
elseif mode == "exec" then
perms = "(F)"
end
local ok
-- Take ownership of the given file
ok = fs.execute_quiet("takeown /f " .. fs.Q(filename))
if not ok then
return false, "Could not take ownership of the given file"
end
local username = os.getenv('USERNAME')
-- Grant the current user the proper rights
ok = fs.execute_quiet(vars.ICACLS .. " " .. fs.Q(filename) .. " /inheritance:d /grant:r " .. fs.Q(username) .. ":" .. perms)
if not ok then
return false, "Failed setting permission " .. mode .. " for " .. scope
end
-- Finally, remove all the other users from the ACL in order to deny them access to the file
for _, user in pairs(get_system_users()) do
if username ~= user then
local ok = fs.execute_quiet(vars.ICACLS .. " " .. fs.Q(filename) .. " /remove " .. fs.Q(user))
if not ok then
return false, "Failed setting permission " .. mode .. " for " .. scope
end
end
end
elseif scope == "all" then
local my_perms, others_perms
if mode == "read" then
my_perms = "(R,W,M)"
others_perms = "(R)"
elseif mode == "exec" then
my_perms = "(F)"
others_perms = "(RX)"
end
local ok
-- Grant permissions available to all users
ok = fs.execute_quiet(vars.ICACLS .. " " .. fs.Q(filename) .. " /inheritance:d /grant:r *S-1-1-0:" .. others_perms)
if not ok then
return false, "Failed setting permission " .. mode .. " for " .. scope
end
-- Grant permissions available only to the current user
ok = fs.execute_quiet(vars.ICACLS .. " " .. fs.Q(filename) .. " /inheritance:d /grant \"%USERNAME%\":" .. my_perms)
-- This may not be necessary if the above syntax is correct,
-- but I couldn't really test the extra quotes above, so if that
-- fails we try again with the syntax used in previous releases
-- just to be on the safe side
if not ok then
ok = fs.execute_quiet(vars.ICACLS .. " " .. fs.Q(filename) .. " /inheritance:d /grant %USERNAME%:" .. my_perms)
end
if not ok then
return false, "Failed setting permission " .. mode .. " for " .. scope
end
end
return true
end
function tools.browser(url)
return fs.execute(cfg.web_browser..' "Starting docs..." '..fs.Q(url))
end
-- Set access and modification times for a file.
-- @param filename File to set access and modification times for.
-- @param time may be a string or number containing the format returned
-- by os.time, or a table ready to be processed via os.time; if
-- nil, current time is assumed.
function tools.set_time(filename, time)
return true -- FIXME
end
return tools

View file

@ -1,143 +0,0 @@
--- A set of basic functional utilities
local fun = {}
local unpack = table.unpack or unpack
function fun.concat(xs, ys)
local rs = {}
local n = #xs
for i = 1, n do
rs[i] = xs[i]
end
for i = 1, #ys do
rs[i + n] = ys[i]
end
return rs
end
function fun.contains(xs, v)
for _, x in ipairs(xs) do
if v == x then
return true
end
end
return false
end
function fun.map(xs, f)
local rs = {}
for i = 1, #xs do
rs[i] = f(xs[i])
end
return rs
end
function fun.filter(xs, f)
local rs = {}
for i = 1, #xs do
local v = xs[i]
if f(v) then
rs[#rs+1] = v
end
end
return rs
end
function fun.traverse(t, f)
return fun.map(t, function(x)
return type(x) == "table" and fun.traverse(x, f) or f(x)
end)
end
function fun.reverse_in(t)
for i = 1, math.floor(#t/2) do
local m, n = i, #t - i + 1
local a, b = t[m], t[n]
t[m] = b
t[n] = a
end
return t
end
function fun.sort_in(t, f)
table.sort(t, f)
return t
end
function fun.flip(f)
return function(a, b)
return f(b, a)
end
end
function fun.find(xs, f)
if type(xs) == "function" then
for v in xs do
local x = f(v)
if x then
return x
end
end
elseif type(xs) == "table" then
for _, v in ipairs(xs) do
local x = f(v)
if x then
return x
end
end
end
end
function fun.partial(f, ...)
local n = select("#", ...)
if n == 1 then
local a = ...
return function(...)
return f(a, ...)
end
elseif n == 2 then
local a, b = ...
return function(...)
return f(a, b, ...)
end
else
local pargs = { n = n, ... }
return function(...)
local m = select("#", ...)
local fargs = { ... }
local args = {}
for i = 1, n do
args[i] = pargs[i]
end
for i = 1, m do
args[i+n] = fargs[i]
end
return f(unpack(args, 1, n+m))
end
end
end
function fun.memoize(fn)
local memory = setmetatable({}, { __mode = "k" })
local errors = setmetatable({}, { __mode = "k" })
local NIL = {}
return function(arg)
if memory[arg] then
if memory[arg] == NIL then
return nil, errors[arg]
end
return memory[arg]
end
local ret1, ret2 = fn(arg)
if ret1 ~= nil then
memory[arg] = ret1
else
memory[arg] = NIL
errors[arg] = ret2
end
return ret1, ret2
end
end
return fun

View file

@ -1,233 +0,0 @@
--- 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.
-- luacheck: globals luarocks
local loaders = package.loaders or package.searchers
local require, ipairs, table, type, next, tostring, error =
require, ipairs, table, type, next, tostring, error
local unpack = unpack or table.unpack
local loader = {}
local is_clean = not package.loaded["luarocks.core.cfg"]
-- This loader module depends only on core modules.
local cfg = require("luarocks.core.cfg")
local cfg_ok, err = cfg.init()
if cfg_ok then
cfg.init_package_paths()
end
local path = require("luarocks.core.path")
local manif = require("luarocks.core.manif")
local vers = require("luarocks.core.vers")
local require = nil -- luacheck: ignore 411
--------------------------------------------------------------------------------
-- Workaround for wrappers produced by older versions of LuaRocks
local temporary_global = false
local status, luarocks_value = pcall(function() return luarocks end)
if status and luarocks_value then
-- The site_config.lua file generated by old versions uses module(),
-- so it produces a global `luarocks` table. Since we have the table,
-- add the `loader` field to make the old wrappers happy.
luarocks.loader = loader
else
-- When a new version is installed on top of an old version,
-- site_config.lua may be replaced, and then it no longer creates
-- a global.
-- Detect when being called via -lluarocks.loader; this is
-- most likely a wrapper.
local info = debug and debug.getinfo(2, "nS")
if info and info.what == "C" and not info.name then
luarocks = { loader = loader }
temporary_global = true
-- For the other half of this hack,
-- see the next use of `temporary_global` below.
end
end
loader.context = {}
--- 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 loader.add_context(name, version)
-- assert(type(name) == "string")
-- assert(type(version) == "string")
if temporary_global then
-- The first thing a wrapper does is to call add_context.
-- From here on, it's safe to clean the global environment.
luarocks = nil
temporary_global = false
end
local tree_manifests = manif.load_rocks_tree_manifests()
if not tree_manifests then
return nil
end
return manif.scan_dependencies(name, version, tree_manifests, loader.context)
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 _, a_loader in ipairs(loaders) do
if a_loader ~= loader.luarocks_loader then
local results = { a_loader(module_name) }
if type(results[1]) == "function" then
return unpack(results)
end
end
end
return "Failed loading module "..module.." in LuaRocks rock "..name.." "..version
end
local function add_providers(providers, entries, tree, module, filter_file_name)
for i, entry in ipairs(entries) do
local name, version = entry:match("^([^/]*)/(.*)$")
local file_name = tree.manifest.repository[name][version][1].modules[module]
if type(file_name) ~= "string" then
error("Invalid data in manifest file for module "..tostring(module).." (invalid data for "..tostring(name).." "..tostring(version)..")")
end
file_name = filter_file_name(file_name, name, version, tree.tree, i)
if loader.context[name] == version then
return name, version, file_name
end
version = vers.parse_version(version)
table.insert(providers, {name = name, version = version, module_name = file_name, tree = tree})
end
end
--- Search for a module in the rocks trees
-- @param module string: module name (eg. "socket.core")
-- @param filter_file_name function(string, string, string, string, number):
-- a function that takes the module file name (eg "socket/core.so"), 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, (string or table):
-- * name of the rock containing the module (eg. "luasocket")
-- * version of the rock (eg. "2.0.2-1")
-- * return value of filter_file_name
-- * tree of the module (string or table in `tree_manifests` format)
local function select_module(module, filter_file_name)
--assert(type(module) == "string")
--assert(type(filter_module_name) == "function")
local tree_manifests = manif.load_rocks_tree_manifests()
if not tree_manifests then
return nil
end
local providers = {}
local initmodule
for _, tree in ipairs(tree_manifests) do
local entries = tree.manifest.modules[module]
if entries then
local n, v, f = add_providers(providers, entries, tree, module, filter_file_name)
if n then
return n, v, f
end
else
initmodule = initmodule or module .. ".init"
entries = tree.manifest.modules[initmodule]
if entries then
local n, v, f = add_providers(providers, entries, tree, initmodule, filter_file_name)
if n then
return n, v, f
end
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, first.tree
end
end
--- Search for a module
-- @param module string: module name (eg. "socket.core")
-- @return string, string, string, (string or table):
-- * name of the rock containing the module (eg. "luasocket")
-- * version of the rock (eg. "2.0.2-1")
-- * name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is stored versioned).
-- * tree of the module (string or table in `tree_manifests` format)
local function pick_module(module)
return
select_module(module, function(file_name, name, version, tree, i)
if i > 1 then
file_name = path.versioned_name(file_name, "", name, version)
end
return path.path_to_module(file_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 filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so"),
-- the rock name and the rock version.
function loader.which(module)
local rock_name, rock_version, file_name = select_module(module, path.which_i)
return file_name, rock_name, rock_version
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 <a href="http://www.lua.org/manual/5.1/manual.html#pdf-require">require()</a>
-- in the Lua reference manual for details.
function loader.luarocks_loader(module)
local name, version, module_name = pick_module(module)
if not name then
return "No LuaRocks module found for "..module
else
loader.add_context(name, version)
return call_other_loaders(module, name, version, module_name)
end
end
table.insert(loaders, 1, loader.luarocks_loader)
if is_clean then
for modname, _ in pairs(package.loaded) do
if modname:match("^luarocks%.") then
package.loaded[modname] = nil
end
end
end
return loader

View file

@ -1,225 +0,0 @@
--- 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.
local manif = {}
local core = require("luarocks.core.manif")
local persist = require("luarocks.persist")
local fetch = require("luarocks.fetch")
local dir = require("luarocks.dir")
local fs = require("luarocks.fs")
local cfg = require("luarocks.core.cfg")
local path = require("luarocks.path")
local util = require("luarocks.util")
local queries = require("luarocks.queries")
local type_manifest = require("luarocks.type.manifest")
manif.cache_manifest = core.cache_manifest
manif.load_rocks_tree_manifests = core.load_rocks_tree_manifests
manif.scan_dependencies = core.scan_dependencies
manif.rock_manifest_cache = {}
local function check_manifest(repo_url, manifest, globals)
local ok, err = type_manifest.check(manifest, globals)
if not ok then
core.cache_manifest(repo_url, cfg.lua_version, nil)
return nil, "Error checking manifest: "..err, "type"
end
return manifest
end
local postprocess_dependencies
do
local postprocess_check = setmetatable({}, { __mode = "k" })
postprocess_dependencies = function(manifest)
if postprocess_check[manifest] then
return
end
if manifest.dependencies then
for name, versions in pairs(manifest.dependencies) do
for version, entries in pairs(versions) do
for k, v in pairs(entries) do
entries[k] = queries.from_persisted_table(v)
end
end
end
end
postprocess_check[manifest] = true
end
end
function manif.load_rock_manifest(name, version, root)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
local name_version = name.."/"..version
if manif.rock_manifest_cache[name_version] then
return manif.rock_manifest_cache[name_version].rock_manifest
end
local pathname = path.rock_manifest_file(name, version, root)
local rock_manifest = persist.load_into_table(pathname)
if not rock_manifest then
return nil, "rock_manifest file not found for "..name.." "..version.." - not a LuaRocks tree?"
end
manif.rock_manifest_cache[name_version] = rock_manifest
return 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 this function.
-- @param repo_url string: URL or pathname for the repository.
-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
-- @param versioned_only boolean: If true, do not fall back to the main manifest
-- if a versioned manifest was not found.
-- @return table or (nil, string, [string]): A table representing the manifest,
-- or nil followed by an error message and an optional error code.
function manif.load_manifest(repo_url, lua_version, versioned_only)
assert(type(repo_url) == "string")
assert(type(lua_version) == "string" or not lua_version)
lua_version = lua_version or cfg.lua_version
local cached_manifest = core.get_cached_manifest(repo_url, lua_version)
if cached_manifest then
postprocess_dependencies(cached_manifest)
return cached_manifest
end
local filenames = {
"manifest-"..lua_version..".zip",
"manifest-"..lua_version,
not versioned_only and "manifest" or nil,
}
local protocol, repodir = dir.split_url(repo_url)
local pathname, from_cache
if protocol == "file" then
for _, filename in ipairs(filenames) do
pathname = dir.path(repodir, filename)
if fs.exists(pathname) then
break
end
end
else
local err, errcode
for _, filename in ipairs(filenames) do
pathname, err, errcode, from_cache = fetch.fetch_caching(dir.path(repo_url, filename), "no_mirror")
if pathname then
break
end
end
if not pathname then
return nil, err, errcode
end
end
if pathname:match(".*%.zip$") then
pathname = fs.absolute_name(pathname)
local nozip = pathname:match("(.*)%.zip$")
if not from_cache then
local dirname = dir.dir_name(pathname)
fs.change_dir(dirname)
fs.delete(nozip)
local ok, err = fs.unzip(pathname)
fs.pop_dir()
if not ok then
fs.delete(pathname)
fs.delete(pathname..".timestamp")
return nil, "Failed extracting manifest file: " .. err
end
end
pathname = nozip
end
local manifest, err, errcode = core.manifest_loader(pathname, repo_url, lua_version)
if not manifest then
return nil, err, errcode
end
postprocess_dependencies(manifest)
return check_manifest(repo_url, manifest, err)
end
--- Get type and name of an item (a module or a command) provided by a file.
-- @param deploy_type string: rock manifest subtree the file comes from ("bin", "lua", or "lib").
-- @param file_path string: path to the file relatively to deploy_type subdirectory.
-- @return (string, string): item type ("module" or "command") and name.
function manif.get_provided_item(deploy_type, file_path)
assert(type(deploy_type) == "string")
assert(type(file_path) == "string")
local item_type = deploy_type == "bin" and "command" or "module"
local item_name = item_type == "command" and file_path or path.path_to_module(file_path)
return item_type, item_name
end
local function get_providers(item_type, item_name, repo)
assert(type(item_type) == "string")
assert(type(item_name) == "string")
local rocks_dir = path.rocks_dir(repo or cfg.root_dir)
local manifest = manif.load_manifest(rocks_dir)
return manifest and manifest[item_type .. "s"][item_name]
end
--- Given a name of a module or a command, figure out which rock name and version
-- correspond to it in the rock tree manifest.
-- @param item_type string: "module" or "command".
-- @param item_name string: module or command name.
-- @param root string or nil: A local root dir for a rocks tree. If not given, the default is used.
-- @return (string, string) or nil: name and version of the provider rock or nil if there
-- is no provider.
function manif.get_current_provider(item_type, item_name, repo)
local providers = get_providers(item_type, item_name, repo)
if providers then
return providers[1]:match("([^/]*)/([^/]*)")
end
end
function manif.get_next_provider(item_type, item_name, repo)
local providers = get_providers(item_type, item_name, repo)
if providers and providers[2] then
return providers[2]:match("([^/]*)/([^/]*)")
end
end
--- Get all versions of a package listed in a manifest file.
-- @param name string: a package name.
-- @param deps_mode string: "one", to use only the currently
-- configured tree; "order" to select trees based on order
-- (use the current tree and all trees below it on the list)
-- or "all", to use all trees.
-- @return table: An array of strings listing installed
-- versions of a package, and a table indicating where they are found.
function manif.get_versions(dep, deps_mode)
assert(type(dep) == "table")
assert(type(deps_mode) == "string")
local name = dep.name
local namespace = dep.namespace
local version_set = {}
path.map_trees(deps_mode, function(tree)
local manifest = manif.load_manifest(path.rocks_dir(tree))
if manifest and manifest.repository[name] then
for version in pairs(manifest.repository[name]) do
if dep.namespace then
local ns_file = path.rock_namespace_file(name, version, tree)
local fd = io.open(ns_file, "r")
if fd then
local ns = fd:read("*a")
fd:close()
if ns == namespace then
version_set[version] = tree
end
end
else
version_set[version] = tree
end
end
end
end)
return util.keys(version_set), version_set
end
return manif

View file

@ -1,494 +0,0 @@
local writer = {}
local cfg = require("luarocks.core.cfg")
local search = require("luarocks.search")
local repos = require("luarocks.repos")
local deps = require("luarocks.deps")
local vers = require("luarocks.core.vers")
local fs = require("luarocks.fs")
local util = require("luarocks.util")
local dir = require("luarocks.dir")
local fetch = require("luarocks.fetch")
local path = require("luarocks.path")
local persist = require("luarocks.persist")
local manif = require("luarocks.manif")
local queries = require("luarocks.queries")
--- Update storage table to account for items provided by a package.
-- @param storage table: a table storing items in the following format:
-- keys are item names and values are arrays of packages providing each item,
-- where a package is specified as string `name/version`.
-- @param items table: a table mapping item names to paths.
-- @param name string: package name.
-- @param version string: package version.
local function store_package_items(storage, name, version, items)
assert(type(storage) == "table")
assert(type(items) == "table")
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
local package_identifier = name.."/"..version
for item_name, path in pairs(items) do -- luacheck: ignore 431
if not storage[item_name] then
storage[item_name] = {}
end
table.insert(storage[item_name], package_identifier)
end
end
--- Update storage table removing items provided by a package.
-- @param storage table: a table storing items in the following format:
-- keys are item names and values are arrays of packages providing each item,
-- where a package is specified as string `name/version`.
-- @param items table: a table mapping item names to paths.
-- @param name string: package name.
-- @param version string: package version.
local function remove_package_items(storage, name, version, items)
assert(type(storage) == "table")
assert(type(items) == "table")
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
local package_identifier = name.."/"..version
for item_name, path in pairs(items) do -- luacheck: ignore 431
local key = item_name
local all_identifiers = storage[key]
if not all_identifiers then
key = key .. ".init"
all_identifiers = storage[key]
end
if all_identifiers then
for i, identifier in ipairs(all_identifiers) do
if identifier == package_identifier then
table.remove(all_identifiers, i)
break
end
end
if #all_identifiers == 0 then
storage[key] = nil
end
else
util.warning("Cannot find entry for " .. item_name .. " in manifest -- corrupted manifest?")
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.
-- @param deps_mode string: Dependency mode: "one" for the current default tree,
-- "all" for all trees, "order" for all trees with priority >= the current default,
-- "none" for no trees.
local function update_dependencies(manifest, deps_mode)
assert(type(manifest) == "table")
assert(type(deps_mode) == "string")
for pkg, versions in pairs(manifest.repository) do
for version, repositories in pairs(versions) do
for _, repo in ipairs(repositories) do
if repo.arch == "installed" then
repo.dependencies = {}
deps.scan_deps(repo.dependencies, manifest, pkg, version, deps_mode)
repo.dependencies[pkg] = nil
end
end
end
end
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 vers.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
--- Filter manifest table by Lua version, removing rockspecs whose Lua version
-- does not match.
-- @param manifest table: a manifest table.
-- @param lua_version string or nil: filter by Lua version
-- @param repodir string: directory of repository being scanned
-- @param cache table: temporary rockspec cache table
local function filter_by_lua_version(manifest, lua_version, repodir, cache)
assert(type(manifest) == "table")
assert(type(repodir) == "string")
assert((not cache) or type(cache) == "table")
cache = cache or {}
lua_version = vers.parse_version(lua_version)
for pkg, versions in pairs(manifest.repository) do
local to_remove = {}
for version, repositories in pairs(versions) do
for _, repo in ipairs(repositories) do
if repo.arch == "rockspec" then
local pathname = dir.path(repodir, pkg.."-"..version..".rockspec")
local rockspec, err = cache[pathname]
if not rockspec then
rockspec, err = fetch.load_local_rockspec(pathname, true)
end
if rockspec then
cache[pathname] = rockspec
for _, dep in ipairs(rockspec.dependencies) do
if dep.name == "lua" then
if not vers.match_constraints(lua_version, dep.constraints) then
table.insert(to_remove, version)
end
break
end
end
else
util.printerr("Error loading rockspec for "..pkg.." "..version..": "..err)
end
end
end
end
if next(to_remove) then
for _, incompat in ipairs(to_remove) do
versions[incompat] = nil
end
if not next(versions) then
manifest.repository[pkg] = nil
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, err = manif.load_rock_manifest(name, version)
if not rock_manifest then return nil, err end
entrytable.modules = repos.package_modules(name, version)
store_package_items(manifest.modules, name, version, entrytable.modules)
entrytable.commands = repos.package_commands(name, version)
store_package_items(manifest.commands, name, version, entrytable.commands)
end
table.insert(versiontable, entrytable)
end
pkgtable[version] = versiontable
end
manifest.repository[name] = pkgtable
end
sort_package_matching_table(manifest.modules)
sort_package_matching_table(manifest.commands)
return true
end
--- 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" and not name:match("/"))
assert(type(tbl) == "table")
local filename = dir.path(where, name)
local ok, err = persist.save_from_table(filename..".tmp", tbl)
if ok then
ok, err = fs.replace_file(filename, filename..".tmp")
end
return ok, err
end
function writer.make_rock_manifest(name, version)
local install_dir = path.install_dir(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 filename in file:gmatch("[^/]+") do
local next = walk[filename]
if not next then
next = {}
walk[filename] = next
end
last = walk
last_name = filename
walk = next
end
if fs.is_file(full_path) then
local sum, err = fs.get_md5(full_path)
if not sum then
return nil, "Failed producing checksum: "..tostring(err)
end
last[last_name] = sum
end
end
local rock_manifest = { rock_manifest=tree }
manif.rock_manifest_cache[name.."/"..version] = rock_manifest
save_table(install_dir, "rock_manifest", rock_manifest )
return true
end
-- Writes a 'rock_namespace' file in a locally installed rock directory.
-- @param name string: the rock name, without a namespace
-- @param version string: the rock version
-- @param namespace string?: the namespace
-- @return true if successful (or unnecessary, if there is no namespace),
-- or nil and an error message.
function writer.make_namespace_file(name, version, namespace)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
assert(type(namespace) == "string" or not namespace)
if not namespace then
return true
end
local fd, err = io.open(path.rock_namespace_file(name, version), "w")
if not fd then
return nil, err
end
local ok, err = fd:write(namespace)
if not ok then
return nil, err
end
fd:close()
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.
-- @param deps_mode string: Dependency mode: "one" for the current default tree,
-- "all" for all trees, "order" for all trees with priority >= the current default,
-- "none" for the default dependency mode from the configuration.
-- @param remote boolean: 'true' if making a manifest for a rocks server.
-- @return boolean or (nil, string): True if manifest was generated,
-- or nil and an error message.
function writer.make_manifest(repo, deps_mode, remote)
assert(type(repo) == "string")
assert(type(deps_mode) == "string")
if deps_mode == "none" then deps_mode = cfg.deps_mode end
if not fs.is_dir(repo) then
return nil, "Cannot access repository at "..repo
end
local query = queries.all("any")
local results = search.disk_search(repo, query)
local manifest = { repository = {}, modules = {}, commands = {} }
manif.cache_manifest(repo, nil, manifest)
local ok, err = store_results(results, manifest)
if not ok then return nil, err end
if remote then
local cache = {}
for luaver in util.lua_versions() do
local vmanifest = { repository = {}, modules = {}, commands = {} }
local ok, err = store_results(results, vmanifest)
filter_by_lua_version(vmanifest, luaver, repo, cache)
if not cfg.no_manifest then
save_table(repo, "manifest-"..luaver, vmanifest)
end
end
else
update_dependencies(manifest, deps_mode)
end
if cfg.no_manifest then
-- We want to have cache updated; but exit before save_table is called
return true
end
return save_table(repo, "manifest", manifest)
end
--- Update manifest file for a local repository
-- adding information about a version of a package installed in that repository.
-- @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 is used.
-- @param deps_mode string: Dependency mode: "one" for the current default tree,
-- "all" for all trees, "order" for all trees with priority >= the current default,
-- "none" for using the default dependency mode from the configuration.
-- @return boolean or (nil, string): True if manifest was updated successfully,
-- or nil and an error message.
function writer.add_to_manifest(name, version, repo, deps_mode)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
local rocks_dir = path.rocks_dir(repo or cfg.root_dir)
assert(type(deps_mode) == "string")
if deps_mode == "none" then deps_mode = cfg.deps_mode end
local manifest, err = manif.load_manifest(rocks_dir)
if not manifest then
util.printerr("No existing manifest. Attempting to rebuild...")
-- Manifest built by `writer.make_manifest` should already
-- include information about given name and version,
-- no need to update it.
return writer.make_manifest(rocks_dir, deps_mode)
end
local results = {[name] = {[version] = {{arch = "installed", repo = rocks_dir}}}}
local ok, err = store_results(results, manifest)
if not ok then return nil, err end
update_dependencies(manifest, deps_mode)
if cfg.no_manifest then
return true
end
return save_table(rocks_dir, "manifest", manifest)
end
--- Update manifest file for a local repository
-- removing information about a version of a package.
-- @param name string: Name of a package removed from the repository.
-- @param version string: Version of a package removed from the repository.
-- @param repo string or nil: Pathname of a local repository. If not given,
-- the default local repository is used.
-- @param deps_mode string: Dependency mode: "one" for the current default tree,
-- "all" for all trees, "order" for all trees with priority >= the current default,
-- "none" for using the default dependency mode from the configuration.
-- @return boolean or (nil, string): True if manifest was updated successfully,
-- or nil and an error message.
function writer.remove_from_manifest(name, version, repo, deps_mode)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
local rocks_dir = path.rocks_dir(repo or cfg.root_dir)
assert(type(deps_mode) == "string")
if deps_mode == "none" then deps_mode = cfg.deps_mode end
local manifest, err = manif.load_manifest(rocks_dir)
if not manifest then
util.printerr("No existing manifest. Attempting to rebuild...")
-- Manifest built by `writer.make_manifest` should already
-- include up-to-date information, no need to update it.
return writer.make_manifest(rocks_dir, deps_mode)
end
local package_entry = manifest.repository[name]
if package_entry == nil or package_entry[version] == nil then
-- entry is already missing from repository, no need to do anything
return true
end
local version_entry = package_entry[version][1]
if not version_entry then
-- manifest looks corrupted, rebuild
return writer.make_manifest(rocks_dir, deps_mode)
end
remove_package_items(manifest.modules, name, version, version_entry.modules)
remove_package_items(manifest.commands, name, version, version_entry.commands)
package_entry[version] = nil
manifest.dependencies[name][version] = nil
if not next(package_entry) then
-- No more versions of this package.
manifest.repository[name] = nil
manifest.dependencies[name] = nil
end
update_dependencies(manifest, deps_mode)
if cfg.no_manifest then
return true
end
return save_table(rocks_dir, "manifest", manifest)
end
--- Report missing dependencies for all rocks installed in a repository.
-- @param repo string or nil: Pathname of a local repository. If not given,
-- the default local repository is used.
-- @param deps_mode string: Dependency mode: "one" for the current default tree,
-- "all" for all trees, "order" for all trees with priority >= the current default,
-- "none" for using the default dependency mode from the configuration.
function writer.check_dependencies(repo, deps_mode)
local rocks_dir = path.rocks_dir(repo or cfg.root_dir)
assert(type(deps_mode) == "string")
if deps_mode == "none" then deps_mode = cfg.deps_mode end
local manifest = manif.load_manifest(rocks_dir)
if not manifest then
return
end
for name, versions in util.sortedpairs(manifest.repository) do
for version, version_entries in util.sortedpairs(versions, vers.compare_versions) do
for _, entry in ipairs(version_entries) do
if entry.arch == "installed" then
if manifest.dependencies[name] and manifest.dependencies[name][version] then
deps.report_missing_dependencies(name, version, manifest.dependencies[name][version], deps_mode, util.get_rocks_provided())
end
end
end
end
end
end
return writer

View file

@ -1,183 +0,0 @@
-- Create rock files, packing sources or binaries.
local pack = {}
local unpack = unpack or table.unpack
local queries = require("luarocks.queries")
local path = require("luarocks.path")
local repos = require("luarocks.repos")
local fetch = require("luarocks.fetch")
local fs = require("luarocks.fs")
local cfg = require("luarocks.core.cfg")
local util = require("luarocks.util")
local dir = require("luarocks.dir")
local manif = require("luarocks.manif")
local search = require("luarocks.search")
local signing = require("luarocks.signing")
--- 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.
function pack.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_abs_filename
local name_version = rockspec.name .. "-" .. rockspec.version
local rock_file = fs.absolute_name(name_version .. ".src.rock")
local temp_dir, err = fs.make_temp_dir("pack-"..name_version)
if not temp_dir then
return nil, "Failed creating temporary directory: "..err
end
util.schedule_function(fs.delete, temp_dir)
local source_file, source_dir = fetch.fetch_sources(rockspec, true, temp_dir)
if not source_file then
return nil, source_dir
end
local ok, err = fs.change_dir(source_dir)
if not ok then return nil, err end
fs.delete(rock_file)
fs.copy(rockspec_file, source_dir, "read")
ok, err = fs.zip(rock_file, dir.base_name(rockspec_file), dir.base_name(source_file))
if not ok then
return nil, "Failed packing "..rock_file.." - "..err
end
fs.pop_dir()
return rock_file
end
local function copy_back_files(name, version, file_tree, deploy_dir, pack_dir, perms)
local ok, err = fs.make_dir(pack_dir)
if not ok then return nil, err end
for file, sub in pairs(file_tree) do
local source = dir.path(deploy_dir, file)
local target = dir.path(pack_dir, file)
if type(sub) == "table" then
local ok, err = copy_back_files(name, version, sub, source, target)
if not ok then return nil, err end
else
local versioned = path.versioned_name(source, deploy_dir, name, version)
if fs.exists(versioned) then
fs.copy(versioned, target, perms)
else
fs.copy(source, target, perms)
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.
-- @param tree string or nil: An optional tree to pick the package from.
-- @return string or (nil, string): The filename of the resulting
-- .src.rock file; or nil and an error message.
function pack.pack_installed_rock(query, tree)
local name, version, repo, repo_url = search.pick_installed_rock(query, tree)
if not name then
return nil, version
end
local root = path.root_from_rocks_dir(repo_url)
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, err = manif.load_rock_manifest(name, version, root)
if not rock_manifest then return nil, err 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
local ok, err = copy_back_files(name, version, rock_manifest.lib, path.deploy_lib_dir(repo), dir.path(temp_dir, "lib"), "exec")
if not ok then return nil, "Failed copying back files: " .. err end
is_binary = true
end
if rock_manifest.lua then
local ok, err = copy_back_files(name, version, rock_manifest.lua, path.deploy_lua_dir(repo), dir.path(temp_dir, "lua"), "read")
if not ok then return nil, "Failed copying back files: " .. err end
end
local ok, err = fs.change_dir(temp_dir)
if not ok then return nil, err end
if not is_binary and not repos.has_binaries(name, version) then
rock_file = rock_file:gsub("%."..cfg.arch:gsub("%-","%%-").."%.", ".all.")
end
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.report_and_sign_local_file(file, err, sign)
if err then
return nil, err
end
local sigfile
if sign then
sigfile, err = signing.sign_file(file)
util.printout()
end
util.printout("Packed: "..file)
if sigfile then
util.printout("Signature stored in: "..sigfile)
end
if err then
return nil, err
end
return true
end
function pack.pack_binary_rock(name, namespace, version, sign, 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, err = fs.make_temp_dir("luarocks-build-pack-"..dir.base_name(name))
if not temp_dir then
return nil, "Failed creating temporary directory: "..err
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
local query = queries.new(rname, namespace, rversion)
local file, err = pack.pack_installed_rock(query, temp_dir)
return pack.report_and_sign_local_file(file, err, sign)
end
return pack

View file

@ -1,262 +0,0 @@
--- 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.
local path = {}
local core = require("luarocks.core.path")
local dir = require("luarocks.dir")
local cfg = require("luarocks.core.cfg")
local util = require("luarocks.util")
path.rocks_dir = core.rocks_dir
path.versioned_name = core.versioned_name
path.path_to_module = core.path_to_module
path.deploy_lua_dir = core.deploy_lua_dir
path.deploy_lib_dir = core.deploy_lib_dir
path.map_trees = core.map_trees
path.rocks_tree_to_string = core.rocks_tree_to_string
--- 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 path.rockspec_name_from_rock(rock_name)
assert(type(rock_name) == "string")
local base_name = dir.base_name(rock_name)
return base_name:match("(.*)%.[^.]*.rock") .. ".rockspec"
end
function path.root_from_rocks_dir(rocks_dir)
assert(type(rocks_dir) == "string")
return rocks_dir:match("(.*)" .. util.matchquote(cfg.rocks_subdir) .. ".*$")
end
function path.root_dir(tree)
if type(tree) == "string" then
return tree
else
assert(type(tree) == "table")
return tree.root
end
end
function path.deploy_bin_dir(tree)
return dir.path(path.root_dir(tree), "bin")
end
function path.manifest_file(tree)
return dir.path(path.rocks_dir(tree), "manifest")
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 path.versions_dir(name, tree)
assert(type(name) == "string" and not name:match("/"))
return dir.path(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 path.install_dir(name, version, tree)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
return dir.path(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 path.rockspec_file(name, version, tree)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
return dir.path(path.rocks_dir(tree), name, version, name.."-"..version..".rockspec")
end
--- Get the local filename of the rock_manifest file of an installed rock.
-- @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 path.rock_manifest_file(name, version, tree)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
return dir.path(path.rocks_dir(tree), name, version, "rock_manifest")
end
--- Get the local filename of the rock_namespace file of an installed rock.
-- @param name string: The package name (without a namespace).
-- @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 path.rock_namespace_file(name, version, tree)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
return dir.path(path.rocks_dir(tree), name, version, "rock_namespace")
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 path.lib_dir(name, version, tree)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
return dir.path(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 path.lua_dir(name, version, tree)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
return dir.path(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 path.doc_dir(name, version, tree)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
return dir.path(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 path.conf_dir(name, version, tree)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
return dir.path(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 path.bin_dir(name, version, tree)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
return dir.path(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 path.parse_name(file_name)
assert(type(file_name) == "string")
if file_name:match("%.rock$") then
return dir.base_name(file_name):match("(.*)-([^-]+-%d+)%.([^.]+)%.rock$")
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 path.make_url(pathname, name, version, arch)
assert(type(pathname) == "string")
assert(type(name) == "string" and not name:match("/"))
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
--- 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 path.module_to_path(mod)
assert(type(mod) == "string")
return (mod:gsub("[^.]*$", ""):gsub("%.", "/"))
end
function path.use_tree(tree)
cfg.root_dir = tree
cfg.rocks_dir = path.rocks_dir(tree)
cfg.deploy_bin_dir = path.deploy_bin_dir(tree)
cfg.deploy_lua_dir = path.deploy_lua_dir(tree)
cfg.deploy_lib_dir = path.deploy_lib_dir(tree)
-- TODO Do we want LuaRocks itself to use whatever tree is in use?
-- package.path = dir.path(path.deploy_lua_dir(tree), "?.lua") .. ";"
-- .. dir.path(path.deploy_lua_dir(tree), "?/init.lua") .. ";"
-- .. package.path
-- package.cpath = dir.path(path.deploy_lib_dir(tree), "?." .. cfg.lib_extension) .. ";"
-- .. package.cpath
end
--- Get the namespace of a locally-installed rock, if any.
-- @param name string: The rock name, without a namespace.
-- @param version string: The rock version.
-- @param tree string: The local tree to use.
-- @return string?: The namespace if it exists, or nil.
function path.read_namespace(name, version, tree)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
assert(type(tree) == "string")
local namespace
local fd = io.open(path.rock_namespace_file(name, version, tree), "r")
if fd then
namespace = fd:read("*a")
fd:close()
end
return namespace
end
function path.package_paths(deps_mode)
local lpaths = {}
local lcpaths = {}
path.map_trees(deps_mode, function(tree)
local root = path.root_dir(tree)
table.insert(lpaths, dir.path(root, cfg.lua_modules_path, "?.lua"))
table.insert(lpaths, dir.path(root, cfg.lua_modules_path, "?/init.lua"))
table.insert(lcpaths, dir.path(root, cfg.lib_modules_path, "?." .. cfg.lib_extension))
end)
return table.concat(lpaths, ";"), table.concat(lcpaths, ";")
end
return path

View file

@ -1,257 +0,0 @@
--- Utility module for loading files into tables and
-- saving tables into files.
local persist = {}
local core = require("luarocks.core.persist")
local util = require("luarocks.util")
local dir = require("luarocks.dir")
local fs = require("luarocks.fs")
persist.run_file = core.run_file
persist.load_into_table = core.load_into_table
local write_table
--- Write a value as Lua code.
-- This function handles only numbers and strings, invoking write_table
-- to write tables.
-- @param out table or userdata: a writer object supporting :write() method.
-- @param v: the value to be written.
-- @param level number: the indentation level
-- @param sub_order table: optional prioritization table
-- @see write_table
function persist.write_value(out, v, level, sub_order)
if type(v) == "table" then
level = level or 0
write_table(out, v, level + 1, sub_order)
elseif type(v) == "string" then
if v:match("[\r\n]") then
local open, close = "[[", "]]"
local equals = 0
local v_with_bracket = v.."]"
while v_with_bracket: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(("%q"):format(v))
end
else
out:write(tostring(v))
end
end
local is_valid_plain_key
do
local keywords = {
["and"] = true,
["break"] = true,
["do"] = true,
["else"] = true,
["elseif"] = true,
["end"] = true,
["false"] = true,
["for"] = true,
["function"] = true,
["goto"] = true,
["if"] = true,
["in"] = true,
["local"] = true,
["nil"] = true,
["not"] = true,
["or"] = true,
["repeat"] = true,
["return"] = true,
["then"] = true,
["true"] = true,
["until"] = true,
["while"] = true,
}
function is_valid_plain_key(k)
return type(k) == "string"
and k:match("^[a-zA-Z_][a-zA-Z0-9_]*$")
and not keywords[k]
end
end
local function write_table_key_assignment(out, k, level)
if is_valid_plain_key(k) then
out:write(k)
else
out:write("[")
persist.write_value(out, k, level)
out:write("]")
end
out:write(" = ")
end
--- Write a table as Lua code in curly brackets notation to a writer object.
-- Only numbers, strings and tables (containing numbers, strings
-- or other recursively processed tables) are supported.
-- @param out table or userdata: a writer object supporting :write() method.
-- @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 _ = 1, level do out:write(indentation) end
end
if k == i then
i = i + 1
else
write_table_key_assignment(out, k, level)
end
persist.write_value(out, v, level, sub_order)
if type(v) == "number" then
sep = ", "
indent = false
else
sep = ",\n"
indent = true
end
end
if sep ~= "\n" then
out:write("\n")
for _ = 1, level - 1 do out:write(indentation) end
end
out:write("}")
end
--- Write a table as series of assignments to a writer object.
-- @param out table or userdata: a writer object supporting :write() method.
-- @param tbl table: the table to be written.
-- @param field_order table: optional prioritization table
-- @return true if successful; nil and error message if failed.
local function write_table_as_assignments(out, tbl, field_order)
for k, v, sub_order in util.sortedpairs(tbl, field_order) do
if not is_valid_plain_key(k) then
return nil, "cannot store '"..tostring(k).."' as a plain key."
end
out:write(k.." = ")
persist.write_value(out, v, 0, sub_order)
out:write("\n")
end
return true
end
--- Write a table using Lua table syntax to a writer object.
-- @param out table or userdata: a writer object supporting :write() method.
-- @param tbl table: the table to be written.
local function write_table_as_table(out, tbl)
out:write("return {\n")
for k, v, sub_order in util.sortedpairs(tbl) do
out:write(" ")
write_table_key_assignment(out, k, 1)
persist.write_value(out, v, 1, sub_order)
out:write(",\n")
end
out:write("}\n")
end
--- Save the contents of a table to a string.
-- 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 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 persisted data as string; or nil and an error message
function persist.save_from_table_to_string(tbl, field_order)
local out = {buffer = {}}
function out:write(data) table.insert(self.buffer, data) end
local ok, err = write_table_as_assignments(out, tbl, field_order)
if not ok then
return nil, err
end
return table.concat(out.buffer)
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 persist.save_from_table(filename, tbl, field_order)
local out = io.open(filename, "w")
if not out then
return nil, "Cannot create file at "..filename
end
local ok, err = write_table_as_assignments(out, tbl, field_order)
out:close()
if not ok then
return nil, err
end
return true
end
--- Save the contents of a table as a module.
-- The module contains a 'return' statement that returns the table.
-- 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
-- @return boolean or (nil, string): true if successful, or nil and a
-- message in case of errors.
function persist.save_as_module(filename, tbl)
local out = io.open(filename, "w")
if not out then
return nil, "Cannot create file at "..filename
end
write_table_as_table(out, tbl)
out:close()
return true
end
function persist.load_config_file_if_basic(filename, cfg)
local env = {
home = cfg.home
}
local result, err, errcode = persist.load_into_table(filename, env)
if errcode == "load" or errcode == "run" then
-- bad config file or depends on env, so error out
return nil, "Could not read existing config file " .. filename
end
local tbl
if errcode == "open" then
-- could not open, maybe file does not exist
tbl = {}
else
tbl = result
tbl.home = nil
end
return tbl
end
function persist.save_default_lua_version(prefix, lua_version)
local ok, err = fs.make_dir(prefix)
if not ok then
return nil, err
end
local fd, err = io.open(dir.path(prefix, "default-lua-version.lua"), "w")
if not fd then
return nil, err
end
fd:write('return "' .. lua_version .. '"\n')
fd:close()
return true
end
return persist

View file

@ -1,215 +0,0 @@
local queries = {}
local vers = require("luarocks.core.vers")
local util = require("luarocks.util")
local cfg = require("luarocks.core.cfg")
local query_mt = {}
query_mt.__index = query_mt
function query_mt.type()
return "query"
end
-- Fallback default value for the `arch` field, if not explicitly set.
query_mt.arch = {
src = true,
all = true,
rockspec = true,
installed = true,
-- [cfg.arch] = true, -- this is set later
}
-- Fallback default value for the `substring` field, if not explicitly set.
query_mt.substring = false
--- Convert the arch field of a query table to table format.
-- @param input string, table or nil
local function arch_to_table(input)
if type(input) == "table" then
return input
elseif type(input) == "string" then
local arch = {}
for a in input:gmatch("[%w_-]+") do
arch[a] = true
end
return arch
end
end
--- Prepare a query in dependency table format.
-- @param name string: the package name.
-- @param namespace string?: the package namespace.
-- @param version string?: the package version.
-- @param substring boolean?: match substrings of the name
-- (default is false, match full name)
-- @param arch string?: a string with pipe-separated accepted arch values
-- @param operator string?: operator for version matching (default is "==")
-- @return table: A query in table format
function queries.new(name, namespace, version, substring, arch, operator)
assert(type(name) == "string")
assert(type(namespace) == "string" or not namespace)
assert(type(version) == "string" or not version)
assert(type(substring) == "boolean" or not substring)
assert(type(arch) == "string" or not arch)
assert(type(operator) == "string" or not operator)
operator = operator or "=="
local self = {
name = name,
namespace = namespace,
constraints = {},
substring = substring,
arch = arch_to_table(arch),
}
if version then
table.insert(self.constraints, { op = operator, version = vers.parse_version(version)})
end
query_mt.arch[cfg.arch] = true
return setmetatable(self, query_mt)
end
-- Query for all packages
-- @param arch string (optional)
function queries.all(arch)
assert(type(arch) == "string" or not arch)
return queries.new("", nil, nil, true, arch)
end
do
local parse_constraints
do
local parse_constraint
do
local operators = {
["=="] = "==",
["~="] = "~=",
[">"] = ">",
["<"] = "<",
[">="] = ">=",
["<="] = "<=",
["~>"] = "~>",
-- plus some convenience translations
[""] = "==",
["="] = "==",
["!="] = "~="
}
--- 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.
parse_constraint = function(input)
assert(type(input) == "string")
local no_upgrade, op, version, rest = input:match("^(@?)([<>=~!]*)%s*([%w%.%_%-]+)[%s,]*(.*)")
local _op = operators[op]
version = vers.parse_version(version)
if not _op then
return nil, "Encountered bad constraint operator: '"..tostring(op).."' in '"..input.."'"
end
if not version then
return nil, "Could not parse version from constraint: '"..input.."'"
end
return { op = _op, version = version, no_upgrade = no_upgrade=="@" and true or nil }, rest
end
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.
parse_constraints = function(input)
assert(type(input) == "string")
local constraints, oinput, constraint = {}, input
while #input > 0 do
constraint, input = parse_constraint(input)
if constraint then
table.insert(constraints, constraint)
else
return nil, "Failed to parse constraint '"..tostring(oinput).."' with error: ".. input
end
end
return constraints
end
end
--- Prepare a query in dependency table format.
-- @param depstr string: A dependency in string format
-- as entered in rockspec files.
-- @return table: A query in table format, or nil and an error message in case of errors.
function queries.from_dep_string(depstr)
assert(type(depstr) == "string")
local ns_name, rest = depstr:match("^%s*([a-zA-Z0-9%.%-%_]*/?[a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*([^/]*)")
if not ns_name then
return nil, "failed to extract dependency name from '"..depstr.."'"
end
local constraints, err = parse_constraints(rest)
if not constraints then
return nil, err
end
local name, namespace = util.split_namespace(ns_name)
local self = {
name = name,
namespace = namespace,
constraints = constraints,
}
query_mt.arch[cfg.arch] = true
return setmetatable(self, query_mt)
end
end
function queries.from_persisted_table(tbl)
query_mt.arch[cfg.arch] = true
return setmetatable(tbl, query_mt)
end
--- Build a string representation of a query package name.
-- Includes namespace, name and version, but not arch or constraints.
-- @param query table: a query table
-- @return string: a result such as `my_user/my_rock 1.0` or `my_rock`.
function query_mt:__tostring()
local out = {}
if self.namespace then
table.insert(out, self.namespace)
table.insert(out, "/")
end
table.insert(out, self.name)
if #self.constraints > 0 then
local pretty = {}
for _, c in ipairs(self.constraints) do
local v = c.version.string
if c.op == "==" then
table.insert(pretty, v)
else
table.insert(pretty, c.op .. " " .. v)
end
end
table.insert(out, " ")
table.insert(out, table.concat(pretty, ", "))
end
return table.concat(out)
end
return queries

View file

@ -1,135 +0,0 @@
local remove = {}
local search = require("luarocks.search")
local deps = require("luarocks.deps")
local fetch = require("luarocks.fetch")
local repos = require("luarocks.repos")
local path = require("luarocks.path")
local util = require("luarocks.util")
local cfg = require("luarocks.core.cfg")
local manif = require("luarocks.manif")
local queries = require("luarocks.queries")
--- 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, deps_mode)
local dependents = {}
local skip_set = {}
skip_set[name] = {}
for version, _ in pairs(versions) do
skip_set[name][version] = true
end
local local_rocks = {}
local query_all = queries.all()
search.local_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.dependencies, rockspec.rocks_provided, skip_set, deps_mode)
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.
-- @param deps_mode: string: Which trees to check dependencies for:
-- "one" for the current default tree, "all" for all trees,
-- "order" for all trees with priority >= the current default, "none" for no trees.
-- @return boolean or (nil, string): true on success or nil and an error message.
local function delete_versions(name, versions, deps_mode)
for version, _ in pairs(versions) do
util.printout("Removing "..name.." "..version.."...")
local ok, err = repos.delete_version(name, version, deps_mode)
if not ok then return nil, err end
end
return true
end
function remove.remove_search_results(results, name, deps_mode, force, fast)
local versions = results[name]
local version = next(versions)
local second = next(versions, version)
local dependents = {}
if not fast then
util.printout("Checking stability of dependencies in the absence of")
util.printout(name.." "..table.concat(util.keys(versions), ", ").."...")
util.printout()
dependents = check_dependents(name, versions, deps_mode)
end
if #dependents > 0 then
if force or fast 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()
else
if not second then
util.printerr("Will not remove "..name.." "..version..".")
util.printerr("Removing it would break dependencies for: ")
else
util.printerr("Will not remove installed versions of "..name..".")
util.printerr("Removing them would break dependencies for: ")
end
for _, dependent in ipairs(dependents) do
util.printerr(dependent.name.." "..dependent.version)
end
util.printerr()
util.printerr("Use --force to force removal (warning: this may break modules).")
return nil, "Failed removing."
end
end
local ok, err = delete_versions(name, versions, deps_mode)
if not ok then return nil, err end
util.printout("Removal successful.")
return true
end
function remove.remove_other_versions(name, version, force, fast)
local results = {}
local query = queries.new(name, nil, version, false, nil, "~=")
search.local_manifest_search(results, cfg.rocks_dir, query)
local warn
if results[name] then
local ok, err = remove.remove_search_results(results, name, cfg.deps_mode, force, fast)
if not ok then -- downgrade failure to a warning
warn = err
end
end
if not fast then
-- since we're not using --keep, this means that all files of the rock being installed
-- should be available as non-versioned variants. Double-check that:
local rock_manifest, load_err = manif.load_rock_manifest(name, version)
local ok, err = repos.check_everything_is_installed(name, version, rock_manifest, cfg.root_dir, false)
if not ok then
return nil, err
end
end
return true, nil, warn
end
return remove

View file

@ -1,689 +0,0 @@
--- Functions for managing the repository on disk.
local repos = {}
local fs = require("luarocks.fs")
local path = require("luarocks.path")
local cfg = require("luarocks.core.cfg")
local util = require("luarocks.util")
local dir = require("luarocks.dir")
local manif = require("luarocks.manif")
local vers = require("luarocks.core.vers")
local unpack = unpack or table.unpack -- luacheck: ignore 211
--- Get type and name of an item (a module or a command) provided by a file.
-- @param deploy_type string: rock manifest subtree the file comes from ("bin", "lua", or "lib").
-- @param file_path string: path to the file relatively to deploy_type subdirectory.
-- @return (string, string): item type ("module" or "command") and name.
local function get_provided_item(deploy_type, file_path)
assert(type(deploy_type) == "string")
assert(type(file_path) == "string")
local item_type = deploy_type == "bin" and "command" or "module"
local item_name = item_type == "command" and file_path or path.path_to_module(file_path)
return item_type, item_name
end
-- Tree of files installed by a package are stored
-- in its rock manifest. Some of these files have to
-- be deployed to locations where Lua can load them as
-- modules or where they can be used as commands.
-- These files are characterised by pair
-- (deploy_type, file_path), where deploy_type is the first
-- component of the file path and file_path is the rest of the
-- path. Only files with deploy_type in {"lua", "lib", "bin"}
-- are deployed somewhere.
-- Each deployed file provides an "item". An item is
-- characterised by pair (item_type, item_name).
-- item_type is "command" for files with deploy_type
-- "bin" and "module" for deploy_type in {"lua", "lib"}.
-- item_name is same as file_path for commands
-- and is produced using path.path_to_module(file_path)
-- for modules.
--- 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.
local function get_installed_versions(name)
assert(type(name) == "string" and not name:match("/"))
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 repos.is_installed(name, version)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
return fs.is_dir(path.install_dir(name, version))
end
function repos.recurse_rock_manifest_entry(entry, action)
assert(type(action) == "function")
if entry == nil then
return true
end
local function do_recurse_rock_manifest_entry(tree, parent_path)
for file, sub in pairs(tree) do
local sub_path = (parent_path and (parent_path .. "/") or "") .. file
local ok, err -- luacheck: ignore 231
if type(sub) == "table" then
ok, err = do_recurse_rock_manifest_entry(sub, sub_path)
else
ok, err = action(sub_path)
end
if err then return nil, err end
end
return true
end
return do_recurse_rock_manifest_entry(entry)
end
local function store_package_data(result, rock_manifest, deploy_type)
if rock_manifest[deploy_type] then
repos.recurse_rock_manifest_entry(rock_manifest[deploy_type], function(file_path)
local _, item_name = get_provided_item(deploy_type, file_path)
result[item_name] = file_path
return true
end)
end
end
--- Obtain a table of modules within an installed package.
-- @param name 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 names
-- and values are file paths of files providing modules
-- relative to "lib" or "lua" rock manifest subtree.
-- If no modules are found or if package name or version
-- are invalid, an empty table is returned.
function repos.package_modules(name, version)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
local result = {}
local rock_manifest = manif.load_rock_manifest(name, version)
if not rock_manifest then return result end
store_package_data(result, rock_manifest, "lib")
store_package_data(result, rock_manifest, "lua")
return result
end
--- Obtain a table of command-line scripts within an installed package.
-- @param name 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 commands where keys and values are command names
-- as strings - file paths of files providing commands
-- relative to "bin" rock manifest subtree.
-- If no commands are found or if package name or version
-- are invalid, an empty table is returned.
function repos.package_commands(name, version)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
local result = {}
local rock_manifest = manif.load_rock_manifest(name, version)
if not rock_manifest then return result end
store_package_data(result, 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 repos.has_binaries(name, version)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
local rock_manifest = manif.load_rock_manifest(name, version)
if rock_manifest and rock_manifest.bin then
for bin_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, bin_name)) then
return true
end
end
end
return false
end
function repos.run_hook(rockspec, hook_name)
assert(rockspec:type() == "rockspec")
assert(type(hook_name) == "string")
local hooks = rockspec.hooks
if not hooks then
return true
end
if cfg.hooks_enabled == false then
return nil, "This rockspec contains hooks, which are blocked by the 'hooks_enabled' setting in your LuaRocks configuration."
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
function repos.should_wrap_bin_scripts(rockspec)
assert(rockspec:type() == "rockspec")
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
local function find_suffixed(file, suffix)
local filenames = {file}
if suffix and suffix ~= "" then
table.insert(filenames, 1, file .. suffix)
end
for _, filename in ipairs(filenames) do
if fs.exists(filename) then
return filename
end
end
return nil, table.concat(filenames, ", ") .. " not found"
end
local function check_suffix(filename, suffix)
local suffixed_filename, err = find_suffixed(filename, suffix)
if not suffixed_filename then
return ""
end
return suffixed_filename:sub(#filename + 1)
end
-- Files can be deployed using versioned and non-versioned names.
-- Several items with same type and name can exist if they are
-- provided by different packages or versions. In any case
-- item from the newest version of lexicographically smallest package
-- is deployed using non-versioned name and others use versioned names.
local function get_deploy_paths(name, version, deploy_type, file_path, repo)
assert(type(name) == "string")
assert(type(version) == "string")
assert(type(deploy_type) == "string")
assert(type(file_path) == "string")
repo = repo or cfg.root_dir
local deploy_dir = path["deploy_" .. deploy_type .. "_dir"](repo)
local non_versioned = dir.path(deploy_dir, file_path)
local versioned = path.versioned_name(non_versioned, deploy_dir, name, version)
return { nv = non_versioned, v = versioned }
end
local function check_spot_if_available(name, version, deploy_type, file_path)
local item_type, item_name = get_provided_item(deploy_type, file_path)
local cur_name, cur_version = manif.get_current_provider(item_type, item_name)
-- older versions of LuaRocks (< 3) registered "foo.init" files as "foo"
-- (which caused problems, so that behavior was changed). But look for that
-- in the manifest anyway for backward compatibility.
if not cur_name and deploy_type == "lua" and item_name:match("%.init$") then
cur_name, cur_version = manif.get_current_provider(item_type, (item_name:gsub("%.init$", "")))
end
if (not cur_name)
or (name < cur_name)
or (name == cur_name and (version == cur_version
or vers.compare_versions(version, cur_version))) then
return "nv", cur_name, cur_version, item_name
else
-- Existing version has priority, deploy new version using versioned name.
return "v", cur_name, cur_version, item_name
end
end
local function backup_existing(should_backup, target)
if not should_backup then
fs.delete(target)
return
end
if fs.exists(target) then
local backup = target
repeat
backup = backup.."~"
until not fs.exists(backup) -- Slight race condition here, but shouldn't be a problem.
util.warning(target.." is not tracked by this installation of LuaRocks. Moving it to "..backup)
local move_ok, move_err = os.rename(target, backup)
if not move_ok then
return nil, move_err
end
return backup
end
end
local function prepare_op_install()
local mkdirs = {}
local rmdirs = {}
local function memoize_mkdir(d)
if mkdirs[d] then
return true
end
local ok, err = fs.make_dir(d)
if not ok then
return nil, err
end
mkdirs[d] = true
return true
end
local function op_install(op)
local ok, err = memoize_mkdir(dir.dir_name(op.dst))
if not ok then
return nil, err
end
local backup, err = backup_existing(op.backup, op.realdst or op.dst)
if err then
return nil, err
end
if backup then
op.backup_file = backup
end
ok, err = op.fn(op.src, op.dst, op.backup)
if not ok then
return nil, err
end
rmdirs[dir.dir_name(op.src)] = true
return true
end
local function done_op_install()
for d, _ in pairs(rmdirs) do
fs.remove_dir_tree_if_empty(d)
end
end
return op_install, done_op_install
end
local function rollback_install(op)
fs.delete(op.dst)
if op.backup_file then
os.rename(op.backup_file, op.dst)
end
fs.remove_dir_tree_if_empty(dir.dir_name(op.dst))
return true
end
local function op_rename(op)
if op.suffix then
local suffix = check_suffix(op.src, op.suffix)
op.src = op.src .. suffix
op.dst = op.dst .. suffix
end
if fs.exists(op.src) then
fs.make_dir(dir.dir_name(op.dst))
fs.delete(op.dst)
local ok, err = os.rename(op.src, op.dst)
fs.remove_dir_tree_if_empty(dir.dir_name(op.src))
return ok, err
else
return true
end
end
local function rollback_rename(op)
return op_rename({ src = op.dst, dst = op.src })
end
local function prepare_op_delete()
local deletes = {}
local rmdirs = {}
local function done_op_delete()
for _, f in ipairs(deletes) do
os.remove(f)
end
for d, _ in pairs(rmdirs) do
fs.remove_dir_tree_if_empty(d)
end
end
local function op_delete(op)
if op.suffix then
local suffix = check_suffix(op.name, op.suffix)
op.name = op.name .. suffix
end
table.insert(deletes, op.name)
rmdirs[dir.dir_name(op.name)] = true
end
return op_delete, done_op_delete
end
local function rollback_ops(ops, op_fn, n)
for i = 1, n do
op_fn(ops[i])
end
end
--- Double check that all files referenced in `rock_manifest` are installed in `repo`.
function repos.check_everything_is_installed(name, version, rock_manifest, repo, accept_versioned)
local missing = {}
for _, category in ipairs({"bin", "lua", "lib"}) do
local suffix = (category == "bin") and cfg.wrapper_suffix or ""
if rock_manifest[category] then
repos.recurse_rock_manifest_entry(rock_manifest[category], function(file_path)
local paths = get_deploy_paths(name, version, category, file_path, repo)
if not (fs.exists(paths.nv .. suffix) or (accept_versioned and fs.exists(paths.v .. suffix))) then
table.insert(missing, paths.nv .. suffix)
end
end)
end
end
if #missing > 0 then
return nil, "failed deploying files. " ..
"The following files were not installed:\n" ..
table.concat(missing, "\n")
end
return true
end
--- Deploy a package from the rocks subdirectory.
-- @param name string: name of package
-- @param version string: exact package version in string format
-- @param wrap_bin_scripts bool: whether commands written in Lua should be wrapped.
-- @param deps_mode: string: Which trees to check dependencies for:
-- "one" for the current default tree, "all" for all trees,
-- "order" for all trees with priority >= the current default, "none" for no trees.
function repos.deploy_files(name, version, wrap_bin_scripts, deps_mode)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
assert(type(wrap_bin_scripts) == "boolean")
local rock_manifest, load_err = manif.load_rock_manifest(name, version)
if not rock_manifest then return nil, load_err end
local repo = cfg.root_dir
local renames = {}
local installs = {}
local function install_binary(source, target)
if wrap_bin_scripts and fs.is_lua(source) then
return fs.wrap_script(source, target, deps_mode, name, version)
else
return fs.copy_binary(source, target)
end
end
local function move_lua(source, target)
return fs.move(source, target, "read")
end
local function move_lib(source, target)
return fs.move(source, target, "exec")
end
if rock_manifest.bin then
local source_dir = path.bin_dir(name, version)
repos.recurse_rock_manifest_entry(rock_manifest.bin, function(file_path)
local source = dir.path(source_dir, file_path)
local paths = get_deploy_paths(name, version, "bin", file_path, repo)
local mode, cur_name, cur_version = check_spot_if_available(name, version, "bin", file_path)
if mode == "nv" and cur_name then
local cur_paths = get_deploy_paths(cur_name, cur_version, "bin", file_path, repo)
table.insert(renames, { src = cur_paths.nv, dst = cur_paths.v, suffix = cfg.wrapper_suffix })
end
local target = mode == "nv" and paths.nv or paths.v
local backup = name ~= cur_name or version ~= cur_version
local realdst = (wrap_bin_scripts and fs.is_lua(source))
and (target .. (cfg.wrapper_suffix or ""))
or target
table.insert(installs, { fn = install_binary, src = source, dst = target, backup = backup, realdst = realdst })
end)
end
if rock_manifest.lua then
local source_dir = path.lua_dir(name, version)
repos.recurse_rock_manifest_entry(rock_manifest.lua, function(file_path)
local source = dir.path(source_dir, file_path)
local paths = get_deploy_paths(name, version, "lua", file_path, repo)
local mode, cur_name, cur_version = check_spot_if_available(name, version, "lua", file_path)
if mode == "nv" and cur_name then
local cur_paths = get_deploy_paths(cur_name, cur_version, "lua", file_path, repo)
table.insert(renames, { src = cur_paths.nv, dst = cur_paths.v })
cur_paths = get_deploy_paths(cur_name, cur_version, "lib", file_path:gsub("%.lua$", "." .. cfg.lib_extension), repo)
table.insert(renames, { src = cur_paths.nv, dst = cur_paths.v })
end
local target = mode == "nv" and paths.nv or paths.v
local backup = name ~= cur_name or version ~= cur_version
table.insert(installs, { fn = move_lua, src = source, dst = target, backup = backup })
end)
end
if rock_manifest.lib then
local source_dir = path.lib_dir(name, version)
repos.recurse_rock_manifest_entry(rock_manifest.lib, function(file_path)
local source = dir.path(source_dir, file_path)
local paths = get_deploy_paths(name, version, "lib", file_path, repo)
local mode, cur_name, cur_version = check_spot_if_available(name, version, "lib", file_path)
if mode == "nv" and cur_name then
local cur_paths = get_deploy_paths(cur_name, cur_version, "lua", file_path:gsub("%.[^.]+$", ".lua"), repo)
table.insert(renames, { src = cur_paths.nv, dst = cur_paths.v })
cur_paths = get_deploy_paths(cur_name, cur_version, "lib", file_path, repo)
table.insert(renames, { src = cur_paths.nv, dst = cur_paths.v })
end
local target = mode == "nv" and paths.nv or paths.v
local backup = name ~= cur_name or version ~= cur_version
table.insert(installs, { fn = move_lib, src = source, dst = target, backup = backup })
end)
end
for i, op in ipairs(renames) do
local ok, err = op_rename(op)
if not ok then
rollback_ops(renames, rollback_rename, i - 1)
return nil, err
end
end
local op_install, done_op_install = prepare_op_install()
for i, op in ipairs(installs) do
local ok, err = op_install(op)
if not ok then
rollback_ops(installs, rollback_install, i - 1)
rollback_ops(renames, rollback_rename, #renames)
return nil, err
end
end
done_op_install()
local ok, err = repos.check_everything_is_installed(name, version, rock_manifest, repo, true)
if not ok then
return nil, err
end
local writer = require("luarocks.manif.writer")
return writer.add_to_manifest(name, version, nil, deps_mode)
end
local function add_to_double_checks(double_checks, name, version)
double_checks[name] = double_checks[name] or {}
double_checks[name][version] = true
end
local function double_check_all(double_checks, repo)
local errs = {}
for next_name, versions in pairs(double_checks) do
for next_version in pairs(versions) do
local rock_manifest, load_err = manif.load_rock_manifest(next_name, next_version)
local ok, err = repos.check_everything_is_installed(next_name, next_version, rock_manifest, repo, true)
if not ok then
table.insert(errs, err)
end
end
end
if next(errs) then
return nil, table.concat(errs, "\n")
end
return true
end
--- Delete a package from the local repository.
-- @param name string: name of package
-- @param version string: exact package version in string format
-- @param deps_mode: string: Which trees to check dependencies for:
-- "one" for the current default tree, "all" for all trees,
-- "order" for all trees with priority >= the current default, "none" for no trees.
-- @param quick boolean: do not try to fix the versioned name
-- of another version that provides the same module that
-- was deleted. This is used during 'purge', as every module
-- will be eventually deleted.
function repos.delete_version(name, version, deps_mode, quick)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
assert(type(deps_mode) == "string")
local rock_manifest, load_err = manif.load_rock_manifest(name, version)
if not rock_manifest then
if not quick then
local writer = require("luarocks.manif.writer")
writer.remove_from_manifest(name, version, nil, deps_mode)
return nil, "rock_manifest file not found for "..name.." "..version.." - removed entry from the manifest"
end
return nil, load_err
end
local repo = cfg.root_dir
local renames = {}
local deletes = {}
local double_checks = {}
if rock_manifest.bin then
repos.recurse_rock_manifest_entry(rock_manifest.bin, function(file_path)
local paths = get_deploy_paths(name, version, "bin", file_path, repo)
local mode, cur_name, cur_version, item_name = check_spot_if_available(name, version, "bin", file_path)
if mode == "v" then
table.insert(deletes, { name = paths.v, suffix = cfg.wrapper_suffix })
else
table.insert(deletes, { name = paths.nv, suffix = cfg.wrapper_suffix })
local next_name, next_version = manif.get_next_provider("command", item_name)
if next_name then
add_to_double_checks(double_checks, next_name, next_version)
local next_paths = get_deploy_paths(next_name, next_version, "bin", file_path, repo)
table.insert(renames, { src = next_paths.v, dst = next_paths.nv, suffix = cfg.wrapper_suffix })
end
end
end)
end
if rock_manifest.lua then
repos.recurse_rock_manifest_entry(rock_manifest.lua, function(file_path)
local paths = get_deploy_paths(name, version, "lua", file_path, repo)
local mode, cur_name, cur_version, item_name = check_spot_if_available(name, version, "lua", file_path)
if mode == "v" then
table.insert(deletes, { name = paths.v })
else
table.insert(deletes, { name = paths.nv })
local next_name, next_version = manif.get_next_provider("module", item_name)
if next_name then
add_to_double_checks(double_checks, next_name, next_version)
local next_lua_paths = get_deploy_paths(next_name, next_version, "lua", file_path, repo)
table.insert(renames, { src = next_lua_paths.v, dst = next_lua_paths.nv })
local next_lib_paths = get_deploy_paths(next_name, next_version, "lib", file_path:gsub("%.[^.]+$", ".lua"), repo)
table.insert(renames, { src = next_lib_paths.v, dst = next_lib_paths.nv })
end
end
end)
end
if rock_manifest.lib then
repos.recurse_rock_manifest_entry(rock_manifest.lib, function(file_path)
local paths = get_deploy_paths(name, version, "lib", file_path, repo)
local mode, cur_name, cur_version, item_name = check_spot_if_available(name, version, "lib", file_path)
if mode == "v" then
table.insert(deletes, { name = paths.v })
else
table.insert(deletes, { name = paths.nv })
local next_name, next_version = manif.get_next_provider("module", item_name)
if next_name then
add_to_double_checks(double_checks, next_name, next_version)
local next_lua_paths = get_deploy_paths(next_name, next_version, "lua", file_path:gsub("%.[^.]+$", ".lua"), repo)
table.insert(renames, { src = next_lua_paths.v, dst = next_lua_paths.nv })
local next_lib_paths = get_deploy_paths(next_name, next_version, "lib", file_path, repo)
table.insert(renames, { src = next_lib_paths.v, dst = next_lib_paths.nv })
end
end
end)
end
local op_delete, done_op_delete = prepare_op_delete()
for _, op in ipairs(deletes) do
op_delete(op)
end
done_op_delete()
if not quick then
for _, op in ipairs(renames) do
op_rename(op)
end
local ok, err = double_check_all(double_checks, repo)
if not ok then
return nil, err
end
end
fs.delete(path.install_dir(name, version))
if not get_installed_versions(name) then
fs.delete(dir.path(cfg.rocks_dir, name))
end
if quick then
return true
end
local writer = require("luarocks.manif.writer")
return writer.remove_from_manifest(name, version, nil, deps_mode)
end
return repos

View file

@ -1,2 +0,0 @@
--- Retained for compatibility reasons only. Use luarocks.loader instead.
return require("luarocks.loader")

View file

@ -1,62 +0,0 @@
local results = {}
local vers = require("luarocks.core.vers")
local util = require("luarocks.util")
local result_mt = {}
result_mt.__index = result_mt
function result_mt.type()
return "result"
end
function results.new(name, version, repo, arch, namespace)
assert(type(name) == "string" and not name:match("/"))
assert(type(version) == "string")
assert(type(repo) == "string")
assert(type(arch) == "string" or not arch)
assert(type(namespace) == "string" or not namespace)
if not namespace then
name, namespace = util.split_namespace(name)
end
local self = {
name = name,
version = version,
namespace = namespace,
arch = arch,
repo = repo,
}
return setmetatable(self, result_mt)
end
--- Test the name field of a query.
-- If query has a boolean field substring set to true,
-- 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)
if query.substring then
return name:find(query.name, 0, true) and true or false
else
return name == query.name
end
end
--- Returns true if the result satisfies a given query.
-- @param query: a query.
-- @return boolean.
function result_mt:satisfies(query)
assert(query:type() == "query")
return match_name(query, self.name)
and (query.arch[self.arch] or query.arch["any"])
and ((not query.namespace) or (query.namespace == self.namespace))
and vers.match_constraints(vers.parse_version(self.version), query.constraints)
end
return results

View file

@ -1,161 +0,0 @@
local rockspecs = {}
local cfg = require("luarocks.core.cfg")
local dir = require("luarocks.dir")
local path = require("luarocks.path")
local queries = require("luarocks.queries")
local type_rockspec = require("luarocks.type.rockspec")
local util = require("luarocks.util")
local vers = require("luarocks.core.vers")
local rockspec_mt = {}
rockspec_mt.__index = rockspec_mt
function rockspec_mt.type()
return "rockspec"
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
-- detected platforms setting are used. For example, if
-- platform "unix" is detected, then the fields of
-- tbl.platforms.unix 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.
local function platform_overrides(tbl)
assert(type(tbl) == "table" or not tbl)
if not tbl then return end
if tbl.platforms then
for platform in cfg.each_platform() do
local platform_tbl = tbl.platforms[platform]
if platform_tbl then
util.deep_merge(tbl, platform_tbl)
end
end
end
tbl.platforms = nil
end
local function convert_dependencies(rockspec, key)
if rockspec[key] then
for i = 1, #rockspec[key] do
local parsed, err = queries.from_dep_string(rockspec[key][i])
if not parsed then
return nil, "Parse error processing dependency '"..rockspec[key][i].."': "..tostring(err)
end
rockspec[key][i] = parsed
end
else
rockspec[key] = {}
end
return true
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.
local function configure_paths(rockspec)
local vars = {}
for k,v in pairs(cfg.variables) do
vars[k] = v
end
local name, version = rockspec.name, rockspec.version
vars.PREFIX = path.install_dir(name, version)
vars.LUADIR = path.lua_dir(name, version)
vars.LIBDIR = path.lib_dir(name, version)
vars.CONFDIR = path.conf_dir(name, version)
vars.BINDIR = path.bin_dir(name, version)
vars.DOCDIR = path.doc_dir(name, version)
rockspec.variables = vars
end
function rockspecs.from_persisted_table(filename, rockspec, globals, quick)
assert(type(rockspec) == "table")
assert(type(globals) == "table" or globals == nil)
assert(type(filename) == "string")
assert(type(quick) == "boolean" or quick == nil)
if rockspec.rockspec_format then
if vers.compare_versions(rockspec.rockspec_format, type_rockspec.rockspec_format) then
return nil, "Rockspec format "..rockspec.rockspec_format.." is not supported, please upgrade LuaRocks."
end
end
if not quick then
local ok, err = type_rockspec.check(rockspec, globals or {})
if not ok then
return nil, err
end
end
--- Check if rockspec format version satisfies version requirement.
-- @param rockspec table: The rockspec table.
-- @param version string: required version.
-- @return boolean: true if rockspec format matches version or is newer, false otherwise.
do
local parsed_format = vers.parse_version(rockspec.rockspec_format or "1.0")
rockspec.format_is_at_least = function(self, version)
return parsed_format >= vers.parse_version(version)
end
end
platform_overrides(rockspec.build)
platform_overrides(rockspec.dependencies)
platform_overrides(rockspec.build_dependencies)
platform_overrides(rockspec.test_dependencies)
platform_overrides(rockspec.external_dependencies)
platform_overrides(rockspec.source)
platform_overrides(rockspec.hooks)
platform_overrides(rockspec.test)
rockspec.name = rockspec.package:lower()
local protocol, pathname = dir.split_url(rockspec.source.url)
if dir.is_basic_protocol(protocol) then
rockspec.source.file = rockspec.source.file or dir.base_name(rockspec.source.url)
end
rockspec.source.protocol, rockspec.source.pathname = protocol, pathname
-- 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
rockspec.local_abs_filename = filename
local filebase = rockspec.source.file or rockspec.source.url
local base = dir.deduce_base_dir(filebase)
rockspec.source.dir_set = rockspec.source.dir ~= nil
rockspec.source.dir = rockspec.source.dir
or rockspec.source.module
or ( (filebase:match("%.lua$") or filebase:match("%.c$"))
and (rockspec:format_is_at_least("3.0")
and (dir.is_basic_protocol(protocol) and "." or base)
or ".") )
or base
rockspec.rocks_provided = util.get_rocks_provided(rockspec)
for _, key in ipairs({"dependencies", "build_dependencies", "test_dependencies"}) do
local ok, err = convert_dependencies(rockspec, key)
if not ok then
return nil, err
end
end
if not quick then
configure_paths(rockspec)
end
return setmetatable(rockspec, rockspec_mt)
end
return rockspecs

View file

@ -1,394 +0,0 @@
local search = {}
local dir = require("luarocks.dir")
local path = require("luarocks.path")
local manif = require("luarocks.manif")
local vers = require("luarocks.core.vers")
local cfg = require("luarocks.core.cfg")
local util = require("luarocks.util")
local queries = require("luarocks.queries")
local results = require("luarocks.results")
--- Store a search result (a rock or rockspec) in the result tree.
-- @param result_tree table: The result tree, where keys are package names and
-- values are tables matching version strings to arrays of
-- tables with fields "arch" and "repo".
-- @param result table: A result.
function search.store_result(result_tree, result)
assert(type(result_tree) == "table")
assert(result:type() == "result")
local name = result.name
local version = result.version
if not result_tree[name] then result_tree[name] = {} end
if not result_tree[name][version] then result_tree[name][version] = {} end
table.insert(result_tree[name][version], {
arch = result.arch,
repo = result.repo,
namespace = result.namespace,
})
end
--- Store a match in a result tree 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 result_tree table: The result tree, where keys are package names and
-- values are tables matching version strings to arrays of
-- tables with fields "arch" and "repo".
-- @param result table: a result object.
-- @param query table: a query object.
local function store_if_match(result_tree, result, query)
assert(result:type() == "result")
assert(query:type() == "query")
if result:satisfies(query) then
search.store_result(result_tree, result)
end
end
--- Perform search on a local repository.
-- @param repo string: The pathname of the local repository.
-- @param query table: a query object.
-- @param result_tree table or nil: If given, this table will store the
-- result tree; if not given, a new table will be created.
-- @return table: The result tree, where keys are package names and
-- values are tables matching version strings to arrays of
-- tables with fields "arch" and "repo".
-- If a table was given in the "result_tree" parameter, that is the result value.
function search.disk_search(repo, query, result_tree)
assert(type(repo) == "string")
assert(query:type() == "query")
assert(type(result_tree) == "table" or not result_tree)
local fs = require("luarocks.fs")
if not result_tree then
result_tree = {}
end
for name in fs.dir(repo) do
local pathname = dir.path(repo, name)
local rname, rversion, rarch = path.parse_name(name)
if rname and (pathname:match(".rockspec$") or pathname:match(".rock$")) then
local result = results.new(rname, rversion, repo, rarch)
store_if_match(result_tree, result, query)
elseif fs.is_dir(pathname) then
for version in fs.dir(pathname) do
if version:match("-%d+$") then
local namespace = path.read_namespace(name, version, repo)
local result = results.new(name, version, repo, "installed", namespace)
store_if_match(result_tree, result, query)
end
end
end
end
return result_tree
end
--- Perform search on a rocks server or tree.
-- @param result_tree table: The result tree, where keys are package names and
-- values are tables matching version strings to arrays of
-- tables with fields "arch" and "repo".
-- @param repo string: The URL of a rocks server or
-- the pathname of a rocks tree (as returned by path.rocks_dir()).
-- @param query table: a query object.
-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
-- @param is_local boolean
-- @return true or, in case of errors, nil, an error message and an optional error code.
local function manifest_search(result_tree, repo, query, lua_version, is_local)
assert(type(result_tree) == "table")
assert(type(repo) == "string")
assert(query:type() == "query")
-- FIXME do not add this in local repos
if (not is_local) and query.namespace then
repo = repo .. "/manifests/" .. query.namespace
end
local manifest, err, errcode = manif.load_manifest(repo, lua_version, not is_local)
if not manifest then
return nil, err, errcode
end
for name, versions in pairs(manifest.repository) do
for version, items in pairs(versions) do
local namespace = is_local and path.read_namespace(name, version, repo) or query.namespace
for _, item in ipairs(items) do
local result = results.new(name, version, repo, item.arch, namespace)
store_if_match(result_tree, result, query)
end
end
end
return true
end
local function remote_manifest_search(result_tree, repo, query, lua_version)
return manifest_search(result_tree, repo, query, lua_version, false)
end
function search.local_manifest_search(result_tree, repo, query, lua_version)
return manifest_search(result_tree, repo, query, lua_version, true)
end
--- Search on all configured rocks servers.
-- @param query table: a query object.
-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
-- @return table: A table where keys are package names
-- and values are tables matching version strings to arrays of
-- tables with fields "arch" and "repo".
function search.search_repos(query, lua_version)
assert(query:type() == "query")
local result_tree = {}
for _, repo in ipairs(cfg.rocks_servers) do
if type(repo) == "string" then
repo = { repo }
end
for _, mirror in ipairs(repo) do
if not cfg.disabled_servers[mirror] then
local protocol, pathname = dir.split_url(mirror)
if protocol == "file" then
mirror = pathname
end
local ok, err, errcode = remote_manifest_search(result_tree, mirror, query, lua_version)
if errcode == "network" then
cfg.disabled_servers[mirror] = true
end
if ok then
break
else
util.warning("Failed searching manifest: "..err)
end
end
end
end
-- search through rocks in rocks_provided
local provided_repo = "provided by VM or rocks_provided"
for name, version in pairs(util.get_rocks_provided()) do
local result = results.new(name, version, provided_repo, "installed")
store_if_match(result_tree, result, query)
end
return result_tree
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 result trees.
-- @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" and not name:match("/"))
assert(type(versions) == "table")
local vtables = {}
for v, _ in pairs(versions) do
table.insert(vtables, vers.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
-- Find out which other Lua versions provide rock versions matching a query,
-- @param query table: a query object.
-- @return table: array of Lua versions supported, in "5.x" format.
local function supported_lua_versions(query)
assert(query:type() == "query")
local result_tree = {}
for lua_version in util.lua_versions() do
if lua_version ~= cfg.lua_version then
util.printout("Checking for Lua " .. lua_version .. "...")
if search.search_repos(query, lua_version)[query.name] then
table.insert(result_tree, lua_version)
end
end
end
return result_tree
end
--- Attempt to get a single URL for a given search for a rock.
-- @param query table: a query object.
-- @return string or (nil, string, string): URL for latest matching version
-- of the rock if it was found, or nil followed by an error message
-- and an error code.
function search.find_suitable_rock(query)
assert(query:type() == "query")
local rocks_provided = util.get_rocks_provided()
if rocks_provided[query.name] ~= nil then
-- Do not install versions listed in rocks_provided.
return nil, "Rock "..query.name.." "..rocks_provided[query.name]..
" is already provided by VM or via 'rocks_provided' in the config file.", "provided"
end
local result_tree = search.search_repos(query)
local first_rock = next(result_tree)
if not first_rock then
return nil, "No results matching query were found for Lua " .. cfg.lua_version .. ".", "notfound"
elseif next(result_tree, first_rock) then
-- Shouldn't happen as query must match only one package.
return nil, "Several rocks matched query.", "manyfound"
else
return pick_latest_version(query.name, result_tree[first_rock])
end
end
function search.find_src_or_rockspec(name, namespace, version, check_lua_versions)
local query = queries.new(name, namespace, version, false, "src|rockspec")
local url, err = search.find_rock_checking_lua_versions(query, check_lua_versions)
if not url then
return nil, "Could not find a result named "..tostring(query)..": "..err
end
return url
end
function search.find_rock_checking_lua_versions(query, check_lua_versions)
local url, err, errcode = search.find_suitable_rock(query)
if url then
return url
end
if errcode == "notfound" then
local add
if check_lua_versions then
util.printout(query.name .. " not found for Lua " .. cfg.lua_version .. ".")
util.printout("Checking if available for other Lua versions...")
-- Check if constraints are satisfiable with other Lua versions.
local lua_versions = supported_lua_versions(query)
if #lua_versions ~= 0 then
-- Build a nice message in "only Lua 5.x and 5.y but not 5.z." format
for i, lua_version in ipairs(lua_versions) do
lua_versions[i] = "Lua "..lua_version
end
local versions_message = "only "..table.concat(lua_versions, " and ")..
" but not Lua "..cfg.lua_version.."."
if #query.constraints == 0 then
add = query.name.." supports "..versions_message
elseif #query.constraints == 1 and query.constraints[1].op == "==" then
add = query.name.." "..query.constraints[1].version.string.." supports "..versions_message
else
add = "Matching "..query.name.." versions support "..versions_message
end
else
add = query.name.." is not available for any Lua versions."
end
else
add = "To check if it is available for other Lua versions, use --check-lua-versions."
end
err = err .. "\n" .. add
end
return nil, err
end
--- Print a list of rocks/rockspecs on standard output.
-- @param result_tree table: A result tree.
-- @param porcelain boolean or nil: A flag to force machine-friendly output.
function search.print_result_tree(result_tree, porcelain)
assert(type(result_tree) == "table")
assert(type(porcelain) == "boolean" or not porcelain)
if porcelain then
for package, versions in util.sortedpairs(result_tree) do
for version, repos in util.sortedpairs(versions, vers.compare_versions) do
for _, repo in ipairs(repos) do
local nrepo = dir.normalize(repo.repo)
util.printout(package, version, repo.arch, nrepo, repo.namespace)
end
end
end
return
end
for package, versions in util.sortedpairs(result_tree) do
local namespaces = {}
for version, repos in util.sortedpairs(versions, vers.compare_versions) do
for _, repo in ipairs(repos) do
local key = repo.namespace or ""
local list = namespaces[key] or {}
namespaces[key] = list
repo.repo = dir.normalize(repo.repo)
table.insert(list, " "..version.." ("..repo.arch..") - "..path.root_dir(repo.repo))
end
end
for key, list in util.sortedpairs(namespaces) do
util.printout(key == "" and package or key .. "/" .. package)
for _, line in ipairs(list) do
util.printout(line)
end
util.printout()
end
end
end
function search.pick_installed_rock(query, given_tree)
assert(query:type() == "query")
local result_tree = {}
local tree_map = {}
local trees = cfg.rocks_trees
if given_tree then
trees = { given_tree }
end
for _, tree in ipairs(trees) do
local rocks_dir = path.rocks_dir(tree)
tree_map[rocks_dir] = tree
search.local_manifest_search(result_tree, rocks_dir, query)
end
if not next(result_tree) then
return nil, "cannot find package "..tostring(query).."\nUse 'list' to find installed rocks."
end
if not result_tree[query.name] and next(result_tree, next(result_tree)) then
local out = { "multiple installed packages match the name '"..tostring(query).."':\n\n" }
for name, _ in util.sortedpairs(result_tree) do
table.insert(out, " " .. name .. "\n")
end
table.insert(out, "\nPlease specify a single rock.\n")
return nil, table.concat(out)
end
local version = nil
local repo_url
local name, versions
if result_tree[query.name] then
name, versions = query.name, result_tree[query.name]
else
name, versions = util.sortedpairs(result_tree)()
end
--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, repositories in util.sortedpairs(versions, vers.compare_versions) do
if not version then version = vs end
for _, rp in ipairs(repositories) do repo_url = rp.repo end
end
local repo = tree_map[repo_url]
return name, version, repo, repo_url
end
return search

View file

@ -1,48 +0,0 @@
local signing = {}
local cfg = require("luarocks.core.cfg")
local fs = require("luarocks.fs")
local function get_gpg()
local vars = cfg.variables
local gpg = vars.GPG
local gpg_ok, err = fs.is_tool_available(gpg, "gpg")
if not gpg_ok then
return nil, err
end
return gpg
end
function signing.signature_url(url)
return url .. ".asc"
end
function signing.sign_file(file)
local gpg, err = get_gpg()
if not gpg then
return nil, err
end
local sigfile = file .. ".asc"
if fs.execute(gpg, "--armor", "--output", sigfile, "--detach-sign", file) then
return sigfile
else
return nil, "failed running " .. gpg .. " to sign " .. file
end
end
function signing.verify_signature(file, sigfile)
local gpg, err = get_gpg()
if not gpg then
return nil, err
end
if fs.execute(gpg, "--verify", sigfile, file) then
return true
else
return nil, "GPG returned a verification error"
end
end
return signing

View file

@ -1,78 +0,0 @@
local test = {}
local fetch = require("luarocks.fetch")
local deps = require("luarocks.deps")
local test_types = {
"busted",
"command",
}
local test_modules = {}
for _, test_type in ipairs(test_types) do
local mod = require("luarocks.test." .. test_type)
table.insert(test_modules, mod)
test_modules[test_type] = mod
test_modules[mod] = test_type
end
local function get_test_type(rockspec)
if rockspec.test and rockspec.test.type then
return rockspec.test.type
end
for _, test_module in ipairs(test_modules) do
if test_module.detect_type() then
return test_modules[test_module]
end
end
return nil, "could not detect test type -- no test suite for " .. rockspec.package .. "?"
end
-- Run test suite as configured in rockspec in the current directory.
function test.run_test_suite(rockspec_arg, test_type, args, prepare)
local rockspec
if type(rockspec_arg) == "string" then
local err, errcode
rockspec, err, errcode = fetch.load_rockspec(rockspec_arg)
if err then
return nil, err, errcode
end
else
assert(type(rockspec_arg) == "table")
rockspec = rockspec_arg
end
if not test_type then
local err
test_type, err = get_test_type(rockspec, test_type)
if not test_type then
return nil, err
end
end
assert(test_type)
if next(rockspec.test_dependencies) then
local ok, err, errcode = deps.fulfill_dependencies(rockspec, "test_dependencies", "all")
if err then
return nil, err, errcode
end
end
local mod_name = "luarocks.test." .. test_type
local pok, test_mod = pcall(require, mod_name)
if not pok then
return nil, "failed loading test execution module " .. mod_name
end
if prepare then
return test_mod.run_tests(rockspec_arg, {"--version"})
else
return test_mod.run_tests(rockspec.test, args)
end
end
return test

View file

@ -1,60 +0,0 @@
local busted = {}
local fs = require("luarocks.fs")
local deps = require("luarocks.deps")
local path = require("luarocks.path")
local dir = require("luarocks.dir")
local queries = require("luarocks.queries")
local unpack = table.unpack or unpack
function busted.detect_type()
if fs.exists(".busted") then
return true
end
return false
end
function busted.run_tests(test, args)
if not test then
test = {}
end
local ok, bustedver, where = deps.fulfill_dependency(queries.new("busted"), nil, nil, nil, "test_dependencies")
if not ok then
return nil, bustedver
end
local busted_exe
if test.busted_executable then
busted_exe = test.busted_executable
else
busted_exe = dir.path(path.root_dir(where), "bin", "busted")
-- Windows fallback
local busted_bat = dir.path(path.root_dir(where), "bin", "busted.bat")
if not fs.exists(busted_exe) and not fs.exists(busted_bat) then
return nil, "'busted' executable failed to be installed"
end
end
if type(test.flags) == "table" then
-- insert any flags given in test.flags at the front of args
for i = 1, #test.flags do
table.insert(args, i, test.flags[i])
end
end
local err
ok, err = fs.execute(busted_exe, unpack(args))
if ok then
return true
else
return nil, err or "test suite failed."
end
end
return busted

Some files were not shown because too many files have changed in this diff Show more