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