Edgewall Software

Ticket #919: category.1060.patch

File category.1060.patch, 92.9 kB (added by cboos@…, 4 years ago)

The previous patch was incomplete (trac/upgrades/db8.py was missing)

  • htdocs/css/trac.css

    === htdocs/stable-bct-trac_banner.png
    ==================================================================
    Cannot display: file marked as a binary type.
    
    Property changes on: htdocs/stable-bct-trac_banner.png
    ___________________________________________________________________
    Name: svn:executable
     +*
    Name: svn:mime-type
     +image/x-png
    
    === htdocs/css/trac.css
    ==================================================================
     
    240240a.missing:link,a.missing:visited { background: #fafaf0; color: #998 } 
    241241a.missing:hover { color: #000; } 
    242242 
     243a.external:link,a.external:visited { color: #00b } 
     244 
    243245#content.wiki { line-height: 140% } 
    244246.wikitoolbar { 
    245247 border: solid #d7d7d7; 
     
    345347#content.error pre, div.system-message pre { margin-left: 1em; overflow: auto } 
    346348div.system-message p { margin: 0; } 
    347349div.system-message p.system-message-title { font-weight: bold; } 
     350div.sidebar, div.contents {  
     351 background: #f7f7f0; 
     352 border: 1px outset #998; 
     353 float: right; 
     354 font-size: 90%; 
     355 padding: .8em; 
     356 margin: 0 1em 1em; 
     357 width: 26em;margin: 0;  
     358} 
     359p.sidebar-title, p.topic-title { font-weight: bold; } 
     360div.note {  
     361 background: #d7d7f0; 
     362 border: 1px outset #998; 
     363 float: left 
     364 font-size: 90%; 
     365 padding: .8em; 
     366 margin: 0 1em 1em; 
     367 width: 26em; 
     368} 
     369p.admonition-title { font-weight: bold;text-align: center } 
    348370 
    349371/* Styles for search word highlighting */ 
    350372.searchword0 { background: #ff9 } 
  • htdocs/css/browser.css

    === htdocs/css/browser.css
    ==================================================================
     
    4040#chglist td.rev a, #chglist td.chgset a { border-bottom: none } 
    4141#chglist td.summary { width: 100% } 
    4242 
     43/* Styles for the diff forms inside the log table */ 
     44#chglist input { 
     45 font-size: 10px; 
     46 margin: 0; 
     47 padding: 0; 
     48 text-align: center; 
     49 vertical-align: middle; 
     50} 
     51#chglist form { 
     52 margin: 0; 
     53 padding: 0; 
     54 white-space: nowrap; 
     55} 
     56 
    4357/* Styles for the revision info in the file module */ 
    4458#info { 
    4559 background: #f7f7f0; 
  • htdocs/css/ticket.css

    === htdocs/css/ticket.css
    ==================================================================
     
    2121#ticket th { color: #996; font-weight: normal; text-align: left } 
    2222#ticket hr { color: #dd9; border-color: #dd9; border-width: 1px 0 0; height: 1px; margin: .5em 0 0 } 
    2323 
     24#ticket .category { font-size: 200% }  
     25 
    2426#attachments { border: 1px outset #996; padding: 1em } 
    2527#attachments .attachments { list-style: square; margin-left: 2em; padding: 0 } 
    2628 
  • htdocs/css/timeline.css

    === htdocs/css/timeline.css
    ==================================================================
     
    2727dt .time { color: #777 } 
    2828dd { font-size: 80%; margin: 0 0 .5em 5em; padding: 0 } 
    2929 
     30 
    3031/* Apply icon background-image twice to avoid hover-flicker in IE/Win */ 
    3132dt.changeset, dt.changeset a { background-image: url(../changeset.png) !important } 
    3233dt.newticket, dt.newticket a { background-image: url(../newticket.png) !important } 
    3334dt.closedticket, dt.closedticket a { background-image: url(../closedticket.png) !important } 
    3435dt.wiki, dt.wiki a { background-image: url(../wiki.png) !important } 
    3536dt.milestone, dt.milestone a { background-image: url(../milestone.png) !important } 
     37dt.ticketcomment a { font-size: 80%; color: #555 } 
     38dd.ticketcomment { font-size: 70%; color: #555; margin: 0 0 .5em 5em; padding: 0 } 
    3639 
     40 
    3741.diff-unmod { color: #000 } 
    3842.diff-rem { color: #e00 } 
    3943.diff-add { color: #2e2 } 
  • scripts/trac-admin

    === htdocs/exp-svk-trac_banner.png
    ==================================================================
    Cannot display: file marked as a binary type.
    
    Property changes on: htdocs/exp-svk-trac_banner.png
    ___________________________________________________________________
    Name: svn:mime-type
     +image/x-png
    
    === htdocs/exp-bct-trac_banner.png
    ==================================================================
    Cannot display: file marked as a binary type.
    
    Property changes on: htdocs/exp-bct-trac_banner.png
    ___________________________________________________________________
    Name: svn:executable
     +*
    Name: svn:mime-type
     +image/x-png
    
    === htdocs/stable-svk-trac_banner.png
    ==================================================================
    Cannot display: file marked as a binary type.
    
    Property changes on: htdocs/stable-svk-trac_banner.png
    ___________________________________________________________________
    Name: svn:mime-type
     +image/x-png
    
    === scripts/trac-admin
    ==================================================================
     
    706706                self._do_wiki_import(filename, page, cursor) 
    707707 
    708708 
     709    ## (Ticket) Category 
     710    _help_category = [('category list', 'Show possible ticket categories'), 
     711                       ('category add <value>', 'Add a category value option'), 
     712                       ('category change <value> <newvalue>', 
     713                        'Change a category value'), 
     714                       ('category remove <value>', 'Remove category value')] 
     715 
     716    def complete_category (self, text, line, begidx, endidx): 
     717        if begidx == 16: 
     718            comp = self.get_enum_list ('category') 
     719        elif begidx < 15: 
     720            comp = ['list','add','change','remove'] 
     721        return self.word_complete(text, comp) 
     722 
     723    def do_category(self, line): 
     724        self._do_enum('category', line) 
     725 
    709726    ## (Ticket) Priority 
    710727    _help_priority = [('priority list', 'Show possible ticket priorities'), 
    711728                       ('priority add <value>', 'Add a priority value option'), 
  • README.tracd

    === README.tracd
    ==================================================================
     
     1======================== 
    12Trac in stand-alone mode 
    23======================== 
     4 
    35Trac 0.7 introduces among many other important features, the capability to run 
    46Trac as a stand-alone server (daemon), without a web server. 
    57 
    6 *** NOTE:  THIS IS STILL AN EXPERIMENTAL FEATURE *** 
     8.. NOTE::  THIS IS STILL AN EXPERIMENTAL FEATURE  
    79 
    810As of writing, tracd is still experimental, but we encourage testing it and 
    911providing feedback so we can improve it. Tracd supports all features of 
     
    1214 
    1315Running tracd 
    1416------------- 
    15 tracd [options] <database> [database] ... 
     17 
     18tracd [options] <environment> [environment2 ...] 
    1619Options: 
     20   
     21  -a, --auth <project,htdigest_file,realm>        Use Digest Authentication 
     22  -p, --port <port>                        Port number to use (default: 80) 
     23  -b, --hostname <hostname>                     IP to bind to (default: '') 
    1724 
    18     -a --auth [project],[htdigest_file],[realm] 
    19     -p --port [port]\t\tPort number to use (default: 80) 
    20     -b --hostname [hostname]\tIP to bind to (default: '') 
    2125 
    2226 
    23 Example: 
     27Example 1, without authentication:: 
    2428 
    2529  $ tracd -p 9090 /var/trac/myproject 
    2630 
     31Example 2, with authentication:: 
    2732 
     33  $ TRAC_ENV=/var/trac/myproject 
     34  $ tracd -a `basename $TRAC_ENV`,`dirname $TRAC_ENV`/passwd.digest,REALM \ 
     35      -p 9090 $TRAC_ENV 
     36 
     37The file htdigest can be generated using the Apache2 tool htdigest. 
     38 
     39 
    2840Feedback and bug reports 
    2941------------------------ 
    3042Please provide feedback on tracd using the issue tracker or the mailing list. 
  • trac/core.py

    === trac/core.py
    ==================================================================
     
    4646#    name           (module_name, class_name, requires_svn) 
    4747    'log'         : ('Log', 'Log', 1), 
    4848    'file'        : ('File', 'File', 1), 
    49     'wiki'        : ('Wiki', 'WikiModule', 0), 
     49    'wiki'        : ('Wiki', 'WikiModule', 1), # support Svn backend for Wiki pages 
    5050    'about_trac'  : ('About', 'About', 0), 
    5151    'search'      : ('Search', 'Search', 0), 
    5252    'report'      : ('Report', 'Report', 0), 
     
    199199    pass 
    200200 
    201201def populate_hdf(hdf, env, db, req): 
     202    sql_to_hdf(db, "SELECT name FROM enum WHERE type='category' " 
     203               "ORDER BY value", hdf, 'enums.category') 
    202204    sql_to_hdf(db, "SELECT name FROM enum WHERE type='priority' " 
    203205               "ORDER BY value", hdf, 'enums.priority') 
    204206    sql_to_hdf(db, "SELECT name FROM enum WHERE type='severity' " 
  • trac/db_default.py

    === trac/db_default.py
    ==================================================================
     
    2121 
    2222 
    2323# Database version identifier. Used for automatic upgrades. 
    24 db_version = 7 
     24db_version = 8 
    2525 
    2626def __mkreports(reps): 
    2727    """Utility function used to create report data in same syntax as the 
  • trac/Query.py

    === trac/Query.py
    ==================================================================
     
    5959            results.append({ 
    6060                'id': id, 
    6161                'href': self.env.href.ticket(id), 
     62                'category': row['category'], 
    6263                'summary': util.escape(row['summary'] or '(no summary)'), 
    6364                'status': row['status'] or '', 
    6465                'component': row['component'] or '', 
     
    7879        if self.args.has_key('search'): 
    7980            self.req.redirect(self.env.href.query(constraints, order, desc, 
    8081                                                  action='view')) 
     82        if self.args.has_key('clear'): 
     83            self.req.redirect(self.env.href.query()) 
    8184 
    8285        action = self.args.get('action') 
    8386        if not action and not constraints: 
     
    9194 
    9295    def _render_editor(self, constraints, order, desc): 
    9396        self.req.hdf.setValue('title', 'Custom Query') 
     97        self.req.hdf.setValue('query.clear_href', self.env.href.query(action='edit')) 
    9498        util.add_to_hdf(constraints, self.req.hdf, 'query.constraints') 
    9599        self.req.hdf.setValue('query.order', order) 
    96100        if desc: self.req.hdf.setValue('query.desc', '1') 
     
    112116                del constraints[field] 
    113117 
    114118        cursor = self.db.cursor() 
     119        add_options('category', constraints, 'query.options.', cursor, 
     120                    "SELECT name FROM enum WHERE type='category' ORDER BY value") 
    115121        add_options('status', constraints, 'query.options.', cursor, 
    116122                    "SELECT name FROM enum WHERE type='status' ORDER BY value") 
    117123        add_options('resolution', constraints, 'query.options.', cursor, 
     
    129135 
    130136        custom_fields = get_custom_fields(self.env) 
    131137        for custom in custom_fields: 
    132             if custom['type'] == 'select' or custom['type'] == 'radio': 
     138            if custom['type'] in ['select', 'radio', 'multi']: 
    133139                check = constraints.has_key(custom['name']) 
    134140                options = filter(None, custom['options']) 
    135141                for i in range(len(options)): 
     
    146152 
    147153        # FIXME: the user should be able to configure which columns should 
    148154        # be displayed 
    149         headers = [ 'id', 'summary', 'status', 'component', 'owner' ] 
     155        headers = [ 'category', 'id', 'summary', 'status', 'component', 'owner' ] 
    150156        cols = headers 
    151157        if not 'priority' in cols: 
    152158            cols.append('priority') 
     
    176182                      "(id=%s.ticket AND %s.name='%s')" 
    177183                      % (k, k, k, k)) 
    178184 
    179         for col in [c for c in ['status', 'resolution', 'priority', 'severity'] 
     185        for col in [c for c in ['category', 'status', 'resolution', 'priority', 'severity'] 
    180186                    if c in cols]: 
    181187            sql.append(" INNER JOIN (SELECT name AS %s_name, value AS %s_value " \ 
    182188                                   "FROM enum WHERE type='%s')" \ 
     
    194200        if clauses: 
    195201            sql.append(" WHERE " + " AND ".join(clauses)) 
    196202 
    197         if order in ['status', 'resolution', 'priority', 'severity']: 
     203        if order in ['category', 'status', 'resolution', 'priority', 'severity']: 
    198204            sql.append(" ORDER BY %s_value" % order) 
    199205        else: 
    200206            sql.append(" ORDER BY " + order) 
  • trac/Timeline.py

    === trac/Timeline.py
    ==================================================================
     
    3434    template_name = 'timeline.cs' 
    3535    template_rss_name = 'timeline_rss.cs' 
    3636 
    37     def get_info (self, start, stop, maxrows, tickets, 
     37    def get_info (self, start, stop, maxrows, tickets, ticket_comments, 
    3838                  changeset, wiki, milestone): 
    3939        cursor = self.db.cursor () 
    4040 
    4141        tickets = tickets and self.perm.has_permission(perm.TICKET_VIEW) 
     42        ticket_comments = ticket_comments and self.perm.has_permission(perm.TICKET_VIEW) 
    4243        changeset = changeset and self.perm.has_permission(perm.CHANGESET_VIEW) 
    4344        wiki = wiki and self.perm.has_permission(perm.WIKI_VIEW) 
    4445        milestone = milestone and self.perm.has_permission(perm.MILESTONE_VIEW) 
     
    5253        REOPENED_TICKET = 4 
    5354        WIKI = 5 
    5455        MILESTONE = 6 
     56        TICKET_COMMENT = 7 
    5557 
    5658        q = [] 
    5759        if changeset: 
    5860            q.append("SELECT time, rev AS idata, '' AS tdata, 1 AS type, " 
    59                      " message, author " 
     61                     " message, author, '' AS category " 
    6062                     "FROM revision WHERE time>=%s AND time<=%s" % 
    6163                     (start, stop)) 
    6264        if tickets: 
    6365            q.append("SELECT time, id AS idata, '' AS tdata, 2 AS type, " 
    64                      "summary AS message, reporter AS author " 
     66                     " summary AS message, reporter AS author, category " 
    6567                     "FROM ticket WHERE time>=%s AND time<=%s" % 
    6668                     (start, stop)) 
    67             q.append("SELECT time, ticket AS idata, '' AS tdata, 4 AS type, " 
    68                      "'' AS message, author " 
    69                      "FROM ticket_change WHERE field='status' " 
    70                      "AND newvalue='reopened' AND time>=%s AND time<=%s" % 
     69            q.append("SELECT t1.time, t1.ticket AS idata, '' AS tdata, 4 AS type, " 
     70                     " '' AS message, t1.author, t0.category AS category " 
     71                     "FROM ticket_change t1 " 
     72                     " LEFT JOIN ticket t0 ON t0.id = t1.ticket " 
     73                     "WHERE t1.field='status' " 
     74                     "AND t1.newvalue='reopened' AND t1.time>=%s AND t1.time<=%s" % 
    7175                     (start, stop)) 
    7276            q.append("SELECT t1.time AS time, t1.ticket AS idata," 
    7377                     "       t2.newvalue AS tdata, 3 AS type," 
    74                      "       t3.newvalue AS message, t1.author AS author" 
     78                     "       t3.newvalue AS message, t1.author AS author, t0.category AS category" 
    7579                     " FROM ticket_change t1" 
     80                     "   LEFT JOIN ticket t0 ON t0.id = t1.ticket" 
    7681                     "   INNER JOIN ticket_change t2 ON t1.ticket = t2.ticket" 
    7782                     "     AND t1.time = t2.time" 
    7883                     "   LEFT OUTER JOIN ticket_change t3 ON t1.time = t3.time" 
     
    8287                     "   AND t1.time >= %s AND t1.time <= %s" % (start,stop)) 
    8388        if wiki: 
    8489            q.append("SELECT time, -1 AS idata, name AS tdata, 5 AS type, " 
    85                      "comment AS message, author " 
     90                     "comment AS message, author, '' AS category " 
    8691                        "FROM wiki WHERE time>=%s AND time<=%s" % 
    8792                     (start, stop)) 
    8893        if milestone: 
    8994            q.append("SELECT time, -1 AS idata, '' AS tdata, 6 AS type, " 
    90                      "name AS message, '' AS author "  
     95                     "name AS message, '' AS author, '' AS category "  
    9196                     "FROM milestone WHERE time>=%s AND time<=%s" % 
    9297                     (start, stop)) 
    9398 
     99        if ticket_comments: 
     100            q.append("SELECT t1.time AS time, t1.ticket AS idata, '' AS tdata, 7 AS type, " 
     101                     "t1.newvalue AS message, t1.author AS author, t0.category AS category " 
     102                     "FROM ticket_change t1" 
     103                     "   LEFT JOIN ticket t0 ON t0.id = t1.ticket " 
     104                     "WHERE t1.field = 'comment' " 
     105                     "AND t1.time>=%s AND t1.time<=%s" % (start, stop)) 
     106 
    94107        q_str = string.join(q, ' UNION ALL ') 
    95108        q_str += ' ORDER BY time DESC' 
    96109        if maxrows: 
     
    100113 
    101114        # Make the data more HDF-friendly 
    102115        info = [] 
     116        tickets = {} 
    103117        while 1: 
    104118            row = cursor.fetchone() 
    105119            if not row: 
     
    113127                    'tdata': row['tdata'], 
    114128                    'type': int(row['type']), 
    115129                    'message': row['message'] or '', 
     130                    'category': row['category'], 
    116131                    'author': util.escape(row['author'] or 'anonymous') 
    117132                    } 
    118133 
     
    168183            elif item['type'] == MILESTONE: 
    169184                item['href'] = self.env.href.milestone(item['message']) 
    170185                item['message'] = util.escape(item['message']) 
    171             else:               # TICKET 
     186            else:               # all the TICKET types 
    172187                item['href'] = self.env.href.ticket(item['idata']) 
     188                if item['type'] == TICKET_COMMENT: 
     189                # The following would be ok if there would be a cost effective way 
     190                # to get that change number... 
     191                # item['href'] += '#change_%d' % item['change'] 
     192                    pass 
     193                else: 
     194                    tickets[(item['idata'], item['time'])] = 1 
    173195                msg = item['message'] 
    174196                item['shortmsg'] = util.escape(util.shorten_line(msg)) 
    175197                item['message'] = wiki_to_oneliner( 
     
    187209            item['message.rss'] = util.escape(item['message'] or '') 
    188210 
    189211            info.append(item) 
    190         return info 
     212        # Ok, the following line is maybe not Python 2.1 friendly, I don't know... 
     213        # return [ i for i in info if i['type'] != 7 or not tickets.has_key((i['idata'], i['time'])) ] 
     214        info2 = [] 
     215        for item in info: 
     216            if item['type'] != 7 or not tickets.has_key((item['idata'], item['time'])): 
     217                info2.append(item) 
     218        return info2 
    191219 
    192220    def render (self): 
    193221        self.perm.assert_permission(perm.TIMELINE_VIEW) 
     
    221249 
    222250        wiki = self.args.has_key('wiki')  
    223251        ticket = self.args.has_key('ticket') 
     252        ticket_comments = self.args.has_key('ticket_comments') 
    224253        changeset = self.args.has_key('changeset') 
    225254        milestone = self.args.has_key('milestone') 
    226255        if not (wiki or ticket or changeset or milestone): 
     
    230259            self.req.hdf.setValue('timeline.wiki', 'checked') 
    231260        if ticket: 
    232261            self.req.hdf.setValue('timeline.ticket', 'checked') 
     262        if ticket_comments: 
     263            self.req.hdf.setValue('timeline.ticket_comments', 'checked') 
    233264        if changeset: 
    234265            self.req.hdf.setValue('timeline.changeset', 'checked') 
    235266        if milestone: 
    236267            self.req.hdf.setValue('timeline.milestone', 'checked') 
    237268 
    238         info = self.get_info (start, stop, maxrows, ticket, 
     269        info = self.get_info (start, stop, maxrows, ticket, ticket_comments,  
    239270                              changeset, wiki, milestone) 
    240271        util.add_dictlist_to_hdf(info, self.req.hdf, 'timeline.items') 
    241272        self.req.hdf.setValue('title', 'Timeline') 
  • trac/tests/wiki-tests.txt

    === trac/tests/wiki-tests.txt
    ==================================================================
     
    127127------------------------------ 
    128128<h2>Heading with trailing white-space</h2> 
    129129============================== 
     130[[HelloWorld(hej hopp)]] 
     131------------------------------ 
     132<p> 
     133<pre class="wiki">hej hopp</pre> 
     134</p> 
     135============================== 
     136[[HelloWorld(hej hopp) ]] # This shouldnt executed as macro since it contain whitespace between ) and ] 
     137------------------------------ 
     138<p> 
     139[[HelloWorld(hej hopp) ]] # This shouldnt executed as macro since it contain whitespace between ) and ] 
     140</p> 
     141============================== 
     142[[HelloWorld(hej hopp))]] # Extra right brace and still executed 
     143------------------------------ 
     144<p> 
     145<pre class="wiki">hej hopp)</pre> # Extra right brace and still executed 
     146</p> 
     147============================== 
     148[[HelloWorld(hej hopp)]] [[HelloWorld(hej hopp2)]] # Test non greedy match 
     149------------------------------ 
     150<p> 
     151<pre class="wiki">hej hopp</pre> <pre class="wiki">hej hopp2</pre> # Test non greedy match 
     152</p> 
     153============================== 
     154Inline [[html(<B> Test </B>)]] text 
     155------------------------------ 
     156<p> 
     157Inline <B> Test </B> text 
     158</p> 
     159============================== 
    130160A0B1, ST62T53C6, IR32V1H000 
    131161------------------------------ 
    132162<p> 
  • trac/tests/wiki.py

    === trac/tests/wiki.py
    ==================================================================
     
    44 
    55from Wiki import Formatter 
    66 
     7 
    78class WikiTestCase(unittest.TestCase): 
    89    def __init__(self, input, correct): 
    910        unittest.TestCase.__init__(self, 'test') 
     
    1314    def test(self): 
    1415        """Testing WikiFormatter""" 
    1516        import Href 
     17        import Mimeview 
    1618        class Environment: 
    1719            def __init__(self): 
    1820                self.href = Href.Href('/') 
    1921                self._wiki_pages = {} 
     22                self.mimeview = Mimeview.Mimeview(self) 
    2023        class Cursor: 
    2124            def execute(self, *kwargs): pass 
    2225            def fetchone(self): return [] 
     
    2831        out = StringIO.StringIO() 
    2932        Formatter(None, Environment(), Connection()).format(self.input, out) 
    3033        if out.getvalue() != self.correct: 
    31             print "'%s' != '%s'" % (out.getvalue(), self.correct) 
     34            print "\n'%s' != \n'%s'" % (out.getvalue(), self.correct) 
    3235            assert self.correct == out.getvalue() 
    3336 
    3437def suite(): 
  • trac/util.py

    === trac/util.py
    ==================================================================
     
    7070                    .replace('>', '&gt;') \ 
    7171                    .replace('"', '&#34;') 
    7272 
     73def unescape(text): 
     74    """Reverses Escapes &, <, > and \"""" 
     75    if not text: 
     76        return '' 
     77    if type(text) is StringType: 
     78        text = text.replace('&#34;', '"') \ 
     79               .replace('&gt;', '>') \ 
     80               .replace('&lt;', '<') \ 
     81               .replace('&amp;', '&')  
     82    return text 
     83 
    7384def get_first_line(text, maxlen): 
    7485    """ 
    7586    returns the first line of text. If the line is longer then 
  • trac/Log.py

    === trac/Log.py
    ==================================================================
     
    5353            'log.raw'  : util.escape(log), 
    5454            'log'      : wiki_to_oneliner(util.shorten_line(util.wiki_escape_newline(log)), self.req.hdf, self.env,self.db), 
    5555            'shortlog' : util.escape(shortlog), 
     56            'original_file_href': self.env.href.browser(self.path, rev), 
    5657            'file_href': self.env.href.browser(self.path, rev), 
    5758            'changeset_href': self.env.href.changeset(rev) 
    5859            } 
     
    7172        # Loop through all revisions and update the path 
    7273        # after each tag/branch/copy/rename. 
    7374        path = self.path 
     75        seq = len(self.log_info) 
    7476        for item in self.log_info: 
     77            item['seq'] = seq 
     78            seq -= 1 
    7579            item['file_href'] = self.env.href.browser(path, item['rev']) 
     80            item['intermediate_file_href'] = self.env.href.browser(path, item['rev']) 
    7681            if self.branch_info.has_key(item['rev']): 
    7782                for info in self.branch_info[item['rev']]: 
    7883                    if path[:len(info[1])] == info[1]: 
    7984                        rel_path = path[len(info[1]):] 
    8085                        path = info[0]+rel_path 
     86        # Add suggested base revision for diffing 
     87        prev = None 
     88        log_info_backward = self.log_info[:] 
     89        log_info_backward.reverse() 
     90        for item in log_info_backward: 
     91            if prev: 
     92                item['diff'] = prev 
     93            prev = item['rev'] 
    8194        return self.log_info 
    8295 
    8396    def generate_path_links(self, rev, rev_specified): 
  • trac/wikimacros/rst.py

    === trac/wikimacros/rst.py
    ==================================================================
     
    4343    raise EnvironmentError, 'Docutils version >= %s required, %s found' % (docutils_required, __version__) 
    4444 
    4545from trac.Href import Href 
     46from trac.WikiFormatter import WikiProcessor 
    4647 
    4748__docformat__ = 'reStructuredText' 
    4849 
    49 WIKI_LINK = re.compile(r'(?:wiki:)?(?P<w>[A-Za-z][\w\#\?]*[^\w\#\?]*)') # Links must begin with Letters, \# ? so we can link inside pages. 
    50 #WIKI_LINK = re.compile(r'(?:wiki:)?(?P<w>(^|(?<=[^A-Za-z]))[!]?[A-Z][a-z/]+(?:[A-Z][a-z/]+)+)') 
     50WIKI_LINK = re.compile(r'(?:wiki:)?(.+)') 
     51#WIKI_LINK = re.compile(r'(?:wiki:)?(?P<wikilink>[A-Za-z][\w\-]*[^\w\#\?]*)') 
    5152TICKET_LINK = re.compile(r'(?:#(\d+))|(?:ticket:(\d+))') 
    5253REPORT_LINK = re.compile(r'(?:{(\d+)})|(?:report:(\d+))') 
    5354CHANGESET_LINK = re.compile(r'(?:\[(\d+)\])|(?:changeset:(\d+))') 
    5455FILE_LINK = re.compile(r'(?:browser|repos|source):([^#]+)#?(.*)') 
    5556 
     57#import trac.Logging 
     58#log = trac.Logging.logger_factory(logtype='file', logfile="/tmp/debug_rst.txt", level='ALL') 
     59 
    5660def _wikipage(href, args): 
    5761    return href.wiki(args[0]) 
    5862 
     
    7175    return href.browser(path, rev) 
    7276 
    7377# TracLink REs and callback functions 
    74 LINKS = [(WIKI_LINK, _wikipage), 
    75          (TICKET_LINK, _ticket), 
     78LINKS = [(TICKET_LINK, _ticket), 
    7679         (REPORT_LINK, _report), 
    7780         (CHANGESET_LINK, _changeset), 
    78          (FILE_LINK, _browser)] 
     81         (FILE_LINK, _browser), 
     82         (WIKI_LINK, _wikipage)] 
    7983 
    8084 
    81 def trac_get_reference(env, rawtext, text): 
     85def trac_get_reference(env, rawtext, link, text): 
     86 
    8287    for (pattern, function) in LINKS: 
    83         m = pattern.match(text) 
     88        m = pattern.match(link) 
    8489        if m: 
    8590            g = filter(None, m.groups()) 
    8691            missing = False 
     92            if not text: 
     93                text = g[0] 
    8794            if pattern == WIKI_LINK: 
    88                 if not (env._wiki_pages.has_key(g[0])): 
     95                pagename = re.search(r'^[^\#]+',g[0]) 
     96                if not (env._wiki_pages.has_key(pagename.group())): 
    8997                        missing = True 
    90                         text = text + "?" 
     98                        text = text + "?"             
    9199            uri = function(env.href, g) 
    92100            reference = nodes.reference(rawtext, text) 
    93101            reference['refuri']= uri 
    94102            if missing: 
    95103                reference.set_class('missing') 
    96104            return reference 
     105         
    97106    return None 
    98107