#95 Major rework of lua routines and forge macros
Closed 3 years ago by nim. Opened 3 years ago by nim.

file added
+239
@@ -0,0 +1,239 @@ 

+ -- 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,

+ }

file added
+1
@@ -0,0 +1,1 @@ 

+ auto_changelog buildsys_changelog

file added
+1
@@ -0,0 +1,1 @@ 

+ auto_sources buildsys_sources

file added
+156
@@ -0,0 +1,156 @@ 

+ -- buildsys macros routines, safe to use at SRPM build stage

+ 

+ local fedora = require "fedora.common"

+ 

+ local namespace = "buildsys"

+ local rads = {

+    ["start"] = {"name"},

+    ["evr"]   = {"epoch", "version", "release", "post_release"},

+    ["end"]   = {"summary", "license", "url", "tags", "description"},

+ }

+ 

+ local function radicals()

+   local R = {}

+   for k, v in pairs(rads) do

+     R[k] = v

+   end

+   local all = {}

+   for k, v in pairs(R) do

+     all = fedora.mergelists({all, v})

+   end

+   R["all"] = all

+   return R

+ end

+ 

+ local function srpm_pkg_start(verbose)

+   print(fedora.expand([[

+ Name:           %{source_name}

+ ]]))

+   -- Name: is declared, %{_sourcedir} can be used

+   local sn = "source"

+   local myrads = radicals()

+   fedora.mset(myrads["evr"], namespace, '', {

+                 fedora.mread(myrads["evr"], sn, '', false),

+               }, verbose, false)

+   local changelog = ''

+   local changelog_file = '%{_sourcedir}/%{' .. namespace .. '_changelog_file}'

+   local f = io.open(fedora.expand(changelog_file), "r")

+   if f then

+     for l in f:lines() do

+       changelog = changelog .. l .. "\n"

+     end

+     io.close(f)

+   end

+   fedora.set(namespace .. "_changelog_content", changelog, verbose)

+   print(fedora.expand([[

+ %{?buildsys_epoch:Epoch:          %{buildsys_epoch}}

+ Version:        %{buildsys_version}

+ Release:        %{buildsys_release}%{?dist}%{?buildsys_post_release:.%{buildsys_post_release}}]]))

+   -- Make sure the environment is ready for eventual pkg_end() execution

+   -- pkg_end is not srpm specific and does not operate from the source namespace

+   local cn = "__current_" .. namespace

+   fedora.mset(myrads["end"], cn, '', {

+                 fedora.mread(myrads["end"], sn, '', false),

+               }, verbose, true)

+   fedora.set("__" .. namespace .. "_srpm_done", true, verbose)

+ end

+ 

+ local function pkg_end()

+   local cn = "__current_" .. namespace

+   local itags = {}

+   for t, m in pairs({["Epoch"] = "epoch", ["Version"] = "version"}) do

+     local v = fedora.read(cn .. '_' .. m)

+     if v and (v ~= fedora.read('source_' .. m)) then

+       table.insert(itags, t .. ': ' .. v)

+     end

+   end

+   print(rpm.expand([[

+ 

+ Summary:        %{__current_buildsys_summary}

+ ]] .. table.concat(itags, '\n') .. [[

+ %{?__current_buildsys_license:License:        %{__current_buildsys_license}}

+ %{?__current_buildsys_url:URL:            %{__current_buildsys_url}}

+ %{?__current_buildsys_tags}

+ %description -n %{__current_buildsys_name}

+ %wordwrap    -v   __current_buildsys_description

+ ]]))

+ end

+ 

+ -- %new_package core

+ local function new_package(pkg_name, name_suffix, verbose)

+   local sn = "source"

+   local cn = "__current_" .. namespace

+   local source_name = fedora.read(sn .. "_name")

+   -- Safety net when the wrapper is used in conjunction with traditional syntax

+   if fedora.read("name") and (not source_name) then

+     warning([[

+ Something already set a package name. However, %%{source_name} is not set.

+ Please set %%{source_name} to the SRPM name to ensure reliable processing.

+ ]])

+     if name_suffix then

+       print(fedora.expand("%package        " .. name_suffix))

+     else

+       print(fedora.expand("%package     -n " .. pkg_name))

+     end

+     return

+   end

+   -- New processing

+   -- We can not rely on cn .. "_name" because new_package (unlike pkg)

+   -- does not require users to clear past environement between calls

+   if not (pkg_name or name_suffix or source_name) then

+     fedora.error(

+       "You need to set %%{source_name} or provide explicit package naming!")

+   end

+   local first = not fedora.read("__" .. namespace .. "_srpm_done")

+   if name_suffix then

+     pkg_name = "%{source_name}-" .. name_suffix

+     print(fedora.expand("%package        "  .. name_suffix))

+   else

+     if first and not source_name then

+       source_name = pkg_name

+       fedora.safeset(sn .. "_name", source_name, verbose)

+     end

+     if not pkg_name then

+       pkg_name = source_name

+     end

+     if (pkg_name == source_name) then

+       local myrads = radicals()

+       -- Collect bits that may have been declared in the __current_

+       -- namespace. srpm_pkg_start will take the source namespace as only

+       -- trusted reference

+       fedora.mset(myrads["all"], sn, "", {

+           -- cn is a temporary reusable ref, all mreads must resolve

+           fedora.mread({"epoch", "version"}, cn, '', true),

+           fedora.mread(myrads["end"], cn, '', true),

+         }, verbose, false)

+       srpm_pkg_start()

+     else

+       print(fedora.expand("%package     -n " .. pkg_name))

+     end

+   end

+   _ = fedora.suffix({[namespace .. "_name"] = pkg_name}, true, verbose)

+   local cn = "__current_" .. namespace

+   fedora.set(cn .. "_name", pkg_name, verbose)

+ end

+ 

+ local function pkg(verbose)

+   local cn = "__current_" .. namespace

+   local pkg_name = fedora.read(cn .. "_name")

+   new_package(pkg_name, nil, verbose)

+   pkg_end()

+ end

+ 

+ local function reset(verbose)

+   local cn = "__current_" .. namespace

+   local myrads = radicals()

+   fedora.unset("__buildsys_srpm_done", verbose)

+   fedora.mset(myrads["all"], cn, '', {{}}, verbose, true)

+ end

+ 

+ return {

+   namespace   = namespace,

+   radicals    = radicals()['all'],

+   new_package = new_package,

+   pkg         = pkg,

+   reset       = reset,

+ }

file modified
+517 -194
@@ -1,17 +1,77 @@ 

  -- Convenience Lua functions that can be used within rpm macros

  

- -- Reads an rpm variable. Unlike a basic rpm.expand("{?foo}"), returns nil if

- -- the variable is unset, which is convenient in lua tests and enables

- -- differentiating unset variables from variables set to ""

- local function read(rpmvar)

+ -- Reads an rpm variable reference. Returns "%{" .. rpmvar.. "}" if rpmvar is

+ -- set to something, and nil otherwise. This is convenient in lua tests and to

+ -- distinguish between an unset variable and a variable set to something that

+ -- expands to "" at this point of the spec file.

+ local function ref(rpmvar)

    if not rpmvar or

      (rpm.expand("%{" .. rpmvar .. "}") == "%{" .. rpmvar .. "}") then

      return nil

    else

-     return rpm.expand("%{?" .. rpmvar .. "}")

+     return "%{" .. rpmvar .. "}"

    end

  end

  

+ -- Expands <run> till there is no expansion left to do

+ local function expand(run)

+   if not run then

+     return nil

+   end

+   run = run:gsub("%%%%", "\029")

+   local expanded = rpm.expand(run)

+   while run ~= expanded do

+     run = expanded

+     expanded = rpm.expand(run)

+   end

+   expanded = expanded:gsub("\029", "%%%%")

+   return expanded

+ end

+ 

+ -- Reads an rpm variable (reads the variable reference, and evaluates it).

+ -- Unlike a basic rpm.expand("{?" .. rpmvar .. "}"), returns nil if the

+ -- variable is unset, which is convenient in lua tests.

+ local function read(rpmvar)

+   local ref = ref(rpmvar)

+   if ref then

+     return expand(ref)

+   else

+     return ref

+   end

+ end

+ 

+ -- Sometimes it is convenient to distinguish between an unset variable and a

+ -- variable explicitly set to false. Unlike read, readbool returns a tristate,

+ -- true, false or nil

+ local function readbool(rpmvar)

+   local value = read(rpmvar)

+   if value then

+     if (value:lower() == "false") then

+       return false

+     else

+       return true

+     end

+   else

+     return value

+   end

+ end

+ 

+ -- Builds a list of un-commented and non-empty lines from a multiline rpm

+ -- variable. This allows using multiline expands for private %sourcelist-like

+ -- containers.

+ local function readlines(rpmvar)

+   local lines = read(rpmvar)

+   local L = {}

+   if lines then

+     for line in string.gmatch(lines,'[^\r\n]+') do

+       if string.match(line, '^[^#]') then

+         table.insert(L, line)

+       end

+     end

+   end

+   return L

+ end

+ 

  -- Returns true if the macro that called this function had flag set

  --   – for example, hasflag("z") would give the following results:

  --     %foo -z bar → true
@@ -40,114 +100,420 @@ 

    end

  end

  

- -- Sets a spec variable; echoes the result if verbose

- local function explicitset(rpmvar, value, verbose)

-   local value = value

-   if (value == nil) or (value == "") then

-     value = "%{nil}"

+ -- %wordwrap core

+ local function wordwrap(text)

+   text = expand(text .. "\n")

+   text = text:gsub("%%%%", "\029")

+   text = text:gsub("\t",               "  ")

+   text = text:gsub("\r",               "\n")

+   text = text:gsub(" +\n",             "\n")

+   text = text:gsub("\n+\n",            "\n\n")

+   text = text:gsub("^\n",              "")

+   text = text:gsub("\n( *)[-*—][  ]+", "\n%1– ")

+   output = ""

+   for line in text:gmatch("[^\n]*\n") do

+     local pos = 0

+     local advance = ""

+     for word in line:gmatch("%s*[^%s]*\n?") do

+       local wl, bad = utf8.len(word)

+       if not wl then

+         -- Can not use warning in wordwrap since warning uses wordwrap

+         rpm.expand([[

+ %{warn:Invalid UTF-8 sequence detected in:}

+ %{warn:]] .. word .. [[}

+ %{warn:It may produce unexpected results.}

+ ]])

+         wl = bad

+       end

+       if (pos == 0) then

+         advance, n = word:gsub("^(%s*– ).*", "%1")

+         if (n == 0) then

+           advance  = word:gsub("^(%s*).*",   "%1")

+         end

+         advance = advance:gsub("– ", "  ")

+         pos = pos + wl

+       elseif  (pos + wl  < 81) or

+              ((pos + wl == 81) and word:match("\n$")) then

+         pos = pos + wl

+       else

+         word = advance .. word:gsub("^%s*", "")

+         output = output .. "\n"

+         pos = utf8.len(word)

+       end

+       output = output .. word

+       if pos > 80 then

+         pos = 0

+         if not word:match("\n$") then

+           output = output .. "\n"

+         end

+       end

+     end

    end

-   rpm.define(rpmvar .. " " .. value)

-   if verbose then

-     rpm.expand("%{warn:Setting %%{" .. rpmvar .. "} = " .. value .. "}")

+   output = output:gsub("^\n*", "")

+   output = output:gsub("\n*$", "\n")

+   -- Escape %’s – we want macros that were preserved from wordwrap expansion to

+   -- be preserved at the next stage too

+   output = output:gsub("\029", "%%%%")

+   return output

+ end

+ 

+ -- Reformats text and outputs it using a built-in rpm verb such as echo, warn

+ -- or error

+ local function message(verb, text)

+   rpm.expand("%{" .. verb .. ":" .. wordwrap(text):gsub("\n*$", "") .. "}")

+ end

+ 

+ -- Writes some text to stdout

+ local function echo(text)

+   message("echo", text)

+ end

+ 

+ -- Writes the list of z-suffixed rpmvars to the console, if set

+ local function echovars(rpmvars, z)

+   for _, rpmvar in ipairs(rpmvars) do

+     local suffixed = rpmvar .. z

+     local header = string.sub("  " .. suffixed .. ":                                               ",1,24)

+     local v = ref(suffixed)

+     if v then

+       echo(header .. v)

+     end

    end

  end

  

- -- Unsets a spec variable if it is defined; echoes the result if verbose

- local function explicitunset(rpmvar, verbose)

-   if (rpm.expand("%{" .. rpmvar .. "}") ~= "%{" .. rpmvar .. "}") then

-     rpm.define(rpmvar .. " %{nil}")

-     if verbose then

-       rpm.expand("%{warn:Unsetting %%{" .. rpmvar .. "}}")

+ -- Writes some text as a warning

+ local function warning(text)

+   message("warn", text)

+ end

+ 

+ -- Writes some text as an error

+ local function err(text)

+   message("error", text)

+ end

+ 

+ -- Returns a table of <radical> = <value>, for all <radical>s in <radicals>,

+ -- with <value> = reference of <namespace>_<radical><suffix> if

+ -- <namespace>_<radical><suffix> is set. Radicals for which

+ -- <namespace>_<radical><suffix> is not set are omitted in results.

+ local function mread(radicals, namespace, suffix, resolve)

+   local R = {}

+   for _, radical in ipairs(radicals) do

+     local name = radical

+     if namespace and (namespace ~= "") then

+       name = namespace .. "_" .. name

+     end

+     local ref = ref(name .. suffix)

+     if ref then

+       if resolve then

+         ref = expand(ref)

+       end

+       R[radical] = ref

+     end

+   end

+   return R

+ end

+ 

+ -- Sets a spec variable; echoes the result if verbose

+ local function set(rpmvar, value, verbose)

+   if rpmvar then

+     -- Empty the stack state

+     while read(rpmvar) do

+       rpm.undefine(rpmvar)

+     end

+     if (value == nil) then

+       if ref(rpmvar) then

+         if verbose then

+           -- Already did it, white lie

+           warning("Unsetting " .. rpmvar)

+         end

+       end

+     else

+       if (value == false) then

+         value = "false"

+       elseif (value == true) then

+         value = "true"

+       end

+       if verbose then

+         warning("Setting "  .. rpmvar .. " = " .. value)

+       end

+       rpm.define(rpmvar .. " %{expand:" .. value .. "}")

      end

    end

  end

  

+ -- Unsets a spec variable if it is defined; echoes the result if verbose

+ local function unset(rpmvar, verbose)

+   set(rpmvar, nil, verbose)

+ end

+ 

  -- Sets a spec variable, if not already set; echoes the result if verbose

  local function safeset(rpmvar, value, verbose)

-   if (rpm.expand("%{" .. rpmvar .. "}") == "%{" .. rpmvar .. "}") then

-     explicitset(rpmvar,value,verbose)

+   if not ref(rpmvar) then

+     set(rpmvar, value, verbose)

    end

  end

  

- -- Aliases a list of rpm variables to the same variables suffixed with 0 (and

- -- vice versa); echoes the result if verbose

- local function zalias(rpmvars, verbose)

-   for _, sfx in ipairs({{"","0"},{"0",""}}) do

-     for _, rpmvar in ipairs(rpmvars) do

-       local toalias = "%{?" .. rpmvar .. sfx[1] .. "}"

-       if (rpm.expand(toalias) ~= "") then

-         safeset(rpmvar .. sfx[2], toalias, verbose)

