summaryrefslogtreecommitdiffstats
path: root/gitlint/cli.py
diff options
context:
space:
mode:
Diffstat (limited to 'gitlint/cli.py')
-rw-r--r--gitlint/cli.py100
1 files changed, 51 insertions, 49 deletions
diff --git a/gitlint/cli.py b/gitlint/cli.py
index f284792..b162e5b 100644
--- a/gitlint/cli.py
+++ b/gitlint/cli.py
@@ -8,19 +8,20 @@ import stat
import sys
import click
-# Error codes
-MAX_VIOLATION_ERROR_CODE = 252 # noqa
-USAGE_ERROR_CODE = 253 # noqa
-GIT_CONTEXT_ERROR_CODE = 254 # noqa
-CONFIG_ERROR_CODE = 255 # noqa
-
import gitlint
from gitlint.lint import GitLinter
from gitlint.config import LintConfigBuilder, LintConfigError, LintConfigGenerator
from gitlint.git import GitContext, GitContextError, git_version
from gitlint import hooks
from gitlint.shell import shell
-from gitlint.utils import ustr, LOG_FORMAT, IS_PY2
+from gitlint.utils import LOG_FORMAT
+from gitlint.exception import GitlintError
+
+# Error codes
+MAX_VIOLATION_ERROR_CODE = 252
+USAGE_ERROR_CODE = 253
+GIT_CONTEXT_ERROR_CODE = 254
+CONFIG_ERROR_CODE = 255
DEFAULT_CONFIG_FILE = ".gitlint"
# -n: disable swap files. This fixes a vim error on windows (E303: Unable to open swap file for <path>)
@@ -34,7 +35,7 @@ click.UsageError.exit_code = USAGE_ERROR_CODE
LOG = logging.getLogger("gitlint.cli")
-class GitLintUsageError(Exception):
+class GitLintUsageError(GitlintError):
""" Exception indicating there is an issue with how gitlint is used. """
pass
@@ -134,7 +135,7 @@ def get_stdin_data():
# Only return the input data if there's actually something passed
# i.e. don't consider empty piped data
if input_data:
- return ustr(input_data)
+ return str(input_data)
return False
@@ -151,7 +152,7 @@ def build_git_context(lint_config, msg_filename, refspec):
# 1. Any data specified via --msg-filename
if msg_filename:
LOG.debug("Using --msg-filename.")
- return from_commit_msg(ustr(msg_filename.read()))
+ return from_commit_msg(str(msg_filename.read()))
# 2. Any data sent to stdin (unless stdin is being ignored)
if not lint_config.ignore_stdin:
@@ -162,15 +163,28 @@ def build_git_context(lint_config, msg_filename, refspec):
return from_commit_msg(stdin_input)
if lint_config.staged:
- raise GitLintUsageError(u"The 'staged' option (--staged) can only be used when using '--msg-filename' or "
- u"when piping data to gitlint via stdin.")
+ raise GitLintUsageError("The 'staged' option (--staged) can only be used when using '--msg-filename' or "
+ "when piping data to gitlint via stdin.")
# 3. Fallback to reading from local repository
LOG.debug("No --msg-filename flag, no or empty data passed to stdin. Using the local repo.")
return GitContext.from_local_repository(lint_config.target, refspec)
-class ContextObj(object):
+def handle_gitlint_error(ctx, exc):
+ """ Helper function to handle exceptions """
+ if isinstance(exc, GitContextError):
+ click.echo(exc)
+ ctx.exit(GIT_CONTEXT_ERROR_CODE)
+ elif isinstance(exc, GitLintUsageError):
+ click.echo(f"Error: {exc}")
+ ctx.exit(USAGE_ERROR_CODE)
+ elif isinstance(exc, LintConfigError):
+ click.echo(f"Config Error: {exc}")
+ ctx.exit(CONFIG_ERROR_CODE)
+
+
+class ContextObj:
""" Simple class to hold data that is passed between Click commands via the Click context. """
def __init__(self, config, config_builder, refspec, msg_filename, gitcontext=None):
@@ -187,7 +201,7 @@ class ContextObj(object):
type=click.Path(exists=True, resolve_path=True, file_okay=False, readable=True),
help="Path of the target git repository. [default: current working directory]")
@click.option('-C', '--config', type=click.Path(exists=True, dir_okay=False, readable=True, resolve_path=True),
- help="Config file location [default: {0}]".format(DEFAULT_CONFIG_FILE))
+ help=f"Config file location [default: {DEFAULT_CONFIG_FILE}]")
@click.option('-c', multiple=True,
help="Config flags in format <rule>.<option>=<value> (e.g.: -c T1.line-length=80). " +
"Flag can be used multiple times to set multiple config values.") # pylint: disable=bad-continuation
@@ -230,7 +244,7 @@ def cli( # pylint: disable=too-many-arguments
# store it in the context (click allows storing an arbitrary object in ctx.obj).
config, config_builder = build_config(target, config, c, extra_path, ignore, contrib,
ignore_stdin, staged, verbose, silent, debug)
- LOG.debug(u"Configuration\n%s", ustr(config))
+ LOG.debug("Configuration\n%s", config)
ctx.obj = ContextObj(config, config_builder, commits, msg_filename)
@@ -238,15 +252,8 @@ def cli( # pylint: disable=too-many-arguments
if ctx.invoked_subcommand is None:
ctx.invoke(lint)
- except GitContextError as e:
- click.echo(ustr(e))
- ctx.exit(GIT_CONTEXT_ERROR_CODE)
- except GitLintUsageError as e:
- click.echo(u"Error: {0}".format(ustr(e)))
- ctx.exit(USAGE_ERROR_CODE)
- except LintConfigError as e:
- click.echo(u"Config Error: {0}".format(ustr(e)))
- ctx.exit(CONFIG_ERROR_CODE)
+ except GitlintError as e:
+ handle_gitlint_error(ctx, e)
@cli.command("lint")
@@ -294,7 +301,7 @@ def lint(ctx):
if violations:
# Display the commit hash & new lines intelligently
if number_of_commits > 1 and commit.sha:
- linter.display.e(u"{0}Commit {1}:".format(
+ linter.display.e("{0}Commit {1}:".format(
"\n" if not first_violation or commit is last_commit else "",
commit.sha[:10]
))
@@ -315,10 +322,10 @@ def install_hook(ctx):
try:
hooks.GitHookInstaller.install_commit_msg_hook(ctx.obj.config)
hook_path = hooks.GitHookInstaller.commit_msg_hook_path(ctx.obj.config)
- click.echo(u"Successfully installed gitlint commit-msg hook in {0}".format(hook_path))
+ click.echo(f"Successfully installed gitlint commit-msg hook in {hook_path}")
ctx.exit(0)
except hooks.GitHookInstallerError as e:
- click.echo(ustr(e), err=True)
+ click.echo(e, err=True)
ctx.exit(GIT_CONTEXT_ERROR_CODE)
@@ -329,10 +336,10 @@ def uninstall_hook(ctx):
try:
hooks.GitHookInstaller.uninstall_commit_msg_hook(ctx.obj.config)
hook_path = hooks.GitHookInstaller.commit_msg_hook_path(ctx.obj.config)
- click.echo(u"Successfully uninstalled gitlint commit-msg hook from {0}".format(hook_path))
+ click.echo(f"Successfully uninstalled gitlint commit-msg hook from {hook_path}")
ctx.exit(0)
except hooks.GitHookInstallerError as e:
- click.echo(ustr(e), err=True)
+ click.echo(e, err=True)
ctx.exit(GIT_CONTEXT_ERROR_CODE)
@@ -344,8 +351,10 @@ def run_hook(ctx):
exit_code = 1
while exit_code > 0:
try:
- click.echo(u"gitlint: checking commit message...")
+ click.echo("gitlint: checking commit message...")
ctx.invoke(lint)
+ except GitlintError as e:
+ handle_gitlint_error(ctx, e)
except click.exceptions.Exit as e:
# Flush stderr andstdout, this resolves an issue with output ordering in Cygwin
sys.stderr.flush()
@@ -353,11 +362,11 @@ def run_hook(ctx):
exit_code = e.exit_code
if exit_code == 0:
- click.echo(u"gitlint: " + click.style("OK", fg='green') + u" (no violations in commit message)")
+ click.echo("gitlint: " + click.style("OK", fg='green') + " (no violations in commit message)")
continue
- click.echo(u"-----------------------------------------------")
- click.echo(u"gitlint: " + click.style("Your commit message contains the above violations.", fg='red'))
+ click.echo("-----------------------------------------------")
+ click.echo("gitlint: " + click.style("Your commit message contains the above violations.", fg='red'))
value = None
while value not in ["y", "n", "e"]:
@@ -374,14 +383,7 @@ def run_hook(ctx):
# - https://github.com/pallets/click/pull/1372
# - From https://click.palletsprojects.com/en/7.x/utils/#getting-characters-from-terminal
# Note that this function will always read from the terminal, even if stdin is instead a pipe.
- #
- # We also need a to use raw_input() in Python2 as input() is unsafe (and raw_input() doesn't exist in
- # Python3). See https://stackoverflow.com/a/4960216/381010
- input_func = input
- if IS_PY2:
- input_func = raw_input # noqa pylint: disable=undefined-variable
-
- value = input_func()
+ value = input()
if value == "y":
LOG.debug("run-hook: commit message accepted")
@@ -396,15 +398,15 @@ def run_hook(ctx):
LOG.debug("run-hook: %s %s", editor, msg_filename_path)
shell(editor + " " + msg_filename_path)
else:
- click.echo(u"Editing only possible when --msg-filename is specified.")
+ click.echo("Editing only possible when --msg-filename is specified.")
ctx.exit(exit_code)
elif value == "n":
LOG.debug("run-hook: commit message declined")
- click.echo(u"Commit aborted.")
- click.echo(u"Your commit message: ")
- click.echo(u"-----------------------------------------------")
+ click.echo("Commit aborted.")
+ click.echo("Your commit message: ")
+ click.echo("-----------------------------------------------")
click.echo(ctx.obj.gitcontext.commits[0].message.full)
- click.echo(u"-----------------------------------------------")
+ click.echo("-----------------------------------------------")
ctx.exit(exit_code)
ctx.exit(exit_code)
@@ -418,14 +420,14 @@ def generate_config(ctx):
path = os.path.realpath(path)
dir_name = os.path.dirname(path)
if not os.path.exists(dir_name):
- click.echo(u"Error: Directory '{0}' does not exist.".format(dir_name), err=True)
+ click.echo(f"Error: Directory '{dir_name}' does not exist.", err=True)
ctx.exit(USAGE_ERROR_CODE)
elif os.path.exists(path):
- click.echo(u"Error: File \"{0}\" already exists.".format(path), err=True)
+ click.echo(f"Error: File \"{path}\" already exists.", err=True)
ctx.exit(USAGE_ERROR_CODE)
LintConfigGenerator.generate_config(path)
- click.echo(u"Successfully generated {0}".format(path))
+ click.echo(f"Successfully generated {path}")
ctx.exit(0)