用于重写存储库主干中所有svn:externals的脚本/实用程序

时间:2011-06-23 00:58:25

标签: python scripting svn-externals

假设有人希望将所有绝对的svn:externals URLS转换为整个存储库中的相对URL。

或者,如果注意tip in the svn:externals docs(“你应该认真考虑使用明确的修订号......”),人们可能会发现自己需要在整个存储库的许多地方定期为外部提取新版本。

以编程方式更新大量svn:externals属性的最佳方法是什么?

我的解决方案发布在下面。

1 个答案:

答案 0 :(得分:4)

这是我的类从svn:externals属性的单行中提取部分:

from urlparse import urlparse
import re
class SvnExternalsLine:
    '''Consult https://subversion.apache.org/docs/release-notes/1.5.html#externals for parsing algorithm.
    The old svn:externals format consists of:
        <local directory> [revision] <absolute remote URL>

    The NEW svn:externals format consists of:
        [revision] <absolute or relative remote URL> <local directory>

    Therefore, "relative" remote paths always come *after* the local path.
    One complication is the possibility of local paths with spaces.
    We just assume that the remote path cannot have spaces, and treat all other
    tokens (except the revision specifier) as part of the local path.
    '''

    REVISION_ARGUMENT_REGEXP = re.compile("-r(\d+)")

    def __init__(self, original_line):
        self.original_line = original_line

        self.pinned_revision_number = None
        self.repo_url = None
        self.local_pathname_components = []

        for token in self.original_line.split():

            revision_match = self.REVISION_ARGUMENT_REGEXP.match(token)
            if revision_match:
                self.pinned_revision_number = int(revision_match.group(1))
            elif urlparse(token).scheme or any(map(lambda p: token.startswith(p), ["^", "//", "/", "../"])):
                self.repo_url = token
            else:
                self.local_pathname_components.append(token)

    # ---------------------------------------------------------------------
    def constructLine(self):
        '''Reconstruct the externals line in the Subversion 1.5+ format'''

        tokens = []

        # Update the revision specifier if one existed
        if self.pinned_revision_number is not None:
            tokens.append( "-r%d" % (self.pinned_revision_number) )

        tokens.append( self.repo_url )
        tokens.extend( self.local_pathname_components )

        if self.repo_url is None:
            raise Exception("Found a bad externals property: %s; Original definition: %s" % (str(tokens), repr(self.original_line)))

        return " ".join(tokens)

我使用pysvn库以递归方式遍历拥有svn:externals属性的所有目录,然后按新行拆分该属性值,并根据解析后的SvnExternalsLine对每一行进行操作。

必须在存储库的本地检出中执行该过程。以下是pysvnpropget)可用于检索外部的方法:

client.propget( "svn:externals", base_checkout_path, recurse=True)

迭代此函数的返回值,并在修改每个目录的属性后

client.propset("svn:externals", new_externals_property, path)