Add colors to output and make output consistent.

- Run all error and warning messages through one standard function
- Use one standard function to abort Tito
- Consistently print errors to stderr
This commit is contained in:
Alex Wood 2015-06-04 16:58:54 -04:00
parent d489dd9c3f
commit 53144dc63e
8 changed files with 90 additions and 82 deletions

View file

@ -12,7 +12,6 @@
# in this software or its documentation.
import re
import os
import os.path
import shutil
@ -43,8 +42,7 @@ class FetchBuilder(ConfigObject, BuilderBase):
user_config=user_config, args=args, **kwargs)
if tag:
error_out("FetchBuilder does not support building "
"specific tags.")
error_out("FetchBuilder does not support building specific tags.")
if not config.has_option("builder",
"fetch_strategy"):
@ -56,8 +54,7 @@ class FetchBuilder(ConfigObject, BuilderBase):
'tito.builder.fetch.ArgSourceStrategy')
self.build_tag = '%s-%s' % (self.project_name,
get_spec_version_and_release(self.start_dir,
'%s.spec' % self.project_name))
get_spec_version_and_release(self.start_dir, '%s.spec' % self.project_name))
def tgz(self):
self.ran_tgz = True

View file

@ -32,7 +32,7 @@ from tito.common import scl_to_rpm_option, get_latest_tagged_version, \
get_commit_count, find_gemspec_file, create_builder, compare_version,\
find_cheetah_template_file, render_cheetah, replace_spec_release, \
find_spec_like_file, warn_out, get_commit_timestamp, chdir, mkdir_p, \
find_git_root
find_git_root, info_out
from tito.compat import getoutput, getstatusoutput
from tito.exception import RunCommandException
from tito.exception import TitoException
@ -127,7 +127,7 @@ class BuilderBase(object):
NOTE: this method may do nothing if the user requested no build actions
be performed. (i.e. only release tagging, etc)
"""
print("Building package [%s]" % (self.build_tag))
info_out("Building package [%s]" % (self.build_tag))
self.no_cleanup = options.no_cleanup
# Reset list of artifacts on each call to run().
@ -257,7 +257,7 @@ class BuilderBase(object):
self.artifacts.extend(files_written)
print
print("Successfully built: %s" % ' '.join(files_written))
info_out("Successfully built: %s" % ' '.join(files_written))
def _scl_to_rpmbuild_option(self):
""" Returns rpmbuild option which disable or enable SC and print warning if needed """
@ -350,10 +350,11 @@ class Builder(ConfigObject, BuilderBase):
if self.config.has_option("requirements", "tito"):
if loose_version(self.config.get("requirements", "tito")) > \
loose_version(require('tito')[0].version):
print("Error: tito version %s or later is needed to build this project." %
self.config.get("requirements", "tito"))
print("Your version: %s" % require('tito')[0].version)
sys.exit(-1)
error_out([
"tito version %s or later is needed to build this project." %
self.config.get("requirements", "tito"),
"Your version: %s" % require('tito')[0].version
])
self.display_version = self._get_display_version()
@ -364,8 +365,6 @@ class Builder(ConfigObject, BuilderBase):
self.relative_project_dir = get_relative_project_dir(
project_name=self.project_name, commit=self.git_commit_id)
if self.relative_project_dir is None and self.test:
sys.stderr.write("WARNING: .tito/packages/%s doesn't exist "
"in git, using current directory\n" % self.project_name)
warn_out(".tito/packages/%s doesn't exist "
"in git, using current directory" % self.project_name)
self.relative_project_dir = get_relative_project_dir_cwd(
@ -447,7 +446,7 @@ class Builder(ConfigObject, BuilderBase):
self.ran_tgz = True
full_path = os.path.join(self.rpmbuild_basedir, self.tgz_filename)
print("Wrote: %s" % full_path)
info_out("Wrote: %s" % full_path)
self.sources.append(full_path)
self.artifacts.append(full_path)
return full_path
@ -925,7 +924,7 @@ class MeadBuilder(Builder):
if status == 0:
try:
print("Running Maven build...")
info_out("Running Maven build...")
# We always want to deploy to a tito controlled location during local builds
local_properties = formatted_properties + [
"-DaltDeploymentRepository=local-output::default::file://%s" % self.deploy_dir]
@ -1011,7 +1010,7 @@ class MeadBuilder(Builder):
# that use a git SHA1 for their version.
self.spec_file = os.path.join(self.rpmbuild_gitcopy, self.spec_file_name)
print("Wrote: %s" % destination_file)
info_out("Wrote: %s" % destination_file)
self.sources.append(destination_file)
self.artifacts.append(destination_file)
self.ran_tgz = True
@ -1125,7 +1124,7 @@ class MockBuilder(Builder):
run_command("cp -v %s/*.rpm %s" %
(mock_output_dir, self.rpmbuild_basedir))
print
print("Wrote:")
info_out("Wrote:")
for rpm in files:
rpm_path = os.path.join(self.rpmbuild_basedir, rpm)
print(" %s" % rpm_path)
@ -1176,7 +1175,7 @@ class BrewDownloadBuilder(Builder):
run_command("cp -v %s/*.rpm %s" %
(self.rpmbuild_dir, self.rpmbuild_basedir))
print
print("Wrote:")
info_out("Wrote:")
for rpm in files:
# Just incase anything slips into the build dir:
if not rpm.endswith(".rpm"):

View file

@ -22,7 +22,7 @@ from optparse import OptionParser, SUPPRESS_HELP
from tito.common import find_git_root, error_out, debug, get_class_by_name, \
DEFAULT_BUILDER, BUILDCONFIG_SECTION, DEFAULT_TAGGER, \
create_builder, get_project_name, get_relative_project_dir, \
DEFAULT_BUILD_DIR, run_command, tito_config_dir
DEFAULT_BUILD_DIR, run_command, tito_config_dir, warn_out, info_out
from tito.compat import RawConfigParser, getstatusoutput, getoutput
from tito.exception import TitoException
@ -105,15 +105,15 @@ class ConfigLoader(object):
if config.has_section('globalconfig'):
if not config.has_section('buildconfig'):
config.add_section('buildconfig')
print("WARNING: Please rename [globalconfig] to [buildconfig] in "
warn_out("Please rename [globalconfig] to [buildconfig] in "
"tito.props")
for k, v in config.items('globalconfig'):
if k == 'default_builder':
print("WARNING: please rename 'default_builder' to "
warn_out("please rename 'default_builder' to "
"'builder' in tito.props")
config.set('buildconfig', 'builder', v)
elif k == 'default_tagger':
print("WARNING: please rename 'default_tagger' to "
warn_out("please rename 'default_tagger' to "
"'tagger' in tito.props")
config.set('buildconfig', 'tagger', v)
else:
@ -300,8 +300,7 @@ class BaseCliModule(object):
sys.path.append(lib_dir)
debug("Added lib dir to PYTHONPATH: %s" % lib_dir)
else:
print("WARNING: lib_dir specified but does not exist: %s" %
lib_dir)
warn_out("lib_dir specified but does not exist: %s" % lib_dir)
def _validate_options(self):
"""
@ -507,7 +506,7 @@ class ReleaseModule(BaseCliModule):
# Handle koji:
if self.config.has_section("koji") and not \
releaser_config.has_section("koji"):
print("WARNING: legacy 'koji' section in tito.props, please "
warn_out("legacy 'koji' section in tito.props, please "
"consider creating a target in releasers.conf.")
print("Simulating 'koji' release target for now.")
releaser_config.add_section('koji')
@ -755,7 +754,7 @@ class InitModule(BaseCliModule):
getoutput('git commit -m "Initialized to use tito. "')
print(" - committed to git")
print("Done!")
info_out("Done!")
return []

View file

@ -10,6 +10,8 @@
# Red Hat trademarks are not licensed under GPLv2. No permission is
# granted to use or replicate Red Hat trademarks that are incorporated
# in this software or its documentation.
from __future__ import print_function
from contextlib import contextmanager
"""
Common operations.
@ -185,32 +187,35 @@ class BugzillaExtractor(object):
return bugzilla.getbug(bug_id, include_fields=['id', 'flags'])
def _out(msgs, prefix, color_func):
def _out(msgs, prefix, color_func, stream=sys.stdout):
if prefix is None:
fmt = "%(msg)s"
else:
fmt = "%(prefix)s: %(msg)s"
if isinstance(msgs, list):
first_line = msgs.pop(0)
print(color_func(fmt % {'prefix': prefix, 'msg': first_line}), file=stream)
for line in msgs:
print(color_func(fmt % {'prefix': prefix, 'msg': line}))
print(color_func("%s" % line), file=stream)
else:
print(color_func(fmt % {'prefix': prefix, 'msg': msgs}))
print(color_func(fmt % {'prefix': prefix, 'msg': msgs}), file=stream)
def error_out(error_msgs):
def error_out(error_msgs, die=True):
"""
Print the given error message (or list of messages) and exit.
"""
term = Terminal()
_out(error_msgs, "ERROR", term.red)
sys.exit(1)
_out(error_msgs, "ERROR", term.red, sys.stderr)
if die:
sys.exit(1)
def info_out(msgs):
term = Terminal()
_out(msgs, None, term.blue)
sys.exit(1)
def warn_out(msgs):
"""
@ -375,10 +380,12 @@ def run_command(command, print_on_success=False):
"""
(status, output) = getstatusoutput(command)
if status > 0:
sys.stderr.write("\n########## ERROR ############\n")
sys.stderr.write("Error running command: %s\n" % command)
sys.stderr.write("Status code: %s\n" % status)
sys.stderr.write("Command output: %s\n" % output)
msgs = [
"Error running command: %s\n" % command,
"Status code: %s\n" % status,
"Command output: %s\n" % output,
]
error_out(msgs, die=False)
raise RunCommandException(command, status, output)
elif print_on_success:
print("Command: %s\n" % command)
@ -457,7 +464,7 @@ def tag_exists_remotely(tag):
try:
get_git_repo_url()
except:
sys.stderr.write('Warning: remote.origin do not exist. Assuming --offline, for remote tag checking.\n')
warn_out('remote.origin does not exist. Assuming --offline, for remote tag checking.\n')
return False
sha1 = get_remote_tag_sha1(tag)
debug("sha1 = %s" % sha1)
@ -533,7 +540,7 @@ def check_tag_exists(tag, offline=False):
try:
get_git_repo_url()
except:
sys.stderr.write('Warning: remote.origin do not exist. Assuming --offline, for remote tag checking.\n')
warn_out('remote.origin does not exist. Assuming --offline, for remote tag checking.\n')
return
upstream_tag_sha1 = get_remote_tag_sha1(tag)
if upstream_tag_sha1 == "":
@ -632,13 +639,17 @@ def scl_to_rpm_option(scl, silent=None):
output = run_command(cmd).rstrip()
if scl:
if (output != scl) and (output != "%scl") and not silent:
print("Warning: Meta package of software collection %s installed, but --scl defines %s" % (output, scl))
print(" Redefining scl macro to %s for this package." % scl)
warn_out([
"Meta package of software collection %s installed, but --scl defines %s" % (output, scl),
"Redefining scl macro to %s for this package." % scl
])
rpm_options += " --define 'scl %s'" % scl
else:
if (output != "%scl") and (not silent):
print("Warning: Meta package of software collection %s installed, but --scl is not present." % output)
print(" Undefining scl macro for this package.")
warn_out([
"Warning: Meta package of software collection %s installed, but --scl is not present." % output,
"Undefining scl macro for this package.",
])
# can be replaced by "--undefined scl" when el6 and fc17 is retired
rpm_options += " --eval '%undefine scl'"
return rpm_options
@ -873,7 +884,7 @@ def normalize_class_name(name):
"""
look_for = "spacewalk.releng."
if name.startswith(look_for):
sys.stderr.write("Warning: spacewalk.releng.* namespace in tito.props is obsolete. Use tito.* instead.\n")
warn_out("spacewalk.releng.* namespace in tito.props is obsolete. Use tito.* instead.\n")
name = "%s%s" % ("tito.", name[len(look_for):])
return name

View file

@ -11,10 +11,9 @@
# granted to use or replicate Red Hat trademarks that are incorporated
# in this software or its documentation.
import os
import os.path
from tito.common import run_command
from tito.common import run_command, info_out
from tito.release import KojiReleaser
@ -70,5 +69,5 @@ class CoprReleaser(KojiReleaser):
print("Uploading src.rpm.")
print(run_command(cmd_upload))
self.srpm_submitted = srpm_location
print("Submiting build into %s." % self.NAME)
info_out("Submiting build into %s." % self.NAME)
print(run_command(cmd_submit))

View file

@ -17,12 +17,12 @@ import sys
import tempfile
from tito.common import run_command, BugzillaExtractor, debug, extract_sources, \
MissingBugzillaCredsException, error_out, chdir, warn_out
MissingBugzillaCredsException, error_out, chdir, warn_out, info_out
from tito.compat import getoutput, getstatusoutput, write
from tito.release import Releaser
from tito.release.main import PROTECTED_BUILD_SYS_FILES
from tito.buildparser import BuildTargetParser
from tito.exception import RunCommandException, ConfigException
from tito.exception import RunCommandException
import getpass
MEAD_SCM_USERNAME = 'MEAD_SCM_USERNAME'
@ -220,7 +220,7 @@ class FedoraGitReleaser(Releaser):
self._build(main_branch)
for branch in self.git_branches[1:]:
print("Merging branch: '%s' -> '%s'" % (main_branch, branch))
info_out("Merging branch: '%s' -> '%s'" % (main_branch, branch))
run_command("%s switch-branch %s" % (self.cli_tool, branch))
self._merge(main_branch)
@ -244,7 +244,7 @@ class FedoraGitReleaser(Releaser):
run_command("git merge %s" % main_branch)
except:
print
print("WARNING!!! Conflicts occurred during merge.")
warn_out("Conflicts occurred during merge.")
print
print("You are being dropped to a shell in the working directory.")
print
@ -274,16 +274,17 @@ class FedoraGitReleaser(Releaser):
self.print_dry_run_warning(build_cmd)
return
print("Submitting build: %s" % build_cmd)
info_out("Submitting build: %s" % build_cmd)
(status, output) = getstatusoutput(build_cmd)
if status > 0:
if "already been built" in output:
print("Build has been submitted previously, continuing...")
warn_out("Build has been submitted previously, continuing...")
else:
sys.stderr.write("ERROR: Unable to submit build.\n")
sys.stderr.write(" Status code: %s\n" % status)
sys.stderr.write(" Output: %s\n" % output)
sys.exit(1)
error_out([
"Unable to submit build."
" Status code: %s\n" % status,
" Output: %s\n" % output,
])
# Print the task ID and URL:
for line in extract_task_info(output):
@ -457,7 +458,7 @@ class DistGitMeadReleaser(DistGitReleaser):
return
with chdir(self.git_root):
print("Syncing local repo with %s" % self.push_url)
info_out("Syncing local repo with %s" % self.push_url)
try:
run_command(cmd)
except RunCommandException as e:
@ -516,16 +517,17 @@ class DistGitMeadReleaser(DistGitReleaser):
self.print_dry_run_warning(build_cmd)
return
print("Submitting build: %s" % build_cmd)
info_out("Submitting build: %s" % build_cmd)
(status, output) = getstatusoutput(build_cmd)
if status > 0:
if "already been built" in output:
print("Build has been submitted previously, continuing...")
warn_out("Build has been submitted previously, continuing...")
else:
sys.stderr.write("ERROR: Unable to submit build.\n")
sys.stderr.write(" Status code: %s\n" % status)
sys.stderr.write(" Output: %s\n" % output)
sys.exit(1)
error_out([
"Unable to submit build.",
" Status code: %s\n" % status,
" Output: %s\n" % output,
])
# Print the task ID and URL:
for line in extract_task_info(output):

View file

@ -507,14 +507,16 @@ class KojiReleaser(Releaser):
# whitelist implies only those packages can be built to the
# tag,regardless if blacklist is also defined.
if not self.__is_whitelisted(koji_tag, scl):
warn_out("%s not specified in whitelist for %s" % (
self.project_name, koji_tag))
print(" Package *NOT* submitted to %s." % self.NAME)
warn_out([
"%s not specified in whitelist for %s" % (self.project_name, koji_tag),
" Package *NOT* submitted to %s." % self.NAME,
])
continue
elif self.__is_blacklisted(koji_tag, scl):
warn_out("%s specified in blacklist for %s" % (
self.project_name, koji_tag))
print(" Package *NOT* submitted to %s." % self.NAME)
warn_out([
"%s specified in blacklist for %s" % (self.project_name, koji_tag),
" Package *NOT* submitted to %s." % self.NAME,
])
continue
# Getting tricky here, normally Builder's are only used to

View file

@ -31,8 +31,8 @@ from tito.common import (debug, error_out, run_command,
find_spec_like_file, get_project_name, get_latest_tagged_version,
get_spec_version_and_release, replace_version,
tag_exists_locally, tag_exists_remotely, head_points_to_tag, undo_tag,
increase_version, reset_release, increase_zstream,
BUILDCONFIG_SECTION, get_relative_project_dir_cwd)
increase_version, reset_release, increase_zstream, warn_out,
BUILDCONFIG_SECTION, get_relative_project_dir_cwd, info_out)
from tito.compat import write, StringIO, getstatusoutput
from tito.exception import TitoException
from tito.config_object import ConfigObject
@ -83,7 +83,7 @@ class VersionTagger(ConfigObject):
be performed. (i.e. only release tagging, etc)
"""
if options.tag_release:
print("WARNING: --tag-release option no longer necessary,"
warn_out("--tag-release option no longer necessary,"
" 'tito tag' will accomplish the same thing.")
if options.no_auto_changelog:
self._no_auto_changelog = True
@ -137,7 +137,7 @@ class VersionTagger(ConfigObject):
"""
tag = "%s-%s" % (self.project_name,
get_latest_tagged_version(self.project_name))
print("Undoing tag: %s" % tag)
info_out("Undoing tag: %s" % tag)
if not tag_exists_locally(tag):
raise TitoException(
"Cannot undo tag that does not exist locally.")
@ -264,7 +264,7 @@ class VersionTagger(ConfigObject):
os.unlink(name)
if not found_changelog:
print("WARNING: no %changelog section find in spec file. Changelog entry was not appended.")
warn_out("no %changelog section find in spec file. Changelog entry was not appended.")
in_f.close()
out_f.close()
@ -424,7 +424,7 @@ class VersionTagger(ConfigObject):
msg = "Error getting bumped package version, try: \n"
msg = msg + " 'rpm -q --specfile %s'" % self.spec_file
error_out(msg)
print("Tagging new version of %s: %s -> %s" % (self.project_name,
info_out("Tagging new version of %s: %s -> %s" % (self.project_name,
old_version, new_version))
return new_version
@ -473,7 +473,7 @@ class VersionTagger(ConfigObject):
new_tag = self._get_new_tag(new_version)
run_command('git tag -m "%s" %s' % (tag_msg, new_tag))
print
print("Created tag: %s" % new_tag)
info_out("Created tag: %s" % new_tag)
print(" View: git show HEAD")
print(" Undo: tito tag -u")
print(" Push: git push origin && git push origin %s" % new_tag)
@ -513,8 +513,7 @@ class VersionTagger(ConfigObject):
debug("Updating %s with new version." %
metadata_file)
else:
print("WARNING: %s also references %s" % (filename,
self.relative_project_dir))
warn_out("%s also references %s" % (filename, self.relative_project_dir))
print("Assuming package has been renamed and removing it.")
run_command("git rm %s" % metadata_file)
@ -523,12 +522,12 @@ class VersionTagger(ConfigObject):
try:
name = run_command('git config --get user.name')
except:
sys.stderr.write('Warning: user.name in ~/.gitconfig not set.\n')
warn_out('user.name in ~/.gitconfig not set.\n')
name = 'Unknown name'
try:
email = run_command('git config --get user.email')
except:
sys.stderr.write('Warning: user.email in ~/.gitconfig not set.\n')
warn_out('user.email in ~/.gitconfig not set.\n')
email = None
return (name, email)