]> Dogcows Code - chaz/yoink/blobdiff - tools/install.lua
improved build tools
[chaz/yoink] / tools / install.lua
diff --git a/tools/install.lua b/tools/install.lua
new file mode 100755 (executable)
index 0000000..89f60cd
--- /dev/null
@@ -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
+
This page took 0.024335 seconds and 4 git commands to generate.