X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=tools%2Finstall.lua;fp=tools%2Finstall.lua;h=89f60cda5defa5e30a8c514a712c03f0914c94f5;hp=0000000000000000000000000000000000000000;hb=eceb970628068ae621ef9523a669a2b66a82fd8a;hpb=1aae4e16c9b4881aad76caf5b4781c7dda29dd24 diff --git a/tools/install.lua b/tools/install.lua new file mode 100755 index 0000000..89f60cd --- /dev/null +++ b/tools/install.lua @@ -0,0 +1,109 @@ +#!/usr/bin/env lua + +-- +-- Yoink +-- This script is a predictable alternative to the system install program. +-- + +function show_help() + print([[ + +Install files, optionally changing the mode of the installed files. +Usage: + install.lua [-m MODE] SOURCE... DEST + +If DEST is a directory, the source(s) will be copied into DEST with their +same names. +]]) +end + + +-- Get the next argument passed to the script. +function shift() + var = arg[1] + table.remove(arg, 1) + return var +end + +-- Execute a command and return its output or nil if the command failed to +-- run. +function backtick_run(command) + local fd = io.popen(command.." 2>/dev/null") + if fd then local stdout = fd:read("*l") fd:close() return stdout end + return nil +end + +-- Return true if a filespec is a directory, false otherwise. +function is_directory(path) + return os.execute(string.format("test -d %q", path)) == 0 +end + +-- Get the basename of a path. +function basename(path, ext) + if not ext then ext = "" end + return backtick_run(string.format("basename %q %s", path, ext)) +end + +-- Get the directory part of a path. +function dirname(path) + if path:sub(-1) == "/" then path = path .. "." end + return backtick_run(string.format("dirname %q", path)) +end + +-- Like mkdir -p except portable. +function mkdir(path) + if path:sub(1,1) ~= "/" then path = os.getenv("PWD") .. "/" .. path end + path = path:gsub("/$", "") + path = path:gsub("/+", "/") + path = path:gsub("/[^/]+/%.%.", "") + path = path:gsub("%./", "") + path = path:gsub("/%.", "") + + local compound = "" + for component in path:gmatch("(/[^/]*)") do + compound = compound .. component + if not is_directory(compound) then + local result = os.execute(string.format("mkdir %q", compound)) + if result ~= 0 then os.exit(1) end + end + end +end + +-- Change the mode of a file or directory. +function chmod(mode, filespec) + if not mode or mode == "" then return end + local result = os.execute(string.format("chmod %s %q", mode, filespec)) + if result ~= 0 then os.exit(1) end +end + +-- Install a file. If destination is a directory, the source will be +-- installed into the directory with the same name. +function install(mode, source, dest) + if is_directory(dest) then dest = dest .. "/" .. basename(source) end + local result = os.execute(string.format("cp %q %q", source, dest)) + if result == 0 then chmod(mode, dest) else os.exit(1) end +end + + +files = {} + +-- Consume and parse each argument. +while 0 < #arg do + local v = shift() + if v == "-h" or v == "--help" then show_help() os.exit(0) end + if v == "-m" then mode = shift() else table.insert(files, v) end +end + +-- Check the arguments and determine the target. +if #files < 2 then show_help() os.exit(1) +else target = table.remove(files) end + +-- Perform the installation. +if 1 < #files then + mkdir(target) + for i,file in ipairs(files) do install(mode, file, target) end +else + mkdir(dirname(target)) + install(mode, files[1], target) +end +