Harbor

branch main
showing the latest snapshot on main
process.lua 2.8 KB · Lua
gpu/tools/lua/process.lua 0644 Raw
local path = require("tools.lua.path")

local process = {}

local function parse_elapsed_seconds(s)
	if not s then return nil end
	local parts = {}
	for part in tostring(s):gmatch("[^:]+") do
		parts[#parts + 1] = tonumber(part)
	end
	if #parts == 3 then
		return parts[1] * 3600 + parts[2] * 60 + parts[3]
	elseif #parts == 2 then
		return parts[1] * 60 + parts[2]
	elseif #parts == 1 then
		return parts[1]
	end
	return nil
end

local function normalize_status(a, b, c)
	if type(a) == "boolean" then
		return a and 0 or (c or 1)
	end
	if type(a) == "number" then
		if a == 0 then return 0 end
		return a
	end
	return 1
end

function process.capture(cmd)
	local f = assert(io.popen(cmd))
	local out = f:read("*a")
	local a, b, c = f:close()
	return out, normalize_status(a, b, c)
end

function process.run(cmd)
	local a, b, c = os.execute(cmd)
	return normalize_status(a, b, c)
end

function process.with_cwd(root, cmd)
	if path.is_windows then
		return "cd /d " .. path.shell_quote(root) .. " && " .. cmd
	end
	return "cd " .. path.shell_quote(root) .. " && " .. cmd
end

function process.env_prefix(env)
	local keys = {}
	for k, _ in pairs(env or {}) do keys[#keys + 1] = k end
	table.sort(keys)
	if #keys == 0 then return "" end

	if path.is_windows then
		local parts = {}
		for _, k in ipairs(keys) do
			parts[#parts + 1] = "set " .. k .. "=" .. tostring(env[k]) .. "&&"
		end
		return table.concat(parts, " ") .. " "
	end

	local parts = {}
	for _, k in ipairs(keys) do
		parts[#parts + 1] = k .. "=" .. path.shell_quote(env[k])
	end
	return table.concat(parts, " ") .. " "
end

function process.command_exists(name)
	local cmd
	if path.is_windows then
		cmd = "where " .. path.shell_quote(name) .. " >NUL 2>NUL"
	else
		cmd = "command -v " .. path.shell_quote(name) .. " >/dev/null 2>&1"
	end
	return process.run(cmd) == 0
end

function process.uname()
	if path.is_windows then return "Windows" end
	local out = process.capture("uname -s 2>/dev/null")
	return (out or ""):match("([^\r\n]+)") or "Unix"
end

function process.read_time_v(pathname)
	if not pathname or not path.exists(pathname) then return {} end
	local text = path.read_file(pathname)
	local out = {}
	out.user_seconds = tonumber(text:match("User time %(seconds%):%s*([%d%.]+)"))
	out.system_seconds = tonumber(text:match("System time %(seconds%):%s*([%d%.]+)"))
	out.max_rss_kib = tonumber(text:match("Maximum resident set size %(kbytes%):%s*(%d+)"))
	out.elapsed = text:match("Elapsed %(wall clock%) time.-%):%s*([^\n]+)")
	out.elapsed_seconds = parse_elapsed_seconds(out.elapsed)
	if not out.max_rss_kib then
		local rss_bytes = tonumber(text:match("maximum resident set size:%s*(%d+)"))
		if rss_bytes then
			out.max_rss_kib = math.floor(rss_bytes / 1024)
		end
	end
	return out
end

process.parse_elapsed_seconds = parse_elapsed_seconds

return process