public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Brian Dolbec" <dolsen@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/portage:repoman commit in: pym/repoman/
Date: Sat, 19 Sep 2015 01:22:10 +0000 (UTC)	[thread overview]
Message-ID: <1442625548.e7607003f01c16b34def04d2069a72f140dfe999.dolsen@gentoo> (raw)

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	other threads:[~2015-09-19  1:22 UTC|newest]

Thread overview: 216+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-19  1:22 Brian Dolbec [this message]
  -- strict thread matches above, loose matches on Subject: below --
2016-05-03  9:33 [gentoo-commits] proj/portage:repoman commit in: pym/repoman/ Brian Dolbec
2016-04-29 17:24 [gentoo-commits] proj/portage:master " Brian Dolbec
2016-04-28 15:05 ` [gentoo-commits] proj/portage:repoman " Brian Dolbec
2016-04-29 17:24 [gentoo-commits] proj/portage:master " Brian Dolbec
2016-04-28 15:05 ` [gentoo-commits] proj/portage:repoman " Brian Dolbec
2016-04-29 17:24 [gentoo-commits] proj/portage:master " Brian Dolbec
2016-04-26 14:47 ` [gentoo-commits] proj/portage:repoman " Brian Dolbec
2016-04-28 15:05 Brian Dolbec
2016-04-27  5:22 Brian Dolbec
2016-04-27  5:22 Brian Dolbec
2016-04-27  5:22 Brian Dolbec
2016-04-26 18:08 Zac Medico
2016-04-25 15:32 Brian Dolbec
2016-04-25 15:32 Brian Dolbec
2016-04-25 15:32 Brian Dolbec
2016-04-21 16:54 Brian Dolbec
2016-04-21 16:54 Brian Dolbec
2016-04-21 16:54 Brian Dolbec
2016-04-21 16:54 Brian Dolbec
2016-04-17 15:42 Brian Dolbec
2016-04-16 20:00 Zac Medico
2016-03-15 19:00 Brian Dolbec
2016-03-12 18:10 Brian Dolbec
2016-03-12 18:10 Brian Dolbec
2016-03-12 18:10 Brian Dolbec
2016-03-11  0:41 Brian Dolbec
2016-03-11  0:41 Brian Dolbec
2016-03-11  0:41 Brian Dolbec
2016-03-07 21:53 Brian Dolbec
2016-03-07 21:53 Brian Dolbec
2016-03-07 21:53 Brian Dolbec
2016-02-01  7:55 Zac Medico
2016-02-01  7:21 Zac Medico
2016-01-31 20:03 Brian Dolbec
2016-01-31 20:03 Brian Dolbec
2016-01-31 20:03 Brian Dolbec
2016-01-30  8:00 Brian Dolbec
2016-01-30  8:00 Brian Dolbec
2016-01-30  8:00 Brian Dolbec
2016-01-30  6:58 Brian Dolbec
2016-01-30  6:58 Brian Dolbec
2016-01-30  6:58 Brian Dolbec
2016-01-29  5:01 Brian Dolbec
2016-01-29  5:01 Brian Dolbec
2016-01-29  5:01 Brian Dolbec
2016-01-27 23:15 Brian Dolbec
2016-01-27 23:15 Brian Dolbec
2016-01-27 23:15 Brian Dolbec
2016-01-23  1:42 Brian Dolbec
2016-01-23  1:42 Brian Dolbec
2016-01-23  1:42 Brian Dolbec
2016-01-22 20:55 Brian Dolbec
2016-01-22 20:55 Brian Dolbec
2016-01-22 20:55 Brian Dolbec
2016-01-21 19:42 Brian Dolbec
2016-01-21 19:42 Brian Dolbec
2016-01-21 19:15 Brian Dolbec
2016-01-21 18:30 Brian Dolbec
2016-01-21 18:30 Brian Dolbec
2016-01-18 19:23 Brian Dolbec
2016-01-18 19:23 Brian Dolbec
2016-01-11  8:01 Brian Dolbec
2016-01-11  8:01 Brian Dolbec
2016-01-11  6:31 Brian Dolbec
2016-01-11  6:31 Brian Dolbec
2016-01-11  6:31 Brian Dolbec
2016-01-10 20:17 Brian Dolbec
2016-01-10 20:17 Brian Dolbec
2016-01-10 20:17 Brian Dolbec
2016-01-10  3:26 Brian Dolbec
2016-01-10  3:26 Brian Dolbec
2016-01-10  3:26 Brian Dolbec
2016-01-06  4:21 Brian Dolbec
2016-01-06  4:21 Brian Dolbec
2015-12-30 23:38 Brian Dolbec
2015-09-21 23:51 [gentoo-commits] proj/portage:master " Brian Dolbec
2015-09-21 23:47 ` [gentoo-commits] proj/portage:repoman " Brian Dolbec
2015-09-21 23:51 [gentoo-commits] proj/portage:master " Brian Dolbec
2015-09-21 23:47 ` [gentoo-commits] proj/portage:repoman " Brian Dolbec
2015-09-21 23:51 [gentoo-commits] proj/portage:master " Brian Dolbec
2015-09-21 23:47 ` [gentoo-commits] proj/portage:repoman " Brian Dolbec
2015-09-21 23:51 [gentoo-commits] proj/portage:master " Brian Dolbec
2015-09-21 23:47 ` [gentoo-commits] proj/portage:repoman " Brian Dolbec
2015-09-21 23:51 [gentoo-commits] proj/portage:master " Brian Dolbec
2015-09-21 23:47 ` [gentoo-commits] proj/portage:repoman " Brian Dolbec
2015-09-21 23:47 Brian Dolbec
2015-09-21 23:47 Brian Dolbec
2015-09-21 23:47 Brian Dolbec
2015-09-21 23:47 Brian Dolbec
2015-09-21 23:47 Brian Dolbec
2015-09-21 23:47 Brian Dolbec
2015-09-21 23:47 Brian Dolbec
2015-09-21 23:47 Brian Dolbec
2015-09-21 23:47 Brian Dolbec
2015-09-21 23:47 Brian Dolbec
2015-09-21 23:47 Brian Dolbec
2015-09-21 23:47 Brian Dolbec
2015-09-20  2:06 Brian Dolbec
2015-09-20  2:06 Brian Dolbec
2015-09-20  2:06 Brian Dolbec
2015-09-20  2:06 Brian Dolbec
2015-09-20  2:06 Brian Dolbec
2015-09-20  2:06 Brian Dolbec
2015-09-20  2:06 Brian Dolbec
2015-09-20  2:06 Brian Dolbec
2015-09-20  2:06 Brian Dolbec
2015-09-20  2:06 Brian Dolbec
2015-09-20  2:06 Brian Dolbec
2015-09-20  2:06 Brian Dolbec
2015-09-20  2:06 Brian Dolbec
2015-09-20  2:06 Brian Dolbec
2015-09-20  2:06 Brian Dolbec
2015-09-20  2:06 Brian Dolbec
2015-09-20  2:06 Brian Dolbec
2015-09-20  0:20 Brian Dolbec
2015-09-19 17:32 Brian Dolbec
2015-09-19 16:48 Brian Dolbec
2015-09-19 16:28 Brian Dolbec
2015-09-19 16:28 Brian Dolbec
2015-09-19  4:36 Brian Dolbec
2015-09-19  4:36 Brian Dolbec
2015-09-19  4:36 Brian Dolbec
2015-09-19  4:36 Brian Dolbec
2015-09-19  4:36 Brian Dolbec
2015-09-19  4:36 Brian Dolbec
2015-09-19  4:36 Brian Dolbec
2015-09-19  4:36 Brian Dolbec
2015-09-19  4:36 Brian Dolbec
2015-09-19  4:36 Brian Dolbec
2015-09-19  1:22 Brian Dolbec
2015-09-17 18:58 Brian Dolbec
2015-09-17 18:58 Brian Dolbec
2015-09-17 15:32 Brian Dolbec
2015-09-17  4:51 Brian Dolbec
2015-09-17  4:51 Brian Dolbec
2015-09-17  4:51 Brian Dolbec
2015-09-17  4:51 Brian Dolbec
2015-09-17  4:51 Brian Dolbec
2015-09-17  4:51 Brian Dolbec
2015-09-17  4:51 Brian Dolbec
2015-09-17  4:51 Brian Dolbec
2015-09-17  4:51 Brian Dolbec
2015-09-17  3:08 Brian Dolbec
2015-09-17  3:08 Brian Dolbec
2015-09-17  3:08 Brian Dolbec
2015-09-17  3:08 Brian Dolbec
2015-09-17  3:08 Brian Dolbec
2015-09-17  3:08 Brian Dolbec
2015-09-17  3:08 Brian Dolbec
2015-09-17  3:08 Brian Dolbec
2015-09-17  3:08 Brian Dolbec
2015-09-17  2:45 Brian Dolbec
2015-09-17  2:45 Brian Dolbec
2015-09-17  2:45 Brian Dolbec
2015-09-05 21:48 Brian Dolbec
2015-09-05 21:48 Brian Dolbec
2015-09-05 21:48 Brian Dolbec
2015-09-05 21:48 Brian Dolbec
2015-09-05 21:48 Brian Dolbec
2015-09-05 21:48 Brian Dolbec
2015-09-05 21:27 Brian Dolbec
2015-09-05 21:27 Brian Dolbec
2015-09-05 21:27 Brian Dolbec
2015-09-05 21:27 Brian Dolbec
2015-09-05 21:27 Brian Dolbec
2015-09-05 21:27 Brian Dolbec
2015-08-11 23:54 Brian Dolbec
2015-08-11 23:54 Brian Dolbec
2015-08-11 23:54 Brian Dolbec
2015-08-11 23:54 Brian Dolbec
2015-08-11 23:54 Brian Dolbec
2015-08-11 23:54 Brian Dolbec
2015-08-10 14:45 Michał Górny
2015-08-10 14:45 Michał Górny
2015-08-10 14:45 Michał Górny
2015-08-10 14:45 Michał Górny
2015-08-10 14:45 Michał Górny
2015-08-10 14:45 Michał Górny
2015-08-10 13:44 Brian Dolbec
2015-08-10 13:44 Brian Dolbec
2015-08-10 13:44 Brian Dolbec
2015-08-10 13:44 Brian Dolbec
2015-08-10 13:44 Brian Dolbec
2015-08-10 13:44 Brian Dolbec
2014-11-17  2:08 Brian Dolbec
2014-11-17  0:55 Brian Dolbec
2014-11-17  0:55 Brian Dolbec
2014-11-17  0:55 Brian Dolbec
2014-11-17  0:55 Brian Dolbec
2014-11-17  0:55 Brian Dolbec
2014-10-01 23:46 Brian Dolbec
2014-10-01 23:46 Brian Dolbec
2014-10-01 23:46 Brian Dolbec
2014-10-01 23:46 Brian Dolbec
2014-10-01 23:46 Brian Dolbec
2014-10-01 23:02 Brian Dolbec
2014-10-01 23:02 Brian Dolbec
2014-10-01 23:02 Brian Dolbec
2014-10-01 23:02 Brian Dolbec
2014-10-01 23:02 Brian Dolbec
2014-06-03 19:33 Brian Dolbec
2014-06-03 18:15 Brian Dolbec
2014-06-03 18:15 Brian Dolbec
2014-06-03 11:29 Tom Wijsman
2014-06-02 17:01 Tom Wijsman
2014-06-02 15:44 Brian Dolbec
2014-06-02 15:44 Brian Dolbec
2014-06-02 15:44 Brian Dolbec
2014-06-02 15:01 Tom Wijsman
2014-06-02 14:24 Brian Dolbec
2014-06-02 14:11 Tom Wijsman
2014-06-02  1:10 Brian Dolbec
2014-06-02  1:10 Brian Dolbec
2014-05-30 13:03 Brian Dolbec
2014-05-30 13:03 Brian Dolbec
2014-05-30 13:03 Brian Dolbec
2014-05-27  6:04 Brian Dolbec
2014-05-27  6:04 Brian Dolbec
2014-05-27  6:04 Brian Dolbec
2014-05-27  6:04 Brian Dolbec
2014-05-27  5:04 Brian Dolbec
2014-05-27  5:04 Brian Dolbec
2014-05-27  5:04 Brian Dolbec

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1442625548.e7607003f01c16b34def04d2069a72f140dfe999.dolsen@gentoo \
    --to=dolsen@gentoo.org \
    --cc=gentoo-commits@lists.gentoo.org \
    --cc=gentoo-dev@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox