aboutsummaryrefslogtreecommitdiffstats
path: root/MgaRepo/rpmutil.py
diff options
context:
space:
mode:
Diffstat (limited to 'MgaRepo/rpmutil.py')
-rw-r--r--MgaRepo/rpmutil.py314
1 files changed, 243 insertions, 71 deletions
diff --git a/MgaRepo/rpmutil.py b/MgaRepo/rpmutil.py
index 769167c..49ef07f 100644
--- a/MgaRepo/rpmutil.py
+++ b/MgaRepo/rpmutil.py
@@ -1,9 +1,10 @@
#!/usr/bin/python3
from MgaRepo import Error, config
from MgaRepo import mirror, layout, log, binrepo
+from MgaRepo.git import GIT
from MgaRepo.svn import SVN
from MgaRepo.simplerpm import SRPM
-from MgaRepo.util import execcmd
+from MgaRepo.util import execcmd, CommandError
from MgaRepo.command import default_parent
import rpm
import urllib.parse
@@ -14,13 +15,38 @@ import glob
import sys
import os
+def detectVCS(url):
+ if ':' in url:
+ protocol,uri = url.split(":")
+ if "svn" in protocol:
+ return SVN(url=url)
+ elif "git" in protocol:
+ return GIT(url=url)
+ elif "http" in protocol:
+ if uri.endswith(".git"):
+ return GIT(url=url)
+ elif "svn" in uri:
+ return SVN(url=url)
+ raise Error("Unknown protocol %s for %s" % (protocol, url))
+ elif os.path.exists(url) and os.path.isdir(url):
+ while True:
+ url = os.path.abspath(url)
+ for vcs in (SVN, GIT):
+ vcsdir = os.path.join(url, vcs.vcs_dirname)
+ if os.path.exists(vcsdir) and os.path.isdir(vcsdir):
+ return vcs(path=url)
+ url = os.path.dirname(url)
+ if url == "/":
+ break
+ raise Error("No supported repository found at path: %s" % url)
+
def get_spec(pkgdirurl, targetdir=".", submit=False):
- svn = SVN()
+ svn = detectVCS(pkgdirurl)
tmpdir = tempfile.mktemp()
try:
geturl = layout.checkout_url(pkgdirurl, append_path="SPECS")
mirror.info(geturl)
- svn.export("'%s'" % geturl, tmpdir)
+ svn.export(geturl, tmpdir)
speclist = glob.glob(os.path.join(tmpdir, "*.spec"))
if not speclist:
raise Error("no spec files found")
@@ -33,14 +59,9 @@ def get_spec(pkgdirurl, targetdir=".", submit=False):
if os.path.isdir(tmpdir):
shutil.rmtree(tmpdir)
-def rpm_macros_defs(macros):
- defs = ("--define \"%s %s\"" % macro for macro in macros)
- args = " ".join(defs)
- return args
-
#FIXME move it to another module
def rev_touched_url(url, rev):
- svn = SVN()
+ svn = detectVCS(url)
info = svn.info2(url)
if info is None:
raise Error("can't fetch svn info about the URL: %s" % url)
@@ -95,16 +116,21 @@ def get_srpm(pkgdirurl,
template = None,
macros = [],
verbose = 0,
- strict = False):
- svn = SVN()
+ strict = False,
+ fullnames = False):
+ svn = detectVCS(pkgdirurl)
tmpdir = tempfile.mktemp()
- topdir = "--define '_topdir %s'" % tmpdir
- builddir = "--define '_builddir %s/%s'" % (tmpdir, "BUILD")
- rpmdir = "--define '_rpmdir %s/%s'" % (tmpdir, "RPMS")
- sourcedir = "--define '_sourcedir %s/%s'" % (tmpdir, "SOURCES")
- specdir = "--define '_specdir %s/%s'" % (tmpdir, "SPECS")
- srcrpmdir = "--define '_srcrpmdir %s/%s'" % (tmpdir, "SRPMS")
- patchdir = "--define '_patchdir %s/%s'" % (tmpdir, "SOURCES")
+ topdir = "_topdir %s" % tmpdir
+ builddir = "_builddir %s/%s" % (tmpdir, "BUILD")
+ rpmdir = "_rpmdir %s/%s" % (tmpdir, "RPMS")
+ sourcedir = "_sourcedir %s/%s" % (tmpdir, "SOURCES")
+ specdir = "_specdir %s/%s" % (tmpdir, "SPECS")
+ srcrpmdir = "_srcrpmdir %s/%s" % (tmpdir, "SRPMS")
+ patchdir = "_patchdir %s/%s" % (tmpdir, "SOURCES")
+ temppath = "_tmppath %s" % (tmpdir)
+
+ rpmdefs = [("--define", expr) for expr in (topdir, builddir, rpmdir,
+ sourcedir, specdir, srcrpmdir, patchdir, temppath)]
try:
if mode == "version":
@@ -133,24 +159,29 @@ def get_srpm(pkgdirurl,
if config.getbool("srpm", "run-prep", False):
makefile = os.path.join(tmpdir, "Makefile")
if os.path.exists(makefile):
- execcmd("make", "-C", tmpdir, "srpm-prep")
+ execcmd(("make", "-C", tmpdir, "srpm-prep"))
if not speclist:
raise Error("no spec files found")
spec = speclist[0]
- defs = rpm_macros_defs(macros)
sourcecmd = config.get("helper", "rpmbuild", "rpmbuild")
if packager:
packager = " --define 'packager %s'" % packager
+ sourcecmd = config.get("helper", "rpmbuild", "rpmbuild")
+ args = [sourcecmd, "-bs", "--nodeps"]
+ for pair in rpmdefs:
+ args.extend(pair)
+ for pair in macros:
+ args.extend(("--define", "%s %s" % pair))
+ args.append(spec)
if svnlog:
submit = not not revision
try:
log.specfile_svn2rpm(pkgdirurl, spec, revision, submit=submit,
- template=template, macros=macros, exported=tmpdir)
+ template=template, macros=macros, exported=tmpdir, fullnames=fullnames)
except:
- execcmd("%s -bs --nodeps %s %s %s %s %s %s %s %s %s %s" %
- (sourcecmd, topdir, builddir, rpmdir, sourcedir, specdir,
- srcrpmdir, patchdir, packager, spec, defs))
+ #cmd = [sourcecmd, topdir, builddir, rpmdir, sourcedir, specdir
+ execcmd(args)
cp_srpms(revision, revname, geturl, targetdirs, srpmsdir, verbose)
log.specfile_svn2rpm(pkgdirurl, spec, revision, submit=submit,
template=template, macros=macros, exported=tmpdir, create=True)
@@ -162,9 +193,15 @@ def get_srpm(pkgdirurl,
if status != 0:
raise Error("script %s failed" % script)
- execcmd("%s -bs --nodeps %s %s %s %s %s %s %s %s %s %s" %
- (sourcecmd, topdir, builddir, rpmdir, sourcedir, specdir,
- srcrpmdir, patchdir, packager, spec, defs))
+ try:
+ execcmd(args)
+ except CommandError as e:
+ if config.getbool("global", "verbose"):
+ cmdline = e.cmdline + "\n"
+ else:
+ cmdline = ""
+ raise Error("error while creating the source RPM "
+ "(with %s):\n%s%s" % (sourcecmd, cmdline, e.output))
# copy the generated SRPMs to their target locations
targetsrpms = cp_srpms(revision, revname, geturl, targetdirs, srpmsdir, verbose)
@@ -175,7 +212,7 @@ def get_srpm(pkgdirurl,
def patch_spec(pkgdirurl, patchfile, log=""):
#FIXME use get_spec
- svn = SVN()
+ svn = detectVCS(pkgdirurl)
tmpdir = tempfile.mktemp()
try:
geturl = layout.checkout_url(pkgdirurl, append_path="SPECS")
@@ -184,7 +221,7 @@ def patch_spec(pkgdirurl, patchfile, log=""):
if not speclist:
raise Error("no spec files found")
spec = speclist[0]
- status, output = execcmd("patch", spec, patchfile)
+ status, output = execcmd(["patch", spec, patchfile])
if status != 0:
raise Error("can't apply patch:\n%s\n" % output)
else:
@@ -195,7 +232,6 @@ def patch_spec(pkgdirurl, patchfile, log=""):
def put_srpm(srpmfile, markrelease=False, striplog=True, branch=None,
baseurl=None, baseold=None, logmsg=None, rename=True):
- svn = SVN()
srpm = SRPM(srpmfile)
tmpdir = tempfile.mktemp()
if baseurl:
@@ -203,6 +239,7 @@ def put_srpm(srpmfile, markrelease=False, striplog=True, branch=None,
else:
pkgurl = layout.package_url(srpm.name, distro=branch,
mirrored=False)
+ svn = detectVCS(pkgdirurl)
print("Importing package to %s" % pkgurl)
try:
if srpm.epoch:
@@ -264,9 +301,9 @@ def put_srpm(srpmfile, markrelease=False, striplog=True, branch=None,
svn.remove(entrypath)
# Copy all files
- execcmd("cp -rlf", uspecsdir, currentdir)
+ execcmd(["cp", "-rf", uspecsdir, currentdir])
if os.path.isdir(usourcesdir):
- execcmd("cp -rlf", usourcesdir, currentdir)
+ execcmd(["cp", "-rlf", usourcesdir, currentdir])
# Add new entries
for entry in [x for x in uspecsentries
@@ -355,8 +392,106 @@ def put_srpm(srpmfile, markrelease=False, striplog=True, branch=None,
log="Copying release %s-%s to releases/ directory." %
(version, srpm.release))
+def build_rpm(build_cmd="b",
+ verbose=True,
+ rpmlint=True,
+ short_circuit=False,
+ packager = None,
+ installdeps = True,
+ use_dnf = False,
+ svnlog = False,
+ fullnames = True,
+ macros = [],
+ **rpmargs):
+ top = os.getcwd()
+ topdir = "_topdir %s" % top
+ builddir = "_builddir %s/%s" % (top, "BUILD")
+ rpmdir = "_rpmdir %s/%s" % (top, "RPMS")
+ sourcedir = "_sourcedir %s/%s" % (top, "SOURCES")
+ specdir = "_specdir %s/%s" % (top, "SPECS")
+ srcrpmdir = "_srcrpmdir %s/%s" % (top, "SRPMS")
+ patchdir = "_patchdir %s/%s" % (top, "SOURCES")
+
+ build = os.path.join(top, "BUILD")
+ if not os.path.exists(build):
+ os.mkdir(build)
+ specsdir = os.path.join(top, "SPECS")
+ speclist = glob.glob(os.path.join(specsdir, "*.spec"))
+ if not speclist:
+ raise Error("no spec files found")
+ spec = speclist[0]
+
+ # If we're building package with %changelog, we'll make a temporary
+ # copy of the spec file with %changelog applied that we'll use for
+ # building. This way we avoid modifying files in repository.
+ # TODO: implement support for external changelog in rpm
+ if svnlog:
+ vcs = detectVCS(top)
+ specsdir = tempfile.mkdtemp()
+ shutil.copy(spec, specsdir)
+ specdir = "_specdir "+specsdir
+ spec = os.path.join(specsdir,os.path.basename(spec))
+ info = vcs.info2(top)
+ pkgdirurl = layout.remove_current(info["URL"])
+ log.specfile_svn2rpm(pkgdirurl, spec, rev=None, submit=False,
+ template=None, macros=macros, exported=top, fullnames=fullnames)
+
+ rpmdefs = [("--define", expr) for expr in (topdir, builddir, rpmdir,
+ sourcedir, specdir, srcrpmdir, patchdir)]
+
+ if packager:
+ rpmdefs.append(("--define", "packager %s" % packager))
+
+ if rpmlint:
+ rpmdefs.append(("--define", "_build_pkgcheck_set %{_bindir}/rpmlint"))
+
+ rpmbuild = config.get("helper", "rpmbuild", "rpmbuild")
+ args = [rpmbuild, spec]
+ if short_circuit:
+ args.append("--short-circuit")
+ for pair in rpmdefs:
+ args.extend(pair)
+ for pair in macros:
+ args.extend(("--define", "%s %s" % pair))
+ args.extend(("--define", "_disable_source_fetch 0"))
+ args.extend(*rpmargs.values())
+ os.environ["LC_ALL"] = "C"
+ # First check whether dependencies are satisfied
+ status, output = execcmd(*args + ["--nobuild"], show=verbose, collecterr=True, noerror=True)
+ if status:
+ if "error: Failed build dependencies:" in output:
+ if not installdeps:
+ raise Error("Automatic installation of dependencies disabled,"
+ "aborting...")
+ else:
+ if verbose:
+ print("Installing missing build dependencies")
+ if use_dnf:
+ pkg_mgr_base = ["dnf"]
+ pkg_mgr_builddep = pkg_mgr_base + ["--assume-yes", "--setopt=install_weak_deps=False", "builddep"]
+ else:
+ pkg_mgr_base = ["urpmi"]
+ pkg_mgr_builddep = pkg_mgr_base + ["--auto", "--buildrequires", "--no-recommends"]
+ if os.getuid() != 0:
+ print("Trying to obtain privileges for installing build dependencies:")
+ sudocheck = ["sudo", "-l"] + pkg_mgr_base
+ status, output = execcmd(*sudocheck, collecter=True, noerror=True)
+ if status:
+ raise Error("%s\nFailed! Cannot proceed without, aborting..."
+ % output.splitlines()[-1])
+ cmd_base = ["sudo"] + pkg_mgr_builddep
+ else:
+ cmd_base = pkg_mgr_builddep
+ cmd = cmd_base + [spec]
+ status, output = execcmd(*cmd, show=verbose, collecter=True, noerror=True)
+
+ status, output = execcmd(*args + ["-b"+build_cmd], show=verbose)
+ if svnlog:
+ if os.path.isdir(specsdir):
+ shutil.rmtree(specsdir)
+
def create_package(pkgdirurl, log="", verbose=0):
- svn = SVN()
+ svn = detectVCS(pkgdirurl)
tmpdir = tempfile.mktemp()
try:
basename = layout.package_name(pkgdirurl)
@@ -397,7 +532,7 @@ revision: %s
return log
def mark_release(pkgdirurl, version, release, revision):
- svn = SVN()
+ svn = detectVCS(pkgdirurl)
releasesurl = layout.checkout_url(pkgdirurl, releases=True)
versionurl = "/".join([releasesurl, version])
releaseurl = "/".join([versionurl, release])
@@ -419,7 +554,7 @@ def mark_release(pkgdirurl, version, release, revision):
log=markreleaselog)
def check_changed(pkgdirurl, all=0, show=0, verbose=0):
- svn = SVN()
+ svn = detectVCS(pkgdirurl)
if all:
baseurl = pkgdirurl
packages = []
@@ -490,33 +625,48 @@ def checkout(pkgdirurl, path=None, revision=None, branch=None, distro=None, back
if path is None:
path = layout.package_name(pkgdirurl)
mirror.info(current, write=True)
- svn = SVN()
+ svn = detectVCS(pkgdirurl)
svn.checkout(current, path, rev=revision, show=1)
if not spec:
binrepo.download_binaries(path)
-def getpkgtopdir(basedir=None):
- #FIXME this implementation doesn't work well with relative path names,
- # which is something we need in order to have a friendlier output
- if basedir is None:
- basedir = os.path.curdir
- while not ispkgtopdir(basedir):
- if os.path.abspath(basedir) == "/":
- raise Error("can't find top package directories SOURCES and SPECS")
- basedir = os.path.join(basedir, os.path.pardir)
- if basedir.startswith("./"):
- basedir = basedir[2:]
- return basedir
-
-def ispkgtopdir(path=None):
+def clone(pkgdirurl, path=None, revision=None, branch=None, distro=None, backports=None,
+ spec=False, fullnames = True, bindownload = True):
+ o_pkgdirurl = pkgdirurl
+ pkgdirurl = layout.package_url(o_pkgdirurl, distro=distro, backports=backports)
+ append = None
+ if spec:
+ append = "SPECS"
+ current = layout.checkout_url(pkgdirurl, branch=branch, backports=backports,
+ append_path=append)
+ if path is None:
+ path = layout.package_name(pkgdirurl)
+ mirror.info(current, write=True)
+ git = GIT()
+ git.clone(current, path, fullnames=fullnames, show=1)
+ if not spec and bindownload:
+ binrepo.download_binaries(path)
+
+def getpkgtopdir(basedir=os.path.curdir):
+ vcs = detectVCS(basedir)
+ if vcs:
+ basedir = os.path.relpath(vcs.get_topdir())
+ if ispkgtopdir(basedir, vcs_dirname=vcs.vcs_dirname):
+ return basedir
+ raise Error("can't find top package directories SOURCES and SPECS")
+
+def ispkgtopdir(path=None, vcs_dirname=None):
if path is None:
path = os.getcwd()
names = os.listdir(path)
- return (".svn" in names and "SPECS" in names and "SOURCES" in names)
+ if not vcs_dirname:
+ vcs = detectVCS(path)
+ vcs_dirname = vcs.vcs_dirname
+ return (vcs_dirname in names and "SPECS" in names and "SOURCES" in names)
def sync(dryrun=False, commit=False, download=False):
- svn = SVN()
topdir = getpkgtopdir()
+ svn = detectVCS(topdir)
spath = binrepo.sources_path(topdir)
binrepoentries = binrepo.parse_sources(spath)
# run svn info because svn st does not complain when topdir is not an
@@ -598,7 +748,7 @@ def sync(dryrun=False, commit=False, download=False):
upload([path], commit=commit)
def commit(target=".", message=None, logfile=None):
- svn = SVN()
+ svn = detectVCS(target)
status = svn.status(target, quiet=True)
if not status:
print("nothing to commit")
@@ -633,39 +783,41 @@ def spec_sources(topdir):
return sources
def update(target=None):
- svn = SVN()
+ vcs = None
info = None
- svn_target = None
+ vcs_target = None
br_target = None
if target:
- svn_target = target
+ vcs_target = target
else:
top = getpkgtopdir()
- svn_target = top
+ vcs_target = top
br_target = top
- if svn_target:
- svn.update(svn_target, show=True)
+ if vcs_target:
+ vcs = detectVCS(vcs_target)
+ vcs.update(vcs_target, show=True)
if br_target:
- info = svn.info2(svn_target)
- if not br_target and not svn_target:
- raise Error("target not in SVN nor in binaries "\
- "repository: %s" % target)
+ if not vcs:
+ vcs = detectVCS(br_target)
+ info = vcs.info2(vcs_target)
+ if not br_target and not vcs_target:
+ raise Error("target not in %s nor in binaries "\
+ "repository: %s" % (type(vcs).__name__,target))
url = info["URL"]
binrepo.download_binaries(br_target)
def upload(paths, commit=False):
+ topdir = getpkgtopdir()
+ svn = detectVCS(topdir)
for path in paths:
if os.path.isdir(path) or binrepo.is_binary(path):
- topdir = getpkgtopdir()
binrepo.upload_binary(topdir, os.path.basename(path))
binrepo.update_sources(topdir, added=[path])
if commit:
- svn = SVN()
silent = config.get("log", "ignore-string", "SILENT")
message = "%s: new file %s" % (silent, path)
svn.commit(binrepo.sources_path(topdir), log=message)
else:
- svn = SVN()
svn.add(path, local=True)
if commit:
silent = config.get("log", "ignore-string", "SILENT")
@@ -674,16 +826,15 @@ def upload(paths, commit=False):
def delete(paths, commit=False):
silent = config.get("log", "ignore-string", "SILENT")
+ topdir = getpkgtopdir()
+ svn = detectVCS(topdir)
for path in paths:
message = "%s: delete file %s" % (silent, path)
if binrepo.is_binary(path):
- topdir = getpkgtopdir()
binrepo.update_sources(topdir, removed=[os.path.basename(path)])
if commit:
- svn = SVN()
svn.commit(binrepo.sources_path(topdir), log=message)
else:
- svn = SVN()
svn.remove(path, local=True)
if commit:
svn.commit(path, log=message)
@@ -692,7 +843,7 @@ def obsolete(pkgdirurl, branch=None, distro=None, backports=None, commit=False,
o_pkgdirurl = pkgdirurl
pkgdirurl = layout.package_url(o_pkgdirurl, distro=distro, backports=backports)
pkgdest = layout.package_url(o_pkgdirurl, obsolete=True, backports=backports)
- svn = SVN()
+ svn = detectVCS(pkgdirurl)
svn.mv(pkgdirurl, pkgdest, message=log)
if commit:
svn.commit(path, log=log)
@@ -727,7 +878,7 @@ def get_submit_info(path):
if not os.path.isdir(os.path.join(path, ".svn")):
raise Error("subversion directory not found")
- svn = SVN()
+ svn = detectVCS(path)
# Now, extract the package name.
info = svn.info2(path)
@@ -766,4 +917,25 @@ def get_submit_info(path):
return name, url, max
+def get_pkg_tag(tag, path=os.path.curdir, subpkg=None):
+ topdir = getpkgtopdir(path)
+ speclist = glob.glob(os.path.join(topdir, "SPECS", "*.spec"))
+ if not speclist:
+ raise Error("no spec files found")
+ specfile = speclist[0]
+
+ pkg = rpm.spec(specfile)
+ if subpkg is None:
+ header = pkg.sourceHeader
+ elif isinstance(subpkg,int):
+ header = pkg.packages(subpkg)
+ else:
+ raise Error("Subpkg must be the index number of a package,"\
+ "or None for source package")
+
+ if isinstance(header[tag],bytes):
+ return header[tag].decode("utf8")
+ else:
+ return header[tag]
+
# vim:et:ts=4:sw=4