summaryrefslogtreecommitdiff
path: root/scripts/context/lua/mtx-watch.lua
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2007-12-05 13:56:00 +0100
committerHans Hagen <pragma@wxs.nl>2007-12-05 13:56:00 +0100
commit6312e2b2913bc7de6f3c0ba30b993e2b4714edf1 (patch)
treee0e90382ddb930a0b4f534824892235b343dcdc4 /scripts/context/lua/mtx-watch.lua
parent19af23ac5cb927d986a64ac1dc52ed2d7bad2450 (diff)
downloadcontext-6312e2b2913bc7de6f3c0ba30b993e2b4714edf1.tar.gz
stable 2007.12.05 13:56
Diffstat (limited to 'scripts/context/lua/mtx-watch.lua')
-rw-r--r--scripts/context/lua/mtx-watch.lua224
1 files changed, 224 insertions, 0 deletions
diff --git a/scripts/context/lua/mtx-watch.lua b/scripts/context/lua/mtx-watch.lua
new file mode 100644
index 000000000..651865ab4
--- /dev/null
+++ b/scripts/context/lua/mtx-watch.lua
@@ -0,0 +1,224 @@
+if not modules then modules = { } end modules ['mtx-watch'] = {
+ version = 1.001,
+ comment = "companion to mtxrun.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+texmf.instance = instance -- we need to get rid of this / maybe current instance in global table
+
+scripts = scripts or { }
+scripts.watch = scripts.watch or { }
+
+function scripts.watch.watch()
+ local delay = environment.argument("delay") or 5
+ local logpath = environment.argument("logpath") or ""
+ local pipe = environment.argument("pipe") or false
+ if #environment.files > 0 then
+ for _, path in ipairs(environment.files) do
+ logs.report("watch", "watching path ".. path)
+ end
+ local function glob(files,path)
+ for name in lfs.dir(path) do
+ if name:find("^%.") then
+ -- skip . and ..
+ else
+ name = path .. "/" .. name
+ local a = lfs.attributes(name)
+ if not a then
+ -- weird
+ elseif a.mode == "directory" then
+ if name:find("graphics$") or name:find("figures$") or name:find("resources$") then
+ -- skip these too
+ else
+ glob(files,name)
+ end
+ elseif name:find(".%luj$") then
+ files[name] = a.change or a.ctime or a.modification or a.mtime
+ end
+ end
+ end
+ end
+ local n = 0
+ local function process()
+ local done = false
+ for _, path in ipairs(environment.files) do
+ lfs.chdir(path)
+ local files = { }
+ glob(files,path)
+ table.sort(files) -- what gets sorted here
+ for name, time in pairs(files) do
+ --~ local ok, joblog = xpcall(function() return dofile(name) end, function() end )
+ local ok, joblog = pcall(dofile,name)
+ if ok and joblog then
+ if joblog.status == "processing" then
+ logs.report("watch",string.format("aborted job, %s added to queue",name))
+ joblog.status = "queued"
+ io.savedata(name, table.serialize(joblog,true))
+ elseif joblog.status == "queued" then
+ local command = joblog.command
+ if command then
+ local replacements = {
+ inputpath = (joblog.paths and joblog.paths.input ) or ".",
+ outputpath = (joblog.paths and joblog.paths.output) or ".",
+ filename = joblog.filename or "",
+ }
+ command = command:gsub("%%(.-)%%", replacements)
+ if command ~= "" then
+ joblog.status = "processing"
+ joblog.runtime = os.time() -- os.clock()
+ io.savedata(name, table.serialize(joblog,true))
+ logs.report("watch",string.format("running: %s", command))
+ local newpath = file.dirname(name)
+ io.flush()
+ local result = ""
+ if newpath ~= "" and newpath ~= "." then
+ local oldpath = lfs.currentdir()
+ lfs.chdir(newpath)
+ if pipe then result = os.resultof(command) else result = os.execute(command) end
+ lfs.chdir(oldpath)
+ else
+ if pipe then result = os.resultof(command) else result = os.execute(command) end
+ end
+ logs.report("watch",string.format("return value: %s", result))
+ done = true
+ local path, base = replacements.outputpath, file.basename(replacements.filename)
+ joblog.runtime = os.time() - joblog.runtime -- os.clock() - joblog.runtime
+ joblog.result = file.replacesuffix(file.join(path,base),"pdf")
+ joblog.size = lfs.attributes(joblog.result,"size")
+ joblog.status = "finished"
+ else
+ joblog.status = "invalid command"
+ end
+ else
+ joblog.status = "no command"
+ end
+ -- pcall, when error sleep + again
+ io.savedata(name, table.serialize(joblog,true))
+ if logpath ~= "" then
+ local name = string.format("%s/%s%04i%09i.lua", logpath, os.time(), math.floor((os.clock()*100)%1000), math.random(99999999))
+ io.savedata(name, table.serialize(joblog,true))
+ logs.report("watch", "saving joblog ".. name)
+ end
+ end
+ end
+ end
+ end
+ end
+ local function wait()
+ io.flush()
+ if not done then
+ n = n + 1
+ if n >= 10 then
+ logs.report("watch", "still sleeping " .. os.clock())
+ n = 0
+ end
+ os.sleep(delay)
+ end
+ end
+ while true do
+ pcall(process)
+ pcall(wait)
+ end
+ else
+ logs.report("watch", "no paths to watch")
+ end
+end
+
+function scripts.watch.collect_logs(path) -- clean 'm up too
+ path = path or environment.argument("logpath") or ""
+ path = (path == "" and ".") or path
+ local files = dir.globfiles(path,false,"^%d+%.lua$")
+ local collection = { }
+ local valid = table.tohash({"filename","result","runtime","size","status"})
+ for _, name in ipairs(files) do
+ local t = dofile(name)
+ if t and type(t) == "table" and t.status then
+ for k, v in pairs(t) do
+ if not valid[k] then
+ t[k] = nil
+ end
+ end
+ collection[name:gsub("[^%d]","")] = t
+ end
+ end
+ return collection
+end
+
+function scripts.watch.save_logs(collection,path) -- play safe
+ if collection and not table.is_empty(collection) then
+ path = path or environment.argument("logpath") or ""
+ path = (path == "" and ".") or path
+ local filename = string.format("%s/collected-%s.lua",path,tostring(os.time()))
+ io.savedata(filename,table.serialize(collection,true))
+ local check = dofile(filename)
+ for k,v in pairs(check) do
+ if not collection[k] then
+ logs.error("watch", "error in saving file")
+ os.remove(filename)
+ return false
+ end
+ end
+ for k,v in pairs(check) do
+ os.remove(string.format("%s.lua",k))
+ end
+ return true
+ else
+ return false
+ end
+end
+
+function scripts.watch.collect_collections(path) -- removes duplicates
+ path = path or environment.argument("logpath") or ""
+ path = (path == "" and ".") or path
+ local files = dir.globfiles(path,false,"^collected%-%d+%.lua$")
+ local collection = { }
+ for _, name in ipairs(files) do
+ local t = dofile(name)
+ if t and type(t) == "table" then
+ for k, v in pairs(t) do
+ collection[k] = v
+ end
+ end
+ end
+ return collection
+end
+
+function scripts.watch.show_logs(path) -- removes duplicates
+ local collection = scripts.watch.collect_collections(path) or { }
+ local max = 0
+ for k,v in pairs(collection) do
+ v = v.filename or "?"
+ if #v > max then max = #v end
+ end
+ print(max)
+ for k,v in ipairs(table.sortedkeys(collection)) do
+ local c = collection[v]
+ local f, s, r, n = c.filename or "?", c.status or "?", c.runtime or 0, c.size or 0
+ logs.report("watch", string.format("%s %s %3i %8i %s",string.padd(f,max," "),string.padd(s,10," "),r,n,v))
+ end
+end
+
+banner = banner .. " | watchdog"
+
+messages.help = [[
+--logpath optional path for log files
+--watch watch given path
+--pipe use pipe instead of execute
+--delay delay between sweeps
+--collect condense log files
+--showlog show log data
+]]
+
+input.verbose = true
+
+if environment.argument("watch") then
+ scripts.watch.watch()
+elseif environment.argument("collect") then
+ scripts.watch.save_logs(scripts.watch.collect_logs())
+elseif environment.argument("showlog") then
+ scripts.watch.show_logs()
+else
+ input.help(banner,messages.help)
+end