예제 #1
0
파일: config.py 프로젝트: exocad/exotrac
    def __get__(self, instance, owner):
        if instance is None:
            return self
        order = ListOption.__get__(self, instance, owner)
        components = []
        implementing_classes = []
        for impl in self.xtnpt.extensions(instance):
            implementing_classes.append(impl.__class__.__name__)
            if self.include_missing or impl.__class__.__name__ in order:
                components.append(impl)
        not_found = sorted(set(order) - set(implementing_classes))
        if not_found:
            raise ConfigurationError(
                tag_("Cannot find implementation(s) of the %(interface)s "
                     "interface named %(implementation)s. Please check "
                     "that the Component is enabled or update the option "
                     "%(option)s in trac.ini.",
                     interface=tag.tt(self.xtnpt.interface.__name__),
                     implementation=tag(
                         (', ' if idx != 0 else None, tag.tt(impl))
                         for idx, impl in enumerate(not_found)),
                     option=tag.tt("[%s] %s" % (self.section, self.name))))

        def compare(x, y):
            x, y = x.__class__.__name__, y.__class__.__name__
            if x not in order:
                return int(y in order)
            if y not in order:
                return -int(x in order)
            return cmp(order.index(x), order.index(y))
        components.sort(compare)
        return components
예제 #2
0
    def __get__(self, instance, owner):
        if instance is None:
            return self
        order = ListOption.__get__(self, instance, owner)
        components = []
        implementing_classes = []
        for impl in self.xtnpt.extensions(instance):
            implementing_classes.append(impl.__class__.__name__)
            if self.include_missing or impl.__class__.__name__ in order:
                components.append(impl)
        not_found = sorted(set(order) - set(implementing_classes))
        if not_found:
            raise ConfigurationError(
                tag_("Cannot find implementation(s) of the %(interface)s "
                     "interface named %(implementation)s. Please check "
                     "that the Component is enabled or update the option "
                     "%(option)s in trac.ini.",
                     interface=tag.tt(self.xtnpt.interface.__name__),
                     implementation=tag(
                         (', ' if idx != 0 else None, tag.tt(impl))
                         for idx, impl in enumerate(not_found)),
                     option=tag.tt("[%s] %s" % (self.section, self.name))))

        def compare(x, y):
            x, y = x.__class__.__name__, y.__class__.__name__
            if x not in order:
                return int(y in order)
            if y not in order:
                return -int(x in order)
            return cmp(order.index(x), order.index(y))
        components.sort(compare)
        return components
예제 #3
0
def _arg_as_int(val, key=None, min=None, max=None):
    int_val = as_int(val, None, min=min, max=max)
    if int_val is None:
        raise MacroError(
            tag_("Invalid macro argument %(expr)s",
                 expr=tag.tt("%s=%s" % (key, val)) if key else tag.tt(val)))
    return int_val
예제 #4
0
파일: admin.py 프로젝트: nyuhuhuu/trachacks
 def _do_repositories(self, req, category, page):
     # Check that the setttings have been set.
     parentpath = self.config.get('svnadmin', 'parent_path')
     client = self.config.get('svnadmin', 'svn_client_location')
     admin = self.config.get('svnadmin', 'svnadmin_location')
     if not parentpath or not client or not admin:
         add_warning(req, _('You must provide settings before continuing.'))
         req.redirect(req.href.admin(category, 'config'))
     
     data = {}
     
     svn_provider = self.env[SvnRepositoryProvider]
     db_provider = self.env[DbRepositoryProvider]
     
     if req.method == 'POST':
         # Add a repository
         if svn_provider and req.args.get('add_repos'):
             name = req.args.get('name')
             dir = os.path.join(parentpath, name)
             if name is None or name == "" or not dir:
                 add_warning(req, _('Missing arguments to add a repository.'))
             elif self._check_dir(req, dir):
                 try:
                     svn_provider.add_repository(name)
                     db_provider.add_repository(name, dir, 'svn')
                     add_notice(req, _('The repository "%(name)s" has been '
                                       'added.', name=name))
                     resync = tag.tt('trac-admin $ENV repository resync '
                                     '"%s"' % name)
                     msg = tag_('You should now run %(resync)s to '
                                'synchronize Trac with the repository.',
                                resync=resync)
                     add_notice(req, msg)
                     cset_added = tag.tt('trac-admin $ENV changeset '
                                         'added "%s" $REV' % name)
                     msg = tag_('You should also set up a post-commit hook '
                                'on the repository to call %(cset_added)s '
                                'for each committed changeset.',
                                cset_added=cset_added)
                     add_notice(req, msg)
                     req.redirect(req.href.admin(category, page))
                 except TracError, why:
                     add_warning(req, str(why))
         
         # Remove repositories
         elif svn_provider and req.args.get('remove'):
             sel = req.args.getlist('sel')
             if sel:
                 for name in sel:
                     svn_provider.remove_repository(name)
                     db_provider.remove_repository(name)
                 add_notice(req, _('The selected repositories have '
                                   'been removed.'))
                 req.redirect(req.href.admin(category, page))
             add_warning(req, _('No repositories were selected.'))
예제 #5
0
파일: config.py 프로젝트: exocad/exotrac
 def __get__(self, instance, owner):
     if instance is None:
         return self
     value = Option.__get__(self, instance, owner)
     for impl in self.xtnpt.extensions(instance):
         if impl.__class__.__name__ == value:
             return impl
     raise ConfigurationError(
         tag_("Cannot find an implementation of the %(interface)s "
              "interface named %(implementation)s. Please check "
              "that the Component is enabled or update the option "
              "%(option)s in trac.ini.",
              interface=tag.tt(self.xtnpt.interface.__name__),
              implementation=tag.tt(value),
              option=tag.tt("[%s] %s" % (self.section, self.name))))
예제 #6
0
    def send(self, from_addr, recipients, message):
        # Ensure the message complies with RFC2822: use CRLF line endings
        message = fix_eol(message, CRLF)

        self.log.info("Sending notification through SMTP at %s:%d to %s",
                      self.smtp_server, self.smtp_port, recipients)
        try:
            server = smtplib.SMTP(self.smtp_server, self.smtp_port)
        except smtplib.socket.error, e:
            raise ConfigurationError(
                tag_("SMTP server connection error (%(error)s). Please "
                     "modify %(option1)s or %(option2)s in your "
                     "configuration.",
                     error=to_unicode(e),
                     option1=tag.tt("[notification] smtp_server"),
                     option2=tag.tt("[notification] smtp_port")))
예제 #7
0
    def expand_macro(self, formatter, name, args):
        from trac.config import Option
        section_filter = key_filter = ''
        args, kw = parse_args(args)
        if args:
            section_filter = args.pop(0).strip()
        if args:
            key_filter = args.pop(0).strip()

        registry = Option.get_registry(self.compmgr)
        sections = {}
        for (section, key), option in registry.iteritems():
            if section.startswith(section_filter):
                sections.setdefault(section, {})[key] = option

        return tag.div(class_='tracini')(
            (tag.h3(tag.code('[%s]' % section), id='%s-section' % section),
             tag.table(class_='wiki')(
                 tag.tbody(tag.tr(tag.td(tag.tt(option.name)),
                                  tag.td(format_to_oneliner(
                                      self.env, formatter.context,
                                      to_unicode(option.__doc__))))
                           for option in sorted(sections[section].itervalues(),
                                                key=lambda o: o.name)
                           if option.name.startswith(key_filter))))
            for section in sorted(sections))
예제 #8
0
    def _provider_failure(self, exc, req, ep, current_filters, all_filters):
        """Raise a TracError exception explaining the failure of a provider.

        At the same time, the message will contain a link to the timeline
        without the filters corresponding to the guilty event provider `ep`.
        """
        ep_name, exc_name = [i.__class__.__name__ for i in (ep, exc)]
        self.log.error("Timeline event provider failed: %s", exception_to_unicode(exc, traceback=True))

        guilty_filters = [f[0] for f in ep.get_timeline_filters(req)]
        guilty_kinds = [f[1] for f in ep.get_timeline_filters(req)]
        other_filters = [f for f in current_filters if not f in guilty_filters]
        if not other_filters:
            other_filters = [f for f in all_filters if not f in guilty_filters]
        args = [(a, req.args.get(a)) for a in ("from", "format", "max", "daysback")]
        href = req.href.timeline(args + [(f, "on") for f in other_filters])
        raise TracError(
            tag(
                tag.p(
                    ", ".join(guilty_kinds),
                    " event provider (",
                    tag.tt(ep_name),
                    ") failed:",
                    tag.br(),
                    exc_name,
                    ": ",
                    to_unicode(exc),
                    class_="message",
                ),
                tag.p("You may want to see the other kind of events from the ", tag.a("Timeline", href=href)),
            )
        )
