diff --git a/docs/configuration.md b/docs/configuration.md index 9bf9dc1e..d172f467 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -36,6 +36,9 @@ The block below shows a sample ```.gitlint``` file. Details about rule config op # By default gitlint will ignore squash commits. Set to 'false' to disable. # ignore-squash-commits=true +# Ignore any data send to gitlint via stdin +# ignore-stdin=true + # Enable debug mode (prints more output). Disabled by default. # debug=true diff --git a/gitlint/cli.py b/gitlint/cli.py index bd0b0ee9..f3099b23 100644 --- a/gitlint/cli.py +++ b/gitlint/cli.py @@ -128,6 +128,27 @@ def get_stdin_data(): return False +def build_git_context(lint_config, msg_filename, refspec): + """ Builds a git context based on passed parameters and order of precedence """ + # Order of precedence: + # 1. Any data specified via --msg-filename + if msg_filename: + LOG.debug("Attempting to read from --msg-filename.") + return GitContext.from_commit_msg(ustr(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: %r", stdin_input) + LOG.debug("Stdin detected and not ignored. Will be used as input.") + return GitContext.from_commit_msg(stdin_input) + + # 3. Fallback to reading from local repository + LOG.debug("No --msg-filename flag, no or empty data passed to stdin. Attempting to read from the local repo.") + return GitContext.from_local_repository(lint_config.target, refspec) + + @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', type=click.Path(exists=True, resolve_path=True, file_okay=False, readable=True), @@ -170,7 +191,6 @@ 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(ctx, target, config, c, extra_path, ignore, contrib, ignore_stdin, verbose, silent, debug) - LOG.debug(u"Configuration\n%s", ustr(config)) ctx.obj = (config, config_builder, commits, msg_filename) @@ -189,26 +209,10 @@ def cli( # pylint: disable=too-many-arguments def lint(ctx): """ Lints a git repository [default command] """ lint_config = ctx.obj[0] + refspec = ctx.obj[2] msg_filename = ctx.obj[3] - # Let's determine where our input data is coming from: - # Order of precedence: - # 1. Any data specified via --msg-filename - # 2. Any data sent to stdin - # 3. Fallback to reading from local repository - stdin_input = get_stdin_data() - if stdin_input: - LOG.debug("Stdin data: %r", stdin_input) - - if msg_filename: - LOG.debug("Attempting to read from --msg-filename.") - gitcontext = GitContext.from_commit_msg(ustr(msg_filename.read())) - elif stdin_input and not lint_config.ignore_stdin: - LOG.debug("Stdin detected and not ignored. Will be used as input.") - gitcontext = GitContext.from_commit_msg(stdin_input) - else: - LOG.debug("No --msg-filename flag, no or empty data passed to stdin. Attempting to read from the local repo.") - gitcontext = GitContext.from_local_repository(lint_config.target, ctx.obj[2]) + gitcontext = build_git_context(lint_config, msg_filename, refspec) number_of_commits = len(gitcontext.commits) # Exit if we don't have commits in the specified range. Use a 0 exit code, since a popular use-case is one diff --git a/gitlint/config.py b/gitlint/config.py index 1ac08496..2d892bbd 100644 --- a/gitlint/config.py +++ b/gitlint/config.py @@ -281,6 +281,7 @@ def __eq__(self, other): self.ignore_merge_commits == other.ignore_merge_commits and \ self.ignore_fixup_commits == other.ignore_fixup_commits and \ self.ignore_squash_commits == other.ignore_squash_commits and \ + self.ignore_stdin == other.ignore_stdin and \ self.debug == other.debug and \ self.ignore == other.ignore and \ self._config_path == other._config_path # noqa @@ -295,6 +296,7 @@ def __str__(self): return_str += u"ignore-merge-commits: {0}\n".format(self.ignore_merge_commits) return_str += u"ignore-fixup-commits: {0}\n".format(self.ignore_fixup_commits) return_str += u"ignore-squash-commits: {0}\n".format(self.ignore_squash_commits) + return_str += u"ignore-stdin: {0}\n".format(self.ignore_stdin) return_str += u"verbosity: {0}\n".format(self.verbosity) return_str += u"debug: {0}\n".format(self.debug) return_str += u"target: {0}\n".format(self.target) diff --git a/gitlint/files/gitlint b/gitlint/files/gitlint index 44ed23e2..c12d2bf9 100644 --- a/gitlint/files/gitlint +++ b/gitlint/files/gitlint @@ -15,6 +15,9 @@ # By default gitlint will ignore squash commits. Set to 'false' to disable. # ignore-squash-commits=true +# Ignore any data send to gitlint via stdin +# ignore-stdin=true + # Enable debug mode (prints more output). Disabled by default. # debug=true diff --git a/gitlint/tests/expected/debug_configuration_output1 b/gitlint/tests/expected/debug_configuration_output1 index 82ba2abb..33c7609e 100644 --- a/gitlint/tests/expected/debug_configuration_output1 +++ b/gitlint/tests/expected/debug_configuration_output1 @@ -7,6 +7,7 @@ ignore: title-trailing-whitespace,B2 ignore-merge-commits: False ignore-fixup-commits: True ignore-squash-commits: True +ignore-stdin: False verbosity: 1 debug: True target: {target} diff --git a/gitlint/tests/test_cli.py b/gitlint/tests/test_cli.py index 75528f66..b952b5c9 100644 --- a/gitlint/tests/test_cli.py +++ b/gitlint/tests/test_cli.py @@ -200,7 +200,7 @@ def test_input_stream(self, _): @patch('gitlint.cli.get_stdin_data', return_value="Should be ignored\n") @patch('gitlint.git.sh') - def test_lint_ignore_stdin(self, sh, _): + def test_lint_ignore_stdin(self, sh, stdin_data): """ Test for ignoring stdin when --ignore-stdin flag is enabled""" sh.git.side_effect = self.GIT_CONFIG_SIDE_EFFECTS + [ "6f29bf81a8322a04071bb794666e48c443a90360", @@ -214,6 +214,9 @@ def test_lint_ignore_stdin(self, sh, _): self.assertEqual(stderr.getvalue(), u'3: B5 Body message is too short (11<20): "commït-body"\n') self.assertEqual(result.exit_code, 1) + # Assert that we didn't even try to get the stdin data + self.assertEqual(stdin_data.call_count, 0) + @patch('gitlint.cli.get_stdin_data', return_value=False) def test_msg_filename(self, _): expected_output = u"3: B6 Body message is missing\n" @@ -472,8 +475,8 @@ def test_install_hook(self, _, install_hook): result = self.cli.invoke(cli.cli, ["install-hook"]) expected_path = os.path.join(u"/hür", u"dur", hooks.COMMIT_MSG_HOOK_DST_PATH) expected = u"Successfully installed gitlint commit-msg hook in {0}\n".format(expected_path) - self.assertEqual(result.exit_code, 0) self.assertEqual(result.output, expected) + self.assertEqual(result.exit_code, 0) expected_config = config.LintConfig() expected_config.target = os.path.realpath(os.getcwd()) install_hook.assert_called_once_with(expected_config) diff --git a/qa/expected/debug_output1 b/qa/expected/debug_output1 index 04e632d6..05b9f4df 100644 --- a/qa/expected/debug_output1 +++ b/qa/expected/debug_output1 @@ -13,6 +13,7 @@ ignore: title-trailing-punctuation,B2 ignore-merge-commits: True ignore-fixup-commits: True ignore-squash-commits: True +ignore-stdin: False verbosity: 2 debug: True target: {target}