incubator-bloodhound-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From g..@apache.org
Subject svn commit: r1398858 [28/33] - in /incubator/bloodhound/vendor/trac/current: ./ contrib/ doc/ doc/api/ doc/utils/ sample-plugins/ sample-plugins/permissions/ sample-plugins/workflow/ trac/ trac/admin/ trac/admin/templates/ trac/admin/tests/ trac/db/ tr...
Date Tue, 16 Oct 2012 15:55:11 GMT
Modified: incubator/bloodhound/vendor/trac/current/trac/util/tests/text.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/util/tests/text.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/util/tests/text.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/util/tests/text.py Tue Oct 16 15:55:00 2012
@@ -4,11 +4,12 @@ import unittest
 from StringIO import StringIO
 
 from trac.util.text import empty, expandtabs, fix_eol, javascript_quote, \
-                           normalize_whitespace, to_unicode, \
+                           to_js_string, normalize_whitespace, to_unicode, \
                            text_width, print_table, unicode_quote, \
                            unicode_quote_plus, unicode_unquote, \
                            unicode_urlencode, wrap, quote_query_string, \
-                           unicode_to_base64, unicode_from_base64
+                           unicode_to_base64, unicode_from_base64, stripws, \
+                           levenshtein_distance
 
 
 class ToUnicodeTestCase(unittest.TestCase):
@@ -65,6 +66,19 @@ class JavascriptQuoteTestCase(unittest.T
         self.assertEqual(r'\u0026\u003c\u003e',
                          javascript_quote('&<>'))
 
+
+class ToJsStringTestCase(unittest.TestCase):
+    def test_(self):
+        self.assertEqual(r'"Quote \" in text"',
+                         to_js_string('Quote " in text'))
+        self.assertEqual(r'''"\\\"\b\f\n\r\t'"''',
+                         to_js_string('\\"\b\f\n\r\t\''))
+        self.assertEqual(r'"\u0002\u001e"',
+                         to_js_string('\x02\x1e'))
+        self.assertEqual(r'"\u0026\u003c\u003e"',
+                         to_js_string('&<>'))
+
+
 class UnicodeQuoteTestCase(unittest.TestCase):
     def test_unicode_quote(self):
         self.assertEqual(u'the%20%C3%9C%20thing',
@@ -289,12 +303,38 @@ class UnicodeBase64TestCase(unittest.Tes
         self.assertEqual(text, unicode_from_base64(text_base64_no_strip))
 
 
+class StripwsTestCase(unittest.TestCase):
+    def test_stripws(self):
+        self.assertEquals(u'stripws',
+                          stripws(u' \u200b\t\u3000stripws \u200b\t\u2008'))
+        self.assertEquals(u'stripws \u3000\t',
+                          stripws(u'\u200b\t\u2008 stripws \u3000\t',
+                                  trailing=False))
+        self.assertEquals(u' \t\u3000stripws',
+                          stripws(u' \t\u3000stripws \u200b\t\u2008',
+                                  leading=False))
+        self.assertEquals(u' \t\u3000stripws \u200b\t\u2008',
+                          stripws(u' \t\u3000stripws \u200b\t\u2008',
+                                  leading=False, trailing=False))
+
+
+
+class LevenshteinDistanceTestCase(unittest.TestCase):
+    def test_distance(self):
+        self.assertEqual(5, levenshtein_distance('kitten', 'sitting'))
+        self.assertEqual(1, levenshtein_distance('wii', 'wiki'))
+        self.assertEqual(2, levenshtein_distance('comfig', 'config'))
+        self.assertEqual(5, levenshtein_distance('update', 'upgrade'))
+        self.assertEqual(0, levenshtein_distance('milestone', 'milestone'))
+
+
 def suite():
     suite = unittest.TestSuite()
     suite.addTest(unittest.makeSuite(ToUnicodeTestCase, 'test'))
     suite.addTest(unittest.makeSuite(ExpandtabsTestCase, 'test'))
     suite.addTest(unittest.makeSuite(UnicodeQuoteTestCase, 'test'))
     suite.addTest(unittest.makeSuite(JavascriptQuoteTestCase, 'test'))
+    suite.addTest(unittest.makeSuite(ToJsStringTestCase, 'test'))
     suite.addTest(unittest.makeSuite(QuoteQueryStringTestCase, 'test'))
     suite.addTest(unittest.makeSuite(WhitespaceTestCase, 'test'))
     suite.addTest(unittest.makeSuite(TextWidthTestCase, 'test'))
@@ -302,6 +342,8 @@ def suite():
     suite.addTest(unittest.makeSuite(WrapTestCase, 'test'))
     suite.addTest(unittest.makeSuite(FixEolTestCase, 'test'))
     suite.addTest(unittest.makeSuite(UnicodeBase64TestCase, 'test'))
+    suite.addTest(unittest.makeSuite(StripwsTestCase, 'test'))
+    suite.addTest(unittest.makeSuite(LevenshteinDistanceTestCase, 'test'))
     return suite
 
 if __name__ == '__main__':

Modified: incubator/bloodhound/vendor/trac/current/trac/util/text.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/util/text.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/util/text.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/util/text.py Tue Oct 16 15:55:00 2012
@@ -3,7 +3,7 @@
 # Copyright (C) 2003-2009 Edgewall Software
 # Copyright (C) 2003-2004 Jonas Borgström <jonas@edgewall.com>
 # Copyright (C) 2006 Matthew Good <trac@matt-good.net>
-# Copyright (C) 2005-2006 Christian Boos <cboos@neuf.fr>
+# Copyright (C) 2005-2006 Christian Boos <cboos@edgewall.org>
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -16,7 +16,7 @@
 #
 # Author: Jonas Borgström <jonas@edgewall.com>
 #         Matthew Good <trac@matt-good.net>
-#         Christian Boos <cboos@neuf.fr>
+#         Christian Boos <cboos@edgewall.org>
 
 import __builtin__
 import locale
@@ -95,15 +95,36 @@ def path_to_unicode(path):
     return unicode(path)
 
 
+_ws_leading_re = re.compile(ur'\A[\s\u200b]+', re.UNICODE)
+_ws_trailing_re = re.compile(ur'[\s\u200b]+\Z', re.UNICODE)
+
+def stripws(text, leading=True, trailing=True):
+    """Strips unicode white-spaces and ZWSPs from ``text``.
+
+    :param leading: strips leading spaces from ``text`` unless ``leading`` is
+                    `False`.
+    :param trailing: strips trailing spaces from ``text`` unless ``trailing``
+                     is `False`.
+    """
+    if leading:
+        text = _ws_leading_re.sub('', text)
+    if trailing:
+        text = _ws_trailing_re.sub('', text)
+    return text
+
+
 _js_quote = {'\\': '\\\\', '"': '\\"', '\b': '\\b', '\f': '\\f',
              '\n': '\\n', '\r': '\\r', '\t': '\\t', "'": "\\'"}
 for i in range(0x20) + [ord(c) for c in '&<>']:
     _js_quote.setdefault(chr(i), '\\u%04x' % i)
 _js_quote_re = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t\'&<>]')
+_js_string_re = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t&<>]')
 
 
 def javascript_quote(text):
-    """Quote strings for inclusion in javascript"""
+    """Quote strings for inclusion in single or double quote delimited
+    Javascript strings
+    """
     if not text:
         return ''
     def replace(match):
@@ -111,6 +132,17 @@ def javascript_quote(text):
     return _js_quote_re.sub(replace, text)
 
 
+def to_js_string(text):
+    """Embed the given string in a double quote delimited Javascript string
+    (conform to the JSON spec)
+    """
+    if not text:
+        return ''
+    def replace(match):
+        return _js_quote[match.group(0)]
+    return '"%s"' % _js_string_re.sub(replace, text)
+
+
 def unicode_quote(value, safe='/'):
     """A unicode aware version of `urllib.quote`
 
@@ -541,7 +573,7 @@ def normalize_whitespace(text, to_space=
 def unquote_label(txt):
     """Remove (one level of) enclosing single or double quotes.
 
-    .. versionadded :: 0.13
+    .. versionadded :: 1.0
     """
     return txt[1:-1] if txt and txt[0] in "'\"" and txt[0] == txt[-1] else txt
 
@@ -626,3 +658,22 @@ def unicode_to_base64(text, strip_newlin
 def unicode_from_base64(text):
     """Safe conversion of ``text`` to unicode based on utf-8 bytes."""
     return text.decode('base64').decode('utf-8')
+
+
+def levenshtein_distance(lhs, rhs):
+    """Return the Levenshtein distance between two strings."""
+    if len(lhs) > len(rhs):
+        rhs, lhs = lhs, rhs
+    if not lhs:
+        return len(rhs)
+
+    prev = range(len(rhs) + 1)
+    for lidx, lch in enumerate(lhs):
+        curr = [lidx + 1]
+        for ridx, rch in enumerate(rhs):
+            cost = (lch != rch) * 2
+            curr.append(min(prev[ridx + 1] + 1, # deletion
+                            curr[ridx] + 1,     # insertion
+                            prev[ridx] + cost)) # substitution
+        prev = curr
+    return prev[-1]

Modified: incubator/bloodhound/vendor/trac/current/trac/versioncontrol/api.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/versioncontrol/api.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/versioncontrol/api.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/versioncontrol/api.py Tue Oct 16 15:55:00 2012
@@ -663,7 +663,11 @@ class RepositoryManager(Component):
                 try:
                     changeset = repos.get_changeset(rev)
                 except NoSuchChangeset:
-                    continue
+                    try:
+                        repos.sync_changeset(rev)
+                        changeset = repos.get_changeset(rev)
+                    except NoSuchChangeset:
+                        continue
                 self.log.debug("Event %s on %s for revision %s",
                                event, repos.reponame or '(default)', rev)
                 for listener in self.change_listeners:
@@ -1139,7 +1143,7 @@ class Changeset(object):
     def get_tags(self):
         """Yield tags associated with this changeset.
 
-        .. versionadded :: 0.13
+        .. versionadded :: 1.0
         """
         return []
 

Modified: incubator/bloodhound/vendor/trac/current/trac/versioncontrol/cache.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/versioncontrol/cache.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/versioncontrol/cache.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/versioncontrol/cache.py Tue Oct 16 15:55:00 2012
@@ -30,6 +30,12 @@ _actionmap = {'A': Changeset.ADD, 'C': C
               'D': Changeset.DELETE, 'E': Changeset.EDIT,
               'M': Changeset.MOVE}
 
+def _invert_dict(d):
+    return dict(zip(d.values(), d.keys()))
+
+_inverted_kindmap = _invert_dict(_kindmap)
+_inverted_actionmap = _invert_dict(_actionmap)
+
 CACHE_REPOSITORY_DIR = 'repository_dir'
 CACHE_YOUNGEST_REV = 'youngest_rev'
 
@@ -89,10 +95,13 @@ class CachedRepository(Repository):
                     """, (self.id, srev)):
                 old_cset = Changeset(self.repos, cset.rev, message, author,
                                      from_utimestamp(time))
