This repository has been archived by the owner on Feb 16, 2020. It is now read-only.
/
exec.lua
111 lines (93 loc) · 3.01 KB
/
exec.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
local obj = {}
obj.__index = obj
local NOOP = function () end
function obj.new(spoon)
local self = { spoon = spoon, log = spoon.log }
setmetatable(self, obj)
return self
end
local function quote(str)
str = string.gsub(str, [[%\]], [[\\]])
str = string.gsub(str, [[%"]], [[\"]])
return '"' .. str .. '"'
end
local function rstrip(str)
return string.gsub(output, "[%\r%\n]+$", "")
end
local function join(list)
return table.concat(list, " ")
end
local function append(dest, src)
return table.move(src, 1, #src, #dest + 1, dest)
end
local function makeTempFile()
local output, success = hs.execute("mktemp")
if not success then
error("mktemp failed: " .. output)
end
return string.gsub(output, "[%\r%\n]+$", "")
end
local function tailFile(path, onOutput)
local args = { "-c", "tail -f " .. path }
local task = hs.task.new("/bin/sh", NOOP, onOutput, args)
task:start()
return task
end
local function buildResticEnv(self)
local env = {
RESTIC_REPOSITORY = self.spoon:getRepository(),
RESTIC_PASSWORD = self.spoon:getPassword(),
}
for key, val in pairs(self.spoon:getEnvironment()) do
env[key] = val
end
if env.RESTIC_REPOSITORY:sub(1, 3) == "s3:" and not env.AWS_ACCESS_KEY_ID then
error("Must call :setS3Credentials() first")
end
return env
end
function obj:newTask(shell, onComplete, asAdmin)
local setCommand = [[set cmd to ]] .. quote(join(shell))
local doShellScript = [[do shell script "sh -c " & quoted form of cmd]]
if asAdmin then
doShellScript = doShellScript .. [[ with administrator privileges]]
end
local args = { "-e", setCommand, "-e", doShellScript }
return hs.task.new("/usr/bin/osascript", onComplete, args)
end
function obj:newLongTask(shell, onComplete, onOutput, asAdmin)
local pidFile = makeTempFile()
local outputFile = makeTempFile()
local tailOutput = tailFile(outputFile, onOutput)
local task
shell = append({
"{ sleep 10; while cat", pidFile, "| xargs kill -INFO; do sleep 10; done } & :;",
"echo $$ >", pidFile, ";",
"exec 1>", outputFile, ";",
"exec",
}, shell)
task = self:newTask(shell, function (...)
tailOutput:terminate()
os.remove(pidFile)
return onComplete(...)
end, asAdmin)
local terminate = function ()
local shell = { "cat", pidFile, "| xargs kill" }
local task = self:newTask(shell, NOOP, asAdmin)
task:start()
end
return task, terminate, outputFile
end
function obj:newResticTask(args, onComplete, onOutput, asAdmin)
local restic = self.spoon:getResticPath()
local shell = append({ restic }, args)
local task, terminate, outputFile
if onOutput then
task, terminate, outputFile = self:newLongTask(shell, onComplete, onOutput, asAdmin)
else
task = self:newTask(shell, onComplete, asAdmin)
end
task:setEnvironment(buildResticEnv(self))
return task, terminate, outputFile
end
return obj