예제 #9
0
    def expand_macro(self, formatter, name, args):
        from trac.mimeview.api import Mimeview
        mime_map = Mimeview(self.env).mime_map
        mime_type_filter = ''
        args, kw = parse_args(args)
        if args:
            mime_type_filter = args.pop(0).strip().rstrip('*')

        mime_types = {}
        for key, mime_type in mime_map.iteritems():
            if (not mime_type_filter or
                mime_type.startswith(mime_type_filter)) and key != mime_type:
                mime_types.setdefault(mime_type, []).append(key)

        return tag.div(class_='mimetypes')(
            tag.table(class_='wiki')(
                tag.thead(tag.tr(
                    tag.th(_("MIME Types")), # always use plural
                    tag.th(tag.a("WikiProcessors",
                                 href=formatter.context.href.wiki(
                                     'WikiProcessors'))))),
                tag.tbody(
                    tag.tr(tag.th(tag.tt(mime_type),
                                  style="text-align: left"),
                           tag.td(tag.code(
                               ' '.join(sorted(mime_types[mime_type])))))
                    for mime_type in sorted(mime_types.keys()))))
예제 #10
0
def _invalid_db_str(db_str):
    return ConfigurationError(
        tag_(
            "Invalid format %(db_str)s for the database connection string. "
            "Please refer to the %(doc)s for help.",
            db_str=tag.tt(db_str),
            doc=_doc_db_str()))
예제 #11
0
    def _provider_failure(self, exc, req, ep, current_filters, all_filters):
        """Raise a TracError exception explaining the failure of a provider.

        At the same time, the message will contain a link to the timeline
        without the filters corresponding to the guilty event provider `ep`.
        """
        self.log.error('Timeline event provider failed: %s',
                       exception_to_unicode(exc, traceback=True))

        ep_kinds = dict((f[0], f[1])
                        for f in ep.get_timeline_filters(req) or [])
        ep_filters = set(ep_kinds.keys())
        current_filters = set(current_filters)
        other_filters = set(current_filters) - ep_filters
        if not other_filters:
            other_filters = set(all_filters) -  ep_filters
        args = [(a, req.args.get(a)) for a in ('from', 'format', 'max',
                                               'daysback')]
        href = req.href.timeline(args + [(f, 'on') for f in other_filters])
        # TRANSLATOR: ...want to see the 'other kinds of events' from... (link)
        other_events = tag.a(_('other kinds of events'), href=href)
        raise TracError(tag(
            tag.p(tag_("Event provider %(name)s failed for filters "
                       "%(kinds)s: ",
                       name=tag.tt(ep.__class__.__name__),
                       kinds=', '.join('"%s"' % ep_kinds[f] for f in
                                       current_filters & ep_filters)),
                  tag.b(exception_to_unicode(exc)), class_='message'),
            tag.p(tag_("You may want to see the %(other_events)s from the "
                       "Timeline or notify your Trac administrator about the "
                       "error (detailed information was written to the log).",
                       other_events=other_events))))
예제 #12
0
 def _render_property(self, name, mode, context, props):
     repos, revs = props[name]
     def link(rev):
         chgset = repos.get_changeset(rev)
         return tag.a(rev, class_="changeset",
                      title=shorten_line(chgset.message),
                      href=context.href.changeset(rev, repos.reponame))
     if name == 'Parents' and len(revs) == 2: # merge
         new = context.resource.id
         parent_links = [
                 (link(rev), ' (',
                  tag.a('diff', title=_("Diff against this parent "
                        "(show the changes merged from the other parents)"),
                        href=context.href.changeset(new, repos.reponame, 
                                                    old=rev)), ')')
                        for rev in revs]
         return tag([(parent, ', ') for parent in parent_links[:-1]],
                    parent_links[-1], tag.br(),
                    tag.span(tag_("Note: this is a %(merge)s changeset, "
                                  "the changes displayed below correspond "
                                  "to the merge itself.",
                                  merge=tag.strong('merge')),
                             class_='hint'), tag.br(), 
                    # TODO: only keep chunks present in both parents 
                    #       (conflicts) or in none (extra changes)
                    # tag.span('No changes means the merge was clean.',
                    #         class_='hint'), tag.br(), 
                    tag.span(tag_("Use the %(diff)s links above to see all "
                                  "the changes relative to each parent.",
                                  diff=tag.tt('(diff)')),
                             class_='hint'))
     return tag([tag(link(rev), ', ') for rev in revs[:-1]],
                link(revs[-1]))
예제 #13
0
파일: macros.py 프로젝트: exocad/exotrac
    def expand_macro(self, formatter, name, content):
        from trac.mimeview.api import Mimeview
        mime_map = Mimeview(self.env).mime_map
        mime_type_filter = ''
        args, kw = parse_args(content)
        if args:
            mime_type_filter = args.pop(0).strip().rstrip('*')

        mime_types = {}
        for key, mime_type in mime_map.iteritems():
            if (not mime_type_filter or
                mime_type.startswith(mime_type_filter)) and key != mime_type:
                mime_types.setdefault(mime_type, []).append(key)

        return tag.div(class_='mimetypes')(
            tag.table(class_='wiki')(
                tag.thead(tag.tr(
                    tag.th(_("MIME Types")),  # always use plural
                    tag.th(tag.a("WikiProcessors",
                                 href=formatter.context.href.wiki(
                                     'WikiProcessors'))))),
                tag.tbody(
                    tag.tr(tag.th(tag.tt(mime_type),
                                  style="text-align: left"),
                           tag.td(tag.code(
                               ' '.join(sorted(mime_types[mime_type])))))
                    for mime_type in sorted(mime_types.keys()))))
예제 #14
0
    def __init__(self, path, log=None, params={}):
        if have_pysqlite == 0:
            raise TracError(_("Cannot load Python bindings for SQLite"))
        self.cnx = None
        if path != ':memory:':
            if not os.access(path, os.F_OK):
                raise ConfigurationError(
                    _('Database "%(path)s" not found.', path=path))

            dbdir = os.path.dirname(path)
            if not os.access(path, os.R_OK + os.W_OK) or \
                   not os.access(dbdir, os.R_OK + os.W_OK):
                raise ConfigurationError(
                    tag_(
                        "The user %(user)s requires read _and_ write permissions "
                        "to the database file %(path)s and the directory it is "
                        "located in.",
                        user=tag.tt(getuser()),
                        path=tag.tt(path)))

        self._active_cursors = weakref.WeakKeyDictionary()
        timeout = int(params.get('timeout', 10.0))
        self._eager = params.get('cursor', 'eager') == 'eager'
        # eager is default, can be turned off by specifying ?cursor=
        if isinstance(path, unicode):  # needed with 2.4.0
            path = path.encode('utf-8')
        cnx = sqlite.connect(path,
                             detect_types=sqlite.PARSE_DECLTYPES,
                             isolation_level=None,
                             check_same_thread=sqlite_version < (3, 3, 1),
                             timeout=timeout)
        # load extensions
        extensions = params.get('extensions', [])
        if len(extensions) > 0:
            cnx.enable_load_extension(True)
            for ext in extensions:
                cnx.load_extension(ext)
            cnx.enable_load_extension(False)

        cursor = cnx.cursor()
        _set_journal_mode(cursor, params.get('journal_mode'))
        _set_synchronous(cursor, params.get('synchronous'))
        cursor.close()
        cnx.isolation_level = 'DEFERRED'
        ConnectionWrapper.__init__(self, cnx, log)
예제 #15
0
 def render_property(self, name, mode, context, props):
     repos, value = props[name]
     try:
         return unicode(value)
     except UnicodeDecodeError:
         if len(value) <= 100:
             return tag.tt(''.join(("%02x" % ord(c)) for c in value))
         else:
             return tag.em(_("(binary, size greater than 100 bytes)"))
