diff options
Diffstat (limited to 'RepSys/rpmutil.py')
-rw-r--r-- | RepSys/rpmutil.py | 161 |
1 files changed, 108 insertions, 53 deletions
diff --git a/RepSys/rpmutil.py b/RepSys/rpmutil.py index 4cbba62..3bb1b50 100644 --- a/RepSys/rpmutil.py +++ b/RepSys/rpmutil.py @@ -5,11 +5,11 @@ from RepSys.svn import SVN from RepSys.simplerpm import SRPM from RepSys.log import specfile_svn2rpm from RepSys.util import execcmd -import pysvn from RepSys.command import default_parent import rpm import tempfile import shutil +import string import glob import sys import os @@ -19,7 +19,7 @@ def get_spec(pkgdirurl, targetdir=".", submit=False): tmpdir = tempfile.mktemp() try: geturl = "/".join([pkgdirurl, "current", "SPECS"]) - svn.export("%s" % geturl, tmpdir) + svn.export("'%s'" % geturl, tmpdir) speclist = glob.glob(os.path.join(tmpdir, "*.spec")) if not speclist: raise Error, "no spec files found" @@ -34,6 +34,22 @@ def rpm_macros_defs(macros): args = " ".join(defs) return args +def rev_touched_url(url, rev): + svn = SVN() + info = svn.info2(url) + if info is None: + raise Error, "can't fetch svn info about the URL: %s" % url + root = info["Repository Root"] + urlpath = url[len(root):] + touched = False + entries = svn.log(root, start=rev, limit=1) + entry = entries[0] + for change in entry.changed: + path = change.get("path") + if path and path.startswith(urlpath): + touched = True + return touched + def get_srpm(pkgdirurl, mode = "current", targetdirs = None, @@ -47,7 +63,8 @@ def get_srpm(pkgdirurl, submit = False, template = None, macros = [], - verbose = 0): + verbose = 0, + strict = False): svn = SVN() tmpdir = tempfile.mktemp() topdir = "--define '_topdir %s'" % tmpdir @@ -67,7 +84,13 @@ def get_srpm(pkgdirurl, geturl = os.path.join(pkgdirurl, "current") else: raise Error, "unsupported get_srpm mode: %s" % mode - exportedrev = svn.export(geturl, tmpdir, revision=SVN.makerev(revision)) + strict = strict or config.getbool("submit", "strict-revision", False) + if strict and not rev_touched_url(geturl, revision): + #FIXME would be nice to have the revision number even when + # revision is None + raise Error, "the revision %s does not change anything "\ + "inside %s" % (revision or "HEAD", geturl) + svn.export(geturl, tmpdir, rev=revision) srpmsdir = os.path.join(tmpdir, "SRPMS") os.mkdir(srpmsdir) specsdir = os.path.join(tmpdir, "SPECS") @@ -79,6 +102,9 @@ def get_srpm(pkgdirurl, submit = not not revision specfile_svn2rpm(pkgdirurl, spec, revision, submit=submit, template=template, macros=macros, exported=tmpdir) + #FIXME revisioreal not needed if revision is None + #FIXME use geturl instead of pkgdirurl + revisionreal = svn.revision(pkgdirurl) for script in scripts: #FIXME revision can be "None" status, output = execcmd(script, tmpdir, spec, str(revision), @@ -93,13 +119,13 @@ def get_srpm(pkgdirurl, (topdir, builddir, rpmdir, sourcedir, specdir, srcrpmdir, patchdir, packager, spec, defs)) - if revision: + if revision and revisionreal: #FIXME duplicate glob line srpm = glob.glob(os.path.join(srpmsdir, "*.src.rpm"))[0] srpminfo = SRPM(srpm) release = srpminfo.release srpmbase = os.path.basename(srpm) - os.rename(srpm, "%s/@%s:%s" % (srpmsdir, exportedrev.number, srpmbase)) + os.rename(srpm, "%s/@%s:%s" % (srpmsdir, revisionreal, srpmbase)) srpm = glob.glob(os.path.join(srpmsdir, "*.src.rpm"))[0] if not targetdirs: targetdirs = (".",) @@ -131,7 +157,7 @@ def patch_spec(pkgdirurl, patchfile, log=""): if status != 0: raise Error, "can't apply patch:\n%s\n" % output else: - svn.checkin(tmpdir, log=log) + svn.commit(tmpdir, log="") finally: if os.path.isdir(tmpdir): shutil.rmtree(tmpdir) @@ -149,7 +175,9 @@ def put_srpm(pkgdirurl, srpmfile, appendname=0, log=""): version = srpm.version versionurl = "/".join([pkgdirurl, "releases", version]) releaseurl = "/".join([versionurl, srpm.release]) - ret = svn.mkdir(pkgdirurl, "Created package directory", noerror=1) + #FIXME when pre-commit hook fails, there's no clear way to know + # what happened + ret = svn.mkdir(pkgdirurl, noerror=1, log="Created package directory") if ret: svn.checkout(pkgdirurl, tmpdir) svn.mkdir(os.path.join(tmpdir, "releases")) @@ -161,7 +189,7 @@ def put_srpm(pkgdirurl, srpmfile, appendname=0, log=""): version_exists = 1 currentdir = os.path.join(tmpdir, "current") else: - if svn.exists(releaseurl): + if svn.ls(releaseurl, noerror=1): raise Error, "release already exists" svn.checkout("/".join([pkgdirurl, "current"]), tmpdir) svn.mkdir(versionurl, noerror=1, @@ -217,7 +245,7 @@ def put_srpm(pkgdirurl, srpmfile, appendname=0, log=""): if os.path.isdir(unpackdir): shutil.rmtree(unpackdir) - svn.checkin(tmpdir, log=log) + svn.commit(tmpdir, log=log) finally: if os.path.isdir(tmpdir): shutil.rmtree(tmpdir) @@ -257,7 +285,7 @@ def create_package(pkgdirurl, log="", verbose=0): if verbose: print "done" print "Committing...", - svn.checkin(tmpdir, + svn.commit(tmpdir, log="Created package structure for '%s'." % basename) print "done" finally: @@ -280,7 +308,7 @@ def mark_release(pkgdirurl, version, release, revision): releasesurl = "/".join([pkgdirurl, "releases"]) versionurl = "/".join([releasesurl, version]) releaseurl = "/".join([versionurl, release]) - if svn.exists(releaseurl, noerror=1): + if svn.ls(releaseurl, noerror=1): raise Error, "release already exists" svn.mkdir(releasesurl, noerror=1, log="Created releases directory.") @@ -294,7 +322,7 @@ def mark_release(pkgdirurl, version, release, revision): log="Copying release %s-%s to pristine/ directory." % (version, release)) markreleaselog = create_markrelease_log(version, release, revision) - svn.copy(currenturl, releaseurl, revision=revision, + svn.copy(currenturl, releaseurl, rev=revision, log=markreleaselog) def check_changed(pkgdirurl, all=0, show=0, verbose=0): @@ -305,29 +333,30 @@ def check_changed(pkgdirurl, all=0, show=0, verbose=0): if verbose: print "Getting list of packages...", sys.stdout.flush() - packages = [x['name'] for x in svn.ls(baseurl)] + packages = [x[:-1] for x in svn.ls(baseurl)] if verbose: print "done" if not packages: raise Error, "couldn't get list of packages" else: - packages = [pkgdirurl] + baseurl, basename = os.path.split(pkgdirurl) + packages = [basename] clean = [] changed = [] nopristine = [] nocurrent = [] - for pkgdirurl in packages: - package = os.path.basename(pkgdirurl) + for package in packages: + pkgdirurl = os.path.join(baseurl, package) current = os.path.join(pkgdirurl, "current") pristine = os.path.join(pkgdirurl, "pristine") if verbose: print "Checking package %s..." % package, sys.stdout.flush() - if not svn.exists(current): + if not svn.ls(current, noerror=1): if verbose: print "NO CURRENT" nocurrent.append(package) - elif not svn.exists(pristine): + elif not svn.ls(pristine, noerror=1): if verbose: print "NO PRISTINE" nopristine.append(package) @@ -368,7 +397,7 @@ def checkout(pkgdirurl, path=None, revision=None, use_mirror=True): current = mirror.checkout_url(current) print "checking out from mirror", current svn = SVN() - svn.checkout(current, path, revision=SVN.makerev(revision), show=1) + svn.checkout(current, path, rev=revision, show=1) def _getpkgtopdir(basedir=None): if basedir is None: @@ -378,15 +407,15 @@ def _getpkgtopdir(basedir=None): if dirname == "SPECS" or dirname == "SOURCES": topdir = os.pardir else: - topdir = "." + topdir = "" return topdir -def sync(dryrun=False): +def sync(dryrun=False, download=False): svn = SVN() topdir = _getpkgtopdir() # run svn info because svn st does not complain when topdir is not an # working copy - svn.info(topdir) + svn.info(topdir or ".") specsdir = os.path.join(topdir, "SPECS/") sourcesdir = os.path.join(topdir, "SOURCES/") for path in (specsdir, sourcesdir): @@ -401,18 +430,34 @@ def sync(dryrun=False): spec = rpm.TransactionSet().parseSpec(specpath) except rpm.error, e: raise Error, "could not load spec file: %s" % e - sources = [os.path.basename(name) - for name, no, flags in spec.sources()] - sourcesst = dict((os.path.basename(st.path), st) - for st in svn.status(sourcesdir, get_all=False, ignore=True)) + sources = dict((os.path.basename(name), name) + for name, no, flags in spec.sources()) + sourcesst = dict((os.path.basename(path), (path, st)) + for st, path in svn.status(sourcesdir, noignore=True)) toadd = [] - for source in sources: + for source, url in sources.iteritems(): sourcepath = os.path.join(sourcesdir, source) - if sourcesst.get(source): + pst = sourcesst.get(source) + if pst: + if os.path.isfile(sourcepath): + toadd.append(sourcepath) + else: + sys.stderr.write("warning: %s not found, skipping\n" % sourcepath) + elif download and not os.path.isfile(sourcepath): + print "%s not found, downloading from %s" % (sourcepath, url) + fmt = config.get("global", "download-command", + "wget -c -O '$dest' $url") + context = {"dest": sourcepath, "url": url} + try: + cmd = string.Template(fmt).substitute(context) + except KeyError, e: + raise Error, "invalid variable %r in download-command "\ + "configuration option" % e + execcmd(cmd, show=True) if os.path.isfile(sourcepath): toadd.append(sourcepath) else: - sys.stderr.write("warning: %s not found\n" % sourcepath) + raise Error, "file not found: %s" % sourcepath # rm entries not found in sources and still in svn found = os.listdir(sourcesdir) toremove = [] @@ -426,31 +471,35 @@ def sync(dryrun=False): for path in toremove: print "D\t%s" % path if not dryrun: - svn.remove(path) + svn.remove(path, local=True) for path in toadd: print "A\t%s" % path if not dryrun: - svn.add(path) + svn.add(path, local=True) -def commit(target=".", message=None): +def commit(target=".", message=None, logfile=None): svn = SVN() - status = svn.status(target, silent=True) + status = svn.status(target, quiet=True) if not status: print "nothing to commit" return - info = svn.info(target) - url = info.url + info = svn.info2(target) + url = info.get("URL") if url is None: raise Error, "working copy URL not provided by svn info" mirrored = mirror.enabled(url) if mirrored: newurl = mirror.switchto_parent(svn, url, target) print "relocated to", newurl - # we can't use the svn object here because pexpect hides VISUAL - mopt = "" + # we can't use the svn object here because svn --non-interactive option + # hides VISUAL + opts = [] if message is not None: - mopt = "-m \"%s\"" % message - os.system("svn ci %s %s" % (mopt, target)) + opts.append("-m \"%s\"" % message) + if logfile is not None: + opts.append("-F \"%s\"" % logfile) + mopts = " ".join(opts) + os.system("svn ci %s %s" % (mopts, target)) if mirrored: print "use \"repsys switch\" in order to switch back to mirror "\ "later" @@ -458,8 +507,10 @@ def commit(target=".", message=None): def switch(mirrorurl=None): svn = SVN() topdir = _getpkgtopdir() - info = svn.info(topdir) - wcurl = info.url + info = svn.info2(topdir) + wcurl = info.get("URL") + if wcurl is None: + raise Error, "working copy URL not provided by svn info" newurl = mirror.autoswitch(svn, topdir, wcurl, mirrorurl) print "switched to", newurl @@ -483,14 +534,16 @@ def get_submit_info(path): if not os.path.isdir(os.path.join(path, ".svn")): raise Error, "subversion directory not found" - # Now, extract the package name. svn = SVN() - info = svn.info(path) - url = info.url + # Now, extract the package name. + info = svn.info2(path) + url = info.get("URL") + if url is None: + raise Error, "missing URL from svn info %s" % path toks = url.split("/") if len(toks) < 2 or toks[-1] != "current": - raise Error, "invalid package URL %s, needs current/" % url + raise Error, "unexpected URL received from 'svn info'" name = toks[-2] # Finally, guess revision. @@ -498,15 +551,17 @@ def get_submit_info(path): files = [] files.extend(glob.glob("%s/*" % specsdir)) files.extend(glob.glob("%s/*" % sourcesdir)) - for file in files: - info = svn.info(file) - if info is None: # not in working copy + for file in files: + info = svn.info2(file) + if info is None: continue - rev = info.commit_revision.number - if rev > max: - max = rev + rawrev = info.get("Last Changed Rev") + if rawrev: + rev = int(rawrev) + if rev > max: + max = rev if max == -1: - raise Error, "unable to find the latest revision" + raise Error, "revision tag not found in 'svn info' output" return name, max |