RPM Community Forums

Mailing List Message of <rpm-devel>

Re: off topic: some curiosity

From: Ralf S. Engelschall <rse+rpm-devel@rpm5.org>
Date: Fri 01 Feb 2008 - 08:20:48 CET
Message-ID: <20080201072048.GA54200@engelschall.com>
On Fri, Feb 01, 2008, devzero2000 wrote:

>     But..... you can have reason but i think if there isn't so much
>     feature in RPM5 for a developer and repo mantainer perhaps there
>     isn't so much interest in using it. Doesn't it ?

I personally would distinguish between the distribution vendor and its
package developers. Because RPM 5 provides many very good improvements
over RPM 4, but they are only visible to and reasonably usable by the
package developers if the distribution vendor also decides to use them
and partly also explicitly prepares them.

To give you an impression: RPM 4 already had Lua scripting support
implemented, but both in a buggy and and functionality-wise very limited
way. RPM 5 now ships with a fully usable and full-featured Lua scripting
functionality. But this is something more for the distribution vendor
to provide new packaging features and possibly packaging tricks to its
own package developers. Just the raw %{lua:...} IMHO should be not
used by any package developer for a particular package. It should be
used by the distribution vendor in its global "rpmmacros" file(s) to
implement its distribution-specific addon functionalities (scripted
macros) -- especially in combination with the "arbitrary tags" Jeff
already mentioned.

To give you a standalone and still simple but sophisticated
enough examples: the distribution vendor can add to its global
"rpmmacros" and "rpmpopt" the following code (this is from OpenPKG's
"<prefix>/etc/openpkg/rpmmacros" file):

1. The following allows one to "mark" a package with an arbitrary
   string during build-time via "rpm --rebuild --marker <string>" and
   later check for all marked packages via "rpm -qa --qf '%{NAME}
   %{MARKER}\n' marker=*'":

   rpmpopt:
   | #   RPM extension: "rpm --marker <marker>"
   | rpm alias --mark --define "__marker !#:+" \
   |     --POPTdesc=$"mark package with Marker: <marker>" \
   |     --POPTargs=$"<marker>"

   rpmmacros:
   | %description\
   |     [...]
   |     %{?__hook_description_2}\
   |     [...]
   |
   | #   auto-generate arbitrary tag "Marker" (via "rpm --marker <marker>")
   | %__hook_description_2 %{?__marker:Marker: %{__marker}}\
   | %{nil}

2. The following allows the OpenPKG package developers to unpack a SRPM, patch it
   (usually via "OSSP svs" which automatically creates *.orig files
   when editing files) so that file "foo" is modifed and its original
   content is preserved in a new file "foo.orig", and then pack together
   the SRPM again and let RPM automatically pickup and pack also the
   *.orig files. That is, RPM for each "Source: foo" checks whether a
   "foo.orig" exists and if it exists it on-the-fly generates a tag
   "SourceXXXXX: foo.orig" as it would have been manually entered into
   the .spec file. This allows one to very easily patch SRPMs without
   version control system requirements and still carry around the
   changes without loosing the original and having to change the .spec
   file manually for each file change.

   rpmmacros:
   | %description\
   |     [...]
   |     %{?__hook_description_4}\
   |     [...]
   |
   | #   magically pickup all patched packaging source files (.orig/.rej)
   | %__hook_description_4 %{lua: \
   |     --  assemble RPM's information about SourceN and PatchN \
   |     local sources = {} \
   |     local macros = rpm.macros() \
   |     for name, value in pairs(macros) do \
   |         local s, _, m = util.rmatch(name, "^(?i)(SOURCE|PATCH)((?:URL)?)(\\\\d+)$") \
   |         if s ~= nil and value["body"] ~= nil then \
   |             local n = string.upper(string.sub(m[1], 1, 1)) .. string.lower(string.sub(m[1], 2)) .. m[3] \
   |             if sources[n] == nil then \
   |                 sources[n] = { url = "", file = "" } \
   |             end \
   |             if m[2] ~= nil and m[2] ~= "" then \
   |                 sources[n].url = value["body"] \
   |             else \
   |                 sources[n].file = value["body"] \
   |             end \
   |         end \
   |     end \
   |     \
   |     --  add implicit .spec source file \
   |     sources["Source999"] = { \
   |         url  = rpm.expand("%{name}.spec"), \
   |         file = rpm.expand("%{_specdir}/%{name}.spec") \
   |     } \
   |     \
   |     --  auto-generate tags for local SourceN and PatchN files \
   |     --  where any corresponding .orig/.rej files exists \
   |     for id, s in pairs(sources) do \
   |         if util.rmatch(s.url, "^(?:ftp|https?)://.+") == nil then \
   |             for i, ext in ipairs({ ".orig", ".rej" }) do \
   |                 if posix.access(s.file .. ext, "r") == 0 then \
   |                     local _, _, m = util.rmatch(id, "^(?i)(Source|Patch)(\\\\d+)$") \
   |                     local tag = string.format("%s%d: %s\\n", m[1], 10000 * i + m[2], s.url .. ext) \
   |                     print(tag) \
   |                 end \
   |             end \
   |         end \
   |     end \
   | }

Perhaps this already gives you an impression how powerful RPM 5 can
be if the distribution vendor takes action and really delivers the
available functionalities to its package developers...

Or in short: most of RPM 5's new and exciting functionalities are "under
the cover" and hence are unfortunately not immediately visible to a
package developer. But once uncovered they provide really a lot more
than what good old RPM 4 provided.

                                       Ralf S. Engelschall
                                       rse@engelschall.com
                                       www.engelschall.com
Received on Fri Feb 1 08:22:03 2008
Driven by Jeff Johnson and the RPM project team.
Hosted by OpenPKG and Ralf S. Engelschall.
Powered by FreeBSD and OpenPKG.