RPM Community Forums

Mailing List Message of <rpm-devel>

Re: Another strange request

From: Ralf S. Engelschall <rse+rpm-devel@rpm5.org>
Date: Mon 24 Dec 2007 - 16:19:25 CET
Message-ID: <20071224151925.GA15387@engelschall.com>
On Fri, Dec 14, 2007, Ralf S. Engelschall wrote:

> I'm currently trying to figure out whether the following would be
> possible to easily support VCS-less package modifications for end users:
>
> 1. Someone unpacks a *.src.rpm to the local filesystem
> 2. He changes some files (usually via svs(1) which automatically
>    generates the *.orig files for him, etc) according to his needs.
> 3. He then packs a new *.src.rpm from the changed source files.
>
> And here the request comes: could it be achieved that for each already
> existing "SourceX: foo" and "PatchX: bar" lines in the *.spec file,
> an RPM macro hack automatically generates additional "Source1000X:
> foo.orig" and "Patch1000X: bar.orig" lines in order to include those
> files into the new *.src.rpm?
>
> The question is not whether the Source1000X tags can be generated.
> That's clear, it can be done similar to what I did yesterday for
> the Environment tag. The question is how I can figure out in the
> generation-macro which *.orig files exists. For this I first have to...
>
> 1. reliably locate the *.spec file.
>    How can this be done?
>    A "rpm --eval '%{_specdir}'" doesn't work as it still might contain
>    %{name} which depends on the current package.
>
> 2. query all its SourceX and PatchX header.
>    How can this be done?
>    A "rpm -q --specfile *.spec --qf '%{SOURCE0}' didn't worked.
>
> Any clues?

Ok, after having to fix up some problems in the RPM Lua area, I was now
came up with a solution based on RPM Lua:

===========================================================================
%description %{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
    --  auto-generate tags for local SourceN and PatchN files where corresponding .orig files exists
    for id, s in pairs(sources) do
        if util.rmatch(s.url, "^(?:ftp|https?)://.+") == nil then
            if posix.access(s.file .. ".orig", "r") == 0 then
                local _, _, m = util.rmatch(id, "^(?i)(Source|Patch)(\\d+)$")
                local tag = string.format("%s%d: %s\n", m[1], 1000 + m[2], s.url .. ".orig")
                io.stderr:write("[auto-tag] " .. tag)
                print(tag)
            end
        end
    end
}\
%%description
===========================================================================

This hooks into the .spec parsing via overloaded "%description",
assembles the SourceN and PatchN information and for each one which has
a corresponding .orig staying around (the result of patching an unpacked
package via tools like my "OSSP svs" or manually) it auto-generates a
SourceN/PatchN tag for the .orig file.

I partly disliked the Lua hacking as I'm
not the greatest Lua fan on earth (see also
http://trainofthoughts.org/blog/2007/09/16/lua-popularity/ ;-), but it
at least allowed to be to hack in this functionality. Hence, RPM Lua is
fine for solving those tasks...

                                       Ralf S. Engelschall
                                       rse@engelschall.com
                                       www.engelschall.com
Received on Mon Dec 24 16:20:09 2007
Driven by Jeff Johnson and the RPM project team.
Hosted by OpenPKG and Ralf S. Engelschall.
Powered by FreeBSD and OpenPKG.