+ -- Sets the <namespace>_<radical><suffix> variable for all <radical>s in

+ -- <radicals>, to a <value> taken in the <stack> list of <radical> = <value>

+ -- tables. When <radical> exists in multiple tables, only its first <value> is

+ -- taken into account. When <radical> does not exist in any table, no

+ -- <namespace>_<radical><suffix> is set.

+ -- <stack> is usually constructed with multiple mread calls, taking

+ -- domain-specific fallback needs into consideration.

+ -- If <force> set via set (and unset variables with no matches), otherwise set

+ -- via safeset.

+ -- mset is a complex function; its specializations like alias, bialias, zalias

+ -- and set_current are sufficient for many needs.

+ local function mset(radicals, namespace, suffix, stack, verbose, force)

+   for _, radical in ipairs(radicals) do

+     local value = nil

+     local found = false

+     for _, values in ipairs(stack) do

+       for k, v in pairs(values) do

+         if k == radical then

+           value = v

+           found = true

+           break

+         end

+       end

+       if found then

+         break

        end

      end

+     local name = radical

+     if namespace and (namespace ~= "") then

+       name = namespace .. "_" .. name

+     end

+     if force then

+       set(    name .. suffix, value, verbose)

+     else

+       safeset(name .. suffix, value, verbose)

+     end

    end

  end

  

- -- Takes a list of rpm variable roots and a suffix and alias current<root> to

- -- <root><suffix> if it resolves to something not empty

- local function setcurrent(rpmvars, suffix, verbose)

-   for _, rpmvar in ipairs(rpmvars) do

-     if (rpm.expand("%{?" .. rpmvar .. suffix .. "}") ~= "") then

-       explicitset(  "current" .. rpmvar, "%{" .. rpmvar .. suffix .. "}", verbose)

-     else

-       explicitunset("current" .. rpmvar,                                  verbose)

+ -- Sets the <namespace>_<radical><suffix> variable for all <radical>s in

+ -- <radicals>, to a reference to <from_namespace>_<radical><from_suffix>,

+ -- if <from_namespace>_<radical><from_suffix> is set.

+ -- inherit_from is recursive: the next <from_suffix> is read in

+ -- <from_namespace>_<from_key><from_suffix>

+ local function inherit_from (radicals, namespace, suffix, from_namespace,

+                              from_suffix, from_key, verbose)

+   local seen  = {}

+   local stack = {}

+   local function icopy(z)

+     if not z or seen[z] then

+       return

+     end

+     seen[z] = true

+     table.insert(stack, mread(radicals, from_namespace, z, false))

+     if from_key and (from_key ~= "") then

+       local new_key = from_key .. z

+       if from_namespace and (from_namespace ~= "") then

+         new_key = from_namespace .. "_" .. new_key

+       end

+       icopy(read(new_key))

      end

    end

+   icopy(from_suffix)

+   mset(radicals, namespace, suffix, stack, verbose, false, false)

  end

  

- -- Echo the list of rpm variables, with suffix, if set

- local function echovars(rpmvars, suffix)

-   for _, rpmvar in ipairs(rpmvars) do

-     rpmvar = rpmvar .. suffix

-     local header = string.sub("  " .. rpmvar .. ":                                               ",1,21)

-     rpm.expand("%{?" .. rpmvar .. ":%{echo:" .. header .. "%{?" .. rpmvar .. "}}}")

+ -- Sets the <namespace>_<radical><suffix> variable for all <radical>s in

+ -- <radicals>, to a reference to <namespace>_<radical><from_suffix>,

+ -- if <namespace>_<radical><from_suffix> is set.

+ -- <from_suffix> is read in <namespace>_<from_key><suffix>

+ -- inherit is recursive, and will also process <from_key> at the next level

+ local function inherit(radicals, namespace, suffix, key, verbose)

+   local k = key .. suffix

+   if namespace and (namespace ~= "") then

+     k = namespace .. "_" .. k

    end

+   local from_suffix = read(k)

+   inherit_from(radicals, namespace, suffix, namespace, from_suffix, key,

+                verbose)

  end

  

- -- Returns an array, indexed by suffix, containing the non-empy values of

- -- <rpmvar><suffix>, with suffix an integer string or the empty string

- local function getsuffixed(rpmvar)

-   local suffixes = {}

-   zalias({rpmvar})

-   for suffix=0,9999 do

-     local value = rpm.expand("%{?" .. rpmvar .. suffix .. "}")

-     if (value ~= "") then

-       suffixes[tostring(suffix)] = value

+ -- for each radical in radicals, safeset <to_namespace><radical><to_suffix>

+ -- to %{<from_namespace><radical><from_suffix>} if

+ -- <from_namespace><radical><from_suffix> is set to something

+ local function alias(radicals, from_namespace, from_suffix,

+                                to_namespace,   to_suffix,   verbose)

+   mset(radicals, to_namespace, to_suffix,

+         {mread(radicals, from_namespace, from_suffix, false)},

+         verbose, false)

+ end

+ 

+ -- Alias back and forth

+ local function bialias(radicals, namespace1, suffix1,

+                                  namespace2, suffix2, verbose)

+   alias(radicals, namespace1, suffix1, namespace2, suffix2, verbose)

+   alias(radicals, namespace2, suffix2, namespace1, suffix1, verbose)

+ end

+ 

+ -- Aliases a list of rpm variables to the same variables suffixed with 0 (and

+ -- vice versa); echoes the result if verbose

+ local function zalias(rpmvars, verbose)

+   bialias(rpmvars, "", "", "",  "0", verbose)

+ end

+ 

+ -- Takes a list of rpm variable roots and a suffix and alias __current_<rpmvar>

+ -- to <rpmvar><suffix> if it resolves to something not empty

+ local function set_current(rpmvars, suffix, verbose)

+   mset(rpmvars, "__current", "",

+        {mread(rpmvars, "", suffix, false)}, verbose, true)

+ end

+ 

+ -- Sets the usual verbosity variables in a generic way

+ local function set_verbose(verbose)

+   if verbose then

+     set(  "__current_verbose",       "-v",     verbose)

+     unset("__current_quiet",                   verbose)

+     unset("__current_shell_quiet",             verbose)

+     unset("__current_shell_verbose",           verbose)

+   else

+     unset("__current_verbose",                 verbose)

+     set(  "__current_quiet",         "-q",     verbose)

+     set(  "__current_shell_quiet",   "set +x", verbose)

+     set(  "__current_shell_verbose", "set -x", verbose)

+   end

+ end

+ 

+ -- Returns an array of <namespace>_<radical>

+ local function qualify(radicals, namespace)

+   local R = {}

+   if (namespace ~= "") then

+     namespace = namespace .. "_"

+   end

+   for _, radical in ipairs(radicals) do

+     table.insert(R, namespace .. radical)

+   end

+   return R

+ end

+ 

+ -- Merges two lists, removing duplicates and ordering the result

+ -- The result is a list containing an ordered set of values

+ local function mergelists(list_of_lists)

+   local S = {}

+   local L = {}

+   for   _, l in ipairs(list_of_lists) do

+     for _, v in ipairs(l) do

+       S[v] = true

+     end

+   end

+   for k, _ in  pairs(S) do

+     table.insert(L, k)

+   end

+   table.sort(L)

+   return L

+ end

+ 

+ -- Returns a list of suffixes, for which <rpmvar><suffix> is set to something

+ local function suffixes(rpmvar)

+   local S = {}

+   for z=0,9999 do

+     if ref(rpmvar .. z) then

+       table.insert(S, tostring(z))

      end

    end

    -- rpm convention is to alias no suffix to zero suffix

    -- only add no suffix if zero suffix is different

-   local value = rpm.expand("%{?" .. rpmvar .. "}")

-   if (value ~= "") and (value ~= suffixes["0"]) then

-      suffixes[""] = value

+   local value = read(rpmvar)

+   if value and not (value == read(rpmvar .. "0")) then

+     table.insert(S, "")

    end

-   return suffixes

+   return S

  end

  

  -- Returns the list of suffixes, including the empty string, for which

- -- <rpmvar><suffix> is set to a non empty value

- local function getsuffixes(rpmvar)

-   suffixes = {}

-   for suffix in pairs(getsuffixed(rpmvar)) do

-     table.insert(suffixes,suffix)

+ -- <rpmvar><suffix> is set to a non empty value, for any rpmvar in rpmvars

+ local function all_suffixes(rpmvars)

+   local SL = {}

+   local S  = {}

+   for _, rpmvar in ipairs(rpmvars) do

+     table.insert(SL, suffixes(rpmvar))

    end

