Modified: bloodhound/vendor/trac/current/trac/admin/web_ui.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/admin/web_ui.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/admin/web_ui.py (original) +++ bloodhound/vendor/trac/current/trac/admin/web_ui.py Fri Nov 14 11:06:23 2014 @@ -22,11 +22,6 @@ import pkg_resources import re import shutil -try: - from babel.core import Locale -except ImportError: - Locale = None - from genshi import HTML from genshi.builder import tag @@ -37,7 +32,7 @@ from trac.perm import PermissionSystem, from trac.util.datefmt import all_timezones, pytz from trac.util.text import exception_to_unicode, \ unicode_to_base64, unicode_from_base64 -from trac.util.translation import _, get_available_locales, ngettext +from trac.util.translation import _, Locale, get_available_locales, ngettext from trac.web import HTTPNotFound, IRequestHandler from trac.web.chrome import add_notice, add_stylesheet, \ add_warning, Chrome, INavigationContributor, \ @@ -71,8 +66,8 @@ class AdminModule(Component): # admin panel is available panels, providers = self._get_panels(req) if panels: - yield 'mainnav', 'admin', tag.a(_('Admin'), href=req.href.admin(), - title=_('Administration')) + yield 'mainnav', 'admin', tag.a(_("Admin"), href=req.href.admin(), + title=_("Administration")) # IRequestHandler methods @@ -88,7 +83,7 @@ class AdminModule(Component): def process_request(self, req): panels, providers = self._get_panels(req) if not panels: - raise HTTPNotFound(_('No administration panels available')) + raise HTTPNotFound(_("No administration panels available")) def _panel_order(p1, p2): if p1[::2] == ('general', 'basics'): @@ -114,11 +109,11 @@ class AdminModule(Component): panel_id = \ filter(lambda panel: panel[0] == cat_id, panels)[0][2] except IndexError: - raise HTTPNotFound(_('Unknown administration panel')) + raise HTTPNotFound(_("Unknown administration panel")) provider = providers.get((cat_id, panel_id), None) if not provider: - raise HTTPNotFound(_('Unknown administration panel')) + raise HTTPNotFound(_("Unknown administration panel")) if hasattr(provider, 'render_admin_panel'): template, data = provider.render_admin_panel(req, cat_id, panel_id, @@ -189,14 +184,14 @@ def _save_config(config, req, log, notic try: config.save() if notices is None: - notices = [_('Your changes have been saved.')] + notices = [_("Your changes have been saved.")] for notice in notices: add_notice(req, notice) except Exception, e: - log.error('Error writing to trac.ini: %s', exception_to_unicode(e)) - add_warning(req, _('Error writing to trac.ini, make sure it is ' - 'writable by the web server. Your changes have ' - 'not been saved.')) + log.error("Error writing to trac.ini: %s", exception_to_unicode(e)) + add_warning(req, _("Error writing to trac.ini, make sure it is " + "writable by the web server. Your changes have " + "not been saved.")) class BasicsAdminPanel(Component): @@ -207,7 +202,7 @@ class BasicsAdminPanel(Component): def get_admin_panels(self, req): if 'TRAC_ADMIN' in req.perm('admin', 'general/basics'): - yield ('general', _('General'), 'basics', _('Basic Settings')) + yield ('general', _("General"), 'basics', _("Basic Settings")) def render_admin_panel(self, req, cat, page, path_info): if Locale: @@ -267,7 +262,7 @@ class LoggingAdminPanel(Component): def get_admin_panels(self, req): if 'TRAC_ADMIN' in req.perm('admin', 'general/logging'): - yield ('general', _('General'), 'logging', _('Logging')) + yield ('general', _("General"), 'logging', _("Logging")) def render_admin_panel(self, req, cat, page, path_info): log_type = self.env.log_type @@ -276,16 +271,18 @@ class LoggingAdminPanel(Component): log_dir = os.path.join(self.env.path, 'log') log_types = [ - dict(name='none', label=_('None'), selected=log_type == 'none', disabled=False), - dict(name='stderr', label=_('Console'), + dict(name='none', label=_("None"), + selected=log_type == 'none', disabled=False), + dict(name='stderr', label=_("Console"), selected=log_type == 'stderr', disabled=False), - dict(name='file', label=_('File'), selected=log_type == 'file', - disabled=False), - dict(name='syslog', label=_('Syslog'), disabled=os.name != 'posix', - selected=log_type in ('unix', 'syslog')), - dict(name='eventlog', label=_('Windows event log'), - disabled=os.name != 'nt', - selected=log_type in ('winlog', 'eventlog', 'nteventlog')), + dict(name='file', label=_("File"), + selected=log_type == 'file', disabled=False), + dict(name='syslog', label=_("Syslog"), + selected=log_type in ('unix', 'syslog'), + disabled=os.name != 'posix'), + dict(name='eventlog', label=_("Windows event log"), + selected=log_type in ('winlog', 'eventlog', 'nteventlog'), + disabled=os.name != 'nt'), ] log_levels = ['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'] @@ -296,8 +293,8 @@ class LoggingAdminPanel(Component): new_type = req.args.get('log_type') if new_type not in [t['name'] for t in log_types]: raise TracError( - _('Unknown log type %(type)s', type=new_type), - _('Invalid log type') + _("Unknown log type %(type)s", type=new_type), + _("Invalid log type") ) if new_type != log_type: self.config.set('logging', 'log_type', new_type) @@ -311,8 +308,8 @@ class LoggingAdminPanel(Component): new_level = req.args.get('log_level') if new_level not in log_levels: raise TracError( - _('Unknown log level %(level)s', level=new_level), - _('Invalid log level')) + _("Unknown log level %(level)s", level=new_level), + _("Invalid log level")) if new_level != log_level: self.config.set('logging', 'log_level', new_level) changed = True @@ -325,8 +322,8 @@ class LoggingAdminPanel(Component): changed = True log_file = new_file if not log_file: - raise TracError(_('You must specify a log file'), - _('Missing field')) + raise TracError(_("You must specify a log file"), + _("Missing field")) else: self.config.remove('logging', 'log_file') changed = True @@ -356,7 +353,7 @@ class PermissionAdminPanel(Component): def get_admin_panels(self, req): perm = req.perm('admin', 'general/perm') if 'PERMISSION_GRANT' in perm or 'PERMISSION_REVOKE' in perm: - yield ('general', _('General'), 'perm', _('Permissions')) + yield ('general', _("General"), 'perm', _("Permissions")) def render_admin_panel(self, req, cat, page, path_info): perm = PermissionSystem(self.env) @@ -370,24 +367,24 @@ class PermissionAdminPanel(Component): if subject and subject.isupper() or \ group and group.isupper(): - raise TracError(_('All upper-cased tokens are reserved for ' - 'permission names')) + raise TracError(_("All upper-cased tokens are reserved for " + "permission names")) # Grant permission to subject if req.args.get('add') and subject and action: req.perm('admin', 'general/perm').require('PERMISSION_GRANT') if action not in all_actions: - raise TracError(_('Unknown action')) + raise TracError(_("Unknown action")) req.perm.require(action) if (subject, action) not in all_permissions: perm.grant_permission(subject, action) - add_notice(req, _('The subject %(subject)s has been ' - 'granted the permission %(action)s.', + add_notice(req, _("The subject %(subject)s has been " + "granted the permission %(action)s.", subject=subject, action=action)) req.redirect(req.href.admin(cat, page)) else: - add_warning(req, _('The permission %(action)s was already ' - 'granted to %(subject)s.', + add_warning(req, _("The permission %(action)s was already " + "granted to %(subject)s.", action=action, subject=subject)) # Add subject to group @@ -396,19 +393,25 @@ class PermissionAdminPanel(Component): for action in perm.get_user_permissions(group): if not action in all_actions: # plugin disabled? self.env.log.warn("Adding %s to group %s: " - "Permission %s unavailable, skipping perm check." - % (subject, group, action)) + "Permission %s unavailable, skipping perm check.", + subject, group, action) else: - req.perm.require(action) + req.perm.require(action, + message=_("The subject %(subject)s was not added " + "to the group %(group)s because the " + "group has %(perm)s permission and " + "users cannot grant permissions they " + "don't possess.", subject=subject, + group=group, perm=action)) if (subject, group) not in all_permissions: perm.grant_permission(subject, group) - add_notice(req, _('The subject %(subject)s has been added ' - 'to the group %(group)s.', + add_notice(req, _("The subject %(subject)s has been added " + "to the group %(group)s.", subject=subject, group=group)) req.redirect(req.href.admin(cat, page)) else: - add_warning(req, _('The subject %(subject)s was already ' - 'added to the group %(group)s.', + add_warning(req, _("The subject %(subject)s was already " + "added to the group %(group)s.", subject=subject, group=group)) # Remove permissions action @@ -422,8 +425,8 @@ class PermissionAdminPanel(Component): action = unicode_from_base64(action) if (subject, action) in perm.get_all_permissions(): perm.revoke_permission(subject, action) - add_notice(req, _('The selected permissions have been ' - 'revoked.')) + add_notice(req, _("The selected permissions have been " + "revoked.")) req.redirect(req.href.admin(cat, page)) perms = [perm for perm in all_permissions if perm[1].isupper()] @@ -443,7 +446,7 @@ class PluginAdminPanel(Component): def get_admin_panels(self, req): if 'TRAC_ADMIN' in req.perm('admin', 'general/plugin'): - yield ('general', _('General'), 'plugin', _('Plugins')) + yield ('general', _("General"), 'plugin', _("Plugins")) def render_admin_panel(self, req, cat, page, path_info): if req.method == 'POST': @@ -465,25 +468,25 @@ class PluginAdminPanel(Component): def _do_install(self, req): """Install a plugin.""" if 'plugin_file' not in req.args: - raise TracError(_('No file uploaded')) + raise TracError(_("No file uploaded")) upload = req.args['plugin_file'] if isinstance(upload, unicode) or not upload.filename: - raise TracError(_('No file uploaded')) + raise TracError(_("No file uploaded")) plugin_filename = upload.filename.replace('\\', '/').replace(':', '/') plugin_filename = os.path.basename(plugin_filename) if not plugin_filename: - raise TracError(_('No file uploaded')) + raise TracError(_("No file uploaded")) if not plugin_filename.endswith('.egg') and \ not plugin_filename.endswith('.py'): - raise TracError(_('Uploaded file is not a Python source file or ' - 'egg')) + raise TracError(_("Uploaded file is not a Python source file or " + "egg")) target_path = os.path.join(self.env.path, 'plugins', plugin_filename) if os.path.isfile(target_path): - raise TracError(_('Plugin %(name)s already installed', + raise TracError(_("Plugin %(name)s already installed", name=plugin_filename)) - self.log.info('Installing plugin %s', plugin_filename) + self.log.info("Installing plugin %s", plugin_filename) flags = os.O_CREAT + os.O_WRONLY + os.O_EXCL try: flags += os.O_BINARY @@ -492,7 +495,7 @@ class PluginAdminPanel(Component): pass with os.fdopen(os.open(target_path, flags, 0666), 'w') as target_file: shutil.copyfileobj(upload.file, target_file) - self.log.info('Plugin %s installed to %s', plugin_filename, + self.log.info("Plugin %s installed to %s", plugin_filename, target_path) # TODO: Validate that the uploaded file is actually a valid Trac plugin @@ -507,7 +510,7 @@ class PluginAdminPanel(Component): plugin_path = os.path.join(self.env.path, 'plugins', plugin_filename) if not os.path.isfile(plugin_path): return - self.log.info('Uninstalling plugin %s', plugin_filename) + self.log.info("Uninstalling plugin %s", plugin_filename) os.remove(plugin_path) # Make the environment reset itself on the next request @@ -528,8 +531,8 @@ class PluginAdminPanel(Component): if is_enabled != must_enable: self.config.set('components', component, 'disabled' if is_enabled else 'enabled') - self.log.info('%sabling component %s', - 'Dis' if is_enabled else 'En', component) + self.log.info("%sabling component %s", + "Dis" if is_enabled else "En", component) if must_enable: added.append(component) else: @@ -547,13 +550,13 @@ class PluginAdminPanel(Component): removed.sort() notices = [] if removed: - msg = ngettext('The following component has been disabled:', - 'The following components have been disabled:', + msg = ngettext("The following component has been disabled:", + "The following components have been disabled:", len(removed)) notices.append(tag(msg, make_list(removed))) if added: - msg = ngettext('The following component has been enabled:', - 'The following components have been enabled:', + msg = ngettext("The following component has been enabled:", + "The following components have been enabled:", len(added)) notices.append(tag(msg, make_list(added))) @@ -566,7 +569,7 @@ class PluginAdminPanel(Component): try: return format_to_html(self.env, context, text) except Exception, e: - self.log.error('Unable to render component documentation: %s', + self.log.error("Unable to render component documentation: %s", exception_to_unicode(e, traceback=True)) return tag.pre(text)
Modified: bloodhound/vendor/trac/current/trac/cache.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/cache.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/cache.py (original) +++ bloodhound/vendor/trac/current/trac/cache.py Fri Nov 14 11:06:23 2014 @@ -13,6 +13,8 @@ from __future__ import with_statement +import functools + from .core import Component from .util import arity from .util.concurrency import ThreadLocal, threading @@ -34,12 +36,15 @@ def key_to_id(s): return result -class CachedPropertyBase(object): - """Base class for cached property descriptors""" +class CachedPropertyBase(property): + """Base class for cached property descriptors. + + :since 1.0.2: inherits from `property`. + """ def __init__(self, retriever): self.retriever = retriever - self.__doc__ = retriever.__doc__ + functools.update_wrapper(self, retriever) def make_key(self, cls): attr = self.retriever.__name__ Modified: bloodhound/vendor/trac/current/trac/db/api.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/api.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/db/api.py (original) +++ bloodhound/vendor/trac/current/trac/db/api.py Fri Nov 14 11:06:23 2014 @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C)2005-2009 Edgewall Software +# Copyright (C)2005-2014 Edgewall Software # Copyright (C) 2005 Christopher Lenz <cml...@gmx.de> # All rights reserved. # @@ -22,6 +22,7 @@ import urllib from trac.config import BoolOption, IntOption, Option from trac.core import * +from trac.db.schema import Table from trac.util.concurrency import ThreadLocal from trac.util.text import unicode_passwd from trac.util.translation import _ @@ -61,9 +62,9 @@ def with_transaction(env, db=None): :deprecated: This decorator is in turn deprecated in favor of context managers now that python 2.4 support has been - dropped. Use instead the new context manager, - `QueryContextManager` and - `TransactionContextManager`, which makes for much + dropped. It will be removed in Trac 1.3.1. Use instead + the new context managers, `QueryContextManager` and + `TransactionContextManager`, which make for much simpler to write code: >>> def api_method(p1, p2): @@ -250,6 +251,31 @@ class DatabaseManager(Component): args['schema'] = schema connector.init_db(**args) + def create_tables(self, schema): + """Create the specified tables. + + :param schema: an iterable of table objects. + + :since: version 1.0.2 + """ + connector = self.get_connector()[0] + with self.env.db_transaction as db: + for table in schema: + for sql in connector.to_sql(table): + db(sql) + + def drop_tables(self, schema): + """Drop the specified tables. + + :param schema: an iterable of `Table` objects or table names. + + :since: version 1.0.2 + """ + with self.env.db_transaction as db: + for table in schema: + table_name = table.name if isinstance(table, Table) else table + db.drop_table(table_name) + def get_connection(self, readonly=False): """Get a database connection from the pool. @@ -287,7 +313,7 @@ class DatabaseManager(Component): backup_dir = os.path.join(self.env.path, backup_dir) db_str = self.config.get('trac', 'database') db_name, db_path = db_str.split(":", 1) - dest_name = '%s.%i.%d.bak' % (db_name, self.env.get_version(), + dest_name = '%s.%i.%d.bak' % (db_name, self.env.database_version, int(time.time())) dest = os.path.join(backup_dir, dest_name) else: Modified: bloodhound/vendor/trac/current/trac/db/mysql_backend.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/mysql_backend.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/db/mysql_backend.py (original) +++ bloodhound/vendor/trac/current/trac/db/mysql_backend.py Fri Nov 14 11:06:23 2014 @@ -361,6 +361,7 @@ class MySQLConnection(ConnectionWrapper) name) cnx = MySQLdb.connect(db=path, user=user, passwd=password, host=host, port=port, charset='utf8', **opts) + self.schema = path if hasattr(cnx, 'encoders'): # 'encoders' undocumented but present since 1.2.1 (r422) cnx.encoders[Markup] = cnx.encoders[types.UnicodeType] @@ -374,6 +375,24 @@ class MySQLConnection(ConnectionWrapper) ConnectionWrapper.__init__(self, cnx, log) self._is_closed = False + def cursor(self): + return IterableCursor(MySQLUnicodeCursor(self.cnx), self.log) + + def rollback(self): + self.cnx.ping() + try: + self.cnx.rollback() + except MySQLdb.ProgrammingError: + self._is_closed = True + + def close(self): + if not self._is_closed: + try: + self.cnx.close() + except MySQLdb.ProgrammingError: + pass # this error would mean it's already closed. So, ignore + self._is_closed = True + def cast(self, column, type): if type == 'int' or type == 'int64': type = 'signed' @@ -384,6 +403,27 @@ class MySQLConnection(ConnectionWrapper) def concat(self, *args): return 'concat(%s)' % ', '.join(args) + def drop_table(self, table): + cursor = MySQLdb.cursors.Cursor(self.cnx) + cursor._defer_warnings = True # ignore "Warning: Unknown table ..." + cursor.execute("DROP TABLE IF EXISTS " + self.quote(table)) + + def get_column_names(self, table): + rows = self.execute(""" + SELECT column_name FROM information_schema.columns + WHERE table_schema=%s AND table_name=%s + """, (self.schema, table)) + return [row[0] for row in rows] + + def get_last_id(self, cursor, table, column='id'): + return cursor.lastrowid + + def get_table_names(self): + rows = self.execute(""" + SELECT table_name FROM information_schema.tables + WHERE table_schema=%s""", (self.schema,)) + return [row[0] for row in rows] + def like(self): """Return a case-insensitive LIKE clause.""" return "LIKE %%s COLLATE %s_general_ci ESCAPE '/'" % self.charset @@ -391,31 +431,18 @@ class MySQLConnection(ConnectionWrapper) def like_escape(self, text): return _like_escape_re.sub(r'/\1', text) + def prefix_match(self): + """Return a case sensitive prefix-matching operator.""" + return "LIKE %s ESCAPE '/'" + + def prefix_match_value(self, prefix): + """Return a value for case sensitive prefix-matching operator.""" + return self.like_escape(prefix) + '%' + def quote(self, identifier): """Return the quoted identifier.""" return "`%s`" % identifier.replace('`', '``') - def get_last_id(self, cursor, table, column='id'): - return cursor.lastrowid - def update_sequence(self, cursor, table, column='id'): # MySQL handles sequence updates automagically pass - - def rollback(self): - self.cnx.ping() - try: - self.cnx.rollback() - except MySQLdb.ProgrammingError: - self._is_closed = True - - def close(self): - if not self._is_closed: - try: - self.cnx.close() - except MySQLdb.ProgrammingError: - pass # this error would mean it's already closed. So, ignore - self._is_closed = True - - def cursor(self): - return IterableCursor(MySQLUnicodeCursor(self.cnx), self.log) Modified: bloodhound/vendor/trac/current/trac/db/postgres_backend.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/postgres_backend.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/db/postgres_backend.py (original) +++ bloodhound/vendor/trac/current/trac/db/postgres_backend.py Fri Nov 14 11:06:23 2014 @@ -22,7 +22,7 @@ from trac.core import * from trac.config import Option from trac.db.api import IDatabaseConnector, _parse_db_str from trac.db.util import ConnectionWrapper, IterableCursor -from trac.util import get_pkginfo +from trac.util import get_pkginfo, lazy from trac.util.compat import close_fds from trac.util.text import empty, exception_to_unicode, to_unicode from trac.util.translation import _ @@ -231,6 +231,9 @@ class PostgreSQLConnection(ConnectionWra cnx.rollback() ConnectionWrapper.__init__(self, cnx, log) + def cursor(self): + return IterableCursor(self.cnx.cursor(), self.log) + def cast(self, column, type): # Temporary hack needed for the union of selects in the search module return 'CAST(%s AS %s)' % (column, _type_map.get(type, type)) @@ -238,6 +241,37 @@ class PostgreSQLConnection(ConnectionWra def concat(self, *args): return '||'.join(args) + def drop_table(self, table): + if (self._version or '').startswith(('8.0.', '8.1.')): + cursor = self.cursor() + cursor.execute("""SELECT table_name FROM information_schema.tables + WHERE table_schema=current_schema() + AND table_name=%s""", (table,)) + for row in cursor: + if row[0] == table: + self.execute("DROP TABLE " + self.quote(table)) + break + else: + self.execute("DROP TABLE IF EXISTS " + self.quote(table)) + + def get_column_names(self, table): + rows = self.execute(""" + SELECT column_name FROM information_schema.columns + WHERE table_schema=%s AND table_name=%s + """, (self.schema, table)) + return [row[0] for row in rows] + + def get_last_id(self, cursor, table, column='id'): + cursor.execute("SELECT CURRVAL(%s)", + (self.quote(self._sequence_name(table, column)),)) + return cursor.fetchone()[0] + + def get_table_names(self): + rows = self.execute(""" + SELECT table_name FROM information_schema.tables + WHERE table_schema=%s""", (self.schema,)) + return [row[0] for row in rows] + def like(self): """Return a case-insensitive LIKE clause.""" return "ILIKE %s ESCAPE '/'" @@ -245,18 +279,31 @@ class PostgreSQLConnection(ConnectionWra def like_escape(self, text): return _like_escape_re.sub(r'/\1', text) + def prefix_match(self): + """Return a case sensitive prefix-matching operator.""" + return "LIKE %s ESCAPE '/'" + + def prefix_match_value(self, prefix): + """Return a value for case sensitive prefix-matching operator.""" + return self.like_escape(prefix) + '%' + def quote(self, identifier): """Return the quoted identifier.""" return '"%s"' % identifier.replace('"', '""') - def get_last_id(self, cursor, table, column='id'): - cursor.execute("""SELECT CURRVAL('"%s_%s_seq"')""" % (table, column)) - return cursor.fetchone()[0] - def update_sequence(self, cursor, table, column='id'): - cursor.execute(""" - SELECT setval('"%s_%s_seq"', (SELECT MAX(id) FROM %s)) - """ % (table, column, table)) - - def cursor(self): - return IterableCursor(self.cnx.cursor(), self.log) + cursor.execute("SELECT SETVAL(%%s, (SELECT MAX(%s) FROM %s))" + % (self.quote(column), self.quote(table)), + (self.quote(self._sequence_name(table, column)),)) + + def _sequence_name(self, table, column): + return '%s_%s_seq' % (table, column) + + @lazy + def _version(self): + cursor = self.cursor() + cursor.execute('SELECT version()') + for version, in cursor: + # retrieve "8.1.23" from "PostgreSQL 8.1.23 on ...." + if version.startswith('PostgreSQL '): + return version.split(' ', 2)[1] Modified: bloodhound/vendor/trac/current/trac/db/sqlite_backend.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/sqlite_backend.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/db/sqlite_backend.py (original) +++ bloodhound/vendor/trac/current/trac/db/sqlite_backend.py Fri Nov 14 11:06:23 2014 @@ -27,6 +27,8 @@ from trac.util.translation import _ _like_escape_re = re.compile(r'([/_%])') +_glob_escape_re = re.compile(r'[*?\[]') + try: import pysqlite2.dbapi2 as sqlite have_pysqlite = 2 @@ -313,6 +315,24 @@ class SQLiteConnection(ConnectionWrapper def concat(self, *args): return '||'.join(args) + def drop_table(self, table): + cursor = self.cursor() + cursor.execute("DROP TABLE IF EXISTS " + self.quote(table)) + + def get_column_names(self, table): + cursor = self.cnx.cursor() + rows = cursor.execute("PRAGMA table_info(%s)" + % self.quote(table)) + return [row[1] for row in rows] + + def get_last_id(self, cursor, table, column='id'): + return cursor.lastrowid + + def get_table_names(self): + rows = self.execute(""" + SELECT name FROM sqlite_master WHERE type='table'""") + return [row[0] for row in rows] + def like(self): """Return a case-insensitive LIKE clause.""" if sqlite_version >= (3, 1, 0): @@ -326,13 +346,18 @@ class SQLiteConnection(ConnectionWrapper else: return text + def prefix_match(self): + """Return a case sensitive prefix-matching operator.""" + return 'GLOB %s' + + def prefix_match_value(self, prefix): + """Return a value for case sensitive prefix-matching operator.""" + return _glob_escape_re.sub(lambda m: '[%s]' % m.group(0), prefix) + '*' + def quote(self, identifier): """Return the quoted identifier.""" return "`%s`" % identifier.replace('`', '``') - def get_last_id(self, cursor, table, column='id'): - return cursor.lastrowid - def update_sequence(self, cursor, table, column='id'): # SQLite handles sequence updates automagically # http://www.sqlite.org/autoinc.html Modified: bloodhound/vendor/trac/current/trac/db/tests/__init__.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/tests/__init__.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/db/tests/__init__.py (original) +++ bloodhound/vendor/trac/current/trac/db/tests/__init__.py Fri Nov 14 11:06:23 2014 @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2005-2013 Edgewall Software +# Copyright (C) 2005-2014 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which @@ -14,11 +14,10 @@ import unittest from trac.db.tests import api, mysql_test, postgres_test, util - from trac.db.tests.functional import functionalSuite -def suite(): +def suite(): suite = unittest.TestSuite() suite.addTest(api.suite()) suite.addTest(mysql_test.suite()) Modified: bloodhound/vendor/trac/current/trac/db/tests/api.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/tests/api.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/db/tests/api.py (original) +++ bloodhound/vendor/trac/current/trac/db/tests/api.py Fri Nov 14 11:06:23 2014 @@ -16,8 +16,11 @@ from __future__ import with_statement import os import unittest +import trac.tests.compat from trac.db.api import DatabaseManager, _parse_db_str, get_column_names, \ with_transaction +from trac.db_default import schema as default_schema +from trac.db.schema import Column, Table from trac.test import EnvironmentStub, Mock from trac.util.concurrency import ThreadLocal @@ -287,6 +290,9 @@ class StringsTestCase(unittest.TestCase) def setUp(self): self.env = EnvironmentStub() + def tearDown(self): + self.env.reset_db() + def test_insert_unicode(self): self.env.db_transaction( "INSERT INTO system (name,value) VALUES (%s,%s)", @@ -318,41 +324,172 @@ class StringsTestCase(unittest.TestCase) self.assertEqual(r'alpha\`\"\'\\beta``gamma""delta', get_column_names(cursor)[0]) + def test_quoted_id_with_percent(self): + db = self.env.get_read_db() + name = """%?`%s"%'%%""" + + def test(db, logging=False): + cursor = db.cursor() + if logging: + cursor.log = self.env.log + + cursor.execute('SELECT 1 AS ' + db.quote(name)) + self.assertEqual(name, get_column_names(cursor)[0]) + cursor.execute('SELECT %s AS ' + db.quote(name), (42,)) + self.assertEqual(name, get_column_names(cursor)[0]) + cursor.executemany("UPDATE system SET value=%s WHERE " + "1=(SELECT 0 AS " + db.quote(name) + ")", + []) + cursor.executemany("UPDATE system SET value=%s WHERE " + "1=(SELECT 0 AS " + db.quote(name) + ")", + [('42',), ('43',)]) + + test(db) + test(db, logging=True) + + def test_prefix_match_case_sensitive(self): + @self.env.with_transaction() + def do_insert(db): + cursor = db.cursor() + cursor.executemany("INSERT INTO system (name,value) VALUES (%s,1)", + [('blahblah',), ('BlahBlah',), ('BLAHBLAH',), + (u'BlähBlah',), (u'BlahBläh',)]) + + db = self.env.get_read_db() + cursor = db.cursor() + cursor.execute("SELECT name FROM system WHERE name %s" % + db.prefix_match(), + (db.prefix_match_value('Blah'),)) + names = sorted(name for name, in cursor) + self.assertEqual('BlahBlah', names[0]) + self.assertEqual(u'BlahBläh', names[1]) + self.assertEqual(2, len(names)) + + def test_prefix_match_metachars(self): + def do_query(prefix): + db = self.env.get_read_db() + cursor = db.cursor() + cursor.execute("SELECT name FROM system WHERE name %s " + "ORDER BY name" % db.prefix_match(), + (db.prefix_match_value(prefix),)) + return [name for name, in cursor] + + @self.env.with_transaction() + def do_insert(db): + values = ['foo*bar', 'foo*bar!', 'foo?bar', 'foo?bar!', + 'foo[bar', 'foo[bar!', 'foo]bar', 'foo]bar!', + 'foo%bar', 'foo%bar!', 'foo_bar', 'foo_bar!', + 'foo/bar', 'foo/bar!', 'fo*ob?ar[fo]ob%ar_fo/obar'] + cursor = db.cursor() + cursor.executemany("INSERT INTO system (name,value) VALUES (%s,1)", + [(value,) for value in values]) + + self.assertEqual(['foo*bar', 'foo*bar!'], do_query('foo*')) + self.assertEqual(['foo?bar', 'foo?bar!'], do_query('foo?')) + self.assertEqual(['foo[bar', 'foo[bar!'], do_query('foo[')) + self.assertEqual(['foo]bar', 'foo]bar!'], do_query('foo]')) + self.assertEqual(['foo%bar', 'foo%bar!'], do_query('foo%')) + self.assertEqual(['foo_bar', 'foo_bar!'], do_query('foo_')) + self.assertEqual(['foo/bar', 'foo/bar!'], do_query('foo/')) + self.assertEqual(['fo*ob?ar[fo]ob%ar_fo/obar'], do_query('fo*')) + self.assertEqual(['fo*ob?ar[fo]ob%ar_fo/obar'], + do_query('fo*ob?ar[fo]ob%ar_fo/obar')) + class ConnectionTestCase(unittest.TestCase): def setUp(self): self.env = EnvironmentStub() + self.schema = [ + Table('HOURS', key='ID')[ + Column('ID', auto_increment=True), + Column('AUTHOR')], + Table('blog', key='bid')[ + Column('bid', auto_increment=True), + Column('author') + ] + ] + self.env.global_databasemanager.drop_tables(self.schema) + self.env.global_databasemanager.create_tables(self.schema) def tearDown(self): + self.env.global_databasemanager.drop_tables(self.schema) self.env.reset_db() def test_get_last_id(self): - id1 = id2 = None q = "INSERT INTO report (author) VALUES ('anonymous')" with self.env.db_transaction as db: cursor = db.cursor() cursor.execute(q) # Row ID correct before... id1 = db.get_last_id(cursor, 'report') - self.assertNotEqual(0, id1) db.commit() cursor.execute(q) # ... and after commit() db.commit() id2 = db.get_last_id(cursor, 'report') - self.assertEqual(id1 + 1, id2) - def test_update_sequence(self): - self.env.db_transaction( - "INSERT INTO report (id, author) VALUES (42, 'anonymous')") + self.assertNotEqual(0, id1) + self.assertEqual(id1 + 1, id2) + + def test_update_sequence_default_column(self): with self.env.db_transaction as db: + db("INSERT INTO report (id, author) VALUES (42, 'anonymous')") cursor = db.cursor() db.update_sequence(cursor, 'report', 'id') + self.env.db_transaction( "INSERT INTO report (author) VALUES ('next-id')") + self.assertEqual(43, self.env.db_query( "SELECT id FROM report WHERE author='next-id'")[0][0]) + def test_update_sequence_nondefault_column(self): + with self.env.db_transaction as db: + cursor = db.cursor() + cursor.execute( + "INSERT INTO blog (bid, author) VALUES (42, 'anonymous')") + db.update_sequence(cursor, 'blog', 'bid') + + self.env.db_transaction( + "INSERT INTO blog (author) VALUES ('next-id')") + + self.assertEqual(43, self.env.db_query( + "SELECT bid FROM blog WHERE author='next-id'")[0][0]) + + def test_identifiers_need_quoting(self): + """Test for regression described in comment:4:ticket:11512.""" + with self.env.db_transaction as db: + db("INSERT INTO %s (%s, %s) VALUES (42, 'anonymous')" + % (db.quote('HOURS'), db.quote('ID'), db.quote('AUTHOR'))) + cursor = db.cursor() + db.update_sequence(cursor, 'HOURS', 'ID') + + with self.env.db_transaction as db: + cursor = db.cursor() + cursor.execute( + "INSERT INTO %s (%s) VALUES ('next-id')" + % (db.quote('HOURS'), db.quote('AUTHOR'))) + last_id = db.get_last_id(cursor, 'HOURS', 'ID') + + self.assertEqual(43, last_id) + + def test_table_names(self): + schema = default_schema + self.schema + with self.env.db_query as db: + db_tables = db.get_table_names() + self.assertEqual(len(schema), len(db_tables)) + for table in schema: + self.assertIn(table.name, db_tables) + + def test_get_column_names(self): + schema = default_schema + self.schema + with self.env.db_transaction as db: + for table in schema: + db_columns = db.get_column_names(table.name) + self.assertEqual(len(table.columns), len(db_columns)) + for column in table.columns: + self.assertIn(column.name, db_columns) + def suite(): suite = unittest.TestSuite() Modified: bloodhound/vendor/trac/current/trac/db/tests/mysql_test.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/tests/mysql_test.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/db/tests/mysql_test.py (original) +++ bloodhound/vendor/trac/current/trac/db/tests/mysql_test.py Fri Nov 14 11:06:23 2014 @@ -13,10 +13,10 @@ import unittest +import trac.tests.compat from trac.db.mysql_backend import MySQLConnector from trac.db.schema import Table, Column, Index from trac.test import EnvironmentStub, Mock -from trac.tests import compat class MySQLTableAlterationSQLTest(unittest.TestCase): Modified: bloodhound/vendor/trac/current/trac/db/tests/util.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/tests/util.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/db/tests/util.py (original) +++ bloodhound/vendor/trac/current/trac/db/tests/util.py Fri Nov 14 11:06:23 2014 @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2010-2013 Edgewall Software +# Copyright (C) 2010-2014 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which @@ -31,6 +31,37 @@ class SQLEscapeTestCase(unittest.TestCas self.assertEqual("'%% %%'", sql_escape_percent("'% %'")) self.assertEqual("'%%s %%i'", sql_escape_percent("'%s %i'")) + self.assertEqual("%", sql_escape_percent("%")) + self.assertEqual("`%%`", sql_escape_percent("`%`")) + self.assertEqual("``%``", sql_escape_percent("``%``")) + self.assertEqual("```%%```", sql_escape_percent("```%```")) + self.assertEqual("```%%`", sql_escape_percent("```%`")) + self.assertEqual("%s", sql_escape_percent("%s")) + self.assertEqual("% %", sql_escape_percent("% %")) + self.assertEqual("%s %i", sql_escape_percent("%s %i")) + self.assertEqual("`%%s`", sql_escape_percent("`%s`")) + self.assertEqual("`%% %%`", sql_escape_percent("`% %`")) + self.assertEqual("`%%s %%i`", sql_escape_percent("`%s %i`")) + + self.assertEqual('%', sql_escape_percent('%')) + self.assertEqual('"%%"', sql_escape_percent('"%"')) + self.assertEqual('""%""', sql_escape_percent('""%""')) + self.assertEqual('"""%%"""', sql_escape_percent('"""%"""')) + self.assertEqual('"""%%"', sql_escape_percent('"""%"')) + self.assertEqual('%s', sql_escape_percent('%s')) + self.assertEqual('% %', sql_escape_percent('% %')) + self.assertEqual('%s %i', sql_escape_percent('%s %i')) + self.assertEqual('"%%s"', sql_escape_percent('"%s"')) + self.assertEqual('"%% %%"', sql_escape_percent('"% %"')) + self.assertEqual('"%%s %%i"', sql_escape_percent('"%s %i"')) + + self.assertEqual("""'%%?''"%%s`%%i`%%%%"%%S'""", + sql_escape_percent("""'%?''"%s`%i`%%"%S'""")) + self.assertEqual("""`%%?``'%%s"%%i"%%%%'%%S`""", + sql_escape_percent("""`%?``'%s"%i"%%'%S`""")) + self.assertEqual('''"%%?""`%%s'%%i'%%%%`%%S"''', + sql_escape_percent('''"%?""`%s'%i'%%`%S"''')) + def suite(): suite = unittest.TestSuite() Modified: bloodhound/vendor/trac/current/trac/db/util.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db/util.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/db/util.py (original) +++ bloodhound/vendor/trac/current/trac/db/util.py Fri Nov 14 11:06:23 2014 @@ -15,11 +15,18 @@ # # Author: Christopher Lenz <cml...@gmx.de> +import re + +_sql_escape_percent_re = re.compile(""" + '(?:[^']+|'')*' | + `(?:[^`]+|``)*` | + "(?:[^"]+|"")*" """, re.VERBOSE) + def sql_escape_percent(sql): - import re - return re.sub("'((?:[^']|(?:''))*)'", - lambda m: m.group(0).replace('%', '%%'), sql) + def repl(match): + return match.group(0).replace('%', '%%') + return _sql_escape_percent_re.sub(repl, sql) class IterableCursor(object): @@ -118,7 +125,7 @@ class ConnectionWrapper(object): """ dql = self.check_select(query) cursor = self.cnx.cursor() - cursor.execute(query, params) + cursor.execute(query, params if params is not None else []) rows = cursor.fetchall() if dql else None cursor.close() return rows Modified: bloodhound/vendor/trac/current/trac/db_default.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/db_default.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/db_default.py (original) +++ bloodhound/vendor/trac/current/trac/db_default.py Fri Nov 14 11:06:23 2014 @@ -300,8 +300,7 @@ USER dynamic variable, replaced with the logged in user when executed. """, """\ -SELECT DISTINCT - p.value AS __color__, +SELECT p.value AS __color__, (CASE WHEN owner = $USER AND status = 'accepted' THEN 'Accepted' WHEN owner = $USER THEN 'Owned' @@ -313,12 +312,14 @@ SELECT DISTINCT reporter AS _reporter FROM ticket t LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' - LEFT JOIN ticket_change tc ON tc.ticket = t.id AND tc.author = $USER - AND tc.field = 'comment' - WHERE t.status <> 'closed' - AND (owner = $USER OR reporter = $USER OR author = $USER) - ORDER BY (owner = $USER AND status = 'accepted') DESC, - owner = $USER DESC, reporter = $USER DESC, + WHERE t.status <> 'closed' AND + (owner = $USER OR reporter = $USER OR + EXISTS (SELECT * FROM ticket_change tc + WHERE tc.ticket = t.id AND tc.author = $USER AND + tc.field = 'comment')) + ORDER BY (COALESCE(owner, '') = $USER AND status = 'accepted') DESC, + COALESCE(owner, '') = $USER DESC, + COALESCE(reporter, '') = $USER DESC, """ + db.cast('p.value', 'int') + """, milestone, t.type, t.time """), #---------------------------------------------------------------------------- Modified: bloodhound/vendor/trac/current/trac/dist.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/dist.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/dist.py (original) +++ bloodhound/vendor/trac/current/trac/dist.py Fri Nov 14 11:06:23 2014 @@ -466,6 +466,17 @@ try: self.run_command('compile_catalog') def run(self): self.l10n_run() + # When bdist_egg is called on distribute 0.6.29 and later, the + # egg file includes no *.mo and *.js files which are generated + # in l10n_run() method. + # We remove build_py.data_files property to re-compute in order + # to avoid the issue (#11640). + build_py = self.get_finalized_command('build_py') + if 'data_files' in build_py.__dict__ and \ + not any(any(name.endswith('.mo') for name in filenames) + for pkg, src_dir, build_dir, filenames + in build_py.data_files): + del build_py.__dict__['data_files'] _install_lib.run(self) return build, install_lib Modified: bloodhound/vendor/trac/current/trac/env.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/env.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/env.py (original) +++ bloodhound/vendor/trac/current/trac/env.py Fri Nov 14 11:06:23 2014 @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2003-2011 Edgewall Software +# Copyright (C) 2003-2014 Edgewall Software # Copyright (C) 2003-2007 Jonas Borgström <jo...@edgewall.com> # All rights reserved. # @@ -26,7 +26,8 @@ from urlparse import urlsplit from trac import db_default from trac.admin import AdminCommandError, IAdminCommandProvider from trac.cache import CacheManager -from trac.config import * +from trac.config import BoolOption, ConfigSection, Configuration, Option, \ + PathOption from trac.core import Component, ComponentManager, implements, Interface, \ ExtensionPoint, TracError from trac.db.api import (DatabaseManager, QueryContextManager, @@ -392,7 +393,8 @@ class Environment(Component, ComponentMa def get_db_cnx(self): """Return a database connection from the connection pool - :deprecated: Use :meth:`db_transaction` or :meth:`db_query` instead + :deprecated: Use :meth:`db_transaction` or :meth:`db_query` instead. + Removed in Trac 1.1.2. `db_transaction` for obtaining the `db` database connection which can be used for performing any query @@ -433,13 +435,21 @@ class Environment(Component, ComponentMa return DatabaseManager(self).get_exceptions() def with_transaction(self, db=None): - """Decorator for transaction functions :deprecated:""" + """Decorator for transaction functions. + + :deprecated: Use the query and transaction context managers instead. + Will be removed in Trac 1.3.1. + """ return with_transaction(self, db) def get_read_db(self): - """Return a database connection for read purposes :deprecated: + """Return a database connection for read purposes. - See `trac.db.api.get_read_db` for detailed documentation.""" + See `trac.db.api.get_read_db` for detailed documentation. + + :deprecated: Use :meth:`db_query` instead. + Will be removed in Trac 1.3.1. + """ return DatabaseManager(self).get_connection(readonly=True) @property @@ -581,6 +591,25 @@ class Environment(Component, ComponentMa # Create the database DatabaseManager(self).init_db() + @lazy + def database_version(self): + """Returns the current version of the database. + + :since 1.0.2: + """ + return self.get_version() + + @lazy + def database_initial_version(self): + """Returns the version of the database at the time of creation. + + In practice, for database created before 0.11, this will + return `False` which is "older" than any db version number. + + :since 1.0.2: + """ + return self.get_version(initial=True) + def get_version(self, db=None, initial=False): """Return the current version of the database. If the optional argument `initial` is set to `True`, the version of @@ -593,6 +622,11 @@ class Environment(Component, ComponentMa :since 1.0: deprecation warning: the `db` parameter is no longer used and will be removed in version 1.1.1 + + :since 1.0.2: The lazily-evaluated attributes `database_version` and + `database_initial_version` should be used instead. This + method will be renamed to a private method in + release 1.3.1. """ rows = self.db_query(""" SELECT value FROM system WHERE name='%sdatabase_version' @@ -711,6 +745,7 @@ class Environment(Component, ComponentMa participant.upgrade_environment(db) # Database schema may have changed, so close all connections DatabaseManager(self).shutdown() + del self.database_version return True @lazy @@ -749,7 +784,7 @@ class EnvironmentSetup(Component): self._update_sample_config() def environment_needs_upgrade(self, db): - dbver = self.env.get_version() + dbver = self.env.database_version if dbver == db_default.db_version: return False elif dbver > db_default.db_version: @@ -763,7 +798,7 @@ class EnvironmentSetup(Component): upgrades/dbN.py, where 'N' is the version number (int). """ cursor = db.cursor() - dbver = self.env.get_version() + dbver = self.env.database_version for i in range(dbver + 1, db_default.db_version + 1): name = 'db%i' % i try: @@ -787,9 +822,8 @@ class EnvironmentSetup(Component): if not os.path.isfile(filename): return config = Configuration(filename) - for section, default_options in config.defaults().iteritems(): - for name, value in default_options.iteritems(): - config.set(section, name, value) + for (section, name), option in Option.get_registry().iteritems(): + config.set(section, name, option.dumps(option.default)) try: config.save() self.log.info("Wrote sample configuration file with the new " Modified: bloodhound/vendor/trac/current/trac/htdocs/css/admin.css URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/htdocs/css/admin.css?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/htdocs/css/admin.css (original) +++ bloodhound/vendor/trac/current/trac/htdocs/css/admin.css Fri Nov 14 11:06:23 2014 @@ -132,4 +132,3 @@ table.trac-pluglist td { padding-left: 1 padding: 0; white-space: nowrap; } -fieldset tr.field th { text-align: right; } Modified: bloodhound/vendor/trac/current/trac/htdocs/css/report.css URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/htdocs/css/report.css?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/htdocs/css/report.css (original) +++ bloodhound/vendor/trac/current/trac/htdocs/css/report.css Fri Nov 14 11:06:23 2014 @@ -25,7 +25,6 @@ .report div.reports { clear: both } - .report div.reports h2 { /* taken from .wikipage h2 */ border-bottom: 1px solid #ddd; @@ -81,8 +80,13 @@ h2.report-result { } #report-descr { margin: 0 2em; font-size: 90% } #report-notfound { margin: 2em; font-size: 110% } + +/* Report edit form */ +#content.report.edit form { + max-width: 54em; +} #content.report .field { margin: 1em 0; } -#content.report .field label { padding-bottom: .3em; } +#content.report .field label { display: block; padding-bottom: .3em; } #query { clear: right } #query fieldset, #query fieldset input, #query fieldset select { @@ -179,9 +183,9 @@ h2.report-result { .tickets tr.color2-even { background: #ffd; border-color: #dd8; color: #880 } .tickets tr.color3-odd { background: #fbfbfb; border-color: #ddd; color: #444 } .tickets tr.color3-even { background: #f6f6f6; border-color: #ccc; color: #333 } -.tickets tr.color4-odd { background: #e7ffff; border-color: #cee; color: #099 } +.tickets tr.color4-odd { background: #e7ffff; border-color: #cee; color: #099 } .tickets tr.color4-even { background: #dff; border-color: #bee; color: #099 } -.tickets tr.color5-odd { background: #e7eeff; border-color: #cde; color: #469 } +.tickets tr.color5-odd { background: #e7eeff; border-color: #cde; color: #469 } .tickets tr.color5-even { background: #dde7ff; border-color: #cde; color: #469 } .tickets tr.color6-odd { background: #f0f0f0; border-color: #ddd; color: #888 } .tickets tr.color6-even { background: #f7f7f7; border-color: #ddd; color: #888 } @@ -207,7 +211,7 @@ table.tickets tbody tr.prio1 { backgroun table.tickets tbody tr.even.prio1 { background: #fed; border-color: #e99 } table.tickets tbody tr.prio2 { background: #ffb; border-color: #eea } table.tickets tbody tr.even.prio2 { background: #ffd; border-color: #dd8 } -table.tickets tbody tr.prio3 { background: #fbfbfb; border-color: #ddd } +table.tickets tbody tr.prio3 { background: #fbfbfb; border-color: #ddd } table.tickets tbody tr.even.prio3 { background: #f6f6f6; border-color: #ccc } table.tickets tbody tr.prio4 { background: #e7ffff; border-color: #cee } table.tickets tbody tr.even.prio4 { background: #dff; border-color: #bee } @@ -216,10 +220,10 @@ table.tickets tbody tr.even.prio5 { back table.tickets tbody tr.prio6 { background: #f0f0f0; border-color: #ddd } table.tickets tbody tr.even.prio6 { background: #f7f7f7 } table.tickets tbody tr.fullrow th { - border: none; - vertical-align: middle; - text-align: center; - font-size: 85%; + border: none; + vertical-align: middle; + text-align: center; + font-size: 85%; } table.tickets tbody tr p:first-child { margin-top: 0 } table.tickets tbody tr p:last-child { margin-bottom: 0 } @@ -227,7 +231,7 @@ table.tickets tbody tr p:last-child { ma /* Batchmod Form */ #batchmod_form { display: none; } -#batchmod_form fieldset input#batchmod_submit { font-size: 14px; } +#batchmod_form fieldset input#batchmod_submit { font-size: 100% } #batchmod_form fieldset input[type="button"]{ padding: 0.1em 0.5em; } #batchmod_form > fieldset { margin-top: 1.5em } #batchmod_form fieldset.collapsed { @@ -238,10 +242,8 @@ table.tickets tbody tr p:last-child { ma .batchmod_property { width: 100%; } .batchmod_required:before { content: " * "; } #batchmod_form fieldset input, -#batchmod_form fieldset select, -.batchmod_property, -.batchmod_label { - font-size: 11px; +#batchmod_form fieldset select, .batchmod_property, .batchmod_label { + font-size: 11px; } #batchmod_action { margin-top: 0; line-height: 2em; } #batchmod_form th { Modified: bloodhound/vendor/trac/current/trac/htdocs/css/roadmap.css URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/htdocs/css/roadmap.css?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/htdocs/css/roadmap.css (original) +++ bloodhound/vendor/trac/current/trac/htdocs/css/roadmap.css Fri Nov 14 11:06:23 2014 @@ -95,6 +95,3 @@ p.percent { #edit .field { margin: 0.5em 0 } #edit label { padding-left: .2em } #edit fieldset { margin-left: 1px; margin-right: 1px } -#edit textarea#description { margin-left: -1px; margin-right: -1px; padding: 0; width: 100% } -#edit .wikitoolbar { margin-left: -1px } -#edit div.trac-resizable { width: 100% } Modified: bloodhound/vendor/trac/current/trac/htdocs/css/ticket.css URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/htdocs/css/ticket.css?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/htdocs/css/ticket.css (original) +++ bloodhound/vendor/trac/current/trac/htdocs/css/ticket.css Fri Nov 14 11:06:23 2014 @@ -8,7 +8,6 @@ } #field-description-help { float: right } -#properties div.trac-resizable, #field-description { width: 100% } #content.ticket .trac-topnav { float: none; @@ -158,14 +157,7 @@ ul.children > li.child { /* Comment editor */ #trac-comment-editor { margin-left: 2em; margin-bottom: 1em } -#trac-comment-editor div.trac-resizable { width: 100% } -#trac-comment-editor textarea { - background: #ffffe0; - margin-left: -1px; - margin-right: -1px; - width: 100%; -} -#trac-comment-editor .wikitoolbar { margin-left: -1px } +#trac-comment-editor textarea { background: #ffffe0; } .trac-new { border-left: 0.31em solid #c0f0c0; padding-left: 0.31em; } .trac-loading { @@ -208,22 +200,39 @@ button.trac-revert div { display: none; form .field { margin-top: .75em; width: 100% } form .field fieldset { margin-left: 1px; margin-right: 1px } label[for=comment] { float: right } -#comment { margin-left: -1px; margin-right: -1px; padding: 0; width: 100% } -form .field .wikitoolbar { margin-left: -1px } -form .field div.trac-resizable { width: 100% } #propertyform { margin-bottom: 2em; } #properties { white-space: nowrap; line-height: 160%; padding: .5em } -#properties table { border-spacing: 0; width: 100%; padding: 0 .5em } -#properties table th { +#properties table { + border-spacing: 0; + padding: 0 .5em; + table-layout: fixed; + width: 100%; +} +#properties table th, +#properties table col.th { padding: .4em; text-align: right; - width: 20%; vertical-align: top; + white-space: normal; + width: 17%; } #properties table th.col2 { border-left: 1px dotted #d7d7d7 } -#properties table td { vertical-align: middle; width: 30% } -#properties table td.fullrow { vertical-align: middle; width: 80% } +#properties table td, +#properties table col.td { + padding-right: 0.6em; + vertical-align: middle; + width: 33% +} +#properties table td.fullrow { width: 83% } +#properties table td input[type="text"] { + -moz-box-sizing: border-box; + box-sizing: border-box; + width: 100%; +} +#properties table td.col1 label, +#properties table td.col2 label { float: left; margin-right: 0.5em; } +#properties table td select { max-width: 100% } #action { line-height: 2em } Modified: bloodhound/vendor/trac/current/trac/htdocs/css/trac.css URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/htdocs/css/trac.css?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/htdocs/css/trac.css (original) +++ bloodhound/vendor/trac/current/trac/htdocs/css/trac.css Fri Nov 14 11:06:23 2014 @@ -82,6 +82,11 @@ span:target { /* Forms */ input, textarea, select { margin: 2px } +/* Avoid respect to system font settings for controls on Firefox, #11607 */ +input, select, button { + font-family: Arial,Verdana,'Bitstream Vera Sans',Helvetica,sans-serif; + font-size: 100%; +} /* Avoid to inherit white-space of its parent element for IE 11, #11376 */ textarea { white-space: pre-wrap } input, select { vertical-align: middle } @@ -178,6 +183,14 @@ input[type=button].trac-delete:hover, input[type=submit].trac-delete:hover { color: #e31313; } +textarea.trac-fullwidth, input.trac-fullwidth { + -moz-box-sizing: border-box; + box-sizing: border-box; + margin-left: 0; + margin-right: 0; + width: 100%; +} +textarea.trac-fullwidth { padding: 2px; } /* Header */ #header hr { display: none } @@ -239,7 +252,7 @@ input[type=submit].trac-delete:hover { outline: 0; background: transparent; font-family: inherit; - font-size: inherit; + font-size: 100%; color: #b00; border-bottom: 1px dotted #bbb; cursor: pointer; @@ -564,7 +577,6 @@ table.wiki tbody tr.odd { background-col .wikitoolbar { margin-top: 0.3em; - margin-left: 2px; border: solid #d7d7d7; border-width: 1px 1px 1px 0; height: 18px; @@ -595,7 +607,7 @@ table.wiki tbody tr.odd { background-col .wikitoolbar a#img { background-position: 0 -128px } /* Textarea resizer */ -div.trac-resizable { display: table; width: 1px } +div.trac-resizable { display: table; width: 100% } div.trac-resizable > div { display: table-cell } div.trac-resizable textarea { display: block; margin-bottom: 0 } div.trac-grip { Modified: bloodhound/vendor/trac/current/trac/htdocs/css/wiki.css URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/htdocs/css/wiki.css?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/htdocs/css/wiki.css (original) +++ bloodhound/vendor/trac/current/trac/htdocs/css/wiki.css Fri Nov 14 11:06:23 2014 @@ -50,15 +50,11 @@ #edit fieldset { margin-left: 1px; margin-right: 1px } #edit #text { clear: both; - margin-left: -1px; - margin-right: -1px; - padding: 0; - width: 100%; min-height: 10em; resize: vertical; } -#edit .wikitoolbar { float: left; margin-left: -1px } -#edit div.trac-resizable { clear: both; width: 100% } +#edit .wikitoolbar { float: left } +#edit div.trac-resizable { clear: both } #edit + #info { margin-top: 1em } #edit + #attachments { margin-top: 1.5em } #changeinfo { padding: .5em } Modified: bloodhound/vendor/trac/current/trac/htdocs/js/auto_preview.js URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/htdocs/js/auto_preview.js?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== Binary files - no diff available. Modified: bloodhound/vendor/trac/current/trac/htdocs/js/wikitoolbar.js URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/htdocs/js/wikitoolbar.js?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== Binary files - no diff available. Modified: bloodhound/vendor/trac/current/trac/loader.py URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/loader.py?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/loader.py (original) +++ bloodhound/vendor/trac/current/trac/loader.py Fri Nov 14 11:06:23 2014 @@ -182,7 +182,10 @@ def get_plugin_info(env, include_core=Fa version = (getattr(module, 'version', '') or getattr(module, 'revision', '')) # special handling for "$Rev$" strings - version = version.replace('$', '').replace('Rev: ', 'r') + if version != '$Rev$': + version = version.replace('$', '').replace('Rev: ', 'r') + else: # keyword hasn't been expanded + version = '' plugins[dist.project_name] = { 'name': dist.project_name, 'version': version, 'path': dist.location, 'plugin_filename': plugin_filename, Modified: bloodhound/vendor/trac/current/trac/locale/de/LC_MESSAGES/messages.po URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/locale/de/LC_MESSAGES/messages.po?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/locale/de/LC_MESSAGES/messages.po (original) +++ bloodhound/vendor/trac/current/trac/locale/de/LC_MESSAGES/messages.po Fri Nov 14 11:06:23 2014 @@ -4948,7 +4948,7 @@ msgstr "Repositorys" #, python-format msgid "You should now run %(resync)s to synchronize Trac with the repository." msgstr "" -"Sie sollten jetzt %(resync)s ausführen, um Trac mit dem Reposiory zu " +"Sie sollten jetzt %(resync)s ausführen, um Trac mit dem Repository zu " "synchronisieren." #: trac/versioncontrol/admin.py:225 Modified: bloodhound/vendor/trac/current/trac/locale/ja/LC_MESSAGES/messages-js.po URL: http://svn.apache.org/viewvc/bloodhound/vendor/trac/current/trac/locale/ja/LC_MESSAGES/messages-js.po?rev=1639602&r1=1639601&r2=1639602&view=diff ============================================================================== --- bloodhound/vendor/trac/current/trac/locale/ja/LC_MESSAGES/messages-js.po (original) +++ bloodhound/vendor/trac/current/trac/locale/ja/LC_MESSAGES/messages-js.po Fri Nov 14 11:06:23 2014 @@ -1,13 +1,13 @@ # Japanese translations for Trac. -# Copyright (C) 2010-2013 Edgewall Software +# Copyright (C) 2010-2014 Edgewall Software # This file is distributed under the same license as the Trac project. -# Jun Omae <jun6...@gmail.com>, 2010-2013. +# Jun Omae <jun6...@gmail.com>, 2010-2014. # msgid "" msgstr "" -"Project-Id-Version: Trac 1.0\n" +"Project-Id-Version: Trac 1.0.2\n" "Report-Msgid-Bugs-To: trac-...@googlegroups.com\n" -"POT-Creation-Date: 2013-03-21 22:54+0100\n" +"POT-Creation-Date: 2014-09-01 12:43+0000\n" "PO-Revision-Date: 2010-05-25 18:45+0900\n" "Last-Translator: Jun Omae <jun6...@gmail.com>\n" "Language-Team: ja <l...@li.org>\n" @@ -15,7 +15,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 0.9.6dev-r0\n" +"Generated-By: Babel 0.9.6\n" #: trac/htdocs/js/blame.js:84 msgid "(no changeset information)" @@ -76,7 +76,7 @@ msgstr "$yearå¹´$month" #. TRANSLATOR: Link that closes the datepicker #. TRANSLATOR: Link that closes the timepicker -#: trac/htdocs/js/jquery-ui-i18n.js:7 trac/htdocs/js/jquery-ui-i18n.js:39 +#: trac/htdocs/js/jquery-ui-i18n.js:7 trac/htdocs/js/jquery-ui-i18n.js:40 msgid "Done" msgstr "éãã" @@ -101,34 +101,34 @@ msgid "Wk" msgstr "é±" #. TRANSLATOR: Heading of the standalone timepicker -#: trac/htdocs/js/jquery-ui-i18n.js:30 +#: trac/htdocs/js/jquery-ui-i18n.js:31 msgid "Choose Time" msgstr "æéãé¸æ" #. TRANSLATOR: Time selector label -#: trac/htdocs/js/jquery-ui-i18n.js:32 +#: trac/htdocs/js/jquery-ui-i18n.js:33 msgid "Time" msgstr "æé" #. TRANSLATOR: Time labels in the timepicker -#: trac/htdocs/js/jquery-ui-i18n.js:34 +#: trac/htdocs/js/jquery-ui-i18n.js:35 msgid "Hour" msgstr "æ" -#: trac/htdocs/js/jquery-ui-i18n.js:34 +#: trac/htdocs/js/jquery-ui-i18n.js:35 msgid "Minute" msgstr "å" -#: trac/htdocs/js/jquery-ui-i18n.js:34 +#: trac/htdocs/js/jquery-ui-i18n.js:35 msgid "Second" msgstr "ç§" -#: trac/htdocs/js/jquery-ui-i18n.js:35 +#: trac/htdocs/js/jquery-ui-i18n.js:36 msgid "Time Zone" msgstr "ã¿ã¤ã ã¾ã¼ã³" #. TRANSLATOR: Link to pick the current time in the timepicker -#: trac/htdocs/js/jquery-ui-i18n.js:37 +#: trac/htdocs/js/jquery-ui-i18n.js:38 msgid "Now" msgstr "ç¾æå»" @@ -169,7 +169,7 @@ msgstr " 追å :" msgid "Select ticket %(id)s for modification" msgstr "æ´æ°å¯¾è±¡ã¨ãã¦ãã±ãã %(id)s ãé¸æãã" -#: trac/htdocs/js/query.js:387 +#: trac/htdocs/js/query.js:388 msgid "Toggle selection of all tickets shown in this group" msgstr "ãã®ã°ã«ã¼ãã«è¡¨ç¤ºãã¦ãããã¹ã¦ã®ãã±ããã«å¯¾ããé¸æãåãæ¿ãã" @@ -177,39 +177,39 @@ msgstr "ãã®ã°ã«ã¼ã msgid "Link here" msgstr "ããã«ãªã³ã¯ãã" -#: trac/htdocs/js/wikitoolbar.js:56 +#: trac/htdocs/js/wikitoolbar.js:59 msgid "Bold text: '''Example'''" msgstr "太å: '''ä¾'''" -#: trac/htdocs/js/wikitoolbar.js:59 +#: trac/htdocs/js/wikitoolbar.js:62 msgid "Italic text: ''Example''" msgstr "æä½: '''ä¾'''" -#: trac/htdocs/js/wikitoolbar.js:62 +#: trac/htdocs/js/wikitoolbar.js:65 msgid "Heading: == Example ==" msgstr "ããã: == ä¾ ==" -#: trac/htdocs/js/wikitoolbar.js:65 +#: trac/htdocs/js/wikitoolbar.js:68 msgid "Link: [http://www.example.com/ Example]" msgstr "ãªã³ã¯: [http://www.example.com/ ä¾]" -#: trac/htdocs/js/wikitoolbar.js:68 +#: trac/htdocs/js/wikitoolbar.js:71 msgid "Code block: {{{ example }}}" msgstr "ã³ã¼ããããã¯: {{{ ä¾ }}}" -#: trac/htdocs/js/wikitoolbar.js:71 +#: trac/htdocs/js/wikitoolbar.js:74 msgid "Horizontal rule: ----" msgstr "横罫ç·: ----" -#: trac/htdocs/js/wikitoolbar.js:74 +#: trac/htdocs/js/wikitoolbar.js:77 msgid "New paragraph" msgstr "段è½" -#: trac/htdocs/js/wikitoolbar.js:77 +#: trac/htdocs/js/wikitoolbar.js:80 msgid "Line break: [[BR]]" msgstr "æ¹è¡: [[BR]]" -#: trac/htdocs/js/wikitoolbar.js:80 +#: trac/htdocs/js/wikitoolbar.js:83 msgid "Image: [[Image()]]" msgstr "ç»å: [[Image()]]"