Skip to content

feat(commit): new retry argument to execute previous commit again #41

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# CHANGELOG

## Unreleased

### Feature

- new retry argument to execute previous commit again

## v1.5.1

### Fix
Expand Down
7 changes: 7 additions & 0 deletions commitizen/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@
"name": ["commit", "c"],
"help": "create new commit",
"func": commands.Commit,
"arguments": [
{
"name": ["--retry"],
"action": "store_true",
"help": "retry last commit",
},
]
},
{
"name": "example",
Expand Down
42 changes: 35 additions & 7 deletions commitizen/commands/commit.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,64 @@
import contextlib
import os
import questionary
import tempfile

from commitizen import factory, out, git


NO_ANSWERS = 5
COMMIT_ERROR = 6
NO_COMMIT_BACKUP = 7


class Commit:
"""Show prompt for the user to create a guided commit."""

def __init__(self, config: dict, *args):
def __init__(self, config: dict, arguments: dict):
self.config: dict = config
self.cz = factory.commiter_factory(self.config)
self.arguments = arguments
self.temp_file: str = os.path.join(tempfile.gettempdir(), "cz.commit.backup")

def __call__(self):
cz = self.cz
questions = cz.questions()
answers = questionary.prompt(questions)
if not answers:
raise SystemExit(NO_ANSWERS)
m = cz.message(answers)
retry: bool = self.arguments.get("retry")

if retry:
# Check the commit backup file exists
if not os.path.isfile(self.temp_file):
out.error("No commit backup found")
raise SystemExit(NO_COMMIT_BACKUP)

# Read commit message from backup
with open(self.temp_file, "r") as f:
m = f.read().strip()
else:
# Prompt user for the commit message
cz = self.cz
questions = cz.questions()
answers = questionary.prompt(questions)
if not answers:
raise SystemExit(NO_ANSWERS)
m = cz.message(answers)

out.info(f"\n{m}\n")
c = git.commit(m)

if c.err:
out.error(c.err)

# Create commit backup
with open(self.temp_file, "w") as f:
f.write(m)

raise SystemExit(COMMIT_ERROR)

if "nothing added" in c.out or "no changes added to commit" in c.out:
out.error(c.out)
elif c.err:
out.error(c.err)
else:
with contextlib.suppress(FileNotFoundError):
os.remove(self.temp_file)
out.write(c.out)
out.success("Commit successful!")
6 changes: 3 additions & 3 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def test_sysexit_no_argv():

def test_ls(mocker, capsys):
testargs = ["cz", "-n", "cz_jira", "ls"]
mocker.patch.object(sys, 'argv', testargs)
mocker.patch.object(sys, "argv", testargs)
cli.main()
out, err = capsys.readouterr()

Expand All @@ -21,5 +21,5 @@ def test_ls(mocker, capsys):
def test_version(mocker):
testargs = ["cz", "--version"]
with pytest.raises(SystemExit):
mocker.patch.object(sys, 'argv', testargs)
cli.main()
mocker.patch.object(sys, "argv", testargs)
cli.main()
51 changes: 49 additions & 2 deletions tests/test_commands.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# import pytest
import os
import pytest
from unittest import mock

from commitizen import defaults, commands, cmd

config = {"name": defaults.name}
Expand All @@ -20,8 +22,53 @@ def test_commit(mocker):
commit_mock.return_value = cmd.Command("success", "", "", "")
success_mock = mocker.patch("commitizen.out.success")

commands.Commit(config)()
commands.Commit(config, {})()
success_mock.assert_called_once()


def test_commit_retry_fails_no_backup(mocker):
commit_mock = mocker.patch("commitizen.git.commit")
commit_mock.return_value = cmd.Command("success", "", "", "")

with pytest.raises(SystemExit):
commands.Commit(config, {"retry": True})()


def test_commit_retry_works(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("", "error", "", "")
error_mock = mocker.patch("commitizen.out.error")

with pytest.raises(SystemExit):
commit_cmd = commands.Commit(config, {})
temp_file = commit_cmd.temp_file
commit_cmd()

prompt_mock.assert_called_once()
error_mock.assert_called_once()
assert os.path.isfile(temp_file)

# Previous commit failed, so retry should pick up the backup commit
# commit_mock = mocker.patch("commitizen.git.commit")
commit_mock.return_value = cmd.Command("success", "", "", "")
success_mock = mocker.patch("commitizen.out.success")

commands.Commit(config, {"retry": True})()

commit_mock.assert_called_with("feat: user created\n\ncloses #21")
prompt_mock.assert_called_once()
success_mock.assert_called_once()
assert not os.path.isfile(temp_file)


def test_example():
Expand Down