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