aboutsummaryrefslogtreecommitdiffstats
path: root/RepSys/rpmutil.py
diff options
context:
space:
mode:
Diffstat (limited to 'RepSys/rpmutil.py')
-rw-r--r--RepSys/rpmutil.py161
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