diff --git a/commitizen/commands/bump.py b/commitizen/commands/bump.py index ee1894d3a4..928d525e16 100644 --- a/commitizen/commands/bump.py +++ b/commitizen/commands/bump.py @@ -77,12 +77,12 @@ def __call__(self): current_version, increment, prerelease=prerelease ) new_tag_version = bump.create_tag(new_version, tag_format=tag_format) - message = f"Bump version {current_version} → {new_version}" + message = f"bump: version {current_version} → {new_version}" # Report found information out.write(message) - out.write(f"Tag to create: {new_tag_version}") - out.write(f"Increment detected: {increment}") + out.write(f"tag to create: {new_tag_version}") + out.write(f"increment detected: {increment}") # Do not perform operations over files or git. if dry_run: diff --git a/commitizen/commands/commit.py b/commitizen/commands/commit.py index 3b4c7195ca..b84a24707d 100644 --- a/commitizen/commands/commit.py +++ b/commitizen/commands/commit.py @@ -1,4 +1,9 @@ -from commitizen import factory +import questionary +from commitizen import factory, out, git + + +NO_ANSWERS = 5 +COMMIT_ERROR = 6 class Commit: @@ -9,4 +14,23 @@ def __init__(self, config: dict, *args): self.cz = factory.commiter_factory(self.config) def __call__(self): - self.cz.run() + cz = self.cz + questions = cz.questions() + answers = questionary.prompt(questions) + if not answers: + raise SystemExit(NO_ANSWERS) + m = cz.message(answers) + + c = git.commit(m) + + if c.err: + out.error(c.err) + 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: + out.write(c.out) + out.success("Commit successful!") diff --git a/commitizen/commands/example.py b/commitizen/commands/example.py index 61cdb41bef..66246d4f55 100644 --- a/commitizen/commands/example.py +++ b/commitizen/commands/example.py @@ -1,4 +1,4 @@ -from commitizen import factory +from commitizen import factory, out class Example: @@ -9,4 +9,4 @@ def __init__(self, config: dict, *args): self.cz = factory.commiter_factory(self.config) def __call__(self): - self.cz.show_example() + out.write(self.cz.example()) diff --git a/commitizen/commands/info.py b/commitizen/commands/info.py index bd11c45278..f8450e6b0d 100644 --- a/commitizen/commands/info.py +++ b/commitizen/commands/info.py @@ -1,4 +1,4 @@ -from commitizen import factory +from commitizen import factory, out class Info: @@ -9,4 +9,4 @@ def __init__(self, config: dict, *args): self.cz = factory.commiter_factory(self.config) def __call__(self): - self.cz.show_info() + out.write(self.cz.info()) diff --git a/commitizen/commands/schema.py b/commitizen/commands/schema.py index d4bbbd0a4c..fdb488295b 100644 --- a/commitizen/commands/schema.py +++ b/commitizen/commands/schema.py @@ -1,4 +1,4 @@ -from commitizen import factory +from commitizen import factory, out class Schema: @@ -9,4 +9,4 @@ def __init__(self, config: dict, *args): self.cz = factory.commiter_factory(self.config) def __call__(self): - self.cz.show_schema() + out.write(self.cz.schema()) diff --git a/commitizen/cz/base.py b/commitizen/cz/base.py index 3cc00e5752..4dbaa21ab3 100644 --- a/commitizen/cz/base.py +++ b/commitizen/cz/base.py @@ -1,11 +1,4 @@ -import sys -import logging - -from commitizen import out, git from abc import ABCMeta, abstractmethod -from questionary import prompt - -logger = logging.getLogger(__name__) class BaseCommitizen(metaclass=ABCMeta): @@ -13,84 +6,21 @@ def __init__(self, config: dict): self.config = config @abstractmethod - def questions(self): - """Questions regarding the commit message. - - Must have 'whaaaaat' format. - More info: https://github.com/finklabs/whaaaaat/ - - :rtype: list - """ + def questions(self) -> list: + """Questions regarding the commit message.""" @abstractmethod - def message(self, answers): - """Format your git message. - - :param answers: Use answers - :type answers: dict + def message(self, answers: dict) -> str: + """Format your git message.""" - :rtype: string - """ - - def commit(self, message: str): - c = git.commit(message) - # f = NamedTemporaryFile("wb", delete=False) - # f.write(message.encode("utf-8")) - # f.close() - - # c = cmd.run(f"git commit -F {f.name}") - # os.unlink(f.name) - return c - - def example(self): - """Example of the commit message. - - :rtype: string - """ + def example(self) -> str: + """Example of the commit message.""" raise NotImplementedError("Not Implemented yet") - def schema(self): - """Schema definition of the commit message. - - :rtype: string - """ + def schema(self) -> str: + """Schema definition of the commit message.""" raise NotImplementedError("Not Implemented yet") - def info(self): - """Information about the standardized commit message. - - :rtype: string - """ + def info(self) -> str: + """Information about the standardized commit message.""" raise NotImplementedError("Not Implemented yet") - - def show_example(self, *args, **kwargs): - out.write(self.example()) - - def show_schema(self, *args, **kwargs): - out.write(self.schema()) - - def show_info(self, *args, **kwargs): - out.write(self.info()) - - def run(self, *args, **kwargs): - questions = self.questions() - answers = prompt(questions) - logger.debug("Answers:\n %s", answers) - m = self.message(answers) - logger.debug("Commit message generated:\n %s", m) - - c = self.commit(m) - - if c.err: - logger.warning(c.err) - sys.exit(1) - - 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: - out.write(c.out) - out.success("Commit successful!") - - sys.exit(0) diff --git a/commitizen/cz/conventional_commits/conventional_commits.py b/commitizen/cz/conventional_commits/conventional_commits.py index 6b79ffa061..6fe9ff4672 100644 --- a/commitizen/cz/conventional_commits/conventional_commits.py +++ b/commitizen/cz/conventional_commits/conventional_commits.py @@ -30,7 +30,7 @@ def parse_subject(text): class ConventionalCommitsCz(BaseCommitizen): - def questions(self): + def questions(self) -> list: questions = [ { "type": "list", @@ -45,13 +45,6 @@ def questions(self): "value": "feat", "name": "feat: A new feature. Correlates with MINOR in SemVer", }, - { - "value": "BREAKING CHANGE", - "name": ( - "BREAKING CHANGE: introduces a breaking API change. " - "Correlates with MAJOR in SemVer" - ), - }, {"value": "docs", "name": "docs: Documentation only changes"}, { "value": "style", @@ -112,6 +105,12 @@ def questions(self): "Imperative, lower case and no final dot:\n" ), }, + { + "type": "confirm", + "message": "Is this a BREAKING CHANGE? Correlates with MAJOR in SemVer", + "name": "is_breaking_change", + "default": False, + }, { "type": "input", "name": "body", @@ -131,46 +130,46 @@ def questions(self): ] return questions - def message(self, answers): + def message(self, answers: dict) -> str: prefix = answers["prefix"] scope = answers["scope"] subject = answers["subject"] body = answers["body"] footer = answers["footer"] - message = "" - - if prefix: - message += "{0}".format(prefix) - if scope: - message += "({0})".format(scope) - message += ": " - if subject: - message += "{0}".format(subject) + is_breaking_change = answers["is_breaking_change"] + + if scope: + scope = f"({scope})" + if is_breaking_change: + body = f"BREAKING CHANGE: {body}" if body: - message += "\n\n{0}".format(body) + body = f"\n\n{body}" if footer: - message += "\n\n{0}".format(footer) + footer = f"\n\n{footer}" + + message = f"{prefix}{scope}: {subject}{body}{footer}" + return message - def example(self): + def example(self) -> str: return ( - "feat($injector): ability to load new modules after bootstrapping\n" - "\nThe new method `$injector.loadNewModules(modules)` will add " - "each of the\ninjectables to the injector and execute all of the " - "config and run blocks\nfor each module passed to the method.\n" - "\nCloses #324" + "fix: correct minor typos in code\n" + "\n" + "see the issue for details on the typos fixed\n" + "\n" + "closes issue #12" ) - def schema(self): + def schema(self) -> str: return ( "(): \n" "\n" - "\n" + "(BREAKING CHANGE: )\n" "\n" "