mirror of
https://github.com/TECHNOFAB11/bumpver.git
synced 2025-12-12 06:20:08 +01:00
mv __main__.py -> cli.py
This commit is contained in:
parent
7760d7de72
commit
82d06c3032
4 changed files with 397 additions and 388 deletions
2
setup.py
2
setup.py
|
|
@ -54,7 +54,7 @@ setuptools.setup(
|
|||
install_requires=install_requires,
|
||||
entry_points="""
|
||||
[console_scripts]
|
||||
pycalver=pycalver.__main__:cli
|
||||
pycalver=pycalver.cli:cli
|
||||
""",
|
||||
zip_safe=True,
|
||||
|
||||
|
|
|
|||
|
|
@ -5,348 +5,12 @@
|
|||
# Copyright (c) 2019 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CLI module for PyCalVer.
|
||||
__main__ module for PyCalVer.
|
||||
|
||||
Provided subcommands: show, test, init, bump
|
||||
Enables use as module: $ python -m pycalver --version
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import click
|
||||
import logging
|
||||
import typing as typ
|
||||
|
||||
from . import vcs
|
||||
from . import config
|
||||
from . import version
|
||||
from . import rewrite
|
||||
|
||||
|
||||
_VERBOSE = 0
|
||||
|
||||
|
||||
# To enable pretty tracebacks:
|
||||
# echo "export ENABLE_BACKTRACE=1;" >> ~/.bashrc
|
||||
if os.environ.get('ENABLE_BACKTRACE') == '1':
|
||||
import backtrace
|
||||
|
||||
backtrace.hook(align=True, strip_path=True, enable_on_envvar_only=True)
|
||||
|
||||
|
||||
click.disable_unicode_literals_warning = True
|
||||
|
||||
|
||||
VALID_RELEASE_VALUES = ("alpha", "beta", "dev", "rc", "post", "final")
|
||||
|
||||
|
||||
log = logging.getLogger("pycalver.cli")
|
||||
|
||||
|
||||
def _configure_logging(verbose: int = 0) -> None:
|
||||
if verbose >= 2:
|
||||
log_format = "%(asctime)s.%(msecs)03d %(levelname)-7s %(name)-15s - %(message)s"
|
||||
log_level = logging.DEBUG
|
||||
elif verbose == 1:
|
||||
log_format = "%(levelname)-7s - %(message)s"
|
||||
log_level = logging.INFO
|
||||
else:
|
||||
log_format = "%(levelname)-7s - %(message)s"
|
||||
log_level = logging.INFO
|
||||
|
||||
logging.basicConfig(level=log_level, format=log_format, datefmt="%Y-%m-%dT%H:%M:%S")
|
||||
log.debug("Logging configured.")
|
||||
|
||||
|
||||
def _validate_release_tag(release: str) -> None:
|
||||
if release in VALID_RELEASE_VALUES:
|
||||
return
|
||||
|
||||
log.error(f"Invalid argument --release={release}")
|
||||
log.error(f"Valid arguments are: {', '.join(VALID_RELEASE_VALUES)}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@click.group()
|
||||
@click.version_option(version="v201903.0028")
|
||||
@click.help_option()
|
||||
@click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.")
|
||||
def cli(verbose: int = 0) -> None:
|
||||
"""Automatically update PyCalVer version strings on python projects."""
|
||||
global _VERBOSE
|
||||
_VERBOSE = verbose
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.argument("old_version")
|
||||
@click.argument("pattern", default="{pycalver}")
|
||||
@click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.")
|
||||
@click.option(
|
||||
"--release", default=None, metavar="<name>", help="Override release name of current_version"
|
||||
)
|
||||
@click.option("--major", is_flag=True, default=False, help="Increment major component.")
|
||||
@click.option("--minor", is_flag=True, default=False, help="Increment minor component.")
|
||||
@click.option("--patch", is_flag=True, default=False, help="Increment patch component.")
|
||||
def test(
|
||||
old_version: str,
|
||||
pattern : str = "{pycalver}",
|
||||
verbose : int = 0,
|
||||
release : str = None,
|
||||
major : bool = False,
|
||||
minor : bool = False,
|
||||
patch : bool = False,
|
||||
) -> None:
|
||||
"""Increment a version number for demo purposes."""
|
||||
_configure_logging(verbose=max(_VERBOSE, verbose))
|
||||
|
||||
if release:
|
||||
_validate_release_tag(release)
|
||||
|
||||
new_version = version.incr(
|
||||
old_version, pattern=pattern, release=release, major=major, minor=minor, patch=patch
|
||||
)
|
||||
if new_version is None:
|
||||
log.error(f"Invalid version '{old_version}' and/or pattern '{pattern}'.")
|
||||
sys.exit(1)
|
||||
|
||||
pep440_version = version.to_pep440(new_version)
|
||||
|
||||
print("New Version:", new_version)
|
||||
print("PEP440 :", pep440_version)
|
||||
|
||||
|
||||
def _update_cfg_from_vcs(cfg: config.Config, fetch: bool) -> config.Config:
|
||||
try:
|
||||
_vcs = vcs.get_vcs()
|
||||
log.debug(f"vcs found: {_vcs.name}")
|
||||
if fetch:
|
||||
log.info(f"fetching tags from remote (to turn off use: -n / --no-fetch)")
|
||||
_vcs.fetch()
|
||||
|
||||
version_tags = [tag for tag in _vcs.ls_tags() if version.is_valid(tag, cfg.version_pattern)]
|
||||
if version_tags:
|
||||
version_tags.sort(reverse=True)
|
||||
log.debug(f"found {len(version_tags)} tags: {version_tags[:2]}")
|
||||
latest_version_tag = version_tags[0]
|
||||
latest_version_pep440 = version.to_pep440(latest_version_tag)
|
||||
if latest_version_tag > cfg.current_version:
|
||||
log.info(f"Working dir version : {cfg.current_version}")
|
||||
log.info(f"Latest version from {_vcs.name:>3} tag: {latest_version_tag}")
|
||||
cfg = cfg._replace(
|
||||
current_version=latest_version_tag, pep440_version=latest_version_pep440
|
||||
)
|
||||
|
||||
else:
|
||||
log.debug("no vcs tags found")
|
||||
except OSError:
|
||||
log.debug("No vcs found")
|
||||
|
||||
return cfg
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.")
|
||||
@click.option(
|
||||
"-f/-n", "--fetch/--no-fetch", is_flag=True, default=True, help="Sync tags from remote origin."
|
||||
)
|
||||
def show(verbose: int = 0, fetch: bool = True) -> None:
|
||||
"""Show current version."""
|
||||
_configure_logging(verbose=max(_VERBOSE, verbose))
|
||||
|
||||
ctx: config.ProjectContext = config.init_project_ctx(project_path=".")
|
||||
cfg: config.MaybeConfig = config.parse(ctx)
|
||||
|
||||
if cfg is None:
|
||||
log.error("Could not parse configuration. Perhaps try 'pycalver init'.")
|
||||
sys.exit(1)
|
||||
|
||||
cfg = _update_cfg_from_vcs(cfg, fetch=fetch)
|
||||
|
||||
print(f"Current Version: {cfg.current_version}")
|
||||
print(f"PEP440 : {cfg.pep440_version}")
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.")
|
||||
@click.option(
|
||||
"--dry", default=False, is_flag=True, help="Display diff of changes, don't rewrite files."
|
||||
)
|
||||
def init(verbose: int = 0, dry: bool = False) -> None:
|
||||
"""Initialize [pycalver] configuration."""
|
||||
_configure_logging(verbose=max(_VERBOSE, verbose))
|
||||
|
||||
ctx: config.ProjectContext = config.init_project_ctx(project_path=".")
|
||||
cfg: config.MaybeConfig = config.parse(ctx)
|
||||
|
||||
if cfg:
|
||||
log.error(f"Configuration already initialized in {ctx.config_filepath}")
|
||||
sys.exit(1)
|
||||
|
||||
if dry:
|
||||
print(f"Exiting because of '--dry'. Would have written to {ctx.config_filepath}:")
|
||||
cfg_text: str = config.default_config(ctx)
|
||||
print("\n " + "\n ".join(cfg_text.splitlines()))
|
||||
sys.exit(0)
|
||||
|
||||
config.write_content(ctx)
|
||||
|
||||
|
||||
def _assert_not_dirty(_vcs: vcs.VCS, filepaths: typ.Set[str], allow_dirty: bool):
|
||||
dirty_files = _vcs.status(required_files=filepaths)
|
||||
|
||||
if dirty_files:
|
||||
log.warning(f"{_vcs.name} working directory is not clean. Uncomitted file(s):")
|
||||
for dirty_file in dirty_files:
|
||||
log.warning(" " + dirty_file)
|
||||
|
||||
if not allow_dirty and dirty_files:
|
||||
sys.exit(1)
|
||||
|
||||
dirty_pattern_files = set(dirty_files) & filepaths
|
||||
if dirty_pattern_files:
|
||||
log.error("Not commiting when pattern files are dirty:")
|
||||
for dirty_file in dirty_pattern_files:
|
||||
log.warning(" " + dirty_file)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def _bump(cfg: config.Config, new_version: str, allow_dirty: bool = False) -> None:
|
||||
_vcs: typ.Optional[vcs.VCS]
|
||||
|
||||
try:
|
||||
_vcs = vcs.get_vcs()
|
||||
except OSError:
|
||||
log.warning("Version Control System not found, aborting commit.")
|
||||
_vcs = None
|
||||
|
||||
filepaths = set(cfg.file_patterns.keys())
|
||||
|
||||
if _vcs:
|
||||
_assert_not_dirty(_vcs, filepaths, allow_dirty)
|
||||
|
||||
try:
|
||||
rewrite.rewrite(new_version, cfg.file_patterns)
|
||||
except ValueError as ex:
|
||||
log.error(str(ex))
|
||||
sys.exit(1)
|
||||
|
||||
if _vcs is None or not cfg.commit:
|
||||
return
|
||||
|
||||
for filepath in filepaths:
|
||||
_vcs.add(filepath)
|
||||
|
||||
_vcs.commit(f"bump version to {new_version}")
|
||||
|
||||
if cfg.commit and cfg.tag:
|
||||
_vcs.tag(new_version)
|
||||
|
||||
if cfg.commit and cfg.tag and cfg.push:
|
||||
_vcs.push(new_version)
|
||||
|
||||
|
||||
def _print_diff(cfg: config.Config, new_version: str) -> None:
|
||||
diff: str = rewrite.diff(new_version, cfg.file_patterns)
|
||||
|
||||
if sys.stdout.isatty():
|
||||
for line in diff.splitlines():
|
||||
if line.startswith("+++") or line.startswith("---"):
|
||||
print(line)
|
||||
elif line.startswith("+"):
|
||||
print("\u001b[32m" + line + "\u001b[0m")
|
||||
elif line.startswith("-"):
|
||||
print("\u001b[31m" + line + "\u001b[0m")
|
||||
elif line.startswith("@"):
|
||||
print("\u001b[36m" + line + "\u001b[0m")
|
||||
else:
|
||||
print(line)
|
||||
else:
|
||||
print(diff)
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option("-v", "--verbose", count=True, help="Control log level. -vv for debug level.")
|
||||
@click.option(
|
||||
"-f/-n", "--fetch/--no-fetch", is_flag=True, default=True, help="Sync tags from remote origin."
|
||||
)
|
||||
@click.option(
|
||||
"--dry", default=False, is_flag=True, help="Display diff of changes, don't rewrite files."
|
||||
)
|
||||
@click.option(
|
||||
"--release",
|
||||
default=None,
|
||||
metavar="<name>",
|
||||
help=(
|
||||
f"Override release name of current_version. Valid options are: "
|
||||
f"{', '.join(VALID_RELEASE_VALUES)}."
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
"--allow-dirty",
|
||||
default=False,
|
||||
is_flag=True,
|
||||
help=(
|
||||
"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."
|
||||
),
|
||||
)
|
||||
@click.option("--major", is_flag=True, default=False, help="Increment major component.")
|
||||
@click.option("--minor", is_flag=True, default=False, help="Increment minor component.")
|
||||
@click.option("--patch", is_flag=True, default=False, help="Increment patch component.")
|
||||
def bump(
|
||||
release : typ.Optional[str] = None,
|
||||
verbose : int = 0,
|
||||
dry : bool = False,
|
||||
allow_dirty: bool = False,
|
||||
fetch : bool = True,
|
||||
major : bool = False,
|
||||
minor : bool = False,
|
||||
patch : bool = False,
|
||||
) -> None:
|
||||
"""Increment the current version string and update project files."""
|
||||
verbose = max(_VERBOSE, verbose)
|
||||
_configure_logging(verbose)
|
||||
|
||||
if release:
|
||||
_validate_release_tag(release)
|
||||
|
||||
ctx: config.ProjectContext = config.init_project_ctx(project_path=".")
|
||||
cfg: config.MaybeConfig = config.parse(ctx)
|
||||
|
||||
if cfg is None:
|
||||
log.error("Could not parse configuration. Perhaps try 'pycalver init'.")
|
||||
sys.exit(1)
|
||||
|
||||
cfg = _update_cfg_from_vcs(cfg, fetch=fetch)
|
||||
|
||||
old_version = cfg.current_version
|
||||
new_version = version.incr(
|
||||
old_version,
|
||||
pattern=cfg.version_pattern,
|
||||
release=release,
|
||||
major=major,
|
||||
minor=minor,
|
||||
patch=patch,
|
||||
)
|
||||
if new_version is None:
|
||||
log.error(f"Invalid version '{old_version}' and/or pattern '{cfg.version_pattern}'.")
|
||||
sys.exit(1)
|
||||
|
||||
log.info(f"Old Version: {old_version}")
|
||||
log.info(f"New Version: {new_version}")
|
||||
|
||||
if dry or verbose >= 2:
|
||||
try:
|
||||
_print_diff(cfg, new_version)
|
||||
except ValueError as ex:
|
||||
log.error(str(ex))
|
||||
sys.exit(1)
|
||||
|
||||
if dry:
|
||||
return
|
||||
|
||||
_bump(cfg, new_version, allow_dirty)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
cli()
|
||||
from . import cli
|
||||
|
||||
cli.cli()
|
||||
|
|
|
|||
351
src/pycalver/cli.py
Executable file
351
src/pycalver/cli.py
Executable file
|
|
@ -0,0 +1,351 @@
|
|||
#!/usr/bin/env python
|
||||
# This file is part of the pycalver project
|
||||
# https://gitlab.com/mbarkhau/pycalver
|
||||
#
|
||||
# Copyright (c) 2019 Manuel Barkhau (mbarkhau@gmail.com) - MIT License
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CLI module for PyCalVer.
|
||||
|
||||
Provided subcommands: show, test, init, bump
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import click
|
||||
import logging
|
||||
import typing as typ
|
||||
|
||||
from . import vcs
|
||||
from . import config
|
||||
from . import version
|
||||
from . import rewrite
|
||||
|
||||
|
||||
_VERBOSE = 0
|
||||
|
||||
|
||||
# To enable pretty tracebacks:
|
||||
# echo "export ENABLE_BACKTRACE=1;" >> ~/.bashrc
|
||||
if os.environ.get('ENABLE_BACKTRACE') == '1':
|
||||
import backtrace
|
||||
|
||||
backtrace.hook(align=True, strip_path=True, enable_on_envvar_only=True)
|
||||
|
||||
|
||||
click.disable_unicode_literals_warning = True
|
||||
|
||||
|
||||
VALID_RELEASE_VALUES = ("alpha", "beta", "dev", "rc", "post", "final")
|
||||
|
||||
|
||||
log = logging.getLogger("pycalver.cli")
|
||||
|
||||
|
||||
def _configure_logging(verbose: int = 0) -> None:
|
||||
if verbose >= 2:
|
||||
log_format = "%(asctime)s.%(msecs)03d %(levelname)-7s %(name)-15s - %(message)s"
|
||||
log_level = logging.DEBUG
|
||||
elif verbose == 1:
|
||||
log_format = "%(levelname)-7s - %(message)s"
|
||||
log_level = logging.INFO
|
||||
else:
|
||||
log_format = "%(levelname)-7s - %(message)s"
|
||||
log_level = logging.INFO
|
||||
|
||||
logging.basicConfig(level=log_level, format=log_format, datefmt="%Y-%m-%dT%H:%M:%S")
|
||||
log.debug("Logging configured.")
|
||||
|
||||
|
||||
def _validate_release_tag(release: str) -> None:
|
||||
if release in VALID_RELEASE_VALUES:
|
||||
return
|
||||
|
||||
log.error(f"Invalid argument --release={release}")
|
||||
log.error(f"Valid arguments are: {', '.join(VALID_RELEASE_VALUES)}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@click.group()
|
||||
@click.version_option(version="v201903.0028")
|
||||
@click.help_option()
|
||||
@click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.")
|
||||
def cli(verbose: int = 0) -> None:
|
||||
"""Automatically update PyCalVer version strings on python projects."""
|
||||
global _VERBOSE
|
||||
_VERBOSE = verbose
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.argument("old_version")
|
||||
@click.argument("pattern", default="{pycalver}")
|
||||
@click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.")
|
||||
@click.option(
|
||||
"--release", default=None, metavar="<name>", help="Override release name of current_version"
|
||||
)
|
||||
@click.option("--major", is_flag=True, default=False, help="Increment major component.")
|
||||
@click.option("--minor", is_flag=True, default=False, help="Increment minor component.")
|
||||
@click.option("--patch", is_flag=True, default=False, help="Increment patch component.")
|
||||
def test(
|
||||
old_version: str,
|
||||
pattern : str = "{pycalver}",
|
||||
verbose : int = 0,
|
||||
release : str = None,
|
||||
major : bool = False,
|
||||
minor : bool = False,
|
||||
patch : bool = False,
|
||||
) -> None:
|
||||
"""Increment a version number for demo purposes."""
|
||||
_configure_logging(verbose=max(_VERBOSE, verbose))
|
||||
|
||||
if release:
|
||||
_validate_release_tag(release)
|
||||
|
||||
new_version = version.incr(
|
||||
old_version, pattern=pattern, release=release, major=major, minor=minor, patch=patch
|
||||
)
|
||||
if new_version is None:
|
||||
log.error(f"Invalid version '{old_version}' and/or pattern '{pattern}'.")
|
||||
sys.exit(1)
|
||||
|
||||
pep440_version = version.to_pep440(new_version)
|
||||
|
||||
print("New Version:", new_version)
|
||||
print("PEP440 :", pep440_version)
|
||||
|
||||
|
||||
def _update_cfg_from_vcs(cfg: config.Config, fetch: bool) -> config.Config:
|
||||
try:
|
||||
_vcs = vcs.get_vcs()
|
||||
log.debug(f"vcs found: {_vcs.name}")
|
||||
if fetch:
|
||||
log.info(f"fetching tags from remote (to turn off use: -n / --no-fetch)")
|
||||
_vcs.fetch()
|
||||
|
||||
version_tags = [tag for tag in _vcs.ls_tags() if version.is_valid(tag, cfg.version_pattern)]
|
||||
if version_tags:
|
||||
version_tags.sort(reverse=True)
|
||||
log.debug(f"found {len(version_tags)} tags: {version_tags[:2]}")
|
||||
latest_version_tag = version_tags[0]
|
||||
latest_version_pep440 = version.to_pep440(latest_version_tag)
|
||||
if latest_version_tag > cfg.current_version:
|
||||
log.info(f"Working dir version : {cfg.current_version}")
|
||||
log.info(f"Latest version from {_vcs.name:>3} tag: {latest_version_tag}")
|
||||
cfg = cfg._replace(
|
||||
current_version=latest_version_tag, pep440_version=latest_version_pep440
|
||||
)
|
||||
|
||||
else:
|
||||
log.debug("no vcs tags found")
|
||||
except OSError:
|
||||
log.debug("No vcs found")
|
||||
|
||||
return cfg
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.")
|
||||
@click.option(
|
||||
"-f/-n", "--fetch/--no-fetch", is_flag=True, default=True, help="Sync tags from remote origin."
|
||||
)
|
||||
def show(verbose: int = 0, fetch: bool = True) -> None:
|
||||
"""Show current version."""
|
||||
_configure_logging(verbose=max(_VERBOSE, verbose))
|
||||
|
||||
ctx: config.ProjectContext = config.init_project_ctx(project_path=".")
|
||||
cfg: config.MaybeConfig = config.parse(ctx)
|
||||
|
||||
if cfg is None:
|
||||
log.error("Could not parse configuration. Perhaps try 'pycalver init'.")
|
||||
sys.exit(1)
|
||||
|
||||
cfg = _update_cfg_from_vcs(cfg, fetch=fetch)
|
||||
|
||||
print(f"Current Version: {cfg.current_version}")
|
||||
print(f"PEP440 : {cfg.pep440_version}")
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option('-v', '--verbose', count=True, help="Control log level. -vv for debug level.")
|
||||
@click.option(
|
||||
"--dry", default=False, is_flag=True, help="Display diff of changes, don't rewrite files."
|
||||
)
|
||||
def init(verbose: int = 0, dry: bool = False) -> None:
|
||||
"""Initialize [pycalver] configuration."""
|
||||
_configure_logging(verbose=max(_VERBOSE, verbose))
|
||||
|
||||
ctx: config.ProjectContext = config.init_project_ctx(project_path=".")
|
||||
cfg: config.MaybeConfig = config.parse(ctx)
|
||||
|
||||
if cfg:
|
||||
log.error(f"Configuration already initialized in {ctx.config_filepath}")
|
||||
sys.exit(1)
|
||||
|
||||
if dry:
|
||||
print(f"Exiting because of '--dry'. Would have written to {ctx.config_filepath}:")
|
||||
cfg_text: str = config.default_config(ctx)
|
||||
print("\n " + "\n ".join(cfg_text.splitlines()))
|
||||
sys.exit(0)
|
||||
|
||||
config.write_content(ctx)
|
||||
|
||||
|
||||
def _assert_not_dirty(_vcs: vcs.VCS, filepaths: typ.Set[str], allow_dirty: bool):
|
||||
dirty_files = _vcs.status(required_files=filepaths)
|
||||
|
||||
if dirty_files:
|
||||
log.warning(f"{_vcs.name} working directory is not clean. Uncomitted file(s):")
|
||||
for dirty_file in dirty_files:
|
||||
log.warning(" " + dirty_file)
|
||||
|
||||
if not allow_dirty and dirty_files:
|
||||
sys.exit(1)
|
||||
|
||||
dirty_pattern_files = set(dirty_files) & filepaths
|
||||
if dirty_pattern_files:
|
||||
log.error("Not commiting when pattern files are dirty:")
|
||||
for dirty_file in dirty_pattern_files:
|
||||
log.warning(" " + dirty_file)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def _bump(cfg: config.Config, new_version: str, allow_dirty: bool = False) -> None:
|
||||
_vcs: typ.Optional[vcs.VCS]
|
||||
|
||||
try:
|
||||
_vcs = vcs.get_vcs()
|
||||
except OSError:
|
||||
log.warning("Version Control System not found, aborting commit.")
|
||||
_vcs = None
|
||||
|
||||
filepaths = set(cfg.file_patterns.keys())
|
||||
|
||||
if _vcs:
|
||||
_assert_not_dirty(_vcs, filepaths, allow_dirty)
|
||||
|
||||
try:
|
||||
rewrite.rewrite(new_version, cfg.file_patterns)
|
||||
except ValueError as ex:
|
||||
log.error(str(ex))
|
||||
sys.exit(1)
|
||||
|
||||
if _vcs is None or not cfg.commit:
|
||||
return
|
||||
|
||||
for filepath in filepaths:
|
||||
_vcs.add(filepath)
|
||||
|
||||
_vcs.commit(f"bump version to {new_version}")
|
||||
|
||||
if cfg.commit and cfg.tag:
|
||||
_vcs.tag(new_version)
|
||||
|
||||
if cfg.commit and cfg.tag and cfg.push:
|
||||
_vcs.push(new_version)
|
||||
|
||||
|
||||
def _print_diff(cfg: config.Config, new_version: str) -> None:
|
||||
diff: str = rewrite.diff(new_version, cfg.file_patterns)
|
||||
|
||||
if sys.stdout.isatty():
|
||||
for line in diff.splitlines():
|
||||
if line.startswith("+++") or line.startswith("---"):
|
||||
print(line)
|
||||
elif line.startswith("+"):
|
||||
print("\u001b[32m" + line + "\u001b[0m")
|
||||
elif line.startswith("-"):
|
||||
print("\u001b[31m" + line + "\u001b[0m")
|
||||
elif line.startswith("@"):
|
||||
print("\u001b[36m" + line + "\u001b[0m")
|
||||
else:
|
||||
print(line)
|
||||
else:
|
||||
print(diff)
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option("-v", "--verbose", count=True, help="Control log level. -vv for debug level.")
|
||||
@click.option(
|
||||
"-f/-n", "--fetch/--no-fetch", is_flag=True, default=True, help="Sync tags from remote origin."
|
||||
)
|
||||
@click.option(
|
||||
"--dry", default=False, is_flag=True, help="Display diff of changes, don't rewrite files."
|
||||
)
|
||||
@click.option(
|
||||
"--release",
|
||||
default=None,
|
||||
metavar="<name>",
|
||||
help=(
|
||||
f"Override release name of current_version. Valid options are: "
|
||||
f"{', '.join(VALID_RELEASE_VALUES)}."
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
"--allow-dirty",
|
||||
default=False,
|
||||
is_flag=True,
|
||||
help=(
|
||||
"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."
|
||||
),
|
||||
)
|
||||
@click.option("--major", is_flag=True, default=False, help="Increment major component.")
|
||||
@click.option("--minor", is_flag=True, default=False, help="Increment minor component.")
|
||||
@click.option("--patch", is_flag=True, default=False, help="Increment patch component.")
|
||||
def bump(
|
||||
release : typ.Optional[str] = None,
|
||||
verbose : int = 0,
|
||||
dry : bool = False,
|
||||
allow_dirty: bool = False,
|
||||
fetch : bool = True,
|
||||
major : bool = False,
|
||||
minor : bool = False,
|
||||
patch : bool = False,
|
||||
) -> None:
|
||||
"""Increment the current version string and update project files."""
|
||||
verbose = max(_VERBOSE, verbose)
|
||||
_configure_logging(verbose)
|
||||
|
||||
if release:
|
||||
_validate_release_tag(release)
|
||||
|
||||
ctx: config.ProjectContext = config.init_project_ctx(project_path=".")
|
||||
cfg: config.MaybeConfig = config.parse(ctx)
|
||||
|
||||
if cfg is None:
|
||||
log.error("Could not parse configuration. Perhaps try 'pycalver init'.")
|
||||
sys.exit(1)
|
||||
|
||||
cfg = _update_cfg_from_vcs(cfg, fetch=fetch)
|
||||
|
||||
old_version = cfg.current_version
|
||||
new_version = version.incr(
|
||||
old_version,
|
||||
pattern=cfg.version_pattern,
|
||||
release=release,
|
||||
major=major,
|
||||
minor=minor,
|
||||
patch=patch,
|
||||
)
|
||||
if new_version is None:
|
||||
log.error(f"Invalid version '{old_version}' and/or pattern '{cfg.version_pattern}'.")
|
||||
sys.exit(1)
|
||||
|
||||
log.info(f"Old Version: {old_version}")
|
||||
log.info(f"New Version: {new_version}")
|
||||
|
||||
if dry or verbose >= 2:
|
||||
try:
|
||||
_print_diff(cfg, new_version)
|
||||
except ValueError as ex:
|
||||
log.error(str(ex))
|
||||
sys.exit(1)
|
||||
|
||||
if dry:
|
||||
return
|
||||
|
||||
_bump(cfg, new_version, allow_dirty)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
cli()
|
||||
|
|
@ -10,7 +10,7 @@ from click.testing import CliRunner
|
|||
|
||||
import pycalver.config as config
|
||||
import pycalver.patterns as patterns
|
||||
import pycalver.__main__ as pycalver
|
||||
import pycalver.cli as cli
|
||||
|
||||
|
||||
SETUP_CFG_FIXTURE = """
|
||||
|
|
@ -66,7 +66,7 @@ def runner(tmpdir):
|
|||
|
||||
|
||||
def test_help(runner):
|
||||
result = runner.invoke(pycalver.cli, ['--help', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['--help', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
assert "PyCalVer" in result.output
|
||||
assert "bump " in result.output
|
||||
|
|
@ -76,7 +76,7 @@ def test_help(runner):
|
|||
|
||||
|
||||
def test_version(runner):
|
||||
result = runner.invoke(pycalver.cli, ['--version', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['--version', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
assert " version v20" in result.output
|
||||
match = patterns.PYCALVER_RE.search(result.output)
|
||||
|
|
@ -87,7 +87,7 @@ def test_incr_default(runner):
|
|||
old_version = "v201701.0999-alpha"
|
||||
initial_version = config._initial_version()
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['test', "--verbose", old_version])
|
||||
result = runner.invoke(cli.cli, ['test', "--verbose", old_version])
|
||||
assert result.exit_code == 0
|
||||
new_version = initial_version.replace(".0001-alpha", ".11000-alpha")
|
||||
assert f"Version: {new_version}\n" in result.output
|
||||
|
|
@ -98,37 +98,31 @@ def test_incr_semver(runner):
|
|||
old_version = "0.1.0"
|
||||
new_version = "0.1.1"
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['test', "--verbose", "--patch", old_version, "{semver}"])
|
||||
result = runner.invoke(cli.cli, ['test', "--verbose", "--patch", old_version, "{semver}"])
|
||||
assert result.exit_code == 0
|
||||
assert f"Version: {new_version}\n" in result.output
|
||||
|
||||
result = runner.invoke(
|
||||
pycalver.cli, ['test', "--verbose", "--patch", old_version, semver_pattern]
|
||||
)
|
||||
result = runner.invoke(cli.cli, ['test', "--verbose", "--patch", old_version, semver_pattern])
|
||||
assert result.exit_code == 0
|
||||
assert f"Version: {new_version}\n" in result.output
|
||||
|
||||
old_version = "0.1.1"
|
||||
new_version = "0.2.0"
|
||||
|
||||
result = runner.invoke(
|
||||
pycalver.cli, ['test', "--verbose", "--minor", old_version, semver_pattern]
|
||||
)
|
||||
result = runner.invoke(cli.cli, ['test', "--verbose", "--minor", old_version, semver_pattern])
|
||||
assert result.exit_code == 0
|
||||
assert f"Version: {new_version}\n" in result.output
|
||||
|
||||
old_version = "0.1.1"
|
||||
new_version = "1.0.0"
|
||||
|
||||
result = runner.invoke(
|
||||
pycalver.cli, ['test', "--verbose", "--major", old_version, semver_pattern]
|
||||
)
|
||||
result = runner.invoke(cli.cli, ['test', "--verbose", "--major", old_version, semver_pattern])
|
||||
assert result.exit_code == 0
|
||||
assert f"Version: {new_version}\n" in result.output
|
||||
|
||||
|
||||
def test_incr_semver_invalid(runner, caplog):
|
||||
result = runner.invoke(pycalver.cli, ['test', "--verbose", "--patch", "0.1.1"])
|
||||
result = runner.invoke(cli.cli, ['test', "--verbose", "--patch", "0.1.1"])
|
||||
assert result.exit_code == 1
|
||||
assert len(caplog.records) > 0
|
||||
log_record = caplog.records[0]
|
||||
|
|
@ -140,7 +134,7 @@ def test_incr_to_beta(runner):
|
|||
old_version = "v201701.0999-alpha"
|
||||
initial_version = config._initial_version()
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['test', old_version, "--verbose", "--release", "beta"])
|
||||
result = runner.invoke(cli.cli, ['test', old_version, "--verbose", "--release", "beta"])
|
||||
assert result.exit_code == 0
|
||||
new_version = initial_version.replace(".0001-alpha", ".11000-beta")
|
||||
assert f"Version: {new_version}\n" in result.output
|
||||
|
|
@ -150,7 +144,7 @@ def test_incr_to_final(runner):
|
|||
old_version = "v201701.0999-alpha"
|
||||
initial_version = config._initial_version()
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['test', old_version, "--verbose", "--release", "final"])
|
||||
result = runner.invoke(cli.cli, ['test', old_version, "--verbose", "--release", "final"])
|
||||
assert result.exit_code == 0
|
||||
new_version = initial_version.replace(".0001-alpha", ".11000")
|
||||
assert f"Version: {new_version}\n" in result.output
|
||||
|
|
@ -159,7 +153,7 @@ def test_incr_to_final(runner):
|
|||
def test_incr_invalid(runner):
|
||||
old_version = "v201701.0999-alpha"
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['test', old_version, "--verbose", "--release", "alfa"])
|
||||
result = runner.invoke(cli.cli, ['test', old_version, "--verbose", "--release", "alfa"])
|
||||
assert result.exit_code == 1
|
||||
|
||||
|
||||
|
|
@ -188,7 +182,7 @@ def _add_project_files(*files):
|
|||
|
||||
def test_nocfg(runner, caplog):
|
||||
_add_project_files("README.md")
|
||||
result = runner.invoke(pycalver.cli, ['show', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['show', "--verbose"])
|
||||
assert result.exit_code == 1
|
||||
assert any(
|
||||
bool("Could not parse configuration. Perhaps try 'pycalver init'." in r.message)
|
||||
|
|
@ -199,7 +193,7 @@ def test_nocfg(runner, caplog):
|
|||
def test_novcs_nocfg_init(runner, caplog, capsys):
|
||||
_add_project_files("README.md")
|
||||
# dry mode test
|
||||
result = runner.invoke(pycalver.cli, ['init', "--verbose", "--dry"])
|
||||
result = runner.invoke(cli.cli, ['init', "--verbose", "--dry"])
|
||||
assert result.exit_code == 0
|
||||
assert not os.path.exists("pycalver.toml")
|
||||
|
||||
|
|
@ -215,7 +209,7 @@ def test_novcs_nocfg_init(runner, caplog, capsys):
|
|||
# assert "Would have written to pycalver.toml:" in captured.out
|
||||
|
||||
# non dry mode
|
||||
result = runner.invoke(pycalver.cli, ['init', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['init', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
# check logging
|
||||
|
|
@ -232,12 +226,12 @@ def test_novcs_nocfg_init(runner, caplog, capsys):
|
|||
assert base_str in cfg_content
|
||||
assert config.DEFAULT_TOML_README_MD_STR in cfg_content
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['show', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['show', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
assert f"Current Version: {config._initial_version()}\n" in result.output
|
||||
assert f"PEP440 : {config._initial_version_pep440()}\n" in result.output
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['init', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['init', "--verbose"])
|
||||
assert result.exit_code == 1
|
||||
|
||||
# check logging
|
||||
|
|
@ -249,7 +243,7 @@ def test_novcs_nocfg_init(runner, caplog, capsys):
|
|||
|
||||
def test_novcs_setupcfg_init(runner):
|
||||
_add_project_files("README.md", "setup.cfg")
|
||||
result = runner.invoke(pycalver.cli, ['init', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['init', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
with pl.Path("setup.cfg").open(mode="r", encoding="utf-8") as fh:
|
||||
|
|
@ -261,7 +255,7 @@ def test_novcs_setupcfg_init(runner):
|
|||
assert base_str in cfg_content
|
||||
assert config.DEFAULT_CONFIGPARSER_README_MD_STR in cfg_content
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['show', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['show', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
assert f"Current Version: {config._initial_version()}\n" in result.output
|
||||
assert f"PEP440 : {config._initial_version_pep440()}\n" in result.output
|
||||
|
|
@ -269,7 +263,7 @@ def test_novcs_setupcfg_init(runner):
|
|||
|
||||
def test_novcs_pyproject_init(runner):
|
||||
_add_project_files("README.md", "pyproject.toml")
|
||||
result = runner.invoke(pycalver.cli, ['init', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['init', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
with pl.Path("pyproject.toml").open(mode="r", encoding="utf-8") as fh:
|
||||
|
|
@ -279,7 +273,7 @@ def test_novcs_pyproject_init(runner):
|
|||
assert base_str in cfg_content
|
||||
assert config.DEFAULT_TOML_README_MD_STR in cfg_content
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['show'])
|
||||
result = runner.invoke(cli.cli, ['show'])
|
||||
assert result.exit_code == 0
|
||||
assert f"Current Version: {config._initial_version()}\n" in result.output
|
||||
assert f"PEP440 : {config._initial_version_pep440()}\n" in result.output
|
||||
|
|
@ -299,10 +293,10 @@ def test_git_init(runner):
|
|||
_add_project_files("README.md")
|
||||
_vcs_init("git")
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['init', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['init', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['show'])
|
||||
result = runner.invoke(cli.cli, ['show'])
|
||||
assert result.exit_code == 0
|
||||
assert f"Current Version: {config._initial_version()}\n" in result.output
|
||||
assert f"PEP440 : {config._initial_version_pep440()}\n" in result.output
|
||||
|
|
@ -312,10 +306,10 @@ def test_hg_init(runner):
|
|||
_add_project_files("README.md")
|
||||
_vcs_init("hg")
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['init', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['init', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['show'])
|
||||
result = runner.invoke(cli.cli, ['show'])
|
||||
assert result.exit_code == 0
|
||||
assert f"Current Version: {config._initial_version()}\n" in result.output
|
||||
assert f"PEP440 : {config._initial_version_pep440()}\n" in result.output
|
||||
|
|
@ -327,7 +321,7 @@ def test_git_tag_eval(runner):
|
|||
|
||||
# This will set a version that is older than the version tag
|
||||
# we set in the vcs, which should take precedence.
|
||||
result = runner.invoke(pycalver.cli, ['init', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['init', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
initial_version = config._initial_version()
|
||||
tag_version = initial_version.replace(".0001-alpha", ".0123-beta")
|
||||
|
|
@ -335,7 +329,7 @@ def test_git_tag_eval(runner):
|
|||
|
||||
sh("git", "tag", "--annotate", tag_version, "--message", f"bump version to {tag_version}")
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['show', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['show', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
assert f"Current Version: {tag_version}\n" in result.output
|
||||
assert f"PEP440 : {tag_version_pep440}\n" in result.output
|
||||
|
|
@ -347,7 +341,7 @@ def test_hg_tag_eval(runner):
|
|||
|
||||
# This will set a version that is older than the version tag
|
||||
# we set in the vcs, which should take precedence.
|
||||
result = runner.invoke(pycalver.cli, ['init', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['init', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
initial_version = config._initial_version()
|
||||
tag_version = initial_version.replace(".0001-alpha", ".0123-beta")
|
||||
|
|
@ -355,7 +349,7 @@ def test_hg_tag_eval(runner):
|
|||
|
||||
sh("hg", "tag", tag_version, "--message", f"bump version to {tag_version}")
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['show', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['show', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
assert f"Current Version: {tag_version}\n" in result.output
|
||||
assert f"PEP440 : {tag_version_pep440}\n" in result.output
|
||||
|
|
@ -364,10 +358,10 @@ def test_hg_tag_eval(runner):
|
|||
def test_novcs_bump(runner):
|
||||
_add_project_files("README.md")
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['init', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['init', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['bump', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['bump', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
calver = config._initial_version()[:7]
|
||||
|
|
@ -377,7 +371,7 @@ def test_novcs_bump(runner):
|
|||
assert calver + ".0002-alpha !\n" in content
|
||||
assert calver[1:] + ".2a0 !\n" in content
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['bump', "--verbose", "--release", "beta"])
|
||||
result = runner.invoke(cli.cli, ['bump', "--verbose", "--release", "beta"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
with pl.Path("README.md").open() as fh:
|
||||
|
|
@ -390,13 +384,13 @@ def test_git_bump(runner):
|
|||
_add_project_files("README.md")
|
||||
_vcs_init("git")
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['init', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['init', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
sh("git", "add", "pycalver.toml")
|
||||
sh("git", "commit", "-m", "initial commit")
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['bump', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['bump', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
calver = config._initial_version()[:7]
|
||||
|
|
@ -410,13 +404,13 @@ def test_hg_bump(runner):
|
|||
_add_project_files("README.md")
|
||||
_vcs_init("hg")
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['init', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['init', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
sh("hg", "add", "pycalver.toml")
|
||||
sh("hg", "commit", "-m", "initial commit")
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['bump', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['bump', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
calver = config._initial_version()[:7]
|
||||
|
|
@ -430,7 +424,7 @@ def test_empty_git_bump(runner, caplog):
|
|||
sh("git", "init")
|
||||
with pl.Path("setup.cfg").open(mode="w") as fh:
|
||||
fh.write("")
|
||||
result = runner.invoke(pycalver.cli, ['init', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['init', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
with pl.Path("setup.cfg").open(mode="r") as fh:
|
||||
|
|
@ -441,7 +435,7 @@ def test_empty_git_bump(runner, caplog):
|
|||
assert "\n[pycalver:file_patterns]\n" in default_cfg_data
|
||||
assert "\nsetup.cfg =\n" in default_cfg_data
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['bump'])
|
||||
result = runner.invoke(cli.cli, ['bump'])
|
||||
|
||||
assert any(("working directory is not clean" in r.message) for r in caplog.records)
|
||||
assert any(("setup.cfg" in r.message) for r in caplog.records)
|
||||
|
|
@ -451,7 +445,7 @@ def test_empty_hg_bump(runner, caplog):
|
|||
sh("hg", "init")
|
||||
with pl.Path("setup.cfg").open(mode="w") as fh:
|
||||
fh.write("")
|
||||
result = runner.invoke(pycalver.cli, ['init', "--verbose"])
|
||||
result = runner.invoke(cli.cli, ['init', "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
with pl.Path("setup.cfg").open(mode="r") as fh:
|
||||
|
|
@ -462,7 +456,7 @@ def test_empty_hg_bump(runner, caplog):
|
|||
assert "\n[pycalver:file_patterns]\n" in default_cfg_data
|
||||
assert "\nsetup.cfg =\n" in default_cfg_data
|
||||
|
||||
result = runner.invoke(pycalver.cli, ['bump'])
|
||||
result = runner.invoke(cli.cli, ['bump'])
|
||||
|
||||
assert any(("working directory is not clean" in r.message) for r in caplog.records)
|
||||
assert any(("setup.cfg" in r.message) for r in caplog.records)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue