Edgewall Software

Ticket #7715: t7715-fix-eligible-start-r8299.2.patch

File t7715-fix-eligible-start-r8299.2.patch, 7.2 KB (added by cboos, 3 years ago)

Improved version of the previous patch (smarter CachedRepository._get_node_revs)

  • trac/versioncontrol/svn_fs.py

     
    433433 
    434434        return SubversionNode(path, rev, self, self.pool) 
    435435 
    436     def _get_node_revs(self, path, rev=None): 
    437         """Return the revisions affecting `path` between its creation and 
    438         `rev`. 
     436    def _get_node_revs(self, path, last=None, first=None): 
     437        """Return the revisions affecting `path` between `first` and `last`  
     438        revs. If `first` is not given, it goes down to the revision in which 
     439        the branch was created. 
    439440        """ 
    440         node = self.get_node(path, rev) 
     441        node = self.get_node(path, last) 
    441442        revs = [] 
    442443        for (p, r, chg) in node.get_history(): 
    443             if p != path: 
     444            if p != path or (first and r < first): 
    444445                break 
    445446            revs.append(r) 
    446447        return revs 
     
    785786        return fs.node_prop(self.root, self._scoped_path_utf8, name, 
    786787                            self.pool()) 
    787788 
     789    def get_copy_origin(self): 
     790        root_and_path = fs.closest_copy(self.root, self._scoped_path_utf8) 
     791        if root_and_path: 
     792            root, path = root_and_path 
     793            rev = fs.revision_root_revision(root) 
     794            if (path, rev) == (self.path, self.rev): 
     795                rev, path = fs.copied_from(root, path) 
     796            return SubversionNode(path, rev, self.repos, self.pool, root) 
    788797 
     798 
    789799class SubversionChangeset(Changeset): 
    790800 
    791801    def __init__(self, rev, authz, scope, fs_ptr, pool=None): 
  • trac/versioncontrol/web_ui/browser.py

     
    343343        except NoSuchChangeset, e: 
    344344            raise ResourceNotFound(e.message, _('Invalid Changeset Number')) 
    345345 
    346         context = Context.from_request(req, 'source', path, node.created_rev) 
     346        context = Context.from_request(req, 'source', path, rev_or_latest) 
    347347 
    348348        path_links = get_path_links(req.href, path, rev, order, desc) 
    349349        if len(path_links) > 1: 
  • trac/versioncontrol/cache.py

     
    1414# 
    1515# Author: Christopher Lenz <cmlenz@gmx.de> 
    1616 
    17 import bisect 
    1817from datetime import datetime 
    1918import os 
    2019import posixpath 
     
    233232    def get_node(self, path, rev=None): 
    234233        return self.repos.get_node(path, rev) 
    235234 
    236     def _get_node_revs(self, path, rev=None): 
    237         """Return the revisions affecting `path` between its creation and 
    238         `rev`. 
     235    def _get_node_revs(self, path, last=None, first=None): 
     236        """Return the revisions affecting `path` between `first` and `last` 
     237        revisions. 
    239238        """ 
    240         rev = self.normalize_rev(rev) 
    241         node = self.get_node(path, rev)     # Check node existence and perms 
     239        last = self.normalize_rev(last) 
     240        node = self.get_node(path, last)     # Check node existence and perms 
    242241        db = self.getdb() 
    243242        cursor = db.cursor() 
     243        rev_as_int = db.cast('rev', 'int') 
     244        if not first: 
     245            cursor.execute("SELECT rev FROM node_change " 
     246                           "WHERE path = %%s " 
     247                           "  AND change_type IN ('A', 'C', 'M') " 
     248                           "  AND %s <= %%s " 
     249                           "ORDER BY %s DESC " 
     250                           "LIMIT 1" % ((rev_as_int,) * 2), 
     251                           (path, last)) 
     252            first = 0 
     253            for row in cursor: 
     254                first = int(row[0]) 
    244255        cursor.execute("SELECT DISTINCT rev FROM node_change " 
    245256                       "WHERE (path = %%s OR path %s) " 
    246                        "  AND %s <= %%s" % (db.like(), db.cast('rev', 'int')), 
    247                        (path, db.like_escape(path + '/') + '%', rev)) 
     257                       " AND %s >= %%s AND %s <= %%s" %  
     258                       (db.like(), rev_as_int, rev_as_int), 
     259                       (path, db.like_escape(path + '/') + '%', first, last)) 
    248260        revs = [int(row[0]) for row in cursor] 
    249261        revs.sort() 
    250         cursor.execute("SELECT rev FROM node_change " 
    251                        "WHERE path = %%s " 
    252                        "  AND change_type IN ('A', 'C', 'M') " 
    253                        "  AND %s <= %%s " 
    254                        "ORDER BY %s DESC " 
    255                        "LIMIT 1" % ((db.cast('rev', 'int'),) * 2), 
    256                        (path, rev)) 
    257         created = 0 
    258         for row in cursor: 
    259             created = int(row[0]) 
    260         return revs[bisect.bisect_left(revs, created):] 
     262        return revs 
    261263 
    262264    def has_node(self, path, rev=None): 
    263265        return self.repos.has_node(path, rev) 
  • trac/versioncontrol/svn_prop.py

     
    120120        revs_label = (_('merged'), _('blocked'))[name.endswith('blocked')] 
    121121        revs_cols = has_eligible and 2 or None 
    122122        repos = self.env.get_repository() 
     123        target_path = context.resource.id 
     124        target_rev = context.resource.version 
     125        if has_eligible: 
     126            branch_starts = {} 
     127            node = repos.get_node(target_path, target_rev) 
     128            while node: 
     129                node = node.get_copy_origin() 
     130                if node and node.path != target_path: 
     131                    branch_starts[node.path] = node.rev + 1 
    123132        rows = [] 
    124133        for line in props[name].splitlines(): 
    125134            path, revs = line.split(':', 1) 
     
    128137            deleted = False 
    129138            if 'LOG_VIEW' in context.perm('source', spath): 
    130139                try: 
    131                     node = repos.get_node(spath, context.resource.version) 
     140                    node = repos.get_node(spath, target_rev) 
    132141                    row = [self._get_source_link(path, context), 
    133142                           self._get_revs_link(revs_label, context, 
    134143                                               spath, revs)] 
    135144                    if has_eligible: 
    136                         eligible = set(repos._get_node_revs(spath, 
    137                                                     context.resource.version)) 
     145                        first_rev = branch_starts.get(path) 
     146                        eligible = set(repos._get_node_revs(spath, target_rev, 
     147                                                            first_rev)) 
    138148                        eligible -= set(Ranges(revs)) 
    139149                        blocked = self._get_blocked_revs(props, name, spath) 
    140150                        eligible -= set(Ranges(blocked)) 
     
    237247            removed = old_revs - new_revs 
    238248            try: 
    239249                all_revs = set(repos._get_node_revs(spath)) 
     250                # TODO: also pass first_rev here, for getting smaller a set 
     251                #       (this is an optmization fix, result is already correct) 
    240252                added &= all_revs 
    241253                removed &= all_revs 
    242254            except NoSuchNode: