From a2aa51f5702b18016c25d943499941323952704d Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 19 Nov 2022 15:52:46 +0100 Subject: Adding upstream version 0.18.0. Signed-off-by: Daniel Baumann --- gitlint-core/gitlint/cli.py | 135 ++++++++++++++++++++++++++++++-------------- 1 file changed, 92 insertions(+), 43 deletions(-) (limited to 'gitlint-core/gitlint/cli.py') diff --git a/gitlint-core/gitlint/cli.py b/gitlint-core/gitlint/cli.py index 19676b3..387072e 100644 --- a/gitlint-core/gitlint/cli.py +++ b/gitlint-core/gitlint/cli.py @@ -11,6 +11,7 @@ import click import gitlint from gitlint.lint import GitLinter from gitlint.config import LintConfigBuilder, LintConfigError, LintConfigGenerator +from gitlint.deprecation import LOG as DEPRECATED_LOG, DEPRECATED_LOG_FORMAT from gitlint.git import GitContext, GitContextError, git_version from gitlint import hooks from gitlint.shell import shell @@ -37,19 +38,29 @@ LOG = logging.getLogger("gitlint.cli") class GitLintUsageError(GitlintError): - """ Exception indicating there is an issue with how gitlint is used. """ + """Exception indicating there is an issue with how gitlint is used.""" + pass def setup_logging(): - """ Setup gitlint logging """ + """Setup gitlint logging""" + + # Root log, mostly used for debug root_log = logging.getLogger("gitlint") root_log.propagate = False # Don't propagate to child loggers, the gitlint root logger handles everything + root_log.setLevel(logging.ERROR) handler = logging.StreamHandler() formatter = logging.Formatter(LOG_FORMAT) handler.setFormatter(formatter) root_log.addHandler(handler) - root_log.setLevel(logging.ERROR) + + # Deprecated log, to log deprecation warnings + DEPRECATED_LOG.propagate = False # Don't propagate to child logger + DEPRECATED_LOG.setLevel(logging.WARNING) + deprecated_log_handler = logging.StreamHandler() + deprecated_log_handler.setFormatter(logging.Formatter(DEPRECATED_LOG_FORMAT)) + DEPRECATED_LOG.addHandler(deprecated_log_handler) def log_system_info(): @@ -62,10 +73,20 @@ def log_system_info(): def build_config( # pylint: disable=too-many-arguments - target, config_path, c, extra_path, ignore, contrib, ignore_stdin, staged, fail_without_commits, verbose, - silent, debug + target, + config_path, + c, + extra_path, + ignore, + contrib, + ignore_stdin, + staged, + fail_without_commits, + verbose, + silent, + debug, ): - """ Creates a LintConfig object based on a set of commandline parameters. """ + """Creates a LintConfig object based on a set of commandline parameters.""" config_builder = LintConfigBuilder() # Config precedence: # First, load default config or config from configfile @@ -79,33 +100,33 @@ def build_config( # pylint: disable=too-many-arguments # Finally, overwrite with any convenience commandline flags if ignore: - config_builder.set_option('general', 'ignore', ignore) + config_builder.set_option("general", "ignore", ignore) if contrib: - config_builder.set_option('general', 'contrib', contrib) + config_builder.set_option("general", "contrib", contrib) if ignore_stdin: - config_builder.set_option('general', 'ignore-stdin', ignore_stdin) + config_builder.set_option("general", "ignore-stdin", ignore_stdin) if silent: - config_builder.set_option('general', 'verbosity', 0) + config_builder.set_option("general", "verbosity", 0) elif verbose > 0: - config_builder.set_option('general', 'verbosity', verbose) + config_builder.set_option("general", "verbosity", verbose) if extra_path: - config_builder.set_option('general', 'extra-path', extra_path) + config_builder.set_option("general", "extra-path", extra_path) if target: - config_builder.set_option('general', 'target', target) + config_builder.set_option("general", "target", target) if debug: - config_builder.set_option('general', 'debug', debug) + config_builder.set_option("general", "debug", debug) if staged: - config_builder.set_option('general', 'staged', staged) + config_builder.set_option("general", "staged", staged) if fail_without_commits: - config_builder.set_option('general', 'fail-without-commits', fail_without_commits) + config_builder.set_option("general", "fail-without-commits", fail_without_commits) config = config_builder.build() @@ -113,7 +134,7 @@ def build_config( # pylint: disable=too-many-arguments def get_stdin_data(): - """ Helper function that returns data send to stdin or False if nothing is send """ + """Helper function that returns data sent to stdin or False if nothing is sent""" # STDIN can only be 3 different types of things ("modes") # 1. An interactive terminal device (i.e. a TTY -> sys.stdin.isatty() or stat.S_ISCHR) # 2. A (named) pipe (stat.S_ISFIFO) @@ -145,13 +166,17 @@ def get_stdin_data(): def build_git_context(lint_config, msg_filename, commit_hash, refspec): - """ Builds a git context based on passed parameters and order of precedence """ + """Builds a git context based on passed parameters and order of precedence""" # Determine which GitContext method to use if a custom message is passed from_commit_msg = GitContext.from_commit_msg if lint_config.staged: LOG.debug("Fetching additional meta-data from staged commit") - from_commit_msg = lambda message: GitContext.from_staged_commit(message, lint_config.target) # noqa + from_commit_msg = ( + lambda message: GitContext.from_staged_commit( # pylint: disable=unnecessary-lambda-assignment + message, lint_config.target + ) + ) # Order of precedence: # 1. Any data specified via --msg-filename @@ -168,8 +193,10 @@ def build_git_context(lint_config, msg_filename, commit_hash, refspec): return from_commit_msg(stdin_input) if lint_config.staged: - raise GitLintUsageError("The 'staged' option (--staged) can only be used when using '--msg-filename' or " - "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.") @@ -177,11 +204,25 @@ def build_git_context(lint_config, msg_filename, commit_hash, refspec): if commit_hash and refspec: raise GitLintUsageError("--commit and --commits are mutually exclusive, use one or the other.") - return GitContext.from_local_repository(lint_config.target, refspec=refspec, commit_hash=commit_hash) + # 3.1 Linting a range of commits + if refspec: + # 3.1.1 Not real refspec, but comma-separated list of commit hashes + if "," in refspec: + commit_hashes = [hash.strip() for hash in refspec.split(",")] + return GitContext.from_local_repository(lint_config.target, commit_hashes=commit_hashes) + # 3.1.2 Real refspec + return GitContext.from_local_repository(lint_config.target, refspec=refspec) + + # 3.2 Linting a specific commit + if commit_hash: + return GitContext.from_local_repository(lint_config.target, commit_hashes=[commit_hash]) + + # 3.3 Fallback to linting the current HEAD + return GitContext.from_local_repository(lint_config.target) def handle_gitlint_error(ctx, exc): - """ Helper function to handle exceptions """ + """Helper function to handle exceptions""" if isinstance(exc, GitContextError): click.echo(exc) ctx.exit(GIT_CONTEXT_ERROR_CODE) @@ -194,7 +235,7 @@ def handle_gitlint_error(ctx, exc): class ContextObj: - """ Simple class to hold data that is passed between Click commands via the Click context. """ + """Simple class to hold data that is passed between Click commands via the Click context.""" def __init__(self, config, config_builder, commit_hash, refspec, msg_filename, gitcontext=None): self.config = config @@ -205,29 +246,34 @@ class ContextObj: self.gitcontext = gitcontext +# fmt: off @click.group(invoke_without_command=True, context_settings={'max_content_width': 120}, epilog="When no COMMAND is specified, gitlint defaults to 'gitlint lint'.") @click.option('--target', envvar='GITLINT_TARGET', 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), +@click.option('-C', '--config', envvar='GITLINT_CONFIG', + type=click.Path(exists=True, dir_okay=False, readable=True, resolve_path=True), help=f"Config file location [default: {DEFAULT_CONFIG_FILE}]") @click.option('-c', multiple=True, help="Config flags in format .