Changeset 1895

Show
Ignore:
Timestamp:
01/23/07 17:33:15 (2 years ago)
Author:
eblot
Message:

RevtreePlugin:

  • Fix up an issue w/ Python2.3
  • Improve module definition and fix up plugin files
  • Remove unsupported tests
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • revtreeplugin/0.10/enhancers/logenhancer/__init__.py

    r1696 r1895  
    11# -*- coding: utf-8 -*- 
    22# 
    3 # Copyright (C) 2006 Emmanuel Blot <emmanuel.blot@free.fr> 
     3# Copyright (C) 2006-2007 Emmanuel Blot <emmanuel.blot@free.fr> 
    44# All rights reserved. 
    55# 
  • revtreeplugin/0.10/enhancers/logenhancer/logenhancer.py

    r1856 r1895  
    11# -*- coding: utf-8 -*- 
    22# 
    3 # Copyright (C) 2006 Emmanuel Blot <emmanuel.blot@free.fr> 
     3# Copyright (C) 2006-2007 Emmanuel Blot <emmanuel.blot@free.fr> 
    44# All rights reserved. 
    55# 
     
    1717from trac.core import * 
    1818 
     19__all__ = ['LogEnhancer'] 
    1920 
    2021class SimpleContainer(object): 
  • revtreeplugin/0.10/enhancers/setup.py

    r1696 r1895  
    22# -*- coding: utf-8 -*- 
    33# 
    4 # Copyright (C) 2006 Emmanuel Blot <emmanuel.blot@free.fr> 
     4# Copyright (C) 2006-2007 Emmanuel Blot <emmanuel.blot@free.fr> 
    55# All rights reserved. 
    66# 
     
    1616 
    1717PACKAGE = 'TracRevtreeEnhancers' 
    18 VERSION = '0.1.0
     18VERSION = '0.1.1
    1919 
    2020setup ( 
  • revtreeplugin/0.10/revtree/api.py

    r1694 r1895  
    11# -*- coding: utf-8 -*- 
    22# 
    3 # Copyright (C) 2006 Emmanuel Blot <emmanuel.blot@free.fr> 
     3# Copyright (C) 2006-2007 Emmanuel Blot <emmanuel.blot@free.fr> 
    44# All rights reserved. 
    55# 
     
    1616from trac.core import * 
    1717 
     18__all__ = ['IRevtreeEnhancer', 'IRevtreeOptimizer',  
     19           'EmptyRangeError', 'RevtreeSystem'] 
    1820 
    1921class IRevtreeEnhancer(Interface): 
  • revtreeplugin/0.10/revtree/enhancer.py

    r1696 r1895  
    11# -*- coding: utf-8 -*- 
    22# 
    3 # Copyright (C) 2006 Emmanuel Blot <emmanuel.blot@free.fr> 
     3# Copyright (C) 2006-2007 Emmanuel Blot <emmanuel.blot@free.fr> 
    44# All rights reserved. 
    55# 
     
    1313# 
    1414 
    15 from revtree import IRevtreeEnhancer 
     15from revtree.api import IRevtreeEnhancer 
    1616from revtree.svgview import SvgOperation, SvgGroup 
    1717from trac.core import * 
    1818 
     19__all__ = ['SimpleEnhancer'] 
    1920 
    2021class SimpleContainer(object): 
  • revtreeplugin/0.10/revtree/__init__.py

    r1694 r1895  
    11# -*- coding: utf-8 -*- 
    22# 
    3 # Copyright (C) 2006 Emmanuel Blot <emmanuel.blot@free.fr> 
     3# Copyright (C) 2006-2007 Emmanuel Blot <emmanuel.blot@free.fr> 
    44# All rights reserved. 
    55# 
     
    1212# history and logs, available at http://projects.edgewall.com/trac/. 
    1313 
    14 from revtree.api import EmptyRangeError, IRevtreeEnhancer, \ 
    15                         IRevtreeOptimizer, RevtreeSystem 
     14from revtree.api import * 
  • revtreeplugin/0.10/revtree/model.py

    r1859 r1895  
    11# -*- coding: utf-8 -*- 
    22# 
    3 # Copyright (C) 2006 Emmanuel Blot <emmanuel.blot@free.fr> 
     3# Copyright (C) 2006-2007 Emmanuel Blot <emmanuel.blot@free.fr> 
    44# All rights reserved. 
    55# 
     
    2222from svn import fs 
    2323 
    24  
    25 class DefaultRevtreeOptimizer(Component): 
    26     """Default optmizer""" 
    27      
    28     implements(IRevtreeOptimizer)     
    29          
    30     def optimize(self, repos, branches): 
    31         """Computes the optimal placement of branches. 
    32          
    33         Optimal placement is recommended to reduce the number of operation  
    34         links that cross each other on the rendered graphic. 
    35         This rudimentary example is FAR from providing optimal placements... 
    36         """ 
    37         # FIXME: really stupid algorithm 
    38         graph = {} 
    39         for v in repos.branches().values(): 
    40             k = v.name 
    41             src = v.source() 
    42             if src: 
    43                 (rev, path) = src 
    44                 if graph.has_key(path): 
    45                     graph[path].append(k) 
    46                 else: 
    47                     graph[path] = [k] 
    48         density = [] 
    49         for (p, v) in graph.items(): 
    50             density.append((p,len(v))) 
    51         density.sort(lambda a,b: cmp(a[1],b[1])) 
    52         density.reverse() 
    53         order = [] 
    54         cur = 0 
    55         for (branch, weight) in density: 
    56             order.insert(cur, branch) 
    57             if cur: 
    58                 cur = 0 
    59             else: 
    60                 cur = len(order) 
    61         nbranches = [] 
    62         for br in graph.values(): 
    63             nbranches.extend(br) 
    64         nbranches.extend([br.name for br in repos.branches().values() \ 
    65                           if br.name not in nbranches]) 
    66         for branch in nbranches: 
    67             if branch in order: 
    68                 continue 
    69             order.insert(cur, branch) 
    70             if cur: 
    71                 cur = 0 
    72             else: 
    73                 cur = len(order) 
    74         obranches = [repos.branch(name) for name in order] 
    75         # FIXME: use filter() 
    76         return [b for b in obranches if b in branches] 
    77  
     24__all__ = ['Repository'] 
    7825 
    7926class BranchChangeset(object): 
  • revtreeplugin/0.10/revtree/optimizer.py

    r1859 r1895  
    11# -*- coding: utf-8 -*- 
    22# 
    3 # Copyright (C) 2006 Emmanuel Blot <emmanuel.blot@free.fr> 
     3# Copyright (C) 2006-2007 Emmanuel Blot <emmanuel.blot@free.fr> 
    44# All rights reserved. 
    55# 
     
    1313# 
    1414 
    15 import re 
    16 import time 
     15from revtree.api import IRevtreeOptimizer 
     16from trac.core import * 
    1717 
    18 from revtree import EmptyRangeError, IRevtreeOptimizer 
    19 from trac.versioncontrol import Node, Changeset 
    20 from trac.core import * 
    21 # only for get_revision_properties 
    22 from svn import fs 
    23  
     18__all__ = ['DefaultRevtreeOptimizer'] 
    2419 
    2520class DefaultRevtreeOptimizer(Component): 
     
    7570        # FIXME: use filter() 
    7671        return [b for b in obranches if b in branches] 
    77  
    78  
    79 class BranchChangeset(object): 
    80     """Represents a Subversion revision with additionnal properties""" 
    81  
    82     def __init__(self, repos, changeset): 
    83         # Repository 
    84         self.repos = repos 
    85         # Trac changeset 
    86         self.changeset = changeset 
    87         ## revision number 
    88         self.rev = self.changeset.rev 
    89         # branch name 
    90         self.branchname = None 
    91         # clone information (if any) 
    92         self.clone = None 
    93         # last changeset of a branch 
    94         self.last = False 
    95         # SVN properties 
    96         self.properties = None 
    97          
    98     def __cmp__(self, other): 
    99         """Compares to another changeset, based on the revision number""" 
    100         return cmp(self.rev, other.rev) 
    101              
    102     def build(self, bcre): 
    103         """Loads a changeset from a SVN repository""" 
    104         """ 
    105         cre should define two named groups 'branch' and 'path' 
    106         """ 
    107         try: 
    108             if not self._find_simple_branch(bcre): 
    109                 self._find_plain_branch(bcre) 
    110         except AssertionError, e: 
    111             raise AssertionError, "%s rev: %d" % (e, self.rev or 0) 
    112          
    113     def _load_properties(self): 
    114         self.properties = self.repos.get_revision_properties(self.rev) 
    115          
    116     def prop(self, prop): 
    117         if not isinstance(self.properties, dict): 
    118             self._load_properties() 
    119         return self.properties.has_key(prop) and self.properties[prop] or '' 
    120              
    121     def props(self, majtype=None): 
    122         if not isinstance(self.properties, dict): 
    123             self._load_properties() 
    124         if majtype is None: 
    125             return self.properties 
    126         else: 
    127             props = {} 
    128             for (k,v) in self.properties.items(): 
    129                 items = k.split(':') 
    130                 if len(items) and (items[0] == majtype): 
    131                     props[items[1]] = v 
    132             return props 
    133              
    134     def _find_simple_branch(self, bcre): 
    135         change_gen = self.changeset.get_changes() 
    136         item = change_gen.next() 
    137         try: 
    138             change_gen.next() 
    139         except StopIteration: 
    140             pass 
    141         else: 
    142             return False 
    143         (path, kind, change, base_path, base_rev) = item 
    144         if kind is not Node.DIRECTORY: 
    145             return False 
    146         if change is Changeset.COPY: 
    147             path_mo = bcre.match(path) 
    148             src_mo = bcre.match(base_path) 
    149         elif change is Changeset.DELETE: 
    150             self.last = True 
    151             path_mo = bcre.match(base_path) 
    152             src_mo = False 
    153         else: 
    154             return False 
    155         if not path_mo: 
    156             return False 
    157         if path_mo.group('path'): 
    158             return False 
    159         self.branchname = path_mo.group('branch').lower() 
    160         if src_mo: 
    161             self.clone = (int(base_rev), src_mo.group('branch').lower()) 
    162         return True 
    163  
    164     def _find_plain_branch(self, bcre): 
    165         branch = None 
    166         for item in self.changeset.get_changes(): 
    167             (path, kind, change, base_path, base_rev) = item 
    168             mo = bcre.match(path) 
    169             if mo: 
    170                 try: 
    171                     br = mo.group('branch').lower() 
    172                 except IndexError: 
    173                     raise AssertionError, "Invalid RE: missing 'branch' group" 
    174             else: 
    175                 return False 
    176             if not branch: 
    177                 branch = br 
    178             elif branch != br: 
    179                 raise AssertionError, 'Incoherent path [%s] != [%s]' \ 
    180                                       % (br, branch) 
    181         self.branchname = branch 
    182         return True 
    183  
    184 class Branch(object): 
    185     """Represents a branch in Subversion, tracking the associated  
    186        changesets""" 
    187  
    188     def __init__(self, name): 
    189         # Name (path) 
    190         self.name = name 
    191         # Source 
    192         self._source = None 
    193         # Changesets instances tied to the branch 
    194         self._changesets = [] 
    195  
    196     def add_changeset(self, changeset): 
    197         """Adds a new changeset to the branch""" 
    198         self._changesets.append(changeset) 
    199         self._changesets.sort() 
    200          
    201     def __len__(self): 
    202         """Counts the number of tracked changesets""" 
    203         return len(self._changesets) 
    204  
    205     def changesets(self, revrange=None): 
    206         """Returns the tracked changeset as a sequence""" 
    207         if revrange is None: 
    208             return self._changesets 
    209         else: 
    210             return filter(lambda c,mn=revrange[0],mx=revrange[1]: \ 
    211                           mn <= c.rev <= mx, self._changesets) 
    212  
    213     def revision_range(self): 
    214         """Returns a tuple representing the extent of tracked revisions  
    215            (first, last)""" 
    216         if not self._changesets: 
    217             return (0, 0) 
    218         return (self._changesets[0].revision, self._changesets[-1].revision) 
    219  
    220     def authors(self): 
    221         """Returns a list of authors that have committed to the branch""" 
    222         authors = [] 
    223         for chg in self._changesets: 
    224             author = chg.changeset.author 
    225             if author not in authors: 
    226                 authors.append(author) 
    227         return authors 
    228  
    229     def source(self): 
    230         """Search for the origin of the branch""" 
    231         return self._source 
    232  
    233     def youngest(self): 
    234         if len(self._changesets) > 0: 
    235             return self._changesets[-1] 
    236         else:  
    237             return None 
    238  
    239     def oldest(self): 
    240         if len(self._changesets) > 0: 
    241             return self._changesets[0] 
    242         else:  
    243             return None 
    244  
    245     def is_active(self, range): 
    246         y = self.youngest() 
    247         if not y: 
    248             return False 
    249         if not (range[0] <= y.rev <= range[1]): 
    250             return False 
    251         if y.last: 
    252             return False 
    253         return True     
    254  
    255     def build(self, repos): 
    256         if len(self._changesets) > 0: 
    257             clone = self._changesets[0].clone 
    258             if clone: 
    259                 node = repos.find_node(clone[1], clone[0]) 
    260                 self._source = (int(node[1]), node[0]) 
    261  
    262 class Repository(object): 
    263     """Represents a Subversion repositories as a set of branches and a set 
    264        of changesets""" 
    265  
    266     def __init__(self, env, authname): 
    267         # Environment 
    268         self.env = env 
    269         # Logger 
    270         self.log = env.log 
    271         # Trac version control 
    272         self._crepos = self.env.get_repository(authname) 
    273         # Dictionnary of changesets 
    274         self._changesets = {} 
    275         # Dictionnary of branches 
    276         self._branches = {} 
    277  
    278     def _build_branches(self): 
    279         """Constructs the branch dictionnary from the changeset dictionnary"""  
    280         for chgset in self._changesets.values(): 
    281             br = chgset.branchname 
    282             if not self._branches.has_key(br): 
    283                 self._branches[br] = Branch(br) 
    284             self._branches[br].add_changeset(chgset) 
    285         map(lambda b: b.build(self), self._branches.values()) 
    286  
    287     def changeset(self, revision): 
    288         """Returns a tracked changeset from the revision number""" 
    289         if self._changesets.has_key(revision): 
    290             return self._changesets[revision] 
    291         else: 
    292             return None 
    293  
    294     def branch(self, branchname): 
    295         """Returns a tracked branch from its name (path)""" 
    296         if not self._branches.has_key(branchname): 
    297             return None 
    298         else: 
    299             return self._branches[branchname] 
    300  
    301     def changesets(self): 
    302         """Returns the dictionnary of changesets (keys are rev. numbers)""" 
    303         return self._changesets 
    304  
    305     def branches(self): 
    306         """Returns the dictionnary of branches (keys are branch names)""" 
    307         return self._branches 
    308  
    309     def revision_range(self): 
    310         """Returns a tuple representing the extent of tracked revisions  
    311            (first, last)""" 
    312         return (self._revrange) 
    313  
    314     def authors(self): 
    315         """Returns a list of authors that have committed to the repository""" 
    316         authors = [] 
    317         for chg in self._changesets.values(): 
    318             author = chg.changeset.author 
    319             if author not in authors: 
    320                 authors.append(author) 
    321         return authors 
    322          
    323     def get_revision_properties(self, revision): 
    324         """Returns the revision properties 
    325         Ideally, this should be implemented by Trac core...""" 
    326         return fs.svn_fs_revision_proplist(self._crepos.repos.fs_ptr, revision,  
    327                                            self._crepos.repos.pool()) 
    328                                             
    329     def find_node(self, path, rev): 
    330         node = self._crepos.get_node(path, rev) 
    331         return (node.get_name(), node.rev) 
    332  
    333     def build(self, bcre, revrange=None, timerange=None): 
    334         """Builds an internal representation of the repository, which  
    335            is used to generate a graphical view of it""" 
    336         start = 0 
    337         stop = int(time.time()) 
    338         if timerange: 
    339             if timerange[0]: 
    340                 start = timerange[0] 
    341             if timerange[1]: 
    342                 stop = timerange[1] 
    343         vcchangesets = self._crepos.get_changesets(start, stop) 
    344         if revrange: 
    345             revmin = self._crepos.get_oldest_rev() 
    346             revmax = self._crepos.get_youngest_rev() 
    347             if revrange[0]: 
    348                 revmin = revrange[0] 
    349             if revrange[1]: 
    350                 revmax = revrange[1] 
    351             vcsort = [(c.rev, c) for c in vcchangesets \ 
    352                       if revmin <= c.rev <= revmax] 
    353         else: 
    354             vcsort = [(c.rev, c) for c in vcchangesets] 
    355         if len(vcsort) < 1: 
    356             raise EmptyRangeError 
    357         vcsort.sort() 
    358         self._revrange = (vcsort[0][1].rev,vcsort[-1][1].rev) 
    359         vcsort.reverse() 
    360         for (rev, vc) in vcsort: 
    361             chgset = BranchChangeset(self, vc) 
    362             chgset.build(bcre) 
    363             self._changesets[rev] = chgset 
    364         self._build_branches() 
    365  
    366     def __str__(self): 
    367         """Returns a string representation of the repository""" 
    368         msg = "Revision counter: %d\n" % len(self._changesets) 
    369         for br in self._branches.keys(): 
    370             msg += "Branch %s, %d revisions\n" % \ 
    371               (br, len(self._branches[br])) 
    372         return msg 
    373  
  • revtreeplugin/0.10/revtree/svgview.py

    r1707 r1895  
    11# -*- coding: utf-8 -*- 
    22# 
    3 # Copyright (C) 2006 Emmanuel Blot <emmanuel.blot@free.fr> 
     3# Copyright (C) 2006-2007 Emmanuel Blot <emmanuel.blot@free.fr> 
    44# All rights reserved. 
    55# 
     
    2020from math import sqrt 
    2121from random import randrange, seed 
    22 from revtree import EmptyRangeError, IRevtreeEnhancer, IRevtreeOptimizer 
     22from revtree.api import * 
    2323from trac.core import * 
     24 
     25__all__ = ['SvgColor', 'SvgGroup', 'SvgOperation', 'SvgRevtree'] 
    2426 
    2527UNIT = 25 
     
    8991         
    9092    def str2col(string): 
    91         if string[0] is '#'
     93        if string.startswith('#')
    9294            string = string[1:] 
    9395            if len(string) == 6: 
  • revtreeplugin/0.10/revtree/web_ui.py

    r1711 r1895  
    11# -*- coding: utf-8 -*- 
    22# 
    3 # Copyright (C) 2006 Emmanuel Blot <emmanuel.blot@free.fr> 
     3# Copyright (C) 2006-2007 Emmanuel Blot <emmanuel.blot@free.fr> 
    44# All rights reserved. 
    55# 
     
    2929from trac.wiki import wiki_to_html, WikiSystem 
    3030 
     31__all__ = ['RevtreeModule'] 
    3132 
    3233class RevtreeStore(object): 
  • revtreeplugin/0.10/setup.py

    r1707 r1895  
    22# -*- coding: utf-8 -*- 
    33# 
    4 # Copyright (C) 2006 Emmanuel Blot <emmanuel.blot@free.fr> 
     4# Copyright (C) 2006-2007 Emmanuel Blot <emmanuel.blot@free.fr> 
    55# All rights reserved. 
    66# 
     
    1616 
    1717PACKAGE = 'TracRevtreePlugin' 
    18 VERSION = '0.4.5
     18VERSION = '0.4.7
    1919 
    2020setup ( 
     
    3939        'trac.plugins': [ 
    4040            'revtree.web_ui = revtree.web_ui', 
    41             'revtree.enhancer = revtree.enhancer' 
     41            'revtree.enhancer = revtree.enhancer', 
     42            'revtree.optimizer = revtree.optimizer' 
    4243        ] 
    4344    }