From 5f1a15b9c7b253c0267d05613683ac1fb5f88e6c Mon Sep 17 00:00:00 2001 From: Bogdano Arendartchuk Date: Tue, 5 Jun 2007 19:17:27 +0000 Subject: Improved (and fixed) the support to mirrors and "switch" subcommand - added the switch subcommand to quickly switch between the default and the mirrored repositories - fixed bug of generating bogus mirror URLs - make "ci" smarter by only relocation if something has been changed in the working copy and it is not already relocated. --- RepSys/commands/switch.py | 32 ++++++++++++++++++++ RepSys/mirror.py | 76 +++++++++++++++++++++++++++++++++++++++++++---- RepSys/rpmutil.py | 29 +++++++++++++++--- RepSys/svn.py | 2 ++ repsys | 1 + 5 files changed, 131 insertions(+), 9 deletions(-) create mode 100644 RepSys/commands/switch.py diff --git a/RepSys/commands/switch.py b/RepSys/commands/switch.py new file mode 100644 index 0000000..dcbdd17 --- /dev/null +++ b/RepSys/commands/switch.py @@ -0,0 +1,32 @@ +#!/usr/bin/python +from RepSys.command import * +from RepSys.rpmutil import switch + +HELP = """\ +Usage: repsys switch [URL] + +Relocates the working copy to the base location URL. If URL is not +provided, it will use the option default_parent from repsys.conf as +default, or, if the current working copy is already based in +default_parent, it will use the location from the mirror option from +repsys.conf. + +If the current work is based in another URL, it will use default_parent. + +Options: + -h Show this message + +Examples: + repsys switch + repsys switch https://mirrors.localnetwork/svn/packages/cooker +""" + +def parse_options(): + parser = OptionParser(help=HELP) + opts, args = parser.parse_args() + if len(args): + opts.mirrorurl = args[0] + return opts + +def main(): + do_command(parse_options, switch) diff --git a/RepSys/mirror.py b/RepSys/mirror.py index a24f594..6acc839 100644 --- a/RepSys/mirror.py +++ b/RepSys/mirror.py @@ -4,16 +4,46 @@ import urlparse from RepSys import config from RepSys.svn import SVN +def _normdirurl(url): + """normalize url for relocate_path needs""" + parsed = urlparse.urlparse(url) + path = os.path.normpath(parsed.path) + path += "/" # assuming we always deal with directories + newurl = urlparse.urlunparse((parsed.scheme, parsed.netloc, path, + parsed.params, parsed.query, parsed.fragment)) + return newurl + +def _joinurl(url, relpath): + parsed = urlparse.urlparse(url) + newpath = os.path.join(parsed.path, relpath) + newurl = urlparse.urlunparse((parsed.scheme, parsed.netloc, newpath, + parsed.params, parsed.query, parsed.fragment)) + return newurl + +def same_base(parent, url): + """returns true if parent is parent of url""" + parent = _normdirurl(parent) + url = _normdirurl(url) + #FIXME handle paths with/without username/password + return url.startswith(parent) + def relocate_path(oldparent, newparent, url): - subpath = url[len(oldparent)-1:] - newurl = newparent + "/" + subpath # subpath usually gets / at begining + oldparent = _normdirurl(oldparent) + newparent = _normdirurl(newparent) + url = _normdirurl(url) + subpath = url[len(oldparent):] + newurl = _joinurl(newparent, subpath) # subpath usually gets / at begining return newurl -def enabled(): +def enabled(wcurl=None): mirror = config.get("global", "mirror") default_parent = config.get("global", "default_parent") - return (mirror is not None and - default_parent is not None) + enabled = False + if mirror and default_parent: + enabled = True + if wcurl and (not same_base(mirror, wcurl)): + enabled = False + return enabled def mirror_relocate(oldparent, newparent, url, wcpath): svn = SVN(noauth=True) @@ -40,3 +70,39 @@ def checkout_url(url): if mirror is not None and default_parent is not None: return relocate_path(default_parent, mirror, url) return url + +def autoswitch(svn, wcpath, wcurl, newbaseurl=None): + """Switches between mirror, default_parent, or newbaseurl""" + nobase = False + mirror = config.get("global", "mirror") + default_parent = config.get("global", "default_parent") + current = default_parent + if default_parent is None: + raise Error, "the option default_parent from repsys.conf is "\ + "required" + indefault = same_base(default_parent, wcurl) + if not newbaseurl: + if not mirror: + raise Error, "an URL is needed when the option mirror "\ + "from repsys.conf is not set" + if indefault: + chosen = mirror + elif same_base(mirror, wcurl): + current = mirror + chosen = default_parent + else: + nobase = True + else: + if mirror and same_base(mirror, wcurl): + current = mirror + elif indefault: + pass # !!!! + else: + nobase = True + chosen = newbaseurl + if nobase: + raise Error, "the URL of this working copy is not based in "\ + "default_parent nor mirror URLs" + assert current != chosen + newurl = mirror_relocate(current, chosen, wcurl, wcpath) + return newurl diff --git a/RepSys/rpmutil.py b/RepSys/rpmutil.py index a0eb22e..413c152 100644 --- a/RepSys/rpmutil.py +++ b/RepSys/rpmutil.py @@ -368,14 +368,20 @@ def checkout(pkgdirurl, path=None, revision=None): print "checking out from mirror", current svn.checkout(current, path, rev=revision, show=1) -def sync(dryrun=False): - svn = SVN(noauth=True) +def _getpkgtopdir(basedir=None): + if basedir is None: + basedir = os.getcwd() cwd = os.getcwd() dirname = os.path.basename(cwd) if dirname == "SPECS" or dirname == "SOURCES": topdir = os.pardir else: topdir = "" + return topdir + +def sync(dryrun=False): + svn = SVN(noauth=True) + topdir = _getpkgtopdir() # run svn info because svn st does not complain when topdir is not an # working copy svn.info(topdir or ".") @@ -425,11 +431,16 @@ def sync(dryrun=False): def commit(target=".", message=None): svn = SVN(noauth=True) + status = svn.status(target, quiet=True) + if not status: + print "nothing to commit" + return info = svn.info2(target) url = info.get("URL") if url is None: raise Error, "working copy URL not provided by svn info" - if mirror.enabled(): + mirrored = mirror.enabled(url) + if mirrored: newurl = mirror.switchto_parent(svn, url, target) print "relocated to", newurl try: @@ -439,10 +450,20 @@ def commit(target=".", message=None): mopt = "-m \"%s\"" % message os.system("svn ci %s %s" % (mopt, target)) finally: - if mirror.enabled(): + if mirrored: mirror.switchto_mirror(svn, newurl, target) print "relocated back to", url +def switch(mirrorurl=None): + svn = SVN(noauth=True) + topdir = _getpkgtopdir() + 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 + def get_submit_info(path): path = os.path.abspath(path) diff --git a/RepSys/svn.py b/RepSys/svn.py index b4ad4e9..cc3811d 100644 --- a/RepSys/svn.py +++ b/RepSys/svn.py @@ -189,6 +189,8 @@ class SVN: cmd.append("-v") if kwargs.get("noignore"): cmd.append("--no-ignore") + if kwargs.get("quiet"): + cmd.append("--quiet") status, output = self._execsvn(*cmd, **kwargs) if status == 0: return [x.split() for x in output.splitlines()] diff --git a/repsys b/repsys index 6c4d4b9..10b2b55 100755 --- a/repsys +++ b/repsys @@ -21,6 +21,7 @@ Useful commands: changed authoremail putsrpm + switch Run "repsys COMMAND --help" for more information. -- cgit v1.2.1