-   table.sort(suffixes,

+   S = mergelists(SL)

+   table.sort(S,

               function(a,b) return (tonumber(a) or 0) < (tonumber(b) or 0) end)

-   return suffixes

+   return S

  end

  

- -- Returns the suffix for which <rpmvar><suffix> has a non-empty value that

- -- matches best the beginning of the value string

- local function getbestsuffix(rpmvar, value)

-   local best         = nil

-   local currentmatch = ""

-   for suffix, setvalue in pairs(getsuffixed(rpmvar)) do

-   if (string.len(setvalue) > string.len(currentmatch)) and

-      (string.find(value, "^" .. setvalue)) then

-       currentmatch = setvalue

-       best         = suffix

+ local function suffix_new(set, verbose)

+   local s = 0

+   local used = false

+   repeat

+     z = tostring(s)

+     used = false

+     for k, _ in pairs(set) do

+       used = used or ref(k .. z)

      end

+     s = s + 1

+   until (not used)

+   for k, v in pairs(set) do

+     safeset(k .. z, v, verbose)

    end

-   return best

+   return z

+ end

+ 

+ local function suffix_reuse(set, verbose)

+   for s = 0, 9999 do

+     z = tostring(s)

+     local matches = true

+     for k, v in pairs(set) do

+       matches = matches and (read(k .. z) == v)

+     end

+     if matches then

+       return z

+     end

+   end

+   return suffix_new(set, verbose)

+ end

+ 

+ -- Takes a set[key] = <value> table and returns a suffix for which all the

+ -- <key><suffix> rpm variables have the corresponding <value> set.

+ -- If reuse attempts to find an existing suffix that matches, otherwise,

+ -- takes an available suffix and creates the variable set from scratch

+ local function suffix(set, reuse, verbose)

+   if reuse then

+     return suffix_reuse(set, verbose)

+   else

+     return suffix_new(set, verbose)

+   end

+ end

+ 

+ -- Returns the suffix/number of a source/patch filename

+ -- We could do it with source_num/patch_num but those are dependant on a

+ -- specific rpm version and are not available for all the other variables we

+ -- use suffixes() with

+ local function sourcedir_suffix(filename, radical)

+   if not filename then

+     return nil

+   end

+   filename = expand(filename)

+   if not filename then

+     return nil

+   end

+   filename = filename:match("[^/]+$")

+   if not filename then

+     return nil

+   end

+   filename = expand("%{_sourcedir}/" .. filename)

+   for _, z in ipairs(suffixes(radical)) do

+     if expand('%{' .. radical .. z .. "}") == filename then

+       return z

+     end

+   end

+   return nil

+ end

+ 

+ -- Returns the source suffix/number of a filename

+ local function source_suffix(filename)

+   return sourcedir_suffix(filename, "SOURCE")

+ end

+ 

+ -- Returns the patch suffix/number of a filename

+ local function patch_suffix(filename)

+   return sourcedir_suffix(filename, "PATCH")

  end

  

  -- %writevars core
@@ -159,136 +525,93 @@ 

    end

  end

  

- -- https://github.com/rpm-software-management/rpm/issues/566

- -- Reformat a text intended to be used used in a package description, removing

- -- rpm macro generation artefacts.

- -- – remove leading and ending empty lines

- -- – trim intermediary empty lines to a single line

- -- – fold on spaces

- -- Should really be a %%{wordwrap:…} verb

- local function wordwrap(text)

-   text = rpm.expand(text .. "\n")

-   text = string.gsub(text, "\t",              "  ")

-   text = string.gsub(text, "\r",              "\n")

-   text = string.gsub(text, " +\n",            "\n")

-   text = string.gsub(text, "\n+\n",           "\n\n")

-   text = string.gsub(text, "^\n",             "")

-   text = string.gsub(text, "\n( *)[-*—][  ]+", "\n%1– ")

-   output = ""

-   for line in string.gmatch(text, "[^\n]*\n") do

-     local pos = 0

-     local advance = ""

-     for word in string.gmatch(line, "%s*[^%s]*\n?") do

-       local wl, bad = utf8.len(word)

-       if not wl then

-         print("%{warn:Invalid UTF-8 sequence detected in:}" ..

-               "%{warn:" .. word .. "}" ..

-               "%{warn:It may produce unexpected results.}")

-         wl = bad

-       end

-       if (pos == 0) then

-         advance, n = string.gsub(word, "^(%s*– ).*", "%1")

-         if (n == 0) then

-           advance = string.gsub(word, "^(%s*).*", "%1")

-         end

-         advance = string.gsub(advance, "– ", "  ")

-         pos = pos + wl

-       elseif  (pos + wl  < 81) or

-              ((pos + wl == 81) and string.match(word, "\n$")) then

-         pos = pos + wl

-       else

-         word = advance .. string.gsub(word, "^%s*", "")

-         output = output .. "\n"

-         pos = utf8.len(word)

-       end

-       output = output .. word

-       if pos > 80 then

-         pos = 0

-         if not string.match(word, "\n$") then

-           output = output .. "\n"

-         end

-       end

+ 

+ 

+ -- deprecated graveyard

+ -- those can be removed as soon as a port of fonts-rpm-macros and go-rpm-macros

+ -- to the new API lands in koji

+ 

+ local function setcurrent(rpmvars, suffix, verbose)

+   warning("setcurrent is deprecated, replace it with set_current")

+   for _, rpmvar in ipairs(rpmvars) do

+     local suffixed = rpmvar .. suffix

+     if ref(suffixed) then

+       set(  "current" .. rpmvar, "%{?" .. suffixed .. "}", verbose)

+     else

+       unset("current" .. rpmvar,                           verbose)

      end

    end

-   output = string.gsub(output, "\n*$", "\n")

-   return output

  end

  

- -- Because rpmbuild will fail if a subpackage is declared before the source

- -- package itself, provide a source package declaration shell as fallback.

- local function srcpkg(verbose)

-   if verbose then

-     rpm.expand([[

- %{echo:Creating a header for the SRPM from %%{source_name}, %%{source_summary} and}

- %{echo:%%{source_description}. If that is not the intended result, please declare the}

- %{echo:SRPM header and set %%{source_name} in your spec file before calling a macro}

- %{echo:that creates other package headers.}

- ]])

-   end

-   print(rpm.expand([[

- Name:           %{source_name}

- Summary:        %{source_summary}

- %description

- %wordwrap -v source_description

- ]]))

-   explicitset("currentname", "%{source_name}", verbose)

- end

- 

- -- %new_package core

- local function new_package(source_name, pkg_name, name_suffix, first, verbose)

-   -- Safety net when the wrapper is used in conjunction with traditional syntax

-   if (not first) and (not source_name) then

-     rpm.expand([[

- %{warn:Something already set a package name. However, %%{source_name} is not set.}

- %{warn:Please set %%{source_name} to the SRPM name to ensure reliable processing.}

- ]])

-     if name_suffix then

-       print(rpm.expand("%package        " .. name_suffix))

-     else

-       print(rpm.expand("%package     -n " .. pkg_name))

+ local function getsuffixed(rpmvar)

+   local S = {}

+   zalias({rpmvar}, false)

+   for z=0,9999 do

+     local value = read(rpmvar .. z)

+     if value then

+       S[tostring(z)] = value

      end

-     return

    end

-   -- New processing

-   if not (pkg_name or name_suffix or source_name) then

-     rpm.expand([[

- %{error:You need to set %%{source_name} or provide explicit package naming!}

- ]])

+   -- rpm convention is to alias no suffix to zero suffix

+   -- only add no suffix if zero suffix is different

+   local value = read(rpmvar)

+   if value and (value ~= S["0"]) then

+     S[""] = value

    end

-   if name_suffix then

-     print(rpm.expand("%package        "  .. name_suffix))

-     explicitset("currentname", "%{source_name}-" .. name_suffix, verbose)

-   else

-     if not source_name then

-       source_name = pkg_name

-     end

-     if (pkg_name == source_name) then

-       safeset("source_name", source_name, verbose)

-       print(rpm.expand("Name:           %{source_name}"))

-     else

-       if source_name and first then

-         srcpkg(verbose)

-       end

-       print(rpm.expand("%package     -n " .. pkg_name))

+   return S

+ end

+ 

+ local function getbestsuffix(rpmvar, value)

+   local best         = nil

+   local currentmatch = ""

+   for z, setvalue in pairs(getsuffixed(rpmvar)) do

+   if ((not best) or (string.len(setvalue) < string.len(currentmatch))) and

+      (string.find(setvalue, "^" .. value)) then

+       currentmatch = setvalue

+       best         = z

      end

-     explicitset("currentname", pkg_name, verbose)

    end

+   return best

  end

  

  return {

-   read          = read,

-   hasflag       = hasflag,

-   readflag      = readflag,

-   explicitset   = explicitset,

-   explicitunset = explicitunset,

-   safeset       = safeset,

-   zalias        = zalias,

-   setcurrent    = setcurrent,

-   echovars      = echovars,

-   getsuffixed   = getsuffixed,

-   getsuffixes   = getsuffixes,

-   getbestsuffix = getbestsuffix,

-   writevars     = writevars,

-   wordwrap      = wordwrap,

-   new_package   = new_package,

+   ref            = ref,

+   expand         = expand,

+   read           = read,

+   readbool       = readbool,

+   readlines      = readlines,

+   hasflag        = hasflag,

+   readflag       = readflag,

+   wordwrap       = wordwrap,

+   echo           = echo,

+   echovars       = echovars,

+   warning        = warning,

+   error          = err,

+   mread          = mread,

+   set            = set,

+   unset          = unset,

+   safeset        = safeset,

+   mset           = mset,

+   inherit_from   = inherit_from,

+   inherit        = inherit,

+   alias          = alias,

+   bialias        = bialias,

+   zalias         = zalias,

+   set_current    = set_current,

+   set_verbose    = set_verbose,

+   qualify        = qualify,

+   mergelists     = mergelists,

+   suffixes       = suffixes,

+   all_suffixes   = all_suffixes,

+   suffix         = suffix,

+   source_suffix  = source_suffix,

+   patch_suffix   = patch_suffix,

+   writevars      = writevars,

+   -- deprecated aliases

+   explicitset    = set,

+   explicitunset  = unset,

+   getsuffixes    = suffixes,

+   setcurrent     = setcurrent,

+   getsuffixed    = getsuffixed,

+   getbestsuffix  = getbestsuffix,

  }

file added
+2
@@ -0,0 +1,2 @@ 

+ auto_install  doc_install

+ auto_files    doc_files

file added
+27
@@ -0,0 +1,27 @@ 

+ local fedora = require "fedora.common"

+ local   auto = require "fedora.auto"

+ local    doc = require "fedora.srpm.doc"

+ 

+ local namespace = "doc"

+ 

+ local function install(suffix, verbose)

+  auto.id(namespace .. '.install("' .. suffix .. '")')

+   doc.env(suffix, verbose)

+   print(rpm.expand([[

+ %__]] .. namespace .. [[_install

+ ]]))

+ end

+ 

+ local function files(suffix, verbose)

+  auto.id(namespace .. '.files("' .. suffix .. '")')

+   doc.env(suffix, verbose)

+   print(rpm.expand([[

+ %__]] .. namespace .. [[_files

+ ]]))

+ end

+ 

+ return {

+   floop   = doc.floop,

+   install = install,

+   files   = files,

+ }

file added
+2
@@ -0,0 +1,2 @@ 

+ auto_init  doc_init

+ auto_pkg   doc_pkg

file added
+103
@@ -0,0 +1,103 @@ 

+ 

+ local fedora = require "fedora.common"

+ local   auto = require "fedora.auto"

+ local buildsys = require "fedora.srpm.buildsys"

+ 

+ local namespace = "doc"

+ 

+ local rads = {

+   ["key"]      = {"docs"},

+   ["read"]     = {"epoch", "version", "license", "licenses",

+                   "licenses_exclude", "docs", "docs_exclude", "tags"},

+   ["computed"] = {"name", "summary", "requires", "description", "list"}

+ }

+ 

+ local function suffixes()

+   return fedora.all_suffixes(fedora.qualify(rads["key"], namespace))

+ end

+ 

+ local function floop(f, index, otherargs, verbose)

+   local range = suffixes(verbose)

+   auto.floop(f, index, range, otherargs)

+ end

+ 

+ local function radicals()

+   local R = {}

+   for k, v in pairs(rads) do

+     R[k] = v

+   end

+   local all = {}

+   for k, v in pairs(R) do

+     all = fedora.mergelists({all, v})

+   end

+   R["all"] = all

+   return R

+ end

+ 

+ local function init(suffix, verbose, informative)

+  auto.id(namespace .. '.init("' .. suffix .. '")')

+   local ismain = (suffix == "") or (suffix == "0")

+   local myrads = radicals()

+   local requires = [[%{lua:

+     local fedora = require "fedora.common"

+     local namespace = "]] .. namespace .. [["

+     local suffix    = "]] .. suffix .. [["

+     local requires = {}

+     local pkgs = fedora.read(namespace .. "_packages" .. suffix)

+     if pkgs then

+       for pkg in pkgs:gmatch("[^%s,;]+") do

+         table.insert(requires, "Enhances:       " .. pkg)

+       end

+     else

+       for _, z in ipairs(fedora.suffixes("buildsys_name")) do

+         if not fedora.read("buildsys_name" .. z):match("-doc$") then

+           table.insert(requires,

+             "Enhances:       %{buildsys_name" .. z .. "}")

+         end

+       end

+     end

+     print(table.concat(requires, "\\n"))

+     }]]

+   fedora.mset(myrads["all"], namespace, suffix, {{

+       ["name"]        = "%{source_name}-doc",

+       ["summary"]     = "Optional documentation files %{source_name}",

+       ["requires"]    = requires,

+       ["description"] = [[

+ %{?source_description}

+ 

+ This package provides optional documentation files shipped with %{source_name}.

+ ]],

+       ["list"] = "%{_builddir}/%{?buildsubdir}/" ..

+                  "%{" .. namespace .. "_name" .. suffix .. "}.lst",

+     }}, verbose, false)

+   if informative then

+     fedora.echo("Variables read or set by %%" .. namespace .. "_init")

+     fedora.echovars(fedora.qualify(myrads["all"], namespace), suffix)

+   end

+ end

+ 

+ local function env(suffix, verbose)

+   local myrads = radicals(suffix, verbose)

+   fedora.set_current(fedora.qualify(myrads["all"], namespace), suffix, verbose)

+ end

+ 

+ local function pkg(suffix, verbose)

+   auto.id(namespace .. '.pkg("' .. suffix .. '")')

+   fedora.mset(buildsys.radicals, "__current_buildsys", "", {

+       { ["tags"] = [[

+ BuildArch:      noarch

+ %{?]] .. namespace .. [[_requires]] .. suffix .. [[}

+ %{?]] .. namespace .. [[_tags]]     .. suffix .. [[}]] },

+       fedora.mread({"name", "summary", "epoch", "version", "license",

+                     "description"}, namespace, suffix, false),

+     }, verbose, true)

+   buildsys.pkg(verbose)

+ end

+ 

+ return {

+   suffixes = suffixes,

+   floop    = floop,

+   init     = init,

+   env      = env,

+   pkg      = pkg,

+ }

file added
+1
@@ -0,0 +1,1 @@ 

+ auto_prep forge_prep

file added
+44
@@ -0,0 +1,44 @@ 

+ -- Lua code used by macros.forge and derivatives; RPM stage

+ 

+ local fedora = require "fedora.common"

+ local   auto = require "fedora.auto"

+ local  forge = require "fedora.srpm.forge"

+ 

+ -- This is constrained by the design of %apply_patch

+ local function apply_patches(suffix, verbose)

+   local quiet = ""

+   if not verbose then

+     quiet = "-q "

+   end

+   for _, patch in ipairs(fedora.readlines("forge_patchlist" .. suffix)) do

+     local ps = fedora.patch_suffix(patch)

+     if ps then

+       for _, o in ipairs({"patch_mode", "patch_level"}) do

+         fedora.safeset(o .. ps, "%{forge_" .. o .. suffix .. "}")

+       end

+       -- %apply_patch does not have the notion of a disposable local currentfoo-like

+       -- control variable, you need to override the main one

+       fedora.set("__scm", "%{patch_mode" .. ps .. "}")

+       -- %apply_patch requires specifying the patch to apply in 3 different forms!

+       -- As a filename, as a full path, and as a patch suffix

+       print(rpm.expand(

+         "%apply_patch " ..  quiet .. "%{patch_level" .. ps .. "} " ..

+         "-m " .. patch .. " %{_sourcedir}/" .. patch .. " " .. ps .. "\n"))

+     end

+   end

+ end

+ 

+ -- %forge_prep core

+ local function prep(suffix, verbose)

+   auto.id('forge.prep("' .. suffix .. '")')

+   forge.env(suffix, verbose)

+   print(rpm.expand([[

+ %setup %{?__current_quiet} %{__current_forge_setup_arguments}

+ ]]))

+   apply_patches(suffix, verbose)

+ end

+ 

+ return {

+   floop     = forge.floop,

+   prep      = prep,

+ }

file added
+3
@@ -0,0 +1,3 @@ 

+ auto_init    forge_init

+ auto_sources forge_sources

+ auto_patches forge_patches

file added
+438
@@ -0,0 +1,438 @@ 

+ -- Lua code used by macros.forge-srpm and derivatives

+ 

+ local fedora = require "fedora.common"

+ local   auto = require "fedora.auto"

+ 

+ -- Computes the suffix of a version string, removing vprefix if it matches

+ -- For example with vprefix 1.2.3: 1.2.3.rc2 → .rc2 but 1.2.30 → 1.2.30 not 0

+ local function version_suffix(vstring, vprefix)

+   if (vstring:sub(1, #vprefix) == vprefix) and

+      (not string.match(vstring:sub(#vprefix + 1), "^%.?%d")) then

+     return vstring:sub(#vprefix + 1)

+   else

+     return vstring

+   end

+ end

+ 

+ -- Check if an identified url is sane

+ local function check_forge_url(url, id, silent)

+   local checkedurl  = nil

+   local checkedid   = nil

+   local urlpatterns = {

+     ["gitlab"] = {

+       ["pattern"]     = 'https://[^/]+/[^/]+/[^/#?]+',

+       ["description"] = 'https://(…[-.])gitlab[-.]…/owner/repo'},

+     ["pagure"] = {

+       ["pattern"]     = 'https://[^/]+/[^/#?]+',

+       ["description"] = 'https://pagure.io/repo'},

+     ["pagure_ns"] = {

+       ["pattern"]     = 'https://[^/]+/[^/]+/[^/#?]+',

+       ["description"] = 'https://pagure.io/namespace/repo'},

+     ["pagure_fork"] = {

+       ["pattern"]     = 'https://[^/]+/fork/[^/]+/[^/#?]+',

+       ["description"] = 'https://pagure.io/fork/owner/repo'},

+     ["pagure_ns_fork"] = {

+       ["pattern"]     = 'https://[^/]+/fork/[^/]+/[^/]+/[^/#?]+',

+       ["description"] = 'https://pagure.io/fork/owner/namespace/repo'},

+     ["gitea.com"] = {

+       ["pattern"]     = 'https://[^/]+/[^/]+/[^/#?]+',

+       ["description"] = 'https://gitea.com/owner/repo'},

+     ["github"] = {

+       ["pattern"]     = 'https://[^/]+/[^/]+/[^/#?]+',

+       ["description"] = 'https://(…[-.])github[-.]…/owner/repo'},

+     ["code.googlesource.com"] = {

+       ["pattern"]     = 'https://code.googlesource.com/[^#?]*[^/#?]+',

+       ["description"] = 'https://code.googlesource.com/…/repo'},

+     ["bitbucket.org"] = {

+       ["pattern"]     = 'https://[^/]+/[^/]+/[^/#?]+',

+       ["description"] = 'https://bitbucket.org/owner/repo'}}

+   if (urlpatterns[id] ~= nil) then

+     checkedurl = url:match(urlpatterns[id]["pattern"])

+     if (checkedurl == nil) then

+       if not silent then

+         fedora.error(id .. " URLs must match " ..

+                      urlpatterns[id]["description"] .. "!")

+       end

+     else

+       checkedid = id

+     end

+   end

+   return checkedurl, checkedid

+ end

+ 

+ -- Check if an url matches a known forge

+ local function idforge(url, silent)

+   local forge_url = nil

+   local forge    = nil

+   if (url ~= "") then

+     forge = url:match("^[^:]+://([^/]+)/")

+     if not forge then

+       if not silent then

+         fedora.error([[

+ URLs must include a protocol such as https:// and a path starting with /. Read:

+ ]] .. url)

+       end

+     else

+       if (forge == "pagure.io") then

+         if     url:match("[^:]+://pagure.io/fork/[^/]+/[^/]+/[^/]+") then

+           forge = "pagure_ns_fork"

+         elseif url:match("[^:]+://pagure.io/fork/[^/]+/[^/]+") then

+           forge = "pagure_fork"

+         elseif url:match("[^:]+://pagure.io/[^/]+/[^/]+") then

+           forge = "pagure_ns"

+         elseif url:match("[^:]+://pagure.io/[^/]+") then

+           forge = "pagure"

+         end

+       elseif forge:match("^gitlab[%.-]") or forge:match("[%.-]gitlab[%.]") then

+         forge = "gitlab"

+       elseif forge:match("^github[%.-]") or forge:match("[%.-]github[%.]") then

+         forge = "github"

+       end

+       forge_url, forge = check_forge_url(url, forge, silent)

+     end

+   end

+   return forge_url, forge

+ end

+ 

+ -- rpm variable radicals

+ local rads = {

+   -- Elements that will be pushed SRPM-level

+   ["source"] = {"version", "url"},

+   ["forge"]  = {

+     -- key variables that may control a declaration block

+     ["key"]      = {"url"},

+     -- variables, used to compute a SCM reference

+     ["ref"]      = {"tag", "commit", "branch", "version", "ref"},

+     -- other computed or recomputed variables

+     ["computed"] = {"tag", "source", "source_suffix", "setup_arguments",

+                     "patch_mode", "patch_level", "extract_dir",

+                     "time", "date", "file_ref"},},

+ }

+ 

+ -- Return all the suffixes for which one of the forge key variables is set

+ local function suffixes()

+   return fedora.all_suffixes(fedora.qualify(rads["forge"]["key"], "forge"))

+ 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 readflag() to process rpm flag arguments safely.

+ --     — otherwise execute f for the specified index value only.

+ --   – f is passed index then otherargs as arguments.

+ --   – the index range is controlled by suffixes()

+ local function floop(f, index, otherargs)

+   auto.floop(f, index, suffixes(), otherargs)

+ end

+ 

+ -- forge variable derivation patterns

+ local function rules(suffix)

+   local R = {

+   ["default"] = {

+     ["scm"]           = "git",

+     ["archive_extension"]  = "tar.bz2",

+     ["repo"]          = '%{lua:print(rpm.expand("%{forge_url' .. suffix .. '}"):match("^[^:]+://[^/]+/[^/]+/([^/?#]+)"))}',

+     ["archive_name"]  = "%{forge_repo"         .. suffix .. "}-%{forge_ref" .. suffix .. "}",

+     ["top_dir"]       = "%{forge_archive_name" .. suffix .. "}" },

+   ["gitlab"] = {

+     ["source"]  = "%{forge_url" .. suffix .. "}/-/archive/%{forge_ref" .. suffix .. "}/%{forge_archive_name" .. suffix .. "}.%{forge_archive_extension" .. suffix .. "}" },

+   ["pagure"] = {

+     ["archive_extension"]  = "tar.gz",

+     ["repo"]          = '%{lua:print(rpm.expand("%{forge_url' .. suffix .. '}"):match("^[^:]+://[^/]+/([^/?#]+)"))}',

+     ["source"]        = "%{forge_url" .. suffix ..   "}/archive/%{forge_ref" .. suffix .. "}/%{forge_archive_name" .. suffix .. "}.%{forge_archive_extension" .. suffix .. "}" },

+   ["pagure_ns"] = {

+     ["archive_extension"]  = "tar.gz",

+     ["namespace"]    = '%{lua:print(rpm.expand("%{forge_url' .. suffix .. '}"):match("^[^:]+://[^/]+/([^/]+)/[^/?#]+"))}',

+     ["repo"]         = '%{lua:print(rpm.expand("%{forge_url' .. suffix .. '}"):match("^[^:]+://[^/]+/[^/]+/([^/?#]+)"))}',

+     ["archive_name"] = "%{forge_namespace" .. suffix .. "}-%{forge_repo" .. suffix .. "}-%{forge_ref" .. suffix .. "}",

+     ["source"]       = "%{forge_url" .. suffix .. "}/archive/%{forge_ref"   .. suffix .. "}/%{forge_archive_name" .. suffix .. "}.%{forge_archive_extension" .. suffix .. "}" },

+   ["pagure_fork"] = {

+     ["archive_extension"]  = "tar.gz",

+     ["owner"]        = '%{lua:print(rpm.expand("%{forge_url' .. suffix .. '}"):match("https://[^/]+/fork/([^/]+)/[^/?#]+"))}',

+     ["repo"]         = '%{lua:print(rpm.expand("%{forge_url' .. suffix .. '}"):match("https://[^/]+/fork/[^/]+/([^/?#]+)"))}',

+     ["archive_name"] = "%{forge_owner" .. suffix .. "}-%{forge_repo" .. suffix .. "}-%{forge_ref" .. suffix .. "}",

+     ["source"]  = "%{forge_url" .. suffix .. "}/archive/%{forge_ref" .. suffix .. "}/%{forge_archive_name" .. suffix .. "}.%{forge_archive_extension" .. suffix .. "}" },

+   ["pagure_ns_fork"] = {

+     ["owner"]        = '%{lua:print(rpm.expand("%{forge_url' .. suffix .. '}"):match("https://[^/]+/fork/([^/]+)/[^/]+/[^/?#]+"))}',

+     ["namespace"]    = '%{lua:print(rpm.expand("%{forge_url' .. suffix .. '}"):match("https://[^/]+/fork/[^/]+/([^/]+)/[^/?#]+")}',

+     ["repo"]         = '%{lua:print(rpm.expand("%{forge_url' .. suffix .. '}"):match("https://[^/]+/fork/[^/]+/[^/]+/([^/?#]+)")}',

+     ["archive_name"] = "%{forge_owner" .. suffix .. "}-%{forge_namespace" .. suffix .. "}-%{forge_repo" .. suffix .. "}-%{forge_ref" .. suffix .. "}",

+     ["source"]       = "%{forge_url" .. suffix .. "}/archive/%{forge_ref" .. suffix .. "}/%{forge_archive_name" .. suffix .. "}.%{forge_archive_extension" .. suffix .. "}" },

+   ["gitea.com"]  = {

+     ["archive_extension"]  = "tar.gz",

+     ["archive_name"]       = "%{forge_file_ref" .. suffix .. "}",

+     ["source"]             = "%{forge_url" .. suffix .. "}/archive/%{forge_ref" .. suffix .. "}.%{forge_archive_extension" .. suffix .. "}",

+     ["top_dir"]            = "%{forge_repo}" },

+   ["github"] = {

+     ["archive_extension"]  = "tar.gz",

+     ["archive_name"]       = "%{forge_repo" .. suffix .. "}-%{forge_file_ref" .. suffix .. "}",

+     ["source"]             = "%{forge_url"  .. suffix .. "}/archive/%{forge_ref" .. suffix .. "}/%{forge_archive_name" .. suffix .. "}.%{forge_archive_extension" .. suffix .. "}" },

+   ["code.googlesource.com"] = {

+     ["archive_extension"]  = "tar.gz",

+     ["repo"]               = '%{lua:print(rpm.expand("%{forge_url' .. suffix .. '}"):match("^[^:]+://.+/([^/?#]+)"))}',

+     ["source"]             = "%{forge_url" .. suffix .. "}/+archive/%{forge_ref" .. suffix .. "}.%{forge_archive_extension"  .. suffix .. "}",

+     ["top_dir"]            = "" },

+   ["bitbucket.org"] = {

+     ["short_commit"] = '%{lua:print(string.sub(rpm.expand("%{forge_commit' .. suffix .. '}"), 1, 12))}',

+     ["owner"]        = '%{lua:print(rpm.expand("%{forge_url' .. suffix .. '}"):match("^[^:]+://[^/]+/([^/?#]+)"))}',

+     ["archive_name"] = "%{forge_owner" .. suffix .. "}-%{forge_repo" .. suffix .. "}-%{forge_short_commit" .. suffix .. "}",

+     ["source"]       = "%{forge_url" .. suffix .. "}/get/%{forge_ref" .. suffix .. "}.%{forge_archive_extension"  .. suffix .. "}" } }

+   return R

+ end

+ 

+ -- Returns forge radicals

+ local function radicals(suffix)

+   local R = {}

+   for k, v in pairs(rads["forge"]) do

+     R[k] = v

+   end

+   R["rules"] = {}

+   for _, v in pairs(rules(suffix)) do

+     local l = {}

+     for k, _ in pairs(v) do

+       table.insert(l, k)

+     end

+     R["rules"] = fedora.mergelists({R["rules"], l})

+   end

+   R["computed"] = fedora.mergelists({R["computed"], R["key"], R["rules"]})

+   local all = {}

+   for k, v in pairs(R) do

+     all = fedora.mergelists({all, v})

+   end

+   R["all"] = all

+   return R

+ end

+ 

+ -- %forge_init core

+ local function init(suffix, verbose, informative, silent)

+   auto.id('forge.init("' .. suffix .. '")')

+   local myrads = radicals(suffix)

+   print([[

+ # forge_init ]] .. suffix .. [[

+ ]])

+   local spec = {}

+   for _, v in ipairs(fedora.qualify(myrads["all"], "forge")) do

+     spec[v] = fedora.read(v .. suffix)

+   end

+   -- Compute the reference of the object to fetch

+   if not (spec["forge_tag"] or spec["forge_commit"] or spec["forge_branch"] or

+           spec["forge_version"]) then

+     fedora.error([[

+ You need to set one of:

+   – %%{forge_tag]]     .. suffix .. [[}

+   – %%{forge_commit]]  .. suffix .. [[}

+ with your:

+ %%{forge_url]] .. suffix .. [[} %{?forge_url]] .. suffix .. [[}

+ declaration.

+ ]])

+   end

+   local keep_version =  "true"

+   local keep_file_ref = "true"

+   local forge_url = spec["forge_url"]

+   local forge

+   forge_url, forge = idforge(forge_url, silent)

+   if forge then

+     if (forge == "github") or (forge == "code.googlesource.com") then

+       keep_version = "false"

+     elseif (forge == "bitbucket.org") and not spec["forge_commit"] then

+       fedora.error("All BitBucket URLs require commit value knowledge: " ..

+                    "you need to set %{forge_commit}!")

+     end

+     if (forge == "github") then

+       keep_file_ref = "false"

+     end

+   end

+   local ref = [[%{lua:

+     local       fedora = require "fedora.common"

+     local       suffix = "]] .. suffix       .. [["

+     local keep_version = "]] .. keep_version .. [["

+     local r = "tag"

+     for _, k in ipairs({"tag", "commit", "branch", "version"}) do

+       if fedora.read("forge_" .. k .. suffix) then

+         r = k

+         break

+       end

+     end

+     if (r == "version") and

+        not (keep_version == "true") then

+       r = "v%{forge_" .. r .. suffix .. "}"

+     else

+       r =  "%{forge_" .. r .. suffix .. "}"

+     end

+     print(r)

+     }]]

+   local file_ref = [[%{lua:

+     local        fedora = require "fedora.common"

+     local           ref = [=[]] .. ref           .. [[]=]

+     local        suffix =   "]] .. suffix        .. [["

+     local keep_file_ref =   "]] .. keep_file_ref .. [["

+     local f = fedora.expand(ref)

+     local c = fedora.read("forge_commit" .. suffix)

+     if (not (c and (c == f))) and

+         f:match("^v[%d]") and

+         not (keep_file_ref == "true") then

+       f = f:gsub("^v", "")

+     end

+     f = f:gsub("/", "-")

+     print(f)

+     }]]

+   fedora.mset(myrads["all"], "forge", suffix,

+     { { ["url"]      = forge_url,

+         ["ref"]      = ref,

+         ["file_ref"] = file_ref },

+       rules(suffix)[forge], rules(suffix)["default"] }, verbose)

+   -- Update lua copy with the result

+   for _, v in ipairs(fedora.qualify(myrads["rules"], "forge")) do

+     spec[v] = fedora.read(v .. suffix)

+   end

+   -- Source URL processing

+   local source = "%{forge_source" .. suffix .. "}"

+   local archive_file = "%{forge_archive_name" .. suffix ..

+                        "}.%{forge_archive_extension" .. suffix .. "}"

+   if (fedora.expand(source):match("/([^/]+)$")

+       ~= fedora.expand(archive_file)) then

+     source = source .. "#/" .. archive_file

+   end

+   -- Setup processing

+   local source_suffix = [[%{lua:

+     local fedora = require "fedora.common"

+     print(fedora.source_suffix("%{forge_source]] .. suffix .. [[}"))

+   }]]

+   local extract_dir

+   local setup_arguments = "-n %{forge_extract_dir" .. suffix .. "}"

+   if not spec["forge_top_dir"] then

+     extract_dir = "%{forge_archive_name"  .. suffix .. "}"

+     setup_arguments   = "-T -D -a " ..

+                         "%{forge_source_suffix" .. suffix .. "} " ..

+                         "-c " .. setup_arguments

+   else

+     extract_dir = "%{forge_top_dir" .. suffix .. "}"

+     setup_arguments   = "-T -D -b " ..

+                         "%{forge_source_suffix" .. suffix .. "} " ..

+                         setup_arguments

+   end

+   local time

+   if spec["forge_date"] then

+     time = [[%{lua:

+       local fedora = require "fedora.common"

+       local suffix = "]] .. suffix .. [["

+       local   date = fedora.read("forge_date" .. suffix)

+       if date and (date ~= "") then

+         rpm.expand("%(date -u --iso-8601=seconds -d " .. date .. ")")

+       end

+     }]]

+   else

+     time = "%([ -r %{_sourcedir}/" .. archive_file .. " ] && " ..

+            "date -u --iso-8601=seconds -r %{_sourcedir}/" ..

+            archive_file .. ")"

+   end

+   local date = '%{?forge_time' .. suffix .. ':' ..

+                '%([[ -n "%{forge_time' .. suffix .. '}" ]] && ' ..

+                'date -u +%Y%m%d -d %{forge_time' .. suffix .. '})}'

+   fedora.mset(myrads["all"], "forge", suffix, {{

+       ["source"]            = source,

+       ["source_suffix"]     = source_suffix,

+       ["extract_dir"]       = extract_dir,

+       ["setup_arguments"]   = setup_arguments,

+       -- Due to the design of %apply_patch we will need to set %{__scm} from

+       -- %{forge_patch_modeX} later. Therefore, expand the fallback to avoid

+       -- loops and inter-block side effects

+       ["patch_mode"]        = fedora.read("__scm"),

+       ["patch_level"]       = "-p 1",

+       ["date"]              = date,

+       ["time"]              = time,

+     }}, verbose)

+   -- set srpm values if not set yet

+   fedora.alias(rads["source"], "forge", suffix, "source", "", verbose)

+   -- dist processing

+   local distprefix = [[%{lua:

+     local fedora = require "fedora.common"

+     local    ref = [=[]] .. ref    .. [[]=]

+     local suffix =   "]] .. suffix .. [["

+     local d = fedora.expand(ref)

+     local c = fedora.read("forge_commit" .. suffix)

+     if c and (c == d) then

+       d = d:sub(1, 7)

+     else

+       local forge = require "fedora.srpm.forge"

+       local     v = fedora.read("source_version")

+       if v then

+         if not v:match("%%") then

+           v = v:lower():gsub("[%p%s]+", ".")

+         end

+         if not d:match("%%") then

+           d = d:lower():gsub("[%p%s]+", ".")

+         end

+         for _, p in ipairs({'', 'v', 'v.', 'version', 'version.',

+                             'tags.v', 'tags.v.'}) do

+           d = forge.version_suffix(d, p .. v)

+         end

+       end

+     end

+     if (d ~= "") then

+       d = ".%{?forge_scm" .. suffix .. "}" ..

+           "%{?forge_date" .. suffix .. "}" .. d

+       d = fedora.expand(d)

+       if not d:match("%%") then

+         d = d:lower():gsub("[%p%s]+", ".")

+       end

+       print(d)

+     end

+   }]]

+   distprefix_suffix = fedora.suffix({

+     ["distprefix"] = distprefix}, true, verbose)

+   -- Final spec variable summary if the macro was called with -i

+   if informative then

+     fedora.echo("Variables read or set by %%forge_init")

+     fedora.echovars(fedora.qualify(myrads["all"], "forge"), suffix)

+     if distprefix_suffix then

+       fedora.echovars({"distprefix"}, distprefix_suffix)

+     end

+     fedora.echo([[

+ Note: unless explicitly set, snapshot timestamp will be computed once

+ %%{_sourcedir}/]] .. archive_file .. [[

+ 

+ is available.

+ ]])

+   end

+ end

+ 

+ -- post-init info that does not depend on a particular forge suffix

+ local function info_generic(informative)

+   if informative then

+     fedora.echo("Other variables, that may have been set by %%forge_init")

+     fedora.echovars(fedora.qualify(rads["source"], "source"), "")

+   end

+ end

+ 

+ -- %forge_sources core

+ local function source(suffix)

+   auto.id('forge.source("' .. suffix .. '")')

+   print(rpm.expand([[

+ %{?forge_source]] .. suffix .. [[}

+ ]]))

+ end

+ 

+ -- %forge_patches core

+ local function patchlist(suffix)

+   auto.id('forge.patchlist("' .. suffix .. '")')

+   print(rpm.expand([[

+ %{?forge_patchlist]] .. suffix .. "}"))

+ end

+ 

+ local function env(suffix, verbose)

+   local myrads = radicals(suffix)

+   fedora.set_current(fedora.qualify(myrads["all"], "forge"), suffix,

+                      verbose)

+   fedora.set_verbose(verbose)

+ end

+ 

+ return {

+   version_suffix = version_suffix,

+   floop          = floop,

+   init           = init,

+   info_generic   = info_generic,

+   env            = env,

+   source         = source,

+   patchlist      = patchlist,

+ }

file removed
-312
@@ -1,312 +0,0 @@ 

- -- Lua code used by macros.forge and derivatives

- 

- -- Computes the suffix of a version string, removing vprefix if it matches

- -- For example with vprefix 1.2.3: 1.2.3.rc2 → .rc2 but 1.2.30 → 1.2.30 not 0

- local function getversionsuffix(vstring,vprefix)

-   if (string.sub(vstring, 1, #vprefix) == vprefix) and

-      (not string.match(string.sub(vstring, #vprefix + 1), "^%.?%d")) then

-     return string.sub(vstring, #vprefix + 1)

-   else

-     return vstring

-   end

- end

- 

- -- Check if an identified url is sane

- local function checkforgeurl(url, id, silent)

-   local checkedurl  = nil

-   local checkedid   = nil

-   local urlpatterns = {

-     gitlab = {

-       pattern     = 'https://[^/]+/[^/]+/[^/#?]+',

-       description = 'https://(…[-.])gitlab[-.]…/owner/repo'},

-     pagure = {

-       pattern     = 'https://[^/]+/[^/#?]+',

-       description = 'https://pagure.io/repo'},

-     pagure_ns = {

-       pattern     = 'https://[^/]+/[^/]+/[^/#?]+',

-       description = 'https://pagure.io/namespace/repo'},

-     pagure_fork = {

-       pattern     = 'https://[^/]+/fork/[^/]+/[^/#?]+',

-       description = 'https://pagure.io/fork/owner/repo'},

-     pagure_ns_fork = {

-       pattern     = 'https://[^/]+/fork/[^/]+/[^/]+/[^/#?]+',

-       description = 'https://pagure.io/fork/owner/namespace/repo'},

-     ["gitea.com"] = {

-       pattern     = 'https://[^/]+/[^/]+/[^/#?]+',

-       description = 'https://gitea.com/owner/repo'},

-     github = {

-       pattern     = 'https://[^/]+/[^/]+/[^/#?]+',

-       description = 'https://(…[-.])github[-.]…/owner/repo'},

-     ["code.googlesource.com"] = {

-       pattern     = 'https://code.googlesource.com/[^#?]*[^/#?]+',

-       description = 'https://code.googlesource.com/…/repo'},

-     ["bitbucket.org"] = {

-       pattern     = 'https://[^/]+/[^/]+/[^/#?]+',

-       description = 'https://bitbucket.org/owner/repo'}}

-   if (urlpatterns[id] ~= nil) then

-     checkedurl = string.match(url,urlpatterns[id]["pattern"])

-     if (checkedurl == nil) then

-       if not silent then

-         rpm.expand("%{error:" .. id .. " URLs must match " .. urlpatterns[id]["description"] .. " !}")

-       end

-     else

-       checkedid = id

-     end

-   end

-   return checkedurl, checkedid

- end

- 

- -- Check if an url matches a known forge

- local function idforge(url, silent)

-   local forgeurl = nil

-   local forge    = nil

-   if (url ~= "") then

-     forge = string.match(url, "^[^:]+://([^/]+)/")

-     if (forge == nil) then

-       if not silent then

-         rpm.expand("%{error:URLs must include a protocol such as https:// and a path starting with / !}")

-       end

-     else

-       if (forge == "pagure.io") then

-         if     string.match(url, "[^:]+://pagure.io/fork/[^/]+/[^/]+/[^/]+") then

-           forge = "pagure_ns_fork"

-         elseif string.match(url, "[^:]+://pagure.io/fork/[^/]+/[^/]+") then

-           forge = "pagure_fork"

-         elseif  string.match(url, "[^:]+://pagure.io/[^/]+/[^/]+") then

-           forge = "pagure_ns"

-         elseif  string.match(url, "[^:]+://pagure.io/[^/]+") then

-           forge = "pagure"

-         end

-       elseif (string.match(forge, "^gitlab[%.-]") or string.match(forge, "[%.-]gitlab[%.]")) then

-         forge = "gitlab"

-       elseif (string.match(forge, "^github[%.-]") or string.match(forge, "[%.-]github[%.]")) then

-         forge = "github"

-       end

-       forgeurl, forge = checkforgeurl(url, forge, silent)

-     end

-   end

-   return forgeurl, forge

- end

- 

- -- The forgemeta macro main processing function

- -- See the documentation in the macros.forge file for argument description

- -- Also called directly by gometa

- local function meta(suffix, verbose, informative, silent)

-   local fedora = require "fedora.common"

-   local ismain = (suffix == "") or (suffix == "0")

-   if ismain then

-     fedora.zalias({"forgeurl", "forgesource", "forgesetupargs",

-                       "archivename", "archiveext", "archiveurl",

-                       "topdir", "extractdir", "repo", "owner", "namespace",

-                       "scm", "tag", "commit", "shortcommit", "branch", "version",

-                       "date", "distprefix"}, verbose)

-   end

-   local variables = {

-     default = {

-       scm         = "git",

-       archiveext  = "tar.bz2",

-       repo        = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "^[^:]+://[^/]+/[^/]+/([^/?#]+)"))}',

-       archivename = "%{repo"         .. suffix .. "}-%{ref"           .. suffix .. "}",

-       topdir      = "%{archivename"  .. suffix .. "}" },

-     gitlab = {

-       archiveurl  = "%{forgeurl"     .. suffix .. "}/-/archive/%{ref" .. suffix .. "}/%{archivename" .. suffix .. "}.%{archiveext" .. suffix .. "}" },

-     pagure = {

-       archiveext  = "tar.gz",

-       repo        = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "^[^:]+://[^/]+/([^/?#]+)"))}',

-       archiveurl  = "%{forgeurl"     .. suffix .. "}/archive/%{ref"   .. suffix .. "}/%{archivename" .. suffix .. "}.%{archiveext" .. suffix .. "}" },

-     pagure_ns = {

-       archiveext  = "tar.gz",

-       namespace   = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "^[^:]+://[^/]+/([^/]+)/[^/?#]+"))}',

-       repo        = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "^[^:]+://[^/]+/[^/]+/([^/?#]+)"))}',

-       archivename = "%{namespace"    .. suffix .. "}-%{repo"          .. suffix .. "}-%{ref"         .. suffix .. "}",

-       archiveurl  = "%{forgeurl"     .. suffix .. "}/archive/%{ref"   .. suffix .. "}/%{archivename" .. suffix .. "}.%{archiveext" .. suffix .. "}" },

-     pagure_fork = {

-       archiveext  = "tar.gz",

-       owner       = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "https://[^/]+/fork/([^/]+)/[^/?#]+"))}',

-       repo        = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "https://[^/]+/fork/[^/]+/([^/?#]+)"))}',

