Coverage for /Users/OORDCOR/Documents/code/bump-my-version/bumpversion/bump.py: 19%
62 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-15 09:15 -0600
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-15 09:15 -0600
1"""Version changing methods."""
2import shlex
3from pathlib import Path
4from typing import TYPE_CHECKING, ChainMap, List, Optional
6if TYPE_CHECKING: # pragma: no-coverage 6 ↛ 7line 6 didn't jump to line 7, because the condition on line 6 was never true
7 from bumpversion.files import ConfiguredFile
8 from bumpversion.version_part import Version
10from bumpversion.config import Config
11from bumpversion.config.files import update_config_file
12from bumpversion.config.files_legacy import update_ini_config_file
13from bumpversion.exceptions import ConfigurationError
14from bumpversion.ui import get_indented_logger
15from bumpversion.utils import get_context, key_val_string
17logger = get_indented_logger(__name__)
20def get_next_version(
21 current_version: "Version", config: Config, version_part: Optional[str], new_version: Optional[str]
22) -> "Version":
23 """
24 Bump the version_part to the next value.
26 Args:
27 current_version: The current version
28 config: The current configuration
29 version_part: Optional part of the version to bump
30 new_version: Optional specific version to bump to
32 Returns:
33 The new version
35 Raises:
36 ConfigurationError: If it can't generate the next version.
37 """
38 if new_version:
39 logger.info("Attempting to set new version '%s'", new_version)
40 logger.indent()
41 next_version = config.version_config.parse(new_version)
42 elif version_part:
43 logger.info("Attempting to increment part '%s'", version_part)
44 logger.indent()
45 next_version = current_version.bump(version_part, config.version_config.order)
46 else:
47 raise ConfigurationError("Unable to get the next version.")
49 logger.info("Values are now: %s", key_val_string(next_version.values))
50 logger.dedent()
51 return next_version
54def do_bump(
55 version_part: Optional[str],
56 new_version: Optional[str],
57 config: Config,
58 config_file: Optional[Path] = None,
59 dry_run: bool = False,
60) -> None:
61 """
62 Bump the version_part to the next value or set the version to new_version.
64 Args:
65 version_part: The version part to bump
66 new_version: The explicit version to set
67 config: The configuration to use
68 config_file: The configuration file to update
69 dry_run: True if the operation should be a dry run
70 """
71 from bumpversion.files import modify_files, resolve_file_config
73 logger.indent()
75 ctx = get_context(config)
76 logger.info("Parsing current version '%s'", config.current_version)
77 logger.indent()
78 version = config.version_config.parse(config.current_version)
79 logger.dedent()
80 next_version = get_next_version(version, config, version_part, new_version)
81 next_version_str = config.version_config.serialize(next_version, ctx)
82 logger.info("New version will be '%s'", next_version_str)
84 if config.current_version == next_version_str:
85 logger.info("Version is already '%s'", next_version_str)
86 return
88 logger.dedent()
90 if dry_run:
91 logger.info("Dry run active, won't touch any files.")
93 ctx = get_context(config, version, next_version)
95 configured_files = resolve_file_config(config.files_to_modify, config.version_config)
96 modify_files(configured_files, version, next_version, ctx, dry_run)
97 if config_file and config_file.suffix in {".cfg", ".ini"}:
98 update_ini_config_file(config_file, config.current_version, next_version_str, dry_run)
99 else:
100 update_config_file(config_file, config, version, next_version, ctx, dry_run)
102 ctx = get_context(config, version, next_version)
103 ctx["new_version"] = next_version_str
104 commit_and_tag(config, config_file, configured_files, ctx, dry_run)
105 logger.info("Done.")
108def commit_and_tag(
109 config: Config,
110 config_file: Optional[Path],
111 configured_files: List["ConfiguredFile"],
112 ctx: ChainMap,
113 dry_run: bool = False,
114) -> None:
115 """
116 Commit and tag the changes, if a tool is configured.
118 Args:
119 config: The configuration
120 config_file: The configuration file to include in the commit, if it exists
121 configured_files: A list of files to commit
122 ctx: The context used to render the tag and tag message
123 dry_run: True if the operation should be a dry run
124 """
125 if not config.scm_info.tool:
126 return
128 extra_args = shlex.split(config.commit_args) if config.commit_args else []
130 commit_files = {f.file_change.filename for f in configured_files}
131 if config_file:
132 commit_files |= {str(config_file)}
134 config.scm_info.tool.commit_to_scm(list(commit_files), config, ctx, extra_args, dry_run)
135 config.scm_info.tool.tag_in_scm(config, ctx, dry_run)