On 05/17/2013 04:46 PM, Daniel P. Berrange wrote:
On Fri, May 17, 2013 at 04:37:13PM +0200, Florian Weimer wrote:
I'd like some scriptable way to unpack SRPMs up and including to the
%prep stage. Ideally, the results would end up in a directory I
specify, and intermediate directories which only contain a single
subdirectory are skipped. (The eventual goal is to run two such
directory tress through diff -uraN, and I want to avoid spurious
differences due to an update from foo-1.2 to foo-1.3.)
I've already learned the hard way that I need to use something like
mock because some %prep script assume that build requires are
installed. But mock does not appear to support an option to stop
after the %prep stage.
I guess you were using the --rebuild arg to mock ? Can you do
something like this where you invoke rpmbuild explicitly with
the args you need to just run upto %prep:
mock --init
mock --installdeps /path/to/srpm
mock --copyin /path/to/srpm /srpm
mock --shell /usr/bin/rpmbuild -bp /srpm
I put the various suggestions in this thread together and the attached
script appears to work. Admittedly, some parts of it are rather ugly.
--
Florian Weimer / Red Hat Product Security Team
#!/usr/bin/python
# Copyright (C) 2013 Red Hat, Inc.
# Written by Florian Weimer <fweimer@xxxxxxxxxx>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# This script expects a mock configuration name and a path to a source
# RPM. It unpacks the source RPM by executing the build process in a
# mock configuration up to and including the %prep stage. The
# resulting directory tree is then copied into a subdirectory of the
# current directory, named after the source package NVR.
import base64
import getopt
import os.path
import rpm
import subprocess
import sys
MOCK = '/usr/bin/mock'
VERBOSE = False
SKIP_DIRECTORIES = True
def usage():
sys.stderr.write("""usage: {0} [-Sv] [-d PATH] MOCK-CONFIG SRPM-FILE
Options:
-S do not strip leading directories which contain a single subdirectory
-v increase verbosity
-d PATH set the destination directory to PATH
""".format(sys.argv[0]))
sys.exit(1)
def run_mock(config, *args):
argv = [MOCK]
if VERBOSE:
argv += ["-v"]
argv += ["-r", config]
argv += args
subprocess.call(argv)
def run_mock_shell(config, cmd):
# Do not depend on multiple unquoting steps within mock.
quoted = base64.b64encode(cmd)
run_mock(config, "--shell", "echo {}|base64 -d|bash".format(quoted))
def read_rpm(rpmpath):
ts = rpm.TransactionSet()
ts.VSFlags = rpm._RPMVSF_NOSIGNATURES
with file(rpmpath, "rb") as f:
return ts.hdrFromFdno(f.fileno())
def skip_directories(target):
# Prunes leading directories which contain only one subdirectory.
while True:
subdirs = os.listdir(target)
if len(subdirs) == 1:
tmp = target + ".tmp"
os.rename(target, tmp)
os.rename(os.path.join(tmp, subdirs[0]), target)
os.rmdir(tmp)
else:
break
def err(fmt, *args):
sys.stderr.write("error: " + fmt.format(*args) + "\n")
sys.exit(1)
def doit(config, rpmpath, target):
if not os.path.exists(rpmpath):
err("source RPM file not found: {}", rpmpath)
rpm_header = read_rpm(rpmpath)
rpm_name = rpm_header[rpm.RPMTAG_NAME]
nvr = "-".join((rpm_name,
rpm_header[rpm.RPMTAG_VERSION],
rpm_header[rpm.RPMTAG_RELEASE]))
for bad in " /'\"":
if bad in nvr:
err("invalid character {!r} in NVR: {!r}", bad, nvr)
if target is None:
target = nvr
if os.path.exists(target):
err("destination directory already exists: {}", target)
srpm_in_chroot = "/{}.src.rpm".format(nvr)
dbdir_in_chroot = "/{}.src.db".format(nvr)
builddir_in_chroot = "/builddir/build/BUILD"
spec_in_chroot = "/builddir/build/SPECS/{}.spec".format(rpm_name)
run_mock(config, "--init")
run_mock(config, "--installdeps", rpmpath)
run_mock(config, "--copyin", rpmpath, srpm_in_chroot)
# Use separate RPM database because even inside the chroot, the
# host RPM database format is used, which is generally
# incompatible with the /usr/bin/rpm in the chroot.
cmd = "rpm -i --dbpath {0} {1} && rpmbuild -bp --nodeps {2} ".format(
dbdir_in_chroot, srpm_in_chroot, spec_in_chroot)
if VERBOSE:
cmd = "set -x; " + cmd
run_mock_shell(config, cmd)
run_mock(config, "--copyout", builddir_in_chroot, "./" + target)
if SKIP_DIRECTORIES:
skip_directories(target)
try:
options, arguments = getopt.gnu_getopt(sys.argv[1:], "Sd:v")
except getopt.GetoptError:
usage()
target = None
for opt, arg in options:
if opt == "-S":
SKIP_DIRECTORIES = False
elif opt == "-d":
target = arg
elif opt == "-v":
VERBOSE = True
else:
assert False
if len(arguments) != 2:
usage()
doit(arguments[0], arguments[1], target)
--
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxxx
https://admin.fedoraproject.org/mailman/listinfo/devel