-- Lua code used by macros.auto*
local fedora = require "fedora.common"
-- Executes f(k) for k in range, returning a table of ks for which
-- f(k) = value. Used to compute a pre_range for pfloop for example
local function fmatch(f, range, value)
local K = {}
for _, k in ipairs(range) do
if (f(k) == value) then
table.insert(K, k)
end
end
return K
end
-- Executes the <f> function in a loop
-- – the loop is controled by <index> (a string):
-- — if the <index> value given to floop is nil, loop over the whole
-- <range>. Use fedora.readflag() to process rpm flag arguments safely.
-- — otherwise execute <f> for the specified <index> value only, if
-- <index> is part of <range>
-- – <f> is passed <index> then <otherargs> as arguments.
-- – <pre_range> index values are processed before the rest of <range>.
local function pfloop(f, index, pre_range, range, otherargs)
local only = {}
local first = {}
local last = {}
for _, i in ipairs(range) do
if (index == nil) then
local pre = false
for _, p in ipairs(pre_range) do
if (i == p) then
pre = true
break
end
end
if pre then
table.insert(first, i)
else
table.insert(last, i)
end
elseif (i == index) then
table.insert(only, i)
break
end
end
for _, R in ipairs({only, first, last}) do
for _, i in ipairs(R) do
f(i, table.unpack(otherargs))
end
end
end
-- Executes the <f> function in a loop
-- – the loop is controled by <index> (a string):
-- — if the <index> value given to floop is nil, loop over the whole
-- <range>. Use fedora.readflag() to process rpm flag arguments safely.
-- — otherwise execute <f> for the specified <index> value only, if
-- <index> is part of <range>
-- – <f> is passed <index> then <otherargs> as arguments.
-- – <pre_range> index values are processed before the rest of <range>.
local function floop(f, index, range, otherargs)
pfloop(f, index, {}, range, otherargs)
end
-- Executes the <pkg> function in a loop, in a way compatible with package
-- header generation requirements
-- – the loop is controled by <index> (a string):
-- — if the <index> value given to floop is nil, loop over the whole
-- <range>. Use fedora.readflag() to process rpm flag arguments safely.
-- — otherwise execute <pkg> for the specified <index> value only, if
-- <index> is part of <range>
-- – <pkg> is passed <index> then <otherargs> as arguments.
-- – <name>(<index>) must return the %{name} of the SRPM header that would
-- be generated if <pkg>(<index>, <otherargs>) is called before something
-- else generates the SRPM header.
-- – if %{source_name} is set, <name>(<index>) results will be compared to
-- %{source_name} for all valid <index> in the loop. <index> values for
-- which that comparison matches will be scheduled first
local function pkg_floop(pkg, index, otherargs, name, range)
local source_range = {}
local source_name = fedora.read("source_name")
if source_name then
source_range = fmatch(name, range, source_name)
end
pfloop(pkg, index, source_range, range, otherargs)
end
-- A small helper to return <name>(<index>) for all <index> values in <range>, since
-- pkg_floop() will usually be used in conjunction with pkg_exec()
local function names(name, range)
local N = {}
for _, i in ipairs(range) do
table.insert(N, name(i))
end
return N
end
local function registered(call)
local macros = {}
local auto_dir = fedora.read("_rpmautodir")
if auto_dir then
for filename in posix.files(auto_dir) do
if filename:match('%.auto$') then
local f = io.open(auto_dir .. "/" .. filename, "r")
for l in f:lines() do
local macro = l:match('^%%?' .. call ..'%s+%%?(%S+)')
if macro then
table.insert(macros, macro)
end
end
end
end
end
return macros
end
-- Executes all the macros in <macros>, passing -v as verbosity flag if
-- verbose. Each %<name> macro will be executed after the macros listed in the
-- %{<name>_after} variable (when those are also registered for the call).
-- Absent other constrains, %<name> macros for which %{<name>_last} is set to
-- anything else than false will be executed last
local function execute(macros, verbose)
local found = {}
local first = {}
local last = {}
local seen = {}
local plan = {}
local v = ""
if verbose then
v = " -v"
end
for _, macro in ipairs(macros) do
found[macro] = true
if fedora.readbool(macro .. "_last") then
table.insert(last, macro)
else
table.insert(first, macro)
end
end
local function insert(macro)
if seen[macro] then
return
end
seen[macro] = true
local deps = fedora.read(macro .. "_after")
if deps then
for dep in deps:gmatch("%S+") do
if found[dep] then
insert(dep)
end
end
end
table.insert(plan, macro)
end
for _, M in ipairs({first, last}) do
for _, macro in ipairs(M) do
insert(macro)
end
end
for _, macro in ipairs(plan) do
fedora.echo("%%" .. macro .. v)
print([[
#]] .. macro .. v ..
rpm.expand([[
%]] .. macro .. v .. [[
]]))
end
end
-- Executes all the macros registered for call, passing -v as verbosity flag if
-- verbose. Each %<name> macro will be executed after the macros listed in the
-- %{<name>_after} variable (when those are also registered for the call).
local function exec(call, verbose)
execute(registered(call), verbose)
end
-- Executes all the automated macros in the macros space-separated list of
-- <name>s, passing -v as verbosity flag if verbose.
-- This variant is intended to be used for package header generation purposes,
-- when those headers may include the SRPM header. To that effect, each %<name>
-- macro must have a %<name>_source_names counterpart that returns the list of
-- SRPM names that would be generated (if any), allowing <pkg_exec> to schedule
-- those that match %{source_name} first.
local function pkg_exec(call, verbose)
local source_name = fedora.read("source_name")
local macros = registered(call)
local first = {}
local last = {}
local v = ""
if verbose then
v = " -v"
end
for _, macro in ipairs(macros) do
local inserted = false
if source_name then
fedora.echo("%%" .. macro .. "_source_names")
local names = fedora.expand("%" .. macro .. "_source_names" .. v)
for name in names:gmatch("%S+") do
if name == source_name then
inserted = true
table.insert(first, macro)
break
end
end
end
if not inserted then
table.insert(last, macro)
end
end
if source_name and next(first) == nil then
table.insert(first, "buildsys_pkg")
end
local macros = {}
for _, M in ipairs({first, last}) do
for _, macro in ipairs(M) do
table.insert(macros, macro)
end
end
execute(macros, verbose)
end
-- A small helper to add function id to spec and console output, and keep track
-- of what is running when rpm barfs without providing any useful info
local function id(identifier)
fedora.echo(" " .. identifier)
print("#" .. identifier .. "\n")
end
return {
floop = floop,
pkg_floop = pkg_floop,
names = names,
exec = exec,
pkg_exec = pkg_exec,
id = id,
}