예제 #16
0
    def expand_macro(self, formatter, name, args):
        from trac.config import ConfigSection, Option
        section_filter = key_filter = ''
        args, kw = parse_args(args)
        if args:
            section_filter = args.pop(0).strip()
        if args:
            key_filter = args.pop(0).strip()

        def getdoc(option_or_section):
            doc = to_unicode(option_or_section.__doc__)
            if doc:
                doc = dgettext(option_or_section.doc_domain, doc)
            return doc

        registry = ConfigSection.get_registry(self.compmgr)
        sections = dict((name, getdoc(section))
                        for name, section in registry.iteritems()
                        if name.startswith(section_filter))

        registry = Option.get_registry(self.compmgr)
        options = {}
        for (section, key), option in registry.iteritems():
            if section.startswith(section_filter):
                options.setdefault(section, {})[key] = option
                sections.setdefault(section, '')

        def default_cell(option):
            default = option.default
            if default is True:
                default = 'true'
            elif default is False:
                default = 'false'
            elif default == 0:
                default = '0.0' if isinstance(default, float) else '0'
            elif default:
                default = ', '.join(to_unicode(val) for val in default) \
                          if isinstance(default, (list, tuple)) \
                          else to_unicode(default)
            else:
                return tag.td(_("(no default)"), class_='nodefault')
            return tag.td(tag.code(default), class_='default')

        return tag.div(class_='tracini')(
            (tag.h3(tag.code('[%s]' % section), id='%s-section' % section),
             format_to_html(self.env, formatter.context, section_doc),
             tag.table(class_='wiki')(tag.tbody(
                 tag.tr(
                     tag.td(tag.tt(option.name)),
                     tag.td(
                         format_to_oneliner(self.env, formatter.context,
                                            getdoc(option))),
                     default_cell(option))
                 for option in sorted(options.get(section, {}).itervalues(),
                                      key=lambda o: o.name)
                 if option.name.startswith(key_filter))))
            for section, section_doc in sorted(sections.iteritems()))
예제 #17
0
    def send(self, from_addr, recipients, message):
        global local_hostname
        # Ensure the message complies with RFC2822: use CRLF line endings
        message = fix_eol(message, CRLF)

        self.log.info("Sending notification through SMTP at %s:%d to %s",
                      self.smtp_server, self.smtp_port, recipients)
        try:
            server = smtplib.SMTP(self.smtp_server, self.smtp_port,
                                  local_hostname)
            local_hostname = server.local_hostname
        except smtplib.socket.error, e:
            raise ConfigurationError(
                tag_("SMTP server connection error (%(error)s). Please "
                     "modify %(option1)s or %(option2)s in your "
                     "configuration.",
                     error=to_unicode(e),
                     option1=tag.tt("[notification] smtp_server"),
                     option2=tag.tt("[notification] smtp_port")))
예제 #18
0
    def expand_macro(self, formatter, name, args):
        from trac.config import ConfigSection, Option
        section_filter = key_filter = ''
        args, kw = parse_args(args)
        if args:
            section_filter = args.pop(0).strip()
        if args:
            key_filter = args.pop(0).strip()

        def getdoc(option_or_section):
            doc = to_unicode(option_or_section.__doc__)
            if doc:
                doc = dgettext(option_or_section.doc_domain, doc)
            return doc

        registry = ConfigSection.get_registry(self.compmgr)
        sections = dict((name, getdoc(section))
                        for name, section in registry.iteritems()
                        if name.startswith(section_filter))

        registry = Option.get_registry(self.compmgr)
        options = {}
        for (section, key), option in registry.iteritems():
            if section.startswith(section_filter):
                options.setdefault(section, {})[key] = option
                sections.setdefault(section, '')

        def default_cell(option):
            default = option.default
            if default is True:
                default = 'true'
            elif default is False:
                default = 'false'
            elif default == 0:
                default = '0.0' if isinstance(default, float) else '0'
            elif default:
                default = ', '.join(to_unicode(val) for val in default) \
                          if isinstance(default, (list, tuple)) \
                          else to_unicode(default)
            else:
                return tag.td(_("(no default)"), class_='nodefault')
            return tag.td(tag.code(default), class_='default')

        return tag.div(class_='tracini')(
            (tag.h3(tag.code('[%s]' % section), id='%s-section' % section),
             format_to_html(self.env, formatter.context, section_doc),
             tag.table(class_='wiki')(tag.tbody(
                 tag.tr(tag.td(tag.tt(option.name)),
                        tag.td(format_to_oneliner(
                            self.env, formatter.context, getdoc(option))),
                        default_cell(option))
                 for option in sorted(options.get(section, {}).itervalues(),
                                      key=lambda o: o.name)
                 if option.name.startswith(key_filter))))
            for section, section_doc in sorted(sections.iteritems()))
예제 #19
0
    def __init__(self, path, log=None, params={}):
        if have_pysqlite == 0:
            raise TracError(_("Cannot load Python bindings for SQLite"))
        self.cnx = None
        if path != ':memory:':
            if not os.access(path, os.F_OK):
                raise ConfigurationError(_('Database "%(path)s" not found.',
                                           path=path))

            dbdir = os.path.dirname(path)
            if not os.access(path, os.R_OK + os.W_OK) or \
                   not os.access(dbdir, os.R_OK + os.W_OK):
                raise ConfigurationError(tag_(
                    "The user %(user)s requires read _and_ write permissions "
                    "to the database file %(path)s and the directory it is "
                    "located in.", user=tag.tt(getuser()), path=tag.tt(path)))

        self._active_cursors = weakref.WeakKeyDictionary()
        timeout = int(params.get('timeout', 10.0))
        self._eager = params.get('cursor', 'eager') == 'eager'
        # eager is default, can be turned off by specifying ?cursor=
        if isinstance(path, unicode): # needed with 2.4.0
            path = path.encode('utf-8')
        cnx = sqlite.connect(path, detect_types=sqlite.PARSE_DECLTYPES,
                             check_same_thread=sqlite_version < (3, 3, 1),
                             timeout=timeout)
        # load extensions
        extensions = params.get('extensions', [])
        if len(extensions) > 0:
            cnx.enable_load_extension(True)
            for ext in extensions:
                cnx.load_extension(ext)
            cnx.enable_load_extension(False)

        cursor = cnx.cursor()
        _set_journal_mode(cursor, params.get('journal_mode'))
        _set_synchronous(cursor, params.get('synchronous'))
        ConnectionWrapper.__init__(self, cnx, log)
예제 #20
0
    def expand_macro(self, formatter, name, content):
        from trac.config import ConfigSection, Option
        section_filter = key_filter = ''
        args, kw = parse_args(content)
        if args:
            section_filter = args.pop(0).strip()
        if args:
            key_filter = args.pop(0).strip()

        def getdoc(option_or_section):
            doc = to_unicode(option_or_section.__doc__)
            if doc:
                doc = dgettext(option_or_section.doc_domain, doc)
            return doc

        registry = ConfigSection.get_registry(self.compmgr)
        sections = dict((name, getdoc(section))
                        for name, section in registry.iteritems()
                        if name.startswith(section_filter))

        registry = Option.get_registry(self.compmgr)
        options = {}
        for (section, key), option in registry.iteritems():
            if section.startswith(section_filter):
                options.setdefault(section, {})[key] = option
                sections.setdefault(section, '')

        def default_cell(option):
            default = option.default
            if default is not None and default != '':
                return tag.td(tag.code(option.dumps(default)),
                              class_='default')
            else:
                return tag.td(_("(no default)"), class_='nodefault')

        return tag.div(class_='tracini')(
            (tag.h3(tag.code('[%s]' % section), id='%s-section' % section),
             format_to_html(self.env, formatter.context, section_doc),
             tag.table(class_='wiki')(tag.tbody(
                 tag.tr(tag.td(tag.tt(option.name)),
                        tag.td(
                            format_to_html(self.env, formatter.context,
                                           getdoc(option))),
                        default_cell(option),
                        class_='odd' if idx % 2 else 'even')
                 for idx, option in enumerate(
                     sorted(options.get(section, {}).itervalues(),
                            key=lambda o: o.name))
                 if option.name.startswith(key_filter))))
            for section, section_doc in sorted(sections.iteritems()))
