openpkg/rpmlua

changeset 428
f880f219c566
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/openpkg/rpmlua	Tue Jul 31 12:23:42 2012 +0200
     1.3 @@ -0,0 +1,228 @@
     1.4 +--
     1.5 +--  rpmlua -- OpenPKG RPM Lua Script
     1.6 +--  Copyright (c) 2000-2012 OpenPKG GmbH <http://openpkg.com/>
     1.7 +--
     1.8 +--  This software is property of the OpenPKG GmbH, DE MUC HRB 160208.
     1.9 +--  All rights reserved. Licenses which grant limited permission to use,
    1.10 +--  copy, modify and distribute this software are available from the
    1.11 +--  OpenPKG GmbH.
    1.12 +--
    1.13 +--  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
    1.14 +--  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    1.15 +--  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    1.16 +--  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
    1.17 +--  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.18 +--  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.19 +--  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
    1.20 +--  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    1.21 +--  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    1.22 +--  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    1.23 +--  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    1.24 +--  SUCH DAMAGE.
    1.25 +--
    1.26 +
    1.27 +--
    1.28 +--  The purpose of this Lua script is to extend the default Lua functions
    1.29 +--  in the OpenPKG RPM installation for the @l_prefix@ hierarchy.
    1.30 +--
    1.31 +
    1.32 +--  provide namespace
    1.33 +openpkg = {}
    1.34 +
    1.35 +--  small wrapper around the realpath(3) call provided by RPM
    1.36 +function openpkg.realpath(path)
    1.37 +    if posix.stat(path) ~= nil then
    1.38 +        --  path exists, so resolve as a whole
    1.39 +        path = rpm.realpath(path)
    1.40 +    else
    1.41 +        --  path not exists, so recursively resolve only prefix
    1.42 +        local s, _, m = util.rmatch(path, "^(.+?)/([^/]+)/?$")
    1.43 +        if s ~= nil then
    1.44 +            local prefix = openpkg.realpath(m[1])
    1.45 +            if util.rmatch(prefix, "/$") == nil then
    1.46 +                prefix = prefix .. "/"
    1.47 +            end
    1.48 +            path = prefix .. m[2]
    1.49 +        end
    1.50 +    end
    1.51 +    return path
    1.52 +end
    1.53 +
    1.54 +--  try to reduce real path to symbolic one (if posssible)
    1.55 +function openpkg.unrealpath(path, prefix_unreal)
    1.56 +    local prefix_real = openpkg.realpath(prefix_unreal)
    1.57 +    if prefix_real ~= prefix_unreal then
    1.58 +        if string.sub(path, 1, string.len(prefix_real)) == prefix_real then
    1.59 +            path = prefix_unreal .. string.sub(path, string.len(prefix_real)+1)
    1.60 +        end
    1.61 +    end
    1.62 +    return path
    1.63 +end
    1.64 +
    1.65 +--  canonicalize filesystem path as good as possible
    1.66 +function openpkg.canonicalize(path)
    1.67 +    path = openpkg.unrealpath(path, os.getenv("PWD"))
    1.68 +    path = openpkg.unrealpath(path, rpm.expand("%{l_prefix}"))
    1.69 +    return path
    1.70 +end
    1.71 +
    1.72 +--  temporary directory determination
    1.73 +function openpkg.tmpdir()
    1.74 +    local tmpdir = os.getenv("TMPDIR")
    1.75 +    if tmpdir ~= nil then
    1.76 +        tmpdir = openpkg.canonicalize(openpkg.realpath(tmpdir))
    1.77 +    else
    1.78 +        tmpdir = "/tmp"
    1.79 +    end
    1.80 +    tmpdir = tmpdir .. "/openpkg"
    1.81 +    return tmpdir
    1.82 +end
    1.83 +
    1.84 +--  layout determination: RPM Lua based implementation
    1.85 +function openpkg.layout(args)
    1.86 +    local dir = ""
    1.87 +
    1.88 +    --   parse arguments
    1.89 +    local arg = {
    1.90 +        variable   = "",
    1.91 +        layout     = "",
    1.92 +        macrosfile = "",
    1.93 +        basedir    = "",
    1.94 +        shared     = "no",
    1.95 +        debug      = "no",
    1.96 +        specdir    = "",
    1.97 +        sourcedir  = "",
    1.98 +        builddir   = "",
    1.99 +        tmppath    = "",
   1.100 +        rpmdir     = "",
   1.101 +        srcrpmdir  = ""
   1.102 +    }
   1.103 +    local arg_map_fwd = {
   1.104 +        binrpmdir = "rpmdir",
   1.105 +        tmpdir    = "tmppath"
   1.106 +    }
   1.107 +    local arg_map_rev = {
   1.108 +        rpmdir    = "binrpmdir",
   1.109 +        tmppath   = "tmpdir"
   1.110 +    }
   1.111 +    if rpm.debug() then
   1.112 +        arg.debug = "yes"
   1.113 +    end
   1.114 +    util.rsubst(args, "(?s)\\s*([a-z_][a-zA-Z0-9_-]*)=(?:\"((?:\\\\.|[^\"])*)\"|(\\S*))",
   1.115 +        function (key, _, value1, value2)
   1.116 +            if arg_map_fwd[key] ~= nil then
   1.117 +                key = arg_map_fwd[key]
   1.118 +            end
   1.119 +            if arg[key] == nil then
   1.120 +                io.stderr:write("rpm: invalid parameter \"" .. key .. "\" on call to \"openpkg.layout()\"\n")
   1.121 +            else
   1.122 +                if value1 ~= nil then arg[key] = value1 else arg[key] = value2 end
   1.123 +            end
   1.124 +            return false
   1.125 +        end
   1.126 +    )
   1.127 +    if arg.variable == "" then
   1.128 +        io.stderr:write("rpm: missing \"variable\" parameter on call to \"openpkg.layout()\"\n")
   1.129 +        return ""
   1.130 +    end
   1.131 +    if arg.layout == "" then
   1.132 +        io.stderr:write("rpm: missing \"layout\" parameter on call to \"openpkg.layout()\"\n")
   1.133 +        return ""
   1.134 +    end
   1.135 +    if arg.macrosfile == "" and arg.basedir == "" then
   1.136 +        io.stderr:write("rpm: missing \"macrosfile\" or \"basedir\" parameter on call to \"openpkg.layout()\"\n")
   1.137 +        return ""
   1.138 +    end
   1.139 +
   1.140 +    --   determine base directory
   1.141 +    if arg.basedir == "" then
   1.142 +        if util.rmatch(arg.macrosfile, "^.*/\.openpkg/rpmmacros$") ~= nil then
   1.143 +            arg.basedir = openpkg.canonicalize(openpkg.realpath(
   1.144 +                util.rsubst(
   1.145 +                    openpkg.realpath(arg.macrosfile),
   1.146 +                    "/[^/]+$", "/.."
   1.147 +                )
   1.148 +            ))
   1.149 +        else
   1.150 +            arg.basedir = rpm.expand("%{l_prefix}")
   1.151 +        end
   1.152 +    end
   1.153 +
   1.154 +    --  temporarily define "__openpkg_basedir" macro
   1.155 +    rpm.define("__openpkg_basedir " .. arg.basedir)
   1.156 +
   1.157 +    --  temporarily define "__openpkg_shared" macro
   1.158 +    if arg.shared == "yes" then
   1.159 +        rpm.define("__openpkg_shared yes")
   1.160 +    end
   1.161 +
   1.162 +    --  determine layout directory list
   1.163 +    local list = ""
   1.164 +    if arg[arg.variable] ~= nil and arg[arg.variable] ~= "" then
   1.165 +        list = arg[arg.variable]
   1.166 +    else
   1.167 +        list = rpm.expand(
   1.168 +            "%{?__openpkg_layout_" .. arg.layout .. "_" .. arg.variable .. "}" ..
   1.169 +            "%{!?__openpkg_layout_" .. arg.layout .. "_" .. arg.variable .. ":" ..
   1.170 +            "%{__openpkg_layout_global_" .. arg.variable .. "}}"
   1.171 +        )
   1.172 +    end
   1.173 +
   1.174 +    --  remove temporarily defined "__openpkg_basedir" macro
   1.175 +    rpm.undefine("__openpkg_basedir")
   1.176 +
   1.177 +    --  remove temporarily defined "__openpkg_shared" macro
   1.178 +    if arg.shared == "yes" then
   1.179 +        rpm.undefine("__openpkg_shared")
   1.180 +    end
   1.181 +
   1.182 +    --  iterate over all directory specifications
   1.183 +    local dirs = util.rsplit(list, "(?s)\\s+")
   1.184 +    local k = table.maxn(dirs)
   1.185 +    for i, _ in ipairs(dirs) do
   1.186 +        --  parse specification into path to check and optionally path to make
   1.187 +        local path_check  = dirs[i]
   1.188 +        local path_append = false
   1.189 +        local path_make   = path_check
   1.190 +        local s, _, m = util.rmatch(path_check, "^(.+):(\\+?)(.*)$")
   1.191 +        if s ~= nil then
   1.192 +            path_check  = m[1]
   1.193 +            path_append = (m[2] == "+")
   1.194 +            path_make   = m[3]
   1.195 +        end
   1.196 +        --  check whether path should be taken (last path is always taken)
   1.197 +        if posix.stat(path_check) ~= nil or i == k then
   1.198 +            if path_append then
   1.199 +                --  special case: simply append a suffix
   1.200 +                dir = path_check .. path_make
   1.201 +            else
   1.202 +                --  regular case: use full path to make
   1.203 +                dir = path_make
   1.204 +            end
   1.205 +            break
   1.206 +        end
   1.207 +    end
   1.208 +    if dir ~= "" then
   1.209 +        --  make sure path really exists and resolve to absolute path
   1.210 +        if posix.stat(dir) == nil then
   1.211 +            io.stderr:write("rpm: creating \"" .. arg.variable .. "\" directory \"" .. dir .. "\"\n")
   1.212 +            if posix.mkdir(dir) ~= 0 then
   1.213 +                io.stderr:write("rpm: failed to create directory \"" .. dir .. "\"\n")
   1.214 +            end
   1.215 +        end
   1.216 +        dir = openpkg.canonicalize(openpkg.realpath(dir))
   1.217 +    end
   1.218 +
   1.219 +    --  debugging
   1.220 +    if arg.debug == "yes" then
   1.221 +        local variable = arg.variable
   1.222 +        if arg_map_rev[variable] ~= nil then
   1.223 +            variable = arg_map_rev[variable]
   1.224 +        end
   1.225 +        io.stderr:write(string.format("rpm: openpkg: layout: [%s] %s = \"%s\"\n", arg.layout, variable, dir))
   1.226 +    end
   1.227 +
   1.228 +    --  provide result directory
   1.229 +    return dir
   1.230 +end
   1.231 +

mercurial