commit:     e7607003f01c16b34def04d2069a72f140dfe999
Author:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
AuthorDate: Sat Sep 19 00:48:05 2015 +0000
Commit:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
CommitDate: Sat Sep 19 01:19:08 2015 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=e7607003

repoman: Move the remaining actions to an Actions class

 pym/repoman/{main.py => actions.py} | 658 +++++++++++++------------------
 pym/repoman/main.py                 | 756 ++----------------------------------
 2 files changed, 298 insertions(+), 1116 deletions(-)

diff --git a/pym/repoman/main.py b/pym/repoman/actions.py
old mode 100755
new mode 100644
similarity index 66%
copy from pym/repoman/main.py
copy to pym/repoman/actions.py
index 2b2f91d..615d5f4
--- a/pym/repoman/main.py
+++ b/pym/repoman/actions.py
@@ -1,337 +1,77 @@
-#!/usr/bin/python -bO
-# Copyright 1999-2015 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-from __future__ import print_function, unicode_literals
 
 import errno
 import io
 import logging
+import platform
 import re
 import signal
 import subprocess
 import sys
 import tempfile
-import platform
 from itertools import chain
 
-from os import path as osp
-if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), 
".portage_not_installed")):
-       pym_path = osp.join(osp.dirname(osp.dirname(osp.realpath(__file__)))) 
#, "pym")
-       sys.path.insert(0, pym_path)
-# import our centrally initialized portage instance
-from repoman._portage import portage
-portage._internal_caller = True
-portage._disable_legacy_globals()
-
+from _emerge.UserQuery import UserQuery
 
+import portage
+from portage import cvstree
 from portage import os
 from portage import _encodings
 from portage import _unicode_encode
-from _emerge.UserQuery import UserQuery
-import portage.checksum
-import portage.const
-import portage.repository.config
-from portage import cvstree
-from portage import util
-from portage.process import find_binary, spawn
 from portage.output import (
-       bold, create_color_func, green, nocolor, red)
-from portage.output import ConsoleStyleFile, StyleWriter
-from portage.util import formatter
-from portage.util import writemsg_level
+       bold, create_color_func, green, red)
 from portage.package.ebuild.digestgen import digestgen
+from portage.process import find_binary, spawn
+from portage.util import writemsg_level
 
-from repoman.argparser import parse_args
-from repoman.checks.ebuilds.checks import checks_init
+from repoman._subprocess import repoman_popen, repoman_getstatusoutput
 from repoman.errors import err
 from repoman.gpg import gpgsign, need_signature
-from repoman.qa_data import (
-       format_qa_output, format_qa_output_column, qahelp,
-       qawarnings, qacats)
-from repoman.repos import RepoSettings
-from repoman.scanner import Scanner
-from repoman._subprocess import repoman_popen, repoman_getstatusoutput
 from repoman import utilities
-from repoman.vcs.vcs import (
-       git_supports_gpg_sign, vcs_files_to_cps, VCSSettings)
-
-
-if sys.hexversion >= 0x3000000:
-       basestring = str
-
-util.initialize_logger()
+from repoman.vcs.vcs import git_supports_gpg_sign, vcs_files_to_cps
 
 bad = create_color_func("BAD")
 
