Blame SOURCES/common.lua

f9efe2
-- Convenience Lua functions that can be used within rpm macros
f9efe2
f9efe2
-- Reads an rpm variable. Unlike a basic rpm.expand("{?foo}"), returns nil if
f9efe2
-- the variable is unset, which is convenient in lua tests and enables
f9efe2
-- differentiating unset variables from variables set to ""
f9efe2
local function read(rpmvar)
f9efe2
  if not rpmvar or
f9efe2
    (rpm.expand("%{" .. rpmvar .. "}") == "%{" .. rpmvar .. "}") then
f9efe2
    return nil
f9efe2
  else
f9efe2
    return rpm.expand("%{?" .. rpmvar .. "}")
f9efe2
  end
f9efe2
end
f9efe2
f9efe2
-- Returns true if the macro that called this function had flag set
f9efe2
--   – for example, hasflag("z") would give the following results:
f9efe2
--     %foo -z bar → true
f9efe2
--     %foo -z     → true
f9efe2
--     %foo        → false
f9efe2
local function hasflag(flag)
f9efe2
  return (rpm.expand("%{-" .. flag .. "}") ~= "")
f9efe2
end
f9efe2
f9efe2
-- Returns the argument passed to flag in the macro that called this function
f9efe2
--  – for example, readflag("z") would give the following results:
f9efe2
--      %foo -z bar → bar
f9efe2
--      %foo        → nil
f9efe2
--      %foo -z ""  → empty string
f9efe2
--      %foo -z ''  → empty string
f9efe2
local function readflag(flag)
f9efe2
  if not hasflag(flag) then
f9efe2
    return nil
f9efe2
  else
f9efe2
    local a = rpm.expand("%{-" .. flag .. "*}")
f9efe2
    -- Handle "" and '' as empty strings
f9efe2
    if (a == '""') or (a == "''") then
f9efe2
      a = ''
f9efe2
    end
f9efe2
    return a
f9efe2
  end
f9efe2
end
f9efe2
f9efe2
-- Sets a spec variable; echoes the result if verbose
f9efe2
local function explicitset(rpmvar, value, verbose)
f9efe2
  local value = value
f9efe2
  if (value == nil) or (value == "") then
f9efe2
    value = "%{nil}"
f9efe2
  end
f9efe2
  rpm.define(rpmvar .. " " .. value)
f9efe2
  if verbose then
f9efe2
    rpm.expand("%{warn:Setting %%{" .. rpmvar .. "} = " .. value .. "}")
f9efe2
  end
f9efe2
end
f9efe2
f9efe2
-- Unsets a spec variable if it is defined; echoes the result if verbose
f9efe2
local function explicitunset(rpmvar, verbose)
f9efe2
  if (rpm.expand("%{" .. rpmvar .. "}") ~= "%{" .. rpmvar .. "}") then
f9efe2
    rpm.define(rpmvar .. " %{nil}")
f9efe2
    if verbose then
f9efe2
      rpm.expand("%{warn:Unsetting %%{" .. rpmvar .. "}}")
f9efe2
    end
f9efe2
  end
f9efe2
end
f9efe2
f9efe2
-- Sets a spec variable, if not already set; echoes the result if verbose
f9efe2
local function safeset(rpmvar, value, verbose)
f9efe2
  if (rpm.expand("%{" .. rpmvar .. "}") == "%{" .. rpmvar .. "}") then
f9efe2
    explicitset(rpmvar,value,verbose)
f9efe2
  end
f9efe2
end
f9efe2
f9efe2
-- Aliases a list of rpm variables to the same variables suffixed with 0 (and
f9efe2
-- vice versa); echoes the result if verbose
f9efe2
local function zalias(rpmvars, verbose)
f9efe2
  for _, sfx in ipairs({{"","0"},{"0",""}}) do
f9efe2
    for _, rpmvar in ipairs(rpmvars) do
f9efe2
      local toalias = "%{?" .. rpmvar .. sfx[1] .. "}"
f9efe2
      if (rpm.expand(toalias) ~= "") then
f9efe2
        safeset(rpmvar .. sfx[2], toalias, verbose)
f9efe2
      end
f9efe2
    end
f9efe2
  end
f9efe2
end
f9efe2
f9efe2
-- Takes a list of rpm variable roots and a suffix and alias current<root> to
f9efe2
-- <root><suffix> if it resolves to something not empty
f9efe2
local function setcurrent(rpmvars, suffix, verbose)
f9efe2
  for _, rpmvar in ipairs(rpmvars) do
f9efe2
    if (rpm.expand("%{?" .. rpmvar .. suffix .. "}") ~= "") then
f9efe2
      explicitset(  "current" .. rpmvar, "%{" .. rpmvar .. suffix .. "}", verbose)
f9efe2
    else
f9efe2
      explicitunset("current" .. rpmvar,                                  verbose)
f9efe2
    end
f9efe2
  end
