Blame SOURCES/common.lua

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