예제 #21
0
파일: macros.py 프로젝트: exocad/exotrac
    def expand_macro(self, formatter, name, content):
        from trac.config import ConfigSection, Option
        section_filter = key_filter = ''
        args, kw = parse_args(content)
        if args:
            section_filter = args.pop(0).strip()
        if args:
            key_filter = args.pop(0).strip()

        def getdoc(option_or_section):
            doc = to_unicode(option_or_section.__doc__)
            if doc:
                doc = dgettext(option_or_section.doc_domain, doc)
            return doc

        registry = ConfigSection.get_registry(self.compmgr)
        sections = dict((name, getdoc(section))
                        for name, section in registry.iteritems()
                        if name.startswith(section_filter))

        registry = Option.get_registry(self.compmgr)
        options = {}
        for (section, key), option in registry.iteritems():
            if section.startswith(section_filter):
                options.setdefault(section, {})[key] = option
                sections.setdefault(section, '')

        def default_cell(option):
            default = option.default
            if default is not None and default != '':
                return tag.td(tag.code(option.dumps(default)),
                              class_='default')
            else:
                return tag.td(_("(no default)"), class_='nodefault')

        return tag.div(class_='tracini')(
            (tag.h3(tag.code('[%s]' % section), id='%s-section' % section),
             format_to_html(self.env, formatter.context, section_doc),
             tag.table(class_='wiki')(tag.tbody(
                 tag.tr(tag.td(tag.tt(option.name)),
                        tag.td(format_to_oneliner(
                            self.env, formatter.context, getdoc(option))),
                        default_cell(option),
                        class_='odd' if idx % 2 else 'even')
                 for idx, option in
                    enumerate(sorted(options.get(section, {}).itervalues(),
                                     key=lambda o: o.name))
                 if option.name.startswith(key_filter))))
            for section, section_doc in sorted(sections.iteritems()))
예제 #22
0
    def send(self, from_addr, recipients, message):
        # Use native line endings in message
        message = fix_eol(message, os.linesep)

        self.log.info("Sending notification through sendmail at %s to %s",
                      self.sendmail_path, recipients)
        cmdline = [self.sendmail_path, "-i", "-f", from_addr]
        cmdline.extend(recipients)
        self.log.debug("Sendmail command line: %s", cmdline)
        try:
            child = Popen(cmdline, bufsize=-1, stdin=PIPE, stdout=PIPE,
                          stderr=PIPE, close_fds=close_fds)
        except OSError, e:
            raise ConfigurationError(
                tag_("Sendmail error (%(error)s). Please modify %(option)s "
                     "in your configuration.",
                     error=to_unicode(e),
                     option=tag.tt("[notification] sendmail_path")))
예제 #23
0
    def send(self, from_addr, recipients, message):
        # Use native line endings in message
        message = fix_eol(message, os.linesep)

        self.log.info("Sending notification through sendmail at %s to %s",
                      self.sendmail_path, recipients)
        cmdline = [self.sendmail_path, "-i", "-f", from_addr]
        cmdline.extend(recipients)
        self.log.debug("Sendmail command line: %s", cmdline)
        try:
            child = Popen(cmdline, bufsize=-1, stdin=PIPE, stdout=PIPE,
                          stderr=PIPE, close_fds=close_fds)
        except OSError, e:
            raise ConfigurationError(
                tag_("Sendmail error (%(error)s). Please modify %(option)s "
                     "in your configuration.",
                     error=to_unicode(e),
                     option=tag.tt("[notification] sendmail_path")))
예제 #24
0
    def expand_macro(self, formatter, name, content):
        def wikify(text):
            return format_to_oneliner(self.env, formatter.context, text)

        return tag.div(
            tag.p(wikify(_("""
                The following tokens can be used in the `PageTemplates/MyPage`
                or `PageTemplates/MyPage/<user>` wiki pages:
                """))),
            tag.dl([(tag.dt(tag.tt(token)),
                     tag.dd(wikify(gettext(description))))
                    for token, description in
                    sorted(MyPageModule(self.env).tokens.values())]),
            tag.p(wikify(_("""
                Note that you can also use the `[[MyPageNav]]` wiki macro for
                creating dynamic links to other ''MyPage'' pages (use
                `[[MyPageNav?]]` to get help on this macro).
                """)))
            )
예제 #25
0
    def expand_macro(self, formatter, name, args):
        from trac.config import ConfigSection, Option
        section_filter = key_filter = ''
        args, kw = parse_args(args)
        if args:
            section_filter = args.pop(0).strip()
        if args:
            key_filter = args.pop(0).strip()

        registry = ConfigSection.get_registry(self.compmgr)
        sections = dict(
            (name, dgettext(section.doc_domain, to_unicode(section.__doc__)))
            for name, section in registry.iteritems()
            if name.startswith(section_filter))

        registry = Option.get_registry(self.compmgr)
        options = {}
        for (section, key), option in registry.iteritems():
            if section.startswith(section_filter):
                options.setdefault(section, {})[key] = option
                sections.setdefault(section, '')

        return tag.div(class_='tracini')(
            (tag.h3(tag.code('[%s]' % section), id='%s-section' % section),
             format_to_html(self.env, formatter.context, section_doc),
             tag.table(class_='wiki')(tag.tbody(
                 tag.tr(
                     tag.td(tag.tt(option.name)),
                     tag.td(
                         format_to_oneliner(
                             self.env, formatter.context,
                             dgettext(option.doc_domain,
                                      to_unicode(option.__doc__)))),
                     tag.td(
                         tag.code(option.default or 'false') if option.default
                         or option.default is False else _("(no default)"),
                         class_='default' if option.default
                         or option.default is False else 'nodefault'))
                 for option in sorted(options.get(section, {}).itervalues(),
                                      key=lambda o: o.name)
                 if option.name.startswith(key_filter))))
            for section, section_doc in sorted(sections.iteritems()))
예제 #26
0
    def expand_macro(self, formatter, name, args):
        from trac.config import ConfigSection, Option
        section_filter = key_filter = ''
        args, kw = parse_args(args)
        if args:
            section_filter = args.pop(0).strip()
        if args:
            key_filter = args.pop(0).strip()

        registry = ConfigSection.get_registry(self.compmgr)
        sections = dict((name, dgettext(section.doc_domain,
                                        to_unicode(section.__doc__)))
                        for name, section in registry.iteritems()
                        if name.startswith(section_filter))

        registry = Option.get_registry(self.compmgr)
        options = {}
        for (section, key), option in registry.iteritems():
            if section.startswith(section_filter):
                options.setdefault(section, {})[key] = option
                sections.setdefault(section, '')

        return tag.div(class_='tracini')(
            (tag.h3(tag.code('[%s]' % section), id='%s-section' % section),
             format_to_html(self.env, formatter.context, section_doc),
             tag.table(class_='wiki')(tag.tbody(
                 tag.tr(tag.td(tag.tt(option.name)),
                        tag.td(format_to_oneliner(
                            self.env, formatter.context,
                            dgettext(option.doc_domain,
                                     to_unicode(option.__doc__)))),
                        tag.td(tag.code(option.default or 'false')
                                   if option.default or option.default is False
                                   else _("(no default)"),
                               class_='default' if option.default or 
                                                   option.default is False 
                                                else 'nodefault'))
                 for option in sorted(options.get(section, {}).itervalues(),
                                      key=lambda o: o.name)
                 if option.name.startswith(key_filter))))
            for section, section_doc in sorted(sections.iteritems()))
예제 #27
0
    def expand_macro(self, formatter, name, args):
        from trac.config import Option
        section_filter = key_filter = ''
        args, kw = parse_args(args)
        if args:
            section_filter = args.pop(0).strip()
        if args:
            key_filter = args.pop(0).strip()

        sections = set([section for section, option in Option.registry.keys()
                        if section.startswith(section_filter)])

        return tag.div(class_='tracini')(
            [(tag.h2('[%s]' % section, id='%s-section' % section),
              tag.table(class_='wiki')(
            tag.tbody([tag.tr(tag.td(tag.tt(option.name)),
                              tag.td(format_to_oneliner(
                                            self.env, formatter.context,
                                            to_unicode(option.__doc__))))
                       for option in sorted(Option.registry.values(),
                                            key=lambda o: o.name)
                       if option.section == section and
                           option.name.startswith(key_filter)])))
             for section in sorted(sections)])
