aboutsummaryrefslogtreecommitdiff
path: root/release/scripts/pkgbase-stage.lua
blob: 1b48b4faede36542e94bb61c51ede7d2588a4a2c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/libexec/flua

-- SPDX-License-Identifier: BSD-2-Clause
--
-- Copyright(c) 2025 The FreeBSD Foundation.
--
-- This software was developed by Isaac Freund <ifreund@freebsdfoundation.org>
-- under sponsorship from the FreeBSD Foundation.

-- Run a command using the OS shell and capture the stdout
-- Strips exactly one trailing newline if present, does not strip any other whitespace.
-- Asserts that the command exits cleanly
local function capture(command)
	local p = io.popen(command)
	local output = p:read("*a")
	assert(p:close())
	-- Strip exactly one trailing newline from the output, if there is one
	return output:match("(.-)\n$") or output
end

local function append_list(list, other)
	for _, item in ipairs(other) do
		table.insert(list, item)
	end
end

-- Returns a list of packages to be included in the given media
local function select_packages(pkg, media, all_libcompats)
	local components = {
		kernel = {},
		kernel_dbg = {},
		base = {},
		base_dbg = {},
		src = {},
		tests = {},
	}

	for compat in all_libcompats:gmatch("%S+") do
		components["lib" .. compat] = {}
		components["lib" .. compat .. "_dbg"] = {}
	end

	local rquery = capture(pkg .. "rquery -U -r FreeBSD-base %n")
	for package in rquery:gmatch("[^\n]+") do
		if package == "FreeBSD-src" or package:match("^FreeBSD%-src%-.*") then
			table.insert(components["src"], package)
		elseif package == "FreeBSD-tests" or package:match("^FreeBSD%-tests%-.*") then
			table.insert(components["tests"], package)
		elseif package:match("^FreeBSD%-kernel%-.*") and
			package ~= "FreeBSD-kernel-man"
		then
			-- Kernels other than FreeBSD-kernel-generic are ignored
			if package == "FreeBSD-kernel-generic" then
				table.insert(components["kernel"], package)
			elseif package == "FreeBSD-kernel-generic-dbg" then
				table.insert(components["kernel_dbg"], package)
			end
		elseif package:match(".*%-dbg$") then
			table.insert(components["base_dbg"], package)
		else
			local found = false
			for compat in all_libcompats:gmatch("%S+") do
				if package:match(".*%-dbg%-lib" .. compat .. "$") then
					table.insert(components["lib" .. compat .. "_dbg"], package)
					found = true
					break
				elseif package:match(".*%-lib" .. compat .. "$") then
					table.insert(components["lib" .. compat], package)
					found = true
					break
				end
			end
			if not found then
				table.insert(components["base"], package)
			end
		end
	end
	assert(#components["kernel"] == 1)
	assert(#components["base"] > 0)

	local selected = {}
	if media == "disc" then
		append_list(selected, components["base"])
		append_list(selected, components["kernel"])
		append_list(selected, components["kernel_dbg"])
		append_list(selected, components["src"])
		append_list(selected, components["tests"])
		for compat in all_libcompats:gmatch("%S+") do
			append_list(selected, components["lib" .. compat])
		end
	else
		assert(media == "dvd")
		append_list(selected, components["base"])
		append_list(selected, components["base_dbg"])
		append_list(selected, components["kernel"])
		append_list(selected, components["kernel_dbg"])
		append_list(selected, components["src"])
		append_list(selected, components["tests"])
		for compat in all_libcompats:gmatch("%S+") do
			append_list(selected, components["lib" .. compat])
			append_list(selected, components["lib" .. compat .. "_dbg"])
		end
	end

	return selected
end

local function main()
	-- Determines package subset selected
	local media = assert(arg[1])
	assert(media == "disc" or media == "dvd")
	-- Local repository to fetch from
	local source = assert(arg[2])
	-- Directory to create new repository
	local target = assert(arg[3])
	-- =hitespace separated list of all libcompat names (e.g. "32")
	local all_libcompats = assert(arg[4])

	assert(os.execute("mkdir -p pkgbase-repo-conf"))
	local f <close> = assert(io.open("pkgbase-repo-conf/FreeBSD-base.conf", "w"))
	assert(f:write(string.format([[
	FreeBSD-base: {
	  url: "file://%s",
	  enabled: yes
	}
	]], source)))
	assert(f:close())

	local pkg = "pkg -o ASSUME_ALWAYS_YES=yes -o IGNORE_OSVERSION=yes " ..
	    "-o INSTALL_AS_USER=1 -o PKG_DBDIR=./pkgdb -R ./pkgbase-repo-conf "

	assert(os.execute(pkg .. "update"))

	local packages = select_packages(pkg, media, all_libcompats)

	assert(os.execute(pkg .. "fetch -o " .. target .. " " .. table.concat(packages, " ")))
	assert(os.execute(pkg .. "repo " .. target))
end

main()