-# A sane umask is needed for files that portage creates.
-os.umask(0o22)
-
-
-def repoman_main(argv):
-       config_root = os.environ.get("PORTAGE_CONFIGROOT")
-       repoman_settings = portage.config(config_root=config_root, 
local_config=False)
-
-       if repoman_settings.get("NOCOLOR", "").lower() in ("yes", "true") or \
-               repoman_settings.get('TERM') == 'dumb' or \
-               not sys.stdout.isatty():
-               nocolor()
-
-       options, arguments = parse_args(
-               sys.argv, qahelp, repoman_settings.get("REPOMAN_DEFAULT_OPTS", 
""))
-
-       if options.version:
-               print("Portage", portage.VERSION)
-               sys.exit(0)
-
-       if options.experimental_inherit == 'y':
-               # This is experimental, so it's non-fatal.
-               qawarnings.add("inherit.missing")
-               checks_init(experimental_inherit=True)
-
-       # Set this to False when an extraordinary issue (generally
-       # something other than a QA issue) makes it impossible to
-       # commit (like if Manifest generation fails).
-       can_force = True
-
-       portdir, portdir_overlay, mydir = 
utilities.FindPortdir(repoman_settings)
-       if portdir is None:
-               sys.exit(1)
-
-       myreporoot = os.path.basename(portdir_overlay)
-       myreporoot += mydir[len(portdir_overlay):]
-
-       vcs_settings = VCSSettings(options, repoman_settings)
-
-       repo_settings = RepoSettings(
-               config_root, portdir, portdir_overlay,
-               repoman_settings, vcs_settings, options, qawarnings)
-       repoman_settings = repo_settings.repoman_settings
-       portdb = repo_settings.portdb
-
-       if 'digest' in repoman_settings.features and options.digest != 'n':
-               options.digest = 'y'
-
-       logging.debug("vcs: %s" % (vcs_settings.vcs,))
-       logging.debug("repo config: %s" % (repo_settings.repo_config,))
-       logging.debug("options: %s" % (options,))
-
-       # It's confusing if these warnings are displayed without the user
-       # being told which profile they come from, so disable them.
-       env = os.environ.copy()
-       env['FEATURES'] = env.get('FEATURES', '') + ' -unknown-features-warn'
-
-       # Perform the main checks
-       scanner = Scanner(repo_settings, myreporoot, config_root, options,
-                                       vcs_settings, mydir, env)
-       qatracker, can_force = scanner.scan_pkgs(can_force)
-
-       commitmessage = None
-
-       if options.if_modified == "y" and len(scanner.effective_scanlist) < 1:
-               logging.warning("--if-modified is enabled, but no modified 
packages were found!")
-
-       # dofail will be true if we have failed in at least one non-warning 
category
-       dofail = 0
-       # dowarn will be true if we tripped any warnings
-       dowarn = 0
-       # dofull will be true if we should print a "repoman full" informational 
message
-       dofull = options.mode != 'full'
-
-       # early out for manifest generation
-       if options.mode == "manifest":
-               sys.exit(dofail)
-
-       for x in qacats:
-               if x not in qatracker.fails:
-                       continue
-               dowarn = 1
-               if x not in qawarnings:
-                       dofail = 1
-
-       if dofail or \
-               (dowarn and not (options.quiet or options.mode == "scan")):
-               dofull = 0
-
-       # Save QA output so that it can be conveniently displayed
-       # in $EDITOR while the user creates a commit message.
-       # Otherwise, the user would not be able to see this output
-       # once the editor has taken over the screen.
-       qa_output = io.StringIO()
-       style_file = ConsoleStyleFile(sys.stdout)
-       if options.mode == 'commit' and \
-               (not commitmessage or not commitmessage.strip()):
-               style_file.write_listener = qa_output
-       console_writer = StyleWriter(file=style_file, maxcol=9999)
-       console_writer.style_listener = style_file.new_styles
-
-       f = formatter.AbstractFormatter(console_writer)
-
-       format_outputs = {
-               'column': format_qa_output_column,
-               'default': format_qa_output
-       }
-
-       format_output = format_outputs.get(
-               options.output_style, format_outputs['default'])
-       format_output(f, qatracker.fails, dofull, dofail, options, qawarnings)
-
-       style_file.flush()
-       del console_writer, f, style_file
-       qa_output = qa_output.getvalue()
-       qa_output = qa_output.splitlines(True)
-
-       suggest_ignore_masked = False
-       suggest_include_dev = False
-
-       if scanner.have['pmasked'] and not (options.without_mask or 
options.ignore_masked):
-               suggest_ignore_masked = True
-       if scanner.have['dev_keywords'] and not options.include_dev:
-               suggest_include_dev = True
-
-       if suggest_ignore_masked or suggest_include_dev:
-               print()
-               if suggest_ignore_masked:
-                       print(bold(
-                               "Note: use --without-mask to check "
-                               "KEYWORDS on dependencies of masked packages"))
 
-               if suggest_include_dev:
-                       print(bold(
-                               "Note: use --include-dev (-d) to check "
-                               "dependencies for 'dev' profiles"))
-               print()
+class Actions(object):
+       '''Handles post check result output and performs
+       the various vcs activities for committing the results'''
+
+       def __init__(self, repo_settings, options, scanner, vcs_settings):
+               self.repo_settings = repo_settings
+               self.options = options
+               self.scanner = scanner
+               self.vcs_settings = vcs_settings
+               self.suggest = {
+                       'ignore_masked': False,
+                       'include_dev': False,
+               }
+               if scanner.have['pmasked'] and not (options.without_mask or 
options.ignore_masked):
+                       self.suggest['ignore_masked'] = True
+               if scanner.have['dev_keywords'] and not options.include_dev:
+                       self.suggest['include_dev'] = True
+
+
+       def inform(self, can_force, result):
+               '''Inform the user of all the problems found'''
+               if self.suggest['ignore_masked'] or self.suggest['include_dev']:
+                       self._suggest()
+               if self.options.mode != 'commit':
+                       self._non_commit(result)
+               else:
+                       self._fail(result, can_force)
+                       if self.options.pretend:
+                               utilities.repoman_sez(
+                                       "\"So, you want to play it safe. Good 
call.\"\n")
 
-       if options.mode != 'commit':
-               if dofull:
-                       print(bold("Note: type \"repoman full\" for a complete 
listing."))
-               if dowarn and not dofail:
-                       utilities.repoman_sez(
-                               "\"You're only giving me a partial QA 
payment?\n"
-                               "              I'll take it this time, but I'm 
not happy.\"")
-               elif not dofail:
-                       utilities.repoman_sez(
-                               "\"If everyone were like you, I'd be out of 
business!\"")
-               elif dofail:
-                       print(bad("Please fix these important QA issues 
first."))
-                       utilities.repoman_sez(
-                               "\"Make your QA payment on time"
-                               " and you'll never see the likes of me.\"\n")
-                       sys.exit(1)
-       else:
-               if dofail and can_force and options.force and not 
options.pretend:
-                       utilities.repoman_sez(
-                               " \"You want to commit even with these QA 
issues?\n"
-                               "              I'll take it this time, but I'm 
not happy.\"\n")
-               elif dofail:
-                       if options.force and not can_force:
-                               print(bad(
-                                       "The --force option has been disabled"
-                                       " due to extraordinary issues."))
-                       print(bad("Please fix these important QA issues 
first."))
-                       utilities.repoman_sez(
-                               "\"Make your QA payment on time"
-                               " and you'll never see the likes of me.\"\n")
-                       sys.exit(1)
 
-               if options.pretend:
-                       utilities.repoman_sez(
-                               "\"So, you want to play it safe. Good 
call.\"\n")
+       def perform(self, qa_output):
+               myunadded, mydeleted = self._vcs_unadded()
 
-               myunadded = []
-               if vcs_settings.vcs == "cvs":
-                       try:
-                               myvcstree = portage.cvstree.getentries("./", 
recursive=1)
-                               myunadded = portage.cvstree.findunadded(
-                                       myvcstree, recursive=1, basedir="./")
-                       except SystemExit as e:
-                               raise  # TODO propagate this
-                       except:
-                               err("Error retrieving CVS tree; exiting.")
-               if vcs_settings.vcs == "svn":
-                       try:
-                               with repoman_popen("svn status --no-ignore") as 
f:
-                                       svnstatus = f.readlines()
-                               myunadded = [
-                                       "./" + elem.rstrip().split()[1]
-                                       for elem in svnstatus
-                                       if elem.startswith("?") or 
elem.startswith("I")]
-                       except SystemExit as e:
-                               raise  # TODO propagate this
-                       except:
-                               err("Error retrieving SVN info; exiting.")
-               if vcs_settings.vcs == "git":
-                       # get list of files not under version control or missing
-                       myf = repoman_popen("git ls-files --others")
-                       myunadded = ["./" + elem[:-1] for elem in myf]
-                       myf.close()
-               if vcs_settings.vcs == "bzr":
-                       try:
-                               with repoman_popen("bzr status -S .") as f:
-                                       bzrstatus = f.readlines()
-                               myunadded = [
-                                       "./" + 
elem.rstrip().split()[1].split('/')[-1:][0]
-                                       for elem in bzrstatus
-                                       if elem.startswith("?") or elem[0:2] == 
" D"]
-                       except SystemExit as e:
-                               raise  # TODO propagate this
-                       except:
-                               err("Error retrieving bzr info; exiting.")
-               if vcs_settings.vcs == "hg":
-                       with repoman_popen("hg status --no-status --unknown .") 
as f:
-                               myunadded = f.readlines()
-                       myunadded = ["./" + elem.rstrip() for elem in myunadded]
+               myautoadd = self._vcs_autoadd(myunadded)
 
-                       # Mercurial doesn't handle manually deleted files as 
removed from
-                       # the repository, so the user need to remove them 
before commit,
-                       # using "hg remove [FILES]"
-                       with repoman_popen("hg status --no-status --deleted .") 
as f:
-                               mydeleted = f.readlines()
-                       mydeleted = ["./" + elem.rstrip() for elem in mydeleted]
+               self._vcs_deleted(mydeleted)
 
-               myautoadd = []
-               if myunadded:
-                       for x in range(len(myunadded) - 1, -1, -1):
-                               xs = myunadded[x].split("/")
-                               if 
repo_settings.repo_config.find_invalid_path_char(myunadded[x]) != -1:
-                                       # The Manifest excludes this file,
-                                       # so it's safe to ignore.
-                                       del myunadded[x]
-                               elif xs[-1] == "files":
-                                       print("!!! files dir is not added! 
Please correct this.")
-                                       sys.exit(-1)
-                               elif xs[-1] == "Manifest":
-                                       # It's a manifest... auto add
-                                       myautoadd += [myunadded[x]]
-                                       del myunadded[x]
-
-               if myunadded:
-                       print(red(
-                               "!!! The following files are in your local tree"
-                               " but are not added to the master"))
-                       print(red(
-                               "!!! tree. Please remove them from the local 
tree"
-                               " or add them to the master tree."))
-                       for x in myunadded:
-                               print("   ", x)
-                       print()
-                       print()
-                       sys.exit(1)
-
-               if vcs_settings.vcs == "hg" and mydeleted:
-                       print(red(
-                               "!!! The following files are removed manually"
-                               " from your local tree but are not"))
-                       print(red(
-                               "!!! removed from the repository."
-                               " Please remove them, using \"hg remove 
[FILES]\"."))
-                       for x in mydeleted:
-                               print("   ", x)
-                       print()
-                       print()
-                       sys.exit(1)
-
-               if vcs_settings.vcs == "cvs":
+               if self.vcs_settings.vcs == "cvs":
                        mycvstree = cvstree.getentries("./", recursive=1)
                        mychanged = cvstree.findchanged(mycvstree, recursive=1, 
basedir="./")
                        mynew = cvstree.findnew(mycvstree, recursive=1, 
basedir="./")
@@ -340,7 +80,7 @@ def repoman_main(argv):
                        no_expansion = set(portage.cvstree.findoption(
                                mycvstree, bin_blob_pattern, recursive=1, 
basedir="./"))
 
-               if vcs_settings.vcs == "svn":
+               if self.vcs_settings.vcs == "svn":
                        with repoman_popen("svn status") as f:
                                svnstatus = f.readlines()
                        mychanged = [
@@ -363,7 +103,7 @@ def repoman_main(argv):
                                ("./" + prop.split(" - ")[0], prop.split(" - 
")[1].split())
                                for prop in props if " - " in prop)
 
-               elif vcs_settings.vcs == "git":
+               elif self.vcs_settings.vcs == "git":
                        with repoman_popen(
                                "git diff-index --name-only "
                                "--relative --diff-filter=M HEAD") as f:
@@ -382,7 +122,7 @@ def repoman_main(argv):
                                myremoved = f.readlines()
                        myremoved = ["./" + elem[:-1] for elem in myremoved]
 
-               if vcs_settings.vcs == "bzr":
+               if self.vcs_settings.vcs == "bzr":
                        with repoman_popen("bzr status -S .") as f:
                                bzrstatus = f.readlines()
                        mychanged = [
@@ -403,7 +143,7 @@ def repoman_main(argv):
                                if elem and (elem[1:2] == "K" or elem[0:1] == 
"R")]
                        # Bazaar expands nothing.
 
-               if vcs_settings.vcs == "hg":
+               if self.vcs_settings.vcs == "hg":
                        with repoman_popen("hg status --no-status --modified 
.") as f:
                                mychanged = f.readlines()
                        mychanged = ["./" + elem.rstrip() for elem in mychanged]
@@ -416,9 +156,9 @@ def repoman_main(argv):
                                myremoved = f.readlines()
                        myremoved = ["./" + elem.rstrip() for elem in myremoved]
 
-               if vcs_settings.vcs:
+               if self.vcs_settings.vcs:
                        a_file_is_changed = mychanged or mynew or myremoved
-                       a_file_is_deleted_hg = vcs_settings.vcs == "hg" and 
mydeleted
+                       a_file_is_deleted_hg = self.vcs_settings.vcs == "hg" 
and mydeleted
 
                        if not (a_file_is_changed or a_file_is_deleted_hg):
                                utilities.repoman_sez(
@@ -442,12 +182,12 @@ def repoman_main(argv):
                mymanifests = list(mymanifests)
                myheaders = []
 
-               commitmessage = options.commitmsg
-               if options.commitmsgfile:
+               commitmessage = self.options.commitmsg
+               if self.options.commitmsgfile:
                        try:
                                f = io.open(
                                        _unicode_encode(
-                                               options.commitmsgfile,
+                                               self.options.commitmsgfile,
                                                encoding=_encodings['fs'], 
errors='strict'),
                                        mode='r', 
encoding=_encodings['content'], errors='replace')
                                commitmessage = f.read()
@@ -457,15 +197,15 @@ def repoman_main(argv):
                                if e.errno == errno.ENOENT:
                                        portage.writemsg(
                                                "!!! File Not Found:"
-                                               " --commitmsgfile='%s'\n" % 
options.commitmsgfile)
+                                               " --commitmsgfile='%s'\n" % 
self.options.commitmsgfile)
                                else:
                                        raise
                        # We've read the content so the file is no longer 
needed.
                        commitmessagefile = None
                if not commitmessage or not commitmessage.strip():
                        msg_prefix = ""
-                       if scanner.repolevel > 1:
-                               msg_prefix = "/".join(scanner.reposplit[1:]) + 
": "
+                       if self.scanner.repolevel > 1:
+                               msg_prefix = 
"/".join(self.scanner.reposplit[1:]) + ": "
 
                        try:
                                editor = os.environ.get("EDITOR")
@@ -484,29 +224,29 @@ def repoman_main(argv):
                commitmessage = commitmessage.rstrip()
                changelog_msg = commitmessage
                portage_version = getattr(portage, "VERSION", None)
-               gpg_key = repoman_settings.get("PORTAGE_GPG_KEY", "")
-               dco_sob = repoman_settings.get("DCO_SIGNED_OFF_BY", "")
+               gpg_key = self.repoman_settings.get("PORTAGE_GPG_KEY", "")
+               dco_sob = self.repoman_settings.get("DCO_SIGNED_OFF_BY", "")
                if portage_version is None:
                        sys.stderr.write("Failed to insert portage version in 
message!\n")
                        sys.stderr.flush()
                        portage_version = "Unknown"
 
                report_options = []
-               if options.force:
+               if self.options.force:
                        report_options.append("--force")
-               if options.ignore_arches:
+               if self.options.ignore_arches:
                        report_options.append("--ignore-arches")
-               if scanner.include_arches is not None:
+               if self.scanner.include_arches is not None:
                        report_options.append(
                                "--include-arches=\"%s\"" %
-                               " ".join(sorted(scanner.include_arches)))
+                               " ".join(sorted(self.scanner.include_arches)))
 
-               if vcs_settings.vcs == "git":
+               if self.vcs_settings.vcs == "git":
                        # Use new footer only for git (see bug #438364).
                        commit_footer = "\n\nPackage-Manager: portage-%s" % 
portage_version
                        if report_options:
                                commit_footer += "\nRepoMan-Options: " + " 
".join(report_options)
-                       if repo_settings.sign_manifests:
+                       if self.repo_settings.sign_manifests:
                                commit_footer += "\nManifest-Sign-Key: %s" % 
(gpg_key, )
                        if dco_sob:
                                commit_footer += "\nSigned-off-by: %s" % 
(dco_sob, )
@@ -520,10 +260,10 @@ def repoman_main(argv):
                        if dco_sob:
                                commit_footer += "Signed-off-by: %s\n" % 
(dco_sob, )
                        commit_footer += "(Portage version: %s/%s/%s" % \
-                               (portage_version, vcs_settings.vcs, unameout)
+                               (portage_version, self.vcs_settings.vcs, 
unameout)
                        if report_options:
                                commit_footer += ", RepoMan options: " + " 
".join(report_options)
-                       if repo_settings.sign_manifests:
+                       if self.repo_settings.sign_manifests:
                                commit_footer += ", signed Manifest commit with 
key %s" % \
                                        (gpg_key, )
                        else:
@@ -533,24 +273,24 @@ def repoman_main(argv):
                commitmessage += commit_footer
 
                broken_changelog_manifests = []
-               if options.echangelog in ('y', 'force'):
+               if self.options.echangelog in ('y', 'force'):
                        logging.info("checking for unmodified ChangeLog files")
-                       committer_name = 
utilities.get_committer_name(env=repoman_settings)
+                       committer_name = 
utilities.get_committer_name(env=self.repoman_settings)
                        for x in sorted(vcs_files_to_cps(
                                chain(myupdates, mymanifests, myremoved),
-                               scanner.repolevel, scanner.reposplit, 
scanner.categories)):
+                               self.scanner.repolevel, self.scanner.reposplit, 
self.scanner.categories)):
                                catdir, pkgdir = x.split("/")
-                               checkdir = repo_settings.repodir + "/" + x
+                               checkdir = self.repo_settings.repodir + "/" + x
                                checkdir_relative = ""
-                               if scanner.repolevel < 3:
+                               if self.scanner.repolevel < 3:
                                        checkdir_relative = 
os.path.join(pkgdir, checkdir_relative)
-                               if scanner.repolevel < 2:
+                               if self.scanner.repolevel < 2:
                                        checkdir_relative = 
os.path.join(catdir, checkdir_relative)
                                checkdir_relative = os.path.join(".", 
checkdir_relative)
 
                                changelog_path = 
os.path.join(checkdir_relative, "ChangeLog")
-                               changelog_modified = changelog_path in 
scanner.changed.changelogs
-                               if changelog_modified and options.echangelog != 
'force':
+                               changelog_modified = changelog_path in 
self.scanner.changed.changelogs
+                               if changelog_modified and 
self.options.echangelog != 'force':
                                        continue
 
                                # get changes for this package
@@ -566,15 +306,15 @@ def repoman_main(argv):
                                nontrivial_cl_files = set()
                                nontrivial_cl_files.update(clnew, clremoved, 
clchanged)
                                
nontrivial_cl_files.difference_update(['Manifest'])
-                               if not nontrivial_cl_files and 
options.echangelog != 'force':
+                               if not nontrivial_cl_files and 
self.options.echangelog != 'force':
                                        continue
 
                                new_changelog = utilities.UpdateChangeLog(
                                        checkdir_relative, committer_name, 
changelog_msg,
-                                       os.path.join(repo_settings.repodir, 
'skel.ChangeLog'),
+                                       
os.path.join(self.repo_settings.repodir, 'skel.ChangeLog'),
                                        catdir, pkgdir,
                                        new=clnew, removed=clremoved, 
changed=clchanged,
-                                       pretend=options.pretend)
+                                       pretend=self.options.pretend)
                                if new_changelog is None:
                                        writemsg_level(
                                                "!!! Updating the ChangeLog 
failed\n",
@@ -588,18 +328,18 @@ def repoman_main(argv):
                                else:
                                        myupdates.append(changelog_path)
 
-                               if options.ask and not options.pretend:
+                               if self.options.ask and not 
self.options.pretend:
                                        # regenerate Manifest for modified 
ChangeLog (bug #420735)
-                                       repoman_settings["O"] = checkdir
-                                       digestgen(mysettings=repoman_settings, 
myportdb=portdb)
+                                       self.repoman_settings["O"] = checkdir
+                                       
digestgen(mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb)
                                else:
                                        broken_changelog_manifests.append(x)
 
                if myautoadd:
                        print(">>> Auto-Adding missing Manifest/ChangeLog 
file(s)...")
-                       add_cmd = [vcs_settings.vcs, "add"]
+                       add_cmd = [self.vcs_settings.vcs, "add"]
                        add_cmd += myautoadd
-                       if options.pretend:
+                       if self.options.pretend:
                                portage.writemsg_stdout(
                                        "(%s)\n" % " ".join(add_cmd),
                                        noiselevel=-1)
@@ -618,22 +358,22 @@ def repoman_main(argv):
                                retcode = subprocess.call(add_cmd)
                                if retcode != os.EX_OK:
                                        logging.error(
-                                               "Exiting on %s error code: 
%s\n" % (vcs_settings.vcs, retcode))
+                                               "Exiting on %s error code: 
%s\n" % (self.vcs_settings.vcs, retcode))
                                        sys.exit(retcode)
 
                        myupdates += myautoadd
 
                print("* %s files being committed..." % 
green(str(len(myupdates))), end=' ')
 
-               if vcs_settings.vcs not in ('cvs', 'svn'):
+               if self.vcs_settings.vcs not in ('cvs', 'svn'):
                        # With git, bzr and hg, there's never any keyword 
expansion, so
                        # there's no need to regenerate manifests and all files 
will be
                        # committed in one big commit at the end.
                        print()
-               elif not repo_settings.repo_config.thin_manifest:
-                       if vcs_settings.vcs == 'cvs':
+               elif not self.repo_settings.repo_config.thin_manifest:
+                       if self.vcs_settings.vcs == 'cvs':
                                headerstring = "'\$(Header|Id).*\$'"
-                       elif vcs_settings.vcs == "svn":
+                       elif self.vcs_settings.vcs == "svn":
                                svn_keywords = dict((k.lower(), k) for k in [
                                        "Rev",
                                        "Revision",
@@ -651,12 +391,12 @@ def repoman_main(argv):
                        for myfile in myupdates:
 
                                # for CVS, no_expansion contains files that are 
excluded from expansion
-                               if vcs_settings.vcs == "cvs":
+                               if self.vcs_settings.vcs == "cvs":
                                        if myfile in no_expansion:
                                                continue
 
                                # for SVN, expansion contains files that are 
included in expansion
-                               elif vcs_settings.vcs == "svn":
+                               elif self.vcs_settings.vcs == "svn":
                                        if myfile not in expansion:
                                                continue
 
@@ -684,8 +424,8 @@ def repoman_main(argv):
                logging.info("myupdates: %s", myupdates)
                logging.info("myheaders: %s", myheaders)
 
-               uq = UserQuery(options)
-               if options.ask and uq.query('Commit changes?', True) != 'Yes':
+               uq = UserQuery(self.options)
+               if self.options.ask and uq.query('Commit changes?', True) != 
'Yes':
                        print("* aborting commit.")
                        sys.exit(128 + signal.SIGINT)
 
@@ -713,22 +453,22 @@ def repoman_main(argv):
                        # so strip the prefix.
                        myfiles = [f.lstrip("./") for f in myfiles]
 
-                       commit_cmd = [vcs_settings.vcs]
-                       commit_cmd.extend(vcs_settings.vcs_global_opts)
+                       commit_cmd = [self.vcs_settings.vcs]
+                       commit_cmd.extend(self.vcs_settings.vcs_global_opts)
                        commit_cmd.append("commit")
-                       commit_cmd.extend(vcs_settings.vcs_local_opts)
+                       commit_cmd.extend(self.vcs_settings.vcs_local_opts)
                        commit_cmd.extend(["-F", commitmessagefile])
                        commit_cmd.extend(myfiles)
 
                        try:
-                               if options.pretend:
+                               if self.options.pretend:
                                        print("(%s)" % (" ".join(commit_cmd),))
                                else:
-                                       retval = spawn(commit_cmd, 
env=repo_settings.commit_env)
+                                       retval = spawn(commit_cmd, 
env=self.repo_settings.commit_env)
                                        if retval != os.EX_OK:
                                                writemsg_level(
                                                        "!!! Exiting on %s 
(shell) "
-                                                       "error code: %s\n" % 
(vcs_settings.vcs, retval),
+                                                       "error code: %s\n" % 
(self.vcs_settings.vcs, retval),
                                                        level=logging.ERROR, 
noiselevel=-1)
                                                sys.exit(retval)
                        finally:
@@ -759,39 +499,39 @@ def repoman_main(argv):
                        if modified:
                                portage.util.write_atomic(x, b''.join(mylines), 
mode='wb')
 
-               if scanner.repolevel == 1:
+               if self.scanner.repolevel == 1:
                        utilities.repoman_sez(
                                "\"You're rather crazy... "
                                "doing the entire repository.\"\n")
 
-               if vcs_settings.vcs in ('cvs', 'svn') and (myupdates or 
myremoved):
+               if self.vcs_settings.vcs in ('cvs', 'svn') and (myupdates or 
myremoved):
                        for x in sorted(vcs_files_to_cps(
                                chain(myupdates, myremoved, mymanifests),
-                               scanner.repolevel, scanner.reposplit, 
scanner.categories)):
-                               repoman_settings["O"] = 
os.path.join(repo_settings.repodir, x)
-                               digestgen(mysettings=repoman_settings, 
myportdb=portdb)
+                               self.scanner.repolevel, self.scanner.reposplit, 
self.scanner.categories)):
+                               self.repoman_settings["O"] = 
os.path.join(self.repo_settings.repodir, x)
+                               digestgen(mysettings=self.repoman_settings, 
myportdb=self.repo_settings.portdb)
 
                elif broken_changelog_manifests:
                        for x in broken_changelog_manifests:
-                               repoman_settings["O"] = 
os.path.join(repo_settings.repodir, x)
-                               digestgen(mysettings=repoman_settings, 
myportdb=portdb)
+                               self.repoman_settings["O"] = 
os.path.join(self.repo_settings.repodir, x)
+                               digestgen(mysettings=self.repoman_settings, 
myportdb=self.repo_settings.portdb)
 
-               if repo_settings.sign_manifests:
+               if self.repo_settings.sign_manifests:
                        try:
                                for x in sorted(vcs_files_to_cps(
                                        chain(myupdates, myremoved, 
mymanifests),
-                                       scanner.repolevel, scanner.reposplit, 
scanner.categories)):
-                                       repoman_settings["O"] = 
os.path.join(repo_settings.repodir, x)
-                                       manifest_path = 
os.path.join(repoman_settings["O"], "Manifest")
+                                       self.scanner.repolevel, 
self.scanner.reposplit, self.scanner.categories)):
+                                       self.repoman_settings["O"] = 
os.path.join(self.repo_settings.repodir, x)
+                                       manifest_path = 
os.path.join(self.repoman_settings["O"], "Manifest")
                                        if not need_signature(manifest_path):
                                                continue
-                                       gpgsign(manifest_path, 
repoman_settings, options)
+                                       gpgsign(manifest_path, 
self.repoman_settings, self.options)
                        except portage.exception.PortageException as e:
                                portage.writemsg("!!! %s\n" % str(e))
                                portage.writemsg("!!! Disabled 
FEATURES='sign'\n")
-                               repo_settings.sign_manifests = False
+                               self.repo_settings.sign_manifests = False
 
-               if vcs_settings.vcs == 'git':
+               if self.vcs_settings.vcs == 'git':
                        # It's not safe to use the git commit -a option since 
there might
                        # be some modified files elsewhere in the working tree 
that the
                        # user doesn't want to commit. Therefore, call git 
update-index
@@ -802,14 +542,14 @@ def repoman_main(argv):
                        myfiles.sort()
                        update_index_cmd = ["git", "update-index"]
                        update_index_cmd.extend(f.lstrip("./") for f in myfiles)
-                       if options.pretend:
+                       if self.options.pretend:
                                print("(%s)" % (" ".join(update_index_cmd),))
                        else:
                                retval = spawn(update_index_cmd, env=os.environ)
                                if retval != os.EX_OK:
                                        writemsg_level(
                                                "!!! Exiting on %s (shell) "
-                                               "error code: %s\n" % 
(vcs_settings.vcs, retval),
+                                               "error code: %s\n" % 
(self.vcs_settings.vcs, retval),
                                                level=logging.ERROR, 
noiselevel=-1)
                                        sys.exit(retval)
 
@@ -829,15 +569,15 @@ def repoman_main(argv):
                        mymsg.close()
 
                        commit_cmd = []
-                       if options.pretend and vcs_settings.vcs is None:
+                       if self.options.pretend and self.vcs_settings.vcs is 
None:
                                # substitute a bogus value for pretend output
                                commit_cmd.append("cvs")
                        else:
-                               commit_cmd.append(vcs_settings.vcs)
-                       commit_cmd.extend(vcs_settings.vcs_global_opts)
+                               commit_cmd.append(self.vcs_settings.vcs)
+                       commit_cmd.extend(self.vcs_settings.vcs_global_opts)
                        commit_cmd.append("commit")
-                       commit_cmd.extend(vcs_settings.vcs_local_opts)
-                       if vcs_settings.vcs == "hg":
+                       commit_cmd.extend(self.vcs_settings.vcs_local_opts)
+                       if self.vcs_settings.vcs == "hg":
                                commit_cmd.extend(["--logfile", 
commitmessagefile])
                                commit_cmd.extend(myfiles)
                        else:
@@ -845,12 +585,12 @@ def repoman_main(argv):
                                commit_cmd.extend(f.lstrip("./") for f in 
myfiles)
 
                        try:
-                               if options.pretend:
+                               if self.options.pretend:
                                        print("(%s)" % (" ".join(commit_cmd),))
                                else:
-                                       retval = spawn(commit_cmd, 
env=repo_settings.commit_env)
+                                       retval = spawn(commit_cmd, 
env=self.repo_settings.commit_env)
                                        if retval != os.EX_OK:
-                                               if 
repo_settings.repo_config.sign_commit and vcs_settings.vcs == 'git' and \
+                                               if 
self.repo_settings.repo_config.sign_commit and self.vcs_settings.vcs == 'git' 
and \
                                                        not 
git_supports_gpg_sign():
                                                        # Inform user that 
newer git is needed (bug #403323).
                                                        logging.error(
@@ -858,7 +598,7 @@ def repoman_main(argv):
 
                                                writemsg_level(
                                                        "!!! Exiting on %s 
(shell) "
-                                                       "error code: %s\n" % 
(vcs_settings.vcs, retval),
+                                                       "error code: %s\n" % 
(self.vcs_settings.vcs, retval),
                                                        level=logging.ERROR, 
noiselevel=-1)
                                                sys.exit(retval)
                        finally:
@@ -868,7 +608,7 @@ def repoman_main(argv):
                                        pass
 
                print()
-               if vcs_settings.vcs:
+               if self.vcs_settings.vcs:
                        print("Commit complete.")
                else:
                        print(
@@ -877,4 +617,154 @@ def repoman_main(argv):
                                " that he forgot to commit anything")
                utilities.repoman_sez(
                        "\"If everyone were like you, I'd be out of 
business!\"\n")
-       sys.exit(0)
+
+
+       def _suggest(self):
+               print()
+               if self.suggest['ignore_masked']:
+                       print(bold(
+                               "Note: use --without-mask to check "
+                               "KEYWORDS on dependencies of masked packages"))
+
+               if self.suggest['include_dev']:
+                       print(bold(
+                               "Note: use --include-dev (-d) to check "
+                               "dependencies for 'dev' profiles"))
+               print()
+
+
+       def _non_commit(self, result):
+               if result['full']:
+                       print(bold("Note: type \"repoman full\" for a complete 
listing."))
+               if result['warn'] and not result['fail']:
+                       utilities.repoman_sez(
+                               "\"You're only giving me a partial QA 
payment?\n"
+                               "              I'll take it this time, but I'm 
not happy.\"")
+               elif not result['fail']:
+                       utilities.repoman_sez(
+                               "\"If everyone were like you, I'd be out of 
business!\"")
+               elif result['fail']:
+                       print(bad("Please fix these important QA issues 
first."))
+                       utilities.repoman_sez(
+                               "\"Make your QA payment on time"
+                               " and you'll never see the likes of me.\"\n")
+                       sys.exit(1)
+
+
+       def _fail(self, result, can_force):
+               if result['fail'] and can_force and self.options.force and not 
self.options.pretend:
+                       utilities.repoman_sez(
+                               " \"You want to commit even with these QA 
issues?\n"
+                               "              I'll take it this time, but I'm 
not happy.\"\n")
+               elif result['fail']:
+                       if self.options.force and not can_force:
+                               print(bad(
+                                       "The --force option has been disabled"
+                                       " due to extraordinary issues."))
+                       print(bad("Please fix these important QA issues 
first."))
+                       utilities.repoman_sez(
+                               "\"Make your QA payment on time"
+                               " and you'll never see the likes of me.\"\n")
+                       sys.exit(1)
+
+
+       def _vcs_unadded(self):
+               myunadded = []
+               mydeleted = []
+               if self.vcs_settings.vcs == "cvs":
+                       try:
+                               myvcstree = portage.cvstree.getentries("./", 
recursive=1)
+                               myunadded = portage.cvstree.findunadded(
+                                       myvcstree, recursive=1, basedir="./")
+                       except SystemExit:
+                               raise  # TODO propagate this
+                       except:
+                               err("Error retrieving CVS tree; exiting.")
+               if self.vcs_settings.vcs == "svn":
+                       try:
+                               with repoman_popen("svn status --no-ignore") as 
f:
+                                       svnstatus = f.readlines()
+                               myunadded = [
+                                       "./" + elem.rstrip().split()[1]
+                                       for elem in svnstatus
+                                       if elem.startswith("?") or 
elem.startswith("I")]
+                       except SystemExit:
+                               raise  # TODO propagate this
+                       except:
+                               err("Error retrieving SVN info; exiting.")
+               if self.vcs_settings.vcs == "git":
+                       # get list of files not under version control or missing
+                       myf = repoman_popen("git ls-files --others")
+                       myunadded = ["./" + elem[:-1] for elem in myf]
+                       myf.close()
+               if self.vcs_settings.vcs == "bzr":
+                       try:
+                               with repoman_popen("bzr status -S .") as f:
+                                       bzrstatus = f.readlines()
+                               myunadded = [
+                                       "./" + 
elem.rstrip().split()[1].split('/')[-1:][0]
+                                       for elem in bzrstatus
+                                       if elem.startswith("?") or elem[0:2] == 
" D"]
+                       except SystemExit:
+                               raise # TODO propagate this
+                       except:
+                               err("Error retrieving bzr info; exiting.")
+               if self.vcs_settings.vcs == "hg":
+                       with repoman_popen("hg status --no-status --unknown .") 
as f:
+                               myunadded = f.readlines()
+                       myunadded = ["./" + elem.rstrip() for elem in myunadded]
+
+                       # Mercurial doesn't handle manually deleted files as 
removed from
+                       # the repository, so the user need to remove them 
before commit,
+                       # using "hg remove [FILES]"
+                       with repoman_popen("hg status --no-status --deleted .") 
as f:
+                               mydeleted = f.readlines()
+                       mydeleted = ["./" + elem.rstrip() for elem in mydeleted]
+               return myunadded, mydeleted
+
+
+       def _vcs_autoadd(self, myunadded):
+               myautoadd = []
+               if myunadded:
+                       for x in range(len(myunadded) - 1, -1, -1):
+                               xs = myunadded[x].split("/")
+                               if 
self.repo_settings.repo_config.find_invalid_path_char(myunadded[x]) != -1:
+                                       # The Manifest excludes this file,
+                                       # so it's safe to ignore.
+                                       del myunadded[x]
+                               elif xs[-1] == "files":
+                                       print("!!! files dir is not added! 
Please correct this.")
+                                       sys.exit(-1)
+                               elif xs[-1] == "Manifest":
+                                       # It's a manifest... auto add
+                                       myautoadd += [myunadded[x]]
+                                       del myunadded[x]
+
+               if myunadded:
+                       print(red(
+                               "!!! The following files are in your local tree"
+                               " but are not added to the master"))
+                       print(red(
+                               "!!! tree. Please remove them from the local 
tree"
+                               " or add them to the master tree."))
+                       for x in myunadded:
+                               print("   ", x)
+                       print()
+                       print()
+                       sys.exit(1)
+               return myautoadd
+
+
+       def _vcs_deleted(self, mydeleted):
+               if self.vcs_settings.vcs == "hg" and mydeleted:
+                       print(red(
+                               "!!! The following files are removed manually"
+                               " from your local tree but are not"))
+                       print(red(
+                               "!!! removed from the repository."
+                               " Please remove them, using \"hg remove 
[FILES]\"."))
+                       for x in mydeleted:
+                               print("   ", x)
+                       print()
+                       print()
+                       sys.exit(1)

diff --git a/pym/repoman/main.py b/pym/repoman/main.py
index 2b2f91d..b6f88b2 100755
--- a/pym/repoman/main.py
+++ b/pym/repoman/main.py
@@ -4,16 +4,9 @@
 
 from __future__ import print_function, unicode_literals
 
-import errno
 import io
 import logging
-import re
-import signal
-import subprocess
 import sys
-import tempfile
-import platform
-from itertools import chain
 
 from os import path as osp
 if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), 
".portage_not_installed")):
@@ -26,36 +19,24 @@ portage._disable_legacy_globals()
 
 
 from portage import os
-from portage import _encodings
-from portage import _unicode_encode
-from _emerge.UserQuery import UserQuery
 import portage.checksum
 import portage.const
 import portage.repository.config
-from portage import cvstree
 from portage import util
-from portage.process import find_binary, spawn
-from portage.output import (
-       bold, create_color_func, green, nocolor, red)
+from portage.output import create_color_func, nocolor
 from portage.output import ConsoleStyleFile, StyleWriter
 from portage.util import formatter
-from portage.util import writemsg_level
-from portage.package.ebuild.digestgen import digestgen
 
+from repoman.actions import Actions
 from repoman.argparser import parse_args
 from repoman.checks.ebuilds.checks import checks_init
-from repoman.errors import err
-from repoman.gpg import gpgsign, need_signature
 from repoman.qa_data import (
        format_qa_output, format_qa_output_column, qahelp,
        qawarnings, qacats)
 from repoman.repos import RepoSettings
 from repoman.scanner import Scanner
-from repoman._subprocess import repoman_popen, repoman_getstatusoutput
 from repoman import utilities
-from repoman.vcs.vcs import (
-       git_supports_gpg_sign, vcs_files_to_cps, VCSSettings)
-
+from repoman.vcs.vcs import VCSSettings
 
 if sys.hexversion >= 0x3000000:
        basestring = str
@@ -107,7 +88,6 @@ def repoman_main(argv):
                config_root, portdir, portdir_overlay,
                repoman_settings, vcs_settings, options, qawarnings)
        repoman_settings = repo_settings.repoman_settings
-       portdb = repo_settings.portdb
 
        if 'digest' in repoman_settings.features and options.digest != 'n':
                options.digest = 'y'
@@ -131,27 +111,29 @@ def repoman_main(argv):
        if options.if_modified == "y" and len(scanner.effective_scanlist) < 1:
                logging.warning("--if-modified is enabled, but no modified 
packages were found!")
 
-       # dofail will be true if we have failed in at least one non-warning 
category
-       dofail = 0
-       # dowarn will be true if we tripped any warnings
-       dowarn = 0
-       # dofull will be true if we should print a "repoman full" informational 
message
-       dofull = options.mode != 'full'
+       result = {
+               # fail will be true if we have failed in at least one 
non-warning category
+               'fail': 0,
+               # warn will be true if we tripped any warnings
+               'warn': 0,
+               # full will be true if we should print a "repoman full" 
informational message
+               'full': options.mode != 'full',
+       }
 
        # early out for manifest generation
        if options.mode == "manifest":
-               sys.exit(dofail)
+               sys.exit(result['fail'])
 
        for x in qacats:
                if x not in qatracker.fails:
                        continue
-               dowarn = 1
+               result['warn'] = 1
                if x not in qawarnings:
-                       dofail = 1
+                       result['fail'] = 1
 
-       if dofail or \
-               (dowarn and not (options.quiet or options.mode == "scan")):
-               dofull = 0
+       if result['fail'] or \
+               (result['warn'] and not (options.quiet or options.mode == 
"scan")):
+               result['full'] = 0
 
        # Save QA output so that it can be conveniently displayed
        # in $EDITOR while the user creates a commit message.
@@ -174,707 +156,17 @@ def repoman_main(argv):
 
        format_output = format_outputs.get(
                options.output_style, format_outputs['default'])
-       format_output(f, qatracker.fails, dofull, dofail, options, qawarnings)
+       format_output(f, qatracker.fails, result['full'], result['fail'], 
options, qawarnings)
 
        style_file.flush()
        del console_writer, f, style_file
        qa_output = qa_output.getvalue()
        qa_output = qa_output.splitlines(True)
 
-       suggest_ignore_masked = False
-       suggest_include_dev = False
-
-       if scanner.have['pmasked'] and not (options.without_mask or 
options.ignore_masked):
-               suggest_ignore_masked = True
-       if scanner.have['dev_keywords'] and not options.include_dev:
-               suggest_include_dev = True
-
-       if suggest_ignore_masked or suggest_include_dev:
-               print()
-               if suggest_ignore_masked:
-                       print(bold(
-                               "Note: use --without-mask to check "
-                               "KEYWORDS on dependencies of masked packages"))
-
-               if suggest_include_dev:
-                       print(bold(
-                               "Note: use --include-dev (-d) to check "
-                               "dependencies for 'dev' profiles"))
-               print()
-
-       if options.mode != 'commit':
-               if dofull:
-                       print(bold("Note: type \"repoman full\" for a complete 
listing."))
-               if dowarn and not dofail:
-                       utilities.repoman_sez(
-                               "\"You're only giving me a partial QA 
payment?\n"
-                               "              I'll take it this time, but I'm 
not happy.\"")
-               elif not dofail:
-                       utilities.repoman_sez(
-                               "\"If everyone were like you, I'd be out of 
business!\"")
-               elif dofail:
-                       print(bad("Please fix these important QA issues 
first."))
-                       utilities.repoman_sez(
-                               "\"Make your QA payment on time"
-                               " and you'll never see the likes of me.\"\n")
-                       sys.exit(1)
-       else:
-               if dofail and can_force and options.force and not 
options.pretend:
-                       utilities.repoman_sez(
-                               " \"You want to commit even with these QA 
issues?\n"
-                               "              I'll take it this time, but I'm 
not happy.\"\n")
-               elif dofail:
-                       if options.force and not can_force:
-                               print(bad(
-                                       "The --force option has been disabled"
-                                       " due to extraordinary issues."))
-                       print(bad("Please fix these important QA issues 
first."))
-                       utilities.repoman_sez(
-                               "\"Make your QA payment on time"
-                               " and you'll never see the likes of me.\"\n")
-                       sys.exit(1)
-
-               if options.pretend:
-                       utilities.repoman_sez(
-                               "\"So, you want to play it safe. Good 
call.\"\n")
-
-               myunadded = []
-               if vcs_settings.vcs == "cvs":
-                       try:
-                               myvcstree = portage.cvstree.getentries("./", 
recursive=1)
-                               myunadded = portage.cvstree.findunadded(
-                                       myvcstree, recursive=1, basedir="./")
-                       except SystemExit as e:
-                               raise  # TODO propagate this
-                       except:
-                               err("Error retrieving CVS tree; exiting.")
-               if vcs_settings.vcs == "svn":
-                       try:
-                               with repoman_popen("svn status --no-ignore") as 
f:
-                                       svnstatus = f.readlines()
-                               myunadded = [
-                                       "./" + elem.rstrip().split()[1]
-                                       for elem in svnstatus
-                                       if elem.startswith("?") or 
elem.startswith("I")]
-                       except SystemExit as e:
-                               raise  # TODO propagate this
-                       except:
-                               err("Error retrieving SVN info; exiting.")
-               if vcs_settings.vcs == "git":
-                       # get list of files not under version control or missing
-                       myf = repoman_popen("git ls-files --others")
-                       myunadded = ["./" + elem[:-1] for elem in myf]
-                       myf.close()
-               if vcs_settings.vcs == "bzr":
-                       try:
-                               with repoman_popen("bzr status -S .") as f:
-                                       bzrstatus = f.readlines()
-                               myunadded = [
-                                       "./" + 
elem.rstrip().split()[1].split('/')[-1:][0]
-                                       for elem in bzrstatus
-                                       if elem.startswith("?") or elem[0:2] == 
" D"]
-                       except SystemExit as e:
-                               raise  # TODO propagate this
-                       except:
-                               err("Error retrieving bzr info; exiting.")
-               if vcs_settings.vcs == "hg":
-                       with repoman_popen("hg status --no-status --unknown .") 
as f:
-                               myunadded = f.readlines()
-                       myunadded = ["./" + elem.rstrip() for elem in myunadded]
-
-                       # Mercurial doesn't handle manually deleted files as 
removed from
-                       # the repository, so the user need to remove them 
before commit,
-                       # using "hg remove [FILES]"
-                       with repoman_popen("hg status --no-status --deleted .") 
as f:
-                               mydeleted = f.readlines()
-                       mydeleted = ["./" + elem.rstrip() for elem in mydeleted]
-
-               myautoadd = []
-               if myunadded:
-                       for x in range(len(myunadded) - 1, -1, -1):
-                               xs = myunadded[x].split("/")
-                               if 
repo_settings.repo_config.find_invalid_path_char(myunadded[x]) != -1:
-                                       # The Manifest excludes this file,
-                                       # so it's safe to ignore.
-                                       del myunadded[x]
-                               elif xs[-1] == "files":
-                                       print("!!! files dir is not added! 
Please correct this.")
-                                       sys.exit(-1)
-                               elif xs[-1] == "Manifest":
-                                       # It's a manifest... auto add
-                                       myautoadd += [myunadded[x]]
-                                       del myunadded[x]
-
-               if myunadded:
-                       print(red(
-                               "!!! The following files are in your local tree"
-                               " but are not added to the master"))
-                       print(red(
-                               "!!! tree. Please remove them from the local 
tree"
-                               " or add them to the master tree."))
-                       for x in myunadded:
-                               print("   ", x)
-                       print()
-                       print()
-                       sys.exit(1)
-
-               if vcs_settings.vcs == "hg" and mydeleted:
-                       print(red(
-                               "!!! The following files are removed manually"
-                               " from your local tree but are not"))
-                       print(red(
-                               "!!! removed from the repository."
-                               " Please remove them, using \"hg remove 
[FILES]\"."))
-                       for x in mydeleted:
-                               print("   ", x)
-                       print()
-                       print()
-                       sys.exit(1)
-
-               if vcs_settings.vcs == "cvs":
-                       mycvstree = cvstree.getentries("./", recursive=1)
-                       mychanged = cvstree.findchanged(mycvstree, recursive=1, 
basedir="./")
-                       mynew = cvstree.findnew(mycvstree, recursive=1, 
basedir="./")
-                       myremoved = portage.cvstree.findremoved(mycvstree, 
recursive=1, basedir="./")
-                       bin_blob_pattern = re.compile("^-kb$")
-                       no_expansion = set(portage.cvstree.findoption(
-                               mycvstree, bin_blob_pattern, recursive=1, 
basedir="./"))
-
-               if vcs_settings.vcs == "svn":
-                       with repoman_popen("svn status") as f:
-                               svnstatus = f.readlines()
-                       mychanged = [
-                               "./" + elem.split()[-1:][0]
-                               for elem in svnstatus
-                               if (elem[:1] in "MR" or elem[1:2] in "M")]
-                       mynew = [
-                               "./" + elem.split()[-1:][0]
-                               for elem in svnstatus
-                               if elem.startswith("A")]
-                       myremoved = [
-                               "./" + elem.split()[-1:][0]
-                               for elem in svnstatus
-                               if elem.startswith("D")]
-
-                       # Subversion expands keywords specified in svn:keywords 
properties.
-                       with repoman_popen("svn propget -R svn:keywords") as f:
-                               props = f.readlines()
-                       expansion = dict(
-                               ("./" + prop.split(" - ")[0], prop.split(" - 
")[1].split())
-                               for prop in props if " - " in prop)
-
-               elif vcs_settings.vcs == "git":
-                       with repoman_popen(
-                               "git diff-index --name-only "
-                               "--relative --diff-filter=M HEAD") as f:
-                               mychanged = f.readlines()
-                       mychanged = ["./" + elem[:-1] for elem in mychanged]
-
-                       with repoman_popen(
-                               "git diff-index --name-only "
-                               "--relative --diff-filter=A HEAD") as f:
-                               mynew = f.readlines()
-                       mynew = ["./" + elem[:-1] for elem in mynew]
-
-                       with repoman_popen(
-                               "git diff-index --name-only "
-                               "--relative --diff-filter=D HEAD") as f:
-                               myremoved = f.readlines()
-                       myremoved = ["./" + elem[:-1] for elem in myremoved]
-
-               if vcs_settings.vcs == "bzr":
-                       with repoman_popen("bzr status -S .") as f:
-                               bzrstatus = f.readlines()
-                       mychanged = [
-                               "./" + elem.split()[-1:][0].split('/')[-1:][0]
-                               for elem in bzrstatus
-                               if elem and elem[1:2] == "M"]
-                       mynew = [
-                               "./" + elem.split()[-1:][0].split('/')[-1:][0]
-                               for elem in bzrstatus
-                               if elem and (elem[1:2] in "NK" or elem[0:1] == 
"R")]
-                       myremoved = [
-                               "./" + elem.split()[-1:][0].split('/')[-1:][0]
-                               for elem in bzrstatus
-                               if elem.startswith("-")]
-                       myremoved = [
-                               "./" + elem.split()[-3:-2][0].split('/')[-1:][0]
-                               for elem in bzrstatus
-                               if elem and (elem[1:2] == "K" or elem[0:1] == 
"R")]
-                       # Bazaar expands nothing.
-
-               if vcs_settings.vcs == "hg":
-                       with repoman_popen("hg status --no-status --modified 
.") as f:
-                               mychanged = f.readlines()
-                       mychanged = ["./" + elem.rstrip() for elem in mychanged]
-
-                       with repoman_popen("hg status --no-status --added .") 
as f:
-                               mynew = f.readlines()
-                       mynew = ["./" + elem.rstrip() for elem in mynew]
-
-                       with repoman_popen("hg status --no-status --removed .") 
as f:
-                               myremoved = f.readlines()
-                       myremoved = ["./" + elem.rstrip() for elem in myremoved]
-
-               if vcs_settings.vcs:
-                       a_file_is_changed = mychanged or mynew or myremoved
-                       a_file_is_deleted_hg = vcs_settings.vcs == "hg" and 
mydeleted
-
-                       if not (a_file_is_changed or a_file_is_deleted_hg):
-                               utilities.repoman_sez(
-                                       "\"Doing nothing is not always good for 
QA.\"")
-                               print()
-                               print("(Didn't find any changed files...)")
-                               print()
-                               sys.exit(1)
-
-               # Manifests need to be regenerated after all other commits, so 
don't commit
-               # them now even if they have changed.
-               mymanifests = set()
-               myupdates = set()
-               for f in mychanged + mynew:
-                       if "Manifest" == os.path.basename(f):
-                               mymanifests.add(f)
-                       else:
-                               myupdates.add(f)
-               myupdates.difference_update(myremoved)
-               myupdates = list(myupdates)
-               mymanifests = list(mymanifests)
-               myheaders = []
-
-               commitmessage = options.commitmsg
-               if options.commitmsgfile:
-                       try:
-                               f = io.open(
-                                       _unicode_encode(
-                                               options.commitmsgfile,
-                                               encoding=_encodings['fs'], 
errors='strict'),
-                                       mode='r', 
encoding=_encodings['content'], errors='replace')
-                               commitmessage = f.read()
-                               f.close()
-                               del f
-                       except (IOError, OSError) as e:
-                               if e.errno == errno.ENOENT:
-                                       portage.writemsg(
-                                               "!!! File Not Found:"
-                                               " --commitmsgfile='%s'\n" % 
options.commitmsgfile)
-                               else:
-                                       raise
-                       # We've read the content so the file is no longer 
needed.
-                       commitmessagefile = None
-               if not commitmessage or not commitmessage.strip():
-                       msg_prefix = ""
-                       if scanner.repolevel > 1:
-                               msg_prefix = "/".join(scanner.reposplit[1:]) + 
": "
-
-                       try:
-                               editor = os.environ.get("EDITOR")
-                               if editor and 
utilities.editor_is_executable(editor):
-                                       commitmessage = 
utilities.get_commit_message_with_editor(
-                                               editor, message=qa_output, 
prefix=msg_prefix)
-                               else:
-                                       commitmessage = 
utilities.get_commit_message_with_stdin()
-                       except KeyboardInterrupt:
-                               logging.fatal("Interrupted; exiting...")
-                               sys.exit(1)
-                       if (not commitmessage or not commitmessage.strip()
-                                       or commitmessage.strip() == msg_prefix):
-                               print("* no commit message?  aborting commit.")
-                               sys.exit(1)
-               commitmessage = commitmessage.rstrip()
-               changelog_msg = commitmessage
-               portage_version = getattr(portage, "VERSION", None)
-               gpg_key = repoman_settings.get("PORTAGE_GPG_KEY", "")
-               dco_sob = repoman_settings.get("DCO_SIGNED_OFF_BY", "")
-               if portage_version is None:
-                       sys.stderr.write("Failed to insert portage version in 
message!\n")
-                       sys.stderr.flush()
-                       portage_version = "Unknown"
-
-               report_options = []
-               if options.force:
-                       report_options.append("--force")
-               if options.ignore_arches:
-                       report_options.append("--ignore-arches")
-               if scanner.include_arches is not None:
-                       report_options.append(
-                               "--include-arches=\"%s\"" %
-                               " ".join(sorted(scanner.include_arches)))
-
-               if vcs_settings.vcs == "git":
-                       # Use new footer only for git (see bug #438364).
-                       commit_footer = "\n\nPackage-Manager: portage-%s" % 
portage_version
-                       if report_options:
-                               commit_footer += "\nRepoMan-Options: " + " 
".join(report_options)
-                       if repo_settings.sign_manifests:
-                               commit_footer += "\nManifest-Sign-Key: %s" % 
(gpg_key, )
-                       if dco_sob:
-                               commit_footer += "\nSigned-off-by: %s" % 
(dco_sob, )
-               else:
-                       unameout = platform.system() + " "
-                       if platform.system() in ["Darwin", "SunOS"]:
-                               unameout += platform.processor()
-                       else:
-                               unameout += platform.machine()
-                       commit_footer = "\n\n"
-                       if dco_sob:
-                               commit_footer += "Signed-off-by: %s\n" % 
(dco_sob, )
-                       commit_footer += "(Portage version: %s/%s/%s" % \
-                               (portage_version, vcs_settings.vcs, unameout)
-                       if report_options:
-                               commit_footer += ", RepoMan options: " + " 
".join(report_options)
-                       if repo_settings.sign_manifests:
-                               commit_footer += ", signed Manifest commit with 
key %s" % \
-                                       (gpg_key, )
-                       else:
-                               commit_footer += ", unsigned Manifest commit"
-                       commit_footer += ")"
-
-               commitmessage += commit_footer
-
-               broken_changelog_manifests = []
-               if options.echangelog in ('y', 'force'):
-                       logging.info("checking for unmodified ChangeLog files")
-                       committer_name = 
utilities.get_committer_name(env=repoman_settings)
-                       for x in sorted(vcs_files_to_cps(
-                               chain(myupdates, mymanifests, myremoved),
-                               scanner.repolevel, scanner.reposplit, 
scanner.categories)):
-                               catdir, pkgdir = x.split("/")
-                               checkdir = repo_settings.repodir + "/" + x
-                               checkdir_relative = ""
-                               if scanner.repolevel < 3:
-                                       checkdir_relative = 
os.path.join(pkgdir, checkdir_relative)
-                               if scanner.repolevel < 2:
-                                       checkdir_relative = 
os.path.join(catdir, checkdir_relative)
-                               checkdir_relative = os.path.join(".", 
checkdir_relative)
-
-                               changelog_path = 
os.path.join(checkdir_relative, "ChangeLog")
-                               changelog_modified = changelog_path in 
scanner.changed.changelogs
-                               if changelog_modified and options.echangelog != 
'force':
-                                       continue
-
-                               # get changes for this package
-                               cdrlen = len(checkdir_relative)
-                               check_relative = lambda e: 
e.startswith(checkdir_relative)
-                               split_relative = lambda e: e[cdrlen:]
-                               clnew = list(map(split_relative, 
filter(check_relative, mynew)))
-                               clremoved = list(map(split_relative, 
filter(check_relative, myremoved)))
-                               clchanged = list(map(split_relative, 
filter(check_relative, mychanged)))
-
-                               # Skip ChangeLog generation if only the 
Manifest was modified,
-                               # as discussed in bug #398009.
-                               nontrivial_cl_files = set()
-                               nontrivial_cl_files.update(clnew, clremoved, 
clchanged)
-                               
nontrivial_cl_files.difference_update(['Manifest'])
-                               if not nontrivial_cl_files and 
options.echangelog != 'force':
-                                       continue
-
-                               new_changelog = utilities.UpdateChangeLog(
-                                       checkdir_relative, committer_name, 
changelog_msg,
-                                       os.path.join(repo_settings.repodir, 
'skel.ChangeLog'),
-                                       catdir, pkgdir,
-                                       new=clnew, removed=clremoved, 
changed=clchanged,
-                                       pretend=options.pretend)
-                               if new_changelog is None:
-                                       writemsg_level(
-                                               "!!! Updating the ChangeLog 
failed\n",
-                                               level=logging.ERROR, 
noiselevel=-1)
-                                       sys.exit(1)
-
-                               # if the ChangeLog was just created, add it to 
vcs
-                               if new_changelog:
-                                       myautoadd.append(changelog_path)
-                                       # myautoadd is appended to myupdates 
below
-                               else:
-                                       myupdates.append(changelog_path)
-
-                               if options.ask and not options.pretend:
-                                       # regenerate Manifest for modified 
ChangeLog (bug #420735)
-                                       repoman_settings["O"] = checkdir
-                                       digestgen(mysettings=repoman_settings, 
myportdb=portdb)
-                               else:
-                                       broken_changelog_manifests.append(x)
-
-               if myautoadd:
-                       print(">>> Auto-Adding missing Manifest/ChangeLog 
file(s)...")
-                       add_cmd = [vcs_settings.vcs, "add"]
-                       add_cmd += myautoadd
-                       if options.pretend:
-                               portage.writemsg_stdout(
-                                       "(%s)\n" % " ".join(add_cmd),
-                                       noiselevel=-1)
-                       else:
-
-                               if sys.hexversion < 0x3020000 and 
sys.hexversion >= 0x3000000 and \
-                                       not os.path.isabs(add_cmd[0]):
-                                       # Python 3.1 _execvp throws TypeError 
for non-absolute executable
-                                       # path passed as bytes (see 
http://bugs.python.org/issue8513).
-                                       fullname = find_binary(add_cmd[0])
-                                       if fullname is None:
-                                               raise 
portage.exception.CommandNotFound(add_cmd[0])
-                                       add_cmd[0] = fullname
-
-                               add_cmd = [_unicode_encode(arg) for arg in 
add_cmd]
-                               retcode = subprocess.call(add_cmd)
-                               if retcode != os.EX_OK:
-                                       logging.error(
-                                               "Exiting on %s error code: 
%s\n" % (vcs_settings.vcs, retcode))
-                                       sys.exit(retcode)
-
-                       myupdates += myautoadd
-
-               print("* %s files being committed..." % 
green(str(len(myupdates))), end=' ')
-
-               if vcs_settings.vcs not in ('cvs', 'svn'):
-                       # With git, bzr and hg, there's never any keyword 
expansion, so
-                       # there's no need to regenerate manifests and all files 
will be
-                       # committed in one big commit at the end.
-                       print()
-               elif not repo_settings.repo_config.thin_manifest:
-                       if vcs_settings.vcs == 'cvs':
-                               headerstring = "'\$(Header|Id).*\$'"
-                       elif vcs_settings.vcs == "svn":
-                               svn_keywords = dict((k.lower(), k) for k in [
-                                       "Rev",
-                                       "Revision",
-                                       "LastChangedRevision",
-                                       "Date",
-                                       "LastChangedDate",
-                                       "Author",
-                                       "LastChangedBy",
-                                       "URL",
-                                       "HeadURL",
-                                       "Id",
-                                       "Header",
-                               ])
-
-                       for myfile in myupdates:
-
-                               # for CVS, no_expansion contains files that are 
excluded from expansion
-                               if vcs_settings.vcs == "cvs":
-                                       if myfile in no_expansion:
-                                               continue
-
-                               # for SVN, expansion contains files that are 
included in expansion
-                               elif vcs_settings.vcs == "svn":
-                                       if myfile not in expansion:
-                                               continue
-
-                                       # Subversion keywords are 
case-insensitive
-                                       # in svn:keywords properties,
-                                       # but case-sensitive in contents of 
files.
-                                       enabled_keywords = []
-                                       for k in expansion[myfile]:
-                                               keyword = 
svn_keywords.get(k.lower())
-                                               if keyword is not None:
-                                                       
enabled_keywords.append(keyword)
-
-                                       headerstring = "'\$(%s).*\$'" % 
"|".join(enabled_keywords)
-
-                               myout = repoman_getstatusoutput(
-                                       "egrep -q %s %s" % (headerstring, 
portage._shell_quote(myfile)))
-                               if myout[0] == 0:
-                                       myheaders.append(myfile)
-
-                       print("%s have headers that will change." % 
green(str(len(myheaders))))
-                       print(
-                               "* Files with headers will"
-                               " cause the manifests to be changed and 
committed separately.")
-
-               logging.info("myupdates: %s", myupdates)
-               logging.info("myheaders: %s", myheaders)
-
-               uq = UserQuery(options)
-               if options.ask and uq.query('Commit changes?', True) != 'Yes':
-                       print("* aborting commit.")
-                       sys.exit(128 + signal.SIGINT)
-
-               # Handle the case where committed files have keywords which
-               # will change and need a priming commit before the Manifest
-               # can be committed.
-               if (myupdates or myremoved) and myheaders:
-                       myfiles = myupdates + myremoved
-                       fd, commitmessagefile = tempfile.mkstemp(".repoman.msg")
-                       mymsg = os.fdopen(fd, "wb")
-                       mymsg.write(_unicode_encode(commitmessage))
-                       mymsg.close()
-
-                       separator = '-' * 78
-
-                       print()
-                       print(green("Using commit message:"))
-                       print(green(separator))
-                       print(commitmessage)
-                       print(green(separator))
-                       print()
-
-                       # Having a leading ./ prefix on file paths can trigger 
a bug in
-                       # the cvs server when committing files to multiple 
directories,
-                       # so strip the prefix.
-                       myfiles = [f.lstrip("./") for f in myfiles]
-
-                       commit_cmd = [vcs_settings.vcs]
-                       commit_cmd.extend(vcs_settings.vcs_global_opts)
-                       commit_cmd.append("commit")
-                       commit_cmd.extend(vcs_settings.vcs_local_opts)
-                       commit_cmd.extend(["-F", commitmessagefile])
-                       commit_cmd.extend(myfiles)
-
-                       try:
-                               if options.pretend:
-                                       print("(%s)" % (" ".join(commit_cmd),))
-                               else:
-                                       retval = spawn(commit_cmd, 
env=repo_settings.commit_env)
-                                       if retval != os.EX_OK:
-                                               writemsg_level(
-                                                       "!!! Exiting on %s 
(shell) "
-                                                       "error code: %s\n" % 
(vcs_settings.vcs, retval),
-                                                       level=logging.ERROR, 
noiselevel=-1)
-                                               sys.exit(retval)
-                       finally:
-                               try:
-                                       os.unlink(commitmessagefile)
-                               except OSError:
-                                       pass
-
-               # When files are removed and re-added, the cvs server will put 
/Attic/
-               # inside the $Header path. This code detects the problem and 
corrects it
-               # so that the Manifest will generate correctly. See bug #169500.
-               # Use binary mode in order to avoid potential character 
encoding issues.
-               cvs_header_re = re.compile(br'^#\s*\$Header.*\$$')
-               attic_str = b'/Attic/'
-               attic_replace = b'/'
-               for x in myheaders:
-                       f = open(
-                               _unicode_encode(x, encoding=_encodings['fs'], 
errors='strict'),
-                               mode='rb')
-                       mylines = f.readlines()
-                       f.close()
-                       modified = False
-                       for i, line in enumerate(mylines):
-                               if cvs_header_re.match(line) is not None and \
-                                       attic_str in line:
-                                       mylines[i] = line.replace(attic_str, 
attic_replace)
-                                       modified = True
-                       if modified:
-                               portage.util.write_atomic(x, b''.join(mylines), 
mode='wb')
-
-               if scanner.repolevel == 1:
-                       utilities.repoman_sez(
-                               "\"You're rather crazy... "
-                               "doing the entire repository.\"\n")
-
-               if vcs_settings.vcs in ('cvs', 'svn') and (myupdates or 
myremoved):
-                       for x in sorted(vcs_files_to_cps(
-                               chain(myupdates, myremoved, mymanifests),
-                               scanner.repolevel, scanner.reposplit, 
scanner.categories)):
-                               repoman_settings["O"] = 
os.path.join(repo_settings.repodir, x)
-                               digestgen(mysettings=repoman_settings, 
myportdb=portdb)
-
-               elif broken_changelog_manifests:
-                       for x in broken_changelog_manifests:
-                               repoman_settings["O"] = 
os.path.join(repo_settings.repodir, x)
-                               digestgen(mysettings=repoman_settings, 
myportdb=portdb)
-
-               if repo_settings.sign_manifests:
-                       try:
-                               for x in sorted(vcs_files_to_cps(
-                                       chain(myupdates, myremoved, 
mymanifests),
-                                       scanner.repolevel, scanner.reposplit, 
scanner.categories)):
-                                       repoman_settings["O"] = 
os.path.join(repo_settings.repodir, x)
-                                       manifest_path = 
os.path.join(repoman_settings["O"], "Manifest")
-                                       if not need_signature(manifest_path):
-                                               continue
-                                       gpgsign(manifest_path, 
repoman_settings, options)
-                       except portage.exception.PortageException as e:
-                               portage.writemsg("!!! %s\n" % str(e))
-                               portage.writemsg("!!! Disabled 
FEATURES='sign'\n")
-                               repo_settings.sign_manifests = False
-
-               if vcs_settings.vcs == 'git':
-                       # It's not safe to use the git commit -a option since 
there might
-                       # be some modified files elsewhere in the working tree 
that the
-                       # user doesn't want to commit. Therefore, call git 
update-index
-                       # in order to ensure that the index is updated with the 
latest
-                       # versions of all new and modified files in the 
relevant portion
-                       # of the working tree.
-                       myfiles = mymanifests + myupdates
-                       myfiles.sort()
-                       update_index_cmd = ["git", "update-index"]
-                       update_index_cmd.extend(f.lstrip("./") for f in myfiles)
-                       if options.pretend:
-                               print("(%s)" % (" ".join(update_index_cmd),))
-                       else:
-                               retval = spawn(update_index_cmd, env=os.environ)
-                               if retval != os.EX_OK:
-                                       writemsg_level(
-                                               "!!! Exiting on %s (shell) "
-                                               "error code: %s\n" % 
(vcs_settings.vcs, retval),
-                                               level=logging.ERROR, 
noiselevel=-1)
-                                       sys.exit(retval)
-
-               if True:
-                       myfiles = mymanifests[:]
-                       # If there are no header (SVN/CVS keywords) changes in
-                       # the files, this Manifest commit must include the
-                       # other (yet uncommitted) files.
-                       if not myheaders:
-                               myfiles += myupdates
-                               myfiles += myremoved
-                       myfiles.sort()
-
-                       fd, commitmessagefile = tempfile.mkstemp(".repoman.msg")
-                       mymsg = os.fdopen(fd, "wb")
-                       mymsg.write(_unicode_encode(commitmessage))
-                       mymsg.close()
-
-                       commit_cmd = []
-                       if options.pretend and vcs_settings.vcs is None:
-                               # substitute a bogus value for pretend output
-                               commit_cmd.append("cvs")
-                       else:
-                               commit_cmd.append(vcs_settings.vcs)
-                       commit_cmd.extend(vcs_settings.vcs_global_opts)
-                       commit_cmd.append("commit")
-                       commit_cmd.extend(vcs_settings.vcs_local_opts)
-                       if vcs_settings.vcs == "hg":
-                               commit_cmd.extend(["--logfile", 
commitmessagefile])
-                               commit_cmd.extend(myfiles)
-                       else:
-                               commit_cmd.extend(["-F", commitmessagefile])
-                               commit_cmd.extend(f.lstrip("./") for f in 
myfiles)
-
-                       try:
-                               if options.pretend:
-                                       print("(%s)" % (" ".join(commit_cmd),))
-                               else:
-                                       retval = spawn(commit_cmd, 
env=repo_settings.commit_env)
-                                       if retval != os.EX_OK:
-                                               if 
repo_settings.repo_config.sign_commit and vcs_settings.vcs == 'git' and \
-                                                       not 
git_supports_gpg_sign():
-                                                       # Inform user that 
newer git is needed (bug #403323).
-                                                       logging.error(
-                                                               "Git >=1.7.9 is 
required for signed commits!")
-
-                                               writemsg_level(
-                                                       "!!! Exiting on %s 
(shell) "
-                                                       "error code: %s\n" % 
(vcs_settings.vcs, retval),
-                                                       level=logging.ERROR, 
noiselevel=-1)
-                                               sys.exit(retval)
-                       finally:
-                               try:
-                                       os.unlink(commitmessagefile)
-                               except OSError:
-                                       pass
-
-               print()
-               if vcs_settings.vcs:
-                       print("Commit complete.")
-               else:
-                       print(
-                               "repoman was too scared"
-                               " by not seeing any familiar version control 
file"
-                               " that he forgot to commit anything")
-               utilities.repoman_sez(
-                       "\"If everyone were like you, I'd be out of 
business!\"\n")
+       # output the results
+       actions = Actions(repo_settings, options, scanner, vcs_settings)
+       actions.inform(can_force, result)
+       # perform any other actions
+       actions.perform(qa_output)
+
        sys.exit(0)

Reply via email to