Index: trunk/contrib/make_status.py
===================================================================
--- trunk/contrib/make_status.py (revision 17537)
+++ trunk/contrib/make_status.py (revision 17560)
@@ -22,7 +22,5 @@
return '%d.%d.%d' % version + str(core.SVN_VER_TAG, 'utf-8')
-
def _pytidylib_version():
- import pkg_resources
version = pkg_resources.get_distribution('pytidylib').version
try:
@@ -42,4 +40,7 @@
return '%s (%s)' % (version, info) if info else version
+def _pysqlite3_version():
+ return pkg_resources.get_distribution('pysqlite3').version
+
PACKAGES = [
@@ -52,6 +53,6 @@
("sqlite3", ('sqlite3.version',
'sqlite3.sqlite_version')),
- ("PySqlite", ('pysqlite2.dbapi2.version',
- 'pysqlite2.dbapi2.sqlite_version')),
+ ("PySqlite3", ('__main__._pysqlite3_version()',
+ 'pysqlite3.dbapi2.sqlite_version')),
("PyMySQL", 'pymysql.__version__'),
("Psycopg2", 'psycopg2.__version__'),
Index: trunk/contrib/trac-pre-commit-hook
===================================================================
--- trunk/contrib/trac-pre-commit-hook (revision 17537)
+++ trunk/contrib/trac-pre-commit-hook (revision 17560)
@@ -26,6 +26,4 @@
# /usr/bin/python /some/path/trac-pre-commit-hook "$TRAC_ENV" "$LOG" || exit 1
#
-
-from __future__ import print_function
import os
Index: trunk/setup.cfg
===================================================================
Index: trunk/trac/__init__.py
===================================================================
--- trunk/trac/__init__.py (revision 17537)
+++ trunk/trac/__init__.py (revision 17560)
@@ -17,3 +17,3 @@
__version__ = get_distribution('Trac').version
except DistributionNotFound:
- __version__ = '1.5.3'
+ __version__ = '1.5.4'
Index: trunk/trac/db/sqlite_backend.py
===================================================================
--- trunk/trac/db/sqlite_backend.py (revision 17537)
+++ trunk/trac/db/sqlite_backend.py (revision 17560)
@@ -35,5 +35,5 @@
try:
- import pysqlite2.dbapi2 as sqlite
+ import pysqlite3.dbapi2 as sqlite
except ImportError:
import sqlite3 as sqlite
@@ -46,5 +46,4 @@
% pysqlite_version)
min_sqlite_version = (3, 0, 0)
-min_pysqlite_version = (2, 6, 0) # version provided by Python 2.7
@@ -171,7 +170,4 @@
version=sqlite_version_string,
min_version='%d.%d.%d' % min_sqlite_version)
- elif pysqlite_version < min_pysqlite_version:
- self.error = _("Need at least PySqlite %(version)s or higher",
- version='%d.%d.%d' % min_pysqlite_version)
yield 'sqlite', -1 if self.error else 1
Index: trunk/trac/htdocs/js/wiki.js
===================================================================
--- trunk/trac/htdocs/js/wiki.js (revision 17537)
+++ trunk/trac/htdocs/js/wiki.js (revision 17560)
@@ -5,4 +5,6 @@
window.wikiColumn = function($wikipage) {
+ if ($wikipage.length === 0)
+ return;
var $content = $("#content");
$("").on("click", function () {
Index: trunk/trac/ticket/templates/report_view.html
===================================================================
--- trunk/trac/ticket/templates/report_view.html (revision 17537)
+++ trunk/trac/ticket/templates/report_view.html (revision 17560)
@@ -163,4 +163,5 @@
# if loop.first:
+ # set header_group, header = None, None
# set column_headers
# for header_group in header_groups:
Index: trunk/trac/util/html.py
===================================================================
--- trunk/trac/util/html.py (revision 17537)
+++ trunk/trac/util/html.py (revision 17560)
@@ -25,5 +25,5 @@
from html.parser import HTMLParser
-from markupsafe import Markup, escape as escape_quotes
+from markupsafe import Markup, escape as escape_quotes, soft_unicode
try:
Index: trunk/trac/util/presentation.py
===================================================================
--- trunk/trac/util/presentation.py (revision 17537)
+++ trunk/trac/util/presentation.py (revision 17560)
@@ -22,11 +22,11 @@
import re
-from jinja2 import Markup, Undefined, contextfilter, evalcontextfilter
+from jinja2 import Undefined, contextfilter, evalcontextfilter
from jinja2.filters import make_attrgetter
-from jinja2.utils import soft_unicode
from trac.core import TracError
from .datefmt import to_utimestamp, utc
-from .html import Fragment, classes, html_attribute, styles, tag
+from .html import (Fragment, Markup, classes, html_attribute, soft_unicode,
+ styles, tag)
from .text import javascript_quote
Index: trunk/trac/util/text.py
===================================================================
--- trunk/trac/util/text.py (revision 17537)
+++ trunk/trac/util/text.py (revision 17560)
@@ -23,4 +23,5 @@
import locale
import os
+import pkg_resources
import re
import sys
@@ -43,4 +44,9 @@
# -- Jinja2
+
+_jinja2_ver = pkg_resources.parse_version(jinja2.__version__)
+_jinja2_exts = ['jinja2.ext.do', 'jinja2.ext.i18n']
+if _jinja2_ver < pkg_resources.parse_version('3'):
+ _jinja2_exts.append('jinja2.ext.with_')
def jinja2env(**kwargs):
@@ -66,5 +72,5 @@
trim_blocks=True,
lstrip_blocks=True,
- extensions=['jinja2.ext.do', 'jinja2.ext.i18n', 'jinja2.ext.with_'],
+ extensions=list(_jinja2_exts),
finalize=filterout_none,
autoescape=autoescape_extensions,
Index: trunk/trac/web/_fcgi.py
===================================================================
--- trunk/trac/web/_fcgi.py (revision 17537)
+++ trunk/trac/web/_fcgi.py (revision 17560)
@@ -40,26 +40,16 @@
__version__ = '$Revision: 2025 $'
+import _thread
+import codecs
+import errno
import io
+import os
+import select
+import signal
+import socket
+import struct
import sys
-import os
-import signal
-import struct
-import select
-import socket
-import errno
+import threading
import traceback
-
-try:
- import thread
- import threading
- thread_available = True
-except ImportError:
- import dummy_thread as thread
- import dummy_threading as threading
- thread_available = False
-
-# Apparently 2.3 doesn't define SHUT_WR? Assume it is 1 in this case.
-if not hasattr(socket, 'SHUT_WR'):
- socket.SHUT_WR = 1
__all__ = ['WSGIServer']
@@ -138,5 +128,5 @@
self._shrinkThreshold = conn.server.inputStreamShrinkThreshold
- self._buf = ''
+ self._buf = b''
self._bufList = []
self._pos = 0 # Current read position.
@@ -160,5 +150,5 @@
def read(self, n=-1):
if self._pos == self._avail and self._eof:
- return ''
+ return b''
while True:
if n < 0 or (self._avail - self._pos) < n:
@@ -177,5 +167,5 @@
# Merge buffer list, if necessary.
if self._bufList:
- self._buf += ''.join(self._bufList)
+ self._buf += _bytes_join(self._bufList)
self._bufList = []
r = self._buf[self._pos:newPos]
@@ -186,9 +176,9 @@
def readline(self, length=None):
if self._pos == self._avail and self._eof:
- return ''
+ return b''
while True:
# Unfortunately, we need to merge the buffer list early.
if self._bufList:
- self._buf += ''.join(self._bufList)
+ self._buf += _bytes_join(self._bufList)
self._bufList = []
# Find newline.
@@ -317,4 +307,5 @@
def write(self, data):
assert not self.closed
+ assert type(data) is bytes
if not data:
@@ -337,5 +328,5 @@
# Only need to flush if this OutputStream is actually buffered.
if self._buffered:
- data = ''.join(self._bufList)
+ data = _bytes_join(self._bufList)
self._bufList = []
self._write(data)
@@ -397,22 +388,22 @@
are returned.
"""
- nameLength = ord(s[pos])
- if nameLength & 128:
- nameLength = struct.unpack('!L', s[pos:pos+4])[0] & 0x7fffffff
+ namelen = s[pos]
+ if namelen & 128:
+ namelen = struct.unpack('!L', s[pos:pos+4])[0] & 0x7fffffff
pos += 4
else:
pos += 1
- valueLength = ord(s[pos])
- if valueLength & 128:
- valueLength = struct.unpack('!L', s[pos:pos+4])[0] & 0x7fffffff
+ valuelen = s[pos]
+ if valuelen & 128:
+ valuelen = struct.unpack('!L', s[pos:pos+4])[0] & 0x7fffffff
pos += 4
else:
pos += 1
- name = s[pos:pos+nameLength]
- pos += nameLength
- value = s[pos:pos+valueLength]
- pos += valueLength
+ name = str(s[pos:pos+namelen], 'iso-8859-1')
+ pos += namelen
+ value = str(s[pos:pos+valuelen], 'iso-8859-1')
+ pos += valuelen
return pos, (name, value)
@@ -424,17 +415,25 @@
The encoded string is returned.
"""
- nameLength = len(name)
- if nameLength < 128:
- s = chr(nameLength)
+ name = name.encode('iso-8859-1')
+ value = value.encode('iso-8859-1')
+
+ namelen = len(name)
+ if namelen < 128:
+ namelen = _code2bytes(namelen)
else:
- s = struct.pack('!L', nameLength | 0x80000000)
-
- valueLength = len(value)
- if valueLength < 128:
- s += chr(valueLength)
+ namelen = struct.pack('!L', namelen | 0x80000000)
+
+ valuelen = len(value)
+ if valuelen < 128:
+ valuelen = _code2bytes(valuelen)
else:
- s += struct.pack('!L', valueLength | 0x80000000)
-
- return s + name + value
+ valuelen = struct.pack('!L', valuelen | 0x80000000)
+
+ return namelen + valuelen + name + value
+
+_bytes_join = b''.join
+_str_join = ''.join
+_code2bytes = lambda code: b'%c' % code
+_utf8_writer = lambda f: codecs.getwriter('utf-8')(f)
class Record(object):
@@ -450,5 +449,5 @@
self.contentLength = 0
self.paddingLength = 0
- self.contentData = ''
+ self.contentData = b''
@staticmethod
@@ -464,5 +463,5 @@
data = sock.recv(length)
except socket.error as e:
- if e[0] == errno.EAGAIN:
+ if e.errno == errno.EAGAIN:
select.select([sock], [], [])
continue
@@ -475,5 +474,5 @@
recvLen += dataLen
length -= dataLen
- return ''.join(dataList), recvLen
+ return _bytes_join(dataList), recvLen
def read(self, sock):
@@ -516,4 +515,5 @@
Writes data to a socket and does not return until all the data is sent.
"""
+ assert type(data) is bytes
length = len(data)
while length:
@@ -521,5 +521,5 @@
sent = sock.send(data)
except socket.error as e:
- if e[0] == errno.EAGAIN:
+ if e.errno == errno.EAGAIN:
select.select([], [sock], [])
continue
@@ -545,5 +545,5 @@
self._sendall(sock, self.contentData)
if self.paddingLength:
- self._sendall(sock, '\x00'*self.paddingLength)
+ self._sendall(sock, b'\x00' * self.paddingLength)
class Request(object):
@@ -563,5 +563,6 @@
self.stdin = inputStreamClass(conn)
self.stdout = OutputStream(conn, self, FCGI_STDOUT)
- self.stderr = OutputStream(conn, self, FCGI_STDERR, buffered=True)
+ self.stderr = _utf8_writer(OutputStream(conn, self, FCGI_STDERR,
+ buffered=True))
self.data = inputStreamClass(conn)
@@ -585,5 +586,5 @@
self._end(appStatus, protocolStatus)
except socket.error as e:
- if e[0] != errno.EPIPE:
+ if e.errno != errno.EPIPE:
raise
@@ -645,6 +646,6 @@
try:
while True:
- r, w, e = select.select([self._sock], [], [])
- if not r or not self._sock.recv(1024):
+ rlist, wlist, xlist = select.select([self._sock], [], [])
+ if not rlist or not self._sock.recv(1024):
break
except:
@@ -660,6 +661,6 @@
except EOFError:
break
- except (select.error, socket.error) as e:
- if e[0] == errno.EBADF: # Socket was closed by Request.
+ except select.error as e:
+ if e.errno == errno.EBADF: # Socket was closed by Request.
break
raise
@@ -675,10 +676,10 @@
while self._keepGoing:
try:
- r, w, e = select.select([self._sock], [], [], 1.0)
+ rlist, wlist, xlist = select.select([self._sock], [], [], 1.0)
except ValueError:
# Sigh. ValueError gets thrown sometimes when passing select
# a closed socket.
raise EOFError
- if r: break
+ if rlist: break
if not self._keepGoing:
return
@@ -876,5 +877,5 @@
def _start_request(self, req):
- thread.start_new_thread(req.run, ())
+ _thread.start_new_thread(req.run, ())
def _do_params(self, inrec):
@@ -948,31 +949,22 @@
self.handler = handler
self.maxwrite = maxwrite
- if thread_available:
- try:
- import resource
- # Attempt to glean the maximum number of connections
- # from the OS.
- maxConns = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
- except (ImportError, AttributeError):
- maxConns = 100 # Just some made up number.
- maxReqs = maxConns
- if multiplexed:
- self._connectionClass = MultiplexedConnection
- maxReqs *= 5 # Another made up number.
- else:
- self._connectionClass = Connection
- self.capability = {
- FCGI_MAX_CONNS: maxConns,
- FCGI_MAX_REQS: maxReqs,
- FCGI_MPXS_CONNS: multiplexed and 1 or 0
- }
+ try:
+ import resource
+ # Attempt to glean the maximum number of connections
+ # from the OS.
+ maxConns = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
+ except (ImportError, AttributeError):
+ maxConns = 100 # Just some made up number.
+ maxReqs = maxConns
+ if multiplexed:
+ self._connectionClass = MultiplexedConnection
+ maxReqs *= 5 # Another made up number.
else:
self._connectionClass = Connection
- self.capability = {
- # If threads aren't available, these are pretty much correct.
- FCGI_MAX_CONNS: 1,
- FCGI_MAX_REQS: 1,
- FCGI_MPXS_CONNS: 0
- }
+ self.capability = {
+ FCGI_MAX_CONNS: maxConns,
+ FCGI_MAX_REQS: maxReqs,
+ FCGI_MPXS_CONNS: 1 if multiplexed else 0,
+ }
self._bindAddress = bindAddress
self._umask = umask
@@ -987,8 +979,8 @@
sock.getpeername()
except socket.error as e:
- if e[0] == errno.ENOTSOCK:
+ if e.errno == errno.ENOTSOCK:
# Not a socket, assume CGI context.
isFCGI = False
- elif e[0] != errno.ENOTCONN:
+ elif e.errno != errno.ENOTCONN:
raise
@@ -1072,15 +1064,15 @@
while self._keepGoing:
try:
- r, w, e = select.select([sock], [], [], timeout)
+ rlist, wlist, xlist = select.select([sock], [], [], timeout)
except select.error as e:
- if e[0] == errno.EINTR:
+ if e.errno == errno.EINTR:
continue
raise
- if r:
+ if rlist:
try:
clientSock, addr = sock.accept()
except socket.error as e:
- if e[0] in (errno.EINTR, errno.EAGAIN):
+ if e.errno in (errno.EINTR, errno.EAGAIN):
continue
raise
@@ -1094,5 +1086,5 @@
# messages (either in a new thread or this thread).
conn = self._connectionClass(clientSock, addr, self)
- thread.start_new_thread(conn.run, ())
+ _thread.start_new_thread(conn.run, ())
self._mainloopPeriodic()
@@ -1134,7 +1126,8 @@
should be overridden.
"""
- import cgitb
- req.stdout.write('Content-Type: text/html\r\n\r\n' +
- cgitb.html(sys.exc_info()))
+ out = _utf8_writer(req.stdout)
+ out.write('Content-Type: text/plain; charset=utf-8\r\n\r\n')
+ traceback.print_exc(file=out)
+ out.flush()
class WSGIServer(Server):
@@ -1164,5 +1157,5 @@
# Used to force single-threadedness
- self._app_lock = thread.allocate_lock()
+ self._app_lock = _thread.allocate_lock()
def handler(self, req):
@@ -1175,5 +1168,5 @@
environ.update(self.environ)
- environ['wsgi.version'] = (1,0)
+ environ['wsgi.version'] = (1, 0)
environ['wsgi.input'] = req.stdin
if self._bindAddress is None:
@@ -1183,5 +1176,5 @@
environ['wsgi.errors'] = stderr
environ['wsgi.multithread'] = not isinstance(req, CGIRequest) and \
- thread_available and self.multithreaded
+ self.multithreaded
# Rationale for the following: If started by the web server
# (self._bindAddress is None) in either FastCGI or CGI mode, the
@@ -1207,26 +1200,15 @@
def write(data):
- assert type(data) is str, 'write() argument must be string'
+ assert type(data) is bytes, 'write() argument must be bytes'
assert headers_set, 'write() before start_response()'
if not headers_sent:
- status, responseHeaders = headers_sent[:] = headers_set
- found = False
- for header,value in responseHeaders:
- if header.lower() == 'content-length':
- found = True
- break
- if not found and result is not None:
- try:
- if len(result) == 1:
- responseHeaders.append(('Content-Length',
- str(len(data))))
- except:
- pass
- s = 'Status: %s\r\n' % status
- for header in responseHeaders:
- s += '%s: %s\r\n' % header
- s += '\r\n'
- req.stdout.write(s)
+ status, headers = headers_sent[:] = headers_set
+ def generator():
+ yield 'Status: %s\r\n' % status
+ for header in headers:
+ yield '%s: %s\r\n' % header
+ yield '\r\n'
+ req.stdout.write(_str_join(generator()).encode('iso-8859-1'))
req.stdout.write(data)
@@ -1266,11 +1248,11 @@
write(data)
if not headers_sent:
- write('') # in case body was empty
+ write(b'') # in case body was empty
finally:
if hasattr(result, 'close'):
result.close()
except socket.error as e:
- if e[0] != errno.EPIPE:
- raise # Don't let EPIPE propagate beyond server
+ if e.errno != errno.EPIPE:
+ raise # Don't let EPIPE propagate beyond server
finally:
if not self.multithreaded:
Index: trunk/trac/web/fcgi_frontend.py
===================================================================
--- trunk/trac/web/fcgi_frontend.py (revision 17537)
+++ trunk/trac/web/fcgi_frontend.py (revision 17560)
@@ -27,5 +27,4 @@
use_flup = False
-
class FlupMiddleware(object):
"""Flup doesn't URL unquote the PATH_INFO, so we need to do it."""
@@ -43,8 +42,9 @@
try:
from flup.server.fcgi import WSGIServer
+ except ImportError:
+ use_flup = False
+ else:
params['maxThreads'] = 15
dispatch_request = FlupMiddleware(dispatch_request)
- except ImportError:
- use_flup = False
if not use_flup:
Index: trunk/trac/web/standalone.py
===================================================================
--- trunk/trac/web/standalone.py (revision 17537)
+++ trunk/trac/web/standalone.py (revision 17560)
@@ -345,4 +345,5 @@
certfile=args.certfile,
keyfile=args.keyfile)
+ httpd.environ['HTTPS'] = 'yes'
httpd.serve_forever()
elif args.protocol in ('scgi', 'ajp', 'fcgi'):
Index: trunk/trac/web/templates/deploy_trac.cgi
===================================================================
--- trunk/trac/web/templates/deploy_trac.cgi (revision 17537)
+++ trunk/trac/web/templates/deploy_trac.cgi (revision 17560)
@@ -15,6 +15,4 @@
{##}#
{##}# Author: Jonas Borgström
-
-from __future__ import print_function
try:
Index: trunk/trac/web/templates/deploy_trac.fcgi
===================================================================
--- trunk/trac/web/templates/deploy_trac.fcgi (revision 17537)
+++ trunk/trac/web/templates/deploy_trac.fcgi (revision 17560)
@@ -15,6 +15,4 @@
{##}#
{##}# Author: Jonas Borgström
-
-from __future__ import print_function
try:
@@ -36,14 +34,12 @@
raise
except Exception as e:
- print("Content-Type: text/plain\r\n\r\n", end=' ')
+ print("Content-Type: text/plain", end="\r\n")
+ print("", end="\r\n")
print("Oops...")
- print()
+ print("")
print("Trac detected an internal error:")
- print()
+ print("")
print(e)
- print()
+ print("", flush=True)
import traceback
- import io
- tb = io.Bytes()
- traceback.print_exc(file=tb)
- print(tb.getvalue())
+ traceback.print_exc(file=sys.stdout)
Index: trunk/trac/wiki/tests/functional.py
===================================================================
--- trunk/trac/wiki/tests/functional.py (revision 17537)
+++ trunk/trac/wiki/tests/functional.py (revision 17560)
@@ -234,4 +234,6 @@
self._tester.go_to_wiki(page_name)
tc.submit(formname='modifypage')
+ tc.url('%s/wiki/%s?action=edit' % (self._tester.url, page_name),
+ regexp=False)
tc.find(readonly_checkbox)
tc.formvalue('edit', 'readonly', True)
Index: trunk/tracopt/versioncontrol/git/PyGIT.py
===================================================================
--- trunk/tracopt/versioncontrol/git/PyGIT.py (revision 17537)
+++ trunk/tracopt/versioncontrol/git/PyGIT.py (revision 17560)
@@ -27,5 +27,5 @@
from trac.core import TracBaseError
-from trac.util import terminate
+from trac.util import as_int, terminate
from trac.util.compat import close_fds
from trac.util.datefmt import time_now
@@ -333,34 +333,25 @@
def git_version(git_bin='git'):
GIT_VERSION_MIN_REQUIRED = (1, 5, 6)
- try:
- g = GitCore(git_bin=git_bin)
- [v] = g.version().splitlines()
- version = v.strip().split()[2]
- # 'version' has usually at least 3 numeric version
- # components, e.g.::
- # 1.5.4.2
- # 1.5.4.3.230.g2db511
- # 1.5.4.GIT
-
- def try_int(s):
- try:
- return int(s)
- except ValueError:
- return s
-
- split_version = tuple(map(try_int, version.split(b'.')))
-
- result = {}
- result['v_str'] = version
- result['v_tuple'] = split_version
- result['v_min_tuple'] = GIT_VERSION_MIN_REQUIRED
- result['v_min_str'] = ".".join(map(str, GIT_VERSION_MIN_REQUIRED))
- result['v_compatible'] = split_version >= GIT_VERSION_MIN_REQUIRED
- return result
-
- except Exception as e:
- raise GitError("Could not retrieve GIT version (tried to "
- "execute/parse '%s --version' but got %s)"
- % (git_bin, repr(e)))
+ version = str(GitCore(git_bin=git_bin).version(), 'utf-8')
+ # 'version' should have at least 3 numeric version components:
+ # 1.5.6
+ # 1.5.6.windows.1
+ # 1.5.6.2
+ # 1.5.6.3.230.g2db511
+ # 1.5.6.GIT
+ m = re.match('git version (.*)\n$', version)
+ if not m:
+ raise GitError("Could not retrieve GIT version. "
+ "'%s --version' returned %s"
+ % (git_bin, repr(version)))
+ version_str = m.group(1)
+ version_tuple = tuple(as_int(s, s) for s in version_str.split('.'))
+ return {
+ 'v_str': version_str,
+ 'v_tuple': version_tuple,
+ 'v_min_str': '.'.join(map(str, GIT_VERSION_MIN_REQUIRED)),
+ 'v_min_tuple': GIT_VERSION_MIN_REQUIRED,
+ 'v_compatible': version_tuple >= GIT_VERSION_MIN_REQUIRED,
+ }
def __init__(self, git_dir, log, git_bin='git', git_fs_encoding=None,
Index: trunk/tracopt/versioncontrol/git/tests/PyGIT.py
===================================================================
--- trunk/tracopt/versioncontrol/git/tests/PyGIT.py (revision 17537)
+++ trunk/tracopt/versioncontrol/git/tests/PyGIT.py (revision 17560)
@@ -38,6 +38,11 @@
def test_git_version(self):
v = Storage.git_version()
- self.assertTrue(v)
+ self.assertIsInstance(v, dict)
self.assertTrue(v['v_compatible'])
+ self.assertIsInstance(v['v_str'], str)
+ self.assertGreaterEqual(len(v['v_tuple']), 3)
+ self.assertIsInstance(v['v_tuple'][0], int)
+ self.assertIsInstance(v['v_tuple'][1], int)
+ self.assertIsInstance(v['v_tuple'][2], int)
Index: trunk/tracopt/versioncontrol/svn/svn_fs.py
===================================================================
--- trunk/tracopt/versioncontrol/svn/svn_fs.py (revision 17537)
+++ trunk/tracopt/versioncontrol/svn/svn_fs.py (revision 17560)
@@ -276,5 +276,5 @@
self.fs_ptr = repos.svn_repos_fs(self.repos)
- self.uuid = fs.get_uuid(self.fs_ptr, self.pool)
+ self.uuid = _from_svn(fs.get_uuid(self.fs_ptr, self.pool))
self.base = 'svn:%s:%s' % (self.uuid, root_path)
name = 'svn:%s:%s' % (self.uuid, path)
Index: trunk/tracopt/versioncontrol/svn/tests/svn_fs.py
===================================================================
--- trunk/tracopt/versioncontrol/svn/tests/svn_fs.py (revision 17537)
+++ trunk/tracopt/versioncontrol/svn/tests/svn_fs.py (revision 17560)
@@ -43,4 +43,5 @@
REPOS_PATH = None
REPOS_NAME = 'repo'
+REPOS_UUID = '92ea810a-adf3-0310-b540-bef912dcf5ba'
URL = 'svn://test'
@@ -151,4 +152,10 @@
if td:
return td
+
+ def test_repos_properties(self):
+ self.assertEqual(REPOS_UUID, self.repos.uuid)
+ self.assertEqual('svn:%s:%s' % (REPOS_UUID, REPOS_PATH),
+ self.repos.base)
+ self.assertEqual(self.repos.name, self.repos.base)
def test_invalid_path_raises(self):
@@ -1104,4 +1111,11 @@
class ScopedTests(object):
+ def test_repos_properties(self):
+ self.assertEqual(REPOS_UUID, self.repos.uuid)
+ self.assertEqual('svn:%s:%s' % (REPOS_UUID, REPOS_PATH),
+ self.repos.base)
+ self.assertEqual('svn:%s:%s/tête' % (REPOS_UUID, REPOS_PATH),
+ self.repos.name)
+
def test_repos_normalize_path(self):
self.assertEqual('/', self.repos.normalize_path('/'))
@@ -1591,7 +1605,9 @@
skipped = {
'SvnCachedRepositoryNormalTests': [
+ 'test_repos_properties',
'test_changeset_repos_creation',
],
'SvnCachedRepositoryScopedTests': [
+ 'test_repos_properties',
'test_changeset_repos_creation',
'test_rev_navigation',