Edgewall Software

Ticket #7116: 7116-pointer-aliases-r9085.patch

File 7116-pointer-aliases-r9085.patch, 47.3 KB (added by rblank, 8 months ago)

Make aliases pointers to repositories.

  • trac/util/__init__.py

    diff --git a/trac/util/__init__.py b/trac/util/__init__.py
    a b  
    870870    if max is not None and value > max: 
    871871        value = max 
    872872    return value 
     873 
     874def pathjoin(*args): 
     875    """Strip `/` from the arguments and join them with a single `/`.""" 
     876    return '/'.join(filter(None, (each.strip('/') for each in args if each))) 
  • trac/versioncontrol/templates/browser.html

    diff --git a/trac/versioncontrol/templates/browser.html b/trac/versioncontrol/templates/browser.html
    a b  
    111111        <tr py:if="file"> 
    112112          <td class="message searchable" py:choose=""> 
    113113            <py:when test="wiki_format_messages" xml:space="preserve"> 
    114               ${wiki_to_html(context('changeset', file.changeset.rev, parent=repos_resource), 
     114              ${wiki_to_html(context('changeset', file.changeset.rev, parent=repos.resource), 
    115115                             file.changeset.message, escape_newlines=True)} 
    116116            </py:when> 
    117117            <py:otherwise>${file.changeset.message}</py:otherwise> 
     
    159159      <div id="anydiff"> 
    160160        <form action="${href.diff()}" method="get"> 
    161161          <div class="buttons"> 
    162             <input type="hidden" name="new_path" value="$reponame/$path" /> 
    163             <input type="hidden" name="old_path" value="$reponame/$path" /> 
     162            <input type="hidden" name="new_path" value="${'/' + pathjoin(reponame, path)}" /> 
     163            <input type="hidden" name="old_path" value="${'/' + pathjoin(reponame, path)}" /> 
    164164            <input type="hidden" name="new_rev" value="$stickyrev" /> 
    165165            <input type="hidden" name="old_rev" value="$stickyrev" /> 
    166166            <input type="submit" value="${_('View changes...')}" title="${_('Select paths and revs for Diff')}" /> 
  • trac/versioncontrol/templates/changeset.html

    diff --git a/trac/versioncontrol/templates/changeset.html b/trac/versioncontrol/templates/changeset.html
    a b  
    5151        id="prefs" action=""> 
    5252        <div> 
    5353          <py:if test="not changeset"> 
    54             <input type="hidden" name="old_path" value="$reponame/$old_path" /> 
    55             <input type="hidden" name="new_path" value="$reponame/$new_path" /> 
     54            <input type="hidden" name="old_path" value="${'/' + pathjoin(reponame, old_path)}" /> 
     55            <input type="hidden" name="new_path" value="${'/' + pathjoin(reponame, new_path)}" /> 
    5656            <input type="hidden" name="old" value="$old_rev" /> 
    5757            <input type="hidden" name="new" value="$new_rev" /> 
    5858          </py:if> 
  • trac/versioncontrol/templates/dir_entries.html

    diff --git a/trac/versioncontrol/templates/dir_entries.html b/trac/versioncontrol/templates/dir_entries.html
    a b  
    77  </py:if> 
    88  <py:for each="idx, entry in enumerate(dir.entries)"> 
    99    <py:with vars="change = dir.changes[entry.rev]; 
    10                    chgset_context = change and context('changeset', change.rev, parent=repos_resource); 
     10                   chgset_context = change and context('changeset', change.rev, parent=repos.resource); 
    1111                   chgset_view = change and change.can_view(perm)"> 
    1212      <tr class="${idx % 2 and 'even' or 'odd'}"> 
    1313        <td class="name"> 
  • trac/versioncontrol/templates/repository_index.html

    diff --git a/trac/versioncontrol/templates/repository_index.html b/trac/versioncontrol/templates/repository_index.html
    a b  
    55  <table class="listing dirlist" id="${repoindex or None}"> 
    66    <xi:include href="dirlist_thead.html" /> 
    77    <tbody> 
    8       <py:for each="idx, (reponame, repoinfo, change, err) in enumerate(repo.repositories)" 
    9               py:with="chgset_context = change and context('changeset', change.rev, parent=Resource('repository', reponame)); 
     8      <py:for each="idx, (reponame, repoinfo, repos, change, err) in enumerate(repo.repositories)" 
     9              py:with="chgset_context = change and context('changeset', change.rev, parent=repos.resource); 
    1010                       chgset_view = change and change.can_view(perm)"> 
    1111        <tr class="${idx % 2 and 'even' or 'odd'}"> 
    1212          <td class="name"> 
    1313            <em py:strip="not err"> 
    1414              <b py:strip="repoinfo.alias != ''"> 
    1515                <a class="dir" title="View Root Directory" 
    16                   href="${href.browser(reponame, order=(order != 'name' and order or None), desc=desc)}">$reponame</a> 
     16                  href="${href.browser(repos.reponame, order=(order != 'name' and order or None), desc=desc)}">$reponame</a> 
    1717              </b> 
    1818            </em> 
    1919          </td> 
    2020          <td class="size" /> 
    2121          <td class="rev"> 
    2222            <py:if test="not err"> 
    23               <a title="View Revision Log" href="${href.log(reponame)}">$change.rev</a> 
    24               <a title="View Changeset" class="chgset" href="${href.changeset(change.rev, reponame)}">&nbsp;</a> 
     23              <a title="View Revision Log" href="${href.log(repos.reponame)}">$change.rev</a> 
     24              <a title="View Changeset" class="chgset" href="${href.changeset(change.rev, repos.reponame)}">&nbsp;</a> 
    2525            </py:if> 
    2626          </td> 
    2727          <td class="age" style="${chgset_view and change and repo.timerange and 'border-color: rgb(%s,%s,%s)' % 
  • trac/versioncontrol/templates/revisionlog.html

    diff --git a/trac/versioncontrol/templates/revisionlog.html b/trac/versioncontrol/templates/revisionlog.html
    a b  
    110110            <py:for each="idx, item in enumerate(items)"> 
    111111              <py:with vars="change = changes[item.rev]; 
    112112                             is_separator = item.change is None; 
    113                              chgset_context = context('changeset', change.rev, parent=context.resource.parent); 
     113                             chgset_context = context('changeset', change.rev, parent=repos.resource); 
    114114                             odd_even = idx % 2 and 'odd' or 'even'"> 
    115115                <!--! highlight copy or rename operations --> 
    116116                <tr py:if="not is_separator and item.get('copyfrom_path')" class="$odd_even"> 
  • trac/versioncontrol/templates/revisionlog.rss

    diff --git a/trac/versioncontrol/templates/revisionlog.rss b/trac/versioncontrol/templates/revisionlog.rss
    a b  
    1717 
    1818    <item py:for="item in items"  
    1919          py:with="change = changes[item.rev];  
    20                    item_context = context('changeset', change.rev, parent=context.resource.parent)"> 
     20                   item_context = context('changeset', change.rev, parent=repos.resource)"> 
    2121      ${author_or_creator(change.author, email_map)} 
    2222      <pubDate>${http_date(change.date)}</pubDate> 
    2323      <title>Revision $item.rev: ${shorten_line(change.message)}</title> 
  • trac/versioncontrol/templates/revisionlog.txt

    diff --git a/trac/versioncontrol/templates/revisionlog.txt b/trac/versioncontrol/templates/revisionlog.txt
    a b  
    11# 
    2 # ChangeLog for $path${reponame and _(" in $(reponame)s", reponame=reponame) or ''} 
     2# ChangeLog for $path${reponame and _(" in $(reponame)s", reponame=reponame) or None} 
    33#  
    44# Generated by Trac $trac.version 
    55# ${format_datetime()} 
  • trac/versioncontrol/web_ui/browser.py

    diff --git a/trac/versioncontrol/web_ui/browser.py b/trac/versioncontrol/web_ui/browser.py
    a b  
    2626from trac.mimeview.api import Mimeview, is_binary, \ 
    2727                              IHTMLPreviewAnnotator, Context 
    2828from trac.perm import IPermissionRequestor 
    29 from trac.resource import Resource, ResourceNotFound 
     29from trac.resource import ResourceNotFound 
    3030from trac.util import embedded_numbers 
    3131from trac.util.compat import any 
    3232from trac.util.datefmt import http_date, utc 
     
    291291 
    292292    def get_navigation_items(self, req): 
    293293        rm = RepositoryManager(self.env) 
    294         all_repos = rm.get_all_repositories() 
    295         if any(info.get('hidden') not in _TRUE_VALUES 
    296                and rm.get_repository(reponame).can_view(req.perm) 
    297                for reponame, info in all_repos.iteritems()): 
     294        if any(repos and repos.params.get('hidden') not in _TRUE_VALUES 
     295               and repos.can_view(req.perm) 
     296               for repos in rm.get_real_repositories()): 
    298297            yield ('mainnav', 'browser', 
    299298                   tag.a(_('Browse Source'), href=req.href.browser())) 
    300299 
     
    347346            raise ResourceNotFound(_("No repository '%(repo)s' found", 
    348347                                   repo=reponame)) 
    349348 
     349        if reponame != repos.reponame:  # Redirect alias 
     350            qs = req.query_string 
     351            req.redirect(req.href.browser(repos.reponame or None, path) 
     352                         + (qs and '?' + qs or '')) 
     353         
    350354        # Find node for the requested path/rev 
    351355        context = Context.from_request(req) 
    352356        node = None 
     
    362366                raise ResourceNotFound(e.message, 
    363367                                       _('Invalid changeset number')) 
    364368 
    365             repos_resource = Resource('repository', reponame) 
    366             context = context(repos_resource.child('source', path, 
     369            context = context(repos.resource.child('source', path, 
    367370                                                   version=node.created_rev)) 
    368371 
    369372        # Prepare template data 
    370         path_links = get_path_links(req.href, reponame, path, rev, order, desc) 
     373        path_links = get_path_links(req.href, repos.reponame, path, rev, 
     374                                    order, desc) 
    371375 
    372376        repo_data = dir_data = file_data = None 
    373377        if all_repositories: 
     
    375379                    context, all_repositories, order, desc) 
    376380        if node: 
    377381            if node.isdir: 
    378                 dir_data = self._render_dir( 
    379                         req, reponame, repos, node, rev, order, desc) 
     382                dir_data = self._render_dir(req, repos, node, rev, order, desc) 
    380383            elif node.isfile: 
    381                 file_data = self._render_file( 
    382                         req, context, reponame, repos, node, rev) 
     384                file_data = self._render_file(req, context, repos, node, rev) 
    383385 
    384386        quickjump_data = properties_data = None 
    385387        if node and not xhr: 
     
    387389                    'browser', context, node.get_properties()) 
    388390            quickjump_data = list(repos.get_quickjump_entries(rev)) 
    389391 
     392        reponame = repos.reponame or None 
    390393        data = { 
    391             'context': context, 'reponame': reponame or None, 
    392             'repos_resource': repos and repos_resource, 
     394            'context': context, 'reponame': reponame, 
     395            'repos': repos, 
    393396            'path': path, 'rev': node and node.rev, 'stickyrev': rev, 
    394397            'created_path': node and node.created_path, 
    395398            'created_rev': node and node.created_rev, 
     
    415418                prev_rev = repos.previous_rev(rev=node.rev, 
    416419                                              path=node.created_path) 
    417420                if prev_rev: 
    418                     href = req.href.browser(reponame or None, 
     421                    href = req.href.browser(reponame, 
    419422                                            node.created_path, rev=prev_rev) 
    420423                    add_link(req, 'prev', href, 
    421424                             _('Revision %(num)s', num=prev_rev)) 
    422425                if rev is not None: 
    423                     add_link(req, 'up', req.href.browser(reponame or None, 
     426                    add_link(req, 'up', req.href.browser(reponame, 
    424427                                                         node.created_path)) 
    425428                next_rev = repos.next_rev(rev=node.rev, 
    426429                                          path=node.created_path) 
    427430                if next_rev: 
    428                     href = req.href.browser(reponame or None, 
    429                                             node.created_path, rev=next_rev) 
     431                    href = req.href.browser(reponame, node.created_path, 
     432                                            rev=next_rev) 
    430433                    add_link(req, 'next', href, 
    431434                             _('Revision %(num)s', num=next_rev)) 
    432435                prevnext_nav(req, _('Previous Revision'), _('Next Revision'), 
     
    436439                    add_link(req, 'up', path_links[-2]['href'], 
    437440                             _('Parent directory')) 
    438441            add_ctxtnav(req, tag.a(_('Last Change'),  
    439                         href=req.href.changeset(node.rev, reponame or None, 
     442                        href=req.href.changeset(node.rev, reponame, 
    440443                                                node.created_path))) 
    441444            if node.isfile: 
    442445                if data['file']['annotate']: 
    443446                    add_ctxtnav(req, _('Normal'),  
    444447                                title=_('View file without annotations'),  
    445                                 href=req.href.browser(reponame or None, 
     448                                href=req.href.browser(reponame, 
    446449                                                      node.created_path,  
    447450                                                      rev=node.rev)) 
    448451                else: 
     
    450453                                title=_('Annotate each line with the last ' 
    451454                                        'changed revision ' 
    452455                                        '(this can be time consuming...)'),  
    453                                 href=req.href.browser(reponame or None, 
     456                                href=req.href.browser(reponame, 
    454457                                                      node.created_path,  
    455458                                                      rev=node.rev, 
    456459                                                      annotate='blame')) 
    457460            add_ctxtnav(req, _('Revision Log'),  
    458                         href=req.href.log(reponame or None, path, rev=rev)) 
     461                        href=req.href.log(reponame, path, rev=rev)) 
    459462            path_url = repos.get_path_url(path, rev) 
    460463            if path_url: 
    461464                if path_url.startswith('//'): 
     
    489492                            timerange = TimeRange(youngest.date) 
    490493                        else: 
    491494                            timerange.insert(youngest.date) 
    492                     entry = (reponame, repoinfo, youngest, None) 
     495                    entry = (reponame, repoinfo, repos, youngest, None) 
    493496                else: 
    494                     entry = (reponame, repoinfo, None, "XXX") 
     497                    entry = (reponame, repoinfo, None, None, "XXX") 
    495498            except TracError, err: 
    496                 entry = (reponame, repoinfo, None, exception_to_unicode(err)) 
     499                entry = (reponame, repoinfo, None, None, 
     500                         exception_to_unicode(err)) 
    497501            repositories.append(entry) 
    498502 
    499503        # Ordering of repositories 
    500504        if order == 'date': 
    501             def repo_order((reponame, repoinfo, repos, youngest)): 
     505            def repo_order((reponame, repoinfo, repos, youngest, err)): 
    502506                return youngest and youngest.date 
    503507        else: 
    504             def repo_order((reponame, repoinfo, repos, youngest)): 
     508            def repo_order((reponame, repoinfo, repos, youngest, err)): 
    505509                return embedded_numbers(reponame.lower()) 
    506510 
    507511        repositories = sorted(repositories, key=repo_order, reverse=desc) 
     
    509513        return {'repositories' : repositories, 
    510514                'timerange': timerange, 'colorize_age': custom_colorizer} 
    511515 
    512     def _render_dir(self, req, reponame, repos, node, rev, order, desc): 
     516    def _render_dir(self, req, repos, node, rev, order, desc): 
    513517        req.perm(node.resource).require('BROWSER_VIEW') 
    514518 
    515519        # Entries metadata 
     
    564568        if node.path and patterns and \ 
    565569               filter(None, [fnmatchcase(node.path, p) for p in patterns]): 
    566570            zip_href = req.href.changeset(rev or repos.youngest_rev,  
    567                                           reponame, node.path, old=rev,  
    568                                           old_path=reponame or '/',  
     571                                          repos.reponame or None, node.path, 
     572                                          old=rev, 
     573                                          old_path=repos.reponame or '/', 
    569574                                          format='zip') 
    570575            add_link(req, 'alternate', zip_href, _('Zip Archive'), 
    571576                     'application/zip', 'zip') 
     
    578583                                   timerange.to_seconds(timerange.oldest)), 
    579584                } 
    580585 
    581     def _render_file(self, req, context, reponame, repos, node, rev=None): 
     586    def _render_file(self, req, context, repos, node, rev=None): 
    582587        req.perm(node.resource).require('FILE_VIEW') 
    583588 
    584589        mimeview = Mimeview(self.env) 
     
    618623 
    619624            # add ''Plain Text'' alternate link if needed 
    620625            if not is_binary(chunk) and mime_type != 'text/plain': 
    621                 plain_href = req.href.browser(reponame or None, node.path, 
    622                                               rev=rev, format='txt') 
     626                plain_href = req.href.browser(repos.reponame or None, 
     627                                              node.path, rev=rev, format='txt') 
    623628                add_link(req, 'alternate', plain_href, _('Plain Text'), 
    624629                         'text/plain') 
    625630 
    626631            # add ''Original Format'' alternate link (always) 
    627632            raw_href = req.href.export(rev or repos.youngest_rev,  
    628                                        reponame, node.path) 
     633                                       repos.reponame or None, node.path) 
    629634            add_link(req, 'alternate', raw_href, _('Original Format'), 
    630635                     mime_type) 
    631636 
     
    784789                         if fnmatchcase(rdata[0], glob)) 
    785790 
    786791        if format == 'table': 
    787             data = self._render_repository_index( 
    788                     formatter.context, all_repos, order, desc) 
     792            repo = self._render_repository_index(formatter.context, all_repos, 
     793                                                order, desc) 
    789794 
    790795            add_stylesheet(formatter.req, 'common/css/browser.css') 
     796            data = {'repo': repo, 'desc': desc and 1 or None, 
     797                    'reponame': None, 'path': '/', 'stickyrev': None} 
    791798            from trac.web.chrome import Chrome 
    792799            return Chrome(self.env).render_template( 
    793                     formatter.req, 'repository_index.html',  
    794                     {'repo': data}, None, fragment=True) 
     800                    formatter.req, 'repository_index.html', data, None, 
     801                    fragment=True) 
    795802 
    796         def repolink(reponame): 
     803        def repolink(reponame, repos): 
    797804            label = reponame or _('(default)') 
    798805            return Markup(tag.a(label,  
    799806                          title=_('View repository %(repo)s', repo=label), 
    800                           href=formatter.href.browser(reponame or None))) 
     807                          href=formatter.href.browser(repos.reponame or None))) 
    801808 
    802         all_repos = sorted( 
    803             (reponame, info) for reponame, info in all_repos.iteritems() 
    804             if info.get('hidden') not in _TRUE_VALUE 
    805                and rm.get_repository(reponame).can_view(formatter.perm)) 
     809        all_repos = dict((reponame, rm.get_repository(reponame)) 
     810                         for reponame in all_repos) 
     811        all_repos = sorted((reponame, repos) for reponame, repos in all_repos 
     812                           if repos 
     813                           and repos.params.get('hidden') not in _TRUE_VALUE 
     814                           and repos.can_view(formatter.perm)) 
    806815 
    807816        if format == 'list': 
    808817            return tag.dl([ 
    809                 tag(tag.dt(repolink(reponame)), 
    810                     tag.dd(repoinfo.get('description'))) 
    811                 for reponame, repoinfo in all_repos]) 
     818                tag(tag.dt(repolink(reponame, repos)), 
     819                    tag.dd(repos.params.get('description'))) 
     820                for reponame, repos in all_repos]) 
    812821        else: # compact 
    813             return Markup(', ').join([repolink(reponame) 
    814                                       for reponame, repoinfo in all_repos]) 
     822            return Markup(', ').join([repolink(reponame, repos) 
     823                                      for reponame, repos in all_repos]) 
    815824 
    816825         
    817826 
     
    820829    def __init__(self, env, context): 
    821830        self.env = env 
    822831        self.context = context 
    823         self.reponame = context.resource.parent.id 
     832        self.repos = env.get_repository(context.resource.parent.id) 
    824833        self.path = context.resource.id 
    825         self.repos = env.get_repository(self.reponame) 
    826834        self.rev = context.resource.version 
    827835        # maintain state 
    828836        self.prev_chgset = None 
     
    876884         
    877885        # -- compute anchor and style once per revision 
    878886        if rev not in self.chgset_data: 
    879             chgset_href = self.context.href.changeset(rev, 
    880                                                       self.reponame or None, 
    881                                                       path) 
     887            chgset_href = \ 
     888                self.context.href.changeset(rev, self.repos.reponame or None, 
     889                                            path) 
    882890            short_author = chgset.author.split(' ', 1)[0] 
    883891            title = shorten_line('%s: %s' % (short_author, chgset.message)) 
    884892            anchor = tag.a('[%s]' % self.repos.short_rev(rev), # shortname 
  • trac/versioncontrol/web_ui/changeset.py

    diff --git a/trac/versioncontrol/web_ui/changeset.py b/trac/versioncontrol/web_ui/changeset.py
    a b  
    3434from trac.resource import Resource, ResourceNotFound 
    3535from trac.search import ISearchSource, search_to_sql, shorten_result 
    3636from trac.timeline.api import ITimelineEventProvider 
    37 from trac.util import embedded_numbers, content_disposition 
     37from trac.util import content_disposition, embedded_numbers, pathjoin 
    3838from trac.util.compat import any, set 
    3939from trac.util.datefmt import pretty_timedelta, utc 
    4040from trac.util.text import exception_to_unicode, to_unicode, \ 
     
    252252        try: 
    253253            new_path = repos.normalize_path(new_path) 
    254254            new = repos.normalize_rev(new) 
     255            full_new_path = '/' + pathjoin(repos.reponame, new_path) 
    255256            old_path = repos.normalize_path(old_path or new_path) 
    256257            old = repos.normalize_rev(old or new) 
     258            full_old_path = '/' + pathjoin(repos.reponame, old_path) 
    257259        except NoSuchChangeset, e: 
    258260            raise ResourceNotFound(e.message, _('Invalid Changeset Number')) 
    259261 
     
    269271        else: 
    270272            restricted = old_path == new_path # (same path or not) 
    271273 
    272         # -- redirect if changing the diff options 
    273         if req.args.has_key('update'): 
     274        # -- redirect if changing the diff options or alias requested 
     275        if req.args.has_key('update') or reponame != repos.reponame: 
     276            reponame = repos.reponame or None 
    274277            if chgset: 
    275278                if restricted: 
    276                     req.redirect(req.href.changeset(new, reponame or None, 
    277                                                     new_path)) 
     279                    req.redirect(req.href.changeset(new, reponame, new_path)) 
    278280                else: 
    279                     req.redirect(req.href.changeset(new, reponame or None)) 
     281                    req.redirect(req.href.changeset(new, reponame)) 
    280282            else: 
    281                 req.redirect(req.href.changeset(new, reponame or None, 
     283                req.redirect(req.href.changeset(new, reponame, 
    282284                                                new_path, old=old, 
    283285                                                old_path=full_old_path)) 
    284286 
     
    300302                old_path = new_path 
    301303            data = {'old_path': old_path, 'old_rev': old, 
    302304                    'new_path': new_path, 'new_rev': new} 
    303         data['reponame'] = reponame or None 
    304         data['diff'] = diff_data 
    305         data['wiki_format_messages'] = self.wiki_format_messages 
     305        data.update({'repos': repos, 'reponame': repos.reponame or None, 
     306                     'diff': diff_data, 
     307                     'wiki_format_messages': self.wiki_format_messages}) 
    306308 
    307309        if chgset: 
    308310            chgset = repos.get_changeset(new) 
     
    340342                self._render_zip(req, filename, repos, data) 
    341343 
    342344        # -- HTML format 
    343         self._render_html(req, reponame, repos, chgset, restricted, xhr, data) 
     345        self._render_html(req, repos, chgset, restricted, xhr, data) 
    344346         
    345347        if chgset: 
    346348            diff_params = 'new=%s' % new 
    347349        else: 
    348             diff_params = unicode_urlencode({'new_path': new_path, 
    349                                              'new': new, 
    350                                              'old_path': old_path, 
    351                                              'old': old}) 
    352         add_link(req, 'alternate', '?format=diff&'+diff_params, 
     350            diff_params = unicode_urlencode({'new_path': new_path, 'new': new, 
     351                                             'old_path': old_path, 'old': old}) 
     352        add_link(req, 'alternate', '?format=diff&' + diff_params, 
    353353                 _('Unified Diff'), 'text/plain', 'diff') 
    354         add_link(req, 'alternate', '?format=zip&'+diff_params, _('Zip Archive'), 
    355                  'application/zip', 'zip') 
     354        add_link(req, 'alternate', '?format=zip&' + diff_params, 
     355                 _('Zip Archive'), 'application/zip', 'zip') 
    356356        add_script(req, 'common/js/diff.js') 
    357357        add_stylesheet(req, 'common/css/changeset.css') 
    358358        add_stylesheet(req, 'common/css/diff.css') 
     
    371371 
    372372    # Internal methods 
    373373 
    374     def _render_html(self, req, reponame, repos, chgset, restricted, xhr, data): 
     374    def _render_html(self, req, repos, chgset, restricted, xhr, data): 
    375375        """HTML version""" 
    376376        data['restricted'] = restricted 
    377377        browser = BrowserModule(self.env) 
     378        reponame = repos.reponame or None 
    378379 
    379380        if chgset: # Changeset Mode (possibly restricted on a path) 
    380381            path, rev = data['new_path'], data['new_rev'] 
     
    405406            title = _changeset_title(rev) 
    406407 
    407408            # Support for revision properties (#2545) 
    408             repos_resource = Resource('repository', reponame) 
    409409            context = Context.from_request(req, 'changeset', chgset.rev, 
    410                                            parent=repos_resource) 
     410                                           parent=repos.resource) 
    411411            data['context'] = context 
    412412            revprops = chgset.get_properties() 
    413413            data['properties'] = browser.render_properties('revprop', context, 
     
    419419                    if prev: 
    420420                        prev_path, prev_rev = prev[:2] 
    421421                        if prev_rev: 
    422                             prev_href = req.href.changeset(prev_rev, 
    423                                                            reponame or None, 
     422                            prev_href = req.href.changeset(prev_rev, reponame, 
    424423                                                           prev_path) 
    425424                    else: 
    426425                        prev_path = prev_rev = None 
    427426                else: 
    428427                    add_link(req, 'first',  
    429                              req.href.changeset(oldest_rev, reponame or None), 
     428                             req.href.changeset(oldest_rev, reponame), 
    430429                             _('Changeset %(id)s', id=oldest_rev)) 
    431430                    prev_path = data['old_path'] 
    432431                    prev_rev = repos.previous_rev(chgset.rev) 
    433432                    if prev_rev: 
    434                         prev_href = req.href.changeset(prev_rev, 
    435                                                        reponame or None) 
     433                        prev_href = req.href.changeset(prev_rev, reponame) 
    436434                if prev_rev: 
    437435                    add_link(req, 'prev', prev_href, _changeset_title(prev_rev)) 
    438436            youngest_rev = repos.youngest_rev 
     
    441439                    next_rev = repos.next_rev(chgset.rev, path) 
    442440                    if next_rev: 
    443441                        if repos.has_node(path, next_rev): 
    444                             next_href = req.href.changeset(next_rev, 
    445                                                            reponame or None, 
     442                            next_href = req.href.changeset(next_rev, reponame, 
    446443                                                           path) 
    447444                        else: # must be a 'D'elete or 'R'ename, show full cset 
    448                             next_href = req.href.changeset(next_rev, 
    449                                                            reponame or None) 
     445                            next_href = req.href.changeset(next_rev, reponame) 
    450446                else: 
    451447                    add_link(req, 'last',  
    452                              req.href.changeset(youngest_rev, 
    453                                                 reponame or None), 
     448                             req.href.changeset(youngest_rev, reponame), 
    454449                             _('Changeset %(id)s', id=youngest_rev)) 
    455450                    next_rev = repos.next_rev(chgset.rev) 
    456451                    if next_rev: 
    457                         next_href = req.href.changeset(next_rev, 
    458                                                        reponame or None) 
     452                        next_href = req.href.changeset(next_rev, reponame) 
    459453                if next_rev: 
    460454                    add_link(req, 'next', next_href, _changeset_title(next_rev)) 
    461455 
     
    478472            return {'path': node.path, 
    479473                    'rev': node.rev, 
    480474                    'shortrev': repos.short_rev(node.rev), 
    481                     'href': req.href.browser(reponame or None, 
     475                    'href': req.href.browser(reponame, 
    482476                                             node.created_path, 
    483477                                             rev=node.created_rev, 
    484478                                             annotate=annotated and 'blame' or \ 
     
    623617                filestats[change] += 1 
    624618                if change in Changeset.DIFF_CHANGES: 
    625619                    if chgset: 
    626                         href = req.href.changeset(new_node.rev, 
    627                                                   reponame or None,  
     620                        href = req.href.changeset(new_node.rev, reponame, 
    628621                                                  new_node.path) 
    629622                        title = _('Show the changeset %(id)s restricted to ' 
    630623                                  '%(path)s', id=new_node.rev, 
    631624                                  path=new_node.path) 
    632625                    else: 
    633626                        href = req.href.changeset( 
    634                             new_node.created_rev, reponame or None, 
     627                            new_node.created_rev, reponame, 
    635628                            new_node.created_path, 
    636629                            old=old_node.created_rev, 
    637                             old_path=posixpath.join(reponame,  
    638                                                     old_node.created_path)) 
     630                            old_path=pathjoin(repos.reponame,  
     631                                              old_node.created_path)) 
    639632                        title = _('Show the %(range)s differences restricted ' 
    640633                                  'to %(path)s', 
    641634                                  range='r%s:%s' % (old_node.rev, new_node.rev), 
     
    713706            else: 
    714707                old_node_path = repos.normalize_path(old_node.path) 
    715708                diff_old_path = repos.normalize_path(data['old_path']) 
    716                 new_path = posixpath.join(data['new_path'], 
    717                                           old_node_path[len(diff_old_path)+1:]) 
     709                new_path = pathjoin(data['new_path'], 
     710                                    old_node_path[len(diff_old_path) + 1:]) 
    718711 
    719712            if old_content != new_content: 
    720713                options = data['diff']['options'] 
     
    845838            # only repository filter. 
    846839            filters = [] 
    847840            rm = RepositoryManager(self.env) 
    848             repositories = rm.get_all_repositories() 
     841            repositories = rm.get_real_repositories() 
    849842            if len(repositories) > 1: 
    850                 visible_repos = set( 
    851                     name for name, info in repositories.items() 
    852                     if info.get('hidden') not in _TRUE_VALUES 
    853                     and rm.get_repository(name).can_view(req.perm)) 
    854                 default_is_aliased = any(info.get('alias') == '' and 
    855                                          name in visible_repos 
    856                                          for name, info in repositories.items()) 
    857                 default_is_alias = repositories.get('', {}).get('alias') \ 
    858                                    in visible_repos 
    859                 for reponame in repositories.keys(): 
    860                     if reponame: 
    861                         label = reponame 
    862                     elif default_is_aliased or default_is_alias: 
    863                         continue 
    864                     else: 
    865                         label = _('(default)') 
    866                     if reponame in visible_repos: 
    867                         filters.append(('repo-' + reponame, 
    868                                         u"\xa0\xa0-\xa0" + label)) 
     843                filters = [ 
     844                    ('repo-' + repos.reponame, 
     845                     u"\xa0\xa0-\xa0" + (repos.reponame or _('(default)'))) 
     846                    for repos in repositories 
     847                    if repos.params.get('hidden') not in _TRUE_VALUES 
     848                    and repos.can_view(req.perm)] 
    869849                filters.sort() 
    870850                add_script(req, 'common/js/timeline_multirepos.js') 
    871851                changeset_label = _('Changesets in all repositories') 
     
    893873                collapse_changesets = lambda c: c.rev 
    894874                 
    895875            uids_seen = {} 
    896             def generate_changesets(reponame, repos): 
    897                 repos_resource = Resource('repository', reponame) 
     876            def generate_changesets(repos): 
    898877                for _, changesets in groupby(repos.get_changesets(start, stop), 
    899878                                             key=collapse_changesets): 
    900879                    viewable_changesets = [] 
    901880                    for cset in changesets: 
    902881                        cset_resource = Resource('changeset', cset.rev, 
    903                                                  parent=repos_resource) 
     882                                                 parent=repos.resource) 
    904883                        if cset.can_view(req.perm): 
    905                             repos_for_uid = [reponame] 
     884                            repos_for_uid = [repos.reponame] 
    906885                            uid = repos.get_changeset_uid(cset.rev) 
    907886                            if uid: 
    908887                                # uid can be seen in multiple repositories 
    909888                                if uid in uids_seen: 
    910                                     uids_seen[uid].append(reponame) 
     889                                    uids_seen[uid].append(repos.reponame) 
    911890                                    continue # already viewable, simply append 
    912891                                uids_seen[uid] = repos_for_uid 
    913892                            viewable_changesets.append((cset, cset_resource, 
     
    919898                                show_location, show_files)) 
    920899 
    921900            rm = RepositoryManager(self.env) 
    922             for reponame in rm.get_all_repositories(): 
    923                 if all_repos or ('repo-' + reponame) in repo_filters: 
     901            for repos in rm.get_real_repositories(): 
     902                if all_repos or ('repo-' + repos.reponame) in repo_filters: 
    924903                    try: 
    925                         repos = rm.get_repository(reponame) 
    926                         for event in generate_changesets(reponame, repos): 
     904                        for event in generate_changesets(repos): 
    927905                            yield event 
    928906                    except TracError, e: 
    929907                        self.log.error("Timeline event provider for repository" 
    930908                                       " '%s' failed: %r",  
    931                                        reponame, exception_to_unicode(e)) 
     909                                       repos.reponame, exception_to_unicode(e)) 
    932910 
    933911    def render_timeline_event(self, context, field, event): 
    934912        changesets, show_location, show_files = event[3] 
     
    10621040            try: 
    10631041                changeset = repos.get_changeset(rev) 
    10641042                if changeset.can_view(formatter.perm): 
    1065                     href = formatter.href.changeset(rev, reponame or None, 
     1043                    href = formatter.href.changeset(rev, 
     1044                                                    repos.reponame or None, 
    10661045                                                    path) 
    10671046                    return tag.a(label, class_="changeset", 
    10681047                                 title=shorten_line(changeset.message), 
     
    11191098    def get_search_results(self, req, terms, filters): 
    11201099        if not 'changeset' in filters: 
    11211100            return 
     1101        rm = RepositoryManager(self.env) 
     1102        repositories = dict((repos.params['id'], repos) 
     1103                            for repos in rm.get_real_repositories()) 
    11221104        db = self.env.get_db_cnx() 
    11231105        sql, args = search_to_sql(db, ['rev', 'message', 'author'], terms) 
    11241106        cursor = db.cursor() 
    11251107        cursor.execute("SELECT repos,rev,time,author,message " 
    11261108                       "FROM revision WHERE " + sql, args) 
    1127         for reponame, rev, ts, author, log in cursor: 
    1128             repos = self.env.get_repository(reponame) 
     1109        for id, rev, ts, author, log in cursor: 
     1110            repos = repositories.get(id) 
    11291111            if not repos: 
    11301112                continue # revisions for a no longer active repository 
    1131             cset = Resource('repository', repos.reponame).child('changeset', 
    1132                                                                 rev) 
     1113            cset = repos.resource.child('changeset', rev) 
    11331114            if 'CHANGESET_VIEW' in req.perm(cset): 
    1134                 yield (req.href.changeset(rev, reponame or None), 
     1115                yield (req.href.changeset(rev, repos.reponame or None), 
    11351116                       '[%s]: %s' % (rev, shorten_line(log)), 
    11361117                       datetime.fromtimestamp(ts, utc), author, 
    11371118                       shorten_result(log, terms)) 
     
    11591140 
    11601141            if repos: 
    11611142                entries = [(e.isdir, e.name,  
    1162                             '/' + posixpath.join(reponame, e.path)) 
     1143                            '/' + pathjoin(repos.reponame, e.path)) 
    11631144                           for e in repos.get_node(path).get_entries() 
    11641145                           if e.can_view(req.perm)] 
    11651146            if not reponame: 
    1166                 entries.extend((True, name, '/' + name) 
    1167                                for name in rm.get_all_repositories() 
    1168                                if rm.get_repository(name).can_view(req.perm)) 
     1147                entries.extend((True, repos.reponame, '/' + repos.reponame) 
     1148                               for repos in rm.get_real_repositories() 
     1149                               if repos.can_view(req.perm)) 
    11691150 
    11701151            elem = tag.ul( 
    11711152                [tag.li(isdir and tag.b(path) or path) 
     
    11921173        old_rev = old_repos.normalize_rev(old_rev) 
    11931174 
    11941175        # -- prepare rendering 
    1195         data = {'new_path': posixpath.join(new_reponame, new_path), 
     1176        data = {'new_path': '/' + pathjoin(new_repos.reponame, new_path), 
    11961177                'new_rev': new_rev, 
    1197                 'old_path': posixpath.join(old_reponame, old_path), 
     1178                'old_path': '/' + pathjoin(old_repos.reponame, old_path), 
    11981179                'old_rev': old_rev} 
    11991180 
    12001181        add_script(req, 'common/js/suggest.js') 
  • trac/versioncontrol/web_ui/log.py

    diff --git a/trac/versioncontrol/web_ui/log.py b/trac/versioncontrol/web_ui/log.py
    a b  
    2525from trac.core import * 
    2626from trac.mimeview import Context 
    2727from trac.perm import IPermissionRequestor 
    28 from trac.resource import Resource 
    2928from trac.util import Ranges 
    3029from trac.util.compat import any 
    3130from trac.util.html import html 
     
    8281        verbose = req.args.get('verbose') 
    8382        limit = int(req.args.get('limit') or self.default_log_limit) 
    8483 
    85         reponame, repos, path = RepositoryManager(self.env).\ 
    86                 get_repository_by_path(path) 
     84        rm = RepositoryManager(self.env) 
     85        reponame, repos, path = rm.get_repository_by_path(path) 
     86         
     87        if not repos: 
     88            raise ResourceNotFound(_("No repository '%(repo)s' found", 
     89                                   repo=reponame)) 
     90 
     91        if reponame != repos.reponame:  # Redirect alias 
     92            qs = req.query_string 
     93            req.redirect(req.href.log(repos.reponame or None, path) 
     94                         + (qs and '?' + qs or '')) 
    8795 
    8896        normpath = repos.normalize_path(path) 
    8997        # if `revs` parameter is given, then we're restricted to the  
     
    198206            params.update(args) 
    199207            if verbose: 
    200208                params['verbose'] = verbose 
    201             return req.href.log(reponame or None, path, **params) 
     209            return req.href.log(repos.reponame or None, path, **params) 
    202210 
    203211        if format in ('rss', 'changelog'): 
    204212            info = [i for i in info if i['change']] # drop separators 
     
    247255                cs['actions'] = actions 
    248256                extra_changes[rev] = cs 
    249257 
    250         repos_resource = Resource('repository', reponame) 
    251258        data = { 
    252259            'context': Context.from_request(req, 'source', path, 
    253                                             parent=repos_resource), 
    254             'reponame': reponame or None, 'repos': repos, 
     260                                            parent=repos.resource), 
     261            'reponame': repos.reponame or None, 'repos': repos, 
    255262            'path': path, 'rev': rev, 'stop_rev': stop_rev,  
    256263            'revranges': revranges, 
    257264            'mode': mode, 'verbose': verbose, 'limit' : limit, 
     
    265272            return 'revisionlog.txt', data, 'text/plain' 
    266273        elif req.args.get('format') == 'rss': 
    267274            data['context'] = Context.from_request(req, 'source',  
    268                                                    path, parent=repos_resource, 
     275                                                   path, parent=repos.resource, 
    269276                                                   absurls=True) 
    270277            return 'revisionlog.rss', data, 'application/rss+xml' 
    271278 
     
    286293        add_stylesheet(req, 'common/css/diff.css') 
    287294        add_stylesheet(req, 'common/css/browser.css') 
    288295 
    289         path_links = get_path_links(req.href, reponame, path, rev) 
     296        path_links = get_path_links(req.href, repos.reponame, path, rev) 
    290297        if path_links: 
    291298            data['path_links'] = path_links 
    292299        if len(path_links) > 1: 
     
    301308        add_link(req, 'alternate', changelog_href, _('ChangeLog'), 'text/plain') 
    302309 
    303310        add_ctxtnav(req, _('View Latest Revision'),  
    304                     href=req.href.browser(reponame or None, path)) 
     311                    href=req.href.browser(repos.reponame or None, path)) 
    305312        if 'next' in req.chrome['links']: 
    306313            next = req.chrome['links']['next'][0] 
    307314            add_ctxtnav(req, tag.span(tag.a(_('Older Revisions'),  
     
    368375            revs = None 
    369376        if 'LOG_VIEW' in formatter.perm: 
    370377            if revranges: 
    371                 href = formatter.href.log(reponame or None, path or '/', 
     378                href = formatter.href.log(repos.reponame or None, path or '/', 
    372379                                          revs=str(revranges))  
    373380            else: 
    374381                try: 
    375382                    rev = repos.normalize_rev(revs) 
    376383                except NoSuchChangeset: 
    377384                    rev = None 
    378                 href = formatter.href.log(reponame or None, path or '/', 
     385                href = formatter.href.log(repos.reponame or None, path or '/', 
    379386                                          rev=rev) 
    380387            if query and (revranges or revs): 
    381388                query = '&' + query[1:] 
  • trac/versioncontrol/web_ui/tests/wikisyntax.py

    diff --git a/trac/versioncontrol/web_ui/tests/wikisyntax.py b/trac/versioncontrol/web_ui/tests/wikisyntax.py
    a b  
    33import unittest 
    44 
    55from trac.test import Mock 
    6 from trac.wiki.tests import formatter 
    76from trac.versioncontrol import NoSuchChangeset 
    87from trac.versioncontrol.api import * 
    98from trac.versioncontrol.web_ui import * 
     9from trac.wiki.tests import formatter 
    1010 
    1111 
    1212def _get_changeset(rev): 
     
    2525            raise NoSuchChangeset(rev) 
    2626     
    2727def _get_repository(reponame): 
    28     return Mock(get_changeset=_get_changeset, youngest_rev='200', 
     28    return Mock(reponame=reponame, youngest_rev='200', 
     29                get_changeset=_get_changeset, 
    2930                normalize_rev=_normalize_rev) 
    3031 
    3132def repository_setup(tc): 
  • trac/web/chrome.py

    diff --git a/trac/web/chrome.py b/trac/web/chrome.py
    a b  
    5858from trac.mimeview import get_mimetype, Context 
    5959from trac.resource import * 
    6060from trac.util import compat, get_reporter_id, presentation, get_pkginfo, \ 
    61                       translation 
     61                      pathjoin, translation 
    6262from trac.util.compat import any, partial 
    6363from trac.util.html import escape, plaintext 
    6464from trac.util.text import pretty_size, obfuscate_email_address, \ 
     
    366366        'ngettext': translation.ngettext, 
    367367        'paginate': presentation.paginate, 
    368368        'partial': partial, 
     369        'pathjoin': pathjoin, 
    369370        'plaintext': plaintext, 
    370371        'pprint': pprint.pformat, 
    371372        'pretty_size': pretty_size, 
  • tracopt/ticket/commit_updater.py

    diff --git a/tracopt/ticket/commit_updater.py b/tracopt/ticket/commit_updater.py
    a b  
    4343from trac.config import BoolOption, Option 
    4444from trac.core import Component, implements 
    4545from trac.perm import PermissionCache 
    46 from trac.resource import Resource 
    4746from trac.ticket import Ticket 
    4847from trac.ticket.notification import TicketNotifyEmail 
    4948from trac.ticket.web_ui import TicketModule 
     
    276275        reponame = args.get('repository') 
    277276        rev = args.get('revision') 
    278277        repos = RepositoryManager(self.env).get_repository(reponame) 
    279         changeset = repos.get_changeset(rev) 
     278        if repos: 
     279            changeset = repos.get_changeset(rev) 
     280            message = changeset.message 
     281            rev = changeset.rev 
     282        else: 
     283            message = content 
    280284        if formatter.context.resource.realm == 'ticket': 
    281285            ticket_re = CommitTicketUpdater.ticket_re 
    282286            if not any(int(tkt_id) == formatter.context.resource.id 
    283                        for tkt_id in ticket_re.findall(changeset.message)): 
     287                       for tkt_id in ticket_re.findall(message)): 
    284288                return tag.p("(The changeset message doesn't reference this " 
    285289                             "ticket)", class_='hint') 
    286290        if ChangesetModule(self.env).wiki_format_messages: 
    287291            return tag.div(format_to_html(self.env, 
    288                 formatter.context('changeset', changeset.rev, 
    289                                   parent=Resource('repository', reponame)), 
    290                 changeset.message, escape_newlines=True), class_='message') 
     292                formatter.context('changeset', rev, parent=repos.resource), 
     293                message, escape_newlines=True), class_='message') 
    291294        else: 
    292             return tag.pre(changeset.message, class_='message') 
     295            return tag.pre(message, class_='message')