]> Dogcows Code - chaz/yoink/blob - tools/install.lua
further implementing runloop support
[chaz/yoink] / tools / install.lua
1 #!/usr/bin/env lua
2
3 --
4 -- Yoink
5 -- This script is a predictable alternative to the system install program.
6 --
7
8 function show_help()
9 print([[
10
11 Install files, optionally changing the mode of the installed files.
12 Usage:
13 install.lua [-m MODE] SOURCE... DEST
14
15 If DEST is a directory, the source(s) will be copied into DEST with their
16 same names.
17 ]])
18 end
19
20
21 -- Get the next argument passed to the script.
22 function shift()
23 var = arg[1]
24 table.remove(arg, 1)
25 return var
26 end
27
28 -- Execute a command and return its output or nil if the command failed to
29 -- run.
30 function backtick_run(command)
31 local fd = io.popen(command.." 2>/dev/null")
32 if fd then local stdout = fd:read("*l") fd:close() return stdout end
33 return nil
34 end
35
36 -- Return true if a filespec is a directory, false otherwise.
37 function is_directory(path)
38 return os.execute(string.format("test -d %q", path)) == 0
39 end
40
41 -- Get the basename of a path.
42 function basename(path, ext)
43 if not ext then ext = "" end
44 return backtick_run(string.format("basename %q %s", path, ext))
45 end
46
47 -- Get the directory part of a path.
48 function dirname(path)
49 if path:sub(-1) == "/" then path = path .. "." end
50 return backtick_run(string.format("dirname %q", path))
51 end
52
53 -- Like mkdir -p except portable.
54 function mkdir(path)
55 if path:sub(1,1) ~= "/" then path = os.getenv("PWD") .. "/" .. path end
56 path = path:gsub("/$", "")
57 path = path:gsub("/+", "/")
58 path = path:gsub("/[^/]+/%.%.", "")
59 path = path:gsub("%./", "")
60 path = path:gsub("/%.", "")
61
62 local compound = ""
63 for component in path:gmatch("(/[^/]*)") do
64 compound = compound .. component
65 if not is_directory(compound) then
66 local result = os.execute(string.format("mkdir %q", compound))
67 if result ~= 0 then os.exit(1) end
68 end
69 end
70 end
71
72 -- Change the mode of a file or directory.
73 function chmod(mode, filespec)
74 if not mode or mode == "" then return end
75 local result = os.execute(string.format("chmod %s %q", mode, filespec))
76 if result ~= 0 then os.exit(1) end
77 end
78
79 -- Install a file. If destination is a directory, the source will be
80 -- installed into the directory with the same name.
81 function install(mode, source, dest)
82 if is_directory(dest) then dest = dest .. "/" .. basename(source) end
83 local result = os.execute(string.format("cp %q %q", source, dest))
84 if result == 0 then chmod(mode, dest) else os.exit(1) end
85 end
86
87
88 files = {}
89
90 -- Consume and parse each argument.
91 while 0 < #arg do
92 local v = shift()
93 if v == "-h" or v == "--help" then show_help() os.exit(0) end
94 if v == "-m" then mode = shift() else table.insert(files, v) end
95 end
96
97 -- Check the arguments and determine the target.
98 if #files < 2 then show_help() os.exit(1)
99 else target = table.remove(files) end
100
101 -- Perform the installation.
102 if 1 < #files then
103 mkdir(target)
104 for i,file in ipairs(files) do install(mode, file, target) end
105 else
106 mkdir(dirname(target))
107 install(mode, files[1], target)
108 end
109
This page took 0.033276 seconds and 4 git commands to generate.