-       archivename = "%{owner"        .. suffix .. "}-%{repo"          .. suffix .. "}-%{ref"         .. suffix .. "}",

-       archiveurl  = "%{forgeurl"     .. suffix .. "}/archive/%{ref"   .. suffix .. "}/%{archivename" .. suffix .. "}.%{archiveext" .. suffix .. "}" },

-     pagure_ns_fork = {

-       owner       = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "https://[^/]+/fork/([^/]+)/[^/]+/[^/?#]+"))}',

-       namespace   = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "https://[^/]+/fork/[^/]+/([^/]+)/[^/?#]+")}',

-       repo        = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "https://[^/]+/fork/[^/]+/[^/]+/([^/?#]+)")}',

-       archivename = "%{owner"        .. suffix .. "}-%{namespace"     .. suffix .. "}-%{repo"        .. suffix .. "}-%{ref"        .. suffix .. "}",

-       archiveurl  = "%{forgeurl"     .. suffix .. "}/archive/%{ref"   .. suffix .. "}/%{archivename" .. suffix .. "}.%{archiveext" .. suffix .. "}" },

-     ["gitea.com"] = {

-       archiveext  = "tar.gz",

-       archivename = "%{fileref"      .. suffix .. "}",

-       archiveurl  = "%{forgeurl"     .. suffix .. "}/archive/%{ref"   .. suffix .. "}.%{archiveext" .. suffix .. "}",

-       topdir      = "%{repo}" },

