Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
38 changes: 24 additions & 14 deletions commitizen/commands/bump.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,21 +382,31 @@ def __call__(self) -> None:

# FIXME: check if any changes have been staged
Comment thread
bearomorphism marked this conversation as resolved.
Outdated
git.add(*updated_files)
Comment thread
bearomorphism marked this conversation as resolved.
Outdated
c = git.commit(message, args=self._get_commit_args())
if self.retry and c.return_code != 0 and self.changelog_flag:
# Maybe pre-commit reformatted some files? Retry once
logger.debug("1st git.commit error: %s", c.err)
logger.info("1st commit attempt failed; retrying once")
git.add(*updated_files)
c = git.commit(message, args=self._get_commit_args())
if c.return_code != 0:
err = c.err.strip() or c.out
raise BumpCommitFailedError(f'2nd git.commit error: "{err}"')

for msg in (c.out, c.err):
if msg:
out_func = out.diagnostic if self.git_output_to_stderr else out.write
out_func(msg)
# When there is nothing for the bump to commit (e.g. ``version_provider
# = "scm"`` with no ``version_files`` and no ``--changelog``), skip the
# commit step and just tag ``HEAD``. Calling ``git commit`` here would
# fail with ``nothing to commit, working tree clean`` (#1530).
if not git.has_pending_changes():
out.info("No file changes; skipping bump commit and tagging HEAD.")
else:
c = git.commit(message, args=self._get_commit_args())
if self.retry and c.return_code != 0 and self.changelog_flag:
# Maybe pre-commit reformatted some files? Retry once
logger.debug("1st git.commit error: %s", c.err)
logger.info("1st commit attempt failed; retrying once")
git.add(*updated_files)
c = git.commit(message, args=self._get_commit_args())
if c.return_code != 0:
err = c.err.strip() or c.out
raise BumpCommitFailedError(f'2nd git.commit error: "{err}"')

for msg in (c.out, c.err):
if msg:
out_func = (
out.diagnostic if self.git_output_to_stderr else out.write
)
out_func(msg)

c = git.tag(
new_tag_version,
Expand Down
12 changes: 12 additions & 0 deletions commitizen/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,18 @@ def is_staging_clean() -> bool:
return not bool(c.out)


def has_pending_changes() -> bool:
"""Check whether there are any tracked-file changes for `git commit -a` to commit.

Returns ``True`` if there are staged or unstaged modifications to tracked
files, ``False`` if the working tree is clean for tracked files. Untracked
files are intentionally ignored — they would be ignored by ``git commit -a``
too.
"""
Comment thread
bearomorphism marked this conversation as resolved.
Outdated
c = cmd.run(["git", "status", "--porcelain", "--untracked-files=no"])
return bool(c.out.strip())


def is_git_project() -> bool:
c = cmd.run(["git", "rev-parse", "--is-inside-work-tree"])
return c.out.strip() == "true"
Expand Down
32 changes: 32 additions & 0 deletions tests/commands/test_bump_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -1375,6 +1375,38 @@ def test_bump_warn_but_dont_fail_on_invalid_tags(
assert git.tag_exist("0.4.3") is True


def test_bump_skips_commit_when_no_files_changed(
tmp_commitizen_project: Path, util: UtilFixture
):
"""Regression test for #1530: with ``version_provider = "scm"`` and no
``version_files`` / ``--changelog``, ``cz bump`` should not fail with
``nothing to commit, working tree clean`` -- it should just create the
tag on ``HEAD``.
"""
project_root = tmp_commitizen_project
tmp_commitizen_cfg_file = project_root / "pyproject.toml"
tmp_commitizen_cfg_file.write_text(
"\n".join(
[
"[tool.commitizen]",
'version_provider = "scm"',
'tag_format = "v$version"',
]
),
)
util.create_file_and_commit("feat: first feature")

util.run_cli("bump", "--yes")

assert git.tag_exist("v0.1.0") is True

util.create_file_and_commit("fix: second change")

util.run_cli("bump", "--yes")

assert git.tag_exist("v0.1.1") is True


def test_is_initial_tag(mocker: MockFixture, tmp_commitizen_project, util: UtilFixture):
"""Test the _is_initial_tag method behavior."""
# Create a commit but no tags
Expand Down
Loading