Edgewall Software

Ticket #1135: component+svn_filtering.diff

File component+svn_filtering.diff, 14.8 KB (added by fog@…, 4 years ago)

version 2 of the patch (replaces 2 previous files)

  • templates/timeline.cs

    diff -ru trac-0.8.orig/templates/timeline.cs trac-0.8/templates/timeline.cs
    old new  
    11<?cs set:html.stylesheet = 'css/timeline.css' ?> 
    22<?cs include "header.cs"?> 
     3<?cs include "macros.cs"?> 
    34 
    45<div id="ctxtnav" class="nav"></div> 
    56 
     
    3536      if:timeline.milestone ?>checked="checked"<?cs /if ?> /> 
    3637    <label for="milestone">Milestones</label> 
    3738   </div><?cs /if ?> 
     39   <div class="field"> 
     40    <input type="checkbox" id="component" name="component" <?cs 
     41      if:timeline.component ?>checked="checked"<?cs /if ?> /> 
     42    <label for="component">Component: </label><?cs 
     43    call:hdf_select(timeline.components, "cfilter", timeline.cfilter) ?> 
     44   </div> 
    3845  </fieldset> 
    3946  <div class="buttons"> 
    4047   <input type="submit" value="Update" /> 
     
    6067 
    6168<?cs each:item = timeline.items ?> 
    6269 <?cs call:day_separator(item.date) ?> 
     70  <?cs if:item.component ?> 
     71   <?cs set:component = ' (' + $item.component + ')' ?> 
     72  <?cs else ?> 
     73   <?cs set:component = '' ?> 
     74  <?cs /if ?> 
    6375 <?cs if:item.type == #1 ?><!-- Changeset --> 
    6476  <?cs call:tlitem(item.href, 'changeset', 
    65     'Changeset <em>['+$item.idata+']</em> by '+$item.author,$item.node_list+item.message) ?> 
     77    'Changeset <em>['+$item.idata+']</em>'+$component+' by '+$item.author,$item.node_list+item.message) ?> 
    6678 <?cs elif:item.type == #2 ?><!-- New ticket --> 
    6779  <?cs call:tlitem(item.href, 'newticket', 
    68     'Ticket <em>#'+$item.idata+'</em> created by '+$item.author, item.message) ?> 
     80    'Ticket <em>#'+$item.idata+'</em>'+$component+' created by '+$item.author, item.message) ?> 
    6981 <?cs elif:item.type == #3 ?><!-- Closed ticket --> 
    7082  <?cs if:item.message ?> 
    7183   <?cs set:imessage = ' - ' + $item.message ?> 
     
    7385   <?cs set:imessage = '' ?> 
    7486  <?cs /if ?> 
    7587  <?cs call:tlitem(item.href, 'closedticket', 
    76     'Ticket <em>#'+$item.idata+'</em> resolved by '+$item.author,  
     88    'Ticket <em>#'+$item.idata+'</em>'+$component+' resolved by '+$item.author,  
    7789    $item.tdata+$imessage) ?> 
    7890 <?cs elif:item.type == #4 ?><!-- Reopened ticket --> 
    7991  <?cs call:tlitem(item.href, 'newticket', 
    80     'Ticket <em>#'+$item.idata+'</em> reopened by '+$item.author, '') ?> 
     92    'Ticket <em>#'+$item.idata+'</em>'+$component+' reopened by '+$item.author, '') ?> 
    8193 <?cs elif:item.type == #5 ?><!-- Wiki change --> 
    8294  <?cs call:tlitem(item.href, 'wiki', 
    8395    '<em>'+$item.tdata+'</em> edited by '+$item.author, item.message) ?> 
  • templates/timeline_rss.cs

    diff -ru trac-0.8.orig/templates/timeline_rss.cs trac-0.8/templates/timeline_rss.cs
    old new  
    3333        <link><?cs var:$base_url ?><?cs var:$trac.href.timeline ?></link> 
    3434      </image> 
    3535      <?cs each:item = $timeline.items ?><?cs 
     36        if:item.component ?> 
     37          <?cs set:component = ' (' + $item.component + ')' ?><?cs 
     38        else ?> 
     39          <?cs set:component = '' ?><?cs 
     40        /if ?><?cs 
    3641        if:item.type == #1  
    3742        ?><!-- Changeset --><?cs call:rss_item('Changeset', 
    38                              'Changeset ['+$item.idata+'] by '+$item.author,  
     43                             'Changeset ['+$item.idata+']'+$component+' by '+$item.author,  
    3944                             $item.href, $item.msg_escwiki)  
    4045        ?><?cs elif:item.type == #2  
    4146        ?><!-- New ticket --> <?cs call:rss_item('Ticket', 
    42                              'Ticket #'+$item.idata+' created by '+$item.author, 
     47                             'Ticket #'+$item.idata+$component+' created by '+$item.author, 
    4348                             $item.href, $item.msg_escwiki)  
    4449        ?><?cs elif:item.type == #3 
    4550        ?><!-- Closed ticket --> <?cs call:rss_item('Ticket', 
    46                              'Ticket #'+$item.idata+' resolved: '+$item.shortmsg, 
     51                             'Ticket #'+$item.idata+$component+' resolved: '+$item.shortmsg, 
    4752                             $item.href, $item.msg_escwiki)  
    4853        ?><?cs elif:item.type == #4  
    4954        ?><!-- Reopened ticket --><?cs call:rss_item('Ticket', 
    50                              '#'+$item.idata+' reopened: '+$item.shortmsg, 
     55                             '#'+$item.idata+$component+' reopened: '+$item.shortmsg, 
    5156                             $item.href, $item.msg_escwiki)  
    5257        ?><?cs elif:item.type == #5  
    5358        ?><!-- Wiki change --><?cs call:rss_item('Wiki', 
     
    6267        <?cs /if ?> 
    6368      <?cs /each ?> 
    6469    </channel> 
    65 </rss> 
    66  No newline at end of file 
     70</rss> 
  • trac/Browser.py

    diff -ru trac-0.8.orig/trac/Browser.py trac-0.8/trac/Browser.py
    old new  
    2222import time 
    2323import string 
    2424import posixpath 
     25import re 
    2526 
    2627import svn 
    2728 
     
    4243        # class provided by modpython might give us some strange string-like object 
    4344        # that svn doesn't like. 
    4445        path = str(path) 
     46        rfilter = self.env.get_config('trac', 'repository_filter', '') 
     47         
    4548        try: 
    4649            root = svn.fs.revision_root(self.fs_ptr, revision, self.pool) 
    4750        except svn.core.SubversionException: 
     
    6568        for item in entries.keys(): 
    6669            fullpath = posixpath.join(path, item) 
    6770 
     71            if rfilter and not re.search(rfilter, fullpath): 
     72                continue 
     73             
    6874            is_dir = svn.fs.is_dir(root, fullpath, self.pool) 
    6975            if is_dir: 
    7076                name = item + '/' 
  • trac/Timeline.py

    diff -ru trac-0.8.orig/trac/Timeline.py trac-0.8/trac/Timeline.py
    old new  
    2222import time 
    2323import string 
    2424import urllib 
     25import re 
    2526 
    2627import perm 
    2728import util 
     
    3536    template_rss_name = 'timeline_rss.cs' 
    3637 
    3738    def get_info (self, start, stop, maxrows, tickets, 
    38                   changeset, wiki, milestone): 
     39                  changeset, wiki, milestone, component, cfilter): 
    3940        cursor = self.db.cursor () 
    4041 
    4142        tickets = tickets and self.perm.has_permission(perm.TICKET_VIEW) 
     
    5354        WIKI = 5 
    5455        MILESTONE = 6 
    5556 
    56         q = [] 
     57        try: 
     58            display_components = int(self.env.get_config('timeline', 'display_components', 0)) 
     59        except ValueError, e: 
     60            self.env.log.warning("Invalid 'display_components' value, " 
     61                                 "please edit trac.ini : %s" % e) 
     62            display_components = 0 
     63 
     64        try: 
     65            guess_component = int(self.env.get_config('timeline', 'changeset_guess_component', 0)) 
     66        except ValueError, e: 
     67            self.env.log.warning("Invalid 'changeset_guess_component' value, " 
     68                                 "please edit trac.ini : %s" % e) 
     69            guess_component = 0 
     70 
     71        rfilter = self.env.get_config('trac', 'repository_filter', '') 
     72        rcomponent = self.env.get_config('trac', 'repository_component') 
     73 
     74        q = [] 
    5775        if changeset: 
    5876            q.append("SELECT time, rev AS idata, '' AS tdata, 1 AS type, " 
    59                      " message, author " 
     77                     " message, author, '' AS component " 
    6078                     "FROM revision WHERE time>=%s AND time<=%s" % 
    6179                     (start, stop)) 
    6280        if tickets: 
    6381            q.append("SELECT time, id AS idata, '' AS tdata, 2 AS type, " 
    64                      "summary AS message, reporter AS author " 
     82                     "summary AS message, reporter AS author, component " 
    6583                     "FROM ticket WHERE time>=%s AND time<=%s" % 
    6684                     (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" % 
     85            q.append("SELECT t1.time, t1.ticket AS idata, '' AS tdata, 4 AS type, " 
     86                     "  '' AS message, t1.author, t2.component AS component " 
     87                     "FROM ticket_change t1, ticket t2 " 
     88                     "WHERE t1.field='status' " 
     89                     "  AND t1.newvalue='reopened' AND t1.ticket = t2.id " 
     90                     "  AND t1.time>=%s AND t1.time<=%s" % 
    7191                     (start, stop)) 
    7292            q.append("SELECT t1.time AS time, t1.ticket AS idata," 
    7393                     "       t2.newvalue AS tdata, 3 AS type," 
    74                      "       t3.newvalue AS message, t1.author AS author" 
     94                     "       t3.newvalue AS message, t1.author AS author," 
     95                     "       t4.component AS component" 
    7596                     " FROM ticket_change t1" 
    7697                     "   INNER JOIN ticket_change t2 ON t1.ticket = t2.ticket" 
    7798                     "     AND t1.time = t2.time" 
    78                      "   LEFT OUTER JOIN ticket_change t3 ON t1.time = t3.time" 
     99                     "   INNER JOIN ticket t4 ON t1.ticket = t4.id" 
     100                     "   LEFT OUTER JOIN ticket_change t3 ON t1.time = t3.time" 
    79101                     "     AND t1.ticket = t3.ticket AND t3.field = 'comment'" 
    80102                     " WHERE t1.field = 'status' AND t1.newvalue = 'closed'" 
    81103                     "   AND t2.field = 'resolution'" 
    82104                     "   AND t1.time >= %s AND t1.time <= %s" % (start,stop)) 
    83105        if wiki: 
    84106            q.append("SELECT time, -1 AS idata, name AS tdata, 5 AS type, " 
    85                      "comment AS message, author " 
     107                     "comment AS message, author, '' AS component " 
    86108                        "FROM wiki WHERE time>=%s AND time<=%s" % 
    87109                     (start, stop)) 
    88110        if milestone: 
    89111            q.append("SELECT time, -1 AS idata, '' AS tdata, 6 AS type, " 
    90                      "name AS message, '' AS author "  
     112                     "name AS message, '' AS author, '' AS component "  
    91113                     "FROM milestone WHERE time>=%s AND time<=%s" % 
    92114                     (start, stop)) 
    93115 
     
    113135                    'tdata': row['tdata'], 
    114136                    'type': int(row['type']), 
    115137                    'message': row['message'] or '', 
    116                     'author': util.escape(row['author'] or 'anonymous') 
     138                    'author': util.escape(row['author'] or 'anonymous'), 
     139                    'component': row['component'] or '' 
    117140                    } 
    118141 
    119142            if item['type'] == CHANGESET: 
    120                 item['href'] = self.env.href.changeset(item['idata']) 
     143                changeset_component = '' 
     144                changeset_filtered = 1 
     145                item['href'] = self.env.href.changeset(item['idata']) 
    121146                msg = item['message'] 
    122147                item['shortmsg'] = util.escape(util.shorten_line(msg)) 
    123148                item['msg_nowiki'] = util.escape(msg) 
     
    134159                    self.env.log.warning("Invalid 'changeset_show_files' value, " 
    135160                                         "please edit trac.ini : %s" % e) 
    136161                    max_node = 0 
    137                      
    138                 if max_node != 0: 
    139                     cursor_node = self.db.cursor () 
     162 
     163                if guess_component or rfilter or max_node != 0: 
     164                    cursor_node = self.db.cursor () 
     165                    if guess_component: 
     166                        cursor_node.execute("SELECT name FROM component " 
     167                                            "ORDER BY name") 
     168                        components = map(lambda x: x[0], cursor_node.fetchall()) 
     169             
    140170                    cursor_node.execute("SELECT name, change " 
    141171                                        "FROM node_change WHERE rev=%d" % item['idata']) 
     172                    row_node = cursor_node.fetchone() 
     173                 
     174                if rfilter: 
     175                    if re.search(rfilter, row_node['name']): 
     176                        changeset_filtered = 0 
     177                else: 
     178                    changeset_filtered = 0 
     179 
     180                if guess_component: 
     181                    if rcomponent: 
     182                        try: 
     183                            m = re.search(rcomponent, row_node['name']) 
     184                            if m: changeset_component = m.group(1) 
     185                        except StandardError, e: 
     186                            self.env.log.warning("'repository_component' should have one group on match : %s" % e) 
     187                    else: 
     188                        p = row_node['name'].split('/')[0] 
     189                        if p in components: 
     190                            changeset_component = p 
     191                     
     192                if max_node != 0: 
    142193                    node_list = '' 
    143194                    node_data = '' 
    144195                    node_count = 0; 
    145196                    while 1: 
    146                         row_node = cursor_node.fetchone() 
    147                         if not row_node: 
    148                             break 
    149197                        if node_count != 0: 
    150198                            node_list += ', ' 
    151199                        if (max_node != -1) and (node_count >= max_node): 
     
    159207                            node_data = '<span class="diff-rem">' + row_node['name'] + "</span>" 
    160208                        node_list += node_data 
    161209                        node_count += 1 
     210                        if re.search(rfilter, row_node['name']): 
     211                            changeset_filtered = 0 
     212                        row_node = cursor_node.fetchone() 
     213                        if not row_node: 
     214                            break 
    162215                    item['node_list'] = node_list + ': ' 
    163  
     216                                         
     217                if changeset_filtered: 
     218                    continue 
     219                 
     220                item['component'] = changeset_component; 
     221                 
    164222            elif item['type'] == WIKI: 
    165223                item['href'] = self.env.href.wiki(row['tdata']) 
    166224                item['message'] = wiki_to_oneliner(util.shorten_line(item['message']), 
     
    186244                item['author.rss'] = '' 
    187245            item['message.rss'] = util.escape(item['message'] or '') 
    188246 
    189             info.append(item) 
    190         return info 
     247            if not component or item['component'] == '' or item['component'] == cfilter: 
     248                info.append(item) 
     249 
     250            # now, after appending,  remove the component if asked for 
     251            if not display_components: 
     252                item['component'] = '' 
     253         
     254        return info 
    191255 
    192256    def render (self): 
    193257        self.perm.assert_permission(perm.TIMELINE_VIEW) 
     
    223287        ticket = self.args.has_key('ticket') 
    224288        changeset = self.args.has_key('changeset') 
    225289        milestone = self.args.has_key('milestone') 
     290        component = self.args.has_key('component') 
     291         
    226292        if not (wiki or ticket or changeset or milestone): 
    227293            wiki = ticket = changeset = milestone = 1 
    228294 
     
    234300            self.req.hdf.setValue('timeline.changeset', 'checked') 
    235301        if milestone: 
    236302            self.req.hdf.setValue('timeline.milestone', 'checked') 
    237  
     303        if component: 
     304            self.req.hdf.setValue('timeline.component', 'checked') 
     305             
     306        if self.args.has_key('cfilter'): 
     307            cfilter = self.args['cfilter'] 
     308        else: 
     309            cfilter = '' 
     310        self.req.hdf.setValue('timeline.cfilter', cfilter) 
     311         
    238312        info = self.get_info (start, stop, maxrows, ticket, 
    239                               changeset, wiki, milestone) 
     313                              changeset, wiki, milestone, component, cfilter) 
    240314        util.add_dictlist_to_hdf(info, self.req.hdf, 'timeline.items') 
    241315        self.req.hdf.setValue('title', 'Timeline') 
    242  
     316        util.sql_to_hdf(self.db, 'SELECT name FROM component ORDER BY name', 
     317                        self.req.hdf, 'timeline.components') 
     318     
    243319    def display_rss(self): 
    244320        self.req.display(self.template_rss_name, 'text/xml')