-     github = {

-       archiveext  = "tar.gz",

-       archivename = "%{repo"         .. suffix .. "}-%{fileref"       .. suffix .. "}",

-       archiveurl  = "%{forgeurl"     .. suffix .. "}/archive/%{ref"   .. suffix .. "}/%{archivename" .. suffix .. "}.%{archiveext" .. suffix .. "}" },

-     ["code.googlesource.com"] = {

-       archiveext  = "tar.gz",

-       repo        = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "^[^:]+://.+/([^/?#]+)"))}',

-       archiveurl  = "%{forgeurl"     .. suffix .. "}/+archive/%{ref"  .. suffix .. "}.%{archiveext"  .. suffix .. "}",

-       topdir      = "" },

-     ["bitbucket.org"] = {

-       shortcommit = '%{lua:print(string.sub(rpm.expand("%{commit'     .. suffix .. '}"), 1, 12))}',

-       owner       = '%{lua:print(string.match(rpm.expand("%{forgeurl' .. suffix .. '}"), "^[^:]+://[^/]+/([^/?#]+)"))}',

-       archivename = "%{owner"        .. suffix .. "}-%{repo"          .. suffix .. "}-%{shortcommit" .. suffix .. "}",

-       archiveurl  = "%{forgeurl"     .. suffix .. "}/get/%{ref"       .. suffix .. "}.%{archiveext"  .. suffix .. "}" } }

-   -- Packaging a moving branch is quite a bad idea, but since at least Gitlab

-   -- will treat branches and tags the same way better support branches explicitly

-   -- than have packagers hijack %{tag} to download branch states

-   local spec = {}

-   for _, v in ipairs({'forgeurl','tag','commit','branch','version'}) do

-     spec[v] = rpm.expand("%{?" .. v .. suffix .. "}")

-   end

-   -- Compute the reference of the object to fetch

-   local isrelease = false

-   if     (spec["tag"]     ~= "") then       ref = "%{?tag"     .. suffix .. "}"

-   elseif (spec["commit"]  ~= "") then       ref = "%{?commit"  .. suffix .. "}"

-   elseif (spec["branch"]  ~= "") then       ref = "%{?branch"  .. suffix .. "}"

-   else                                      ref = "%{?version" .. suffix .. "}"

-                                       isrelease = true

-   end

-   if (rpm.expand(ref) == "") then

-     if (suffix == "") then

-       rpm.expand("%{error:You need to define Version:, %{commit} or %{tag} before the macro invocation !}")

-     else

-       rpm.expand("%{error:You need to define %{version" .. suffix .. "}, %{commit" .. suffix .. "} or %{tag" .. suffix .. "} before the macro invocation !}")

-     end

-   end

-   local    forgeurl = spec["forgeurl"]

-   -- For backwards compatibility only

-   local expliciturl = rpm.expand("%{?-u*}")

-   if   (expliciturl ~= "") then

-     rpm.expand("%{warn:-u use in %%forgemeta is deprecated, use -z instead to select a separate set of rpm variables!}")

-            forgeurl = expliciturl

-   end

-   local forge

-   forgeurl,   forge = idforge(forgeurl, silent)

-   if (forge ~= nil) then

-     fedora.explicitset("forgeurl" .. suffix, forgeurl, verbose)

-     -- Custom processing of quirky forges that can not be handled with simple variables

-     if (forge == "github") then

-       -- Workaround the way GitHub injects "v"s before some version strings (but not all!)

-       -- To package one of the minority of sane GitHub projects that do not munge their version

-       -- strings set tag to %{version} in your spec

-       local fileref = ref

-       if (ref == "%{?version"  .. suffix .. "}") then

-         ref = "v" .. ref

-       elseif (fileref ~= "%{?commit" .. suffix .. "}") and

-              string.match(rpm.expand(fileref), "^v[%d]") then

-         fileref = string.gsub(rpm.expand(fileref), "^v", "")

-       elseif (string.match(rpm.expand(fileref), "/")) then

-         fileref = string.gsub(rpm.expand(fileref), "/", "-")

-       end

-       fedora.safeset("fileref" .. suffix, fileref, verbose)

-     elseif (forge == "gitea.com") then

-       -- Workaround the way gitea mangles /s in ref names

-       local fileref = ref

-       fileref = string.gsub(rpm.expand(fileref), "/", "-")

-       fedora.safeset("fileref" .. suffix, fileref, verbose)

-     elseif (forge == "code.googlesource.com") then

-       if (ref == "%{?version"  .. suffix .. "}") then

-         ref = "v" .. ref

-       end

-     elseif (forge == "bitbucket.org") then

-       if (spec["commit"] == "") then

-         rpm.expand("%{error:All BitBucket URLs require commit value knowledge: you need to define %{commit}!}")

-       end

-     end

-     fedora.safeset("ref" .. suffix, ref, verbose)

-     -- Mass setting of the remaining variables

-     for k,v in pairs(variables[forge]) do

-       fedora.safeset(k .. suffix, variables[forge][k], verbose)

-     end

-     for k,v in pairs(variables["default"]) do

-       if (variables[forge][k] == nil) then

-         fedora.safeset(k .. suffix, variables["default"][k], verbose)

-       end

-     end

-   end

-   -- Generic rules

-   for _, v in ipairs({'archiveurl','archivename','archiveext','topdir'}) do

-     spec[v] = rpm.expand("%{?" .. v .. suffix .. "}")

-   end

-   -- Source URL processing (computing the forgesource spec variable)

-   local forgesource = "%{archiveurl" .. suffix .. "}"

-   if (string.match(spec["archiveurl"], "/([^/]+)$") ~= spec["archivename"] .. "." .. spec["archiveext"]) then

-     forgesource     = "%{?archiveurl" .. suffix .. "}#/%{?archivename" .. suffix .. "}.%{archiveext" .. suffix .. "}"

-   end

-   fedora.safeset("forgesource" .. suffix, forgesource, verbose)

-   -- Setup processing      (computing the forgesetup and extractdir variables)

-   local forgesetupargs = "-n %{extractdir" .. suffix .. "}"

-   local extractdir     = "%{topdir"        .. suffix .. "}"

-   if (spec["topdir"] == "") then

-     forgesetupargs     = "-c " .. forgesetupargs

-     extractdir         = "%{archivename"   .. suffix .. "}"

-   end

-   if not ismain then

-     if (spec["topdir"] ~= "") then

-       forgesetupargs = "-T -D -b " .. suffix .. " " .. forgesetupargs

-     else

-       forgesetupargs = "-T -D -a " .. suffix .. " " .. forgesetupargs

-     end

-   end

-   fedora.safeset("forgesetupargs" .. suffix, forgesetupargs, verbose)

