xref: /freebsd/release/scripts/pkgbase-stage.lua (revision 62d18f8c4c10a5e680b0b795040abffc7964977e)
1*62d18f8cSIsaac Freund#!/usr/libexec/flua
2*62d18f8cSIsaac Freund
3*62d18f8cSIsaac Freund-- SPDX-License-Identifier: BSD-2-Clause
4*62d18f8cSIsaac Freund--
5*62d18f8cSIsaac Freund-- Copyright(c) 2025 The FreeBSD Foundation.
6*62d18f8cSIsaac Freund--
7*62d18f8cSIsaac Freund-- This software was developed by Isaac Freund <ifreund@freebsdfoundation.org>
8*62d18f8cSIsaac Freund-- under sponsorship from the FreeBSD Foundation.
9*62d18f8cSIsaac Freund
10*62d18f8cSIsaac Freund-- Run a command using the OS shell and capture the stdout
11*62d18f8cSIsaac Freund-- Strips exactly one trailing newline if present, does not strip any other whitespace.
12*62d18f8cSIsaac Freund-- Asserts that the command exits cleanly
13*62d18f8cSIsaac Freundlocal function capture(command)
14*62d18f8cSIsaac Freund	local p = io.popen(command)
15*62d18f8cSIsaac Freund	local output = p:read("*a")
16*62d18f8cSIsaac Freund	assert(p:close())
17*62d18f8cSIsaac Freund	-- Strip exactly one trailing newline from the output, if there is one
18*62d18f8cSIsaac Freund	return output:match("(.-)\n$") or output
19*62d18f8cSIsaac Freundend
20*62d18f8cSIsaac Freund
21*62d18f8cSIsaac Freundlocal function append_list(list, other)
22*62d18f8cSIsaac Freund	for _, item in ipairs(other) do
23*62d18f8cSIsaac Freund		table.insert(list, item)
24*62d18f8cSIsaac Freund	end
25*62d18f8cSIsaac Freundend
26*62d18f8cSIsaac Freund
27*62d18f8cSIsaac Freund-- Returns a list of packages to be included in the given media
28*62d18f8cSIsaac Freundlocal function select_packages(pkg, media, all_libcompats)
29*62d18f8cSIsaac Freund	local components = {
30*62d18f8cSIsaac Freund		kernel = {},
31*62d18f8cSIsaac Freund		kernel_dbg = {},
32*62d18f8cSIsaac Freund		base = {},
33*62d18f8cSIsaac Freund		base_dbg = {},
34*62d18f8cSIsaac Freund		src = {},
35*62d18f8cSIsaac Freund		tests = {},
36*62d18f8cSIsaac Freund	}
37*62d18f8cSIsaac Freund
38*62d18f8cSIsaac Freund	for compat in all_libcompats:gmatch("%S+") do
39*62d18f8cSIsaac Freund		components["lib" .. compat] = {}
40*62d18f8cSIsaac Freund		components["lib" .. compat .. "_dbg"] = {}
41*62d18f8cSIsaac Freund	end
42*62d18f8cSIsaac Freund
43*62d18f8cSIsaac Freund	local rquery = capture(pkg .. "rquery -U -r FreeBSD-base %n")
44*62d18f8cSIsaac Freund	for package in rquery:gmatch("[^\n]+") do
45*62d18f8cSIsaac Freund		if package == "FreeBSD-src" or package:match("^FreeBSD%-src%-.*") then
46*62d18f8cSIsaac Freund			table.insert(components["src"], package)
47*62d18f8cSIsaac Freund		elseif package == "FreeBSD-tests" or package:match("^FreeBSD%-tests%-.*") then
48*62d18f8cSIsaac Freund			table.insert(components["tests"], package)
49*62d18f8cSIsaac Freund		elseif package:match("^FreeBSD%-kernel%-.*") then
50*62d18f8cSIsaac Freund			-- Kernels other than FreeBSD-kernel-generic are ignored
51*62d18f8cSIsaac Freund			if package == "FreeBSD-kernel-generic" then
52*62d18f8cSIsaac Freund				table.insert(components["kernel"], package)
53*62d18f8cSIsaac Freund			elseif package == "FreeBSD-kernel-generic-dbg" then
54*62d18f8cSIsaac Freund				table.insert(components["kernel_dbg"], package)
55*62d18f8cSIsaac Freund			end
56*62d18f8cSIsaac Freund		elseif package:match(".*%-dbg$") then
57*62d18f8cSIsaac Freund			table.insert(components["base_dbg"], package)
58*62d18f8cSIsaac Freund		else
59*62d18f8cSIsaac Freund			local found = false
60*62d18f8cSIsaac Freund			for compat in all_libcompats:gmatch("%S+") do
61*62d18f8cSIsaac Freund				if package:match(".*%-dbg%-lib" .. compat .. "$") then
62*62d18f8cSIsaac Freund					table.insert(components["lib" .. compat .. "_dbg"], package)
63*62d18f8cSIsaac Freund					found = true
64*62d18f8cSIsaac Freund					break
65*62d18f8cSIsaac Freund				elseif package:match(".*%-lib" .. compat .. "$") then
66*62d18f8cSIsaac Freund					table.insert(components["lib" .. compat], package)
67*62d18f8cSIsaac Freund					found = true
68*62d18f8cSIsaac Freund					break
69*62d18f8cSIsaac Freund				end
70*62d18f8cSIsaac Freund			end
71*62d18f8cSIsaac Freund			if not found then
72*62d18f8cSIsaac Freund				table.insert(components["base"], package)
73*62d18f8cSIsaac Freund			end
74*62d18f8cSIsaac Freund		end
75*62d18f8cSIsaac Freund	end
76*62d18f8cSIsaac Freund	assert(#components["kernel"] == 1)
77*62d18f8cSIsaac Freund	assert(#components["base"] > 0)
78*62d18f8cSIsaac Freund
79*62d18f8cSIsaac Freund	local selected = {}
80*62d18f8cSIsaac Freund	if media == "disc" then
81*62d18f8cSIsaac Freund		append_list(selected, components["base"])
82*62d18f8cSIsaac Freund		append_list(selected, components["kernel"])
83*62d18f8cSIsaac Freund		append_list(selected, components["kernel_dbg"])
84*62d18f8cSIsaac Freund		append_list(selected, components["src"])
85*62d18f8cSIsaac Freund		append_list(selected, components["tests"])
86*62d18f8cSIsaac Freund		for compat in all_libcompats:gmatch("%S+") do
87*62d18f8cSIsaac Freund			append_list(selected, components["lib" .. compat])
88*62d18f8cSIsaac Freund		end
89*62d18f8cSIsaac Freund	else
90*62d18f8cSIsaac Freund		assert(media == "dvd")
91*62d18f8cSIsaac Freund		append_list(selected, components["base"])
92*62d18f8cSIsaac Freund		append_list(selected, components["base_dbg"])
93*62d18f8cSIsaac Freund		append_list(selected, components["kernel"])
94*62d18f8cSIsaac Freund		append_list(selected, components["kernel_dbg"])
95*62d18f8cSIsaac Freund		append_list(selected, components["src"])
96*62d18f8cSIsaac Freund		append_list(selected, components["tests"])
97*62d18f8cSIsaac Freund		for compat in all_libcompats:gmatch("%S+") do
98*62d18f8cSIsaac Freund			append_list(selected, components["lib" .. compat])
99*62d18f8cSIsaac Freund			append_list(selected, components["lib" .. compat .. "_dbg"])
100*62d18f8cSIsaac Freund		end
101*62d18f8cSIsaac Freund	end
102*62d18f8cSIsaac Freund
103*62d18f8cSIsaac Freund	return selected
104*62d18f8cSIsaac Freundend
105*62d18f8cSIsaac Freund
106*62d18f8cSIsaac Freundlocal function main()
107*62d18f8cSIsaac Freund	-- Determines package subset selected
108*62d18f8cSIsaac Freund	local media = assert(arg[1])
109*62d18f8cSIsaac Freund	assert(media == "disc" or media == "dvd")
110*62d18f8cSIsaac Freund	-- Local repository to fetch from
111*62d18f8cSIsaac Freund	local source = assert(arg[2])
112*62d18f8cSIsaac Freund	-- Directory to create new repository
113*62d18f8cSIsaac Freund	local target = assert(arg[3])
114*62d18f8cSIsaac Freund	-- =hitespace separated list of all libcompat names (e.g. "32")
115*62d18f8cSIsaac Freund	local all_libcompats = assert(arg[4])
116*62d18f8cSIsaac Freund
117*62d18f8cSIsaac Freund	assert(os.execute("mkdir -p pkgbase-repo-conf"))
118*62d18f8cSIsaac Freund	local f <close> = assert(io.open("pkgbase-repo-conf/FreeBSD-base.conf", "w"))
119*62d18f8cSIsaac Freund	assert(f:write(string.format([[
120*62d18f8cSIsaac Freund	FreeBSD-base: {
121*62d18f8cSIsaac Freund	  url: "file://%s",
122*62d18f8cSIsaac Freund	  enabled: yes
123*62d18f8cSIsaac Freund	}
124*62d18f8cSIsaac Freund	]], source)))
125*62d18f8cSIsaac Freund	assert(f:close())
126*62d18f8cSIsaac Freund
127*62d18f8cSIsaac Freund	local pkg = "pkg -o ASSUME_ALWAYS_YES=yes -o IGNORE_OSVERSION=yes " ..
128*62d18f8cSIsaac Freund	    "-o INSTALL_AS_USER=1 -o PKG_DBDIR=./pkgdb -R ./pkgbase-repo-conf "
129*62d18f8cSIsaac Freund
130*62d18f8cSIsaac Freund	assert(os.execute(pkg .. "update"))
131*62d18f8cSIsaac Freund
132*62d18f8cSIsaac Freund	local packages = select_packages(pkg, media, all_libcompats)
133*62d18f8cSIsaac Freund
134*62d18f8cSIsaac Freund	assert(os.execute(pkg .. "fetch -o " .. target .. " " .. table.concat(packages, " ")))
135*62d18f8cSIsaac Freund	assert(os.execute(pkg .. "repo " .. target))
136*62d18f8cSIsaac Freundend
137*62d18f8cSIsaac Freund
138*62d18f8cSIsaac Freundmain()
139