config.lua

  1-- SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  2--
  3-- SPDX-License-Identifier: GPL-3.0-or-later
  4
  5---@class wt.config
  6local M = {}
  7
  8---Substitute ${project} in template string
  9---@param template string
 10---@param project_name string
 11---@return string
 12function M.resolve_url_template(template, project_name)
 13	local escaped = project_name:gsub("%%", "%%%%")
 14	return (template:gsub("%${project}", escaped))
 15end
 16
 17---Parse git URLs to extract project name
 18---@param url string
 19---@return string|nil
 20function M.extract_project_name(url)
 21	if not url or url == "" then
 22		return nil
 23	end
 24
 25	url = url:gsub("[?#].*$", "")
 26	url = url:gsub("/+$", "")
 27
 28	if url == "" or url == "/" then
 29		return nil
 30	end
 31
 32	url = url:gsub("%.git$", "")
 33
 34	if not url:match("://") then
 35		local scp_path = url:match("^[^@]+@[^:]+:(.+)$")
 36		if scp_path and scp_path ~= "" then
 37			url = scp_path
 38		end
 39	end
 40
 41	local name = url:match("([^/]+)$") or url:match("([^:]+)$")
 42	if not name or name == "" then
 43		return nil
 44	end
 45	return name
 46end
 47
 48---Load global config from ~/.config/wt/config.lua
 49---@return table
 50function M.load_global_config()
 51	local home = os.getenv("HOME")
 52	if not home then
 53		return {}
 54	end
 55	local config_path = home .. "/.config/wt/config.lua"
 56	local f = io.open(config_path, "r")
 57	if not f then
 58		return {}
 59	end
 60	local content = f:read("*a")
 61	f:close()
 62	local chunk, err = load(content, config_path, "t", {})
 63	if not chunk then
 64		chunk, err = load("return " .. content, config_path, "t", {})
 65	end
 66	if not chunk then
 67		io.stderr:write("warning: config syntax error in " .. config_path .. ": " .. err .. "\n")
 68		return {}
 69	end
 70	local ok, result = pcall(chunk)
 71	if not ok then
 72		io.stderr:write("warning: config execution error in " .. config_path .. ": " .. result .. "\n")
 73		return {}
 74	end
 75	if type(result) ~= "table" then
 76		io.stderr:write("warning: config must return a table in " .. config_path .. "\n")
 77		return {}
 78	end
 79	return result
 80end
 81
 82---Load project config from <root>/.wt.lua
 83---@param root string
 84---@return {hooks?: {copy?: string[], symlink?: string[], run?: string[]}}
 85function M.load_project_config(root)
 86	local config_path = root .. "/.wt.lua"
 87	local f = io.open(config_path, "r")
 88	if not f then
 89		return {}
 90	end
 91	local content = f:read("*a")
 92	f:close()
 93
 94	local chunk, err = load(content, config_path, "t", {})
 95	if not chunk then
 96		chunk, err = load("return " .. content, config_path, "t", {})
 97	end
 98	if not chunk then
 99		io.stderr:write("warning: config syntax error in " .. config_path .. ": " .. err .. "\n")
100		return {}
101	end
102	local ok, result = pcall(chunk)
103	if not ok then
104		io.stderr:write("warning: config execution error in " .. config_path .. ": " .. result .. "\n")
105		return {}
106	end
107	if type(result) ~= "table" then
108		io.stderr:write("warning: config must return a table in " .. config_path .. "\n")
109		return {}
110	end
111	return result
112end
113
114return M