diff options
-rw-r--r-- | README.md | 15 | ||||
-rw-r--r-- | examples/gitlint | 1 | ||||
-rw-r--r-- | gitlint/cli.py | 4 | ||||
-rw-r--r-- | gitlint/tests/test_cli.py | 16 | ||||
-rw-r--r-- | gitlint/tests/test_hooks.py | 59 |
5 files changed, 81 insertions, 14 deletions
@@ -78,6 +78,7 @@ Usage: gitlint [OPTIONS] Options: --install-hook Install gitlint as a git commit-msg hook + --uninstall-hook Uninstall gitlint commit-msg hook -C, --config PATH Config file location (default: .gitlint). -c TEXT Config flags in format <rule>.<option>=<value> (e.g.: -c T1.line-length=80). Flag can be used multiple times to @@ -120,6 +121,7 @@ gitlint --config myconfigfile By default, gitlint will look for an optional ```.gitlint``` file for configuration. ```ini +# All these sections are optional, edit this file as you like. [general] ignore=title-trailing-punctuation, T3 # verbosity should be a value between 1 and 3, the commandline -v flags take precedence over @@ -200,15 +202,13 @@ after each commit. ```bash gitlint --install-hook +# To remove the hook +gitlint --uninstall-hook ``` -Important Notes: - -- You currently cannot uninstall the ```commit-msg``` hook using gitlint. You will need to manually remove the hook from - ```.git/hooks/commit-msg``` in your local git repository. -- Gitlint cannot work together with an existing hook. If you already have a ```.git/hooks/commit-msg``` file in your - local repository, gitlint will refuse to install the ```commit-msg``` hook. - +Important: Gitlint cannot work together with an existing hook. If you already have a ```.git/hooks/commit-msg``` +file in your local repository, gitlint will refuse to install the ```commit-msg``` hook. gitlint will also only +uninstall unmodified commit-msg hooks that were installed by gitlint. ## Contributing ## @@ -262,7 +262,6 @@ python setup.py --long-description | rst2html.py > output.html - body-changed-file-mention: list all files/directories that need to be mentioned as part of the violation - body-changed-file-mention: distinction between change file and directory in output - Git hooks: - - uninstall of gitlint ```commit-msg``` hook (only uninstall if the hook is a gitlint hook) - appending to an existing hook (after user confirmation) - Check a range of commit messages at once (similar to how git log works, eg.: ```git log -3```) - Rules for different attributes of the the commit message: author, date, etc diff --git a/examples/gitlint b/examples/gitlint index 230dfb8..4696aed 100644 --- a/examples/gitlint +++ b/examples/gitlint @@ -1,3 +1,4 @@ +# All these sections are optional, edit this file as you like. [general] ignore=title-trailing-punctuation, T3 # verbosity should be a value between 1 and 3, the commandline -v flags take precedence over diff --git a/gitlint/cli.py b/gitlint/cli.py index f127c1b..deff009 100644 --- a/gitlint/cli.py +++ b/gitlint/cli.py @@ -64,7 +64,7 @@ def uninstall_hook(ctx, param, value): @click.option('--install-hook', is_flag=True, callback=install_hook, is_eager=True, expose_value=False, help="Install gitlint as a git commit-msg hook") @click.option('--uninstall-hook', is_flag=True, callback=uninstall_hook, is_eager=True, expose_value=False, - help="[experimental] Uninstall gitlint commit-msg hook") + help="Uninstall gitlint commit-msg hook") @click.option('-C', '--config', type=click.Path(exists=True), help="Config file location (default: {0}).".format(DEFAULT_CONFIG_FILE)) @click.option('-c', multiple=True, @@ -97,7 +97,7 @@ def cli(config, c, ignore, verbose, silent): lint_config.verbosity = verbose except LintConfigError as e: click.echo("Config Error: {0}".format(e.message)) - exit(CONFIG_ERROR_CODE) # return 10000 on config error + exit(CONFIG_ERROR_CODE) # return CONFIG_ERROR_CODE on config error if sys.stdin.isatty(): gitcontext = GitContext.from_local_repository() diff --git a/gitlint/tests/test_cli.py b/gitlint/tests/test_cli.py index 35789f4..594a677 100644 --- a/gitlint/tests/test_cli.py +++ b/gitlint/tests/test_cli.py @@ -60,3 +60,19 @@ class CLITests(BaseTestCase): self.assertEqual(result.exit_code, 1) self.assertEqual(result.output, "test\n") install_hook.assert_called_once_with() + + @patch('gitlint.hooks.GitHookInstaller.uninstall_commit_msg_hook') + def test_uninstall_hook(self, uninstall_hook): + result = self.cli.invoke(cli.cli, ["--uninstall-hook"]) + expected = "Successfully uninstalled gitlint commit-msg hook from {0}\n\n".format( + hooks.COMMIT_MSG_HOOK_DST_PATH) + self.assertEqual(result.exit_code, 0) + self.assertEqual(result.output, expected) + uninstall_hook.assert_called_once_with() + + @patch('gitlint.hooks.GitHookInstaller.uninstall_commit_msg_hook', side_effect=hooks.GitHookInstallerError("test")) + def test_uninstall_hook_negative(self, uninstall_hook): + result = self.cli.invoke(cli.cli, ["--uninstall-hook"]) + self.assertEqual(result.exit_code, 1) + self.assertEqual(result.output, "test\n") + uninstall_hook.assert_called_once_with() diff --git a/gitlint/tests/test_hooks.py b/gitlint/tests/test_hooks.py index 48fdbfb..b80685f 100644 --- a/gitlint/tests/test_hooks.py +++ b/gitlint/tests/test_hooks.py @@ -1,6 +1,7 @@ from gitlint.tests.base import BaseTestCase -from gitlint.hooks import GitHookInstaller, GitHookInstallerError, COMMIT_MSG_HOOK_SRC_PATH, COMMIT_MSG_HOOK_DST_PATH -from mock import patch, ANY +from gitlint.hooks import GitHookInstaller, GitHookInstallerError, COMMIT_MSG_HOOK_SRC_PATH, COMMIT_MSG_HOOK_DST_PATH, \ + GITLINT_HOOK_IDENTIFIER +from mock import patch, ANY, mock_open class HookTests(BaseTestCase): @@ -23,7 +24,8 @@ class HookTests(BaseTestCase): def test_install_commit_msg_hook_negative(self, isdir, path_exists, copy): # mock that current dir is not a git repo isdir.return_value = False - with self.assertRaises(GitHookInstallerError): + expected_msg = "The current directory is not a git repository" + with self.assertRaisesRegexp(GitHookInstallerError, expected_msg): GitHookInstaller.install_commit_msg_hook() isdir.assert_called_once_with('.git/hooks') path_exists.assert_not_called() @@ -32,5 +34,54 @@ class HookTests(BaseTestCase): # mock that there is already a commit hook present isdir.return_value = True path_exists.return_value = True - with self.assertRaises(GitHookInstallerError): + expected_msg = "There is already a commit-msg hook file present in {}".format(COMMIT_MSG_HOOK_DST_PATH) + \ + ". gitlint currently does not support appending to an existing commit-msg file." + with self.assertRaisesRegexp(GitHookInstallerError, expected_msg): GitHookInstaller.install_commit_msg_hook() + + @patch('os.remove') + @patch('os.path.exists', return_value=True) + @patch('os.path.isdir', return_value=True) + def test_uninstall_commit_msg_hook(self, isdir, path_exists, remove): + read_data = "#!/bin/sh\n" + GITLINT_HOOK_IDENTIFIER + with patch('gitlint.hooks.open', mock_open(read_data=read_data), create=True): + GitHookInstaller.uninstall_commit_msg_hook() + + isdir.assert_called_once_with('.git/hooks') + path_exists.assert_called_once_with(COMMIT_MSG_HOOK_DST_PATH) + remove.assert_called_once_with(COMMIT_MSG_HOOK_DST_PATH) + + @patch('os.remove') + @patch('os.path.exists', return_value=True) + @patch('os.path.isdir', return_value=True) + def test_uninstall_commit_msg_hook_negative(self, isdir, path_exists, remove): + # mock that the current directory is not a git repo + isdir.return_value = False + expected_msg = "The current directory is not a git repository" + with self.assertRaisesRegexp(GitHookInstallerError, expected_msg): + GitHookInstaller.install_commit_msg_hook() + isdir.assert_called_once_with('.git/hooks') + path_exists.assert_not_called() + remove.assert_not_called() + + # mock that there is no commit hook present + isdir.return_value = True + path_exists.return_value = False + expected_msg = "There is no commit-msg hook present in {}".format(COMMIT_MSG_HOOK_DST_PATH) + with self.assertRaisesRegexp(GitHookInstallerError, expected_msg): + GitHookInstaller.uninstall_commit_msg_hook() + isdir.assert_called_once_with('.git/hooks') + path_exists.assert_called_once_with(COMMIT_MSG_HOOK_DST_PATH) + remove.assert_not_called() + + # mock that there is a different (=not gitlint) commit hook + isdir.return_value = True + path_exists.return_value = True + read_data = "#!/bin/sh\nfoo" + expected_msg = "The commit-msg hook in {} was not installed by gitlint ".format(COMMIT_MSG_HOOK_DST_PATH) + \ + "\(or it was modified\).\nUninstallation of 3th party or modified gitlint hooks " + \ + "is not supported." + with patch('gitlint.hooks.open', mock_open(read_data=read_data), create=True): + with self.assertRaisesRegexp(GitHookInstallerError, expected_msg): + GitHookInstaller.uninstall_commit_msg_hook() + remove.assert_not_called() |