예제 #28
0
    def render_admin_panel(self, req, category, page, path_info):
        req.perm.require('VERSIONCONTROL_ADMIN')

        # Retrieve info for all repositories
        rm = RepositoryManager(self.env)
        all_repos = rm.get_all_repositories()
        db_provider = self.env[DbRepositoryProvider]

        if path_info:
            # Detail view
            reponame = path_info if not is_default(path_info) else ''
            info = all_repos.get(reponame)
            if info is None:
                raise TracError(
                    _("Repository '%(repo)s' not found", repo=path_info))
            if req.method == 'POST':
                if req.args.get('cancel'):
                    req.redirect(req.href.admin(category, page))

                elif db_provider and req.args.get('save'):
                    # Modify repository
                    changes = {}
                    for field in db_provider.repository_attrs:
                        value = normalize_whitespace(req.args.get(field))
                        if (value is not None or field == 'hidden') \
                                and value != info.get(field):
                            changes[field] = value
                    if 'dir' in changes \
                            and not self._check_dir(req, changes['dir']):
                        changes = {}
                    if changes:
                        db_provider.modify_repository(reponame, changes)
                        add_notice(req, _('Your changes have been saved.'))
                    name = req.args.get('name')
                    resync = tag.tt('trac-admin $ENV repository resync "%s"' %
                                    (name or '(default)'))
                    if 'dir' in changes:
                        msg = tag_(
                            'You should now run %(resync)s to '
                            'synchronize Trac with the repository.',
                            resync=resync)
                        add_notice(req, msg)
                    elif 'type' in changes:
                        msg = tag_(
                            'You may have to run %(resync)s to '
                            'synchronize Trac with the repository.',
                            resync=resync)
                        add_notice(req, msg)
                    if name and name != path_info and not 'alias' in info:
                        cset_added = tag.tt('trac-admin $ENV changeset '
                                            'added "%s" $REV' %
                                            (name or '(default)'))
                        msg = tag_(
                            'You will need to update your post-commit '
                            'hook to call %(cset_added)s with the new '
                            'repository name.',
                            cset_added=cset_added)
                        add_notice(req, msg)
                    if changes:
                        req.redirect(req.href.admin(category, page))

            Chrome(self.env).add_wiki_toolbars(req)
            data = {'view': 'detail', 'reponame': reponame}

        else:
            # List view
            if req.method == 'POST':
                # Add a repository
                if db_provider and req.args.get('add_repos'):
                    name = req.args.get('name')
                    type_ = req.args.get('type')
                    # Avoid errors when copy/pasting paths
                    dir = normalize_whitespace(req.args.get('dir', ''))
                    if name is None or type_ is None or not dir:
                        add_warning(
                            req, _('Missing arguments to add a '
                                   'repository.'))
                    elif self._check_dir(req, dir):
                        db_provider.add_repository(name, dir, type_)
                        name = name or '(default)'
                        add_notice(
                            req,
                            _('The repository "%(name)s" has been '
                              'added.',
                              name=name))
                        resync = tag.tt('trac-admin $ENV repository resync '
                                        '"%s"' % name)
                        msg = tag_(
                            'You should now run %(resync)s to '
                            'synchronize Trac with the repository.',
                            resync=resync)
                        add_notice(req, msg)
                        cset_added = tag.tt('trac-admin $ENV changeset '
                                            'added "%s" $REV' % name)
                        msg = tag_(
                            'You should also set up a post-commit hook '
                            'on the repository to call %(cset_added)s '
                            'for each committed changeset.',
                            cset_added=cset_added)
                        add_notice(req, msg)
                        req.redirect(req.href.admin(category, page))

                # Add a repository alias
                elif db_provider and req.args.get('add_alias'):
                    name = req.args.get('name')
                    alias = req.args.get('alias')
                    if name is not None and alias is not None:
                        db_provider.add_alias(name, alias)
                        add_notice(
                            req,
                            _('The alias "%(name)s" has been '
                              'added.',
                              name=name or '(default)'))
                        req.redirect(req.href.admin(category, page))
                    add_warning(req, _('Missing arguments to add an '
                                       'alias.'))

                # Refresh the list of repositories
                elif req.args.get('refresh'):
                    req.redirect(req.href.admin(category, page))

                # Remove repositories
                elif db_provider and req.args.get('remove'):
                    sel = req.args.getlist('sel')
                    if sel:
                        for name in sel:
                            db_provider.remove_repository(name)
                        add_notice(
                            req,
                            _('The selected repositories have '
                              'been removed.'))
                        req.redirect(req.href.admin(category, page))
                    add_warning(req, _('No repositories were selected.'))

            data = {'view': 'list'}

        # Find repositories that are editable
        db_repos = {}
        if db_provider is not None:
            db_repos = dict(db_provider.get_repositories())

        # Prepare common rendering data
        repositories = dict(
            (reponame,
             self._extend_info(reponame, info.copy(), reponame in db_repos))
            for (reponame, info) in all_repos.iteritems())
        types = sorted([''] + rm.get_supported_types())
        data.update({
            'types': types,
            'default_type': rm.repository_type,
            'repositories': repositories
        })

        return 'admin_repositories.html', data
예제 #29
0
 def _cli_formatter(self, formatter, match, fullmatch):
     host = fullmatch.group('host')
     codeblock = fullmatch.group('codeblock')
     return tag.tt(host, class_='USERPROMPTHOST') +\
         tag.tt(codeblock, class_='USERPROMPT') + tag.br
예제 #30
0
 def _file_formatter(self, formatter, match, fullmatch):
     return tag.tt(fullmatch.group('filename'),class_='FILENAME')
예제 #31
0
    def render_admin_panel(self, req, category, page, path_info):
        req.perm.require("VERSIONCONTROL_ADMIN")

        # Retrieve info for all repositories
        rm = RepositoryManager(self.env)
        all_repos = rm.get_all_repositories()
        db_provider = self.env[DbRepositoryProvider]

        if path_info:
            # Detail view
            reponame = path_info if not is_default(path_info) else ""
            info = all_repos.get(reponame)
            if info is None:
                raise TracError(_("Repository '%(repo)s' not found", repo=path_info))
            if req.method == "POST":
                if req.args.get("cancel"):
                    req.redirect(req.href.admin(category, page))

                elif db_provider and req.args.get("save"):
                    # Modify repository
                    changes = {}
                    for field in db_provider.repository_attrs:
                        value = normalize_whitespace(req.args.get(field))
                        if (value is not None or field == "hidden") and value != info.get(field):
                            changes[field] = value
                    if "dir" in changes and not self._check_dir(req, changes["dir"]):
                        changes = {}
                    if changes:
                        db_provider.modify_repository(reponame, changes)
                        add_notice(req, _("Your changes have been saved."))
                    name = req.args.get("name")
                    resync = tag.tt('trac-admin $ENV repository resync "%s"' % (name or "(default)"))
                    if "dir" in changes:
                        msg = tag_(
                            "You should now run %(resync)s to " "synchronize Trac with the repository.", resync=resync
                        )
                        add_notice(req, msg)
                    elif "type" in changes:
                        msg = tag_(
                            "You may have to run %(resync)s to " "synchronize Trac with the repository.", resync=resync
                        )
                        add_notice(req, msg)
                    if name and name != path_info and not "alias" in info:
                        cset_added = tag.tt("trac-admin $ENV changeset " 'added "%s" $REV' % (name or "(default)"))
                        msg = tag_(
                            "You will need to update your post-commit "
                            "hook to call %(cset_added)s with the new "
                            "repository name.",
                            cset_added=cset_added,
                        )
                        add_notice(req, msg)
                    if changes:
                        req.redirect(req.href.admin(category, page))

            Chrome(self.env).add_wiki_toolbars(req)
            data = {"view": "detail", "reponame": reponame}

        else:
            # List view
            if req.method == "POST":
                # Add a repository
                if db_provider and req.args.get("add_repos"):
                    name = req.args.get("name")
                    type_ = req.args.get("type")
                    # Avoid errors when copy/pasting paths
                    dir = normalize_whitespace(req.args.get("dir", ""))
                    if name is None or type_ is None or not dir:
                        add_warning(req, _("Missing arguments to add a " "repository."))
                    elif self._check_dir(req, dir):
                        db_provider.add_repository(name, dir, type_)
                        name = name or "(default)"
                        add_notice(req, _('The repository "%(name)s" has been ' "added.", name=name))
                        resync = tag.tt("trac-admin $ENV repository resync " '"%s"' % name)
                        msg = tag_(
                            "You should now run %(resync)s to " "synchronize Trac with the repository.", resync=resync
                        )
                        add_notice(req, msg)
                        cset_added = tag.tt("trac-admin $ENV changeset " 'added "%s" $REV' % name)
                        msg = tag_(
                            "You should also set up a post-commit hook "
                            "on the repository to call %(cset_added)s "
                            "for each committed changeset.",
                            cset_added=cset_added,
                        )
                        add_notice(req, msg)
                        req.redirect(req.href.admin(category, page))

                # Add a repository alias
                elif db_provider and req.args.get("add_alias"):
                    name = req.args.get("name")
                    alias = req.args.get("alias")
                    if name is not None and alias is not None:
                        db_provider.add_alias(name, alias)
                        add_notice(req, _('The alias "%(name)s" has been ' "added.", name=name or "(default)"))
                        req.redirect(req.href.admin(category, page))
                    add_warning(req, _("Missing arguments to add an " "alias."))

                # Refresh the list of repositories
                elif req.args.get("refresh"):
                    req.redirect(req.href.admin(category, page))

                # Remove repositories
                elif db_provider and req.args.get("remove"):
                    sel = req.args.getlist("sel")
                    if sel:
                        for name in sel:
                            db_provider.remove_repository(name)
                        add_notice(req, _("The selected repositories have " "been removed."))
                        req.redirect(req.href.admin(category, page))
                    add_warning(req, _("No repositories were selected."))

            data = {"view": "list"}

        # Find repositories that are editable
        db_repos = {}
        if db_provider is not None:
            db_repos = dict(db_provider.get_repositories())

        # Prepare common rendering data
        repositories = dict(
            (reponame, self._extend_info(reponame, info.copy(), reponame in db_repos))
            for (reponame, info) in all_repos.iteritems()
        )
        types = sorted([""] + rm.get_supported_types())
        data.update({"types": types, "default_type": rm.repository_type, "repositories": repositories})

        return "admin_repositories.html", data