-            db("""UPDATE revision SET time=%s, author=%s, message=%s
-                  WHERE repos=%s AND rev=%s
-                  """, (to_utimestamp(cset.date), cset.author, cset.message,
-                        self.id, srev))
+            if old_cset:
+                db("""UPDATE revision SET time=%s, author=%s, message=%s
+                      WHERE repos=%s AND rev=%s
+                      """, (to_utimestamp(cset.date), cset.author,
+                            cset.message, self.id, srev))
+            else:
+                self._insert_changeset(db, rev, cset)
         return old_cset
 
     @cached('_metadata_id')
@@ -215,69 +224,69 @@ class CachedRepository(Repository):
                     self.repos.clear(youngest_rev=youngest)
                     return
 
-            # 1. prepare for resyncing
-            #    (there still might be a race condition at this point)
-
-            kindmap = dict(zip(_kindmap.values(), _kindmap.keys()))
-            actionmap = dict(zip(_actionmap.values(), _actionmap.keys()))
-
+            # prepare for resyncing (there might still be a race
+            # condition at this point)
             while next_youngest is not None:
                 srev = self.db_rev(next_youngest)
-                
+
                 with self.env.db_transaction as db:
-                    
-                    # 1.1 Attempt to resync the 'revision' table
                     self.log.info("Trying to sync revision [%s]",
                                   next_youngest)
                     cset = self.repos.get_changeset(next_youngest)
                     try:
-                        db("""INSERT INTO revision
-                                (repos, rev, time, author, message)
-                              VALUES (%s, %s, %s, %s, %s)
-                              """, (self.id, srev, to_utimestamp(cset.date),
-                                    cset.author, cset.message))
-                    except Exception, e: # *another* 1.1. resync attempt won 
+                        # steps 1. and 2.
+                        self._insert_changeset(db, next_youngest, cset)
+                    except Exception, e: # *another* 1.1. resync attempt won
                         self.log.warning('Revision %s already cached: %r',
                                          next_youngest, e)
-                        # also potentially in progress, so keep ''previous''
-                        # notion of 'youngest'
+                        # the other resync attempts is also
+                        # potentially still in progress, so for our
+                        # process/thread, keep ''previous'' notion of
+                        # 'youngest'
                         self.repos.clear(youngest_rev=youngest)
                         # FIXME: This aborts a containing transaction
                         db.rollback()
                         return
-    
-                    # 1.2. now *only* one process was able to get there
-                    #      (i.e. there *shouldn't* be any race condition here)
-    
-                    for path, kind, action, bpath, brev in cset.get_changes():
-                        self.log.debug("Caching node change in [%s]: %r",
-                                       next_youngest,
-                                       (path, kind, action, bpath, brev))
-                        kind = kindmap[kind]
-                        action = actionmap[action]
-                        db("""INSERT INTO node_change
-                                (repos, rev, path, node_type, change_type,
-                                 base_path, base_rev)
-                              VALUES (%s, %s, %s, %s, %s, %s, %s)
-                              """, (self.id, srev, path, kind, action, bpath,
-                                    brev))
-    
-                    # 1.3. update 'youngest_rev' metadata 
-                    #      (minimize possibility of failures at point 0.)
-                    db("""UPDATE repository SET value=%s
-                          WHERE id=%s AND name=%s
-                          """, (str(next_youngest), 
-                                self.id, CACHE_YOUNGEST_REV))
+
+                    # 3. update 'youngest_rev' metadata (minimize
+                    # possibility of failures at point 0.)
+                    db("""
+                        UPDATE repository SET value=%s WHERE id=%s AND name=%s
+                        """, (str(next_youngest), self.id, CACHE_YOUNGEST_REV))
                     del self.metadata
 
-                # 1.4. iterate (1.1 should always succeed now)
+                # 4. iterate (1. should always succeed now)
                 youngest = next_youngest
                 next_youngest = self.repos.next_rev(next_youngest)
 
-                # 1.5. provide some feedback
+                # 5. provide some feedback
                 if feedback:
                     feedback(youngest)
 
+    def _insert_changeset(self, db, rev, cset):
+        srev = self.db_rev(rev)
+        # 1. Attempt to resync the 'revision' table.  In case of
+        # concurrent syncs, only such insert into the `revision` table
+        # will succeed, the others will fail and raise an exception.
+        db("""
+            INSERT INTO revision (repos,rev,time,author,message)
+            VALUES (%s,%s,%s,%s,%s)
+            """, (self.id, srev, to_utimestamp(cset.date),
+                  cset.author, cset.message))
+        # 2. now *only* one process was able to get there (i.e. there
+        # *shouldn't* be any race condition here)
+        for path, kind, action, bpath, brev in cset.get_changes():
+            self.log.debug("Caching node change in [%s]: %r", rev,
+                           (path, kind, action, bpath, brev))
+            kind = _inverted_kindmap[kind]
+            action = _inverted_actionmap[action]
+            db("""
+                INSERT INTO node_change
+                    (repos,rev,path,node_type,change_type,base_path,
+                     base_rev)
+                VALUES (%s,%s,%s,%s,%s,%s,%s)
+                """, (self.id, srev, path, kind, action, bpath, brev))
+
     def get_node(self, path, rev=None):
         return self.repos.get_node(path, self.normalize_rev(rev))
 

