Coverage for /Users/OORDCOR/Documents/code/bump-my-version/bumpversion/bump.py: 19%

1"""Version changing methods."""

2 import shlex

3 from pathlib import Path

4 from typing import TYPE_CHECKING, ChainMap, List, Optional

5

6 if 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

9

10 from bumpversion.config import Config

11 from bumpversion.config.files import update_config_file

12 from bumpversion.config.files_legacy import update_ini_config_file

13 from bumpversion.exceptions import ConfigurationError

14 from bumpversion.ui import get_indented_logger

15 from bumpversion.utils import get_context, key_val_string

16

17 logger = get_indented_logger(__name__)

18

19

20 def 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.

25

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

31

32 Returns:

33 The new version

34

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.")

48

49 logger.info("Values are now: %s", key_val_string(next_version.values))

50 logger.dedent()

51 return next_version

52

53

54 def 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.

63

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

72

73 logger.indent()

74

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)

83

84 if config.current_version == next_version_str:

85 logger.info("Version is already '%s'", next_version_str)

86 return

87

88 logger.dedent()

89

90 if dry_run:

91 logger.info("Dry run active, won't touch any files.")

92

93 ctx = get_context(config, version, next_version)

94

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)

101

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.")

106

107

108 def 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.

117

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

127

128 extra_args = shlex.split(config.commit_args) if config.commit_args else []

129

130 commit_files = {f.file_change.filename for f in configured_files}

131 if config_file:

132 commit_files |= {str(config_file)}

133

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)