예제 #32
0
    def _do_repositories(self, req, category, page):
        # Check that the setttings have been set.
        parentpath = self.config.get('svnadmin', 'parent_path')
        client = self.config.get('svnadmin', 'svn_client_location')
        admin = self.config.get('svnadmin', 'svnadmin_location')
        if not parentpath or not client or not admin:
            add_warning(req, _('You must provide settings before continuing.'))
            req.redirect(req.href.admin(category, 'config'))

        data = {}

        svn_provider = self.env[SvnRepositoryProvider]
        db_provider = self.env[DbRepositoryProvider]

        if req.method == 'POST':
            # Add a repository
            if svn_provider and req.args.get('add_repos'):
                name = req.args.get('name')
                dir = os.path.join(parentpath, name)
                if name is None or name == "" or not dir:
                    add_warning(req,
                                _('Missing arguments to add a repository.'))
                elif self._check_dir(req, dir):
                    try:
                        svn_provider.add_repository(name)
                        db_provider.add_repository(name, dir, 'svn')
                        add_notice(
                            req,
                            _('The repository "%(name)s" has been '
                              'added.',
                              name=name))
                        resync = tag.tt('trac-admin $ENV repository resync '
                                        '"%s"' % name)
                        msg = tag_(
                            'You should now run %(resync)s to '
                            'synchronize Trac with the repository.',
                            resync=resync)
                        add_notice(req, msg)
                        cset_added = tag.tt('trac-admin $ENV changeset '
                                            'added "%s" $REV' % name)
                        msg = tag_(
                            'You should also set up a post-commit hook '
                            'on the repository to call %(cset_added)s '
                            'for each committed changeset.',
                            cset_added=cset_added)
                        add_notice(req, msg)
                        req.redirect(req.href.admin(category, page))
                    except TracError, why:
                        add_warning(req, str(why))

            # Remove repositories
            elif svn_provider and req.args.get('remove'):
                sel = req.args.getlist('sel')
                if sel:
                    for name in sel:
                        svn_provider.remove_repository(name)
                        db_provider.remove_repository(name)
                    add_notice(
                        req,
                        _('The selected repositories have '
                          'been removed.'))
                    req.redirect(req.href.admin(category, page))
                add_warning(req, _('No repositories were selected.'))
예제 #33
0
class CsetPropertyRenderer(Component):

    implements(IPropertyRenderer)

    # relied upon by GitChangeset
    def match_property(self, name, mode):
        # default renderer has priority 1
        return (name in (
            'Parents',
            'Children',
            'Branches',
            'git-committer',
            'git-author',
        ) and mode == 'revprop') and 4 or 0

    def render_property(self, name, mode, context, props):
        def sha_link(sha, label=None):
            # sha is assumed to be a non-abbreviated 40-chars sha id
            try:
                reponame = context.resource.parent.id
                repos = self.env.get_repository(reponame)
                cset = repos.get_changeset(sha)
                if label is None:
                    label = repos.display_rev(sha)

                return tag.a(label,
                             class_='changeset',
                             title=shorten_line(cset.message),
                             href=context.href.changeset(sha, repos.reponame))

            except Exception, e:
                return tag.a(sha,
                             class_='missing changeset',
                             title=to_unicode(e),
                             rel='nofollow')

        if name == 'Branches':
            branches = props[name]

            # simple non-merge commit
            return tag(*intersperse(', ', (sha_link(rev, label)
                                           for label, rev in branches)))

        elif name in ('Parents', 'Children'):
            revs = props[name]  # list of commit ids

            if name == 'Parents' and len(revs) > 1:
                # we got a merge...
                current_sha = context.resource.id
                reponame = context.resource.parent.id

                parent_links = intersperse(', ', \
                    ((sha_link(rev),
                      ' (',
                      tag.a('diff',
                            title="Diff against this parent (show the " \
                                  "changes merged from the other parents)",
                            href=context.href.changeset(current_sha, reponame,
                                                        old=rev)),
                      ')')
                     for rev in revs))

                return tag(
                    list(parent_links), tag.br(),
                    tag.span(tag(
                        "Note: this is a ", tag.strong("merge"), " changeset, "
                        "the changes displayed below "
                        "correspond to the merge itself."),
                             class_='hint'), tag.br(),
                    tag.span(tag(
                        "Use the ", tag.tt("(diff)"),
                        " links above to see all the changes "
                        "relative to each parent."),
                             class_='hint'))

            # simple non-merge commit
            return tag(*intersperse(', ', map(sha_link, revs)))

        elif name in ('git-committer', 'git-author'):
            user_, time_ = props[name]
            _str = "%s (%s)" % (Chrome(self.env).format_author(
                context.req,
                user_), format_datetime(time_, tzinfo=context.req.tz))
            return unicode(_str)

        raise TracError("Internal error")
예제 #34
0
    def _do_save(self, req, db, milestone):
        if milestone.exists:
            req.perm(milestone.resource).require('MILESTONE_MODIFY')
        else:
            req.perm(milestone.resource).require('MILESTONE_CREATE')

        ticket_module = TicketModule(self.env)
        ticket_module._populate(req, milestone.ticket, False)
        if not milestone.exists:
            reporter_id = get_reporter_id(req, 'author')
            milestone.ticket.values['reporter'] = reporter_id

        action = req.args.get('action', 'leave')

        field_changes, problems = ticket_module.get_ticket_changes(
            req, milestone.ticket, action)
        if problems:
            for problem in problems:
                add_warning(req, problem)
                add_warning(
                    req,
                    tag(
                        tag.p('Please review your configuration, '
                              'probably starting with'),
                        tag.pre('[trac]\nworkflow = ...\n'),
                        tag.p('in your ', tag.tt('trac.ini'), '.')))

        ticket_module._apply_ticket_changes(milestone.ticket, field_changes)

        old_name = milestone.name
        new_name = milestone.ticket['summary']

        milestone.name = new_name
        milestone.description = milestone.ticket['description']

        due = req.args.get('duedate', '')
        milestone.due = due and parse_date(due, tzinfo=req.tz) or None
        milestone.ticket['duedate'] = milestone.due and str(
            to_timestamp(milestone.due)) or None

        completed = req.args.get('completedate', '')
        retarget_to = req.args.get('target')

        # Instead of raising one single error, check all the constraints and
        # let the user fix them by going back to edit mode showing the warnings
        warnings = []

        def warn(msg):
            add_warning(req, msg)
            warnings.append(msg)

        # -- check the name
        if new_name:
            if new_name != old_name:
                # check that the milestone doesn't already exists
                # FIXME: the whole .exists business needs to be clarified
                #        (#4130) and should behave like a WikiPage does in
                #        this respect.
                try:
                    other_milestone = StructuredMilestone(
                        self.env, new_name, db)
                    warn(
                        _(
                            'Milestone "%(name)s" already exists, please '
                            'choose another name',
                            name=new_name))
                except ResourceNotFound:
                    pass
        else:
            warn(_('You must provide a name for the milestone.'))

        # -- check completed date
        if action in MilestoneSystem(self.env).starting_action:
            milestone.ticket['started'] = str(to_timestamp(datetime.now(utc)))
        if action in MilestoneSystem(self.env).completing_action:
            milestone.completed = datetime.now(utc)

        if warnings:
            return self._render_editor(req, db, milestone)

        # -- actually save changes
        if milestone.exists:
            cnum = req.args.get('cnum')
            replyto = req.args.get('replyto')
            internal_cnum = cnum
            if cnum and replyto:  # record parent.child relationship
                internal_cnum = '%s.%s' % (replyto, cnum)

            now = datetime.now(utc)
            milestone.save_changes(get_reporter_id(req, 'author'),
                                   req.args.get('comment'),
                                   when=now,
                                   cnum=internal_cnum)
            # eventually retarget opened tickets associated with the milestone
            if 'retarget' in req.args and completed:
                cursor = db.cursor()
                cursor.execute(
                    "UPDATE ticket SET milestone=%s WHERE "
                    "milestone=%s and status != 'closed'",
                    (retarget_to, old_name))
                self.env.log.info('Tickets associated with milestone %s '
                                  'retargeted to %s' % (old_name, retarget_to))
        else:
            milestone.insert()
        db.commit()

        add_notice(req, _('Your changes have been saved.'))
        jump_to = req.args.get('jump_to', 'roadmap')
        if jump_to == 'roadmap':
            req.redirect(req.href.roadmap())
        elif jump_to == 'whiteboard':
            req.redirect(
                req.href.whiteboard('team_tasks') + '#' + milestone.name)
        else:
            req.redirect(req.href.milestone(milestone.name))
