From 9669515af475bddda398e84096557c3ad08f4a5b Mon Sep 17 00:00:00 2001 From: akshatkarani Date: Tue, 13 Aug 2019 20:50:05 +0530 Subject: [PATCH] EditCommitMessageAction: New action This adds a new action for GitCommitBear. When applied it opens up a editor for user to edit commit message of the HEAD commit. This also makes changes is CommitBear.py to pass EditCommitMessageAction when Result is yielded. --- bears/vcs/CommitBear.py | 30 ++++++++++++------- bears/vcs/actions/EditCommitMessageAction.py | 17 +++++++++++ .../actions/EditCommitMessageActionTest.py | 24 +++++++++++++++ 3 files changed, 61 insertions(+), 10 deletions(-) create mode 100644 bears/vcs/actions/EditCommitMessageAction.py create mode 100644 tests/vcs/actions/EditCommitMessageActionTest.py diff --git a/bears/vcs/CommitBear.py b/bears/vcs/CommitBear.py index a9a225f2a2..295dace211 100644 --- a/bears/vcs/CommitBear.py +++ b/bears/vcs/CommitBear.py @@ -13,6 +13,7 @@ from coalib.settings.Setting import typed_list from coalib.settings.FunctionMetadata import FunctionMetadata from dependency_management.requirements.PipRequirement import PipRequirement +from bears.vcs.actions.EditCommitMessageAction import EditCommitMessageAction class _CommitBear(GlobalBear): @@ -188,13 +189,15 @@ def check_shortlog(self, shortlog, 'character(s). This is {} character(s) longer than ' 'the limit ({} > {}).'.format( len(shortlog), diff, - len(shortlog), shortlog_length)) + len(shortlog), shortlog_length), + actions=[EditCommitMessageAction()]) if (shortlog[-1] != '.') == shortlog_trailing_period: yield Result(self, 'Shortlog of HEAD commit contains no period at end.' if shortlog_trailing_period else - 'Shortlog of HEAD commit contains a period at end.') + 'Shortlog of HEAD commit contains a period at end.', + actions=[EditCommitMessageAction()]) if shortlog_regex: match = re.fullmatch(shortlog_regex, shortlog) @@ -202,7 +205,8 @@ def check_shortlog(self, shortlog, yield Result( self, 'Shortlog of HEAD commit does not match given regex:' - ' {regex}'.format(regex=shortlog_regex)) + ' {regex}'.format(regex=shortlog_regex), + actions=[EditCommitMessageAction()]) if shortlog_imperative_check: colon_pos = shortlog.find(':') @@ -214,7 +218,8 @@ def check_shortlog(self, shortlog, bad_word = has_flaws[0] yield Result(self, "Shortlog of HEAD commit isn't in imperative " - "mood! Bad words are '{}'".format(bad_word)) + "mood! Bad words are '{}'".format(bad_word), + actions=[EditCommitMessageAction()]) if shortlog_wip_check: if 'wip' in shortlog.lower()[:4]: yield Result( @@ -267,12 +272,15 @@ def check_body(self, body, """ if len(body) == 0: if force_body: - yield Result(self, 'No commit message body at HEAD.') + yield Result(self, 'No commit message body at HEAD.', + actions=[EditCommitMessageAction()]) return if body[0] != '\n': - yield Result(self, 'No newline found between shortlog and body at ' - 'HEAD commit. Please add one.') + yield Result(self, + 'No newline found between shortlog and body at ' + 'HEAD commit. Please add one.', + actions=[EditCommitMessageAction()]) return if body_regex and not re.fullmatch(body_regex, body.strip()): @@ -284,9 +292,11 @@ def check_body(self, body, if any((len(line) > body_line_length and not any(regex.search(line) for regex in ignore_regexes)) for line in body[1:]): - yield Result(self, 'Body of HEAD commit contains too long lines. ' - 'Commit body lines should not exceed {} ' - 'characters.'.format(body_line_length)) + yield Result(self, + 'Body of HEAD commit contains too long lines. ' + 'Commit body lines should not exceed {} ' + 'characters.'.format(body_line_length), + actions=[EditCommitMessageAction()]) def check_issue_reference(self, body, body_close_issue: bool = False, diff --git a/bears/vcs/actions/EditCommitMessageAction.py b/bears/vcs/actions/EditCommitMessageAction.py new file mode 100644 index 0000000000..6f72f0a147 --- /dev/null +++ b/bears/vcs/actions/EditCommitMessageAction.py @@ -0,0 +1,17 @@ +import subprocess +from coalib.results.result_actions.ResultAction import ResultAction + + +class EditCommitMessageAction(ResultAction): + """ + Opens an editor to edit the commit message of the HEAD commit. + """ + + SUCCESS_MESSAGE = 'Commit message edited successfully.' + + def apply(self, result, original_file_dict, file_diff_dict): + """ + Edit (C)ommit Message [Note: This may rewrite your commit history] + """ + subprocess.check_call(['git', 'commit', '-o', '--amend']) + return file_diff_dict diff --git a/tests/vcs/actions/EditCommitMessageActionTest.py b/tests/vcs/actions/EditCommitMessageActionTest.py new file mode 100644 index 0000000000..dd39b61d42 --- /dev/null +++ b/tests/vcs/actions/EditCommitMessageActionTest.py @@ -0,0 +1,24 @@ +import unittest +from unittest.mock import patch +from coala_utils.ContextManagers import retrieve_stdout +from coalib.results.Result import Result +from bears.vcs.actions.EditCommitMessageAction import EditCommitMessageAction + + +class EditCommitMessageActionTest(unittest.TestCase): + + def setUp(self): + self.uut = EditCommitMessageAction() + self.result = Result('origin', 'message') + + def test_is_applicable(self): + self.assertTrue(self.uut.is_applicable(self.result, {}, {})) + + def test_apply(self): + with retrieve_stdout() as stdout: + patcher = ('bears.vcs.actions.EditCommitMessageAction.' + 'subprocess.check_call') + with patch(patcher): + ret = self.uut.apply(self.result, {}, {'file': 'diff'}) + self.assertEqual(ret, {'file': 'diff'}) + self.assertEqual(stdout.getvalue(), '')