diff options
author | Nicolas Vigier <boklm@mageia.org> | 2011-01-11 00:35:59 +0000 |
---|---|---|
committer | Nicolas Vigier <boklm@mageia.org> | 2011-01-11 00:35:59 +0000 |
commit | ad7fb7807ceaee96521d779993a5e1b28650723f (patch) | |
tree | 2ece42aa7e83b7fdb51702b298aa3eec95da3573 /RepSys | |
parent | 715e125cc8d0b3fc4a79752e28a8b76a4ce97d5a (diff) | |
download | mgarepo-ad7fb7807ceaee96521d779993a5e1b28650723f.tar mgarepo-ad7fb7807ceaee96521d779993a5e1b28650723f.tar.gz mgarepo-ad7fb7807ceaee96521d779993a5e1b28650723f.tar.bz2 mgarepo-ad7fb7807ceaee96521d779993a5e1b28650723f.tar.xz mgarepo-ad7fb7807ceaee96521d779993a5e1b28650723f.zip |
rename repsys to mgarepo, RepSys to MgaRepo, and update docs and examples for Mageia
Diffstat (limited to 'RepSys')
39 files changed, 0 insertions, 4916 deletions
diff --git a/RepSys/ConfigParser.py b/RepSys/ConfigParser.py deleted file mode 100644 index 3b4e213..0000000 --- a/RepSys/ConfigParser.py +++ /dev/null @@ -1,434 +0,0 @@ -""" -This is a heavily hacked version of ConfigParser to keep the order in -which options and sections are read, and allow multiple options with -the same key. -""" -from __future__ import generators -import string, types -import re - -__all__ = ["NoSectionError","DuplicateSectionError","NoOptionError", - "InterpolationError","InterpolationDepthError","ParsingError", - "MissingSectionHeaderError","ConfigParser", - "MAX_INTERPOLATION_DEPTH"] - -DEFAULTSECT = "DEFAULT" - -MAX_INTERPOLATION_DEPTH = 10 - -# exception classes -class Error(Exception): - def __init__(self, msg=''): - self._msg = msg - Exception.__init__(self, msg) - def __repr__(self): - return self._msg - __str__ = __repr__ - -class NoSectionError(Error): - def __init__(self, section): - Error.__init__(self, 'No section: %s' % section) - self.section = section - -class DuplicateSectionError(Error): - def __init__(self, section): - Error.__init__(self, "Section %s already exists" % section) - self.section = section - -class NoOptionError(Error): - def __init__(self, option, section): - Error.__init__(self, "No option `%s' in section: %s" % - (option, section)) - self.option = option - self.section = section - -class InterpolationError(Error): - def __init__(self, reference, option, section, rawval): - Error.__init__(self, - "Bad value substitution:\n" - "\tsection: [%s]\n" - "\toption : %s\n" - "\tkey : %s\n" - "\trawval : %s\n" - % (section, option, reference, rawval)) - self.reference = reference - self.option = option - self.section = section - -class InterpolationDepthError(Error): - def __init__(self, option, section, rawval): - Error.__init__(self, - "Value interpolation too deeply recursive:\n" - "\tsection: [%s]\n" - "\toption : %s\n" - "\trawval : %s\n" - % (section, option, rawval)) - self.option = option - self.section = section - -class ParsingError(Error): - def __init__(self, filename): - Error.__init__(self, 'File contains parsing errors: %s' % filename) - self.filename = filename - self.errors = [] - - def append(self, lineno, line): - self.errors.append((lineno, line)) - self._msg = self._msg + '\n\t[line %2d]: %s' % (lineno, line) - -class MissingSectionHeaderError(ParsingError): - def __init__(self, filename, lineno, line): - Error.__init__( - self, - 'File contains no section headers.\nfile: %s, line: %d\n%s' % - (filename, lineno, line)) - self.filename = filename - self.lineno = lineno - self.line = line - -class ConfigParser: - def __init__(self, defaults=None): - # Options are stored in __sections_list like this: - # [(sectname, [(optname, optval), ...]), ...] - self.__sections_list = [] - self.__sections_dict = {} - if defaults is None: - self.__defaults = {} - else: - self.__defaults = defaults - - def defaults(self): - return self.__defaults - - def sections(self): - return self.__sections_dict.keys() - - def has_section(self, section): - return self.__sections_dict.has_key(section) - - def options(self, section): - self.__sections_dict[section] - try: - opts = self.__sections_dict[section].keys() - except KeyError: - raise NoSectionError(section) - return self.__defaults.keys()+opts - - def read(self, filenames): - if type(filenames) in types.StringTypes: - filenames = [filenames] - for filename in filenames: - try: - fp = open(filename) - except IOError: - continue - self.__read(fp, filename) - fp.close() - - def readfp(self, fp, filename=None): - if filename is None: - try: - filename = fp.name - except AttributeError: - filename = '<???>' - self.__read(fp, filename) - - def set(self, section, option, value): - if self.__sections_dict.has_key(section): - sectdict = self.__sections_dict[section] - sectlist = [] - self.__sections_list.append((section, sectlist)) - elif section == DEFAULTSECT: - sectdict = self.__defaults - sectlist = None - else: - sectdict = {} - self.__sections_dict[section] = sectdict - sectlist = [] - self.__sections_list.append((section, sectlist)) - xform = self.optionxform(option) - sectdict[xform] = value - if sectlist is not None: - sectlist.append([xform, value]) - - def get(self, section, option, raw=0, vars=None): - d = self.__defaults.copy() - try: - d.update(self.__sections_dict[section]) - except KeyError: - if section != DEFAULTSECT: - raise NoSectionError(section) - if vars: - d.update(vars) - option = self.optionxform(option) - try: - rawval = d[option] - except KeyError: - raise NoOptionError(option, section) - if raw: - return rawval - return self.__interpolate(rawval, d) - - def getall(self, section, option, raw=0, vars=None): - option = self.optionxform(option) - values = [] - d = self.__defaults.copy() - if section != DEFAULTSECT: - for sectname, options in self.__sections_list: - if sectname == section: - for optname, value in options: - if optname == option: - values.append(value) - d[optname] = value - if raw: - return values - if vars: - d.update(vars) - for i in len(values): - values[i] = self.__interpolate(values[i], d) - return values - - def walk(self, section, option=None, raw=0, vars=None): - # Build dictionary for interpolation - try: - d = self.__sections_dict[section].copy() - except KeyError: - if section == DEFAULTSECT: - d = {} - else: - raise NoSectionError(section) - d.update(self.__defaults) - if vars: - d.update(vars) - - # Start walking - if option: - option = self.optionxform(option) - if section != DEFAULTSECT: - for sectname, options in self.__sections_list: - if sectname == section: - for optname, value in options: - if not option or optname == option: - if not raw: - value = self.__interpolate(value, d) - yield (optname, value) - - def __interpolate(self, value, vars): - rawval = value - depth = 0 - while depth < 10: - depth = depth + 1 - if value.find("%(") >= 0: - try: - value = value % vars - except KeyError, key: - raise InterpolationError(key, option, section, rawval) - else: - break - if value.find("%(") >= 0: - raise InterpolationDepthError(option, section, rawval) - return value - - def __get(self, section, conv, option): - return conv(self.get(section, option)) - - def getint(self, section, option): - return self.__get(section, string.atoi, option) - - def getfloat(self, section, option): - return self.__get(section, string.atof, option) - - def getboolean(self, section, option): - states = {'1': 1, 'yes': 1, 'true': 1, 'on': 1, - '0': 0, 'no': 0, 'false': 0, 'off': 0} - v = self.get(section, option) - if not states.has_key(v.lower()): - raise ValueError, 'Not a boolean: %s' % v - return states[v.lower()] - - def optionxform(self, optionstr): - #return optionstr.lower() - return optionstr - - def has_option(self, section, option): - """Check for the existence of a given option in a given section.""" - if not section or section == "DEFAULT": - return self.__defaults.has_key(option) - elif not self.has_section(section): - return 0 - else: - option = self.optionxform(option) - return self.__sections_dict[section].has_key(option) - - SECTCRE = re.compile(r'\[(?P<header>[^]]+)\]') - OPTCRE = re.compile(r'(?P<option>\S+)\s*(?P<vi>[:=])\s*(?P<value>.*)$') - - def __read(self, fp, fpname): - cursectdict = None # None, or a dictionary - optname = None - lineno = 0 - e = None # None, or an exception - while 1: - line = fp.readline() - if not line: - break - lineno = lineno + 1 - # comment or blank line? - if line.strip() == '' or line[0] in '#;': - continue - if line.split()[0].lower() == 'rem' \ - and line[0] in "rR": # no leading whitespace - continue - # continuation line? - if line[0] in ' \t' and cursectdict is not None and optname: - value = line.strip() - if value: - k = self.optionxform(optname) - cursectdict[k] = "%s\n%s" % (cursectdict[k], value) - cursectlist[-1][1] = "%s\n%s" % (cursectlist[-1][1], value) - # a section header or option header? - else: - # is it a section header? - mo = self.SECTCRE.match(line) - if mo: - sectname = mo.group('header') - if self.__sections_dict.has_key(sectname): - cursectdict = self.__sections_dict[sectname] - cursectlist = [] - self.__sections_list.append((sectname, cursectlist)) - elif sectname == DEFAULTSECT: - cursectdict = self.__defaults - cursectlist = None - else: - cursectdict = {} - self.__sections_dict[sectname] = cursectdict - cursectlist = [] - self.__sections_list.append((sectname, cursectlist)) - # So sections can't start with a continuation line - optname = None - # no section header in the file? - elif cursectdict is None: - raise MissingSectionHeaderError(fpname, lineno, `line`) - # an option line? - else: - mo = self.OPTCRE.match(line) - if mo: - optname, vi, optval = mo.group('option', 'vi', 'value') - if vi in ('=', ':') and ';' in optval: - # ';' is a comment delimiter only if it follows - # a spacing character - pos = optval.find(';') - if pos and optval[pos-1] in string.whitespace: - optval = optval[:pos] - optval = optval.strip() - # allow empty values - if optval == '""': - optval = '' - xform = self.optionxform(optname) - cursectdict[xform] = optval - if cursectlist is not None: - cursectlist.append([xform, optval]) - else: - # a non-fatal parsing error occurred. set up the - # exception but keep going. the exception will be - # raised at the end of the file and will contain a - # list of all bogus lines - if not e: - e = ParsingError(fpname) - e.append(lineno, `line`) - # if any parsing errors occurred, raise an exception - if e: - raise e - -# Here we wrap this hacked ConfigParser into something more useful -# for us. - -import os - -class Config: - def __init__(self): - self._config = ConfigParser() - self._wrapped = {} - conffiles = [] - repsys_conf = os.environ.get("REPSYS_CONF") - if repsys_conf: - conffiles.append(repsys_conf) - else: - conffiles.append("/etc/repsys.conf") - conffiles.append(os.path.expanduser("~/.repsys/config")) - for file in conffiles: - if os.path.isfile(file): - self._config.read(file) - - def wrap(self, section, handler, option=None): - """Set one wrapper for a given section - - The wrapper must be a function - f(section, option=None, default=None, walk=False). - """ - self._wrapped[section] = handler - - def sections(self): - try: - return self._config.sections() - except Error: - return [] - - def options(self, section): - try: - return self._config.options(section) - except Error: - return [] - - def set(self, section, option, value): - return self._config.set(section, option, value) - - def walk(self, section, option=None, raw=0, vars=None): - handler = self._wrapped.get(section) - if handler: - return handler(section, option, walk=True) - return self._config.walk(section, option, raw, vars) - - def get(self, section, option, default=None, raw=False, wrap=True): - if wrap: - handler = self._wrapped.get(section) - if handler: - handler = self._wrapped.get(section) - return handler(section, option, default) - try: - return self._config.get(section, option, raw=raw) - except Error: - return default - - def getint(self, section, option, default=None): - ret = self.get(section, option, default) - if type(ret) == type(""): - return int(ret) - - def getbool(self, section, option, default=None): - ret = self.get(section, option, default) - states = {'1': 1, 'yes': 1, 'true': 1, 'on': 1, - '0': 0, 'no': 0, 'false': 0, 'off': 0} - if type(ret) == type("") and states.has_key(ret.lower()): - return states[ret.lower()] - return default - -def test(): - config = Config() - def handler(section, option=None, default=None, walk=False): - d = {"fulano": "ciclano", - "foolano": "ceeclano"} - if walk: - return d.items() - elif option in d: - return d[option] - else: - return config.get(section, option, default, wrap=False) - config.wrap("users", handler=handler) - print config.get("users", "fulano") # found in wrapper - print config.get("users", "andreas") # found in repsys.conf - print config.walk("users") - -if __name__ == "__main__": - test() -# vim:ts=4:sw=4:et diff --git a/RepSys/__init__.py b/RepSys/__init__.py deleted file mode 100644 index b0df184..0000000 --- a/RepSys/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/python -import re -import os -import tempfile - -import ConfigParser - -config = ConfigParser.Config() -tempfile.tempdir = config.get("global", "tempdir", None) or None # when "" -del ConfigParser - -def disable_mirror(*a, **kw): - config.set("global", "use-mirror", "no") - -class Error(Exception): pass - -class SilentError(Error): pass - -# vim:et:ts=4:sw=4 diff --git a/RepSys/binrepo.py b/RepSys/binrepo.py deleted file mode 100644 index 4035128..0000000 --- a/RepSys/binrepo.py +++ /dev/null @@ -1,395 +0,0 @@ -from RepSys import Error, config, mirror, layout -from RepSys.util import execcmd, rellink -from RepSys.svn import SVN - -import sys -import os -import string -import stat -import shutil -import re -import tempfile -import hashlib -import urlparse -import threading -from cStringIO import StringIO - -DEFAULT_TARBALLS_REPO = "/tarballs" -BINARIES_DIR_NAME = "SOURCES" -BINARIES_CHECKOUT_NAME = "SOURCES-bin" - -PROP_USES_BINREPO = "mdv:uses-binrepo" -PROP_BINREPO_REV = "mdv:binrepo-rev" - -BINREPOS_SECTION = "binrepos" - -SOURCES_FILE = "sha1.lst" - -class ChecksumError(Error): - pass - -def svn_baseurl(target): - svn = SVN() - info = svn.info2(target) - if info is None: - # unversioned resource - newtarget = os.path.dirname(target) - info = svn.info2(newtarget) - assert info is not None, "svn_basedir should not be used with a "\ - "non-versioned directory" - root = info["Repository Root"] - url = info["URL"] - kind = info["Node Kind"] - path = url[len(root):] - if kind == "directory": - return url - basepath = os.path.dirname(path) - baseurl = mirror.normalize_path(url + "/" + basepath) - return baseurl - -def svn_root(target): - svn = SVN() - info = svn.info2(target) - if info is None: - newtarget = os.path.dirname(target) - info = svn.info2(newtarget) - assert info is not None - return info["Repository Root"] - -def enabled(url): - #TODO use information from url to find out whether we have a binrepo - # available for this url - use = config.getbool("global", "use-binaries-repository", False) - return use - -def default_repo(): - base = config.get("global", "binaries-repository", None) - if base is None: - default_parent = config.get("global", "default_parent", None) - if default_parent is None: - raise Error, "no binaries-repository nor default_parent "\ - "configured" - comps = urlparse.urlparse(default_parent) - base = comps[1] + ":" + DEFAULT_TARBALLS_REPO - return base - -def translate_url(url): - url = mirror.normalize_path(url) - main = mirror.normalize_path(layout.repository_url()) - subpath = url[len(main)+1:] - # [binrepos] - # updates/2009.0 = svn+ssh://svn.mandriva.com/svn/binrepo/20090/ - ## svn+ssh://svn.mandriva.com/svn/packages/2009.0/trafshow/current - ## would translate to - ## svn+ssh://svn.mandriva.com/svn/binrepo/20090/updates/trafshow/current/ - binbase = None - if BINREPOS_SECTION in config.sections(): - for option, value in config.walk(BINREPOS_SECTION): - if subpath.startswith(option): - binbase = value - break - binurl = mirror._joinurl(binbase or default_repo(), subpath) - return binurl - -def translate_topdir(path): - """Returns the URL in the binrepo from a given path inside a SVN - checkout directory. - - @path: if specified, returns a URL in the binrepo whose path is the - same as the path inside the main repository. - """ - baseurl = svn_baseurl(path) - binurl = translate_url(baseurl) - target = mirror.normalize_path(binurl) - return target - -def is_binary(path): - raw = config.get("binrepo", "upload-match", - "\.(7z|Z|bin|bz2|cpio|db|deb|egg|gem|gz|jar|jisp|lzma|"\ - "pdf|pgn\\.gz|pk3|png|rpm|run|sdz|smzip|tar|tbz|"\ - "tbz2|tgz|ttf|uqm|wad|war|xar|xpi|xz|zip|wav|mp3|ogg|"\ - "jpg|png|gif|avi|mpg|mpeg|rar)$") - maxsize = config.getint("binrepo", "upload-match-size", "1048576") # 1MiB - expr = re.compile(raw) - name = os.path.basename(path) - if expr.search(name): - return True - st = os.stat(path) - if st[stat.ST_SIZE] >= maxsize: - return True - return False - -def find_binaries(paths): - new = [] - for path in paths: - if os.path.isdir(path): - for name in os.listdir(path): - fpath = os.path.join(path, name) - if is_binary(fpath): - new.append(fpath) - else: - if is_binary(path): - new.append(path) - return new - -def make_symlinks(source, dest): - todo = [] - tomove = [] - for name in os.listdir(source): - path = os.path.join(source, name) - if not os.path.isdir(path) and not name.startswith("."): - destpath = os.path.join(dest, name) - linkpath = rellink(path, destpath) - if os.path.exists(destpath): - if (os.path.islink(destpath) and - os.readlink(destpath) == linkpath): - continue - movepath = destpath + ".repsys-moved" - if os.path.exists(movepath): - raise Error, "cannot create symlink, %s already "\ - "exists (%s too)" % (destpath, movepath) - tomove.append((destpath, movepath)) - todo.append((destpath, linkpath)) - for destpath, movepath in tomove: - os.rename(destpath, movepath) - for destpath, linkpath in todo: - os.symlink(linkpath, destpath) - -def download(targetdir, pkgdirurl=None, export=False, show=True, - revision=None, symlinks=True, check=False): - assert not export or (export and pkgdirurl) - svn = SVN() - sourcespath = os.path.join(targetdir, "SOURCES") - binpath = os.path.join(targetdir, BINARIES_CHECKOUT_NAME) - if pkgdirurl: - topurl = translate_url(pkgdirurl) - else: - topurl = translate_topdir(targetdir) - binrev = None - if revision: - if pkgdirurl: - binrev = mapped_revision(pkgdirurl, revision) - else: - binrev = mapped_revision(targetdir, revision, wc=True) - binurl = mirror._joinurl(topurl, BINARIES_DIR_NAME) - if export: - svn.export(binurl, binpath, rev=binrev, show=show) - else: - svn.checkout(binurl, binpath, rev=binrev, show=show) - if symlinks: - make_symlinks(binpath, sourcespath) - if check: - check_sources(targetdir) - -def import_binaries(topdir, pkgname): - """Import all binaries from a given package checkout - - (with pending svn adds) - - @topdir: the path to the svn checkout - """ - svn = SVN() - topurl = translate_topdir(topdir) - sourcesdir = os.path.join(topdir, "SOURCES") - bintopdir = tempfile.mktemp("repsys") - try: - svn.checkout(topurl, bintopdir) - checkout = True - except Error: - bintopdir = tempfile.mkdtemp("repsys") - checkout = False - try: - bindir = os.path.join(bintopdir, BINARIES_DIR_NAME) - if not os.path.exists(bindir): - if checkout: - svn.mkdir(bindir) - else: - os.mkdir(bindir) - binaries = find_binaries([sourcesdir]) - update = update_sources_threaded(topdir, added=binaries) - for path in binaries: - name = os.path.basename(path) - binpath = os.path.join(bindir, name) - os.rename(path, binpath) - try: - svn.remove(path) - except Error: - # file not tracked - svn.revert(path) - if checkout: - svn.add(binpath) - log = "imported binaries for %s" % pkgname - if checkout: - rev = svn.commit(bindir, log=log) - else: - rev = svn.import_(bintopdir, topurl, log=log) - svn.propset(PROP_USES_BINREPO, "yes", topdir) - svn.propset(PROP_BINREPO_REV, str(rev), topdir) - update.join() - svn.add(sources_path(topdir)) - finally: - shutil.rmtree(bintopdir) - -def create_package_dirs(bintopdir): - svn = SVN() - binurl = mirror._joinurl(bintopdir, BINARIES_DIR_NAME) - silent = config.get("log", "ignore-string", "SILENT") - message = "%s: created binrepo package structure" % silent - svn.mkdir(binurl, log=message, parents=True) - -def parse_sources(path): - entries = {} - f = open(path) - for rawline in f: - line = rawline.strip() - try: - sum, name = line.split(None, 1) - except ValueError: - # failed to unpack, line format error - raise Error, "invalid line in sources file: %s" % rawline - entries[name] = sum - return entries - -def check_hash(path, sum): - newsum = file_hash(path) - if newsum != sum: - raise ChecksumError, "different checksums for %s: expected %s, "\ - "but %s was found" % (path, sum, newsum) - -def check_sources(topdir): - spath = sources_path(topdir) - if not os.path.exists(spath): - raise Error, "'%s' was not found" % spath - entries = parse_sources(spath) - for name, sum in entries.iteritems(): - fpath = os.path.join(topdir, "SOURCES", name) - check_hash(fpath, sum) - -def file_hash(path): - sum = hashlib.sha1() - f = open(path) - while True: - block = f.read(4096) - if not block: - break - sum.update(block) - f.close() - return sum.hexdigest() - -def sources_path(topdir): - path = os.path.join(topdir, "SOURCES", SOURCES_FILE) - return path - -def update_sources(topdir, added=[], removed=[]): - path = sources_path(topdir) - entries = {} - if os.path.isfile(path): - entries = parse_sources(path) - f = open(path, "w") # open before calculating hashes - for name in removed: - entries.pop(removed) - for added_path in added: - name = os.path.basename(added_path) - entries[name] = file_hash(added_path) - for name in sorted(entries): - f.write("%s %s\n" % (entries[name], name)) - f.close() - -def update_sources_threaded(*args, **kwargs): - t = threading.Thread(target=update_sources, args=args, kwargs=kwargs) - t.start() - t.join() - return t - -def upload(path, message=None): - from RepSys.rpmutil import getpkgtopdir - svn = SVN() - if not os.path.exists(path): - raise Error, "not found: %s" % path - # XXX check if the path is under SOURCES/ - paths = find_binaries([path]) - if not paths: - raise Error, "'%s' does not seem to have any tarballs" % path - topdir = getpkgtopdir() - bintopdir = translate_topdir(topdir) - binurl = mirror._joinurl(bintopdir, BINARIES_DIR_NAME) - sourcesdir = os.path.join(topdir, "SOURCES") - bindir = os.path.join(topdir, BINARIES_CHECKOUT_NAME) - silent = config.get("log", "ignore-string", "SILENT") - if not os.path.exists(bindir): - try: - download(topdir, show=False) - except Error: - # possibly the package does not exist - # (TODO check whether it is really a 'path not found' error) - pass - if not os.path.exists(bindir): - create_package_dirs(bintopdir) - svn.propset(PROP_USES_BINREPO, "yes", topdir) - svn.commit(topdir, log="%s: created binrepo structure" % silent) - download(topdir, show=False) - for path in paths: - if svn.info2(path): - sys.stderr.write("'%s' is already tracked by svn, ignoring\n" % - path) - continue - name = os.path.basename(path) - binpath = os.path.join(bindir, name) - os.rename(path, binpath) - svn.add(binpath) - if not message: - message = "%s: new binary files %s" % (silent, " ".join(paths)) - make_symlinks(bindir, sourcesdir) - update = update_sources_threaded(topdir, added=paths) - rev = svn.commit(binpath, log=message) - svn.propset(PROP_BINREPO_REV, str(rev), topdir) - sources = sources_path(topdir) - svn.add(sources) - update.join() - svn.commit(topdir + " " + sources, log=message, nonrecursive=True) - -def mapped_revision(target, revision, wc=False): - """Maps a txtrepo revision to a binrepo datespec - - This datespec can is intended to be used by svn .. -r DATE. - - @target: a working copy path or a URL - @revision: if target is a URL, the revision number used when fetching - svn info - @wc: if True indicates that 'target' must be interpreted as a - the path of a svn working copy, otherwise it is handled as a URL - """ - svn = SVN() - binrev = None - if wc: - spath = sources_path(target) - if os.path.exists(spath): - infolines = svn.info(spath, xml=True) - if infolines: - rawinfo = "".join(infolines) # arg! - found = re.search("<date>(.*?)</date>", rawinfo).groups() - date = found[0] - else: - raise Error, "bogus 'svn info' for '%s'" % spath - else: - raise Error, "'%s' was not found" % spath - else: - url = mirror._joinurl(target, sources_path("")) - date = svn.propget("svn:date", url, rev=revision, revprop=True) - if not date: - raise Error, "no valid date available for '%s'" % url - binrev = "{%s}" % date - return binrev - -def markrelease(sourceurl, releasesurl, version, release, revision): - svn = SVN() - binrev = mapped_revision(sourceurl, revision) - binsource = translate_url(sourceurl) - binreleases = translate_url(releasesurl) - versiondir = mirror._joinurl(binreleases, version) - dest = mirror._joinurl(versiondir, release) - svn.mkdir(binreleases, noerror=1, log="created directory for releases") - svn.mkdir(versiondir, noerror=1, log="created directory for version %s" % version) - svn.copy(binsource, dest, rev=binrev, - log="%%markrelease ver=%s rel=%s rev=%s binrev=%s" % (version, release, - revision, binrev)) diff --git a/RepSys/cgi/__init__.py b/RepSys/cgi/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/RepSys/cgi/__init__.py +++ /dev/null diff --git a/RepSys/cgi/soapserver.py b/RepSys/cgi/soapserver.py deleted file mode 100644 index 2f6b751..0000000 --- a/RepSys/cgi/soapserver.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/python -from RepSys import Error, config -from RepSys.rpmutil import get_srpm -from RepSys.cgiutil import CgiError, get_targets -import sys -import os - -try: - import NINZ.dispatch -except ImportError: - NINZ = None - -class SoapIface: - def author_email(self, author): - return config.get("users", author) - - def submit_package(self, packageurl, packagerev, targetname): - username = os.environ.get("REMOTE_USER") - packager = config.get("users", username) - if not packager: - raise CgiError, "your email was not found" - elif not packagerev: - raise CgiError, "no revision provided" - elif not targetname: - raise CgiError, "no target provided" - else: - targetname = targetname.lower() - for target in get_targets(): - if target.name.lower() == targetname: - break - else: - raise CgiError, "target not found" - try: - tmp = int(packagerev) - except ValueError: - raise CgiError, "invalid revision provided" - for allowed in target.allowed: - if packageurl.startswith(allowed): - break - else: - raise CgiError, "%s is not allowed for this target" \ - % packageurl - get_srpm(packageurl, - revision=packagerev, - targetdirs=target.target, - packager=packager, - revname=1, - svnlog=1, - scripts=target.scripts) - return 1 - - def submit_targets(self): - return [x.name for x in get_targets()] - -TEMPLATE = """\ -Content-type: text/html - -<html> -<head> -<title>Repository system SOAP server</title> -</head> -<body bgcolor="white"> -<br> -<hr> -<center> -<b>%(message)s</b> -</center> -<hr> -</body> -</html> -""" - -def show(msg="", error=0): - if error: - msg = '<font color="red">%s</font>' % msg - print TEMPLATE % {"message":msg} - -def main(): - if not os.environ.has_key('REQUEST_METHOD'): - sys.stderr.write("error: this program is meant to be used as a cgi\n") - sys.exit(1) - if not NINZ: - show("NINZ is not properly installed in this system", error=1) - sys.exit(1) - username = os.environ.get("REMOTE_USER") - method = os.environ.get("REQUEST_METHOD") - if not username or method != "POST": - show("This is a SOAP interface!", error=1) - sys.exit(1) - - NINZ.dispatch.AsCGI(modules=(SoapIface(),)) - -# vim:et:ts=4:sw=4 diff --git a/RepSys/cgi/submit.py b/RepSys/cgi/submit.py deleted file mode 100644 index 10f7cb2..0000000 --- a/RepSys/cgi/submit.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/python -from RepSys import Error, config -from RepSys.rpmutil import get_srpm -from RepSys.cgiutil import CgiError, get_targets -import cgi -import sys -import os - -TEMPLATE = """\ -<html> -<head> -<title>Repository package submission system</title> -</head> -<body bgcolor="white"> -<table cellspacing=0 cellpadding=0 border=0 width="100%%"> - <tr bgcolor="#020264"><td align="left" valign="middle"><img src="http://qa.mandriva.com/mandriva.png" hspace=0 border=0 alt=""></td></tr> -</table> -<br> -<hr> -<center> -<b>%(message)s</b> -<br><br> -<form method="POST" action=""> -<table><tr><td valign="top"> - Package URL:<br> - <input name="packageurl" size="60" value="svn+ssh://cvs.mandriva.com/svn/mdv/cooker/"><br> - <small>Ex. svn+ssh://cvs.mandriva.com/svn/mdv/cooker/pkgname</small><br> - </td><td valign="top"> - Revision:<br> - <input name="packagerev" size="10" value=""><br> - </td></tr></table> - <br> - Package target:<br> - <select name="target" size=5> - %(targetoptions)s - </select><br> - <br> - <input type="submit" value="Submit package"> -</form> -</center> -<hr/> -</body> -</html> -""" - -def get_targetoptions(): - s = "" - selected = " selected" - for target in get_targets(): - s += '<option value="%s"%s>%s</option>' \ - % (target.name, selected, target.name) - selected = "" - return s - -def show(msg="", error=0): - if error: - msg = '<font color="red">%s</font>' % msg - print TEMPLATE % {"message":msg, "targetoptions":get_targetoptions()} - -def submit_packages(packager): - form = cgi.FieldStorage() - packageurl = form.getfirst("packageurl", "").strip() - packagerev = form.getfirst("packagerev", "").strip() - if not packageurl: - show() - elif not packagerev: - raise CgiError, "No revision provided!" - else: - targetname = form.getfirst("target") - if not targetname: - raise CgiError, "No target selected!" - for target in get_targets(): - if target.name == targetname: - break - else: - raise CgiError, "Target not found!" - try: - tmp = int(packagerev) - except ValueError: - raise CgiError, "Invalid revision provided!" - for allowed in target.allowed: - if packageurl.startswith(allowed): - break - else: - raise CgiError, "%s is not allowed for this target!" % packageurl - get_srpm(packageurl, - revision=packagerev, - targetdirs=target.target, - packager=packager, - revname=1, - svnlog=1, - scripts=target.scripts) - show("Package submitted!") - -def main(): - if not os.environ.has_key('REQUEST_METHOD'): - sys.stderr.write("error: this program is meant to be used as a cgi\n") - sys.exit(1) - print "Content-type: text/html\n\n" - try: - username = os.environ.get("REMOTE_USER") - method = os.environ.get("REQUEST_METHOD") - if not username or method != "POST": - show() - else: - useremail = config.get("users", username) - if not useremail: - raise CgiError, \ - "Your email was not found. Contact the administrator!" - submit_packages(useremail) - except CgiError, e: - show(str(e), error=1) - except Error, e: - error = str(e) - show(error[0].upper()+error[1:], error=1) - except: - cgi.print_exception() - -# vim:et:ts=4:sw=4 diff --git a/RepSys/cgi/xmlrpcserver.py b/RepSys/cgi/xmlrpcserver.py deleted file mode 100644 index e0851d1..0000000 --- a/RepSys/cgi/xmlrpcserver.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/python -from RepSys import Error, config -from RepSys.rpmutil import get_srpm -from RepSys.cgiutil import CgiError, get_targets -import sys -import os - -import xmlrpclib, cgi - -class XmlRpcIface: - def author_email(self, author): - return config.get("users", author) - - def submit_package(self, packageurl, packagerev, targetname): - username = os.environ.get("REMOTE_USER") - packager = config.get("users", username) - if not packager: - raise CgiError, "your email was not found" - elif not packagerev: - raise CgiError, "no revision provided" - elif not targetname: - raise CgiError, "no target provided" - else: - targetname = targetname.lower() - for target in get_targets(): - if target.name.lower() == targetname: - break - else: - raise CgiError, "target not found" - try: - tmp = int(packagerev) - except ValueError: - raise CgiError, "invalid revision provided" - for allowed in target.allowed: - if packageurl.startswith(allowed): - break - else: - raise CgiError, "%s is not allowed for this target" \ - % packageurl - get_srpm(packageurl, - revision=packagerev, - targetdirs=target.target, - packager=packager, - revname=1, - svnlog=1, - scripts=target.scripts) - return 1 - - def submit_targets(self): - return [x.name for x in get_targets()] - -TEMPLATE = """\ -Content-type: text/html - -<html> -<head> -<title>Repository system SOAP server</title> -</head> -<body bgcolor="white"> -<br> -<hr> -<center> -<b>%(message)s</b> -</center> -<hr> -</body> -</html> -""" - -def show(msg="", error=0): - if error: - msg = '<font color="red">%s</font>' % msg - print TEMPLATE % {"message":msg} - -def main(): - if not os.environ.has_key('REQUEST_METHOD'): - sys.stderr.write("error: this program is meant to be used as a cgi\n") - sys.exit(1) - username = os.environ.get("REMOTE_USER") - method = os.environ.get("REQUEST_METHOD") - if not username or method != "POST": - show("This is a XMLRPC interface!", error=1) - sys.exit(1) - - iface = XmlRpcIface() - - response = "" - try: - form = cgi.FieldStorage() - parms, method = xmlrpclib.loads(form.value) - meth = getattr(iface, method) - response = (meth(*parms),) - except CgiError, e: - msg = str(e) - try: - msg = msg.decode("iso-8859-1") - except UnicodeError: - pass - response = xmlrpclib.Fault(1, msg) - except Exception, e: - msg = str(e) - try: - msg = msg.decode("iso-8859-1") - except UnicodeError: - pass - response = xmlrpclib.Fault(1, msg) - - sys.stdout.write("Content-type: text/xml\n\n") - sys.stdout.write(xmlrpclib.dumps(response, methodresponse=1)) - -# vim:et:ts=4:sw=4 diff --git a/RepSys/cgiutil.py b/RepSys/cgiutil.py deleted file mode 100644 index 35c5efb..0000000 --- a/RepSys/cgiutil.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/python -from RepSys import Error, config -from RepSys.svn import SVN -from RepSys.ConfigParser import NoSectionError -import time -import re - -class CgiError(Error): pass - -class SubmitTarget: - def __init__(self): - self.name = "" - self.target = "" - self.macros = [] - self.allowed = [] - self.scripts = [] - -TARGETS = [] - -def parse_macrosref(refs, config): - macros = [] - for name in refs: - secname = "macros %s" % name - try: - macros.extend(config.walk(secname, raw=True)) - except NoSectionError: - raise Error, "missing macros section " \ - "%r in configuration" % secname - return macros - -def get_targets(): - global TARGETS - if not TARGETS: - target = SubmitTarget() - targetoptions = {} - submit_re = re.compile("^submit\s+(.+)$") - for section in config.sections(): - m = submit_re.match(section) - if m: - target = SubmitTarget() - target.name = m.group(1) - for option, value in config.walk(section): - if option in ("target", "allowed", "scripts"): - setattr(target, option, value.split()) - elif option == "rpm-macros": - refs = value.split() - target.macros = parse_macrosref(refs, config) - else: - raise Error, "unknown [%s] option %s" % (section, option) - TARGETS.append(target) - return TARGETS - -# vim:et:ts=4:sw=4 diff --git a/RepSys/command.py b/RepSys/command.py deleted file mode 100644 index 63f2df9..0000000 --- a/RepSys/command.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/python -from RepSys import SilentError, Error, config -import sys, os -import urlparse -import optparse - -__all__ = ["OptionParser", "do_command", "default_parent"] - -class CapitalizeHelpFormatter(optparse.IndentedHelpFormatter): - - def format_usage(self, usage): - return optparse.IndentedHelpFormatter \ - .format_usage(self, usage).capitalize() - - def format_heading(self, heading): - return optparse.IndentedHelpFormatter \ - .format_heading(self, heading).capitalize() - -class OptionParser(optparse.OptionParser): - - def __init__(self, usage=None, help=None, **kwargs): - if not "formatter" in kwargs: - kwargs["formatter"] = CapitalizeHelpFormatter() - optparse.OptionParser.__init__(self, usage, **kwargs) - self._overload_help = help - - def format_help(self, formatter=None): - if self._overload_help: - return self._overload_help - else: - return optparse.OptionParser.format_help(self, formatter) - - def error(self, msg): - raise Error, msg - -def do_command(parse_options_func, main_func): - try: - opt = parse_options_func() - main_func(**opt.__dict__) - except SilentError: - sys.exit(1) - except Error, e: - sys.stderr.write("error: %s\n" % str(e)) - sys.exit(1) - except KeyboardInterrupt: - sys.stderr.write("interrupted\n") - sys.stderr.flush() - sys.exit(1) - -def default_parent(url): - if url.find("://") == -1: - default_parent = config.get("global", "default_parent") - if not default_parent: - raise Error, "received a relative url, " \ - "but default_parent was not setup" - parsed = list(urlparse.urlparse(default_parent)) - parsed[2] = os.path.normpath(parsed[2] + "/" + url) - url = urlparse.urlunparse(parsed) - return url - -# vim:et:ts=4:sw=4 diff --git a/RepSys/commands/__init__.py b/RepSys/commands/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/RepSys/commands/__init__.py +++ /dev/null diff --git a/RepSys/commands/authoremail.py b/RepSys/commands/authoremail.py deleted file mode 100644 index f5b8b70..0000000 --- a/RepSys/commands/authoremail.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/python -from RepSys import Error, config -from RepSys.command import * -import sys -import getopt - -HELP = """\ -Usage: repsys authoremail [OPTIONS] AUTHOR - -Shows the e-mail of an SVN author. It is just a simple interface to access -the [authors] section of repsys.conf. - -Options: - -h Show this message - -Examples: - repsys authoremail john -""" - -def parse_options(): - parser = OptionParser(help=HELP) - opts, args = parser.parse_args() - if len(args) != 1: - raise Error, "invalid arguments" - opts.author = args[0] - return opts - -def print_author_email(author): - email = config.get("users", author) - if not email: - raise Error, "author not found" - print email - -def main(): - do_command(parse_options, print_author_email) - -# vim:et:ts=4:sw=4 diff --git a/RepSys/commands/changed.py b/RepSys/commands/changed.py deleted file mode 100644 index 66c1a53..0000000 --- a/RepSys/commands/changed.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/python -from RepSys import Error, disable_mirror -from RepSys.command import * -from RepSys.layout import package_url -from RepSys.rpmutil import check_changed -import getopt -import sys - -HELP = """\ -Usage: repsys changed [OPTIONS] URL - -Shows if there are pending changes since the last package release. - -Options: - -a Check all packages in given URL - -s Show differences - -M Do not use the mirror (use the main repository) - -h Show this message - -Examples: - repsys changed http://repos/svn/cnc/snapshot/foo - repsys changed -a http://repos/svn/cnc/snapshot -""" - -def parse_options(): - parser = OptionParser(help=HELP) - parser.add_option("-a", dest="all", action="store_true") - parser.add_option("-s", dest="show", action="store_true") - parser.add_option("-M", "--no-mirror", action="callback", - callback=disable_mirror) - opts, args = parser.parse_args() - if len(args) != 1: - raise Error, "invalid arguments" - opts.pkgdirurl = package_url(args[0]) - opts.verbose = 1 # Unconfigurable - return opts - -def main(): - do_command(parse_options, check_changed) - -# vim:et:ts=4:sw=4 diff --git a/RepSys/commands/ci.py b/RepSys/commands/ci.py deleted file mode 100644 index 8d373b5..0000000 --- a/RepSys/commands/ci.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/python -from RepSys.command import * -from RepSys.rpmutil import commit - -HELP = """\ -Usage: repsys ci [TARGET] - -Will commit recent modifications in the package. - -The difference between an ordinary "svn ci" and "repsys ci" is that it -relocates the working copy to the default repository in case the option -"mirror" is set in repsys.conf. - -Options: - -h Show this message - -m MSG Use the MSG as the log message - -F FILE Read log message from FILE - -Examples: - repsys ci - repsys ci SPECS/package.spec SPECS/package-patch.patch -""" - -def parse_options(): - parser = OptionParser(help=HELP) - parser.add_option("-m", dest="message", default=None) - parser.add_option("-F", dest="logfile", type="string", - default=None) - opts, args = parser.parse_args() - if len(args): - opts.target = args[0] - return opts - -def main(): - do_command(parse_options, commit) diff --git a/RepSys/commands/co.py b/RepSys/commands/co.py deleted file mode 100644 index 81e4140..0000000 --- a/RepSys/commands/co.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/python -from RepSys import Error, disable_mirror -from RepSys.command import * -from RepSys.rpmutil import checkout -import getopt -import sys - -HELP = """\ -Usage: repsys co [OPTIONS] URL [LOCALPATH] - -Checkout the package source from the Mandriva repository. - -If the 'mirror' option is enabled, the package is obtained from the mirror -repository. - -You can specify the distro branch to checkout from by using distro/pkgname. - -Options: - -d The distribution branch to checkout from - -b The package branch - -r REV Revision to checkout - -S Do not download sources from the binaries repository - -L Do not make symlinks of the binaries downloaded in SOURCES/ - -s Only checkout the SPECS/ directory - -M Do not use the mirror (use the main repository) - --check Check integrity of files fetched from the binary repository - -h Show this message - -Examples: - repsys co pkgname - repsys co -d 2009.0 pkgname - repsys co 2009.0/pkgame - repsys co http://repos/svn/cnc/snapshot/foo - repsys co http://repos/svn/cnc/snapshot/foo foo-pkg -""" - -def parse_options(): - parser = OptionParser(help=HELP) - parser.add_option("-r", dest="revision") - parser.add_option("-S", dest="use_binrepo", default=True, - action="store_false") - parser.add_option("--check", dest="binrepo_check", default=False, - action="store_true") - parser.add_option("-L", dest="binrepo_link", default=True, - action="store_false") - parser.add_option("--distribution", "-d", dest="distro", default=None) - parser.add_option("--branch", "-b", dest="branch", default=None) - parser.add_option("-s", "--spec", dest="spec", default=False, - action="store_true") - parser.add_option("-M", "--no-mirror", action="callback", - callback=disable_mirror) - opts, args = parser.parse_args() - if len(args) not in (1, 2): - raise Error, "invalid arguments" - # here we don't use package_url in order to notify the user we are - # using the mirror - opts.pkgdirurl = args[0] - if len(args) == 2: - opts.path = args[1] - else: - opts.path = None - return opts - -def main(): - do_command(parse_options, checkout) - -# vim:et:ts=4:sw=4 diff --git a/RepSys/commands/create.py b/RepSys/commands/create.py deleted file mode 100644 index ded8abe..0000000 --- a/RepSys/commands/create.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/python -from RepSys import Error -from RepSys.command import * -from RepSys.layout import package_url -from RepSys.rpmutil import create_package -import getopt -import sys - -HELP = """\ -Usage: repsys create [OPTIONS] URL - -Creates the minimal structure of a package in the repository. - -Options: - -h Show this message - -Examples: - repsys create newpkg - repsys create svn+ssh://svn.mandriva.com/svn/packages/cooker/newpkg -""" - -def parse_options(): - parser = OptionParser(help=HELP) - opts, args = parser.parse_args() - if len(args) != 1: - raise Error, "invalid arguments" - opts.pkgdirurl = package_url(args[0], mirrored=False) - opts.verbose = 1 # Unconfigurable - return opts - -def main(): - do_command(parse_options, create_package) - -# vim:et:ts=4:sw=4 diff --git a/RepSys/commands/del.py b/RepSys/commands/del.py deleted file mode 100644 index 2c6902e..0000000 --- a/RepSys/commands/del.py +++ /dev/null @@ -1,30 +0,0 @@ -from RepSys import Error -from RepSys.command import * -from RepSys.rpmutil import binrepo_delete - -HELP = """\ -Usage: repsys del [OPTIONS] [PATH] - -Remove a given file from the binary sources repository. - -Changes in the sources file will be left uncommited. - -Options: - -c automatically commit the 'sources' file - -h help - -""" - -def parse_options(): - parser = OptionParser(help=HELP) - parser.add_option("-c", dest="commit", default=False, - action="store_true") - opts, args = parser.parse_args() - if len(args): - opts.paths = args - else: - raise Error, "you need to provide a path" - return opts - -def main(): - do_command(parse_options, binrepo_delete) diff --git a/RepSys/commands/editlog.py b/RepSys/commands/editlog.py deleted file mode 100644 index 9d1afc5..0000000 --- a/RepSys/commands/editlog.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/python -from RepSys import Error -from RepSys.command import * -from RepSys.layout import package_url -from RepSys.svn import SVN -import re - -HELP = """\ -Usage: repsys editlog [OPTIONS] [URL] REVISION - -Options: - -h Show this message - -Examples: - repsys editlog 14800 - repsys editlog https://repos/svn/cnc/snapshot 14800 -""" - -def parse_options(): - parser = OptionParser(help=HELP) - opts, args = parser.parse_args() - if len(args) == 2: - pkgdirurl, revision = args - elif len(args) == 1: - pkgdirurl, revision = "", args[0] - else: - raise Error, "invalid arguments" - opts.pkgdirurl = package_url(pkgdirurl, mirrored=False) - opts.revision = re.compile(r".*?(\d+).*").sub(r"\1", revision) - return opts - -def editlog(pkgdirurl, revision): - svn = SVN() - svn.propedit("svn:log", pkgdirurl, rev=revision) - -def main(): - do_command(parse_options, editlog) - -# vim:et:ts=4:sw=4 diff --git a/RepSys/commands/getspec.py b/RepSys/commands/getspec.py deleted file mode 100644 index a357ef9..0000000 --- a/RepSys/commands/getspec.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/python -from RepSys import Error, disable_mirror -from RepSys.command import * -from RepSys.layout import package_url -from RepSys.rpmutil import get_spec -import getopt -import sys - -HELP = """\ -Usage: repsys getspec [OPTIONS] REPPKGURL - -Prints the .spec file of a given package. - -Options: - -t DIR Use DIR as target for spec file (default is ".") - -M Do not use the mirror (use the main repository) - -h Show this message - -Examples: - repsys getspec pkgname - repsys getspec svn+ssh://svn.mandriva.com/svn/packages/cooker/pkgname -""" - -def parse_options(): - parser = OptionParser(help=HELP) - parser.add_option("-t", dest="targetdir", default=".") - parser.add_option("-M", "--no-mirror", action="callback", - callback=disable_mirror) - opts, args = parser.parse_args() - if len(args) != 1: - raise Error, "invalid arguments" - opts.pkgdirurl = package_url(args[0]) - return opts - -def main(): - do_command(parse_options, get_spec) - -# vim:et:ts=4:sw=4 diff --git a/RepSys/commands/getsrpm.py b/RepSys/commands/getsrpm.py deleted file mode 100644 index 1767bb7..0000000 --- a/RepSys/commands/getsrpm.py +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/python -# -# This program will extract given version/revision of the named package -# from the Conectiva Linux repository system. -# -from RepSys import Error, config, disable_mirror -from RepSys.command import * -from RepSys.layout import package_url -from RepSys.rpmutil import get_srpm -import tempfile -import shutil -import getopt -import glob -import sys -import os - -HELP = """\ -Usage: repsys getsrpm [OPTIONS] REPPKGURL - -Generates the source RPM (.srpm) file of a given package. - -Options: - -c Use files in current/ directory (default) - -p Use files in pristine/ directory - -v VER Use files from the version specified by VER (e.g. 2.2.1-2cl) - -r REV Use files from current directory, in revision REV (e.g. 1001) - -t DIR Put SRPM file in directory DIR when done (default is ".") - -P USER Define the RPM packager inforamtion to USER - -s FILE Run script with "FILE TOPDIR SPECFILE" command - -n Rename the package to include the revision number - -l Use subversion log to build rpm %changelog - -T FILE Template to be used to generate the %changelog - -M Do not use the mirror (use the main repository) - -h Show this message - -S Do not download sources from the binary repository - --check Check integrity of files fetched from the binary repository - --strict Check if the given revision contains changes in REPPKGURL - -Examples: - repsys getsrpm python - repsys getsrpm -l python - repsys getsrpm http://foo.bar/svn/cnc/snapshot/python - repsys getsrpm -p http://foo.bar/svn/cnc/releases/8cl/python - repsys getsrpm -r 1001 file:///svn/cnc/snapshot/python -""" - -def mode_callback(option, opt, val, parser, mode): - opts = parser.values - opts.mode = mode - if mode == "version": - try: - opts.version, opts.release = val.split("-", 1) - except ValueError: - raise Error, "wrong version, use something like 2.2-1mdk" - elif mode == "revision": - opts.revision = val - -def parse_options(): - parser = OptionParser(help=HELP) - parser.defaults["mode"] = "current" - parser.defaults["version"] = None - parser.defaults["release"] = None - parser.defaults["revision"] = None - parser.defaults["submit"] = False - callback_options = dict(action="callback", callback=mode_callback, - type="string", dest="__ignore") - parser.add_option("-c", callback_kwargs={"mode": "current"}, nargs=0, - **callback_options) - parser.add_option("-p", callback_kwargs={"mode": "pristine"}, nargs=0, - **callback_options) - parser.add_option("-r", callback_kwargs={"mode": "revision"}, nargs=1, - **callback_options) - parser.add_option("-v", callback_kwargs={"mode": "version"}, nargs=1, - **callback_options) - parser.add_option("-t", dest="targetdirs", action="append", default=[]) - parser.add_option("-s", dest="scripts", action="append", default=[]) - parser.add_option("-P", dest="packager", default="") - parser.add_option("-n", dest="revname", action="store_true") - parser.add_option("-l", dest="svnlog", action="store_true") - parser.add_option("-T", dest="template", type="string", default=None) - parser.add_option("-S", dest="use_binrepo", default=True, - action="store_false") - parser.add_option("--check", dest="binrepo_check", default=False, - action="store_true") - parser.add_option("-M", "--no-mirror", action="callback", - callback=disable_mirror) - parser.add_option("--strict", dest="strict", default=False, - action="store_true") - opts, args = parser.parse_args() - del opts.__ignore - if len(args) != 1: - raise Error, "invalid arguments" - opts.pkgdirurl = package_url(args[0]) - opts.verbose = 1 - return opts - -def main(): - do_command(parse_options, get_srpm) - -# vim:et:ts=4:sw=4 diff --git a/RepSys/commands/log.py b/RepSys/commands/log.py deleted file mode 100644 index 28df27d..0000000 --- a/RepSys/commands/log.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/python -from RepSys import config, mirror, disable_mirror -from RepSys.command import * -from RepSys.layout import package_url, checkout_url -from RepSys.rpmutil import sync -from RepSys.util import execcmd -import sys -import os - -HELP = """\ -Usage: repsys log [OPTIONS] [PACKAGE] - -Shows the SVN log for a given package. - -Options: - -h Show this message - -v Show changed paths - -l LIMIT Limit of log entries to show - -r REV Show a specific revision - -M Do not use the mirror (use the main repository) - -Examples: - repsys log mutt - repsys log 2009.1/mutt -""" - -def parse_options(): - parser = OptionParser(help=HELP) - parser.add_option("-v", dest="verbose", action="store_true", - default=False) - parser.add_option("-l", "--limit", dest="limit", type="int", - default=None) - parser.add_option("-r", dest="revision", type="string", default=None) - parser.add_option("-M", "--no-mirror", action="callback", - callback=disable_mirror) - opts, args = parser.parse_args() - if len(args): - opts.pkgdirurl = package_url(args[0]) - else: - parser.error("log requires a package name") - return opts - -def svn_log(pkgdirurl, verbose=False, limit=None, revision=None): - mirror.info(pkgdirurl) - url = checkout_url(pkgdirurl) - svncmd = config.get("global", "svn-command", "svn") - args = [svncmd, "log", url] - if verbose: - args.append("-v") - if limit: - args.append("-l") - args.append(limit) - if revision: - args.append("-r") - args.append(revision) - if os.isatty(sys.stdin.fileno()): - args.append("| less") - rawcmd = " ".join(args) - execcmd(rawcmd, show=True) - -def main(): - do_command(parse_options, svn_log) diff --git a/RepSys/commands/markrelease.py b/RepSys/commands/markrelease.py deleted file mode 100644 index 057cf1d..0000000 --- a/RepSys/commands/markrelease.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/python -# -# This program will append a release to the Conectiva Linux package -# repository system. It's meant to be a startup system to include -# pre-packaged SRPMS in the repository, thus, you should not commit -# packages over an ongoing package structure (with changes in current/ -# directory and etc). Also, notice that packages must be included in -# cronological order. -# -from RepSys import Error -from RepSys.command import * -from RepSys.layout import package_url -from RepSys.simplerpm import SRPM -from RepSys.rpmutil import mark_release -from RepSys.util import get_auth -import getopt -import sys -import os - -HELP = """\ -*** WARNING --- You probably SHOULD NOT use this program! --- WARNING *** - -Usage: repsys markrelease [OPTIONS] REPPKGURL - -This subcommand creates a 'tag' for a given revision of a given package. - -The tag will be stored in the directory releases/ inside the package -structure. - -Options: - -f FILE Try to extract information from given file - -r REV Revision which will be used to make the release copy tag - -v VER Version which will be used to make the release copy tag - -n Append package name to provided URL - -h Show this message - -Examples: - repsys markrelease -r 68 -v 1.0-1 file://svn/cnc/snapshot/foo - repsys markrelease -f @68:foo-1.0-1.src.rpm file://svn/cnc/snapshot/foo - repsys markrelease -r 68 -f foo-1.0.src.rpm file://svn/cnc/snapshot/foo -""" - -def version_callback(option, opt, val, parser): - opts = parser.values - try: - opts.version, opts.release = val.split("-", 1) - except ValueError: - raise Error, "wrong version, use something like 1:2.2-1mdk" - -def parse_options(): - parser = OptionParser(help=HELP) - parser.defaults["version"] = None - parser.defaults["release"] = None - parser.add_option("-v", action="callback", callback=version_callback, - nargs=1, type="string", dest="__ignore") - parser.add_option("-r", dest="revision") - parser.add_option("-f", dest="filename") - parser.add_option("-n", dest="appendname", action="store_true") - opts, args = parser.parse_args() - - if len(args) != 1: - raise Error, "invalid arguments" - - opts.pkgdirurl = package_url(args[0], mirrored=False) - - filename = opts.filename - appendname = opts.appendname - del opts.filename, opts.appendname, opts.__ignore - - if filename: - if not os.path.isfile(filename): - raise Error, "file not found: "+filename - if not opts.revision: - basename = os.path.basename(filename) - end = basename.find(":") - if basename[0] != "@" or end == -1: - raise Error, "couldn't guess revision from filename" - opts.revision = basename[1:end] - srpm = None - if not opts.version: - srpm = SRPM(filename) - if srpm.epoch: - opts.version = "%s:%s" % (srpm.epoch, srpm.version) - else: - opts.version = srpm.version - opts.release = srpm.release - if appendname: - if not srpm: - srpm = SRPM(filename) - opts.pkgdirurl = "/".join([opts.pkgdirurl, srpm.name]) - elif appendname: - raise Error, "option -n requires option -f" - elif not opts.revision: - raise Error, "no revision provided" - elif not opts.version: - raise Error, "no version provided" - #get_auth() - return opts - -def main(): - do_command(parse_options, mark_release) - -# vim:et:ts=4:sw=4 diff --git a/RepSys/commands/patchspec.py b/RepSys/commands/patchspec.py deleted file mode 100644 index 9a4881b..0000000 --- a/RepSys/commands/patchspec.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/python -# -# This program will try to patch a spec file from a given package url. -# -from RepSys import Error -from RepSys.rpmutil import patch_spec -from RepSys.command import * -from RepSys.layout import package_url -import getopt -import sys - -HELP = """\ -Usage: repsys patchspec [OPTIONS] REPPKGURL PATCHFILE - -It will try to patch a spec file from a given package url. - -Options: - -l LOG Use LOG as log message - -h Show this message - -Examples: - repsys patchspec http://repos/svn/cnc/snapshot/foo -""" - -def parse_options(): - parser = OptionParser(help=HELP) - parser.add_option("-l", dest="log", default="") - opts, args = parser.parse_args() - if len(args) != 2: - raise Error, "invalid arguments" - opts.pkgdirurl = package_url(args[0], mirrored=False) - opts.patchfile = args[1] - return opts - -def main(): - do_command(parse_options, patch_spec) - -# vim:et:ts=4:sw=4 diff --git a/RepSys/commands/putsrpm.py b/RepSys/commands/putsrpm.py deleted file mode 100644 index efe1a15..0000000 --- a/RepSys/commands/putsrpm.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/python -from RepSys import Error -from RepSys.command import * -from RepSys.layout import package_url -from RepSys.rpmutil import put_srpm -import getopt -import sys, os - -HELP = """\ -Usage: repsys putsrpm [OPTIONS] SOURCERPMS - -Will import source RPMs into the SVN repository. - -If the package was already imported, it will add the new files and remove -those not present in the source RPM. - -Options: - -m LOG Log message used when commiting changes - -t Create version-release tag on releases/ - -b NAME The distribution branch to place it - -d URL The URL of base directory where packages will be placed - -c URL The URL of the base directory where the changelog will be - placed - -s Don't strip the changelog from the spec - (nor import it into misc/) - -n Don't try to rename the spec file - -h Show this message - -Examples: - repsys putsrpm pkg/SRPMS/pkg-2.0-1.src.rpm - repsys putsrpm -b 2009.1 foo-1.1-1.src.rpm -""" - -def parse_options(): - parser = OptionParser(help=HELP) - parser.add_option("-l", dest="logmsg", default="") - parser.add_option("-t", dest="markrelease", action="store_true", - default=False) - parser.add_option("-s", dest="striplog", action="store_false", - default=True) - parser.add_option("-b", dest="branch", type="string", default=None) - parser.add_option("-d", dest="baseurl", type="string", default=None) - parser.add_option("-c", dest="baseold", type="string", default=None) - parser.add_option("-n", dest="rename", action="store_false", - default=True) - opts, args = parser.parse_args() - opts.srpmfiles = args - return opts - -def put_srpm_cmd(srpmfiles, markrelease=False, striplog=True, branch=None, - baseurl=None, baseold=None, logmsg=None, rename=False): - for path in srpmfiles: - put_srpm(path, markrelease, striplog, branch, baseurl, baseold, - logmsg, rename) - -def main(): - do_command(parse_options, put_srpm_cmd) - -# vim:et:ts=4:sw=4 diff --git a/RepSys/commands/rpmlog.py b/RepSys/commands/rpmlog.py deleted file mode 100644 index 238b675..0000000 --- a/RepSys/commands/rpmlog.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/python -# -# This program will convert the output of "svn log" to be suitable -# for usage in an rpm %changelog session. -# -from RepSys import Error, layout, disable_mirror -from RepSys.command import * -from RepSys.svn import SVN -from RepSys.log import get_changelog, split_spec_changelog -from cStringIO import StringIO -import getopt -import os -import sys - -HELP = """\ -Usage: repsys rpmlog [OPTIONS] REPPKGDIRURL - -Prints the RPM changelog of a given package. - -Options: - -r REV Collect logs from given revision to revision 0 - -n NUM Output only last NUM entries - -T FILE %changelog template file to be used - -o Append old package changelog - -p Append changelog found in .spec file - -s Sort changelog entries, even from the old log - -M Do not use the mirror (use the main repository) - -h Show this message - -Examples: - repsys rpmlog python - repsys rpmlog http://svn.mandriva.com/svn/packages/cooker/python -""" - -def parse_options(): - parser = OptionParser(help=HELP) - parser.add_option("-r", dest="revision") - parser.add_option("-n", dest="size", type="int") - parser.add_option("-T", "--template", dest="template", type="string") - parser.add_option("-o", dest="oldlog", default=False, - action="store_true") - parser.add_option("-p", dest="usespec", default=False, - action="store_true") - parser.add_option("-s", dest="sort", default=False, - action="store_true") - parser.add_option("-M", "--no-mirror", action="callback", - callback=disable_mirror) - opts, args = parser.parse_args() - if len(args) != 1: - raise Error, "invalid arguments" - opts.pkgdirurl = layout.package_url(args[0]) - return opts - -def rpmlog(pkgdirurl, revision, size, template, oldlog, usespec, sort): - another = None - if usespec: - svn = SVN() - specurl = layout.package_spec_url(pkgdirurl) - rawspec = svn.cat(specurl, rev=revision) - spec, another = split_spec_changelog(StringIO(rawspec)) - newlog = get_changelog(pkgdirurl, another=another, rev=revision, - size=size, sort=sort, template=template, oldlog=oldlog) - sys.stdout.writelines(newlog) - -def main(): - do_command(parse_options, rpmlog) - -# vim:sw=4:ts=4:et diff --git a/RepSys/commands/submit.py b/RepSys/commands/submit.py deleted file mode 100644 index 2924329..0000000 --- a/RepSys/commands/submit.py +++ /dev/null @@ -1,211 +0,0 @@ -#!/usr/bin/python -from RepSys import Error, config, layout, mirror -from RepSys.svn import SVN -from RepSys.command import * -from RepSys.rpmutil import get_spec, get_submit_info -from RepSys.util import get_auth, execcmd, get_helper -import urllib -import getopt -import sys -import re -import subprocess -import uuid - -import xmlrpclib - -HELP = """\ -Usage: repsys submit [OPTIONS] [URL[@REVISION] ...] - -Submits the package from URL to the submit host. - -The submit host will try to build the package, and upon successful -completion will 'tag' the package and upload it to the official -repositories. - -The package name can refer to an alias to a group of packages defined in -the section submit-groups of the configuration file. - -The status of the submit can visualized at: - -http://kenobi.mandriva.com/bs/output.php - -If no URL and revision are specified, the latest changed revision in the -package working copy of the current directory will be used. - -Options: - -t TARGET Submit given package URL to given target - -l Just list available targets - -r REV Provides a revision number (when not providing as an - argument) - -s The host in which the package URL will be submitted - (defaults to the host in the URL) - -a Submit all URLs at once (depends on server-side support) - -i SID Use the submit identifier SID - -h Show this message - --distro The distribution branch where the packages come from - --define Defines one variable to be used by the submit scripts - in the submit host - -Examples: - repsys submit - repsys submit foo - repsys submit 2009.1/foo - repsys submit foo@14800 bar baz@11001 - repsys submit https://repos/svn/mdv/cooker/foo - repsys submit -l https://repos - repsys submit 2008.1/my-packages@11011 - repsys submit --define section=main/testing -t 2008.1 -""" - -DEFAULT_TARGET = "Cooker" - -def parse_options(): - parser = OptionParser(help=HELP) - parser.defaults["revision"] = None - parser.add_option("-t", dest="target", default=None) - parser.add_option("-l", action="callback", callback=list_targets) - parser.add_option("-r", dest="revision", type="string", nargs=1) - parser.add_option("-s", dest="submithost", type="string", nargs=1, - default=None) - parser.add_option("-i", dest="sid", type="string", nargs=1, - default=None) - parser.add_option("-a", dest="atonce", action="store_true", default=False) - parser.add_option("--distro", dest="distro", type="string", - default=None) - parser.add_option("--define", action="append", default=[]) - opts, args = parser.parse_args() - if not args: - name, url, rev = get_submit_info(".") - args = ["%s@%s" % (url, str(rev))] - print "Submitting %s at revision %s" % (name, rev) - print "URL: %s" % url - if opts.revision is not None: - # backwards compatibility with the old -r usage - if len(args) == 1: - args[0] = args[0] + "@" + opts.revision - else: - raise Error, "can't use -r REV with more than one package name" - del opts.revision - if len(args) == 2: - # prevent from using the old <name> <rev> syntax - try: - rev = int(args[1]) - except ValueError: - # ok, it is a package name, let it pass - pass - else: - raise Error, "the format <name> <revision> is deprecated, "\ - "use <name>@<revision> instead" - # expand group aliases - expanded = [] - for nameurl in args: - expanded.extend(expand_group(nameurl)) - if expanded != args: - print "Submitting: %s" % " ".join(expanded) - args = expanded - # generate URLs for package names: - opts.urls = [mirror.strip_username( - layout.package_url(nameurl, distro=opts.distro, mirrored=False)) - for nameurl in args] - # find the revision if not specified: - newurls = [] - for url in opts.urls: - if not "@" in url: - print "Fetching revision..." - courl = layout.checkout_url(url) - log = SVN().log(courl, limit=1) - if not log: - raise Error, "can't find a revision for %s" % courl - ci = log[0] - print "URL:", url - print "Commit:", - print "%d | %s" % (ci.revision, ci.author), - if ci.lines: - line = " ".join(ci.lines).strip() - if len(line) > 57: - line = line[:57] + "..." - print "| %s" % line, - print - url = url + "@" + str(ci.revision) - newurls.append(url) - opts.urls[:] = newurls - # choose a target if not specified: - if opts.target is None and opts.distro is None: - target = layout.distro_branch(opts.urls[0]) or DEFAULT_TARGET - print "Implicit target: %s" % target - opts.target = target - del opts.distro - return opts - -def expand_group(group): - name, rev = layout.split_url_revision(group) - distro = None - if "/" in name: - distro, name = name.rsplit("/", 1) - found = config.get("submit-groups", name) - packages = [group] - if found: - packages = found.split() - if rev: - packages = [("%s@%s" % (package, rev)) - for package in packages] - if distro: - packages = ["%s/%s" % (distro, package) - for package in packages] - return packages - -def list_targets(option, opt, val, parser): - host = config.get("submit", "host") - if host is None: - raise Error, "no submit host defined in repsys.conf" - createsrpm = get_helper("create-srpm") - #TODO make it configurable - command = "ssh %s %s --list" % (host, createsrpm) - execcmd(command, show=True) - sys.exit(0) - -def submit(urls, target, define=[], submithost=None, atonce=False, sid=None): - if submithost is None: - submithost = config.get("submit", "host") - if submithost is None: - # extract the submit host from the svn host - type, rest = urllib.splittype(pkgdirurl) - host, path = urllib.splithost(rest) - user, host = urllib.splituser(host) - submithost, port = urllib.splitport(host) - del type, user, port, path, rest - # runs a create-srpm in the server through ssh, which will make a - # copy of the rpm in the export directory - createsrpm = get_helper("create-srpm") - baseargs = ["ssh", submithost, createsrpm, "-t", target] - if not sid: - sid = uuid.uuid4() - define.append("sid=%s" % sid) - for entry in reversed(define): - baseargs.append("--define") - baseargs.append(entry) - cmdsargs = [] - if len(urls) == 1: - # be compatible with server-side repsys versions older than 1.6.90 - url, rev = layout.split_url_revision(urls[0]) - baseargs.append("-r") - baseargs.append(str(rev)) - baseargs.append(url) - cmdsargs.append(baseargs) - elif atonce: - cmdsargs.append(baseargs + urls) - else: - cmdsargs.extend((baseargs + [url]) for url in urls) - for cmdargs in cmdsargs: - command = subprocess.list2cmdline(cmdargs) - status, output = execcmd(command) - if status == 0: - print "Package submitted!" - else: - sys.stderr.write(output) - sys.exit(status) - -def main(): - do_command(parse_options, submit) - -# vim:et:ts=4:sw=4 diff --git a/RepSys/commands/switch.py b/RepSys/commands/switch.py deleted file mode 100644 index 998ae2c..0000000 --- a/RepSys/commands/switch.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/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 repository 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/ -""" - -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/commands/sync.py b/RepSys/commands/sync.py deleted file mode 100644 index b4bdaba..0000000 --- a/RepSys/commands/sync.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/python -from RepSys.command import * -from RepSys.rpmutil import sync - -HELP = """\ -Usage: repsys sync - -Will add or remove from the working copy those files added or removed -in the spec file. - -It will not commit the changes. - -Options: - -c Commit the changes, as in ci - --dry-run Print results without changing the working copy - --download -d - Try to download the source files not found - -h Show this message - -Examples: - repsys sync -""" - -def parse_options(): - parser = OptionParser(help=HELP) - parser.add_option("--dry-run", dest="dryrun", default=False, - action="store_true") - parser.add_option("-c", dest="ci", default=False, - action="store_true") - parser.add_option("-d", "--download", dest="download", default=False, - action="store_true") - opts, args = parser.parse_args() - if len(args): - opts.target = args[0] - return opts - -def main(): - do_command(parse_options, sync) diff --git a/RepSys/commands/up.py b/RepSys/commands/up.py deleted file mode 100644 index 02a1a9f..0000000 --- a/RepSys/commands/up.py +++ /dev/null @@ -1,22 +0,0 @@ -from RepSys import Error -from RepSys.command import * -from RepSys.rpmutil import update - -HELP = """\ -Usage: repsys up [PATH] - -Update the package working copy and synchronize all binaries. - -Options: - -h help -""" - -def parse_options(): - parser = OptionParser(help=HELP) - opts, args = parser.parse_args() - if args: - opts.target = args[0] - return opts - -def main(): - do_command(parse_options, update) diff --git a/RepSys/commands/upload.py b/RepSys/commands/upload.py deleted file mode 100644 index 6af50ea..0000000 --- a/RepSys/commands/upload.py +++ /dev/null @@ -1,28 +0,0 @@ -from RepSys import Error -from RepSys.command import * -from RepSys.rpmutil import upload - -HELP = """\ -Usage: repsys upload [OPTIONS] [PATH] - -Upload a given file to the binary sources repository. - -It will also update the contents of the 'binrepo.lst' file and leave it -uncommited. - -If the path is a directory, all the contents of the directory will be -uploaded or removed. - -Options: - -h help - -""" - -def parse_options(): - parser = OptionParser(help=HELP) - opts, args = parser.parse_args() - opts.paths = args - return opts - -def main(): - do_command(parse_options, upload) diff --git a/RepSys/layout.py b/RepSys/layout.py deleted file mode 100644 index fb50acd..0000000 --- a/RepSys/layout.py +++ /dev/null @@ -1,207 +0,0 @@ -""" Handles repository layout scheme and package URLs.""" - -import os -import urlparse - -from RepSys import Error, config -from RepSys.svn import SVN - -__all__ = ["package_url", "checkout_url", "repository_url", "get_url_revision"] - -def layout_dirs(): - devel_branch = config.get("global", "trunk-dir", "cooker/") - devel_branch = os.path.normpath(devel_branch) - branches_dir = config.get("global", "branches-dir", "updates/") - branches_dir = os.path.normpath(branches_dir) - return devel_branch, branches_dir - -def get_url_revision(url, retrieve=True): - """Get the revision from a given URL - - If the URL contains an explicit revision number (URL@REV), just use it - without even checking if the revision really exists. - - The parameter retrieve defines whether it must ask the SVN server for - the revision number or not when it is not found in the URL. - """ - url, rev = split_url_revision(url) - if rev is None and retrieve: - # if no revspec was found, ask the server - svn = SVN() - rev = svn.revision(url) - return rev - -def unsplit_url_revision(url, rev): - if rev is None: - newurl = url - else: - parsed = list(urlparse.urlparse(url)) - path = os.path.normpath(parsed[2]) - parsed[2] = path + "@" + str(rev) - newurl = urlparse.urlunparse(parsed) - return newurl - -def split_url_revision(url): - """Returns a tuple (url, rev) from an subversion URL with @REV - - If the revision is not present in the URL, rev is None. - """ - parsed = list(urlparse.urlparse(url)) - path = os.path.normpath(parsed[2]) - dirs = path.rsplit("/", 1) - lastname = dirs[-1] - newname = lastname - index = lastname.rfind("@") - rev = None - if index != -1: - newname = lastname[:index] - rawrev = lastname[index+1:] - if rawrev: - try: - rev = int(rawrev) - if rev < 0: - raise ValueError - except ValueError: - raise Error, "invalid revision specification on URL: %s" % url - dirs[-1] = newname - newpath = "/".join(dirs) - parsed[2] = newpath - newurl = urlparse.urlunparse(parsed) - return newurl, rev - -def checkout_url(pkgdirurl, branch=None, version=None, release=None, - releases=False, pristine=False, append_path=None): - """Get the URL of a branch of the package, defaults to current/ - - It tries to preserve revisions in the format @REV. - """ - parsed = list(urlparse.urlparse(pkgdirurl)) - path, rev = split_url_revision(parsed[2]) - if releases: - path = os.path.normpath(path + "/releases") - elif version: - assert release is not None - path = os.path.normpath(path + "/releases/" + version + "/" + release) - elif pristine: - path = os.path.join(path, "pristine") - elif branch: - path = os.path.join(path, "branches", branch) - else: - path = os.path.join(path, "current") - if append_path: - path = os.path.join(path, append_path) - path = unsplit_url_revision(path, rev) - parsed[2] = path - newurl = urlparse.urlunparse(parsed) - return newurl - -def convert_default_parent(url): - """Removes the cooker/ component from the URL""" - parsed = list(urlparse.urlparse(url)) - path = os.path.normpath(parsed[2]) - rest, last = os.path.split(path) - parsed[2] = rest - newurl = urlparse.urlunparse(parsed) - return newurl - -def remove_current(pkgdirurl): - parsed = list(urlparse.urlparse(pkgdirurl)) - path = os.path.normpath(parsed[2]) - rest, last = os.path.split(path) - if last == "current": - # FIXME this way we will not allow packages to be named "current" - path = rest - parsed[2] = path - newurl = urlparse.urlunparse(parsed) - return newurl - -def repository_url(mirrored=False): - url = None - if mirrored and config.getbool("global", "use-mirror", "yes"): - url = config.get("global", "mirror") - if url is None: - url = config.get("global", "repository") - if not url: - # compatibility with the default_parent configuration option - default_parent = config.get("global", "default_parent") - if default_parent is None: - raise Error, "you need to set the 'repository' " \ - "configuration option on repsys.conf" - url = convert_default_parent(default_parent) - return url - -def package_url(name_or_url, version=None, release=None, distro=None, - mirrored=True): - """Returns a tuple with the absolute package URL and its name - - @name_or_url: name, relative path, or URL of the package. In case it is - a URL, the URL will just be 'normalized'. - @version: the version to be fetched from releases/ (requires release) - @release: the release number to be fetched from releases/$version/ - @distro: the name of the repository branch inside updates/ - @mirrored: return an URL based on the mirror repository, if enabled - """ - from RepSys import mirror - if "://" in name_or_url: - pkgdirurl = mirror.normalize_path(name_or_url) - pkgdirurl = remove_current(pkgdirurl) - if mirror.using_on(pkgdirurl) and not mirrored: - pkgdirurl = mirror.relocate_path(mirror.mirror_url(), - repository_url(), pkgdirurl) - else: - name = name_or_url - devel_branch, branches_dir = layout_dirs() - if distro or "/" in name: - default_branch = branches_dir - if distro: - default_branch = os.path.join(default_branch, distro) - else: - default_branch = devel_branch # cooker - path = os.path.join(default_branch, name) - parsed = list(urlparse.urlparse(repository_url(mirrored=mirrored))) - parsed[2] = os.path.join(parsed[2], path) - pkgdirurl = urlparse.urlunparse(parsed) - return pkgdirurl - -def package_name(pkgdirurl): - """Returns the package name from a package URL - - It takes care of revision numbers""" - parsed = urlparse.urlparse(pkgdirurl) - path, rev = split_url_revision(parsed[2]) - rest, name = os.path.split(path) - return name - -def package_spec_url(pkgdirurl, *args, **kwargs): - """Returns the URL of the specfile of a given package URL - - The parameters are the same used by checkout_url, except append_path. - """ - kwargs["append_path"] = "SPECS/" + package_name(pkgdirurl) + ".spec" - specurl = checkout_url(pkgdirurl, *args, **kwargs) - return specurl - -def distro_branch(pkgdirurl): - """Tries to guess the distro branch name from a package URL""" - from RepSys.mirror import same_base - found = None - repo = repository_url() - if same_base(repo, pkgdirurl): - devel_branch, branches_dir = layout_dirs() - repo_path = urlparse.urlparse(repo)[2] - devel_path = os.path.join(repo_path, devel_branch) - branches_path = os.path.join(repo_path, branches_dir) - parsed = urlparse.urlparse(pkgdirurl) - path = os.path.normpath(parsed[2]) - if path.startswith(devel_path): - # devel_branch must be before branches_dir in order to allow - # devel_branch to be inside branches_dir, as in /branches/cooker - _, found = os.path.split(devel_branch) - elif path.startswith(branches_path): - comps = path.split("/") - if branches_path == "/": - found = comps[1] - elif len(comps) >= 2: # must be at least branch/pkgname - found = comps[branches_path.count("/")+1] - return found - diff --git a/RepSys/log.py b/RepSys/log.py deleted file mode 100644 index 6cb9da1..0000000 --- a/RepSys/log.py +++ /dev/null @@ -1,633 +0,0 @@ -#!/usr/bin/python -from RepSys import Error, config, layout -from RepSys.svn import SVN -from RepSys.util import execcmd - -try: - from Cheetah.Template import Template -except ImportError: - raise Error, "repsys requires the package python-cheetah" - -from cStringIO import StringIO - -import sys -import os -import re -import time -import locale -import glob -import tempfile -import shutil -import subprocess - - -locale.setlocale(locale.LC_ALL, "C") - -default_template = """ -#if not $releases_by_author[-1].visible - ## Hide the first release that contains no changes. It must be a - ## reimported package and the log gathered from misc/ already should - ## contain a correct entry for the version-release: - #set $releases_by_author = $releases_by_author[:-1] -#end if -#for $rel in $releases_by_author -* $rel.date $rel.author_name <$rel.author_email> $rel.version-$rel.release -+ Revision: $rel.revision -## #if not $rel.released -##+ Status: not released -## #end if - #if not $rel.visible -+ rebuild (emptylog) - #end if - #for $rev in $rel.release_revisions - #for $line in $rev.lines -$line - #end for - #end for - - #for $author in $rel.authors - #if not $author.visible - #continue - #end if - ##alternatively, one could use: - ###if $author.email == "root" - ## #continue - ###end if - + $author.name <$author.email> - #for $rev in $author.revisions - #for $line in $rev.lines - $line - #end for - #end for - - #end for -#end for -""" - -def getrelease(pkgdirurl, rev=None, macros=[], exported=None): - """Tries to obtain the version-release of the package for a - yet-not-markrelease revision of the package. - - Is here where things should be changed if "automatic release increasing" - will be used. - """ - from RepSys.rpmutil import rpm_macros_defs - svn = SVN() - pkgcurrenturl = os.path.join(pkgdirurl, "current") - specurl = os.path.join(pkgcurrenturl, "SPECS") - if exported is None: - tmpdir = tempfile.mktemp() - svn.export(specurl, tmpdir, rev=rev) - else: - tmpdir = os.path.join(exported, "SPECS") - try: - found = glob.glob(os.path.join(tmpdir, "*.spec")) - if not found: - raise Error, "no .spec file found inside %s" % specurl - specpath = found[0] - options = rpm_macros_defs(macros) - command = (("rpm -q --qf '%%{EPOCH}:%%{VERSION}-%%{RELEASE}\n' " - "--specfile %s %s") % - (specpath, options)) - pipe = subprocess.Popen(command, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, shell=True) - pipe.wait() - output = pipe.stdout.read() - error = pipe.stderr.read() - if pipe.returncode != 0: - raise Error, "Error in command %s: %s" % (command, error) - releases = output.split() - try: - epoch, vr = releases[0].split(":", 1) - version, release = vr.split("-", 1) - except ValueError: - raise Error, "Invalid command output: %s: %s" % \ - (command, output) - #XXX check if this is the right way: - if epoch == "(none)": - ev = version - else: - ev = epoch + ":" + version - return ev, release - finally: - if exported is None and os.path.isdir(tmpdir): - shutil.rmtree(tmpdir) - -class _Revision: - lines = [] - date = None - raw_date = None - revision = None - author_name = None - author_email = None - - def __init__(self, **kwargs): - self.__dict__.update(kwargs) - - def __repr__(self): - lines = repr(self.lines)[:30] + "...]" - line = "<_Revision %d author=%r date=%r lines=%s>" % \ - (self.revision, self.author, self.date, lines) - return line - - -class _Release(_Revision): - version = None - release = None - revisions = [] - release_revisions = [] - authors = [] - visible = False - - def __init__(self, **kwargs): - self.revisions = [] - _Revision.__init__(self, **kwargs) - - def __repr__(self): - line = "<_Release v=%s r=%s revs=%r>" % \ - (self.version, self.release, self.revisions) - return line - -unescaped_macro_pat = re.compile(r"([^%])%([^%])") - -def escape_macros(text): - escaped = unescaped_macro_pat.sub("\\1%%\\2", text) - return escaped - -def format_lines(lines): - first = 1 - entrylines = [] - perexpr = re.compile(r"([^%])%([^%])") - for line in lines: - if line: - line = escape_macros(line) - if first: - first = 0 - line = line.lstrip() - if line[0] != "-": - nextline = "- " + line - else: - nextline = line - elif line[0] != " " and line[0] != "-": - nextline = " " + line - else: - nextline = line - if nextline not in entrylines: - entrylines.append(nextline) - return entrylines - - -class _Author: - name = None - email = None - revisions = None - visible = False - - -def group_releases_by_author(releases): - allauthors = [] - grouped = [] - for release in releases: - - # group revisions of the release by author - authors = {} - latest = None - for revision in release.revisions: - authors.setdefault(revision.author, []).append(revision) - - # create _Authors and sort them by their latest revisions - decorated = [] - for authorname, revs in authors.iteritems(): - author = _Author() - author.name = revs[0].author_name - author.email = revs[0].author_email - author.revisions = revs - # #41117: mark those authors without visible messages - author.visible = bool(sum(len(rev.lines) for rev in revs)) - revlatest = author.revisions[0] - # keep the latest revision even for completely invisible - # authors (below) - if latest is None or revlatest.revision > latest.revision: - latest = revlatest - if not author.visible: - # only sort those visible authors, invisible ones are used - # only in "latest" - continue - decorated.append((revlatest.revision, author)) - decorated.sort(reverse=1) - - if release.visible: - release.authors = [t[1] for t in decorated] - firstrel, release.authors = release.authors[0], release.authors[1:] - release.author_name = firstrel.name - release.author_email = firstrel.email - release.release_revisions = firstrel.revisions - else: - # we don't care about other possible authors in completely - # invisible releases - firstrev = release.revisions[0] - release.author_name = firstrev.author_name - release.author_email = firstrev.author_email - release.raw_date = firstrev.raw_date - release.date = firstrev.date - - release.date = latest.date - release.raw_date = latest.raw_date - release.revision = latest.revision - - grouped.append(release) - - return grouped - - -def group_revisions_by_author(currentlog): - revisions = [] - last_author = None - for entry in currentlog: - revision = _Revision() - revision.lines = format_lines(entry.lines) - revision.raw_date = entry.date - revision.date = parse_raw_date(entry.date) - revision.revision = entry.revision - if entry.author == last_author: - revisions[-1].revisions.append(revision) - else: - author = _Author() - author.name, author.email = get_author_name(entry.author) - author.revisions = [revision] - revisions.append(author) - last_author = entry.author - return revisions - - -emailpat = re.compile("(?P<name>.*?)\s*<(?P<email>.*?)>") - -def get_author_name(author): - found = emailpat.match(config.get("users", author, author)) - name = ((found and found.group("name")) or author) - email = ((found and found.group("email")) or author) - return name, email - -def parse_raw_date(rawdate): - return time.strftime("%a %b %d %Y", rawdate) - -def filter_log_lines(lines): - # Lines in commit messages beginning with CLOG will be the only shown - # in the changelog. These lines will have the CLOG token and blanks - # stripped from the beginning. - onlylines = None - clogstr = config.get("log", "unignore-string") - if clogstr: - clogre = re.compile(r"(^%s[^ \t]?[ \t])" % clogstr) - onlylines = [clogre.sub("", line) - for line in lines if line.startswith(clogstr)] - if onlylines: - filtered = onlylines - else: - # Lines in commit messages containing SILENT at any position will be - # skipped; commits with their log messages beggining with SILENT in the - # first positionj of the first line will have all lines ignored. - ignstr = config.get("log", "ignore-string", "SILENT") - if len(lines) and lines[0].startswith(ignstr): - return [] - filtered = [line for line in lines if ignstr not in line] - return filtered - - -def make_release(author=None, revision=None, date=None, lines=None, - entries=[], released=True, version=None, release=None): - rel = _Release() - rel.author = author - if author: - rel.author_name, rel.author_email = get_author_name(author) - rel.revision = revision - rel.version = version - rel.release = release - rel.date = (date and parse_raw_date(date)) or None - rel.lines = lines - rel.released = released - rel.visible = False - for entry in entries: - lines = filter_log_lines(entry.lines) - revision = _Revision() - revision.revision = entry.revision - revision.lines = format_lines(lines) - if revision.lines: - rel.visible = True - revision.date = parse_raw_date(entry.date) - revision.raw_date = entry.date - revision.author = entry.author - (revision.author_name, revision.author_email) = \ - get_author_name(entry.author) - rel.revisions.append(revision) - return rel - - -def dump_file(releases, currentlog=None, template=None): - templpath = template or config.get("template", "path", - "/usr/share/repsys/default.chlog") - params = {} - if templpath is None or not os.path.exists(templpath): - params["source"] = default_template - sys.stderr.write("warning: %s not found. using built-in template.\n"% - templpath) - else: - params["file"] = templpath - releases_author = group_releases_by_author(releases) - revisions_author = group_revisions_by_author(currentlog) - params["searchList"] = [{"releases_by_author" : releases_author, - "releases" : releases, - "revisions_by_author": revisions_author}] - t = Template(**params) - return t.respond() - - -class InvalidEntryError(Exception): - pass - -def parse_repsys_entry(revlog): - # parse entries in the format: - # %repsys <operation> - # key: value - # .. - # <newline> - # <comments> - # - if len(revlog.lines) == 0 or not revlog.lines[0].startswith("%repsys"): - raise InvalidEntryError - try: - data = {"operation" : revlog.lines[0].split()[1]} - except IndexError: - raise InvalidEntryError - for line in revlog.lines[1:]: - if not line: - break - try: - key, value = line.split(":", 1) - except ValueError: - raise InvalidEntryError - data[key.strip().lower()] = value.strip() # ??? - return data - - -def get_revision_offset(): - try: - revoffset = config.getint("log", "revision-offset", 0) - except (ValueError, TypeError): - raise Error, ("Invalid revision-offset number in configuration " - "file(s).") - return revoffset or 0 - -oldmsgpat = re.compile( - r"Copying release (?P<rel>[^\s]+) to (?P<dir>[^\s]+) directory\.") - -def parse_markrelease_log(relentry): - if not ((relentry.lines and oldmsgpat.match(relentry.lines[0]) \ - or parse_repsys_entry(relentry))): - raise InvalidEntryError - from_rev = None - path = None - for changed in relentry.changed: - if changed["action"] == "A" and changed["from_rev"]: - from_rev = changed["from_rev"] - path = changed["path"] - break - else: - raise InvalidEntryError - # get the version and release from the names in the path, do not relay - # on log messages - version, release = path.rsplit(os.path.sep, 3)[-2:] - return version, release, from_rev - - -def svn2rpm(pkgdirurl, rev=None, size=None, submit=False, - template=None, macros=[], exported=None): - concat = config.get("log", "concat", "").split() - revoffset = get_revision_offset() - svn = SVN() - pkgreleasesurl = layout.checkout_url(pkgdirurl, releases=True) - pkgcurrenturl = layout.checkout_url(pkgdirurl) - releaseslog = svn.log(pkgreleasesurl, noerror=1) - currentlog = svn.log(pkgcurrenturl, limit=size, start=rev, - end=revoffset) - - # sort releases by copyfrom-revision, so that markreleases for same - # revisions won't look empty - releasesdata = [] - if releaseslog: - for relentry in releaseslog[::-1]: - try: - (version, release, relrevision) = \ - parse_markrelease_log(relentry) - except InvalidEntryError: - continue - releasesdata.append((relrevision, -relentry.revision, relentry, - version, release)) - releasesdata.sort() - - # collect valid releases using the versions provided by the changes and - # the packages - prevrevision = 0 - releases = [] - for (relrevision, dummy, relentry, version, release) in releasesdata: - if prevrevision == relrevision: - # ignore older markrelease of the same revision, since they - # will have no history - continue - entries = [entry for entry in currentlog - if relrevision >= entry.revision and - (prevrevision < entry.revision)] - if not entries: - #XXX probably a forced release, without commits in current/, - # check if this is the right behavior - sys.stderr.write("warning: skipping (possible) release " - "%s-%s@%s, no commits since previous markrelease (r%r)\n" % - (version, release, relrevision, prevrevision)) - continue - - release = make_release(author=relentry.author, - revision=relentry.revision, date=relentry.date, - lines=relentry.lines, entries=entries, - version=version, release=release) - releases.append(release) - prevrevision = relrevision - - # look for commits that have been not submitted (released) yet - # this is done by getting all log entries newer (greater revision no.) - # than releasesdata[-1] (in the case it exists) - if releasesdata: - latest_revision = releasesdata[-1][0] # the latest copied rev - else: - latest_revision = 0 - notsubmitted = [entry for entry in currentlog - if entry.revision > latest_revision] - if notsubmitted: - # if they are not submitted yet, what we have to do is to add - # a release/version number from getrelease() - version, release = getrelease(pkgdirurl, macros=macros, - exported=exported) - toprelease = make_release(entries=notsubmitted, released=False, - version=version, release=release) - releases.append(toprelease) - - data = dump_file(releases[::-1], currentlog=currentlog, template=template) - return data - -def _split_changelog(stream): - current = None - count = 0 - def finish(entry): - lines = entry[2] - # strip newlines at the end - for i in xrange(len(lines)-1, -1, -1): - if lines[i] != "\n": - break - del lines[i] - return entry - for line in stream: - if line.startswith("*"): - if current: - yield finish(current) - fields = line.split() - rawdate = " ".join(fields[:5]) - try: - date = time.strptime(rawdate, "* %a %b %d %Y") - except ValueError, e: - raise Error, "failed to parse spec changelog: %s" % e - curlines = [line] - current = (date, count, curlines) - # count used to ensure stable sorting when changelog entries - # have the same date, otherwise it would also compare the - # changelog lines - count -= 1 - elif current: - curlines.append(line) - else: - pass # not good, but ignore - if current: - yield finish(current) - -def sort_changelog(stream): - entries = _split_changelog(stream) - log = StringIO() - for time, count, elines in sorted(entries, reverse=True): - log.writelines(elines) - log.write("\n") - return log - -def split_spec_changelog(stream): - chlog = StringIO() - spec = StringIO() - found = 0 - visible = 0 - for line in stream: - if line.startswith("%changelog"): - found = 1 - elif not found: - spec.write(line) - elif found: - if line.strip(): - visible = 1 - chlog.write(line) - elif line.startswith("%"): - found = 0 - spec.write(line) - spec.seek(0) - if not visible: - # when there are only blanks in the changelog, make it empty - chlog = StringIO() - return spec, chlog - -def get_old_log(pkgdirurl): - chlog = StringIO() - oldurl = config.get("log", "oldurl") - if oldurl: - svn = SVN() - tmpdir = tempfile.mktemp() - try: - pkgname = layout.package_name(pkgdirurl) - pkgoldurl = os.path.join(oldurl, pkgname) - try: - # we're using HEAD here because fixes in misc/ (oldurl) may - # be newer than packages' last changed revision. - svn.export(pkgoldurl, tmpdir) - except Error: - pass - else: - logfile = os.path.join(tmpdir, "log") - if os.path.isfile(logfile): - file = open(logfile) - chlog.write("\n") # TODO needed? - log = file.read() - log = escape_macros(log) - chlog.write(log) - file.close() - finally: - if os.path.isdir(tmpdir): - shutil.rmtree(tmpdir) - chlog.seek(0) - return chlog - -def get_changelog(pkgdirurl, another=None, svn=True, rev=None, size=None, - submit=False, sort=False, template=None, macros=[], exported=None, - oldlog=False): - """Generates the changelog for a given package URL - - @another: a stream with the contents of a changelog to be merged with - the one generated - @svn: enable changelog from svn - @rev: generate the changelog with the changes up to the given - revision - @size: the number of revisions to be used (as in svn log --limit) - @submit: defines whether the latest unreleased log entries should have - the version parsed from the spec file - @sort: should changelog entries be reparsed and sorted after appending - the oldlog? - @template: the path to the cheetah template used to generate the - changelog from svn - @macros: a list of tuples containing macros to be defined when - parsing the version in the changelog - @exported: the path of a directory containing an already existing - checkout of the package, so that the spec file can be - parsed from there - @oldlog: if set it will try to append the old changelog file defined - in oldurl in repsys.conf - """ - newlog = StringIO() - if svn: - rawsvnlog = svn2rpm(pkgdirurl, rev=rev, size=size, submit=submit, - template=template, macros=macros, exported=exported) - newlog.write(rawsvnlog) - if another: - newlog.writelines(another) - if oldlog: - newlog.writelines(get_old_log(pkgdirurl)) - if sort: - newlog.seek(0) - newlog = sort_changelog(newlog) - newlog.seek(0) - return newlog - -def specfile_svn2rpm(pkgdirurl, specfile, rev=None, size=None, - submit=False, sort=False, template=None, macros=[], exported=None): - fi = open(specfile) - spec, oldchlog = split_spec_changelog(fi) - fi.close() - another = None - if config.getbool("log", "merge-spec", False): - another = oldchlog - sort = sort or config.getbool("log", "sort", False) - chlog = get_changelog(pkgdirurl, another=another, rev=rev, size=size, - submit=submit, sort=sort, template=template, macros=macros, - exported=exported, oldlog=True) - fo = open(specfile, "w") - fo.writelines(spec) - fo.write("\n\n%changelog\n") - fo.writelines(chlog) - fo.close() - -if __name__ == "__main__": - l = svn2rpm(sys.argv[1]) - print l - -# vim:et:ts=4:sw=4 diff --git a/RepSys/mirror.py b/RepSys/mirror.py deleted file mode 100644 index 94720cc..0000000 --- a/RepSys/mirror.py +++ /dev/null @@ -1,129 +0,0 @@ -import sys -import os -import urlparse -import urllib - -from RepSys import Error, config, layout -from RepSys.svn import SVN - -def mirror_url(): - mirror = config.get("global", "mirror") - return mirror - -def normalize_path(url): - """normalize url for relocate_path needs""" - parsed = urlparse.urlparse(url) - path = os.path.normpath(parsed[2]) - newurl = urlparse.urlunparse((parsed[0], parsed[1], path, - parsed[3], parsed[4], parsed[5])) - return newurl - -def _joinurl(url, relpath): - parsed = urlparse.urlparse(url) - newpath = os.path.join(parsed[2], relpath) - newurl = urlparse.urlunparse((parsed[0], parsed[1], newpath, - parsed[3], parsed[4], parsed[5])) - return newurl - - -def strip_username(url): - parsed = list(urlparse.urlparse(url)) - _, parsed[1] = urllib.splituser(parsed[1]) - newurl = urlparse.urlunparse(parsed) - return newurl - -def same_base(parent, url): - """returns true if parent is parent of url""" - parent = normalize_path(parent) - url = normalize_path(url) - url = strip_username(url) - return url.startswith(parent) - -def relocate_path(oldparent, newparent, url): - oldparent = normalize_path(oldparent) - newparent = normalize_path(newparent) - url = normalize_path(url) - subpath = url[len(oldparent)+1:] - newurl = _joinurl(newparent, subpath) # subpath usually gets / at begining - return newurl - -def enabled(wcurl=None): - mirror = mirror_url() - repository = layout.repository_url() - enabled = False - if mirror and repository: - enabled = True - if wcurl and not same_base(mirror, wcurl): - enabled = False - return enabled - -def using_on(url): - """returnes True if the URL points to the mirror repository""" - mirror = mirror_url() - if mirror: - using = same_base(mirror, url) - else: - using = False - return using - -def info(url, write=False, stream=sys.stderr): - if using_on(url): - stream.write("Using the svn mirror.\n") - if write: - stream.write("To be able to commit changes, use " - "'repsys switch' first.\n") - -def mirror_relocate(oldparent, newparent, url, wcpath): - svn = SVN() - newurl = relocate_path(oldparent, newparent, url) - svn.switch(newurl, url, path=wcpath, relocate=True) - return newurl - -def switchto_parent(svn, url, path): - """Relocates the working copy to default_parent""" - newurl = mirror_relocate(mirror_url(), layout.repository_url(), url, path) - return newurl - -def switchto_parent_url(url): - newurl = relocate_path(mirror_url(), layout.repository_url(), url) - return newurl - -def switchto_mirror(svn, url, path): - newurl = mirror_relocate(layout.repository_url(), mirror_url(), url, path) - return newurl - -def autoswitch(svn, wcpath, wcurl, newbaseurl=None): - """Switches between mirror, default_parent, or newbaseurl""" - nobase = False - mirror = mirror_url() - repository = layout.repository_url() - current = repository - if repository is None: - raise Error, "the option repository from repsys.conf is "\ - "required" - indefault = same_base(repository, 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 = repository - 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 "\ - "repository nor mirror URLs" - assert current != chosen - newurl = mirror_relocate(current, chosen, wcurl, wcpath) - return newurl diff --git a/RepSys/plugins/__init__.py b/RepSys/plugins/__init__.py deleted file mode 100644 index e4f4e08..0000000 --- a/RepSys/plugins/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -import os - -loaded = {} - -def load(): - # based on smart's plugin system - pluginsdir = os.path.dirname(__file__) - for entry in os.listdir(pluginsdir): - if entry != "__init__.py" and entry.endswith(".py"): - name = entry[:-3] - loaded[name] = __import__("RepSys.plugins."+name, {}, {}, - [name]) - elif os.path.isdir(entry): - initfile = os.path.join(entry, "__init__.py") - if os.path.isfile(initfile): - loaded[entry] = __import__("RepSys.plugins."+entry, {}, {}, - [entry]) - -def list(): - return loaded.keys() - -def help(name): - from RepSys import Error - try: - return loaded[name].__doc__ - except KeyError: - raise Error, "plugin %s not found" % name diff --git a/RepSys/plugins/ldapusers.py b/RepSys/plugins/ldapusers.py deleted file mode 100644 index e56371d..0000000 --- a/RepSys/plugins/ldapusers.py +++ /dev/null @@ -1,189 +0,0 @@ -""" -A Repsys plugin for obtaining users from a LDAP server. - -In order to enable the plugin, the user must define the following -options in the [global] section of repsys.conf: - - ldap-uri [required if ldap-server is unset] - the URI of the server, you can refer to more than one server by - adding more URIs separated by spaces:: - - ldap-uri = ldap://ldap.network/ ldaps://backup.network:22389/ - - ldap-server [required if ldap-uri is unset] - the host name of the LDAP server - ldap-port [optional] [default: 389] - the port of the LDAP server - ldap-base [required] - the base DN where the search will be performed - ldap-binddn [optional] [default: empty] - the DN used to bind - ldap-bindpw [optional] [default: empty] - the password used to bind - ldap-starttls [optional] [default: no] - use "yes" or "no" to enable or disable the use of the STARTTLS - LDAP extension - ldap-filterformat [optional] - [default: (&(objectClass=inetOrgPerson)(uid=$username))] - RFC-2254 filter string used in the search of the user entry. - Note that this is a python template string and will have the - user name as parameter. For example: - - ldap-filterformat = (&(objectClass=inetOrgPerson)(uid=$username)) - - Will result in the search filter: - - (&(objectClass=inetOrgPerson)(uid=john)) - - ldap-resultformat [optional] [default: $cn <$mail>] - This is a python template string. This string will be - formatted using one dict object containing the fields - returned in the LDAP search, for example: - - >>> format = Template("$cn <$mail>") - >>> d = search(basedn, filter) - >>> d - {"cn": "John Doe", "mail": "john@mandriva.org", - "uidNumber": "1290", "loginShell": "/bin/bash", - ... many other attributes ... } - >>> value = format.substitute(d) - >>> print value - John Doe <john@mandriva.org> - - Note that only the first value of the attributes will be - used. - -When the searched option is not found, it will try in repsys.conf. All -the values found. (including from repsys.conf) will be cached between -each configuration access. - -This plugin requires the package python-ldap. - -For more information, look http://qa.mandriva.com/show_bug.cgi?id=30549 -""" -from RepSys import Error, config - -import string - -users_cache = {} - -class LDAPError(Error): - def __init__(self, ldaperr): - self.ldaperr = ldaperr - name = ldaperr.__class__.__name__ - desc = ldaperr.message["desc"] - self.message = "LDAP error %s: %s" % (name, desc) - self.args = self.message, - -def strip_entry(entry): - "Leave only the first value in all keys in the entry" - new = dict((key, value[0]) for key, value in entry.iteritems()) - return new - -def interpolate(optname, format, data): - tmpl = string.Template(format) - try: - return tmpl.substitute(data) - except KeyError, e: - raise Error, "the key %s was not found in LDAP search, " \ - "check your %s configuration" % (e, optname) - except (TypeError, ValueError), e: - raise Error, "LDAP response formatting error: %s. Check " \ - "your %s configuration" % (e, optname) - -def used_attributes(format): - class DummyDict: - def __init__(self): - self.found = [] - def __getitem__(self, key): - self.found.append(key) - return key - dd = DummyDict() - t = string.Template(format) - t.safe_substitute(dd) - return dd.found - -def make_handler(): - uri = config.get("global", "ldap-uri") - if not uri: - server = config.get("global", "ldap-server") - if not server: - # ldap support is not enabled if ldap-uri nor ldap-server are - # defined - def dummy_wrapper(section, option=None, default=None, walk=False): - return config.get(section, option, default, wrap=False) - return dummy_wrapper - - try: - port = int(config.get("global", "ldap-port", 389)) - except ValueError: - raise Error, "the option ldap-port requires an integer, please "\ - "check your configuration files" - uri = "ldap://%s:%d" % (server, port) - - basedn = config.get("global", "ldap-base") - binddn = config.get("global", "ldap-binddn") - bindpw = config.get("global", "ldap-bindpw", "") - filterformat = config.get("global", "ldap-filterformat", - "(&(objectClass=inetOrgPerson)(uid=$username))", raw=1) - format = config.get("global", "ldap-resultformat", "$cn <$mail>", raw=1) - - valid = {"yes": True, "no": False} - raw = config.get("global", "ldap-starttls", "no") - try: - starttls = valid[raw] - except KeyError: - raise Error, "invalid value %r for ldap-starttls, use "\ - "'yes' or 'no'" % raw - - try: - import ldap - except ImportError: - raise Error, "LDAP support needs the python-ldap package "\ - "to be installed" - else: - from ldap.filter import escape_filter_chars - - def users_wrapper(section, option=None, default=None, walk=False): - global users_cache - if walk: - raise Error, "ldapusers plugin does not support user listing" - assert option is not None, \ - "When not section walking, option is required" - - value = users_cache.get(option) - if value is not None: - return value - - try: - l = ldap.initialize(uri) - if starttls: - l.start_tls_s() - if binddn: - l.bind(binddn, bindpw) - except ldap.LDAPError, e: - raise LDAPError(e) - try: - data = {"username": escape_filter_chars(option)} - filter = interpolate("ldap-filterformat", filterformat, data) - attrs = used_attributes(format) - try: - found = l.search_s(basedn, ldap.SCOPE_SUBTREE, filter, - attrlist=attrs) - except ldap.LDAPError, e: - raise LDAPError(e) - if found: - dn, entry = found[0] - entry = strip_entry(entry) - value = interpolate("ldap-resultformat", format, entry) - else: - # issue a warning? - value = config.get(section, option, default, wrap=False) - users_cache[option] = value - return value - finally: - l.unbind_s() - - return users_wrapper - -config.wrap("users", handler=make_handler()) diff --git a/RepSys/plugins/sample.py.txt b/RepSys/plugins/sample.py.txt deleted file mode 100644 index 9877f3c..0000000 --- a/RepSys/plugins/sample.py.txt +++ /dev/null @@ -1,14 +0,0 @@ -# Sample repsys plugin. In order to test it, rename to sample.py -# vim:ft=python -from RepSys import config - -def users_wrapper(section, option=None, default=None, walk=False): - d = {"foolano": "Foolano De Tal <foolano@bla.com>", - "ceeclano": "Ceeclano Algumacoisa <ceeclano@bli.com>", - "beltrano": "Beltrano Bla <beltrano@mail.ru>"} - if walk: - return d.items() - - return d.get(option, default) - -config.wrap("users", handler=users_wrapper) diff --git a/RepSys/rpmutil.py b/RepSys/rpmutil.py deleted file mode 100644 index bff744b..0000000 --- a/RepSys/rpmutil.py +++ /dev/null @@ -1,759 +0,0 @@ -#!/usr/bin/python -from RepSys import Error, config -from RepSys import mirror, layout, log, binrepo -from RepSys.svn import SVN -from RepSys.simplerpm import SRPM -from RepSys.util import execcmd -from RepSys.command import default_parent -import rpm -import urlparse -import tempfile -import shutil -import string -import glob -import sys -import os - -def get_spec(pkgdirurl, targetdir=".", submit=False): - svn = SVN() - tmpdir = tempfile.mktemp() - try: - geturl = layout.checkout_url(pkgdirurl, append_path="SPECS") - mirror.info(geturl) - svn.export("'%s'" % geturl, tmpdir) - speclist = glob.glob(os.path.join(tmpdir, "*.spec")) - if not speclist: - raise Error, "no spec files found" - spec = speclist[0] - shutil.copy(spec, targetdir) - name = os.path.basename(spec) - path = os.path.join(targetdir, name) - print "Wrote %s" % (name) - finally: - 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() - 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, - version = None, - release = None, - revision = None, - packager = "", - revname = 0, - svnlog = 0, - scripts = [], - submit = False, - template = None, - macros = [], - verbose = 0, - strict = False, - use_binrepo = False, - binrepo_check = True): - svn = SVN() - 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") - - try: - if mode == "version": - geturl = layout.checkout_url(pkgdirurl, version=version, - release=release) - elif mode == "pristine": - geturl = layout.checkout_url(pkgdirurl, pristine=True) - elif mode == "current" or mode == "revision": - #FIXME we should handle revisions specified using @REV - geturl = layout.checkout_url(pkgdirurl) - else: - raise Error, "unsupported get_srpm mode: %s" % mode - 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) - mirror.info(geturl) - svn.export(geturl, tmpdir, rev=revision) - if use_binrepo: - binrepo_check = (binrepo_check or - config.getbool("binrepo", "getsrpm-check", False)) - download_binaries(tmpdir, geturl, revision=revision, - export=True, check=binrepo_check) - srpmsdir = os.path.join(tmpdir, "SRPMS") - os.mkdir(srpmsdir) - specsdir = os.path.join(tmpdir, "SPECS") - speclist = glob.glob(os.path.join(specsdir, "*.spec")) - if config.getbool("srpm", "run-prep", False): - makefile = os.path.join(tmpdir, "Makefile") - if os.path.exists(makefile): - execcmd("make", "-C", tmpdir, "srpm-prep") - if not speclist: - raise Error, "no spec files found" - spec = speclist[0] - if svnlog: - submit = not not revision - log.specfile_svn2rpm(pkgdirurl, spec, revision, submit=submit, - template=template, macros=macros, exported=tmpdir) - for script in scripts: - #FIXME revision can be "None" - status, output = execcmd(script, tmpdir, spec, str(revision), - noerror=1) - if status != 0: - raise Error, "script %s failed" % script - if packager: - packager = " --define 'packager %s'" % packager - - defs = rpm_macros_defs(macros) - sourcecmd = config.get("helper", "rpmbuild", "rpmbuild") - 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)) - - # copy the generated SRPMs to their target locations - targetsrpms = [] - urlrev = None - if revname: - urlrev = revision or layout.get_url_revision(geturl) - if not targetdirs: - targetdirs = (".",) - srpms = glob.glob(os.path.join(srpmsdir, "*.src.rpm")) - if not srpms: - # something fishy happened - raise Error, "no SRPMS were found at %s" % srpmsdir - for srpm in srpms: - name = os.path.basename(srpm) - if revname: - name = "@%s:%s" % (urlrev, name) - for targetdir in targetdirs: - newpath = os.path.join(targetdir, name) - targetsrpms.append(newpath) - if os.path.exists(newpath): - # should we warn? - os.unlink(newpath) - shutil.copy(srpm, newpath) - if verbose: - sys.stderr.write("Wrote: %s\n" % newpath) - return targetsrpms - finally: - if os.path.isdir(tmpdir): - shutil.rmtree(tmpdir) - -def patch_spec(pkgdirurl, patchfile, log=""): - #FIXME use get_spec - svn = SVN() - tmpdir = tempfile.mktemp() - try: - geturl = layout.checkout_url(pkgdirurl, append_path="SPECS") - svn.checkout(geturl, tmpdir) - speclist = glob.glob(os.path.join(tmpdir, "*.spec")) - if not speclist: - raise Error, "no spec files found" - spec = speclist[0] - status, output = execcmd("patch", spec, patchfile) - if status != 0: - raise Error, "can't apply patch:\n%s\n" % output - else: - svn.commit(tmpdir, log="") - finally: - if os.path.isdir(tmpdir): - shutil.rmtree(tmpdir) - -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: - pkgurl = mirror._joinurl(baseurl, srpm.name) - else: - pkgurl = layout.package_url(srpm.name, distro=branch, - mirrored=False) - print "Importing package to %s" % pkgurl - try: - if srpm.epoch: - version = "%s:%s" % (srpm.epoch, srpm.version) - else: - version = srpm.version - versionurl = "/".join([pkgurl, "releases", version]) - releaseurl = "/".join([versionurl, srpm.release]) - currenturl = "/".join([pkgurl, "current"]) - currentdir = os.path.join(tmpdir, "current") - #FIXME when pre-commit hook fails, there's no clear way to know - # what happened - ret = svn.mkdir(pkgurl, noerror=1, log="Created package directory") - if ret or not svn.ls(currenturl, noerror=1): - svn.checkout(pkgurl, tmpdir) - svn.mkdir(os.path.join(tmpdir, "releases")) - svn.mkdir(currentdir) - svn.mkdir(os.path.join(currentdir, "SPECS")) - svn.mkdir(os.path.join(currentdir, "SOURCES")) - #svn.commit(tmpdir,log="Created package structure.") - version_exists = 1 - else: - if svn.ls(releaseurl, noerror=1): - raise Error, "release already exists" - svn.checkout("/".join([pkgurl, "current"]), tmpdir) - svn.mkdir(versionurl, noerror=1, - log="Created directory for version %s." % version) - currentdir = tmpdir - - specsdir = os.path.join(currentdir, "SPECS") - sourcesdir = os.path.join(currentdir, "SOURCES") - - unpackdir = tempfile.mktemp() - os.mkdir(unpackdir) - try: - srpm.unpack(unpackdir) - - uspecsdir = os.path.join(unpackdir, "SPECS") - usourcesdir = os.path.join(unpackdir, "SOURCES") - - uspecsentries = os.listdir(uspecsdir) - usourcesentries = os.listdir(usourcesdir) - specsentries = os.listdir(specsdir) - sourcesentries = os.listdir(sourcesdir) - - # Remove old entries - for entry in [x for x in specsentries - if x not in uspecsentries]: - if entry == ".svn": - continue - entrypath = os.path.join(specsdir, entry) - os.unlink(entrypath) - svn.remove(entrypath) - for entry in [x for x in sourcesentries - if x not in usourcesentries]: - if entry == ".svn": - continue - entrypath = os.path.join(sourcesdir, entry) - os.unlink(entrypath) - svn.remove(entrypath) - - # Copy all files - execcmd("cp -rf", uspecsdir, currentdir) - execcmd("cp -rf", usourcesdir, currentdir) - - # Add new entries - for entry in [x for x in uspecsentries - if x not in specsentries]: - entrypath = os.path.join(specsdir, entry) - svn.add(entrypath) - for entry in [x for x in usourcesentries - if x not in sourcesentries]: - entrypath = os.path.join(sourcesdir, entry) - svn.add(entrypath) - finally: - if os.path.isdir(unpackdir): - shutil.rmtree(unpackdir) - - specs = glob.glob(os.path.join(specsdir, "*.spec")) - if not specs: - raise Error, "no spec file found on %s" % specsdir - if len(specs) > 1: - raise Error, "more than one spec file found on %s" % specsdir - specpath = specs[0] - if rename: - specfile = os.path.basename(specpath) - specname = specfile[:-len(".spec")] - if specname != srpm.name: - newname = srpm.name + ".spec" - newpath = os.path.join(specsdir, newname) - sys.stderr.write("warning: renaming spec file to '%s' " - "(use -n to disable it)\n" % (newname)) - os.rename(specpath, newpath) - try: - svn.remove(specpath) - except Error: - # file not tracked - svn.revert(specpath) - svn.add(newpath) - specpath = newpath - - if striplog: - specpath = specpath - fspec = open(specpath) - spec, chlog = log.split_spec_changelog(fspec) - fspec.close() - fspec = open(specpath, "w") - fspec.writelines(spec) - fspec.close() - chlog.seek(0, os.SEEK_END) - if chlog.tell() != 0: - chlog.seek(0) - #FIXME move it to layout.py - oldurl = baseold or config.get("log", "oldurl") - pkgoldurl = mirror._joinurl(oldurl, srpm.name) - svn.mkdir(pkgoldurl, noerror=1, - log="created old log directory for %s" % srpm.name) - logtmp = tempfile.mktemp() - try: - svn.checkout(pkgoldurl, logtmp) - miscpath = os.path.join(logtmp, "log") - fmisc = open(miscpath, "w+") - fmisc.writelines(chlog) - fmisc.close() - svn.add(miscpath) - svn.commit(logtmp, - log="imported old log for %s" % srpm.name) - finally: - if os.path.isdir(logtmp): - shutil.rmtree(logtmp) - binrepo.import_binaries(currentdir, srpm.name) - svn.commit(tmpdir, - log=logmsg or ("imported package %s" % srpm.name)) - finally: - if os.path.isdir(tmpdir): - shutil.rmtree(tmpdir) - - # Do revision and pristine tag copies - pristineurl = layout.checkout_url(pkgurl, pristine=True) - svn.remove(pristineurl, noerror=1, - log="Removing previous pristine/ directory.") - currenturl = layout.checkout_url(pkgurl) - svn.copy(currenturl, pristineurl, - log="Copying release %s-%s to pristine/ directory." % - (version, srpm.release)) - if markrelease: - svn.copy(currenturl, releaseurl, - log="Copying release %s-%s to releases/ directory." % - (version, srpm.release)) - -def create_package(pkgdirurl, log="", verbose=0): - svn = SVN() - tmpdir = tempfile.mktemp() - try: - basename = layout.package_name(pkgdirurl) - if verbose: - print "Creating package directory...", - sys.stdout.flush() - ret = svn.mkdir(pkgdirurl, - log="Created package directory for '%s'." % basename) - if verbose: - print "done" - print "Checking it out...", - svn.checkout(pkgdirurl, tmpdir) - if verbose: - print "done" - print "Creating package structure...", - svn.mkdir(os.path.join(tmpdir, "current")) - svn.mkdir(os.path.join(tmpdir, "current", "SPECS")) - svn.mkdir(os.path.join(tmpdir, "current", "SOURCES")) - if verbose: - print "done" - print "Committing...", - svn.commit(tmpdir, - log="Created package structure for '%s'." % basename) - print "done" - finally: - if os.path.isdir(tmpdir): - shutil.rmtree(tmpdir) - - -def create_markrelease_log(version, release, revision): - log = """%%repsys markrelease -version: %s -release: %s -revision: %s - -%s""" % (version, release, revision, - ("Copying %s-%s to releases/ directory." % (version, release))) - return log - -def mark_release(pkgdirurl, version, release, revision): - svn = SVN() - releasesurl = layout.checkout_url(pkgdirurl, releases=True) - versionurl = "/".join([releasesurl, version]) - releaseurl = "/".join([versionurl, release]) - currenturl = layout.checkout_url(pkgdirurl) - binrepo.markrelease(currenturl, releasesurl, version, release, revision) - if svn.ls(releaseurl, noerror=1): - raise Error, "release already exists" - svn.mkdir(releasesurl, noerror=1, - log="Created releases directory.") - svn.mkdir(versionurl, noerror=1, - log="Created directory for version %s." % version) - pristineurl = layout.checkout_url(pkgdirurl, pristine=True) - svn.remove(pristineurl, noerror=1, - log="Removing previous pristine/ directory.") - svn.copy(currenturl, pristineurl, - log="Copying release %s-%s to pristine/ directory." % - (version, release)) - markreleaselog = create_markrelease_log(version, release, revision) - svn.copy(currenturl, releaseurl, rev=revision, - log=markreleaselog) - -def check_changed(pkgdirurl, all=0, show=0, verbose=0): - svn = SVN() - if all: - baseurl = pkgdirurl - packages = [] - if verbose: - print "Getting list of packages...", - sys.stdout.flush() - 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: - baseurl, basename = os.path.split(pkgdirurl) - packages = [basename] - clean = [] - changed = [] - nopristine = [] - nocurrent = [] - for package in packages: - pkgdirurl = os.path.join(baseurl, package) - current = layout.checkout_url(pkgdirurl) - pristine = layout.checkout_url(pkgdirurl, pristine=True) - if verbose: - print "Checking package %s..." % package, - sys.stdout.flush() - if not svn.ls(current, noerror=1): - if verbose: - print "NO CURRENT" - nocurrent.append(package) - elif not svn.ls(pristine, noerror=1): - if verbose: - print "NO PRISTINE" - nopristine.append(package) - else: - diff = svn.diff(pristine, current) - if diff: - changed.append(package) - if verbose: - print "CHANGED" - if show: - print diff - else: - if verbose: - print "clean" - clean.append(package) - if verbose: - if not packages: - print "No packages found!" - elif all: - print "Total clean packages: %s" % len(clean) - print "Total CHANGED packages: %d" % len(changed) - print "Total NO CURRENT packages: %s" % len(nocurrent) - print "Total NO PRISTINE packages: %s" % len(nopristine) - return {"clean": clean, - "changed": changed, - "nocurrent": nocurrent, - "nopristine": nopristine} - -def checkout(pkgdirurl, path=None, revision=None, branch=None, distro=None, - spec=False, use_binrepo=False, binrepo_check=True, binrepo_link=True): - o_pkgdirurl = pkgdirurl - pkgdirurl = layout.package_url(o_pkgdirurl, distro=distro) - append = None - if spec: - append = "SPECS" - current = layout.checkout_url(pkgdirurl, branch=branch, - append_path=append) - if path is None: - path = layout.package_name(pkgdirurl) - mirror.info(current, write=True) - svn = SVN() - svn.checkout(current, path, rev=revision, show=1) - if use_binrepo: - download_binaries(path, revision=revision, symlinks=binrepo_link, - check=binrepo_check) - -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): - if path is None: - path = os.getcwd() - names = os.listdir(path) - return (".svn" in names and "SPECS" in names and "SOURCES" in names) - -def sync(dryrun=False, ci=False, download=False): - # TODO FIXME XXX fix it! - raise Error, "sync is not expected to work these days" - svn = SVN() - topdir = getpkgtopdir() - # run svn info because svn st does not complain when topdir is not an - # working copy - svn.info(topdir) - specsdir = os.path.join(topdir, "SPECS/") - sourcesdir = os.path.join(topdir, "SOURCES/") - for path in (specsdir, sourcesdir): - if not os.path.isdir(path): - raise Error, "%s directory not found" % path - specs = glob.glob(os.path.join(specsdir, "*.spec")) - if not specs: - raise Error, "no .spec files found in %s" % specsdir - specpath = specs[0] # FIXME better way? - try: - rpm.addMacro("_topdir", os.path.abspath(topdir)) - spec = rpm.TransactionSet().parseSpec(specpath) - except rpm.error, e: - raise Error, "could not load spec file: %s" % e - 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_br = [] - toadd_svn = [] - toremove_svn = [] - toremove_br = [] - # add the spec file itself, in case of a new package - specstl = svn.status(specpath, noignore=True) - if specstl: - specst, _ = specstl[0] - if specst == "?": - toadd_svn.append(specpath) - # add source files: - for source, url in sources.iteritems(): - sourcepath = os.path.join(sourcesdir, source) - if sourcesst.get(source): - if not os.path.islink(sourcepath): - if not binrepo.is_tracked(sourcepath): - if binrepo.is_binary(sourcepath): - toadd_br.append(sourcepath) - else: - toadd_svn.append(sourcepath) - else: - sys.stderr.write("warning: %s not found\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): - if binrepo.is_binary(sourcepath): - toadd_br.append(sourcepath) - else: - toadd_svn.append(sourcepath) - else: - raise Error, "file not found: %s" % sourcepath - # rm entries not found in sources and still in svn - found = os.listdir(sourcesdir) - for entry in found: - if entry == ".svn" or entry == "sources": - continue - status = sourcesst.get(entry) - path = os.path.join(sourcesdir, entry) - if entry not in sources: - if status is None: # file is tracked by svn - toremove_svn.append(path) - elif binrepo.is_tracked(path): - toremove_br.append(path) - for path in toremove_svn: - print "D\t%s" % path - if not dryrun: - svn.remove(path, local=True) - for path in toremove_br: - print "DB\t%s" % path - if not dryrun: - binrepo.delete_pending(path) - for path in toadd_svn: - print "A\t%s" % path - if not dryrun: - svn.add(path, local=True) - for path in toadd_br: - print "AB\t%s" % path - if not dryrun: - binrepo.upload_pending(path) - if commit: - commit(topdir) - -def commit(target=".", message=None, logfile=None): - topdir = getpkgtopdir(target) - sourcesdir = os.path.join(topdir, "SOURCES") - binrepo.commit(sourcesdir) #TODO make it optional - svn = SVN() - 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" - mirrored = mirror.using_on(url) - if mirrored: - newurl = mirror.switchto_parent(svn, url, target) - print "relocated to", newurl - # we can't use the svn object here because svn --non-interactive option - # hides VISUAL - opts = [] - if message is not None: - 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" - -def spec_sources(topdir): - specs = glob.glob(os.path.join(topdir, "SPECS/*.spec")) - spec_path = specs[0] # FIXME use svn info to ensure which one - ts = rpm.ts() - spec = ts.parseSpec(spec_path) - sources = [name for name, x, y in spec.sources()] - return sources - -def download_binaries(target, pkgdirurl=None, export=False, revision=None, - symlinks=True, check=False): - refurl = pkgdirurl - if refurl is None: - refurl = binrepo.svn_root(target) - if binrepo.enabled(refurl): - binrepo.download(target, pkgdirurl, export=export, - revision=revision, symlinks=symlinks, check=check) - -def update(target=None): - svn = SVN() - info = None - svn_target = None - br_target = None - if target: - svn_target = target - else: - top = getpkgtopdir() - svn_target = top - br_target = top - if svn_target: - svn.update(svn_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 - url = info["URL"] - download_binaries(br_target, url) - -def upload(paths): - for path in paths: - binrepo.upload(path) - -def binrepo_delete(paths, commit=False): - #TODO handle files tracked by svn - refurl = binrepo.svn_root(paths[0]) - if not binrepo.enabled(refurl): - raise Error, "binary repository is not enabled for %s" % refurl - added, deleted = binrepo.remove(paths) - if commit: - svn = SVN() - spath = binrepo.sources_path(paths[0]) - log = _sources_log(added, deleted) - svn.commit(spath, log=log) - -def switch(mirrorurl=None): - svn = SVN() - 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) - - # First, look for SPECS and SOURCES directories. - found = False - while path != "/": - if os.path.isdir(path): - specsdir = os.path.join(path, "SPECS") - sourcesdir = os.path.join(path, "SOURCES") - if os.path.isdir(specsdir) and os.path.isdir(sourcesdir): - found = True - break - path = os.path.dirname(path) - if not found: - raise Error, "SPECS and/or SOURCES directories not found" - - # Then, check if this is really a subversion directory. - if not os.path.isdir(os.path.join(path, ".svn")): - raise Error, "subversion directory not found" - - svn = SVN() - - # 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, "unexpected URL received from 'svn info'" - name = toks[-2] - url = "/".join(toks[:-1]) - - # Finally, guess revision. - max = -1 - files = [] - files.extend(glob.glob("%s/*" % specsdir)) - files.extend(glob.glob("%s/*" % sourcesdir)) - for file in files: - try: - info = svn.info2(file) - except Error: - # possibly not tracked - continue - if info is None: - continue - rawrev = info.get("Last Changed Rev") - if rawrev: - rev = int(rawrev) - if rev > max: - max = rev - if max == -1: - raise Error, "revision tag not found in 'svn info' output" - - if mirror.using_on(url): - url = mirror.switchto_parent_url(url) - - return name, url, max - -# vim:et:ts=4:sw=4 diff --git a/RepSys/simplerpm.py b/RepSys/simplerpm.py deleted file mode 100644 index d448c5f..0000000 --- a/RepSys/simplerpm.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/python -from RepSys.util import execcmd - -class SRPM: - def __init__(self, filename): - self.filename = filename - self._getinfo() - - def _getinfo(self): - cmdstr = "rpm -qp --qf '%%{name} %%{epoch} %%{release} %%{version}' %s" - status, output = execcmd(cmdstr % self.filename) - self.name, self.epoch, self.release, self.version = output.split() - if self.epoch == "(none)": - self.epoch = None - - def unpack(self, topdir): - execcmd("rpm -i --define '_topdir %s' %s" % (topdir, self.filename)) - -# vim:et:ts=4:sw=4 diff --git a/RepSys/svn.py b/RepSys/svn.py deleted file mode 100644 index 605ea8e..0000000 --- a/RepSys/svn.py +++ /dev/null @@ -1,430 +0,0 @@ -from RepSys import Error, SilentError, config -from RepSys.util import execcmd, get_auth -import sys -import os -import re -import time - -__all__ = ["SVN", "SVNLook", "SVNLogEntry"] - -class SVNLogEntry: - def __init__(self, revision, author, date): - self.revision = revision - self.author = author - self.date = date - self.changed = [] - self.lines = [] - - def __cmp__(self, other): - return cmp(self.date, other.date) - -class SVN: - def _execsvn(self, *args, **kwargs): - localcmds = ("add", "revert", "cleanup") - if not kwargs.get("show") and args[0] not in localcmds: - args = list(args) - args.append("--non-interactive") - else: - kwargs["geterr"] = True - kwargs["cleanerr"] = True - if kwargs.get("xml"): - args.append("--xml") - self._set_env() - svn_command = config.get("global", "svn-command", "svn") - cmdstr = svn_command + " " + " ".join(args) - try: - return execcmd(cmdstr, **kwargs) - except Error, e: - msg = None - if e.args: - if "Permission denied" in e.args[0]: - msg = ("It seems ssh-agent or ForwardAgent are not setup " - "or your username is wrong. See " - "http://wiki.mandriva.com/en/Development/Docs/Contributor_Tricks#SSH_configuration" - " for more information.") - elif "authorization failed" in e.args[0]: - msg = ("Note that repsys does not support any HTTP " - "authenticated access.") - if kwargs.get("show") and \ - not config.getbool("global", "verbose", 0): - # svn has already dumped error messages, we don't need to - # do it too - if msg: - sys.stderr.write("\n") - sys.stderr.write(msg) - sys.stderr.write("\n") - raise SilentError - elif msg: - raise Error, "%s\n%s" % (e, msg) - raise - - def _set_env(self): - wrapper = "repsys-ssh" - repsys = config.get("global", "repsys-cmd") - if repsys: - dir = os.path.dirname(repsys) - path = os.path.join(dir, wrapper) - if os.path.exists(path): - wrapper = path - defaults = {"SVN_SSH": wrapper} - os.environ.update(defaults) - raw = config.get("global", "svn-env") - if raw: - for line in raw.split("\n"): - env = line.strip() - if not env: - continue - try: - name, value = env.split("=", 1) - except ValueError: - sys.stderr.write("invalid svn environment line: %r\n" % env) - continue - os.environ[name] = value - - def _execsvn_success(self, *args, **kwargs): - status, output = self._execsvn(*args, **kwargs) - return status == 0 - - def _add_log(self, cmd_args, received_kwargs, optional=0): - if (not optional or - received_kwargs.has_key("log") or - received_kwargs.has_key("logfile")): - ret = received_kwargs.get("log") - if ret is not None: - cmd_args.append("-m '%s'" % ret) - ret = received_kwargs.get("logfile") - if ret is not None: - cmd_args.append("-F '%s'" % ret) - - def _add_revision(self, cmd_args, received_kwargs, optional=0): - if not optional or received_kwargs.has_key("rev"): - ret = received_kwargs.get("rev") - if isinstance(ret, basestring): - if not ret.startswith("{"): # if not a datespec - try: - ret = int(ret) - except ValueError: - raise Error, "invalid revision provided" - if ret: - cmd_args.append("-r '%s'" % ret) - - def add(self, path, **kwargs): - cmd = ["add", path + '@'] - return self._execsvn_success(noauth=1, *cmd, **kwargs) - - def copy(self, pathfrom, pathto, **kwargs): - cmd = ["copy", pathfrom + '@', pathto + '@'] - self._add_revision(cmd, kwargs, optional=1) - self._add_log(cmd, kwargs) - return self._execsvn_success(*cmd, **kwargs) - - def remove(self, path, force=0, **kwargs): - cmd = ["remove", path + '@'] - self._add_log(cmd, kwargs) - if force: - cmd.append("--force") - return self._execsvn_success(*cmd, **kwargs) - - def mkdir(self, path, **kwargs): - cmd = ["mkdir", path + '@'] - if kwargs.get("parents"): - cmd.append("--parents") - self._add_log(cmd, kwargs) - return self._execsvn_success(*cmd, **kwargs) - - def _execsvn_commit(self, *cmd, **kwargs): - status, output = self._execsvn(*cmd, **kwargs) - match = re.search("Committed revision (?P<rev>\\d+)\\.$", output) - if match: - rawrev = match.group("rev") - return int(rawrev) - - def commit(self, path, **kwargs): - cmd = ["commit", path + '@'] - if kwargs.get("nonrecursive"): - cmd.append("-N") - self._add_log(cmd, kwargs) - return self._execsvn_commit(*cmd, **kwargs) - - def import_(self, path, url, **kwargs): - cmd = ["import", "'%s'" % path, "'%s'" % url] - self._add_log(cmd, kwargs) - return self._execsvn_commit(*cmd, **kwargs) - - def export(self, url, targetpath, **kwargs): - cmd = ["export", "'%s'" % url, targetpath] - self._add_revision(cmd, kwargs, optional=1) - return self._execsvn_success(*cmd, **kwargs) - - def checkout(self, url, targetpath, **kwargs): - cmd = ["checkout", "'%s'" % url, targetpath] - self._add_revision(cmd, kwargs, optional=1) - return self._execsvn_success(*cmd, **kwargs) - - def propget(self, propname, targets, **kwargs): - cmd = ["propget", propname, targets] - if kwargs.get("revprop"): - cmd.append("--revprop") - self._add_revision(cmd, kwargs) - status, output = self._execsvn(local=True, *cmd, **kwargs) - return output - - def propset(self, propname, value, targets, **kwargs): - cmd = ["propset", propname, "'%s'" % value, targets] - return self._execsvn_success(*cmd, **kwargs) - - def propedit(self, propname, target, **kwargs): - cmd = ["propedit", propname, target] - if kwargs.get("rev"): - cmd.append("--revprop") - self._add_revision(cmd, kwargs) - return self._execsvn_success(local=True, show=True, *cmd, **kwargs) - - def revision(self, path, **kwargs): - cmd = ["info", path + '@'] - status, output = self._execsvn(local=True, *cmd, **kwargs) - if status == 0: - for line in output.splitlines(): - if line.startswith("Last Changed Rev: "): - return int(line.split()[3]) - return None - - def info(self, path, **kwargs): - cmd = ["info", path + '@'] - status, output = self._execsvn(local=True, noerror=True, *cmd, **kwargs) - if "Not a versioned resource" not in output: - return output.splitlines() - return None - - def info2(self, *args, **kwargs): - lines = self.info(*args, **kwargs) - if lines is None: - return None - pairs = [[w.strip() for w in line.split(":", 1)] for line in lines] - info = dict(pairs) - return info - - def ls(self, path, **kwargs): - cmd = ["ls", path + '@'] - status, output = self._execsvn(*cmd, **kwargs) - if status == 0: - return output.split() - return None - - def status(self, path, **kwargs): - cmd = ["status", path + '@'] - if kwargs.get("verbose"): - 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()] - return None - - def cleanup(self, path, **kwargs): - cmd = ["cleanup", path + '@'] - return self._execsvn_success(*cmd, **kwargs) - - def revert(self, path, **kwargs): - cmd = ["revert", path + '@'] - status, output = self._execsvn(*cmd, **kwargs) - if status == 0: - return [x.split() for x in output.split()] - return None - - def switch(self, url, oldurl=None, path=None, relocate=False, **kwargs): - cmd = ["switch"] - if relocate: - if oldurl is None: - raise Error, "You must supply the old URL when "\ - "relocating working copies" - cmd.append("--relocate") - cmd.append(oldurl) - cmd.append(url) - if path is not None: - cmd.append(path) - return self._execsvn_success(*cmd, **kwargs) - - def update(self, path, **kwargs): - cmd = ["update", path + '@'] - self._add_revision(cmd, kwargs, optional=1) - status, output = self._execsvn(*cmd, **kwargs) - if status == 0: - return [x.split() for x in output.split()] - return None - - def merge(self, url1, url2=None, rev1=None, rev2=None, path=None, - **kwargs): - cmd = ["merge"] - if rev1 and rev2 and not url2: - cmd.append("-r") - cmd.append("%s:%s" % (rev1, rev2)) - cmd.append(url1) - else: - if not url2: - raise ValueError, \ - "url2 needed if two revisions are not provided" - if rev1: - cmd.append("%s@%s" % (url1, rev1)) - else: - cmd.append(url1) - if rev2: - cmd.append("%s@%s" % (url2, rev2)) - else: - cmd.append(url2) - if path: - cmd.append(path) - status, output = self._execsvn(*cmd, **kwargs) - if status == 0: - return [x.split() for x in output.split()] - return None - - def diff(self, pathurl1, pathurl2=None, **kwargs): - cmd = ["diff", pathurl1] - self._add_revision(cmd, kwargs, optional=1) - if pathurl2: - cmd.append(pathurl2) - status, output = self._execsvn(*cmd, **kwargs) - if status == 0: - return output - return None - - def cat(self, url, **kwargs): - cmd = ["cat", url] - self._add_revision(cmd, kwargs, optional=1) - status, output = self._execsvn(*cmd, **kwargs) - if status == 0: - return output - return None - - def log(self, url, start=None, end=0, limit=None, **kwargs): - cmd = ["log", "-v", url] - if start is not None or end != 0: - if start is not None and type(start) is not type(0): - try: - start = int(start) - except (ValueError, TypeError): - raise Error, "invalid log start revision provided" - if type(end) is not type(0): - try: - end = int(end) - except (ValueError, TypeError): - raise Error, "invalid log end revision provided" - start = start or "HEAD" - cmd.append("-r %s:%s" % (start, end)) - if limit is not None: - try: - limit = int(limit) - except (ValueError, TypeError): - raise Error, "invalid limit number provided" - cmd.append("--limit %d" % limit) - status, output = self._execsvn(*cmd, **kwargs) - if status != 0: - return None - - revheader = re.compile("^r(?P<revision>[0-9]+) \| (?P<author>[^\|]+) \| (?P<date>[^\|]+) \| (?P<lines>[0-9]+) (?:line|lines)$") - changedpat = re.compile(r"^\s+(?P<action>[^\s]+) (?P<path>[^\s]+)(?: \([^\s]+ (?P<from_path>[^:]+)(?:\:(?P<from_rev>[0-9]+))?\))?$") - logseparator = "-"*72 - linesleft = 0 - entry = None - log = [] - appendchanged = 0 - changedheader = 0 - for line in output.splitlines(): - line = line.rstrip() - if changedheader: - appendchanged = 1 - changedheader = 0 - elif appendchanged: - if not line: - appendchanged = 0 - continue - m = changedpat.match(line) - if m: - changed = m.groupdict().copy() - from_rev = changed.get("from_rev") - if from_rev is not None: - try: - changed["from_rev"] = int(from_rev) - except (ValueError, TypeError): - raise Error, "invalid revision number in svn log" - entry.changed.append(changed) - elif linesleft == 0: - if line != logseparator: - m = revheader.match(line) - if m: - linesleft = int(m.group("lines")) - timestr = " ".join(m.group("date").split()[:2]) - timetuple = time.strptime(timestr, - "%Y-%m-%d %H:%M:%S") - entry = SVNLogEntry(int(m.group("revision")), - m.group("author"), timetuple) - log.append(entry) - changedheader = 1 - else: - entry.lines.append(line) - linesleft -= 1 - log.sort() - log.reverse() - return log - -class SVNLook: - def __init__(self, repospath, txn=None, rev=None): - self.repospath = repospath - self.txn = txn - self.rev = rev - - def _execsvnlook(self, cmd, *args, **kwargs): - execcmd_args = ["svnlook", cmd, self.repospath] - self._add_txnrev(execcmd_args, kwargs) - execcmd_args += args - execcmd_kwargs = {} - keywords = ["show", "noerror"] - for key in keywords: - if kwargs.has_key(key): - execcmd_kwargs[key] = kwargs[key] - return execcmd(*execcmd_args, **execcmd_kwargs) - - def _add_txnrev(self, cmd_args, received_kwargs): - if received_kwargs.has_key("txn"): - txn = received_kwargs.get("txn") - if txn is not None: - cmd_args += ["-t", txn] - elif self.txn is not None: - cmd_args += ["-t", self.txn] - if received_kwargs.has_key("rev"): - rev = received_kwargs.get("rev") - if rev is not None: - cmd_args += ["-r", rev] - elif self.rev is not None: - cmd_args += ["-r", self.rev] - - def changed(self, **kwargs): - status, output = self._execsvnlook("changed", **kwargs) - if status != 0: - return None - changes = [] - for line in output.splitlines(): - line = line.rstrip() - if not line: - continue - entry = [None, None, None] - changedata, changeprop, path = None, None, None - if line[0] != "_": - changedata = line[0] - if line[1] != " ": - changeprop = line[1] - path = line[4:] - changes.append((changedata, changeprop, path)) - return changes - - def author(self, **kwargs): - status, output = self._execsvnlook("author", **kwargs) - if status != 0: - return None - return output.strip() - -# vim:et:ts=4:sw=4 diff --git a/RepSys/util.py b/RepSys/util.py deleted file mode 100644 index 84840b9..0000000 --- a/RepSys/util.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/python - -from RepSys import Error, config - -import subprocess -import getpass -import sys -import os -import re -import logging -from cStringIO import StringIO -#import commands - -log = logging.getLogger("repsys") - -# Our own version of commands' getstatusoutput(). We have a commands -# module directory, so we can't import Python's standard module -def commands_getstatusoutput(cmd): - """Return (status, output) of executing cmd in a shell.""" - import os - pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r') - text = pipe.read() - sts = pipe.close() - if sts is None: sts = 0 - if text[-1:] == '\n': text = text[:-1] - return sts, text - -def execcmd(*cmd, **kwargs): - cmdstr = " ".join(cmd) - if kwargs.get("show"): - if kwargs.get("geterr"): - err = StringIO() - pipe = subprocess.Popen(cmdstr, shell=True, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - of = pipe.stdout.fileno() - ef = pipe.stderr.fileno() - while True: - odata = os.read(of, 8192) - sys.stdout.write(odata) - edata = os.read(ef, 8192) - err.write(edata) - sys.stderr.write(edata) - status = pipe.poll() - if status is not None and not (odata and edata): - break - output = err.getvalue() - else: - status = os.system(cmdstr) - output = "" - else: - status, output = commands_getstatusoutput( - "LANG=C LANGUAGE=C LC_ALL=C "+cmdstr) - verbose = config.getbool("global", "verbose", 0) - if status != 0 and not kwargs.get("noerror"): - if kwargs.get("cleanerr") and not verbose: - raise Error, output - else: - raise Error, "command failed: %s\n%s\n" % (cmdstr, output) - if verbose: - print cmdstr - sys.stdout.write(output) - return status, output - -def get_auth(username=None, password=None): - set_username = 1 - set_password = 1 - if not username: - username = config.get("auth", "username") - if not username: - username = raw_input("username: ") - else: - set_username = 0 - if not password: - password = config.get("auth", "password") - if not password: - password = getpass.getpass("password: ") - else: - set_password = 0 - if set_username: - config.set("auth", "username", username) - if set_password: - config.set("auth", "password", password) - return username, password - - -def mapurl(url): - """Maps a url following the regexp provided by the option url-map in - repsys.conf - """ - urlmap = config.get("global", "url-map") - newurl = url - if urlmap: - try: - expr_, replace = urlmap.split()[:2] - except ValueError: - log.error("invalid url-map: %s", urlmap) - else: - try: - newurl = re.sub(expr_, replace, url) - except re.error, errmsg: - log.error("error in URL mapping regexp: %s", errmsg) - return newurl - - -def get_helper(name): - """Tries to find the path of a helper script - - It first looks if the helper has been explicitly defined in - configuration, if not, falls back to the default helper path, which can - also be defined in configuration file(s). - """ - helperdir = config.get("helper", "prefix", "/usr/share/repsys") - hpath = config.get("helper", name, None) or \ - os.path.join(helperdir, name) - if not os.path.isfile(hpath): - log.warn("providing unexistent helper: %s", hpath) - return hpath - -def rellink(src, dst): - """Creates relative symlinks - - It will find the common ancestor and append to the src path. - """ - asrc = os.path.abspath(src) - adst = os.path.abspath(dst) - csrc = asrc.split(os.path.sep) - cdst = adst.split(os.path.sep) - dstname = cdst.pop() - i = 0 - l = min(len(csrc), len(cdst)) - while i < l: - if csrc[i] != cdst[i]: - break - i += 1 - dstextra = len(cdst[i:]) - steps = [os.path.pardir] * dstextra - steps.extend(csrc[i:]) - return os.path.sep.join(steps) - - -# vim:et:ts=4:sw=4 |