commit bumpversion for openSUSE:Factory
Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package bumpversion for openSUSE:Factory checked in at 2021-12-29 21:10:55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/bumpversion (Old) and /work/SRC/openSUSE:Factory/.bumpversion.new.2520 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "bumpversion" Wed Dec 29 21:10:55 2021 rev:2 rq:942976 version:0.6.0 Changes: -------- --- /work/SRC/openSUSE:Factory/bumpversion/bumpversion.changes 2017-09-04 12:34:18.244541356 +0200 +++ /work/SRC/openSUSE:Factory/.bumpversion.new.2520/bumpversion.changes 2021-12-29 21:11:25.682308780 +0100 @@ -1,0 +2,11 @@ +Tue Dec 21 17:35:09 UTC 2021 - Sebastian Wagner <sebix+novell.com@sebix.at> + +- require python-rpm-macros for building to fix build on Leap + +------------------------------------------------------------------- +Sun May 17 20:00:21 UTC 2020 - Sebastian Wagner <sebix+novell.com@sebix.at> + +- update to version 0.6.0: + * Deprecation: publish package that links to the newer bump2version for seamless upgrades (see: https://www.python.org/dev/peps/pep-0423/#id106) + +------------------------------------------------------------------- Old: ---- bumpversion-0.5.3.tar.gz New: ---- bumpversion-0.6.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ bumpversion.spec ++++++ --- /var/tmp/diff_new_pack.XVOFYD/_old 2021-12-29 21:11:26.110309132 +0100 +++ /var/tmp/diff_new_pack.XVOFYD/_new 2021-12-29 21:11:26.114309135 +0100 @@ -1,7 +1,7 @@ # # spec file for package bumpversion # -# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -12,20 +12,21 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# Please submit bugfixes or comments via https://bugs.opensuse.org/ # Name: bumpversion -Version: 0.5.3 +Version: 0.6.0 Release: 0 Summary: Version-bump your software with a single command License: MIT Group: Development/Tools/Version Control -Url: https://github.com/peritus/bumpversion +URL: https://github.com/peritus/bumpversion Source: https://files.pythonhosted.org/packages/source/b/bumpversion/bumpversion-%{version}.tar.gz -BuildRequires: python3-devel +BuildRequires: python-rpm-macros BuildRequires: python3-setuptools +Requires: python3-base Provides: python-bumpversion = %version Obsoletes: python-bumpversion < %version BuildArch: noarch @@ -47,7 +48,6 @@ %files %doc README.rst -%{_bindir}/bumpversion %{python3_sitelib}/bumpversion* %changelog ++++++ bumpversion-0.5.3.tar.gz -> bumpversion-0.6.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumpversion-0.5.3/LICENSE.rst new/bumpversion-0.6.0/LICENSE.rst --- old/bumpversion-0.5.3/LICENSE.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/bumpversion-0.6.0/LICENSE.rst 2020-05-14 04:02:16.000000000 +0200 @@ -0,0 +1,20 @@ +Copyright (C) 2013-2014 Filip Noetzel + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumpversion-0.5.3/MANIFEST.in new/bumpversion-0.6.0/MANIFEST.in --- old/bumpversion-0.5.3/MANIFEST.in 2013-03-16 08:12:47.000000000 +0100 +++ new/bumpversion-0.6.0/MANIFEST.in 2020-05-14 04:17:55.000000000 +0200 @@ -1 +1,2 @@ -include README.rst +include README.rst LICENSE.rst +#recursive-include tests *.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumpversion-0.5.3/PKG-INFO new/bumpversion-0.6.0/PKG-INFO --- old/bumpversion-0.5.3/PKG-INFO 2015-04-15 11:14:23.000000000 +0200 +++ new/bumpversion-0.6.0/PKG-INFO 2020-05-14 04:18:10.000000000 +0200 @@ -1,12 +1,19 @@ Metadata-Version: 1.1 Name: bumpversion -Version: 0.5.3 +Version: 0.6.0 Summary: Version-bump your software with a single command! Home-page: https://github.com/peritus/bumpversion Author: Filip Noetzel Author-email: filip+bumpversion@j03.de License: MIT -Description: =========== +Description: **������ Current status of this project** + + * ����If you want to start **using bumpversion**, you're best advised to **install one of the maintained forks**, e.g. ��� `@c4urself's bump2version <https://github.com/c4urself/bump2version/#installation>`_. + * ����If you want to **help maintain** bumpversion, there's an `ongoing discussion about merging the fork back to the original project as well as forming a group of maintainers <https://github.com/c4urself/bump2version/issues/86>`_ to ensure a long-term future for this project. Please contribute. + + ----- + + =========== bumpversion =========== @@ -131,7 +138,7 @@ Also available on the command line as ``(--tag | --no-tag)``. ``tag_name =`` - **default:** "``v{new_version}``" + **default:** ``v{new_version}`` The name of the tag that will be created. Only valid when using ``--tag`` / ``tag = True``. @@ -153,7 +160,7 @@ Also available as ``(--commit | --no-commit)``. ``message =`` - **default:** "``Bump version: {current_version} ��� {new_version}``" + **default:** ``Bump version: {current_version} ��� {new_version}`` The commit message to use when creating a commit. Only valid when using ``--commit`` / ``commit = True``. @@ -242,7 +249,7 @@ ``[bumpversion:file:���]`` ``parse =`` - **default:** "``(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)``" + **default:** ``(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)`` Regular expression (using `Python regular expression syntax <http://docs.python.org/2/library/re.html#regular-expression-syntax>`_) on @@ -254,7 +261,7 @@ Also available as ``--parse`` ``serialize =`` - **default:** "``{major}.{minor}.{patch}``" + **default:** ``{major}.{minor}.{patch}`` Template specifying how to serialize the version parts back to a version string. @@ -280,7 +287,7 @@ given like ``--serialize {major}.{minor} --serialize {major}`` ``search =`` - **default:** "``{current_version}``" + **default:** ``{current_version}`` Template string how to search for the string to be replaced in the file. Useful if the remotest possibility exists that the current version number @@ -289,7 +296,7 @@ <http://docs.python.org/2/library/string.html#format-string-syntax>`_. ``replace =`` - **default:** "``{new_version}``" + **default:** ``{new_version}`` Template to create the string that will replace the current version number in the file. @@ -341,6 +348,27 @@ ``-h, --help`` Print help and exit + Using bumpversion in a script + ============================= + + If you need to use the version generated by bumpversion in a script you can make use of + the `--list` option, combined with `grep` and `sed`. + + Say for example that you are using git-flow to manage your project and want to automatically + create a release. When you issue `git flow release start` you already need to know the + new version, before applying the change. + + The standard way to get it in a bash script is + + bumpversion --dry-run --list <part> | grep <field name> | sed -r s,"^.*=",, + + where <part> is as usual the part of the version number you are updating. You need to specify + `--dry-run` to avoid bumpversion actually bumping the version number. + + For example, if you are updating the minor number and looking for the new version number this becomes + + bumpversion --dry-run --list minor | grep new_version | sed -r s,"^.*=",, + Development =========== @@ -370,7 +398,10 @@ Changes ======= - **unreleased** + **0.6.0** + + - Deprecation: publish package that links to the newer bump2version for seamless + upgrades (see: https://www.python.org/dev/peps/pep-0423/#id106) **v0.5.3** @@ -506,7 +537,7 @@ Platform: UNKNOWN -Classifier: Development Status :: 4 - Beta +Classifier: Development Status :: 7 - Inactive Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumpversion-0.5.3/README.rst new/bumpversion-0.6.0/README.rst --- old/bumpversion-0.5.3/README.rst 2015-04-15 11:13:47.000000000 +0200 +++ new/bumpversion-0.6.0/README.rst 2020-05-14 04:17:55.000000000 +0200 @@ -1,3 +1,10 @@ +**������ Current status of this project** + +* ����If you want to start **using bumpversion**, you're best advised to **install one of the maintained forks**, e.g. ��� `@c4urself's bump2version <https://github.com/c4urself/bump2version/#installation>`_. +* ����If you want to **help maintain** bumpversion, there's an `ongoing discussion about merging the fork back to the original project as well as forming a group of maintainers <https://github.com/c4urself/bump2version/issues/86>`_ to ensure a long-term future for this project. Please contribute. + +----- + =========== bumpversion =========== @@ -123,7 +130,7 @@ Also available on the command line as ``(--tag | --no-tag)``. ``tag_name =`` - **default:** "``v{new_version}``" + **default:** ``v{new_version}`` The name of the tag that will be created. Only valid when using ``--tag`` / ``tag = True``. @@ -145,7 +152,7 @@ Also available as ``(--commit | --no-commit)``. ``message =`` - **default:** "``Bump version: {current_version} ��� {new_version}``" + **default:** ``Bump version: {current_version} ��� {new_version}`` The commit message to use when creating a commit. Only valid when using ``--commit`` / ``commit = True``. @@ -234,7 +241,7 @@ ``[bumpversion:file:���]`` ``parse =`` - **default:** "``(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)``" + **default:** ``(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)`` Regular expression (using `Python regular expression syntax <http://docs.python.org/2/library/re.html#regular-expression-syntax>`_) on @@ -246,7 +253,7 @@ Also available as ``--parse`` ``serialize =`` - **default:** "``{major}.{minor}.{patch}``" + **default:** ``{major}.{minor}.{patch}`` Template specifying how to serialize the version parts back to a version string. @@ -272,7 +279,7 @@ given like ``--serialize {major}.{minor} --serialize {major}`` ``search =`` - **default:** "``{current_version}``" + **default:** ``{current_version}`` Template string how to search for the string to be replaced in the file. Useful if the remotest possibility exists that the current version number @@ -281,7 +288,7 @@ <http://docs.python.org/2/library/string.html#format-string-syntax>`_. ``replace =`` - **default:** "``{new_version}``" + **default:** ``{new_version}`` Template to create the string that will replace the current version number in the file. @@ -333,6 +340,27 @@ ``-h, --help`` Print help and exit +Using bumpversion in a script +============================= + +If you need to use the version generated by bumpversion in a script you can make use of +the `--list` option, combined with `grep` and `sed`. + +Say for example that you are using git-flow to manage your project and want to automatically +create a release. When you issue `git flow release start` you already need to know the +new version, before applying the change. + +The standard way to get it in a bash script is + + bumpversion --dry-run --list <part> | grep <field name> | sed -r s,"^.*=",, + +where <part> is as usual the part of the version number you are updating. You need to specify +`--dry-run` to avoid bumpversion actually bumping the version number. + +For example, if you are updating the minor number and looking for the new version number this becomes + + bumpversion --dry-run --list minor | grep new_version | sed -r s,"^.*=",, + Development =========== @@ -362,7 +390,10 @@ Changes ======= -**unreleased** +**0.6.0** + +- Deprecation: publish package that links to the newer bump2version for seamless + upgrades (see: https://www.python.org/dev/peps/pep-0423/#id106) **v0.5.3** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumpversion-0.5.3/bumpversion/__init__.py new/bumpversion-0.6.0/bumpversion/__init__.py --- old/bumpversion-0.5.3/bumpversion/__init__.py 2015-04-15 11:12:43.000000000 +0200 +++ new/bumpversion-0.6.0/bumpversion/__init__.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,1005 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals - -try: - from configparser import RawConfigParser, NoOptionError -except ImportError: - from ConfigParser import RawConfigParser, NoOptionError - -try: - from StringIO import StringIO -except: - from io import StringIO - - -import argparse -import os -import re -import sre_constants -import subprocess -import warnings -import io -from string import Formatter -from datetime import datetime -from difflib import unified_diff -from tempfile import NamedTemporaryFile - -import sys -import codecs - -if sys.version_info[0] == 2: - sys.stdout = codecs.getwriter('utf-8')(sys.stdout) - -__VERSION__ = '0.5.3' - -DESCRIPTION = 'bumpversion: v{} (using Python v{})'.format( - __VERSION__, - sys.version.split("\n")[0].split(" ")[0], -) - -import logging -logger = logging.getLogger("bumpversion.logger") -logger_list = logging.getLogger("bumpversion.list") - -from argparse import _AppendAction -class DiscardDefaultIfSpecifiedAppendAction(_AppendAction): - - ''' - Fixes bug http://bugs.python.org/issue16399 for 'append' action - ''' - - def __call__(self, parser, namespace, values, option_string=None): - if getattr(self, "_discarded_default", None) is None: - setattr(namespace, self.dest, []) - self._discarded_default = True - - super(DiscardDefaultIfSpecifiedAppendAction, self).__call__( - parser, namespace, values, option_string=None) - -time_context = { - 'now': datetime.now(), - 'utcnow': datetime.utcnow(), -} - -class BaseVCS(object): - - @classmethod - def commit(cls, message): - f = NamedTemporaryFile('wb', delete=False) - f.write(message.encode('utf-8')) - f.close() - subprocess.check_output(cls._COMMIT_COMMAND + [f.name], env=dict( - list(os.environ.items()) + [(b'HGENCODING', b'utf-8')] - )) - os.unlink(f.name) - - @classmethod - def is_usable(cls): - try: - return subprocess.call( - cls._TEST_USABLE_COMMAND, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE - ) == 0 - except OSError as e: - if e.errno == 2: - # mercurial is not installed then, ok. - return False - raise - - -class Git(BaseVCS): - - _TEST_USABLE_COMMAND = ["git", "rev-parse", "--git-dir"] - _COMMIT_COMMAND = ["git", "commit", "-F"] - - @classmethod - def assert_nondirty(cls): - lines = [ - line.strip() for line in - subprocess.check_output( - ["git", "status", "--porcelain"]).splitlines() - if not line.strip().startswith(b"??") - ] - - if lines: - raise WorkingDirectoryIsDirtyException( - "Git working directory is not clean:\n{}".format( - b"\n".join(lines))) - - @classmethod - def latest_tag_info(cls): - try: - # git-describe doesn't update the git-index, so we do that - subprocess.check_output(["git", "update-index", "--refresh"]) - - # get info about the latest tag in git - describe_out = subprocess.check_output([ - "git", - "describe", - "--dirty", - "--tags", - "--long", - "--abbrev=40", - "--match=v*", - ], stderr=subprocess.STDOUT - ).decode().split("-") - except subprocess.CalledProcessError: - # logger.warn("Error when running git describe") - return {} - - info = {} - - if describe_out[-1].strip() == "dirty": - info["dirty"] = True - describe_out.pop() - - info["commit_sha"] = describe_out.pop().lstrip("g") - info["distance_to_latest_tag"] = int(describe_out.pop()) - info["current_version"] = "-".join(describe_out).lstrip("v") - - return info - - @classmethod - def add_path(cls, path): - subprocess.check_output(["git", "add", "--update", path]) - - @classmethod - def tag(cls, name): - subprocess.check_output(["git", "tag", name]) - - -class Mercurial(BaseVCS): - - _TEST_USABLE_COMMAND = ["hg", "root"] - _COMMIT_COMMAND = ["hg", "commit", "--logfile"] - - @classmethod - def latest_tag_info(cls): - return {} - - @classmethod - def assert_nondirty(cls): - lines = [ - line.strip() for line in - subprocess.check_output( - ["hg", "status", "-mard"]).splitlines() - if not line.strip().startswith(b"??") - ] - - if lines: - raise WorkingDirectoryIsDirtyException( - "Mercurial working directory is not clean:\n{}".format( - b"\n".join(lines))) - - @classmethod - def add_path(cls, path): - pass - - @classmethod - def tag(cls, name): - subprocess.check_output(["hg", "tag", name]) - -VCS = [Git, Mercurial] - - -def prefixed_environ(): - return dict((("${}".format(key), value) for key, value in os.environ.items())) - -class ConfiguredFile(object): - - def __init__(self, path, versionconfig): - self.path = path - self._versionconfig = versionconfig - - def should_contain_version(self, version, context): - - context['current_version'] = self._versionconfig.serialize(version, context) - - serialized_version = self._versionconfig.search.format(**context) - - if self.contains(serialized_version): - return - - msg = "Did not find '{}' or '{}' in file {}".format(version.original, serialized_version, self.path) - - if version.original: - assert self.contains(version.original), msg - return - - assert False, msg - - def contains(self, search): - with io.open(self.path, 'rb') as f: - search_lines = search.splitlines() - lookbehind = [] - - for lineno, line in enumerate(f.readlines()): - lookbehind.append(line.decode('utf-8').rstrip("\n")) - - if len(lookbehind) > len(search_lines): - lookbehind = lookbehind[1:] - - if (search_lines[0] in lookbehind[0] and - search_lines[-1] in lookbehind[-1] and - search_lines[1:-1] == lookbehind[1:-1]): - logger.info("Found '{}' in {} at line {}: {}".format( - search, self.path, lineno - (len(lookbehind) - 1), line.decode('utf-8').rstrip())) - return True - return False - - def replace(self, current_version, new_version, context, dry_run): - - with io.open(self.path, 'rb') as f: - file_content_before = f.read().decode('utf-8') - - context['current_version'] = self._versionconfig.serialize(current_version, context) - context['new_version'] = self._versionconfig.serialize(new_version, context) - - search_for = self._versionconfig.search.format(**context) - replace_with = self._versionconfig.replace.format(**context) - - file_content_after = file_content_before.replace( - search_for, replace_with - ) - - if file_content_before == file_content_after: - # TODO expose this to be configurable - file_content_after = file_content_before.replace( - current_version.original, - replace_with, - ) - - if file_content_before != file_content_after: - logger.info("{} file {}:".format( - "Would change" if dry_run else "Changing", - self.path, - )) - logger.info("\n".join(list(unified_diff( - file_content_before.splitlines(), - file_content_after.splitlines(), - lineterm="", - fromfile="a/"+self.path, - tofile="b/"+self.path - )))) - else: - logger.info("{} file {}".format( - "Would not change" if dry_run else "Not changing", - self.path, - )) - - if not dry_run: - with io.open(self.path, 'wb') as f: - f.write(file_content_after.encode('utf-8')) - - def __str__(self): - return self.path - - def __repr__(self): - return '<bumpversion.ConfiguredFile:{}>'.format(self.path) - -class VersionPartConfiguration(object): - pass - -class ConfiguredVersionPartConfiguration(object): - - def __init__(self, values, optional_value=None, first_value=None): - - assert len(values) > 0 - - self._values = values - - if optional_value is None: - optional_value = values[0] - - assert optional_value in values - - self.optional_value = optional_value - - if first_value is None: - first_value = values[0] - - assert first_value in values - - self.first_value = first_value - - def bump(self, value): - return self._values[self._values.index(value)+1] - -class NumericVersionPartConfiguration(VersionPartConfiguration): - - optional_value = "0" - - FIRST_NUMERIC = re.compile('([^\d]*)(\d+)(.*)') - - def __init__(self, first_value=None): - - if first_value is None: - first_value = "0" - - int(first_value) # make sure that it's numeric - - self.first_value = first_value - - @classmethod - def bump(cls, value): - part_prefix, numeric_version, part_suffix = cls.FIRST_NUMERIC.search(value).groups() - bumped_numeric = str(int(numeric_version) + 1) - return "".join([part_prefix, bumped_numeric, part_suffix]) - -class VersionPart(object): - - def __init__(self, value, config=None): - self._value = value - - if config is None: - config = NumericVersionPartConfiguration() - - self.config = config - - @property - def value(self): - return self._value or self.config.optional_value - - def copy(self): - return VersionPart(self._value) - - def bump(self): - return VersionPart(self.config.bump(self.value), self.config) - - def is_optional(self): - return self.value == self.config.optional_value - - def __format__(self, format_spec): - return self.value - - def __repr__(self): - return '<bumpversion.VersionPart:{}:{}>'.format( - self.config.__class__.__name__, - self.value - ) - - def null(self): - return VersionPart(self.config.first_value, self.config) - -class IncompleteVersionRepresenationException(Exception): - def __init__(self, message): - self.message = message - -class MissingValueForSerializationException(Exception): - def __init__(self, message): - self.message = message - -class WorkingDirectoryIsDirtyException(Exception): - def __init__(self, message): - self.message = message - -def keyvaluestring(d): - return ", ".join("{}={}".format(k, v) for k, v in sorted(d.items())) - -class Version(object): - - def __init__(self, values, original=None): - self._values = dict(values) - self.original = original - - def __getitem__(self, key): - return self._values[key] - - def __len__(self): - return len(self._values) - - def __iter__(self): - return iter(self._values) - - def __repr__(self): - return '<bumpversion.Version:{}>'.format(keyvaluestring(self._values)) - - def bump(self, part_name, order): - bumped = False - - new_values = {} - - for label in order: - if not label in self._values: - continue - elif label == part_name: - new_values[label] = self._values[label].bump() - bumped = True - elif bumped: - new_values[label] = self._values[label].null() - else: - new_values[label] = self._values[label].copy() - - new_version = Version(new_values) - - return new_version - -class VersionConfig(object): - - """ - Holds a complete representation of a version string - """ - - def __init__(self, parse, serialize, search, replace, part_configs=None): - - try: - self.parse_regex = re.compile(parse, re.VERBOSE) - except sre_constants.error as e: - logger.error("--parse '{}' is not a valid regex".format(parse)) - raise e - - self.serialize_formats = serialize - - if not part_configs: - part_configs = {} - - self.part_configs = part_configs - self.search = search - self.replace = replace - - def _labels_for_format(self, serialize_format): - return ( - label - for _, label, _, _ in Formatter().parse(serialize_format) - if label - ) - - def order(self): - # currently, order depends on the first given serialization format - # this seems like a good idea because this should be the most complete format - return self._labels_for_format(self.serialize_formats[0]) - - def parse(self, version_string): - - regexp_one_line = "".join([l.split("#")[0].strip() for l in self.parse_regex.pattern.splitlines()]) - - logger.info("Parsing version '{}' using regexp '{}'".format(version_string, regexp_one_line)) - - match = self.parse_regex.search(version_string) - - _parsed = {} - if not match: - logger.warn("Evaluating 'parse' option: '{}' does not parse current version '{}'".format( - self.parse_regex.pattern, version_string)) - return - - for key, value in match.groupdict().items(): - _parsed[key] = VersionPart(value, self.part_configs.get(key)) - - - v = Version(_parsed, version_string) - - logger.info("Parsed the following values: %s" % keyvaluestring(v._values)) - - return v - - def _serialize(self, version, serialize_format, context, raise_if_incomplete=False): - """ - Attempts to serialize a version with the given serialization format. - - Raises MissingValueForSerializationException if not serializable - """ - values = context.copy() - for k in version: - values[k] = version[k] - - # TODO dump complete context on debug level - - try: - # test whether all parts required in the format have values - serialized = serialize_format.format(**values) - - except KeyError as e: - missing_key = getattr(e, - 'message', # Python 2 - e.args[0] # Python 3 - ) - raise MissingValueForSerializationException( - "Did not find key {} in {} when serializing version number".format( - repr(missing_key), repr(version))) - - keys_needing_representation = set() - found_required = False - - for k in self.order(): - v = values[k] - - if not isinstance(v, VersionPart): - # values coming from environment variables don't need - # representation - continue - - if not v.is_optional(): - found_required = True - keys_needing_representation.add(k) - elif not found_required: - keys_needing_representation.add(k) - - required_by_format = set(self._labels_for_format(serialize_format)) - - # try whether all parsed keys are represented - if raise_if_incomplete: - if not (keys_needing_representation <= required_by_format): - raise IncompleteVersionRepresenationException( - "Could not represent '{}' in format '{}'".format( - "', '".join(keys_needing_representation ^ required_by_format), - serialize_format, - )) - - return serialized - - - def _choose_serialize_format(self, version, context): - - chosen = None - - # logger.info("Available serialization formats: '{}'".format("', '".join(self.serialize_formats))) - - for serialize_format in self.serialize_formats: - try: - self._serialize(version, serialize_format, context, raise_if_incomplete=True) - chosen = serialize_format - # logger.info("Found '{}' to be a usable serialization format".format(chosen)) - except IncompleteVersionRepresenationException as e: - # logger.info(e.message) - if not chosen: - chosen = serialize_format - except MissingValueForSerializationException as e: - logger.info(e.message) - raise e - - if not chosen: - raise KeyError("Did not find suitable serialization format") - - # logger.info("Selected serialization format '{}'".format(chosen)) - - return chosen - - def serialize(self, version, context): - serialized = self._serialize(version, self._choose_serialize_format(version, context), context) - # logger.info("Serialized to '{}'".format(serialized)) - return serialized - -OPTIONAL_ARGUMENTS_THAT_TAKE_VALUES = [ - '--config-file', - '--current-version', - '--message', - '--new-version', - '--parse', - '--serialize', - '--search', - '--replace', - '--tag-name', -] - - -def split_args_in_optional_and_positional(args): - # manually parsing positional arguments because stupid argparse can't mix - # positional and optional arguments - - positions = [] - for i, arg in enumerate(args): - - previous = None - - if i > 0: - previous = args[i-1] - - if ((not arg.startswith('--')) and - (previous not in OPTIONAL_ARGUMENTS_THAT_TAKE_VALUES)): - positions.append(i) - - positionals = [arg for i, arg in enumerate(args) if i in positions] - args = [arg for i, arg in enumerate(args) if i not in positions] - - return (positionals, args) - -def main(original_args=None): - - positionals, args = split_args_in_optional_and_positional( - sys.argv[1:] if original_args is None else original_args - ) - - if len(positionals[1:]) > 2: - warnings.warn("Giving multiple files on the command line will be deprecated, please use [bumpversion:file:...] in a config file.", PendingDeprecationWarning) - - parser1 = argparse.ArgumentParser(add_help=False) - - parser1.add_argument( - '--config-file', metavar='FILE', - default=argparse.SUPPRESS, required=False, - help='Config file to read most of the variables from (default: .bumpversion.cfg)') - - parser1.add_argument( - '--verbose', action='count', default=0, - help='Print verbose logging to stderr', required=False) - - parser1.add_argument( - '--list', action='store_true', default=False, - help='List machine readable information', required=False) - - parser1.add_argument( - '--allow-dirty', action='store_true', default=False, - help="Don't abort if working directory is dirty", required=False) - - known_args, remaining_argv = parser1.parse_known_args(args) - - logformatter = logging.Formatter('%(message)s') - - if len(logger.handlers) == 0: - ch = logging.StreamHandler(sys.stderr) - ch.setFormatter(logformatter) - logger.addHandler(ch) - - if len(logger_list.handlers) == 0: - ch2 = logging.StreamHandler(sys.stdout) - ch2.setFormatter(logformatter) - logger_list.addHandler(ch2) - - if known_args.list: - logger_list.setLevel(1) - - log_level = { - 0: logging.WARNING, - 1: logging.INFO, - 2: logging.DEBUG, - }.get(known_args.verbose, logging.DEBUG) - - logger.setLevel(log_level) - - logger.debug("Starting {}".format(DESCRIPTION)) - - defaults = {} - vcs_info = {} - - for vcs in VCS: - if vcs.is_usable(): - vcs_info.update(vcs.latest_tag_info()) - - if 'current_version' in vcs_info: - defaults['current_version'] = vcs_info['current_version'] - - config = RawConfigParser('') - - # don't transform keys to lowercase (which would be the default) - config.optionxform = lambda option: option - - config.add_section('bumpversion') - - explicit_config = hasattr(known_args, 'config_file') - - if explicit_config: - config_file = known_args.config_file - elif not os.path.exists('.bumpversion.cfg') and \ - os.path.exists('setup.cfg'): - config_file = 'setup.cfg' - else: - config_file = '.bumpversion.cfg' - - config_file_exists = os.path.exists(config_file) - - part_configs = {} - - files = [] - - if config_file_exists: - - logger.info("Reading config file {}:".format(config_file)) - logger.info(io.open(config_file, 'rt', encoding='utf-8').read()) - - config.readfp(io.open(config_file, 'rt', encoding='utf-8')) - - log_config = StringIO() - config.write(log_config) - - if 'files' in dict(config.items("bumpversion")): - warnings.warn( - "'files =' configuration is will be deprecated, please use [bumpversion:file:...]", - PendingDeprecationWarning - ) - - defaults.update(dict(config.items("bumpversion"))) - - for listvaluename in ("serialize",): - try: - value = config.get("bumpversion", listvaluename) - defaults[listvaluename] = list(filter(None, (x.strip() for x in value.splitlines()))) - except NoOptionError: - pass # no default value then ;) - - for boolvaluename in ("commit", "tag", "dry_run"): - try: - defaults[boolvaluename] = config.getboolean( - "bumpversion", boolvaluename) - except NoOptionError: - pass # no default value then ;) - - for section_name in config.sections(): - - section_name_match = re.compile("^bumpversion:(file|part):(.+)").match(section_name) - - if not section_name_match: - continue - - section_prefix, section_value = section_name_match.groups() - - section_config = dict(config.items(section_name)) - - if section_prefix == "part": - - ThisVersionPartConfiguration = NumericVersionPartConfiguration - - if 'values' in section_config: - section_config['values'] = list(filter(None, (x.strip() for x in section_config['values'].splitlines()))) - ThisVersionPartConfiguration = ConfiguredVersionPartConfiguration - - part_configs[section_value] = ThisVersionPartConfiguration(**section_config) - - elif section_prefix == "file": - - filename = section_value - - if 'serialize' in section_config: - section_config['serialize'] = list(filter(None, (x.strip() for x in section_config['serialize'].splitlines()))) - - section_config['part_configs'] = part_configs - - if not 'parse' in section_config: - section_config['parse'] = defaults.get("parse", '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)') - - if not 'serialize' in section_config: - section_config['serialize'] = defaults.get('serialize', [str('{major}.{minor}.{patch}')]) - - if not 'search' in section_config: - section_config['search'] = defaults.get("search", '{current_version}') - - if not 'replace' in section_config: - section_config['replace'] = defaults.get("replace", '{new_version}') - - files.append(ConfiguredFile(filename, VersionConfig(**section_config))) - - else: - message = "Could not read config file at {}".format(config_file) - if explicit_config: - raise argparse.ArgumentTypeError(message) - else: - logger.info(message) - - parser2 = argparse.ArgumentParser(prog='bumpversion', add_help=False, parents=[parser1]) - parser2.set_defaults(**defaults) - - parser2.add_argument('--current-version', metavar='VERSION', - help='Version that needs to be updated', required=False) - parser2.add_argument('--parse', metavar='REGEX', - help='Regex parsing the version string', - default=defaults.get("parse", '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)')) - parser2.add_argument('--serialize', metavar='FORMAT', - action=DiscardDefaultIfSpecifiedAppendAction, - help='How to format what is parsed back to a version', - default=defaults.get("serialize", [str('{major}.{minor}.{patch}')])) - parser2.add_argument('--search', metavar='SEARCH', - help='Template for complete string to search', - default=defaults.get("search", '{current_version}')) - parser2.add_argument('--replace', metavar='REPLACE', - help='Template for complete string to replace', - default=defaults.get("replace", '{new_version}')) - - known_args, remaining_argv = parser2.parse_known_args(args) - - defaults.update(vars(known_args)) - - assert type(known_args.serialize) == list - - context = dict(list(time_context.items()) + list(prefixed_environ().items()) + list(vcs_info.items())) - - try: - vc = VersionConfig( - parse=known_args.parse, - serialize=known_args.serialize, - search=known_args.search, - replace=known_args.replace, - part_configs=part_configs, - ) - except sre_constants.error as e: - sys.exit(1) - - current_version = vc.parse(known_args.current_version) if known_args.current_version else None - - new_version = None - - if not 'new_version' in defaults and known_args.current_version: - try: - if current_version and len(positionals) > 0: - logger.info("Attempting to increment part '{}'".format(positionals[0])) - new_version = current_version.bump(positionals[0], vc.order()) - logger.info("Values are now: " + keyvaluestring(new_version._values)) - defaults['new_version'] = vc.serialize(new_version, context) - except MissingValueForSerializationException as e: - logger.info("Opportunistic finding of new_version failed: " + e.message) - except IncompleteVersionRepresenationException as e: - logger.info("Opportunistic finding of new_version failed: " + e.message) - except KeyError as e: - logger.info("Opportunistic finding of new_version failed") - - parser3 = argparse.ArgumentParser( - prog='bumpversion', - description=DESCRIPTION, - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - conflict_handler='resolve', - parents=[parser2], - ) - - parser3.set_defaults(**defaults) - - parser3.add_argument('--current-version', metavar='VERSION', - help='Version that needs to be updated', - required=not 'current_version' in defaults) - parser3.add_argument('--dry-run', '-n', action='store_true', - default=False, help="Don't write any files, just pretend.") - parser3.add_argument('--new-version', metavar='VERSION', - help='New version that should be in the files', - required=not 'new_version' in defaults) - - commitgroup = parser3.add_mutually_exclusive_group() - - commitgroup.add_argument('--commit', action='store_true', dest="commit", - help='Commit to version control', default=defaults.get("commit", False)) - commitgroup.add_argument('--no-commit', action='store_false', dest="commit", - help='Do not commit to version control', default=argparse.SUPPRESS) - - taggroup = parser3.add_mutually_exclusive_group() - - taggroup.add_argument('--tag', action='store_true', dest="tag", default=defaults.get("tag", False), - help='Create a tag in version control') - taggroup.add_argument('--no-tag', action='store_false', dest="tag", - help='Do not create a tag in version control', default=argparse.SUPPRESS) - - parser3.add_argument('--tag-name', metavar='TAG_NAME', - help='Tag name (only works with --tag)', - default=defaults.get('tag_name', 'v{new_version}')) - - parser3.add_argument('--message', '-m', metavar='COMMIT_MSG', - help='Commit message', - default=defaults.get('message', 'Bump version: {current_version} ��� {new_version}')) - - - file_names = [] - if 'files' in defaults: - assert defaults['files'] != None - file_names = defaults['files'].split(' ') - - parser3.add_argument('part', - help='Part of the version to be bumped.') - parser3.add_argument('files', metavar='file', - nargs='*', - help='Files to change', default=file_names) - - args = parser3.parse_args(remaining_argv + positionals) - - if args.dry_run: - logger.info("Dry run active, won't touch any files.") - - if args.new_version: - new_version = vc.parse(args.new_version) - - logger.info("New version will be '{}'".format(args.new_version)) - - file_names = file_names or positionals[1:] - - for file_name in file_names: - files.append(ConfiguredFile(file_name, vc)) - - for vcs in VCS: - if vcs.is_usable(): - try: - vcs.assert_nondirty() - except WorkingDirectoryIsDirtyException as e: - if not defaults['allow_dirty']: - logger.warn( - "{}\n\nUse --allow-dirty to override this if you know what you're doing.".format(e.message)) - raise - break - else: - vcs = None - - # make sure files exist and contain version string - - logger.info("Asserting files {} contain the version string:".format(", ".join([str(f) for f in files]))) - - for f in files: - f.should_contain_version(current_version, context) - - # change version string in files - for f in files: - f.replace(current_version, new_version, context, args.dry_run) - - commit_files = [f.path for f in files] - - config.set('bumpversion', 'new_version', args.new_version) - - for key, value in config.items('bumpversion'): - logger_list.info("{}={}".format(key, value)) - - config.remove_option('bumpversion', 'new_version') - - config.set('bumpversion', 'current_version', args.new_version) - - new_config = StringIO() - - try: - write_to_config_file = (not args.dry_run) and config_file_exists - - logger.info("{} to config file {}:".format( - "Would write" if not write_to_config_file else "Writing", - config_file, - )) - - config.write(new_config) - logger.info(new_config.getvalue()) - - if write_to_config_file: - with io.open(config_file, 'wb') as f: - f.write(new_config.getvalue().encode('utf-8')) - - except UnicodeEncodeError: - warnings.warn( - "Unable to write UTF-8 to config file, because of an old configparser version. " - "Update with `pip install --upgrade configparser`." - ) - - if config_file_exists: - commit_files.append(config_file) - - if not vcs: - return - - assert vcs.is_usable(), "Did find '{}' unusable, unable to commit.".format(vcs.__name__) - - do_commit = (not args.dry_run) and args.commit - do_tag = (not args.dry_run) and args.tag - - logger.info("{} {} commit".format( - "Would prepare" if not do_commit else "Preparing", - vcs.__name__, - )) - - for path in commit_files: - logger.info("{} changes in file '{}' to {}".format( - "Would add" if not do_commit else "Adding", - path, - vcs.__name__, - )) - - if do_commit: - vcs.add_path(path) - - vcs_context = { - "current_version": args.current_version, - "new_version": args.new_version, - } - vcs_context.update(time_context) - vcs_context.update(prefixed_environ()) - - commit_message = args.message.format(**vcs_context) - - logger.info("{} to {} with message '{}'".format( - "Would commit" if not do_commit else "Committing", - vcs.__name__, - commit_message, - )) - - if do_commit: - vcs.commit(message=commit_message) - - tag_name = args.tag_name.format(**vcs_context) - logger.info("{} '{}' in {}".format( - "Would tag" if not do_tag else "Tagging", - tag_name, - vcs.__name__ - )) - - if do_tag: - vcs.tag(tag_name) - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumpversion-0.5.3/bumpversion.egg-info/PKG-INFO new/bumpversion-0.6.0/bumpversion.egg-info/PKG-INFO --- old/bumpversion-0.5.3/bumpversion.egg-info/PKG-INFO 2015-04-15 11:14:21.000000000 +0200 +++ new/bumpversion-0.6.0/bumpversion.egg-info/PKG-INFO 2020-05-14 04:18:10.000000000 +0200 @@ -1,12 +1,19 @@ Metadata-Version: 1.1 Name: bumpversion -Version: 0.5.3 +Version: 0.6.0 Summary: Version-bump your software with a single command! Home-page: https://github.com/peritus/bumpversion Author: Filip Noetzel Author-email: filip+bumpversion@j03.de License: MIT -Description: =========== +Description: **������ Current status of this project** + + * ����If you want to start **using bumpversion**, you're best advised to **install one of the maintained forks**, e.g. ��� `@c4urself's bump2version <https://github.com/c4urself/bump2version/#installation>`_. + * ����If you want to **help maintain** bumpversion, there's an `ongoing discussion about merging the fork back to the original project as well as forming a group of maintainers <https://github.com/c4urself/bump2version/issues/86>`_ to ensure a long-term future for this project. Please contribute. + + ----- + + =========== bumpversion =========== @@ -131,7 +138,7 @@ Also available on the command line as ``(--tag | --no-tag)``. ``tag_name =`` - **default:** "``v{new_version}``" + **default:** ``v{new_version}`` The name of the tag that will be created. Only valid when using ``--tag`` / ``tag = True``. @@ -153,7 +160,7 @@ Also available as ``(--commit | --no-commit)``. ``message =`` - **default:** "``Bump version: {current_version} ��� {new_version}``" + **default:** ``Bump version: {current_version} ��� {new_version}`` The commit message to use when creating a commit. Only valid when using ``--commit`` / ``commit = True``. @@ -242,7 +249,7 @@ ``[bumpversion:file:���]`` ``parse =`` - **default:** "``(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)``" + **default:** ``(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)`` Regular expression (using `Python regular expression syntax <http://docs.python.org/2/library/re.html#regular-expression-syntax>`_) on @@ -254,7 +261,7 @@ Also available as ``--parse`` ``serialize =`` - **default:** "``{major}.{minor}.{patch}``" + **default:** ``{major}.{minor}.{patch}`` Template specifying how to serialize the version parts back to a version string. @@ -280,7 +287,7 @@ given like ``--serialize {major}.{minor} --serialize {major}`` ``search =`` - **default:** "``{current_version}``" + **default:** ``{current_version}`` Template string how to search for the string to be replaced in the file. Useful if the remotest possibility exists that the current version number @@ -289,7 +296,7 @@ <http://docs.python.org/2/library/string.html#format-string-syntax>`_. ``replace =`` - **default:** "``{new_version}``" + **default:** ``{new_version}`` Template to create the string that will replace the current version number in the file. @@ -341,6 +348,27 @@ ``-h, --help`` Print help and exit + Using bumpversion in a script + ============================= + + If you need to use the version generated by bumpversion in a script you can make use of + the `--list` option, combined with `grep` and `sed`. + + Say for example that you are using git-flow to manage your project and want to automatically + create a release. When you issue `git flow release start` you already need to know the + new version, before applying the change. + + The standard way to get it in a bash script is + + bumpversion --dry-run --list <part> | grep <field name> | sed -r s,"^.*=",, + + where <part> is as usual the part of the version number you are updating. You need to specify + `--dry-run` to avoid bumpversion actually bumping the version number. + + For example, if you are updating the minor number and looking for the new version number this becomes + + bumpversion --dry-run --list minor | grep new_version | sed -r s,"^.*=",, + Development =========== @@ -370,7 +398,10 @@ Changes ======= - **unreleased** + **0.6.0** + + - Deprecation: publish package that links to the newer bump2version for seamless + upgrades (see: https://www.python.org/dev/peps/pep-0423/#id106) **v0.5.3** @@ -506,7 +537,7 @@ Platform: UNKNOWN -Classifier: Development Status :: 4 - Beta +Classifier: Development Status :: 7 - Inactive Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumpversion-0.5.3/bumpversion.egg-info/SOURCES.txt new/bumpversion-0.6.0/bumpversion.egg-info/SOURCES.txt --- old/bumpversion-0.5.3/bumpversion.egg-info/SOURCES.txt 2015-04-15 11:14:22.000000000 +0200 +++ new/bumpversion-0.6.0/bumpversion.egg-info/SOURCES.txt 2020-05-14 04:18:10.000000000 +0200 @@ -1,10 +1,10 @@ +LICENSE.rst MANIFEST.in README.rst setup.cfg setup.py -bumpversion/__init__.py bumpversion.egg-info/PKG-INFO bumpversion.egg-info/SOURCES.txt bumpversion.egg-info/dependency_links.txt -bumpversion.egg-info/entry_points.txt +bumpversion.egg-info/requires.txt bumpversion.egg-info/top_level.txt \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumpversion-0.5.3/bumpversion.egg-info/entry_points.txt new/bumpversion-0.6.0/bumpversion.egg-info/entry_points.txt --- old/bumpversion-0.5.3/bumpversion.egg-info/entry_points.txt 2015-04-15 11:14:21.000000000 +0200 +++ new/bumpversion-0.6.0/bumpversion.egg-info/entry_points.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,3 +0,0 @@ -[console_scripts] -bumpversion = bumpversion:main - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumpversion-0.5.3/bumpversion.egg-info/requires.txt new/bumpversion-0.6.0/bumpversion.egg-info/requires.txt --- old/bumpversion-0.5.3/bumpversion.egg-info/requires.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/bumpversion-0.6.0/bumpversion.egg-info/requires.txt 2020-05-14 04:18:10.000000000 +0200 @@ -0,0 +1 @@ +bump2version diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumpversion-0.5.3/bumpversion.egg-info/top_level.txt new/bumpversion-0.6.0/bumpversion.egg-info/top_level.txt --- old/bumpversion-0.5.3/bumpversion.egg-info/top_level.txt 2015-04-15 11:14:21.000000000 +0200 +++ new/bumpversion-0.6.0/bumpversion.egg-info/top_level.txt 2020-05-14 04:18:10.000000000 +0200 @@ -1 +1 @@ -bumpversion + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumpversion-0.5.3/setup.cfg new/bumpversion-0.6.0/setup.cfg --- old/bumpversion-0.5.3/setup.cfg 2015-04-15 11:14:23.000000000 +0200 +++ new/bumpversion-0.6.0/setup.cfg 2020-05-14 04:18:10.000000000 +0200 @@ -4,5 +4,4 @@ [egg_info] tag_build = tag_date = 0 -tag_svn_revision = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumpversion-0.5.3/setup.py new/bumpversion-0.6.0/setup.py --- old/bumpversion-0.5.3/setup.py 2015-04-15 11:12:43.000000000 +0200 +++ new/bumpversion-0.6.0/setup.py 2020-05-14 04:17:55.000000000 +0200 @@ -11,21 +11,18 @@ setup( name='bumpversion', - version='0.5.3', + version='0.6.0', url='https://github.com/peritus/bumpversion', author='Filip Noetzel', author_email='filip+bumpversion@j03.de', license='MIT', - packages=['bumpversion'], + install_requires=[ + 'bump2version', + ], description=description, long_description=long_description, - entry_points={ - 'console_scripts': [ - 'bumpversion = bumpversion:main', - ] - }, classifiers=( - 'Development Status :: 4 - Beta', + 'Development Status :: 7 - Inactive', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent',
participants (1)
-
Source-Sync