-   fedora.safeset("extractdir"     .. suffix, extractdir, verbose)

-   -- dist processing       (computing the correct prefix for snapshots)

-   local distprefix = ""

-   if not isrelease then

-     distprefix = string.lower(rpm.expand(ref))

-     if     (ref == "%{?commit" .. suffix .. "}") then

-       distprefix = string.sub(distprefix, 1, 7)

-     elseif (ref ~= "%{?branch" .. suffix .. "}") then

-       distprefix = string.gsub(distprefix,      "[%p%s]+", ".")

-       distprefix = string.gsub(distprefix, "^" .. string.lower(rpm.expand("%{?repo}")) .. "%.?", "")

-       local    v = string.gsub(rpm.expand("%{version}"), "[%p%s]+", ".")

-       for _, p in ipairs({'','v','v.','version','version.','tags.v', 'tags.v.'}) do

-         distprefix = getversionsuffix(distprefix, p .. v)

-       end

-       distprefix = string.gsub(distprefix, "^%.", "")

-     end

-     if (distprefix ~= "") then

-       distprefix = "%{scm"     .. suffix .. "}" .. distprefix

-       date = rpm.expand("%{?date" .. suffix .. "}")

-       if (date ~= "") then

-         distprefix = date .. distprefix

-       else

-         distprefix = "%([ -r %{_sourcedir}/%{archivename" .. suffix .. "}.%{archiveext" .. suffix .. "} ] && date +%Y%m%d -u -r %{_sourcedir}/%{archivename" .. suffix .. "}.%{archiveext" .. suffix .. "})" .. distprefix

-       end

-       distprefix = "." .. distprefix

-     end

-   end

-   if (spec["version"] ~= "") and

-      (spec["version"] ~= "0") and

-      (spec["version"] ~= rpm.expand("%{?version}")) then

-     distprefix = ".%{version" .. suffix .. "}" .. distprefix

-   end

-   if (rpm.expand(distprefix) ~= "") then

-     if not ismain then

-       distprefix = string.gsub(distprefix, "^%.", ".s")

-     end

-     fedora.safeset ("distprefix"    .. suffix, distprefix, verbose)

-   end

-   if ismain then

-     fedora.zalias({"forgeurl", "forgesource", "forgesetupargs",

-                       "archivename", "archiveext", "archiveurl",

-                       "topdir", "extractdir", "repo", "owner", "namespace",

-                       "scm", "shortcommit", "distprefix"}, verbose)

-   end

-   -- Final spec variable summary if the macro was called with -i

-   if informative then

-     rpm.expand("%{echo:Packaging variables read or set by %%forgemeta}")

-     fedora.echovars({"forgeurl", "forgesource", "forgesetupargs",

-                         "archivename", "archiveext", "archiveurl",

-                         "topdir", "extractdir", "repo", "owner", "namespace",

-                         "scm", "tag", "commit", "shortcommit", "branch", "version",

-                         "date", "distprefix"}, suffix)

-     fedora.echovars({"dist"},"")

-     rpm.expand("%{echo:  (snapshot date is either manually supplied or computed once %%{_sourcedir}/%%{archivename" .. suffix .. "}.%%{archiveext" .. suffix .. "} is available)}")

-   end

- end

- 

- return {

-   meta = meta,

- }

- 

@@ -0,0 +1,73 @@ 

+ -- Lua code used by macros.forge_deprecated-srpm

+ 

+ local fedora = require "fedora.common"

+ local   auto = require "fedora.auto"

+ 

+ local function suffixes()

+   return fedora.suffixes("forgeurl")

+ end

+ 

+ local function floop(f, index, otherargs)

+   auto.floop(f, index, suffixes(), otherargs)

+ end

+ 

+ local changed = {

+   ["forgeurl"]       = "forge_url",

+   ["forgesource"]    = "forge_source",

+   ["forgesetupargs"] = "forge_setup_arguments",

+   ["shortcommit"]    = "forge_short_commit",

+   ["extractdir"]     = "forge_extract_dir",

+   ["topdir"]         = "forge_top_dir",

+   ["archivename"]    = "forge_archive_name",

+   ["archiveext"]     = "forge_archive_extension",

+   ["archiveurl"]     = "forge_source",

+   ["fileref"]        = "forge_file_ref"

+ }

+ 

+ local namespaced = {"scm", "ref", "tag", "commit", "version", "branch",

+                     "owner", "repo", "namespace", "date"}

+ 

+ -- %forge_deprecated_init core

+ local function init(suffix, verbose)

+   auto.id('forge_deprecated.init("' .. suffix .. '")')

+   fedora.warning([[

+ Aliasing deprecated variable names to “forge_” variables. This aliasing will be

+ removed.]])

+   local ismain = (suffix == "") or (suffix == "0")

+   if ismain then

+     olds = {}

+     for old, _ in pairs(changed) do

+       table.insert(olds, old)

+     end

+     fedora.zalias(olds, verbose)

+     fedora.zalias(namespaced, verbose)

+   end

+   for old, new in pairs(changed) do

+     fedora.safeset(new .. suffix, fedora.ref(old .. suffix), verbose)

+   end

+   fedora.alias(namespaced, "", suffix, "forge", suffix, verbose)

+ end

+ 

+ local function post_init(suffix, verbose)

+   auto.id('forge_deprecated.post_init("' .. suffix .. '")')

+   local ismain = (suffix == "") or (suffix == "0")

+   for old, new in pairs(changed) do

+     fedora.safeset(old .. suffix, fedora.ref(new .. suffix), verbose)

+   end

+   fedora.alias(namespaced, "forge", suffix, "", suffix, verbose)

+   if ismain then

+     olds = {}

+     for old, _ in pairs(changed) do

+       table.insert(olds, old)

+     end

+     fedora.zalias(olds, verbose)

+     fedora.zalias(namespaced, verbose)

+   end

+ end

+ 

+ 

+ return {

+   floop     = floop,

+   init      = init,

+   post_init = post_init,

+ }

file added
+73
@@ -0,0 +1,73 @@ 

+ # Automated packaging framework, safe to use after the SRPM build stage

+ 

+ # Macro registration is described in macros.auto-srpm

+ 

+ # Executes automated packaging macros in the %prep section

+ # Control variables, flags and arguments:

+ #   -v               be verbose

+ %auto_prep(v) %{lua:

+ local      fedora = require "fedora.common"

+ local        auto = require "fedora.auto"

+ local     verbose = fedora.hasflag("v")

+ auto.exec("auto_prep", verbose)

+ }

+ 

+ # Executes automated packaging macros in the %generate_buildrequires section

+ # <name> macros registered for %auto_pkg execution must make sure to ignore

+ # verbosity flags or process them in a way that does not interfere with the

+ # way %generate_buildrequires captures stdout

+ %auto_generate_buildrequires() %{lua:

+ local      fedora = require "fedora.common"

+ local        auto = require "fedora.auto"

+ auto.exec("auto_generate_buildrequires", false)

+ }

+ 

+ # Executes automated packaging macros in the %build section

+ # Control variables, flags and arguments:

+ #   -v               be verbose

+ %auto_build(v) %{lua:

+ local      fedora = require "fedora.common"

+ local        auto = require "fedora.auto"

+ local     verbose = fedora.hasflag("v")

+ auto.exec("auto_build", verbose)

+ }

+ 

+ # Executes automated packaging macros in the %install section

+ # Control variables, flags and arguments:

+ #   -v               be verbose

+ %auto_install(v) %{lua:

+ local      fedora = require "fedora.common"

+ local        auto = require "fedora.auto"

+ local     verbose = fedora.hasflag("v")

+ auto.exec("auto_install", verbose)

+ }

+ 

+ # Executes automated packaging macros in the %check section

+ # Control variables, flags and arguments:

+ #   -v               be verbose

+ %auto_check(v) %{lua:

+ local      fedora = require "fedora.common"

+ local        auto = require "fedora.auto"

+ local     verbose = fedora.hasflag("v")

+ auto.exec("auto_check", verbose)

+ }

+ 

+ # Executes automated packaging macros that create %files sections

+ # Control variables, flags and arguments:

+ #   -v               be verbose

+ %auto_files(v) %{lua:

+ local      fedora = require "fedora.common"

+ local        auto = require "fedora.auto"

+ local     verbose = fedora.hasflag("v")

+ auto.exec("auto_files", verbose)

+ }

+ 

+ # Executes automated packaging macros that populate the changelog

+ # Control variables, flags and arguments:

+ #   -v               be verbose

+ %auto_changelog(v) %{lua:

+ local      fedora = require "fedora.common"

+ local        auto = require "fedora.auto"

+ local     verbose = fedora.hasflag("v")

+ auto.exec("auto_changelog", verbose)

+ }

file added
+82
@@ -0,0 +1,82 @@ 

+ # Automated packaging framework, SRPM build stage

+ 

+ # To register macros for execution by one of the %auto_<call> macros, drop a

+ # file with the auto extension in %auto_dir that contains lines in the

+ # following syntax:

+ # auto_<call> <your_macro_name>

+ #

+ # Registered macros MUST accept the -v verbosity flag. They will usually depend

+ # on control variables computed and set as part of %auto_init.

+ #

+ # %auto_<call> macros accept %{<name>_after} control variables. When that

+ # is the case:

+ #   – %{<name>_after} should contain a space separated list of macro names,

+ #     without leading %s

+ #   – if <name> is registered for %auto_<call>, %auto_<call> will make sure to

+ #     execute <name> after all the macros listed in %{<name>_after},

+ #   – elements listed in %{<name>_after} but not registered for %auto_<call>,

+ #     are ignored

+ #

+ #  %auto_<call> macros accept %{<name>_last}. When %{<name>_last} is set to

+ #  anything other than false, and absent other considerations, %<name> will be

+ #  moved to the end of the execution plan.

+ 

+ # Directory holding auto_ macro registrations.

+ %_rpmautodir @@_RPMAUTODIR@@

+ 

+ # Executes automated packaging macros in the preamble, to initialize variables

+ # (before %auto_pkg)

+ # Control variables, flags and arguments:

+ #   -v               be verbose

+ %auto_init(v) %{lua:

+ local      fedora = require "fedora.common"

+ local        auto = require "fedora.auto"

+ local     verbose = fedora.hasflag("v")

+ auto.exec("auto_init", verbose)

+ }

+ 

+ # Executes automated packaging macros in the preamble, to create package

+ # headers (after %auto_init)

+ # <name> macros registered for %auto_pkg execution must provide a

+ # %<name>_source_names counterpart that returns a space-separated list of the

+ # potential SRPM names that they may create

+ # Control variables, flags and arguments:

+ #   -v              be verbose

+ %auto_pkg(v) %{lua:

+ local      fedora = require "fedora.common"

+ local        auto = require "fedora.auto"

+ local    buildsys = require "fedora.srpm.buildsys"

+ local     verbose = fedora.hasflag("v")

+ if fedora.read("__auto_pkg_done") then

+   if verbose then

+     fedora.echo([[

+ Detected previous %%auto_pkg execution, resetting SRPM state. Additive

+ executions of %%auto_pkg are not supported due to the fact rpmbuild will

+ itself re-execute the preamble under some circumstances.

+     ]])

+   end

+   buildsys.reset(verbose)

+ end

+ auto.pkg_exec("auto_pkg", verbose)

+ fedora.safeset("__auto_pkg_done", true, verbose)

+ }

+ 

+ # Executes automated packaging macros in the %sourcelist section

+ # Control variables, flags and arguments:

+ #   -v               be verbose

+ %auto_sources(v) %{lua:

+ local      fedora = require "fedora.common"

+ local        auto = require "fedora.auto"

+ local     verbose = fedora.hasflag("v")

+ auto.exec("auto_sources", verbose)

+ }

+ 

+ # Executes automated packaging macros in the %patchlist section

+ # Control variables, flags and arguments:

+ #   -v               be verbose

+ %auto_patches(v) %{lua:

+ local      fedora = require "fedora.common"

+ local        auto = require "fedora.auto"

+ local     verbose = fedora.hasflag("v")

+ auto.exec("auto_patches", verbose)

+ }

file added
+6
@@ -0,0 +1,6 @@ 

+ # buildsys macros, safe to use at RPM build stage

+ 

+ # Adds buildsys changelog to spec

+ %buildsys_changelog(v) %{expand:

+ %{buildsys_changelog_content}

+ }

file added
+63
@@ -0,0 +1,63 @@ 

+ # buildsys macros, safe to use at SRPM build stage

+ 

+ # State files required in package sources

+ %buildsys_changelog_file rpm-changelog.txt

+ 

+ # A single Name: and %package substitute

+ # Control variables, flags and arguments:

+ #   %{source_name}          the SRPM name

+ #   %{source_summary}       the SRPM summary

+ #   %{source_epoch}         the SRPM epoch

+ #   %{source_version}       the SRPM version

+ #   %{source_release}       the SRPM release (before %{?dist})

+ #   %{source_post_release}  the SRPM release (after %{?dist})

+ #   %{source_license}       the SRPM license

+ #   %{source_url}           the SRPM URL

+ #   %{source_description}   the SRPM description

+ #   -n <name>               declare a package named <name>

+ #                           (%package-like behavior)

+ #   -v                      be verbose

+ #   %1                      declare a package named %{source_name}-%{%1}

+ #                           (%package-like behavior)

+ %new_package(n:v) %{lua:

+ local      fedora = require "fedora.common"

+ local    buildsys = require "fedora.srpm.buildsys"

+ local    pkg_name = fedora.readflag("n")

+ local     verbose = fedora.hasflag("v")

+ local name_suffix = fedora.read("1")

+ buildsys.new_package(pkg_name, name_suffix, verbose)

+ }

+ 

+ # A complete package header generator

+ # Control variables, flags and arguments:

+ #   %{__current_buildsys_name}         the (sub)package name

+ #   %{__current_buildsys_summary}      the (sub)package summary

+ #   %{__current_buildsys_epoch}        the (sub)package epoch

+ #   %{__current_buildsys_version}      the (sub)package version

+ #   %{__current_buildsys_release}      the (sub)package release (before %{dist})

+ #   %{__current_buildsys_post_release} the (sub)package release (after %{dist})

+ #   %{__current_buildsys_license}      the (sub)package license

+ #   %{__current_buildsys_url}          the (sub)package URL

+ #   %{__current_buildsys_tags}         free-form additional (sub)package tags

+ #   %{__current_buildsys_description}  the (sub)package description

+ #   -v                                 be verbose

+ %buildsys_pkg(v) %{lua:

+ local      fedora = require "fedora.common"

+ local    buildsys = require "fedora.srpm.buildsys"

+ local     verbose = fedora.hasflag("v")

+ buildsys.pkg(verbose)

+ }

+ 

+ # Prints sources in %sourcelist compatible format

+ %buildsys_sources(v) %{lua:

+   for _, r in ipairs({'changelog_file'}) do

+     local f = '%{buildsys_' .. r .. '}'

+     local p = '%{_sourcedir}/' .. f

+     print(rpm.expand([=[

+ %([[ ! -e ']=] .. p .. [=[' ]] && echo "             " > ]=] .. p .. [=[)

+ ]=] .. f .. [=[

+ ]=]))

+   end

+ }

+ 

+ %buildsys_sources_last true

file added
+25
@@ -0,0 +1,25 @@ 

+ # Installs the files associated with a documentation package in %install

+ # Control variables, flags and arguments:

+ #   -z <number>  only process the zth block of definitions

+ #                "" for the no-suffix block

+ #   -v           be verbose

