diff --git a/commitizen/cli.py b/commitizen/cli.py index 264bddb2f..921424114 100644 --- a/commitizen/cli.py +++ b/commitizen/cli.py @@ -66,6 +66,11 @@ "action": "store_true", "help": "Sign off the commit", }, + { + "name": "--allow-empty", + "action": "store_true", + "help": "Allow to create commit on an empty staging", + }, ], }, { diff --git a/commitizen/commands/commit.py b/commitizen/commands/commit.py index 13e61abe6..376850d61 100644 --- a/commitizen/commands/commit.py +++ b/commitizen/commands/commit.py @@ -62,9 +62,15 @@ def prompt_commit_questions(self) -> str: return cz.message(answers) def __call__(self): + args = [] + allow_empty: bool = self.arguments.get("allow_empty") + + if allow_empty: + args.append("--allow-empty") + dry_run: bool = self.arguments.get("dry_run") - if git.is_staging_clean() and not dry_run: + if git.is_staging_clean() and not (dry_run or allow_empty): raise NothingToCommitError("No files added to staging!") retry: bool = self.arguments.get("retry") @@ -82,9 +88,9 @@ def __call__(self): signoff: bool = self.arguments.get("signoff") if signoff: - c = git.commit(m, "-s") - else: - c = git.commit(m) + args.append("-s") + + c = git.commit(m, *args) if c.return_code != 0: out.error(c.err) diff --git a/tests/commands/test_commit_command.py b/tests/commands/test_commit_command.py index 8544833c8..f4ace3d38 100644 --- a/tests/commands/test_commit_command.py +++ b/tests/commands/test_commit_command.py @@ -52,6 +52,28 @@ def test_commit_retry_fails_no_backup(config, mocker): assert NoCommitBackupError.message in str(excinfo.value) +@pytest.mark.usefixtures("staging_is_clean") +def test_commit_allow_empty(config, mocker): + prompt_mock = mocker.patch("questionary.prompt") + prompt_mock.return_value = { + "prefix": "feat", + "subject": "user created", + "scope": "", + "is_breaking_change": False, + "body": "closes #21", + "footer": "", + } + + commit_mock = mocker.patch("commitizen.git.commit") + commit_mock.return_value = cmd.Command("success", "", "", "", 0) + success_mock = mocker.patch("commitizen.out.success") + + commands.Commit(config, {"allow_empty": True})() + + commit_mock.assert_called_with("feat: user created\n\ncloses #21", "--allow-empty") + success_mock.assert_called_once() + + @pytest.mark.usefixtures("staging_is_clean") def test_commit_retry_works(config, mocker): prompt_mock = mocker.patch("questionary.prompt")