예제 #35
0
def parse_connection_uri(db_str):
    """Parse the database connection string.

    The database connection string for an environment is specified through
    the `database` option in the `[trac]` section of trac.ini.

    :return: a tuple containing the scheme and a dictionary of attributes:
             `user`, `password`, `host`, `port`, `path`, `params`.
    :since: 1.1.3
    """
    if not db_str:
        section = tag.a("[trac]",
                        title=_("TracIni documentation"),
                        class_='trac-target-new',
                        href='http://trac.edgewall.org/wiki/TracIni'
                        '#trac-section')
        raise ConfigurationError(
            tag_(
                "Database connection string is empty. Set the %(option)s "
                "configuration option in the %(section)s section of "
                "trac.ini. Please refer to the %(doc)s for help.",
                option=tag.tt("database"),
                section=section,
                doc=_doc_db_str()))

    try:
        scheme, rest = db_str.split(':', 1)
    except ValueError:
        raise _invalid_db_str(db_str)

    if not rest.startswith('/'):
        if scheme == 'sqlite' and rest:
            # Support for relative and in-memory SQLite connection strings
            host = None
            path = rest
        else:
            raise _invalid_db_str(db_str)
    else:
        if not rest.startswith('//'):
            host = None
            rest = rest[1:]
        elif rest.startswith('///'):
            host = None
            rest = rest[3:]
        else:
            rest = rest[2:]
            if '/' in rest:
                host, rest = rest.split('/', 1)
            else:
                host = rest
                rest = ''
        path = None

    if host and '@' in host:
        user, host = host.split('@', 1)
        if ':' in user:
            user, password = user.split(':', 1)
        else:
            password = None
        if user:
            user = urllib.unquote(user)
        if password:
            password = unicode_passwd(urllib.unquote(password))
    else:
        user = password = None

    if host and ':' in host:
        host, port = host.split(':', 1)
        try:
            port = int(port)
        except ValueError:
            raise _invalid_db_str(db_str)
    else:
        port = None

    if not path:
        path = '/' + rest
    if os.name == 'nt':
        # Support local paths containing drive letters on Win32
        if len(rest) > 1 and rest[1] == '|':
            path = "%s:%s" % (rest[0], rest[2:])

    params = {}
    if '?' in path:
        path, qs = path.split('?', 1)
        qs = qs.split('&')
        for param in qs:
            try:
                name, value = param.split('=', 1)
            except ValueError:
                raise _invalid_db_str(db_str)
            value = urllib.unquote(value)
            params[name] = value

    args = zip(('user', 'password', 'host', 'port', 'path', 'params'),
               (user, password, host, port, path, params))
    return scheme, dict([(key, value) for key, value in args if value])
예제 #36
0
파일: admin.py 프로젝트: zjj/trac_hack
    def render_admin_panel(self, req, category, page, path_info):
        req.perm.require('VERSIONCONTROL_ADMIN')
        
        # Retrieve info for all repositories
        rm = RepositoryManager(self.env)
        all_repos = rm.get_all_repositories()
        db_provider = self.env[DbRepositoryProvider]
        
        if path_info:
            # Detail view
            reponame = not is_default(path_info) and path_info or ''
            info = all_repos.get(reponame)
            if info is None:
                raise TracError(_("Repository '%(repo)s' not found",
                                  repo=path_info))
            if req.method == 'POST':
                if req.args.get('cancel'):
                    req.redirect(req.href.admin(category, page))
                
                elif db_provider and req.args.get('save'):
                    # Modify repository
                    changes = {}
                    for field in db_provider.repository_attrs:
                        value = normalize_whitespace(req.args.get(field))
                        if (value is not None or field == 'hidden') \
                                and value != info.get(field):
                            changes[field] = value
                    if 'dir' in changes \
                            and not self._check_dir(req, changes['dir']):
                        changes = {}
                    if changes:
                        db_provider.modify_repository(reponame, changes)
                        add_notice(req, _('Your changes have been saved.'))
                    name = req.args.get('name')
                    resync = tag.tt('trac-admin $ENV repository resync "%s"'
                                    % (name or '(default)'))
                    if 'dir' in changes:
                        msg = tag_('You should now run %(resync)s to '
                                   'synchronize Trac with the repository.',
                                   resync=resync)
                        add_notice(req, msg)
                    elif 'type' in changes:
                        msg = tag_('You may have to run %(resync)s to '
                                   'synchronize Trac with the repository.',
                                   resync=resync)
                        add_notice(req, msg)
                    if name and name != path_info and not 'alias' in info:
                        cset_added = tag.tt('trac-admin $ENV changeset '
                                            'added "%s" $REV'
                                            % (name or '(default)'))
                        msg = tag_('You will need to update your post-commit '
                                   'hook to call %(cset_added)s with the new '
                                   'repository name.', cset_added=cset_added)
                        add_notice(req, msg)
                    if changes:
                        req.redirect(req.href.admin(category, page))
            
            Chrome(self.env).add_wiki_toolbars(req)
            data = {'view': 'detail', 'reponame': reponame}
        
        else:
            # List view
            if req.method == 'POST':
                # Add a repository
                if db_provider and req.args.get('add_repos'):
                    name = req.args.get('name')
                    type_ = req.args.get('type')
                    # Avoid errors when copy/pasting paths
                    dir = normalize_whitespace(req.args.get('dir', ''))
                    if name is None or type_ is None or not dir:
                        add_warning(req, _('Missing arguments to add a '
                                           'repository.'))
                    elif self._check_dir(req, dir):
                        db_provider.add_repository(name, dir, type_)
                        name = name or '(default)'
                        add_notice(req, _('The repository "%(name)s" has been '
                                          'added.', name=name))
                        resync = tag.tt('trac-admin $ENV repository resync '
                                        '"%s"' % name)
                        msg = tag_('You should now run %(resync)s to '
                                   'synchronize Trac with the repository.',
                                   resync=resync)
                        add_notice(req, msg)
                        cset_added = tag.tt('trac-admin $ENV changeset '
                                            'added "%s" $REV' % name)
                        msg = tag_('You should also set up a post-commit hook '
                                   'on the repository to call %(cset_added)s '
                                   'for each committed changeset.',
                                   cset_added=cset_added)
                        add_notice(req, msg)
                        req.redirect(req.href.admin(category, page))
                
                # Add a repository alias
                elif db_provider and req.args.get('add_alias'):
                    name = req.args.get('name')
                    alias = req.args.get('alias')
                    if name is not None and alias is not None:
                        db_provider.add_alias(name, alias)
                        add_notice(req, _('The alias "%(name)s" has been '
                                          'added.', name=name or '(default)'))
                        req.redirect(req.href.admin(category, page))
                    add_warning(req, _('Missing arguments to add an '
                                       'alias.'))
                
                # Refresh the list of repositories
                elif req.args.get('refresh'):
                    req.redirect(req.href.admin(category, page))
                
                # Remove repositories
                elif db_provider and req.args.get('remove'):
                    sel = req.args.getlist('sel')
                    if sel:
                        for name in sel:
                            db_provider.remove_repository(name)
                        add_notice(req, _('The selected repositories have '
                                          'been removed.'))
                        req.redirect(req.href.admin(category, page))
                    add_warning(req, _('No repositories were selected.'))
            
            data = {'view': 'list'}

        # Find repositories that are editable
        db_repos = {}
        if db_provider is not None:
            db_repos = dict(db_provider.get_repositories())
        
        # Prepare common rendering data
        repositories = dict((reponame, self._extend_info(reponame, info.copy(),
                                                         reponame in db_repos))
                            for (reponame, info) in all_repos.iteritems())
        types = sorted([''] + rm.get_supported_types())
        data.update({'types': types, 'default_type': rm.repository_type,
                     'repositories': repositories})
        
        return 'admin_repositories.html', data
