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