commit: 018e8a127455b18593d8c07a28df3eef665a7332 Author: Brian Dolbec <dolsen <AT> gentoo <DOT> org> AuthorDate: Wed Dec 30 23:24:22 2015 +0000 Commit: Brian Dolbec <dolsen <AT> gentoo <DOT> org> CommitDate: Wed Dec 30 23:24:22 2015 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=018e8a12
initial repoman stage2 vcs plugin system started Signed-off-by: Brian Dolbec <dolsen <AT> gentoo.org> pym/repoman/actions.py | 5 +- pym/repoman/main.py | 9 +- pym/repoman/modules/commit/repochecks.py | 5 +- pym/repoman/scanner.py | 9 +- pym/repoman/vcs/__init__.py | 14 +++ pym/repoman/vcs/modules/__init__.py | 1 + pym/repoman/vcs/modules/bzr/__init__.py | 23 +++++ pym/repoman/vcs/modules/bzr/bzrstatus.py | 36 ++++++++ pym/repoman/vcs/modules/cvs/__init__.py | 23 +++++ pym/repoman/vcs/modules/cvs/cvsstatus.py | 102 +++++++++++++++++++++ pym/repoman/vcs/modules/git/__init__.py | 23 +++++ pym/repoman/vcs/modules/git/gitstatus.py | 46 ++++++++++ pym/repoman/vcs/modules/hg/__init__.py | 23 +++++ pym/repoman/vcs/modules/hg/hgstatus.py | 30 ++++++ pym/repoman/vcs/modules/svn/__init__.py | 23 +++++ pym/repoman/vcs/modules/svn/svnstatus.py | 121 ++++++++++++++++++++++++ pym/repoman/vcs/settings.py | 74 +++++++++++++++ pym/repoman/vcs/vcs.py | 152 ------------------------------- pym/repoman/vcs/vcsstatus.py | 106 +-------------------- 19 files changed, 556 insertions(+), 269 deletions(-) diff --git a/pym/repoman/actions.py b/pym/repoman/actions.py index f461703..a17c205 100644 --- a/pym/repoman/actions.py +++ b/pym/repoman/actions.py @@ -30,7 +30,7 @@ from repoman._subprocess import repoman_popen, repoman_getstatusoutput from repoman.errors import err from repoman.gpg import gpgsign, need_signature from repoman import utilities -from repoman.vcs.vcs import git_supports_gpg_sign, vcs_files_to_cps +from repoman.vcs.vcs import vcs_files_to_cps bad = create_color_func("BAD") @@ -662,8 +662,7 @@ class Actions(object): else: retval = spawn(commit_cmd, env=self.repo_settings.commit_env) if retval != os.EX_OK: - if self.repo_settings.repo_config.sign_commit and self.vcs_settings.vcs == 'git' and \ - not git_supports_gpg_sign(): + if self.repo_settings.repo_config.sign_commit and not self.vcs_settings.status.supports_gpg_sign(): # Inform user that newer git is needed (bug #403323). logging.error( "Git >=1.7.9 is required for signed commits!") diff --git a/pym/repoman/main.py b/pym/repoman/main.py index 00d48e7..c41e943 100755 --- a/pym/repoman/main.py +++ b/pym/repoman/main.py @@ -33,7 +33,7 @@ from repoman.qa_data import ( from repoman.repos import RepoSettings from repoman.scanner import Scanner from repoman import utilities -from repoman.vcs.vcs import VCSSettings +from repoman.vcs.settings import VCSSettings if sys.hexversion >= 0x3000000: basestring = str @@ -101,7 +101,7 @@ def repoman_main(argv): # Perform the main checks scanner = Scanner(repo_settings, myreporoot, config_root, options, vcs_settings, mydir, env) - qatracker, can_force = scanner.scan_pkgs(can_force) + can_force = scanner.scan_pkgs(can_force) commitmessage = None @@ -122,7 +122,7 @@ def repoman_main(argv): sys.exit(result['fail']) for x in qacats: - if x not in qatracker.fails: + if x not in vcs_settings.qatracker.fails: continue result['warn'] = 1 if x not in qawarnings: @@ -153,7 +153,8 @@ def repoman_main(argv): format_output = format_outputs.get( options.output_style, format_outputs['default']) - format_output(f, qatracker.fails, result['full'], result['fail'], options, qawarnings) + format_output(f, vcs_settings.qatracker.fails, result['full'], + result['fail'], options, qawarnings) style_file.flush() del console_writer, f, style_file diff --git a/pym/repoman/modules/commit/repochecks.py b/pym/repoman/modules/commit/repochecks.py index 163466d..ff7f604 100644 --- a/pym/repoman/modules/commit/repochecks.py +++ b/pym/repoman/modules/commit/repochecks.py @@ -5,7 +5,6 @@ from __future__ import print_function, unicode_literals from portage.output import red from repoman.errors import err -from repoman.vcs.vcs import detect_vcs_conflicts def commit_check(repolevel, reposplit): @@ -32,4 +31,6 @@ def commit_check(repolevel, reposplit): def conflict_check(vcs_settings, options): if vcs_settings.vcs: - detect_vcs_conflicts(options, vcs_settings.vcs) + status = vcssettings.get_status(None, None) + conflicts = status.detect_conflicts(options) + diff --git a/pym/repoman/scanner.py b/pym/repoman/scanner.py index d1c10d7..eb1896f 100644 --- a/pym/repoman/scanner.py +++ b/pym/repoman/scanner.py @@ -40,7 +40,6 @@ from repoman.ebuild import Ebuild from repoman.modules.commit import repochecks from repoman.profile import check_profiles, dev_profile_keywords, setup_profile from repoman.qa_data import missingvars, suspect_virtual, suspect_rdepend -from repoman.qa_tracker import QATracker from repoman.repos import repo_metadata from repoman.scan import Changes, scan from repoman.vcs.vcsstatus import VCSStatus @@ -141,7 +140,7 @@ class Scanner(object): self.dev_keywords = dev_profile_keywords(self.profiles) - self.qatracker = QATracker() + self.qatracker = self.vcs_settings.qatracker if self.options.echangelog is None and self.repo_settings.repo_config.update_changelog: self.options.echangelog = 'y' @@ -209,7 +208,7 @@ class Scanner(object): self.is_ebuild = IsEbuild(self.repo_settings.repoman_settings, self.repo_settings, self.portdb, self.qatracker) self.filescheck = FileChecks( self.qatracker, self.repo_settings.repoman_settings, self.repo_settings, self.portdb, self.vcs_settings) - self.status_check = VCSStatus(self.vcs_settings, self.qatracker) + self.status_check = VCSStatus(self.vcs_settings) self.fetchcheck = FetchChecks( self.qatracker, self.repo_settings, self.portdb, self.vcs_settings) self.pkgmeta = PkgMetadata(self.options, self.qatracker, @@ -270,7 +269,7 @@ class Scanner(object): checkdir, checkdirlist, checkdir_relative, self.changed.changed, self.changed.new) self.status_check.check(self.check['ebuild_notadded'], checkdir, checkdir_relative, xpkg) - self.eadded.extend(self.status_check.eadded) + self.eadded.extend(self.status_check.vcs_settings.eadded) self.fetchcheck.check( xpkg, checkdir, checkdir_relative, self.changed.changed, self.changed.new) @@ -285,7 +284,7 @@ class Scanner(object): self.changelog_modified = changelog_path in self.changed.changelogs self._scan_ebuilds(ebuildlist, xpkg, catdir, pkgdir) - return self.qatracker, can_force + return can_force def _scan_ebuilds(self, ebuildlist, xpkg, catdir, pkgdir): diff --git a/pym/repoman/vcs/__init__.py b/pym/repoman/vcs/__init__.py index e69de29..d7f6af9 100644 --- a/pym/repoman/vcs/__init__.py +++ b/pym/repoman/vcs/__init__.py @@ -0,0 +1,14 @@ + +import os +from portage.module import Modules + +path = os.path.join(os.path.dirname(__file__), "modules") +# initial development debug info +#print("module path:", path) + +module_controller = Modules(path=path, namepath="repoman.vcs.modules") + +# initial development debug info +#print(module_controller.module_names) +module_names = module_controller.module_names[:] + diff --git a/pym/repoman/vcs/modules/__init__.py b/pym/repoman/vcs/modules/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/pym/repoman/vcs/modules/__init__.py @@ -0,0 +1 @@ + diff --git a/pym/repoman/vcs/modules/bzr/__init__.py b/pym/repoman/vcs/modules/bzr/__init__.py new file mode 100644 index 0000000..6f3aaa2 --- /dev/null +++ b/pym/repoman/vcs/modules/bzr/__init__.py @@ -0,0 +1,23 @@ +# Copyright 2014-2015 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +doc = """BZR plug-in module for portage. +Performs variaous Bazaar actions and checks on repositories.""" +__doc__ = doc[:] + + +module_spec = { + 'name': 'bzr', + 'description': doc, + 'provides':{ + 'bzr-module': { + 'name': "bzrstatus", + 'class': "Status", + 'description': doc, + 'functions': ['check', 'supports_gpg_sign', 'detect_conflicts'], + 'func_desc': { + }, + 'vcs_preserves_mtime': True, + } + } +} diff --git a/pym/repoman/vcs/modules/bzr/bzrstatus.py b/pym/repoman/vcs/modules/bzr/bzrstatus.py new file mode 100644 index 0000000..5839272 --- /dev/null +++ b/pym/repoman/vcs/modules/bzr/bzrstatus.py @@ -0,0 +1,36 @@ + +from repoman._portage import portage +from portage import os +from repoman._subprocess import repoman_popen + + +class Status(object): + + def __init__(self, qatracker, eadded): + self.qatracker = qatracker + self.eadded = eadded + + def check_bzr(self, checkdir, checkdir_relative, xpkg): + try: + myf = repoman_popen( + "bzr ls -v --kind=file " + + portage._shell_quote(checkdir)) + myl = myf.readlines() + myf.close() + except IOError: + raise + for l in myl: + if l[1:2] == "?": + continue + l = l.split()[-1] + if l[-7:] == ".ebuild": + self.eadded.append(os.path.basename(l[:-7])) + return True + + @staticmethod + def detect_conflicts(options): + return False + + @staticmethod + def supports_gpg_sign(): + return False diff --git a/pym/repoman/vcs/modules/cvs/__init__.py b/pym/repoman/vcs/modules/cvs/__init__.py new file mode 100644 index 0000000..0cd4bc7 --- /dev/null +++ b/pym/repoman/vcs/modules/cvs/__init__.py @@ -0,0 +1,23 @@ +# Copyright 2014-2015 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +doc = """CVS plug-in module for portage. +Performs variaous CVS actions and checks on repositories.""" +__doc__ = doc[:] + + +module_spec = { + 'name': 'cvs', + 'description': doc, + 'provides':{ + 'git-module': { + 'name': "cvsstatus", + 'class': "Status", + 'description': doc, + 'functions': ['check', 'supports_gpg_sign', 'detect_conflicts'], + 'func_desc': { + }, + 'vcs_preserves_mtime': True, + } + } +} diff --git a/pym/repoman/vcs/modules/cvs/cvsstatus.py b/pym/repoman/vcs/modules/cvs/cvsstatus.py new file mode 100644 index 0000000..726bd65 --- /dev/null +++ b/pym/repoman/vcs/modules/cvs/cvsstatus.py @@ -0,0 +1,102 @@ + +import logging +import subprocess +import sys + +from repoman._portage import portage +from portage import os +from portage.const import BASH_BINARY +from portage.output import red, green +from portage import _unicode_encode, _unicode_decode + + +class Status(object): + + def __init__(self, qatracker, eadded): + self.qatracker = qatracker + self.eadded = eadded + + def check_cvs(self, checkdir, checkdir_relative, xpkg): + try: + myf = open(checkdir + "/CVS/Entries", "r") + myl = myf.readlines() + myf.close() + except IOError: + self.qatracker.add_error( + "CVS/Entries.IO_error", checkdir + "/CVS/Entries") + return True + for l in myl: + if l[0] != "/": + continue + splitl = l[1:].split("/") + if not len(splitl): + continue + if splitl[0][-7:] == ".ebuild": + self.eadded.append(splitl[0][:-7]) + return True + + @staticmethod + def detect_conflicts(options): + """Determine if the checkout has cvs conflicts. + + TODO(antarus): Also this should probably not call sys.exit() as + repoman is run on >1 packages and one failure should not cause + subsequent packages to fail. + + Returns: + None (calls sys.exit on fatal problems) + """ + + cmd = ("cvs -n up 2>/dev/null | " + "egrep '^[^\?] .*' | " + "egrep -v '^. .*/digest-[^/]+|^cvs server: .* -- ignored$'") + msg = ("Performing a %s with a little magic grep to check for updates." + % green("cvs -n up")) + + logging.info(msg) + # Use Popen instead of getstatusoutput(), in order to avoid + # unicode handling problems (see bug #310789). + args = [BASH_BINARY, "-c", cmd] + args = [_unicode_encode(x) for x in args] + proc = subprocess.Popen( + args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + out = _unicode_decode(proc.communicate()[0]) + proc.wait() + mylines = out.splitlines() + myupdates = [] + for line in mylines: + if not line: + continue + + # [ ] Unmodified (SVN) [U] Updates [P] Patches + # [M] Modified [A] Added [R] Removed / Replaced + # [D] Deleted + if line[0] not in " UPMARD": + # Stray Manifest is fine, we will readd it anyway. + if line[0] == '?' and line[1:].lstrip() == 'Manifest': + continue + logging.error(red( + "!!! Please fix the following issues reported " + "from cvs: %s" % green("(U,P,M,A,R,D are ok)"))) + logging.error(red( + "!!! Note: This is a pretend/no-modify pass...")) + logging.error(out) + sys.exit(1) + elif line[0] in "UP": + myupdates.append(line[2:]) + + if myupdates: + logging.info(green("Fetching trivial updates...")) + if options.pretend: + logging.info("(cvs update " + " ".join(myupdates) + ")") + retval = os.EX_OK + else: + retval = os.system("cvs update " + " ".join(myupdates)) + if retval != os.EX_OK: + logging.fatal("!!! cvs exited with an error. Terminating.") + sys.exit(retval) + return False + + @staticmethod + def supports_gpg_sign(): + return False diff --git a/pym/repoman/vcs/modules/git/__init__.py b/pym/repoman/vcs/modules/git/__init__.py new file mode 100644 index 0000000..d8a2eea --- /dev/null +++ b/pym/repoman/vcs/modules/git/__init__.py @@ -0,0 +1,23 @@ +# Copyright 2014-2015 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +doc = """Git plug-in module for portage. +Performs variaous git actions and checks on repositories.""" +__doc__ = doc[:] + + +module_spec = { + 'name': 'git', + 'description': doc, + 'provides':{ + 'git-module': { + 'name': "gitstatus", + 'class': "Status", + 'description': doc, + 'functions': ['check', 'supports_gpg_sign', 'detect_conflicts'], + 'func_desc': { + }, + 'vcs_preserves_mtime': False, + } + } +} diff --git a/pym/repoman/vcs/modules/git/gitstatus.py b/pym/repoman/vcs/modules/git/gitstatus.py new file mode 100644 index 0000000..affe21c --- /dev/null +++ b/pym/repoman/vcs/modules/git/gitstatus.py @@ -0,0 +1,46 @@ + +import re + +from repoman._portage import portage +from portage import os +from repoman._subprocess import repoman_popen, repoman_getstatusoutput + + +class Status(object): + + def __init__(self, qatracker, eadded): + self.qatracker = qatracker + self.eadded = eadded + + def check(self, checkdir, checkdir_relative, xpkg): + myf = repoman_popen( + "git ls-files --others %s" % + (portage._shell_quote(checkdir_relative),)) + for l in myf: + if l[:-1][-7:] == ".ebuild": + self.qatracker.add_error( + "ebuild.notadded", + os.path.join(xpkg, os.path.basename(l[:-1]))) + myf.close() + return True + + @staticmethod + def supports_gpg_sign(): + status, cmd_output = \ + repoman_getstatusoutput("git --version") + cmd_output = cmd_output.split() + if cmd_output: + version = re.match(r'^(\d+)\.(\d+)\.(\d+)', cmd_output[-1]) + if version is not None: + version = [int(x) for x in version.groups()] + if version[0] > 1 or \ + (version[0] == 1 and version[1] > 7) or \ + (version[0] == 1 and version[1] == 7 and version[2] >= 9): + return True + return False + + @staticmethod + def detect_conflicts(options): + return False + + diff --git a/pym/repoman/vcs/modules/hg/__init__.py b/pym/repoman/vcs/modules/hg/__init__.py new file mode 100644 index 0000000..68cccf2 --- /dev/null +++ b/pym/repoman/vcs/modules/hg/__init__.py @@ -0,0 +1,23 @@ +# Copyright 2014-2015 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +doc = """HG plug-in module for portage. +Performs variaous mercurial actions and checks on repositories.""" +__doc__ = doc[:] + + +module_spec = { + 'name': 'hg', + 'description': doc, + 'provides':{ + 'hg-module': { + 'name': "hgstatus", + 'class': "Status", + 'description': doc, + 'functions': ['check', 'supports_gpg_sign', 'detect_conflicts'], + 'func_desc': { + }, + 'vcs_preserves_mtime': False, + } + } +} diff --git a/pym/repoman/vcs/modules/hg/hgstatus.py b/pym/repoman/vcs/modules/hg/hgstatus.py new file mode 100644 index 0000000..a0a0d9e --- /dev/null +++ b/pym/repoman/vcs/modules/hg/hgstatus.py @@ -0,0 +1,30 @@ + +from repoman._portage import portage +from portage import os +from repoman._subprocess import repoman_popen + +class Status(object): + + def __init__(self, qatracker, eadded): + self.qatracker = qatracker + self.eadded = eadded + + def check_hg(self, checkdir, checkdir_relative, xpkg): + myf = repoman_popen( + "hg status --no-status --unknown %s" % + (portage._shell_quote(checkdir_relative),)) + for l in myf: + if l[:-1][-7:] == ".ebuild": + self.qatracker.add_error( + "ebuild.notadded", + os.path.join(xpkg, os.path.basename(l[:-1]))) + myf.close() + return True + + @staticmethod + def detect_conflicts(options): + return False + + @staticmethod + def supports_gpg_sign(): + return False diff --git a/pym/repoman/vcs/modules/svn/__init__.py b/pym/repoman/vcs/modules/svn/__init__.py new file mode 100644 index 0000000..2e2811d --- /dev/null +++ b/pym/repoman/vcs/modules/svn/__init__.py @@ -0,0 +1,23 @@ +# Copyright 2014-2015 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +doc = """SVN plug-in module for portage. +Performs variaous subversion actions and checks on repositories.""" +__doc__ = doc[:] + + +module_spec = { + 'name': 'svn', + 'description': doc, + 'provides':{ + 'svn-module': { + 'name': "svnstatus", + 'class': "Status", + 'description': doc, + 'functions': ['check', 'supports_gpg_sign', 'detect_conflicts'], + 'func_desc': { + }, + 'vcs_preserves_mtime': False, + } + } +} diff --git a/pym/repoman/vcs/modules/svn/svnstatus.py b/pym/repoman/vcs/modules/svn/svnstatus.py new file mode 100644 index 0000000..4a70455 --- /dev/null +++ b/pym/repoman/vcs/modules/svn/svnstatus.py @@ -0,0 +1,121 @@ + +import logging +import subprocess +import sys + +from repoman._portage import portage +from portage import os +from portage.const import BASH_BINARY +from portage.output import red, green +from portage import _unicode_encode, _unicode_decode + +from repoman._subprocess import repoman_popen + + +class Status(object): + + def __init__(self, qatracker, eadded): + self.qatracker = qatracker + self.eadded = eadded + + def check_svn(self, checkdir, checkdir_relative, xpkg): + try: + myf = repoman_popen( + "svn status --depth=files --verbose " + + portage._shell_quote(checkdir)) + myl = myf.readlines() + myf.close() + except IOError: + raise + for l in myl: + if l[:1] == "?": + continue + if l[:7] == ' >': + # tree conflict, new in subversion 1.6 + continue + l = l.split()[-1] + if l[-7:] == ".ebuild": + self.eadded.append(os.path.basename(l[:-7])) + try: + myf = repoman_popen( + "svn status " + + portage._shell_quote(checkdir)) + myl = myf.readlines() + myf.close() + except IOError: + raise + for l in myl: + if l[0] == "A": + l = l.rstrip().split(' ')[-1] + if l[-7:] == ".ebuild": + self.eadded.append(os.path.basename(l[:-7])) + return True + + @staticmethod + def detect_conflicts(options): + """Determine if the checkout has problems like cvs conflicts. + + If you want more vcs support here just keep adding if blocks... + This could be better. + + TODO(antarus): Also this should probably not call sys.exit() as + repoman is run on >1 packages and one failure should not cause + subsequent packages to fail. + + Args: + vcs - A string identifying the version control system in use + Returns: + None (calls sys.exit on fatal problems) + """ + + cmd = "svn status -u 2>&1 | egrep -v '^. +.*/digest-[^/]+' | head -n-1" + msg = ("Performing a %s with a little magic grep to check for updates." + % green("svn status -u")) + + logging.info(msg) + # Use Popen instead of getstatusoutput(), in order to avoid + # unicode handling problems (see bug #310789). + args = [BASH_BINARY, "-c", cmd] + args = [_unicode_encode(x) for x in args] + proc = subprocess.Popen( + args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + out = _unicode_decode(proc.communicate()[0]) + proc.wait() + mylines = out.splitlines() + myupdates = [] + for line in mylines: + if not line: + continue + + # [ ] Unmodified (SVN) [U] Updates [P] Patches + # [M] Modified [A] Added [R] Removed / Replaced + # [D] Deleted + if line[0] not in " UPMARD": + # Stray Manifest is fine, we will readd it anyway. + if line[0] == '?' and line[1:].lstrip() == 'Manifest': + continue + logging.error(red( + "!!! Please fix the following issues reported " + "from cvs: %s" % green("(U,P,M,A,R,D are ok)"))) + logging.error(red( + "!!! Note: This is a pretend/no-modify pass...")) + logging.error(out) + sys.exit(1) + elif line[8] == '*': + myupdates.append(line[9:].lstrip(" 1234567890")) + + if myupdates: + logging.info(green("Fetching trivial updates...")) + if options.pretend: + logging.info("(svn update " + " ".join(myupdates) + ")") + retval = os.EX_OK + else: + retval = os.system("svn update " + " ".join(myupdates)) + if retval != os.EX_OK: + logging.fatal("!!! svn exited with an error. Terminating.") + sys.exit(retval) + return False + + @staticmethod + def supports_gpg_sign(): + return False diff --git a/pym/repoman/vcs/settings.py b/pym/repoman/vcs/settings.py new file mode 100644 index 0000000..a62427c --- /dev/null +++ b/pym/repoman/vcs/settings.py @@ -0,0 +1,74 @@ + +import logging +import sys + +from repoman._portage import portage +from portage.output import red +from repoman.vcs import module_controller, module_names +from repoman.vcs.vcs import FindVCS +from repoman.qa_tracker import QATracker + + +class VCSSettings(object): + '''Holds various VCS settings''' + + def __init__(self, options=None, repoman_settings=None): + if options.vcs: + if options.vcs in module_names: + self.vcs = options.vcs + else: + self.vcs = None + else: + vcses = FindVCS() + if len(vcses) > 1: + print(red( + '*** Ambiguous workdir -- more than one VCS found' + ' at the same depth: %s.' % ', '.join(vcses))) + print(red( + '*** Please either clean up your workdir' + ' or specify --vcs option.')) + sys.exit(1) + elif vcses: + self.vcs = vcses[0] + else: + self.vcs = None + + if options.if_modified == "y" and self.vcs is None: + logging.info( + "Not in a version controlled repository; " + "disabling --if-modified.") + options.if_modified = "n" + + self._status = None + self.module_controller = module_controller + self.module_names = module_names + + # Disable copyright/mtime check if vcs does not preserve mtime (bug #324075). + self.vcs_preserves_mtime = module_controller.modules["%sstatus" % self.vcs]['vcs_preserves_mtime'] + + self.vcs_local_opts = repoman_settings.get( + "REPOMAN_VCS_LOCAL_OPTS", "").split() + self.vcs_global_opts = repoman_settings.get( + "REPOMAN_VCS_GLOBAL_OPTS") + if self.vcs_global_opts is None: + if self.vcs in ('cvs', 'svn'): + self.vcs_global_opts = "-q" + else: + self.vcs_global_opts = "" + self.vcs_global_opts = self.vcs_global_opts.split() + + if options.mode == 'commit' and not options.pretend and not self.vcs: + logging.info( + "Not in a version controlled repository; " + "enabling pretend mode.") + options.pretend = True + self.qatracker = QATracker() + self.eadded = [] + + @property + def status(self): + if not self._status: + status = self.module_controller.get_class('%sstatus' % self.vcs) + self._status = status(self.qatracker, self.eadded) + return self._status + diff --git a/pym/repoman/vcs/vcs.py b/pym/repoman/vcs/vcs.py index a463335..8ec7270 100644 --- a/pym/repoman/vcs/vcs.py +++ b/pym/repoman/vcs/vcs.py @@ -4,17 +4,9 @@ from __future__ import print_function, unicode_literals import collections import logging -import re -import subprocess -import sys from itertools import chain from portage import os -from portage.const import BASH_BINARY -from portage.output import red, green -from portage import _unicode_encode, _unicode_decode - -from repoman._subprocess import repoman_getstatusoutput _vcs_type = collections.namedtuple('_vcs_type', 'name dir_name') @@ -141,147 +133,3 @@ def vcs_new_changed(relative_path, mychanged, mynew): return False -def git_supports_gpg_sign(): - status, cmd_output = \ - repoman_getstatusoutput("git --version") - cmd_output = cmd_output.split() - if cmd_output: - version = re.match(r'^(\d+)\.(\d+)\.(\d+)', cmd_output[-1]) - if version is not None: - version = [int(x) for x in version.groups()] - if version[0] > 1 or \ - (version[0] == 1 and version[1] > 7) or \ - (version[0] == 1 and version[1] == 7 and version[2] >= 9): - return True - return False - - -def detect_vcs_conflicts(options, vcs): - """Determine if the checkout has problems like cvs conflicts. - - If you want more vcs support here just keep adding if blocks... - This could be better. - - TODO(antarus): Also this should probably not call sys.exit() as - repoman is run on >1 packages and one failure should not cause - subsequent packages to fail. - - Args: - vcs - A string identifying the version control system in use - Returns: - None (calls sys.exit on fatal problems) - """ - - cmd = None - if vcs == 'cvs': - logging.info( - "Performing a %s with a little magic grep to check for updates." % - green("cvs -n up")) - cmd = ( - "cvs -n up 2>/dev/null | " - "egrep '^[^\?] .*' | " - "egrep -v '^. .*/digest-[^/]+|^cvs server: .* -- ignored$'") - if vcs == 'svn': - logging.info( - "Performing a %s with a little magic grep to check for updates." % - green("svn status -u")) - cmd = ( - "svn status -u 2>&1 | " - "egrep -v '^. +.*/digest-[^/]+' | " - "head -n-1") - - if cmd is not None: - # Use Popen instead of getstatusoutput(), in order to avoid - # unicode handling problems (see bug #310789). - args = [BASH_BINARY, "-c", cmd] - args = [_unicode_encode(x) for x in args] - proc = subprocess.Popen( - args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - out = _unicode_decode(proc.communicate()[0]) - proc.wait() - mylines = out.splitlines() - myupdates = [] - for line in mylines: - if not line: - continue - - # [ ] Unmodified (SVN) [U] Updates [P] Patches - # [M] Modified [A] Added [R] Removed / Replaced - # [D] Deleted - if line[0] not in " UPMARD": - # Stray Manifest is fine, we will readd it anyway. - if line[0] == '?' and line[1:].lstrip() == 'Manifest': - continue - logging.error(red( - "!!! Please fix the following issues reported " - "from cvs: %s" % green("(U,P,M,A,R,D are ok)"))) - logging.error(red( - "!!! Note: This is a pretend/no-modify pass...")) - logging.error(out) - sys.exit(1) - elif vcs == 'cvs' and line[0] in "UP": - myupdates.append(line[2:]) - elif vcs == 'svn' and line[8] == '*': - myupdates.append(line[9:].lstrip(" 1234567890")) - - if myupdates: - logging.info(green("Fetching trivial updates...")) - if options.pretend: - logging.info("(" + vcs + " update " + " ".join(myupdates) + ")") - retval = os.EX_OK - else: - retval = os.system(vcs + " update " + " ".join(myupdates)) - if retval != os.EX_OK: - logging.fatal("!!! " + vcs + " exited with an error. Terminating.") - sys.exit(retval) - - -class VCSSettings(object): - '''Holds various VCS settings''' - - def __init__(self, options=None, repoman_settings=None): - if options.vcs: - if options.vcs in ('cvs', 'svn', 'git', 'bzr', 'hg'): - self.vcs = options.vcs - else: - self.vcs = None - else: - vcses = FindVCS() - if len(vcses) > 1: - print(red( - '*** Ambiguous workdir -- more than one VCS found' - ' at the same depth: %s.' % ', '.join(vcses))) - print(red( - '*** Please either clean up your workdir' - ' or specify --vcs option.')) - sys.exit(1) - elif vcses: - self.vcs = vcses[0] - else: - self.vcs = None - - if options.if_modified == "y" and self.vcs is None: - logging.info( - "Not in a version controlled repository; " - "disabling --if-modified.") - options.if_modified = "n" - - # Disable copyright/mtime check if vcs does not preserve mtime (bug #324075). - self.vcs_preserves_mtime = self.vcs in ('cvs',) - - self.vcs_local_opts = repoman_settings.get( - "REPOMAN_VCS_LOCAL_OPTS", "").split() - self.vcs_global_opts = repoman_settings.get( - "REPOMAN_VCS_GLOBAL_OPTS") - if self.vcs_global_opts is None: - if self.vcs in ('cvs', 'svn'): - self.vcs_global_opts = "-q" - else: - self.vcs_global_opts = "" - self.vcs_global_opts = self.vcs_global_opts.split() - - if options.mode == 'commit' and not options.pretend and not self.vcs: - logging.info( - "Not in a version controlled repository; " - "enabling pretend mode.") - options.pretend = True diff --git a/pym/repoman/vcs/vcsstatus.py b/pym/repoman/vcs/vcsstatus.py index 53b8ffe..f0ad52c 100644 --- a/pym/repoman/vcs/vcsstatus.py +++ b/pym/repoman/vcs/vcsstatus.py @@ -1,114 +1,14 @@ # -*- coding:utf-8 -*- -# import our initialized portage instance -from repoman._portage import portage - -from portage import os - -from repoman._subprocess import repoman_popen - - class VCSStatus(object): '''Determines the status of the vcs repositories to determine if files are not added''' - def __init__(self, vcs_settings, qatracker): + def __init__(self, vcs_settings): self.vcs_settings = vcs_settings - self.vcs = vcs_settings.vcs - self.eadded = [] - self.qatracker = qatracker def check(self, check_not_added, checkdir, checkdir_relative, xpkg): - if self.vcs and check_not_added: - vcscheck = getattr(self, 'check_%s' % self.vcs) - vcscheck(checkdir, checkdir_relative, xpkg) - - def post_git_hg(self, myf, xpkg): - for l in myf: - if l[:-1][-7:] == ".ebuild": - self.qatracker.add_error( - "ebuild.notadded", - os.path.join(xpkg, os.path.basename(l[:-1]))) - myf.close() - - def check_git(self, checkdir, checkdir_relative, xpkg): - myf = repoman_popen( - "git ls-files --others %s" % - (portage._shell_quote(checkdir_relative),)) - self.post_git_hg(myf, xpkg) - - def check_hg(self, checkdir, checkdir_relative, xpkg): - myf = repoman_popen( - "hg status --no-status --unknown %s" % - (portage._shell_quote(checkdir_relative),)) - self.post_git_hg(myf, xpkg) - - def check_cvs(self, checkdir, checkdir_relative, xpkg): - try: - myf = open(checkdir + "/CVS/Entries", "r") - myl = myf.readlines() - myf.close() - except IOError: - self.qatracker.add_error( - "CVS/Entries.IO_error", checkdir + "/CVS/Entries") - return True - for l in myl: - if l[0] != "/": - continue - splitl = l[1:].split("/") - if not len(splitl): - continue - if splitl[0][-7:] == ".ebuild": - self.eadded.append(splitl[0][:-7]) - return True - - def check_svn(self, checkdir, checkdir_relative, xpkg): - try: - myf = repoman_popen( - "svn status --depth=files --verbose " + - portage._shell_quote(checkdir)) - myl = myf.readlines() - myf.close() - except IOError: - raise - for l in myl: - if l[:1] == "?": - continue - if l[:7] == ' >': - # tree conflict, new in subversion 1.6 - continue - l = l.split()[-1] - if l[-7:] == ".ebuild": - self.eadded.append(os.path.basename(l[:-7])) - try: - myf = repoman_popen( - "svn status " + - portage._shell_quote(checkdir)) - myl = myf.readlines() - myf.close() - except IOError: - raise - for l in myl: - if l[0] == "A": - l = l.rstrip().split(' ')[-1] - if l[-7:] == ".ebuild": - self.eadded.append(os.path.basename(l[:-7])) - return True + if self.vcs_settings.vcs and check_not_added: + self.vcs_settings.status.check(checkdir, checkdir_relative, xpkg) - def check_bzr(self, checkdir, checkdir_relative, xpkg): - try: - myf = repoman_popen( - "bzr ls -v --kind=file " + - portage._shell_quote(checkdir)) - myl = myf.readlines() - myf.close() - except IOError: - raise - for l in myl: - if l[1:2] == "?": - continue - l = l.split()[-1] - if l[-7:] == ".ebuild": - self.eadded.append(os.path.basename(l[:-7])) - return True