Modified: incubator/bloodhound/vendor/trac/current/trac/wiki/tests/formatter.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/wiki/tests/formatter.py?rev=1398858&r1=1398857&r2=1398858&view=diff ============================================================================== --- incubator/bloodhound/vendor/trac/current/trac/wiki/tests/formatter.py (original) +++ incubator/bloodhound/vendor/trac/current/trac/wiki/tests/formatter.py Tue Oct 16 15:55:00 2012 @@ -8,20 +8,14 @@ import unittest try: from unittest.util import safe_repr - unittest.case.safe_repr = lambda obj, short: safe_repr(obj, False) + unittest.case.safe_repr = lambda obj, short=False: safe_repr(obj, False) except ImportError: pass - from datetime import datetime -try: - from babel import Locale -except ImportError: - Locale = None - from trac.core import * -from trac.test import Mock, MockPerm, EnvironmentStub +from trac.test import Mock, MockPerm, EnvironmentStub, locale_en from trac.util.datefmt import utc from trac.util.html import html from trac.util.text import to_unicode @@ -132,7 +126,7 @@ class WikiTestCase(unittest.TestCase): req = Mock(href=Href('/'), abs_href=Href('http://www.example.com/'), authname='anonymous', perm=MockPerm(), tz=utc, args={}, - locale=Locale.parse('en_US') if Locale else None) + locale=locale_en, lc_time=locale_en) if context: if isinstance(context, tuple): context = web_context(req, *context) @@ -184,7 +178,7 @@ class WikiTestCase(unittest.TestCase): """Testing WikiFormatter""" formatter = self.formatter() v = unicode(formatter.generate(**self.generate_opts)) - v = v.replace('\r', '').replace(u'\u200b', '') + v = v.replace('\r', '').replace(u'\u200b', '') # FIXME: keep ZWSP try: self.assertEquals(self.correct, v) except AssertionError, e:
Modified: incubator/bloodhound/vendor/trac/current/trac/wiki/tests/macros.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/wiki/tests/macros.py?rev=1398858&r1=1398857&r2=1398858&view=diff ============================================================================== --- incubator/bloodhound/vendor/trac/current/trac/wiki/tests/macros.py (original) +++ incubator/bloodhound/vendor/trac/current/trac/wiki/tests/macros.py Tue Oct 16 15:55:00 2012 @@ -2,7 +2,8 @@ from datetime import datetime import unittest -from trac.util.datefmt import utc +from trac.test import locale_en +from trac.util.datefmt import format_date, utc from trac.wiki.model import WikiPage from trac.wiki.tests import formatter @@ -88,6 +89,15 @@ IMAGE_MACRO_TEST_CASES = u""" </p> ------------------------------ <a style="padding:0; border:none" href="/wiki/WikiStart"><img src="/browser/%C2%AB%20test%C2%A0%C2%BB?format=raw" alt="/browser/« test »" title="/browser/« test »" /></a> +============================== Strip unicode white-spaces and ZWSPs (#10668) +[[Image(â âsource:« test ».pngã â, nolink)]] +------------------------------ +<p> +<img src="/browser/%C2%AB%20test%C2%A0%C2%BB.png?format=raw" alt="source:« test ».png" title="source:« test ».png" /> +</p> +------------------------------ +<img src="/browser/%C2%AB%20test%C2%A0%C2%BB.png?format=raw" alt="source:« test ».png" title="source:« test ».png" /> +------------------------------ """ # Note: in the <img> src attribute above, the Unicode characters @@ -318,6 +328,58 @@ def titleindex5_setup(tc): ]) +RECENTCHANGES_MACRO_TEST_CASES = u"""" +============================== RecentChanges, group option +[[RecentChanges()]] +[[RecentChanges(group=date)]] +[[RecentChanges(group=none)]] +[[RecentChanges(,2,group=none)]] +[[RecentChanges(Wiki,group=none)]] +[[RecentChanges(Wiki,1,group=none)]] +------------------------------ +<p> +</p><div><h3>%(date)s</h3><ul><li><a href="/wiki/WikiEnd">WikiEnd</a> +</li><li><a href="/wiki/WikiMid">WikiMid</a> +</li><li><a href="/wiki/WikiStart">WikiStart</a> +</li></ul></div><p> +</p><div><h3>%(date)s</h3><ul><li><a href="/wiki/WikiEnd">WikiEnd</a> +</li><li><a href="/wiki/WikiMid">WikiMid</a> +</li><li><a href="/wiki/WikiStart">WikiStart</a> +</li></ul></div><p> +</p><div><ul><li><a href="/wiki/WikiEnd">WikiEnd</a> +</li><li><a href="/wiki/WikiMid">WikiMid</a> +</li><li><a href="/wiki/WikiStart">WikiStart</a> +</li></ul></div><p> +</p><div><ul><li><a href="/wiki/WikiEnd">WikiEnd</a> +</li><li><a href="/wiki/WikiMid">WikiMid</a> +</li></ul></div><p> +</p><div><ul><li><a href="/wiki/WikiEnd">WikiEnd</a> +</li><li><a href="/wiki/WikiMid">WikiMid</a> +</li><li><a href="/wiki/WikiStart">WikiStart</a> +</li></ul></div><p> +</p><div><ul><li><a href="/wiki/WikiEnd">WikiEnd</a> +</li></ul></div><p> +</p> +------------------------------ +""" % {'date': format_date(tzinfo=utc, locale=locale_en)} + +def recentchanges_setup(tc): + def add_pages(tc, names): + for name in names: + now = datetime.now(utc) + w = WikiPage(tc.env) + w.name = name + w.text = '--' + w.save('joe', 'the page ' + name, '::1', now) + add_pages(tc, [ + 'WikiMid', + 'WikiEnd', + ]) + +def recentchanges_teardown(tc): + tc.env.reset_db() + + def suite(): suite = unittest.TestSuite() suite.addTest(formatter.suite(IMAGE_MACRO_TEST_CASES, file=__file__)) @@ -334,6 +396,9 @@ def suite(): suite.addTest(formatter.suite(TITLEINDEX5_MACRO_TEST_CASES, file=__file__, setup=titleindex5_setup, teardown=titleindex_teardown)) + suite.addTest(formatter.suite(RECENTCHANGES_MACRO_TEST_CASES, file=__file__, + setup=recentchanges_setup, + teardown=recentchanges_teardown)) return suite Modified: incubator/bloodhound/vendor/trac/current/trac/wiki/tests/wiki-tests.txt URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/wiki/tests/wiki-tests.txt?rev=1398858&r1=1398857&r2=1398858&view=diff ============================================================================== --- incubator/bloodhound/vendor/trac/current/trac/wiki/tests/wiki-tests.txt (original) +++ incubator/bloodhound/vendor/trac/current/trac/wiki/tests/wiki-tests.txt Tue Oct 16 15:55:00 2012 @@ -412,8 +412,8 @@ http://example.com/img.png?foo=bar </p> ------------------------------ ============================== mailto: links and automatic e-mail detection -Author: mailto:cb...@neuf.fr, -i.e. [mailto:cb...@neuf.fr me] +Author: mailto:cb...@edgewall.org, +i.e. [mailto:cb...@edgewall.org me] joe'b...@site.info, trac+de...@another-site.fr, @@ -422,8 +422,8 @@ T_r+a-c1.23@yet_another-site.edu.au someone@louvre.museum- ------------------------------ <p> -Author: <a class="mail-link" href="mailto:cb...@neuf.fr"><span class="icon"></span>mailto:cb...@neuf.fr</a>, -i.e. <a class="mail-link" href="mailto:cb...@neuf.fr"><span class="icon"></span>me</a> +Author: <a class="mail-link" href="mailto:cb...@edgewall.org"><span class="icon"></span>mailto:cb...@edgewall.org</a>, +i.e. <a class="mail-link" href="mailto:cb...@edgewall.org"><span class="icon"></span>me</a> </p> <p> <a class="mail-link" href="mailto:joe'b...@site.info"><span class="icon"></span>joe'b...@site.info</a>, @@ -503,7 +503,7 @@ unsafe://scheme is not rendered [[link:pl/de|%de]] -i.e. [[mailto:cb...@neuf.fr|me]] +i.e. [[mailto:cb...@edgewall.org|me]] [[th:]] [[th:|Trac Hacks]] @@ -530,7 +530,7 @@ i.e. [[mailto:cb...@neuf.fr|me]] <a class="text resolver" href="/stuff/pl/de">%de</a> </p> <p> -i.e. <a class="mail-link" href="mailto:cb...@neuf.fr"><span class="icon"></span>me</a> +i.e. <a class="mail-link" href="mailto:cb...@edgewall.org"><span class="icon"></span>me</a> </p> <p> <a class="ext-link" href="http://trac-hacks.org/intertrac/" title="Trac Hacks"><span class="icon"></span>th</a> @@ -1578,6 +1578,21 @@ OTOH, the following is a roman numbered Paragraph </p> ------------------------------ +============================== Unicode digits will not start a numbered list + ³. U+00B3 will not start a numbered list. + ੧. U+0A67 will not start a numbered list. + ൬. U+0D6C will not start a numbered list. + â. U+2780 will not start a numbered list. +------------------------------ +<blockquote> +<p> +³. U+00B3 will not start a numbered list. +੧. U+0A67 will not start a numbered list. +൬. U+0D6C will not start a numbered list. +â. U+2780 will not start a numbered list. +</p> +</blockquote> +------------------------------ ============================== Mixed lists multi-line items 1. multi-line numbered list Modified: incubator/bloodhound/vendor/trac/current/trac/wiki/tests/wikisyntax.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/wiki/tests/wikisyntax.py?rev=1398858&r1=1398857&r2=1398858&view=diff ============================================================================== --- incubator/bloodhound/vendor/trac/current/trac/wiki/tests/wikisyntax.py (original) +++ incubator/bloodhound/vendor/trac/current/trac/wiki/tests/wikisyntax.py Tue Oct 16 15:55:00 2012 @@ -322,6 +322,19 @@ This is not a link: x,://localhost This is not a link: x,:<em>localhost </em></p> ------------------------------ +============================== Wiki links with @version using unicode digits +WikiStart@ââ +WikiStart@ââ#heading +[WikiStart@ââ] +[WikiStart@ââ#heading] +------------------------------ +<p> +<a class="wiki" href="/wiki/WikiStart">WikiStart</a>@ââ +<a class="wiki" href="/wiki/WikiStart">WikiStart</a>@ââ#heading +[<a class="wiki" href="/wiki/WikiStart">WikiStart</a>@ââ] +[<a class="wiki" href="/wiki/WikiStart">WikiStart</a>@ââ#heading] +</p> +------------------------------ """ #" Emacs likes it that way better Modified: incubator/bloodhound/vendor/trac/current/trac/wiki/web_ui.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/trac/wiki/web_ui.py?rev=1398858&r1=1398857&r2=1398858&view=diff ============================================================================== --- incubator/bloodhound/vendor/trac/current/trac/wiki/web_ui.py (original) +++ incubator/bloodhound/vendor/trac/current/trac/wiki/web_ui.py Tue Oct 16 15:55:00 2012 @@ -509,10 +509,7 @@ class WikiModule(Component): if 'from_editor' in req.args: sidebyside = req.args.get('sidebyside') or None if sidebyside != prefs['sidebyside']: - if sidebyside: - req.session['wiki_sidebyside'] = '1' - else: - del req.session['wiki_sidebyside'] + req.session.set('wiki_sidebyside', int(bool(sidebyside)), 0) else: sidebyside = prefs['sidebyside'] @@ -523,7 +520,8 @@ class WikiModule(Component): editrows = req.args.get('editrows') if editrows: if editrows != prefs['editrows']: - req.session['wiki_editrows'] = editrows + req.session.set('wiki_editrows', editrows, + defaults['editrows']) else: editrows = prefs['editrows'] Modified: incubator/bloodhound/vendor/trac/current/tracopt/perm/authz_policy.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/tracopt/perm/authz_policy.py?rev=1398858&r1=1398857&r2=1398858&view=diff ============================================================================== --- incubator/bloodhound/vendor/trac/current/tracopt/perm/authz_policy.py (original) +++ incubator/bloodhound/vendor/trac/current/tracopt/perm/authz_policy.py Tue Oct 16 15:55:00 2012 @@ -21,7 +21,6 @@ import os from trac.core import * from trac.config import Option from trac.perm import PermissionSystem, IPermissionPolicy -from trac.util.text import to_unicode ConfigObj = None try: @@ -174,7 +173,7 @@ class AuthzPolicy(Component): def parse_authz(self): self.log.debug('Parsing authz security policy %s', self.get_authz_file()) - self.authz = ConfigObj(self.get_authz_file()) + self.authz = ConfigObj(self.get_authz_file(), encoding='utf8') groups = {} for group, users in self.authz.get('groups', {}).iteritems(): if isinstance(users, basestring): @@ -229,7 +228,7 @@ class AuthzPolicy(Component): valid_users = ['*', 'anonymous'] for resource_section in [a for a in self.authz.sections if a != 'groups']: - resource_glob = to_unicode(resource_section) + resource_glob = resource_section if '@' not in resource_glob: resource_glob += '@*' Modified: incubator/bloodhound/vendor/trac/current/tracopt/perm/config_perm_provider.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/tracopt/perm/config_perm_provider.py?rev=1398858&r1=1398857&r2=1398858&view=diff ============================================================================== --- incubator/bloodhound/vendor/trac/current/tracopt/perm/config_perm_provider.py (original) +++ incubator/bloodhound/vendor/trac/current/tracopt/perm/config_perm_provider.py Tue Oct 16 15:55:00 2012 @@ -12,39 +12,42 @@ # history and logs, available at http://trac.edgewall.org/log/. from trac.core import * +from trac.config import ConfigSection from trac.perm import IPermissionRequestor class ExtraPermissionsProvider(Component): - """Extra permission provider. - - This component provides a way to add arbitrary permissions to a Trac - environment. This can be useful for adding new permissions to use for - workflow actions, for example. - - To add new permissions, create a new section `[extra-permissions]` in - your `trac.ini`. Every entry in that section defines a meta-permission - and a comma-separated list of permissions. For example: - {{{ - [extra-permissions] - extra_admin = extra_view, extra_modify, extra_delete - }}} - This entry will define three new permissions `EXTRA_VIEW`, `EXTRA_MODIFY` - and `EXTRA_DELETE`, as well as a meta-permissions `EXTRA_ADMIN` that - grants all three permissions. - - If you don't want a meta-permission, start the meta-name with an - underscore (`_`): - {{{ - [extra-permissions] - _perms = extra_view, extra_modify - }}} - """ + """Extra permission provider.""" + implements(IPermissionRequestor) - + + extra_permissions_section = ConfigSection('extra-permissions', + doc="""This section provides a way to add arbitrary permissions to a + Trac environment. This can be useful for adding new permissions to use + for workflow actions, for example. + + To add new permissions, create a new section `[extra-permissions]` in + your `trac.ini`. Every entry in that section defines a meta-permission + and a comma-separated list of permissions. For example: + {{{ + [extra-permissions] + extra_admin = extra_view, extra_modify, extra_delete + }}} + This entry will define three new permissions `EXTRA_VIEW`, + `EXTRA_MODIFY` and `EXTRA_DELETE`, as well as a meta-permissions + `EXTRA_ADMIN` that grants all three permissions. + + If you don't want a meta-permission, start the meta-name with an + underscore (`_`): + {{{ + [extra-permissions] + _perms = extra_view, extra_modify + }}} + """) + def get_permission_actions(self): permissions = {} - for meta, perms in self.config.options('extra-permissions'): + for meta, perms in self.extra_permissions_section.options(): perms = [each.strip().upper() for each in perms.split(',')] for perm in perms: permissions.setdefault(perm, []) Added: incubator/bloodhound/vendor/trac/current/tracopt/perm/tests/__init__.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/tracopt/perm/tests/__init__.py?rev=1398858&view=auto ============================================================================== --- incubator/bloodhound/vendor/trac/current/tracopt/perm/tests/__init__.py (added) +++ incubator/bloodhound/vendor/trac/current/tracopt/perm/tests/__init__.py Tue Oct 16 15:55:00 2012 @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://trac.edgewall.org/wiki/TracLicense. +# +# 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/. + +import unittest + +from tracopt.perm.tests import authz_policy + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(authz_policy.suite()) + return suite + + +if __name__ == '__main__': + unittest.main(defaultTest='suite') Propchange: incubator/bloodhound/vendor/trac/current/tracopt/perm/tests/__init__.py ------------------------------------------------------------------------------ svn:eol-style = native Added: incubator/bloodhound/vendor/trac/current/tracopt/perm/tests/authz_policy.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/tracopt/perm/tests/authz_policy.py?rev=1398858&view=auto ============================================================================== --- incubator/bloodhound/vendor/trac/current/tracopt/perm/tests/authz_policy.py (added) +++ incubator/bloodhound/vendor/trac/current/tracopt/perm/tests/authz_policy.py Tue Oct 16 15:55:00 2012 @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://trac.edgewall.org/wiki/TracLicense. +# +# 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/. + +import os +import tempfile +import unittest +try: + from configobj import ConfigObj +except ImportError: + ConfigObj = None + +from trac.resource import Resource +from trac.test import EnvironmentStub +from trac.util import create_file +from tracopt.perm.authz_policy import AuthzPolicy + + +class AuthzPolicyTestCase(unittest.TestCase): + + def setUp(self): + tmpdir = os.path.realpath(tempfile.gettempdir()) + self.authz_file = os.path.join(tmpdir, 'trac-authz-policy') + create_file(self.authz_file, """\ +# Unicode user names +[groups] +administrators = éat + +[wiki:WikiStart] +änon = WIKI_VIEW +@administrators = WIKI_VIEW +* = + +# Unicode page names +[wiki:résumé] +änon = +@administrators = WIKI_VIEW +* = +""") + self.env = EnvironmentStub(enable=[AuthzPolicy]) + self.env.config.set('authz_policy', 'authz_file', self.authz_file) + self.authz_policy = AuthzPolicy(self.env) + + def tearDown(self): + self.env.reset_db() + os.remove(self.authz_file) + + def check_permission(self, action, user, resource, perm): + return self.authz_policy.check_permission(action, user, resource, perm) + + def test_unicode_username(self): + resource = Resource('wiki', 'WikiStart') + self.assertEqual( + False, + self.check_permission('WIKI_VIEW', 'anonymous', resource, None)) + self.assertEqual( + True, + self.check_permission('WIKI_VIEW', u'änon', resource, None)) + + def test_unicode_resource_name(self): + resource = Resource('wiki', u'résumé') + self.assertEqual( + False, + self.check_permission('WIKI_VIEW', 'anonymous', resource, None)) + self.assertEqual( + False, + self.check_permission('WIKI_VIEW', u'änon', resource, None)) + self.assertEqual( + True, + self.check_permission('WIKI_VIEW', u'éat', resource, None)) + + +def suite(): + suite = unittest.TestSuite() + if ConfigObj: + suite.addTest(unittest.makeSuite(AuthzPolicyTestCase, 'test')) + else: + print "SKIP: tracopt/perm/tests/authz_policy.py (no configobj " + \ + "installed)" + return suite + + +if __name__ == '__main__': + unittest.main(defaultTest='suite') Propchange: incubator/bloodhound/vendor/trac/current/tracopt/perm/tests/authz_policy.py ------------------------------------------------------------------------------ svn:eol-style = native Modified: incubator/bloodhound/vendor/trac/current/tracopt/ticket/clone.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/tracopt/ticket/clone.py?rev=1398858&r1=1398857&r2=1398858&view=diff ============================================================================== --- incubator/bloodhound/vendor/trac/current/tracopt/ticket/clone.py (original) +++ incubator/bloodhound/vendor/trac/current/tracopt/ticket/clone.py Tue Oct 16 15:55:00 2012 @@ -16,6 +16,7 @@ from genshi.filters import Transformer from trac.core import Component, implements from trac.web.api import ITemplateStreamFilter +from trac.util.presentation import captioned_button from trac.util.translation import _ @@ -55,7 +56,8 @@ class TicketCloneButton(Component): fields[name] = ticket[name] return tag.form( tag.div( - tag.input(type="submit", name="clone", value=_("Clone"), + tag.input(type="submit", name="clone", + value=captioned_button(req, '+#', _("Clone")), title=_("Create a copy of this ticket")), [tag.input(type="hidden", name='field_' + n, value=v) for n, v in fields.iteritems()], Modified: incubator/bloodhound/vendor/trac/current/tracopt/ticket/commit_updater.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/tracopt/ticket/commit_updater.py?rev=1398858&r1=1398857&r2=1398858&view=diff ============================================================================== --- incubator/bloodhound/vendor/trac/current/tracopt/ticket/commit_updater.py (original) +++ incubator/bloodhound/vendor/trac/current/tracopt/ticket/commit_updater.py Tue Oct 16 15:55:00 2012 @@ -200,7 +200,7 @@ class CommitTicketUpdater(Component): if repos.reponame: revstring += '/' + repos.reponame return """\ -In [changeset:%s]: +In [changeset:"%s"]: {{{ #!CommitTicketReference repository="%s" revision="%s" %s Modified: incubator/bloodhound/vendor/trac/current/tracopt/ticket/deleter.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/tracopt/ticket/deleter.py?rev=1398858&r1=1398857&r2=1398858&view=diff ============================================================================== --- incubator/bloodhound/vendor/trac/current/tracopt/ticket/deleter.py (original) +++ incubator/bloodhound/vendor/trac/current/tracopt/ticket/deleter.py Tue Oct 16 15:55:00 2012 @@ -20,6 +20,7 @@ from trac.ticket.model import Ticket from trac.ticket.web_ui import TicketModule from trac.util import get_reporter_id from trac.util.datefmt import from_utimestamp +from trac.util.presentation import captioned_button from trac.util.translation import _ from trac.web.api import IRequestFilter, IRequestHandler, ITemplateStreamFilter from trac.web.chrome import ITemplateProvider, add_notice, add_stylesheet @@ -67,9 +68,12 @@ class TicketDeleter(Component): return tag.form( tag.div( tag.input(type='hidden', name='action', value='delete'), - tag.input(type='submit', value=_('Delete'), - title=_('Delete ticket')), - class_='inlinebuttons'), + tag.input(type='submit', + value=captioned_button(req, u'â', # 'EN DASH' + _("Delete")), + title=_('Delete ticket'), + class_="trac-delete"), + class_="inlinebuttons"), action='#', method='get') def delete_comment(): @@ -81,10 +85,12 @@ class TicketDeleter(Component): value='delete-comment'), tag.input(type='hidden', name='cnum', value=cnum), tag.input(type='hidden', name='cdate', value=cdate), - tag.input(type='submit', value=_('Delete'), - title=_('Delete comment %(num)s', - num=cnum)), - class_='inlinebuttons'), + tag.input(type='submit', + value=captioned_button(req, u'â', # 'EN DASH' + _("Delete")), + title=_('Delete comment %(num)s', num=cnum), + class_="trac-delete"), + class_="inlinebuttons"), action='#', method='get') buffer = StreamBuffer() Modified: incubator/bloodhound/vendor/trac/current/tracopt/versioncontrol/git/PyGIT.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/tracopt/versioncontrol/git/PyGIT.py?rev=1398858&r1=1398857&r2=1398858&view=diff ============================================================================== --- incubator/bloodhound/vendor/trac/current/tracopt/versioncontrol/git/PyGIT.py (original) +++ incubator/bloodhound/vendor/trac/current/tracopt/versioncontrol/git/PyGIT.py Tue Oct 16 15:55:00 2012 @@ -31,12 +31,70 @@ import weakref __all__ = ['GitError', 'GitErrorSha', 'Storage', 'StorageFactory'] + +def terminate(process): + """Python 2.5 compatibility method. + os.kill is not available on Windows before Python 2.7. + In Python 2.6 subprocess.Popen has a terminate method. + (It also seems to have some issues on Windows though.) + """ + + def terminate_win(process): + import ctypes + PROCESS_TERMINATE = 1 + handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, + False, + process.pid) + ctypes.windll.kernel32.TerminateProcess(handle, -1) + ctypes.windll.kernel32.CloseHandle(handle) + + def terminate_nix(process): + import os + import signal + return os.kill(process.pid, signal.SIGTERM) + + if sys.platform == 'win32': + return terminate_win(process) + return terminate_nix(process) + + class GitError(Exception): pass class GitErrorSha(GitError): pass +# Helper functions + +def parse_commit(raw): + """Parse the raw content of a commit (as given by `git cat-file -p <rev>`). + + Return the commit message and a dict of properties. + """ + if not raw: + raise GitErrorSha + lines = raw.splitlines() + if not lines: + raise GitErrorSha + line = lines.pop(0) + props = {} + multiline = multiline_key = None + while line: + if line[0] == ' ': + if not multiline: + multiline_key = key + multiline = [props[multiline_key][-1]] + multiline.append(line[1:]) + else: + key, value = line.split(None, 1) + props.setdefault(key, []).append(value.strip()) + line = lines.pop(0) + if multiline and (not line or key != multiline_key): + props[multiline_key][-1] = '\n'.join(multiline) + multiline = None + return '\n'.join(lines), props + + class GitCore(object): """Low-level wrapper around git executable""" @@ -252,7 +310,7 @@ class Storage(object): try: g = GitCore(git_bin=git_bin) [v] = g.version().splitlines() - _, _, version = v.strip().split() + version = v.strip().split()[2] # 'version' has usually at least 3 numeric version # components, e.g.:: # 1.5.4.2 @@ -299,6 +357,19 @@ class Storage(object): self.logger = log + self.commit_encoding = None + + # caches + self.__rev_cache = None + self.__rev_cache_lock = Lock() + + # cache the last 200 commit messages + self.__commit_msg_cache = SizedDict(200) + self.__commit_msg_lock = Lock() + + self.__cat_file_pipe = None + self.__cat_file_pipe_lock = Lock() + if git_fs_encoding is not None: # validate encoding name codecs.lookup(git_fs_encoding) @@ -318,31 +389,21 @@ class Storage(object): self.logger.error("GIT control files missing in '%s'" % git_dir) if os.path.exists(__git_file_path('.git')): self.logger.error("entry '.git' found in '%s'" - " -- maybe use that folder instead..." + " -- maybe use that folder instead..." % git_dir) raise GitError("GIT control files not found, maybe wrong " "directory?") - self.logger.debug("PyGIT.Storage instance %d constructed" % id(self)) - self.repo = GitCore(git_dir, git_bin=git_bin) - self.commit_encoding = None - - # caches - self.__rev_cache = None - self.__rev_cache_lock = Lock() - - # cache the last 200 commit messages - self.__commit_msg_cache = SizedDict(200) - self.__commit_msg_lock = Lock() - - self.__cat_file_pipe = None + self.logger.debug("PyGIT.Storage instance %d constructed" % id(self)) def __del__(self): - if self.__cat_file_pipe is not None: - self.__cat_file_pipe.stdin.close() - self.__cat_file_pipe.wait() + with self.__cat_file_pipe_lock: + if self.__cat_file_pipe is not None: + self.__cat_file_pipe.stdin.close() + terminate(self.__cat_file_pipe) + self.__cat_file_pipe.wait() # # cache handling @@ -587,20 +648,39 @@ class Storage(object): return self.verifyrev('HEAD') def cat_file(self, kind, sha): - if self.__cat_file_pipe is None: - self.__cat_file_pipe = self.repo.cat_file_batch() - - self.__cat_file_pipe.stdin.write(sha + '\n') - self.__cat_file_pipe.stdin.flush() - _sha, _type, _size = self.__cat_file_pipe.stdout.readline().split() - - if _type != kind: - raise TracError("internal error (got unexpected object kind " - "'%s')" % k) - - size = int(_size) - return self.__cat_file_pipe.stdout.read(size + 1)[:size] + with self.__cat_file_pipe_lock: + if self.__cat_file_pipe is None: + self.__cat_file_pipe = self.repo.cat_file_batch() + try: + self.__cat_file_pipe.stdin.write(sha + '\n') + self.__cat_file_pipe.stdin.flush() + + split_stdout_line = self.__cat_file_pipe.stdout.readline() \ + .split() + if len(split_stdout_line) != 3: + raise GitError("internal error (could not split line " + "'%s')" % (split_stdout_line,)) + + _sha, _type, _size = split_stdout_line + + if _type != kind: + raise GitError("internal error (got unexpected object " + "kind '%s', expected '%s')" + % (_type, kind)) + + size = int(_size) + return self.__cat_file_pipe.stdout.read(size + 1)[:size] + except: + # There was an error, we should close the pipe to get to a + # consistent state (Otherwise it happens that next time we + # call cat_file we get payload from previous call) + self.logger.debug("closing cat_file pipe") + self.__cat_file_pipe.stdin.close() + terminate(self.__cat_file_pipe) + self.__cat_file_pipe.wait() + self.__cat_file_pipe = None + def verifyrev(self, rev): """verify/lookup given revision object and return a sha id or None if lookup failed @@ -737,19 +817,7 @@ class Storage(object): # cache miss raw = self.cat_file('commit', commit_id) raw = unicode(raw, self.get_commit_encoding(), 'replace') - lines = raw.splitlines() - - if not lines: - raise GitErrorSha - - line = lines.pop(0) - props = {} - while line: - key, value = line.split(None, 1) - props.setdefault(key, []).append(value.strip()) - line = lines.pop(0) - - result = ('\n'.join(lines), props) + result = parse_commit(raw) self.__commit_msg_cache[commit_id] = result @@ -821,31 +889,6 @@ class Storage(object): change = {} next_path = [] - def terminate(process): - """Python 2.5 compatibility method. - os.kill is not available on Windows before Python 2.7. - In Python 2.6 subprocess.Popen has a terminate method. - (It also seems to have some issues on Windows though.) - """ - - def terminate_win(process): - import ctypes - PROCESS_TERMINATE = 1 - handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, - False, - process.pid) - ctypes.windll.kernel32.TerminateProcess(handle, -1) - ctypes.windll.kernel32.CloseHandle(handle) - - def terminate_nix(process): - import os - import signal - return os.kill(process.pid, signal.SIGTERM) - - if sys.platform == 'win32': - return terminate_win(process) - return terminate_nix(process) - def name_status_gen(): p[:] = [self.repo.log_pipe('--pretty=format:%n%H', '--name-status', sha, '--', base_path)] Modified: incubator/bloodhound/vendor/trac/current/tracopt/versioncontrol/git/git_fs.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/tracopt/versioncontrol/git/git_fs.py?rev=1398858&r1=1398857&r2=1398858&view=diff ============================================================================== --- incubator/bloodhound/vendor/trac/current/tracopt/versioncontrol/git/git_fs.py (original) +++ incubator/bloodhound/vendor/trac/current/tracopt/versioncontrol/git/git_fs.py Tue Oct 16 15:55:00 2012 @@ -37,7 +37,7 @@ from tracopt.versioncontrol.git import P class GitCachedRepository(CachedRepository): - """Git-specific cached repository + """Git-specific cached repository. Passes through {display,short,normalize}_rev """ @@ -61,7 +61,7 @@ class GitCachedRepository(CachedReposito class GitCachedChangeset(CachedChangeset): - """Git-specific cached changeset + """Git-specific cached changeset. Handles get_branches() """ @@ -85,7 +85,7 @@ def intersperse(sep, iterable): """The 'intersperse' generator takes an element and an iterable and intersperses that element between the elements of the iterable. - inspired by Haskell's Data.List.intersperse + inspired by Haskell's ``Data.List.intersperse`` """ for i, item in enumerate(iterable): @@ -94,12 +94,12 @@ def intersperse(sep, iterable): # helper def _parse_user_time(s): - """parse author/committer attribute lines and return - (user,timestamp) + """Parse author or committer attribute lines and return + corresponding ``(user, timestamp)`` pair. """ user, time, tz_str = s.rsplit(None, 2) - tz = FixedOffset((int(tz_str)*6)/10, tz_str) + tz = FixedOffset((int(tz_str) * 6) / 10, tz_str) time = datetime.fromtimestamp(float(time), tz) return user, time @@ -112,7 +112,7 @@ class GitConnector(Component): self._version = None try: - self._version = PyGIT.Storage.git_version(git_bin=self._git_bin) + self._version = PyGIT.Storage.git_version(git_bin=self.git_bin) except PyGIT.GitError, e: self.log.error("GitError: " + str(e)) @@ -155,7 +155,7 @@ class GitConnector(Component): title=to_unicode(e), rel='nofollow') def get_wiki_syntax(self): - yield (r'(?:\b|!)r?[0-9a-fA-F]{%d,40}\b' % self._wiki_shortrev_len, + yield (r'(?:\b|!)r?[0-9a-fA-F]{%d,40}\b' % self.wiki_shortrev_len, lambda fmt, sha, match: self._format_sha_link(fmt, sha.startswith('r') and sha[1:] or sha, sha)) @@ -166,40 +166,42 @@ class GitConnector(Component): # IRepositoryConnector methods - _persistent_cache = BoolOption('git', 'persistent_cache', 'false', - """enable persistent caching of commit tree""") + persistent_cache = BoolOption('git', 'persistent_cache', 'false', + """Enable persistent caching of commit tree.""") - _cached_repository = BoolOption('git', 'cached_repository', 'false', - """wrap `GitRepository` in `CachedRepository`""") + cached_repository = BoolOption('git', 'cached_repository', 'false', + """Wrap `GitRepository` in `CachedRepository`.""") - _shortrev_len = IntOption('git', 'shortrev_len', 7, - """length rev sha sums should be tried to be abbreviated to - (must be >= 4 and <= 40) + shortrev_len = IntOption('git', 'shortrev_len', 7, + """The length at which a sha1 should be abbreviated to (must + be >= 4 and <= 40). """) - _wiki_shortrev_len = IntOption('git', 'wiki_shortrev_len', 40, - """minimum length of hex-string for which auto-detection as sha id is - performed. - (must be >= 4 and <= 40) - """) - - _trac_user_rlookup = BoolOption('git', 'trac_user_rlookup', 'false', - """enable reverse mapping of git email addresses to trac user ids""") + wiki_shortrev_len = IntOption('git', 'wikishortrev_len', 40, + """The minimum length of an hex-string for which + auto-detection as sha1 is performed (must be >= 4 and <= 40). + """) - _use_committer_id = BoolOption('git', 'use_committer_id', 'true', - """use git-committer id instead of git-author id as changeset owner + trac_user_rlookup = BoolOption('git', 'trac_user_rlookup', 'false', + """Enable reverse mapping of git email addresses to trac user ids + (costly if you have many users).""") + + use_committer_id = BoolOption('git', 'use_committer_id', 'true', + """Use git-committer id instead of git-author id for the + changeset ''Author'' field. """) - _use_committer_time = BoolOption('git', 'use_committer_time', 'true', - """use git-committer-author timestamp instead of git-author timestamp - as changeset timestamp + use_committer_time = BoolOption('git', 'use_committer_time', 'true', + """Use git-committer timestamp instead of git-author timestamp + for the changeset ''Timestamp'' field. """) - _git_fs_encoding = Option('git', 'git_fs_encoding', 'utf-8', - """define charset encoding of paths within git repository""") + git_fs_encoding = Option('git', 'git_fs_encoding', 'utf-8', + """Define charset encoding of paths within git repositories.""") - _git_bin = PathOption('git', 'git_bin', '/usr/bin/git', - """path to git executable (relative to trac project folder!)""") + git_bin = PathOption('git', 'git_bin', '/usr/bin/git', + """Path to git executable (relative to the Trac configuration folder, + so better use an absolute path here).""") def get_supported_types(self): @@ -209,11 +211,11 @@ class GitConnector(Component): """GitRepository factory method""" assert type == 'git' - if not (4 <= self._shortrev_len <= 40): - raise TracError("shortrev_len must be withing [4..40]") + if not (4 <= self.shortrev_len <= 40): + raise TracError("[git] shortrev_len setting must be within [4..40]") - if not (4 <= self._wiki_shortrev_len <= 40): - raise TracError("wiki_shortrev_len must be withing [4..40]") + if not (4 <= self.wiki_shortrev_len <= 40): + raise TracError("[git] wikishortrev_len must be within [4..40]") if not self._version: raise TracError("GIT backend not available") @@ -223,12 +225,12 @@ class GitConnector(Component): (self._version['v_str'], self._version['v_min_str'])) - if self._trac_user_rlookup: + if self.trac_user_rlookup: def rlookup_uid(email): - """reverse map 'real name <u...@domain.tld>' addresses to trac - user ids + """Reverse map 'real name <u...@domain.tld>' addresses to trac + user ids. - returns None if lookup failed + :return: `None` if lookup failed """ try: @@ -250,16 +252,16 @@ class GitConnector(Component): return None repos = GitRepository(dir, params, self.log, - persistent_cache=self._persistent_cache, - git_bin=self._git_bin, - git_fs_encoding=self._git_fs_encoding, - shortrev_len=self._shortrev_len, + persistent_cache=self.persistent_cache, + git_bin=self.git_bin, + git_fs_encoding=self.git_fs_encoding, + shortrev_len=self.shortrev_len, rlookup_uid=rlookup_uid, - use_committer_id=self._use_committer_id, - use_committer_time=self._use_committer_time, + use_committer_id=self.use_committer_id, + use_committer_time=self.use_committer_time, ) - if self._cached_repository: + if self.cached_repository: repos = GitCachedRepository(self.env, repos, self.log) self.log.debug("enabled CachedRepository for '%s'" % dir) else: @@ -369,15 +371,19 @@ class GitRepository(Repository): self.logger = log self.gitrepo = path self.params = params - self._shortrev_len = max(4, min(shortrev_len, 40)) + self.shortrev_len = max(4, min(shortrev_len, 40)) self.rlookup_uid = rlookup_uid - self._use_committer_time = use_committer_time - self._use_committer_id = use_committer_id + self.use_committer_time = use_committer_time + self.use_committer_id = use_committer_id - self.git = PyGIT.StorageFactory(path, log, not persistent_cache, - git_bin=git_bin, - git_fs_encoding=git_fs_encoding) \ - .getInstance() + try: + self.git = PyGIT.StorageFactory(path, log, not persistent_cache, + git_bin=git_bin, + git_fs_encoding=git_fs_encoding) \ + .getInstance() + except PyGIT.GitError, e: + raise TracError("%s does not appear to be a Git " + "repository." % path) Repository.__init__(self, 'git:'+path, self.params, log) @@ -406,7 +412,7 @@ class GitRepository(Repository): def short_rev(self, rev): return self.git.shortrev(self.normalize_rev(rev), - min_len=self._shortrev_len) + min_len=self.shortrev_len) def get_node(self, path, rev=None, historian=None): return GitNode(self, path, rev, self.log, None, historian) @@ -646,22 +652,37 @@ class GitChangeset(Changeset): if _children: props['children'] = _children + committer, author = self._get_committer_and_author() # use 1st author/committer as changeset owner/timestamp - if repos._use_committer_time: - _, time_ = _parse_user_time(props['committer'][0]) + c_user = a_user = c_time = a_time = None + if committer: + c_user, c_time = _parse_user_time(committer) + if author: + a_user, a_time = _parse_user_time(author) + + if repos.use_committer_time: + time = c_time or a_time else: - _, time_ = _parse_user_time(props['author'][0]) + time = a_time or c_time - if repos._use_committer_id: - user_, _ = _parse_user_time(props['committer'][0]) + if repos.use_committer_id: + user = c_user or a_user else: - user_, _ = _parse_user_time(props['author'][0]) + user = a_user or c_user # try to resolve email address to trac uid - user_ = repos.rlookup_uid(user_) or user_ + user = repos.rlookup_uid(user) or user - Changeset.__init__(self, repos, rev=sha, message=msg, author=user_, - date=time_) + Changeset.__init__(self, repos, rev=sha, message=msg, author=user, + date=time) + + def _get_committer_and_author(self): + committer = author = None + if 'committer' in self.props: + committer = self.props['committer'][0] + if 'author' in self.props: + author = self.props['author'][0] + return committer, author def get_properties(self): properties = {} @@ -672,13 +693,10 @@ class GitChangeset(Changeset): if 'children' in self.props: properties['Children'] = self.props['children'] - if 'committer' in self.props: - properties['git-committer'] = \ - _parse_user_time(self.props['committer'][0]) - - if 'author' in self.props: - properties['git-author'] = \ - _parse_user_time(self.props['author'][0]) + committer, author = self._get_committer_and_author() + if author != committer: + properties['git-committer'] = _parse_user_time(committer) + properties['git-author'] = _parse_user_time(author) branches = list(self.repos.git.get_branch_contains(self.rev, resolve=True)) Modified: incubator/bloodhound/vendor/trac/current/tracopt/versioncontrol/git/tests/PyGIT.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/tracopt/versioncontrol/git/tests/PyGIT.py?rev=1398858&r1=1398857&r2=1398858&view=diff ============================================================================== --- incubator/bloodhound/vendor/trac/current/tracopt/versioncontrol/git/tests/PyGIT.py (original) +++ incubator/bloodhound/vendor/trac/current/tracopt/versioncontrol/git/tests/PyGIT.py Tue Oct 16 15:55:00 2012 @@ -14,7 +14,7 @@ import unittest from trac.test import locate -from tracopt.versioncontrol.git.PyGIT import GitCore, Storage +from tracopt.versioncontrol.git.PyGIT import GitCore, Storage, parse_commit class GitTestCase(unittest.TestCase): @@ -32,6 +32,111 @@ class GitTestCase(unittest.TestCase): self.assertTrue(v['v_compatible']) +class TestParseCommit(unittest.TestCase): + commit2240a7b = '''\ +tree b19535236cfb6c64b798745dd3917dafc27bcd0a +parent 30aaca4582eac20a52ac7b2ec35bdb908133e5b1 +parent 5a0dc7365c240795bf190766eba7a27600be3b3e +author Linus Torvalds <torva...@linux-foundation.org> 1323915958 -0800 +committer Linus Torvalds <torva...@linux-foundation.org> 1323915958 -0800 +mergetag object 5a0dc7365c240795bf190766eba7a27600be3b3e + type commit + tag tytso-for-linus-20111214A + tagger Theodore Ts'o <ty...@mit.edu> 1323890113 -0500 + + tytso-for-linus-20111214 + -----BEGIN PGP SIGNATURE----- + Version: GnuPG v1.4.10 (GNU/Linux) + + iQIcBAABCAAGBQJO6PXBAAoJENNvdpvBGATwpuEP/2RCxmdWYZ8/6Z6pmTh3hHN5 + fx6HckTdvLQOvbQs72wzVW0JKyc25QmW2mQc5z3MjSymjf/RbEKihPUITRNbHrTD + T2sP/lWu09AKLioEg4ucAKn/A7Do3UDIkXTszvVVP/t2psVPzLeJ1njQKra14Nyz + o0+gSlnwuGx9WaxfR+7MYNs2ikdSkXIeYsiFAOY4YOxwwC99J/lZ0YaNkbI7UBtC + yu2XLIvPboa5JZXANq2G3VhVIETMmOyRTCC76OAXjqkdp9nLFWDG0ydqQh0vVZwL + xQGOmAj+l3BNTE0QmMni1w7A0SBU3N6xBA5HN6Y49RlbsMYG27aN54Fy5K2R41I3 + QXVhBL53VD6b0KaITcoz7jIGIy6qk9Wx+2WcCYtQBSIjL2YwlaJq0PL07+vRamex + sqHGDejcNY87i6AV0DP6SNuCFCi9xFYoAoMi9Wu5E9+T+Vck0okFzW/luk/FvsSP + YA5Dh+vISyBeCnWQvcnBmsUQyf8d9MaNnejZ48ath+GiiMfY8USAZ29RAG4VuRtS + 9DAyTTIBA73dKpnvEV9u4i8Lwd8hRVMOnPyOO785NwEXk3Ng08pPSSbMklW6UfCY + 4nr5UNB13ZPbXx4uoAvATMpCpYxMaLEdxmeMvgXpkekl0hHBzpVDey1Vu9fb/a5n + dQpo6WWG9HIJ23hOGAGR + =n3Lm + -----END PGP SIGNATURE----- + +Merge tag 'tytso-for-linus-20111214' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4 + +* tag 'tytso-for-linus-20111214' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: + ext4: handle EOF correctly in ext4_bio_write_page() + ext4: remove a wrong BUG_ON in ext4_ext_convert_to_initialized + ext4: correctly handle pages w/o buffers in ext4_discard_partial_buffers() + ext4: avoid potential hang in mpage_submit_io() when blocksize < pagesize + ext4: avoid hangs in ext4_da_should_update_i_disksize() + ext4: display the correct mount option in /proc/mounts for [no]init_itable + ext4: Fix crash due to getting bogus eh_depth value on big-endian systems + ext4: fix ext4_end_io_dio() racing against fsync() + +.. using the new signed tag merge of git that now verifies the gpg +signature automatically. Yay. The branchname was just 'dev', which is +prettier. I'll tell Ted to use nicer tag names for future cases. +''' + + def test_parse(self): + msg, props = parse_commit(self.commit2240a7b) + self.assertTrue(msg) + self.assertTrue(props) + self.assertEquals( + ['30aaca4582eac20a52ac7b2ec35bdb908133e5b1', + '5a0dc7365c240795bf190766eba7a27600be3b3e'], + props['parent']) + self.assertEquals( + ['Linus Torvalds <torva...@linux-foundation.org> 1323915958 -0800'], + props['author']) + self.assertEquals(props['author'], props['committer']) + + # Merge tag + self.assertEquals(['''\ +object 5a0dc7365c240795bf190766eba7a27600be3b3e +type commit +tag tytso-for-linus-20111214A +tagger Theodore Ts\'o <ty...@mit.edu> 1323890113 -0500 + +tytso-for-linus-20111214 +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.10 (GNU/Linux) + +iQIcBAABCAAGBQJO6PXBAAoJENNvdpvBGATwpuEP/2RCxmdWYZ8/6Z6pmTh3hHN5 +fx6HckTdvLQOvbQs72wzVW0JKyc25QmW2mQc5z3MjSymjf/RbEKihPUITRNbHrTD +T2sP/lWu09AKLioEg4ucAKn/A7Do3UDIkXTszvVVP/t2psVPzLeJ1njQKra14Nyz +o0+gSlnwuGx9WaxfR+7MYNs2ikdSkXIeYsiFAOY4YOxwwC99J/lZ0YaNkbI7UBtC +yu2XLIvPboa5JZXANq2G3VhVIETMmOyRTCC76OAXjqkdp9nLFWDG0ydqQh0vVZwL +xQGOmAj+l3BNTE0QmMni1w7A0SBU3N6xBA5HN6Y49RlbsMYG27aN54Fy5K2R41I3 +QXVhBL53VD6b0KaITcoz7jIGIy6qk9Wx+2WcCYtQBSIjL2YwlaJq0PL07+vRamex +sqHGDejcNY87i6AV0DP6SNuCFCi9xFYoAoMi9Wu5E9+T+Vck0okFzW/luk/FvsSP +YA5Dh+vISyBeCnWQvcnBmsUQyf8d9MaNnejZ48ath+GiiMfY8USAZ29RAG4VuRtS +9DAyTTIBA73dKpnvEV9u4i8Lwd8hRVMOnPyOO785NwEXk3Ng08pPSSbMklW6UfCY +4nr5UNB13ZPbXx4uoAvATMpCpYxMaLEdxmeMvgXpkekl0hHBzpVDey1Vu9fb/a5n +dQpo6WWG9HIJ23hOGAGR +=n3Lm +-----END PGP SIGNATURE-----'''], props['mergetag']) + + # Message + self.assertEquals("""Merge tag 'tytso-for-linus-20111214' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4 + +* tag 'tytso-for-linus-20111214' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: + ext4: handle EOF correctly in ext4_bio_write_page() + ext4: remove a wrong BUG_ON in ext4_ext_convert_to_initialized + ext4: correctly handle pages w/o buffers in ext4_discard_partial_buffers() + ext4: avoid potential hang in mpage_submit_io() when blocksize < pagesize + ext4: avoid hangs in ext4_da_should_update_i_disksize() + ext4: display the correct mount option in /proc/mounts for [no]init_itable + ext4: Fix crash due to getting bogus eh_depth value on big-endian systems + ext4: fix ext4_end_io_dio() racing against fsync() + +.. using the new signed tag merge of git that now verifies the gpg +signature automatically. Yay. The branchname was just 'dev', which is +prettier. I'll tell Ted to use nicer tag names for future cases.""", msg) + + #class GitPerformanceTestCase(unittest.TestCase): # """Performance test. Not really a unit test. # Not self-contained: Needs a git repository and prints performance result @@ -185,6 +290,7 @@ def suite(): git = locate("git") if git: suite.addTest(unittest.makeSuite(GitTestCase, 'test')) + suite.addTest(unittest.makeSuite(TestParseCommit, 'test')) else: print("SKIP: tracopt/versioncontrol/git/tests/PyGIT.py (git cli " "binary, 'git', not found)") Added: incubator/bloodhound/vendor/trac/current/tracopt/versioncontrol/svn/__init__.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/vendor/trac/current/tracopt/versioncontrol/svn/__init__.py?rev=1398858&view=auto ============================================================================== (empty) Propchange: incubator/bloodhound/vendor/trac/current/tracopt/versioncontrol/svn/__init__.py ------------------------------------------------------------------------------ svn:eol-style = native