Show
Ignore:
Timestamp:
01/03/08 09:39:12 (11 months ago)
Author:
ttressieres
Message:
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • perforceplugin/branches/trac-0.10/p4trac/api.py

    r2503 r2973  
    11from trac.core import Component, implements, TracError 
    2 from trac.versioncontrol.api import IRepositoryConnector, Repository, Node, \ 
    3      Changeset, Authorizer, NoSuchChangeset, NoSuchNode, PermissionDenied 
    4 from trac.versioncontrol.cache import CachedRepository, _kindmap, _actionmap 
     2from trac.versioncontrol import Changeset, Repository, Node, \ 
     3                                IRepositoryConnector, \ 
     4                                Authorizer, NoSuchChangeset, NoSuchNode 
     5from trac.versioncontrol.cache import CachedRepository 
     6from trac.util.text import to_unicode 
     7 
    58 
    69def normalisePath(path): 
     
    3639    else: 
    3740        return rev 
     41 
    3842 
    3943class PerforceConnector(Component): 
     
    155159        p4.client = '' 
    156160 
    157         repos = PerforceRepository(p4, self.log, jobPrefixLength) 
    158  
    159         from trac.versioncontrol.cache import CachedRepository 
    160         return PerforceCachedRepository(self.env.get_db_cnx(), 
    161                                         repos, 
    162                                         None, 
    163                                         self.log) 
    164  
    165 class PerforceCachedRepository(CachedRepository): 
    166      
    167     def __init__(self, db, repos, authz, log): 
    168         CachedRepository.__init__(self, db, repos, authz, log) 
    169         self.synced = 0 
    170  
    171     def checkRepositoryDir(self): 
    172         """Check that the underlying repository_dir hasn't changed.""" 
    173         cursor = self.db.cursor() 
    174         cursor.execute("SELECT value " 
    175                        "FROM system " 
    176                        "WHERE name='repository_dir'") 
    177         row = cursor.fetchone() 
    178         if row and row[0] != self.name: 
    179             raise TracError("The 'repository_dir' has changed " 
    180                             "a 'trac-admin resync' operation is needed") 
    181  
    182     def storeChangesInDB(self, changes): 
    183         """Store the specified changes in the Trac database. 
    184  
    185         @param changes: List of integers that specifies the changes to store 
    186         in the Trac database. 
    187         """ 
    188         kindmap = dict(zip(_kindmap.values(), _kindmap.keys())) 
    189         actionmap = dict(zip(_actionmap.values(), _actionmap.keys())) 
    190          
    191         cursor = self.db.cursor() 
    192         for change in changes: 
    193             cs = self.repos.get_changeset(change) 
    194             cursor.execute("INSERT INTO revision (rev,time,author,message) " 
    195                            "VALUES (%s,%s,%s,%s)", (str(change), 
    196                                                     cs.date, 
    197                                                     cs.author, 
    198                                                     cs.message)) 
    199             for path, kind, action, base_path, base_rev in cs.get_changes(): 
    200                 kind = kindmap[kind] 
    201                 action = actionmap[action] 
    202                 cursor.execute("INSERT INTO node_change (rev,path, node_type, " 
    203                                "change_type, base_path, base_rev) " 
    204                                "VALUES (%s,%s,%s,%s,%s,%s)", 
    205                                (str(change), 
    206                                 path, kind, action, base_path, base_rev)) 
    207         self.db.commit() 
    208  
    209     def updateCache(self, fromChange): 
    210  
    211         from perforce import ConnectionDropped 
    212  
    213         # Update the database in batches of 1000 changes so that we don't 
    214         # overload the virtual memory system by trying to store information 
    215         # about every change in the repository at once during the initial 
    216         # cache population. 
    217  
    218         batchSize = 1000 
    219         lowerBound = fromChange 
    220         upperBound = self.repos.youngest_rev + 1 
    221  
    222         self.log.debug("Updating cache with changes [%i,%i]" % (lowerBound, 
    223                                                                 upperBound)) 
    224          
    225         try: 
    226             while lowerBound < upperBound: 
    227                 batchUpperBound = min(lowerBound + batchSize, upperBound) 
    228  
    229                 # Get the next batch of changes to cache 
    230                 from p4trac.repos import _P4ChangesOutputConsumer 
    231                 output = _P4ChangesOutputConsumer(self.repos._repos) 
    232                 self.repos._connection.run('changes', '-l', '-s', 'submitted', 
    233                                            '@>=%i,@<%i' % (lowerBound, 
    234                                                            batchUpperBound), 
    235                                            output=output) 
    236              
    237                 if output.errors: 
    238                     from p4trac.repos import PerforceError 
    239                     raise PerforceError(output.errors) 
    240  
    241                 changes = output.changes 
    242                 changes.reverse() 
    243  
    244                 # Pre-cache all information about these changes in memory 
    245                 # before caching in the database. Clear the in-memory cache 
    246                 # afterwards to save on memory usage. 
    247                 self.repos._repos.precacheFileInformationForChanges(changes) 
    248                 self.storeChangesInDB(changes) 
    249                 self.repos._repos.clearFileInformationCache() 
    250  
    251                 lowerBound += batchSize 
    252                  
    253         except ConnectionDropped, e: 
    254             self.log.debug('Rolling back uncommitted cache updates') 
    255             self.db.rollback() 
    256             raise TracError('Connection to Perforce server lost') 
    257          
    258     def sync(self): 
    259  
    260         self.log.debug("Checking whether sync with repository is needed") 
    261  
    262         self.checkRepositoryDir() 
    263          
    264         youngestStored = self.repos.get_youngest_rev_in_cache(self.db) 
    265         if youngestStored is None: 
    266             youngestStored = 0 
    267         else: 
    268             youngestStored = int(youngestStored) 
    269              
    270         if youngestStored != self.repos.youngest_rev: 
    271             # Cache is out of date. 
    272              
    273             # Remove permissions checking while populating the cache 
    274             authz = self.repos.authz 
    275             self.repos.authz = Authorizer() 
    276             try: 
    277                 self.updateCache(fromChange=youngestStored+1) 
    278             finally: 
    279                 self.repos.authz = authz 
    280  
    281         self.youngest = youngestStored 
    282  
    283     def get_changesets(self, start, stop): 
    284         if not self.synced: 
    285             self.sync() 
    286             self.synced = 1 
    287         cursor = self.db.cursor() 
    288         cursor.execute("SELECT rev " 
    289                        "FROM revision " 
    290                        "WHERE time >= %i AND time <= %i " 
    291                        "ORDER BY time DESC" % (int(start), int(stop))) 
    292         for row in cursor: 
    293             yield self.get_changeset(row[0]) 
    294  
    295     # HACK: This method should be in the base class. 
    296     def get_tags(self, rev): 
    297         return self.repos.get_tags(rev) 
    298  
    299 class PerforceRepository(object): 
     161        repos = PerforceRepository(p4, None, self.log, jobPrefixLength) 
     162        crepos = CachedRepository(self.env.get_db_cnx(), repos, None, self.log) 
     163        return crepos 
     164 
     165 
     166class PerforceRepository(Repository): 
    300167    """A Perforce repository implementation. 
    301168 
     
    304171    """ 
    305172 
    306     def __init__(self, connection, log, jobPrefixLength): 
    307  
    308         self.authz = None 
    309  
    310         # length of the job prefix used with PerforceJobScript 
     173    def __init__(self, connection, authz, log, jobPrefixLength): 
    311174        self._job_prefix_length = jobPrefixLength 
    312  
    313         # Log object for logging output 
    314         self._log = log 
    315  
    316         # The connection to the Perforce server 
    317175        self._connection = connection 
    318  
     176        name = 'p4://%s:%s@%s' % (self._connection.user, self._connection.password, self._connection.port) 
     177        Repository.__init__(self, name, None, log) 
    319178        # The Repository object that we query for Perforce info 
    320         from p4trac.repos import Repository 
    321         self._repos = Repository(connection) 
    322  
    323     def get_name(self): 
    324         return 'p4://%s:%s@%s' % (self._connection.user, self._connection.password, self._connection.port) 
    325     name = property(get_name) 
     179        from p4trac.repos import P4Repository 
     180        self._repos = P4Repository(connection) 
     181 
     182    def __del__(self): 
     183        self.close() 
     184 
     185    def clear(self, youngest_rev=None): 
     186        self.youngest = None 
     187        if youngest_rev is not None: 
     188            self.youngest = self.normalize_rev(youngest_rev) 
     189        self.oldest = None 
    326190 
    327191    def close(self): 
     
    329193 
    330194    def get_tags(self, rev): 
    331  
    332195        results = self._connection.run('labels') 
    333  
    334196        if results.errors: 
    335197            from p4trac.repos import PerforceError 
    336198            raise PerforceError(results.errors) 
    337  
    338199        for rec in results.records: 
    339200            name = self._repos.toUnicode(rec['label']) 
    340201            yield (name, u'@%s' % name) 
    341202 
    342  
    343203    def get_branches(self, rev): 
    344204        # TODO: Generate a list of branches 
     
    346206 
    347207    def get_changeset(self, rev): 
    348  
    349         self._log.debug('get_changeset(%r)' % rev) 
    350  
     208        self.log.debug('get_changeset(%r)' % rev) 
    351209        if isinstance(rev, int): 
    352210            change = rev 
     
    354212            from p4trac.util import toUnicode 
    355213            rev = toUnicode(rev) 
    356                  
    357214            if rev.startswith(u'@'): 
    358215                rev = rev[1:] 
    359                  
     216 
    360217            try: 
    361218                change = int(rev) 
    362219            except ValueError: 
    363220                raise TracError(u"Invalid changeset number '%s'" % rev) 
    364              
    365         return PerforceChangeset(change, self._repos, self._log, self._job_prefix_length) 
     221 
     222        return PerforceChangeset(change, self._repos, self.log, self._job_prefix_length) 
    366223 
    367224    def get_changesets(self, start, stop): 
    368  
    369         self._log.debug('PerforceRepository.get_changesets(%r,%r)' % (start, 
    370                                                                       stop)) 
     225        self.log.debug('PerforceRepository.get_changesets(%r,%r)' % (start, stop)) 
    371226 
    372227        import datetime 
     
    382237                             '@>=%s,@<=%s' % (startDate, stopDate), 
    383238                             output=output) 
    384  
    385239        if output.errors: 
    386240            from p4trac.repos import PerforceError 
     
    396250 
    397251    def get_node(self, path, rev=None): 
    398         self._log.debug('get_node(%s, %s) called' % (path, rev)) 
    399  
     252        self.log.debug('get_node(%s, %s) called' % (path, rev)) 
    400253        from p4trac.repos import NodePath 
    401254        nodePath = NodePath(NodePath.normalisePath(path), rev) 
    402          
    403         return PerforceNode(nodePath, self._repos, self._log) 
     255        return PerforceNode(nodePath, self._repos, self.log) 
    404256 
    405257    def get_oldest_rev(self): 
    406258        return self.next_rev(0) 
    407     oldest_rev = property(fget=get_oldest_rev) 
    408259 
    409260    def get_youngest_rev(self): 
    410261        return self._repos.getLatestChange() 
    411     youngest_rev = property(fget=get_youngest_rev) 
    412262 
    413263    def previous_rev(self, rev): 
    414  
    415         self._log.debug('previous_rev(%r)' % rev) 
    416  
     264        self.log.debug('previous_rev(%r)' % rev) 
    417265        if not isinstance(rev, int): 
    418266            rev = self.short_rev(rev) 
     
    423271        output = _P4ChangesOutputConsumer(self._repos) 
    424272        self._connection.run('changes', '-l', '-s', 'submitted', 
    425                              '-m', '1', 
    426                              '@<%i' % rev, 
    427                              output=output) 
    428  
     273                             '-m', '1', '@<%i' % rev, output=output) 
    429274        if output.errors: 
    430275            from p4trac.repos import PerforcError 
    431276            raise PerforcError(output.errors) 
    432  
    433277        if output.changes: 
    434278            return max(output.changes) 
     
    437281 
    438282    def next_rev(self, rev, path=''): 
    439  
    440283        # Finding the next revision is a little more difficult in Perforce 
    441284        # as we can only ask for the n most recent changes according to a 
     
    445288        # it is still fairly efficient if the next change is 1 or 1000 changes 
    446289        # later. 
    447  
    448         self._log.debug('next_rev(%r,%r)' % (rev, path)) 
     290        self.log.debug('next_rev(%r,%r)' % (rev, path)) 
    449291 
    450292        from p4trac.repos import NodePath 
     
    466308 
    467309        queryPath = self._repos.fromUnicode(queryPath) 
    468  
    469         self._log.debug( 
    470             u'Looing for next_rev after change %i for %s' % (rev, path)) 
     310        self.log.debug(u'Looing for next_rev after change %i for %s' % (rev, path)) 
    471311 
    472312        # Perform a binary-search of sorts for the next revision 
     
    476316 
    477317        while lowerBound <= upperBound: 
    478  
    479318            if lowerBound + batchSize > upperBound: 
    480319                batchUpperBound = upperBound 
     
    485324                else: 
    486325                    batchUpperBound = middle 
    487  
    488             self._log.debug( 
     326            self.log.debug( 
    489327                'Looking for changes in range [%i, %i]' % (lowerBound, 
    490328                                                           batchUpperBound)) 
     
    498336                                                    batchUpperBound), 
    499337                                 output=output) 
    500  
    501338            if output.errors: 
    502339                from p4trac.repos import PerforcError 
     
    510347                if lowerBound + batchSize >= batchUpperBound: 
    511348                    # There are no earlier changes 
    512                     self._log.debug('next_rev is %i' % lowest) 
     349                    self.log.debug('next_rev is %i' % lowest) 
    513350                    return lowest 
    514351                else: 
     
    520357                # Try searching from batchUpperBound + 1 onwards 
    521358                lowerBound = batchUpperBound + 1 
    522  
    523359        return None 
    524360 
    525361    def rev_older_than(self, rev1, rev2): 
    526  
    527         self._log.debug('PerforceRepository.rev_older_than(%r,%r)' % (rev1, 
    528                                                                       rev2)) 
    529          
     362        self.log.debug('PerforceRepository.rev_older_than(%r,%r)' % (rev1, rev2)) 
     363 
    530364        rev1 = self.short_rev(rev1) 
    531365        rev2 = self.short_rev(rev2) 
    532  
    533366        # Can compare equal revisions directly 
    534367        if rev1 == rev2: 
     
    540373 
    541374        def parseDateRevision(rev): 
    542  
    543375            if not isinstance(rev, unicode): 
    544376                raise ValueError 
    545              
    546377            if not rev.startswith(u'@'): 
    547378                raise ValueError 
    548  
    549379            # @YYYY/MM/DD[:HH:MM:SS] 
    550380            if len(rev) not in [11, 20]: 
    551381                raise ValueError 
    552  
    553382            year = int(rev[1:5]) 
    554383            month = int(rev[6:8]) 
     
    569398                minute = 0 
    570399                second = 0 
    571  
    572400            return (year, month, day, hour, minute, second) 
    573401 
     
    581409        # Compare based on the latest change number that affects this revision. 
    582410        from p4trac.repos import NodePath 
    583  
    584411        if not isinstance(rev1, int): 
    585412            rootAtRev1 = NodePath(u'//', rev1) 
    586413            rev1 = self._repos.getNode(rootAtRev1).change 
    587  
    588414        if not isinstance(rev2, int): 
    589415            rootAtRev2 = NodePath(u'//', rev2) 
    590416            rev2 = self._repos.getNode(rootAtRev2).change 
    591  
    592         self._log.debug('Comparing by change rev1=%i, rev2=%i' % (rev1, rev2)) 
    593  
     417        self.log.debug('Comparing by change rev1=%i, rev2=%i' % (rev1, rev2)) 
    594418        return rev1 < rev2 
    595          
    596     def get_youngest_rev_in_cache(self, db): 
    597  
    598         cursor = db.cursor() 
    599         cursor.execute("SELECT r.rev " 
    600                        "FROM revision r " 
    601                        "ORDER BY r.time DESC " 
    602                        "LIMIT 1") 
    603         row = cursor.fetchone() 
    604         return row and row[0] or None 
    605419 
    606420    def get_path_history(self, path, rev=None, limit=None): 
     
    609423        from p4trac.repos import NodePath 
    610424        nodePath = NodePath(NodePath.normalisePath(path), rev) 
    611         node = PerforceNode(nodePath, self._repos, self._log) 
     425        node = PerforceNode(nodePath, self._repos, self.log) 
    612426        return node.get_history(limit) 
    613427 
    614428    def normalize_path(self, path): 
    615         self._log.debug('normalize_path(%r)' % path) 
     429        self.log.debug('normalize_path(%r)' % path) 
    616430        return normalisePath(path) 
    617431 
    618432    def normalize_rev(self, rev): 
    619         self._log.debug('normalize_rev(%r)' % rev) 
     433        self.log.debug('normalize_rev(%r)' % rev) 
    620434        rev = normaliseRev(rev) 
    621435        if rev is None: 
     
    625439 
    626440    def short_rev(self, rev): 
    627         self._log.debug('short_rev(%r)' % rev) 
     441        self.log.debug('short_rev(%r)' % rev) 
    628442        return self.normalize_rev(rev) 
    629443 
    630     def get_changes(self, old_path, old_rev, new_path, new_rev, 
    631                     ignore_ancestry=1): 
    632  
    633         self._log.debug('PerforceRepository.get_changes(%r,%r,%r,%r)' % ( 
     444    def get_changes(self, old_path, old_rev, new_path, new_rev, ignore_ancestry=1): 
     445        self.log.debug('PerforceRepository.get_changes(%r,%r,%r,%r)' % ( 
    634446            old_path, old_rev, new_path, new_rev)) 
    635447 
     
    641453        newNode = self._repos.getNode(newNodePath) 
    642454 
    643  
    644455        if (newNode.isFile and oldNode.isDirectory) or \ 
    645456           (newNode.isDirectory and oldNode.isFile): 
     
    647458 
    648459        if newNode.isDirectory or oldNode.isDirectory: 
    649  
    650460            if oldNodePath.isRoot: 
    651461                oldQueryPath = u'//...%s' % oldNodePath.rev 
     
    659469                newQueryPath = u'%s/...%s' % (newNodePath.path, 
    660470                                             newNodePath.rev) 
    661  
    662471        elif newNode.isFile or oldNode.isFile: 
    663  
    664472            oldQueryPath = oldNodePath.fullPath 
    665473            newQueryPath = newNodePath.fullPath 
    666  
    667474        else: 
    668475            raise TracError("Cannot diff two non-existant nodes") 
     
    671478        output = _P4Diff2OutputConsumer(self._repos) 
    672479 
    673         self._connection.run( 
    674                 'diff2', '-ds', 
    675                 self._repos.fromUnicode(oldQueryPath), 
    676                 self._repos.fromUnicode(newQueryPath), 
    677                 output=output) 
    678  
     480        self._connection.run('diff2', '-ds', 
     481                             self._repos.fromUnicode(oldQueryPath), 
     482                             self._repos.fromUnicode(newQueryPath), 
     483                             output=output) 
    679484        if output.errors: 
    680485            from p4trac.repos import PerforceError 
     
    682487 
    683488        for change in output.changes: 
    684  
    685489            oldFileNodePath, newFileNodePath = change 
    686  
    687490            if oldFileNodePath is not None: 
    688491                oldFileNode = PerforceNode(oldFileNodePath, 
    689492                                           self._repos, 
    690                                            self._log) 
     493                                           self.log) 
    691494            else: 
    692495                oldFileNode = None 
     
    695498                newFileNode = PerforceNode(newFileNodePath, 
    696499                                           self._repos, 
    697                                            self._log) 
     500                                           self.log) 
    698501            else: 
    699502                newFileNode = None 
    700503 
    701504            if newFileNode and oldFileNode: 
    702                 yield (oldFileNode, 
    703                        newFileNode, 
    704                        Node.FILE, 
    705                        Changeset.EDIT) 
     505                yield (oldFileNode, newFileNode, Node.FILE, Changeset.EDIT) 
    706506            elif newFileNode: 
    707                 yield (oldFileNode, 
    708                        newFileNode, 
    709                        Node.FILE, 
    710                        Changeset.ADD) 
     507                yield (oldFileNode, newFileNode, Node.FILE, Changeset.ADD) 
    711508            elif oldFileNode: 
    712                 yield (oldFileNode, 
    713                        newFileNode, 
    714                        Node.FILE, 
    715                        Changeset.DELETE) 
    716  
    717 class PerforceNode(object): 
     509                yield (oldFileNode, newFileNode, Node.FILE, Changeset.DELETE) 
     510 
     511 
     512class PerforceNode(Node): 
    718513    """A Perforce repository node (depot, directory or file)""" 
    719514 
    720515    def __init__(self, nodePath, repos, log): 
    721  
    722516        log.debug('Created PerforceNode for %r' % nodePath) 
    723  
     517        self._log = log 
    724518        self._repos = repos 
    725519        self._nodePath = nodePath 
    726         self._log = log 
    727520        self._node = self._repos.getNode(nodePath) 
     521        node_type = self._get_kind() 
     522        self.created_rev = self._node.change 
     523        self.created_path = normalisePath(self._nodePath.path) 
     524        self.rev = self.created_rev 
     525        Node.__init__(self, normalisePath(self._nodePath.path), self.rev, node_type) 
    728526 
    729527    def _get_kind(self): 
    730  
    731528        if self._node.isDirectory: 
    732529            return Node.DIRECTORY 
     
    737534                             self._nodePath.rev) 
    738535 
    739     kind = property(fget=_get_kind) 
    740     isdir = property(fget=lambda self: self.kind == Node.DIRECTORY) 
    741  
    742     def _get_path(self): 
    743         self._log.debug('PerforceNode.path') 
    744         return normalisePath(self._nodePath.path) 
    745     path = property(_get_path) 
    746  
    747     def _get_rev(self): 
    748         self._log.debug('PerforceNode.rev') 
    749         return self._node.change 
    750     rev = property(fget=_get_rev) 
    751  
    752     def _get_created_path(self): 
    753         self._log.debug('PerforceNode.created_path') 
    754         # HACK: When should this be different to self.path? 
    755         return self.path 
    756     created_path = property(fget=_get_created_path) 
    757  
    758     def _get_created_rev(self): 
    759         self._log.debug('PerforceNode.created_rev') 
    760         # HACK: When should this be different to self.rev? 
    761         return self._node.change 
    762     created_rev = property(_get_created_rev) 
    763      
    764536    def get_content(self): 
    765537        self._log.debug('PerforceNode.get_content()') 
     
    821593                        if currentNode.fileRevision > 1: 
    822594                            # Get the previous revision 
    823                             nodePath = NodePath( 
    824                                 currentNode.nodePath.path, 
    825                                 '#%i' % (currentNode.fileRevision - 1)) 
     595                            nodePath = NodePath(currentNode.nodePath.path, 
     596                                                '#%i' % (currentNode.fileRevision - 1)) 
    826597                            currentNode = self._repos.getNode(nodePath) 
    827598                        else: 
     
    882653                queryPath = '//...%s' % self._nodePath.rev 
    883654            else: 
    884                 queryPath = '%s/...%s' % (self._nodePath.path, 
    885                                           self._nodePath.rev) 
     655                queryPath = '%s/...%s' % (self._nodePath.path, self._nodePath.rev) 
    886656 
    887657            if limit is None: 
     
    943713        else: 
    944714            raise NoSuchNode(self._nodePath.path, self._nodePath.rev) 
    945          
    946     def get_previous(self): 
    947         self._log.debug('PerforceNode.get_previous') 
    948         skip = True 
    949         for p in self.get_history(2): 
    950             if skip: 
    951                 skip = False 
    952             else: 
    953                 return p 
    954715 
    955716    def get_properties(self): 
     
    971732        else: 
    972733            return self._node.fileSize 
    973     content_length = property(fget=get_content_length) 
    974734 
    975735    def get_content_type(self): 
     
    978738                return self._node.attributes[u'mime-type'] 
    979739        return None 
    980     content_type = property(fget=get_content_type) 
    981  
    982     def get_name(self): 
    983         return self._nodePath.leaf 
    984     name = property(fget=get_name) 
    985740 
    986741    def get_last_modified(self): 
    987742        return self._repos.getChangelist(self._node.change).time 
    988     last_modified = property(fget=get_last_modified) 
    989  
    990 class PerforceChangeset(object): 
     743 
     744 
     745class PerforceChangeset(Changeset): 
    991746    """A Perforce repository changelist""" 
    992747 
     
    999754        self._log = log 
    1000755        self._changelist = self._repos.getChangelist(self._change) 
    1001  
    1002     def _get_message(self): 
    1003         import p4trac.repos 
    1004         try: 
    1005             return self._changelist.description 
    1006         except p4trac.repos.NoSuchChangelist, e: 
    1007             raise NoSuchChangeset(e.change) 
    1008     message = property(fget=_get_message) 
    1009  
    1010     def _get_date(self): 
    1011         import p4trac.repos 
    1012         try: 
    1013             return self._changelist.time 
    1014         except p4trac.repos.NoSuchChangelist, e: 
    1015             raise NoSuchChangeset(e.change) 
    1016     date = property(fget=_get_date) 
    1017  
    1018     def _get_author(self): 
    1019         import p4trac.repos 
    1020         try: 
    1021             return self._changelist.user 
    1022         except p4trac.repos.NoSuchChangelist, e: 
    1023             raise NoSuchChangeset(e.change) 
    1024     author = property(fget=_get_author) 
    1025  
    1026     def _get_rev(self): 
    1027         import p4trac.repos 
    1028         try: 
    1029             return self._change 
    1030         except p4trac.repos.NoSuchChangelist, e: 
    1031             raise NoSuchChangeset(e.change) 
    1032     rev = property(_get_rev) 
     756        Changeset.__init__(self, self._change, self._changelist.description, 
     757                           self._changelist.user, self._changelist.time) 
    1033758 
    1034759    def get_properties(self): 
     760        self._log.debug('PerforceChangeset.get_properties()') 
    1035761        import p4trac.repos 
    1036762        try: 
     
    1052778 
    1053779    def get_changes(self): 
    1054  
    1055780        self._log.debug('PerforceChangeset.get_changes()') 
    1056  
    1057781        # Force population of the file history for the files modified in this 
    1058782        # changelist. 
    1059  
    1060         self._log.debug("PerforceChangeset(%i).get_changes()" % 
    1061                         self._change) 
    1062  
     783        self._log.debug("PerforceChangeset(%i).get_changes()" % self._change) 
    1063784        self._repos.precacheFileInformationForChanges([self._change]) 
    1064785 
    1065786        for node in self._changelist.nodes: 
    1066  
    1067787            nodePath = node.nodePath 
    1068  
    1069788            self._log.debug('Change %i contains %s%s [%s]' % (self._change, 
    1070789                                                              nodePath.path, 
  • perforceplugin/branches/trac-0.10/p4trac/repos.py

    r2226 r2973  
    77from perforce.results import IOutputConsumer 
    88from p4trac.util import AutoAttributesMeta 
     9 
    910 
    1011class _ChangeInfo(object): 
     
    3132        self.status = None 
    3233        self.files = None 
     34 
    3335 
    3436class _FileInfo(object): 
     
    6163        self.attributes = None 
    6264 
     65 
    6366class _DirectoryInfo(object): 
    6467    """A data structure for recording info about a directory. 
     
    8184        self.change = None 
    8285 
     86 
    8387class PerforceError(Exception): 
    8488 
     
    8993        return '\n'.join([e.format() for e in self.errors]) 
    9094 
     95 
    9196class NoSuchChangelist(Exception): 
    9297 
    9398    def __init__(self, change): 
    9499        self.change = change 
     100 
    95101 
    96102class NoSuchNode(Exception): 
     
    100106        self.rev = rev 
    101107 
     108 
    102109class NoSuchFile(NoSuchNode): 
    103110    pass 
     111 
    104112 
    105113class NoSuchDirectory(NoSuchNode): 
     
    110118_dirSlashDotDotRE = re.compile(ur'[^/]+/..(/|$)') 
    111119_trailingSlashesRE = re.compile(ur'(?<=[^/])/*$') 
     120 
    112121 
    113122class NodePath(object): 
     
    350359        return not (self == other) 
    351360     
     361 
    352362class Changelist(object): 
    353363    """A proxy object that gives access to details about a particular 
     
    490500 
    491501        return nodes 
     502 
    492503 
    493504class Node(object): 
     
    847858        return fileNodes 
    848859 
    849 class Repository(object): 
     860 
     861class P4Repository(object): 
    850862    """The repository object. 
    851863