Changeset 3211

Show
Ignore:
Timestamp:
02/11/08 05:23:35 (10 months ago)
Author:
hvr
Message:

GitPlugin: cleanups, factorizations, and minor fixes

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • gitplugin/0.11/tracext/git/git_fs.py

    r3210 r3211  
    2727 
    2828from datetime import datetime 
    29 import time 
     29import time, sys 
     30 
     31if not sys.version_info[:2] >= (2,5): 
     32        raise TracError("python >= 2.5 dependancy not met") 
    3033 
    3134import pkg_resources 
     
    3437import PyGIT 
    3538 
     39def _last_iterable(iterable): 
     40        "helper for detecting last iteration in for-loop" 
     41        i = iter(iterable) 
     42        v = i.next() 
     43        for nextv in i: 
     44                yield False, v 
     45                v = nextv 
     46        yield True, v 
    3647 
    3748# helper 
     
    208219 
    209220                for chg in self.git.diff_tree(old_rev, new_rev, self.normalize_path(new_path)): 
    210                         (mode1,mode2,obj1,obj2,action,path) = chg 
     221                        (mode1,mode2,obj1,obj2,action,path,path2) = chg 
    211222 
    212223                        kind = Node.FILE 
     
    336347 
    337348        def get_history(self, limit=None): 
    338                 for rev in self.git.history(self.rev, self.__git_path(), limit): 
    339                         yield (self.path, rev, Changeset.EDIT
     349                for is_last,rev in _last_iterable(self.git.history(self.rev, self.__git_path(), limit)): 
     350                        yield (self.path, rev, Changeset.EDIT if not is_last else Changeset.ADD
    340351 
    341352        def get_last_modified(self): 
     
    389400                if 'author' in self.props: 
    390401                        git_author = _parse_user_time(self.props['author'][0]) 
    391                         if not (properties.has_key('git-committer') and 
    392                                 properties['git-committer'] == git_author): 
     402                        if not properties.get('git-committer') == git_author: 
    393403                                properties['git-author'] = git_author 
    394404 
     
    396406 
    397407        def get_changes(self): 
    398                 #print "GitChangeset.get_changes" 
    399                 prev = self.props.has_key('parent') and self.props['parent'][0] or None 
    400                 for chg in self.git.diff_tree(prev, self.rev): 
    401                         (mode1,mode2,obj1,obj2,action,path) = chg 
    402  
    403                         kind = Node.FILE 
    404                         if mode2.startswith('04') or mode1.startswith('04'): 
    405                                 kind = Node.DIRECTORY 
    406  
    407                         change = GitChangeset.action_map[action] 
    408  
    409                         yield (path, kind, change, path, prev) 
     408                # TODO: handle renames/removals 
     409                for parent in self.props.get('parent', [None]): 
     410                        for mode1,mode2,obj1,obj2,action,path,path2 in \ 
     411                                    self.git.diff_tree(parent, self.rev): 
     412                                p_path, p_rev = path, parent 
     413 
     414                                kind = Node.FILE 
     415                                if mode2.startswith('04') or mode1.startswith('04'): 
     416                                        kind = Node.DIRECTORY 
     417 
     418                                action = GitChangeset.action_map[action] 
     419 
     420                                if action == Changeset.ADD: 
     421                                        p_path = '' 
     422                                        p_rev = None 
     423 
     424                                yield (path, kind, action, p_path, p_rev) 
  • gitplugin/0.11/tracext/git/PyGIT.py

    r3205 r3211  
    1313# GNU General Public License for more details. 
    1414 
     15from __future__ import with_statement 
     16 
    1517import os, re, sys, time, weakref, threading 
    1618from collections import deque 
     
    7375        self.logger = log 
    7476 
    75         StorageFactory.__dict_lock.acquire() 
    76  
    77         try: 
    78             i = StorageFactory.__dict[repo] 
    79         except KeyError: 
    80             i = Storage(repo, log) 
    81             StorageFactory.__dict[repo] = i 
    82  
    83         # create or remove additional reference depending on 'weak' argument 
    84         if weak: 
     77        with StorageFactory.__dict_lock: 
    8578            try: 
    86                 del StorageFactory.__dict_nonweak[repo] 
     79                i = StorageFactory.__dict[repo] 
    8780            except KeyError: 
    88                 pass 
    89         else: 
    90             StorageFactory.__dict_nonweak[repo] = i 
    91  
    92         StorageFactory.__dict_lock.release() 
     81                i = Storage(repo, log) 
     82                StorageFactory.__dict[repo] = i 
     83 
     84                # create or remove additional reference depending on 'weak' argument 
     85                if weak: 
     86                    try: 
     87                        del StorageFactory.__dict_nonweak[repo] 
     88                    except KeyError: 
     89                        pass 
     90                else: 
     91                    StorageFactory.__dict_nonweak[repo] = i 
    9392 
    9493        self.__inst = i 
     
    124123 
    125124    def _invalidate_caches(self,youngest_rev=None): 
    126         self._lock.acquire() 
    127  
    128         rc = False 
    129  
    130         if self.last_youngest_rev != youngest_rev: 
    131             self.logger.debug("invalidated caches (%s != %s)" % (self.last_youngest_rev, youngest_rev)) 
    132             rc = True 
    133             self._commit_db = None 
    134             self._oldest_rev = None 
    135             self.last_youngest_rev = None 
    136  
    137         self._lock.release() 
    138         return rc 
     125        with self._lock: 
     126            rc = False 
     127            if self.last_youngest_rev != youngest_rev: 
     128                self.logger.debug("invalidated caches (%s != %s)" % (self.last_youngest_rev, youngest_rev)) 
     129                rc = True 
     130                self._commit_db = None 
     131                self._oldest_rev = None 
     132                self.last_youngest_rev = None 
     133 
     134            return rc 
    139135 
    140136    def get_commits(self): 
    141         self._lock.acquire() 
    142         if self._commit_db is None: 
    143             self.logger.debug("triggered rebuild of commit tree db for %d" % id(self)) 
    144             new_db = {} 
    145             new_tags = set([]) 
    146             parent = None 
    147             youngest = None 
    148             ord_rev = 0 
    149             for revs in self._git_call_f("rev-parse", ["--tags"]).readlines(): 
    150                 new_tags.add(revs.strip()) 
    151  
    152             for revs in self._git_call_f("rev-list", ["--parents", "--all"]).readlines(): 
    153                 revs = revs.strip().split() 
    154  
    155                 rev = revs[0] 
    156                 parents = set(revs[1:]) 
    157  
    158                 ord_rev += 1 
    159  
    160                 if not youngest: 
    161                     youngest = rev 
    162  
    163                 # new_db[rev] = (children(rev), parents(rev), ordinal_id(rev)) 
    164                 if new_db.has_key(rev): 
    165                     _children,_parents,_ord_rev = new_db[rev] 
    166                     assert _children 
    167                     assert not _parents 
    168                     assert _ord_rev == 0 
    169                     new_db[rev] = (_children, parents, ord_rev) 
    170                 else: 
    171                     new_db[rev] = (set(), parents, ord_rev) 
    172  
    173                 # update all parents(rev)'s children 
    174                 for parent in parents: 
    175                     if new_db.has_key(parent): 
    176                         new_db[parent][0].add(rev) 
     137        with self._lock: 
     138            if self._commit_db is None: 
     139                self.logger.debug("triggered rebuild of commit tree db for %d" % id(self)) 
     140                new_db = {} 
     141                new_tags = set([]) 
     142                parent = None 
     143                youngest = None 
     144                ord_rev = 0 
     145                for revs in self._git_call_f("rev-parse", ["--tags"]).readlines(): 
     146                    new_tags.add(revs.strip()) 
     147 
     148                for revs in self._git_call_f("rev-list", ["--parents", "--all"]).readlines(): 
     149                    revs = revs.strip().split() 
     150 
     151                    rev = revs[0] 
     152                    parents = set(revs[1:]) 
     153 
     154                    ord_rev += 1 
     155 
     156                    if not youngest: 
     157                        youngest = rev 
     158 
     159                    # new_db[rev] = (children(rev), parents(rev), ordinal_id(rev)) 
     160                    if new_db.has_key(rev): 
     161                        _children,_parents,_ord_rev = new_db[rev] 
     162                        assert _children 
     163                        assert not _parents 
     164                        assert _ord_rev == 0 
     165                        new_db[rev] = (_children, parents, ord_rev) 
    177166                    else: 
    178                         new_db[parent] = (set([rev]), set(), 0) # dummy ordinal_id 
    179  
    180             self._commit_db = new_db, parent, new_tags 
    181             self.last_youngest_rev = youngest 
    182             self.logger.debug("rebuilt commit tree db for %d with %d entries" % (id(self),len(new_db))) 
    183  
    184         self._lock.release() 
    185  
    186         assert self._commit_db[1] is not None 
    187         assert self._commit_db[0] is not None 
    188  
    189         return self._commit_db[0] 
     167                        new_db[rev] = (set(), parents, ord_rev) 
     168 
     169                    # update all parents(rev)'s children 
     170                    for parent in parents: 
     171                        if new_db.has_key(parent): 
     172                            new_db[parent][0].add(rev) 
     173                        else: 
     174                            new_db[parent] = (set([rev]), set(), 0) # dummy ordinal_id 
     175 
     176                self._commit_db = new_db, parent, new_tags 
     177                self.last_youngest_rev = youngest 
     178                self.logger.debug("rebuilt commit tree db for %d with %d entries" % (id(self),len(new_db))) 
     179 
     180            assert self._commit_db[1] is not None 
     181            assert self._commit_db[0] is not None 
     182 
     183            return self._commit_db[0] 
    190184 
    191185    def sync(self): 
     
    419413 
    420414    def diff_tree(self, tree1, tree2, path=""): 
     415        """calls `git diff-tree` and returns tuples of the kind 
     416        (mode1,mode2,obj1,obj2,action,path,path2)""" 
     417 
     418        # diff-tree returns records with the following structure: 
     419        # :<old-mode> <new-mode> <old-sha> <new-sha> <change> NUL <path> NUL [ <src-path> NUL ] 
     420 
     421        lines = self._git_call("diff-tree", 
     422                               ["-z", "-r", 
     423                                str(tree1) if tree1 else "--root", 
     424                                str(tree2), 
     425                                "--", path]).split('\0') 
     426 
     427        assert lines[-1] == "" 
     428        del lines[-1] 
     429 
    421430        if tree1 is None: 
    422             tree1 = "--root" 
    423  
    424         next_is_path = False 
    425         for chg in self._git_call("diff-tree", ["-z", "-r", 
    426                                                 str(tree1), 
    427                                                 str(tree2), 
    428                                                 "--", path]).split('\0'): 
    429             if not chg
    430                 assert not next_is_path 
    431                 continue 
    432  
    433             if next_is_path: 
    434                 next_is_path = False 
    435                 path = chg 
    436                 yield (mode1,mode2,obj1,obj2,action,path) 
    437                 continue 
    438  
    439             if not chg.startswith(':'): 
    440                 continue 
    441  
    442             (mode1,mode2,obj1,obj2,action) = chg.split(None) 
    443             mode1 = mode1[1:] 
    444             next_is_path = True 
    445  
    446         assert not next_is_path 
     431            # if only one tree-sha is given on commandline, 
     432            # the first line is just the redundant tree-sha itself... 
     433            assert not lines[0].startswith(':') 
     434            del lines[0] 
     435 
     436        chg = None 
     437 
     438        def __chg_tuple()
     439            if len(chg) == 6: 
     440                chg.append(None) 
     441            assert len(chg) == 7 
     442            return tuple(chg) 
     443 
     444        for line in lines: 
     445            if line.startswith(':'): 
     446                if chg: 
     447                    yield __chg_tuple() 
     448 
     449                chg = line[1:].split() 
     450                assert len(chg) == 5 
     451            else: 
     452                chg.append(line) 
     453 
     454        if chg: 
     455            yield __chg_tuple() 
    447456 
    448457if __name__ == '__main__':