f9efe2
end
f9efe2
f9efe2
-- Echo the list of rpm variables, with suffix, if set
f9efe2
local function echovars(rpmvars, suffix)
f9efe2
  for _, rpmvar in ipairs(rpmvars) do
f9efe2
    rpmvar = rpmvar .. suffix
f9efe2
    local header = string.sub("  " .. rpmvar .. ":                                               ",1,21)
f9efe2
    rpm.expand("%{?" .. rpmvar .. ":%{echo:" .. header .. "%{?" .. rpmvar .. "}}}")
f9efe2
  end
f9efe2
end
f9efe2
f9efe2
-- Returns an array, indexed by suffix, containing the non-empy values of
f9efe2
-- <rpmvar><suffix>, with suffix an integer string or the empty string
f9efe2
local function getsuffixed(rpmvar)
f9efe2
  local suffixes = {}
f9efe2
  zalias({rpmvar})
f9efe2
  for suffix=0,9999 do
f9efe2
    local value = rpm.expand("%{?" .. rpmvar .. suffix .. "}")
f9efe2
    if (value ~= "") then
f9efe2
      suffixes[tostring(suffix)] = value
f9efe2
    end
f9efe2
  end
f9efe2
  -- rpm convention is to alias no suffix to zero suffix
f9efe2
  -- only add no suffix if zero suffix is different
f9efe2
  local value = rpm.expand("%{?" .. rpmvar .. "}")
f9efe2
  if (value ~= "") and (value ~= suffixes["0"]) then
f9efe2
     suffixes[""] = value
f9efe2
  end
f9efe2
  return suffixes
f9efe2
end
f9efe2
f9efe2
-- Returns the list of suffixes, including the empty string, for which
f9efe2
-- <rpmvar><suffix> is set to a non empty value
f9efe2
local function getsuffixes(rpmvar)
f9efe2
  suffixes = {}
f9efe2
  for suffix in pairs(getsuffixed(rpmvar)) do
f9efe2
    table.insert(suffixes,suffix)
f9efe2
  end
f9efe2
  table.sort(suffixes,
f9efe2
             function(a,b) return (tonumber(a) or 0) < (tonumber(b) or 0) end)
f9efe2
  return suffixes
f9efe2
end
f9efe2
f9efe2
-- Returns the suffix for which <rpmvar><suffix> has a non-empty value that
f9efe2
-- matches best the beginning of the value string
f9efe2
local function getbestsuffix(rpmvar, value)
f9efe2
  local best         = nil
f9efe2
  local currentmatch = ""
f9efe2
  for suffix, setvalue in pairs(getsuffixed(rpmvar)) do
f9efe2
  if (string.len(setvalue) > string.len(currentmatch)) and
f9efe2
     (string.find(value, "^" .. setvalue)) then
f9efe2
      currentmatch = setvalue
f9efe2
      best         = suffix
f9efe2
    end
f9efe2
  end
f9efe2
  return best
f9efe2
end
f9efe2
f9efe2
-- %writevars core
f9efe2
local function writevars(macrofile, rpmvars)
f9efe2
  for _, rpmvar in ipairs(rpmvars) do
f9efe2
    print("sed -i 's\029" .. string.upper("@@" .. rpmvar .. "@@") ..
f9efe2
                   "\029" .. rpm.expand(  "%{" .. rpmvar .. "}" ) ..
f9efe2
                   "\029g' " .. macrofile .. "\n")
f9efe2
  end
f9efe2
end
f9efe2
f9efe2
-- https://github.com/rpm-software-management/rpm/issues/566
f9efe2
-- Reformat a text intended to be used used in a package description, removing
f9efe2
-- rpm macro generation artefacts.
f9efe2
-- – remove leading and ending empty lines
f9efe2
-- – trim intermediary empty lines to a single line
f9efe2
-- – fold on spaces
f9efe2
-- Should really be a %%{wordwrap:…} verb
f9efe2
local function wordwrap(text)
f9efe2
  text = rpm.expand(text .. "\n")
f9efe2
  text = string.gsub(text, "\t",              "  ")
f9efe2
  text = string.gsub(text, "\r",              "\n")
f9efe2
  text = string.gsub(text, " +\n",            "\n")
f9efe2
  text = string.gsub(text, "\n+\n",           "\n\n")
f9efe2
  text = string.gsub(text, "^\n",             "")
f9efe2
  text = string.gsub(text, "\n( *)[-*—][  ]+", "\n%1– ")
f9efe2
  output = ""
f9efe2
  for line in string.gmatch(text, "[^\n]*\n") do
f9efe2
    local pos = 0
f9efe2
    local advance = ""
f9efe2
    for word in string.gmatch(line, "%s*[^%s]*\n?") do
f9efe2
      local wl, bad = utf8.len(word)
f9efe2
      if not wl then
f9efe2
        print("%{warn:Invalid UTF-8 sequence detected in:}" ..
f9efe2
              "%{warn:" .. word .. "}" ..
f9efe2
              "%{warn:It may produce unexpected results.}")
