mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
This is an important refactor of the way documentation generation works
* Installs luarocks WITH it's executable (easy to install other rocks if necessary) * Use Lua supplied with luarocks * Create Utils/luadocumentor.bat, which works with RELATIVE PATH ! -> Everybody can generate the doc * Updated launch files accordingly
This commit is contained in:
parent
513a103947
commit
3b69cf992e
@ -3,7 +3,6 @@
|
|||||||
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
||||||
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
|
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
|
||||||
</listAttribute>
|
</listAttribute>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Utils/lua/5.1/bin/luadocumentor.bat}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Utils/luadocumentor.bat}"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value=""Moose\Core\*.lua" "Moose\Wrapper\*.lua" "Moose\Actions\*.lua" "Moose\Functional\*.lua" "Moose\Tasking\*.lua" "Moose\Utilities\*.lua" "Moose\AI\*.lua" --dir "${workspace_loc:/Moose_Framework/docs/Documentation} --style ${workspace_loc:/Moose_Framework/docs/Stylesheet/stylesheet.css}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Utils}"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Moose Development}"/>
|
|
||||||
</launchConfiguration>
|
</launchConfiguration>
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
||||||
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
|
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
|
||||||
</listAttribute>
|
</listAttribute>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Utils/lua/5.1/bin/lua.exe}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Utils/luarocks/lua5.1.exe}"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value=""Moose_Create.lua" "D" "${current_date}" "${workspace_loc:/Moose_Framework//Moose Development/Moose}" "${workspace_loc:/Moose_Framework/Moose Mission Setup}""/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value=""Moose_Create.lua" "D" "${current_date}" "${workspace_loc:/Moose_Framework//Moose Development/Moose}" "${workspace_loc:/Moose_Framework/Moose Mission Setup}""/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Moose Mission Setup}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Moose Mission Setup}"/>
|
||||||
</launchConfiguration>
|
</launchConfiguration>
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
||||||
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
|
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
|
||||||
</listAttribute>
|
</listAttribute>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Utils/lua/5.1/bin/lua.exe}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Utils/luarocks/lua5.1.exe}"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value=""Moose_Create.lua" "S" "${current_date}" "${workspace_loc:/Moose_Framework//Moose Development/Moose}" "${workspace_loc:/Moose_Framework/Moose Mission Setup}""/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value=""Moose_Create.lua" "S" "${current_date}" "${workspace_loc:/Moose_Framework//Moose Development/Moose}" "${workspace_loc:/Moose_Framework/Moose Mission Setup}""/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Moose Mission Setup}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Moose Mission Setup}"/>
|
||||||
</launchConfiguration>
|
</launchConfiguration>
|
||||||
|
|||||||
@ -4,6 +4,5 @@
|
|||||||
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
|
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
|
||||||
</listAttribute>
|
</listAttribute>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Moose Mission Setup/Moose Mission Update/Moose_Update_Missions.bat}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Moose Mission Setup/Moose Mission Update/Moose_Update_Missions.bat}"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value=""${folder_prompt}""/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${folder_prompt}"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Moose Mission Setup/Moose Mission Update}"/>
|
|
||||||
</launchConfiguration>
|
</launchConfiguration>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
--- **Core** - The RADIO class is responsible for **transmitting radio communications**.
|
--- **Core** - The RADIO class is responsible for **transmitting radio communications**.
|
||||||
--
|
--
|
||||||
-- --- bitmap
|
-- 
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@ -27,19 +27,20 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Authors: Hugues "Grey_Echo" Bousquet
|
-- ### Author: Hugues "Grey_Echo" Bousquet
|
||||||
--
|
--
|
||||||
-- @module Radio
|
-- @module Radio
|
||||||
|
|
||||||
|
|
||||||
--- # 1) RADIO class, extends @{Base#BASE}
|
--- # 1) RADIO class, extends @{Base#BASE}
|
||||||
--
|
--
|
||||||
-- ## 1.1) RADIO usage
|
-- ## 1.1) RADIO usage
|
||||||
--
|
--
|
||||||
-- There are 3 steps to a successful radio transmission.
|
-- There are 3 steps to a successful radio transmission.
|
||||||
--
|
--
|
||||||
-- * First, you need to **"add" a @{#RADIO} object** to your @{Positionable#POSITIONABLE}. This is done using the @{Positionable#POSITIONABLE.GetRadio}() function,
|
-- * First, you need to **"add a @{#RADIO} object** to your @{Positionable#POSITIONABLE}. This is done using the @{Positionable#POSITIONABLE.GetRadio}() function,
|
||||||
-- * Then, you will **set the relevant parameters** to the transmission (see below),
|
-- * Then, you will **set the relevant parameters** to the transmission (see below),
|
||||||
-- * When done, you can actually **broadcast the transmission** (i.e. play the sound) with the @{Positionable#POSITIONABLE.Broadcast}() function.
|
-- * When done, you can actually **broadcast the transmission** (i.e. play the sound) with the @{RADIO.Broadcast}() function.
|
||||||
--
|
--
|
||||||
-- Methods to set relevant parameters for both a @{Unit#UNIT} or a @{Group#GROUP} or any other @{Positionable#POSITIONABLE}
|
-- Methods to set relevant parameters for both a @{Unit#UNIT} or a @{Group#GROUP} or any other @{Positionable#POSITIONABLE}
|
||||||
--
|
--
|
||||||
@ -53,7 +54,7 @@
|
|||||||
-- * @{#RADIO.SetSubtitle}() : Set both the subtitle and its duration,
|
-- * @{#RADIO.SetSubtitle}() : Set both the subtitle and its duration,
|
||||||
-- * @{#RADIO.NewUnitTransmission}() : Shortcut to set all the relevant parameters in one method call
|
-- * @{#RADIO.NewUnitTransmission}() : Shortcut to set all the relevant parameters in one method call
|
||||||
--
|
--
|
||||||
-- Additional Methods to set relevant parameters if the transmiter is any other @{Wrapper.Positionable#POSITIONABLE}
|
-- Additional Methods to set relevant parameters if the transmiter is any other @{Positionable#POSITIONABLE}
|
||||||
--
|
--
|
||||||
-- * @{#RADIO.SetPower}() : Sets the power of the antenna in Watts
|
-- * @{#RADIO.SetPower}() : Sets the power of the antenna in Watts
|
||||||
-- * @{#RADIO.NewGenericTransmission}() : Shortcut to set all the relevant parameters in one method call
|
-- * @{#RADIO.NewGenericTransmission}() : Shortcut to set all the relevant parameters in one method call
|
||||||
@ -68,7 +69,7 @@
|
|||||||
-- * Note that if the transmission has a subtitle, it will be readable, regardless of the quality of the transmission.
|
-- * Note that if the transmission has a subtitle, it will be readable, regardless of the quality of the transmission.
|
||||||
--
|
--
|
||||||
-- @type RADIO
|
-- @type RADIO
|
||||||
-- @field Wrapper.Positionable#POSITIONABLE Positionable The transmiter
|
-- @field Positionable#POSITIONABLE Positionable The transmiter
|
||||||
-- @field #string FileName Name of the sound file
|
-- @field #string FileName Name of the sound file
|
||||||
-- @field #number Frequency Frequency of the transmission in Hz
|
-- @field #number Frequency Frequency of the transmission in Hz
|
||||||
-- @field #number Modulation Modulation of the transmission (either radio.modulation.AM or radio.modulation.FM)
|
-- @field #number Modulation Modulation of the transmission (either radio.modulation.AM or radio.modulation.FM)
|
||||||
|
|||||||
@ -66,13 +66,6 @@
|
|||||||
-- @module Zone
|
-- @module Zone
|
||||||
|
|
||||||
|
|
||||||
--- The ZONE_BASE class
|
|
||||||
-- @type ZONE_BASE
|
|
||||||
-- @field #string ZoneName Name of the zone.
|
|
||||||
-- @field #number ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability.
|
|
||||||
-- @extends Core.Base#BASE
|
|
||||||
|
|
||||||
|
|
||||||
--- # 1) ZONE_BASE class, extends @{Base#BASE}
|
--- # 1) ZONE_BASE class, extends @{Base#BASE}
|
||||||
--
|
--
|
||||||
-- This class is an abstract BASE class for derived classes, and is not meant to be instantiated.
|
-- This class is an abstract BASE class for derived classes, and is not meant to be instantiated.
|
||||||
@ -107,7 +100,11 @@
|
|||||||
-- * @{#ZONE_BASE.FlareZone}(): Flares the zone boundaries in a color.
|
-- * @{#ZONE_BASE.FlareZone}(): Flares the zone boundaries in a color.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
-- @field #ZONE_BASE ZONE_BASE
|
--
|
||||||
|
-- @type ZONE_BASE
|
||||||
|
-- @field #string ZoneName Name of the zone.
|
||||||
|
-- @field #number ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability.
|
||||||
|
-- @extends Core.Base#BASE
|
||||||
ZONE_BASE = {
|
ZONE_BASE = {
|
||||||
ClassName = "ZONE_BASE",
|
ClassName = "ZONE_BASE",
|
||||||
ZoneName = "",
|
ZoneName = "",
|
||||||
@ -306,12 +303,6 @@ function ZONE_BASE:GetZoneMaybe()
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- The ZONE_RADIUS class, defined by a zone name, a location and a radius.
|
|
||||||
-- @type ZONE_RADIUS
|
|
||||||
-- @field Dcs.DCSTypes#Vec2 Vec2 The current location of the zone.
|
|
||||||
-- @field Dcs.DCSTypes#Distance Radius The radius of the zone.
|
|
||||||
-- @extends Core.Zone#ZONE_BASE
|
|
||||||
|
|
||||||
--- # 2) @{Zone#ZONE_RADIUS} class, extends @{Zone#ZONE_BASE}
|
--- # 2) @{Zone#ZONE_RADIUS} class, extends @{Zone#ZONE_BASE}
|
||||||
--
|
--
|
||||||
-- The ZONE_RADIUS class defined by a zone name, a location and a radius.
|
-- The ZONE_RADIUS class defined by a zone name, a location and a radius.
|
||||||
@ -342,8 +333,11 @@ end
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @field #ZONE_RADIUS ZONE_RADIUS
|
-- The ZONE_RADIUS class, defined by a zone name, a location and a radius.
|
||||||
--
|
-- @type ZONE_RADIUS
|
||||||
|
-- @field Dcs.DCSTypes#Vec2 Vec2 The current location of the zone.
|
||||||
|
-- @field Dcs.DCSTypes#Distance Radius The radius of the zone.
|
||||||
|
-- @extends Core.Zone#ZONE_BASE
|
||||||
ZONE_RADIUS = {
|
ZONE_RADIUS = {
|
||||||
ClassName="ZONE_RADIUS",
|
ClassName="ZONE_RADIUS",
|
||||||
}
|
}
|
||||||
@ -379,7 +373,6 @@ function ZONE_RADIUS:BoundZone( Points, CountryID, UnBound )
|
|||||||
local Angle
|
local Angle
|
||||||
local RadialBase = math.pi*2
|
local RadialBase = math.pi*2
|
||||||
|
|
||||||
--
|
|
||||||
for Angle = 0, 360, (360 / Points ) do
|
for Angle = 0, 360, (360 / Points ) do
|
||||||
local Radial = Angle * RadialBase / 360
|
local Radial = Angle * RadialBase / 360
|
||||||
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
|
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,3 +0,0 @@
|
|||||||
@echo off
|
|
||||||
"C:\Program Files\lua\5.1\bin\lua.exe" -e "package.path=\"C:\\Users\\svenv\\AppData\\Roaming/luarocks/share/lua/5.1/?.lua;C:\\Users\\svenv\\AppData\\Roaming/luarocks/share/lua/5.1/?/init.lua;c:\\program files\\lua\\5.1\\/share/lua/5.1/?.lua;c:\\program files\\lua\\5.1\\/share/lua/5.1/?/init.lua;C:\\Program Files (x86)\\LuaRocks\\lua\\?.lua;\"..package.path; package.cpath=\"C:\\Users\\svenv\\AppData\\Roaming/luarocks/lib/lua/5.1/?.dll;c:\\program files\\lua\\5.1\\/lib/lua/5.1/?.dll;\"..package.cpath" -e "local k,l,_=pcall(require,\"luarocks.loader\") _=k and l.add_context(\"luadocumentor\",\"0.1.5-1\")" "c:\program files\lua\5.1\\lib\luarocks\rocks\luadocumentor\0.1.5-1\bin\luadocumentor" %*
|
|
||||||
exit /b %ERRORLEVEL%
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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
|
|
||||||
@ -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
|
|
||||||
3
Utils/luadocumentor.bat
Normal file
3
Utils/luadocumentor.bat
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
@echo off
|
||||||
|
"./luarocks/lua5.1" -e "package.path=\"./luarocks/systree/share/lua/5.1/?.lua;./luarocks/systree/share/lua/5.1/?/init.lua;./luarocks/systree/share/lua/5.1/?.lua;./luarocks/systree/share/lua/5.1/?/init.lua;./luarocks/lua/?.lua;\"..package.path; package.cpath=\"./luarocks/lib/lua/5.1/?.dll;./luarocks/systree/lib/lua/5.1/?.dll;\"..package.cpath" -e "local k,l,_=pcall(require,\"luarocks.loader\") _=k and l.add_context(\"luadocumentor\",\"0.1.5-1\")" "./luarocks/systree/lib/luarocks/rocks/luadocumentor/0.1.5-1/bin/luadocumentor" -f doc -d "../docs/Documentation" -s "../docs/Stylesheet/stylesheet.css" "../Moose Development/Moose" %*
|
||||||
|
exit /b %ERRORLEVEL%
|
||||||
8
Utils/luarocks/Microsoft.VC80.CRT.manifest
Normal file
8
Utils/luarocks/Microsoft.VC80.CRT.manifest
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||||
|
<noInheritable></noInheritable>
|
||||||
|
<assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50727.762" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
|
||||||
|
<file name="msvcr80.dll" hash="10f4cb2831f1e9288a73387a8734a8b604e5beaa" hashalg="SHA1"><asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Transforms><dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>n9On8FItNsK/DmT8UQxu6jYDtWQ=</dsig:DigestValue></asmv2:hash></file>
|
||||||
|
<file name="msvcp80.dll" hash="b2082dfd3009365c5b287448dcb3b4e2158a6d26" hashalg="SHA1"><asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Transforms><dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>0KJ/VTwP4OUHx98HlIW2AdW1kuY=</dsig:DigestValue></asmv2:hash></file>
|
||||||
|
<file name="msvcm80.dll" hash="542490d0fcf8615c46d0ca487033ccaeb3941f0b" hashalg="SHA1"><asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Transforms><dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>YJuB+9Os2oxW4mY+2oC/r8lICZE=</dsig:DigestValue></asmv2:hash></file>
|
||||||
|
</assembly>
|
||||||
BIN
Utils/luarocks/bin2c5.1.exe
Normal file
BIN
Utils/luarocks/bin2c5.1.exe
Normal file
Binary file not shown.
14
Utils/luarocks/config-5.1.lua
Normal file
14
Utils/luarocks/config-5.1.lua
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
rocks_trees = {
|
||||||
|
home..[[/luarocks]],
|
||||||
|
{ name = [[user]],
|
||||||
|
root = home..[[/luarocks]],
|
||||||
|
},
|
||||||
|
{ name = [[system]],
|
||||||
|
root = [[C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\systree]],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
variables = {
|
||||||
|
MSVCRT = 'MSVCR80',
|
||||||
|
LUALIB = 'lua5.1.lib'
|
||||||
|
}
|
||||||
|
verbose = false -- set to 'true' to enable verbose output
|
||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lua.h,v 1.218.1.7 2012/01/13 20:36:20 roberto Exp $
|
** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $
|
||||||
** Lua - An Extensible Extension Language
|
** Lua - An Extensible Extension Language
|
||||||
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
|
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
|
||||||
** See Copyright Notice at the end of this file
|
** See Copyright Notice at the end of this file
|
||||||
@ -17,9 +17,9 @@
|
|||||||
|
|
||||||
|
|
||||||
#define LUA_VERSION "Lua 5.1"
|
#define LUA_VERSION "Lua 5.1"
|
||||||
#define LUA_RELEASE "Lua 5.1.5"
|
#define LUA_RELEASE "Lua 5.1.4"
|
||||||
#define LUA_VERSION_NUM 501
|
#define LUA_VERSION_NUM 501
|
||||||
#define LUA_COPYRIGHT "Copyright (C) 1994-2012 Lua.org, PUC-Rio"
|
#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
|
||||||
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
|
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
|
||||||
|
|
||||||
|
|
||||||
@ -362,7 +362,7 @@ struct lua_Debug {
|
|||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Copyright (C) 1994-2012 Lua.org, PUC-Rio. All rights reserved.
|
* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
@ -91,7 +91,7 @@
|
|||||||
".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
|
".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
|
||||||
LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua"
|
LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua"
|
||||||
#define LUA_CPATH_DEFAULT \
|
#define LUA_CPATH_DEFAULT \
|
||||||
".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
|
".\\?.dll;" ".\\?51.dll;" LUA_CDIR"?.dll;" LUA_CDIR"?51.dll;" LUA_CDIR"clibs\\?.dll;" LUA_CDIR"clibs\\?51.dll;" LUA_CDIR"loadall.dll;" LUA_CDIR"clibs\\loadall.dll"
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define LUA_ROOT "/usr/local/"
|
#define LUA_ROOT "/usr/local/"
|
||||||
@ -101,7 +101,7 @@
|
|||||||
"./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
|
"./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
|
||||||
LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua"
|
LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua"
|
||||||
#define LUA_CPATH_DEFAULT \
|
#define LUA_CPATH_DEFAULT \
|
||||||
"./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so"
|
"./?.so;" "./lib?51.so;" LUA_CDIR"?.so;" LUA_CDIR"lib?51.so;" LUA_CDIR"loadall.so"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
BIN
Utils/luarocks/lua.ico
Normal file
BIN
Utils/luarocks/lua.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
122
Utils/luarocks/lua/luarocks/add.lua
Normal file
122
Utils/luarocks/lua/luarocks/add.lua
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
|
||||||
|
--- Module implementing the luarocks-admin "add" command.
|
||||||
|
-- Adds a rock or rockspec to a rocks server.
|
||||||
|
local add = {}
|
||||||
|
package.loaded["luarocks.add"] = add
|
||||||
|
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local manif = require("luarocks.manif")
|
||||||
|
local index = require("luarocks.index")
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local cache = require("luarocks.cache")
|
||||||
|
|
||||||
|
util.add_run_function(add)
|
||||||
|
add.help_summary = "Add a rock or rockspec to a rocks server."
|
||||||
|
add.help_arguments = "[--server=<server>] [--no-refresh] {<rockspec>|<rock>...}"
|
||||||
|
add.help = [[
|
||||||
|
Arguments are local files, which may be rockspecs or rocks.
|
||||||
|
The flag --server indicates which server to use.
|
||||||
|
If not given, the default server set in the upload_server variable
|
||||||
|
from the configuration file is used instead.
|
||||||
|
The flag --no-refresh indicates the local cache should not be refreshed
|
||||||
|
prior to generation of the updated manifest.
|
||||||
|
]]
|
||||||
|
|
||||||
|
local function add_files_to_server(refresh, rockfiles, server, upload_server)
|
||||||
|
assert(type(refresh) == "boolean" or not refresh)
|
||||||
|
assert(type(rockfiles) == "table")
|
||||||
|
assert(type(server) == "string")
|
||||||
|
assert(type(upload_server) == "table" or not upload_server)
|
||||||
|
|
||||||
|
local download_url, login_url = cache.get_server_urls(server, upload_server)
|
||||||
|
local at = fs.current_dir()
|
||||||
|
local refresh_fn = refresh and cache.refresh_local_cache or cache.split_server_url
|
||||||
|
|
||||||
|
local local_cache, protocol, server_path, user, password = refresh_fn(server, download_url, cfg.upload_user, cfg.upload_password)
|
||||||
|
if not local_cache then
|
||||||
|
return nil, protocol
|
||||||
|
end
|
||||||
|
if protocol == "file" then
|
||||||
|
return nil, "Server "..server.." is not recognized, check your configuration."
|
||||||
|
end
|
||||||
|
|
||||||
|
if not login_url then
|
||||||
|
login_url = protocol.."://"..server_path
|
||||||
|
end
|
||||||
|
|
||||||
|
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, cfg.perm_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...")
|
||||||
|
manif.make_manifest(local_cache, "one", true)
|
||||||
|
|
||||||
|
manif.zip_manifests()
|
||||||
|
|
||||||
|
util.printout("Updating index.html...")
|
||||||
|
index.make_index(local_cache)
|
||||||
|
|
||||||
|
local login_info = ""
|
||||||
|
if user then login_info = " -u "..user end
|
||||||
|
if password then login_info = login_info..":"..password end
|
||||||
|
if not login_url:match("/$") then
|
||||||
|
login_url = login_url .. "/"
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(files, "index.html")
|
||||||
|
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 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)
|
||||||
|
fs.execute(cmd)
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function add.command(flags, ...)
|
||||||
|
local files = {...}
|
||||||
|
if #files < 1 then
|
||||||
|
return nil, "Argument missing. "..util.see_help("add", "luarocks-admin")
|
||||||
|
end
|
||||||
|
local server, server_table = cache.get_upload_server(flags["server"])
|
||||||
|
if not server then return nil, server_table end
|
||||||
|
return add_files_to_server(not flags["no-refresh"], files, server, server_table)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return add
|
||||||
92
Utils/luarocks/lua/luarocks/admin_remove.lua
Normal file
92
Utils/luarocks/lua/luarocks/admin_remove.lua
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
|
||||||
|
--- Module implementing the luarocks-admin "remove" command.
|
||||||
|
-- Removes a rock or rockspec from a rocks server.
|
||||||
|
local admin_remove = {}
|
||||||
|
package.loaded["luarocks.admin_remove"] = admin_remove
|
||||||
|
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local manif = require("luarocks.manif")
|
||||||
|
local index = require("luarocks.index")
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local cache = require("luarocks.cache")
|
||||||
|
|
||||||
|
util.add_run_function(admin_remove)
|
||||||
|
admin_remove.help_summary = "Remove a rock or rockspec from a rocks server."
|
||||||
|
admin_remove.help_arguments = "[--server=<server>] [--no-refresh] {<rockspec>|<rock>...}"
|
||||||
|
admin_remove.help = [[
|
||||||
|
Arguments are local files, which may be rockspecs or rocks.
|
||||||
|
The flag --server indicates which server to use.
|
||||||
|
If not given, the default server set in the upload_server variable
|
||||||
|
from the configuration file is used instead.
|
||||||
|
The flag --no-refresh indicates the local cache should not be refreshed
|
||||||
|
prior to generation of the updated manifest.
|
||||||
|
]]
|
||||||
|
|
||||||
|
local function remove_files_from_server(refresh, rockfiles, server, upload_server)
|
||||||
|
assert(type(refresh) == "boolean" or not refresh)
|
||||||
|
assert(type(rockfiles) == "table")
|
||||||
|
assert(type(server) == "string")
|
||||||
|
assert(type(upload_server) == "table" or not upload_server)
|
||||||
|
|
||||||
|
local download_url, login_url = cache.get_server_urls(server, upload_server)
|
||||||
|
local at = fs.current_dir()
|
||||||
|
local refresh_fn = refresh and cache.refresh_local_cache or cache.split_server_url
|
||||||
|
|
||||||
|
local local_cache, protocol, server_path, user, password = refresh_fn(server, download_url, cfg.upload_user, cfg.upload_password)
|
||||||
|
if not local_cache then
|
||||||
|
return nil, protocol
|
||||||
|
end
|
||||||
|
if protocol ~= "rsync" then
|
||||||
|
return nil, "This command requires 'rsync', check your configuration."
|
||||||
|
end
|
||||||
|
|
||||||
|
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...")
|
||||||
|
manif.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(flags, ...)
|
||||||
|
local files = {...}
|
||||||
|
if #files < 1 then
|
||||||
|
return nil, "Argument missing. "..util.see_help("remove", "luarocks-admin")
|
||||||
|
end
|
||||||
|
local server, server_table = cache.get_upload_server(flags["server"])
|
||||||
|
if not server then return nil, server_table end
|
||||||
|
return remove_files_from_server(not flags["no-refresh"], files, server, server_table)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return admin_remove
|
||||||
415
Utils/luarocks/lua/luarocks/build.lua
Normal file
415
Utils/luarocks/lua/luarocks/build.lua
Normal file
@ -0,0 +1,415 @@
|
|||||||
|
|
||||||
|
--- Module implementing the LuaRocks "build" command.
|
||||||
|
-- Builds a rock, compiling its C parts if any.
|
||||||
|
local build = {}
|
||||||
|
package.loaded["luarocks.build"] = build
|
||||||
|
|
||||||
|
local pack = require("luarocks.pack")
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local repos = require("luarocks.repos")
|
||||||
|
local fetch = require("luarocks.fetch")
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local deps = require("luarocks.deps")
|
||||||
|
local manif = require("luarocks.manif")
|
||||||
|
local remove = require("luarocks.remove")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
|
||||||
|
util.add_run_function(build)
|
||||||
|
build.help_summary = "Build/compile a rock."
|
||||||
|
build.help_arguments = "[--pack-binary-rock] [--keep] {<rockspec>|<rock>|<name> [<version>]}"
|
||||||
|
build.help = [[
|
||||||
|
Build and install a rock, compiling its C parts if any.
|
||||||
|
Argument may be a rockspec file, a source rock file
|
||||||
|
or the name of a rock to be fetched from a repository.
|
||||||
|
|
||||||
|
--pack-binary-rock Do not install rock. Instead, produce a .rock file
|
||||||
|
with the contents of compilation in the current
|
||||||
|
directory.
|
||||||
|
|
||||||
|
--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.
|
||||||
|
|
||||||
|
--branch=<name> Override the `source.branch` field in the loaded
|
||||||
|
rockspec. Allows to specify a different branch to
|
||||||
|
fetch. Particularly for SCM rocks.
|
||||||
|
|
||||||
|
--only-deps Installs only the dependencies of the rock.
|
||||||
|
|
||||||
|
]]..util.deps_mode_help()
|
||||||
|
|
||||||
|
--- Install files to a given location.
|
||||||
|
-- Takes a table where the array part is a list of filenames to be copied.
|
||||||
|
-- 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: 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_files(files, location, is_module_path, perms)
|
||||||
|
assert(type(files) == "table" or not files)
|
||||||
|
assert(type(location) == "string")
|
||||||
|
if files then
|
||||||
|
for k, file in pairs(files) do
|
||||||
|
local dest = location
|
||||||
|
local filename = dir.base_name(file)
|
||||||
|
if type(k) == "string" then
|
||||||
|
local modname = k
|
||||||
|
if is_module_path then
|
||||||
|
dest = dir.path(location, path.module_to_path(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
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Write to the current directory the contents of a table,
|
||||||
|
-- where each key is a file name and its value is the file content.
|
||||||
|
-- @param files table: The table of files to be written.
|
||||||
|
local function extract_from_rockspec(files)
|
||||||
|
for name, content in pairs(files) do
|
||||||
|
local fd = io.open(dir.path(fs.current_dir(), name), "w+")
|
||||||
|
fd:write(content)
|
||||||
|
fd:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Applies patches inlined in the build.patches section
|
||||||
|
-- and extracts files inlined in the build.extra_files section
|
||||||
|
-- of a rockspec.
|
||||||
|
-- @param rockspec table: A rockspec table.
|
||||||
|
-- @return boolean or (nil, string): True if succeeded or
|
||||||
|
-- nil and an error message.
|
||||||
|
function build.apply_patches(rockspec)
|
||||||
|
assert(type(rockspec) == "table")
|
||||||
|
|
||||||
|
local build_spec = rockspec.build
|
||||||
|
if build_spec.extra_files then
|
||||||
|
extract_from_rockspec(build_spec.extra_files)
|
||||||
|
end
|
||||||
|
if build_spec.patches then
|
||||||
|
extract_from_rockspec(build_spec.patches)
|
||||||
|
for patch, patchdata in util.sortedpairs(build_spec.patches) do
|
||||||
|
util.printout("Applying patch "..patch.."...")
|
||||||
|
local ok, err = fs.apply_patch(tostring(patch), patchdata)
|
||||||
|
if not ok then
|
||||||
|
return nil, "Failed applying patch "..patch
|
||||||
|
end
|
||||||
|
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, cfg.perm_read)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Build and install a rock given a rockspec.
|
||||||
|
-- @param rockspec_file string: local or remote filename of a rockspec.
|
||||||
|
-- @param need_to_fetch boolean: true if sources need to be fetched,
|
||||||
|
-- false if the rockspec was obtained from inside a source rock.
|
||||||
|
-- @param minimal_mode boolean: true if there's no need to fetch,
|
||||||
|
-- unpack or change dir (this is used by "luarocks make"). Implies
|
||||||
|
-- need_to_fetch = false.
|
||||||
|
-- @param deps_mode string: Dependency mode: "one" for the current default tree,
|
||||||
|
-- "all" for all trees, "order" for all trees with priority >= the current default,
|
||||||
|
-- "none" for no trees.
|
||||||
|
-- @param build_only_deps boolean: true to build the listed dependencies only.
|
||||||
|
-- @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_file, need_to_fetch, minimal_mode, deps_mode, build_only_deps)
|
||||||
|
assert(type(rockspec_file) == "string")
|
||||||
|
assert(type(need_to_fetch) == "boolean")
|
||||||
|
|
||||||
|
local rockspec, err, errcode = fetch.load_rockspec(rockspec_file)
|
||||||
|
if err then
|
||||||
|
return nil, err, errcode
|
||||||
|
elseif not rockspec.build then
|
||||||
|
return nil, "Rockspec error: build table not specified"
|
||||||
|
elseif not rockspec.build.type then
|
||||||
|
return nil, "Rockspec error: build type not specified"
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok
|
||||||
|
if not build_only_deps then
|
||||||
|
ok, err, errcode = deps.check_external_deps(rockspec, "build")
|
||||||
|
if err then
|
||||||
|
return nil, err, errcode
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if deps_mode == "none" then
|
||||||
|
util.printerr("Warning: skipping dependency checks.")
|
||||||
|
else
|
||||||
|
local ok, err, errcode = deps.fulfill_dependencies(rockspec, deps_mode)
|
||||||
|
if err then
|
||||||
|
return nil, err, errcode
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local name, version = rockspec.name, rockspec.version
|
||||||
|
if build_only_deps then
|
||||||
|
util.printout("Stopping after installing dependencies for " ..name.." "..version)
|
||||||
|
util.printout()
|
||||||
|
return name, version
|
||||||
|
end
|
||||||
|
|
||||||
|
if repos.is_installed(name, version) then
|
||||||
|
repos.delete_version(name, version, deps_mode)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not minimal_mode then
|
||||||
|
local source_dir
|
||||||
|
if need_to_fetch then
|
||||||
|
ok, source_dir, errcode = fetch.fetch_sources(rockspec, true)
|
||||||
|
if not ok then
|
||||||
|
return nil, source_dir, errcode
|
||||||
|
end
|
||||||
|
local ok, err = fs.change_dir(source_dir)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
elseif rockspec.source.file then
|
||||||
|
local ok, err = fs.unpack_archive(rockspec.source.file)
|
||||||
|
if not ok then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
fs.change_dir(rockspec.source.dir)
|
||||||
|
end
|
||||||
|
|
||||||
|
local dirs = {
|
||||||
|
lua = { name = path.lua_dir(name, version), is_module_path = true, perms = cfg.perm_read },
|
||||||
|
lib = { name = path.lib_dir(name, version), is_module_path = true, perms = cfg.perm_exec },
|
||||||
|
conf = { name = path.conf_dir(name, version), is_module_path = false, perms = cfg.perm_read },
|
||||||
|
bin = { name = path.bin_dir(name, version), is_module_path = false, perms = cfg.perm_exec },
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, d in pairs(dirs) do
|
||||||
|
local ok, err = fs.make_dir(d.name)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
end
|
||||||
|
local rollback = util.schedule_function(function()
|
||||||
|
fs.delete(path.install_dir(name, version))
|
||||||
|
fs.remove_dir_if_empty(path.versions_dir(name))
|
||||||
|
end)
|
||||||
|
|
||||||
|
local build_spec = rockspec.build
|
||||||
|
|
||||||
|
if not minimal_mode then
|
||||||
|
ok, err = build.apply_patches(rockspec)
|
||||||
|
if err then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if build_spec.type ~= "none" then
|
||||||
|
|
||||||
|
-- Temporary compatibility
|
||||||
|
if build_spec.type == "module" then
|
||||||
|
util.printout("Do not use 'module' as a build type. Use 'builtin' instead.")
|
||||||
|
build_spec.type = "builtin"
|
||||||
|
end
|
||||||
|
|
||||||
|
if cfg.accepted_build_types and util.array_contains(cfg.accepted_build_types, build_spec.type) then
|
||||||
|
return nil, "This rockspec uses the '"..build_spec.type.."' build type, which is blocked by the 'accepted_build_types' setting in your LuaRocks configuration."
|
||||||
|
end
|
||||||
|
|
||||||
|
local build_type
|
||||||
|
ok, build_type = pcall(require, "luarocks.build." .. build_spec.type)
|
||||||
|
if not ok or not type(build_type) == "table" then
|
||||||
|
return nil, "Failed initializing build back-end for build type '"..build_spec.type.."': "..build_type
|
||||||
|
end
|
||||||
|
|
||||||
|
ok, err = build_type.run(rockspec)
|
||||||
|
if not ok then
|
||||||
|
return nil, "Build error: " .. err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if build_spec.install then
|
||||||
|
for id, install_dir in pairs(dirs) do
|
||||||
|
ok, err = install_files(build_spec.install[id], install_dir.name, install_dir.is_module_path, install_dir.perms)
|
||||||
|
if not ok then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local copy_directories = build_spec.copy_directories
|
||||||
|
local copying_default = false
|
||||||
|
if not copy_directories then
|
||||||
|
copy_directories = {"doc"}
|
||||||
|
copying_default = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local any_docs = false
|
||||||
|
for _, copy_dir in pairs(copy_directories) do
|
||||||
|
if fs.is_dir(copy_dir) then
|
||||||
|
local dest = dir.path(path.install_dir(name, version), copy_dir)
|
||||||
|
fs.make_dir(dest)
|
||||||
|
fs.copy_contents(copy_dir, dest)
|
||||||
|
any_docs = true
|
||||||
|
else
|
||||||
|
if not copying_default then
|
||||||
|
return nil, "Directory '"..copy_dir.."' not found"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not any_docs then
|
||||||
|
install_default_docs(name, version)
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, d in pairs(dirs) do
|
||||||
|
fs.remove_dir_if_empty(d.name)
|
||||||
|
end
|
||||||
|
|
||||||
|
fs.pop_dir()
|
||||||
|
|
||||||
|
fs.copy(rockspec.local_filename, path.rockspec_file(name, version), cfg.perm_read)
|
||||||
|
if need_to_fetch then
|
||||||
|
fs.pop_dir()
|
||||||
|
end
|
||||||
|
|
||||||
|
ok, err = manif.make_rock_manifest(name, version)
|
||||||
|
if err then return nil, err end
|
||||||
|
|
||||||
|
ok, err = 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
|
||||||
|
|
||||||
|
--- Build and install a rock.
|
||||||
|
-- @param rock_file string: local or remote filename of a rock.
|
||||||
|
-- @param need_to_fetch boolean: true if sources need to be fetched,
|
||||||
|
-- false if the rockspec was obtained from inside a source rock.
|
||||||
|
-- @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 build_only_deps boolean: true to build the listed dependencies only.
|
||||||
|
-- @return boolean or (nil, string, [string]): True if build was successful,
|
||||||
|
-- or false and an error message and an optional error code.
|
||||||
|
function build.build_rock(rock_file, need_to_fetch, deps_mode, build_only_deps)
|
||||||
|
assert(type(rock_file) == "string")
|
||||||
|
assert(type(need_to_fetch) == "boolean")
|
||||||
|
|
||||||
|
local ok, err, errcode
|
||||||
|
local unpack_dir
|
||||||
|
unpack_dir, err, errcode = fetch.fetch_and_unpack_rock(rock_file)
|
||||||
|
if not unpack_dir then
|
||||||
|
return nil, err, errcode
|
||||||
|
end
|
||||||
|
local rockspec_file = path.rockspec_name_from_rock(rock_file)
|
||||||
|
ok, err = fs.change_dir(unpack_dir)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
ok, err, errcode = build.build_rockspec(rockspec_file, need_to_fetch, false, deps_mode, build_only_deps)
|
||||||
|
fs.pop_dir()
|
||||||
|
return ok, err, errcode
|
||||||
|
end
|
||||||
|
|
||||||
|
local function do_build(name, version, deps_mode, build_only_deps)
|
||||||
|
if name:match("%.rockspec$") then
|
||||||
|
return build.build_rockspec(name, true, false, deps_mode, build_only_deps)
|
||||||
|
elseif name:match("%.src%.rock$") then
|
||||||
|
return build.build_rock(name, false, deps_mode, build_only_deps)
|
||||||
|
elseif name:match("%.all%.rock$") then
|
||||||
|
local install = require("luarocks.install")
|
||||||
|
local install_fun = build_only_deps and install.install_binary_rock_deps or install.install_binary_rock
|
||||||
|
return install_fun(name, deps_mode)
|
||||||
|
elseif name:match("%.rock$") then
|
||||||
|
return build.build_rock(name, true, deps_mode, build_only_deps)
|
||||||
|
elseif not name:match(dir.separator) then
|
||||||
|
local search = require("luarocks.search")
|
||||||
|
return search.act_on_src_or_rockspec(do_build, name:lower(), version, nil, deps_mode, build_only_deps)
|
||||||
|
end
|
||||||
|
return nil, "Don't know what to do with "..name
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Driver function for "build" command.
|
||||||
|
-- @param name string: A local or remote rockspec or rock file.
|
||||||
|
-- If a package name is given, forwards the request to "search" and,
|
||||||
|
-- if returned a result, installs the matching rock.
|
||||||
|
-- @param version string: When passing a package name, a version number may
|
||||||
|
-- also be given.
|
||||||
|
-- @return boolean or (nil, string, exitcode): True if build was successful; nil and an
|
||||||
|
-- error message otherwise. exitcode is optionally returned.
|
||||||
|
function build.command(flags, name, version)
|
||||||
|
if type(name) ~= "string" then
|
||||||
|
return nil, "Argument missing. "..util.see_help("build")
|
||||||
|
end
|
||||||
|
assert(type(version) == "string" or not version)
|
||||||
|
|
||||||
|
if flags["pack-binary-rock"] then
|
||||||
|
return pack.pack_binary_rock(name, version, do_build, name, version, deps.get_deps_mode(flags))
|
||||||
|
else
|
||||||
|
local ok, err = fs.check_command_permissions(flags)
|
||||||
|
if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end
|
||||||
|
ok, err = do_build(name, version, deps.get_deps_mode(flags), flags["only-deps"])
|
||||||
|
if not ok then return nil, err end
|
||||||
|
name, version = ok, err
|
||||||
|
|
||||||
|
if (not flags["only-deps"]) and (not flags["keep"]) and not cfg.keep_other_versions then
|
||||||
|
local ok, err = remove.remove_other_versions(name, version, flags["force"], flags["force-fast"])
|
||||||
|
if not ok then util.printerr(err) end
|
||||||
|
end
|
||||||
|
|
||||||
|
manif.check_dependencies(nil, deps.get_deps_mode(flags))
|
||||||
|
return name, version
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return build
|
||||||
78
Utils/luarocks/lua/luarocks/cache.lua
Normal file
78
Utils/luarocks/lua/luarocks/cache.lua
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
|
||||||
|
--- Module handling the LuaRocks local cache.
|
||||||
|
-- Adds a rock or rockspec to a rocks server.
|
||||||
|
local cache = {}
|
||||||
|
package.loaded["luarocks.cache"] = cache
|
||||||
|
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
|
||||||
|
function 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(server, url, user, password)
|
||||||
|
local protocol, server_path = dir.split_url(url)
|
||||||
|
if server_path:match("@") then
|
||||||
|
local credentials
|
||||||
|
credentials, server_path = server_path:match("([^@]*)@(.*)")
|
||||||
|
if credentials:match(":") then
|
||||||
|
user, password = credentials:match("([^:]*):(.*)")
|
||||||
|
else
|
||||||
|
user = credentials
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local local_cache = cfg.local_cache .. "/" .. server
|
||||||
|
return local_cache, protocol, server_path, user, password
|
||||||
|
end
|
||||||
|
|
||||||
|
function cache.refresh_local_cache(server, url, user, password)
|
||||||
|
local local_cache, protocol, server_path, user, password = cache.split_server_url(server, url, user, password)
|
||||||
|
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)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
util.printout("Refreshing cache "..local_cache.."...")
|
||||||
|
|
||||||
|
-- TODO abstract away explicit 'wget' call
|
||||||
|
local ok = false
|
||||||
|
if protocol == "rsync" then
|
||||||
|
local srv, path = server_path:match("([^/]+)(/.+)")
|
||||||
|
ok = fs.execute(cfg.variables.RSYNC.." "..cfg.variables.RSYNCFLAGS.." -e ssh "..user.."@"..srv..":"..path.."/ "..local_cache.."/")
|
||||||
|
else
|
||||||
|
local login_info = ""
|
||||||
|
if user then login_info = " --user="..user end
|
||||||
|
if password then login_info = login_info .. " --password="..password end
|
||||||
|
ok = fs.execute(cfg.variables.WGET.." --no-cache -q -m -np -nd "..protocol.."://"..server_path..login_info)
|
||||||
|
end
|
||||||
|
if not ok then
|
||||||
|
return nil, "Failed downloading cache."
|
||||||
|
end
|
||||||
|
return local_cache, protocol, server_path, user, password
|
||||||
|
end
|
||||||
|
|
||||||
|
return cache
|
||||||
760
Utils/luarocks/lua/luarocks/cfg.lua
Normal file
760
Utils/luarocks/lua/luarocks/cfg.lua
Normal file
@ -0,0 +1,760 @@
|
|||||||
|
--- 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 rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs, package, tonumber, type, assert, _VERSION =
|
||||||
|
rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs, package, tonumber, type, assert, _VERSION
|
||||||
|
|
||||||
|
--module("luarocks.cfg")
|
||||||
|
local cfg = {}
|
||||||
|
package.loaded["luarocks.cfg"] = cfg
|
||||||
|
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
|
||||||
|
cfg.lua_version = _VERSION:match(" (5%.[123])$") or "5.1"
|
||||||
|
local version_suffix = cfg.lua_version:gsub("%.", "_")
|
||||||
|
|
||||||
|
-- Load site-local global configurations
|
||||||
|
local ok, site_config = pcall(require, "luarocks.site_config_"..version_suffix)
|
||||||
|
if not ok then
|
||||||
|
ok, site_config = pcall(require, "luarocks.site_config")
|
||||||
|
end
|
||||||
|
if not ok then
|
||||||
|
io.stderr:write("Site-local luarocks/site_config.lua file not found. Incomplete installation?\n")
|
||||||
|
site_config = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
cfg.program_version = "2.4.2"
|
||||||
|
cfg.program_series = "2.4"
|
||||||
|
cfg.major_version = (cfg.program_version:match("([^.]%.[^.])")) or cfg.program_series
|
||||||
|
cfg.variables = {}
|
||||||
|
cfg.rocks_trees = {}
|
||||||
|
cfg.platforms = {}
|
||||||
|
|
||||||
|
local persist = require("luarocks.persist")
|
||||||
|
|
||||||
|
cfg.errorcodes = setmetatable({
|
||||||
|
OK = 0,
|
||||||
|
UNSPECIFIED = 1,
|
||||||
|
PERMISSIONDENIED = 2,
|
||||||
|
CONFIGFILE = 3,
|
||||||
|
CRASH = 99
|
||||||
|
},{
|
||||||
|
__index = function(t, key)
|
||||||
|
local val = rawget(t, key)
|
||||||
|
if not val then
|
||||||
|
error("'"..tostring(key).."' is not a valid errorcode", 2)
|
||||||
|
end
|
||||||
|
return val
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
local popen_ok, popen_result = pcall(io.popen, "")
|
||||||
|
if popen_ok then
|
||||||
|
if popen_result then
|
||||||
|
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(cfg.errorcodes.UNSPECIFIED)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- System detection:
|
||||||
|
|
||||||
|
-- A proper installation of LuaRocks will hardcode the system
|
||||||
|
-- and proc values with site_config.LUAROCKS_UNAME_S and site_config.LUAROCKS_UNAME_M,
|
||||||
|
-- so that this detection does not run every time. When it is
|
||||||
|
-- performed, we use the Unix way to identify the system,
|
||||||
|
-- even on Windows (assuming UnxUtils or Cygwin).
|
||||||
|
local system = site_config.LUAROCKS_UNAME_S or io.popen("uname -s"):read("*l")
|
||||||
|
local proc = site_config.LUAROCKS_UNAME_M or io.popen("uname -m"):read("*l")
|
||||||
|
if proc:match("i[%d]86") then
|
||||||
|
cfg.target_cpu = "x86"
|
||||||
|
elseif proc:match("amd64") or proc:match("x86_64") then
|
||||||
|
cfg.target_cpu = "x86_64"
|
||||||
|
elseif proc:match("Power Macintosh") then
|
||||||
|
cfg.target_cpu = "powerpc"
|
||||||
|
else
|
||||||
|
cfg.target_cpu = proc
|
||||||
|
end
|
||||||
|
|
||||||
|
if system == "FreeBSD" then
|
||||||
|
cfg.platforms.unix = true
|
||||||
|
cfg.platforms.freebsd = true
|
||||||
|
cfg.platforms.bsd = true
|
||||||
|
elseif system == "OpenBSD" then
|
||||||
|
cfg.platforms.unix = true
|
||||||
|
cfg.platforms.openbsd = true
|
||||||
|
cfg.platforms.bsd = true
|
||||||
|
elseif system == "NetBSD" then
|
||||||
|
cfg.platforms.unix = true
|
||||||
|
cfg.platforms.netbsd = true
|
||||||
|
cfg.platforms.bsd = true
|
||||||
|
elseif system == "Darwin" then
|
||||||
|
cfg.platforms.unix = true
|
||||||
|
cfg.platforms.macosx = true
|
||||||
|
cfg.platforms.bsd = true
|
||||||
|
elseif system == "Linux" then
|
||||||
|
cfg.platforms.unix = true
|
||||||
|
cfg.platforms.linux = true
|
||||||
|
elseif system == "SunOS" then
|
||||||
|
cfg.platforms.unix = true
|
||||||
|
cfg.platforms.solaris = true
|
||||||
|
elseif system and system:match("^CYGWIN") then
|
||||||
|
cfg.platforms.unix = true
|
||||||
|
cfg.platforms.cygwin = true
|
||||||
|
elseif system and system:match("^MSYS") then
|
||||||
|
cfg.platforms.unix = true
|
||||||
|
cfg.platforms.msys = true
|
||||||
|
cfg.platforms.cygwin = true
|
||||||
|
elseif system and system:match("^Windows") then
|
||||||
|
cfg.platforms.windows = true
|
||||||
|
cfg.platforms.win32 = true
|
||||||
|
elseif system and system:match("^MINGW") then
|
||||||
|
cfg.platforms.windows = true
|
||||||
|
cfg.platforms.mingw32 = true
|
||||||
|
cfg.platforms.win32 = true
|
||||||
|
elseif system == "Haiku" then
|
||||||
|
cfg.platforms.unix = true
|
||||||
|
cfg.platforms.haiku = true
|
||||||
|
else
|
||||||
|
cfg.platforms.unix = true
|
||||||
|
-- Fall back to Unix in unknown systems.
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 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
|
||||||
|
"win32",
|
||||||
|
"mingw32",
|
||||||
|
"windows",
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Path configuration:
|
||||||
|
local sys_config_file, home_config_file
|
||||||
|
local sys_config_file_default, home_config_file_default
|
||||||
|
local sys_config_dir, home_config_dir
|
||||||
|
local sys_config_ok, home_config_ok = false, false
|
||||||
|
local extra_luarocks_module_dir
|
||||||
|
sys_config_dir = site_config.LUAROCKS_SYSCONFDIR or site_config.LUAROCKS_PREFIX
|
||||||
|
if cfg.platforms.windows then
|
||||||
|
cfg.home = os.getenv("APPDATA") or "c:"
|
||||||
|
sys_config_dir = sys_config_dir or "c:/luarocks"
|
||||||
|
home_config_dir = cfg.home.."/luarocks"
|
||||||
|
cfg.home_tree = cfg.home.."/luarocks/"
|
||||||
|
else
|
||||||
|
cfg.home = os.getenv("HOME") or ""
|
||||||
|
sys_config_dir = sys_config_dir or "/etc/luarocks"
|
||||||
|
home_config_dir = cfg.home.."/.luarocks"
|
||||||
|
cfg.home_tree = (os.getenv("USER") ~= "root") and cfg.home.."/.luarocks/"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create global environment for the config files;
|
||||||
|
local env_for_config_file = function()
|
||||||
|
local e
|
||||||
|
e = {
|
||||||
|
home = cfg.home,
|
||||||
|
lua_version = cfg.lua_version,
|
||||||
|
platforms = util.make_shallow_copy(cfg.platforms),
|
||||||
|
processor = cfg.target_cpu, -- remains for compat reasons
|
||||||
|
target_cpu = cfg.target_cpu, -- replaces `processor`
|
||||||
|
os_getenv = os.getenv,
|
||||||
|
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 merge_overrides = function(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
|
||||||
|
|
||||||
|
-- load config file from a list until first succesful one. Info is
|
||||||
|
-- added to `cfg` module table, returns filepath of succesfully loaded
|
||||||
|
-- file or nil if it failed
|
||||||
|
local load_config_file = function(list)
|
||||||
|
for _, filepath in ipairs(list) do
|
||||||
|
local result, err, errcode = persist.load_into_table(filepath, env_for_config_file())
|
||||||
|
if (not result) and errcode ~= "open" then
|
||||||
|
-- errcode is either "load" or "run"; bad config file, so error out
|
||||||
|
io.stderr:write(err.."\n")
|
||||||
|
os.exit(cfg.errorcodes.CONFIGFILE)
|
||||||
|
end
|
||||||
|
if result then
|
||||||
|
-- succes in loading and running, merge contents and exit
|
||||||
|
merge_overrides(result)
|
||||||
|
return filepath
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil -- nothing was loaded
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Load system configuration file
|
||||||
|
do
|
||||||
|
sys_config_file_default = sys_config_dir.."/config-"..cfg.lua_version..".lua"
|
||||||
|
sys_config_file = load_config_file({
|
||||||
|
site_config.LUAROCKS_SYSCONFIG or sys_config_file_default,
|
||||||
|
sys_config_dir.."/config.lua",
|
||||||
|
})
|
||||||
|
sys_config_ok = (sys_config_file ~= nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Load user configuration file (if allowed)
|
||||||
|
if not site_config.LUAROCKS_FORCE_CONFIG then
|
||||||
|
|
||||||
|
home_config_file_default = home_config_dir.."/config-"..cfg.lua_version..".lua"
|
||||||
|
|
||||||
|
local config_env_var = "LUAROCKS_CONFIG_" .. version_suffix
|
||||||
|
local config_env_value = os.getenv(config_env_var)
|
||||||
|
if not config_env_value then
|
||||||
|
config_env_var = "LUAROCKS_CONFIG"
|
||||||
|
config_env_value = os.getenv(config_env_var)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- first try environment provided file, so we can explicitly warn when it is missing
|
||||||
|
if config_env_value then
|
||||||
|
local list = { config_env_value }
|
||||||
|
home_config_file = load_config_file(list)
|
||||||
|
home_config_ok = (home_config_file ~= nil)
|
||||||
|
if not home_config_ok then
|
||||||
|
io.stderr:write("Warning: could not load configuration file `"..config_env_value.."` given in environment variable "..config_env_var.."\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- try the alternative defaults if there was no environment specified file or it didn't work
|
||||||
|
if not home_config_ok then
|
||||||
|
local list = {
|
||||||
|
home_config_file_default,
|
||||||
|
home_config_dir.."/config.lua",
|
||||||
|
}
|
||||||
|
home_config_file = load_config_file(list)
|
||||||
|
home_config_ok = (home_config_file ~= nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if not next(cfg.rocks_trees) then
|
||||||
|
if cfg.home_tree then
|
||||||
|
table.insert(cfg.rocks_trees, { name = "user", root = cfg.home_tree } )
|
||||||
|
end
|
||||||
|
if site_config.LUAROCKS_ROCKS_TREE then
|
||||||
|
table.insert(cfg.rocks_trees, { name = "system", root = site_config.LUAROCKS_ROCKS_TREE } )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- update platforms list; keyed -> array
|
||||||
|
do
|
||||||
|
-- if explicitly given by user,
|
||||||
|
if cfg.platforms[1] then
|
||||||
|
local is_windows = cfg.platforms.windows
|
||||||
|
-- Clear auto-detected values
|
||||||
|
for k, _ in pairs(cfg.platforms) do
|
||||||
|
if type(k) == "string" then
|
||||||
|
cfg.platforms[k] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- and set the ones given by the user.
|
||||||
|
for _, plat in ipairs(cfg.platforms) do
|
||||||
|
cfg.platforms[plat] = true
|
||||||
|
end
|
||||||
|
-- If no major platform family was set by the user,
|
||||||
|
if not (cfg.platforms.unix or cfg.platforms.windows) then
|
||||||
|
-- set some fallback defaults in case the user provides an incomplete configuration.
|
||||||
|
-- LuaRocks expects a set of defaults to be available.
|
||||||
|
-- This is used for setting defaults here only; the platform overrides
|
||||||
|
-- will use only the user's list.
|
||||||
|
if is_windows then
|
||||||
|
cfg.platforms.windows = true
|
||||||
|
table.insert(cfg.platforms, "windows")
|
||||||
|
else
|
||||||
|
cfg.platforms.unix = true
|
||||||
|
table.insert(cfg.platforms, "unix")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Sort detected platform defaults
|
||||||
|
local order = {}
|
||||||
|
for i, v in ipairs(platform_order) do
|
||||||
|
order[v] = i
|
||||||
|
end
|
||||||
|
local entries = {}
|
||||||
|
for k, v in pairs(cfg.platforms) do
|
||||||
|
if type(k) == "string" and v == true then
|
||||||
|
table.insert(entries, k)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(entries, function(a, b) return order[a] < order[b] end)
|
||||||
|
util.deep_merge(cfg.platforms, entries)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Configure defaults:
|
||||||
|
local defaults = {
|
||||||
|
|
||||||
|
local_by_default = false,
|
||||||
|
accept_unknown_fields = false,
|
||||||
|
fs_use_modules = true,
|
||||||
|
hooks_enabled = true,
|
||||||
|
deps_mode = "one",
|
||||||
|
check_certificates = false,
|
||||||
|
perm_read = "0644",
|
||||||
|
perm_exec = "0755",
|
||||||
|
|
||||||
|
lua_modules_path = "/share/lua/"..cfg.lua_version,
|
||||||
|
lib_modules_path = "/lib/lua/"..cfg.lua_version,
|
||||||
|
rocks_subdir = site_config.LUAROCKS_ROCKS_SUBDIR or "/lib/luarocks/rocks",
|
||||||
|
|
||||||
|
arch = "unknown",
|
||||||
|
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/",
|
||||||
|
"http://luafr.org/moonrocks/",
|
||||||
|
"http://luarocks.logiceditor.com/rocks",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
disabled_servers = {},
|
||||||
|
|
||||||
|
upload = {
|
||||||
|
server = "https://luarocks.org",
|
||||||
|
tool_version = "1.0.0",
|
||||||
|
api_version = "1",
|
||||||
|
},
|
||||||
|
|
||||||
|
lua_extension = "lua",
|
||||||
|
lua_interpreter = site_config.LUA_INTERPRETER or "lua",
|
||||||
|
downloader = site_config.LUAROCKS_DOWNLOADER or "wget",
|
||||||
|
md5checker = site_config.LUAROCKS_MD5CHECKER or "md5sum",
|
||||||
|
connection_timeout = 30, -- 0 = no timeout
|
||||||
|
|
||||||
|
variables = {
|
||||||
|
MAKE = "make",
|
||||||
|
CC = "cc",
|
||||||
|
LD = "ld",
|
||||||
|
|
||||||
|
CVS = "cvs",
|
||||||
|
GIT = "git",
|
||||||
|
SSCM = "sscm",
|
||||||
|
SVN = "svn",
|
||||||
|
HG = "hg",
|
||||||
|
|
||||||
|
RSYNC = "rsync",
|
||||||
|
WGET = "wget",
|
||||||
|
SCP = "scp",
|
||||||
|
CURL = "curl",
|
||||||
|
|
||||||
|
PWD = "pwd",
|
||||||
|
MKDIR = "mkdir",
|
||||||
|
RMDIR = "rmdir",
|
||||||
|
CP = "cp",
|
||||||
|
LS = "ls",
|
||||||
|
RM = "rm",
|
||||||
|
FIND = "find",
|
||||||
|
TEST = "test",
|
||||||
|
CHMOD = "chmod",
|
||||||
|
MKTEMP = "mktemp",
|
||||||
|
|
||||||
|
ZIP = "zip",
|
||||||
|
UNZIP = "unzip -n",
|
||||||
|
GUNZIP = "gunzip",
|
||||||
|
BUNZIP2 = "bunzip2",
|
||||||
|
TAR = "tar",
|
||||||
|
|
||||||
|
MD5SUM = "md5sum",
|
||||||
|
OPENSSL = "openssl",
|
||||||
|
MD5 = "md5",
|
||||||
|
STAT = "stat",
|
||||||
|
TOUCH = "touch",
|
||||||
|
|
||||||
|
CMAKE = "cmake",
|
||||||
|
SEVENZ = "7z",
|
||||||
|
|
||||||
|
RSYNCFLAGS = "--exclude=.git -Oavz",
|
||||||
|
STATFLAG = "-c '%a'",
|
||||||
|
CURLNOCERTFLAG = "",
|
||||||
|
WGETNOCERTFLAG = "",
|
||||||
|
},
|
||||||
|
|
||||||
|
external_deps_subdirs = site_config.LUAROCKS_EXTERNAL_DEPS_SUBDIRS or {
|
||||||
|
bin = "bin",
|
||||||
|
lib = "lib",
|
||||||
|
include = "include"
|
||||||
|
},
|
||||||
|
runtime_external_deps_subdirs = site_config.LUAROCKS_RUNTIME_EXTERNAL_DEPS_SUBDIRS or {
|
||||||
|
bin = "bin",
|
||||||
|
lib = "lib",
|
||||||
|
include = "include"
|
||||||
|
},
|
||||||
|
|
||||||
|
rocks_provided = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.platforms.windows then
|
||||||
|
local full_prefix = (site_config.LUAROCKS_PREFIX or (os.getenv("PROGRAMFILES")..[[\LuaRocks]]))
|
||||||
|
extra_luarocks_module_dir = full_prefix.."/lua/?.lua"
|
||||||
|
|
||||||
|
home_config_file = home_config_file and home_config_file:gsub("\\","/")
|
||||||
|
defaults.fs_use_modules = false
|
||||||
|
defaults.arch = "win32-"..cfg.target_cpu
|
||||||
|
defaults.lib_extension = "dll"
|
||||||
|
defaults.external_lib_extension = "dll"
|
||||||
|
defaults.obj_extension = "obj"
|
||||||
|
defaults.external_deps_dirs = { "c:/external/" }
|
||||||
|
defaults.variables.LUA_BINDIR = site_config.LUA_BINDIR and site_config.LUA_BINDIR:gsub("\\", "/") or "c:/lua"..cfg.lua_version.."/bin"
|
||||||
|
defaults.variables.LUA_INCDIR = site_config.LUA_INCDIR and site_config.LUA_INCDIR:gsub("\\", "/") or "c:/lua"..cfg.lua_version.."/include"
|
||||||
|
defaults.variables.LUA_LIBDIR = site_config.LUA_LIBDIR and site_config.LUA_LIBDIR:gsub("\\", "/") or "c:/lua"..cfg.lua_version.."/lib"
|
||||||
|
|
||||||
|
defaults.makefile = "Makefile.win"
|
||||||
|
defaults.variables.MAKE = "nmake"
|
||||||
|
defaults.variables.CC = "cl"
|
||||||
|
defaults.variables.RC = "rc"
|
||||||
|
defaults.variables.WRAPPER = full_prefix.."\\rclauncher.c"
|
||||||
|
defaults.variables.LD = "link"
|
||||||
|
defaults.variables.MT = "mt"
|
||||||
|
defaults.variables.LUALIB = "lua"..cfg.lua_version..".lib"
|
||||||
|
defaults.variables.CFLAGS = "/nologo /MD /O2"
|
||||||
|
defaults.variables.LIBFLAG = "/nologo /dll"
|
||||||
|
|
||||||
|
local bins = { "SEVENZ", "CP", "FIND", "LS", "MD5SUM",
|
||||||
|
"MKDIR", "MV", "PWD", "RMDIR", "TEST", "UNAME", "WGET" }
|
||||||
|
for _, var in ipairs(bins) do
|
||||||
|
if defaults.variables[var] then
|
||||||
|
defaults.variables[var] = full_prefix.."\\tools\\"..defaults.variables[var]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defaults.external_deps_patterns = {
|
||||||
|
bin = { "?.exe", "?.bat" },
|
||||||
|
lib = { "?.lib", "?.dll", "lib?.dll" },
|
||||||
|
include = { "?.h" }
|
||||||
|
}
|
||||||
|
defaults.runtime_external_deps_patterns = {
|
||||||
|
bin = { "?.exe", "?.bat" },
|
||||||
|
lib = { "?.dll", "lib?.dll" },
|
||||||
|
include = { "?.h" }
|
||||||
|
}
|
||||||
|
defaults.export_path = "SET PATH=%s"
|
||||||
|
defaults.export_path_separator = ";"
|
||||||
|
defaults.export_lua_path = "SET LUA_PATH=%s"
|
||||||
|
defaults.export_lua_cpath = "SET LUA_CPATH=%s"
|
||||||
|
defaults.wrapper_suffix = ".bat"
|
||||||
|
|
||||||
|
local localappdata = os.getenv("LOCALAPPDATA")
|
||||||
|
if not localappdata then
|
||||||
|
-- for Windows versions below Vista
|
||||||
|
localappdata = os.getenv("USERPROFILE").."/Local Settings/Application Data"
|
||||||
|
end
|
||||||
|
defaults.local_cache = localappdata.."/LuaRocks/Cache"
|
||||||
|
defaults.web_browser = "start"
|
||||||
|
end
|
||||||
|
|
||||||
|
if cfg.platforms.mingw32 then
|
||||||
|
defaults.obj_extension = "o"
|
||||||
|
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.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" }
|
||||||
|
}
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
if cfg.platforms.unix then
|
||||||
|
defaults.lib_extension = "so"
|
||||||
|
defaults.external_lib_extension = "so"
|
||||||
|
defaults.obj_extension = "o"
|
||||||
|
defaults.external_deps_dirs = { "/usr/local", "/usr" }
|
||||||
|
defaults.variables.LUA_BINDIR = site_config.LUA_BINDIR or "/usr/local/bin"
|
||||||
|
defaults.variables.LUA_INCDIR = site_config.LUA_INCDIR or "/usr/local/include"
|
||||||
|
defaults.variables.LUA_LIBDIR = site_config.LUA_LIBDIR or "/usr/local/lib"
|
||||||
|
defaults.variables.CFLAGS = "-O2"
|
||||||
|
defaults.cmake_generator = "Unix Makefiles"
|
||||||
|
defaults.variables.CC = "gcc"
|
||||||
|
defaults.variables.LD = "gcc"
|
||||||
|
defaults.gcc_rpath = true
|
||||||
|
defaults.variables.LIBFLAG = "-shared"
|
||||||
|
defaults.external_deps_patterns = {
|
||||||
|
bin = { "?" },
|
||||||
|
lib = { "lib?.a", "lib?.so", "lib?.so.*" },
|
||||||
|
include = { "?.h" }
|
||||||
|
}
|
||||||
|
defaults.runtime_external_deps_patterns = {
|
||||||
|
bin = { "?" },
|
||||||
|
lib = { "lib?.so", "lib?.so.*" },
|
||||||
|
include = { "?.h" }
|
||||||
|
}
|
||||||
|
defaults.export_path = "export PATH='%s'"
|
||||||
|
defaults.export_path_separator = ":"
|
||||||
|
defaults.export_lua_path = "export LUA_PATH='%s'"
|
||||||
|
defaults.export_lua_cpath = "export LUA_CPATH='%s'"
|
||||||
|
defaults.wrapper_suffix = ""
|
||||||
|
defaults.local_cache = cfg.home.."/.cache/luarocks"
|
||||||
|
if not defaults.variables.CFLAGS:match("-fPIC") then
|
||||||
|
defaults.variables.CFLAGS = defaults.variables.CFLAGS.." -fPIC"
|
||||||
|
end
|
||||||
|
defaults.web_browser = "xdg-open"
|
||||||
|
end
|
||||||
|
|
||||||
|
if cfg.platforms.cygwin then
|
||||||
|
defaults.lib_extension = "so" -- can be overridden in the config file for mingw builds
|
||||||
|
defaults.arch = "cygwin-"..cfg.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 cfg.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" }
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if cfg.platforms.bsd then
|
||||||
|
defaults.variables.MAKE = "gmake"
|
||||||
|
defaults.variables.STATFLAG = "-f '%OLp'"
|
||||||
|
end
|
||||||
|
|
||||||
|
if cfg.platforms.macosx then
|
||||||
|
defaults.variables.MAKE = "make"
|
||||||
|
defaults.external_lib_extension = "dylib"
|
||||||
|
defaults.arch = "macosx-"..cfg.target_cpu
|
||||||
|
defaults.variables.LIBFLAG = "-bundle -undefined dynamic_lookup -all_load"
|
||||||
|
defaults.variables.STAT = "/usr/bin/stat"
|
||||||
|
defaults.variables.STATFLAG = "-f '%A'"
|
||||||
|
local version = io.popen("sw_vers -productVersion"):read("*l")
|
||||||
|
version = tonumber(version and version:match("^[^.]+%.([^.]+)")) or 3
|
||||||
|
if version >= 10 then
|
||||||
|
version = 8
|
||||||
|
elseif version >= 5 then
|
||||||
|
version = 5
|
||||||
|
else
|
||||||
|
defaults.gcc_rpath = false
|
||||||
|
end
|
||||||
|
defaults.variables.CC = "env MACOSX_DEPLOYMENT_TARGET=10."..version.." gcc"
|
||||||
|
defaults.variables.LD = "env MACOSX_DEPLOYMENT_TARGET=10."..version.." gcc"
|
||||||
|
defaults.web_browser = "open"
|
||||||
|
end
|
||||||
|
|
||||||
|
if cfg.platforms.linux then
|
||||||
|
defaults.arch = "linux-"..cfg.target_cpu
|
||||||
|
end
|
||||||
|
|
||||||
|
if cfg.platforms.freebsd then
|
||||||
|
defaults.arch = "freebsd-"..cfg.target_cpu
|
||||||
|
defaults.gcc_rpath = false
|
||||||
|
defaults.variables.CC = "cc"
|
||||||
|
defaults.variables.LD = "cc"
|
||||||
|
end
|
||||||
|
|
||||||
|
if cfg.platforms.openbsd then
|
||||||
|
defaults.arch = "openbsd-"..cfg.target_cpu
|
||||||
|
end
|
||||||
|
|
||||||
|
if cfg.platforms.netbsd then
|
||||||
|
defaults.arch = "netbsd-"..cfg.target_cpu
|
||||||
|
end
|
||||||
|
|
||||||
|
if cfg.platforms.solaris then
|
||||||
|
defaults.arch = "solaris-"..cfg.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
|
||||||
|
defaults.variables.LUAROCKS_PREFIX = site_config.LUAROCKS_PREFIX
|
||||||
|
defaults.variables.LUA = site_config.LUA_DIR_SET and (defaults.variables.LUA_BINDIR.."/"..defaults.lua_interpreter) or defaults.lua_interpreter
|
||||||
|
|
||||||
|
-- Add built-in modules to rocks_provided
|
||||||
|
defaults.rocks_provided["lua"] = cfg.lua_version.."-1"
|
||||||
|
|
||||||
|
if bit32 then -- Lua 5.2+
|
||||||
|
defaults.rocks_provided["bit32"] = cfg.lua_version.."-1"
|
||||||
|
end
|
||||||
|
|
||||||
|
if utf8 then -- Lua 5.3+
|
||||||
|
defaults.rocks_provided["utf8"] = cfg.lua_version.."-1"
|
||||||
|
end
|
||||||
|
|
||||||
|
if package.loaded.jit then
|
||||||
|
-- LuaJIT
|
||||||
|
local lj_version = package.loaded.jit.version:match("LuaJIT (.*)"):gsub("%-","")
|
||||||
|
--defaults.rocks_provided["luajit"] = lj_version.."-1"
|
||||||
|
defaults.rocks_provided["luabitop"] = lj_version.."-1"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Use defaults:
|
||||||
|
|
||||||
|
-- Populate some arrays with values from their 'defaults' counterparts
|
||||||
|
-- if they were not already set by user.
|
||||||
|
for _, entry in ipairs({"variables", "rocks_provided"}) do
|
||||||
|
if not cfg[entry] then
|
||||||
|
cfg[entry] = {}
|
||||||
|
end
|
||||||
|
for k,v in pairs(defaults[entry]) do
|
||||||
|
if not cfg[entry][k] then
|
||||||
|
cfg[entry][k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- For values not set in the config file, use values from the 'defaults' table.
|
||||||
|
local cfg_mt = {
|
||||||
|
__index = function(t, k)
|
||||||
|
local default = defaults[k]
|
||||||
|
if default then
|
||||||
|
rawset(t, k, default)
|
||||||
|
end
|
||||||
|
return default
|
||||||
|
end
|
||||||
|
}
|
||||||
|
setmetatable(cfg, cfg_mt)
|
||||||
|
|
||||||
|
if not cfg.check_certificates then
|
||||||
|
cfg.variables.CURLNOCERTFLAG = "-k"
|
||||||
|
cfg.variables.WGETNOCERTFLAG = "--no-check-certificate"
|
||||||
|
end
|
||||||
|
|
||||||
|
function cfg.make_paths_from_tree(tree)
|
||||||
|
local lua_path, lib_path, bin_path
|
||||||
|
if type(tree) == "string" then
|
||||||
|
lua_path = tree..cfg.lua_modules_path
|
||||||
|
lib_path = tree..cfg.lib_modules_path
|
||||||
|
bin_path = tree.."/bin"
|
||||||
|
else
|
||||||
|
lua_path = tree.lua_dir or tree.root..cfg.lua_modules_path
|
||||||
|
lib_path = tree.lib_dir or tree.root..cfg.lib_modules_path
|
||||||
|
bin_path = tree.bin_dir or tree.root.."/bin"
|
||||||
|
end
|
||||||
|
return 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 = cfg.make_paths_from_tree(tree)
|
||||||
|
table.insert(new_path, lua_path.."/?.lua")
|
||||||
|
table.insert(new_path, lua_path.."/?/init.lua")
|
||||||
|
table.insert(new_cpath, lib_path.."/?."..cfg.lib_extension)
|
||||||
|
table.insert(new_bin, bin_path)
|
||||||
|
end
|
||||||
|
if current then
|
||||||
|
add_tree_to_paths(current)
|
||||||
|
end
|
||||||
|
for _,tree in ipairs(cfg.rocks_trees) do
|
||||||
|
add_tree_to_paths(tree)
|
||||||
|
end
|
||||||
|
if extra_luarocks_module_dir then
|
||||||
|
table.insert(new_path, extra_luarocks_module_dir)
|
||||||
|
end
|
||||||
|
return table.concat(new_path, ";"), table.concat(new_cpath, ";"), table.concat(new_bin, cfg.export_path_separator)
|
||||||
|
end
|
||||||
|
|
||||||
|
function cfg.init_package_paths()
|
||||||
|
local lr_path, lr_cpath, lr_bin = cfg.package_paths()
|
||||||
|
package.path = util.remove_path_dupes(package.path .. ";" .. lr_path, ";")
|
||||||
|
package.cpath = util.remove_path_dupes(package.cpath .. ";" .. lr_cpath, ";")
|
||||||
|
end
|
||||||
|
|
||||||
|
function cfg.which_config()
|
||||||
|
local ret = {
|
||||||
|
system = {
|
||||||
|
file = sys_config_file or sys_config_file_default,
|
||||||
|
ok = sys_config_ok,
|
||||||
|
},
|
||||||
|
user = {
|
||||||
|
file = home_config_file or home_config_file_default,
|
||||||
|
ok = home_config_ok,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret.nearest = (ret.user.ok and ret.user.file) or ret.system.file
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
cfg.user_agent = "LuaRocks/"..cfg.program_version.." "..cfg.arch
|
||||||
|
|
||||||
|
cfg.http_proxy = os.getenv("http_proxy")
|
||||||
|
cfg.https_proxy = os.getenv("https_proxy")
|
||||||
|
cfg.no_proxy = os.getenv("no_proxy")
|
||||||
|
|
||||||
|
--- Check if platform was detected
|
||||||
|
-- @param query string: The platform name to check.
|
||||||
|
-- @return boolean: true if LuaRocks is currently running on queried platform.
|
||||||
|
function cfg.is_platform(query)
|
||||||
|
assert(type(query) == "string")
|
||||||
|
|
||||||
|
for _, platform in ipairs(cfg.platforms) do
|
||||||
|
if platform == query then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return cfg
|
||||||
199
Utils/luarocks/lua/luarocks/command_line.lua
Normal file
199
Utils/luarocks/lua/luarocks/command_line.lua
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
|
||||||
|
--- Functions for command-line scripts.
|
||||||
|
local command_line = {}
|
||||||
|
|
||||||
|
local unpack = unpack or table.unpack
|
||||||
|
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local deps = require("luarocks.deps")
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
|
||||||
|
local program = util.this_program("luarocks")
|
||||||
|
|
||||||
|
local function error_handler(err)
|
||||||
|
return debug.traceback("LuaRocks "..cfg.program_version..
|
||||||
|
" bug (please report at https://github.com/keplerproject/luarocks/issues).\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")
|
||||||
|
util.printerr("\nError: "..message)
|
||||||
|
|
||||||
|
local ok, err = xpcall(util.run_scheduled_functions, error_handler)
|
||||||
|
if not ok then
|
||||||
|
util.printerr("\nError: "..err)
|
||||||
|
exitcode = cfg.errorcodes.CRASH
|
||||||
|
end
|
||||||
|
|
||||||
|
os.exit(exitcode or cfg.errorcodes.UNSPECIFIED)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function replace_tree(flags, tree)
|
||||||
|
tree = dir.normalize(tree)
|
||||||
|
flags["tree"] = tree
|
||||||
|
path.use_tree(tree)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Main command-line processor.
|
||||||
|
-- Parses input arguments and calls the appropriate driver function
|
||||||
|
-- to execute the action requested on the command-line, forwarding
|
||||||
|
-- to it any additional arguments passed by the user.
|
||||||
|
-- Uses the global table "commands", which contains
|
||||||
|
-- the loaded modules representing commands.
|
||||||
|
-- @param ... string: Arguments given on the command-line.
|
||||||
|
function command_line.run_command(...)
|
||||||
|
local args = {...}
|
||||||
|
local cmdline_vars = {}
|
||||||
|
for i = #args, 1, -1 do
|
||||||
|
local arg = args[i]
|
||||||
|
if arg:match("^[^-][^=]*=") then
|
||||||
|
local var, val = arg:match("^([A-Z_][A-Z0-9_]*)=(.*)")
|
||||||
|
if val then
|
||||||
|
cmdline_vars[var] = val
|
||||||
|
table.remove(args, i)
|
||||||
|
else
|
||||||
|
die("Invalid assignment: "..arg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local nonflags = { util.parse_flags(unpack(args)) }
|
||||||
|
local flags = table.remove(nonflags, 1)
|
||||||
|
if flags.ERROR then
|
||||||
|
die(flags.ERROR.." See --help.")
|
||||||
|
end
|
||||||
|
|
||||||
|
if flags["from"] then flags["server"] = flags["from"] end
|
||||||
|
if flags["only-from"] then flags["only-server"] = flags["only-from"] end
|
||||||
|
if flags["only-sources-from"] then flags["only-sources"] = flags["only-sources-from"] end
|
||||||
|
if flags["to"] then flags["tree"] = flags["to"] end
|
||||||
|
if flags["nodeps"] then
|
||||||
|
flags["deps-mode"] = "none"
|
||||||
|
end
|
||||||
|
|
||||||
|
cfg.flags = flags
|
||||||
|
|
||||||
|
local command
|
||||||
|
|
||||||
|
if flags["verbose"] then -- setting it in the config file will kick-in earlier in the process
|
||||||
|
cfg.verbose = true
|
||||||
|
fs.verbose()
|
||||||
|
end
|
||||||
|
|
||||||
|
if flags["timeout"] then -- setting it in the config file will kick-in earlier in the process
|
||||||
|
local timeout = tonumber(flags["timeout"])
|
||||||
|
if timeout then
|
||||||
|
cfg.connection_timeout = timeout
|
||||||
|
else
|
||||||
|
die "Argument error: --timeout expects a numeric argument."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if flags["version"] then
|
||||||
|
util.printout(program.." "..cfg.program_version)
|
||||||
|
util.printout(program_description)
|
||||||
|
util.printout()
|
||||||
|
os.exit(cfg.errorcodes.OK)
|
||||||
|
elseif flags["help"] or #nonflags == 0 then
|
||||||
|
command = "help"
|
||||||
|
else
|
||||||
|
command = table.remove(nonflags, 1)
|
||||||
|
end
|
||||||
|
command = command:gsub("-", "_")
|
||||||
|
|
||||||
|
if cfg.local_by_default then
|
||||||
|
flags["local"] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if flags["deps-mode"] and not deps.check_deps_mode_flag(flags["deps-mode"]) then
|
||||||
|
die("Invalid entry for --deps-mode.")
|
||||||
|
end
|
||||||
|
|
||||||
|
if flags["branch"] then
|
||||||
|
cfg.branch = flags["branch"]
|
||||||
|
end
|
||||||
|
|
||||||
|
if flags["tree"] then
|
||||||
|
local named = false
|
||||||
|
for _, tree in ipairs(cfg.rocks_trees) do
|
||||||
|
if type(tree) == "table" and flags["tree"] == tree.name then
|
||||||
|
if not tree.root then
|
||||||
|
die("Configuration error: tree '"..tree.name.."' has no 'root' field.")
|
||||||
|
end
|
||||||
|
replace_tree(flags, tree.root)
|
||||||
|
named = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not named then
|
||||||
|
local root_dir = fs.absolute_name(flags["tree"])
|
||||||
|
replace_tree(flags, root_dir)
|
||||||
|
end
|
||||||
|
elseif flags["local"] then
|
||||||
|
if not cfg.home_tree then
|
||||||
|
die("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.")
|
||||||
|
end
|
||||||
|
replace_tree(flags, cfg.home_tree)
|
||||||
|
else
|
||||||
|
local trees = cfg.rocks_trees
|
||||||
|
path.use_tree(trees[#trees])
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(cfg.root_dir) == "string" then
|
||||||
|
cfg.root_dir = cfg.root_dir:gsub("/+$", "")
|
||||||
|
else
|
||||||
|
cfg.root_dir.root = cfg.root_dir.root:gsub("/+$", "")
|
||||||
|
end
|
||||||
|
cfg.rocks_dir = cfg.rocks_dir:gsub("/+$", "")
|
||||||
|
cfg.deploy_bin_dir = cfg.deploy_bin_dir:gsub("/+$", "")
|
||||||
|
cfg.deploy_lua_dir = cfg.deploy_lua_dir:gsub("/+$", "")
|
||||||
|
cfg.deploy_lib_dir = cfg.deploy_lib_dir:gsub("/+$", "")
|
||||||
|
|
||||||
|
cfg.variables.ROCKS_TREE = cfg.rocks_dir
|
||||||
|
cfg.variables.SCRIPTS_DIR = cfg.deploy_bin_dir
|
||||||
|
|
||||||
|
if flags["server"] then
|
||||||
|
local protocol, path = dir.split_url(flags["server"])
|
||||||
|
table.insert(cfg.rocks_servers, 1, protocol.."://"..path)
|
||||||
|
end
|
||||||
|
|
||||||
|
if flags["only-server"] then
|
||||||
|
cfg.rocks_servers = { flags["only-server"] }
|
||||||
|
end
|
||||||
|
|
||||||
|
if flags["only-sources"] then
|
||||||
|
cfg.only_sources_from = flags["only-sources"]
|
||||||
|
end
|
||||||
|
|
||||||
|
if command ~= "help" then
|
||||||
|
for k, v in pairs(cmdline_vars) do
|
||||||
|
cfg.variables[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not fs.current_dir() or fs.current_dir() == "" then
|
||||||
|
die("Current directory does not exist. Please run LuaRocks from an existing directory.")
|
||||||
|
end
|
||||||
|
|
||||||
|
if commands[command] then
|
||||||
|
local cmd = require(commands[command])
|
||||||
|
local call_ok, ok, err, exitcode = xpcall(function() return cmd.command(flags, unpack(nonflags)) end, error_handler)
|
||||||
|
if not call_ok then
|
||||||
|
die(ok, cfg.errorcodes.CRASH)
|
||||||
|
elseif not ok then
|
||||||
|
die(err, exitcode)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
die("Unknown command: "..command)
|
||||||
|
end
|
||||||
|
util.run_scheduled_functions()
|
||||||
|
end
|
||||||
|
|
||||||
|
return command_line
|
||||||
72
Utils/luarocks/lua/luarocks/config_cmd.lua
Normal file
72
Utils/luarocks/lua/luarocks/config_cmd.lua
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
--- Module implementing the LuaRocks "config" command.
|
||||||
|
-- Queries information about the LuaRocks configuration.
|
||||||
|
local config_cmd = {}
|
||||||
|
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
|
||||||
|
util.add_run_function(config_cmd)
|
||||||
|
config_cmd.help_summary = "Query information about the LuaRocks configuration."
|
||||||
|
config_cmd.help_arguments = "<flag>"
|
||||||
|
config_cmd.help = [[
|
||||||
|
--lua-incdir Path to Lua header files.
|
||||||
|
|
||||||
|
--lua-libdir Path to Lua library files.
|
||||||
|
|
||||||
|
--lua-ver Lua version (in major.minor format). e.g. 5.1
|
||||||
|
|
||||||
|
--system-config Location of the system config file.
|
||||||
|
|
||||||
|
--user-config Location of the user config file.
|
||||||
|
|
||||||
|
--rock-trees Rocks trees in use. First the user tree, then the system tree.
|
||||||
|
]]
|
||||||
|
|
||||||
|
local function config_file(conf)
|
||||||
|
print(dir.normalize(conf.file))
|
||||||
|
if conf.ok then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return nil, "file not found"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Driver function for "config" command.
|
||||||
|
-- @return boolean: True if succeeded, nil on errors.
|
||||||
|
function config_cmd.command(flags)
|
||||||
|
if flags["lua-incdir"] then
|
||||||
|
print(cfg.variables.LUA_INCDIR)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if flags["lua-libdir"] then
|
||||||
|
print(cfg.variables.LUA_LIBDIR)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if flags["lua-ver"] then
|
||||||
|
print(cfg.lua_version)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
local conf = cfg.which_config()
|
||||||
|
if flags["system-config"] then
|
||||||
|
return config_file(conf.system)
|
||||||
|
end
|
||||||
|
if flags["user-config"] then
|
||||||
|
return config_file(conf.user)
|
||||||
|
end
|
||||||
|
if flags["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
|
||||||
|
|
||||||
|
return nil, "Please provide a flag for querying configuration values. "..util.see_help("config")
|
||||||
|
end
|
||||||
|
|
||||||
|
return config_cmd
|
||||||
752
Utils/luarocks/lua/luarocks/deps.lua
Normal file
752
Utils/luarocks/lua/luarocks/deps.lua
Normal file
@ -0,0 +1,752 @@
|
|||||||
|
|
||||||
|
--- Dependency handling functions.
|
||||||
|
-- Dependencies are represented in LuaRocks through strings with
|
||||||
|
-- a package name followed by a comma-separated list of constraints.
|
||||||
|
-- Each constraint consists of an operator and a version number.
|
||||||
|
-- In this string format, version numbers are represented as
|
||||||
|
-- naturally as possible, like they are used by upstream projects
|
||||||
|
-- (e.g. "2.0beta3"). Internally, LuaRocks converts them to a purely
|
||||||
|
-- numeric representation, allowing comparison following some
|
||||||
|
-- "common sense" heuristics. The precise specification of the
|
||||||
|
-- comparison criteria is the source code of this module, but the
|
||||||
|
-- test/test_deps.lua file included with LuaRocks provides some
|
||||||
|
-- insights on what these criteria are.
|
||||||
|
local deps = {}
|
||||||
|
package.loaded["luarocks.deps"] = deps
|
||||||
|
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local manif_core = require("luarocks.manif_core")
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
|
||||||
|
local operators = {
|
||||||
|
["=="] = "==",
|
||||||
|
["~="] = "~=",
|
||||||
|
[">"] = ">",
|
||||||
|
["<"] = "<",
|
||||||
|
[">="] = ">=",
|
||||||
|
["<="] = "<=",
|
||||||
|
["~>"] = "~>",
|
||||||
|
-- plus some convenience translations
|
||||||
|
[""] = "==",
|
||||||
|
["="] = "==",
|
||||||
|
["!="] = "~="
|
||||||
|
}
|
||||||
|
|
||||||
|
local deltas = {
|
||||||
|
scm = 1100,
|
||||||
|
cvs = 1000,
|
||||||
|
rc = -1000,
|
||||||
|
pre = -10000,
|
||||||
|
beta = -100000,
|
||||||
|
alpha = -1000000
|
||||||
|
}
|
||||||
|
|
||||||
|
local version_mt = {
|
||||||
|
--- Equality comparison for versions.
|
||||||
|
-- All version numbers must be equal.
|
||||||
|
-- If both versions have revision numbers, they must be equal;
|
||||||
|
-- otherwise the revision number is ignored.
|
||||||
|
-- @param v1 table: version table to compare.
|
||||||
|
-- @param v2 table: version table to compare.
|
||||||
|
-- @return boolean: true if they are considered equivalent.
|
||||||
|
__eq = function(v1, v2)
|
||||||
|
if #v1 ~= #v2 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
for i = 1, #v1 do
|
||||||
|
if v1[i] ~= v2[i] then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if v1.revision and v2.revision then
|
||||||
|
return (v1.revision == v2.revision)
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
--- Size comparison for versions.
|
||||||
|
-- All version numbers are compared.
|
||||||
|
-- If both versions have revision numbers, they are compared;
|
||||||
|
-- otherwise the revision number is ignored.
|
||||||
|
-- @param v1 table: version table to compare.
|
||||||
|
-- @param v2 table: version table to compare.
|
||||||
|
-- @return boolean: true if v1 is considered lower than v2.
|
||||||
|
__lt = function(v1, v2)
|
||||||
|
for i = 1, math.max(#v1, #v2) do
|
||||||
|
local v1i, v2i = v1[i] or 0, v2[i] or 0
|
||||||
|
if v1i ~= v2i then
|
||||||
|
return (v1i < v2i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if v1.revision and v2.revision then
|
||||||
|
return (v1.revision < v2.revision)
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
local version_cache = {}
|
||||||
|
setmetatable(version_cache, {
|
||||||
|
__mode = "kv"
|
||||||
|
})
|
||||||
|
|
||||||
|
--- Parse a version string, converting to table format.
|
||||||
|
-- A version table contains all components of the version string
|
||||||
|
-- converted to numeric format, stored in the array part of the table.
|
||||||
|
-- If the version contains a revision, it is stored numerically
|
||||||
|
-- in the 'revision' field. The original string representation of
|
||||||
|
-- the string is preserved in the 'string' field.
|
||||||
|
-- Returned version tables use a metatable
|
||||||
|
-- allowing later comparison through relational operators.
|
||||||
|
-- @param vstring string: A version number in string format.
|
||||||
|
-- @return table or nil: A version table or nil
|
||||||
|
-- if the input string contains invalid characters.
|
||||||
|
function deps.parse_version(vstring)
|
||||||
|
if not vstring then return nil end
|
||||||
|
assert(type(vstring) == "string")
|
||||||
|
|
||||||
|
local cached = version_cache[vstring]
|
||||||
|
if cached then
|
||||||
|
return cached
|
||||||
|
end
|
||||||
|
|
||||||
|
local version = {}
|
||||||
|
local i = 1
|
||||||
|
|
||||||
|
local function add_token(number)
|
||||||
|
version[i] = version[i] and version[i] + number/100000 or number
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- trim leading and trailing spaces
|
||||||
|
vstring = vstring:match("^%s*(.*)%s*$")
|
||||||
|
version.string = vstring
|
||||||
|
-- store revision separately if any
|
||||||
|
local main, revision = vstring:match("(.*)%-(%d+)$")
|
||||||
|
if revision then
|
||||||
|
vstring = main
|
||||||
|
version.revision = tonumber(revision)
|
||||||
|
end
|
||||||
|
while #vstring > 0 do
|
||||||
|
-- extract a number
|
||||||
|
local token, rest = vstring:match("^(%d+)[%.%-%_]*(.*)")
|
||||||
|
if token then
|
||||||
|
add_token(tonumber(token))
|
||||||
|
else
|
||||||
|
-- extract a word
|
||||||
|
token, rest = vstring:match("^(%a+)[%.%-%_]*(.*)")
|
||||||
|
if not token then
|
||||||
|
util.printerr("Warning: version number '"..vstring.."' could not be parsed.")
|
||||||
|
version[i] = 0
|
||||||
|
break
|
||||||
|
end
|
||||||
|
version[i] = deltas[token] or (token:byte() / 1000)
|
||||||
|
end
|
||||||
|
vstring = rest
|
||||||
|
end
|
||||||
|
setmetatable(version, version_mt)
|
||||||
|
version_cache[vstring] = version
|
||||||
|
return version
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Utility function to compare version numbers given as strings.
|
||||||
|
-- @param a string: one version.
|
||||||
|
-- @param b string: another version.
|
||||||
|
-- @return boolean: True if a > b.
|
||||||
|
function deps.compare_versions(a, b)
|
||||||
|
return deps.parse_version(a) > deps.parse_version(b)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Consumes a constraint from a string, converting it to table format.
|
||||||
|
-- For example, a string ">= 1.0, > 2.0" is converted to a table in the
|
||||||
|
-- format {op = ">=", version={1,0}} and the rest, "> 2.0", is returned
|
||||||
|
-- back to the caller.
|
||||||
|
-- @param input string: A list of constraints in string format.
|
||||||
|
-- @return (table, string) or nil: A table representing the same
|
||||||
|
-- constraints and the string with the unused input, or nil if the
|
||||||
|
-- input string is invalid.
|
||||||
|
local function parse_constraint(input)
|
||||||
|
assert(type(input) == "string")
|
||||||
|
|
||||||
|
local no_upgrade, op, version, rest = input:match("^(@?)([<>=~!]*)%s*([%w%.%_%-]+)[%s,]*(.*)")
|
||||||
|
local _op = operators[op]
|
||||||
|
version = deps.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
|
||||||
|
|
||||||
|
--- Convert a list of constraints from string to table format.
|
||||||
|
-- For example, a string ">= 1.0, < 2.0" is converted to a table in the format
|
||||||
|
-- {{op = ">=", version={1,0}}, {op = "<", version={2,0}}}.
|
||||||
|
-- Version tables use a metatable allowing later comparison through
|
||||||
|
-- relational operators.
|
||||||
|
-- @param input string: A list of constraints in string format.
|
||||||
|
-- @return table or nil: A table representing the same constraints,
|
||||||
|
-- or nil if the input string is invalid.
|
||||||
|
function deps.parse_constraints(input)
|
||||||
|
assert(type(input) == "string")
|
||||||
|
|
||||||
|
local constraints, constraint, oinput = {}, nil, 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
|
||||||
|
|
||||||
|
--- Convert a dependency from string to table format.
|
||||||
|
-- For example, a string "foo >= 1.0, < 2.0"
|
||||||
|
-- is converted to a table in the format
|
||||||
|
-- {name = "foo", constraints = {{op = ">=", version={1,0}},
|
||||||
|
-- {op = "<", version={2,0}}}}. Version tables use a metatable
|
||||||
|
-- allowing later comparison through relational operators.
|
||||||
|
-- @param dep string: A dependency in string format
|
||||||
|
-- as entered in rockspec files.
|
||||||
|
-- @return table or nil: A table representing the same dependency relation,
|
||||||
|
-- or nil if the input string is invalid.
|
||||||
|
function deps.parse_dep(dep)
|
||||||
|
assert(type(dep) == "string")
|
||||||
|
|
||||||
|
local name, rest = dep:match("^%s*([a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*(.*)")
|
||||||
|
if not name then return nil, "failed to extract dependency name from '"..tostring(dep).."'" end
|
||||||
|
local constraints, err = deps.parse_constraints(rest)
|
||||||
|
if not constraints then return nil, err end
|
||||||
|
return { name = name, constraints = constraints }
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Convert a version table to a string.
|
||||||
|
-- @param v table: The version table
|
||||||
|
-- @param internal boolean or nil: Whether to display versions in their
|
||||||
|
-- internal representation format or how they were specified.
|
||||||
|
-- @return string: The dependency information pretty-printed as a string.
|
||||||
|
function deps.show_version(v, internal)
|
||||||
|
assert(type(v) == "table")
|
||||||
|
assert(type(internal) == "boolean" or not internal)
|
||||||
|
|
||||||
|
return (internal
|
||||||
|
and table.concat(v, ":")..(v.revision and tostring(v.revision) or "")
|
||||||
|
or v.string)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Convert a dependency in table format to a string.
|
||||||
|
-- @param dep table: The dependency in table format
|
||||||
|
-- @param internal boolean or nil: Whether to display versions in their
|
||||||
|
-- internal representation format or how they were specified.
|
||||||
|
-- @return string: The dependency information pretty-printed as a string.
|
||||||
|
function deps.show_dep(dep, internal)
|
||||||
|
assert(type(dep) == "table")
|
||||||
|
assert(type(internal) == "boolean" or not internal)
|
||||||
|
|
||||||
|
if #dep.constraints > 0 then
|
||||||
|
local pretty = {}
|
||||||
|
for _, c in ipairs(dep.constraints) do
|
||||||
|
table.insert(pretty, c.op .. " " .. deps.show_version(c.version, internal))
|
||||||
|
end
|
||||||
|
return dep.name.." "..table.concat(pretty, ", ")
|
||||||
|
else
|
||||||
|
return dep.name
|
||||||
|
end
|
||||||
|
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 = deps.parse_version(version) end
|
||||||
|
if type(requested) ~= "table" then requested = deps.parse_version(requested) end
|
||||||
|
if not version or not requested then return false end
|
||||||
|
|
||||||
|
for i, ri in ipairs(requested) do
|
||||||
|
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 deps.match_constraints(version, constraints)
|
||||||
|
assert(type(version) == "table")
|
||||||
|
assert(type(constraints) == "table")
|
||||||
|
local ok = true
|
||||||
|
setmetatable(version, version_mt)
|
||||||
|
for _, constr in pairs(constraints) do
|
||||||
|
if type(constr.version) == "string" then
|
||||||
|
constr.version = deps.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
|
||||||
|
|
||||||
|
--- Attempt to match a dependency to an installed rock.
|
||||||
|
-- @param dep table: A dependency parsed in table format.
|
||||||
|
-- @param blacklist table: Versions that can't be accepted. Table where keys
|
||||||
|
-- are program versions and values are 'true'.
|
||||||
|
-- @return string or nil: latest installed version of the rock matching the dependency
|
||||||
|
-- or nil if it could not be matched.
|
||||||
|
local function match_dep(dep, blacklist, deps_mode)
|
||||||
|
assert(type(dep) == "table")
|
||||||
|
|
||||||
|
local versions
|
||||||
|
if cfg.rocks_provided[dep.name] then
|
||||||
|
-- provided rocks have higher priority than manifest's rocks
|
||||||
|
versions = { cfg.rocks_provided[dep.name] }
|
||||||
|
else
|
||||||
|
versions = manif_core.get_versions(dep.name, deps_mode)
|
||||||
|
end
|
||||||
|
|
||||||
|
local latest_version
|
||||||
|
for _, vstring in ipairs(versions) do
|
||||||
|
if not blacklist or not blacklist[vstring] then
|
||||||
|
local version = deps.parse_version(vstring)
|
||||||
|
if deps.match_constraints(version, dep.constraints) then
|
||||||
|
if not latest_version or version > latest_version then
|
||||||
|
latest_version = version
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return latest_version and latest_version.string
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Attempt to match dependencies of a rockspec to installed rocks.
|
||||||
|
-- @param rockspec table: The rockspec loaded as a table.
|
||||||
|
-- @param blacklist table or nil: Program versions to not use as valid matches.
|
||||||
|
-- Table where keys are program names and values are tables where keys
|
||||||
|
-- are program versions and values are 'true'.
|
||||||
|
-- @return table, table, 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(rockspec, blacklist, deps_mode)
|
||||||
|
assert(type(rockspec) == "table")
|
||||||
|
assert(type(blacklist) == "table" or not blacklist)
|
||||||
|
local matched, missing, no_upgrade = {}, {}, {}
|
||||||
|
|
||||||
|
for _, dep in ipairs(rockspec.dependencies) do
|
||||||
|
local found = match_dep(dep, blacklist and blacklist[dep.name] or nil, deps_mode)
|
||||||
|
if found then
|
||||||
|
if not cfg.rocks_provided[dep.name] 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
|
||||||
|
|
||||||
|
--- Return a set of values of a table.
|
||||||
|
-- @param tbl table: The input table.
|
||||||
|
-- @return table: The array of keys.
|
||||||
|
local function values_set(tbl)
|
||||||
|
local set = {}
|
||||||
|
for _, v in pairs(tbl) do
|
||||||
|
set[v] = true
|
||||||
|
end
|
||||||
|
return set
|
||||||
|
end
|
||||||
|
|
||||||
|
local function rock_status(name, deps_mode)
|
||||||
|
local search = require("luarocks.search")
|
||||||
|
local installed = match_dep(search.make_query(name), nil, deps_mode)
|
||||||
|
local installation_type = cfg.rocks_provided[name] 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:
|
||||||
|
-- "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)
|
||||||
|
local first_missing_dep = true
|
||||||
|
|
||||||
|
for _, dep in ipairs(dependencies) do
|
||||||
|
if not match_dep(dep, nil, deps_mode) 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(deps.show_dep(dep), rock_status(dep.name, deps_mode)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check dependencies of a rock and attempt to install any missing ones.
|
||||||
|
-- Packages are installed using the LuaRocks "install" command.
|
||||||
|
-- Aborts the program if a dependency could not be fulfilled.
|
||||||
|
-- @param rockspec table: A rockspec in table format.
|
||||||
|
-- @return boolean or (nil, string, [string]): True if no errors occurred, or
|
||||||
|
-- nil and an error message if any test failed, followed by an optional
|
||||||
|
-- error code.
|
||||||
|
function deps.fulfill_dependencies(rockspec, deps_mode)
|
||||||
|
|
||||||
|
local search = require("luarocks.search")
|
||||||
|
local install = require("luarocks.install")
|
||||||
|
|
||||||
|
if rockspec.supported_platforms then
|
||||||
|
if not deps.platforms_set then
|
||||||
|
deps.platforms_set = values_set(cfg.platforms)
|
||||||
|
end
|
||||||
|
local supported = nil
|
||||||
|
for _, plat in pairs(rockspec.supported_platforms) do
|
||||||
|
local neg, plat = plat:match("^(!?)(.*)")
|
||||||
|
if neg == "!" then
|
||||||
|
if deps.platforms_set[plat] then
|
||||||
|
return nil, "This rockspec for "..rockspec.package.." does not support "..plat.." platforms."
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if deps.platforms_set[plat] then
|
||||||
|
supported = true
|
||||||
|
else
|
||||||
|
if supported == nil then
|
||||||
|
supported = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if supported == false then
|
||||||
|
local plats = table.concat(cfg.platforms, ", ")
|
||||||
|
return nil, "This rockspec for "..rockspec.package.." does not support "..plats.." platforms."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
deps.report_missing_dependencies(rockspec.name, rockspec.version, rockspec.dependencies, deps_mode)
|
||||||
|
|
||||||
|
local first_missing_dep = true
|
||||||
|
|
||||||
|
for _, dep in ipairs(rockspec.dependencies) do
|
||||||
|
if not match_dep(dep, nil, deps_mode) then
|
||||||
|
if first_missing_dep then
|
||||||
|
util.printout()
|
||||||
|
first_missing_dep = false
|
||||||
|
end
|
||||||
|
|
||||||
|
util.printout(("%s %s depends on %s (%s)"):format(
|
||||||
|
rockspec.name, rockspec.version, deps.show_dep(dep), rock_status(dep.name, deps_mode)))
|
||||||
|
|
||||||
|
if dep.constraints[1] and dep.constraints[1].no_upgrade then
|
||||||
|
util.printerr("This version of "..rockspec.name.." is designed for use with")
|
||||||
|
util.printerr(deps.show_dep(dep)..", but is configured to avoid upgrading it")
|
||||||
|
util.printerr("automatically. Please upgrade "..dep.name.." with")
|
||||||
|
util.printerr(" luarocks install "..dep.name)
|
||||||
|
util.printerr("or choose an older version of "..rockspec.name.." with")
|
||||||
|
util.printerr(" luarocks search "..rockspec.name)
|
||||||
|
return nil, "Failed matching dependencies"
|
||||||
|
end
|
||||||
|
|
||||||
|
local url, search_err = search.find_suitable_rock(dep)
|
||||||
|
if not url then
|
||||||
|
return nil, "Could not satisfy dependency "..deps.show_dep(dep)..": "..search_err
|
||||||
|
end
|
||||||
|
util.printout("Installing "..url)
|
||||||
|
local ok, install_err, errcode = install.command({deps_mode = deps_mode}, url)
|
||||||
|
if not ok then
|
||||||
|
return nil, "Failed installing dependency: "..url.." - "..install_err, errcode
|
||||||
|
end
|
||||||
|
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, (pattern:gsub("?", file)))
|
||||||
|
end
|
||||||
|
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(type(rockspec) == "table")
|
||||||
|
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
|
||||||
|
local vars = rockspec.variables
|
||||||
|
local patterns = cfg.external_deps_patterns
|
||||||
|
local subdirs = cfg.external_deps_subdirs
|
||||||
|
if mode == "install" then
|
||||||
|
patterns = cfg.runtime_external_deps_patterns
|
||||||
|
subdirs = cfg.runtime_external_deps_subdirs
|
||||||
|
end
|
||||||
|
if rockspec.external_dependencies then
|
||||||
|
for name, ext_files in util.sortedpairs(rockspec.external_dependencies) do
|
||||||
|
local ok = true
|
||||||
|
local failed_files = {program = {}, header = {}, library = {}}
|
||||||
|
local failed_dirname
|
||||||
|
local failed_testfile
|
||||||
|
for _, extdir in ipairs(cfg.external_deps_dirs) do
|
||||||
|
ok = true
|
||||||
|
local prefix = vars[name.."_DIR"]
|
||||||
|
local dirs = {
|
||||||
|
BINDIR = { subdir = subdirs.bin, testfile = "program", pattern = patterns.bin },
|
||||||
|
INCDIR = { subdir = subdirs.include, testfile = "header", pattern = patterns.include },
|
||||||
|
LIBDIR = { subdir = subdirs.lib, testfile = "library", pattern = patterns.lib }
|
||||||
|
}
|
||||||
|
if mode == "install" then
|
||||||
|
dirs.INCDIR = nil
|
||||||
|
end
|
||||||
|
if not prefix then
|
||||||
|
prefix = extdir
|
||||||
|
end
|
||||||
|
if type(prefix) == "table" then
|
||||||
|
if prefix.bin then
|
||||||
|
dirs.BINDIR.subdir = prefix.bin
|
||||||
|
end
|
||||||
|
if prefix.include then
|
||||||
|
if dirs.INCDIR then
|
||||||
|
dirs.INCDIR.subdir = prefix.include
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if prefix.lib then
|
||||||
|
dirs.LIBDIR.subdir = prefix.lib
|
||||||
|
end
|
||||||
|
prefix = prefix.prefix
|
||||||
|
end
|
||||||
|
for dirname, dirdata in 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 = ext_files[dirdata.testfile]
|
||||||
|
if file then
|
||||||
|
local files = {}
|
||||||
|
if not file:match("%.") then
|
||||||
|
add_all_patterns(file, dirdata.pattern, files)
|
||||||
|
else
|
||||||
|
for _, pattern in ipairs(dirdata.pattern) do
|
||||||
|
local matched = deconstruct_pattern(file, pattern)
|
||||||
|
if matched then
|
||||||
|
add_all_patterns(matched, dirdata.pattern, files)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.insert(files, file)
|
||||||
|
end
|
||||||
|
local found = false
|
||||||
|
for _, f in ipairs(files) do
|
||||||
|
|
||||||
|
-- small convenience hack
|
||||||
|
if f:match("%.so$") or f:match("%.dylib$") or f:match("%.dll$") then
|
||||||
|
f = f:gsub("%.[^.]+$", "."..cfg.external_lib_extension)
|
||||||
|
end
|
||||||
|
|
||||||
|
local pattern
|
||||||
|
if f:match("%*") then
|
||||||
|
pattern = f:gsub("%.", "%%."):gsub("%*", ".*")
|
||||||
|
f = "matching "..f
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, d in ipairs(paths) do
|
||||||
|
if pattern then
|
||||||
|
for entry in fs.dir(d) do
|
||||||
|
if entry:match(pattern) then
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
found = fs.is_file(dir.path(d, f))
|
||||||
|
end
|
||||||
|
if found then
|
||||||
|
dirdata.dir = d
|
||||||
|
break
|
||||||
|
else
|
||||||
|
table.insert(failed_files[dirdata.testfile], f.." in "..d)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if found then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not found then
|
||||||
|
ok = false
|
||||||
|
failed_dirname = dirname
|
||||||
|
failed_testfile = dirdata.testfile
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if ok then
|
||||||
|
for dirname, dirdata in pairs(dirs) do
|
||||||
|
vars[name.."_"..dirname] = dirdata.dir
|
||||||
|
end
|
||||||
|
vars[name.."_DIR"] = prefix
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not ok then
|
||||||
|
local lines = {"Could not find "..failed_testfile.." file for "..name}
|
||||||
|
|
||||||
|
local failed_paths = {}
|
||||||
|
for _, failed_file in ipairs(failed_files[failed_testfile]) do
|
||||||
|
if not failed_paths[failed_file] then
|
||||||
|
failed_paths[failed_file] = true
|
||||||
|
table.insert(lines, " No file "..failed_file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(lines, "You may have to install "..name.." in your system and/or pass "..name.."_DIR or "..name.."_"..failed_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
|
||||||
|
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")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
|
||||||
|
local fetch = require("luarocks.fetch")
|
||||||
|
|
||||||
|
if results[name] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not manifest.dependencies then manifest.dependencies = {} end
|
||||||
|
local dependencies = manifest.dependencies
|
||||||
|
if not dependencies[name] then dependencies[name] = {} end
|
||||||
|
local dependencies_name = dependencies[name]
|
||||||
|
local deplist = dependencies_name[version]
|
||||||
|
local rockspec, err
|
||||||
|
if not deplist then
|
||||||
|
rockspec, err = fetch.load_local_rockspec(path.rockspec_file(name, version), false)
|
||||||
|
if not rockspec then
|
||||||
|
util.printerr("Couldn't load rockspec for "..name.." "..version..": "..err)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
dependencies_name[version] = rockspec.dependencies
|
||||||
|
else
|
||||||
|
rockspec = { dependencies = deplist }
|
||||||
|
end
|
||||||
|
local matched = deps.match_deps(rockspec, nil, deps_mode)
|
||||||
|
results[name] = version
|
||||||
|
for _, match in pairs(matched) do
|
||||||
|
deps.scan_deps(results, manifest, match.name, match.version, deps_mode)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local valid_deps_modes = {
|
||||||
|
one = true,
|
||||||
|
order = true,
|
||||||
|
all = true,
|
||||||
|
none = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
function deps.check_deps_mode_flag(flag)
|
||||||
|
return valid_deps_modes[flag]
|
||||||
|
end
|
||||||
|
|
||||||
|
function deps.get_deps_mode(flags)
|
||||||
|
if flags["deps-mode"] then
|
||||||
|
return flags["deps-mode"]
|
||||||
|
else
|
||||||
|
return cfg.deps_mode
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function deps.deps_mode_to_flag(deps_mode)
|
||||||
|
return "--deps-mode="..deps_mode
|
||||||
|
end
|
||||||
|
|
||||||
|
return deps
|
||||||
74
Utils/luarocks/lua/luarocks/dir.lua
Normal file
74
Utils/luarocks/lua/luarocks/dir.lua
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
|
||||||
|
--- Generic utilities for handling pathnames.
|
||||||
|
local dir = {}
|
||||||
|
package.loaded["luarocks.dir"] = dir
|
||||||
|
|
||||||
|
dir.separator = "/"
|
||||||
|
|
||||||
|
--- Strip the path off a path+filename.
|
||||||
|
-- @param pathname string: A path+name, such as "/a/b/c"
|
||||||
|
-- or "\a\b\c".
|
||||||
|
-- @return string: The filename without its path, such as "c".
|
||||||
|
function 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
|
||||||
|
|
||||||
|
--- 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
|
||||||
|
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")
|
||||||
|
|
||||||
|
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("//", "/")
|
||||||
|
if protocol ~= "file" then pathname = protocol .."://"..pathname end
|
||||||
|
return pathname
|
||||||
|
end
|
||||||
|
|
||||||
|
return dir
|
||||||
157
Utils/luarocks/lua/luarocks/doc.lua
Normal file
157
Utils/luarocks/lua/luarocks/doc.lua
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
|
||||||
|
--- Module implementing the LuaRocks "doc" command.
|
||||||
|
-- Shows documentation for an installed rock.
|
||||||
|
local doc = {}
|
||||||
|
package.loaded["luarocks.doc"] = doc
|
||||||
|
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
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")
|
||||||
|
|
||||||
|
util.add_run_function(doc)
|
||||||
|
doc.help_summary = "Show documentation for an installed rock."
|
||||||
|
|
||||||
|
doc.help = [[
|
||||||
|
<argument> is an existing package name.
|
||||||
|
Without any flags, tries to load the documentation
|
||||||
|
using a series of heuristics.
|
||||||
|
With these flags, return only the desired information:
|
||||||
|
|
||||||
|
--home Open the home page of project.
|
||||||
|
--list List documentation files only.
|
||||||
|
|
||||||
|
For more information about a rock, see the 'show' command.
|
||||||
|
]]
|
||||||
|
|
||||||
|
local function show_homepage(homepage, name, version)
|
||||||
|
if not homepage then
|
||||||
|
return nil, "No 'homepage' field in rockspec for "..name.." "..version
|
||||||
|
end
|
||||||
|
util.printout("Opening "..homepage.." ...")
|
||||||
|
fs.browser(homepage)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function try_to_open_homepage(name, version)
|
||||||
|
local temp_dir, err = fs.make_temp_dir("doc-"..name.."-"..(version or ""))
|
||||||
|
if not temp_dir then
|
||||||
|
return nil, "Failed creating temporary directory: "..err
|
||||||
|
end
|
||||||
|
util.schedule_function(fs.delete, temp_dir)
|
||||||
|
local ok, err = fs.change_dir(temp_dir)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
local filename, err = download.download("rockspec", name, version)
|
||||||
|
if not filename then return nil, err end
|
||||||
|
local rockspec, err = fetch.load_local_rockspec(filename)
|
||||||
|
if not rockspec then return nil, err end
|
||||||
|
fs.pop_dir()
|
||||||
|
local descript = rockspec.description or {}
|
||||||
|
if not descript.homepage then return nil, "No homepage defined for "..name end
|
||||||
|
return show_homepage(descript.homepage, name, version)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Driver function for "doc" command.
|
||||||
|
-- @param name or nil: an existing package name.
|
||||||
|
-- @param version string or nil: a version may also be passed.
|
||||||
|
-- @return boolean: True if succeeded, nil on errors.
|
||||||
|
function doc.command(flags, name, version)
|
||||||
|
if not name then
|
||||||
|
return nil, "Argument missing. "..util.see_help("doc")
|
||||||
|
end
|
||||||
|
|
||||||
|
name = name:lower()
|
||||||
|
|
||||||
|
local iname, iversion, repo = search.pick_installed_rock(name, version, flags["tree"])
|
||||||
|
if not iname then
|
||||||
|
util.printout(name..(version and " "..version or "").." is not installed. Looking for it in the rocks servers...")
|
||||||
|
return try_to_open_homepage(name, version)
|
||||||
|
end
|
||||||
|
name, version = iname, iversion
|
||||||
|
|
||||||
|
local rockspec, err = fetch.load_local_rockspec(path.rockspec_file(name, version, repo))
|
||||||
|
if not rockspec then return nil,err end
|
||||||
|
local descript = rockspec.description or {}
|
||||||
|
|
||||||
|
if flags["home"] then
|
||||||
|
return show_homepage(descript.homepage, name, version)
|
||||||
|
end
|
||||||
|
|
||||||
|
local directory = path.install_dir(name,version,repo)
|
||||||
|
|
||||||
|
local docdir
|
||||||
|
local directories = { "doc", "docs" }
|
||||||
|
for _, d in ipairs(directories) do
|
||||||
|
local dirname = dir.path(directory, d)
|
||||||
|
if fs.is_dir(dirname) then
|
||||||
|
docdir = dirname
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not docdir then
|
||||||
|
if descript.homepage and not flags["list"] then
|
||||||
|
util.printout("Local documentation directory not found -- opening "..descript.homepage.." ...")
|
||||||
|
fs.browser(descript.homepage)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return nil, "Documentation directory not found for "..name.." "..version
|
||||||
|
end
|
||||||
|
|
||||||
|
docdir = dir.normalize(docdir):gsub("/+", "/")
|
||||||
|
local files = fs.find(docdir)
|
||||||
|
local htmlpatt = "%.html?$"
|
||||||
|
local extensions = { htmlpatt, "%.md$", "%.txt$", "%.textile$", "" }
|
||||||
|
local basenames = { "index", "readme", "manual" }
|
||||||
|
|
||||||
|
local porcelain = flags["porcelain"]
|
||||||
|
if #files > 0 then
|
||||||
|
util.title("Documentation files for "..name.." "..version, porcelain)
|
||||||
|
if porcelain then
|
||||||
|
for _, file in ipairs(files) do
|
||||||
|
util.printout(docdir.."/"..file)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
util.printout(docdir.."/")
|
||||||
|
for _, file in ipairs(files) do
|
||||||
|
util.printout("\t"..file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if flags["list"] then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, extension in ipairs(extensions) do
|
||||||
|
for _, basename in ipairs(basenames) do
|
||||||
|
local filename = basename..extension
|
||||||
|
local found
|
||||||
|
for _, file in ipairs(files) do
|
||||||
|
if file:lower():match(filename) and ((not found) or #file < #found) then
|
||||||
|
found = file
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if found then
|
||||||
|
local pathname = dir.path(docdir, found)
|
||||||
|
util.printout()
|
||||||
|
util.printout("Opening "..pathname.." ...")
|
||||||
|
util.printout()
|
||||||
|
local ok = fs.browser(pathname)
|
||||||
|
if not ok and not pathname:match(htmlpatt) then
|
||||||
|
local fd = io.open(pathname, "r")
|
||||||
|
util.printout(fd:read("*a"))
|
||||||
|
fd:close()
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return doc
|
||||||
109
Utils/luarocks/lua/luarocks/download.lua
Normal file
109
Utils/luarocks/lua/luarocks/download.lua
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
|
||||||
|
--- Module implementing the luarocks "download" command.
|
||||||
|
-- Download a rock from the repository.
|
||||||
|
local download = {}
|
||||||
|
package.loaded["luarocks.download"] = download
|
||||||
|
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
local fetch = require("luarocks.fetch")
|
||||||
|
local search = require("luarocks.search")
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
|
||||||
|
util.add_run_function(download)
|
||||||
|
download.help_summary = "Download a specific rock file from a rocks server."
|
||||||
|
download.help_arguments = "[--all] [--arch=<arch> | --source | --rockspec] [<name> [<version>]]"
|
||||||
|
|
||||||
|
download.help = [[
|
||||||
|
--all Download all files if there are multiple matches.
|
||||||
|
--source Download .src.rock if available.
|
||||||
|
--rockspec Download .rockspec if available.
|
||||||
|
--arch=<arch> Download rock for a specific architecture.
|
||||||
|
]]
|
||||||
|
|
||||||
|
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(), cfg.perm_read)
|
||||||
|
if ok then
|
||||||
|
return pathname
|
||||||
|
else
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return fetch.fetch_url(filename)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function download.download(arch, name, version, all)
|
||||||
|
local query = search.make_query(name, version)
|
||||||
|
if arch then query.arch = arch end
|
||||||
|
local search_err
|
||||||
|
|
||||||
|
if all then
|
||||||
|
if name == "" then query.exact_name = false end
|
||||||
|
local results = search.search_repos(query)
|
||||||
|
local has_result = false
|
||||||
|
local all_ok = true
|
||||||
|
local any_err = ""
|
||||||
|
for name, result in pairs(results) do
|
||||||
|
for version, items in pairs(result) do
|
||||||
|
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_suitable_rock(query)
|
||||||
|
if url then
|
||||||
|
return get_file(url)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil, "Could not find a result named "..name..(version and " "..version or "")..
|
||||||
|
(search_err and ": "..search_err or ".")
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Driver function for the "download" command.
|
||||||
|
-- @param name string: a rock name.
|
||||||
|
-- @param version string or nil: if the name of a package is given, a
|
||||||
|
-- version may also be passed.
|
||||||
|
-- @return boolean or (nil, string): true if successful or nil followed
|
||||||
|
-- by an error message.
|
||||||
|
function download.command(flags, name, version)
|
||||||
|
assert(type(version) == "string" or not version)
|
||||||
|
if type(name) ~= "string" and not flags["all"] then
|
||||||
|
return nil, "Argument missing. "..util.see_help("download")
|
||||||
|
end
|
||||||
|
if not name then name, version = "", "" end
|
||||||
|
|
||||||
|
local arch
|
||||||
|
|
||||||
|
if flags["source"] then
|
||||||
|
arch = "src"
|
||||||
|
elseif flags["rockspec"] then
|
||||||
|
arch = "rockspec"
|
||||||
|
elseif flags["arch"] then
|
||||||
|
arch = flags["arch"]
|
||||||
|
end
|
||||||
|
|
||||||
|
local dl, err = download.download(arch, name:lower(), version, flags["all"])
|
||||||
|
return dl and true, err
|
||||||
|
end
|
||||||
|
|
||||||
|
return download
|
||||||
394
Utils/luarocks/lua/luarocks/fetch.lua
Normal file
394
Utils/luarocks/lua/luarocks/fetch.lua
Normal file
@ -0,0 +1,394 @@
|
|||||||
|
|
||||||
|
--- Functions related to fetching and loading local and remote files.
|
||||||
|
local fetch = {}
|
||||||
|
package.loaded["luarocks.fetch"] = fetch
|
||||||
|
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local type_check = require("luarocks.type_check")
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
local deps = require("luarocks.deps")
|
||||||
|
local persist = require("luarocks.persist")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
|
||||||
|
function fetch.is_basic_protocol(protocol, remote)
|
||||||
|
return protocol == "http" or protocol == "https" or protocol == "ftp" or (not remote and protocol == "file")
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Fetch a local or remote file.
|
||||||
|
-- Make a remote or local URL/pathname local, fetching the file if necessary.
|
||||||
|
-- Other "fetch" and "load" functions use this function to obtain files.
|
||||||
|
-- If a local pathname is given, it is returned as a result.
|
||||||
|
-- @param url string: a local pathname or a remote URL.
|
||||||
|
-- @param filename string or nil: this function attempts to detect the
|
||||||
|
-- resulting local filename of the remote file as the basename of the URL;
|
||||||
|
-- if that is not correct (due to a redirection, for example), the local
|
||||||
|
-- filename can be given explicitly as this second argument.
|
||||||
|
-- @return string or (nil, string, [string]): the absolute local pathname for the
|
||||||
|
-- fetched file, or nil and a message in case of errors, followed by
|
||||||
|
-- an optional error code.
|
||||||
|
function fetch.fetch_url(url, filename, cache)
|
||||||
|
assert(type(url) == "string")
|
||||||
|
assert(type(filename) == "string" or not filename)
|
||||||
|
|
||||||
|
local protocol, pathname = dir.split_url(url)
|
||||||
|
if protocol == "file" then
|
||||||
|
return fs.absolute_name(pathname)
|
||||||
|
elseif fetch.is_basic_protocol(protocol, true) then
|
||||||
|
local ok, name = fs.download(url, filename, cache)
|
||||||
|
if not ok then
|
||||||
|
return nil, "Failed downloading "..url..(filename and " - "..filename or ""), "network"
|
||||||
|
end
|
||||||
|
return name
|
||||||
|
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)
|
||||||
|
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 = fetch.fetch_url(url, filename)
|
||||||
|
fs.pop_dir()
|
||||||
|
if not file then
|
||||||
|
return nil, "Error fetching file: "..err, errcode
|
||||||
|
end
|
||||||
|
return file, temp_dir
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Determine base directory of a fetched URL by extracting its
|
||||||
|
-- archive and looking for a directory in the root.
|
||||||
|
-- @param file string: absolute local pathname of the fetched file
|
||||||
|
-- @param temp_dir string: temporary directory in which URL was fetched.
|
||||||
|
-- @param src_url string: URL to use when inferring base directory.
|
||||||
|
-- @param src_dir string or nil: expected base directory (inferred
|
||||||
|
-- from src_url if not given).
|
||||||
|
-- @return (string, string) or (string, nil) or (nil, string):
|
||||||
|
-- The inferred base directory and the one actually found (which may
|
||||||
|
-- be nil if not found), or nil followed by an error message.
|
||||||
|
-- The inferred dir is returned first to avoid confusion with errors,
|
||||||
|
-- because it is never nil.
|
||||||
|
function fetch.find_base_dir(file, temp_dir, src_url, src_dir)
|
||||||
|
local ok, err = fs.change_dir(temp_dir)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
fs.unpack_archive(file)
|
||||||
|
local inferred_dir = src_dir or fetch.url_to_base_dir(src_url)
|
||||||
|
local found_dir = nil
|
||||||
|
if fs.exists(inferred_dir) then
|
||||||
|
found_dir = inferred_dir
|
||||||
|
else
|
||||||
|
util.printerr("Directory "..inferred_dir.." not found")
|
||||||
|
local files = fs.list_dir()
|
||||||
|
if files then
|
||||||
|
table.sort(files)
|
||||||
|
for i,filename in ipairs(files) do
|
||||||
|
if fs.is_dir(filename) then
|
||||||
|
util.printerr("Found "..filename)
|
||||||
|
found_dir = filename
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
fs.pop_dir()
|
||||||
|
return inferred_dir, found_dir
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Obtain a rock and unpack it.
|
||||||
|
-- If a directory is not given, a temporary directory will be created,
|
||||||
|
-- which will be deleted on program termination.
|
||||||
|
-- @param rock_file string: URL or filename of the rock.
|
||||||
|
-- @param dest string or nil: if given, directory will be used as
|
||||||
|
-- a permanent destination.
|
||||||
|
-- @return string or (nil, string, [string]): the directory containing the contents
|
||||||
|
-- of the unpacked rock.
|
||||||
|
function fetch.fetch_and_unpack_rock(rock_file, dest)
|
||||||
|
assert(type(rock_file) == "string")
|
||||||
|
assert(type(dest) == "string" or not dest)
|
||||||
|
|
||||||
|
local name = dir.base_name(rock_file):match("(.*)%.[^.]*%.rock")
|
||||||
|
|
||||||
|
local rock_file, err, errcode = fetch.fetch_url_at_temp_dir(rock_file,"luarocks-rock-"..name)
|
||||||
|
if not rock_file then
|
||||||
|
return nil, "Could not fetch rock file: " .. err, errcode
|
||||||
|
end
|
||||||
|
|
||||||
|
rock_file = fs.absolute_name(rock_file)
|
||||||
|
local unpack_dir
|
||||||
|
if dest then
|
||||||
|
unpack_dir = dest
|
||||||
|
local ok, err = fs.make_dir(unpack_dir)
|
||||||
|
if not ok then
|
||||||
|
return nil, "Failed unpacking rock file: " .. err
|
||||||
|
end
|
||||||
|
else
|
||||||
|
unpack_dir = fs.make_temp_dir(name)
|
||||||
|
end
|
||||||
|
if not dest then
|
||||||
|
util.schedule_function(fs.delete, unpack_dir)
|
||||||
|
end
|
||||||
|
local ok, err = fs.change_dir(unpack_dir)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
ok = fs.unzip(rock_file)
|
||||||
|
if not ok then
|
||||||
|
return nil, "Failed unpacking rock file: " .. rock_file
|
||||||
|
end
|
||||||
|
fs.pop_dir()
|
||||||
|
return unpack_dir
|
||||||
|
end
|
||||||
|
|
||||||
|
function fetch.url_to_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
|
||||||
|
|
||||||
|
--- Back-end function that actually loads the local rockspec.
|
||||||
|
-- Performs some validation and postprocessing of the rockspec contents.
|
||||||
|
-- @param filename string: The local filename of the rockspec file.
|
||||||
|
-- @param quick boolean: if true, skips some steps when loading
|
||||||
|
-- rockspec.
|
||||||
|
-- @return table or (nil, string): A table representing the rockspec
|
||||||
|
-- or nil followed by an error message.
|
||||||
|
function fetch.load_local_rockspec(filename, quick)
|
||||||
|
assert(type(filename) == "string")
|
||||||
|
filename = fs.absolute_name(filename)
|
||||||
|
local rockspec, err = persist.load_into_table(filename)
|
||||||
|
if not rockspec then
|
||||||
|
return nil, "Could not load rockspec file "..filename.." ("..err..")"
|
||||||
|
end
|
||||||
|
if cfg.branch and (type(rockspec.source) == "table") then
|
||||||
|
rockspec.source.branch = cfg.branch
|
||||||
|
end
|
||||||
|
local globals = err
|
||||||
|
|
||||||
|
if rockspec.rockspec_format then
|
||||||
|
if deps.compare_versions(rockspec.rockspec_format, type_check.rockspec_format) then
|
||||||
|
return nil, "Rockspec format "..rockspec.rockspec_format.." is not supported, please upgrade LuaRocks."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not quick then
|
||||||
|
local ok, err = type_check.type_check_rockspec(rockspec, globals)
|
||||||
|
if not ok then
|
||||||
|
return nil, filename..": "..err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
util.platform_overrides(rockspec.build)
|
||||||
|
util.platform_overrides(rockspec.dependencies)
|
||||||
|
util.platform_overrides(rockspec.external_dependencies)
|
||||||
|
util.platform_overrides(rockspec.source)
|
||||||
|
util.platform_overrides(rockspec.hooks)
|
||||||
|
|
||||||
|
local basename = dir.base_name(filename)
|
||||||
|
if basename == "rockspec" then
|
||||||
|
rockspec.name = rockspec.package:lower()
|
||||||
|
else
|
||||||
|
rockspec.name = basename:match("(.*)-[^-]*-[0-9]*")
|
||||||
|
if not rockspec.name then
|
||||||
|
return nil, "Expected filename in format 'name-version-revision.rockspec'."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local protocol, pathname = dir.split_url(rockspec.source.url)
|
||||||
|
if fetch.is_basic_protocol(protocol) then
|
||||||
|
rockspec.source.file = rockspec.source.file or dir.base_name(rockspec.source.url)
|
||||||
|
end
|
||||||
|
rockspec.source.protocol, rockspec.source.pathname = protocol, pathname
|
||||||
|
|
||||||
|
-- Temporary compatibility
|
||||||
|
if rockspec.source.cvs_module then rockspec.source.module = rockspec.source.cvs_module end
|
||||||
|
if rockspec.source.cvs_tag then rockspec.source.tag = rockspec.source.cvs_tag end
|
||||||
|
|
||||||
|
local name_version = rockspec.package:lower() .. "-" .. rockspec.version
|
||||||
|
if basename ~= "rockspec" and basename ~= name_version .. ".rockspec" then
|
||||||
|
return nil, "Inconsistency between rockspec filename ("..basename..") and its contents ("..name_version..".rockspec)."
|
||||||
|
end
|
||||||
|
|
||||||
|
rockspec.local_filename = filename
|
||||||
|
local filebase = rockspec.source.file or rockspec.source.url
|
||||||
|
local base = fetch.url_to_base_dir(filebase)
|
||||||
|
rockspec.source.dir = rockspec.source.dir
|
||||||
|
or rockspec.source.module
|
||||||
|
or ((filebase:match("%.lua$") or filebase:match("%.c$")) and ".")
|
||||||
|
or base
|
||||||
|
if rockspec.dependencies then
|
||||||
|
for i = 1, #rockspec.dependencies do
|
||||||
|
local parsed, err = deps.parse_dep(rockspec.dependencies[i])
|
||||||
|
if not parsed then
|
||||||
|
return nil, "Parse error processing dependency '"..rockspec.dependencies[i].."': "..tostring(err)
|
||||||
|
end
|
||||||
|
rockspec.dependencies[i] = parsed
|
||||||
|
end
|
||||||
|
else
|
||||||
|
rockspec.dependencies = {}
|
||||||
|
end
|
||||||
|
if not quick then
|
||||||
|
path.configure_paths(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.
|
||||||
|
-- @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(filename, location)
|
||||||
|
assert(type(filename) == "string")
|
||||||
|
|
||||||
|
local name
|
||||||
|
local basename = dir.base_name(filename)
|
||||||
|
if basename == "rockspec" then
|
||||||
|
name = "rockspec"
|
||||||
|
else
|
||||||
|
name = basename:match("(.*)%.rockspec")
|
||||||
|
if not name then
|
||||||
|
return nil, "Filename '"..filename.."' does not look like a rockspec."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local 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(filename)
|
||||||
|
fs.pop_dir()
|
||||||
|
else
|
||||||
|
filename, err, errcode = fetch.fetch_url_at_temp_dir(filename,"luarocks-rockspec-"..name)
|
||||||
|
end
|
||||||
|
if not filename then
|
||||||
|
return nil, err, errcode
|
||||||
|
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(type(rockspec) == "table")
|
||||||
|
assert(type(extract) == "boolean")
|
||||||
|
assert(type(dest_dir) == "string" or not dest_dir)
|
||||||
|
|
||||||
|
local url = rockspec.source.url
|
||||||
|
local name = rockspec.name.."-"..rockspec.version
|
||||||
|
local filename = rockspec.source.file
|
||||||
|
local source_file, store_dir
|
||||||
|
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
|
||||||
|
return nil, "Directory "..rockspec.source.dir.." not found inside archive "..rockspec.source.file, "source.dir", source_file, store_dir
|
||||||
|
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(type(rockspec) == "table")
|
||||||
|
assert(type(extract) == "boolean")
|
||||||
|
assert(type(dest_dir) == "string" or not dest_dir)
|
||||||
|
|
||||||
|
local protocol = rockspec.source.protocol
|
||||||
|
local ok, proto
|
||||||
|
if fetch.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
|
||||||
55
Utils/luarocks/lua/luarocks/fetch/cvs.lua
Normal file
55
Utils/luarocks/lua/luarocks/fetch/cvs.lua
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
|
||||||
|
--- 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(type(rockspec) == "table")
|
||||||
|
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
|
||||||
92
Utils/luarocks/lua/luarocks/fetch/git.lua
Normal file
92
Utils/luarocks/lua/luarocks/fetch/git.lua
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
|
||||||
|
--- 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 util = require("luarocks.util")
|
||||||
|
|
||||||
|
--- 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.
|
||||||
|
-- @return boolean: Whether Git can clone by tag.
|
||||||
|
local function git_can_clone_by_tag(git_cmd)
|
||||||
|
local version_string = io.popen(fs.Q(git_cmd)..' --version'):read()
|
||||||
|
local major, minor, tiny = version_string:match('(%d-)%.(%d+)%.?(%d*)')
|
||||||
|
major, minor, tiny = tonumber(major), tonumber(minor), tonumber(tiny) or 0
|
||||||
|
local value = major > 1 or (major == 1 and (minor > 7 or (minor == 7 and tiny >= 10)))
|
||||||
|
git_can_clone_by_tag = function() return value end
|
||||||
|
return value
|
||||||
|
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(type(rockspec) == "table")
|
||||||
|
assert(type(dest_dir) == "string" or not dest_dir)
|
||||||
|
|
||||||
|
local git_cmd = rockspec.variables.GIT
|
||||||
|
local name_version = rockspec.name .. "-" .. rockspec.version
|
||||||
|
local module = dir.base_name(rockspec.source.url)
|
||||||
|
-- Strip off .git from base name if present
|
||||||
|
module = module:gsub("%.git$", "")
|
||||||
|
|
||||||
|
local 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
|
||||||
|
local checkout_command = {fs.Q(git_cmd), "checkout", tag_or_branch}
|
||||||
|
if not fs.execute(unpack(checkout_command)) then
|
||||||
|
return nil, 'Failed to check out the "' .. tag_or_branch ..'" tag or branch.'
|
||||||
|
end
|
||||||
|
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
|
||||||
19
Utils/luarocks/lua/luarocks/fetch/git_file.lua
Normal file
19
Utils/luarocks/lua/luarocks/fetch/git_file.lua
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
--- 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
|
||||||
26
Utils/luarocks/lua/luarocks/fetch/git_http.lua
Normal file
26
Utils/luarocks/lua/luarocks/fetch/git_http.lua
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
--- 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
|
||||||
7
Utils/luarocks/lua/luarocks/fetch/git_https.lua
Normal file
7
Utils/luarocks/lua/luarocks/fetch/git_https.lua
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
--- 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"
|
||||||
32
Utils/luarocks/lua/luarocks/fetch/git_ssh.lua
Normal file
32
Utils/luarocks/lua/luarocks/fetch/git_ssh.lua
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
--- 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
|
||||||
65
Utils/luarocks/lua/luarocks/fetch/hg.lua
Normal file
65
Utils/luarocks/lua/luarocks/fetch/hg.lua
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
|
||||||
|
--- 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(type(rockspec) == "table")
|
||||||
|
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
|
||||||
24
Utils/luarocks/lua/luarocks/fetch/hg_http.lua
Normal file
24
Utils/luarocks/lua/luarocks/fetch/hg_http.lua
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
--- 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
|
||||||
8
Utils/luarocks/lua/luarocks/fetch/hg_https.lua
Normal file
8
Utils/luarocks/lua/luarocks/fetch/hg_https.lua
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
--- 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"
|
||||||
8
Utils/luarocks/lua/luarocks/fetch/hg_ssh.lua
Normal file
8
Utils/luarocks/lua/luarocks/fetch/hg_ssh.lua
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
--- 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"
|
||||||
44
Utils/luarocks/lua/luarocks/fetch/sscm.lua
Normal file
44
Utils/luarocks/lua/luarocks/fetch/sscm.lua
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
--- 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(type(rockspec) == "table")
|
||||||
|
assert(type(dest_dir) == "string" or not dest_dir)
|
||||||
|
|
||||||
|
local sscm_cmd = rockspec.variables.SSCM
|
||||||
|
local module = rockspec.source.module or dir.base_name(rockspec.source.url)
|
||||||
|
local branch, repository = string.match(rockspec.source.pathname, "^([^/]*)/(.*)")
|
||||||
|
if not branch or not repository then
|
||||||
|
return nil, "Error retrieving branch and repository from rockspec."
|
||||||
|
end
|
||||||
|
-- Search for working directory.
|
||||||
|
local working_dir
|
||||||
|
local tmp = io.popen(string.format(sscm_cmd..[[ property "/" -d -b%s -p%s]], branch, repository))
|
||||||
|
for line in tmp:lines() do
|
||||||
|
--%c because a chr(13) comes in the end.
|
||||||
|
working_dir = string.match(line, "Working directory:[%s]*(.*)%c$")
|
||||||
|
if working_dir then break end
|
||||||
|
end
|
||||||
|
tmp:close()
|
||||||
|
if not working_dir then
|
||||||
|
return nil, "Error retrieving working directory from SSCM."
|
||||||
|
end
|
||||||
|
if not fs.execute(sscm_cmd, "get", "*", "-e" , "-r", "-b"..branch, "-p"..repository, "-tmodify", "-wreplace") then
|
||||||
|
return nil, "Failed fetching files from SSCM."
|
||||||
|
end
|
||||||
|
-- FIXME: This function does not honor the dest_dir parameter.
|
||||||
|
return module, working_dir
|
||||||
|
end
|
||||||
|
|
||||||
|
return sscm
|
||||||
64
Utils/luarocks/lua/luarocks/fetch/svn.lua
Normal file
64
Utils/luarocks/lua/luarocks/fetch/svn.lua
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
|
||||||
|
--- 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(type(rockspec) == "table")
|
||||||
|
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, "--version", "Subversion")
|
||||||
|
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
|
||||||
76
Utils/luarocks/lua/luarocks/fs.lua
Normal file
76
Utils/luarocks/lua/luarocks/fs.lua
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
|
||||||
|
--- 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 = {}
|
||||||
|
package.loaded["luarocks.fs"] = fs
|
||||||
|
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
|
||||||
|
local pack = table.pack or function(...) return { n = select("#", ...), ... } end
|
||||||
|
local unpack = table.unpack or unpack
|
||||||
|
|
||||||
|
local old_popen, old_exec
|
||||||
|
fs.verbose = function() -- patch io.popen and os.execute to display commands in verbose mode
|
||||||
|
if old_popen or old_exec then return end
|
||||||
|
old_popen = io.popen
|
||||||
|
io.popen = function(one, two)
|
||||||
|
if two == nil then
|
||||||
|
print("\nio.popen: ", one)
|
||||||
|
else
|
||||||
|
print("\nio.popen: ", one, "Mode:", two)
|
||||||
|
end
|
||||||
|
return old_popen(one, two)
|
||||||
|
end
|
||||||
|
|
||||||
|
old_exec = os.execute
|
||||||
|
os.execute = function(cmd)
|
||||||
|
-- redact api keys if present
|
||||||
|
print("\nos.execute: ", (cmd:gsub("(/api/[^/]+/)([^/]+)/", function(cap, key) return cap.."<redacted>/" end)) )
|
||||||
|
local code = pack(old_exec(cmd))
|
||||||
|
print("Results: "..tostring(code.n))
|
||||||
|
for i = 1,code.n do
|
||||||
|
print(" "..tostring(i).." ("..type(code[i]).."): "..tostring(code[i]))
|
||||||
|
end
|
||||||
|
return unpack(code, 1, code.n)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if cfg.verbose then fs.verbose() end
|
||||||
|
|
||||||
|
local function load_fns(fs_table)
|
||||||
|
for name, fn in pairs(fs_table) do
|
||||||
|
if not fs[name] then
|
||||||
|
fs[name] = fn
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Load platform-specific functions
|
||||||
|
local loaded_platform = nil
|
||||||
|
for _, platform in ipairs(cfg.platforms) do
|
||||||
|
local ok, fs_plat = pcall(require, "luarocks.fs."..platform)
|
||||||
|
if ok and fs_plat then
|
||||||
|
loaded_platform = platform
|
||||||
|
load_fns(fs_plat)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Load platform-independent pure-Lua functionality
|
||||||
|
local fs_lua = require("luarocks.fs.lua")
|
||||||
|
load_fns(fs_lua)
|
||||||
|
|
||||||
|
-- Load platform-specific fallbacks for missing Lua modules
|
||||||
|
local ok, fs_plat_tools = pcall(require, "luarocks.fs."..loaded_platform..".tools")
|
||||||
|
if ok and fs_plat_tools then
|
||||||
|
load_fns(fs_plat_tools)
|
||||||
|
load_fns(require("luarocks.fs.tools"))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return fs
|
||||||
873
Utils/luarocks/lua/luarocks/fs/lua.lua
Normal file
873
Utils/luarocks/lua/luarocks/fs/lua.lua
Normal file
@ -0,0 +1,873 @@
|
|||||||
|
|
||||||
|
--- Native Lua implementation of filesystem and platform abstractions,
|
||||||
|
-- using LuaFileSystem, LZLib, MD5 and LuaCurl.
|
||||||
|
-- module("luarocks.fs.lua")
|
||||||
|
local fs_lua = {}
|
||||||
|
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
|
||||||
|
local socket_ok, zip_ok, unzip_ok, lfs_ok, md5_ok, posix_ok, _
|
||||||
|
local http, ftp, lrzip, luazip, lfs, md5, posix
|
||||||
|
|
||||||
|
if cfg.fs_use_modules then
|
||||||
|
socket_ok, http = pcall(require, "socket.http")
|
||||||
|
_, ftp = pcall(require, "socket.ftp")
|
||||||
|
zip_ok, lrzip = pcall(require, "luarocks.tools.zip")
|
||||||
|
unzip_ok, luazip = pcall(require, "zip"); _G.zip = nil
|
||||||
|
lfs_ok, lfs = pcall(require, "lfs")
|
||||||
|
md5_ok, md5 = pcall(require, "md5")
|
||||||
|
posix_ok, posix = pcall(require, "posix")
|
||||||
|
end
|
||||||
|
|
||||||
|
local patch = require("luarocks.tools.patch")
|
||||||
|
|
||||||
|
local dir_stack = {}
|
||||||
|
|
||||||
|
local dir_separator = "/"
|
||||||
|
|
||||||
|
--- 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 fs_lua.is_writable(file)
|
||||||
|
assert(file)
|
||||||
|
file = dir.normalize(file)
|
||||||
|
local result
|
||||||
|
if fs.is_dir(file) then
|
||||||
|
local file2 = dir.path(file, '.tmpluarockstestwritable')
|
||||||
|
local fh = io.open(file2, 'wb')
|
||||||
|
result = fh ~= nil
|
||||||
|
if fh then fh:close() end
|
||||||
|
os.remove(file2)
|
||||||
|
else
|
||||||
|
local fh = io.open(file, 'r+b')
|
||||||
|
result = fh ~= nil
|
||||||
|
if fh then fh:close() end
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
local function quote_args(command, ...)
|
||||||
|
local out = { command }
|
||||||
|
for _, arg in ipairs({...}) do
|
||||||
|
assert(type(arg) == "string")
|
||||||
|
out[#out+1] = fs.Q(arg)
|
||||||
|
end
|
||||||
|
return table.concat(out, " ")
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Run the given command, quoting its arguments.
|
||||||
|
-- The command is executed in the current directory in the dir stack.
|
||||||
|
-- @param command string: The command to be executed. No quoting/escaping
|
||||||
|
-- is applied.
|
||||||
|
-- @param ... Strings containing additional arguments, which are quoted.
|
||||||
|
-- @return boolean: true if command succeeds (status code 0), false
|
||||||
|
-- otherwise.
|
||||||
|
function fs_lua.execute(command, ...)
|
||||||
|
assert(type(command) == "string")
|
||||||
|
return fs.execute_string(quote_args(command, ...))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Run the given command, quoting its arguments, silencing its output.
|
||||||
|
-- The command is executed in the current directory in the dir stack.
|
||||||
|
-- Silencing is omitted if 'verbose' mode is enabled.
|
||||||
|
-- @param command string: The command to be executed. No quoting/escaping
|
||||||
|
-- is applied.
|
||||||
|
-- @param ... Strings containing additional arguments, which will be quoted.
|
||||||
|
-- @return boolean: true if command succeeds (status code 0), false
|
||||||
|
-- otherwise.
|
||||||
|
function fs_lua.execute_quiet(command, ...)
|
||||||
|
assert(type(command) == "string")
|
||||||
|
if cfg.verbose then -- omit silencing output
|
||||||
|
return fs.execute_string(quote_args(command, ...))
|
||||||
|
else
|
||||||
|
return fs.execute_string(fs.quiet(quote_args(command, ...)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Checks if the given tool is available.
|
||||||
|
-- The tool is executed using a flag, usually just to ask its version.
|
||||||
|
-- @param tool_cmd string: The command to be used to check the tool's presence (e.g. hg in case of Mercurial)
|
||||||
|
-- @param tool_name string: The actual name of the tool (e.g. Mercurial)
|
||||||
|
-- @param arg string: The flag to pass to the tool. '--version' by default.
|
||||||
|
function fs_lua.is_tool_available(tool_cmd, tool_name, arg)
|
||||||
|
assert(type(tool_cmd) == "string")
|
||||||
|
assert(type(tool_name) == "string")
|
||||||
|
|
||||||
|
arg = arg or "--version"
|
||||||
|
assert(type(arg) == "string")
|
||||||
|
|
||||||
|
if not fs.execute_quiet(fs.Q(tool_cmd), arg) then
|
||||||
|
local msg = "'%s' program not found. Make sure %s is installed and is available in your PATH " ..
|
||||||
|
"(or you may want to edit the 'variables.%s' value in file '%s')"
|
||||||
|
return nil, msg:format(tool_cmd, tool_name, tool_name:upper(), cfg.which_config().nearest)
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check the MD5 checksum for a file.
|
||||||
|
-- @param file string: The file to be checked.
|
||||||
|
-- @param md5sum string: The string with the expected MD5 checksum.
|
||||||
|
-- @return boolean: true if the MD5 checksum for 'file' equals 'md5sum', false + msg if not
|
||||||
|
-- or if it could not perform the check for any reason.
|
||||||
|
function fs_lua.check_md5(file, md5sum)
|
||||||
|
file = dir.normalize(file)
|
||||||
|
local computed, msg = fs.get_md5(file)
|
||||||
|
if not computed then
|
||||||
|
return false, msg
|
||||||
|
end
|
||||||
|
if computed:match("^"..md5sum) then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false, "Mismatch MD5 hash for file "..file
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- List the contents of a directory.
|
||||||
|
-- @param at string or nil: directory to list (will be the current
|
||||||
|
-- directory if none is given).
|
||||||
|
-- @return table: an array of strings with the filenames representing
|
||||||
|
-- the contents of a directory.
|
||||||
|
function fs_lua.list_dir(at)
|
||||||
|
local result = {}
|
||||||
|
for file in fs.dir(at) do
|
||||||
|
result[#result+1] = file
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Iterate over the contents of a directory.
|
||||||
|
-- @param at string or nil: directory to list (will be the current
|
||||||
|
-- directory if none is given).
|
||||||
|
-- @return function: an iterator function suitable for use with
|
||||||
|
-- the for statement.
|
||||||
|
function fs_lua.dir(at)
|
||||||
|
if not at then
|
||||||
|
at = fs.current_dir()
|
||||||
|
end
|
||||||
|
at = dir.normalize(at)
|
||||||
|
if not fs.is_dir(at) then
|
||||||
|
return function() end
|
||||||
|
end
|
||||||
|
return coroutine.wrap(function() fs.dir_iterator(at) end)
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
-- LuaFileSystem functions
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
if lfs_ok then
|
||||||
|
|
||||||
|
--- Run the given command.
|
||||||
|
-- The command is executed in the current directory in the dir stack.
|
||||||
|
-- @param cmd string: No quoting/escaping is applied to the command.
|
||||||
|
-- @return boolean: true if command succeeds (status code 0), false
|
||||||
|
-- otherwise.
|
||||||
|
function fs_lua.execute_string(cmd)
|
||||||
|
local code = os.execute(cmd)
|
||||||
|
return (code == 0 or code == true)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Obtain current directory.
|
||||||
|
-- Uses the module's internal dir stack.
|
||||||
|
-- @return string: the absolute pathname of the current directory.
|
||||||
|
function fs_lua.current_dir()
|
||||||
|
return lfs.currentdir()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Change the current directory.
|
||||||
|
-- Uses the module's internal dir stack. This does not have exact
|
||||||
|
-- semantics of chdir, as it does not handle errors the same way,
|
||||||
|
-- but works well for our purposes for now.
|
||||||
|
-- @param d string: The directory to switch to.
|
||||||
|
function fs_lua.change_dir(d)
|
||||||
|
table.insert(dir_stack, lfs.currentdir())
|
||||||
|
d = dir.normalize(d)
|
||||||
|
return lfs.chdir(d)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Change directory to root.
|
||||||
|
-- Allows leaving a directory (e.g. for deleting it) in
|
||||||
|
-- a crossplatform way.
|
||||||
|
function fs_lua.change_dir_to_root()
|
||||||
|
local current = lfs.currentdir()
|
||||||
|
if not current or current == "" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
table.insert(dir_stack, current)
|
||||||
|
lfs.chdir("/") -- works on Windows too
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Change working directory to the previous in the dir stack.
|
||||||
|
-- @return true if a pop ocurred, false if the stack was empty.
|
||||||
|
function fs_lua.pop_dir()
|
||||||
|
local d = table.remove(dir_stack)
|
||||||
|
if d then
|
||||||
|
lfs.chdir(d)
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a directory if it does not already exist.
|
||||||
|
-- If any of the higher levels in the path name do not exist
|
||||||
|
-- too, they are created as well.
|
||||||
|
-- @param directory string: pathname of directory to create.
|
||||||
|
-- @return boolean or (boolean, string): true on success or (false, error message) on failure.
|
||||||
|
function fs_lua.make_dir(directory)
|
||||||
|
assert(type(directory) == "string")
|
||||||
|
directory = dir.normalize(directory)
|
||||||
|
local path = nil
|
||||||
|
if directory:sub(2, 2) == ":" then
|
||||||
|
path = directory:sub(1, 2)
|
||||||
|
directory = directory:sub(4)
|
||||||
|
else
|
||||||
|
if directory:match("^/") then
|
||||||
|
path = ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for d in directory:gmatch("([^"..dir.separator.."]+)"..dir.separator.."*") do
|
||||||
|
path = path and path .. dir.separator .. d or d
|
||||||
|
local mode = lfs.attributes(path, "mode")
|
||||||
|
if not mode then
|
||||||
|
local ok, err = lfs.mkdir(path)
|
||||||
|
if not ok then
|
||||||
|
return false, err
|
||||||
|
end
|
||||||
|
ok, err = fs.chmod(path, cfg.perm_exec)
|
||||||
|
if not ok then
|
||||||
|
return false, err
|
||||||
|
end
|
||||||
|
elseif mode ~= "directory" then
|
||||||
|
return false, path.." is not a directory"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove a directory if it is empty.
|
||||||
|
-- Does not return errors (for example, if directory is not empty or
|
||||||
|
-- if already does not exist)
|
||||||
|
-- @param d string: pathname of directory to remove.
|
||||||
|
function fs_lua.remove_dir_if_empty(d)
|
||||||
|
assert(d)
|
||||||
|
d = dir.normalize(d)
|
||||||
|
lfs.rmdir(d)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove a directory if it is empty.
|
||||||
|
-- Does not return errors (for example, if directory is not empty or
|
||||||
|
-- if already does not exist)
|
||||||
|
-- @param d string: pathname of directory to remove.
|
||||||
|
function fs_lua.remove_dir_tree_if_empty(d)
|
||||||
|
assert(d)
|
||||||
|
d = dir.normalize(d)
|
||||||
|
for i=1,10 do
|
||||||
|
lfs.rmdir(d)
|
||||||
|
d = dir.dir_name(d)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Copy a file.
|
||||||
|
-- @param src string: Pathname of source
|
||||||
|
-- @param dest string: Pathname of destination
|
||||||
|
-- @param perms string or nil: Permissions for destination file,
|
||||||
|
-- or nil to use the source filename permissions
|
||||||
|
-- @return boolean or (boolean, string): true on success, false on failure,
|
||||||
|
-- plus an error message.
|
||||||
|
function fs_lua.copy(src, dest, perms)
|
||||||
|
assert(src and dest)
|
||||||
|
src = dir.normalize(src)
|
||||||
|
dest = dir.normalize(dest)
|
||||||
|
local destmode = lfs.attributes(dest, "mode")
|
||||||
|
if destmode == "directory" then
|
||||||
|
dest = dir.path(dest, dir.base_name(src))
|
||||||
|
end
|
||||||
|
if not perms then perms = fs.get_permissions(src) end
|
||||||
|
local src_h, err = io.open(src, "rb")
|
||||||
|
if not src_h then return nil, err end
|
||||||
|
local dest_h, err = io.open(dest, "w+b")
|
||||||
|
if not dest_h then src_h:close() return nil, err end
|
||||||
|
while true do
|
||||||
|
local block = src_h:read(8192)
|
||||||
|
if not block then break end
|
||||||
|
dest_h:write(block)
|
||||||
|
end
|
||||||
|
src_h:close()
|
||||||
|
dest_h:close()
|
||||||
|
fs.chmod(dest, perms)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Implementation function for recursive copy of directory contents.
|
||||||
|
-- Assumes paths are normalized.
|
||||||
|
-- @param src string: Pathname of source
|
||||||
|
-- @param dest string: Pathname of destination
|
||||||
|
-- @param perms string or nil: Optional permissions.
|
||||||
|
-- If not given, permissions of the source are copied over to the destination.
|
||||||
|
-- @return boolean or (boolean, string): true on success, false on failure
|
||||||
|
local function recursive_copy(src, dest, perms)
|
||||||
|
local srcmode = lfs.attributes(src, "mode")
|
||||||
|
|
||||||
|
if srcmode == "file" then
|
||||||
|
local ok = fs.copy(src, dest, perms)
|
||||||
|
if not ok then return false end
|
||||||
|
elseif srcmode == "directory" then
|
||||||
|
local subdir = dir.path(dest, dir.base_name(src))
|
||||||
|
local ok, err = fs.make_dir(subdir)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
for file in lfs.dir(src) do
|
||||||
|
if file ~= "." and file ~= ".." then
|
||||||
|
local ok = recursive_copy(dir.path(src, file), subdir, perms)
|
||||||
|
if not ok then return false end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Recursively copy the contents of a directory.
|
||||||
|
-- @param src string: Pathname of source
|
||||||
|
-- @param dest string: Pathname of destination
|
||||||
|
-- @param perms string or nil: Optional permissions.
|
||||||
|
-- @return boolean or (boolean, string): true on success, false on failure,
|
||||||
|
-- plus an error message.
|
||||||
|
function fs_lua.copy_contents(src, dest, perms)
|
||||||
|
assert(src and dest)
|
||||||
|
src = dir.normalize(src)
|
||||||
|
dest = dir.normalize(dest)
|
||||||
|
assert(lfs.attributes(src, "mode") == "directory")
|
||||||
|
|
||||||
|
for file in lfs.dir(src) do
|
||||||
|
if file ~= "." and file ~= ".." then
|
||||||
|
local ok = recursive_copy(dir.path(src, file), dest, perms)
|
||||||
|
if not ok then
|
||||||
|
return false, "Failed copying "..src.." to "..dest
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Implementation function for recursive removal of directories.
|
||||||
|
-- Assumes paths are normalized.
|
||||||
|
-- @param name string: Pathname of file
|
||||||
|
-- @return boolean or (boolean, string): true on success,
|
||||||
|
-- or nil and an error message on failure.
|
||||||
|
local function recursive_delete(name)
|
||||||
|
local ok = os.remove(name)
|
||||||
|
if ok then return true end
|
||||||
|
local pok, ok, err = pcall(function()
|
||||||
|
for file in lfs.dir(name) do
|
||||||
|
if file ~= "." and file ~= ".." then
|
||||||
|
local ok, err = recursive_delete(dir.path(name, file))
|
||||||
|
if not ok then return nil, err end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local ok, err = lfs.rmdir(name)
|
||||||
|
return ok, (not ok) and err
|
||||||
|
end)
|
||||||
|
if pok then
|
||||||
|
return ok, err
|
||||||
|
else
|
||||||
|
return pok, ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Delete a file or a directory and all its contents.
|
||||||
|
-- @param name string: Pathname of source
|
||||||
|
-- @return nil
|
||||||
|
function fs_lua.delete(name)
|
||||||
|
name = dir.normalize(name)
|
||||||
|
recursive_delete(name)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Internal implementation function for fs.dir.
|
||||||
|
-- Yields a filename on each iteration.
|
||||||
|
-- @param at string: directory to list
|
||||||
|
-- @return nil
|
||||||
|
function fs_lua.dir_iterator(at)
|
||||||
|
for file in lfs.dir(at) do
|
||||||
|
if file ~= "." and file ~= ".." then
|
||||||
|
coroutine.yield(file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Implementation function for recursive find.
|
||||||
|
-- Assumes paths are normalized.
|
||||||
|
-- @param cwd string: Current working directory in recursion.
|
||||||
|
-- @param prefix string: Auxiliary prefix string to form pathname.
|
||||||
|
-- @param result table: Array of strings where results are collected.
|
||||||
|
local function recursive_find(cwd, prefix, result)
|
||||||
|
for file in lfs.dir(cwd) do
|
||||||
|
if file ~= "." and file ~= ".." then
|
||||||
|
local item = prefix .. file
|
||||||
|
table.insert(result, item)
|
||||||
|
local pathname = dir.path(cwd, file)
|
||||||
|
if lfs.attributes(pathname, "mode") == "directory" then
|
||||||
|
recursive_find(pathname, item..dir_separator, result)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Recursively scan the contents of a directory.
|
||||||
|
-- @param at string or nil: directory to scan (will be the current
|
||||||
|
-- directory if none is given).
|
||||||
|
-- @return table: an array of strings with the filenames representing
|
||||||
|
-- the contents of a directory.
|
||||||
|
function fs_lua.find(at)
|
||||||
|
assert(type(at) == "string" or not at)
|
||||||
|
if not at then
|
||||||
|
at = fs.current_dir()
|
||||||
|
end
|
||||||
|
at = dir.normalize(at)
|
||||||
|
if not fs.is_dir(at) then
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
local result = {}
|
||||||
|
recursive_find(at, "", result)
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Test for existance of a file.
|
||||||
|
-- @param file string: filename to test
|
||||||
|
-- @return boolean: true if file exists, false otherwise.
|
||||||
|
function fs_lua.exists(file)
|
||||||
|
assert(file)
|
||||||
|
file = dir.normalize(file)
|
||||||
|
return type(lfs.attributes(file)) == "table"
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Test is pathname is a directory.
|
||||||
|
-- @param file string: pathname to test
|
||||||
|
-- @return boolean: true if it is a directory, false otherwise.
|
||||||
|
function fs_lua.is_dir(file)
|
||||||
|
assert(file)
|
||||||
|
file = dir.normalize(file)
|
||||||
|
return lfs.attributes(file, "mode") == "directory"
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Test is pathname is a regular file.
|
||||||
|
-- @param file string: pathname to test
|
||||||
|
-- @return boolean: true if it is a file, false otherwise.
|
||||||
|
function fs_lua.is_file(file)
|
||||||
|
assert(file)
|
||||||
|
file = dir.normalize(file)
|
||||||
|
return lfs.attributes(file, "mode") == "file"
|
||||||
|
end
|
||||||
|
|
||||||
|
function fs_lua.set_time(file, time)
|
||||||
|
file = dir.normalize(file)
|
||||||
|
return lfs.touch(file, time)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
-- LuaZip functions
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
if zip_ok then
|
||||||
|
|
||||||
|
function fs_lua.zip(zipfile, ...)
|
||||||
|
return lrzip.zip(zipfile, ...)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
if unzip_ok then
|
||||||
|
--- Uncompress files from a .zip archive.
|
||||||
|
-- @param zipfile string: pathname of .zip archive to be extracted.
|
||||||
|
-- @return boolean: true on success, false on failure.
|
||||||
|
function fs_lua.unzip(zipfile)
|
||||||
|
local zipfile, err = luazip.open(zipfile)
|
||||||
|
if not zipfile then return nil, err end
|
||||||
|
local files = zipfile:files()
|
||||||
|
local file = files()
|
||||||
|
repeat
|
||||||
|
if file.filename:sub(#file.filename) == "/" then
|
||||||
|
local ok, err = fs.make_dir(dir.path(fs.current_dir(), file.filename))
|
||||||
|
if not ok then return nil, err end
|
||||||
|
else
|
||||||
|
local base = dir.dir_name(file.filename)
|
||||||
|
if base ~= "" then
|
||||||
|
base = dir.path(fs.current_dir(), base)
|
||||||
|
if not fs.is_dir(base) then
|
||||||
|
local ok, err = fs.make_dir(base)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local rf, err = zipfile:open(file.filename)
|
||||||
|
if not rf then zipfile:close(); return nil, err end
|
||||||
|
local contents = rf:read("*a")
|
||||||
|
rf:close()
|
||||||
|
local wf, err = io.open(dir.path(fs.current_dir(), file.filename), "wb")
|
||||||
|
if not wf then zipfile:close(); return nil, err end
|
||||||
|
wf:write(contents)
|
||||||
|
wf:close()
|
||||||
|
end
|
||||||
|
file = files()
|
||||||
|
until not file
|
||||||
|
zipfile:close()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
-- LuaSocket functions
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
if socket_ok then
|
||||||
|
|
||||||
|
local ltn12 = require("ltn12")
|
||||||
|
local luasec_ok, https = pcall(require, "ssl.https")
|
||||||
|
|
||||||
|
local redirect_protocols = {
|
||||||
|
http = http,
|
||||||
|
https = luasec_ok and https,
|
||||||
|
}
|
||||||
|
|
||||||
|
local function request(url, method, http, loop_control)
|
||||||
|
local result = {}
|
||||||
|
|
||||||
|
local proxy = cfg.http_proxy
|
||||||
|
if type(proxy) ~= "string" then proxy = nil end
|
||||||
|
-- LuaSocket's http.request crashes when given URLs missing the scheme part.
|
||||||
|
if proxy and not proxy:find("://") then
|
||||||
|
proxy = "http://" .. proxy
|
||||||
|
end
|
||||||
|
|
||||||
|
if cfg.show_downloads then
|
||||||
|
io.write(method.." "..url.." ...\n")
|
||||||
|
end
|
||||||
|
local dots = 0
|
||||||
|
if cfg.connection_timeout and cfg.connection_timeout > 0 then
|
||||||
|
http.TIMEOUT = cfg.connection_timeout
|
||||||
|
end
|
||||||
|
local res, status, headers, err = http.request {
|
||||||
|
url = url,
|
||||||
|
proxy = proxy,
|
||||||
|
method = method,
|
||||||
|
redirect = false,
|
||||||
|
sink = ltn12.sink.table(result),
|
||||||
|
step = cfg.show_downloads and function(...)
|
||||||
|
io.write(".")
|
||||||
|
io.flush()
|
||||||
|
dots = dots + 1
|
||||||
|
if dots == 70 then
|
||||||
|
io.write("\n")
|
||||||
|
dots = 0
|
||||||
|
end
|
||||||
|
return ltn12.pump.step(...)
|
||||||
|
end,
|
||||||
|
headers = {
|
||||||
|
["user-agent"] = cfg.user_agent.." via LuaSocket"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if cfg.show_downloads then
|
||||||
|
io.write("\n")
|
||||||
|
end
|
||||||
|
if not res then
|
||||||
|
return nil, status
|
||||||
|
elseif status == 301 or status == 302 then
|
||||||
|
local location = headers.location
|
||||||
|
if location then
|
||||||
|
local protocol, rest = dir.split_url(location)
|
||||||
|
if redirect_protocols[protocol] then
|
||||||
|
if not loop_control then
|
||||||
|
loop_control = {}
|
||||||
|
elseif loop_control[location] then
|
||||||
|
return nil, "Redirection loop -- broken URL?"
|
||||||
|
end
|
||||||
|
loop_control[url] = true
|
||||||
|
return request(location, method, redirect_protocols[protocol], loop_control)
|
||||||
|
else
|
||||||
|
return nil, "URL redirected to unsupported protocol - install luasec to get HTTPS support.", "https"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil, err
|
||||||
|
elseif status ~= 200 then
|
||||||
|
return nil, err
|
||||||
|
else
|
||||||
|
return result, status, headers, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function http_request(url, http, cached)
|
||||||
|
if cached then
|
||||||
|
local tsfd = io.open(cached..".timestamp", "r")
|
||||||
|
if tsfd then
|
||||||
|
local timestamp = tsfd:read("*a")
|
||||||
|
tsfd:close()
|
||||||
|
local result, status, headers, err = request(url, "HEAD", http)
|
||||||
|
if status == 200 and headers["last-modified"] == timestamp then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if not result then
|
||||||
|
return nil, status, headers
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local result, status, headers, err = request(url, "GET", http)
|
||||||
|
if result then
|
||||||
|
if cached and headers["last-modified"] then
|
||||||
|
local tsfd = io.open(cached..".timestamp", "w")
|
||||||
|
if tsfd then
|
||||||
|
tsfd:write(headers["last-modified"])
|
||||||
|
tsfd:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return table.concat(result)
|
||||||
|
else
|
||||||
|
return nil, status, headers
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local downloader_warning = false
|
||||||
|
|
||||||
|
--- Download a remote file.
|
||||||
|
-- @param url string: URL to be fetched.
|
||||||
|
-- @param filename string or nil: this function attempts to detect the
|
||||||
|
-- resulting local filename of the remote file as the basename of the URL;
|
||||||
|
-- if that is not correct (due to a redirection, for example), the local
|
||||||
|
-- filename can be given explicitly as this second argument.
|
||||||
|
-- @return (boolean, string): true and the filename on success,
|
||||||
|
-- false and the error message on failure.
|
||||||
|
function fs_lua.download(url, filename, cache)
|
||||||
|
assert(type(url) == "string")
|
||||||
|
assert(type(filename) == "string" or not filename)
|
||||||
|
|
||||||
|
filename = fs.absolute_name(filename or dir.base_name(url))
|
||||||
|
|
||||||
|
-- delegate to the configured downloader so we don't have to deal with whitelists
|
||||||
|
if cfg.no_proxy then
|
||||||
|
return fs.use_downloader(url, filename, cache)
|
||||||
|
end
|
||||||
|
|
||||||
|
local content, err, https_err
|
||||||
|
if util.starts_with(url, "http:") then
|
||||||
|
content, err, https_err = http_request(url, http, cache and filename)
|
||||||
|
elseif util.starts_with(url, "ftp:") then
|
||||||
|
content, err = ftp.get(url)
|
||||||
|
elseif util.starts_with(url, "https:") then
|
||||||
|
-- skip LuaSec when proxy is enabled since it is not supported
|
||||||
|
if luasec_ok and not cfg.https_proxy then
|
||||||
|
content, err = http_request(url, https, cache and filename)
|
||||||
|
else
|
||||||
|
https_err = true
|
||||||
|
end
|
||||||
|
else
|
||||||
|
err = "Unsupported protocol"
|
||||||
|
end
|
||||||
|
if https_err then
|
||||||
|
if not downloader_warning then
|
||||||
|
util.printerr("Warning: falling back to "..cfg.downloader.." - install luasec to get native HTTPS support")
|
||||||
|
downloader_warning = true
|
||||||
|
end
|
||||||
|
return fs.use_downloader(url, filename, cache)
|
||||||
|
end
|
||||||
|
if cache and content == true then
|
||||||
|
return true, filename
|
||||||
|
end
|
||||||
|
if not content then
|
||||||
|
return false, tostring(err)
|
||||||
|
end
|
||||||
|
local file = io.open(filename, "wb")
|
||||||
|
if not file then return false end
|
||||||
|
file:write(content)
|
||||||
|
file:close()
|
||||||
|
return true, filename
|
||||||
|
end
|
||||||
|
|
||||||
|
else --...if socket_ok == false then
|
||||||
|
|
||||||
|
function fs_lua.download(url, filename, cache)
|
||||||
|
return fs.use_downloader(url, filename, cache)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
-- MD5 functions
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
if md5_ok then
|
||||||
|
|
||||||
|
-- Support the interface of lmd5 by lhf in addition to md5 by Roberto
|
||||||
|
-- and the keplerproject.
|
||||||
|
if not md5.sumhexa and md5.digest then
|
||||||
|
md5.sumhexa = function(msg)
|
||||||
|
return md5.digest(msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the MD5 checksum for a file.
|
||||||
|
-- @param file string: The file to be computed.
|
||||||
|
-- @return string: The MD5 checksum or nil + error
|
||||||
|
function fs_lua.get_md5(file)
|
||||||
|
file = fs.absolute_name(file)
|
||||||
|
local file_handler = io.open(file, "rb")
|
||||||
|
if not file_handler then return nil, "Failed to open file for reading: "..file end
|
||||||
|
local computed = md5.sumhexa(file_handler:read("*a"))
|
||||||
|
file_handler:close()
|
||||||
|
if computed then return computed end
|
||||||
|
return nil, "Failed to compute MD5 hash for file "..file
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
-- POSIX functions
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
if posix_ok then
|
||||||
|
|
||||||
|
local octal_to_rwx = {
|
||||||
|
["0"] = "---",
|
||||||
|
["1"] = "--x",
|
||||||
|
["2"] = "-w-",
|
||||||
|
["3"] = "-wx",
|
||||||
|
["4"] = "r--",
|
||||||
|
["5"] = "r-x",
|
||||||
|
["6"] = "rw-",
|
||||||
|
["7"] = "rwx",
|
||||||
|
}
|
||||||
|
|
||||||
|
function fs_lua.chmod(file, mode)
|
||||||
|
-- LuaPosix (as of 5.1.15) does not support octal notation...
|
||||||
|
if mode:sub(1,1) == "0" then
|
||||||
|
local new_mode = {}
|
||||||
|
for c in mode:sub(-3):gmatch(".") do
|
||||||
|
table.insert(new_mode, octal_to_rwx[c])
|
||||||
|
end
|
||||||
|
mode = table.concat(new_mode)
|
||||||
|
end
|
||||||
|
local err = posix.chmod(file, mode)
|
||||||
|
return err == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function fs_lua.get_permissions(file)
|
||||||
|
return posix.stat(file, "mode")
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a temporary directory.
|
||||||
|
-- @param name 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 fs_lua.make_temp_dir(name)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
name = dir.normalize(name)
|
||||||
|
|
||||||
|
return posix.mkdtemp((os.getenv("TMPDIR") or "/tmp") .. "/luarocks_" .. name:gsub(dir.separator, "_") .. "-XXXXXX")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
-- Other functions
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Apply a patch.
|
||||||
|
-- @param patchname string: The filename of the patch.
|
||||||
|
-- @param patchdata string or nil: The actual patch as a string.
|
||||||
|
function fs_lua.apply_patch(patchname, patchdata)
|
||||||
|
local p, all_ok = patch.read_patch(patchname, patchdata)
|
||||||
|
if not all_ok then
|
||||||
|
return nil, "Failed reading patch "..patchname
|
||||||
|
end
|
||||||
|
if p then
|
||||||
|
return patch.apply_patch(p, 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Move a file.
|
||||||
|
-- @param src string: Pathname of source
|
||||||
|
-- @param dest string: Pathname of destination
|
||||||
|
-- @param perms string or nil: Permissions for destination file,
|
||||||
|
-- or nil to use the source filename permissions.
|
||||||
|
-- @return boolean or (boolean, string): true on success, false on failure,
|
||||||
|
-- plus an error message.
|
||||||
|
function fs_lua.move(src, dest, perms)
|
||||||
|
assert(src and dest)
|
||||||
|
if fs.exists(dest) and not fs.is_dir(dest) then
|
||||||
|
return false, "File already exists: "..dest
|
||||||
|
end
|
||||||
|
local ok, err = fs.copy(src, dest, perms)
|
||||||
|
if not ok then
|
||||||
|
return false, err
|
||||||
|
end
|
||||||
|
fs.delete(src)
|
||||||
|
if fs.exists(src) then
|
||||||
|
return false, "Failed move: could not delete "..src.." after copy."
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if user has write permissions for the command.
|
||||||
|
-- Assumes the configuration variables under cfg have been previously set up.
|
||||||
|
-- @param flags table: the flags table passed to run() drivers.
|
||||||
|
-- @return boolean or (boolean, string): true on success, false on failure,
|
||||||
|
-- plus an error message.
|
||||||
|
function fs_lua.check_command_permissions(flags)
|
||||||
|
local root_dir = path.root_dir(cfg.rocks_dir)
|
||||||
|
local ok = true
|
||||||
|
local err = ""
|
||||||
|
for _, dir in ipairs { cfg.rocks_dir, root_dir } do
|
||||||
|
if fs.exists(dir) and not fs.is_writable(dir) then
|
||||||
|
ok = false
|
||||||
|
err = "Your user does not have write permissions in " .. dir
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if ok and not fs.exists(root_dir) then
|
||||||
|
local root = fs.root_of(root_dir)
|
||||||
|
local parent = root_dir
|
||||||
|
repeat
|
||||||
|
parent = dir.dir_name(parent)
|
||||||
|
if parent == "" then
|
||||||
|
parent = root
|
||||||
|
end
|
||||||
|
until parent == root or fs.exists(parent)
|
||||||
|
if not fs.is_writable(parent) then
|
||||||
|
ok = false
|
||||||
|
err = root_dir.." does not exist and your user does not have write permissions in " .. parent
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if ok then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
if flags["local"] then
|
||||||
|
err = err .. " \n-- please check your permissions."
|
||||||
|
else
|
||||||
|
err = err .. " \n-- you may want to run as a privileged user or use your local tree with --local."
|
||||||
|
end
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check whether a file is a Lua script
|
||||||
|
-- When the file can be succesfully compiled by the configured
|
||||||
|
-- Lua interpreter, it's considered to be a valid Lua file.
|
||||||
|
-- @param name filename of file to check
|
||||||
|
-- @return boolean true, if it is a Lua script, false otherwise
|
||||||
|
function fs_lua.is_lua(name)
|
||||||
|
name = name:gsub([[%\]],"/") -- normalize on fw slash to prevent escaping issues
|
||||||
|
local lua = fs.Q(dir.path(cfg.variables["LUA_BINDIR"], cfg.lua_interpreter)) -- get lua interpreter configured
|
||||||
|
-- execute on configured interpreter, might not be the same as the interpreter LR is run on
|
||||||
|
local result = fs.execute_string(lua..[[ -e "if loadfile(']]..name..[[') then os.exit() else os.exit(1) end"]])
|
||||||
|
return (result == true)
|
||||||
|
end
|
||||||
|
|
||||||
|
return fs_lua
|
||||||
156
Utils/luarocks/lua/luarocks/fs/tools.lua
Normal file
156
Utils/luarocks/lua/luarocks/fs/tools.lua
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
|
||||||
|
--- Common fs operations implemented with third-party tools.
|
||||||
|
local tools = {}
|
||||||
|
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
|
||||||
|
local vars = cfg.variables
|
||||||
|
|
||||||
|
local dir_stack = {}
|
||||||
|
|
||||||
|
--- 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 = cfg.cache_pwd
|
||||||
|
if not current then
|
||||||
|
local pipe = io.popen(fs.quiet_stderr(fs.Q(vars.PWD)))
|
||||||
|
current = pipe:read("*l")
|
||||||
|
pipe:close()
|
||||||
|
cfg.cache_pwd = current
|
||||||
|
end
|
||||||
|
for _, directory in ipairs(dir_stack) do
|
||||||
|
current = fs.absolute_name(directory, current)
|
||||||
|
end
|
||||||
|
return current
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Change the current directory.
|
||||||
|
-- Uses the module's internal directory stack. This does not have exact
|
||||||
|
-- semantics of chdir, as it does not handle errors the same way,
|
||||||
|
-- but works well for our purposes for now.
|
||||||
|
-- @param directory string: The directory to switch to.
|
||||||
|
-- @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()
|
||||||
|
table.insert(dir_stack, "/")
|
||||||
|
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, fs.Q(vars.LS)))
|
||||||
|
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.
|
||||||
|
-- @return (boolean, string): true and the filename on success,
|
||||||
|
-- false and the error message on failure.
|
||||||
|
function tools.use_downloader(url, filename, cache)
|
||||||
|
assert(type(url) == "string")
|
||||||
|
assert(type(filename) == "string" or not filename)
|
||||||
|
|
||||||
|
filename = fs.absolute_name(filename or dir.base_name(url))
|
||||||
|
|
||||||
|
local ok
|
||||||
|
if cfg.downloader == "wget" then
|
||||||
|
local wget_cmd = fs.Q(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="..tonumber(cfg.connection_timeout).." --tries=1 "
|
||||||
|
end
|
||||||
|
if cache then
|
||||||
|
-- --timestamping is incompatible with --output-document,
|
||||||
|
-- but that's not a problem for our use cases.
|
||||||
|
fs.change_dir(dir.dir_name(filename))
|
||||||
|
ok = fs.execute_quiet(wget_cmd.." --timestamping ", url)
|
||||||
|
fs.pop_dir()
|
||||||
|
elseif filename then
|
||||||
|
ok = fs.execute_quiet(wget_cmd.." --output-document ", filename, url)
|
||||||
|
else
|
||||||
|
ok = fs.execute_quiet(wget_cmd, url)
|
||||||
|
end
|
||||||
|
elseif cfg.downloader == "curl" then
|
||||||
|
local curl_cmd = fs.Q(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 "..tonumber(cfg.connection_timeout).." "
|
||||||
|
end
|
||||||
|
ok = fs.execute_string(fs.quiet_stderr(curl_cmd..fs.Q(url).." > "..fs.Q(filename)))
|
||||||
|
end
|
||||||
|
if ok then
|
||||||
|
return true, filename
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local md5_cmd = {
|
||||||
|
md5sum = fs.Q(vars.MD5SUM),
|
||||||
|
openssl = fs.Q(vars.OPENSSL).." md5",
|
||||||
|
md5 = fs.Q(vars.MD5),
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Get the MD5 checksum for a file.
|
||||||
|
-- @param file string: The file to be computed.
|
||||||
|
-- @return string: The MD5 checksum or nil + message
|
||||||
|
function tools.get_md5(file)
|
||||||
|
local cmd = md5_cmd[cfg.md5checker]
|
||||||
|
if not cmd then return nil, "no MD5 checker command configured" end
|
||||||
|
local pipe = io.popen(cmd.." "..fs.Q(fs.absolute_name(file)))
|
||||||
|
local computed = pipe:read("*a")
|
||||||
|
pipe:close()
|
||||||
|
if computed then
|
||||||
|
computed = computed:match("("..("%x"):rep(32)..")")
|
||||||
|
end
|
||||||
|
if computed then return computed end
|
||||||
|
return nil, "Failed to compute MD5 hash for file "..tostring(fs.absolute_name(file))
|
||||||
|
end
|
||||||
|
|
||||||
|
return tools
|
||||||
135
Utils/luarocks/lua/luarocks/fs/unix.lua
Normal file
135
Utils/luarocks/lua/luarocks/fs/unix.lua
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
|
||||||
|
--- Unix implementation of filesystem and platform abstractions.
|
||||||
|
local unix = {}
|
||||||
|
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
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)
|
||||||
|
|
||||||
|
relative_to = relative_to or fs.current_dir()
|
||||||
|
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 file string: Pathname of script to be made executable.
|
||||||
|
-- @param dest string: Directory where to put the wrapper.
|
||||||
|
-- @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(file, dest, name, version)
|
||||||
|
assert(type(file) == "string")
|
||||||
|
assert(type(dest) == "string")
|
||||||
|
|
||||||
|
local base = dir.base_name(file)
|
||||||
|
local wrapname = fs.is_dir(dest) and dest.."/"..base or dest
|
||||||
|
local lpath, lcpath = cfg.package_paths()
|
||||||
|
local wrapper = io.open(wrapname, "w")
|
||||||
|
if not wrapper then
|
||||||
|
return nil, "Could not open "..wrapname.." for writing."
|
||||||
|
end
|
||||||
|
wrapper:write("#!/bin/sh\n\n")
|
||||||
|
local lua = dir.path(cfg.variables["LUA_BINDIR"], cfg.lua_interpreter)
|
||||||
|
local ppaths = "package.path="..util.LQ(lpath..";").."..package.path; package.cpath="..util.LQ(lcpath..";").."..package.cpath"
|
||||||
|
local addctx = "local k,l,_=pcall(require,"..util.LQ("luarocks.loader")..") _=k and l.add_context("..util.LQ(name)..","..util.LQ(version)..")"
|
||||||
|
wrapper:write('exec '..fs.Q(lua)..' -e '..fs.Q(ppaths)..' -e '..fs.Q(addctx)..' '..fs.Q(file)..' "$@"\n')
|
||||||
|
wrapper:close()
|
||||||
|
if fs.chmod(wrapname, cfg.perm_exec) then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return nil, "Could not make "..wrapname.." executable."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if a file (typically inside path.bin_dir) is an actual binary
|
||||||
|
-- or a Lua wrapper.
|
||||||
|
-- @param filename string: the file name with full path.
|
||||||
|
-- @return boolean: returns true if file is an actual binary
|
||||||
|
-- (or if it couldn't check) or false if it is a Lua wrapper.
|
||||||
|
function 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.printerr("Warning: could not read "..filename)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return first ~= "#!"
|
||||||
|
end
|
||||||
|
|
||||||
|
function unix.copy_binary(filename, dest)
|
||||||
|
return fs.copy(filename, dest, cfg.perm_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
|
||||||
|
|
||||||
|
return unix
|
||||||
237
Utils/luarocks/lua/luarocks/fs/unix/tools.lua
Normal file
237
Utils/luarocks/lua/luarocks/fs/unix/tools.lua
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
|
||||||
|
--- 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.cfg")
|
||||||
|
|
||||||
|
local vars = cfg.variables
|
||||||
|
|
||||||
|
--- 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 or nil: Permissions for destination file,
|
||||||
|
-- @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.chmod(dest, perm) then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false, "Failed setting permissions of "..dest
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false, "Failed copying "..src.." to "..dest
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Recursively copy the contents of a directory.
|
||||||
|
-- @param src string: Pathname of source
|
||||||
|
-- @param dest string: Pathname of destination
|
||||||
|
-- @return boolean or (boolean, string): true on success, false on failure,
|
||||||
|
-- plus an error message.
|
||||||
|
function 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, false on failure.
|
||||||
|
function tools.zip(zipfile, ...)
|
||||||
|
return fs.execute(vars.ZIP.." -r", zipfile, ...)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Uncompress files from a .zip archive.
|
||||||
|
-- @param zipfile string: pathname of .zip archive to be extracted.
|
||||||
|
-- @return boolean: true on success, false on failure.
|
||||||
|
function tools.unzip(zipfile)
|
||||||
|
assert(zipfile)
|
||||||
|
return fs.execute_quiet(vars.UNZIP, zipfile)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Test is file/directory exists
|
||||||
|
-- @param file string: filename to test
|
||||||
|
-- @return boolean: true if file exists, false otherwise.
|
||||||
|
function 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
|
||||||
|
|
||||||
|
function tools.chmod(pathname, mode)
|
||||||
|
if mode then
|
||||||
|
return fs.execute(vars.CHMOD, mode, pathname)
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Unpack an archive.
|
||||||
|
-- Extract the contents of an archive, detecting its format by
|
||||||
|
-- filename extension.
|
||||||
|
-- @param archive string: Filename of archive.
|
||||||
|
-- @return boolean or (boolean, string): true on success, false and an error message on failure.
|
||||||
|
function tools.unpack_archive(archive)
|
||||||
|
assert(type(archive) == "string")
|
||||||
|
|
||||||
|
local pipe_to_tar = " | "..vars.TAR.." -xf -"
|
||||||
|
|
||||||
|
if not cfg.verbose then
|
||||||
|
pipe_to_tar = " 2> /dev/null"..fs.quiet(pipe_to_tar)
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok
|
||||||
|
if archive:match("%.tar%.gz$") or archive:match("%.tgz$") then
|
||||||
|
ok = fs.execute_string(vars.GUNZIP.." -c "..fs.Q(archive)..pipe_to_tar)
|
||||||
|
elseif archive:match("%.tar%.bz2$") then
|
||||||
|
ok = fs.execute_string(vars.BUNZIP2.." -c "..fs.Q(archive)..pipe_to_tar)
|
||||||
|
elseif archive:match("%.zip$") then
|
||||||
|
ok = fs.execute_quiet(vars.UNZIP, archive)
|
||||||
|
elseif archive:match("%.lua$") or archive:match("%.c$") then
|
||||||
|
-- Ignore .lua and .c files; they don't need to be extracted.
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false, "Couldn't extract archive "..archive..": unrecognized filename extension"
|
||||||
|
end
|
||||||
|
if not ok then
|
||||||
|
return false, "Failed extracting "..archive
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function tools.get_permissions(filename)
|
||||||
|
local pipe = io.popen(vars.STAT.." "..vars.STATFLAG.." "..fs.Q(filename))
|
||||||
|
local ret = pipe:read("*l")
|
||||||
|
pipe:close()
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
function tools.browser(url)
|
||||||
|
return fs.execute(cfg.web_browser, url)
|
||||||
|
end
|
||||||
|
|
||||||
|
function tools.set_time(file, time)
|
||||||
|
file = dir.normalize(file)
|
||||||
|
return fs.execute(vars.TOUCH, "-d", "@"..tostring(time), file)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a temporary directory.
|
||||||
|
-- @param name 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)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
name = dir.normalize(name)
|
||||||
|
|
||||||
|
local template = (os.getenv("TMPDIR") or "/tmp") .. "/luarocks_" .. name:gsub(dir.separator, "_") .. "-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
|
||||||
|
|
||||||
|
return tools
|
||||||
266
Utils/luarocks/lua/luarocks/fs/win32.lua
Normal file
266
Utils/luarocks/lua/luarocks/fs/win32.lua
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
--- 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.cfg")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
|
||||||
|
math.randomseed(os.time())
|
||||||
|
|
||||||
|
-- Monkey patch io.popen and os.execute to make sure quoting
|
||||||
|
-- works as expected.
|
||||||
|
-- See http://lua-users.org/lists/lua-l/2013-11/msg00367.html
|
||||||
|
local _prefix = "type NUL && "
|
||||||
|
local _popen, _execute = io.popen, os.execute
|
||||||
|
io.popen = function(cmd, ...) return _popen(_prefix..cmd, ...) end
|
||||||
|
os.execute = function(cmd, ...) return _execute(_prefix..cmd, ...) end
|
||||||
|
|
||||||
|
--- Annotate command string for quiet execution.
|
||||||
|
-- @param cmd string: A command-line string.
|
||||||
|
-- @return string: The command-line, with silencing annotation.
|
||||||
|
function 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 root and the rest.
|
||||||
|
-- Root part consists of an optional drive letter (e.g. "C:")
|
||||||
|
-- and an optional directory separator.
|
||||||
|
local function split_root(path)
|
||||||
|
local root = ""
|
||||||
|
|
||||||
|
if path:match("^.:") then
|
||||||
|
root = path:sub(1, 2)
|
||||||
|
path = path:sub(3)
|
||||||
|
end
|
||||||
|
|
||||||
|
if path:match("^[\\/]") then
|
||||||
|
root = path:sub(1, 1)
|
||||||
|
path = path:sub(2)
|
||||||
|
end
|
||||||
|
|
||||||
|
return root, path
|
||||||
|
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.
|
||||||
|
if split_root(arg) ~= "" 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.
|
||||||
|
if split_root(arg) ~= "" 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()
|
||||||
|
local root, rest = split_root(pathname)
|
||||||
|
if root:match("[\\/]$") then
|
||||||
|
-- It's an absolute path already.
|
||||||
|
return pathname
|
||||||
|
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)
|
||||||
|
return (split_root(fs.absolute_name(pathname)))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a wrapper to make a script executable from the command-line.
|
||||||
|
-- @param file string: Pathname of script to be made executable.
|
||||||
|
-- @param dest string: Directory where to put the wrapper.
|
||||||
|
-- @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(file, dest, name, version)
|
||||||
|
assert(type(file) == "string")
|
||||||
|
assert(type(dest) == "string")
|
||||||
|
|
||||||
|
local base = dir.base_name(file)
|
||||||
|
local wrapname = fs.is_dir(dest) and dest.."/"..base or dest
|
||||||
|
wrapname = wrapname..".bat"
|
||||||
|
local lpath, lcpath = cfg.package_paths()
|
||||||
|
lpath = util.remove_path_dupes(lpath, ";")
|
||||||
|
lcpath = util.remove_path_dupes(lcpath, ";")
|
||||||
|
local wrapper = io.open(wrapname, "w")
|
||||||
|
if not wrapper then
|
||||||
|
return nil, "Could not open "..wrapname.." for writing."
|
||||||
|
end
|
||||||
|
wrapper:write("@echo off\n")
|
||||||
|
local lua = dir.path(cfg.variables["LUA_BINDIR"], cfg.lua_interpreter)
|
||||||
|
local ppaths = "package.path="..util.LQ(lpath..";").."..package.path; package.cpath="..util.LQ(lcpath..";").."..package.cpath"
|
||||||
|
local addctx = "local k,l,_=pcall(require,"..util.LQ("luarocks.loader")..") _=k and l.add_context("..util.LQ(name)..","..util.LQ(version)..")"
|
||||||
|
wrapper:write(fs.Qb(lua)..' -e '..fs.Qb(ppaths)..' -e '..fs.Qb(addctx)..' '..fs.Qb(file)..' %*\n')
|
||||||
|
wrapper:write("exit /b %ERRORLEVEL%\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
|
||||||
|
|
||||||
|
function win32.chmod(filename, mode)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function win32.get_permissions(filename)
|
||||||
|
return ""
|
||||||
|
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
|
||||||
|
|
||||||
|
--- 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 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)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
name = dir.normalize(name)
|
||||||
|
|
||||||
|
local temp_dir = os.getenv("TMP") .. "/luarocks_" .. name:gsub(dir.separator, "_") .. "-" .. 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()
|
||||||
|
return os.getenv("TMP")..os.tmpname()
|
||||||
|
end
|
||||||
|
|
||||||
|
return win32
|
||||||
227
Utils/luarocks/lua/luarocks/fs/win32/tools.lua
Normal file
227
Utils/luarocks/lua/luarocks/fs/win32/tools.lua
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
|
||||||
|
--- 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.cfg")
|
||||||
|
|
||||||
|
local vars = cfg.variables
|
||||||
|
|
||||||
|
--- 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)
|
||||||
|
local drive = directory:match("^([A-Za-z]:)")
|
||||||
|
cmd = "cd " .. fs.Q(directory) .. " & " .. cmd
|
||||||
|
if drive then
|
||||||
|
cmd = drive .. " & " .. cmd
|
||||||
|
end
|
||||||
|
return 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)
|
||||||
|
directory = dir.normalize(directory)
|
||||||
|
fs.execute_quiet(fs.Q(vars.MKDIR).." -p ", directory)
|
||||||
|
if not fs.is_dir(directory) then
|
||||||
|
return false, "failed making directory "..directory
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove a directory if it is empty.
|
||||||
|
-- Does not return errors (for example, if directory is not empty or
|
||||||
|
-- if already does not exist)
|
||||||
|
-- @param directory string: pathname of directory to remove.
|
||||||
|
function tools.remove_dir_if_empty(directory)
|
||||||
|
assert(directory)
|
||||||
|
fs.execute_quiet(fs.Q(vars.RMDIR), directory)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove a directory if it is empty.
|
||||||
|
-- Does not return errors (for example, if directory is not empty or
|
||||||
|
-- if already does not exist)
|
||||||
|
-- @param directory string: pathname of directory to remove.
|
||||||
|
function tools.remove_dir_tree_if_empty(directory)
|
||||||
|
assert(directory)
|
||||||
|
fs.execute_quiet(fs.Q(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(fs.Q(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 fs.execute_quiet(fs.Q(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(fs.Q(vars.FIND))))
|
||||||
|
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, false on failure.
|
||||||
|
function tools.zip(zipfile, ...)
|
||||||
|
return fs.execute_quiet(fs.Q(vars.SEVENZ).." -aoa a -tzip", zipfile, ...)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Uncompress files from a .zip archive.
|
||||||
|
-- @param zipfile string: pathname of .zip archive to be extracted.
|
||||||
|
-- @return boolean: true on success, false on failure.
|
||||||
|
function tools.unzip(zipfile)
|
||||||
|
assert(zipfile)
|
||||||
|
return fs.execute_quiet(fs.Q(vars.SEVENZ).." -aoa x", zipfile)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Test is pathname is a directory.
|
||||||
|
-- @param file string: pathname to test
|
||||||
|
-- @return boolean: true if it is a directory, false otherwise.
|
||||||
|
function tools.is_dir(file)
|
||||||
|
assert(file)
|
||||||
|
return fs.execute_quiet("if not exist " .. fs.Q(file.."\\").." invalidcommandname")
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Test is pathname is a regular file.
|
||||||
|
-- @param file string: pathname to test
|
||||||
|
-- @return boolean: true if it is a regular file, false otherwise.
|
||||||
|
function tools.is_file(file)
|
||||||
|
assert(file)
|
||||||
|
return fs.execute(fs.Q(vars.TEST).." -f", file)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Strip the last extension of a filename.
|
||||||
|
-- Example: "foo.tar.gz" becomes "foo.tar".
|
||||||
|
-- If filename has no dots, returns it unchanged.
|
||||||
|
-- @param filename string: The file name to strip.
|
||||||
|
-- @return string: The stripped name.
|
||||||
|
local function strip_extension(filename)
|
||||||
|
assert(type(filename) == "string")
|
||||||
|
return (filename:gsub("%.[^.]+$", "")) or filename
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Uncompress gzip file.
|
||||||
|
-- @param archive string: Filename of archive.
|
||||||
|
-- @return boolean : success status
|
||||||
|
local function gunzip(archive)
|
||||||
|
return fs.execute_quiet(fs.Q(vars.SEVENZ).." -aoa x", archive)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Unpack an archive.
|
||||||
|
-- Extract the contents of an archive, detecting its format by
|
||||||
|
-- filename extension.
|
||||||
|
-- @param archive string: Filename of archive.
|
||||||
|
-- @return boolean or (boolean, string): true on success, false and an error message on failure.
|
||||||
|
function tools.unpack_archive(archive)
|
||||||
|
assert(type(archive) == "string")
|
||||||
|
|
||||||
|
local ok
|
||||||
|
local sevenzx = fs.Q(vars.SEVENZ).." -aoa x"
|
||||||
|
if archive:match("%.tar%.gz$") then
|
||||||
|
ok = gunzip(archive)
|
||||||
|
if ok then
|
||||||
|
ok = fs.execute_quiet(sevenzx, strip_extension(archive))
|
||||||
|
end
|
||||||
|
elseif archive:match("%.tgz$") then
|
||||||
|
ok = gunzip(archive)
|
||||||
|
if ok then
|
||||||
|
ok = fs.execute_quiet(sevenzx, strip_extension(archive)..".tar")
|
||||||
|
end
|
||||||
|
elseif archive:match("%.tar%.bz2$") then
|
||||||
|
ok = fs.execute_quiet(sevenzx, archive)
|
||||||
|
if ok then
|
||||||
|
ok = fs.execute_quiet(sevenzx, strip_extension(archive))
|
||||||
|
end
|
||||||
|
elseif archive:match("%.zip$") then
|
||||||
|
ok = fs.execute_quiet(sevenzx, archive)
|
||||||
|
elseif archive:match("%.lua$") or archive:match("%.c$") then
|
||||||
|
-- Ignore .lua and .c files; they don't need to be extracted.
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false, "Couldn't extract archive "..archive..": unrecognized filename extension"
|
||||||
|
end
|
||||||
|
if not ok then
|
||||||
|
return false, "Failed extracting "..archive
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Test for existance of a file.
|
||||||
|
-- @param file string: filename to test
|
||||||
|
-- @return boolean: true if file exists, false otherwise.
|
||||||
|
function tools.exists(file)
|
||||||
|
assert(file)
|
||||||
|
return fs.execute_quiet("if not exist " .. fs.Q(file) .. " invalidcommandname")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tools.browser(url)
|
||||||
|
return fs.execute(cfg.web_browser..' "Starting docs..." '..fs.Q(url))
|
||||||
|
end
|
||||||
|
|
||||||
|
return tools
|
||||||
118
Utils/luarocks/lua/luarocks/help.lua
Normal file
118
Utils/luarocks/lua/luarocks/help.lua
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
|
||||||
|
--- Module implementing the LuaRocks "help" command.
|
||||||
|
-- This is a generic help display module, which
|
||||||
|
-- uses a global table called "commands" to find commands
|
||||||
|
-- to show help for; each command should be represented by a
|
||||||
|
-- table containing "help" and "help_summary" fields.
|
||||||
|
local help = {}
|
||||||
|
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
|
||||||
|
local program = util.this_program("luarocks")
|
||||||
|
|
||||||
|
util.add_run_function(help)
|
||||||
|
help.help_summary = "Help on commands. Type '"..program.." help <command>' for more."
|
||||||
|
|
||||||
|
help.help_arguments = "[<command>]"
|
||||||
|
help.help = [[
|
||||||
|
<command> is the command to show help for.
|
||||||
|
]]
|
||||||
|
|
||||||
|
local function print_banner()
|
||||||
|
util.printout("\nLuaRocks "..cfg.program_version..", a module deployment system for Lua")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function print_section(section)
|
||||||
|
util.printout("\n"..section)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function get_status(status)
|
||||||
|
if status then
|
||||||
|
return "ok"
|
||||||
|
else
|
||||||
|
return "not found"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Driver function for the "help" command.
|
||||||
|
-- @param command string or nil: command to show help for; if not
|
||||||
|
-- given, help summaries for all commands are shown.
|
||||||
|
-- @return boolean or (nil, string): true if there were no errors
|
||||||
|
-- or nil and an error message if an invalid command was requested.
|
||||||
|
function help.command(flags, command)
|
||||||
|
if not command then
|
||||||
|
local conf = cfg.which_config()
|
||||||
|
print_banner()
|
||||||
|
print_section("NAME")
|
||||||
|
util.printout("\t"..program..[[ - ]]..program_description)
|
||||||
|
print_section("SYNOPSIS")
|
||||||
|
util.printout("\t"..program..[[ [--from=<server> | --only-from=<server>] [--to=<tree>] [VAR=VALUE]... <command> [<argument>] ]])
|
||||||
|
print_section("GENERAL OPTIONS")
|
||||||
|
util.printout([[
|
||||||
|
These apply to all commands, as appropriate:
|
||||||
|
|
||||||
|
--server=<server> Fetch rocks/rockspecs from this server
|
||||||
|
(takes priority over config file)
|
||||||
|
--only-server=<server> Fetch rocks/rockspecs from this server only
|
||||||
|
(overrides any entries in the config file)
|
||||||
|
--only-sources=<url> Restrict downloads to paths matching the
|
||||||
|
given URL.
|
||||||
|
--tree=<tree> Which tree to operate on.
|
||||||
|
--local Use the tree in the user's home directory.
|
||||||
|
To enable it, see ']]..program..[[ help path'.
|
||||||
|
--verbose Display verbose output of commands executed.
|
||||||
|
--timeout=<seconds> Timeout on network operations, in seconds.
|
||||||
|
0 means no timeout (wait forever).
|
||||||
|
Default is ]]..tostring(cfg.connection_timeout)..[[.]])
|
||||||
|
print_section("VARIABLES")
|
||||||
|
util.printout([[
|
||||||
|
Variables from the "variables" table of the configuration file
|
||||||
|
can be overriden with VAR=VALUE assignments.]])
|
||||||
|
print_section("COMMANDS")
|
||||||
|
for name, command in util.sortedpairs(commands) do
|
||||||
|
local cmd = require(command)
|
||||||
|
util.printout("", name)
|
||||||
|
util.printout("\t", cmd.help_summary)
|
||||||
|
end
|
||||||
|
print_section("CONFIGURATION")
|
||||||
|
util.printout("\tLua version: " .. cfg.lua_version)
|
||||||
|
util.printout("\tConfiguration files:")
|
||||||
|
util.printout("\t\tSystem: ".. dir.normalize(conf.system.file) .. " (" .. get_status(conf.system.ok) ..")")
|
||||||
|
if conf.user.file then
|
||||||
|
util.printout("\t\tUser : ".. dir.normalize(conf.user.file) .. " (" .. get_status(conf.user.ok) ..")\n")
|
||||||
|
else
|
||||||
|
util.printout("\t\tUser : disabled in this LuaRocks installation.\n")
|
||||||
|
end
|
||||||
|
util.printout("\tRocks trees in use: ")
|
||||||
|
for _, tree in ipairs(cfg.rocks_trees) do
|
||||||
|
if type(tree) == "string" then
|
||||||
|
util.printout("\t\t"..dir.normalize(tree))
|
||||||
|
else
|
||||||
|
local name = tree.name and " (\""..tree.name.."\")" or ""
|
||||||
|
util.printout("\t\t"..dir.normalize(tree.root)..name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
command = command:gsub("-", "_")
|
||||||
|
local cmd = commands[command] and require(commands[command])
|
||||||
|
if cmd then
|
||||||
|
local arguments = cmd.help_arguments or "<argument>"
|
||||||
|
print_banner()
|
||||||
|
print_section("NAME")
|
||||||
|
util.printout("\t"..program.." "..command.." - "..cmd.help_summary)
|
||||||
|
print_section("SYNOPSIS")
|
||||||
|
util.printout("\t"..program.." "..command.." "..arguments)
|
||||||
|
print_section("DESCRIPTION")
|
||||||
|
util.printout("",(cmd.help:gsub("\n","\n\t"):gsub("\n\t$","")))
|
||||||
|
print_section("SEE ALSO")
|
||||||
|
util.printout("","'"..program.." help' for general options and configuration.\n")
|
||||||
|
else
|
||||||
|
return nil, "Unknown command: "..command
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return help
|
||||||
186
Utils/luarocks/lua/luarocks/index.lua
Normal file
186
Utils/luarocks/lua/luarocks/index.lua
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
|
||||||
|
--- Module which builds the index.html page to be used in rocks servers.
|
||||||
|
local index = {}
|
||||||
|
package.loaded["luarocks.index"] = index
|
||||||
|
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local deps = require("luarocks.deps")
|
||||||
|
local persist = require("luarocks.persist")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local manif = require("luarocks.manif")
|
||||||
|
|
||||||
|
local ext_url_target = ' target="_blank"'
|
||||||
|
|
||||||
|
local index_header = [[
|
||||||
|
<!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 = [[
|
||||||
|
• <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, ', ').. '</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, deps.compare_versions) do
|
||||||
|
local versions = {}
|
||||||
|
output = output..version..': '
|
||||||
|
table.sort(data, function(a,b) return a.arch < b.arch end)
|
||||||
|
for _, item in ipairs(data) do
|
||||||
|
local 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, ', ') .. '<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
|
||||||
188
Utils/luarocks/lua/luarocks/install.lua
Normal file
188
Utils/luarocks/lua/luarocks/install.lua
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
--- Module implementing the LuaRocks "install" command.
|
||||||
|
-- Installs binary rocks.
|
||||||
|
local install = {}
|
||||||
|
package.loaded["luarocks.install"] = 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 manif = require("luarocks.manif")
|
||||||
|
local remove = require("luarocks.remove")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
|
||||||
|
util.add_run_function(install)
|
||||||
|
install.help_summary = "Install a rock."
|
||||||
|
|
||||||
|
install.help_arguments = "{<rock>|<name> [<version>]}"
|
||||||
|
|
||||||
|
install.help = [[
|
||||||
|
Argument may be the name of a rock to be fetched from a repository
|
||||||
|
or a filename of a locally available rock.
|
||||||
|
|
||||||
|
--keep Do not remove previously installed versions of the
|
||||||
|
rock after installing a new one. This behavior can
|
||||||
|
be made permanent by setting keep_other_versions=true
|
||||||
|
in the configuration file.
|
||||||
|
|
||||||
|
--only-deps Installs only the dependencies of the rock.
|
||||||
|
]]..util.deps_mode_help()
|
||||||
|
|
||||||
|
|
||||||
|
--- Install a binary rock.
|
||||||
|
-- @param rock_file string: local or remote filename of a rock.
|
||||||
|
-- @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 (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, deps_mode)
|
||||||
|
assert(type(rock_file) == "string")
|
||||||
|
|
||||||
|
local name, version, arch = path.parse_name(rock_file)
|
||||||
|
if not name then
|
||||||
|
return nil, "Filename "..rock_file.." does not match format 'name-version-revision.arch.rock'."
|
||||||
|
end
|
||||||
|
|
||||||
|
if arch ~= "all" and arch ~= cfg.arch then
|
||||||
|
return nil, "Incompatible architecture "..arch, "arch"
|
||||||
|
end
|
||||||
|
if repos.is_installed(name, version) then
|
||||||
|
repos.delete_version(name, version, deps_mode)
|
||||||
|
end
|
||||||
|
|
||||||
|
local rollback = util.schedule_function(function()
|
||||||
|
fs.delete(path.install_dir(name, version))
|
||||||
|
fs.remove_dir_if_empty(path.versions_dir(name))
|
||||||
|
end)
|
||||||
|
|
||||||
|
local ok, err, errcode = fetch.fetch_and_unpack_rock(rock_file, path.install_dir(name, version))
|
||||||
|
if not ok then return nil, err, errcode end
|
||||||
|
|
||||||
|
local rockspec, err, errcode = fetch.load_rockspec(path.rockspec_file(name, version))
|
||||||
|
if err then
|
||||||
|
return nil, "Failed loading rockspec for installed package: "..err, errcode
|
||||||
|
end
|
||||||
|
|
||||||
|
if deps_mode == "none" then
|
||||||
|
util.printerr("Warning: skipping dependency checks.")
|
||||||
|
else
|
||||||
|
ok, err, errcode = deps.check_external_deps(rockspec, "install")
|
||||||
|
if err then return nil, err, errcode end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- For compatibility with .rock files built with LuaRocks 1
|
||||||
|
if not fs.exists(path.rock_manifest_file(name, version)) then
|
||||||
|
ok, err = manif.make_rock_manifest(name, version)
|
||||||
|
if err then return nil, err end
|
||||||
|
end
|
||||||
|
|
||||||
|
if deps_mode ~= "none" then
|
||||||
|
ok, err, errcode = deps.fulfill_dependencies(rockspec, deps_mode)
|
||||||
|
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 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 (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, deps_mode)
|
||||||
|
assert(type(rock_file) == "string")
|
||||||
|
|
||||||
|
local name, version, arch = path.parse_name(rock_file)
|
||||||
|
if not name then
|
||||||
|
return nil, "Filename "..rock_file.." does not match format 'name-version-revision.arch.rock'."
|
||||||
|
end
|
||||||
|
|
||||||
|
if arch ~= "all" and arch ~= cfg.arch then
|
||||||
|
return nil, "Incompatible architecture "..arch, "arch"
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok, err, errcode = fetch.fetch_and_unpack_rock(rock_file, path.install_dir(name, version))
|
||||||
|
if not ok then return nil, err, errcode end
|
||||||
|
|
||||||
|
local rockspec, err, errcode = fetch.load_rockspec(path.rockspec_file(name, version))
|
||||||
|
if err then
|
||||||
|
return nil, "Failed loading rockspec for installed package: "..err, errcode
|
||||||
|
end
|
||||||
|
|
||||||
|
ok, err, errcode = deps.fulfill_dependencies(rockspec, deps_mode)
|
||||||
|
if err then return nil, err, errcode end
|
||||||
|
|
||||||
|
util.printout()
|
||||||
|
util.printout("Successfully installed dependencies for " ..name.." "..version)
|
||||||
|
|
||||||
|
return name, version
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Driver function for the "install" command.
|
||||||
|
-- @param name string: name of a binary rock. If an URL or pathname
|
||||||
|
-- to a binary rock is given, fetches and installs it. If a rockspec or a
|
||||||
|
-- source rock is given, forwards the request to the "build" command.
|
||||||
|
-- If a package name is given, forwards the request to "search" and,
|
||||||
|
-- if returned a result, installs the matching rock.
|
||||||
|
-- @param version string: When passing a package name, a version number
|
||||||
|
-- may also be given.
|
||||||
|
-- @return boolean or (nil, string, exitcode): True if installation was
|
||||||
|
-- successful, nil and an error message otherwise. exitcode is optionally returned.
|
||||||
|
function install.command(flags, name, version)
|
||||||
|
if type(name) ~= "string" then
|
||||||
|
return nil, "Argument missing. "..util.see_help("install")
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok, err = fs.check_command_permissions(flags)
|
||||||
|
if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end
|
||||||
|
|
||||||
|
if name:match("%.rockspec$") or name:match("%.src%.rock$") then
|
||||||
|
local build = require("luarocks.build")
|
||||||
|
return build.command(flags, name)
|
||||||
|
elseif name:match("%.rock$") then
|
||||||
|
if flags["only-deps"] then
|
||||||
|
ok, err = install.install_binary_rock_deps(name, deps.get_deps_mode(flags))
|
||||||
|
else
|
||||||
|
ok, err = install.install_binary_rock(name, deps.get_deps_mode(flags))
|
||||||
|
end
|
||||||
|
if not ok then return nil, err end
|
||||||
|
name, version = ok, err
|
||||||
|
|
||||||
|
if (not flags["only-deps"]) and (not flags["keep"]) and not cfg.keep_other_versions then
|
||||||
|
local ok, err = remove.remove_other_versions(name, version, flags["force"], flags["force-fast"])
|
||||||
|
if not ok then util.printerr(err) end
|
||||||
|
end
|
||||||
|
|
||||||
|
manif.check_dependencies(nil, deps.get_deps_mode(flags))
|
||||||
|
return name, version
|
||||||
|
else
|
||||||
|
local search = require("luarocks.search")
|
||||||
|
local url, err = search.find_suitable_rock(search.make_query(name:lower(), version))
|
||||||
|
if not url then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
util.printout("Installing "..url)
|
||||||
|
return install.command(flags, url)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return install
|
||||||
55
Utils/luarocks/lua/luarocks/lint.lua
Normal file
55
Utils/luarocks/lua/luarocks/lint.lua
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
|
||||||
|
--- Module implementing the LuaRocks "lint" command.
|
||||||
|
-- Utility function that checks syntax of the rockspec.
|
||||||
|
local lint = {}
|
||||||
|
package.loaded["luarocks.lint"] = lint
|
||||||
|
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local download = require("luarocks.download")
|
||||||
|
local fetch = require("luarocks.fetch")
|
||||||
|
|
||||||
|
util.add_run_function(lint)
|
||||||
|
lint.help_summary = "Check syntax of a rockspec."
|
||||||
|
lint.help_arguments = "<rockspec>"
|
||||||
|
lint.help = [[
|
||||||
|
This is a utility function that checks the syntax of a rockspec.
|
||||||
|
|
||||||
|
It returns success or failure if the text of a rockspec is
|
||||||
|
syntactically correct.
|
||||||
|
]]
|
||||||
|
|
||||||
|
function lint.command(flags, input)
|
||||||
|
if not input then
|
||||||
|
return nil, "Argument missing. "..util.see_help("lint")
|
||||||
|
end
|
||||||
|
|
||||||
|
local filename = input
|
||||||
|
if not input:match(".rockspec$") then
|
||||||
|
local err
|
||||||
|
filename, err = download.download("rockspec", input: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
|
||||||
97
Utils/luarocks/lua/luarocks/list.lua
Normal file
97
Utils/luarocks/lua/luarocks/list.lua
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
|
||||||
|
--- Module implementing the LuaRocks "list" command.
|
||||||
|
-- Lists currently installed rocks.
|
||||||
|
local list = {}
|
||||||
|
package.loaded["luarocks.list"] = list
|
||||||
|
|
||||||
|
local search = require("luarocks.search")
|
||||||
|
local deps = require("luarocks.deps")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
|
||||||
|
util.add_run_function(list)
|
||||||
|
list.help_summary = "List currently installed rocks."
|
||||||
|
list.help_arguments = "[--porcelain] <filter>"
|
||||||
|
list.help = [[
|
||||||
|
<filter> is a substring of a rock name to filter by.
|
||||||
|
|
||||||
|
--outdated List only rocks for which there is a
|
||||||
|
higher version available in the rocks server.
|
||||||
|
|
||||||
|
--porcelain Produce machine-friendly output.
|
||||||
|
]]
|
||||||
|
|
||||||
|
local function check_outdated(trees, query)
|
||||||
|
local results_installed = {}
|
||||||
|
for _, tree in ipairs(trees) do
|
||||||
|
search.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, deps.compare_versions)
|
||||||
|
local latest_installed = versions[1]
|
||||||
|
|
||||||
|
local query_available = search.make_query(name:lower())
|
||||||
|
query.exact_name = true
|
||||||
|
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, deps.compare_versions)
|
||||||
|
local latest_available = available_versions[1]
|
||||||
|
local latest_available_repo = results_available[name][latest_available][1].repo
|
||||||
|
|
||||||
|
if deps.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.
|
||||||
|
-- @param filter string or nil: A substring of a rock name to filter by.
|
||||||
|
-- @param version string or nil: a version may also be passed.
|
||||||
|
-- @return boolean: True if succeeded, nil on errors.
|
||||||
|
function list.command(flags, filter, version)
|
||||||
|
local query = search.make_query(filter and filter:lower() or "", version)
|
||||||
|
query.exact_name = false
|
||||||
|
local trees = cfg.rocks_trees
|
||||||
|
if flags["tree"] then
|
||||||
|
trees = { flags["tree"] }
|
||||||
|
end
|
||||||
|
|
||||||
|
if flags["outdated"] then
|
||||||
|
return list_outdated(trees, query, flags["porcelain"])
|
||||||
|
end
|
||||||
|
|
||||||
|
local results = {}
|
||||||
|
for _, tree in ipairs(trees) do
|
||||||
|
local ok, err, errcode = search.manifest_search(results, path.rocks_dir(tree), query)
|
||||||
|
if not ok and errcode ~= "open" then
|
||||||
|
util.warning(err)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
util.title("Installed rocks:", flags["porcelain"])
|
||||||
|
search.print_results(results, flags["porcelain"])
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return list
|
||||||
249
Utils/luarocks/lua/luarocks/loader.lua
Normal file
249
Utils/luarocks/lua/luarocks/loader.lua
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
|
||||||
|
--- A module which installs a Lua package loader that is LuaRocks-aware.
|
||||||
|
-- This loader uses dependency information from the LuaRocks tree to load
|
||||||
|
-- correct versions of modules. It does this by constructing a "context"
|
||||||
|
-- table in the environment, which records which versions of packages were
|
||||||
|
-- used to load previous modules, so that the loader chooses versions
|
||||||
|
-- that are declared to be compatible with the ones loaded earlier.
|
||||||
|
local loaders = package.loaders or package.searchers
|
||||||
|
local package, require, ipairs, table, type, next, tostring, error =
|
||||||
|
package, require, ipairs, table, type, next, tostring, error
|
||||||
|
local unpack = unpack or table.unpack
|
||||||
|
|
||||||
|
--module("luarocks.loader")
|
||||||
|
local loader = {}
|
||||||
|
package.loaded["luarocks.loader"] = loader
|
||||||
|
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
cfg.init_package_paths()
|
||||||
|
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
local manif_core = require("luarocks.manif_core")
|
||||||
|
local deps = require("luarocks.deps")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
|
||||||
|
-- Workaround for wrappers produced by older versions of LuaRocks
|
||||||
|
local temporary_global = false
|
||||||
|
if luarocks 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.getinfo(2, "nS")
|
||||||
|
if 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 = {}
|
||||||
|
|
||||||
|
-- Contains a table when rocks trees are loaded,
|
||||||
|
-- or 'false' to indicate rocks trees failed to load.
|
||||||
|
-- 'nil' indicates rocks trees were not attempted to be loaded yet.
|
||||||
|
loader.rocks_trees = nil
|
||||||
|
|
||||||
|
local function load_rocks_trees()
|
||||||
|
local any_ok = false
|
||||||
|
local trees = {}
|
||||||
|
for _, tree in ipairs(cfg.rocks_trees) do
|
||||||
|
local manifest, err = manif_core.load_local_manifest(path.rocks_dir(tree))
|
||||||
|
if manifest then
|
||||||
|
any_ok = true
|
||||||
|
table.insert(trees, {tree=tree, manifest=manifest})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not any_ok then
|
||||||
|
loader.rocks_trees = false
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
loader.rocks_trees = trees
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Process the dependencies of a package to determine its dependency
|
||||||
|
-- chain for loading modules.
|
||||||
|
-- @param name string: The name of an installed rock.
|
||||||
|
-- @param version string: The version of the rock, in string format
|
||||||
|
function 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
|
||||||
|
|
||||||
|
if loader.context[name] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
loader.context[name] = version
|
||||||
|
|
||||||
|
if not loader.rocks_trees and not load_rocks_trees() then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, tree in ipairs(loader.rocks_trees) do
|
||||||
|
local manifest = tree.manifest
|
||||||
|
|
||||||
|
local pkgdeps
|
||||||
|
if manifest.dependencies and manifest.dependencies[name] then
|
||||||
|
pkgdeps = manifest.dependencies[name][version]
|
||||||
|
end
|
||||||
|
if not pkgdeps then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
for _, dep in ipairs(pkgdeps) do
|
||||||
|
local pkg, constraints = dep.name, dep.constraints
|
||||||
|
|
||||||
|
for _, tree in ipairs(loader.rocks_trees) do
|
||||||
|
local entries = tree.manifest.repository[pkg]
|
||||||
|
if entries then
|
||||||
|
for version, pkgs in util.sortedpairs(entries, deps.compare_versions) do
|
||||||
|
if (not constraints) or deps.match_constraints(deps.parse_version(version), constraints) then
|
||||||
|
loader.add_context(pkg, version)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Internal sorting function.
|
||||||
|
-- @param a table: A provider table.
|
||||||
|
-- @param b table: Another provider table.
|
||||||
|
-- @return boolean: True if the version of a is greater than that of b.
|
||||||
|
local function sort_versions(a,b)
|
||||||
|
return a.version > b.version
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Request module to be loaded through other loaders,
|
||||||
|
-- once the proper name of the module has been determined.
|
||||||
|
-- For example, in case the module "socket.core" has been requested
|
||||||
|
-- to the LuaRocks loader and it determined based on context that
|
||||||
|
-- the version 2.0.2 needs to be loaded and it is not the current
|
||||||
|
-- version, the module requested for the other loaders will be
|
||||||
|
-- "socket.core_2_0_2".
|
||||||
|
-- @param module The module name requested by the user, such as "socket.core"
|
||||||
|
-- @param name The rock name, such as "luasocket"
|
||||||
|
-- @param version The rock version, such as "2.0.2-1"
|
||||||
|
-- @param module_name The actual module name, such as "socket.core" or "socket.core_2_0_2".
|
||||||
|
-- @return table or (nil, string): The module table as returned by some other loader,
|
||||||
|
-- or nil followed by an error message if no other loader managed to load the module.
|
||||||
|
local function call_other_loaders(module, name, version, module_name)
|
||||||
|
for i, 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
|
||||||
|
|
||||||
|
--- 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 `rocks_trees` format)
|
||||||
|
local function select_module(module, filter_file_name)
|
||||||
|
--assert(type(module) == "string")
|
||||||
|
--assert(type(filter_module_name) == "function")
|
||||||
|
|
||||||
|
if not loader.rocks_trees and not load_rocks_trees() then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local providers = {}
|
||||||
|
for _, tree in ipairs(loader.rocks_trees) do
|
||||||
|
local entries = tree.manifest.modules[module]
|
||||||
|
if entries then
|
||||||
|
for i, entry in ipairs(entries) do
|
||||||
|
local name, version = entry:match("^([^/]*)/(.*)$")
|
||||||
|
local 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 = deps.parse_version(version)
|
||||||
|
table.insert(providers, {name = name, version = version, module_name = file_name, tree = tree})
|
||||||
|
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 `rocks_trees` 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 string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so")
|
||||||
|
function loader.which(module)
|
||||||
|
local _, _, file_name = select_module(module, path.which_i)
|
||||||
|
return file_name
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Package loader for LuaRocks support.
|
||||||
|
-- A module is searched in installed rocks that match the
|
||||||
|
-- current LuaRocks context. If module is not part of the
|
||||||
|
-- context, or if a context has not yet been set, the module
|
||||||
|
-- in the package with the highest version is used.
|
||||||
|
-- @param module string: The module name, like in plain require().
|
||||||
|
-- @return table: The module table (typically), like in plain
|
||||||
|
-- require(). See <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)
|
||||||
|
|
||||||
|
return loader
|
||||||
92
Utils/luarocks/lua/luarocks/make.lua
Normal file
92
Utils/luarocks/lua/luarocks/make.lua
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
|
||||||
|
--- 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 = {}
|
||||||
|
package.loaded["luarocks.make"] = make
|
||||||
|
|
||||||
|
local build = require("luarocks.build")
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local fetch = require("luarocks.fetch")
|
||||||
|
local pack = require("luarocks.pack")
|
||||||
|
local remove = require("luarocks.remove")
|
||||||
|
local deps = require("luarocks.deps")
|
||||||
|
local manif = require("luarocks.manif")
|
||||||
|
|
||||||
|
util.add_run_function(make)
|
||||||
|
make.help_summary = "Compile package in current directory using a rockspec."
|
||||||
|
make.help_arguments = "[--pack-binary-rock] [<rockspec>]"
|
||||||
|
make.help = [[
|
||||||
|
Builds sources in the current directory, but unlike "build",
|
||||||
|
it does not fetch sources, etc., assuming everything is
|
||||||
|
available in the current directory. If no argument is given,
|
||||||
|
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.
|
||||||
|
|
||||||
|
--pack-binary-rock Do not install rock. Instead, produce a .rock file
|
||||||
|
with the contents of compilation in the current
|
||||||
|
directory.
|
||||||
|
|
||||||
|
--keep Do not remove previously installed versions of the
|
||||||
|
rock after installing a new one. This behavior can
|
||||||
|
be made permanent by setting keep_other_versions=true
|
||||||
|
in the configuration file.
|
||||||
|
|
||||||
|
--branch=<name> Override the `source.branch` field in the loaded
|
||||||
|
rockspec. Allows to specify a different branch to
|
||||||
|
fetch. Particularly for SCM rocks.
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
--- Driver function for "make" command.
|
||||||
|
-- @param name string: A local rockspec.
|
||||||
|
-- @return boolean or (nil, string, exitcode): True if build was successful; nil and an
|
||||||
|
-- error message otherwise. exitcode is optionally returned.
|
||||||
|
function make.command(flags, rockspec)
|
||||||
|
assert(type(rockspec) == "string" or not rockspec)
|
||||||
|
|
||||||
|
if not rockspec then
|
||||||
|
local err
|
||||||
|
rockspec, err = util.get_default_rockspec()
|
||||||
|
if not rockspec then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not rockspec:match("rockspec$") then
|
||||||
|
return nil, "Invalid argument: 'make' takes a rockspec as a parameter. "..util.see_help("make")
|
||||||
|
end
|
||||||
|
|
||||||
|
if flags["pack-binary-rock"] then
|
||||||
|
local rspec, err, errcode = fetch.load_rockspec(rockspec)
|
||||||
|
if not rspec then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
return pack.pack_binary_rock(rspec.name, rspec.version, build.build_rockspec, rockspec, false, true, deps.get_deps_mode(flags))
|
||||||
|
else
|
||||||
|
local ok, err = fs.check_command_permissions(flags)
|
||||||
|
if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end
|
||||||
|
ok, err = build.build_rockspec(rockspec, false, true, deps.get_deps_mode(flags))
|
||||||
|
if not ok then return nil, err end
|
||||||
|
local name, version = ok, err
|
||||||
|
|
||||||
|
if (not flags["keep"]) and not cfg.keep_other_versions then
|
||||||
|
local ok, err = remove.remove_other_versions(name, version, flags["force"], flags["force-fast"])
|
||||||
|
if not ok then util.printerr(err) end
|
||||||
|
end
|
||||||
|
|
||||||
|
manif.check_dependencies(nil, deps.get_deps_mode(flags))
|
||||||
|
return name, version
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return make
|
||||||
53
Utils/luarocks/lua/luarocks/make_manifest.lua
Normal file
53
Utils/luarocks/lua/luarocks/make_manifest.lua
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
|
||||||
|
--- Module implementing the luarocks-admin "make_manifest" command.
|
||||||
|
-- Compile a manifest file for a repository.
|
||||||
|
local make_manifest = {}
|
||||||
|
package.loaded["luarocks.make_manifest"] = make_manifest
|
||||||
|
|
||||||
|
local manif = require("luarocks.manif")
|
||||||
|
local index = require("luarocks.index")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local deps = require("luarocks.deps")
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
|
||||||
|
util.add_run_function(make_manifest)
|
||||||
|
make_manifest.help_summary = "Compile a manifest file for a repository."
|
||||||
|
|
||||||
|
make_manifest.help = [[
|
||||||
|
<argument>, if given, is a local repository pathname.
|
||||||
|
|
||||||
|
--local-tree If given, do not write versioned versions of the manifest file.
|
||||||
|
Use this when rebuilding the manifest of a local rocks tree.
|
||||||
|
]]
|
||||||
|
|
||||||
|
--- Driver function for "make_manifest" command.
|
||||||
|
-- @param repo string or nil: Pathname of a local repository. If not given,
|
||||||
|
-- the default local repository configured as cfg.rocks_dir is used.
|
||||||
|
-- @return boolean or (nil, string): True if manifest was generated,
|
||||||
|
-- or nil and an error message.
|
||||||
|
function make_manifest.command(flags, repo)
|
||||||
|
assert(type(repo) == "string" or not repo)
|
||||||
|
repo = repo or cfg.rocks_dir
|
||||||
|
|
||||||
|
util.printout("Making manifest for "..repo)
|
||||||
|
|
||||||
|
if repo:match("/lib/luarocks") and not flags["local-tree"] then
|
||||||
|
util.warning("This looks like a local rocks tree, but you did not pass --local-tree.")
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok, err = manif.make_manifest(repo, deps.get_deps_mode(flags), not flags["local-tree"])
|
||||||
|
if ok and not flags["local-tree"] then
|
||||||
|
util.printout("Generating index.html for "..repo)
|
||||||
|
index.make_index(repo)
|
||||||
|
end
|
||||||
|
if flags["local-tree"] then
|
||||||
|
for luaver in util.lua_versions() do
|
||||||
|
fs.delete(dir.path(repo, "manifest-"..luaver))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ok, err
|
||||||
|
end
|
||||||
|
|
||||||
|
return make_manifest
|
||||||
628
Utils/luarocks/lua/luarocks/manif.lua
Normal file
628
Utils/luarocks/lua/luarocks/manif.lua
Normal file
@ -0,0 +1,628 @@
|
|||||||
|
--- 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 = {}
|
||||||
|
package.loaded["luarocks.manif"] = manif
|
||||||
|
|
||||||
|
local manif_core = require("luarocks.manif_core")
|
||||||
|
local persist = require("luarocks.persist")
|
||||||
|
local fetch = require("luarocks.fetch")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local search = require("luarocks.search")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
local repos = require("luarocks.repos")
|
||||||
|
local deps = require("luarocks.deps")
|
||||||
|
|
||||||
|
manif.rock_manifest_cache = {}
|
||||||
|
|
||||||
|
--- Commit a table to disk in given local path.
|
||||||
|
-- @param where string: The directory where the table should be saved.
|
||||||
|
-- @param name string: The filename.
|
||||||
|
-- @param tbl table: The table to be saved.
|
||||||
|
-- @return boolean or (nil, string): true if successful, or nil and a
|
||||||
|
-- message in case of errors.
|
||||||
|
local function save_table(where, name, tbl)
|
||||||
|
assert(type(where) == "string")
|
||||||
|
assert(type(name) == "string")
|
||||||
|
assert(type(tbl) == "table")
|
||||||
|
|
||||||
|
local filename = dir.path(where, name)
|
||||||
|
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 manif.load_rock_manifest(name, version, root)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
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 end
|
||||||
|
manif.rock_manifest_cache[name_version] = rock_manifest
|
||||||
|
return rock_manifest.rock_manifest
|
||||||
|
end
|
||||||
|
|
||||||
|
function manif.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 name in file:gmatch("[^/]+") do
|
||||||
|
local next = walk[name]
|
||||||
|
if not next then
|
||||||
|
next = {}
|
||||||
|
walk[name] = next
|
||||||
|
end
|
||||||
|
last = walk
|
||||||
|
last_name = name
|
||||||
|
walk = next
|
||||||
|
end
|
||||||
|
if fs.is_file(full_path) then
|
||||||
|
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 )
|
||||||
|
end
|
||||||
|
|
||||||
|
local function fetch_manifest_from(repo_url, filename)
|
||||||
|
local url = dir.path(repo_url, filename)
|
||||||
|
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
|
||||||
|
return nil, "Failed creating temporary cache directory "..cache_dir
|
||||||
|
end
|
||||||
|
local file, err, errcode = fetch.fetch_url(url, dir.path(cache_dir, filename), true)
|
||||||
|
if not file then
|
||||||
|
return nil, "Failed fetching manifest for "..repo_url..(err and " - "..err or ""), errcode
|
||||||
|
end
|
||||||
|
return file
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Load a local or remote manifest describing a repository.
|
||||||
|
-- All functions that use manifest tables assume they were obtained
|
||||||
|
-- through either this function or load_local_manifest.
|
||||||
|
-- @param repo_url string: URL or pathname for the repository.
|
||||||
|
-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
|
||||||
|
-- @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)
|
||||||
|
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 = manif_core.get_cached_manifest(repo_url, lua_version)
|
||||||
|
if cached_manifest then
|
||||||
|
return cached_manifest
|
||||||
|
end
|
||||||
|
|
||||||
|
local filenames = {
|
||||||
|
"manifest-"..lua_version..".zip",
|
||||||
|
"manifest-"..lua_version,
|
||||||
|
"manifest",
|
||||||
|
}
|
||||||
|
|
||||||
|
local protocol, repodir = dir.split_url(repo_url)
|
||||||
|
local pathname
|
||||||
|
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 = fetch_manifest_from(repo_url, filename)
|
||||||
|
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 dir = dir.dir_name(pathname)
|
||||||
|
fs.change_dir(dir)
|
||||||
|
local nozip = pathname:match("(.*)%.zip$")
|
||||||
|
fs.delete(nozip)
|
||||||
|
local ok = fs.unzip(pathname)
|
||||||
|
fs.pop_dir()
|
||||||
|
if not ok then
|
||||||
|
fs.delete(pathname)
|
||||||
|
fs.delete(pathname..".timestamp")
|
||||||
|
return nil, "Failed extracting manifest file"
|
||||||
|
end
|
||||||
|
pathname = nozip
|
||||||
|
end
|
||||||
|
return manif_core.manifest_loader(pathname, repo_url, lua_version)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- 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")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
|
||||||
|
local package_identifier = name.."/"..version
|
||||||
|
|
||||||
|
for item_name, path in pairs(items) do
|
||||||
|
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")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
|
||||||
|
local package_identifier = name.."/"..version
|
||||||
|
|
||||||
|
for item_name, path in pairs(items) do
|
||||||
|
local all_identifiers = storage[item_name]
|
||||||
|
|
||||||
|
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[item_name] = nil
|
||||||
|
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 deps.compare_versions(va, vb) or na < nb
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Sort items of a package matching table by version number (higher versions first).
|
||||||
|
-- @param tbl table: the package matching table: keys should be strings
|
||||||
|
-- and values arrays of strings with packages names in "name/version" format.
|
||||||
|
local function sort_package_matching_table(tbl)
|
||||||
|
assert(type(tbl) == "table")
|
||||||
|
|
||||||
|
if next(tbl) then
|
||||||
|
for item, pkgs in pairs(tbl) do
|
||||||
|
if #pkgs > 1 then
|
||||||
|
table.sort(pkgs, sort_pkgs)
|
||||||
|
-- Remove duplicates from the sorted array.
|
||||||
|
local prev = nil
|
||||||
|
local i = 1
|
||||||
|
while pkgs[i] do
|
||||||
|
local curr = pkgs[i]
|
||||||
|
if curr == prev then
|
||||||
|
table.remove(pkgs, i)
|
||||||
|
else
|
||||||
|
prev = curr
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Process the dependencies of a manifest table to determine its dependency
|
||||||
|
-- chains for loading modules. The manifest dependencies information is filled
|
||||||
|
-- and any dependency inconsistencies or missing dependencies are reported to
|
||||||
|
-- standard error.
|
||||||
|
-- @param manifest table: a manifest table.
|
||||||
|
-- @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
|
||||||
|
|
||||||
|
--- Filter manifest table by Lua version, removing rockspecs whose Lua version
|
||||||
|
-- does not match.
|
||||||
|
-- @param manifest table: a manifest table.
|
||||||
|
-- @param lua_version string or nil: filter by Lua version
|
||||||
|
-- @param repodir string: directory of repository being scanned
|
||||||
|
-- @param cache table: temporary rockspec cache table
|
||||||
|
local function filter_by_lua_version(manifest, lua_version, repodir, cache)
|
||||||
|
assert(type(manifest) == "table")
|
||||||
|
assert(type(repodir) == "string")
|
||||||
|
assert((not cache) or type(cache) == "table")
|
||||||
|
|
||||||
|
cache = cache or {}
|
||||||
|
lua_version = deps.parse_version(lua_version)
|
||||||
|
for pkg, versions in pairs(manifest.repository) do
|
||||||
|
local to_remove = {}
|
||||||
|
for version, repositories in pairs(versions) do
|
||||||
|
for _, repo in ipairs(repositories) do
|
||||||
|
if repo.arch == "rockspec" then
|
||||||
|
local pathname = dir.path(repodir, pkg.."-"..version..".rockspec")
|
||||||
|
local rockspec, err = cache[pathname]
|
||||||
|
if not rockspec then
|
||||||
|
rockspec, err = fetch.load_local_rockspec(pathname, true)
|
||||||
|
end
|
||||||
|
if rockspec then
|
||||||
|
cache[pathname] = rockspec
|
||||||
|
for _, dep in ipairs(rockspec.dependencies) do
|
||||||
|
if dep.name == "lua" then
|
||||||
|
if not deps.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 = manif.load_rock_manifest(name, version)
|
||||||
|
if not rock_manifest then
|
||||||
|
return nil, "rock_manifest file not found for "..name.." "..version.." - not a LuaRocks 2 tree?"
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
--- 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 manif.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 = search.make_query("")
|
||||||
|
query.exact_name = false
|
||||||
|
query.arch = "any"
|
||||||
|
local results = search.disk_search(repo, query)
|
||||||
|
local manifest = { repository = {}, modules = {}, commands = {} }
|
||||||
|
|
||||||
|
manif_core.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)
|
||||||
|
save_table(repo, "manifest-"..luaver, vmanifest)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
update_dependencies(manifest, deps_mode)
|
||||||
|
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 manif.add_to_manifest(name, version, repo, deps_mode)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
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_core.load_local_manifest(rocks_dir)
|
||||||
|
if not manifest then
|
||||||
|
util.printerr("No existing manifest. Attempting to rebuild...")
|
||||||
|
-- Manifest built by `manif.make_manifest` should already
|
||||||
|
-- include information about given name and version,
|
||||||
|
-- no need to update it.
|
||||||
|
return manif.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)
|
||||||
|
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 manif.remove_from_manifest(name, version, repo, deps_mode)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
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_core.load_local_manifest(rocks_dir)
|
||||||
|
if not manifest then
|
||||||
|
util.printerr("No existing manifest. Attempting to rebuild...")
|
||||||
|
-- Manifest built by `manif.make_manifest` should already
|
||||||
|
-- include up-to-date information, no need to update it.
|
||||||
|
return manif.make_manifest(rocks_dir, deps_mode)
|
||||||
|
end
|
||||||
|
|
||||||
|
local package_entry = manifest.repository[name]
|
||||||
|
|
||||||
|
local version_entry = package_entry[version][1]
|
||||||
|
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)
|
||||||
|
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 manif.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_core.load_local_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, deps.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)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function manif.zip_manifests()
|
||||||
|
for ver in util.lua_versions() do
|
||||||
|
local file = "manifest-"..ver
|
||||||
|
local zip = file..".zip"
|
||||||
|
fs.delete(dir.path(fs.current_dir(), zip))
|
||||||
|
fs.zip(zip, file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- 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_core.load_local_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
|
||||||
|
|
||||||
|
--- Given a name of a module or a command provided by a package, figure out
|
||||||
|
-- which file provides it.
|
||||||
|
-- @param name string: package name.
|
||||||
|
-- @param version string: package version.
|
||||||
|
-- @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): rock manifest subtree the file comes from ("bin", "lua", or "lib")
|
||||||
|
-- and path to the providing file relatively to that subtree.
|
||||||
|
function manif.get_providing_file(name, version, item_type, item_name, repo)
|
||||||
|
local rocks_dir = path.rocks_dir(repo or cfg.root_dir)
|
||||||
|
local manifest = manif_core.load_local_manifest(rocks_dir)
|
||||||
|
|
||||||
|
local entry_table = manifest.repository[name][version][1]
|
||||||
|
local file_path = entry_table[item_type .. "s"][item_name]
|
||||||
|
|
||||||
|
if item_type == "command" then
|
||||||
|
return "bin", file_path
|
||||||
|
end
|
||||||
|
|
||||||
|
-- A module can be in "lua" or "lib". Decide based on extension first:
|
||||||
|
-- most likely Lua modules are in "lua/" and C modules are in "lib/".
|
||||||
|
if file_path:match("%." .. cfg.lua_extension .. "$") then
|
||||||
|
return "lua", file_path
|
||||||
|
elseif file_path:match("%." .. cfg.lib_extension .. "$") then
|
||||||
|
return "lib", file_path
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Fallback to rock manifest scanning.
|
||||||
|
local rock_manifest = manif.load_rock_manifest(name, version)
|
||||||
|
local subtree = rock_manifest.lib
|
||||||
|
|
||||||
|
for path_part in file_path:gmatch("[^/]+") do
|
||||||
|
if type(subtree) == "table" then
|
||||||
|
subtree = subtree[path_part]
|
||||||
|
else
|
||||||
|
-- Assume it's in "lua/" if it's not in "lib/".
|
||||||
|
return "lua", file_path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return type(subtree) == "string" and "lib" or "lua", file_path
|
||||||
|
end
|
||||||
|
|
||||||
|
return manif
|
||||||
106
Utils/luarocks/lua/luarocks/manif_core.lua
Normal file
106
Utils/luarocks/lua/luarocks/manif_core.lua
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
|
||||||
|
--- Core functions for querying manifest files.
|
||||||
|
-- This module requires no specific 'fs' functionality.
|
||||||
|
local manif_core = {}
|
||||||
|
package.loaded["luarocks.manif_core"] = manif_core
|
||||||
|
|
||||||
|
local persist = require("luarocks.persist")
|
||||||
|
local type_check = require("luarocks.type_check")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
|
||||||
|
-- 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_core.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_core.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.
|
||||||
|
-- @param quick boolean: If given, skips type checking.
|
||||||
|
-- @return table or (nil, string, string): the manifest or nil,
|
||||||
|
-- error message and error code ("open", "load", "run" or "type").
|
||||||
|
function manif_core.manifest_loader(file, repo_url, lua_version, quick)
|
||||||
|
local manifest, err, errcode = persist.load_into_table(file)
|
||||||
|
if not manifest then
|
||||||
|
return nil, "Failed loading manifest for "..repo_url..": "..err, errcode
|
||||||
|
end
|
||||||
|
local globals = err
|
||||||
|
if not quick then
|
||||||
|
local ok, err = type_check.type_check_manifest(manifest, globals)
|
||||||
|
if not ok then
|
||||||
|
return nil, "Error checking manifest: "..err, "type"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
manif_core.cache_manifest(repo_url, lua_version, manifest)
|
||||||
|
return manifest
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Load a local manifest describing a repository.
|
||||||
|
-- All functions that use manifest tables assume they were obtained
|
||||||
|
-- through either this function or load_manifest.
|
||||||
|
-- @param repo_url string: URL or pathname for the repository.
|
||||||
|
-- @return table or (nil, string, string): A table representing the manifest,
|
||||||
|
-- or nil followed by an error message and an error code, see manifest_loader.
|
||||||
|
function manif_core.load_local_manifest(repo_url)
|
||||||
|
assert(type(repo_url) == "string")
|
||||||
|
|
||||||
|
local cached_manifest = manif_core.get_cached_manifest(repo_url)
|
||||||
|
if cached_manifest then
|
||||||
|
return cached_manifest
|
||||||
|
end
|
||||||
|
|
||||||
|
local pathname = dir.path(repo_url, "manifest")
|
||||||
|
return manif_core.manifest_loader(pathname, repo_url, nil, true)
|
||||||
|
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.
|
||||||
|
function manif_core.get_versions(name, deps_mode)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
assert(type(deps_mode) == "string")
|
||||||
|
|
||||||
|
local version_set = {}
|
||||||
|
path.map_trees(deps_mode, function(tree)
|
||||||
|
local manifest = manif_core.load_local_manifest(path.rocks_dir(tree))
|
||||||
|
|
||||||
|
if manifest and manifest.repository[name] then
|
||||||
|
for version in pairs(manifest.repository[name]) do
|
||||||
|
version_set[version] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
return util.keys(version_set)
|
||||||
|
end
|
||||||
|
|
||||||
|
return manif_core
|
||||||
200
Utils/luarocks/lua/luarocks/new_version.lua
Normal file
200
Utils/luarocks/lua/luarocks/new_version.lua
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
|
||||||
|
--- 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 type_check = require("luarocks.type_check")
|
||||||
|
|
||||||
|
util.add_run_function(new_version)
|
||||||
|
new_version.help_summary = "Auto-write a rockspec for a new version of a rock."
|
||||||
|
new_version.help_arguments = "[--tag=<tag>] [<package>|<rockspec>] [<new_version>] [<new_url>]"
|
||||||
|
new_version.help = [[
|
||||||
|
This is a utility function that writes a new rockspec, updating data
|
||||||
|
from a previous one.
|
||||||
|
|
||||||
|
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. 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.
|
||||||
|
|
||||||
|
WARNING: it writes the new rockspec to the current directory,
|
||||||
|
overwriting the file if it already exists.
|
||||||
|
]]
|
||||||
|
|
||||||
|
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)
|
||||||
|
local file, temp_dir = fetch.fetch_url_at_temp_dir(out_rs.source.url, "luarocks-new-version-"..out_rs.package)
|
||||||
|
if not file then
|
||||||
|
util.printerr("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
|
||||||
|
if try_replace(out_rs.source, "url", old_ver, new_ver) then
|
||||||
|
return check_url_and_update_md5(out_rs)
|
||||||
|
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.printerr("Warning: URL is the same, but MD5 has changed. Old rockspec is broken.")
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function new_version.command(flags, input, version, url)
|
||||||
|
if not input then
|
||||||
|
local err
|
||||||
|
input, err = util.get_default_rockspec()
|
||||||
|
if not input then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
assert(type(input) == "string")
|
||||||
|
|
||||||
|
local filename, err
|
||||||
|
if input:match("rockspec$") then
|
||||||
|
filename, err = fetch.fetch_url(input)
|
||||||
|
if not filename then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
else
|
||||||
|
filename, err = download.download("rockspec", input: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 flags.tag and not version then
|
||||||
|
version = flags.tag:gsub("^v", "")
|
||||||
|
end
|
||||||
|
|
||||||
|
if version then
|
||||||
|
new_ver, new_rev = version:match("(.*)%-(%d+)$")
|
||||||
|
new_rev = tonumber(new_rev)
|
||||||
|
if not new_rev then
|
||||||
|
new_ver = version
|
||||||
|
new_rev = 1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
new_ver = old_ver
|
||||||
|
new_rev = tonumber(old_rev) + 1
|
||||||
|
end
|
||||||
|
local 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, url, flags.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"
|
||||||
|
|
||||||
|
persist.save_from_table(out_filename, out_rs, type_check.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
|
||||||
197
Utils/luarocks/lua/luarocks/pack.lua
Normal file
197
Utils/luarocks/lua/luarocks/pack.lua
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
|
||||||
|
--- Module implementing the LuaRocks "pack" command.
|
||||||
|
-- Creates a rock, packing sources or binaries.
|
||||||
|
local pack = {}
|
||||||
|
package.loaded["luarocks.pack"] = pack
|
||||||
|
|
||||||
|
local unpack = unpack or table.unpack
|
||||||
|
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
local repos = require("luarocks.repos")
|
||||||
|
local fetch = require("luarocks.fetch")
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local manif = require("luarocks.manif")
|
||||||
|
local search = require("luarocks.search")
|
||||||
|
|
||||||
|
util.add_run_function(pack)
|
||||||
|
pack.help_summary = "Create a rock, packing sources or binaries."
|
||||||
|
pack.help_arguments = "{<rockspec>|<name> [<version>]}"
|
||||||
|
pack.help = [[
|
||||||
|
Argument may be a rockspec file, for creating a source rock,
|
||||||
|
or the name of an installed package, for creating a binary rock.
|
||||||
|
In the latter case, the app version may be given as a second
|
||||||
|
argument.
|
||||||
|
]]
|
||||||
|
|
||||||
|
--- Create a source rock.
|
||||||
|
-- Packages a rockspec and its required source files in a rock
|
||||||
|
-- file with the .src.rock extension, which can later be built and
|
||||||
|
-- installed with the "build" command.
|
||||||
|
-- @param rockspec_file string: An URL or pathname for a rockspec file.
|
||||||
|
-- @return string or (nil, string): The filename of the resulting
|
||||||
|
-- .src.rock file; or nil and an error message.
|
||||||
|
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_filename
|
||||||
|
|
||||||
|
local name_version = rockspec.name .. "-" .. rockspec.version
|
||||||
|
local rock_file = fs.absolute_name(name_version .. ".src.rock")
|
||||||
|
|
||||||
|
local source_file, source_dir = fetch.fetch_sources(rockspec, false)
|
||||||
|
if not source_file then
|
||||||
|
return nil, source_dir
|
||||||
|
end
|
||||||
|
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, cfg.perm_read)
|
||||||
|
if not fs.zip(rock_file, dir.base_name(rockspec_file), dir.base_name(source_file)) then
|
||||||
|
return nil, "Failed packing "..rock_file
|
||||||
|
end
|
||||||
|
fs.pop_dir()
|
||||||
|
|
||||||
|
return rock_file
|
||||||
|
end
|
||||||
|
|
||||||
|
local function copy_back_files(name, version, file_tree, deploy_dir, pack_dir, 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.
|
||||||
|
local function do_pack_binary_rock(name, version, tree)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
assert(type(version) == "string" or not version)
|
||||||
|
|
||||||
|
local repo, repo_url
|
||||||
|
name, version, repo, repo_url = search.pick_installed_rock(name, version, tree)
|
||||||
|
if not name then
|
||||||
|
return nil, version
|
||||||
|
end
|
||||||
|
|
||||||
|
local root = path.root_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 = manif.load_rock_manifest(name, version, root)
|
||||||
|
if not rock_manifest then
|
||||||
|
return nil, "rock_manifest file not found for "..name.." "..version.." - not a LuaRocks 2 tree?"
|
||||||
|
end
|
||||||
|
|
||||||
|
local name_version = name .. "-" .. version
|
||||||
|
local rock_file = fs.absolute_name(name_version .. "."..cfg.arch..".rock")
|
||||||
|
|
||||||
|
local temp_dir = fs.make_temp_dir("pack")
|
||||||
|
fs.copy_contents(prefix, temp_dir)
|
||||||
|
|
||||||
|
local is_binary = false
|
||||||
|
if rock_manifest.lib then
|
||||||
|
local ok, err = copy_back_files(name, version, rock_manifest.lib, path.deploy_lib_dir(root), dir.path(temp_dir, "lib"), cfg.perm_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(root), dir.path(temp_dir, "lua"), cfg.perm_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.pack_binary_rock(name, version, cmd, ...)
|
||||||
|
|
||||||
|
-- The --pack-binary-rock option for "luarocks build" basically performs
|
||||||
|
-- "luarocks build" on a temporary tree and then "luarocks pack". The
|
||||||
|
-- alternative would require refactoring parts of luarocks.build and
|
||||||
|
-- luarocks.pack, which would save a few file operations: the idea would be
|
||||||
|
-- to shave off the final deploy steps from the build phase and the initial
|
||||||
|
-- collect steps from the pack phase.
|
||||||
|
|
||||||
|
local temp_dir, 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
|
||||||
|
return do_pack_binary_rock(rname, rversion, temp_dir)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Driver function for the "pack" command.
|
||||||
|
-- @param arg string: may be a rockspec file, for creating a source rock,
|
||||||
|
-- or the name of an installed package, for creating a binary rock.
|
||||||
|
-- @param version string or nil: if the name of a package is given, a
|
||||||
|
-- version may also be passed.
|
||||||
|
-- @return boolean or (nil, string): true if successful or nil followed
|
||||||
|
-- by an error message.
|
||||||
|
function pack.command(flags, arg, version)
|
||||||
|
assert(type(version) == "string" or not version)
|
||||||
|
if type(arg) ~= "string" then
|
||||||
|
return nil, "Argument missing. "..util.see_help("pack")
|
||||||
|
end
|
||||||
|
|
||||||
|
local file, err
|
||||||
|
if arg:match(".*%.rockspec") then
|
||||||
|
file, err = pack.pack_source_rock(arg)
|
||||||
|
else
|
||||||
|
file, err = do_pack_binary_rock(arg:lower(), version, flags["tree"])
|
||||||
|
end
|
||||||
|
if err then
|
||||||
|
return nil, err
|
||||||
|
else
|
||||||
|
util.printout("Packed: "..file)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return pack
|
||||||
388
Utils/luarocks/lua/luarocks/path.lua
Normal file
388
Utils/luarocks/lua/luarocks/path.lua
Normal file
@ -0,0 +1,388 @@
|
|||||||
|
|
||||||
|
--- 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 dir = require("luarocks.dir")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
|
||||||
|
--- 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.rocks_dir(tree)
|
||||||
|
if type(tree) == "string" then
|
||||||
|
return dir.path(tree, cfg.rocks_subdir)
|
||||||
|
else
|
||||||
|
assert(type(tree) == "table")
|
||||||
|
return tree.rocks_dir or dir.path(tree.root, cfg.rocks_subdir)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function path.root_dir(rocks_dir)
|
||||||
|
assert(type(rocks_dir) == "string")
|
||||||
|
return rocks_dir:match("(.*)" .. util.matchquote(cfg.rocks_subdir) .. ".*$")
|
||||||
|
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
|
||||||
|
|
||||||
|
function path.deploy_bin_dir(tree)
|
||||||
|
if type(tree) == "string" then
|
||||||
|
return dir.path(tree, "bin")
|
||||||
|
else
|
||||||
|
assert(type(tree) == "table")
|
||||||
|
return tree.bin_dir or dir.path(tree.root, "bin")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function 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
|
||||||
|
|
||||||
|
function path.manifest_file(tree)
|
||||||
|
if type(tree) == "string" then
|
||||||
|
return dir.path(tree, cfg.rocks_subdir, "manifest")
|
||||||
|
else
|
||||||
|
assert(type(tree) == "table")
|
||||||
|
return (tree.rocks_dir and dir.path(tree.rocks_dir, "manifest")) or dir.path(tree.root, cfg.rocks_subdir, "manifest")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the directory for all versions of a package in a tree.
|
||||||
|
-- @param name string: The package name.
|
||||||
|
-- @return string: The resulting path -- does not guarantee that
|
||||||
|
-- @param tree string or nil: If given, specifies the local tree to use.
|
||||||
|
-- the package (and by extension, the path) exists.
|
||||||
|
function path.versions_dir(name, tree)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
tree = tree or cfg.root_dir
|
||||||
|
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")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
tree = tree or cfg.root_dir
|
||||||
|
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")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
tree = tree or cfg.root_dir
|
||||||
|
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")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
tree = tree or cfg.root_dir
|
||||||
|
return dir.path(path.rocks_dir(tree), name, version, "rock_manifest")
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the local installation directory for C libraries of a package.
|
||||||
|
-- @param name string: The package name.
|
||||||
|
-- @param version string: The package version.
|
||||||
|
-- @param tree string or nil: If given, specifies the local tree to use.
|
||||||
|
-- @return string: The resulting path -- does not guarantee that
|
||||||
|
-- the package (and by extension, the path) exists.
|
||||||
|
function path.lib_dir(name, version, tree)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
tree = tree or cfg.root_dir
|
||||||
|
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")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
tree = tree or cfg.root_dir
|
||||||
|
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")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
tree = tree or cfg.root_dir
|
||||||
|
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")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
tree = tree or cfg.root_dir
|
||||||
|
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")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
tree = tree or cfg.root_dir
|
||||||
|
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")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
assert(type(arch) == "string")
|
||||||
|
|
||||||
|
local filename = name.."-"..version
|
||||||
|
if arch == "installed" then
|
||||||
|
filename = dir.path(name, version, filename..".rockspec")
|
||||||
|
elseif arch == "rockspec" then
|
||||||
|
filename = filename..".rockspec"
|
||||||
|
else
|
||||||
|
filename = filename.."."..arch..".rock"
|
||||||
|
end
|
||||||
|
return dir.path(pathname, filename)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Convert a pathname to a module identifier.
|
||||||
|
-- In Unix, for example, a path "foo/bar/baz.lua" is converted to
|
||||||
|
-- "foo.bar.baz"; "bla/init.lua" returns "bla"; "foo.so" returns "foo".
|
||||||
|
-- @param file string: Pathname of module
|
||||||
|
-- @return string: The module identifier, or nil if given path is
|
||||||
|
-- not a conformant module path (the function does not check if the
|
||||||
|
-- path actually exists).
|
||||||
|
function path.path_to_module(file)
|
||||||
|
assert(type(file) == "string")
|
||||||
|
|
||||||
|
local name = file:match("(.*)%."..cfg.lua_extension.."$")
|
||||||
|
if name then
|
||||||
|
name = name:gsub(dir.separator, ".")
|
||||||
|
local init = name:match("(.*)%.init$")
|
||||||
|
if init then
|
||||||
|
name = init
|
||||||
|
end
|
||||||
|
else
|
||||||
|
name = file:match("(.*)%."..cfg.lib_extension.."$")
|
||||||
|
if name then
|
||||||
|
name = name:gsub(dir.separator, ".")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not name then name = file end
|
||||||
|
name = name:gsub("^%.+", ""):gsub("%.+$", "")
|
||||||
|
return name
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Obtain the directory name where a module should be stored.
|
||||||
|
-- For example, on Unix, "foo.bar.baz" will return "foo/bar".
|
||||||
|
-- @param mod string: A module name in Lua dot-separated format.
|
||||||
|
-- @return string: A directory name using the platform's separator.
|
||||||
|
function path.module_to_path(mod)
|
||||||
|
assert(type(mod) == "string")
|
||||||
|
return (mod:gsub("[^.]*$", ""):gsub("%.", dir.separator))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set up path-related variables for a given rock.
|
||||||
|
-- Create a "variables" table in the rockspec table, containing
|
||||||
|
-- adjusted variables according to the configuration file.
|
||||||
|
-- @param rockspec table: The rockspec table.
|
||||||
|
function path.configure_paths(rockspec)
|
||||||
|
assert(type(rockspec) == "table")
|
||||||
|
local vars = {}
|
||||||
|
for k,v in pairs(cfg.variables) do
|
||||||
|
vars[k] = v
|
||||||
|
end
|
||||||
|
local name, version = rockspec.name, rockspec.version
|
||||||
|
vars.PREFIX = 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
|
||||||
|
|
||||||
|
--- Produce a versioned version of a filename.
|
||||||
|
-- @param file string: filename (must start with prefix)
|
||||||
|
-- @param prefix string: Path prefix for file
|
||||||
|
-- @param name string: Rock name
|
||||||
|
-- @param version string: Rock version
|
||||||
|
-- @return string: a pathname with the same directory parts and a versioned basename.
|
||||||
|
function path.versioned_name(file, prefix, name, version)
|
||||||
|
assert(type(file) == "string")
|
||||||
|
assert(type(name) == "string")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
|
||||||
|
local rest = file:sub(#prefix+1):gsub("^/*", "")
|
||||||
|
local name_version = (name.."_"..version):gsub("%-", "_"):gsub("%.", "_")
|
||||||
|
return dir.path(prefix, name_version.."-"..rest)
|
||||||
|
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)
|
||||||
|
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 = {}
|
||||||
|
if deps_mode == "one" then
|
||||||
|
table.insert(result, (fn(cfg.root_dir, ...)) or 0)
|
||||||
|
elseif deps_mode == "all" or deps_mode == "order" then
|
||||||
|
local use = false
|
||||||
|
if deps_mode == "all" then
|
||||||
|
use = true
|
||||||
|
end
|
||||||
|
for _, tree in ipairs(cfg.rocks_trees) do
|
||||||
|
if dir.normalize(path.rocks_tree_to_string(tree)) == dir.normalize(path.rocks_tree_to_string(cfg.root_dir)) then
|
||||||
|
use = true
|
||||||
|
end
|
||||||
|
if use then
|
||||||
|
table.insert(result, (fn(tree, ...)) or 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
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
|
||||||
|
|
||||||
|
--- Return the pathname of the file that would be loaded for a module,
|
||||||
|
-- returning the versioned pathname if given version is not the default version
|
||||||
|
-- in the given manifest.
|
||||||
|
-- @param module_name string: module name (eg. "socket.core")
|
||||||
|
-- @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 manifest table: the manifest table for the tree.
|
||||||
|
-- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so")
|
||||||
|
function path.which(module_name, file_name, name, version, tree, manifest)
|
||||||
|
local versions = manifest.modules[module_name]
|
||||||
|
assert(versions)
|
||||||
|
for i, name_version in ipairs(versions) do
|
||||||
|
if name_version == name.."/"..version then
|
||||||
|
return path.which_i(file_name, name, version, tree, i):gsub("//", "/")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
assert(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
return path
|
||||||
69
Utils/luarocks/lua/luarocks/path_cmd.lua
Normal file
69
Utils/luarocks/lua/luarocks/path_cmd.lua
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
|
||||||
|
--- @module luarocks.path_cmd
|
||||||
|
-- Driver for the `luarocks path` command.
|
||||||
|
local path_cmd = {}
|
||||||
|
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
|
||||||
|
util.add_run_function(path_cmd)
|
||||||
|
path_cmd.help_summary = "Return the currently configured package path."
|
||||||
|
path_cmd.help_arguments = ""
|
||||||
|
path_cmd.help = [[
|
||||||
|
Returns the package path currently configured for this installation
|
||||||
|
of LuaRocks, formatted as shell commands to update LUA_PATH and LUA_CPATH.
|
||||||
|
|
||||||
|
--bin Adds the system path to the output
|
||||||
|
|
||||||
|
--append Appends the paths to the existing paths. Default is to prefix
|
||||||
|
the LR paths to the existing paths.
|
||||||
|
|
||||||
|
--lr-path Exports the Lua path (not formatted as shell command)
|
||||||
|
|
||||||
|
--lr-cpath Exports the Lua cpath (not formatted as shell command)
|
||||||
|
|
||||||
|
--lr-bin Exports the system path (not formatted as shell command)
|
||||||
|
|
||||||
|
|
||||||
|
On Unix systems, you may run:
|
||||||
|
eval `luarocks path`
|
||||||
|
And on Windows:
|
||||||
|
luarocks path > "%temp%\_lrp.bat" && call "%temp%\_lrp.bat" && del "%temp%\_lrp.bat"
|
||||||
|
]]
|
||||||
|
|
||||||
|
--- Driver function for "path" command.
|
||||||
|
-- @return boolean This function always succeeds.
|
||||||
|
function path_cmd.command(flags)
|
||||||
|
local lr_path, lr_cpath, lr_bin = cfg.package_paths(flags["tree"])
|
||||||
|
local path_sep = cfg.export_path_separator
|
||||||
|
|
||||||
|
if flags["lr-path"] then
|
||||||
|
util.printout(util.remove_path_dupes(lr_path, ';'))
|
||||||
|
return true
|
||||||
|
elseif flags["lr-cpath"] then
|
||||||
|
util.printout(util.remove_path_dupes(lr_cpath, ';'))
|
||||||
|
return true
|
||||||
|
elseif flags["lr-bin"] then
|
||||||
|
util.printout(util.remove_path_dupes(lr_bin, path_sep))
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if flags["append"] then
|
||||||
|
lr_path = package.path .. ";" .. lr_path
|
||||||
|
lr_cpath = package.cpath .. ";" .. lr_cpath
|
||||||
|
lr_bin = os.getenv("PATH") .. path_sep .. lr_bin
|
||||||
|
else
|
||||||
|
lr_path = lr_path.. ";" .. package.path
|
||||||
|
lr_cpath = lr_cpath .. ";" .. package.cpath
|
||||||
|
lr_bin = lr_bin .. path_sep .. os.getenv("PATH")
|
||||||
|
end
|
||||||
|
|
||||||
|
util.printout(cfg.export_lua_path:format(util.remove_path_dupes(lr_path, ';')))
|
||||||
|
util.printout(cfg.export_lua_cpath:format(util.remove_path_dupes(lr_cpath, ';')))
|
||||||
|
if flags["bin"] then
|
||||||
|
util.printout(cfg.export_path:format(util.remove_path_dupes(lr_bin, path_sep)))
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return path_cmd
|
||||||
210
Utils/luarocks/lua/luarocks/persist.lua
Normal file
210
Utils/luarocks/lua/luarocks/persist.lua
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
|
||||||
|
--- Utility module for loading files into tables and
|
||||||
|
-- saving tables into files.
|
||||||
|
-- Implemented separately to avoid interdependencies,
|
||||||
|
-- as it is used in the bootstrapping stage of the cfg module.
|
||||||
|
local persist = {}
|
||||||
|
package.loaded["luarocks.persist"] = persist
|
||||||
|
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
|
||||||
|
--- 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.
|
||||||
|
local function 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 = run_file(filename, result)
|
||||||
|
|
||||||
|
setmetatable(result, save_mt)
|
||||||
|
|
||||||
|
if not ok then
|
||||||
|
return nil, err, errcode
|
||||||
|
end
|
||||||
|
return result, globals
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
local function write_value(out, v, level, sub_order)
|
||||||
|
if type(v) == "table" then
|
||||||
|
write_table(out, v, level + 1, sub_order)
|
||||||
|
elseif type(v) == "string" then
|
||||||
|
if v:match("[\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
|
||||||
|
|
||||||
|
--- 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 n = 1,level do out:write(indentation) end
|
||||||
|
end
|
||||||
|
|
||||||
|
if k == i then
|
||||||
|
i = i + 1
|
||||||
|
else
|
||||||
|
if type(k) == "string" and k:match("^[a-zA-Z_][a-zA-Z0-9_]*$") then
|
||||||
|
out:write(k)
|
||||||
|
else
|
||||||
|
out:write("[")
|
||||||
|
write_value(out, k, level)
|
||||||
|
out:write("]")
|
||||||
|
end
|
||||||
|
|
||||||
|
out:write(" = ")
|
||||||
|
end
|
||||||
|
|
||||||
|
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 n = 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
|
||||||
|
local function write_table_as_assignments(out, tbl, field_order)
|
||||||
|
for k, v, sub_order in util.sortedpairs(tbl, field_order) do
|
||||||
|
out:write(k.." = ")
|
||||||
|
write_value(out, v, 0, sub_order)
|
||||||
|
out:write("\n")
|
||||||
|
end
|
||||||
|
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 string
|
||||||
|
function persist.save_from_table_to_string(tbl, field_order)
|
||||||
|
local out = {buffer = {}}
|
||||||
|
function out:write(data) table.insert(self.buffer, data) end
|
||||||
|
write_table_as_assignments(out, tbl, field_order)
|
||||||
|
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
|
||||||
|
write_table_as_assignments(out, tbl, field_order)
|
||||||
|
out:close()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return persist
|
||||||
79
Utils/luarocks/lua/luarocks/purge.lua
Normal file
79
Utils/luarocks/lua/luarocks/purge.lua
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
|
||||||
|
--- Module implementing the LuaRocks "purge" command.
|
||||||
|
-- Remove all rocks from a given tree.
|
||||||
|
local purge = {}
|
||||||
|
package.loaded["luarocks.purge"] = purge
|
||||||
|
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
local search = require("luarocks.search")
|
||||||
|
local deps = require("luarocks.deps")
|
||||||
|
local repos = require("luarocks.repos")
|
||||||
|
local manif = require("luarocks.manif")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local remove = require("luarocks.remove")
|
||||||
|
|
||||||
|
util.add_run_function(purge)
|
||||||
|
purge.help_summary = "Remove all installed rocks from a tree."
|
||||||
|
purge.help_arguments = "--tree=<tree> [--old-versions]"
|
||||||
|
purge.help = [[
|
||||||
|
This command removes rocks en masse from a given tree.
|
||||||
|
By default, it removes all rocks from a tree.
|
||||||
|
|
||||||
|
The --tree argument is mandatory: luarocks purge does not
|
||||||
|
assume a default tree.
|
||||||
|
|
||||||
|
--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.
|
||||||
|
]]
|
||||||
|
|
||||||
|
function purge.command(flags)
|
||||||
|
local tree = flags["tree"]
|
||||||
|
|
||||||
|
if type(tree) ~= "string" then
|
||||||
|
return nil, "The --tree argument is mandatory. "..util.see_help("purge")
|
||||||
|
end
|
||||||
|
|
||||||
|
local results = {}
|
||||||
|
local query = search.make_query("")
|
||||||
|
query.exact_name = false
|
||||||
|
if not fs.is_dir(tree) then
|
||||||
|
return nil, "Directory not found: "..tree
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok, err = fs.check_command_permissions(flags)
|
||||||
|
if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end
|
||||||
|
|
||||||
|
search.manifest_search(results, path.rocks_dir(tree), query)
|
||||||
|
|
||||||
|
local sort = function(a,b) return deps.compare_versions(b,a) end
|
||||||
|
if flags["old-versions"] then
|
||||||
|
sort = deps.compare_versions
|
||||||
|
end
|
||||||
|
|
||||||
|
for package, versions in util.sortedpairs(results) do
|
||||||
|
for version, repositories in util.sortedpairs(versions, sort) do
|
||||||
|
if flags["old-versions"] then
|
||||||
|
util.printout("Keeping "..package.." "..version.."...")
|
||||||
|
local ok, err = remove.remove_other_versions(package, version, flags["force"], flags["force-fast"])
|
||||||
|
if not ok 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 manif.make_manifest(cfg.rocks_dir, "one")
|
||||||
|
end
|
||||||
|
|
||||||
|
return purge
|
||||||
33
Utils/luarocks/lua/luarocks/refresh_cache.lua
Normal file
33
Utils/luarocks/lua/luarocks/refresh_cache.lua
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
--- Module implementing the luarocks-admin "refresh_cache" command.
|
||||||
|
local refresh_cache = {}
|
||||||
|
package.loaded["luarocks.refresh_cache"] = refresh_cache
|
||||||
|
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local cache = require("luarocks.cache")
|
||||||
|
|
||||||
|
util.add_run_function(refresh_cache)
|
||||||
|
refresh_cache.help_summary = "Refresh local cache of a remote rocks server."
|
||||||
|
refresh_cache.help_arguments = "[--from=<server>]"
|
||||||
|
refresh_cache.help = [[
|
||||||
|
The flag --from indicates which server to use.
|
||||||
|
If not given, the default server set in the upload_server variable
|
||||||
|
from the configuration file is used instead.
|
||||||
|
]]
|
||||||
|
|
||||||
|
function refresh_cache.command(flags)
|
||||||
|
local server, upload_server = cache.get_upload_server(flags["server"])
|
||||||
|
if not server then return nil, upload_server end
|
||||||
|
local download_url = cache.get_server_urls(server, upload_server)
|
||||||
|
|
||||||
|
local ok, err = cache.refresh_local_cache(server, download_url, cfg.upload_user, cfg.upload_password)
|
||||||
|
if not ok then
|
||||||
|
return nil, err
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return refresh_cache
|
||||||
174
Utils/luarocks/lua/luarocks/remove.lua
Normal file
174
Utils/luarocks/lua/luarocks/remove.lua
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
|
||||||
|
--- Module implementing the LuaRocks "remove" command.
|
||||||
|
-- Uninstalls rocks.
|
||||||
|
local remove = {}
|
||||||
|
package.loaded["luarocks.remove"] = 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.cfg")
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local manif = require("luarocks.manif")
|
||||||
|
|
||||||
|
util.add_run_function(remove)
|
||||||
|
remove.help_summary = "Uninstall a rock."
|
||||||
|
remove.help_arguments = "[--force|--force-fast] <name> [<version>]"
|
||||||
|
remove.help = [[
|
||||||
|
Argument is the name of a rock to be uninstalled.
|
||||||
|
If a version is not given, try to remove all versions at once.
|
||||||
|
Will only perform the removal if it does not break dependencies.
|
||||||
|
To override this check and force the removal, use --force.
|
||||||
|
To perform a forced removal without reporting dependency issues,
|
||||||
|
use --force-fast.
|
||||||
|
|
||||||
|
]]..util.deps_mode_help()
|
||||||
|
|
||||||
|
--- Obtain a list of packages that depend on the given set of packages
|
||||||
|
-- (where all packages of the set are versions of one program).
|
||||||
|
-- @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 blacklist = {}
|
||||||
|
blacklist[name] = {}
|
||||||
|
for version, _ in pairs(versions) do
|
||||||
|
blacklist[name][version] = true
|
||||||
|
end
|
||||||
|
local local_rocks = {}
|
||||||
|
local query_all = search.make_query("")
|
||||||
|
query_all.exact_name = false
|
||||||
|
search.manifest_search(local_rocks, cfg.rocks_dir, query_all)
|
||||||
|
local_rocks[name] = nil
|
||||||
|
for rock_name, rock_versions in pairs(local_rocks) do
|
||||||
|
for rock_version, _ in pairs(rock_versions) do
|
||||||
|
local rockspec, err = fetch.load_rockspec(path.rockspec_file(rock_name, rock_version))
|
||||||
|
if rockspec then
|
||||||
|
local _, missing = deps.match_deps(rockspec, blacklist, 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 = {}
|
||||||
|
search.manifest_search(results, cfg.rocks_dir, { name = name, exact_name = true, constraints = {{ op = "~=", version = version}} })
|
||||||
|
if results[name] then
|
||||||
|
return remove.remove_search_results(results, name, cfg.deps_mode, force, fast)
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Driver function for the "remove" command.
|
||||||
|
-- @param name string: name of a rock. If a version is given, refer to
|
||||||
|
-- a specific version; otherwise, try to remove all versions.
|
||||||
|
-- @param version string: When passing a package name, a version number
|
||||||
|
-- may also be given.
|
||||||
|
-- @return boolean or (nil, string, exitcode): True if removal was
|
||||||
|
-- successful, nil and an error message otherwise. exitcode is optionally returned.
|
||||||
|
function remove.command(flags, name, version)
|
||||||
|
if type(name) ~= "string" then
|
||||||
|
return nil, "Argument missing. "..util.see_help("remove")
|
||||||
|
end
|
||||||
|
|
||||||
|
local deps_mode = flags["deps-mode"] or cfg.deps_mode
|
||||||
|
|
||||||
|
local ok, err = fs.check_command_permissions(flags)
|
||||||
|
if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end
|
||||||
|
|
||||||
|
local rock_type = name:match("%.(rock)$") or name:match("%.(rockspec)$")
|
||||||
|
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
|
||||||
|
|
||||||
|
local results = {}
|
||||||
|
name = name:lower()
|
||||||
|
search.manifest_search(results, cfg.rocks_dir, search.make_query(name, version))
|
||||||
|
if not results[name] then
|
||||||
|
return nil, "Could not find rock '"..name..(version and " "..version or "").."' in "..path.rocks_tree_to_string(cfg.root_dir)
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok, err = remove.remove_search_results(results, name, deps_mode, flags["force"], flags["force-fast"])
|
||||||
|
if not ok then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
|
||||||
|
manif.check_dependencies(nil, deps.get_deps_mode(flags))
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return remove
|
||||||
422
Utils/luarocks/lua/luarocks/repos.lua
Normal file
422
Utils/luarocks/lua/luarocks/repos.lua
Normal file
@ -0,0 +1,422 @@
|
|||||||
|
|
||||||
|
--- Functions for managing the repository on disk.
|
||||||
|
local repos = {}
|
||||||
|
package.loaded["luarocks.repos"] = repos
|
||||||
|
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local manif = require("luarocks.manif")
|
||||||
|
local deps = require("luarocks.deps")
|
||||||
|
|
||||||
|
-- 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")
|
||||||
|
|
||||||
|
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")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
|
||||||
|
return fs.is_dir(path.install_dir(name, version))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function recurse_rock_manifest_tree(file_tree, action)
|
||||||
|
assert(type(file_tree) == "table")
|
||||||
|
assert(type(action) == "function")
|
||||||
|
local function do_recurse_rock_manifest_tree(tree, parent_path, parent_module)
|
||||||
|
|
||||||
|
for file, sub in pairs(tree) do
|
||||||
|
if type(sub) == "table" then
|
||||||
|
local ok, err = do_recurse_rock_manifest_tree(sub, parent_path..file.."/", parent_module..file..".")
|
||||||
|
if not ok then return nil, err end
|
||||||
|
else
|
||||||
|
local ok, err = action(parent_path, parent_module, file)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return do_recurse_rock_manifest_tree(file_tree, "", "")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function store_package_data(result, name, file_tree)
|
||||||
|
if not file_tree then return end
|
||||||
|
return recurse_rock_manifest_tree(file_tree,
|
||||||
|
function(parent_path, parent_module, file)
|
||||||
|
local pathname = parent_path..file
|
||||||
|
result[path.path_to_module(pathname)] = pathname
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Obtain a list of modules within an installed package.
|
||||||
|
-- @param package string: The package name; for example "luasocket"
|
||||||
|
-- @param version string: The exact version number including revision;
|
||||||
|
-- for example "2.0.1-1".
|
||||||
|
-- @return table: A table of modules where keys are module identifiers
|
||||||
|
-- in "foo.bar" format and values are pathnames in architecture-dependent
|
||||||
|
-- "foo/bar.so" format. If no modules are found or if package or version
|
||||||
|
-- are invalid, an empty table is returned.
|
||||||
|
function repos.package_modules(package, version)
|
||||||
|
assert(type(package) == "string")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
|
||||||
|
local result = {}
|
||||||
|
local rock_manifest = manif.load_rock_manifest(package, version)
|
||||||
|
store_package_data(result, package, rock_manifest.lib)
|
||||||
|
store_package_data(result, package, rock_manifest.lua)
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Obtain a list of command-line scripts within an installed package.
|
||||||
|
-- @param package string: The package name; for example "luasocket"
|
||||||
|
-- @param version string: The exact version number including revision;
|
||||||
|
-- for example "2.0.1-1".
|
||||||
|
-- @return table: A table of items where keys are command names
|
||||||
|
-- as strings and values are pathnames in architecture-dependent
|
||||||
|
-- ".../bin/foo" format. If no modules are found or if package or version
|
||||||
|
-- are invalid, an empty table is returned.
|
||||||
|
function repos.package_commands(package, version)
|
||||||
|
assert(type(package) == "string")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
|
||||||
|
local result = {}
|
||||||
|
local rock_manifest = manif.load_rock_manifest(package, version)
|
||||||
|
store_package_data(result, package, rock_manifest.bin)
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Check if a rock contains binary executables.
|
||||||
|
-- @param name string: name of an installed rock
|
||||||
|
-- @param version string: version of an installed rock
|
||||||
|
-- @return boolean: returns true if rock contains platform-specific
|
||||||
|
-- binary executables, or false if it is a pure-Lua rock.
|
||||||
|
function repos.has_binaries(name, version)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
|
||||||
|
local rock_manifest = manif.load_rock_manifest(name, version)
|
||||||
|
if rock_manifest.bin then
|
||||||
|
for name, md5 in pairs(rock_manifest.bin) do
|
||||||
|
-- TODO verify that it is the same file. If it isn't, find the actual command.
|
||||||
|
if fs.is_actual_binary(dir.path(cfg.deploy_bin_dir, name)) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function repos.run_hook(rockspec, hook_name)
|
||||||
|
assert(type(rockspec) == "table")
|
||||||
|
assert(type(hook_name) == "string")
|
||||||
|
|
||||||
|
local hooks = rockspec.hooks
|
||||||
|
if not hooks then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if 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(type(rockspec) == "table")
|
||||||
|
|
||||||
|
if cfg.wrap_bin_scripts ~= nil then
|
||||||
|
return cfg.wrap_bin_scripts
|
||||||
|
end
|
||||||
|
if rockspec.deploy and rockspec.deploy.wrap_bin_scripts == false then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
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 move_suffixed(from_file, to_file, suffix)
|
||||||
|
local suffixed_from_file, err = find_suffixed(from_file, suffix)
|
||||||
|
if not suffixed_from_file then
|
||||||
|
return nil, "Could not move " .. from_file .. " to " .. to_file .. ": " .. err
|
||||||
|
end
|
||||||
|
|
||||||
|
suffix = suffixed_from_file:sub(#from_file + 1)
|
||||||
|
local suffixed_to_file = to_file .. suffix
|
||||||
|
return fs.move(suffixed_from_file, suffixed_to_file)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function delete_suffixed(file, suffix)
|
||||||
|
local suffixed_file, err = find_suffixed(file, suffix)
|
||||||
|
if not suffixed_file then
|
||||||
|
return nil, "Could not remove " .. file .. ": " .. err
|
||||||
|
end
|
||||||
|
|
||||||
|
fs.delete(suffixed_file)
|
||||||
|
if fs.exists(suffixed_file) then
|
||||||
|
return nil, "Failed deleting " .. suffixed_file .. ": file still exists"
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
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)
|
||||||
|
local deploy_dir = cfg["deploy_" .. deploy_type .. "_dir"]
|
||||||
|
local non_versioned = dir.path(deploy_dir, file_path)
|
||||||
|
local versioned = path.versioned_name(non_versioned, deploy_dir, name, version)
|
||||||
|
return non_versioned, versioned
|
||||||
|
end
|
||||||
|
|
||||||
|
local function prepare_target(name, version, deploy_type, file_path, suffix)
|
||||||
|
local non_versioned, versioned = get_deploy_paths(name, version, deploy_type, file_path)
|
||||||
|
local item_type, item_name = manif.get_provided_item(deploy_type, file_path)
|
||||||
|
local cur_name, cur_version = manif.get_current_provider(item_type, item_name)
|
||||||
|
|
||||||
|
if not cur_name then
|
||||||
|
return non_versioned
|
||||||
|
elseif name < cur_name or (name == cur_name and deps.compare_versions(version, cur_version)) then
|
||||||
|
-- New version has priority. Move currently provided version back using versioned name.
|
||||||
|
local cur_deploy_type, cur_file_path = manif.get_providing_file(cur_name, cur_version, item_type, item_name)
|
||||||
|
local cur_non_versioned, cur_versioned = get_deploy_paths(cur_name, cur_version, cur_deploy_type, cur_file_path)
|
||||||
|
|
||||||
|
local dir_ok, dir_err = fs.make_dir(dir.dir_name(cur_versioned))
|
||||||
|
if not dir_ok then return nil, dir_err end
|
||||||
|
|
||||||
|
local move_ok, move_err = move_suffixed(cur_non_versioned, cur_versioned, suffix)
|
||||||
|
if not move_ok then return nil, move_err end
|
||||||
|
|
||||||
|
return non_versioned
|
||||||
|
else
|
||||||
|
-- Current version has priority, deploy new version using versioned name.
|
||||||
|
return versioned
|
||||||
|
end
|
||||||
|
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")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
assert(type(wrap_bin_scripts) == "boolean")
|
||||||
|
|
||||||
|
local rock_manifest = manif.load_rock_manifest(name, version)
|
||||||
|
|
||||||
|
local function deploy_file_tree(deploy_type, source_dir, move_fn, suffix)
|
||||||
|
if not rock_manifest[deploy_type] then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return recurse_rock_manifest_tree(rock_manifest[deploy_type], function(parent_path, parent_module, file)
|
||||||
|
local file_path = parent_path .. file
|
||||||
|
local source = dir.path(source_dir, file_path)
|
||||||
|
|
||||||
|
local target, prepare_err = prepare_target(name, version, deploy_type, file_path, suffix)
|
||||||
|
if not target then return nil, prepare_err end
|
||||||
|
|
||||||
|
local dir_ok, dir_err = fs.make_dir(dir.dir_name(target))
|
||||||
|
if not dir_ok then return nil, dir_err end
|
||||||
|
|
||||||
|
local suffixed_target, mover = move_fn(source, target)
|
||||||
|
if fs.exists(suffixed_target) then
|
||||||
|
local backup = suffixed_target
|
||||||
|
repeat
|
||||||
|
backup = backup.."~"
|
||||||
|
until not fs.exists(backup) -- Slight race condition here, but shouldn't be a problem.
|
||||||
|
|
||||||
|
util.printerr("Warning: "..suffixed_target.." is not tracked by this installation of LuaRocks. Moving it to "..backup)
|
||||||
|
local move_ok, move_err = fs.move(suffixed_target, backup)
|
||||||
|
if not move_ok then return nil, move_err end
|
||||||
|
end
|
||||||
|
|
||||||
|
local move_ok, move_err = mover()
|
||||||
|
if not move_ok then return nil, move_err end
|
||||||
|
|
||||||
|
fs.remove_dir_tree_if_empty(dir.dir_name(source))
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function install_binary(source, target)
|
||||||
|
if wrap_bin_scripts and fs.is_lua(source) then
|
||||||
|
return target .. (cfg.wrapper_suffix or ""), function() return fs.wrap_script(source, target, name, version) end
|
||||||
|
else
|
||||||
|
return target, function() return fs.copy_binary(source, target) end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function make_mover(perms)
|
||||||
|
return function(source, target)
|
||||||
|
return target, function() return fs.move(source, target, perms) end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok, err = deploy_file_tree("bin", path.bin_dir(name, version), install_binary, cfg.wrapper_suffix)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
|
||||||
|
ok, err = deploy_file_tree("lua", path.lua_dir(name, version), make_mover(cfg.perm_read))
|
||||||
|
if not ok then return nil, err end
|
||||||
|
|
||||||
|
ok, err = deploy_file_tree("lib", path.lib_dir(name, version), make_mover(cfg.perm_exec))
|
||||||
|
if not ok then return nil, err end
|
||||||
|
|
||||||
|
return manif.add_to_manifest(name, version, nil, deps_mode)
|
||||||
|
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")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
assert(type(deps_mode) == "string")
|
||||||
|
|
||||||
|
local rock_manifest = manif.load_rock_manifest(name, version)
|
||||||
|
if not rock_manifest then
|
||||||
|
return nil, "rock_manifest file not found for "..name.." "..version.." - not a LuaRocks 2 tree?"
|
||||||
|
end
|
||||||
|
|
||||||
|
local function delete_deployed_file_tree(deploy_type, suffix)
|
||||||
|
if not rock_manifest[deploy_type] then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return recurse_rock_manifest_tree(rock_manifest[deploy_type], function(parent_path, parent_module, file)
|
||||||
|
local file_path = parent_path .. file
|
||||||
|
local non_versioned, versioned = get_deploy_paths(name, version, deploy_type, file_path)
|
||||||
|
|
||||||
|
-- Figure out if the file is deployed using versioned or non-versioned name.
|
||||||
|
local target
|
||||||
|
local item_type, item_name = manif.get_provided_item(deploy_type, file_path)
|
||||||
|
local cur_name, cur_version = manif.get_current_provider(item_type, item_name)
|
||||||
|
|
||||||
|
if cur_name == name and cur_version == version then
|
||||||
|
-- This package has highest priority, should be in non-versioned location.
|
||||||
|
target = non_versioned
|
||||||
|
else
|
||||||
|
target = versioned
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok, err = delete_suffixed(target, suffix)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
|
||||||
|
if not quick and target == non_versioned then
|
||||||
|
-- If another package provides this file, move its version
|
||||||
|
-- into non-versioned location instead.
|
||||||
|
local next_name, next_version = manif.get_next_provider(item_type, item_name)
|
||||||
|
|
||||||
|
if next_name then
|
||||||
|
local next_deploy_type, next_file_path = manif.get_providing_file(next_name, next_version, item_type, item_name)
|
||||||
|
local next_non_versioned, next_versioned = get_deploy_paths(next_name, next_version, next_deploy_type, next_file_path)
|
||||||
|
|
||||||
|
local move_ok, move_err = move_suffixed(next_versioned, next_non_versioned, suffix)
|
||||||
|
if not move_ok then return nil, move_err end
|
||||||
|
|
||||||
|
fs.remove_dir_tree_if_empty(dir.dir_name(next_versioned))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
fs.remove_dir_tree_if_empty(dir.dir_name(target))
|
||||||
|
return true
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok, err = delete_deployed_file_tree("bin", cfg.wrapper_suffix)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
|
||||||
|
ok, err = delete_deployed_file_tree("lua")
|
||||||
|
if not ok then return nil, err end
|
||||||
|
|
||||||
|
ok, err = delete_deployed_file_tree("lib")
|
||||||
|
if not ok then return nil, err 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
|
||||||
|
|
||||||
|
return manif.remove_from_manifest(name, version, nil, deps_mode)
|
||||||
|
end
|
||||||
|
|
||||||
|
return repos
|
||||||
2
Utils/luarocks/lua/luarocks/require.lua
Normal file
2
Utils/luarocks/lua/luarocks/require.lua
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
--- Retained for compatibility reasons only. Use luarocks.loader instead.
|
||||||
|
return require("luarocks.loader")
|
||||||
483
Utils/luarocks/lua/luarocks/search.lua
Normal file
483
Utils/luarocks/lua/luarocks/search.lua
Normal file
@ -0,0 +1,483 @@
|
|||||||
|
|
||||||
|
--- Module implementing the LuaRocks "search" command.
|
||||||
|
-- Queries LuaRocks servers.
|
||||||
|
local search = {}
|
||||||
|
package.loaded["luarocks.search"] = search
|
||||||
|
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
local manif = require("luarocks.manif")
|
||||||
|
local deps = require("luarocks.deps")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
|
||||||
|
util.add_run_function(search)
|
||||||
|
search.help_summary = "Query the LuaRocks servers."
|
||||||
|
search.help_arguments = "[--source] [--binary] { <name> [<version>] | --all }"
|
||||||
|
search.help = [[
|
||||||
|
--source Return only rockspecs and source rocks,
|
||||||
|
to be used with the "build" command.
|
||||||
|
--binary Return only pure Lua and binary rocks (rocks that can be used
|
||||||
|
with the "install" command without requiring a C toolchain).
|
||||||
|
--all List all contents of the server that are suitable to
|
||||||
|
this platform, do not filter by name.
|
||||||
|
]]
|
||||||
|
|
||||||
|
--- Convert the arch field of a query table to table format.
|
||||||
|
-- @param query table: A query table.
|
||||||
|
local function query_arch_as_table(query)
|
||||||
|
local format = type(query.arch)
|
||||||
|
if format == "table" then
|
||||||
|
return
|
||||||
|
elseif format == "nil" then
|
||||||
|
local accept = {}
|
||||||
|
accept["src"] = true
|
||||||
|
accept["all"] = true
|
||||||
|
accept["rockspec"] = true
|
||||||
|
accept["installed"] = true
|
||||||
|
accept[cfg.arch] = true
|
||||||
|
query.arch = accept
|
||||||
|
elseif format == "string" then
|
||||||
|
local accept = {}
|
||||||
|
for a in query.arch:gmatch("[%w_-]+") do
|
||||||
|
accept[a] = true
|
||||||
|
end
|
||||||
|
query.arch = accept
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Store a search result (a rock or rockspec) in the results table.
|
||||||
|
-- @param results table: The results table, where keys are package names and
|
||||||
|
-- values are tables matching version strings to arrays of
|
||||||
|
-- tables with fields "arch" and "repo".
|
||||||
|
-- @param name string: Package name.
|
||||||
|
-- @param version string: Package version.
|
||||||
|
-- @param arch string: Architecture of rock ("all", "src" or platform
|
||||||
|
-- identifier), "rockspec" or "installed"
|
||||||
|
-- @param repo string: Pathname of a local repository of URL of
|
||||||
|
-- rocks server.
|
||||||
|
local function store_result(results, name, version, arch, repo)
|
||||||
|
assert(type(results) == "table")
|
||||||
|
assert(type(name) == "string")
|
||||||
|
assert(type(version) == "string")
|
||||||
|
assert(type(arch) == "string")
|
||||||
|
assert(type(repo) == "string")
|
||||||
|
|
||||||
|
if not results[name] then results[name] = {} end
|
||||||
|
if not results[name][version] then results[name][version] = {} end
|
||||||
|
table.insert(results[name][version], {
|
||||||
|
arch = arch,
|
||||||
|
repo = repo
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Test the name field of a query.
|
||||||
|
-- If query has a boolean field exact_name set to false,
|
||||||
|
-- then substring match is performed; otherwise, exact string
|
||||||
|
-- comparison is done.
|
||||||
|
-- @param query table: A query in dependency table format.
|
||||||
|
-- @param name string: A package name.
|
||||||
|
-- @return boolean: True if names match, false otherwise.
|
||||||
|
local function match_name(query, name)
|
||||||
|
assert(type(query) == "table")
|
||||||
|
assert(type(name) == "string")
|
||||||
|
if query.exact_name == false then
|
||||||
|
return name:find(query.name, 0, true) and true or false
|
||||||
|
else
|
||||||
|
return name == query.name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Store a match in a results table if version matches query.
|
||||||
|
-- Name, version, arch and repository path are stored in a given
|
||||||
|
-- table, optionally checking if version and arch (if given) match
|
||||||
|
-- a query.
|
||||||
|
-- @param results table: The results table, where keys are package names and
|
||||||
|
-- values are tables matching version strings to arrays of
|
||||||
|
-- tables with fields "arch" and "repo".
|
||||||
|
-- @param repo string: URL or pathname of the repository.
|
||||||
|
-- @param name string: The name of the package being tested.
|
||||||
|
-- @param version string: The version of the package being tested.
|
||||||
|
-- @param arch string: The arch of the package being tested.
|
||||||
|
-- @param query table: A table describing the query in dependency
|
||||||
|
-- format (for example, {name = "filesystem", exact_name = false,
|
||||||
|
-- constraints = {op = "~>", version = {1,0}}}, arch = "rockspec").
|
||||||
|
-- If the arch field is omitted, the local architecture (cfg.arch)
|
||||||
|
-- is used. The special value "any" is also recognized, returning all
|
||||||
|
-- matches regardless of architecture.
|
||||||
|
local function store_if_match(results, repo, name, version, arch, query)
|
||||||
|
if match_name(query, name) then
|
||||||
|
if query.arch[arch] or query.arch["any"] then
|
||||||
|
if deps.match_constraints(deps.parse_version(version), query.constraints) then
|
||||||
|
store_result(results, name, version, arch, repo)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Perform search on a local repository.
|
||||||
|
-- @param repo string: The pathname of the local repository.
|
||||||
|
-- @param query table: A table describing the query in dependency
|
||||||
|
-- format (for example, {name = "filesystem", exact_name = false,
|
||||||
|
-- constraints = {op = "~>", version = {1,0}}}, arch = "rockspec").
|
||||||
|
-- If the arch field is omitted, the local architecture (cfg.arch)
|
||||||
|
-- is used. The special value "any" is also recognized, returning all
|
||||||
|
-- matches regardless of architecture.
|
||||||
|
-- @param results table or nil: If given, this table will store the
|
||||||
|
-- results; if not given, a new table will be created.
|
||||||
|
-- @return table: The results table, 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 "results" parameter, that is the result value.
|
||||||
|
function search.disk_search(repo, query, results)
|
||||||
|
assert(type(repo) == "string")
|
||||||
|
assert(type(query) == "table")
|
||||||
|
assert(type(results) == "table" or not results)
|
||||||
|
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
|
||||||
|
if not results then
|
||||||
|
results = {}
|
||||||
|
end
|
||||||
|
query_arch_as_table(query)
|
||||||
|
|
||||||
|
for name in 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
|
||||||
|
store_if_match(results, repo, rname, rversion, rarch, query)
|
||||||
|
elseif fs.is_dir(pathname) then
|
||||||
|
for version in fs.dir(pathname) do
|
||||||
|
if version:match("-%d+$") then
|
||||||
|
store_if_match(results, repo, name, version, "installed", query)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return results
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Perform search on a rocks server or tree.
|
||||||
|
-- @param results table: The results table, 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 table describing the query in dependency
|
||||||
|
-- format (for example, {name = "filesystem", exact_name = false,
|
||||||
|
-- constraints = {op = "~>", version = {1,0}}}, arch = "rockspec").
|
||||||
|
-- If the arch field is omitted, the local architecture (cfg.arch)
|
||||||
|
-- is used. The special value "any" is also recognized, returning all
|
||||||
|
-- matches regardless of architecture.
|
||||||
|
-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
|
||||||
|
-- @return true or, in case of errors, nil, an error message and an optional error code.
|
||||||
|
function search.manifest_search(results, repo, query, lua_version)
|
||||||
|
assert(type(results) == "table")
|
||||||
|
assert(type(repo) == "string")
|
||||||
|
assert(type(query) == "table")
|
||||||
|
|
||||||
|
query_arch_as_table(query)
|
||||||
|
local manifest, err, errcode = manif.load_manifest(repo, lua_version)
|
||||||
|
if not manifest then
|
||||||
|
return nil, err, errcode
|
||||||
|
end
|
||||||
|
for name, versions in pairs(manifest.repository) do
|
||||||
|
for version, items in pairs(versions) do
|
||||||
|
for _, item in ipairs(items) do
|
||||||
|
store_if_match(results, repo, name, version, item.arch, query)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Search on all configured rocks servers.
|
||||||
|
-- @param query table: A dependency query.
|
||||||
|
-- @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(type(query) == "table")
|
||||||
|
|
||||||
|
local results = {}
|
||||||
|
for _, repo in ipairs(cfg.rocks_servers) do
|
||||||
|
if not cfg.disabled_servers[repo] then
|
||||||
|
if type(repo) == "string" then
|
||||||
|
repo = { repo }
|
||||||
|
end
|
||||||
|
for _, mirror in ipairs(repo) do
|
||||||
|
local protocol, pathname = dir.split_url(mirror)
|
||||||
|
if protocol == "file" then
|
||||||
|
mirror = pathname
|
||||||
|
end
|
||||||
|
local ok, err, errcode = search.manifest_search(results, mirror, query, lua_version)
|
||||||
|
if errcode == "network" then
|
||||||
|
cfg.disabled_servers[repo] = true
|
||||||
|
end
|
||||||
|
if ok then
|
||||||
|
break
|
||||||
|
else
|
||||||
|
util.warning("Failed searching manifest: "..err)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- search through rocks in cfg.rocks_provided
|
||||||
|
local provided_repo = "provided by VM or rocks_provided"
|
||||||
|
for name, versions in pairs(cfg.rocks_provided) do
|
||||||
|
store_if_match(results, provided_repo, name, versions, "installed", query)
|
||||||
|
end
|
||||||
|
return results
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Prepare a query in dependency table format.
|
||||||
|
-- @param name string: The query name.
|
||||||
|
-- @param version string or nil:
|
||||||
|
-- @return table: A query in table format
|
||||||
|
function search.make_query(name, version)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
assert(type(version) == "string" or not version)
|
||||||
|
|
||||||
|
local query = {
|
||||||
|
name = name,
|
||||||
|
constraints = {}
|
||||||
|
}
|
||||||
|
if version then
|
||||||
|
table.insert(query.constraints, { op = "==", version = deps.parse_version(version)})
|
||||||
|
end
|
||||||
|
return query
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the URL for the latest in a set of versions.
|
||||||
|
-- @param name string: The package name to be used in the URL.
|
||||||
|
-- @param versions table: An array of version informations, as stored
|
||||||
|
-- in search results tables.
|
||||||
|
-- @return string or nil: the URL for the latest version if one could
|
||||||
|
-- be picked, or nil.
|
||||||
|
local function pick_latest_version(name, versions)
|
||||||
|
assert(type(name) == "string")
|
||||||
|
assert(type(versions) == "table")
|
||||||
|
|
||||||
|
local vtables = {}
|
||||||
|
for v, _ in pairs(versions) do
|
||||||
|
table.insert(vtables, deps.parse_version(v))
|
||||||
|
end
|
||||||
|
table.sort(vtables)
|
||||||
|
local version = vtables[#vtables].string
|
||||||
|
local items = versions[version]
|
||||||
|
if items then
|
||||||
|
local pick = 1
|
||||||
|
for i, item in ipairs(items) do
|
||||||
|
if (item.arch == 'src' and items[pick].arch == 'rockspec')
|
||||||
|
or (item.arch ~= 'src' and item.arch ~= 'rockspec') then
|
||||||
|
pick = i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return path.make_url(items[pick].repo, name, version, items[pick].arch)
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Find out which other Lua versions provide rock versions matching a query,
|
||||||
|
-- @param query table: A dependency query matching a single rock.
|
||||||
|
-- @return table: array of Lua versions supported, in "5.x" format.
|
||||||
|
local function supported_lua_versions(query)
|
||||||
|
local results = {}
|
||||||
|
|
||||||
|
for lua_version in util.lua_versions() do
|
||||||
|
if lua_version ~= cfg.lua_version then
|
||||||
|
if search.search_repos(query, lua_version)[query.name] then
|
||||||
|
table.insert(results, lua_version)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return results
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Attempt to get a single URL for a given search for a rock.
|
||||||
|
-- @param query table: A dependency query matching a single rock.
|
||||||
|
-- @return string or (nil, string): URL for latest matching version
|
||||||
|
-- of the rock if it was found, or nil followed by an error message.
|
||||||
|
function search.find_suitable_rock(query)
|
||||||
|
assert(type(query) == "table")
|
||||||
|
|
||||||
|
local results = search.search_repos(query)
|
||||||
|
local first_rock = next(results)
|
||||||
|
if not first_rock then
|
||||||
|
if cfg.rocks_provided[query.name] == nil then
|
||||||
|
-- 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
|
||||||
|
return nil, query.name.." supports "..versions_message
|
||||||
|
elseif #query.constraints == 1 and query.constraints[1].op == "==" then
|
||||||
|
return nil, query.name.." "..query.constraints[1].version.string.." supports "..versions_message
|
||||||
|
else
|
||||||
|
return nil, "Matching "..query.name.." versions support "..versions_message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil, "No results matching query were found."
|
||||||
|
elseif next(results, first_rock) then
|
||||||
|
-- Shouldn't happen as query must match only one package.
|
||||||
|
return nil, "Several rocks matched query."
|
||||||
|
elseif cfg.rocks_provided[query.name] ~= nil then
|
||||||
|
-- Do not install versions listed in cfg.rocks_provided.
|
||||||
|
return nil, "Rock "..query.name.." "..cfg.rocks_provided[query.name]..
|
||||||
|
" was found but it is provided by VM or 'rocks_provided' in the config file."
|
||||||
|
else
|
||||||
|
return pick_latest_version(query.name, results[first_rock])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Print a list of rocks/rockspecs on standard output.
|
||||||
|
-- @param results table: A table where keys are package names and versions
|
||||||
|
-- are tables matching version strings to an array of rocks servers.
|
||||||
|
-- @param porcelain boolean or nil: A flag to force machine-friendly output.
|
||||||
|
function search.print_results(results, porcelain)
|
||||||
|
assert(type(results) == "table")
|
||||||
|
assert(type(porcelain) == "boolean" or not porcelain)
|
||||||
|
|
||||||
|
for package, versions in util.sortedpairs(results) do
|
||||||
|
if not porcelain then
|
||||||
|
util.printout(package)
|
||||||
|
end
|
||||||
|
for version, repos in util.sortedpairs(versions, deps.compare_versions) do
|
||||||
|
for _, repo in ipairs(repos) do
|
||||||
|
repo.repo = dir.normalize(repo.repo)
|
||||||
|
if porcelain then
|
||||||
|
util.printout(package, version, repo.arch, repo.repo)
|
||||||
|
else
|
||||||
|
util.printout(" "..version.." ("..repo.arch..") - "..repo.repo)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not porcelain then
|
||||||
|
util.printout()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Splits a list of search results into two lists, one for "source" results
|
||||||
|
-- to be used with the "build" command, and one for "binary" results to be
|
||||||
|
-- used with the "install" command.
|
||||||
|
-- @param results table: A search results table.
|
||||||
|
-- @return (table, table): Two tables, one for source and one for binary
|
||||||
|
-- results.
|
||||||
|
local function split_source_and_binary_results(results)
|
||||||
|
local sources, binaries = {}, {}
|
||||||
|
for name, versions in pairs(results) do
|
||||||
|
for version, 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
|
||||||
|
store_result(where, name, version, repo.arch, repo.repo)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return sources, binaries
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Given a name and optionally a version, try to find in the rocks
|
||||||
|
-- servers a single .src.rock or .rockspec file that satisfies
|
||||||
|
-- the request, and run the given function on it; or display to the
|
||||||
|
-- user possibilities if it couldn't narrow down a single match.
|
||||||
|
-- @param action function: A function that takes a .src.rock or
|
||||||
|
-- .rockspec URL as a parameter.
|
||||||
|
-- @param name string: A rock name
|
||||||
|
-- @param version string or nil: A version number may also be given.
|
||||||
|
-- @return The result of the action function, or nil and an error message.
|
||||||
|
function search.act_on_src_or_rockspec(action, name, version, ...)
|
||||||
|
assert(type(action) == "function")
|
||||||
|
assert(type(name) == "string")
|
||||||
|
assert(type(version) == "string" or not version)
|
||||||
|
|
||||||
|
local query = search.make_query(name, version)
|
||||||
|
query.arch = "src|rockspec"
|
||||||
|
local url, err = search.find_suitable_rock(query)
|
||||||
|
if not url then
|
||||||
|
return nil, "Could not find a result named "..name..(version and " "..version or "")..": "..err
|
||||||
|
end
|
||||||
|
return action(url, ...)
|
||||||
|
end
|
||||||
|
|
||||||
|
function search.pick_installed_rock(name, version, given_tree)
|
||||||
|
local results = {}
|
||||||
|
local query = search.make_query(name, version)
|
||||||
|
query.exact_name = true
|
||||||
|
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.manifest_search(results, rocks_dir, query)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not next(results) then --
|
||||||
|
return nil,"cannot find package "..name.." "..(version or "").."\nUse 'list' to find installed rocks."
|
||||||
|
end
|
||||||
|
|
||||||
|
version = nil
|
||||||
|
local repo_url
|
||||||
|
local package, versions = util.sortedpairs(results)()
|
||||||
|
--question: what do we do about multiple versions? This should
|
||||||
|
--give us the latest version on the last repo (which is usually the global one)
|
||||||
|
for vs, repositories in util.sortedpairs(versions, deps.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
|
||||||
|
|
||||||
|
--- Driver function for "search" command.
|
||||||
|
-- @param name string: A substring of a rock name to search.
|
||||||
|
-- @param version string or nil: a version may also be passed.
|
||||||
|
-- @return boolean or (nil, string): True if build was successful; nil and an
|
||||||
|
-- error message otherwise.
|
||||||
|
function search.command(flags, name, version)
|
||||||
|
if flags["all"] then
|
||||||
|
name, version = "", nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(name) ~= "string" and not flags["all"] then
|
||||||
|
return nil, "Enter name and version or use --all. "..util.see_help("search")
|
||||||
|
end
|
||||||
|
|
||||||
|
local query = search.make_query(name:lower(), version)
|
||||||
|
query.exact_name = false
|
||||||
|
local results, err = search.search_repos(query)
|
||||||
|
local porcelain = flags["porcelain"]
|
||||||
|
util.title("Search results:", porcelain, "=")
|
||||||
|
local sources, binaries = split_source_and_binary_results(results)
|
||||||
|
if next(sources) and not flags["binary"] then
|
||||||
|
util.title("Rockspecs and source rocks:", porcelain)
|
||||||
|
search.print_results(sources, porcelain)
|
||||||
|
end
|
||||||
|
if next(binaries) and not flags["source"] then
|
||||||
|
util.title("Binary and pure-Lua rocks:", porcelain)
|
||||||
|
search.print_results(binaries, porcelain)
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return search
|
||||||
152
Utils/luarocks/lua/luarocks/show.lua
Normal file
152
Utils/luarocks/lua/luarocks/show.lua
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
--- Module implementing the LuaRocks "show" command.
|
||||||
|
-- Shows information about an installed rock.
|
||||||
|
local show = {}
|
||||||
|
package.loaded["luarocks.show"] = show
|
||||||
|
|
||||||
|
local search = require("luarocks.search")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
local deps = require("luarocks.deps")
|
||||||
|
local fetch = require("luarocks.fetch")
|
||||||
|
local manif = require("luarocks.manif")
|
||||||
|
|
||||||
|
util.add_run_function(show)
|
||||||
|
show.help_summary = "Show information about an installed rock."
|
||||||
|
|
||||||
|
show.help = [[
|
||||||
|
<argument> is an existing package name.
|
||||||
|
Without any flags, show all module information.
|
||||||
|
With these flags, return only the desired information:
|
||||||
|
|
||||||
|
--home home page of project
|
||||||
|
--modules all modules provided by this package as used by require()
|
||||||
|
--deps packages this package depends on
|
||||||
|
--rockspec the full path of the rockspec file
|
||||||
|
--mversion the package version
|
||||||
|
--rock-tree local tree where rock is installed
|
||||||
|
--rock-dir data directory of the installed rock
|
||||||
|
]]
|
||||||
|
|
||||||
|
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(name, tree)
|
||||||
|
local installed, version
|
||||||
|
if cfg.rocks_provided[name] then
|
||||||
|
installed, version = true, cfg.rocks_provided[name]
|
||||||
|
else
|
||||||
|
installed, version = search.pick_installed_rock(name, nil, tree)
|
||||||
|
end
|
||||||
|
return installed and "(using "..version..")" or "(missing)"
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Driver function for "show" command.
|
||||||
|
-- @param name or nil: an existing package name.
|
||||||
|
-- @param version string or nil: a version may also be passed.
|
||||||
|
-- @return boolean: True if succeeded, nil on errors.
|
||||||
|
function show.command(flags, name, version)
|
||||||
|
if not name then
|
||||||
|
return nil, "Argument missing. "..util.see_help("show")
|
||||||
|
end
|
||||||
|
|
||||||
|
local repo, repo_url
|
||||||
|
name, version, repo, repo_url = search.pick_installed_rock(name:lower(), version, flags["tree"])
|
||||||
|
if not name then
|
||||||
|
return nil, version
|
||||||
|
end
|
||||||
|
|
||||||
|
local directory = path.install_dir(name,version,repo)
|
||||||
|
local rockspec_file = path.rockspec_file(name, version, repo)
|
||||||
|
local rockspec, err = fetch.load_local_rockspec(rockspec_file)
|
||||||
|
if not rockspec then return nil,err end
|
||||||
|
|
||||||
|
local descript = rockspec.description or {}
|
||||||
|
local manifest, err = manif.load_manifest(repo_url)
|
||||||
|
if not manifest then return nil,err end
|
||||||
|
local minfo = manifest.repository[name][version][1]
|
||||||
|
|
||||||
|
if flags["rock-tree"] then util.printout(path.rocks_tree_to_string(repo))
|
||||||
|
elseif flags["rock-dir"] then util.printout(directory)
|
||||||
|
elseif flags["home"] then util.printout(descript.homepage)
|
||||||
|
elseif flags["modules"] then util.printout(keys_as_string(minfo.modules, "\n"))
|
||||||
|
elseif flags["deps"] then util.printout(keys_as_string(minfo.dependencies))
|
||||||
|
elseif flags["rockspec"] then util.printout(rockspec_file)
|
||||||
|
elseif flags["mversion"] then util.printout(version)
|
||||||
|
else
|
||||||
|
util.printout()
|
||||||
|
util.printout(rockspec.package.." "..rockspec.version.." - "..(descript.summary or ""))
|
||||||
|
util.printout()
|
||||||
|
if descript.detailed then
|
||||||
|
util.printout(format_text(descript.detailed))
|
||||||
|
util.printout()
|
||||||
|
end
|
||||||
|
if descript.license then
|
||||||
|
util.printout("License: ", descript.license)
|
||||||
|
end
|
||||||
|
if descript.homepage then
|
||||||
|
util.printout("Homepage: ", descript.homepage)
|
||||||
|
end
|
||||||
|
util.printout("Installed in: ", path.rocks_tree_to_string(repo))
|
||||||
|
if next(minfo.modules) then
|
||||||
|
util.printout()
|
||||||
|
util.printout("Modules:")
|
||||||
|
for mod, filename in util.sortedpairs(minfo.modules) do
|
||||||
|
util.printout("\t"..mod.." ("..path.which(mod, filename, name, version, repo, manifest)..")")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local direct_deps = {}
|
||||||
|
if #rockspec.dependencies > 0 then
|
||||||
|
util.printout()
|
||||||
|
util.printout("Depends on:")
|
||||||
|
for _, dep in ipairs(rockspec.dependencies) do
|
||||||
|
direct_deps[dep.name] = true
|
||||||
|
util.printout("\t"..deps.show_dep(dep).." "..installed_rock_label(dep.name, flags["tree"]))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local has_indirect_deps
|
||||||
|
for dep_name in util.sortedpairs(minfo.dependencies) do
|
||||||
|
if not direct_deps[dep_name] then
|
||||||
|
if not has_indirect_deps then
|
||||||
|
util.printout()
|
||||||
|
util.printout("Indirectly pulling:")
|
||||||
|
has_indirect_deps = true
|
||||||
|
end
|
||||||
|
|
||||||
|
util.printout("\t"..dep_name.." "..installed_rock_label(dep_name, flags["tree"]))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
util.printout()
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return show
|
||||||
14
Utils/luarocks/lua/luarocks/site_config_5_1.lua
Normal file
14
Utils/luarocks/lua/luarocks/site_config_5_1.lua
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
local site_config = {}
|
||||||
|
site_config.LUA_INCDIR=[[C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\include]]
|
||||||
|
site_config.LUA_LIBDIR=[[C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks]]
|
||||||
|
site_config.LUA_BINDIR=[[C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks]]
|
||||||
|
site_config.LUA_INTERPRETER=[[lua5.1]]
|
||||||
|
site_config.LUAROCKS_UNAME_S=[[MINGW]]
|
||||||
|
site_config.LUAROCKS_UNAME_M=[[x86]]
|
||||||
|
site_config.LUAROCKS_ROCKS_TREE=[[C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\systree]]
|
||||||
|
site_config.LUAROCKS_PREFIX=[[C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks]]
|
||||||
|
site_config.LUAROCKS_DOWNLOADER=[[wget]]
|
||||||
|
site_config.LUAROCKS_MD5CHECKER=[[md5sum]]
|
||||||
|
site_config.LUAROCKS_FORCE_CONFIG=true
|
||||||
|
site_config.LUAROCKS_SYSCONFDIR=[[C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks]]
|
||||||
|
return site_config
|
||||||
700
Utils/luarocks/lua/luarocks/tools/patch.lua
Normal file
700
Utils/luarocks/lua/luarocks/tools/patch.lua
Normal file
@ -0,0 +1,700 @@
|
|||||||
|
--- Patch utility to apply unified diffs.
|
||||||
|
--
|
||||||
|
-- http://lua-users.org/wiki/LuaPatch
|
||||||
|
--
|
||||||
|
-- (c) 2008 David Manura, Licensed under the same terms as Lua (MIT license).
|
||||||
|
-- Code is heavilly based on the Python-based patch.py version 8.06-1
|
||||||
|
-- Copyright (c) 2008 rainforce.org, MIT License
|
||||||
|
-- Project home: http://code.google.com/p/python-patch/ .
|
||||||
|
-- Version 0.1
|
||||||
|
|
||||||
|
local patch = {}
|
||||||
|
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
|
||||||
|
local io = io
|
||||||
|
local os = os
|
||||||
|
local string = string
|
||||||
|
local table = table
|
||||||
|
local format = string.format
|
||||||
|
|
||||||
|
-- logging
|
||||||
|
local debugmode = false
|
||||||
|
local function debug(_) end
|
||||||
|
local function info(_) end
|
||||||
|
local function warning(s) io.stderr:write(s .. '\n') end
|
||||||
|
|
||||||
|
-- Returns boolean whether string s2 starts with string s.
|
||||||
|
local function startswith(s, s2)
|
||||||
|
return s:sub(1, #s2) == s2
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns boolean whether string s2 ends with string s.
|
||||||
|
local function endswith(s, s2)
|
||||||
|
return #s >= #s2 and s:sub(#s-#s2+1) == s2
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns string s after filtering out any new-line characters from end.
|
||||||
|
local function endlstrip(s)
|
||||||
|
return s:gsub('[\r\n]+$', '')
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns shallow copy of table t.
|
||||||
|
local function table_copy(t)
|
||||||
|
local t2 = {}
|
||||||
|
for k,v in pairs(t) do t2[k] = v end
|
||||||
|
return t2
|
||||||
|
end
|
||||||
|
|
||||||
|
local function exists(filename)
|
||||||
|
local fh = io.open(filename)
|
||||||
|
local result = fh ~= nil
|
||||||
|
if fh then fh:close() end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
local function isfile() return true end --FIX?
|
||||||
|
|
||||||
|
local function read_file(filename)
|
||||||
|
local fh, data, err, oserr
|
||||||
|
fh, err, oserr = io.open(filename, 'rb')
|
||||||
|
if not fh then return fh, err, oserr end
|
||||||
|
data, err, oserr = fh:read'*a'
|
||||||
|
fh:close()
|
||||||
|
if not data then return nil, err, oserr end
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
|
||||||
|
local function write_file(filename, data)
|
||||||
|
local fh, status, err, oserr
|
||||||
|
fh, err, oserr = io.open(filename 'wb')
|
||||||
|
if not fh then return fh, err, oserr end
|
||||||
|
status, err, oserr = fh:write(data)
|
||||||
|
fh:close()
|
||||||
|
if not status then return nil, err, oserr end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function file_copy(src, dest)
|
||||||
|
local data, status, err, oserr
|
||||||
|
data, err, oserr = read_file(src)
|
||||||
|
if not data then return data, err, oserr end
|
||||||
|
status, err, oserr = write_file(dest)
|
||||||
|
if not status then return status, err, oserr end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function string_as_file(s)
|
||||||
|
return {
|
||||||
|
at = 0,
|
||||||
|
str = s,
|
||||||
|
len = #s,
|
||||||
|
eof = false,
|
||||||
|
read = function(self, n)
|
||||||
|
if self.eof then return nil end
|
||||||
|
local chunk = self.str:sub(self.at, self.at + n - 1)
|
||||||
|
self.at = self.at + n
|
||||||
|
if self.at > self.len then
|
||||||
|
self.eof = true
|
||||||
|
end
|
||||||
|
return chunk
|
||||||
|
end,
|
||||||
|
close = function(self)
|
||||||
|
self.eof = true
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- file_lines(f) is similar to f:lines() for file f.
|
||||||
|
-- The main difference is that read_lines includes
|
||||||
|
-- new-line character sequences ("\n", "\r\n", "\r"),
|
||||||
|
-- if any, at the end of each line. Embedded "\0" are also handled.
|
||||||
|
-- Caution: The newline behavior can depend on whether f is opened
|
||||||
|
-- in binary or ASCII mode.
|
||||||
|
-- (file_lines - version 20080913)
|
||||||
|
--
|
||||||
|
local function file_lines(f)
|
||||||
|
local CHUNK_SIZE = 1024
|
||||||
|
local buffer = ""
|
||||||
|
local pos_beg = 1
|
||||||
|
return function()
|
||||||
|
local pos, chars
|
||||||
|
while 1 do
|
||||||
|
pos, chars = buffer:match('()([\r\n].)', pos_beg)
|
||||||
|
if pos or not f then
|
||||||
|
break
|
||||||
|
elseif f then
|
||||||
|
local chunk = f:read(CHUNK_SIZE)
|
||||||
|
if chunk then
|
||||||
|
buffer = buffer:sub(pos_beg) .. chunk
|
||||||
|
pos_beg = 1
|
||||||
|
else
|
||||||
|
f = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not pos then
|
||||||
|
pos = #buffer
|
||||||
|
elseif chars == '\r\n' then
|
||||||
|
pos = pos + 1
|
||||||
|
end
|
||||||
|
local line = buffer:sub(pos_beg, pos)
|
||||||
|
pos_beg = pos + 1
|
||||||
|
if #line > 0 then
|
||||||
|
return line
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function match_linerange(line)
|
||||||
|
local m1, m2, m3, m4 = line:match("^@@ %-(%d+),(%d+) %+(%d+),(%d+)")
|
||||||
|
if not m1 then m1, m3, m4 = line:match("^@@ %-(%d+) %+(%d+),(%d+)") end
|
||||||
|
if not m1 then m1, m2, m3 = line:match("^@@ %-(%d+),(%d+) %+(%d+)") end
|
||||||
|
if not m1 then m1, m3 = line:match("^@@ %-(%d+) %+(%d+)") end
|
||||||
|
return m1, m2, m3, m4
|
||||||
|
end
|
||||||
|
|
||||||
|
function patch.read_patch(filename, data)
|
||||||
|
-- define possible file regions that will direct the parser flow
|
||||||
|
local state = 'header'
|
||||||
|
-- 'header' - comments before the patch body
|
||||||
|
-- 'filenames' - lines starting with --- and +++
|
||||||
|
-- 'hunkhead' - @@ -R +R @@ sequence
|
||||||
|
-- 'hunkbody'
|
||||||
|
-- 'hunkskip' - skipping invalid hunk mode
|
||||||
|
|
||||||
|
local all_ok = true
|
||||||
|
local lineends = {lf=0, crlf=0, cr=0}
|
||||||
|
local files = {source={}, target={}, hunks={}, fileends={}, hunkends={}}
|
||||||
|
local nextfileno = 0
|
||||||
|
local nexthunkno = 0 --: even if index starts with 0 user messages
|
||||||
|
-- number hunks from 1
|
||||||
|
|
||||||
|
-- hunkinfo holds parsed values, hunkactual - calculated
|
||||||
|
local hunkinfo = {
|
||||||
|
startsrc=nil, linessrc=nil, starttgt=nil, linestgt=nil,
|
||||||
|
invalid=false, text={}
|
||||||
|
}
|
||||||
|
local hunkactual = {linessrc=nil, linestgt=nil}
|
||||||
|
|
||||||
|
info(format("reading patch %s", filename))
|
||||||
|
|
||||||
|
local fp
|
||||||
|
if data then
|
||||||
|
fp = string_as_file(data)
|
||||||
|
else
|
||||||
|
fp = filename == '-' and io.stdin or assert(io.open(filename, "rb"))
|
||||||
|
end
|
||||||
|
local lineno = 0
|
||||||
|
|
||||||
|
for line in file_lines(fp) do
|
||||||
|
lineno = lineno + 1
|
||||||
|
if state == 'header' then
|
||||||
|
if startswith(line, "--- ") then
|
||||||
|
state = 'filenames'
|
||||||
|
end
|
||||||
|
-- state is 'header' or 'filenames'
|
||||||
|
end
|
||||||
|
if state == 'hunkbody' then
|
||||||
|
-- skip hunkskip and hunkbody code until definition of hunkhead read
|
||||||
|
|
||||||
|
if line:match"^[\r\n]*$" then
|
||||||
|
-- prepend space to empty lines to interpret them as context properly
|
||||||
|
line = " " .. line
|
||||||
|
end
|
||||||
|
|
||||||
|
-- process line first
|
||||||
|
if line:match"^[- +\\]" then
|
||||||
|
-- gather stats about line endings
|
||||||
|
local he = files.hunkends[nextfileno]
|
||||||
|
if endswith(line, "\r\n") then
|
||||||
|
he.crlf = he.crlf + 1
|
||||||
|
elseif endswith(line, "\n") then
|
||||||
|
he.lf = he.lf + 1
|
||||||
|
elseif endswith(line, "\r") then
|
||||||
|
he.cr = he.cr + 1
|
||||||
|
end
|
||||||
|
if startswith(line, "-") then
|
||||||
|
hunkactual.linessrc = hunkactual.linessrc + 1
|
||||||
|
elseif startswith(line, "+") then
|
||||||
|
hunkactual.linestgt = hunkactual.linestgt + 1
|
||||||
|
elseif startswith(line, "\\") then
|
||||||
|
-- nothing
|
||||||
|
else
|
||||||
|
hunkactual.linessrc = hunkactual.linessrc + 1
|
||||||
|
hunkactual.linestgt = hunkactual.linestgt + 1
|
||||||
|
end
|
||||||
|
table.insert(hunkinfo.text, line)
|
||||||
|
-- todo: handle \ No newline cases
|
||||||
|
else
|
||||||
|
warning(format("invalid hunk no.%d at %d for target file %s",
|
||||||
|
nexthunkno, lineno, files.target[nextfileno]))
|
||||||
|
-- add hunk status node
|
||||||
|
table.insert(files.hunks[nextfileno], table_copy(hunkinfo))
|
||||||
|
files.hunks[nextfileno][nexthunkno].invalid = true
|
||||||
|
all_ok = false
|
||||||
|
state = 'hunkskip'
|
||||||
|
end
|
||||||
|
|
||||||
|
-- check exit conditions
|
||||||
|
if hunkactual.linessrc > hunkinfo.linessrc or
|
||||||
|
hunkactual.linestgt > hunkinfo.linestgt
|
||||||
|
then
|
||||||
|
warning(format("extra hunk no.%d lines at %d for target %s",
|
||||||
|
nexthunkno, lineno, files.target[nextfileno]))
|
||||||
|
-- add hunk status node
|
||||||
|
table.insert(files.hunks[nextfileno], table_copy(hunkinfo))
|
||||||
|
files.hunks[nextfileno][nexthunkno].invalid = true
|
||||||
|
state = 'hunkskip'
|
||||||
|
elseif hunkinfo.linessrc == hunkactual.linessrc and
|
||||||
|
hunkinfo.linestgt == hunkactual.linestgt
|
||||||
|
then
|
||||||
|
table.insert(files.hunks[nextfileno], table_copy(hunkinfo))
|
||||||
|
state = 'hunkskip'
|
||||||
|
|
||||||
|
-- detect mixed window/unix line ends
|
||||||
|
local ends = files.hunkends[nextfileno]
|
||||||
|
if (ends.cr~=0 and 1 or 0) + (ends.crlf~=0 and 1 or 0) +
|
||||||
|
(ends.lf~=0 and 1 or 0) > 1
|
||||||
|
then
|
||||||
|
warning(format("inconsistent line ends in patch hunks for %s",
|
||||||
|
files.source[nextfileno]))
|
||||||
|
end
|
||||||
|
if debugmode then
|
||||||
|
local debuglines = {crlf=ends.crlf, lf=ends.lf, cr=ends.cr,
|
||||||
|
file=files.target[nextfileno], hunk=nexthunkno}
|
||||||
|
debug(format("crlf: %(crlf)d lf: %(lf)d cr: %(cr)d\t " ..
|
||||||
|
"- file: %(file)s hunk: %(hunk)d", debuglines))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- state is 'hunkbody' or 'hunkskip'
|
||||||
|
end
|
||||||
|
|
||||||
|
if state == 'hunkskip' then
|
||||||
|
if match_linerange(line) then
|
||||||
|
state = 'hunkhead'
|
||||||
|
elseif startswith(line, "--- ") then
|
||||||
|
state = 'filenames'
|
||||||
|
if debugmode and #files.source > 0 then
|
||||||
|
debug(format("- %2d hunks for %s", #files.hunks[nextfileno],
|
||||||
|
files.source[nextfileno]))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- state is 'hunkskip', 'hunkhead', or 'filenames'
|
||||||
|
end
|
||||||
|
local advance
|
||||||
|
if state == 'filenames' then
|
||||||
|
if startswith(line, "--- ") then
|
||||||
|
if util.array_contains(files.source, nextfileno) then
|
||||||
|
all_ok = false
|
||||||
|
warning(format("skipping invalid patch for %s",
|
||||||
|
files.source[nextfileno+1]))
|
||||||
|
table.remove(files.source, nextfileno+1)
|
||||||
|
-- double source filename line is encountered
|
||||||
|
-- attempt to restart from this second line
|
||||||
|
end
|
||||||
|
-- Accept a space as a terminator, like GNU patch does.
|
||||||
|
-- Breaks patches containing filenames with spaces...
|
||||||
|
-- FIXME Figure out what does GNU patch do in those cases.
|
||||||
|
local match = line:match("^%-%-%- ([^ \t\r\n]+)")
|
||||||
|
if not match then
|
||||||
|
all_ok = false
|
||||||
|
warning(format("skipping invalid filename at line %d", lineno+1))
|
||||||
|
state = 'header'
|
||||||
|
else
|
||||||
|
table.insert(files.source, match)
|
||||||
|
end
|
||||||
|
elseif not startswith(line, "+++ ") then
|
||||||
|
if util.array_contains(files.source, nextfileno) then
|
||||||
|
all_ok = false
|
||||||
|
warning(format("skipping invalid patch with no target for %s",
|
||||||
|
files.source[nextfileno+1]))
|
||||||
|
table.remove(files.source, nextfileno+1)
|
||||||
|
else
|
||||||
|
-- this should be unreachable
|
||||||
|
warning("skipping invalid target patch")
|
||||||
|
end
|
||||||
|
state = 'header'
|
||||||
|
else
|
||||||
|
if util.array_contains(files.target, nextfileno) then
|
||||||
|
all_ok = false
|
||||||
|
warning(format("skipping invalid patch - double target at line %d",
|
||||||
|
lineno+1))
|
||||||
|
table.remove(files.source, nextfileno+1)
|
||||||
|
table.remove(files.target, nextfileno+1)
|
||||||
|
nextfileno = nextfileno - 1
|
||||||
|
-- double target filename line is encountered
|
||||||
|
-- switch back to header state
|
||||||
|
state = 'header'
|
||||||
|
else
|
||||||
|
-- Accept a space as a terminator, like GNU patch does.
|
||||||
|
-- Breaks patches containing filenames with spaces...
|
||||||
|
-- FIXME Figure out what does GNU patch do in those cases.
|
||||||
|
local re_filename = "^%+%+%+ ([^ \t\r\n]+)"
|
||||||
|
local match = line:match(re_filename)
|
||||||
|
if not match then
|
||||||
|
all_ok = false
|
||||||
|
warning(format(
|
||||||
|
"skipping invalid patch - no target filename at line %d",
|
||||||
|
lineno+1))
|
||||||
|
state = 'header'
|
||||||
|
else
|
||||||
|
table.insert(files.target, match)
|
||||||
|
nextfileno = nextfileno + 1
|
||||||
|
nexthunkno = 0
|
||||||
|
table.insert(files.hunks, {})
|
||||||
|
table.insert(files.hunkends, table_copy(lineends))
|
||||||
|
table.insert(files.fileends, table_copy(lineends))
|
||||||
|
state = 'hunkhead'
|
||||||
|
advance = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- state is 'filenames', 'header', or ('hunkhead' with advance)
|
||||||
|
end
|
||||||
|
if not advance and state == 'hunkhead' then
|
||||||
|
local m1, m2, m3, m4 = match_linerange(line)
|
||||||
|
if not m1 then
|
||||||
|
if not util.array_contains(files.hunks, nextfileno-1) then
|
||||||
|
all_ok = false
|
||||||
|
warning(format("skipping invalid patch with no hunks for file %s",
|
||||||
|
files.target[nextfileno]))
|
||||||
|
end
|
||||||
|
state = 'header'
|
||||||
|
else
|
||||||
|
hunkinfo.startsrc = tonumber(m1)
|
||||||
|
hunkinfo.linessrc = tonumber(m2 or 1)
|
||||||
|
hunkinfo.starttgt = tonumber(m3)
|
||||||
|
hunkinfo.linestgt = tonumber(m4 or 1)
|
||||||
|
hunkinfo.invalid = false
|
||||||
|
hunkinfo.text = {}
|
||||||
|
|
||||||
|
hunkactual.linessrc = 0
|
||||||
|
hunkactual.linestgt = 0
|
||||||
|
|
||||||
|
state = 'hunkbody'
|
||||||
|
nexthunkno = nexthunkno + 1
|
||||||
|
end
|
||||||
|
-- state is 'header' or 'hunkbody'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if state ~= 'hunkskip' then
|
||||||
|
warning(format("patch file incomplete - %s", filename))
|
||||||
|
all_ok = false
|
||||||
|
-- os.exit(?)
|
||||||
|
else
|
||||||
|
-- duplicated message when an eof is reached
|
||||||
|
if debugmode and #files.source > 0 then
|
||||||
|
debug(format("- %2d hunks for %s", #files.hunks[nextfileno],
|
||||||
|
files.source[nextfileno]))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local sum = 0; for _,hset in ipairs(files.hunks) do sum = sum + #hset end
|
||||||
|
info(format("total files: %d total hunks: %d", #files.source, sum))
|
||||||
|
fp:close()
|
||||||
|
return files, all_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
local function find_hunk(file, h, hno)
|
||||||
|
for fuzz=0,2 do
|
||||||
|
local lineno = h.startsrc
|
||||||
|
for i=0,#file do
|
||||||
|
local found = true
|
||||||
|
local location = lineno
|
||||||
|
for l, hline in ipairs(h.text) do
|
||||||
|
if l > fuzz then
|
||||||
|
-- todo: \ No newline at the end of file
|
||||||
|
if startswith(hline, " ") or startswith(hline, "-") then
|
||||||
|
local line = file[lineno]
|
||||||
|
lineno = lineno + 1
|
||||||
|
if not line or #line == 0 then
|
||||||
|
found = false
|
||||||
|
break
|
||||||
|
end
|
||||||
|
if endlstrip(line) ~= endlstrip(hline:sub(2)) then
|
||||||
|
found = false
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if found then
|
||||||
|
local offset = location - h.startsrc - fuzz
|
||||||
|
if offset ~= 0 then
|
||||||
|
warning(format("Hunk %d found at offset %d%s...", hno, offset, fuzz == 0 and "" or format(" (fuzz %d)", fuzz)))
|
||||||
|
end
|
||||||
|
h.startsrc = location
|
||||||
|
h.starttgt = h.starttgt + offset
|
||||||
|
for _=1,fuzz do
|
||||||
|
table.remove(h.text, 1)
|
||||||
|
table.remove(h.text, #h.text)
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
lineno = i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local function load_file(filename)
|
||||||
|
local fp = assert(io.open(filename))
|
||||||
|
local file = {}
|
||||||
|
local readline = file_lines(fp)
|
||||||
|
while true do
|
||||||
|
local line = readline()
|
||||||
|
if not line then break end
|
||||||
|
table.insert(file, line)
|
||||||
|
end
|
||||||
|
fp:close()
|
||||||
|
return file
|
||||||
|
end
|
||||||
|
|
||||||
|
local function find_hunks(file, hunks)
|
||||||
|
for hno, h in ipairs(hunks) do
|
||||||
|
find_hunk(file, h, hno)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function check_patched(file, hunks)
|
||||||
|
local lineno = 1
|
||||||
|
local ok, err = pcall(function()
|
||||||
|
if #file == 0 then
|
||||||
|
error('nomatch', 0)
|
||||||
|
end
|
||||||
|
for hno, h in ipairs(hunks) do
|
||||||
|
-- skip to line just before hunk starts
|
||||||
|
if #file < h.starttgt then
|
||||||
|
error('nomatch', 0)
|
||||||
|
end
|
||||||
|
lineno = h.starttgt
|
||||||
|
for _, hline in ipairs(h.text) do
|
||||||
|
-- todo: \ No newline at the end of file
|
||||||
|
if not startswith(hline, "-") and not startswith(hline, "\\") then
|
||||||
|
local line = file[lineno]
|
||||||
|
lineno = lineno + 1
|
||||||
|
if #line == 0 then
|
||||||
|
error('nomatch', 0)
|
||||||
|
end
|
||||||
|
if endlstrip(line) ~= endlstrip(hline:sub(2)) then
|
||||||
|
warning(format("file is not patched - failed hunk: %d", hno))
|
||||||
|
error('nomatch', 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
-- todo: display failed hunk, i.e. expected/found
|
||||||
|
return err ~= 'nomatch'
|
||||||
|
end
|
||||||
|
|
||||||
|
local function patch_hunks(srcname, tgtname, hunks)
|
||||||
|
local src = assert(io.open(srcname, "rb"))
|
||||||
|
local tgt = assert(io.open(tgtname, "wb"))
|
||||||
|
|
||||||
|
local src_readline = file_lines(src)
|
||||||
|
|
||||||
|
-- todo: detect linefeeds early - in apply_files routine
|
||||||
|
-- to handle cases when patch starts right from the first
|
||||||
|
-- line and no lines are processed. At the moment substituted
|
||||||
|
-- lineends may not be the same at the start and at the end
|
||||||
|
-- of patching. Also issue a warning about mixed lineends
|
||||||
|
|
||||||
|
local srclineno = 1
|
||||||
|
local lineends = {['\n']=0, ['\r\n']=0, ['\r']=0}
|
||||||
|
for hno, h in ipairs(hunks) do
|
||||||
|
debug(format("processing hunk %d for file %s", hno, tgtname))
|
||||||
|
-- skip to line just before hunk starts
|
||||||
|
while srclineno < h.startsrc do
|
||||||
|
local line = src_readline()
|
||||||
|
-- Python 'U' mode works only with text files
|
||||||
|
if endswith(line, "\r\n") then
|
||||||
|
lineends["\r\n"] = lineends["\r\n"] + 1
|
||||||
|
elseif endswith(line, "\n") then
|
||||||
|
lineends["\n"] = lineends["\n"] + 1
|
||||||
|
elseif endswith(line, "\r") then
|
||||||
|
lineends["\r"] = lineends["\r"] + 1
|
||||||
|
end
|
||||||
|
tgt:write(line)
|
||||||
|
srclineno = srclineno + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
for _,hline in ipairs(h.text) do
|
||||||
|
-- todo: check \ No newline at the end of file
|
||||||
|
if startswith(hline, "-") or startswith(hline, "\\") then
|
||||||
|
src_readline()
|
||||||
|
srclineno = srclineno + 1
|
||||||
|
else
|
||||||
|
if not startswith(hline, "+") then
|
||||||
|
src_readline()
|
||||||
|
srclineno = srclineno + 1
|
||||||
|
end
|
||||||
|
local line2write = hline:sub(2)
|
||||||
|
-- detect if line ends are consistent in source file
|
||||||
|
local sum = 0
|
||||||
|
for _,v in pairs(lineends) do if v > 0 then sum=sum+1 end end
|
||||||
|
if sum == 1 then
|
||||||
|
local newline
|
||||||
|
for k,v in pairs(lineends) do if v ~= 0 then newline = k end end
|
||||||
|
tgt:write(endlstrip(line2write) .. newline)
|
||||||
|
else -- newlines are mixed or unknown
|
||||||
|
tgt:write(line2write)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for line in src_readline do
|
||||||
|
tgt:write(line)
|
||||||
|
end
|
||||||
|
tgt:close()
|
||||||
|
src:close()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function strip_dirs(filename, strip)
|
||||||
|
if strip == nil then return filename end
|
||||||
|
for _=1,strip do
|
||||||
|
filename=filename:gsub("^[^/]*/", "")
|
||||||
|
end
|
||||||
|
return filename
|
||||||
|
end
|
||||||
|
|
||||||
|
function patch.apply_patch(the_patch, strip)
|
||||||
|
local all_ok = true
|
||||||
|
local total = #the_patch.source
|
||||||
|
for fileno, filename in ipairs(the_patch.source) do
|
||||||
|
filename = strip_dirs(filename, strip)
|
||||||
|
local continue
|
||||||
|
local f2patch = filename
|
||||||
|
if not exists(f2patch) then
|
||||||
|
f2patch = strip_dirs(the_patch.target[fileno], strip)
|
||||||
|
f2patch = fs.absolute_name(f2patch)
|
||||||
|
if not exists(f2patch) then --FIX:if f2patch nil
|
||||||
|
warning(format("source/target file does not exist\n--- %s\n+++ %s",
|
||||||
|
filename, f2patch))
|
||||||
|
all_ok = false
|
||||||
|
continue = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not continue and not isfile(f2patch) then
|
||||||
|
warning(format("not a file - %s", f2patch))
|
||||||
|
all_ok = false
|
||||||
|
continue = true
|
||||||
|
end
|
||||||
|
if not continue then
|
||||||
|
|
||||||
|
filename = f2patch
|
||||||
|
|
||||||
|
info(format("processing %d/%d:\t %s", fileno, total, filename))
|
||||||
|
|
||||||
|
-- validate before patching
|
||||||
|
local hunks = the_patch.hunks[fileno]
|
||||||
|
local file = load_file(filename)
|
||||||
|
local hunkno = 1
|
||||||
|
local hunk = hunks[hunkno]
|
||||||
|
local hunkfind = {}
|
||||||
|
local validhunks = 0
|
||||||
|
local canpatch = false
|
||||||
|
local hunklineno
|
||||||
|
local isbreak
|
||||||
|
local lineno = 0
|
||||||
|
|
||||||
|
find_hunks(file, hunks)
|
||||||
|
|
||||||
|
for _, line in ipairs(file) do
|
||||||
|
lineno = lineno + 1
|
||||||
|
local continue
|
||||||
|
if not hunk or lineno < hunk.startsrc then
|
||||||
|
continue = true
|
||||||
|
elseif lineno == hunk.startsrc then
|
||||||
|
hunkfind = {}
|
||||||
|
for _,x in ipairs(hunk.text) do
|
||||||
|
if x:sub(1,1) == ' ' or x:sub(1,1) == '-' then
|
||||||
|
hunkfind[#hunkfind+1] = endlstrip(x:sub(2))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
hunklineno = 1
|
||||||
|
|
||||||
|
-- todo \ No newline at end of file
|
||||||
|
end
|
||||||
|
-- check hunks in source file
|
||||||
|
if not continue and lineno < hunk.startsrc + #hunkfind - 1 then
|
||||||
|
if endlstrip(line) == hunkfind[hunklineno] then
|
||||||
|
hunklineno = hunklineno + 1
|
||||||
|
else
|
||||||
|
debug(format("hunk no.%d doesn't match source file %s",
|
||||||
|
hunkno, filename))
|
||||||
|
-- file may be already patched, but check other hunks anyway
|
||||||
|
hunkno = hunkno + 1
|
||||||
|
if hunkno <= #hunks then
|
||||||
|
hunk = hunks[hunkno]
|
||||||
|
continue = true
|
||||||
|
else
|
||||||
|
isbreak = true; break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- check if processed line is the last line
|
||||||
|
if not continue and lineno == hunk.startsrc + #hunkfind - 1 then
|
||||||
|
debug(format("file %s hunk no.%d -- is ready to be patched",
|
||||||
|
filename, hunkno))
|
||||||
|
hunkno = hunkno + 1
|
||||||
|
validhunks = validhunks + 1
|
||||||
|
if hunkno <= #hunks then
|
||||||
|
hunk = hunks[hunkno]
|
||||||
|
else
|
||||||
|
if validhunks == #hunks then
|
||||||
|
-- patch file
|
||||||
|
canpatch = true
|
||||||
|
isbreak = true; break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not isbreak then
|
||||||
|
if hunkno <= #hunks then
|
||||||
|
warning(format("premature end of source file %s at hunk %d",
|
||||||
|
filename, hunkno))
|
||||||
|
all_ok = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if validhunks < #hunks then
|
||||||
|
if check_patched(file, hunks) then
|
||||||
|
warning(format("already patched %s", filename))
|
||||||
|
else
|
||||||
|
warning(format("source file is different - %s", filename))
|
||||||
|
all_ok = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if canpatch then
|
||||||
|
local backupname = filename .. ".orig"
|
||||||
|
if exists(backupname) then
|
||||||
|
warning(format("can't backup original file to %s - aborting",
|
||||||
|
backupname))
|
||||||
|
all_ok = false
|
||||||
|
else
|
||||||
|
assert(os.rename(filename, backupname))
|
||||||
|
if patch_hunks(backupname, filename, hunks) then
|
||||||
|
warning(format("successfully patched %s", filename))
|
||||||
|
assert(os.remove(backupname))
|
||||||
|
else
|
||||||
|
warning(format("error patching file %s", filename))
|
||||||
|
assert(file_copy(filename, filename .. ".invalid"))
|
||||||
|
warning(format("invalid version is saved to %s",
|
||||||
|
filename .. ".invalid"))
|
||||||
|
-- todo: proper rejects
|
||||||
|
assert(os.rename(backupname, filename))
|
||||||
|
all_ok = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end -- if not continue
|
||||||
|
end -- for
|
||||||
|
-- todo: check for premature eof
|
||||||
|
return all_ok
|
||||||
|
end
|
||||||
|
|
||||||
|
return patch
|
||||||
150
Utils/luarocks/lua/luarocks/tools/tar.lua
Normal file
150
Utils/luarocks/lua/luarocks/tools/tar.lua
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
|
||||||
|
--- A pure-Lua implementation of untar (unpacking .tar archives)
|
||||||
|
local tar = {}
|
||||||
|
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
|
||||||
|
local blocksize = 512
|
||||||
|
|
||||||
|
local function get_typeflag(flag)
|
||||||
|
if flag == "0" or flag == "\0" then return "file"
|
||||||
|
elseif flag == "1" then return "link"
|
||||||
|
elseif flag == "2" then return "symlink" -- "reserved" in POSIX, "symlink" in GNU
|
||||||
|
elseif flag == "3" then return "character"
|
||||||
|
elseif flag == "4" then return "block"
|
||||||
|
elseif flag == "5" then return "directory"
|
||||||
|
elseif flag == "6" then return "fifo"
|
||||||
|
elseif flag == "7" then return "contiguous" -- "reserved" in POSIX, "contiguous" in GNU
|
||||||
|
elseif flag == "x" then return "next file"
|
||||||
|
elseif flag == "g" then return "global extended header"
|
||||||
|
elseif flag == "L" then return "long name"
|
||||||
|
elseif flag == "K" then return "long link name"
|
||||||
|
end
|
||||||
|
return "unknown"
|
||||||
|
end
|
||||||
|
|
||||||
|
local function octal_to_number(octal)
|
||||||
|
local exp = 0
|
||||||
|
local number = 0
|
||||||
|
for i = #octal,1,-1 do
|
||||||
|
local digit = tonumber(octal:sub(i,i))
|
||||||
|
if digit then
|
||||||
|
number = number + (digit * 8^exp)
|
||||||
|
exp = exp + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return number
|
||||||
|
end
|
||||||
|
|
||||||
|
local function checksum_header(block)
|
||||||
|
local sum = 256
|
||||||
|
for i = 1,148 do
|
||||||
|
sum = sum + block:byte(i)
|
||||||
|
end
|
||||||
|
for i = 157,500 do
|
||||||
|
sum = sum + block:byte(i)
|
||||||
|
end
|
||||||
|
return sum
|
||||||
|
end
|
||||||
|
|
||||||
|
local function nullterm(s)
|
||||||
|
return s:match("^[^%z]*")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function read_header_block(block)
|
||||||
|
local header = {}
|
||||||
|
header.name = nullterm(block:sub(1,100))
|
||||||
|
header.mode = nullterm(block:sub(101,108))
|
||||||
|
header.uid = octal_to_number(nullterm(block:sub(109,116)))
|
||||||
|
header.gid = octal_to_number(nullterm(block:sub(117,124)))
|
||||||
|
header.size = octal_to_number(nullterm(block:sub(125,136)))
|
||||||
|
header.mtime = octal_to_number(nullterm(block:sub(137,148)))
|
||||||
|
header.chksum = octal_to_number(nullterm(block:sub(149,156)))
|
||||||
|
header.typeflag = get_typeflag(block:sub(157,157))
|
||||||
|
header.linkname = nullterm(block:sub(158,257))
|
||||||
|
header.magic = block:sub(258,263)
|
||||||
|
header.version = block:sub(264,265)
|
||||||
|
header.uname = nullterm(block:sub(266,297))
|
||||||
|
header.gname = nullterm(block:sub(298,329))
|
||||||
|
header.devmajor = octal_to_number(nullterm(block:sub(330,337)))
|
||||||
|
header.devminor = octal_to_number(nullterm(block:sub(338,345)))
|
||||||
|
header.prefix = block:sub(346,500)
|
||||||
|
if header.magic ~= "ustar " and header.magic ~= "ustar\0" then
|
||||||
|
return false, "Invalid header magic "..header.magic
|
||||||
|
end
|
||||||
|
if header.version ~= "00" and header.version ~= " \0" then
|
||||||
|
return false, "Unknown version "..header.version
|
||||||
|
end
|
||||||
|
if not checksum_header(block) == header.chksum then
|
||||||
|
return false, "Failed header checksum"
|
||||||
|
end
|
||||||
|
return header
|
||||||
|
end
|
||||||
|
|
||||||
|
function tar.untar(filename, destdir)
|
||||||
|
assert(type(filename) == "string")
|
||||||
|
assert(type(destdir) == "string")
|
||||||
|
|
||||||
|
local tar_handle = io.open(filename, "r")
|
||||||
|
if not tar_handle then return nil, "Error opening file "..filename end
|
||||||
|
|
||||||
|
local long_name, long_link_name
|
||||||
|
while true do
|
||||||
|
local block
|
||||||
|
repeat
|
||||||
|
block = tar_handle:read(blocksize)
|
||||||
|
until (not block) or checksum_header(block) > 256
|
||||||
|
if not block then break end
|
||||||
|
local header, err = read_header_block(block)
|
||||||
|
if not header then
|
||||||
|
util.printerr(err)
|
||||||
|
end
|
||||||
|
|
||||||
|
local file_data = tar_handle:read(math.ceil(header.size / blocksize) * blocksize):sub(1,header.size)
|
||||||
|
|
||||||
|
if header.typeflag == "long name" then
|
||||||
|
long_name = nullterm(file_data)
|
||||||
|
elseif header.typeflag == "long link name" then
|
||||||
|
long_link_name = nullterm(file_data)
|
||||||
|
else
|
||||||
|
if long_name then
|
||||||
|
header.name = long_name
|
||||||
|
long_name = nil
|
||||||
|
end
|
||||||
|
if long_link_name then
|
||||||
|
header.name = long_link_name
|
||||||
|
long_link_name = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local pathname = dir.path(destdir, header.name)
|
||||||
|
if header.typeflag == "directory" then
|
||||||
|
local ok, err = fs.make_dir(pathname)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
elseif header.typeflag == "file" then
|
||||||
|
local dirname = dir.dir_name(pathname)
|
||||||
|
if dirname ~= "" then
|
||||||
|
local ok, err = fs.make_dir(dirname)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
end
|
||||||
|
local file_handle = io.open(pathname, "wb")
|
||||||
|
file_handle:write(file_data)
|
||||||
|
file_handle:close()
|
||||||
|
fs.set_time(pathname, header.mtime)
|
||||||
|
if fs.chmod then
|
||||||
|
fs.chmod(pathname, header.mode)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--[[
|
||||||
|
for k,v in pairs(header) do
|
||||||
|
util.printout("[\""..tostring(k).."\"] = "..(type(v)=="number" and v or "\""..v:gsub("%z", "\\0").."\""))
|
||||||
|
end
|
||||||
|
util.printout()
|
||||||
|
--]]
|
||||||
|
end
|
||||||
|
tar_handle:close()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return tar
|
||||||
264
Utils/luarocks/lua/luarocks/tools/zip.lua
Normal file
264
Utils/luarocks/lua/luarocks/tools/zip.lua
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
|
||||||
|
--- A Lua implementation of .zip file archiving (used for creating .rock files),
|
||||||
|
-- using only lzlib or lua-lzib.
|
||||||
|
local zip = {}
|
||||||
|
|
||||||
|
local zlib = require("zlib")
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
|
||||||
|
-- zlib module can be provided by both lzlib and lua-lzib packages.
|
||||||
|
-- Create a compatibility layer.
|
||||||
|
local zlib_compress, zlib_crc32
|
||||||
|
if zlib._VERSION:match "^lua%-zlib" then
|
||||||
|
function zlib_compress(data)
|
||||||
|
return (zlib.deflate()(data, "finish"))
|
||||||
|
end
|
||||||
|
|
||||||
|
function zlib_crc32(data)
|
||||||
|
return zlib.crc32()(data)
|
||||||
|
end
|
||||||
|
elseif zlib._VERSION:match "^lzlib" then
|
||||||
|
function zlib_compress(data)
|
||||||
|
return zlib.compress(data)
|
||||||
|
end
|
||||||
|
|
||||||
|
function zlib_crc32(data)
|
||||||
|
return zlib.crc32(zlib.crc32(), data)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
error("unknown zlib library", 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function number_to_bytestring(number, nbytes)
|
||||||
|
local out = {}
|
||||||
|
for _ = 1, nbytes do
|
||||||
|
local byte = number % 256
|
||||||
|
table.insert(out, string.char(byte))
|
||||||
|
number = (number - byte) / 256
|
||||||
|
end
|
||||||
|
return table.concat(out)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Begin a new file to be stored inside the zipfile.
|
||||||
|
-- @param self handle of the zipfile being written.
|
||||||
|
-- @param filename filenome of the file to be added to the zipfile.
|
||||||
|
-- @return true if succeeded, nil in case of failure.
|
||||||
|
local function zipwriter_open_new_file_in_zip(self, filename)
|
||||||
|
if self.in_open_file then
|
||||||
|
self:close_file_in_zip()
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local lfh = {}
|
||||||
|
self.local_file_header = lfh
|
||||||
|
lfh.last_mod_file_time = 0 -- TODO
|
||||||
|
lfh.last_mod_file_date = 0 -- TODO
|
||||||
|
lfh.file_name_length = #filename
|
||||||
|
lfh.extra_field_length = 0
|
||||||
|
lfh.file_name = filename:gsub("\\", "/")
|
||||||
|
lfh.external_attr = 0 -- TODO properly store permissions
|
||||||
|
self.in_open_file = true
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Write data to the file currently being stored in the zipfile.
|
||||||
|
-- @param self handle of the zipfile being written.
|
||||||
|
-- @param data string containing full contents of the file.
|
||||||
|
-- @return true if succeeded, nil in case of failure.
|
||||||
|
local function zipwriter_write_file_in_zip(self, data)
|
||||||
|
if not self.in_open_file then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local lfh = self.local_file_header
|
||||||
|
local compressed = zlib_compress(data):sub(3, -5)
|
||||||
|
lfh.crc32 = zlib_crc32(data)
|
||||||
|
lfh.compressed_size = #compressed
|
||||||
|
lfh.uncompressed_size = #data
|
||||||
|
self.data = compressed
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Complete the writing of a file stored in the zipfile.
|
||||||
|
-- @param self handle of the zipfile being written.
|
||||||
|
-- @return true if succeeded, nil in case of failure.
|
||||||
|
local function zipwriter_close_file_in_zip(self)
|
||||||
|
local zh = self.ziphandle
|
||||||
|
|
||||||
|
if not self.in_open_file then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Local file header
|
||||||
|
local lfh = self.local_file_header
|
||||||
|
lfh.offset = zh:seek()
|
||||||
|
zh:write(number_to_bytestring(0x04034b50, 4)) -- signature
|
||||||
|
zh:write(number_to_bytestring(20, 2)) -- version needed to extract: 2.0
|
||||||
|
zh:write(number_to_bytestring(0, 2)) -- general purpose bit flag
|
||||||
|
zh:write(number_to_bytestring(8, 2)) -- compression method: deflate
|
||||||
|
zh:write(number_to_bytestring(lfh.last_mod_file_time, 2))
|
||||||
|
zh:write(number_to_bytestring(lfh.last_mod_file_date, 2))
|
||||||
|
zh:write(number_to_bytestring(lfh.crc32, 4))
|
||||||
|
zh:write(number_to_bytestring(lfh.compressed_size, 4))
|
||||||
|
zh:write(number_to_bytestring(lfh.uncompressed_size, 4))
|
||||||
|
zh:write(number_to_bytestring(lfh.file_name_length, 2))
|
||||||
|
zh:write(number_to_bytestring(lfh.extra_field_length, 2))
|
||||||
|
zh:write(lfh.file_name)
|
||||||
|
|
||||||
|
-- File data
|
||||||
|
zh:write(self.data)
|
||||||
|
|
||||||
|
-- Data descriptor
|
||||||
|
zh:write(number_to_bytestring(lfh.crc32, 4))
|
||||||
|
zh:write(number_to_bytestring(lfh.compressed_size, 4))
|
||||||
|
zh:write(number_to_bytestring(lfh.uncompressed_size, 4))
|
||||||
|
|
||||||
|
table.insert(self.files, lfh)
|
||||||
|
self.in_open_file = false
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- @return boolean or (boolean, string): true on success,
|
||||||
|
-- false and an error message on failure.
|
||||||
|
local function zipwriter_add(self, file)
|
||||||
|
local fin
|
||||||
|
local ok, err = self:open_new_file_in_zip(file)
|
||||||
|
if not ok then
|
||||||
|
err = "error in opening "..file.." in zipfile"
|
||||||
|
else
|
||||||
|
fin = io.open(fs.absolute_name(file), "rb")
|
||||||
|
if not fin then
|
||||||
|
ok = false
|
||||||
|
err = "error opening "..file.." for reading"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if ok then
|
||||||
|
local data = fin:read("*a")
|
||||||
|
if not data then
|
||||||
|
err = "error reading "..file
|
||||||
|
ok = false
|
||||||
|
else
|
||||||
|
ok = self:write_file_in_zip(data)
|
||||||
|
if not ok then
|
||||||
|
err = "error in writing "..file.." in the zipfile"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if fin then
|
||||||
|
fin:close()
|
||||||
|
end
|
||||||
|
if ok then
|
||||||
|
ok = self:close_file_in_zip()
|
||||||
|
if not ok then
|
||||||
|
err = "error in writing "..file.." in the zipfile"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ok == true, err
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Complete the writing of the zipfile.
|
||||||
|
-- @param self handle of the zipfile being written.
|
||||||
|
-- @return true if succeeded, nil in case of failure.
|
||||||
|
local function zipwriter_close(self)
|
||||||
|
local zh = self.ziphandle
|
||||||
|
|
||||||
|
local central_directory_offset = zh:seek()
|
||||||
|
|
||||||
|
local size_of_central_directory = 0
|
||||||
|
-- Central directory structure
|
||||||
|
for _, lfh in ipairs(self.files) do
|
||||||
|
zh:write(number_to_bytestring(0x02014b50, 4)) -- signature
|
||||||
|
zh:write(number_to_bytestring(3, 2)) -- version made by: UNIX
|
||||||
|
zh:write(number_to_bytestring(20, 2)) -- version needed to extract: 2.0
|
||||||
|
zh:write(number_to_bytestring(0, 2)) -- general purpose bit flag
|
||||||
|
zh:write(number_to_bytestring(8, 2)) -- compression method: deflate
|
||||||
|
zh:write(number_to_bytestring(lfh.last_mod_file_time, 2))
|
||||||
|
zh:write(number_to_bytestring(lfh.last_mod_file_date, 2))
|
||||||
|
zh:write(number_to_bytestring(lfh.crc32, 4))
|
||||||
|
zh:write(number_to_bytestring(lfh.compressed_size, 4))
|
||||||
|
zh:write(number_to_bytestring(lfh.uncompressed_size, 4))
|
||||||
|
zh:write(number_to_bytestring(lfh.file_name_length, 2))
|
||||||
|
zh:write(number_to_bytestring(lfh.extra_field_length, 2))
|
||||||
|
zh:write(number_to_bytestring(0, 2)) -- file comment length
|
||||||
|
zh:write(number_to_bytestring(0, 2)) -- disk number start
|
||||||
|
zh:write(number_to_bytestring(0, 2)) -- internal file attributes
|
||||||
|
zh:write(number_to_bytestring(lfh.external_attr, 4)) -- external file attributes
|
||||||
|
zh:write(number_to_bytestring(lfh.offset, 4)) -- relative offset of local header
|
||||||
|
zh:write(lfh.file_name)
|
||||||
|
size_of_central_directory = size_of_central_directory + 46 + lfh.file_name_length
|
||||||
|
end
|
||||||
|
|
||||||
|
-- End of central directory record
|
||||||
|
zh:write(number_to_bytestring(0x06054b50, 4)) -- signature
|
||||||
|
zh:write(number_to_bytestring(0, 2)) -- number of this disk
|
||||||
|
zh:write(number_to_bytestring(0, 2)) -- number of disk with start of central directory
|
||||||
|
zh:write(number_to_bytestring(#self.files, 2)) -- total number of entries in the central dir on this disk
|
||||||
|
zh:write(number_to_bytestring(#self.files, 2)) -- total number of entries in the central dir
|
||||||
|
zh:write(number_to_bytestring(size_of_central_directory, 4))
|
||||||
|
zh:write(number_to_bytestring(central_directory_offset, 4))
|
||||||
|
zh:write(number_to_bytestring(0, 2)) -- zip file comment length
|
||||||
|
zh:close()
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return a zip handle open for writing.
|
||||||
|
-- @param name filename of the zipfile to be created.
|
||||||
|
-- @return a zip handle, or nil in case of error.
|
||||||
|
function zip.new_zipwriter(name)
|
||||||
|
|
||||||
|
local zw = {}
|
||||||
|
|
||||||
|
zw.ziphandle = io.open(fs.absolute_name(name), "wb")
|
||||||
|
if not zw.ziphandle then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
zw.files = {}
|
||||||
|
zw.in_open_file = false
|
||||||
|
|
||||||
|
zw.add = zipwriter_add
|
||||||
|
zw.close = zipwriter_close
|
||||||
|
zw.open_new_file_in_zip = zipwriter_open_new_file_in_zip
|
||||||
|
zw.write_file_in_zip = zipwriter_write_file_in_zip
|
||||||
|
zw.close_file_in_zip = zipwriter_close_file_in_zip
|
||||||
|
|
||||||
|
return zw
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Compress files in a .zip archive.
|
||||||
|
-- @param zipfile string: pathname of .zip archive to be created.
|
||||||
|
-- @param ... Filenames to be stored in the archive are given as
|
||||||
|
-- additional arguments.
|
||||||
|
-- @return boolean or (boolean, string): true on success,
|
||||||
|
-- false and an error message on failure.
|
||||||
|
function zip.zip(zipfile, ...)
|
||||||
|
local zw = zip.new_zipwriter(zipfile)
|
||||||
|
if not zw then
|
||||||
|
return nil, "error opening "..zipfile
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok, err
|
||||||
|
for _, file in pairs({...}) do
|
||||||
|
if fs.is_dir(file) then
|
||||||
|
for _, entry in pairs(fs.find(file)) do
|
||||||
|
local fullname = dir.path(file, entry)
|
||||||
|
if fs.is_file(fullname) then
|
||||||
|
ok, err = zw:add(fullname)
|
||||||
|
if not ok then break end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
ok, err = zw:add(file)
|
||||||
|
if not ok then break end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ok = zw:close()
|
||||||
|
if not ok then
|
||||||
|
return false, "error closing "..zipfile
|
||||||
|
end
|
||||||
|
return ok, err
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return zip
|
||||||
344
Utils/luarocks/lua/luarocks/type_check.lua
Normal file
344
Utils/luarocks/lua/luarocks/type_check.lua
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
--- Type-checking functions.
|
||||||
|
-- Functions and definitions for doing a basic lint check on files
|
||||||
|
-- loaded by LuaRocks.
|
||||||
|
local type_check = {}
|
||||||
|
package.loaded["luarocks.type_check"] = type_check
|
||||||
|
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local deps = require("luarocks.deps")
|
||||||
|
|
||||||
|
type_check.rockspec_format = "1.1"
|
||||||
|
|
||||||
|
local string_1 = { _type = "string" }
|
||||||
|
local number_1 = { _type = "number" }
|
||||||
|
local mandatory_string_1 = { _type = "string", _mandatory = true }
|
||||||
|
|
||||||
|
-- Syntax for type-checking tables:
|
||||||
|
--
|
||||||
|
-- A type-checking table describes typing data for a value.
|
||||||
|
-- Any key starting with an underscore has a special meaning:
|
||||||
|
-- _type (string) is the Lua type of the value. Default is "table".
|
||||||
|
-- _version (string) is the minimum rockspec_version that supports this value. Default is "1.0".
|
||||||
|
-- _mandatory (boolean) indicates if the value is a mandatory key in its container table. Default is false.
|
||||||
|
-- For "string" types only:
|
||||||
|
-- _pattern (string) is the string-matching pattern, valid for string types only. Default is ".*".
|
||||||
|
-- For "table" types only:
|
||||||
|
-- _any (table) is the type-checking table for unspecified keys, recursively checked.
|
||||||
|
-- _more (boolean) indicates that the table accepts unspecified keys and does not type-check them.
|
||||||
|
-- Any other string keys that don't start with an underscore represent known keys and are type-checking tables, recursively checked.
|
||||||
|
|
||||||
|
local rockspec_types = {
|
||||||
|
rockspec_format = string_1,
|
||||||
|
package = mandatory_string_1,
|
||||||
|
version = { _type = "string", _pattern = "[%w.]+-[%d]+", _mandatory = true },
|
||||||
|
description = {
|
||||||
|
summary = string_1,
|
||||||
|
detailed = string_1,
|
||||||
|
homepage = string_1,
|
||||||
|
license = string_1,
|
||||||
|
maintainer = string_1,
|
||||||
|
},
|
||||||
|
dependencies = {
|
||||||
|
platforms = {}, -- recursively defined below
|
||||||
|
_any = string_1,
|
||||||
|
},
|
||||||
|
supported_platforms = {
|
||||||
|
_any = string_1,
|
||||||
|
},
|
||||||
|
external_dependencies = {
|
||||||
|
platforms = {}, -- recursively defined below
|
||||||
|
_any = {
|
||||||
|
program = string_1,
|
||||||
|
header = string_1,
|
||||||
|
library = string_1,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
source = {
|
||||||
|
_mandatory = true,
|
||||||
|
platforms = {}, -- recursively defined below
|
||||||
|
url = mandatory_string_1,
|
||||||
|
md5 = string_1,
|
||||||
|
file = string_1,
|
||||||
|
dir = string_1,
|
||||||
|
tag = string_1,
|
||||||
|
branch = string_1,
|
||||||
|
module = string_1,
|
||||||
|
cvs_tag = string_1,
|
||||||
|
cvs_module = string_1,
|
||||||
|
},
|
||||||
|
build = {
|
||||||
|
platforms = {}, -- recursively defined below
|
||||||
|
type = string_1,
|
||||||
|
install = {
|
||||||
|
lua = {
|
||||||
|
_more = true
|
||||||
|
},
|
||||||
|
lib = {
|
||||||
|
_more = true
|
||||||
|
},
|
||||||
|
conf = {
|
||||||
|
_more = true
|
||||||
|
},
|
||||||
|
bin = {
|
||||||
|
_more = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
copy_directories = {
|
||||||
|
_any = string_1,
|
||||||
|
},
|
||||||
|
_more = true,
|
||||||
|
_mandatory = true
|
||||||
|
},
|
||||||
|
hooks = {
|
||||||
|
platforms = {}, -- recursively defined below
|
||||||
|
post_install = string_1,
|
||||||
|
},
|
||||||
|
deploy = {
|
||||||
|
_version = "1.1",
|
||||||
|
wrap_bin_scripts = { _type = "boolean", _version = "1.1" },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type_check.rockspec_order = {"rockspec_format", "package", "version",
|
||||||
|
{ "source", { "url", "tag", "branch", "md5" } },
|
||||||
|
{ "description", {"summary", "detailed", "homepage", "license" } },
|
||||||
|
"supported_platforms", "dependencies", "external_dependencies",
|
||||||
|
{ "build", {"type", "modules", "copy_directories", "platforms"} },
|
||||||
|
"hooks"}
|
||||||
|
|
||||||
|
rockspec_types.build.platforms._any = rockspec_types.build
|
||||||
|
rockspec_types.dependencies.platforms._any = rockspec_types.dependencies
|
||||||
|
rockspec_types.external_dependencies.platforms._any = rockspec_types.external_dependencies
|
||||||
|
rockspec_types.source.platforms._any = rockspec_types.source
|
||||||
|
rockspec_types.hooks.platforms._any = rockspec_types.hooks
|
||||||
|
|
||||||
|
local manifest_types = {
|
||||||
|
repository = {
|
||||||
|
_mandatory = true,
|
||||||
|
-- packages
|
||||||
|
_any = {
|
||||||
|
-- versions
|
||||||
|
_any = {
|
||||||
|
-- items
|
||||||
|
_any = {
|
||||||
|
arch = mandatory_string_1,
|
||||||
|
modules = { _any = string_1 },
|
||||||
|
commands = { _any = string_1 },
|
||||||
|
dependencies = { _any = string_1 },
|
||||||
|
-- TODO: to be extended with more metadata.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modules = {
|
||||||
|
_mandatory = true,
|
||||||
|
-- modules
|
||||||
|
_any = {
|
||||||
|
-- providers
|
||||||
|
_any = string_1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
commands = {
|
||||||
|
_mandatory = true,
|
||||||
|
-- modules
|
||||||
|
_any = {
|
||||||
|
-- commands
|
||||||
|
_any = string_1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dependencies = {
|
||||||
|
-- each module
|
||||||
|
_any = {
|
||||||
|
-- each version
|
||||||
|
_any = {
|
||||||
|
-- each dependency
|
||||||
|
_any = {
|
||||||
|
name = string_1,
|
||||||
|
constraints = {
|
||||||
|
_any = {
|
||||||
|
no_upgrade = { _type = "boolean" },
|
||||||
|
op = string_1,
|
||||||
|
version = {
|
||||||
|
string = string_1,
|
||||||
|
_any = number_1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
local function check_version(version, typetbl, context)
|
||||||
|
local typetbl_version = typetbl._version or "1.0"
|
||||||
|
if deps.compare_versions(typetbl_version, version) then
|
||||||
|
if context == "" then
|
||||||
|
return nil, "Invalid rockspec_format version number in rockspec? Please fix rockspec accordingly."
|
||||||
|
else
|
||||||
|
return nil, context.." is not supported in rockspec format "..version.." (requires version "..typetbl_version.."), please fix the rockspec_format field accordingly."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local type_check_table
|
||||||
|
|
||||||
|
--- Type check an object.
|
||||||
|
-- The object is compared against an archetypical value
|
||||||
|
-- matching the expected type -- the actual values don't matter,
|
||||||
|
-- only their types. Tables are type checked recursively.
|
||||||
|
-- @param version string: The version of the item.
|
||||||
|
-- @param item any: The object being checked.
|
||||||
|
-- @param typetbl any: The type-checking table for the object.
|
||||||
|
-- @param context string: A string indicating the "context" where the
|
||||||
|
-- error occurred (the full table path), for error messages.
|
||||||
|
-- @return boolean or (nil, string): true if type checking
|
||||||
|
-- succeeded, or nil and an error message if it failed.
|
||||||
|
-- @see type_check_table
|
||||||
|
local function type_check_item(version, item, typetbl, context)
|
||||||
|
assert(type(version) == "string")
|
||||||
|
|
||||||
|
local ok, err = check_version(version, typetbl, context)
|
||||||
|
if not ok then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
|
||||||
|
local item_type = type(item) or "nil"
|
||||||
|
local expected_type = typetbl._type or "table"
|
||||||
|
|
||||||
|
if expected_type == "number" then
|
||||||
|
if not tonumber(item) then
|
||||||
|
return nil, "Type mismatch on field "..context..": expected a number"
|
||||||
|
end
|
||||||
|
elseif expected_type == "string" then
|
||||||
|
if item_type ~= "string" then
|
||||||
|
return nil, "Type mismatch on field "..context..": expected a string, got "..item_type
|
||||||
|
end
|
||||||
|
if typetbl._pattern then
|
||||||
|
if not item:match("^"..typetbl._pattern.."$") then
|
||||||
|
return nil, "Type mismatch on field "..context..": invalid value "..item.." does not match '"..typetbl._pattern.."'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif expected_type == "table" then
|
||||||
|
if item_type ~= expected_type then
|
||||||
|
return nil, "Type mismatch on field "..context..": expected a table"
|
||||||
|
else
|
||||||
|
return type_check_table(version, item, typetbl, context)
|
||||||
|
end
|
||||||
|
elseif item_type ~= expected_type then
|
||||||
|
return nil, "Type mismatch on field "..context..": expected "..expected_type
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function mkfield(context, field)
|
||||||
|
if context == "" then
|
||||||
|
return tostring(field)
|
||||||
|
elseif type(field) == "string" then
|
||||||
|
return context.."."..field
|
||||||
|
else
|
||||||
|
return context.."["..tostring(field).."]"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Type check the contents of a table.
|
||||||
|
-- The table's contents are compared against a reference table,
|
||||||
|
-- which contains the recognized fields, with archetypical values
|
||||||
|
-- matching the expected types -- the actual values of items in the
|
||||||
|
-- reference table don't matter, only their types (ie, for field x
|
||||||
|
-- in tbl that is correctly typed, type(tbl.x) == type(types.x)).
|
||||||
|
-- If the reference table contains a field called MORE, then
|
||||||
|
-- unknown fields in the checked table are accepted.
|
||||||
|
-- If it contains a field called ANY, then its type will be
|
||||||
|
-- used to check any unknown fields. If a field is prefixed
|
||||||
|
-- with MUST_, it is mandatory; its absence from the table is
|
||||||
|
-- a type error.
|
||||||
|
-- Tables are type checked recursively.
|
||||||
|
-- @param version string: The version of tbl.
|
||||||
|
-- @param tbl table: The table to be type checked.
|
||||||
|
-- @param typetbl table: The type-checking table, containing
|
||||||
|
-- values for recognized fields in the checked table.
|
||||||
|
-- @param context string: A string indicating the "context" where the
|
||||||
|
-- error occurred (such as the name of the table the item is a part of),
|
||||||
|
-- to be used by error messages.
|
||||||
|
-- @return boolean or (nil, string): true if type checking
|
||||||
|
-- succeeded, or nil and an error message if it failed.
|
||||||
|
type_check_table = function(version, tbl, typetbl, context)
|
||||||
|
assert(type(version) == "string")
|
||||||
|
assert(type(tbl) == "table")
|
||||||
|
assert(type(typetbl) == "table")
|
||||||
|
|
||||||
|
local ok, err = check_version(version, typetbl, context)
|
||||||
|
if not ok then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
|
||||||
|
for k, v in pairs(tbl) do
|
||||||
|
local t = typetbl[k] or typetbl._any
|
||||||
|
if t then
|
||||||
|
local ok, err = type_check_item(version, v, t, mkfield(context, k))
|
||||||
|
if not ok then return nil, err end
|
||||||
|
elseif typetbl._more then
|
||||||
|
-- Accept unknown field
|
||||||
|
else
|
||||||
|
if not cfg.accept_unknown_fields then
|
||||||
|
return nil, "Unknown field "..k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for k, v in pairs(typetbl) do
|
||||||
|
if k:sub(1,1) ~= "_" and v._mandatory then
|
||||||
|
if not tbl[k] then
|
||||||
|
return nil, "Mandatory field "..mkfield(context, k).." is missing."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function check_undeclared_globals(globals, typetbl)
|
||||||
|
local undeclared = {}
|
||||||
|
for glob, _ in pairs(globals) do
|
||||||
|
if not (typetbl[glob] or typetbl["MUST_"..glob]) then
|
||||||
|
table.insert(undeclared, glob)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #undeclared == 1 then
|
||||||
|
return nil, "Unknown variable: "..undeclared[1]
|
||||||
|
elseif #undeclared > 1 then
|
||||||
|
return nil, "Unknown variables: "..table.concat(undeclared, ", ")
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Type check a rockspec table.
|
||||||
|
-- Verify the correctness of elements from a
|
||||||
|
-- rockspec table, reporting on unknown fields and type
|
||||||
|
-- mismatches.
|
||||||
|
-- @return boolean or (nil, string): true if type checking
|
||||||
|
-- succeeded, or nil and an error message if it failed.
|
||||||
|
function type_check.type_check_rockspec(rockspec, globals)
|
||||||
|
assert(type(rockspec) == "table")
|
||||||
|
if not rockspec.rockspec_format then
|
||||||
|
rockspec.rockspec_format = "1.0"
|
||||||
|
end
|
||||||
|
local ok, err = check_undeclared_globals(globals, rockspec_types)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
return type_check_table(rockspec.rockspec_format, rockspec, rockspec_types, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Type check a manifest table.
|
||||||
|
-- Verify the correctness of elements from a
|
||||||
|
-- manifest table, reporting on unknown fields and type
|
||||||
|
-- mismatches.
|
||||||
|
-- @return boolean or (nil, string): true if type checking
|
||||||
|
-- succeeded, or nil and an error message if it failed.
|
||||||
|
function type_check.type_check_manifest(manifest, globals)
|
||||||
|
assert(type(manifest) == "table")
|
||||||
|
local ok, err = check_undeclared_globals(globals, manifest_types)
|
||||||
|
if not ok then return nil, err end
|
||||||
|
return type_check_table("1.0", manifest, manifest_types, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
return type_check
|
||||||
166
Utils/luarocks/lua/luarocks/unpack.lua
Normal file
166
Utils/luarocks/lua/luarocks/unpack.lua
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
|
||||||
|
--- Module implementing the LuaRocks "unpack" command.
|
||||||
|
-- Unpack the contents of a rock.
|
||||||
|
local unpack = {}
|
||||||
|
package.loaded["luarocks.unpack"] = 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 cfg = require("luarocks.cfg")
|
||||||
|
|
||||||
|
util.add_run_function(unpack)
|
||||||
|
unpack.help_summary = "Unpack the contents of a rock."
|
||||||
|
unpack.help_arguments = "[--force] {<rock>|<name> [<version>]}"
|
||||||
|
unpack.help = [[
|
||||||
|
Unpacks the contents of a rock in a newly created directory.
|
||||||
|
Argument may be a rock file, or the name of a rock in a rocks server.
|
||||||
|
In the latter case, the app version may be given as a second argument.
|
||||||
|
|
||||||
|
--force Unpack files even if the output directory already exists.
|
||||||
|
]]
|
||||||
|
|
||||||
|
--- Load a rockspec file to the given directory, fetches the source
|
||||||
|
-- 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, "Failed unzipping rock "..rock_file, 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_filename, rockspec.source.dir, cfg.perm_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.
|
||||||
|
-- @param name string: may be a rock filename, for unpacking a
|
||||||
|
-- rock file or the name of a rock to be fetched and unpacked.
|
||||||
|
-- @param version string or nil: if the name of a package is given, a
|
||||||
|
-- version may also be passed.
|
||||||
|
-- @return boolean or (nil, string): true if successful or nil followed
|
||||||
|
-- by an error message.
|
||||||
|
function unpack.command(flags, name, version)
|
||||||
|
assert(type(version) == "string" or not version)
|
||||||
|
if type(name) ~= "string" then
|
||||||
|
return nil, "Argument missing. "..util.see_help("unpack")
|
||||||
|
end
|
||||||
|
|
||||||
|
if name:match(".*%.rock") or name:match(".*%.rockspec") then
|
||||||
|
return run_unpacker(name, flags["force"])
|
||||||
|
else
|
||||||
|
local search = require("luarocks.search")
|
||||||
|
return search.act_on_src_or_rockspec(run_unpacker, name:lower(), version)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return unpack
|
||||||
95
Utils/luarocks/lua/luarocks/upload.lua
Normal file
95
Utils/luarocks/lua/luarocks/upload.lua
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
|
||||||
|
local upload = {}
|
||||||
|
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local fetch = require("luarocks.fetch")
|
||||||
|
local pack = require("luarocks.pack")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local Api = require("luarocks.upload.api")
|
||||||
|
|
||||||
|
util.add_run_function(upload)
|
||||||
|
upload.help_summary = "Upload a rockspec to the public rocks repository."
|
||||||
|
upload.help_arguments = "[--skip-pack] [--api-key=<key>] [--force] <rockspec>"
|
||||||
|
upload.help = [[
|
||||||
|
<rockspec> Pack a source rock file (.src.rock extension),
|
||||||
|
upload rockspec and source rock to server.
|
||||||
|
--skip-pack Do not pack and send source rock.
|
||||||
|
--api-key=<key> Give it an API key. It will be stored for subsequent uses.
|
||||||
|
--force Replace existing rockspec if the same revision of
|
||||||
|
a module already exists. This should be used only
|
||||||
|
in case of upload mistakes: when updating a rockspec,
|
||||||
|
increment the revision number instead.
|
||||||
|
]]
|
||||||
|
|
||||||
|
function upload.command(flags, fname)
|
||||||
|
if not fname then
|
||||||
|
return nil, "Missing rockspec. "..util.see_help("upload")
|
||||||
|
end
|
||||||
|
|
||||||
|
local api, err = Api.new(flags)
|
||||||
|
if not api then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
if cfg.verbose then
|
||||||
|
api.debug = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local rockspec, err, errcode = fetch.load_rockspec(fname)
|
||||||
|
if err then
|
||||||
|
return nil, err, errcode
|
||||||
|
end
|
||||||
|
|
||||||
|
util.printout("Sending " .. tostring(fname) .. " ...")
|
||||||
|
local res, err = api:method("check_rockspec", {
|
||||||
|
package = rockspec.package,
|
||||||
|
version = rockspec.version
|
||||||
|
})
|
||||||
|
if not res then return nil, err end
|
||||||
|
|
||||||
|
if not res.module then
|
||||||
|
util.printout("Will create new module (" .. tostring(rockspec.package) .. ")")
|
||||||
|
end
|
||||||
|
if res.version and not flags["force"] then
|
||||||
|
return nil, "Revision "..rockspec.version.." already exists on the server. "..util.see_help("upload")
|
||||||
|
end
|
||||||
|
|
||||||
|
local rock_fname
|
||||||
|
if not flags["skip-pack"] and not rockspec.version:match("^scm") then
|
||||||
|
util.printout("Packing " .. tostring(rockspec.package))
|
||||||
|
rock_fname, err = pack.pack_source_rock(fname)
|
||||||
|
if not rock_fname then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local multipart = require("luarocks.upload.multipart")
|
||||||
|
|
||||||
|
res, err = api:method("upload", nil, {
|
||||||
|
rockspec_file = multipart.new_file(fname)
|
||||||
|
})
|
||||||
|
if not res then return nil, err end
|
||||||
|
|
||||||
|
if res.is_new and #res.manifests == 0 then
|
||||||
|
util.printerr("Warning: module not added to root manifest due to name taken.")
|
||||||
|
end
|
||||||
|
|
||||||
|
local module_url = res.module_url
|
||||||
|
|
||||||
|
if rock_fname then
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
if not res then return nil, err end
|
||||||
|
end
|
||||||
|
|
||||||
|
util.printout()
|
||||||
|
util.printout("Done: " .. tostring(module_url))
|
||||||
|
util.printout()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return upload
|
||||||
284
Utils/luarocks/lua/luarocks/upload/api.lua
Normal file
284
Utils/luarocks/lua/luarocks/upload/api.lua
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
|
||||||
|
local api = {}
|
||||||
|
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
local persist = require("luarocks.persist")
|
||||||
|
local multipart = require("luarocks.upload.multipart")
|
||||||
|
|
||||||
|
local Api = {}
|
||||||
|
|
||||||
|
local function upload_config_file()
|
||||||
|
local conf = cfg.which_config()
|
||||||
|
if not conf.user.file then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return (conf.user.file:gsub("/[^/]+$", "/upload_config.lua"))
|
||||||
|
end
|
||||||
|
|
||||||
|
function Api:load_config()
|
||||||
|
local upload_conf = upload_config_file()
|
||||||
|
if not upload_conf then return nil end
|
||||||
|
local cfg, err = persist.load_into_table(upload_conf)
|
||||||
|
return cfg
|
||||||
|
end
|
||||||
|
|
||||||
|
function Api:save_config()
|
||||||
|
-- Test configuration before saving it.
|
||||||
|
local res, err = self:raw_method("status")
|
||||||
|
if not res then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
if res.errors then
|
||||||
|
util.printerr("Server says: " .. tostring(res.errors[1]))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local upload_conf = upload_config_file()
|
||||||
|
if not upload_conf then return nil end
|
||||||
|
persist.save_from_table(upload_conf, self.config)
|
||||||
|
fs.chmod(upload_conf, "0600")
|
||||||
|
end
|
||||||
|
|
||||||
|
function Api:check_version()
|
||||||
|
if not self._server_tool_version then
|
||||||
|
local tool_version = cfg.upload.tool_version
|
||||||
|
local res, err = self:request(tostring(self.config.server) .. "/api/tool_version", {
|
||||||
|
current = tool_version
|
||||||
|
})
|
||||||
|
if not res then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
if not res.version then
|
||||||
|
return nil, "failed to fetch tool version"
|
||||||
|
end
|
||||||
|
self._server_tool_version = res.version
|
||||||
|
if res.force_update then
|
||||||
|
return nil, "Your upload client is too out of date to continue, please upgrade LuaRocks."
|
||||||
|
end
|
||||||
|
if res.version ~= tool_version then
|
||||||
|
util.printerr("Warning: Your LuaRocks is out of date, consider upgrading.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function Api:method(...)
|
||||||
|
local res, err = self:raw_method(...)
|
||||||
|
if not res then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
if res.errors then
|
||||||
|
if res.errors[1] == "Invalid key" then
|
||||||
|
return nil, res.errors[1] .. " (use the --api-key flag to change)"
|
||||||
|
end
|
||||||
|
local msg = table.concat(res.errors, ", ")
|
||||||
|
return nil, "API Failed: " .. msg
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
function Api:raw_method(path, ...)
|
||||||
|
self:check_version()
|
||||||
|
local url = tostring(self.config.server) .. "/api/" .. tostring(cfg.upload.api_version) .. "/" .. tostring(self.config.key) .. "/" .. tostring(path)
|
||||||
|
return self:request(url, ...)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function encode_query_string(t, sep)
|
||||||
|
if sep == nil then
|
||||||
|
sep = "&"
|
||||||
|
end
|
||||||
|
local i = 0
|
||||||
|
local buf = { }
|
||||||
|
for k, v in pairs(t) do
|
||||||
|
if type(k) == "number" and type(v) == "table" then
|
||||||
|
k, v = v[1], v[2]
|
||||||
|
end
|
||||||
|
buf[i + 1] = multipart.url_escape(k)
|
||||||
|
buf[i + 2] = "="
|
||||||
|
buf[i + 3] = multipart.url_escape(v)
|
||||||
|
buf[i + 4] = sep
|
||||||
|
i = i + 4
|
||||||
|
end
|
||||||
|
buf[i] = nil
|
||||||
|
return table.concat(buf)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- An ode to the multitude of JSON libraries out there...
|
||||||
|
local function require_json()
|
||||||
|
local list = { "cjson", "dkjson", "json" }
|
||||||
|
for _, lib in ipairs(list) do
|
||||||
|
local json_ok, json = pcall(require, lib)
|
||||||
|
if json_ok then
|
||||||
|
pcall(json.use_lpeg) -- optional feature in dkjson
|
||||||
|
return json_ok, json
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local errmsg = "Failed loading "
|
||||||
|
for i, name in ipairs(list) do
|
||||||
|
if i == #list then
|
||||||
|
errmsg = errmsg .."and '"..name.."'. Use 'luarocks search <partial-name>' to search for a library and 'luarocks install <name>' to install one."
|
||||||
|
else
|
||||||
|
errmsg = errmsg .."'"..name.."', "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil, errmsg
|
||||||
|
end
|
||||||
|
|
||||||
|
local function redact_api_url(url)
|
||||||
|
url = tostring(url)
|
||||||
|
return (url:gsub(".*/api/[^/]+/[^/]+", "")) or ""
|
||||||
|
end
|
||||||
|
|
||||||
|
local ltn12_ok, ltn12 = pcall(require, "ltn12")
|
||||||
|
if not ltn12_ok then -- If not using LuaSocket and/or LuaSec...
|
||||||
|
|
||||||
|
function Api:request(url, params, post_params)
|
||||||
|
local vars = cfg.variables
|
||||||
|
local json_ok, json = require_json()
|
||||||
|
if not json_ok then return nil, "A JSON library is required for this command. "..json end
|
||||||
|
|
||||||
|
if cfg.downloader == "wget" then
|
||||||
|
local curl_ok, err = fs.is_tool_available(vars.CURL, "curl")
|
||||||
|
if not curl_ok then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not self.config.key then
|
||||||
|
return nil, "Must have API key before performing any actions."
|
||||||
|
end
|
||||||
|
if params and next(params) then
|
||||||
|
url = url .. ("?" .. encode_query_string(params))
|
||||||
|
end
|
||||||
|
local method = "GET"
|
||||||
|
local out
|
||||||
|
local tmpfile = fs.tmpname()
|
||||||
|
if post_params then
|
||||||
|
method = "POST"
|
||||||
|
local curl_cmd = fs.Q(vars.CURL).." -f -k -L --silent --user-agent \""..cfg.user_agent.." via curl\" "
|
||||||
|
for k,v in pairs(post_params) do
|
||||||
|
local var = v
|
||||||
|
if type(v) == "table" then
|
||||||
|
var = "@"..v.fname
|
||||||
|
end
|
||||||
|
curl_cmd = curl_cmd .. "--form \""..k.."="..var.."\" "
|
||||||
|
end
|
||||||
|
if cfg.connection_timeout and cfg.connection_timeout > 0 then
|
||||||
|
curl_cmd = curl_cmd .. "--connect-timeout "..tonumber(cfg.connection_timeout).." "
|
||||||
|
end
|
||||||
|
local ok = fs.execute_string(curl_cmd..fs.Q(url).." -o "..fs.Q(tmpfile))
|
||||||
|
if not ok then
|
||||||
|
return nil, "API failure: " .. redact_api_url(url)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local ok, err = fs.download(url, tmpfile)
|
||||||
|
if not ok then
|
||||||
|
return nil, "API failure: " .. tostring(err) .. " - " .. redact_api_url(url)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local tmpfd = io.open(tmpfile)
|
||||||
|
if not tmpfd then
|
||||||
|
os.remove(tmpfile)
|
||||||
|
return nil, "API failure reading temporary file - " .. redact_api_url(url)
|
||||||
|
end
|
||||||
|
out = tmpfd:read("*a")
|
||||||
|
tmpfd:close()
|
||||||
|
os.remove(tmpfile)
|
||||||
|
|
||||||
|
if self.debug then
|
||||||
|
util.printout("[" .. tostring(method) .. " via curl] " .. redact_api_url(url) .. " ... ")
|
||||||
|
end
|
||||||
|
|
||||||
|
return json.decode(out)
|
||||||
|
end
|
||||||
|
|
||||||
|
else -- use LuaSocket and LuaSec
|
||||||
|
|
||||||
|
local warned_luasec = false
|
||||||
|
|
||||||
|
function Api:request(url, params, post_params)
|
||||||
|
local json_ok, json = require_json()
|
||||||
|
if not json_ok then return nil, "A JSON library is required for this command. "..json end
|
||||||
|
local server = tostring(self.config.server)
|
||||||
|
local http_ok, http
|
||||||
|
local via = "luasocket"
|
||||||
|
if server:match("^https://") then
|
||||||
|
http_ok, http = pcall(require, "ssl.https")
|
||||||
|
if http_ok then
|
||||||
|
via = "luasec"
|
||||||
|
else
|
||||||
|
if not warned_luasec then
|
||||||
|
util.printerr("LuaSec is not available; using plain HTTP. Install 'luasec' to enable HTTPS.")
|
||||||
|
warned_luasec = true
|
||||||
|
end
|
||||||
|
http_ok, http = pcall(require, "socket.http")
|
||||||
|
url = url:gsub("^https", "http")
|
||||||
|
via = "luasocket"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
http_ok, http = pcall(require, "socket.http")
|
||||||
|
end
|
||||||
|
if not http_ok then
|
||||||
|
return nil, "Failed loading socket library!"
|
||||||
|
end
|
||||||
|
|
||||||
|
if not self.config.key then
|
||||||
|
return nil, "Must have API key before performing any actions."
|
||||||
|
end
|
||||||
|
local body
|
||||||
|
local headers = {}
|
||||||
|
if params and next(params) then
|
||||||
|
url = url .. ("?" .. encode_query_string(params))
|
||||||
|
end
|
||||||
|
if post_params then
|
||||||
|
local boundary
|
||||||
|
body, boundary = multipart.encode(post_params)
|
||||||
|
headers["Content-length"] = #body
|
||||||
|
headers["Content-type"] = "multipart/form-data; boundary=" .. tostring(boundary)
|
||||||
|
end
|
||||||
|
local method = post_params and "POST" or "GET"
|
||||||
|
if self.debug then
|
||||||
|
util.printout("[" .. tostring(method) .. " via "..via.."] " .. redact_api_url(url) .. " ... ")
|
||||||
|
end
|
||||||
|
local out = {}
|
||||||
|
local _, status = http.request({
|
||||||
|
url = url,
|
||||||
|
headers = headers,
|
||||||
|
method = method,
|
||||||
|
sink = ltn12.sink.table(out),
|
||||||
|
source = body and ltn12.source.string(body)
|
||||||
|
})
|
||||||
|
if self.debug then
|
||||||
|
util.printout(tostring(status))
|
||||||
|
end
|
||||||
|
if status ~= 200 then
|
||||||
|
return nil, "API returned " .. tostring(status) .. " - " .. redact_api_url(url)
|
||||||
|
end
|
||||||
|
return json.decode(table.concat(out))
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function api.new(flags)
|
||||||
|
local self = {}
|
||||||
|
setmetatable(self, { __index = Api })
|
||||||
|
self.config = self:load_config() or {}
|
||||||
|
self.config.server = flags["server"] or self.config.server or cfg.upload.server
|
||||||
|
self.config.version = self.config.version or cfg.upload.version
|
||||||
|
self.config.key = flags["api-key"] or self.config.key
|
||||||
|
self.debug = flags["debug"]
|
||||||
|
if not self.config.key then
|
||||||
|
return nil, "You need an API key to upload rocks.\n" ..
|
||||||
|
"Navigate to "..self.config.server.."/settings to get a key\n" ..
|
||||||
|
"and then pass it through the --api-key=<key> flag."
|
||||||
|
end
|
||||||
|
if flags["api-key"] then
|
||||||
|
self:save_config()
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
return api
|
||||||
|
|
||||||
111
Utils/luarocks/lua/luarocks/upload/multipart.lua
Normal file
111
Utils/luarocks/lua/luarocks/upload/multipart.lua
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
|
||||||
|
local multipart = {}
|
||||||
|
|
||||||
|
local File = {}
|
||||||
|
|
||||||
|
local unpack = unpack or table.unpack
|
||||||
|
|
||||||
|
math.randomseed(os.time())
|
||||||
|
|
||||||
|
-- socket.url.escape(s) from LuaSocket 3.0rc1
|
||||||
|
function multipart.url_escape(s)
|
||||||
|
return (string.gsub(s, "([^A-Za-z0-9_])", function(c)
|
||||||
|
return string.format("%%%02x", string.byte(c))
|
||||||
|
end))
|
||||||
|
end
|
||||||
|
|
||||||
|
function File:mime()
|
||||||
|
if not self.mimetype then
|
||||||
|
local mimetypes_ok, mimetypes = pcall(require, "mimetypes")
|
||||||
|
if mimetypes_ok then
|
||||||
|
self.mimetype = mimetypes.guess(self.fname)
|
||||||
|
end
|
||||||
|
self.mimetype = self.mimetype or "application/octet-stream"
|
||||||
|
end
|
||||||
|
return self.mimetype
|
||||||
|
end
|
||||||
|
|
||||||
|
function File:content()
|
||||||
|
local fd = io.open(self.fname, "rb")
|
||||||
|
if not fd then
|
||||||
|
return nil, "Failed to open file: "..self.fname
|
||||||
|
end
|
||||||
|
local data = fd:read("*a")
|
||||||
|
fd:close()
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
|
||||||
|
local function rand_string(len)
|
||||||
|
local shuffled = {}
|
||||||
|
for i = 1, len do
|
||||||
|
local r = math.random(97, 122)
|
||||||
|
if math.random() >= 0.5 then
|
||||||
|
r = r - 32
|
||||||
|
end
|
||||||
|
shuffled[i] = r
|
||||||
|
end
|
||||||
|
return string.char(unpack(shuffled))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- multipart encodes params
|
||||||
|
-- returns encoded string,boundary
|
||||||
|
-- params is an a table of tuple tables:
|
||||||
|
-- params = {
|
||||||
|
-- {key1, value2},
|
||||||
|
-- {key2, value2},
|
||||||
|
-- key3: value3
|
||||||
|
-- }
|
||||||
|
function multipart.encode(params)
|
||||||
|
local tuples = { }
|
||||||
|
for i = 1, #params do
|
||||||
|
tuples[i] = params[i]
|
||||||
|
end
|
||||||
|
for k,v in pairs(params) do
|
||||||
|
if type(k) == "string" then
|
||||||
|
table.insert(tuples, {k, v})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local chunks = {}
|
||||||
|
for _, tuple in ipairs(tuples) do
|
||||||
|
local k,v = unpack(tuple)
|
||||||
|
k = multipart.url_escape(k)
|
||||||
|
local buffer = { 'Content-Disposition: form-data; name="' .. k .. '"' }
|
||||||
|
local content
|
||||||
|
if type(v) == "table" and v.__class == File then
|
||||||
|
buffer[1] = buffer[1] .. ('; filename="' .. v.fname:gsub(".*/", "") .. '"')
|
||||||
|
table.insert(buffer, "Content-type: " .. v:mime())
|
||||||
|
content = v:content()
|
||||||
|
else
|
||||||
|
content = v
|
||||||
|
end
|
||||||
|
table.insert(buffer, "")
|
||||||
|
table.insert(buffer, content)
|
||||||
|
table.insert(chunks, table.concat(buffer, "\r\n"))
|
||||||
|
end
|
||||||
|
local boundary
|
||||||
|
while not boundary do
|
||||||
|
boundary = "Boundary" .. rand_string(16)
|
||||||
|
for _, chunk in ipairs(chunks) do
|
||||||
|
if chunk:find(boundary) then
|
||||||
|
boundary = nil
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local inner = "\r\n--" .. boundary .. "\r\n"
|
||||||
|
return table.concat({ "--", boundary, "\r\n",
|
||||||
|
table.concat(chunks, inner),
|
||||||
|
"\r\n", "--", boundary, "--", "\r\n" }), boundary
|
||||||
|
end
|
||||||
|
|
||||||
|
function multipart.new_file(fname, mime)
|
||||||
|
local self = {}
|
||||||
|
setmetatable(self, { __index = File })
|
||||||
|
self.__class = File
|
||||||
|
self.fname = fname
|
||||||
|
self.mimetype = mime
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
return multipart
|
||||||
|
|
||||||
714
Utils/luarocks/lua/luarocks/util.lua
Normal file
714
Utils/luarocks/lua/luarocks/util.lua
Normal file
@ -0,0 +1,714 @@
|
|||||||
|
|
||||||
|
--- Assorted utilities for managing tables, plus a scheduler for rollback functions.
|
||||||
|
-- Does not requires modules directly (only as locals
|
||||||
|
-- inside specific functions) to avoid interdependencies,
|
||||||
|
-- as this is used in the bootstrapping stage of luarocks.cfg.
|
||||||
|
|
||||||
|
local util = {}
|
||||||
|
|
||||||
|
local unpack = unpack or table.unpack
|
||||||
|
|
||||||
|
local scheduled_functions = {}
|
||||||
|
local debug = require("debug")
|
||||||
|
|
||||||
|
--- Schedule a function to be executed upon program termination.
|
||||||
|
-- This is useful for actions such as deleting temporary directories
|
||||||
|
-- or failure rollbacks.
|
||||||
|
-- @param f function: Function to be executed.
|
||||||
|
-- @param ... arguments to be passed to function.
|
||||||
|
-- @return table: A token representing the scheduled execution,
|
||||||
|
-- which can be used to remove the item later from the list.
|
||||||
|
function util.schedule_function(f, ...)
|
||||||
|
assert(type(f) == "function")
|
||||||
|
|
||||||
|
local item = { fn = f, args = {...} }
|
||||||
|
table.insert(scheduled_functions, item)
|
||||||
|
return item
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Unschedule a function.
|
||||||
|
-- This is useful for cancelling a rollback of a completed operation.
|
||||||
|
-- @param item table: The token representing the scheduled function that was
|
||||||
|
-- returned from the schedule_function call.
|
||||||
|
function util.remove_scheduled_function(item)
|
||||||
|
for k, v in pairs(scheduled_functions) do
|
||||||
|
if v == item then
|
||||||
|
table.remove(scheduled_functions, k)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Execute scheduled functions.
|
||||||
|
-- Some calls create temporary files and/or directories and register
|
||||||
|
-- corresponding cleanup functions. Calling this function will run
|
||||||
|
-- these function, erasing temporaries.
|
||||||
|
-- Functions are executed in the inverse order they were scheduled.
|
||||||
|
function util.run_scheduled_functions()
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
fs.change_dir_to_root()
|
||||||
|
for i = #scheduled_functions, 1, -1 do
|
||||||
|
local item = scheduled_functions[i]
|
||||||
|
item.fn(unpack(item.args))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Produce a Lua pattern that matches precisely the given string
|
||||||
|
-- (this is suitable to be concatenating to other patterns,
|
||||||
|
-- so it does not include beginning- and end-of-string markers (^$)
|
||||||
|
-- @param s string: The input string
|
||||||
|
-- @return string: The equivalent pattern
|
||||||
|
function util.matchquote(s)
|
||||||
|
return (s:gsub("[?%-+*%[%].%%()$^]","%%%1"))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- List of supported arguments.
|
||||||
|
-- Arguments that take no parameters are marked with the boolean true.
|
||||||
|
-- Arguments that take a parameter are marked with a descriptive string.
|
||||||
|
-- Arguments that may take an empty string are described in quotes,
|
||||||
|
-- (as in the value for --detailed="<text>").
|
||||||
|
-- For all other string values, it means the parameter is mandatory.
|
||||||
|
local supported_flags = {
|
||||||
|
["all"] = true,
|
||||||
|
["api-key"] = "<key>",
|
||||||
|
["append"] = true,
|
||||||
|
["arch"] = "<arch>",
|
||||||
|
["bin"] = true,
|
||||||
|
["binary"] = true,
|
||||||
|
["branch"] = "<branch-name>",
|
||||||
|
["debug"] = true,
|
||||||
|
["deps"] = true,
|
||||||
|
["deps-mode"] = "<mode>",
|
||||||
|
["detailed"] = "\"<text>\"",
|
||||||
|
["force"] = true,
|
||||||
|
["force-fast"] = true,
|
||||||
|
["from"] = "<server>",
|
||||||
|
["help"] = true,
|
||||||
|
["home"] = true,
|
||||||
|
["homepage"] = "\"<url>\"",
|
||||||
|
["keep"] = true,
|
||||||
|
["lib"] = "<library>",
|
||||||
|
["license"] = "\"<text>\"",
|
||||||
|
["list"] = true,
|
||||||
|
["local"] = true,
|
||||||
|
["local-tree"] = true,
|
||||||
|
["lr-bin"] = true,
|
||||||
|
["lr-cpath"] = true,
|
||||||
|
["lr-path"] = true,
|
||||||
|
["lua-version"] = "<vers>",
|
||||||
|
["lua-ver"] = true,
|
||||||
|
["lua-incdir"] = true,
|
||||||
|
["lua-libdir"] = true,
|
||||||
|
["modules"] = true,
|
||||||
|
["mversion"] = true,
|
||||||
|
["no-refresh"] = true,
|
||||||
|
["nodeps"] = true,
|
||||||
|
["old-versions"] = true,
|
||||||
|
["only-deps"] = true,
|
||||||
|
["only-from"] = "<server>",
|
||||||
|
["only-server"] = "<server>",
|
||||||
|
["only-sources"] = "<url>",
|
||||||
|
["only-sources-from"] = "<url>",
|
||||||
|
["outdated"] = true,
|
||||||
|
["output"] = "<file>",
|
||||||
|
["pack-binary-rock"] = true,
|
||||||
|
["porcelain"] = true,
|
||||||
|
["quick"] = true,
|
||||||
|
["rock-dir"] = true,
|
||||||
|
["rock-tree"] = true,
|
||||||
|
["rock-trees"] = true,
|
||||||
|
["rockspec"] = true,
|
||||||
|
["rockspec-format"] = "<ver>",
|
||||||
|
["server"] = "<server>",
|
||||||
|
["skip-pack"] = true,
|
||||||
|
["source"] = true,
|
||||||
|
["summary"] = "\"<text>\"",
|
||||||
|
["system-config"] = true,
|
||||||
|
["tag"] = "<tag>",
|
||||||
|
["timeout"] = "<seconds>",
|
||||||
|
["to"] = "<path>",
|
||||||
|
["tree"] = "<path>",
|
||||||
|
["user-config"] = true,
|
||||||
|
["verbose"] = true,
|
||||||
|
["version"] = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Extract flags from an arguments list.
|
||||||
|
-- Given string arguments, extract flag arguments into a flags set.
|
||||||
|
-- For example, given "foo", "--tux=beep", "--bla", "bar", "--baz",
|
||||||
|
-- it would return the following:
|
||||||
|
-- {["bla"] = true, ["tux"] = "beep", ["baz"] = true}, "foo", "bar".
|
||||||
|
function util.parse_flags(...)
|
||||||
|
local args = {...}
|
||||||
|
local flags = {}
|
||||||
|
local i = 1
|
||||||
|
local out = {}
|
||||||
|
local ignore_flags = false
|
||||||
|
while i <= #args do
|
||||||
|
local flag = args[i]:match("^%-%-(.*)")
|
||||||
|
if flag == "--" then
|
||||||
|
ignore_flags = true
|
||||||
|
end
|
||||||
|
if flag and not ignore_flags then
|
||||||
|
local var,val = flag:match("([a-z_%-]*)=(.*)")
|
||||||
|
if val then
|
||||||
|
local vartype = supported_flags[var]
|
||||||
|
if type(vartype) == "string" then
|
||||||
|
if val == "" and vartype:sub(1,1) ~= '"' then
|
||||||
|
return { ERROR = "Invalid argument: parameter to flag --"..var.."="..vartype.." cannot be empty." }
|
||||||
|
end
|
||||||
|
flags[var] = val
|
||||||
|
else
|
||||||
|
if vartype then
|
||||||
|
return { ERROR = "Invalid argument: flag --"..var.." does not take an parameter." }
|
||||||
|
else
|
||||||
|
return { ERROR = "Invalid argument: unknown flag --"..var.."." }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local var = flag
|
||||||
|
local vartype = supported_flags[var]
|
||||||
|
if type(vartype) == "string" then
|
||||||
|
i = i + 1
|
||||||
|
local val = args[i]
|
||||||
|
if not val then
|
||||||
|
return { ERROR = "Invalid argument: flag --"..var.."="..vartype.." expects a parameter." }
|
||||||
|
end
|
||||||
|
if val:match("^%-%-.*") then
|
||||||
|
return { ERROR = "Invalid argument: flag --"..var.."="..vartype.." expects a parameter (if you really want to pass "..val.." as an argument to --"..var..", use --"..var.."="..val..")." }
|
||||||
|
else
|
||||||
|
if val == "" and vartype:sub(1,1) ~= '"' then
|
||||||
|
return { ERROR = "Invalid argument: parameter to flag --"..var.."="..vartype.." cannot be empty." }
|
||||||
|
end
|
||||||
|
flags[var] = val
|
||||||
|
end
|
||||||
|
elseif vartype == true then
|
||||||
|
flags[var] = true
|
||||||
|
else
|
||||||
|
return { ERROR = "Invalid argument: unknown flag --"..var.."." }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
table.insert(out, args[i])
|
||||||
|
end
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
return flags, unpack(out)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Adds legacy 'run' function to a command module.
|
||||||
|
-- @param command table: command module with 'command' function,
|
||||||
|
-- the added 'run' function calls it after parseing command-line arguments.
|
||||||
|
function util.add_run_function(command)
|
||||||
|
command.run = function(...) return command.command(util.parse_flags(...)) end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Merges contents of src on top of dst's contents.
|
||||||
|
-- @param dst Destination table, which will receive src's contents.
|
||||||
|
-- @param src Table which provides new contents to dst.
|
||||||
|
-- @see platform_overrides
|
||||||
|
function util.deep_merge(dst, src)
|
||||||
|
for k, v in pairs(src) do
|
||||||
|
if type(v) == "table" then
|
||||||
|
if not dst[k] then
|
||||||
|
dst[k] = {}
|
||||||
|
end
|
||||||
|
if type(dst[k]) == "table" then
|
||||||
|
util.deep_merge(dst[k], v)
|
||||||
|
else
|
||||||
|
dst[k] = v
|
||||||
|
end
|
||||||
|
else
|
||||||
|
dst[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Perform platform-specific overrides on a table.
|
||||||
|
-- Overrides values of table with the contents of the appropriate
|
||||||
|
-- subset of its "platforms" field. The "platforms" field should
|
||||||
|
-- be a table containing subtables keyed with strings representing
|
||||||
|
-- platform names. Names that match the contents of the global
|
||||||
|
-- cfg.platforms setting are used. For example, if
|
||||||
|
-- cfg.platforms= {"foo"}, then the fields of
|
||||||
|
-- tbl.platforms.foo will overwrite those of tbl with the same
|
||||||
|
-- names. For table values, the operation is performed recursively
|
||||||
|
-- (tbl.platforms.foo.x.y.z overrides tbl.x.y.z; other contents of
|
||||||
|
-- tbl.x are preserved).
|
||||||
|
-- @param tbl table or nil: Table which may contain a "platforms" field;
|
||||||
|
-- if it doesn't (or if nil is passed), this function does nothing.
|
||||||
|
function util.platform_overrides(tbl)
|
||||||
|
assert(type(tbl) == "table" or not tbl)
|
||||||
|
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
|
||||||
|
if not tbl then return end
|
||||||
|
|
||||||
|
if tbl.platforms then
|
||||||
|
for _, platform in ipairs(cfg.platforms) do
|
||||||
|
local platform_tbl = tbl.platforms[platform]
|
||||||
|
if platform_tbl then
|
||||||
|
util.deep_merge(tbl, platform_tbl)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
tbl.platforms = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local var_format_pattern = "%$%((%a[%a%d_]+)%)"
|
||||||
|
|
||||||
|
--- Create a new shallow copy of a table: a new table with
|
||||||
|
-- the same keys and values. Keys point to the same objects as
|
||||||
|
-- the original table (ie, does not copy recursively).
|
||||||
|
-- @param tbl table: the input table
|
||||||
|
-- @return table: a new table with the same contents.
|
||||||
|
function util.make_shallow_copy(tbl)
|
||||||
|
local copy = {}
|
||||||
|
for k,v in pairs(tbl) do
|
||||||
|
copy[k] = v
|
||||||
|
end
|
||||||
|
return copy
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if a set of needed variables are referenced
|
||||||
|
-- somewhere in a list of definitions, warning the user
|
||||||
|
-- about any unused ones. Each key in needed_set should
|
||||||
|
-- appear as a $(XYZ) variable at least once as a
|
||||||
|
-- substring of some value of var_defs.
|
||||||
|
-- @param var_defs: a table with string keys and string
|
||||||
|
-- values, containing variable definitions.
|
||||||
|
-- @param needed_set: a set where keys are the names of
|
||||||
|
-- needed variables.
|
||||||
|
-- @param msg string: the warning message to display.
|
||||||
|
function util.warn_if_not_used(var_defs, needed_set, msg)
|
||||||
|
needed_set = util.make_shallow_copy(needed_set)
|
||||||
|
for _, val in pairs(var_defs) do
|
||||||
|
for used in val:gmatch(var_format_pattern) do
|
||||||
|
needed_set[used] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for var, _ in pairs(needed_set) do
|
||||||
|
util.warning(msg:format(var))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Output any entries that might remain in $(XYZ) format,
|
||||||
|
-- warning the user that substitutions have failed.
|
||||||
|
-- @param line string: the input string
|
||||||
|
local function warn_failed_matches(line)
|
||||||
|
local any_failed = false
|
||||||
|
if line:match(var_format_pattern) then
|
||||||
|
for unmatched in line:gmatch(var_format_pattern) do
|
||||||
|
util.warning("unmatched variable " .. unmatched)
|
||||||
|
any_failed = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return any_failed
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Perform make-style variable substitutions on string values of a table.
|
||||||
|
-- For every string value tbl.x which contains a substring of the format
|
||||||
|
-- "$(XYZ)" will have this substring replaced by vars["XYZ"], if that field
|
||||||
|
-- exists in vars. Only string values are processed; this function
|
||||||
|
-- does not scan subtables recursively.
|
||||||
|
-- @param tbl table: Table to have its string values modified.
|
||||||
|
-- @param vars table: Table containing string-string key-value pairs
|
||||||
|
-- representing variables to replace in the strings values of tbl.
|
||||||
|
function util.variable_substitutions(tbl, vars)
|
||||||
|
assert(type(tbl) == "table")
|
||||||
|
assert(type(vars) == "table")
|
||||||
|
|
||||||
|
local updated = {}
|
||||||
|
for k, v in pairs(tbl) do
|
||||||
|
if type(v) == "string" then
|
||||||
|
updated[k] = v:gsub(var_format_pattern, vars)
|
||||||
|
if warn_failed_matches(updated[k]) then
|
||||||
|
updated[k] = updated[k]:gsub(var_format_pattern, "")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for k, v in pairs(updated) do
|
||||||
|
tbl[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Return an array of keys of a table.
|
||||||
|
-- @param tbl table: The input table.
|
||||||
|
-- @return table: The array of keys.
|
||||||
|
function util.keys(tbl)
|
||||||
|
local ks = {}
|
||||||
|
for k,_ in pairs(tbl) do
|
||||||
|
table.insert(ks, k)
|
||||||
|
end
|
||||||
|
return ks
|
||||||
|
end
|
||||||
|
|
||||||
|
local function default_sort(a, b)
|
||||||
|
local ta = type(a)
|
||||||
|
local tb = type(b)
|
||||||
|
if ta == "number" and tb == "number" then
|
||||||
|
return a < b
|
||||||
|
elseif ta == "number" then
|
||||||
|
return true
|
||||||
|
elseif tb == "number" then
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
return tostring(a) < tostring(b)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- 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
|
||||||
|
|
||||||
|
function util.lua_versions()
|
||||||
|
local versions = { "5.1", "5.2", "5.3" }
|
||||||
|
local i = 0
|
||||||
|
return function()
|
||||||
|
i = i + 1
|
||||||
|
return versions[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function util.starts_with(s, prefix)
|
||||||
|
return s:sub(1,#prefix) == prefix
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Print a line to standard output
|
||||||
|
function util.printout(...)
|
||||||
|
io.stdout:write(table.concat({...},"\t"))
|
||||||
|
io.stdout:write("\n")
|
||||||
|
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
|
||||||
|
|
||||||
|
function util.title(msg, porcelain, underline)
|
||||||
|
if porcelain then return end
|
||||||
|
util.printout()
|
||||||
|
util.printout(msg)
|
||||||
|
util.printout((underline or "-"):rep(#msg))
|
||||||
|
util.printout()
|
||||||
|
end
|
||||||
|
|
||||||
|
function util.this_program(default)
|
||||||
|
local i = 1
|
||||||
|
local last, cur = default, default
|
||||||
|
while i do
|
||||||
|
local dbg = debug.getinfo(i,"S")
|
||||||
|
if not dbg then break end
|
||||||
|
last = cur
|
||||||
|
cur = dbg.source
|
||||||
|
i=i+1
|
||||||
|
end
|
||||||
|
return last:sub(2)
|
||||||
|
end
|
||||||
|
|
||||||
|
function util.deps_mode_help(program)
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
return [[
|
||||||
|
--deps-mode=<mode> How to handle dependencies. Four modes are supported:
|
||||||
|
* all - use all trees from the rocks_trees list
|
||||||
|
for finding dependencies
|
||||||
|
* one - use only the current tree (possibly set
|
||||||
|
with --tree)
|
||||||
|
* order - use trees based on order (use the current
|
||||||
|
tree and all trees below it on the rocks_trees list)
|
||||||
|
* none - ignore dependencies altogether.
|
||||||
|
The default mode may be set with the deps_mode entry
|
||||||
|
in the configuration file.
|
||||||
|
The current default is "]]..cfg.deps_mode..[[".
|
||||||
|
Type ']]..util.this_program(program or "luarocks")..[[' with no arguments to see
|
||||||
|
your list of rocks trees.
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
|
||||||
|
function util.see_help(command, program)
|
||||||
|
return "See '"..util.this_program(program or "luarocks")..' help'..(command and " "..command or "").."'."
|
||||||
|
end
|
||||||
|
|
||||||
|
function util.announce_install(rockspec)
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
|
||||||
|
local suffix = ""
|
||||||
|
if rockspec.description and rockspec.description.license then
|
||||||
|
suffix = " (license: "..rockspec.description.license..")"
|
||||||
|
end
|
||||||
|
|
||||||
|
local root_dir = path.root_dir(cfg.rocks_dir)
|
||||||
|
util.printout(rockspec.name.." "..rockspec.version.." is now installed in "..root_dir..suffix)
|
||||||
|
util.printout()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Collect rockspecs located in a subdirectory.
|
||||||
|
-- @param versions table: A table mapping rock names to newest rockspec versions.
|
||||||
|
-- @param paths table: A table mapping rock names to newest rockspec paths.
|
||||||
|
-- @param unnamed_paths table: An array of rockspec paths that don't contain rock
|
||||||
|
-- name and version in regular format.
|
||||||
|
-- @param subdir string: path to subdirectory.
|
||||||
|
local function collect_rockspecs(versions, paths, unnamed_paths, subdir)
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
local deps = require("luarocks.deps")
|
||||||
|
|
||||||
|
if fs.is_dir(subdir) then
|
||||||
|
for file in fs.dir(subdir) do
|
||||||
|
file = dir.path(subdir, file)
|
||||||
|
|
||||||
|
if file:match("rockspec$") and fs.is_file(file) then
|
||||||
|
local rock, version = path.parse_name(file)
|
||||||
|
|
||||||
|
if rock then
|
||||||
|
if not versions[rock] or deps.compare_versions(version, versions[rock]) then
|
||||||
|
versions[rock] = version
|
||||||
|
paths[rock] = file
|
||||||
|
end
|
||||||
|
else
|
||||||
|
table.insert(unnamed_paths, file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get default rockspec name for commands that take optional rockspec name.
|
||||||
|
-- @return string or (nil, string): path to the rockspec or nil and error message.
|
||||||
|
function util.get_default_rockspec()
|
||||||
|
local versions, paths, unnamed_paths = {}, {}, {}
|
||||||
|
-- Look for rockspecs in some common locations.
|
||||||
|
collect_rockspecs(versions, paths, unnamed_paths, ".")
|
||||||
|
collect_rockspecs(versions, paths, unnamed_paths, "rockspec")
|
||||||
|
collect_rockspecs(versions, paths, unnamed_paths, "rockspecs")
|
||||||
|
|
||||||
|
if #unnamed_paths > 0 then
|
||||||
|
-- There are rockspecs not following "name-version.rockspec" format.
|
||||||
|
-- More than one are ambiguous.
|
||||||
|
if #unnamed_paths > 1 then
|
||||||
|
return nil, "Please specify which rockspec file to use."
|
||||||
|
else
|
||||||
|
return unnamed_paths[1]
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local rock = next(versions)
|
||||||
|
|
||||||
|
if rock then
|
||||||
|
-- If there are rockspecs for multiple rocks it's ambiguous.
|
||||||
|
if next(versions, rock) then
|
||||||
|
return nil, "Please specify which rockspec file to use."
|
||||||
|
else
|
||||||
|
return paths[rock]
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return nil, "Argument missing: please specify a rockspec to use on current directory."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- from http://lua-users.org/wiki/SplitJoin
|
||||||
|
-- by PhilippeLhoste
|
||||||
|
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
|
||||||
|
|
||||||
|
--- Remove repeated entries from a path-style string.
|
||||||
|
-- Example: given ("a;b;c;a;b;d", ";"), returns "a;b;c;d".
|
||||||
|
-- @param list string: A path string (from $PATH or package.path)
|
||||||
|
-- @param sep string: The separator
|
||||||
|
function util.remove_path_dupes(list, sep)
|
||||||
|
assert(type(list) == "string")
|
||||||
|
assert(type(sep) == "string")
|
||||||
|
local parts = util.split_string(list, sep)
|
||||||
|
local final, entries = {}, {}
|
||||||
|
for _, part in ipairs(parts) do
|
||||||
|
part = part:gsub("//", "/")
|
||||||
|
if not entries[part] then
|
||||||
|
table.insert(final, part)
|
||||||
|
entries[part] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return table.concat(final, sep)
|
||||||
|
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 procesed
|
||||||
|
-- (in the case in which indent is composed by spaces or "--").
|
||||||
|
-- Userdata and function keys and values are shown as strings,
|
||||||
|
-- which logically are exactly not equivalent to the original code.
|
||||||
|
-- This routine can serve for pretty formating tables with
|
||||||
|
-- proper indentations, apart from printing them:
|
||||||
|
-- io.write(table.show(t, "t")) -- a typical use
|
||||||
|
-- Written by Julio Manuel Fernandez-Diaz,
|
||||||
|
-- Heavily based on "Saving tables with cycles", PIL2, p. 113.
|
||||||
|
-- @param t table: is the table.
|
||||||
|
-- @param name string: is the name of the table (optional)
|
||||||
|
-- @param indent string: is a first indentation (optional).
|
||||||
|
-- @return string: the pretty-printed table
|
||||||
|
function util.show_table(t, name, indent)
|
||||||
|
local cart -- a container
|
||||||
|
local autoref -- for self references
|
||||||
|
|
||||||
|
local function isemptytable(t) return next(t) == nil end
|
||||||
|
|
||||||
|
local function basicSerialize (o)
|
||||||
|
local so = tostring(o)
|
||||||
|
if type(o) == "function" then
|
||||||
|
local info = debug.getinfo(o, "S")
|
||||||
|
-- info.name is nil because o is not a calling level
|
||||||
|
if info.what == "C" then
|
||||||
|
return ("%q"):format(so .. ", C function")
|
||||||
|
else
|
||||||
|
-- the information is defined through lines
|
||||||
|
return ("%q"):format(so .. ", defined in (" .. info.linedefined .. "-" .. info.lastlinedefined .. ")" .. info.source)
|
||||||
|
end
|
||||||
|
elseif type(o) == "number" then
|
||||||
|
return so
|
||||||
|
else
|
||||||
|
return ("%q"):format(so)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function addtocart (value, name, indent, saved, field)
|
||||||
|
indent = indent or ""
|
||||||
|
saved = saved or {}
|
||||||
|
field = field or name
|
||||||
|
|
||||||
|
cart = cart .. indent .. field
|
||||||
|
|
||||||
|
if type(value) ~= "table" then
|
||||||
|
cart = cart .. " = " .. basicSerialize(value) .. ";\n"
|
||||||
|
else
|
||||||
|
if saved[value] then
|
||||||
|
cart = cart .. " = {}; -- " .. saved[value] .. " (self reference)\n"
|
||||||
|
autoref = autoref .. name .. " = " .. saved[value] .. ";\n"
|
||||||
|
else
|
||||||
|
saved[value] = name
|
||||||
|
--if tablecount(value) == 0 then
|
||||||
|
if isemptytable(value) then
|
||||||
|
cart = cart .. " = {};\n"
|
||||||
|
else
|
||||||
|
cart = cart .. " = {\n"
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
k = basicSerialize(k)
|
||||||
|
local fname = ("%s[%s]"):format(name, k)
|
||||||
|
field = ("[%s]"):format(k)
|
||||||
|
-- three spaces between levels
|
||||||
|
addtocart(v, fname, indent .. " ", saved, field)
|
||||||
|
end
|
||||||
|
cart = cart .. indent .. "};\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
name = name or "__unnamed__"
|
||||||
|
if type(t) ~= "table" then
|
||||||
|
return name .. " = " .. basicSerialize(t)
|
||||||
|
end
|
||||||
|
cart, autoref = "", ""
|
||||||
|
addtocart(t, name, indent)
|
||||||
|
return cart .. autoref
|
||||||
|
end
|
||||||
|
|
||||||
|
function util.array_contains(tbl, value)
|
||||||
|
for _, v in ipairs(tbl) do
|
||||||
|
if v == value then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Quote Lua string, analogous to fs.Q.
|
||||||
|
-- @param s A string, such as "hello"
|
||||||
|
-- @return string: A quoted string, such as '"hello"'
|
||||||
|
function util.LQ(s)
|
||||||
|
return ("%q"):format(s)
|
||||||
|
end
|
||||||
|
|
||||||
|
return util
|
||||||
159
Utils/luarocks/lua/luarocks/validate.lua
Normal file
159
Utils/luarocks/lua/luarocks/validate.lua
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
|
||||||
|
--- Sandboxed test of build/install of all packages in a repository (unfinished and disabled).
|
||||||
|
local validate = {}
|
||||||
|
package.loaded["luarocks.validate"] = validate
|
||||||
|
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local build = require("luarocks.build")
|
||||||
|
local install = require("luarocks.install")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
|
||||||
|
util.add_run_function(validate)
|
||||||
|
validate.help_summary = "Sandboxed test of build/install of all packages in a repository."
|
||||||
|
|
||||||
|
validate.help = [[
|
||||||
|
<argument>, if given, is a local repository pathname.
|
||||||
|
]]
|
||||||
|
|
||||||
|
local function save_settings(repo)
|
||||||
|
local protocol, path = dir.split_url(repo)
|
||||||
|
table.insert(cfg.rocks_servers, 1, protocol.."://"..path)
|
||||||
|
return {
|
||||||
|
root_dir = cfg.root_dir,
|
||||||
|
rocks_dir = cfg.rocks_dir,
|
||||||
|
deploy_bin_dir = cfg.deploy_bin_dir,
|
||||||
|
deploy_lua_dir = cfg.deploy_lua_dir,
|
||||||
|
deploy_lib_dir = cfg.deploy_lib_dir,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local function restore_settings(settings)
|
||||||
|
cfg.root_dir = settings.root_dir
|
||||||
|
cfg.rocks_dir = settings.rocks_dir
|
||||||
|
cfg.deploy_bin_dir = settings.deploy_bin_dir
|
||||||
|
cfg.deploy_lua_dir = settings.deploy_lua_dir
|
||||||
|
cfg.deploy_lib_dir = settings.deploy_lib_dir
|
||||||
|
cfg.variables.ROCKS_TREE = settings.rocks_dir
|
||||||
|
cfg.variables.SCRIPTS_DIR = settings.deploy_bin_dir
|
||||||
|
table.remove(cfg.rocks_servers, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function prepare_sandbox(file)
|
||||||
|
local root_dir = fs.make_temp_dir(file):gsub("/+$", "")
|
||||||
|
cfg.root_dir = root_dir
|
||||||
|
cfg.rocks_dir = path.rocks_dir(root_dir)
|
||||||
|
cfg.deploy_bin_dir = path.deploy_bin_dir(root_dir)
|
||||||
|
cfg.variables.ROCKS_TREE = cfg.rocks_dir
|
||||||
|
cfg.variables.SCRIPTS_DIR = cfg.deploy_bin_dir
|
||||||
|
return root_dir
|
||||||
|
end
|
||||||
|
|
||||||
|
local function validate_rockspec(file)
|
||||||
|
local ok, err, errcode = build.build_rockspec(file, true, "one")
|
||||||
|
if not ok then
|
||||||
|
util.printerr(err)
|
||||||
|
end
|
||||||
|
return ok, err, errcode
|
||||||
|
end
|
||||||
|
|
||||||
|
local function validate_src_rock(file)
|
||||||
|
local ok, err, errcode = build.build_rock(file, false, "one")
|
||||||
|
if not ok then
|
||||||
|
util.printerr(err)
|
||||||
|
end
|
||||||
|
return ok, err, errcode
|
||||||
|
end
|
||||||
|
|
||||||
|
local function validate_rock(file)
|
||||||
|
local ok, err, errcode = install.install_binary_rock(file, "one")
|
||||||
|
if not ok then
|
||||||
|
util.printerr(err)
|
||||||
|
end
|
||||||
|
return ok, err, errcode
|
||||||
|
end
|
||||||
|
|
||||||
|
function validate.command(flags, repo)
|
||||||
|
repo = repo or cfg.rocks_dir
|
||||||
|
|
||||||
|
util.printout("Verifying contents of "..repo)
|
||||||
|
|
||||||
|
local results = {
|
||||||
|
ok = {}
|
||||||
|
}
|
||||||
|
local settings = save_settings(repo)
|
||||||
|
local sandbox
|
||||||
|
if flags["quick"] then
|
||||||
|
sandbox = prepare_sandbox("luarocks_validate")
|
||||||
|
end
|
||||||
|
if not fs.exists(repo) then
|
||||||
|
return nil, repo.." is not a local repository."
|
||||||
|
end
|
||||||
|
for file in fs.dir(repo) do for _=1,1 do
|
||||||
|
if file == "manifest" or file == "index.html" then
|
||||||
|
break -- continue for
|
||||||
|
end
|
||||||
|
local pathname = fs.absolute_name(dir.path(repo, file))
|
||||||
|
if not flags["quick"] then
|
||||||
|
sandbox = prepare_sandbox(file)
|
||||||
|
end
|
||||||
|
local ok, err, errcode
|
||||||
|
util.printout()
|
||||||
|
util.printout("Verifying "..pathname)
|
||||||
|
if file:match("%.rockspec$") then
|
||||||
|
ok, err, errcode = validate_rockspec(pathname, "one")
|
||||||
|
elseif file:match("%.src%.rock$") then
|
||||||
|
ok, err, errcode = validate_src_rock(pathname)
|
||||||
|
elseif file:match("%.rock$") then
|
||||||
|
ok, err, errcode = validate_rock(pathname)
|
||||||
|
end
|
||||||
|
if ok then
|
||||||
|
table.insert(results.ok, {file=file} )
|
||||||
|
else
|
||||||
|
if not errcode then
|
||||||
|
errcode = "misc"
|
||||||
|
end
|
||||||
|
if not results[errcode] then
|
||||||
|
results[errcode] = {}
|
||||||
|
end
|
||||||
|
table.insert(results[errcode], {file=file, err=err} )
|
||||||
|
end
|
||||||
|
util.run_scheduled_functions()
|
||||||
|
if not flags["quick"] then
|
||||||
|
fs.delete(sandbox)
|
||||||
|
end
|
||||||
|
repeat until not fs.pop_dir()
|
||||||
|
end end
|
||||||
|
if flags["quick"] then
|
||||||
|
fs.delete(sandbox)
|
||||||
|
end
|
||||||
|
restore_settings(settings)
|
||||||
|
util.title("Results:")
|
||||||
|
util.printout("OK: "..tostring(#results.ok))
|
||||||
|
for _, entry in ipairs(results.ok) do
|
||||||
|
util.printout(entry.file)
|
||||||
|
end
|
||||||
|
for errcode, errors in pairs(results) do
|
||||||
|
if errcode ~= "ok" then
|
||||||
|
util.printout()
|
||||||
|
util.printout(errcode.." errors: "..tostring(#errors))
|
||||||
|
for _, entry in ipairs(errors) do
|
||||||
|
util.printout(entry.file, entry.err)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
util.title("Summary:")
|
||||||
|
local total = 0
|
||||||
|
for errcode, errors in pairs(results) do
|
||||||
|
util.printout(errcode..": "..tostring(#errors))
|
||||||
|
total = total + #errors
|
||||||
|
end
|
||||||
|
util.printout("Total: "..total)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return validate
|
||||||
375
Utils/luarocks/lua/luarocks/write_rockspec.lua
Normal file
375
Utils/luarocks/lua/luarocks/write_rockspec.lua
Normal file
@ -0,0 +1,375 @@
|
|||||||
|
|
||||||
|
local write_rockspec = {}
|
||||||
|
package.loaded["luarocks.write_rockspec"] = write_rockspec
|
||||||
|
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
local dir = require("luarocks.dir")
|
||||||
|
local fetch = require("luarocks.fetch")
|
||||||
|
local fs = require("luarocks.fs")
|
||||||
|
local path = require("luarocks.path")
|
||||||
|
local persist = require("luarocks.persist")
|
||||||
|
local type_check = require("luarocks.type_check")
|
||||||
|
local util = require("luarocks.util")
|
||||||
|
|
||||||
|
util.add_run_function(write_rockspec)
|
||||||
|
write_rockspec.help_summary = "Write a template for a rockspec file."
|
||||||
|
write_rockspec.help_arguments = "[--output=<file> ...] [<name>] [<version>] [<url>|<path>]"
|
||||||
|
write_rockspec.help = [[
|
||||||
|
This command writes an initial version of a rockspec file,
|
||||||
|
based on 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 location.
|
||||||
|
LuaRocks will attempt to infer name and version if not given,
|
||||||
|
using 'scm' as default version.
|
||||||
|
|
||||||
|
Note that the generated file is a _starting point_ for writing a
|
||||||
|
rockspec, and is not guaranteed to be complete or correct.
|
||||||
|
|
||||||
|
--output=<file> Write the rockspec with the given filename.
|
||||||
|
If not given, a file is written in the current
|
||||||
|
directory with a filename based on given name and version.
|
||||||
|
--license="<string>" A license string, such as "MIT/X11" or "GNU GPL v3".
|
||||||
|
--summary="<txt>" A short one-line description summary.
|
||||||
|
--detailed="<txt>" A longer description string.
|
||||||
|
--homepage=<url> Project homepage.
|
||||||
|
--lua-version=<ver> Supported Lua versions. Accepted values are "5.1", "5.2",
|
||||||
|
"5.3", "5.1,5.2", "5.2,5.3", or "5.1,5.2,5.3".
|
||||||
|
--rockspec-format=<ver> Rockspec format version, such as "1.0" or "1.1".
|
||||||
|
--tag=<tag> Tag to use. Will attempt to extract version number from it.
|
||||||
|
--lib=<lib>[,<lib>] A comma-separated list of libraries that C files need to
|
||||||
|
link to.
|
||||||
|
]]
|
||||||
|
|
||||||
|
local function open_file(name)
|
||||||
|
return io.open(dir.path(fs.current_dir(), name), "r")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function get_url(rockspec)
|
||||||
|
local file, temp_dir, err_code, err_file, err_temp_dir = fetch.fetch_sources(rockspec, false)
|
||||||
|
if err_code == "source.dir" then
|
||||||
|
file, temp_dir = err_file, err_temp_dir
|
||||||
|
elseif not file then
|
||||||
|
util.warning("Could not fetch sources - "..temp_dir)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
util.printout("File successfully downloaded. Making checksum and checking base dir...")
|
||||||
|
if fetch.is_basic_protocol(rockspec.source.protocol) then
|
||||||
|
rockspec.source.md5 = fs.get_md5(file)
|
||||||
|
end
|
||||||
|
local inferred_dir, found_dir = fetch.find_base_dir(file, temp_dir, rockspec.source.url)
|
||||||
|
return true, found_dir or inferred_dir, temp_dir
|
||||||
|
end
|
||||||
|
|
||||||
|
local function configure_lua_version(rockspec, luaver)
|
||||||
|
if luaver == "5.1" then
|
||||||
|
table.insert(rockspec.dependencies, "lua ~> 5.1")
|
||||||
|
elseif luaver == "5.2" then
|
||||||
|
table.insert(rockspec.dependencies, "lua ~> 5.2")
|
||||||
|
elseif luaver == "5.3" then
|
||||||
|
table.insert(rockspec.dependencies, "lua ~> 5.3")
|
||||||
|
elseif luaver == "5.1,5.2" then
|
||||||
|
table.insert(rockspec.dependencies, "lua >= 5.1, < 5.3")
|
||||||
|
elseif luaver == "5.2,5.3" then
|
||||||
|
table.insert(rockspec.dependencies, "lua >= 5.2, < 5.4")
|
||||||
|
elseif luaver == "5.1,5.2,5.3" then
|
||||||
|
table.insert(rockspec.dependencies, "lua >= 5.1, < 5.4")
|
||||||
|
else
|
||||||
|
util.warning("Please specify supported Lua version with --lua-version=<ver>. "..util.see_help("write_rockspec"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function detect_description()
|
||||||
|
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 function detect_mit_license(data)
|
||||||
|
local strip_copyright = (data:gsub("Copyright [^\n]*\n", ""))
|
||||||
|
local sum = 0
|
||||||
|
for i = 1, #strip_copyright do
|
||||||
|
local num = string.byte(strip_copyright:sub(i,i))
|
||||||
|
if num > 32 and num <= 128 then
|
||||||
|
sum = sum + num
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return sum == 78656
|
||||||
|
end
|
||||||
|
|
||||||
|
local simple_scm_protocols = {
|
||||||
|
git = true, ["git+http"] = true, ["git+https"] = true,
|
||||||
|
hg = true, ["hg+http"] = true, ["hg+https"] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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
|
||||||
|
|
||||||
|
local function show_license(rockspec)
|
||||||
|
local fd = open_file("COPYING") or open_file("LICENSE") or open_file("MIT-LICENSE.txt")
|
||||||
|
if not fd then return nil end
|
||||||
|
local data = fd:read("*a")
|
||||||
|
fd:close()
|
||||||
|
local is_mit = detect_mit_license(data)
|
||||||
|
util.title("License for "..rockspec.package..":")
|
||||||
|
util.printout(data)
|
||||||
|
util.printout()
|
||||||
|
return is_mit
|
||||||
|
end
|
||||||
|
|
||||||
|
local function get_cmod_name(file)
|
||||||
|
local fd = open_file(file)
|
||||||
|
if not fd then return nil end
|
||||||
|
local data = fd:read("*a")
|
||||||
|
fd:close()
|
||||||
|
return (data:match("int%s+luaopen_([a-zA-Z0-9_]+)"))
|
||||||
|
end
|
||||||
|
|
||||||
|
local luamod_blacklist = {
|
||||||
|
test = true,
|
||||||
|
tests = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
local function fill_as_builtin(rockspec, libs)
|
||||||
|
rockspec.build.type = "builtin"
|
||||||
|
rockspec.build.modules = {}
|
||||||
|
local prefix = ""
|
||||||
|
|
||||||
|
for _, parent in ipairs({"src", "lua"}) do
|
||||||
|
if fs.is_dir(parent) then
|
||||||
|
fs.change_dir(parent)
|
||||||
|
prefix = parent.."/"
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local incdirs, libdirs
|
||||||
|
if libs then
|
||||||
|
incdirs, libdirs = {}, {}
|
||||||
|
for _, lib in ipairs(libs) do
|
||||||
|
local upper = lib:upper()
|
||||||
|
incdirs[#incdirs+1] = "$("..upper.."_INCDIR)"
|
||||||
|
libdirs[#libdirs+1] = "$("..upper.."_LIBDIR)"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, file in ipairs(fs.find()) do
|
||||||
|
local luamod = file:match("(.*)%.lua$")
|
||||||
|
if luamod and not luamod_blacklist[luamod] then
|
||||||
|
rockspec.build.modules[path.path_to_module(file)] = prefix..file
|
||||||
|
else
|
||||||
|
local cmod = file:match("(.*)%.c$")
|
||||||
|
if cmod then
|
||||||
|
local modname = get_cmod_name(file) or path.path_to_module(file:gsub("%.c$", ".lua"))
|
||||||
|
rockspec.build.modules[modname] = {
|
||||||
|
sources = prefix..file,
|
||||||
|
libraries = libs,
|
||||||
|
incdirs = incdirs,
|
||||||
|
libdirs = libdirs,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, directory in ipairs({ "doc", "docs", "samples", "tests" }) do
|
||||||
|
if fs.is_dir(directory) then
|
||||||
|
if not rockspec.build.copy_directories then
|
||||||
|
rockspec.build.copy_directories = {}
|
||||||
|
end
|
||||||
|
table.insert(rockspec.build.copy_directories, directory)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if prefix ~= "" then
|
||||||
|
fs.pop_dir()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function rockspec_cleanup(rockspec)
|
||||||
|
rockspec.source.file = nil
|
||||||
|
rockspec.source.protocol = nil
|
||||||
|
rockspec.variables = nil
|
||||||
|
rockspec.name = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function write_rockspec.command(flags, name, version, url_or_dir)
|
||||||
|
if not name then
|
||||||
|
url_or_dir = "."
|
||||||
|
elseif not version then
|
||||||
|
url_or_dir = name
|
||||||
|
name = nil
|
||||||
|
elseif not url_or_dir then
|
||||||
|
url_or_dir = version
|
||||||
|
version = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if flags["tag"] then
|
||||||
|
if not version then
|
||||||
|
version = flags["tag"]:gsub("^v", "")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local protocol, pathname = dir.split_url(url_or_dir)
|
||||||
|
if protocol == "file" then
|
||||||
|
if pathname == "." then
|
||||||
|
name = name or dir.base_name(fs.current_dir())
|
||||||
|
end
|
||||||
|
elseif fetch.is_basic_protocol(protocol) then
|
||||||
|
local filename = dir.base_name(url_or_dir)
|
||||||
|
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(url_or_dir):gsub("%.[^.]+$", "")
|
||||||
|
end
|
||||||
|
|
||||||
|
if not name then
|
||||||
|
return nil, "Could not infer rock name. "..util.see_help("write_rockspec")
|
||||||
|
end
|
||||||
|
version = version or "scm"
|
||||||
|
|
||||||
|
local filename = flags["output"] or dir.path(fs.current_dir(), name:lower().."-"..version.."-1.rockspec")
|
||||||
|
|
||||||
|
local rockspec = {
|
||||||
|
rockspec_format = flags["rockspec-format"],
|
||||||
|
package = name,
|
||||||
|
name = name:lower(),
|
||||||
|
version = version.."-1",
|
||||||
|
source = {
|
||||||
|
url = "*** please add URL for source tarball, zip or repository here ***",
|
||||||
|
tag = flags["tag"],
|
||||||
|
},
|
||||||
|
description = {
|
||||||
|
summary = flags["summary"] or "*** please specify description summary ***",
|
||||||
|
detailed = flags["detailed"] or "*** please enter a detailed description ***",
|
||||||
|
homepage = flags["homepage"] or "*** please enter a project homepage ***",
|
||||||
|
license = flags["license"] or "*** please specify a license ***",
|
||||||
|
},
|
||||||
|
dependencies = {},
|
||||||
|
build = {},
|
||||||
|
}
|
||||||
|
path.configure_paths(rockspec)
|
||||||
|
rockspec.source.protocol = protocol
|
||||||
|
|
||||||
|
configure_lua_version(rockspec, flags["lua-version"])
|
||||||
|
|
||||||
|
local local_dir = url_or_dir
|
||||||
|
|
||||||
|
if url_or_dir:match("://") then
|
||||||
|
rockspec.source.url = url_or_dir
|
||||||
|
rockspec.source.file = dir.base_name(url_or_dir)
|
||||||
|
rockspec.source.dir = "dummy"
|
||||||
|
if not fetch.is_basic_protocol(rockspec.source.protocol) then
|
||||||
|
if version ~= "scm" then
|
||||||
|
rockspec.source.tag = flags["tag"] or "v" .. version
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rockspec.source.dir = nil
|
||||||
|
local ok, base_dir, temp_dir = get_url(rockspec)
|
||||||
|
if ok then
|
||||||
|
if base_dir ~= dir.base_name(url_or_dir) then
|
||||||
|
rockspec.source.dir = base_dir
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if base_dir then
|
||||||
|
local_dir = dir.path(temp_dir, base_dir)
|
||||||
|
else
|
||||||
|
local_dir = nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
rockspec.source.url = detect_scm_url(local_dir) or rockspec.source.url
|
||||||
|
end
|
||||||
|
|
||||||
|
if not local_dir then
|
||||||
|
local_dir = "."
|
||||||
|
end
|
||||||
|
|
||||||
|
if not flags["homepage"] then
|
||||||
|
local url_protocol, url_path = dir.split_url(rockspec.source.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
|
||||||
|
rockspec.description.homepage = "https://"..url_path:gsub("%.git$", "")
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local libs = nil
|
||||||
|
if flags["lib"] then
|
||||||
|
libs = {}
|
||||||
|
rockspec.external_dependencies = {}
|
||||||
|
for lib in flags["lib"]:gmatch("([^,]+)") do
|
||||||
|
table.insert(libs, lib)
|
||||||
|
rockspec.external_dependencies[lib:upper()] = {
|
||||||
|
library = lib
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok, err = fs.change_dir(local_dir)
|
||||||
|
if not ok then return nil, "Failed reaching files from project - error entering directory "..local_dir end
|
||||||
|
|
||||||
|
if (not flags["summary"]) or (not flags["detailed"]) then
|
||||||
|
local summary, detailed = detect_description()
|
||||||
|
rockspec.description.summary = flags["summary"] or summary
|
||||||
|
rockspec.description.detailed = flags["detailed"] or detailed
|
||||||
|
end
|
||||||
|
|
||||||
|
local is_mit = show_license(rockspec)
|
||||||
|
|
||||||
|
if is_mit and not flags["license"] then
|
||||||
|
rockspec.description.license = "MIT"
|
||||||
|
end
|
||||||
|
|
||||||
|
fill_as_builtin(rockspec, libs)
|
||||||
|
|
||||||
|
rockspec_cleanup(rockspec)
|
||||||
|
|
||||||
|
persist.save_from_table(filename, rockspec, type_check.rockspec_order)
|
||||||
|
|
||||||
|
util.printout()
|
||||||
|
util.printout("Wrote template at "..filename.." -- you should now edit and finish it.")
|
||||||
|
util.printout()
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return write_rockspec
|
||||||
BIN
Utils/luarocks/lua5.1.dll
Normal file
BIN
Utils/luarocks/lua5.1.dll
Normal file
Binary file not shown.
BIN
Utils/luarocks/lua5.1.exe
Normal file
BIN
Utils/luarocks/lua5.1.exe
Normal file
Binary file not shown.
BIN
Utils/luarocks/lua5.1.lib
Normal file
BIN
Utils/luarocks/lua5.1.lib
Normal file
Binary file not shown.
BIN
Utils/luarocks/lua51.dll
Normal file
BIN
Utils/luarocks/lua51.dll
Normal file
Binary file not shown.
BIN
Utils/luarocks/lua51.lib
Normal file
BIN
Utils/luarocks/lua51.lib
Normal file
Binary file not shown.
BIN
Utils/luarocks/luac5.1.exe
Normal file
BIN
Utils/luarocks/luac5.1.exe
Normal file
Binary file not shown.
43
Utils/luarocks/luarocks-admin.bat
Normal file
43
Utils/luarocks/luarocks-admin.bat
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
SETLOCAL ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS
|
||||||
|
|
||||||
|
SET "LUA_PATH=C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\lua\?.lua;C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\lua\?\init.lua;%LUA_PATH%"
|
||||||
|
IF NOT "%LUA_PATH_5_2%"=="" (
|
||||||
|
SET "LUA_PATH_5_2=C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\lua\?.lua;C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\lua\?\init.lua;%LUA_PATH_5_2%"
|
||||||
|
)
|
||||||
|
IF NOT "%LUA_PATH_5_3%"=="" (
|
||||||
|
SET "LUA_PATH_5_3=C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\lua\?.lua;C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\lua\?\init.lua;%LUA_PATH_5_3%"
|
||||||
|
)
|
||||||
|
SET "PATH=C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks;%PATH%"
|
||||||
|
"C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\lua5.1" "C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\luarocks-admin.lua" %*
|
||||||
|
SET EXITCODE=%ERRORLEVEL%
|
||||||
|
IF NOT "%EXITCODE%"=="2" GOTO EXITLR
|
||||||
|
|
||||||
|
REM Permission denied error, try and auto elevate...
|
||||||
|
REM already an admin? (checking to prevent loops)
|
||||||
|
NET SESSION >NUL 2>&1
|
||||||
|
IF "%ERRORLEVEL%"=="0" GOTO EXITLR
|
||||||
|
|
||||||
|
REM Do we have PowerShell available?
|
||||||
|
PowerShell /? >NUL 2>&1
|
||||||
|
IF NOT "%ERRORLEVEL%"=="0" GOTO EXITLR
|
||||||
|
|
||||||
|
:GETTEMPNAME
|
||||||
|
SET TMPFILE=%TEMP%\LuaRocks-Elevator-%RANDOM%.bat
|
||||||
|
IF EXIST "%TMPFILE%" GOTO :GETTEMPNAME
|
||||||
|
|
||||||
|
ECHO @ECHO OFF > "%TMPFILE%"
|
||||||
|
ECHO CHDIR /D %CD% >> "%TMPFILE%"
|
||||||
|
ECHO ECHO %0 %* >> "%TMPFILE%"
|
||||||
|
ECHO ECHO. >> "%TMPFILE%"
|
||||||
|
ECHO CALL %0 %* >> "%TMPFILE%"
|
||||||
|
ECHO ECHO. >> "%TMPFILE%"
|
||||||
|
ECHO ECHO Press any key to close this window... >> "%TMPFILE%"
|
||||||
|
ECHO PAUSE ^> NUL >> "%TMPFILE%"
|
||||||
|
ECHO DEL "%TMPFILE%" >> "%TMPFILE%"
|
||||||
|
|
||||||
|
ECHO Now retrying as a privileged user...
|
||||||
|
PowerShell -Command (New-Object -com 'Shell.Application').ShellExecute('%TMPFILE%', '', '', 'runas')
|
||||||
|
|
||||||
|
:EXITLR
|
||||||
|
exit /b %EXITCODE%
|
||||||
19
Utils/luarocks/luarocks-admin.lua
Normal file
19
Utils/luarocks/luarocks-admin.lua
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env lua
|
||||||
|
|
||||||
|
-- this should be loaded first.
|
||||||
|
local cfg = require("luarocks.cfg")
|
||||||
|
|
||||||
|
local loader = require("luarocks.loader")
|
||||||
|
local command_line = require("luarocks.command_line")
|
||||||
|
|
||||||
|
program_description = "LuaRocks repository administration interface"
|
||||||
|
|
||||||
|
commands = {
|
||||||
|
help = "luarocks.help",
|
||||||
|
make_manifest = "luarocks.make_manifest",
|
||||||
|
add = "luarocks.add",
|
||||||
|
remove = "luarocks.admin_remove",
|
||||||
|
refresh_cache = "luarocks.refresh_cache",
|
||||||
|
}
|
||||||
|
|
||||||
|
command_line.run_command(...)
|
||||||
43
Utils/luarocks/luarocks.bat
Normal file
43
Utils/luarocks/luarocks.bat
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
SETLOCAL ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS
|
||||||
|
|
||||||
|
SET "LUA_PATH=C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\lua\?.lua;C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\lua\?\init.lua;%LUA_PATH%"
|
||||||
|
IF NOT "%LUA_PATH_5_2%"=="" (
|
||||||
|
SET "LUA_PATH_5_2=C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\lua\?.lua;C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\lua\?\init.lua;%LUA_PATH_5_2%"
|
||||||
|
)
|
||||||
|
IF NOT "%LUA_PATH_5_3%"=="" (
|
||||||
|
SET "LUA_PATH_5_3=C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\lua\?.lua;C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\lua\?\init.lua;%LUA_PATH_5_3%"
|
||||||
|
)
|
||||||
|
SET "PATH=C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks;%PATH%"
|
||||||
|
"C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\lua5.1" "C:/Users/Hugues/Documents/GitHub/MOOSE/Utils/luarocks\luarocks.lua" %*
|
||||||
|
SET EXITCODE=%ERRORLEVEL%
|
||||||
|
IF NOT "%EXITCODE%"=="2" GOTO EXITLR
|
||||||
|
|
||||||
|
REM Permission denied error, try and auto elevate...
|
||||||
|
REM already an admin? (checking to prevent loops)
|
||||||
|
NET SESSION >NUL 2>&1
|
||||||
|
IF "%ERRORLEVEL%"=="0" GOTO EXITLR
|
||||||
|
|
||||||
|
REM Do we have PowerShell available?
|
||||||
|
PowerShell /? >NUL 2>&1
|
||||||
|
IF NOT "%ERRORLEVEL%"=="0" GOTO EXITLR
|
||||||
|
|
||||||
|
:GETTEMPNAME
|
||||||
|
SET TMPFILE=%TEMP%\LuaRocks-Elevator-%RANDOM%.bat
|
||||||
|
IF EXIST "%TMPFILE%" GOTO :GETTEMPNAME
|
||||||
|
|
||||||
|
ECHO @ECHO OFF > "%TMPFILE%"
|
||||||
|
ECHO CHDIR /D %CD% >> "%TMPFILE%"
|
||||||
|
ECHO ECHO %0 %* >> "%TMPFILE%"
|
||||||
|
ECHO ECHO. >> "%TMPFILE%"
|
||||||
|
ECHO CALL %0 %* >> "%TMPFILE%"
|
||||||
|
ECHO ECHO. >> "%TMPFILE%"
|
||||||
|
ECHO ECHO Press any key to close this window... >> "%TMPFILE%"
|
||||||
|
ECHO PAUSE ^> NUL >> "%TMPFILE%"
|
||||||
|
ECHO DEL "%TMPFILE%" >> "%TMPFILE%"
|
||||||
|
|
||||||
|
ECHO Now retrying as a privileged user...
|
||||||
|
PowerShell -Command (New-Object -com 'Shell.Application').ShellExecute('%TMPFILE%', '', '', 'runas')
|
||||||
|
|
||||||
|
:EXITLR
|
||||||
|
exit /b %EXITCODE%
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user