From 559c1caadaba93841c5426272a844bfbd017529a Mon Sep 17 00:00:00 2001 From: Bjorn Date: Tue, 16 Dec 2014 12:45:56 +0100 Subject: [PATCH 1/2] Added support for Subversion. This assumes standard svn repository layout (/trunk, /branches, /tags), and that development is done on either trunk or branches. --- .gitignore | 1 + bumpversion/__init__.py | 62 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 83b94e0..27cdaf8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ include/ lib/ .Python bumpversion.egg-info/ +*.pyc diff --git a/bumpversion/__init__.py b/bumpversion/__init__.py index 5884a16..67f0c5e 100644 --- a/bumpversion/__init__.py +++ b/bumpversion/__init__.py @@ -24,6 +24,7 @@ from datetime import datetime from difflib import unified_diff from tempfile import NamedTemporaryFile +from contextlib import contextmanager import sys import codecs @@ -42,6 +43,18 @@ logger = logging.getLogger("bumpversion.logger") logger_list = logging.getLogger("bumpversion.list") + +@contextmanager +def message_file(message): + try: + f = NamedTemporaryFile('wb', delete=False) + f.write(message.encode('utf-8')) + f.close() + yield f.name + finally: + os.unlink(f.name) + + from argparse import _AppendAction class DiscardDefaultIfSpecifiedAppendAction(_AppendAction): @@ -89,6 +102,51 @@ def is_usable(cls): raise +class Svn(BaseVCS): + + _TEST_USABLE_COMMAND = ["svn", "info"] + _COMMIT_COMMAND = ["svn", "commit", "--file"] + + @classmethod + def assert_nondirty(cls): + lines = [ + line.strip() for line in + subprocess.check_output( + ["svn", "status"]).splitlines() + if line.strip() + ] + + if lines: + raise WorkingDirectoryIsDirtyException( + "Subversion working directory is not clean:\n{}".format( + b"\n".join(lines))) + + @classmethod + def latest_tag_info(cls): + return {} + + @classmethod + def add_path(cls, path): + pass + + @classmethod + def tag(cls, name, message): + svn_info = subprocess.check_output(["svn", "info"]) + rurl = re.search(r'^relative url: (.*)$', svn_info, + re.M|re.I).groups()[0] + rurl = rurl.split('/trunk')[0] + rurl = rurl.split('/branches')[0] + + with message_file(message) as filename: + subprocess.check_output([ + "svn", + "copy", + ".", + rurl + "/tags/" + name, + "--file=" + filename + ]) + + class Git(BaseVCS): _TEST_USABLE_COMMAND = ["git", "rev-parse", "--git-dir"] @@ -181,7 +239,7 @@ def add_path(cls, path): def tag(cls, name): subprocess.check_output(["hg", "tag", name]) -VCS = [Git, Mercurial] +VCS = [Git, Mercurial, Svn] def prefixed_environ(): @@ -985,5 +1043,5 @@ def main(original_args=None): )) if do_tag: - vcs.tag(tag_name) + vcs.tag(tag_name, message=commit_message) From 79b0982b530cfe101389ccc51bf9219c624a90cc Mon Sep 17 00:00:00 2001 From: Bjorn Date: Tue, 16 Dec 2014 12:49:44 +0100 Subject: [PATCH 2/2] Unify interface to tag method. Subversion performs a tag by copying to /tags, and this requires message. --- bumpversion/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bumpversion/__init__.py b/bumpversion/__init__.py index 67f0c5e..a274f5b 100644 --- a/bumpversion/__init__.py +++ b/bumpversion/__init__.py @@ -130,7 +130,7 @@ def add_path(cls, path): pass @classmethod - def tag(cls, name, message): + def tag(cls, name, message=""): svn_info = subprocess.check_output(["svn", "info"]) rurl = re.search(r'^relative url: (.*)$', svn_info, re.M|re.I).groups()[0] @@ -204,7 +204,7 @@ def add_path(cls, path): subprocess.check_output(["git", "add", "--update", path]) @classmethod - def tag(cls, name): + def tag(cls, name, message=""): subprocess.check_output(["git", "tag", name]) @@ -236,7 +236,7 @@ def add_path(cls, path): pass @classmethod - def tag(cls, name): + def tag(cls, name, message=""): subprocess.check_output(["hg", "tag", name]) VCS = [Git, Mercurial, Svn]