From 72b8c35be4293bd21de123854491c658c53af100 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 4 Dec 2021 04:31:41 +0100 Subject: Adding upstream version 0.17.0. Signed-off-by: Daniel Baumann --- gitlint/__init__.py | 1 - gitlint/cache.py | 53 -- gitlint/cli.py | 454 --------------- gitlint/config.py | 528 ------------------ gitlint/contrib/__init__.py | 0 gitlint/contrib/rules/__init__.py | 0 gitlint/contrib/rules/conventional_commit.py | 37 -- gitlint/contrib/rules/signedoff_by.py | 18 - gitlint/display.py | 36 -- gitlint/exception.py | 4 - gitlint/files/commit-msg | 35 -- gitlint/files/gitlint | 134 ----- gitlint/git.py | 398 ------------- gitlint/hooks.py | 63 --- gitlint/lint.py | 106 ---- gitlint/options.py | 149 ----- gitlint/rule_finder.py | 145 ----- gitlint/rules.py | 440 --------------- gitlint/shell.py | 77 --- gitlint/tests/__init__.py | 0 gitlint/tests/base.py | 191 ------- gitlint/tests/cli/test_cli.py | 593 -------------------- gitlint/tests/cli/test_cli_hooks.py | 281 ---------- gitlint/tests/config/test_config.py | 287 ---------- gitlint/tests/config/test_config_builder.py | 264 --------- gitlint/tests/config/test_config_precedence.py | 98 ---- gitlint/tests/config/test_rule_collection.py | 64 --- gitlint/tests/contrib/__init__.py | 0 gitlint/tests/contrib/rules/__init__.py | 0 .../contrib/rules/test_conventional_commit.py | 75 --- gitlint/tests/contrib/rules/test_signedoff_by.py | 32 -- gitlint/tests/contrib/test_contrib_rules.py | 69 --- gitlint/tests/expected/cli/test_cli/test_contrib_1 | 2 - gitlint/tests/expected/cli/test_cli/test_debug_1 | 124 ----- .../expected/cli/test_cli/test_input_stream_1 | 3 - .../cli/test_cli/test_input_stream_debug_1 | 3 - .../cli/test_cli/test_input_stream_debug_2 | 83 --- .../tests/expected/cli/test_cli/test_lint_commit_1 | 2 - .../cli/test_cli/test_lint_multiple_commits_1 | 8 - .../test_cli/test_lint_multiple_commits_config_1 | 6 - .../cli/test_cli/test_lint_staged_msg_filename_1 | 2 - .../cli/test_cli/test_lint_staged_msg_filename_2 | 86 --- .../expected/cli/test_cli/test_lint_staged_stdin_1 | 3 - .../expected/cli/test_cli/test_lint_staged_stdin_2 | 88 --- .../tests/expected/cli/test_cli/test_named_rules_1 | 4 - .../tests/expected/cli/test_cli/test_named_rules_2 | 86 --- .../cli/test_cli_hooks/test_hook_config_1_stderr | 2 - .../cli/test_cli_hooks/test_hook_config_1_stdout | 5 - .../cli/test_cli_hooks/test_hook_edit_1_stderr | 6 - .../cli/test_cli_hooks/test_hook_edit_1_stdout | 14 - .../test_cli_hooks/test_hook_local_commit_1_stderr | 2 - .../test_cli_hooks/test_hook_local_commit_1_stdout | 4 - .../cli/test_cli_hooks/test_hook_no_1_stderr | 2 - .../cli/test_cli_hooks/test_hook_no_1_stdout | 8 - .../cli/test_cli_hooks/test_hook_no_tty_1_stderr | 2 - .../cli/test_cli_hooks/test_hook_no_tty_1_stdout | 5 - .../test_hook_stdin_no_violations_1_stdout | 2 - .../test_hook_stdin_violations_1_stderr | 2 - .../test_hook_stdin_violations_1_stdout | 5 - .../cli/test_cli_hooks/test_hook_yes_1_stderr | 2 - .../cli/test_cli_hooks/test_hook_yes_1_stdout | 4 - .../cli/test_cli_hooks/test_run_hook_negative_1 | 2 - .../cli/test_cli_hooks/test_run_hook_negative_2 | 2 - gitlint/tests/git/test_git.py | 108 ---- gitlint/tests/git/test_git_commit.py | 619 --------------------- gitlint/tests/git/test_git_context.py | 84 --- gitlint/tests/rules/__init__.py | 0 gitlint/tests/rules/test_body_rules.py | 236 -------- gitlint/tests/rules/test_configuration_rules.py | 140 ----- gitlint/tests/rules/test_meta_rules.py | 59 -- gitlint/tests/rules/test_rules.py | 23 - gitlint/tests/rules/test_title_rules.py | 186 ------- gitlint/tests/rules/test_user_rules.py | 256 --------- gitlint/tests/samples/commit_message/fixup | 1 - gitlint/tests/samples/commit_message/merge | 3 - gitlint/tests/samples/commit_message/no-violations | 6 - gitlint/tests/samples/commit_message/revert | 3 - gitlint/tests/samples/commit_message/sample1 | 14 - gitlint/tests/samples/commit_message/sample2 | 1 - gitlint/tests/samples/commit_message/sample3 | 6 - gitlint/tests/samples/commit_message/sample4 | 7 - gitlint/tests/samples/commit_message/sample5 | 7 - gitlint/tests/samples/commit_message/squash | 3 - gitlint/tests/samples/config/gitlintconfig | 15 - gitlint/tests/samples/config/invalid-option-value | 11 - gitlint/tests/samples/config/named-rules | 8 - gitlint/tests/samples/config/no-sections | 1 - .../samples/config/nonexisting-general-option | 13 - gitlint/tests/samples/config/nonexisting-option | 11 - gitlint/tests/samples/config/nonexisting-rule | 11 - gitlint/tests/samples/user_rules/bogus-file.txt | 2 - .../user_rules/import_exception/invalid_python.py | 3 - .../user_rules/incorrect_linerule/my_line_rule.py | 10 - .../tests/samples/user_rules/my_commit_rules.foo | 16 - .../tests/samples/user_rules/my_commit_rules.py | 26 - .../samples/user_rules/parent_package/__init__.py | 13 - .../user_rules/parent_package/my_commit_rules.py | 12 - gitlint/tests/test_cache.py | 57 -- gitlint/tests/test_display.py | 63 --- gitlint/tests/test_hooks.py | 131 ----- gitlint/tests/test_lint.py | 277 --------- gitlint/tests/test_options.py | 224 -------- gitlint/tests/test_utils.py | 77 --- gitlint/utils.py | 81 --- 104 files changed, 8025 deletions(-) delete mode 100644 gitlint/__init__.py delete mode 100644 gitlint/cache.py delete mode 100644 gitlint/cli.py delete mode 100644 gitlint/config.py delete mode 100644 gitlint/contrib/__init__.py delete mode 100644 gitlint/contrib/rules/__init__.py delete mode 100644 gitlint/contrib/rules/conventional_commit.py delete mode 100644 gitlint/contrib/rules/signedoff_by.py delete mode 100644 gitlint/display.py delete mode 100644 gitlint/exception.py delete mode 100644 gitlint/files/commit-msg delete mode 100644 gitlint/files/gitlint delete mode 100644 gitlint/git.py delete mode 100644 gitlint/hooks.py delete mode 100644 gitlint/lint.py delete mode 100644 gitlint/options.py delete mode 100644 gitlint/rule_finder.py delete mode 100644 gitlint/rules.py delete mode 100644 gitlint/shell.py delete mode 100644 gitlint/tests/__init__.py delete mode 100644 gitlint/tests/base.py delete mode 100644 gitlint/tests/cli/test_cli.py delete mode 100644 gitlint/tests/cli/test_cli_hooks.py delete mode 100644 gitlint/tests/config/test_config.py delete mode 100644 gitlint/tests/config/test_config_builder.py delete mode 100644 gitlint/tests/config/test_config_precedence.py delete mode 100644 gitlint/tests/config/test_rule_collection.py delete mode 100644 gitlint/tests/contrib/__init__.py delete mode 100644 gitlint/tests/contrib/rules/__init__.py delete mode 100644 gitlint/tests/contrib/rules/test_conventional_commit.py delete mode 100644 gitlint/tests/contrib/rules/test_signedoff_by.py delete mode 100644 gitlint/tests/contrib/test_contrib_rules.py delete mode 100644 gitlint/tests/expected/cli/test_cli/test_contrib_1 delete mode 100644 gitlint/tests/expected/cli/test_cli/test_debug_1 delete mode 100644 gitlint/tests/expected/cli/test_cli/test_input_stream_1 delete mode 100644 gitlint/tests/expected/cli/test_cli/test_input_stream_debug_1 delete mode 100644 gitlint/tests/expected/cli/test_cli/test_input_stream_debug_2 delete mode 100644 gitlint/tests/expected/cli/test_cli/test_lint_commit_1 delete mode 100644 gitlint/tests/expected/cli/test_cli/test_lint_multiple_commits_1 delete mode 100644 gitlint/tests/expected/cli/test_cli/test_lint_multiple_commits_config_1 delete mode 100644 gitlint/tests/expected/cli/test_cli/test_lint_staged_msg_filename_1 delete mode 100644 gitlint/tests/expected/cli/test_cli/test_lint_staged_msg_filename_2 delete mode 100644 gitlint/tests/expected/cli/test_cli/test_lint_staged_stdin_1 delete mode 100644 gitlint/tests/expected/cli/test_cli/test_lint_staged_stdin_2 delete mode 100644 gitlint/tests/expected/cli/test_cli/test_named_rules_1 delete mode 100644 gitlint/tests/expected/cli/test_cli/test_named_rules_2 delete mode 100644 gitlint/tests/expected/cli/test_cli_hooks/test_hook_config_1_stderr delete mode 100644 gitlint/tests/expected/cli/test_cli_hooks/test_hook_config_1_stdout delete mode 100644 gitlint/tests/expected/cli/test_cli_hooks/test_hook_edit_1_stderr delete mode 100644 gitlint/tests/expected/cli/test_cli_hooks/test_hook_edit_1_stdout delete mode 100644 gitlint/tests/expected/cli/test_cli_hooks/test_hook_local_commit_1_stderr delete mode 100644 gitlint/tests/expected/cli/test_cli_hooks/test_hook_local_commit_1_stdout delete mode 100644 gitlint/tests/expected/cli/test_cli_hooks/test_hook_no_1_stderr delete mode 100644 gitlint/tests/expected/cli/test_cli_hooks/test_hook_no_1_stdout delete mode 100644 gitlint/tests/expected/cli/test_cli_hooks/test_hook_no_tty_1_stderr delete mode 100644 gitlint/tests/expected/cli/test_cli_hooks/test_hook_no_tty_1_stdout delete mode 100644 gitlint/tests/expected/cli/test_cli_hooks/test_hook_stdin_no_violations_1_stdout delete mode 100644 gitlint/tests/expected/cli/test_cli_hooks/test_hook_stdin_violations_1_stderr delete mode 100644 gitlint/tests/expected/cli/test_cli_hooks/test_hook_stdin_violations_1_stdout delete mode 100644 gitlint/tests/expected/cli/test_cli_hooks/test_hook_yes_1_stderr delete mode 100644 gitlint/tests/expected/cli/test_cli_hooks/test_hook_yes_1_stdout delete mode 100644 gitlint/tests/expected/cli/test_cli_hooks/test_run_hook_negative_1 delete mode 100644 gitlint/tests/expected/cli/test_cli_hooks/test_run_hook_negative_2 delete mode 100644 gitlint/tests/git/test_git.py delete mode 100644 gitlint/tests/git/test_git_commit.py delete mode 100644 gitlint/tests/git/test_git_context.py delete mode 100644 gitlint/tests/rules/__init__.py delete mode 100644 gitlint/tests/rules/test_body_rules.py delete mode 100644 gitlint/tests/rules/test_configuration_rules.py delete mode 100644 gitlint/tests/rules/test_meta_rules.py delete mode 100644 gitlint/tests/rules/test_rules.py delete mode 100644 gitlint/tests/rules/test_title_rules.py delete mode 100644 gitlint/tests/rules/test_user_rules.py delete mode 100644 gitlint/tests/samples/commit_message/fixup delete mode 100644 gitlint/tests/samples/commit_message/merge delete mode 100644 gitlint/tests/samples/commit_message/no-violations delete mode 100644 gitlint/tests/samples/commit_message/revert delete mode 100644 gitlint/tests/samples/commit_message/sample1 delete mode 100644 gitlint/tests/samples/commit_message/sample2 delete mode 100644 gitlint/tests/samples/commit_message/sample3 delete mode 100644 gitlint/tests/samples/commit_message/sample4 delete mode 100644 gitlint/tests/samples/commit_message/sample5 delete mode 100644 gitlint/tests/samples/commit_message/squash delete mode 100644 gitlint/tests/samples/config/gitlintconfig delete mode 100644 gitlint/tests/samples/config/invalid-option-value delete mode 100644 gitlint/tests/samples/config/named-rules delete mode 100644 gitlint/tests/samples/config/no-sections delete mode 100644 gitlint/tests/samples/config/nonexisting-general-option delete mode 100644 gitlint/tests/samples/config/nonexisting-option delete mode 100644 gitlint/tests/samples/config/nonexisting-rule delete mode 100644 gitlint/tests/samples/user_rules/bogus-file.txt delete mode 100644 gitlint/tests/samples/user_rules/import_exception/invalid_python.py delete mode 100644 gitlint/tests/samples/user_rules/incorrect_linerule/my_line_rule.py delete mode 100644 gitlint/tests/samples/user_rules/my_commit_rules.foo delete mode 100644 gitlint/tests/samples/user_rules/my_commit_rules.py delete mode 100644 gitlint/tests/samples/user_rules/parent_package/__init__.py delete mode 100644 gitlint/tests/samples/user_rules/parent_package/my_commit_rules.py delete mode 100644 gitlint/tests/test_cache.py delete mode 100644 gitlint/tests/test_display.py delete mode 100644 gitlint/tests/test_hooks.py delete mode 100644 gitlint/tests/test_lint.py delete mode 100644 gitlint/tests/test_options.py delete mode 100644 gitlint/tests/test_utils.py delete mode 100644 gitlint/utils.py (limited to 'gitlint') diff --git a/gitlint/__init__.py b/gitlint/__init__.py deleted file mode 100644 index 5a313cc..0000000 --- a/gitlint/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "0.16.0" diff --git a/gitlint/cache.py b/gitlint/cache.py deleted file mode 100644 index 1b6558f..0000000 --- a/gitlint/cache.py +++ /dev/null @@ -1,53 +0,0 @@ -class PropertyCache: - """ Mixin class providing a simple cache. """ - - def __init__(self): - self._cache = {} - - def _try_cache(self, cache_key, cache_populate_func): - """ Tries to get a value from the cache identified by `cache_key`. - If no value is found in the cache, do a function call to `cache_populate_func` to populate the cache - and then return the value from the cache. """ - if cache_key not in self._cache: - cache_populate_func() - return self._cache[cache_key] - - -def cache(original_func=None, cachekey=None): # pylint: disable=unused-argument - """ Cache decorator. Caches function return values. - Requires the parent class to extend and initialize PropertyCache. - Usage: - # Use function name as cache key - @cache - def myfunc(args): - ... - - # Specify cache key - @cache(cachekey="foobar") - def myfunc(args): - ... - """ - - # Decorators with optional arguments are a bit convoluted in python, see some of the links below for details. - - def cache_decorator(func): - # Use 'nonlocal' keyword to access parent function variable: - # https://stackoverflow.com/a/14678445/381010 - nonlocal cachekey - if not cachekey: - cachekey = func.__name__ - - def wrapped(*args): - def cache_func_result(): - # Call decorated function and store its result in the cache - args[0]._cache[cachekey] = func(*args) - return args[0]._try_cache(cachekey, cache_func_result) - - return wrapped - - # To support optional kwargs for decorators, we need to check if a function is passed as first argument or not. - # https://stackoverflow.com/a/24617244/381010 - if original_func: - return cache_decorator(original_func) - - return cache_decorator diff --git a/gitlint/cli.py b/gitlint/cli.py deleted file mode 100644 index 19676b3..0000000 --- a/gitlint/cli.py +++ /dev/null @@ -1,454 +0,0 @@ -# pylint: disable=bad-option-value,wrong-import-position -# We need to disable the import position checks because of the windows check that we need to do below -import copy -import logging -import os -import platform -import stat -import sys -import click - -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 LOG_FORMAT -from gitlint.exception import GitlintError - -# Error codes -GITLINT_SUCCESS = 0 -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 ) -DEFAULT_COMMIT_MSG_EDITOR = "vim -n" - -# Since we use the return code to denote the amount of errors, we need to change the default click usage error code -click.UsageError.exit_code = USAGE_ERROR_CODE - -# We don't use logging.getLogger(__main__) here because that will cause DEBUG output to be lost -# when invoking gitlint as a python module (python -m gitlint.cli) -LOG = logging.getLogger("gitlint.cli") - - -class GitLintUsageError(GitlintError): - """ Exception indicating there is an issue with how gitlint is used. """ - pass - - -def setup_logging(): - """ Setup gitlint logging """ - root_log = logging.getLogger("gitlint") - root_log.propagate = False # Don't propagate to child loggers, the gitlint root logger handles everything - handler = logging.StreamHandler() - formatter = logging.Formatter(LOG_FORMAT) - handler.setFormatter(formatter) - root_log.addHandler(handler) - root_log.setLevel(logging.ERROR) - - -def log_system_info(): - LOG.debug("Platform: %s", platform.platform()) - LOG.debug("Python version: %s", sys.version) - LOG.debug("Git version: %s", git_version()) - LOG.debug("Gitlint version: %s", gitlint.__version__) - LOG.debug("GITLINT_USE_SH_LIB: %s", os.environ.get("GITLINT_USE_SH_LIB", "[NOT SET]")) - LOG.debug("DEFAULT_ENCODING: %s", gitlint.utils.DEFAULT_ENCODING) - - -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 -): - """ Creates a LintConfig object based on a set of commandline parameters. """ - config_builder = LintConfigBuilder() - # Config precedence: - # First, load default config or config from configfile - if config_path: - config_builder.set_from_config_file(config_path) - elif os.path.exists(DEFAULT_CONFIG_FILE): - config_builder.set_from_config_file(DEFAULT_CONFIG_FILE) - - # Then process any commandline configuration flags - config_builder.set_config_from_string_list(c) - - # Finally, overwrite with any convenience commandline flags - if ignore: - config_builder.set_option('general', 'ignore', ignore) - - if contrib: - config_builder.set_option('general', 'contrib', contrib) - - if ignore_stdin: - config_builder.set_option('general', 'ignore-stdin', ignore_stdin) - - if silent: - config_builder.set_option('general', 'verbosity', 0) - elif verbose > 0: - config_builder.set_option('general', 'verbosity', verbose) - - if extra_path: - config_builder.set_option('general', 'extra-path', extra_path) - - if target: - config_builder.set_option('general', 'target', target) - - if debug: - config_builder.set_option('general', 'debug', debug) - - if staged: - config_builder.set_option('general', 'staged', staged) - - if fail_without_commits: - config_builder.set_option('general', 'fail-without-commits', fail_without_commits) - - config = config_builder.build() - - return config, config_builder - - -def get_stdin_data(): - """ Helper function that returns data send to stdin or False if nothing is send """ - # 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) - # 3. A regular file (stat.S_ISREG) - # Technically, STDIN can also be other device type like a named unix socket (stat.S_ISSOCK), but we don't - # support that in gitlint (at least not today). - # - # Now, the behavior that we want is the following: - # If someone sends something directly to gitlint via a pipe or a regular file, read it. If not, read from the - # local repository. - # Note that we don't care about whether STDIN is a TTY or not, we only care whether data is via a pipe or regular - # file. - # However, in case STDIN is not a TTY, it HAS to be one of the 2 other things (pipe or regular file), even if - # no-one is actually sending anything to gitlint over them. In this case, we still want to read from the local - # repository. - # To support this use-case (which is common in CI runners such as Jenkins and Gitlab), we need to actually attempt - # to read from STDIN in case it's a pipe or regular file. In case that fails, then we'll fall back to reading - # from the local repo. - - mode = os.fstat(sys.stdin.fileno()).st_mode - stdin_is_pipe_or_file = stat.S_ISFIFO(mode) or stat.S_ISREG(mode) - if stdin_is_pipe_or_file: - input_data = sys.stdin.read() - # Only return the input data if there's actually something passed - # i.e. don't consider empty piped data - if input_data: - return str(input_data) - return False - - -def build_git_context(lint_config, msg_filename, commit_hash, refspec): - """ 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 - - # Order of precedence: - # 1. Any data specified via --msg-filename - if msg_filename: - LOG.debug("Using --msg-filename.") - 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: - stdin_input = get_stdin_data() - if stdin_input: - LOG.debug("Stdin data: '%s'", stdin_input) - LOG.debug("Stdin detected and not ignored. Using as input.") - 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.") - - # 3. Fallback to reading from local repository - LOG.debug("No --msg-filename flag, no or empty data passed to stdin. Using the local repo.") - - 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) - - -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, commit_hash, refspec, msg_filename, gitcontext=None): - self.config = config - self.config_builder = config_builder - self.commit_hash = commit_hash - self.refspec = refspec - self.msg_filename = msg_filename - self.gitcontext = gitcontext - - -@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), - help=f"Config file location [default: {DEFAULT_CONFIG_FILE}]") -@click.option('-c', multiple=True, - help="Config flags in format .