f9efe2
        wl = bad
f9efe2
      end
f9efe2
      if (pos == 0) then
f9efe2
        advance, n = string.gsub(word, "^(%s*– ).*", "%1")
f9efe2
        if (n == 0) then
f9efe2
          advance = string.gsub(word, "^(%s*).*", "%1")
f9efe2
        end
f9efe2
        advance = string.gsub(advance, "– ", "  ")
f9efe2
        pos = pos + wl
f9efe2
      elseif  (pos + wl  < 81) or
f9efe2
             ((pos + wl == 81) and string.match(word, "\n$")) then
f9efe2
        pos = pos + wl
f9efe2
      else
f9efe2
        word = advance .. string.gsub(word, "^%s*", "")
f9efe2
        output = output .. "\n"
f9efe2
        pos = utf8.len(word)
f9efe2
      end
f9efe2
      output = output .. word
f9efe2
      if pos > 80 then
f9efe2
        pos = 0
f9efe2
        if not string.match(word, "\n$") then
f9efe2
          output = output .. "\n"
f9efe2
        end
f9efe2
      end
f9efe2
    end
f9efe2
  end
f9efe2
  output = string.gsub(output, "\n*$", "\n")
f9efe2
  return output
f9efe2
end
f9efe2
f9efe2
-- Because rpmbuild will fail if a subpackage is declared before the source
f9efe2
-- package itself, provide a source package declaration shell as fallback.
f9efe2
local function srcpkg(verbose)
f9efe2
  if verbose then
f9efe2
    rpm.expand([[
f9efe2
%{echo:Creating a header for the SRPM from %%{source_name}, %%{source_summary} and}
f9efe2
%{echo:%%{source_description}. If that is not the intended result, please declare the}
f9efe2
%{echo:SRPM header and set %%{source_name} in your spec file before calling a macro}
f9efe2
%{echo:that creates other package headers.}
f9efe2
]])
f9efe2
  end
f9efe2
  print(rpm.expand([[
f9efe2
Name:           %{source_name}
f9efe2
Summary:        %{source_summary}
f9efe2
%description
f9efe2
%wordwrap -v source_description
f9efe2
]]))
f9efe2
  explicitset("currentname", "%{source_name}", verbose)
f9efe2
end
f9efe2
f9efe2
-- %new_package core
f9efe2
local function new_package(source_name, pkg_name, name_suffix, first, verbose)
f9efe2
  -- Safety net when the wrapper is used in conjunction with traditional syntax
f9efe2
  if (not first) and (not source_name) then
f9efe2
    rpm.expand([[
f9efe2
%{warn:Something already set a package name. However, %%{source_name} is not set.}
f9efe2
%{warn:Please set %%{source_name} to the SRPM name to ensure reliable processing.}
f9efe2
]])
f9efe2
    if name_suffix then
f9efe2
      print(rpm.expand("%package        " .. name_suffix))
f9efe2
    else
f9efe2
      print(rpm.expand("%package     -n " .. pkg_name))
f9efe2
    end
f9efe2
    return
f9efe2
  end
f9efe2
  -- New processing
f9efe2
  if not (pkg_name or name_suffix or source_name) then
f9efe2
    rpm.expand([[
f9efe2
%{error:You need to set %%{source_name} or provide explicit package naming!}
f9efe2
]])
f9efe2
  end
f9efe2
  if name_suffix then
f9efe2
    print(rpm.expand("%package        "  .. name_suffix))
f9efe2
    explicitset("currentname", "%{source_name}-" .. name_suffix, verbose)
f9efe2
  else
f9efe2
    if not source_name then
f9efe2
      source_name = pkg_name
f9efe2
    end
f9efe2
    if (pkg_name == source_name) then
f9efe2
      safeset("source_name", source_name, verbose)
f9efe2
      print(rpm.expand("Name:           %{source_name}"))
f9efe2
    else
f9efe2
      if source_name and first then
f9efe2
        srcpkg(verbose)
f9efe2
      end
f9efe2
      print(rpm.expand("%package     -n " .. pkg_name))
f9efe2
    end
f9efe2
    explicitset("currentname", pkg_name, verbose)
f9efe2
  end
f9efe2
end
f9efe2
f9efe2
return {
f9efe2
  read          = read,
f9efe2
  hasflag       = hasflag,
f9efe2
  readflag      = readflag,
f9efe2
  explicitset   = explicitset,
f9efe2
  explicitunset = explicitunset,
f9efe2
  safeset       = safeset,
f9efe2
  zalias        = zalias,
f9efe2
  setcurrent    = setcurrent,
f9efe2
  echovars      = echovars,
f9efe2
  getsuffixed   = getsuffixed,
f9efe2
  getsuffixes   = getsuffixes,
f9efe2
  getbestsuffix = getbestsuffix,
f9efe2
  writevars     = writevars,
f9efe2
  wordwrap      = wordwrap,
f9efe2
  new_package   = new_package,
f9efe2
}