diff options
author | Hans Hagen <pragma@wxs.nl> | 2007-12-05 13:56:00 +0100 |
---|---|---|
committer | Hans Hagen <pragma@wxs.nl> | 2007-12-05 13:56:00 +0100 |
commit | 6312e2b2913bc7de6f3c0ba30b993e2b4714edf1 (patch) | |
tree | e0e90382ddb930a0b4f534824892235b343dcdc4 /scripts/context/lua/mtx-watch.lua | |
parent | 19af23ac5cb927d986a64ac1dc52ed2d7bad2450 (diff) | |
download | context-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.lua | 224 |
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 |