Source code for rezplugins.release_vcs.svn

# SPDX-License-Identifier: Apache-2.0
# Copyright Contributors to the Rez Project


"""
Svn version control
"""
from __future__ import print_function

from rez.release_vcs import ReleaseVCS
from rez.exceptions import ReleaseVCSError
import os.path
import pysvn

# TODO this needs a rewrite


[docs]class SvnReleaseVCSError(ReleaseVCSError): pass
[docs]def svn_get_client(): # check we're in an svn working copy client = pysvn.Client() client.set_interactive(True) client.set_auth_cache(False) client.set_store_passwords(False) client.callback_get_login = get_svn_login return client
[docs]def get_last_changed_revision(client, url): """ util func, get last revision of url """ try: svn_entries = client.info2(url, pysvn.Revision(pysvn.opt_revision_kind.head), recurse=False) if not svn_entries: raise ReleaseVCSError("svn.info2() returned no results on url %s" % url) return svn_entries[0][1].last_changed_rev except pysvn.ClientError as ce: raise ReleaseVCSError("svn.info2() raised ClientError: %s" % ce)
[docs]def get_svn_login(realm, username, may_save): """ provide svn with permissions. @TODO this will have to be updated to take into account automated releases etc. """ import getpass print("svn requires a password for the user %s:" % username) pwd = '' while not pwd.strip(): pwd = getpass.getpass("--> ") return True, username, pwd, False
[docs]class SvnReleaseVCS(ReleaseVCS):
[docs] @classmethod def name(cls): return 'svn'
def __init__(self, pkg_root, vcs_root=None): super(SvnReleaseVCS, self).__init__(pkg_root, vcs_root=vcs_root) self.svnc = svn_get_client() svn_entry = self.svnc.info(self.pkg_root) if not svn_entry: raise SvnReleaseVCSError("%s is not an svn working copy" % self.pkg_root) self.this_url = str(svn_entry["url"])
[docs] @classmethod def is_valid_root(cls, path): return os.path.isdir(os.path.join(path, '.svn'))
[docs] @classmethod def search_parents_for_root(cls): return True
[docs] def validate_repostate(self): status_list = self.svnc.status(self.pkg_root, get_all=False, update=True) status_list_known = [] for status in status_list: if status.entry: status_list_known.append(status) if status_list_known: raise ReleaseVCSError( "'%s' is not in a state to release - you may need to svn-checkin " "and/or svn-update: %s" % (self.pkg_root, str(status_list_known)))
def _create_tag_impl(self, tag_name, message=None): tag_url = self.get_tag_url(tag_name) print("rez-release: creating project tag in: %s..." % tag_url) self.svnc.callback_get_log_message = lambda x: (True, x) self.svnc.copy2([(self.this_url,)], tag_url, make_parents=True)
[docs] def get_changelog(self, previous_revision=None, max_revisions=None): return "TODO"
[docs] def get_tag_url(self, tag_name=None): # find the base path, ie where 'trunk', 'branches', 'tags' should be pos_tr = self.this_url.find("/trunk") pos_br = self.this_url.find("/branches") pos = max(pos_tr, pos_br) if (pos == -1): raise ReleaseVCSError("%s is not in a branch or trunk" % self.pkg_root) base_url = self.this_url[:pos] tag_url = base_url + "/tags" if tag_name: tag_url += '/' + tag_name return tag_url
[docs] def svn_url_exists(self, url): try: svnlist = self.svnc.info2(url, recurse=False) return bool(svnlist) except pysvn.ClientError: return False
[docs] def get_current_revision(self): return self.svnc.info(self.pkg_root)['revision'].number
[docs] def create_release_tag(self, tag_name, message=None): # svn requires a message - if not provided, make it the same as the # tag name.. if not message: message = tag_name self.svnc.callback_get_log_message = lambda: (True, message) self.svnc.copy(self.pkg_root, self.get_tag_url(tag_name))
[docs]def register_plugin(): return SvnReleaseVCS