Modified: incubator/bloodhound/vendor/trac/current/trac/versioncontrol/diff.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/versioncontrol/diff.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/versioncontrol/diff.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/versioncontrol/diff.py Tue Oct 16 15:55:00 2012
@@ -177,7 +177,7 @@ def filter_ignorable_lines(hunks, fromli
 
 
 def hdf_diff(*args, **kwargs):
-    """:deprecated: use `diff_blocks` (will be removed in 0.14)"""
+    """:deprecated: use `diff_blocks` (will be removed in 1.1.1)"""
     return diff_blocks(*args, **kwargs)
 
 def diff_blocks(fromlines, tolines, context=None, tabwidth=8,
@@ -309,7 +309,7 @@ def get_diff_options(req):
         pref = int(req.session.get('diff_' + name, default))
         arg = int(name in req.args)
         if 'update' in req.args and arg != pref:
-            req.session['diff_' + name] = arg
+            req.session.set('diff_' + name, arg, default)
         else:
             arg = pref
         return arg
@@ -317,7 +317,7 @@ def get_diff_options(req):
     pref = req.session.get('diff_style', 'inline')
     style = req.args.get('style', pref)
     if 'update' in req.args and style != pref:
-        req.session['diff_style'] = style
+        req.session.set('diff_style', style, 'inline')
     data['style'] = style
 
     pref = int(req.session.get('diff_contextlines', 2))
@@ -326,7 +326,7 @@ def get_diff_options(req):
     except ValueError:
         context = -1
     if 'update' in req.args and context != pref:
-        req.session['diff_contextlines'] = context
+        req.session.set('diff_contextlines', context, 2)
     options_data['contextlines'] = context
     
     arg = int(req.args.get('contextall', 0))

Modified: incubator/bloodhound/vendor/trac/current/trac/versioncontrol/svn_fs.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/versioncontrol/svn_fs.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/versioncontrol/svn_fs.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/versioncontrol/svn_fs.py Tue Oct 16 15:55:00 2012
@@ -1,8 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2005-2011 Edgewall Software
-# Copyright (C) 2005 Christopher Lenz <cmlenz@gmx.de>
-# Copyright (C) 2005-2007 Christian Boos <cboos@neuf.fr>
+# Copyright (C) 2012 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -12,1076 +10,10 @@
 # This software consists of voluntary contributions made by many
 # individuals. For the exact contribution history, see the revision
 # history and logs, available at http://trac.edgewall.org/log/.
-#
-# Author: Christopher Lenz <cmlenz@gmx.de>
-#         Christian Boos <cboos@neuf.fr>
-
-"""
-
-Note about Unicode
-------------------
-
-The Subversion bindings are not unicode-aware and they expect to
-receive UTF-8 encoded `string` parameters,
-
-On the other hand, all paths manipulated by Trac are `unicode`
-objects.
-
-Therefore:
-
- * before being handed out to SVN, the Trac paths have to be encoded
-   to UTF-8, using `_to_svn()`
-
- * before being handed out to Trac, a SVN path has to be decoded from
-   UTF-8, using `_from_svn()`
-
-Whenever a value has to be stored as utf8, we explicitly mark the
-variable name with "_utf8", in order to avoid any possible confusion.
-
-Warning: 
-  `SubversionNode.get_content()` returns an object from which one can
-  read a stream of bytes. NO guarantees can be given about what that
-  stream of bytes represents. It might be some text, encoded in some
-  way or another.  SVN properties *might* give some hints about the
-  content, but they actually only reflect the beliefs of whomever set
-  those properties...
-"""
-
-import os.path
-import weakref
-import posixpath
-
-from trac.config import ListOption
-from trac.core import *
-from trac.env import ISystemInfoProvider
-from trac.versioncontrol import Changeset, Node, Repository, \
-                                IRepositoryConnector, \
-                                NoSuchChangeset, NoSuchNode
-from trac.versioncontrol.cache import CachedRepository
-from trac.util import embedded_numbers
-from trac.util.text import exception_to_unicode, to_unicode
-from trac.util.translation import _
-from trac.util.datefmt import from_utimestamp
-
-
-application_pool = None
-
-
-def _import_svn():
-    global fs, repos, core, delta, _kindmap
-    from svn import fs, repos, core, delta
-    _kindmap = {core.svn_node_dir: Node.DIRECTORY,
-                core.svn_node_file: Node.FILE}
-    # Protect svn.core methods from GC
-    Pool.apr_pool_clear = staticmethod(core.apr_pool_clear)
-    Pool.apr_pool_destroy = staticmethod(core.apr_pool_destroy)
-
-def _to_svn(pool, *args):
-    """Expect a pool and a list of `unicode` path components.
-    
-    Returns an UTF-8 encoded string suitable for the Subversion python 
-    bindings (the returned path never starts with a leading "/")
-    """
-    return core.svn_path_canonicalize('/'.join(args).lstrip('/')
-                                                    .encode('utf-8'),
-                                      pool)
-
-def _from_svn(path):
-    """Expect an UTF-8 encoded string and transform it to an `unicode` object
-
-    But Subversion repositories built from conversion utilities can have
-    non-UTF-8 byte strings, so we have to convert using `to_unicode`.
-    """
-    return path and to_unicode(path, 'utf-8')
-    
-# The following 3 helpers deal with unicode paths
-
-def _normalize_path(path):
-    """Remove leading "/", except for the root."""
-    return path and path.strip('/') or '/'
-
-def _path_within_scope(scope, fullpath):
-    """Remove the leading scope from repository paths.
-
-    Return `None` if the path is not is scope.
-    """
-    if fullpath is not None:
-        fullpath = fullpath.lstrip('/')
-        if scope == '/':
-            return _normalize_path(fullpath)
-        scope = scope.strip('/')
-        if (fullpath + '/').startswith(scope + '/'):
-            return fullpath[len(scope) + 1:] or '/'
-
-def _is_path_within_scope(scope, fullpath):
-    """Check whether the given `fullpath` is within the given `scope`"""
-    if scope == '/':
-        return fullpath is not None
-    fullpath = fullpath.lstrip('/') if fullpath else ''
-    scope = scope.strip('/')
-    return (fullpath + '/').startswith(scope + '/')
-
-# svn_opt_revision_t helpers
-
-def _svn_rev(num):
-    value = core.svn_opt_revision_value_t()
-    value.number = num
-    revision = core.svn_opt_revision_t()
-    revision.kind = core.svn_opt_revision_number
-    revision.value = value
-    return revision
-
-def _svn_head():
-    revision = core.svn_opt_revision_t()
-    revision.kind = core.svn_opt_revision_head
-    return revision
-
-# apr_pool_t helpers
-
-def _mark_weakpool_invalid(weakpool):
-    if weakpool():
-        weakpool()._mark_invalid()
-
-
-class Pool(object):
-    """A Pythonic memory pool object"""
-
-    def __init__(self, parent_pool=None):
-        """Create a new memory pool"""
-
-        global application_pool
-        self._parent_pool = parent_pool or application_pool
-
-        # Create pool
-        if self._parent_pool:
-            self._pool = core.svn_pool_create(self._parent_pool())
-        else:
-            # If we are an application-level pool,
-            # then initialize APR and set this pool
-            # to be the application-level pool
-            core.apr_initialize()
-            application_pool = self
-
-            self._pool = core.svn_pool_create(None)
-        self._mark_valid()
-
-    def __call__(self):
-        return self._pool
-
-    def valid(self):
-        """Check whether this memory pool and its parents
-        are still valid"""
-        return hasattr(self,"_is_valid")
-
-    def assert_valid(self):
-        """Assert that this memory_pool is still valid."""
-        assert self.valid()
-
-    def clear(self):
-        """Clear embedded memory pool. Invalidate all subpools."""
-        self.apr_pool_clear(self._pool)
-        self._mark_valid()
-
-    def destroy(self):
-        """Destroy embedded memory pool. If you do not destroy
-        the memory pool manually, Python will destroy it
-        automatically."""
-
-        global application_pool
-
-        self.assert_valid()
-
-        # Destroy pool
-        self.apr_pool_destroy(self._pool)
-
-        # Clear application pool and terminate APR if necessary
-        if not self._parent_pool:
-            application_pool = None
-
-        self._mark_invalid()
-
-    def __del__(self):
-        """Automatically destroy memory pools, if necessary"""
-        if self.valid():
-            self.destroy()
-
-    def _mark_valid(self):
-        """Mark pool as valid"""
-        if self._parent_pool:
-            # Refer to self using a weakreference so that we don't
-            # create a reference cycle
-            weakself = weakref.ref(self)
-
-            # Set up callbacks to mark pool as invalid when parents
-            # are destroyed
-            self._weakref = weakref.ref(self._parent_pool._is_valid,
-                                        lambda x: \
-                                        _mark_weakpool_invalid(weakself))
-
-        # mark pool as valid
-        self._is_valid = lambda: 1
-
-    def _mark_invalid(self):
-        """Mark pool as invalid"""
-        if self.valid():
-            # Mark invalid
-            del self._is_valid
-
-            # Free up memory
-            del self._parent_pool
-            if hasattr(self, "_weakref"):
-                del self._weakref
-
-
-class SvnCachedRepository(CachedRepository):
-    """Subversion-specific cached repository, zero-pads revision numbers
-    in the cache tables.
-    """
-    has_linear_changesets = True
-
-    def db_rev(self, rev):
-        return '%010d' % rev
-
-    def rev_db(self, rev):
-        return int(rev or 0)
-
-
-class SubversionConnector(Component):
-
-    implements(ISystemInfoProvider, IRepositoryConnector)
-
-    branches = ListOption('svn', 'branches', 'trunk, branches/*', doc=
-        """Comma separated list of paths categorized as branches.
-        If a path ends with '*', then all the directory entries found below 
-        that path will be included. 
-        Example: `/trunk, /branches/*, /projectAlpha/trunk, /sandbox/*`
-        """)
-
-    tags = ListOption('svn', 'tags', 'tags/*', doc=
-        """Comma separated list of paths categorized as tags.
-        
-        If a path ends with '*', then all the directory entries found below
-        that path will be included.
-        Example: `/tags/*, /projectAlpha/tags/A-1.0, /projectAlpha/tags/A-v1.1`
-        """)
-
-    error = None
-
-    def __init__(self):
-        self._version = None
-        try:
-            _import_svn()
-            self.log.debug('Subversion bindings imported')
-        except ImportError, e:
-            self.error = e
-            self.log.info('Failed to load Subversion bindings', exc_info=True)
-        else:
-            version = (core.SVN_VER_MAJOR, core.SVN_VER_MINOR,
-                       core.SVN_VER_MICRO)
-            self._version = '%d.%d.%d' % version + core.SVN_VER_TAG
-            if version[0] < 1:
-                self.error = _("Subversion >= 1.0 required, found %(version)s",
-                               version=self._version)
-            Pool()
-
-    # ISystemInfoProvider methods
-    
-    def get_system_info(self):
-        if self._version is not None:
-            yield 'Subversion', self._version
-        
-    # IRepositoryConnector methods
-    
-    def get_supported_types(self):
-        prio = 1
-        if self.error:
-            prio = -1
-        yield ("direct-svnfs", prio * 4)
-        yield ("svnfs", prio * 4)
-        yield ("svn", prio * 2)
-
-    def get_repository(self, type, dir, params):
-        """Return a `SubversionRepository`.
-
-        The repository is wrapped in a `CachedRepository`, unless `type` is
-        'direct-svnfs'.
-        """
-        params.update(tags=self.tags, branches=self.branches)
-        repos = SubversionRepository(dir, params, self.log)
-        if type != 'direct-svnfs':
-            repos = SvnCachedRepository(self.env, repos, self.log)
-        return repos
-
-
-class SubversionRepository(Repository):
-    """Repository implementation based on the svn.fs API."""
-
-    has_linear_changesets = True
-
-    def __init__(self, path, params, log):
-        self.log = log
-        self.pool = Pool()
-        
-        # Remove any trailing slash or else subversion might abort
-        if isinstance(path, unicode):
-            path_utf8 = path.encode('utf-8')
-        else: # note that this should usually not happen (unicode arg expected)
-            path_utf8 = to_unicode(path).encode('utf-8')
-
-        path_utf8 = os.path.normpath(path_utf8).replace('\\', '/')
-        self.path = path_utf8.decode('utf-8')
-        
-        root_path_utf8 = repos.svn_repos_find_root_path(path_utf8, self.pool())
-        if root_path_utf8 is None:
-            raise TracError(_("%(path)s does not appear to be a Subversion "
-                              "repository.", path=to_unicode(path_utf8)))
-
-        try:
-            self.repos = repos.svn_repos_open(root_path_utf8, self.pool())
-        except core.SubversionException, e:
-            raise TracError(_("Couldn't open Subversion repository %(path)s: "
-                              "%(svn_error)s", path=to_unicode(path_utf8),
-                              svn_error=exception_to_unicode(e)))
-        self.fs_ptr = repos.svn_repos_fs(self.repos)
-        
-        self.uuid = fs.get_uuid(self.fs_ptr, self.pool())
-        self.base = 'svn:%s:%s' % (self.uuid, _from_svn(root_path_utf8))
-        name = 'svn:%s:%s' % (self.uuid, self.path)
-
-        Repository.__init__(self, name, params, log)
-
-        # if root_path_utf8 is shorter than the path_utf8, the difference is
-        # this scope (which always starts with a '/')
-        if root_path_utf8 != path_utf8:
-            self.scope = path_utf8[len(root_path_utf8):].decode('utf-8')
-            if not self.scope[-1] == '/':
-                self.scope += '/'
-        else:
-            self.scope = '/'
-        assert self.scope[0] == '/'
-        # we keep root_path_utf8 for  RA 
-        ra_prefix = 'file:///' if os.name == 'nt' else 'file://'
-        self.ra_url_utf8 = ra_prefix + root_path_utf8
-        self.clear()
-
-    def clear(self, youngest_rev=None):
-        """Reset notion of `youngest` and `oldest`"""
-        self.youngest = None
-        if youngest_rev is not None:
-            self.youngest = self.normalize_rev(youngest_rev)
-        self.oldest = None
-
-    def __del__(self):
-        self.close()
-
-    def has_node(self, path, rev=None, pool=None):
-        """Check if `path` exists at `rev` (or latest if unspecified)"""
-        if not pool:
-            pool = self.pool
-        rev = self.normalize_rev(rev)
-        rev_root = fs.revision_root(self.fs_ptr, rev, pool())
-        node_type = fs.check_path(rev_root, _to_svn(pool(), self.scope, path),
-                                  pool())
-        return node_type in _kindmap
-
-    def normalize_path(self, path):
-        """Take any path specification and produce a path suitable for 
-        the rest of the API
-        """
-        return _normalize_path(path)
-
-    def normalize_rev(self, rev):
-        """Take any revision specification and produce a revision suitable
-        for the rest of the API
-        """
-        if rev is None or isinstance(rev, basestring) and \
-               rev.lower() in ('', 'head', 'latest', 'youngest'):
-            return self.youngest_rev
-        else:
-            try:
-                rev = int(rev)
-                if rev <= self.youngest_rev:
-                    return rev
-            except (ValueError, TypeError):
-                pass
-            raise NoSuchChangeset(rev)
-
-    def close(self):
-        """Dispose of low-level resources associated to this repository."""
-        if self.pool:
-            self.pool.destroy()
-        self.repos = self.fs_ptr = self.pool = None
-
-    def get_base(self):
-        """Retrieve the base path corresponding to the Subversion
-        repository itself. 
-
-        This is the same as the `.path` property minus the
-        intra-repository scope, if one was specified.
-        """
-        return self.base
-        
-    def _get_tags_or_branches(self, paths):
-        """Retrieve known branches or tags."""
-        for path in self.params.get(paths, []):
-            if path.endswith('*'):
-                folder = posixpath.dirname(path)
-                try:
-                    entries = [n for n in self.get_node(folder).get_entries()]
-                    for node in sorted(entries, key=lambda n: 
-                                       embedded_numbers(n.path.lower())):
-                        if node.kind == Node.DIRECTORY:
-                            yield node
-                except Exception: # no right (TODO: use a specific Exception)
-                    pass
-            else:
-                try:
-                    yield self.get_node(path)
-                except Exception: # no right
-                    pass
-
-    def get_quickjump_entries(self, rev):
-        """Retrieve known branches, as (name, id) pairs.
-        
-        Purposedly ignores `rev` and always takes the last revision.
-        """
-        for n in self._get_tags_or_branches('branches'):
-            yield 'branches', n.path, n.path, None
-        for n in self._get_tags_or_branches('tags'):
-            yield 'tags', n.path, n.created_path, n.created_rev
-
-    def get_path_url(self, path, rev):
-        """Retrieve the "native" URL from which this repository is reachable
-        from Subversion clients.
-        """
-        url = self.params.get('url', '').rstrip('/')
-        if url:
-            if not path or path == '/':
-                return url
-            return url + '/' + path.lstrip('/')
-    
-    def get_changeset(self, rev):
-        """Produce a `SubversionChangeset` from given revision
-        specification"""
-        rev = self.normalize_rev(rev)
-        return SubversionChangeset(self, rev, self.scope, self.pool)
-
-    def get_changeset_uid(self, rev):
-        """Build a value identifying the `rev` in this repository."""
-        return (self.uuid, rev)
-
-    def get_node(self, path, rev=None):
-        """Produce a `SubversionNode` from given path and optionally revision
-        specifications. No revision given means use the latest.
-        """
-        path = path or ''
-        if path and path[-1] == '/':
-            path = path[:-1]
-        rev = self.normalize_rev(rev) or self.youngest_rev
-        return SubversionNode(path, rev, self, self.pool)
-
-    def _get_node_revs(self, path, last=None, first=None):
-        """Return the revisions affecting `path` between `first` and `last` 
-        revs. If `first` is not given, it goes down to the revision in which
-        the branch was created.
-        """
-        node = self.get_node(path, last)
-        revs = []
-        for (p, r, chg) in node.get_history():
-            if p != path or (first and r < first):
-                break
-            revs.append(r)
-        return revs
-
-    def _history(self, path, start, end, pool):
-        """`path` is a unicode path in the scope.
-
-        Generator yielding `(path, rev)` pairs, where `path` is an `unicode`
-        object. Must start with `(path, created rev)`.
-
-        (wraps ``fs.node_history``)
-        """
-        path_utf8 = _to_svn(pool(), self.scope, path)
-        if start < end:
-            start, end = end, start
-        if (start, end) == (1, 0): # only happens for empty repos
-            return
-        root = fs.revision_root(self.fs_ptr, start, pool())
-        # fs.node_history leaks when path doesn't exist (#6588)
-        if fs.check_path(root, path_utf8, pool()) == core.svn_node_none:
-            return
-        tmp1 = Pool(pool)
-        tmp2 = Pool(pool)
-        history_ptr = fs.node_history(root, path_utf8, tmp1())
-        cross_copies = 1
-        while history_ptr:
-            history_ptr = fs.history_prev(history_ptr, cross_copies, tmp2())
-            tmp1.clear()
-            tmp1, tmp2 = tmp2, tmp1
-            if history_ptr:
-                path_utf8, rev = fs.history_location(history_ptr, tmp2())
-                tmp2.clear()
-                if rev < end:
-                    break
-                path = _from_svn(path_utf8)
-                yield path, rev
-        del tmp1
-        del tmp2
-    
-    def _previous_rev(self, rev, path='', pool=None):
-        if rev > 1: # don't use oldest here, as it's too expensive
-            for _, prev in self._history(path, 1, rev-1, pool or self.pool):
-                return prev
-        return None
-    
-
-    def get_oldest_rev(self):
-        """Gives an approximation of the oldest revision."""
-        if self.oldest is None:
-            self.oldest = 1
-            # trying to figure out the oldest rev for scoped repository
-            # is too expensive and uncovers a big memory leak (#5213)
-            # if self.scope != '/':
-            #    self.oldest = self.next_rev(0, find_initial_rev=True)
-        return self.oldest
-
-    def get_youngest_rev(self):
-        """Retrieve the latest revision in the repository.
-
-        (wraps ``fs.youngest_rev``)
-        """
-        if not self.youngest:
-            self.youngest = fs.youngest_rev(self.fs_ptr, self.pool())
-            if self.scope != '/':
-                for path, rev in self._history('', 1, self.youngest, self.pool):
-                    self.youngest = rev
-                    break
-        return self.youngest
-
-    def previous_rev(self, rev, path=''):
-        """Return revision immediately preceeding `rev`, eventually below 
-        given `path` or globally.
-        """
-        # FIXME optimize for non-scoped
-        rev = self.normalize_rev(rev)
-        return self._previous_rev(rev, path)
-
-    def next_rev(self, rev, path='', find_initial_rev=False):
-        """Return revision immediately following `rev`, eventually below 
-        given `path` or globally.
-        """
-        rev = self.normalize_rev(rev)
-        next = rev + 1
-        youngest = self.youngest_rev
-        subpool = Pool(self.pool)
-        while next <= youngest:
-            subpool.clear()            
-            for _, next in self._history(path, rev+1, next, subpool):
-                return next
-            else:
-                if not find_initial_rev and \
-                         not self.has_node(path, next, subpool):
-                    return next # a 'delete' event is also interesting...
-            next += 1
-        return None
-
-    def rev_older_than(self, rev1, rev2):
-        """Check relative order between two revision specifications."""
-        return self.normalize_rev(rev1) < self.normalize_rev(rev2)
-
-    def get_path_history(self, path, rev=None, limit=None):
-        """Retrieve creation and deletion events that happened on
-        given `path`.
-        """
-        path = self.normalize_path(path)
-        rev = self.normalize_rev(rev)
-        expect_deletion = False
-        subpool = Pool(self.pool)
-        numrevs = 0
-        while rev and (not limit or numrevs < limit):
-            subpool.clear()
-            if self.has_node(path, rev, subpool):
-                if expect_deletion:
-                    # it was missing, now it's there again:
-                    #  rev+1 must be a delete
-                    numrevs += 1
-                    yield path, rev+1, Changeset.DELETE
-                newer = None # 'newer' is the previously seen history tuple
-                older = None # 'older' is the currently examined history tuple
-                for p, r in self._history(path, 1, rev, subpool):
-                    older = (_path_within_scope(self.scope, p), r,
-                             Changeset.ADD)
-                    rev = self._previous_rev(r, pool=subpool)
-                    if newer:
-                        numrevs += 1
-                        if older[0] == path:
-                            # still on the path: 'newer' was an edit
-                            yield newer[0], newer[1], Changeset.EDIT
-                        else:
-                            # the path changed: 'newer' was a copy
-                            rev = self._previous_rev(newer[1], pool=subpool)
-                            # restart before the copy op
-                            yield newer[0], newer[1], Changeset.COPY
-                            older = (older[0], older[1], 'unknown')
-                            break
-                    newer = older
-                if older:
-                    # either a real ADD or the source of a COPY
-                    numrevs += 1
-                    yield older
-            else:
-                expect_deletion = True
-                rev = self._previous_rev(rev, pool=subpool)
-
-    def get_changes(self, old_path, old_rev, new_path, new_rev,
-                    ignore_ancestry=0):
-        """Determine differences between two arbitrary pairs of paths
-        and revisions.
-
-        (wraps ``repos.svn_repos_dir_delta``)
-        """
-        old_node = new_node = None
-        old_rev = self.normalize_rev(old_rev)
-        new_rev = self.normalize_rev(new_rev)
-        if self.has_node(old_path, old_rev):
-            old_node = self.get_node(old_path, old_rev)
-        else:
-            raise NoSuchNode(old_path, old_rev, 'The Base for Diff is invalid')
-        if self.has_node(new_path, new_rev):
-            new_node = self.get_node(new_path, new_rev)
-        else:
-            raise NoSuchNode(new_path, new_rev,
-                             'The Target for Diff is invalid')
-        if new_node.kind != old_node.kind:
-            raise TracError(_('Diff mismatch: Base is a %(oldnode)s '
-                              '(%(oldpath)s in revision %(oldrev)s) and '
-                              'Target is a %(newnode)s (%(newpath)s in '
-                              'revision %(newrev)s).', oldnode=old_node.kind,
-                              oldpath=old_path, oldrev=old_rev,
-                              newnode=new_node.kind, newpath=new_path,
-                              newrev=new_rev))
-        subpool = Pool(self.pool)
-        if new_node.isdir:
-            editor = DiffChangeEditor()
-            e_ptr, e_baton = delta.make_editor(editor, subpool())
-            old_root = fs.revision_root(self.fs_ptr, old_rev, subpool())
-            new_root = fs.revision_root(self.fs_ptr, new_rev, subpool())
-            def authz_cb(root, path, pool):
-                return 1
-            text_deltas = 0 # as this is anyway re-done in Diff.py...
-            entry_props = 0 # "... typically used only for working copy updates"
-            repos.svn_repos_dir_delta(old_root,
-                                      _to_svn(subpool(), self.scope, old_path),
-                                      '', new_root,
-                                      _to_svn(subpool(), self.scope, new_path),
-                                      e_ptr, e_baton, authz_cb,
-                                      text_deltas,
-                                      1, # directory
-                                      entry_props,
-                                      ignore_ancestry,
-                                      subpool())
-            for path, kind, change in editor.deltas:
-                path = _from_svn(path)
-                old_node = new_node = None
-                if change != Changeset.ADD:
-                    old_node = self.get_node(posixpath.join(old_path, path),
-                                             old_rev)
-                if change != Changeset.DELETE:
-                    new_node = self.get_node(posixpath.join(new_path, path),
-                                             new_rev)
-                else:
-                    kind = _kindmap[fs.check_path(old_root,
-                                                  _to_svn(subpool(),
-                                                          self.scope,
-                                                          old_node.path),
-                                                  subpool())]
-                yield  (old_node, new_node, kind, change)
-        else:
-            old_root = fs.revision_root(self.fs_ptr, old_rev, subpool())
-            new_root = fs.revision_root(self.fs_ptr, new_rev, subpool())
-            if fs.contents_changed(old_root,
-                                   _to_svn(subpool(), self.scope, old_path),
-                                   new_root,
-                                   _to_svn(subpool(), self.scope, new_path),
-                                   subpool()):
-                yield (old_node, new_node, Node.FILE, Changeset.EDIT)
-
-
-class SubversionNode(Node):
-
-    def __init__(self, path, rev, repos, pool=None, parent_root=None):
-        self.fs_ptr = repos.fs_ptr
-        self.scope = repos.scope
-        self.pool = Pool(pool)
-        pool = self.pool()
-        self._scoped_path_utf8 = _to_svn(pool, self.scope, path)
-
-        if parent_root:
-            self.root = parent_root
-        else:
-            self.root = fs.revision_root(self.fs_ptr, rev, pool)
-        node_type = fs.check_path(self.root, self._scoped_path_utf8, pool)
-        if not node_type in _kindmap:
-            raise NoSuchNode(path, rev)
-        cp_utf8 = fs.node_created_path(self.root, self._scoped_path_utf8, pool)
-        cp = _from_svn(cp_utf8)
-        cr = fs.node_created_rev(self.root, self._scoped_path_utf8, pool)
-        # Note: `cp` differs from `path` if the last change was a copy,
-        #        In that case, `path` doesn't even exist at `cr`.
-        #        The only guarantees are:
-        #          * this node exists at (path,rev)
-        #          * the node existed at (created_path,created_rev)
-        # Also, `cp` might well be out of the scope of the repository,
-        # in this case, we _don't_ use the ''create'' information.
-        if _is_path_within_scope(self.scope, cp):
-            self.created_rev = cr
-            self.created_path = _path_within_scope(self.scope, cp)
-        else:
-            self.created_rev, self.created_path = rev, path
-        # TODO: check node id
-        Node.__init__(self, repos, path, rev, _kindmap[node_type])
-
-    def get_content(self):
-        """Retrieve raw content as a "read()"able object."""
-        if self.isdir:
-            return None
-        s = core.Stream(fs.file_contents(self.root, self._scoped_path_utf8,
-                                         self.pool()))
-        # The stream object needs to reference the pool to make sure the pool
-        # is not destroyed before the former.
-        s._pool = self.pool
-        return s
-
-    def get_entries(self):
-        """Yield `SubversionNode` corresponding to entries in this directory.
-
-        (wraps ``fs.dir_entries``)
-        """
-        if self.isfile:
-            return
-        pool = Pool(self.pool)
-        entries = fs.dir_entries(self.root, self._scoped_path_utf8, pool())
-        for item in entries.keys():
-            path = posixpath.join(self.path, _from_svn(item))
-            yield SubversionNode(path, self.rev, self.repos, self.pool,
-                                 self.root)
-
-    def get_history(self, limit=None):
-        """Yield change events that happened on this path"""
-        newer = None # 'newer' is the previously seen history tuple
-        older = None # 'older' is the currently examined history tuple
-        pool = Pool(self.pool)
-        numrevs = 0
-        for path, rev in self.repos._history(self.path, 1, self.rev, pool):
-            path = _path_within_scope(self.scope, path)
-            if rev > 0 and path:
-                older = (path, rev, Changeset.ADD)
-                if newer:
-                    if newer[0] == older[0]: # stay on same path
-                        change = Changeset.EDIT
-                    else:
-                        change = Changeset.COPY
-                    newer = (newer[0], newer[1], change)
-                    numrevs += 1
-                    yield newer
-                newer = older
-            if limit and numrevs >= limit:
-                break
-        if newer and (not limit or numrevs < limit):
-            yield newer
-
-    def get_annotations(self):
-        """Return a list the last changed revision for each line.
-        (wraps ``client.blame2``)
-        """
-        annotations = []
-        if self.isfile:
-            def blame_receiver(line_no, revision, author, date, line, pool):
-                annotations.append(revision)
-            try:
-                rev = _svn_rev(self.rev)
-                start = _svn_rev(0)
-                file_url_utf8 = posixpath.join(self.repos.ra_url_utf8,
-                                               self._scoped_path_utf8)
-                self.repos.log.info('opening ra_local session to %r',
-                                    file_url_utf8)
-                from svn import client
-                client.blame2(file_url_utf8, rev, start, rev, blame_receiver,
-                              client.create_context(), self.pool())
-            except (core.SubversionException, AttributeError), e:
-                # svn thinks file is a binary or blame not supported
-                raise TracError(_('svn blame failed on %(path)s: %(error)s',
-                                  path=self.path, error=to_unicode(e)))
-        return annotations
-
-#    def get_previous(self):
-#        # FIXME: redo it with fs.node_history
-
-    def get_properties(self):
-        """Return `dict` of node properties at current revision.
-
-        (wraps ``fs.node_proplist``)
-        """
-        props = fs.node_proplist(self.root, self._scoped_path_utf8, self.pool())
-        for name, value in props.items():
-            # Note that property values can be arbitrary binary values
-            # so we can't assume they are UTF-8 strings...
-            props[_from_svn(name)] = to_unicode(value)
-        return props
-
-    def get_content_length(self):
-        """Retrieve byte size of a file.
-
-        Return `None` for a folder. (wraps ``fs.file_length``)
-        """
-        if self.isdir:
-            return None
-        return fs.file_length(self.root, self._scoped_path_utf8, self.pool())
-
-    def get_content_type(self):
-        """Retrieve mime-type property of a file.
-
-        Return `None` for a folder. (wraps ``fs.revision_prop``)
-        """
-        if self.isdir:
-            return None
-        return self._get_prop(core.SVN_PROP_MIME_TYPE)
-
-    def get_last_modified(self):
-        """Retrieve timestamp of last modification, in micro-seconds.
-
-        (wraps ``fs.revision_prop``)
-        """
-        _date = fs.revision_prop(self.fs_ptr, self.created_rev,
-                                 core.SVN_PROP_REVISION_DATE, self.pool())
-        if not _date:
-            return None
-        return from_utimestamp(core.svn_time_from_cstring(_date, self.pool()))
-
-    def _get_prop(self, name):
-        return fs.node_prop(self.root, self._scoped_path_utf8, name,
-                            self.pool())
-
-    def get_branch_origin(self):
-        """Return the revision in which the node's path was created.
-
-        (wraps ``fs.revision_root_revision(fs.closest_copy)``)
-        """
-        root_and_path = fs.closest_copy(self.root, self._scoped_path_utf8)
-        if root_and_path:
-            return fs.revision_root_revision(root_and_path[0])
-
-    def get_copy_ancestry(self):
-        """Retrieve the list of `(path,rev)` copy ancestors of this node.
-        Most recent ancestor first. Each ancestor `(path, rev)` corresponds 
-        to the path and revision of the source at the time the copy or move
-        operation was performed.
-        """
-        ancestors = []
-        previous = (self._scoped_path_utf8, self.rev, self.root)
-        while previous:
-            (previous_path, previous_rev, previous_root) = previous
-            previous = None
-            root_path = fs.closest_copy(previous_root, previous_path)
-            if root_path:
-                (root, path) = root_path
-                path = path.lstrip('/')
-                rev = fs.revision_root_revision(root)
-                relpath = None
-                if path != previous_path:
-                    # `previous_path` is a subfolder of `path` and didn't
-                    # change since `path` was copied
-                    relpath = previous_path[len(path):].strip('/')
-                copied_from = fs.copied_from(root, path)
-                if copied_from:
-                    (rev, path) = copied_from
-                    path = path.lstrip('/')
-                    root = fs.revision_root(self.fs_ptr, rev, self.pool())
-                    if relpath:
-                        path += '/' + relpath
-                    ui_path = _path_within_scope(self.scope, _from_svn(path))
-                    if ui_path:
-                        ancestors.append((ui_path, rev))
-                    previous = (path, rev, root)
-        return ancestors
-
-
-class SubversionChangeset(Changeset):
-
-    def __init__(self, repos, rev, scope, pool=None):
-        self.rev = rev
-        self.scope = scope
-        self.fs_ptr = repos.fs_ptr
-        self.pool = Pool(pool)
-        try:
-            message = self._get_prop(core.SVN_PROP_REVISION_LOG)
-        except core.SubversionException:
-            raise NoSuchChangeset(rev)
-        author = self._get_prop(core.SVN_PROP_REVISION_AUTHOR)
-        # we _hope_ it's UTF-8, but can't be 100% sure (#4321)
-        message = message and to_unicode(message, 'utf-8')
-        author = author and to_unicode(author, 'utf-8')
-        _date = self._get_prop(core.SVN_PROP_REVISION_DATE)
-        if _date:
-            ts = core.svn_time_from_cstring(_date, self.pool())
-            date = from_utimestamp(ts)
-        else:
-            date = None
-        Changeset.__init__(self, repos, rev, message, author, date)
-
-    def get_properties(self):
-        """Retrieve `dict` of Subversion properties for this revision
-        (revprops)
-        """
-        props = fs.revision_proplist(self.fs_ptr, self.rev, self.pool())
-        properties = {}
-        for k, v in props.iteritems():
-            if k not in (core.SVN_PROP_REVISION_LOG,
-                         core.SVN_PROP_REVISION_AUTHOR,
-                         core.SVN_PROP_REVISION_DATE):
-                properties[k] = to_unicode(v)
-                # Note: the above `to_unicode` has a small probability
-                # to mess-up binary properties, like icons.
-        return properties
-
-    def get_changes(self):
-        """Retrieve file changes for a given revision.
-
-        (wraps ``repos.svn_repos_replay``)
-        """
-        pool = Pool(self.pool)
-        tmp = Pool(pool)
-        root = fs.revision_root(self.fs_ptr, self.rev, pool())
-        editor = repos.RevisionChangeCollector(self.fs_ptr, self.rev, pool())
-        e_ptr, e_baton = delta.make_editor(editor, pool())
-        repos.svn_repos_replay(root, e_ptr, e_baton, pool())
-
-        idx = 0
-        copies, deletions = {}, {}
-        changes = []
-        revroots = {}
-        for path_utf8, change in editor.changes.items():
-            new_path = _from_svn(path_utf8)
-
-            # Filtering on `path`
-            if not _is_path_within_scope(self.scope, new_path):
-                continue
-
-            path_utf8 = change.path
-            base_path_utf8 = change.base_path
-            path = _from_svn(path_utf8)
-            base_path = _from_svn(base_path_utf8)
-            base_rev = change.base_rev
-            change_action = getattr(change, 'action', None)
-
-            # Ensure `base_path` is within the scope
-            if not _is_path_within_scope(self.scope, base_path):
-                base_path, base_rev = None, -1
-
-            # Determine the action
-            if not path and not new_path and self.scope == '/':
-                action = Changeset.EDIT # root property change
-            elif not path or (change_action is not None
-                              and change_action == repos.CHANGE_ACTION_DELETE):
-                if new_path:            # deletion
-                    action = Changeset.DELETE
-                    deletions[new_path.lstrip('/')] = idx
-                else:                   # deletion outside of scope, ignore
-                    continue
-            elif change.added or not base_path: # add or copy
-                action = Changeset.ADD
-                if base_path and base_rev:
-                    action = Changeset.COPY
-                    copies[base_path.lstrip('/')] = idx
-            else:
-                action = Changeset.EDIT
-                # identify the most interesting base_path/base_rev
-                # in terms of last changed information (see r2562)
-                if revroots.has_key(base_rev):
-                    b_root = revroots[base_rev]
-                else:
-                    b_root = fs.revision_root(self.fs_ptr, base_rev, pool())
-                    revroots[base_rev] = b_root
-                tmp.clear()
-                cbase_path_utf8 = fs.node_created_path(b_root, base_path_utf8,
-                                                       tmp())
-                cbase_path = _from_svn(cbase_path_utf8)
-                cbase_rev = fs.node_created_rev(b_root, base_path_utf8, tmp()) 
-                # give up if the created path is outside the scope
-                if _is_path_within_scope(self.scope, cbase_path):
-                    base_path, base_rev = cbase_path, cbase_rev
-
-            kind = _kindmap[change.item_kind]
-            path = _path_within_scope(self.scope, new_path or base_path)
-            base_path = _path_within_scope(self.scope, base_path)
-            changes.append([path, kind, action, base_path, base_rev])
-            idx += 1
-
-        moves = []
-        # a MOVE is a COPY whose `base_path` corresponds to a `new_path`
-        # which has been deleted
-        for k, v in copies.items():
-            if k in deletions:
-                changes[v][2] = Changeset.MOVE
-                moves.append(deletions[k])
-        offset = 0
-        moves.sort()
-        for i in moves:
-            del changes[i - offset]
-            offset += 1
-
-        changes.sort()
-        for change in changes:
-            yield tuple(change)
-
-    def _get_prop(self, name):
-        return fs.revision_prop(self.fs_ptr, self.rev, name, self.pool())
-
-
-#
-# Delta editor for diffs between arbitrary nodes
-#
-# Note 1: the 'copyfrom_path' and 'copyfrom_rev' information is not used
-#         because 'repos.svn_repos_dir_delta' *doesn't* provide it.
-#
-# Note 2: the 'dir_baton' is the path of the parent directory
-#
-
-
-def DiffChangeEditor():
-
-    class DiffChangeEditor(delta.Editor): 
-
-        def __init__(self):
-            self.deltas = []
-    
-        # -- svn.delta.Editor callbacks
-
-        def open_root(self, base_revision, dir_pool):
-            return ('/', Changeset.EDIT)
-
-        def add_directory(self, path, dir_baton, copyfrom_path, copyfrom_rev,
-                          dir_pool):
-            self.deltas.append((path, Node.DIRECTORY, Changeset.ADD))
-            return (path, Changeset.ADD)
-
-        def open_directory(self, path, dir_baton, base_revision, dir_pool):
-            return (path, dir_baton[1])
-
-        def change_dir_prop(self, dir_baton, name, value, pool):
-            path, change = dir_baton
-            if change != Changeset.ADD:
-                self.deltas.append((path, Node.DIRECTORY, change))
-
-        def delete_entry(self, path, revision, dir_baton, pool):
-            self.deltas.append((path, None, Changeset.DELETE))
-
-        def add_file(self, path, dir_baton, copyfrom_path, copyfrom_revision,
-                     dir_pool):
-            self.deltas.append((path, Node.FILE, Changeset.ADD))
-
-        def open_file(self, path, dir_baton, dummy_rev, file_pool):
-            self.deltas.append((path, Node.FILE, Changeset.EDIT))
 
-    return DiffChangeEditor() 
+from trac.util import import_namespace
+import_namespace(globals(), 'tracopt.versioncontrol.svn.svn_fs')
 
+# This module is a stub provided for backward compatibility. The svn_fs
+# module has been moved to tracopt.versioncontrol.svn. Please update your
+# code to use the new location.

Modified: incubator/bloodhound/vendor/trac/current/trac/versioncontrol/svn_prop.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/versioncontrol/svn_prop.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/versioncontrol/svn_prop.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/versioncontrol/svn_prop.py Tue Oct 16 15:55:00 2012
@@ -1,8 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2005-2009 Edgewall Software
-# Copyright (C) 2005 Christopher Lenz <cmlenz@gmx.de>
-# Copyright (C) 2005-2007 Christian Boos <cboos@neuf.fr>
+# Copyright (C) 2012 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -12,391 +10,10 @@
 # This software consists of voluntary contributions made by many
 # individuals. For the exact contribution history, see the revision
 # history and logs, available at http://trac.edgewall.org/log/.
-#
-# Author: Christopher Lenz <cmlenz@gmx.de>
-#         Christian Boos <cboos@neuf.fr>
-
-import posixpath
-
-from genshi.builder import tag
-
-from trac.config import ConfigSection
-from trac.core import *
-from trac.versioncontrol.api import NoSuchNode, RepositoryManager
-from trac.versioncontrol.svn_fs import _path_within_scope
-from trac.versioncontrol.web_ui.browser import IPropertyRenderer
-from trac.versioncontrol.web_ui.changeset import IPropertyDiffRenderer
-from trac.util import Ranges, to_ranges
-from trac.util.translation import _, tag_
-
-
-class SubversionPropertyRenderer(Component):
-
-    implements(IPropertyRenderer)
-
-    svn_externals_section = ConfigSection('svn:externals',
-        """The TracBrowser for Subversion can interpret the `svn:externals`
-        property of folders. By default, it only turns the URLs into links as
-        Trac can't browse remote repositories.
-
-        However, if you have another Trac instance (or an other repository
-        browser like [http://www.viewvc.org/ ViewVC]) configured to browse the
-        target repository, then you can instruct Trac which other repository
-        browser to use for which external URL. This mapping is done in the
-        `[svn:externals]` section of the TracIni.
-        
-        Example:
-        {{{
-        [svn:externals]
-        1 = svn://server/repos1                       http://trac/proj1/browser/$path?rev=$rev
-        2 = svn://server/repos2                       http://trac/proj2/browser/$path?rev=$rev
-        3 = http://theirserver.org/svn/eng-soft       http://ourserver/viewvc/svn/$path/?pathrev=25914
-        4 = svn://anotherserver.com/tools_repository  http://ourserver/tracs/tools/browser/$path?rev=$rev
-        }}}
-        With the above, the
-        `svn://anotherserver.com/tools_repository/tags/1.1/tools` external will
-        be mapped to `http://ourserver/tracs/tools/browser/tags/1.1/tools?rev=`
-        (and `rev` will be set to the appropriate revision number if the
-        external additionally specifies a revision, see the
-        [http://svnbook.red-bean.com/en/1.4/svn.advanced.externals.html SVN Book on externals]
-        for more details).
-        
-        Note that the number used as a key in the above section is purely used
-        as a place holder, as the URLs themselves can't be used as a key due to
-        various limitations in the configuration file parser.
-        
-        Finally, the relative URLs introduced in
-        [http://subversion.apache.org/docs/release-notes/1.5.html#externals Subversion 1.5]
-        are not yet supported.
-
-        (''since 0.11'')""")
-
-    def __init__(self):
-        self._externals_map = {}
-
-    # IPropertyRenderer methods
-
-    def match_property(self, name, mode):
-        if name in ('svn:externals', 'svn:needs-lock'):
-            return 4
-        return 2 if name in ('svn:mergeinfo', 'svnmerge-blocked',
-                             'svnmerge-integrated') else 0
-    
-    def render_property(self, name, mode, context, props):
-        if name == 'svn:externals':
-            return self._render_externals(props[name])
-        elif name == 'svn:needs-lock':
-            return self._render_needslock(context)
-        elif name == 'svn:mergeinfo' or name.startswith('svnmerge-'):
-            return self._render_mergeinfo(name, mode, context, props)
-
-    def _render_externals(self, prop):
-        if not self._externals_map:
-            for dummykey, value in self.svn_externals_section.options():
-                value = value.split()
-                if len(value) != 2:
-                    self.log.warn("svn:externals entry %s doesn't contain "
-                            "a space-separated key value pair, skipping.", 
-                            dummykey)
-                    continue
-                key, value = value
-                self._externals_map[key] = value.replace('%', '%%') \
-                                           .replace('$path', '%(path)s') \
-                                           .replace('$rev', '%(rev)s')
-        externals = []
-        for external in prop.splitlines():
-            elements = external.split()
-            if not elements:
-                continue
-            localpath, rev, url = elements[0], '', elements[-1]
-            if localpath.startswith('#'):
-                externals.append((external, None, None, None, None))
-                continue
-            if len(elements) == 3:
-                rev = elements[1]
-                rev = rev.replace('-r', '')
-            # retrieve a matching entry in the externals map
-            prefix = []
-            base_url = url
-            while base_url:
-                if base_url in self._externals_map or base_url == u'/':
-                    break
-                base_url, pref = posixpath.split(base_url)
-                prefix.append(pref)
-            href = self._externals_map.get(base_url)
-            revstr = ' at revision ' + rev if rev else ''
-            if not href and (url.startswith('http://') or 
-                             url.startswith('https://')):
-                href = url.replace('%', '%%')
-            if href:
-                remotepath = ''
-                if prefix:
-                    remotepath = posixpath.join(*reversed(prefix))
-                externals.append((localpath, revstr, base_url, remotepath,
-                                  href % {'path': remotepath, 'rev': rev}))
-            else:
-                externals.append((localpath, revstr, url, None, None))
-        externals_data = []
-        for localpath, rev, url, remotepath, href in externals:
-            label = localpath
-            if url is None:
-                title = ''
-            elif href:
-                if url:
-                    url = ' in ' + url
-                label += rev + url
-                title = ''.join((remotepath, rev, url))
-            else:
-                title = _('No svn:externals configured in trac.ini')
-            externals_data.append((label, href, title))
-        return tag.ul([tag.li(tag.a(label, href=href, title=title))
-                       for label, href, title in externals_data])
-
-    def _render_needslock(self, context):
-        return tag.img(src=context.href.chrome('common/lock-locked.png'),
-                       alt="needs lock", title="needs lock")
-
-    def _render_mergeinfo(self, name, mode, context, props):
-        rows = []
-        for row in props[name].splitlines():
-            try:
-                (path, revs) = row.rsplit(':', 1)
-                rows.append([tag.td(path),
-                             tag.td(revs.replace(',', u',\u200b'))])
-            except ValueError:
-                rows.append(tag.td(row, colspan=2))
-        return tag.table(tag.tbody([tag.tr(row) for row in rows]),
-                         class_='props')
-
-
-class SubversionMergePropertyRenderer(Component):
-    implements(IPropertyRenderer)
-
-    # IPropertyRenderer methods
-
-    def match_property(self, name, mode):
-        return 4 if name in ('svn:mergeinfo', 'svnmerge-blocked',
-                             'svnmerge-integrated') else 0
-    
-    def render_property(self, name, mode, context, props):
-        """Parse svn:mergeinfo and svnmerge-* properties, converting branch
-        names to links and providing links to the revision log for merged
-        and eligible revisions.
-        """
-        has_eligible = name in ('svnmerge-integrated', 'svn:mergeinfo')
-        revs_label = _('blocked') if name.endswith('blocked') else _('merged')
-        revs_cols = 2 if has_eligible else None
-        reponame = context.resource.parent.id
-        target_path = context.resource.id
-        repos = RepositoryManager(self.env).get_repository(reponame)
-        target_rev = context.resource.version
-        if has_eligible:
-            node = repos.get_node(target_path, target_rev)
-            branch_starts = {}
-            for path, rev in node.get_copy_ancestry(): 
-                if path not in branch_starts:
-                    branch_starts[path] = rev + 1
-        rows = []
-        if name.startswith('svnmerge-'):
-            sources = props[name].split()
-        else:
-            sources = props[name].splitlines()
-        for line in sources:
-            path, revs = line.split(':', 1)
-            spath = _path_within_scope(repos.scope, path)
-            if spath is None:
-                continue
-            revs = revs.strip()
-            inheritable, non_inheritable = _partition_inheritable(revs)
-            revs = ','.join(inheritable)
-            deleted = False
-            try:
-                node = repos.get_node(spath, target_rev)
-                resource = context.resource.parent.child('source', spath)
-                if 'LOG_VIEW' in context.perm(resource):
-                    row = [_get_source_link(spath, context),
-                           _get_revs_link(revs_label, context, spath, revs)]
-                    if non_inheritable:
-                        non_inheritable = ','.join(non_inheritable)
-                        row.append(_get_revs_link(_('non-inheritable'), context,
-                                                  spath, non_inheritable,
-                                                  _('merged on the directory '
-                                                    'itself but not below')))
-                    if has_eligible:
-                        first_rev = branch_starts.get(spath)
-                        if not first_rev:
-                            first_rev = node.get_branch_origin()
-                        eligible = set(xrange(first_rev or 1, target_rev + 1))
-                        eligible -= set(Ranges(revs))
-                        blocked = _get_blocked_revs(props, name, spath)
-                        if blocked:
-                            eligible -= set(Ranges(blocked))
-                        if eligible:
-                            nrevs = repos._get_node_revs(spath, max(eligible),
-                                                         min(eligible))
-                            eligible &= set(nrevs)
-                        eligible = to_ranges(eligible)
-                        row.append(_get_revs_link(_('eligible'), context,
-                                                  spath, eligible))
-                    rows.append((False, spath, [tag.td(each) for each in row]))
-                    continue
-            except NoSuchNode:
-                deleted = True
-            revs = revs.replace(',', u',\u200b')
-            rows.append((deleted, spath,
-                         [tag.td('/' + spath),
-                          tag.td(revs, colspan=revs_cols)]))
-        if not rows:
-            return None
-        rows.sort()
-        has_deleted = rows[-1][0] if rows else None
-        return tag(has_deleted and tag.a(_('(toggle deleted branches)'),
-                                         class_='trac-toggledeleted',
-                                         href='#'),
-                   tag.table(tag.tbody(
-                       [tag.tr(row, class_='trac-deleted' if deleted else None)
-                        for deleted, spath, row in rows]), class_='props'))
-
-
-def _partition_inheritable(revs):
-    """Non-inheritable revision ranges are marked with a trailing '*'."""
-    inheritable, non_inheritable = [], []           
-    for r in revs.split(','):
-        if r and r[-1] == '*':
-            non_inheritable.append(r[:-1])
-        else:
-            inheritable.append(r)
-    return inheritable, non_inheritable
-
-def _get_blocked_revs(props, name, path):
-    """Return the revisions blocked from merging for the given property
-    name and path.
-    """
-    if name == 'svnmerge-integrated':
-        prop = props.get('svnmerge-blocked', '')
-    else:
-        return ""
-    for line in prop.splitlines():
-        try:
-            p, revs = line.split(':', 1)
-            if p.strip('/') == path:
-                return revs
-        except Exception:
-            pass
-    return ""
-
-def _get_source_link(spath, context):
-    """Return a link to a merge source."""
-    reponame = context.resource.parent.id
-    return tag.a('/' + spath, title=_('View merge source'),
-                 href=context.href.browser(reponame or None, spath,
-                                           rev=context.resource.version))
-
-def _get_revs_link(label, context, spath, revs, title=None):
-    """Return a link to the revision log when more than one revision is
-    given, to the revision itself for a single revision, or a `<span>`
-    with "no revision" for none.
-    """
-    reponame = context.resource.parent.id
-    if not revs:
-        return tag.span(label, title=_('No revisions'))
-    elif ',' in revs or '-' in revs:
-        revs_href = context.href.log(reponame or None, spath, revs=revs)
-    else:
-        revs_href = context.href.changeset(revs, reponame or None, spath)
-    revs = revs.replace(',', ', ')
-    if title:
-        title = _("%(title)s: %(revs)s", title=title, revs=revs)
-    else:
-        title = revs
-    return tag.a(label, title=title, href=revs_href)
-
-
-class SubversionMergePropertyDiffRenderer(Component):
-    implements(IPropertyDiffRenderer)
-
-    # IPropertyDiffRenderer methods
 
-    def match_property_diff(self, name):
-        return 4 if name in ('svn:mergeinfo', 'svnmerge-blocked',
-                             'svnmerge-integrated') else 0
+from trac.util import import_namespace
+import_namespace(globals(), 'tracopt.versioncontrol.svn.svn_prop')
 
-    def render_property_diff(self, name, old_context, old_props,
-                             new_context, new_props, options):
-        # Build 5 columns table showing modifications on merge sources
-        # || source || added || removed || added (ni) || removed (ni) ||
-        # || source || removed                                        ||
-        rm = RepositoryManager(self.env)
-        repos = rm.get_repository(old_context.resource.parent.id)
-        def parse_sources(props):
-            sources = {}
-            for line in props[name].splitlines():
-                path, revs = line.split(':', 1)
-                spath = _path_within_scope(repos.scope, path)
-                if spath is not None:
-                    inheritable, non_inheritable = _partition_inheritable(revs)
-                    sources[spath] = (set(Ranges(inheritable)),
-                                      set(Ranges(non_inheritable)))
-            return sources
-        old_sources = parse_sources(old_props)
-        new_sources = parse_sources(new_props)
-        # Go through new sources, detect modified ones or added ones
-        blocked = name.endswith('blocked')
-        added_label = [_("merged: "), _("blocked: ")][blocked]
-        removed_label = [_("reverse-merged: "), _("un-blocked: ")][blocked]
-        added_ni_label = _("marked as non-inheritable: ")
-        removed_ni_label = _("unmarked as non-inheritable: ")
-        def revs_link(revs, context):
-            if revs:
-                revs = to_ranges(revs)
-                return _get_revs_link(revs.replace(',', u',\u200b'),
-                                      context, spath, revs)
-        modified_sources = []
-        for spath, (new_revs, new_revs_ni) in new_sources.iteritems():
-            if spath in old_sources:
-                (old_revs, old_revs_ni), status = old_sources.pop(spath), None
-            else:
-                old_revs = old_revs_ni = set()
-                status = _(' (added)')
-            added = new_revs - old_revs
-            removed = old_revs - new_revs
-            added_ni = new_revs_ni - old_revs_ni
-            removed_ni = old_revs_ni - new_revs_ni
-            try:
-                all_revs = set(repos._get_node_revs(spath))
-                # TODO: also pass first_rev here, for getting smaller a set
-                #       (this is an optmization fix, result is already correct)
-                added &= all_revs
-                removed &= all_revs
-                added_ni &= all_revs
-                removed_ni &= all_revs
-            except NoSuchNode:
-                pass
-            if added or removed:
-                modified_sources.append((
-                    spath, [_get_source_link(spath, new_context), status],
-                    added and tag(added_label, revs_link(added, new_context)),
-                    removed and tag(removed_label,
-                                    revs_link(removed, old_context)),
-                    added_ni and tag(added_ni_label, 
-                                     revs_link(added_ni, new_context)),
-                    removed_ni and tag(removed_ni_label,
-                                       revs_link(removed_ni, old_context))
-                    ))
-        # Go through remaining old sources, those were deleted
-        removed_sources = []
-        for spath, old_revs in old_sources.iteritems():
-            removed_sources.append((spath,
-                                    _get_source_link(spath, old_context)))
-        if modified_sources or removed_sources:
-            modified_sources.sort()
-            removed_sources.sort()
-            changes = tag.table(tag.tbody(
-                [tag.tr(tag.td(c) for c in cols[1:]) 
-                 for cols in modified_sources],
-                [tag.tr(tag.td(src), tag.td(_('removed'), colspan=4))
-                 for spath, src in removed_sources]), class_='props')
-        else:
-            changes = tag.em(_(' (with no actual effect on merging)'))
-        return tag.li(tag_('Property %(prop)s changed', prop=tag.strong(name)),
-                      changes)
+# This module is a stub provided for backward compatibility. The svn_prop
+# module has been moved to tracopt.versioncontrol.svn. Please update your
+# code to use the new location.

Modified: incubator/bloodhound/vendor/trac/current/trac/versioncontrol/templates/admin_repositories.html
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/versioncontrol/templates/admin_repositories.html?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/versioncontrol/templates/admin_repositories.html (original)
+++ incubator/bloodhound/vendor/trac/current/trac/versioncontrol/templates/admin_repositories.html Tue Oct 16 15:55:00 2012
@@ -10,12 +10,12 @@
     <title>Repositories</title>
   </head>
 
-  <body>
+  <body py:with="sorted_repos = sorted(repositories.iteritems(), key=lambda item: item[0].lower())">
     <h2>Manage Repositories</h2>
 
-    <py:def function="type_field(editable, selected=None)">
+    <py:def function="type_field(editable, multiline=False, selected=None)">
       <div class="field">
-        <label>Type:<br/>
+        <label>Type:<br py:if="multiline"/>
           <select size="1" id="trac-type" name="type" disabled="${not editable or None}">
             <option py:for="type in types" value="$type" selected="${type == selected or None}">${type or _('(default)')}</option>
             <option py:if="selected and selected not in types" selected="selected">$selected</option>
@@ -25,11 +25,11 @@
       </div>
     </py:def>
 
-    <py:def function="alias_field(editable, selected=None)">
+    <py:def function="alias_field(editable, multiline=False, selected=None)">
       <div class="field">
-        <label>Repository:<br/>
+        <label>Repository:<br py:if="multiline"/>
           <select size="1" id="trac-repository" name="alias" disabled="${not editable or None}">
-            <option py:for="(reponame, info) in sorted(repositories.iteritems())" py:if="not info.alias"
+            <option py:for="(reponame, info) in sorted_repos" py:if="not info.alias"
                     value="$info.name" selected="${info.name == selected or None}">${info.name or _('(default)')}</option>
             <option py:if="selected is not None and selected not in repositories" selected="selected">$selected</option>
           </select>
@@ -51,10 +51,10 @@
           </div>
           <py:choose>
             <py:when test="'alias' in info">
-              ${alias_field(info.editable, info.alias)}
+              ${alias_field(info.editable, True, info.alias)}
             </py:when>
             <py:otherwise>
-              ${type_field(info.editable, info.type)}
+              ${type_field(info.editable, True, info.type)}
               <div class="field">
                 <label>Directory:<br/><input type="text" name="dir" size="48" value="$info.dir" readonly="$readonly"/></label>
               </div>
@@ -69,7 +69,7 @@
             </label>
           </div>
           <div class="field">
-            <fieldset class="iefix">
+            <fieldset>
               <label for="description" i18n:msg="">
                 Description (you may use <a tabindex="42" href="${href.wiki('WikiFormatting')}">WikiFormatting</a> here):
               </label>
@@ -92,11 +92,11 @@ $info.description</textarea>
           <fieldset>
             <legend>Add Repository:</legend>
             <div class="field">
-              <label>Name:<br/><input type="text" name="name"/></label>
+              <label>Name: <input type="text" name="name"/></label>
             </div>
             ${type_field(True)}
             <div class="field">
-              <label>Directory:<br/><input type="text" name="dir"/></label>
+              <label>Directory: <input type="text" name="dir"/></label>
             </div>
             <div class="buttons">
               <input type="submit" name="add_repos" value="${_('Add')}"/>
@@ -109,7 +109,7 @@ $info.description</textarea>
           <fieldset>
             <legend>Add Alias:</legend>
             <div class="field">
-              <label>Name:<br/><input type="text" name="name"/></label>
+              <label>Name: <input type="text" name="name"/></label>
             </div>
             ${alias_field(True)}
             <div class="buttons">
@@ -126,7 +126,7 @@ $info.description</textarea>
               </tr>
             </thead>
             <tbody>
-              <tr py:for="(reponame, info) in sorted(repositories.iteritems())">
+              <tr py:for="(reponame, info) in sorted_repos">
                 <td class="sel"><input py:if="info.editable" type="checkbox" name="sel" value="$info.name"/></td>
                 <td class="name">
                   <a href="${panel_href(info.name or '(default)')}">${info.name or _('(default)')}</a>

Modified: incubator/bloodhound/vendor/trac/current/trac/versioncontrol/templates/browser.html
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/versioncontrol/templates/browser.html?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/versioncontrol/templates/browser.html (original)
+++ incubator/bloodhound/vendor/trac/current/trac/versioncontrol/templates/browser.html Tue Oct 16 15:55:00 2012
@@ -207,11 +207,6 @@
         <xi:include href="preview_file.html" py:with="preview = file.preview"/>
       </div>
 
-      <div id="help" i18n:msg="">
-        <strong>Note:</strong> See <a href="${href.wiki('TracBrowser')}">TracBrowser</a>
-        for help on using the repository browser.
-      </div>
-
       <div id="anydiff">
         <form action="${href.diff()}" method="get">
           <div class="buttons">
@@ -224,6 +219,11 @@
         </form>
       </div>
 
+      <div id="help" i18n:msg="">
+        <strong>Note:</strong> See <a href="${href.wiki('TracBrowser')}">TracBrowser</a>
+        for help on using the repository browser.
+      </div>
+
     </div>
   </body>
 </html>

Modified: incubator/bloodhound/vendor/trac/current/trac/versioncontrol/tests/__init__.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/versioncontrol/tests/__init__.py?rev=1398858&r1=1398857&r2=1398858&view=diff
==============================================================================
--- incubator/bloodhound/vendor/trac/current/trac/versioncontrol/tests/__init__.py (original)
+++ incubator/bloodhound/vendor/trac/current/trac/versioncontrol/tests/__init__.py Tue Oct 16 15:55:00 2012
@@ -1,6 +1,6 @@
 import unittest
 
-from trac.versioncontrol.tests import cache, diff, svn_authz, svn_fs, api
+from trac.versioncontrol.tests import cache, diff, svn_authz, api
 from trac.versioncontrol.tests.functional import functionalSuite
 
 def suite():
@@ -9,7 +9,6 @@ def suite():
     suite.addTest(cache.suite())
     suite.addTest(diff.suite())
     suite.addTest(svn_authz.suite())
-    suite.addTest(svn_fs.suite())
     suite.addTest(api.suite())
     return suite
 



Mime
View raw message