diff --git a/README.md b/README.md index 9db3588..7e4ae6b 100644 --- a/README.md +++ b/README.md @@ -564,30 +564,29 @@ Usage: bumpver update [OPTIONS] Update project files with the incremented version string. Options: - -d, --dry Display diff of changes, don't rewrite files. - -f, --fetch / -n, --no-fetch Sync tags from remote origin. - -v, --verbose Control log level. -vv for debug level. - --allow-dirty Commit even when working directory is has - uncomitted changes. (WARNING: The commit will - still be aborted if there are uncomitted to - files with version strings. - - --set-version Set version explicitly. - --date Set explicit date in format YYYY-0M-0D (e.g. - 2021-05-13). - - --pin-date Leave date components unchanged. - --tag-num Increment release tag number (rc1, rc2, - rc3..). - - -t, --tag Override release tag of current_version. Valid - options are: alpha, beta, rc, post, final. - - -p, --patch Increment PATCH component. - -m, --minor Increment MINOR component. - --major Increment MAJOR component. - -c, --commit-message Set commit message template. - --help Show this message and exit. + -d, --dry Display diff of changes, don't rewrite files. + -f, --fetch / -n, --no-fetch Sync tags from remote origin. + -v, --verbose Control log level. -vv for debug level. + --allow-dirty Commit even when working directory is has + uncomitted changes. (WARNING: The commit will + still be aborted if there are uncomitted to + files with version strings. + --set-version Set version explicitly. + --date Set explicit date in format YYYY-0M-0D (e.g. + 2021-05-13). + --pin-date Leave date components unchanged. + --tag-num Increment release tag number (rc1, rc2, + rc3..). + -t, --tag Override release tag of current_version. Valid + options are: alpha, beta, rc, post, final. + -p, --patch Increment PATCH component. + -m, --minor Increment MINOR component. + --major Increment MAJOR component. + -c, --commit-message Set commit message template. + --commit / --no-commit Create a commit with all updated files. + --tag-commit / --no-tag-commit Tag the newly created commit. + --push / --no-push Push to the default remote. + --help Show this message and exit. ``` @@ -1016,6 +1015,17 @@ INFO - git tag --annotate 2020.1006 --message 2020.1006 INFO - git push origin --follow-tags 2020.1006 HEAD ``` +It's also possible to override the config values by passing the following command line flags to `bumpver update`: + +| Flag | Override config | +|-------------------|-------------------------------------------------| +| `--commit` | `commit = True` | +| `--no-commit` | `commit = False`, `tag = False`, `push = False` | +| `--tag-commit` | `tag = True` | +| `--no-tag-commit` | `tag = False` | +| `--push` | `push = True` | +| `--no-push` | `push = False` | + ### Custom Commit Message In addition to the `commit_message` configuration, you can also override the string used as the the commit message template with the `-c/--commit-message=` parameter: diff --git a/src/bumpver/cli.py b/src/bumpver/cli.py index d9a4a6f..6fffac3 100755 --- a/src/bumpver/cli.py +++ b/src/bumpver/cli.py @@ -677,6 +677,32 @@ def _update_cfg_from_vcs(cfg: config.Config, fetch: bool) -> config.Config: ) +def _parse_vcs_options( + cfg : config.Config, + commit: typ.Optional[bool] = None, + tag : typ.Optional[bool] = None, + push : typ.Optional[bool] = None, +) -> config.Config: + if commit is not None: + if not commit: + if tag: + raise ValueError("--no-commit and --tag-commit cannot be used at the same time") + if push: + raise ValueError("--no-commit and --push cannot be used at the same time") + cfg = cfg._replace(commit=commit) + if tag is not None: + if tag and not cfg.commit: + raise ValueError( + "--tag-commit requires the --commit flag if commit=False in the config file" + ) + cfg = cfg._replace(tag=tag) + if push is not None: + if push and not cfg.commit: + raise ValueError("--push requires the --commit flag if commit=False in the config file") + cfg = cfg._replace(push=push) + return cfg + + @cli.command() @dry_option @fetch_option @@ -699,6 +725,21 @@ def _update_cfg_from_vcs(cfg: config.Config, fetch: bool) -> config.Config: metavar="", help="Set commit message template.", ) +@click.option( + "--commit/--no-commit", + default=None, + help="Create a commit with all updated files.", +) +@click.option( + "--tag-commit/--no-tag-commit", + default=None, + help="Tag the newly created commit.", +) +@click.option( + "--push/--no-push", + default=None, + help="Push to the default remote.", +) def update( dry : bool = False, allow_dirty : bool = False, @@ -713,6 +754,9 @@ def update( date : typ.Optional[str] = None, set_version : typ.Optional[str] = None, commit_message: typ.Optional[str] = None, + commit : typ.Optional[bool] = None, + tag_commit : typ.Optional[bool] = None, + push : typ.Optional[bool] = None, ) -> None: """Update project files with the incremented version string.""" verbose = max(_VERBOSE, verbose) @@ -726,6 +770,12 @@ def update( logger.error("Could not parse configuration.") sys.exit(1) + try: + cfg = _parse_vcs_options(cfg, commit, tag_commit, push) + except ValueError as ex: + logger.warning(f"Invalid argument: {ex}") + sys.exit(1) + cfg = _update_cfg_from_vcs(cfg, fetch) old_version = cfg.current_version diff --git a/test/test_cli.py b/test/test_cli.py index 963068b..b06972a 100644 --- a/test/test_cli.py +++ b/test/test_cli.py @@ -640,6 +640,190 @@ def test_empty_hg_bump(runner, caplog): assert any(("setup.cfg" in r.message) for r in caplog.records) +def test_incorrect_vcs_option_no_commit_tag(runner, caplog): + _add_project_files("README.md") + _vcs_init("git") + result = runner.invoke(cli.cli, ['init', "-vv"]) + assert result.exit_code == 0 + + result = runner.invoke(cli.cli, ['update', "-vv", "--no-commit", "--tag-commit"]) + assert result.exit_code == 1 + assert len(caplog.records) == 1 + assert ( + "Invalid argument: --no-commit and --tag-commit cannot be used at the same time" + in caplog.records[0].message + ) + + +def test_incorrect_vcs_option_no_commit_push(runner, caplog): + _add_project_files("README.md") + _vcs_init("git") + result = runner.invoke(cli.cli, ['init', "-vv"]) + assert result.exit_code == 0 + + _update_config_val( + "bumpver.toml", + tag="false", + ) + + result = runner.invoke(cli.cli, ['update', "-vv", "--no-commit", "--push"]) + assert result.exit_code == 1 + assert len(caplog.records) == 1 + assert ( + "Invalid argument: --no-commit and --push cannot be used at the same time" + in caplog.records[0].message + ) + + +def test_incorrect_vcs_option_tag_push(runner, caplog): + _add_project_files("README.md") + _vcs_init("git") + result = runner.invoke(cli.cli, ['init', "-vv"]) + assert result.exit_code == 0 + + _update_config_val( + "bumpver.toml", + commit="false", + tag="false", + push="false", + ) + + result = runner.invoke(cli.cli, ['update', "-vv", "--tag-commit"]) + assert result.exit_code == 1 + assert len(caplog.records) == 1 + assert ( + "Invalid argument: --tag-commit requires the --commit flag if commit=False in the config file" + in caplog.records[0].message + ) + + result = runner.invoke(cli.cli, ['update', "-vv", "--push"]) + assert result.exit_code == 1 + assert len(caplog.records) == 2 + assert ( + "Invalid argument: --push requires the --commit flag if commit=False in the config file" + in caplog.records[1].message + ) + + +@pytest.mark.parametrize("version_pattern, cur_version, cur_pep440", DEFAULT_VERSION_PATTERNS) +def test_vcs_option_no_commit(runner, caplog, version_pattern, cur_version, cur_pep440): + _add_project_files("README.md") + _vcs_init("git") + result = runner.invoke(cli.cli, ['init', "-vv"]) + assert result.exit_code == 0 + + _update_config_val( + "bumpver.toml", + version_pattern=version_pattern, + current_version=f'"{cur_version}"', + ) + + shell("git", "add", "bumpver.toml") + shell("git", "commit", "-m", "update bumpver.toml") + + prev_commit_count = shell("git", "rev-list", "HEAD", "--count").decode("utf-8") + + result = runner.invoke(cli.cli, ['update', "-vv", "--no-commit"]) + assert result.exit_code == 0 + + tags = shell("git", "tag", "--list").decode("utf-8") + assert not tags + + commit_count = shell("git", "rev-list", "HEAD", "--count").decode("utf-8") + assert prev_commit_count == commit_count + + +@pytest.mark.parametrize("version_pattern, cur_version, cur_pep440", DEFAULT_VERSION_PATTERNS) +def test_vcs_option_commit(runner, caplog, version_pattern, cur_version, cur_pep440): + _add_project_files("README.md") + _vcs_init("git") + result = runner.invoke(cli.cli, ['init', "-vv"]) + assert result.exit_code == 0 + + _update_config_val( + "bumpver.toml", + version_pattern=version_pattern, + current_version=f'"{cur_version}"', + commit="false", + tag="false", + push="false", + ) + + shell("git", "add", "bumpver.toml") + shell("git", "commit", "-m", "update bumpver.toml") + + result = runner.invoke(cli.cli, ['update', "-vv", "--commit"]) + assert result.exit_code == 0 + + calver = cur_version.split(".")[0] + + tags = shell("git", "tag", "--list").decode("utf-8") + assert not tags + + last_commit = shell("git", "log", "-1").decode("utf-8") + expected = f"bump version {calver}.1001-alpha -> {calver}.1002-alpha" + assert expected in last_commit + + +@pytest.mark.parametrize("version_pattern, cur_version, cur_pep440", DEFAULT_VERSION_PATTERNS) +def test_vcs_option_no_tag(runner, caplog, version_pattern, cur_version, cur_pep440): + _add_project_files("README.md") + _vcs_init("git") + result = runner.invoke(cli.cli, ['init', "-vv"]) + assert result.exit_code == 0 + + _update_config_val( + "bumpver.toml", + version_pattern=version_pattern, + current_version=f'"{cur_version}"', + ) + + shell("git", "add", "bumpver.toml") + shell("git", "commit", "-m", "update bumpver.toml") + + result = runner.invoke(cli.cli, ['update', "-vv", "--no-tag-commit"]) + assert result.exit_code == 0 + + calver = cur_version.split(".")[0] + + tags = shell("git", "tag", "--list").decode("utf-8") + assert not tags + + last_commit = shell("git", "log", "-1").decode("utf-8") + expected = f"bump version {calver}.1001-alpha -> {calver}.1002-alpha" + assert expected in last_commit + + +@pytest.mark.parametrize("version_pattern, cur_version, cur_pep440", DEFAULT_VERSION_PATTERNS) +def test_vcs_option_tag(runner, caplog, version_pattern, cur_version, cur_pep440): + _add_project_files("README.md") + _vcs_init("git") + result = runner.invoke(cli.cli, ['init', "-vv"]) + assert result.exit_code == 0 + + _update_config_val( + "bumpver.toml", + version_pattern=version_pattern, + current_version=f'"{cur_version}"', + tag="false", + ) + + shell("git", "add", "bumpver.toml") + shell("git", "commit", "-m", "update bumpver.toml") + + result = runner.invoke(cli.cli, ['update', "-vv", "--tag-commit"]) + assert result.exit_code == 0 + + calver = cur_version.split(".")[0] + + tags = shell("git", "tag", "--list").decode("utf-8") + assert f"{calver}.1002-alpha" in tags + + last_commit = shell("git", "log", "-1").decode("utf-8") + expected = f"bump version {calver}.1001-alpha -> {calver}.1002-alpha" + assert expected in last_commit + + SETUP_CFG_SEMVER_FIXTURE = """ [metadata] license_file = LICENSE @@ -1028,13 +1212,13 @@ ROLLOVER_TEST_CASES = [ ["{year}.{month}.{MINOR}", "2020.10.3", "2020.11.4", _kwargs(2020, 11, True)], ["{year}.{month}.{MINOR}", "2020.10.3", "2020.11.3", _kwargs(2020, 11, False)], # v2 cases - ["YYYY.MM.MINOR" , "2020.10.3", "2020.10.4", _kwargs(2020, 10, True)], - ["YYYY.MM.MINOR" , "2020.10.3", None, _kwargs(2020, 10, False)], - ["YYYY.MM.MINOR" , "2020.10.3", "2020.11.0", _kwargs(2020, 11, True)], - ["YYYY.MM.MINOR" , "2020.10.3", "2020.11.0", _kwargs(2020, 11, False)], + ["YYYY.MM.MINOR", "2020.10.3", "2020.10.4", _kwargs(2020, 10, True)], + ["YYYY.MM.MINOR", "2020.10.3", None, _kwargs(2020, 10, False)], + ["YYYY.MM.MINOR", "2020.10.3", "2020.11.0", _kwargs(2020, 11, True)], + ["YYYY.MM.MINOR", "2020.10.3", "2020.11.0", _kwargs(2020, 11, False)], ["YYYY.MM[.MINOR]", "2020.10.3", "2020.10.4", _kwargs(2020, 10, True)], ["YYYY.MM[.MINOR]", "2020.10.3", "2020.11", _kwargs(2020, 11, False)], - ["YYYY.MM.MINOR" , "2020.10.3", "2021.10.0", _kwargs(2021, 10, False)], + ["YYYY.MM.MINOR", "2020.10.3", "2021.10.0", _kwargs(2021, 10, False)], # incr0/incr1 part ["YYYY.MM.INC0", "2020.10.3", "2020.10.4", _kwargs(2020, 10)], ["YYYY.MM.INC0", "2020.10.3", "2020.11.0", _kwargs(2020, 11)],