Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A simple Lua install script for Lua modules, extensions and scripts. Tested on Windows and Linux.
#!/usr/bin/env lua
--[[ -- installing LDoc
function install()
-- requires('pl','Penlight')
-- install_script 'ldoc'
end
--]]
-- --[[
function install()
requires ('lfs','luafilesystem')
from 'lua'
install_lua_package 'mod'
end
--]]
function install_lua_package (dir)
copyd(join(dir),lua_lpath())
end
function install_ext_package (dir)
copyd(join(dir),lua_cpath())
end
function install_lua (mod)
local file = mod2file(mod)..'.lua'
copyf(join(file),lpath)
end
function install_ext (mod)
local file = mod2file(mod)..DEXT
copyf(join(file),cpath)
end
function install_script (file)
file = join(file)
local bindir = check_bin_dir()
local name = file
if not exists(file) then
file = exists(file..'.lua')
if not file then quit("cannot find script") end
end
local pwd = cwd()
local dest = bindir..DIRSEP..name..SEXT
local f,e = io.open(dest,'w')
if not f then quit("cannot create script "..e) end
print('writing',dest)
if WINDOWS then
f:write '@echo off\n'
f:write (LUA,' ',pwd,'\\',file,' %*\n')
else
f:write(LUA,' ',pwd,'/',file,' "$@"\n')
end
f:close()
if not WINDOWS then
run_command('chmod +x '..dest)
end
end
function cwd ()
return result_run_command(CWD)
end
function result_run_command(cmd)
local f,e = io.popen(cmd..' 2>&1')
if e then quit(e) end
local res = f:read '*a':gsub('\n$','')
f:close()
return res
end
function mod2file (mod)
return (mod:gsub('%.','/'))
end
function copyf(src, dest)
if not exists(src) then quit("cannot find '"..src.."'") end
local dir = src:match('.-[/\\](.-)[%w_]+%.%a+$')
print ('dir',dir)
if WINDOWS then
run_command( 'xcopy /S /I /Y '..src..' '..quote(dest..dir))
else
local target_dir = dest..dir
mkdir(target_dir)
run_command('cp -r '..src..' '..target_dir)
end
end
function copyd(src,dest)
local dirname = src:match '[%w_]+$'
if WINDOWS then
run_command('xcopy /S /I /Y '..src..' '..quote(dest..dirname))
else
mkdir(dest)
run_command('cp -r '..src..' '..dest)
end
end
function run_command(cmd,dont_fail)
print(cmd)
local res,x1,x2 = os.execute(cmd)
-- Lua 5.1/5.2 compatible check
local ff
if res == nil or (type(res) == 'number' and res ~= 0) then
if not dont_fail then
quit 'command failed: were you running as an administrator?'
end
end
end
function exists(file)
local f = io.open(file)
if not f then return nil
else f:close(); return file
end
end
function err (msg)
io.stderr:write('install: ',msg,'\n')
end
function quit(msg)
err(msg)
os.exit(1)
end
function requires(mod,name,nofail)
local ok
if type(mod) == 'table' then
ok = true
for i = 1,#mod,2 do
ok = ok and requires(mod[i],mod[i+1],true)
end
if ok then return true end
else
ok = pcall(require,mod)
if not ok then
err('this package requires '..name)
end
end
if not ok and not nofail then
quit("unmet dependencies")
end
return ok
end
function check(mod)
requires(mod,'failed')
end
local created = {}
function mkdir(dest)
if not created[dest] then
run_command('mkdir -p '..dest)
created[dest] = true
end
end
function quote (f)
if WINDOWS and f:match '%s' then
f = '"'..f..'"'
end
return f
end
function isabs (f)
return f:match(ABSPAT)
end
function canonical (f)
if not WINDOWS then return f end
return f:gsub('/','\\'):lower()
end
local src_dir
function from (dir)
src_dir = dir
end
function join (p)
p = canonical(p)
if not src_dir then return p end
return src_dir..DIRSEP..p
end
DIRSEP = package.config:sub(1,1)
WINDOWS = DIRSEP == '\\'
if not WINDOWS then
DEXT = '.so'
ABSPAT = '^/'
SEXT = ''
CWD = 'pwd'
else
DEXT = '.dll'
ABSPAT = '^%a:\\'
SEXT = '.bat'
CWD = 'cd'
end
local opath = os.getenv 'PATH'
-- find all directories in a list which are writeable by current user
function user_writeable(paths)
local results, append = {}, table.insert
local me = os.getenv 'USER'
local f = io.popen('ls -ld '..paths..' 2>&1')
for line in f:lines() do
local type,id,user = line:match '(%S+)%s+(%S+)%s+(%S+)'
if user == me then
line = line:match '(%S+)$'
append(results,line)
end
end
f:close()
return results
end
-- are we sudo?
if not WINDOWS then
local f = io.popen 'id -u'
local res = f:read()
f:close()
SUDO = res == '0'
end
local bindir
function which(prog)
if not prog:match '%.exe$' then prog = prog..'.exe' end
for dir in opath:gmatch '[^;]+' do
local file = exists(dir..DIRSEP..prog)
if file then return file end
end
end
-- if we are God, then use /usr/local/bin; otherwise try to see if $HOME/bin
-- is on the path and actually exists.
-- For Windows, use the Lua binary directory for scripts.
function check_bin_dir()
if bindir then return bindir end
if WINDOWS then
if not isabs(LUA) then
LUA = which (LUA)
end
bindir = LUA:match '(.+)\\'
else
if SUDO then
bindir = '/usr/local/bin'
else -- let's go for a hunt
bindir = os.getenv 'HOME'..'/bin'
local paths = user_writeable(opath:gsub(':',' '))
if not contains(paths,bindir) then
quit("sorry cannot install binary without superuser permissions")
end
end
end
return bindir
end
function contains(ls,value)
for _, v in ipairs(ls) do
if v == value then return true end
end
return false
end
-- On Unix, the idea here is to find a Lua module path that is user writeable.
-- find absolute Lua module paths
function find_lua_path(package_path)
local paths, append = {}, table.insert
for p in package_path:gmatch('[^;]+') do
if isabs(p) then
-- get the path with trailiing slash and nothing afterwards
append(paths, p:match ('[^?]+'))
end
end
if not WINDOWS then
paths = user_writeable(table.concat(paths,' '))
if #paths == 0 then
quit("sorry cannot install Lua module without superuser permissions")
end
end
return paths[1]
end
local lpath,cpath
function lua_lpath()
if lpath then return lpath end
lpath = find_lua_path(package.path)
return lpath
end
function lua_cpath()
if cpath then return cpath end
cpath = find_lua_path(package.cpath)
return cpath
end
LUA = arg[-1]
install()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.