예제 #37
0
파일: api.py 프로젝트: exocad/exotrac
def _invalid_db_str(db_str):
    return ConfigurationError(
        tag_("Invalid format %(db_str)s for the database connection string. "
             "Please refer to the %(doc)s for help.",
             db_str=tag.tt(db_str), doc=_doc_db_str()))
예제 #38
0
                    ((sha_link(rev),
                      ' (',
                      tag.a('diff',
                            title="Diff against this parent (show the changes merged from the other parents)",
                            href=context.href.changeset(current_sha, reponame, old=rev)),
                      ')')
                     for rev in revs))

                return tag(list(parent_links),
                           tag.br(),
                           tag.span(tag("Note: this is a ", tag.strong('merge'), " changeset, "
                                        "the changes displayed below correspond "
                                        "to the merge itself."),
                                    class_='hint'),
                           tag.br(),
                           tag.span(tag("Use the ", tag.tt('(diff)'), " links above"
                                        " to see all the changes relative to each parent."),
                                    class_='hint'))

            # simple non-merge commit
            return tag(*intersperse(', ', map(sha_link, revs)))

        elif name in ('git-committer', 'git-author'):
            user_, time_ = props[name]
            _str = "%s (%s)" % (Chrome(self.env).format_author(context.req, user_),
                                format_datetime(time_, tzinfo=context.req.tz))
            return unicode(_str)

        raise TracError("Internal error")

예제 #39
0
    def _do_save(self, req, db, milestone):
        if milestone.exists:
            req.perm(milestone.resource).require('MILESTONE_MODIFY')
        else:
            req.perm(milestone.resource).require('MILESTONE_CREATE')
        
        ticket_module = TicketModule(self.env)
        ticket_module._populate(req, milestone.ticket, False)
        if not milestone.exists:
            reporter_id = get_reporter_id(req, 'author')
            milestone.ticket.values['reporter'] = reporter_id

        action = req.args.get('action', 'leave')

        field_changes, problems = ticket_module.get_ticket_changes(req, milestone.ticket,
                                    action)
        if problems:
            for problem in problems:
                add_warning(req, problem)
                add_warning(req,
                            tag(tag.p('Please review your configuration, '
                                      'probably starting with'),
                                tag.pre('[trac]\nworkflow = ...\n'),
                                tag.p('in your ', tag.tt('trac.ini'), '.'))
                            )

        ticket_module._apply_ticket_changes(milestone.ticket, field_changes)

        old_name = milestone.name
        new_name = milestone.ticket['summary']
        
        milestone.name = new_name
        milestone.description = milestone.ticket['description']

        due = req.args.get('duedate', '')
        milestone.due = due and parse_date(due, tzinfo=req.tz) or None
        milestone.ticket['duedate']=milestone.due and str(to_timestamp(milestone.due)) or None

        completed = req.args.get('completedate', '')
        retarget_to = req.args.get('target')

        # Instead of raising one single error, check all the constraints and
        # let the user fix them by going back to edit mode showing the warnings
        warnings = []
        def warn(msg):
            add_warning(req, msg)
            warnings.append(msg)

        # -- check the name
        if new_name:
            if new_name != old_name:
                # check that the milestone doesn't already exists
                # FIXME: the whole .exists business needs to be clarified
                #        (#4130) and should behave like a WikiPage does in
                #        this respect.
                try:
                    other_milestone = StructuredMilestone(self.env, new_name, db)
                    warn(_('Milestone "%(name)s" already exists, please '
                           'choose another name', name=new_name))
                except ResourceNotFound:
                    pass
        else:
            warn(_('You must provide a name for the milestone.'))

        # -- check completed date
        if action in MilestoneSystem(self.env).starting_action:
            milestone.ticket['started'] = str(to_timestamp(datetime.now(utc)))
        if action in MilestoneSystem(self.env).completing_action:
            milestone.completed = datetime.now(utc)
            
        if warnings:
            return self._render_editor(req, db, milestone)
        
        # -- actually save changes
        if milestone.exists:
            cnum = req.args.get('cnum')
            replyto = req.args.get('replyto')
            internal_cnum = cnum
            if cnum and replyto: # record parent.child relationship
                internal_cnum = '%s.%s' % (replyto, cnum)

            now = datetime.now(utc)
            milestone.save_changes(get_reporter_id(req, 'author'),
                                         req.args.get('comment'), when=now,
                                         cnum=internal_cnum)
            # eventually retarget opened tickets associated with the milestone
            if 'retarget' in req.args and completed:
                cursor = db.cursor()
                cursor.execute("UPDATE ticket SET milestone=%s WHERE "
                               "milestone=%s and status != 'closed'",
                                (retarget_to, old_name))
                self.env.log.info('Tickets associated with milestone %s '
                                  'retargeted to %s' % (old_name, retarget_to))
        else:
            milestone.insert()
        db.commit()

        add_notice(req, _('Your changes have been saved.'))
        jump_to = req.args.get('jump_to', 'roadmap')
        if jump_to=='roadmap':
            req.redirect(req.href.roadmap())
        elif jump_to =='whiteboard':
            req.redirect(req.href.whiteboard('team_tasks')+'#'+milestone.name)
        else:
            req.redirect(req.href.milestone(milestone.name))
예제 #40
0
파일: api.py 프로젝트: exocad/exotrac
def _parse_db_str(db_str):
    if not db_str:
        section = tag.a("[trac]",
                        title=_("TracIni documentation"),
                        class_='trac-target-new',
                        href='http://trac.edgewall.org/wiki/TracIni'
                             '#trac-section')
        raise ConfigurationError(
            tag_("Database connection string is empty. Set the %(option)s "
                 "configuration option in the %(section)s section of "
                 "trac.ini. Please refer to the %(doc)s for help.",
                 option=tag.tt("database"), section=section,
                 doc=_doc_db_str()))

    try:
        scheme, rest = db_str.split(':', 1)
    except ValueError:
        raise _invalid_db_str(db_str)

    if not rest.startswith('/'):
        if scheme == 'sqlite' and rest:
            # Support for relative and in-memory SQLite connection strings
            host = None
            path = rest
        else:
            raise _invalid_db_str(db_str)
    else:
        if not rest.startswith('//'):
            host = None
            rest = rest[1:]
        elif rest.startswith('///'):
            host = None
            rest = rest[3:]
        else:
            rest = rest[2:]
            if '/' in rest:
                host, rest = rest.split('/', 1)
            else:
                host = rest
                rest = ''
        path = None

    if host and '@' in host:
        user, host = host.split('@', 1)
        if ':' in user:
            user, password = user.split(':', 1)
        else:
            password = None
        if user:
            user = urllib.unquote(user)
        if password:
            password = unicode_passwd(urllib.unquote(password))
    else:
        user = password = None

    if host and ':' in host:
        host, port = host.split(':', 1)
        try:
            port = int(port)
        except ValueError:
            raise _invalid_db_str(db_str)
    else:
        port = None

    if not path:
        path = '/' + rest
    if os.name == 'nt':
        # Support local paths containing drive letters on Win32
        if len(rest) > 1 and rest[1] == '|':
            path = "%s:%s" % (rest[0], rest[2:])

    params = {}
    if '?' in path:
        path, qs = path.split('?', 1)
        qs = qs.split('&')
        for param in qs:
            try:
                name, value = param.split('=', 1)
            except ValueError:
                raise _invalid_db_str(db_str)
            value = urllib.unquote(value)
            params[name] = value

    args = zip(('user', 'password', 'host', 'port', 'path', 'params'),
               (user, password, host, port, path, params))
    return scheme, dict([(key, value) for key, value in args if value])