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

1"""Version changing methods.""" 

2import shlex 

3from pathlib import Path 

4from typing import TYPE_CHECKING, ChainMap, List, Optional 

5 

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 

9 

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 

16 

17logger = get_indented_logger(__name__) 

18 

19 

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. 

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 

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. 

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 

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. 

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)