xref: /freebsd/release/packages/generate-set-ucl.lua (revision c8f9a9abd8000a8514e0beee99ffcf48d05ce47b)
1#!/usr/libexec/flua
2--
3-- Copyright (c) 2024-2025 Baptiste Daroussin <bapt@FreeBSD.org>
4-- Copyright (c) 2025 Lexi Winter <ivy@FreeBSD.org>
5--
6-- SPDX-License-Identifier: BSD-2-Clause
7--
8
9--[[ usage:
10generate-set-ucl.lua <template> [<variablename> <variablevalue>]
11
12Generate the UCL for a set metapackage.  The variables provided will be
13substituted as UCL variables.
14]]--
15
16local ucl = require("ucl")
17
18-- This parser is the output UCL we want to build.
19local parser = ucl.parser()
20
21if #arg < 1 then
22	io.stderr:write(arg[0] .. ": missing template filename\n")
23	os.exit(1)
24end
25
26local template = table.remove(arg, 1)
27
28-- Set any $VARIABLES from the command line in the parser.  This causes ucl to
29-- automatically replace them when we load the source ucl.
30if #arg % 2 ~= 0 then
31	io.stderr:write(arg[0] .. ": expected an even number of arguments, "
32	    .. "got " .. #arg .. "\n")
33	os.exit(1)
34end
35
36local pkgprefix = nil
37local pkgversion = nil
38local pkgdeps = ""
39
40for i = 2, #arg, 2 do
41	local varname = arg[i - 1]
42	local varvalue = arg[i]
43
44	if varname == "PKG_NAME_PREFIX" and #varvalue > 0 then
45		pkgprefix = varvalue
46	elseif varname == "VERSION" and #varvalue > 0 then
47		pkgversion = varvalue
48	elseif varname == "SET_DEPENDS" and #varvalue > 0 then
49		pkgdeps = varvalue
50	end
51
52	parser:register_variable(varname, varvalue)
53end
54
55-- Load the source template.
56local res,err = parser:parse_file(template)
57if not res then
58	io.stderr:write(arg[0] .. ": fail to parse(" .. template .. "): "
59	    .. err .. "\n")
60	os.exit(1)
61end
62
63local obj = parser:get_object()
64
65-- Dependency handling.
66obj["deps"] = obj["deps"] or {}
67
68-- If PKG_NAME_PREFIX is provided, rewrite the names of dependency packages.
69-- We can't do this in UCL since variable substitution doesn't work in array
70-- keys.  Note that this only applies to dependencies from the set UCL files,
71-- because SET_DEPENDS already have the correct prefix.
72if pkgprefix ~= nil then
73	newdeps = {}
74	for dep, opts in pairs(obj["deps"]) do
75		local newdep = pkgprefix .. "-" .. dep
76		newdeps[newdep] = opts
77	end
78	obj["deps"] = newdeps
79end
80
81-- Add dependencies from SET_DEPENDS.
82for dep in string.gmatch(pkgdeps, "[^%s]+") do
83	obj["deps"][dep] = {
84		["origin"] = "base/"..dep
85	}
86end
87
88-- Add a version and origin key to all dependencies, otherwise pkg
89-- doesn't like it.
90for dep, opts in pairs(obj["deps"]) do
91	obj["deps"][dep]["origin"] = obj["deps"][dep]["origin"] or "base/"..dep
92	obj["deps"][dep]["version"] = obj["deps"][dep]["version"] or pkgversion
93end
94
95-- If there are no dependencies, remove the deps key, otherwise pkg raises an
96-- error trying to read the manifest.
97if next(obj["deps"]) == nil then
98	obj["deps"] = nil
99end
100
101-- Write the output.
102io.stdout:write(ucl.to_format(obj, 'ucl', true))
103