+ %doc_install(z:v) %{lua:

+ local      fedora = require "fedora.common"

+ local         doc = require "fedora.rpm.doc"

+ local      suffix = fedora.readflag("z")

+ local     verbose = fedora.hasflag("v")

+ doc.floop(doc.install, suffix, {verbose})

+ }

+ 

+ # Creates a %files section for a documentation package

+ # Control variables, flags and arguments:

+ #   -z <number>  only process the zth block of definitions

+ #                "" for the no-suffix block

+ #   -v           be verbose

+ %doc_files(z:v) %{lua:

+ local      fedora = require "fedora.common"

+ local         doc = require "fedora.rpm.doc"

+ local      suffix = fedora.readflag("z")

+ local     verbose = fedora.hasflag("v")

+ doc.floop(doc.files, suffix, {verbose})

+ }

@@ -0,0 +1,34 @@ 

+ # RPM macros for documentation packages

+ #

+ # Internal utility macros

+ # Direct use in spec file is not supported

+ 

+ %__doc_install() %{expand:

+ (

+   %{?__current_shell_quiet}

+   cd %{_builddir}/%{?buildsubdir}

+   echo "%%defattr(644, root, root, 0755)" >> %{?__current_doc_list}

+   (

+     %define listfiles_include %{?__current_doc_docs}

+     %define listfiles_exclude %{?__current_docs_docs_exclude}

+     (%listfiles

+     ) | sed -E '/^$/d

+                 s|^[[:blank:]]*(.+)[[:blank:]]*$|%%doc "./\\1"|g' \\

+       | tee -a %{?__current_doc_list} > /dev/null

+   )

+   (

+     %define listfiles_include %{?__current_doc_licenses}

+     %define listfiles_exclude %{?__current_doc_licenses_exclude}

+     (%listfiles

+     ) | sed -E '/^$/d

+                 s|^[[:blank:]]*(.+)[[:blank:]]*$|license "./\\1"|g

+                 s/^/%%/g' \\

+       | tee -a %{?__current_doc_list} > /dev/null

+   )

+   %{?__current_shell_verbose}

+ )

+ }

+ 

+ %__doc_files() %{expand:

+ %files -n %{__current_doc_name} -f %{__current_doc_list}

+ }

file added
+50
@@ -0,0 +1,50 @@ 

+ # Forge macros, safe to use at SRPM build stage

+ 

+ # Computes documentation-related variables

+ # Control variables, flags and arguments:

+ #   %{doc_packages<number>} <list>            create a documentation package

+ #                                             that enhances the space-separated

+ #                                             <list> of packages (default: all)

+ #   %{doc_docs<number>} <globs>               space-separated list of shell

+ #                                             <globs> matching documentation

+ #                                             files to include, if they exist

+ #                                             at the start of the %install

+ #                                             section; globs are relative to

+ #                                             %{_builddir}/%{?buildsubdir}

+ #   %{doc_docs_exclude<number>} <globs>       space-separated list of shell

+ #                                             <globs> to exclude from

+ #                                             %{doc_docs<number>}

+ #   %{doc_licenses<number>} <globs>           space-separated list of shell

+ #                                             <globs> matching license files to

+ #                                             include, if they exist at the

+ #                                             start of the %install section

+ #   %{doc_licenses_exclude<number>} <globs>   space-separated list of shell

+ #                                             <globs> to exclude from

+ #                                             %{doc_licenses<number>}

+ #   -z <number>           only process the zth block of definitions

+ #                         "" for the no-suffix block

+ #   -v                    be verbose

+ #   -i                    list the resulting variable values

+ %doc_init(z:vi) %{lua:

+ local      fedora = require "fedora.common"

+ local         doc = require "fedora.srpm.doc"

+ local      suffix = fedora.readflag("z")

+ local informative = fedora.hasflag("i")

+ local     verbose = fedora.hasflag("v")

+ doc.floop(doc.init, suffix, {verbose, informative})

+ }

+ 

+ # Creates documentation package headers

+ # Control variables, flags and arguments:

+ #   -z <number>  only process the zth block of definitions

+ #                "" for the no-suffix block

+ #   -v           be verbose

+ %doc_pkg(z:va) %{lua:

+ local      fedora = require "fedora.common"

+ local         doc = require "fedora.srpm.doc"

+ local      suffix = fedora.readflag("z")

+ local     verbose = fedora.hasflag("v")

+ doc.floop(doc.pkg, suffix, {verbose})

+ }

+ 

+ %doc_pkg_last true

