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

Reply via email to