macros.fedora-misc-rpm macros.fedora-misc
file renamed
+14 -10
@@ -12,6 +12,9 @@ 

  #   …                     arguments passed to the macro without flags will be

  #                         interpreted as inclusion globs

  %listfiles(i:x:) %{expand:

+ %dnl %listfiles  must do something shell-side in all cases otherwise (%listfiles

+ %dnl ) | will fail

+ set +x

  %if %{lua: print(string.len(rpm.expand("%{?-i*}%{?listfiles_include}%*")))}

    listfiles_include=$(realpath -e --relative-base=. %{?-i*} %{?listfiles_include} %* | sort -u)

    %if  %{lua: print(string.len(rpm.expand("%{?-x*}%{?listfiles_exclude}")))}
@@ -36,7 +39,7 @@ 

  #                      in myfile

  %writevars(f:) %{lua:

  local    fedora = require "fedora.common"

- local macrofile = rpm.expand("%{-f*}")

+ local macrofile = fedora.readflag("f")

  local   rpmvars = {}

  for i = 1, rpm.expand("%#") do

    table.insert(rpmvars, rpm.expand("%" .. i))
@@ -46,18 +49,19 @@ 

  

  # gpgverify verifies signed sources. There is documentation in the script.

  %gpgverify(k:s:d:) %{lua:

- local script = rpm.expand("%{_rpmconfigdir}/redhat/gpgverify ")

- local keyring = rpm.expand("%{-k*}")

- local signature = rpm.expand("%{-s*}")

- local data = rpm.expand("%{-d*}")

+ local    fedora = require "fedora.common"

+ local    script = rpm.expand("%{_rpmconfigdir}/redhat/gpgverify ")

+ local   keyring = fedora.readflag("k")

+ local signature = fedora.readflag("s")

+ local      data = fedora.readflag("d")

  print(script)

- if keyring ~= "" then

-   print(rpm.expand("--keyring='%{SOURCE" .. keyring ..  "}' "))

+ if keyring then

+   print(rpm.expand(  "--keyring='%{SOURCE" .. keyring ..  "}' "))

  end

- if signature ~= "" then

+ if signature then

    print(rpm.expand("--signature='%{SOURCE" .. signature ..  "}' "))

  end

- if data ~= "" then

-   print(rpm.expand("--data='%{SOURCE" .. data ..  "}' "))

+ if data then

+   print(rpm.expand(     "--data='%{SOURCE" .. data ..  "}' "))

  end

  }

file modified
+1 -21
@@ -13,7 +13,7 @@ 

  # Applies the fedora.wordwrap filter to the content of an rpm variable, and

  # prints the result.

  #   – putting multiple lines of UTF-8 text inside a variable is usually

- #     accomplished with %{expand:some_text}

+ #     accomplished with %{expand:Lorem ipsum dolor sit amet…}

  # Control variables, flags and arguments:

  #   -v <variable_name>  (default value: _description)

  %wordwrap(v:) %{lua:
@@ -21,23 +21,3 @@ 

  local variable = "%{?" .. rpm.expand("%{-v*}%{!-v:_description}") .. "}"

  print(fedora.wordwrap(variable))

  }

- 

- # A single Name: and %package substitute

- # Control variables, flags and arguments:

- #   %{source_name}         the SRPM name

- #   %{source_summary}      the SRPM summary

- #   %{source_description}  the SRPM description

- #   -n <name>              declare a package named <name>

- #                          (%package-like behavior)

- #   -v                     be verbose

- #   %1                     declare a package named %{source_name}-%{%1}

- #                          (%package-like behavior)

- %new_package(n:v) %{lua:

- local      fedora = require "fedora.common"

- local    pkg_name = fedora.readflag("n")

- local     verbose = fedora.hasflag("v")

- local name_suffix = fedora.read("1")

- local source_name = fedora.read("source_name")

- local       first = not ( fedora.read("name") or fedora.read("currentname") )

- fedora.new_package(source_name, pkg_name, name_suffix, first, verbose)

- }

file removed
-70
@@ -1,70 +0,0 @@ 

- # Computes forge-related variables for use in the rest of the spec file

- # Control variables, flags and arguments:

- #   %{forgeurl<number>}  the project url on the target forge

- #   %{tag<number>}       the packaged tag, OR

- #   %{commit<number>}    the packaged commit, OR

- #   %{version<number>}   the packaged version

- #                          – %{version}/%{version0} are set via:

- #                              Version:

- #                          – because git is lacking a built-in version

- #                            reference, %{version<number>} will be translated

- #                            into %{tag<number>} using unreliable heuristics;

- #                            set %{tag<number>} directly if those fail

- #   %{date<number>}      the packaged timestamp

- #   …                    %forgemeta will compute a huge number of variables:

- #                          — the packager can override it by setting some of

- #                            those before the %forgemeta call

- #                          – use the -i flag to list those variables

- #   -z <number>          only process the zth block of definitions

- #                        "" for the no-suffix block

- #   -i                   list the resulting variable values

- #   -s                   silently ignore problems in %{forgeurl<number>}

- #   -v                   be verbose

- #   -a                   process all sources in one go, instead of using

- #                        separate -z calls

- %forgemeta(z:isva) %{lua:

- local      fedora = require "fedora.common"

- local       forge = require "fedora.srpm.forge"

- local     verbose =  rpm.expand("%{-v}") ~= ""

- local informative =  rpm.expand("%{-i}") ~= ""

- local      silent =  rpm.expand("%{-s}") ~= ""

- local  processall = (rpm.expand("%{-a}") ~= "") and (rpm.expand("%{-z}") == "")

- if processall then

-   for _,s in pairs(fedora.getsuffixes("forgeurl")) do

-     forge.meta(s,verbose,informative,silent)

-   end

- else

-   forge.meta(rpm.expand("%{-z*}"),verbose,informative,silent)

- end

- }

- 

- # Unpacks sources computed by %forgemeta

- # Control variables, flags and arguments:

- #   %{forgesource<number>}       the source archive that will be processed

- #   %{forgesetupargs<number>}    %setup arguments

- 

- #   -z <number>                  only process the zth block of definitions

- #                                "" for the no-suffix block

- #   -v                           be verbose

- #   -a                   process all sources in one go, instead of using

- #                        separate -z calls

- %forgesetup(z:va) %{lua:

- local fedora = require "fedora.common"

- if (rpm.expand("%{-z}") == "") and (rpm.expand("%{-a}") ~= "") then

-   for _,s in pairs(fedora.getsuffixes("forgesetupargs")) do

-     print(rpm.expand("%setup %{!-v:-q} %{?forgesetupargs" .. s                     .. "}\\n"))

-   end

- else

-   print(  rpm.expand("%setup %{!-v:-q} %{?forgesetupargs" .. rpm.expand("%{-z*}") .. "}\\n"))

- end

- }

- 

- # Calls %autosetup using %forgemeta results

- #   – this will probably be removed since it is unsafe in presence of multiple

- #     sources

- # Control variables, flags and arguments:

- #   -z <number>  process the zth block of definitions

- #   -v -N -S -p  relayed to %autosetup

- %forgeautosetup(z:vNS:p:q) %{lua:

- print(rpm.expand("%autosetup %{-v} %{-N} %{?-S} %{?-p} %{?forgesetupargs" .. rpm.expand("%{-z*}") .. "}\\n"))

- }

file added
+29
@@ -0,0 +1,29 @@ 

+ # Forge macros, safe to use after the SRPM build stage

+ 

+ # Unpacks and patches sources computed by %forgemeta

+ # Control variables, flags and arguments:

+ #   %{forge_source<number>}           the source archive that will be processed

+ #   %{forge_setup_arguments<number>}  %setup arguments

+ #   %{forge_patchlist<number>}        list of patches to apply using

+ #                                     %apply_patch in %patchlist one filename

+ #                                     per line format

+ #   %{patch_mode<patch_number>}       %apply_patch mode (%{__scm} like)

+ #                                     <patch_number> is the usual %patchX

+ #                                     number

+ #   %{patch_level<patch_number>}      default: -p1

+ #   %{forge_patch_mode<number>}       fallback for %{patch_mode<patch_number>}

+ #                                     if it is not declared for one of the

+ #                                     patches in %{forge_patchlist<number>}

+ #   %{forge_patch_level<number>}      fallback for %{patch_level<patch_number>}

+ #                                     if it is not declared for one of the

+ #                                     patches in %{forge_patchlist<number>}

+ #   -z <number>                       only process the zth block of definitions

+ #                                     "" for the no-suffix block

+ #   -v                                be verbose

+ %forge_prep(z:v) %{lua:

+ local      fedora = require "fedora.common"

+ local       forge = require "fedora.rpm.forge"

+ local      suffix = fedora.readflag("z")

+ local     verbose = fedora.hasflag("v")

+ forge.floop(forge.prep, suffix, {verbose})

+ }

file added
+65
@@ -0,0 +1,65 @@ 

+ # Forge macros, safe to use at SRPM build stage

+ 

+ # Computes forge-related variables for use in the rest of the spec file

+ # Control variables, flags and arguments:

+ #   %{forge_url<number>}  the project url on the target forge

+ #   %{tag<number>}        the packaged tag, OR

+ #   %{commit<number>}     the packaged commit, OR

+ #   %{version<number>}    the packaged version

+ #                           – %{version}/%{version0} are set via:

+ #                               Version:

+ #                           – because git is lacking a built-in version

+ #                             reference, %{version<number>} will be translated

+ #                             into %{tag<number>} using unreliable heuristics;

+ #                             set %{tag<number>} directly if those fail

+ #   %{time<number>}       the packaged timestamp, in RFC 3339 format

+ #                         (as outputed by date -u --iso-8601=seconds)

+ #   …                     %forge_init will compute a huge number of variables:

+ #                           — the packager can override it by setting some of

+ #                             those before the %forge_init call

+ #                           – use the -i flag to list those variables

+ #   -z <number>           only process the zth block of definitions

+ #                         "" for the no-suffix block

+ #   -i                    list the resulting variable values

+ #   -s                    silently ignore problems in %{forgeurl<number>}

+ #   -v                    be verbose

+ %forge_init(z:isv) %{lua:

+ local      fedora = require "fedora.common"

+ local       forge = require "fedora.srpm.forge"

+ local      suffix = fedora.readflag("z")

+ local informative = fedora.hasflag("i")

+ local      silent = fedora.hasflag("s")

+ local     verbose = fedora.hasflag("v")

+ forge.floop(forge.init, suffix, {verbose, informative, silent})

+ forge.info_generic(informative)

+ }

+ 

+ # Returns all the %{forge_source<number>}s

+ #   – typically used in the %sourcelist section

+ # Control variables, flags and arguments:

+ #   %{forge_source<number>}  one of the sources to return

+ #   -z <number>              only process the zth block of definitions

+ #                            "" for the no-suffix block

+ #   -v                       be verbose

+ %forge_sources(z:v) %{lua:

+ local      fedora = require "fedora.common"

+ local       forge = require "fedora.srpm.forge"

+ local      suffix = fedora.readflag("z")

+ local     verbose = fedora.hasflag("v")

+ forge.floop(forge.source, suffix, {})

+ }

+ 

+ # Returns all the patches declared in %{forge_patchlist<number>}s

+ #   – typically used in the %patchlist section

+ # Control variables, flags and arguments:

+ #   %{forge_patchlist<number>}  one of the patch lists to return

+ #   -z <number>                 only process the zth block of definitions

+ #                               "" for the no-suffix block

+ #   -v                           be verbose

+ %forge_patches(z:v) %{lua:

+ local      fedora = require "fedora.common"

+ local       forge = require "fedora.srpm.forge"

+ local      suffix = fedora.readflag("z")

+ local     verbose = fedora.hasflag("v")

+ forge.floop(forge.patchlist, suffix, {})

+ }

@@ -0,0 +1,32 @@ 

+ # Legacy deprecated compatibility forge logic; RPM stage

+ # remove in F35

+ 

+ %forgesetup(z:va)  %{lua:

+ local      fedora = require "fedora.common"

+ local       forge = require "fedora.rpm.forge"

+ local      suffix = fedora.readflag("z")

+ local     verbose = fedora.hasflag("v")

+ local         all = fedora.hasflag("a")

+ fedora.warning([[

+ %%forgesetup is deprecated and will be removed. Adjust your variable names and

+ replace %%forgesetup with %%auto_prep.]])

+ if not (suffix or all) then

+   suffix = "0"

+ end

+ forge.floop(forge.prep, suffix, {verbose})

+ }

+ 

+ # Calls %autosetup using %forgemeta results

+ #   – this is unsafe in presence of multiple sources

+ # Control variables, flags and arguments:

+ #   -z <number>  process the zth block of definitions

+ #   -v -N -S -p  relayed to %autosetup

+ %forgeautosetup(z:vNS:p:q) %{lua:

+ local      fedora = require "fedora.common"

+ fedora.warning([[

+ %%forgeautosetup is deprecated, unsafe, and will be removed. Adjust your

+ variable names replace %%forgeautosetup with %%auto_prep]])

+ print(rpm.expand([[

+ %autosetup %{-v} %{-N} %{?-S} %{?-p} %{?forge_setup_arguments]] .. rpm.expand("%{-z*}") .. [[}

+ ]]))

+ }

@@ -0,0 +1,24 @@ 

+ # Legacy deprecated compatibility forge logic; SRPM stage

+ # remove in F35

+ 

+ %forgemeta(z:isva) %{lua:

+ local      fedora = require "fedora.common"

+ local       forge = require "fedora.srpm.forge"

+ local  deprecated = require "fedora.srpm.forge_deprecated"

+ local      suffix = fedora.readflag("z")

+ local informative = fedora.hasflag("i")

+ local      silent = fedora.hasflag("s")

+ local     verbose = fedora.hasflag("v")

+ local         all = fedora.hasflag("a")

+ fedora.warning([[

+ %%forgemeta is deprecated and will be removed. Adjust your variable names and

+ replace %%forgemeta with %%auto_init.]])

+ deprecated.floop(deprecated.init, suffix, {verbose})

+ if not (suffix or all) then

+   forge.floop(forge.init, "0", {verbose, informative, silent})

+ else

+   forge.floop(forge.init, suffix, {verbose, informative, silent})

+ end

+ forge.info_generic(informative)

+ forge.floop(deprecated.post_init, suffix, {verbose})

+ }

file modified
+57 -12
@@ -26,22 +26,33 @@ 

  

  # The macros defined by these files are for things that need to be defined

  # at srpm creation time when it is not feasible to require the base packages

- # that would otherwise be providing the macros. other language/arch specific

+ # that would otherwise be providing the macros, and when %prep has not been

+ # executed and source content is unknown. Other language/arch specific

  # macros should not be defined here but instead in the base packages that can

  # be pulled in at rpm build time, this is specific for srpm creation.

- Source100: macros.fedora-misc-srpm

  Source102: macros.mono-srpm

  Source103: macros.nodejs-srpm

  Source104: macros.ldc-srpm

  Source105: macros.valgrind-srpm

- 

- # Other misc macros

+ Source106: macros.fedora-misc-srpm

+ Source107: macros.forge-srpm

+ Source108: macros.auto-srpm

+ Source109: macros.forge_deprecated-srpm

+ Source110: macros.doc-srpm

+ Source112: macros.buildsys-srpm

+ 

+ # Other misc macros, for use in %prep and afterwards

  Source150: macros.dwz

  Source151: macros.kmp

  Source152: macros.vpath

- Source153: macros.forge

  Source154: macros.ldconfig

- Source155: macros.fedora-misc

+ Source156: macros.fedora-misc-rpm

+ Source157: macros.forge-rpm

+ Source158: macros.auto-rpm

+ Source159: macros.forge_deprecated-rpm

+ Source160: macros.doc-rpm

+ Source161: macros.doc-rpm.internal

+ Source162: macros.buildsys-rpm

  

  # Build policy scripts

  # this comes from https://github.com/rpm-software-management/rpm/pull/344
@@ -86,7 +97,21 @@ 

  

  # Convenience lua functions

  Source800: common.lua

- Source801: forge.lua

+ Source801: auto.lua

+ Source802: forge-srpm.lua

+ Source803: forge-rpm.lua

+ Source804: forge_deprecated-srpm.lua

+ Source805: doc-srpm.lua

+ Source806: doc-rpm.lua

+ Source807: buildsys-srpm.lua

+ 

+ # Automated macro registration

+ Source850: forge-srpm.auto

+ Source851: forge-rpm.auto

+ Source852: doc-srpm.auto

+ Source853: doc-rpm.auto

+ Source854: buildsys-srpm.auto

+ Source855: buildsys-rpm.auto

  

  # Documentation

  Source900: buildflags.md
@@ -146,6 +171,9 @@ 

  # of source numbers in install section

  %setup -c -T

  cp -p %{sources} .

+ # Auto package macros registry location

+ %global _rpmautodir %{_rpmconfigdir}/auto

+ %writevars -f macros.auto-srpm _rpmautodir

  

  %install

  mkdir -p %{buildroot}%{rrcdir}
@@ -170,8 +198,22 @@ 

  install -p -m 644 -t %{buildroot}%{_fileattrsdir} *.attr

  

  mkdir -p %{buildroot}%{_rpmluadir}/fedora/{rpm,srpm}

- install -p -m 644 -t %{buildroot}%{_rpmluadir}/fedora common.lua

- install -p -m 644 -t %{buildroot}%{_rpmluadir}/fedora/srpm forge.lua

+ install -p -m 644 -t %{buildroot}%{_rpmluadir}/fedora common.lua auto.lua

+ install -p -m 644 forge-srpm.lua \

+          %{buildroot}%{_rpmluadir}/fedora/srpm/forge.lua

+ install -p -m 644 forge_deprecated-srpm.lua \

+          %{buildroot}%{_rpmluadir}/fedora/srpm/forge_deprecated.lua

+ install -p -m 644 forge-rpm.lua \

+          %{buildroot}%{_rpmluadir}/fedora/rpm/forge.lua

+ install -p -m 644 doc-srpm.lua \

+          %{buildroot}%{_rpmluadir}/fedora/srpm/doc.lua

+ install -p -m 644 doc-rpm.lua \

+          %{buildroot}%{_rpmluadir}/fedora/rpm/doc.lua

+ install -p -m 644 buildsys-srpm.lua \

+          %{buildroot}%{_rpmluadir}/fedora/srpm/buildsys.lua

+ 

+ mkdir   -p           %{buildroot}%{_rpmautodir}

+ install -p -m 644 -t %{buildroot}%{_rpmautodir} *auto

  

  %files

  %dir %{rrcdir}
@@ -188,16 +230,19 @@ 

  %{rrcdir}/brp-ldconfig

  %{_fileattrsdir}/*.attr

  %{_rpmconfigdir}/macros.d/macros.*-srpm

+ %{_rpmconfigdir}/macros.d/macros.*-rpm

+ %{_rpmconfigdir}/macros.d/macros.*-rpm.internal

  %{_rpmconfigdir}/macros.d/macros.dwz

- %{_rpmconfigdir}/macros.d/macros.forge

  %{_rpmconfigdir}/macros.d/macros.ldconfig

  %{_rpmconfigdir}/macros.d/macros.vpath

- %{_rpmconfigdir}/macros.d/macros.fedora-misc

  %dir %{_rpmluadir}/fedora

  %dir %{_rpmluadir}/fedora/srpm

  %dir %{_rpmluadir}/fedora/rpm

- %{_rpmluadir}/fedora/*.lua

+ %{_rpmluadir}/fedora/*lua

  %{_rpmluadir}/fedora/srpm/*lua

+ %{_rpmluadir}/fedora/rpm/*lua

+ %dir %{_rpmautodir}

+ %{_rpmautodir}/*auto

  

  %doc buildflags.md

  

Main features:
– clean up lua function naming
– add multiple small additional helpers to help keep lua code short and easy
to check (this is what a non-barebones rpm lua namespace should look like)

– add a plugable %auto_<call> framework. That includes two entry points in the
preamble, %auto_init and %auto_pkg. This is necessary to separate cleanly
the variable initialisation phase from their use in spec sections
(including %package sections). Name: is treated as just another %package
section without any specific handling, to KISS and save packager sanity (of
course, Name: is not another section from the rpm parser POW, but that’s
just one of rpm’s numerous legacy warts).

– add a buildsys subsystem that takes care of reading the rpm changelog from
a detached file

– add a doc subsystem to simplify creation of -doc subpackages that will hold
bulky documents like pdf files

– clean up and namespace properly forge control variables
– make forge macros process patches too (like %autosetup, except in a safe
way that does not break in presence of multiple archives).
– patch processing is done via %apply_patch, and inherits all its quirks,
limitations and lack of documentation
– make forge macros suffix-independant: 0 no longer has any special meaning,
and variables are not zaliased by default. You can write a whole
multi-source and multi-patch spec without dealing with a single source or
patch suffix.

While the switch to uniform naming and the factorisation of common patterns in
small helpers makes the code simpler and more maintainable long term, it does
result in a huge number of changed lines (likewise, when reusing wordwrap in
new functions required moving the wordwrap block in common.lua).

The auto_call framework allows consolidating all macro sets that use this code into:

%global source_name …
%global source_summary …

%global forge_url0 …
%global forge_commit0 …

%global forge_url1 …
%global forge_tag1 …

%global go_module33 …
%global go_description33 …

%global font_family22 …
%global font_conf22 …

%auto_init
%auto_pkg

%sourcelist
%auto_sources

%patchlist
%auto_patches

%prep
%auto_prep

%generate_buildrequires
%auto_generate_buildrequires

%build
%auto_build

%install
%auto_install

%check
%auto_check

%auto_files

%changelog
%auto_changelog

This change is backwards compatible: the old forge syntax works as before (for
now, it will eventually be removed). However mixing old and new syntax in a
single spec file is not supported. Packagers need to convert spec files fully
or not at all.

The lua side of forge macros is now cleanly split into SRPM and post-SRPM
stage. Macros that call directly into the lua forge functions need adjusting
their imports (to my knowledge this is only done by the Go macros that I will
fix once this is merged and pushed to koji).

rebased onto fd4c4955e0fb77e4b78449240947818a945dd613

3 years ago

@nim frankly, the problem of this proposal is not if it is right or wrong or useful or not. The problem is that this proposal is overwhelming. Significantly touching 30 files in single commit? And also proposing to fundamentally change the whole .spec file?

This IMO should be either project on its own or ideally is should be subsumed RPM upstream, bit by bit. With test coverage etc. The documentation and real world examples should be included.

rebased onto 213995c8371837f3689c0d053ed055c25de287c9

3 years ago

@vondruch I agree it is a bit overwhelming. But, it is overwhelming due to the line count not the number of touched files (some of those are 1∕2 liners). And, the number of touched files is the result of structuring the commit and taking care to separate code that deals with different things.

The spec is not “fundamentally changed”. It’s still the same bad old one source per file/one install per file, that does not work very well with the way lua does namespacing. I sorted things a bit to keep the spec readable, if you want a minimal number of files and minimal number of changed lines in the spec I can do that too (even if IMHO the result will be less maintainable IMHO).

The change can be described this way

  1. the common lua library which is a long list of short and easy to check functions (the sole complex function it touches is wordwrap, and it existed before, and it is mostly touched just to move it before other functions that call it). The library is already over-documented, the description to code ratio is quite high, and frankly the code is often more readable than the description, and simple enough a pseudo-code explanation would be no simpler.

  2. the automation framework which is less trivial code than the common library, but there is a lot less of it, and only 3−4 major functions that need understanding. And, unlike the common library, the automation framework is very "visual", the computed execution plans are printed in the build logs of the packages in the copr, and you have enough different specs in there to see it working and understand how it works.

  3. the buildsys subsystem that applies all of the above and is definitely non-trivial due to the fact it workarounds hard rpm limitations that rpm upstream does not want to work on (with detached changelog included, but really this part is trivial and almost identical to your own code, I was a bit disappointed when I discovered yours there was nothing to steal we coded it quite the same way). I did not want to engage in it, rpm upstream told me to make sure Tags occur in a separate order, now the coding is done, you can check it for correctness, it’s miles ahead of the haphazard way humans declare tags in the preamble.

  4. the forge files, which are no more or less complex than before. probably a bit less complex and a bit more maintainable now they dropped a lot of custom logic to rely on a cleaned-up version in the common library

  5. the forge compatibility and doc subsystems, which are simple applications of the common library and the common framework.

Except for the doc and forge compatibility subsystems, it is not possible to merge the rest separately.

The auto framework uses the common library
The common library makes no sense without a user
A lot of the forge changes are due to offloading custom code to the common library, so adding one without removing the other makes no sense. Also, some of the simplifications rely on the common framework.
Had I not coded the forge compatibility subsystem you would have objected to a backwards incompatible change.
Had I not coded the doc subsystem you would have requested real world examples (sorry, you did request real world examples anyway). So the doc subsystem is a real world simple example of how this all works together, as opposed to the forge subsystem that has a lot of pre-existing history, and is where a lot of the code can be traced back to besides.

Fundamentally, the more you push back and ask additional things to "see how it works", the more things I code, and the more abstract the code becomes, because common patterns get subsumed into higher abstractions, and so on.

So, none of the things you ask for would make you like the result more, and all the things you do not like in the commit are the result of people pushing back and refusing to look at things before they were finished and complete.

So now they are finished and complete. You have the low level common code, the higher level common subsystems (buildsys and auto), porting of existing functions to those (forge), new simpler subsystems as example of how things can work without dealing with the complexity of the forge subsystem and as proof the code it not forge or go or fonts specific, and almost 100 real-world Fedora specs that make use of all this (real world as in real world upstream quirks, not 100 identical and bland spec files).

What more do you need? Do you really think that asking for more will result in less code to review? Don’t you see that those demands are the opposite of release early, release often, and will only add more towers to the cathedral?

FESCO finally approved the change, but requested some tweaks.

Therefore, please do not merge before I update the PR to conform to the FESCO decision.

Unfortunately, the whole process took long enough I’m on the eve of leaving for summer vacations, so it will probably have to wait till end of august.

rebased onto 3b07273917f665f7676102b9bb1c397b97a7d11d

3 years ago

rebased onto 824f412

3 years ago

Since FESCO requested removal of code which is documented in the branch name, opening a new PR where the branch name matches the PR content: PR 109

And closing this merge request as a result.

Pull-Request has been closed by nim

3 years ago