Edgewall Software

Ticket #199: diff_module_beta1.diff

File diff_module_beta1.diff, 38.5 KB (added by cboos, 3 years ago)

Things begin to look good (patch against [1756])

  • htdocs/css/browser.css

     
    4545#dirlist td.name a, #dirlist td.rev a { border-bottom: none; display: block } 
    4646#dirlist td.change * { font-size: 9px } 
    4747 
     48/* Log */ 
     49tr.diff input {  
     50 padding: 0 1em 0 1em; 
     51 margin: 0;  
     52} 
     53 
     54#anydiff { 
     55 background: #f7f7f0; 
     56 border: 1px outset #998; 
     57 margin: 0 1em 1em; 
     58 padding: .8em; 
     59 float: left; 
     60} 
     61#anydiff em { 
     62 background: #fbfbfb; 
     63} 
     64#anydiff form, #anydiff div { 
     65 vertical-align: top; 
     66 display: inline; 
     67 margin-right: 0; 
     68 margin-left: 0; 
     69} 
     70#anydiff input {  
     71 vertical-align: baseline; 
     72} 
     73 
    4874/* Styles for the revision log table 
    4975   (extends the styles for "table.listing") */ 
    5076#chglist { margin-top: 0 } 
  • trac/db_default.py

     
    458458 
    459459default_components = ('trac.About', 'trac.attachment', 'trac.Browser', 
    460460                      'trac.Changeset', 'trac.Search', 'trac.Settings', 
     461                      'trac.Diff', 
    461462                      'trac.ticket.query', 'trac.ticket.report', 
    462463                      'trac.Roadmap', 
    463464                      'trac.ticket.web_ui', 'trac.Timeline', 'trac.wiki.web_ui', 
  • trac/versioncontrol/svn_fs.py

     
    2727import os.path 
    2828import time 
    2929import weakref 
     30import posixpath 
    3031 
    3132from svn import fs, repos, core, delta 
    3233 
     
    175176    def __del__(self): 
    176177        self.close() 
    177178 
     179    def has_node(self, path, rev): 
     180        rev_root = fs.revision_root(self.fs_ptr, rev, self.pool) 
     181        node_type = fs.check_path(rev_root, path, self.pool) 
     182        return node_type in _kindmap 
     183 
    178184    def normalize_path(self, path): 
    179         return path == '/' and path or path.strip('/') 
     185        return path == '/' and path or path and path.strip('/') or '' 
    180186 
    181187    def normalize_rev(self, rev): 
    182188        try: 
     
    267273        rev = self.normalize_rev(rev) 
    268274        expect_deletion = False 
    269275        while rev: 
    270             rev_root = fs.revision_root(self.fs_ptr, rev, self.pool) 
    271             node_type = fs.check_path(rev_root, path, self.pool) 
    272             if node_type in _kindmap: # then path exists at that rev 
     276            if self.has_node(path, rev): 
    273277                if expect_deletion: 
    274278                    # it was missing, now it's there again: rev+1 must be a delete 
    275279                    yield path, rev+1, Changeset.DELETE 
     
    294298                expect_deletion = True 
    295299                rev = self.previous_rev(rev) 
    296300 
     301    def get_diffs(self, old_path, old_rev, new_path, new_rev, ignore_ancestry=1): 
     302        old_node = new_node = None 
     303        old_rev = self.normalize_rev(old_rev) 
     304        new_rev = self.normalize_rev(new_rev) 
     305        if self.has_node(old_path, old_rev): 
     306            old_node = self.get_node(old_path, old_rev) 
     307            old_path = old_node.created_path 
     308            old_rev = old_node.created_rev 
     309        if self.has_node(new_path, new_rev): 
     310            new_node = self.get_node(new_path, new_rev) 
     311            new_path = new_node.created_path 
     312            new_rev = new_node.created_rev 
     313        if not old_node and not new_node: 
     314            raise TracError, ('None of the diff arguments are valid: ' 
     315                              'neither %s in revision %s nor %s in revision %s exist ' 
     316                              'in the repository' % (old_path, old_rev, 
     317                                                     new_path, new_rev)) 
     318        elif old_node and new_node: 
     319            if new_node.kind != old_node.kind: 
     320                raise TracError, ('Diff mismatch: Trying to diff ' 
     321                                  'a %s (%s in revision %s) ' 
     322                                  'with a %s (%s in revision %s).' \ 
     323                                  % (old_node.kind, old_path, old_rev, 
     324                                     new_node.kind, new_path, new_rev)) 
     325        if new_node: 
     326            isdir = new_node.isdir 
     327        else: 
     328            isdir = old_node.isdir 
     329        if isdir: 
     330            editor = DiffChangeEditor() 
     331            e_ptr, e_baton = delta.make_editor(editor, self.pool) 
     332            old_root = fs.revision_root(self.fs_ptr, old_rev, self.pool) 
     333            new_root = fs.revision_root(self.fs_ptr, new_rev, self.pool) 
     334            if isdir: 
     335                old_dir, old_entry = old_path, '' 
     336            def authz_cb(root, path, pool): return 1 
     337            text_deltas = 0 # as this is currently re-done in Diff.py... 
     338            entry_props = 0 # ("... typically used only for working copy updates") 
     339            print 'svn_repos_dir_delta: ', old_dir, old_entry, ' -vs.- ', new_path 
     340            repos.svn_repos_dir_delta(old_root, old_path, '', 
     341                                      new_root, new_path, 
     342                                      e_ptr, e_baton, authz_cb, 
     343                                      text_deltas, 
     344                                      isdir and 1 or 0, 
     345                                      entry_props, 
     346                                      ignore_ancestry, 
     347                                      self.pool) 
     348            for d in editor.deltas: 
     349                yield (posixpath.join(old_path,d[0]), posixpath.join(new_path,d[0]), 
     350                       d[1], d[2]) 
     351        else: 
     352            if new_node and old_node: 
     353                change = Changeset.EDIT 
     354            elif new_node: 
     355                change = Changeset.ADD 
     356            elif old_node: 
     357                change = Changeset.DELETE 
     358            yield (old_path, new_path, Node.FILE, change) 
    297359 
     360 
    298361class SubversionNode(Node): 
    299362 
    300363    pool = property(fget=lambda self: self._pool(), 
     
    450513 
    451514    def _get_prop(self, name): 
    452515        return fs.revision_prop(self.fs_ptr, self.rev, name, self.pool) 
     516 
     517 
     518# 
     519# Delta editor for diffs between arbitrary nodes (recycling my old code for #295 :) ) 
     520# 
     521# Note 1: the 'copyfrom_path' and 'copyfrom_rev' information is not used 
     522#         because 'repos.svn_repos_dir_delta' *doesn't* provide it. 
     523# 
     524# Note 2: the 'dir_baton' is the path of the parent directory 
     525# 
     526 
     527class DiffChangeEditor(delta.Editor):  
     528 
     529    def __init__(self): 
     530        self.deltas = [] 
     531        self.skip_dir_prop_change = 0 
     532 
     533    def _norm(self, path): 
     534        """Path are normalized to __not__ have a leading slash""" 
     535        return path == '/' and path or path and path.strip('/') or '' 
     536     
     537    # -- svn.delta.Editor callbacks 
     538 
     539    def open_root(self, base_revision, dir_pool): 
     540        return '/' 
     541 
     542    def add_directory(self, path, dir_baton, copyfrom_path, copyfrom_rev, dir_pool): 
     543        self.deltas.append((path, Node.DIRECTORY, Changeset.ADD)) 
     544        # don't create an additional 'Changeset.EDIT' entry for this directory 
     545        # in case there's also a dir property change: 
     546        self.skip_dir_prop_change = 1  
     547        return path 
     548 
     549    def open_directory(self, path, dir_baton, base_revision, dir_pool): 
     550        self.deltas.append((path, Node.DIRECTORY, Changeset.EDIT)) 
     551        self.skip_dir_prop_change = 0 
     552        return path 
     553 
     554    def change_dir_prop(self, dir_baton, name, value, pool): 
     555        if self.skip_dir_prop_change: 
     556            return 
     557        self.deltas.append((dir_baton, Node.DIRECTORY, Changeset.EDIT)) 
     558        self.skip_dir_prop_change = 1 
     559 
     560    def close_directory(self, dir_baton): 
     561        self.skip_dir_prop_change = 0 
     562 
     563    def delete_entry(self, path, revision, dir_baton, pool): 
     564        self.deltas.append((path, Node.FILE, Changeset.DELETE)) # should be Node.UNKNOWN 
     565 
     566    def add_file(self, path, dir_baton, copyfrom_path, copyfrom_revision, dir_pool): 
     567        self.deltas.append((self._norm(path), Node.FILE, Changeset.ADD)) 
     568 
     569    def open_file(self, path, dir_baton, dummy_rev, file_pool): 
     570        self.deltas.append((self._norm(path), Node.FILE, Changeset.EDIT)) 
     571 
  • trac/versioncontrol/cache.py

     
    8888    def get_node(self, path, rev=None): 
    8989        return self.repos.get_node(path, rev) 
    9090 
     91    def has_node(self, path, rev): 
     92        return self.repos.has_node(path, rev) 
     93 
    9194    def get_oldest_rev(self): 
    9295        return self.repos.oldest_rev 
    9396 
     
    112115    def normalize_rev(self, rev): 
    113116        return self.repos.normalize_rev(rev) 
    114117 
     118    def get_diffs(self, old_path, old_rev, new_path, new_rev, ignore_ancestry=1): 
     119        return self.repos.get_diffs(old_path, old_rev, new_path, new_rev, ignore_ancestry) 
    115120 
     121 
    116122class CachedChangeset(Changeset): 
    117123 
    118124    def __init__(self, rev, db, authz): 
  • trac/versioncontrol/main.py

     
    4242        """ 
    4343        raise NotImplementedError 
    4444 
     45    def has_node(self, path, rev): 
     46        """ 
     47        Tell if there's a node at the specified (path,rev) combination. 
     48        """ 
     49        raise NotImplementedError 
     50     
    4551    def get_node(self, path, rev=None): 
    4652        """ 
    4753        Retrieve a Node (directory or file) from the repository at the 
     
    114120        'None' is a valid revision value and represents the youngest revision. 
    115121        """ 
    116122        return NotImplementedError 
    117          
    118123 
     124    def get_diffs(self, old_path, old_rev, new_path, new_rev, ignore_ancestry=1): 
     125        """ 
     126        Generator that yields (old_path, new_path, kind, change) tuples 
     127        for each node change between the two arbitrary (path,rev) pairs. 
     128        """ 
     129        raise NotImplementedError 
     130 
     131 
    119132class Node(object): 
    120133    """ 
    121134    Represents a directory or file in the repository. 
  • trac/Diff.py

     
    2424from __future__ import generators 
    2525import time 
    2626import re 
     27import posixpath 
    2728 
    2829from trac import mimeview, perm, util 
    2930from trac.core import * 
    30 from trac.Timeline import ITimelineEventProvider 
    3131from trac.versioncontrol import Changeset, Node 
    3232from trac.versioncontrol.diff import get_diff_options, hdf_diff, unified_diff 
    3333from trac.web.chrome import add_link, add_stylesheet 
     
    3535from trac.wiki import wiki_to_html, wiki_to_oneliner 
    3636 
    3737 
    38 class ChangesetModule(Component): 
     38class Diff(dict): 
     39    def __getattr__(self,str): 
     40        return self[str] 
     41     
    3942 
    40     implements(IRequestHandler, ITimelineEventProvider) 
     43class DiffModule(Component): 
    4144 
     45    implements(IRequestHandler) 
     46 
    4247    # IRequestHandler methods 
    4348 
    4449    def match_request(self, req): 
    45         match = re.match(r'/changeset/([0-9]+)$', req.path_info) 
     50        match = re.match(r'/diff(?:(/.*)|$)', req.path_info) 
    4651        if match: 
    47             req.args['rev'] = match.group(1) 
     52            req.args['path'] = match.group(1) 
    4853            return 1 
    4954 
    5055    def process_request(self, req): 
    5156        req.perm.assert_permission(perm.CHANGESET_VIEW) 
    5257 
    53         rev = req.args.get('rev') 
     58        path = req.args.get('path') 
    5459        repos = self.env.get_repository(req.authname) 
     60        path = repos.normalize_path(path) 
     61        rev = req.args.get('rev', repos.youngest_rev) # 'path history' mode 
     62        old = req.args.get('old')                     # 'arbitrary diff' mode 
     63        new = req.args.get('new') 
     64        old_path = req.args.get('old_path', path) 
     65        if old_path == path and old == new: # force 'path history' mode 
     66            print "force 'path history' mode" 
     67            rev = old 
     68            old_path = old = new = None 
    5569 
    5670        diff_options = get_diff_options(req) 
    5771        if req.args.has_key('update'): 
    58             req.redirect(self.env.href.changeset(rev)) 
     72            if old or new: 
     73                req.redirect(self.env.href.diff(path, new=new, old_path=old_path, old=old)) 
     74            else: 
     75                req.redirect(self.env.href.diff(path, rev=rev)) 
    5976 
    60         chgset = repos.get_changeset(rev) 
    61         req.check_modified(chgset.date, 
    62                            diff_options[0] + ''.join(diff_options[1])) 
     77        if old or new: 
     78            chgset = None 
     79            if not new: 
     80                new = repos.next_rev(old) # FIXME: must lookup the next entry in node history 
     81            elif not old: 
     82                old = repos.previous_rev(new) 
     83            if not old_path: 
     84                old_path = path 
     85            diff = Diff(old_path=old_path, old_rev=old, 
     86                        new_path=path, new_rev=new) 
     87            diffargs = 'new=%s&old_path=%s&old=%s' \ 
     88                       % (new, old_path, old) 
     89        else: 
     90            chgset = repos.get_changeset(rev) 
     91            diff = Diff(old_path=path, old_rev=repos.previous_rev(rev), 
     92                        new_path=path, new_rev=rev) 
     93            diffargs = 'rev=%s' % rev 
    6394 
     95        print diff 
     96         
     97        # TODO: 
     98#         req.check_modified(chgset.date, 
     99#                            diff_options[0] + ''.join(diff_options[1])) 
     100 
    64101        format = req.args.get('format') 
    65102        if format == 'diff': 
    66             self._render_diff(req, repos, chgset, diff_options) 
     103            self._render_diff(req, repos, diff, chgset, diff_options) 
    67104            return 
    68105        elif format == 'zip': 
    69             self._render_zip(req, repos, chgset) 
     106            self._render_zip(req, repos, diff, chgset) 
    70107            return 
    71108 
    72         self._render_html(req, repos, chgset, diff_options) 
    73         add_link(req, 'alternate', '?format=diff', 'Unified Diff', 
     109        self._render_html(req, repos, diff, chgset, diff_options) 
     110        add_link(req, 'alternate', '?format=diff&'+diffargs, 'Unified Diff', 
    74111                 'text/plain', 'diff') 
    75         add_link(req, 'alternate', '?format=zip', 'Zip Archive', 
     112        add_link(req, 'alternate', '?format=zip&'+diffargs, 'Zip Archive', 
    76113                 'application/zip', 'zip') 
    77114        add_stylesheet(req, 'changeset.css') 
    78115        add_stylesheet(req, 'diff.css') 
    79         return 'changeset.cs', None 
     116        return 'diff.cs', None 
    80117 
    81     # ITimelineEventProvider methods 
    82118 
    83     def get_timeline_filters(self, req): 
    84         if req.perm.has_permission(perm.CHANGESET_VIEW): 
    85             yield ('changeset', 'Repository checkins') 
    86  
    87     def get_timeline_events(self, req, start, stop, filters): 
    88         if 'changeset' in filters: 
    89             absurls = req.args.get('format') == 'rss' # Kludge 
    90             show_files = int(self.config.get('timeline', 
    91                                              'changeset_show_files')) 
    92             db = self.env.get_db_cnx() 
    93             repos = self.env.get_repository() 
    94             rev = repos.youngest_rev 
    95             while rev: 
    96                 chgset = repos.get_changeset(rev) 
    97                 if chgset.date < start: 
    98                     return 
    99                 if chgset.date < stop: 
    100                     if absurls: 
    101                         href = self.env.abs_href.changeset(chgset.rev) 
    102                     else: 
    103                         href = self.env.href.changeset(chgset.rev) 
    104                     title = 'Changeset <em>[%s]</em> by %s' % ( 
    105                             util.escape(chgset.rev), util.escape(chgset.author)) 
    106                     message = wiki_to_oneliner(util.shorten_line(chgset.message or '--'), 
    107                                                self.env, db, absurls=absurls) 
    108                     if show_files: 
    109                         files = [] 
    110                         for chg in chgset.get_changes(): 
    111                             if show_files > 0 and len(files) >= show_files: 
    112                                 files.append('...') 
    113                                 break 
    114                             files.append('<span class="%s">%s</span>' 
    115                                          % (chg[2], util.escape(chg[0]))) 
    116                         message = '<span class="changes">' + ', '.join(files) +\ 
    117                                   '</span>: ' + message 
    118                     yield 'changeset', href, title, chgset.date, chgset.author,\ 
    119                           message 
    120                 rev = repos.previous_rev(rev) 
    121  
    122119    # Internal methods 
    123120 
    124     def _render_html(self, req, repos, chgset, diff_options): 
     121    def _render_html(self, req, repos, diff, chgset, diff_options): 
    125122        """HTML version""" 
    126         req.hdf['title'] = '[%s]' % chgset.rev 
    127         req.hdf['changeset'] = { 
    128             'revision': chgset.rev, 
    129             'time': time.strftime('%c', time.localtime(chgset.date)), 
    130             'author': util.escape(chgset.author or 'anonymous'), 
    131             'message': wiki_to_html(chgset.message or '--', self.env, req, 
    132                                     escape_newlines=True) 
    133         } 
     123        req.hdf['diff'] = diff 
     124        req.hdf['diff.href'] = { 
     125            'new_rev': self.env.href.changeset(diff.new_rev), 
     126            'old_rev': self.env.href.changeset(diff.old_rev), 
     127            'new_path': self.env.href.browser(diff.new_path, rev=diff.new_rev), 
     128            'old_path': self.env.href.browser(diff.old_path, rev=diff.old_rev) 
     129            } 
     130        if chgset: # 'path history' mode 
     131            req.hdf['title'] = 'Changes for %s at Revision %s' % (diff.new_path, chgset.rev) 
     132            req.hdf['changeset'] = { 
     133                'revision': chgset.rev, 
     134                'time': time.strftime('%c', time.localtime(chgset.date)), 
     135                'author': util.escape(chgset.author or 'anonymous'), 
     136                'message': wiki_to_html(chgset.message or '--', self.env, req, 
     137                                        escape_newlines=True) 
     138                } 
    134139 
    135         oldest_rev = repos.oldest_rev 
    136         if chgset.rev != oldest_rev: 
    137             add_link(req, 'first', self.env.href.changeset(oldest_rev), 
    138                      'Changeset %s' % oldest_rev) 
    139             previous_rev = repos.previous_rev(chgset.rev) 
    140             add_link(req, 'prev', self.env.href.changeset(previous_rev), 
    141                      'Changeset %s' % previous_rev) 
    142         youngest_rev = repos.youngest_rev 
    143         if str(chgset.rev) != str(youngest_rev): 
    144             next_rev = repos.next_rev(chgset.rev) 
    145             add_link(req, 'next', self.env.href.changeset(next_rev), 
    146                      'Changeset %s' % next_rev) 
    147             add_link(req, 'last', self.env.href.changeset(youngest_rev), 
    148                      'Changeset %s' % youngest_rev) 
     140            oldest_rev = repos.oldest_rev 
     141            if chgset.rev != oldest_rev: 
     142                add_link(req, 'first', self.env.href.diff(diff.old_path, rev=oldest_rev), 
     143                         'Changeset %s' % oldest_rev) # FIXME (use the history) 
     144                previous_rev = repos.previous_rev(chgset.rev) 
     145                add_link(req, 'prev', self.env.href.diff(diff.old_path, rev=previous_rev), 
     146                         'Changeset %s' % previous_rev) 
     147            youngest_rev = repos.youngest_rev 
     148            if str(chgset.rev) != str(youngest_rev): 
     149                next_rev = repos.next_rev(chgset.rev) 
     150                add_link(req, 'next', self.env.href.diff(diff.new_path, rev=next_rev), 
     151                         'Changeset %s' % next_rev) 
     152                add_link(req, 'last', self.env.href.diff(diff.new_path, rev=youngest_rev), 
     153                         'Changeset %s' % youngest_rev) 
     154        elif diff.new_path == diff.old_path: # 'diff between 2 revisions' mode 
     155            req.hdf['title'] = 'Diff for %s between Revisions %s and %s' \ 
     156                               % (diff.new_path, diff.old_rev, diff.new_rev) 
     157        else:                           # 'arbitrary diff' mode 
     158            req.hdf['title'] = 'Diff between %s at Revision %s and %s at Revision %s' \ 
     159                               % (diff.old_path, diff.old_rev, 
     160                                  diff.new_path, diff.new_rev) 
    149161 
    150162        edits = [] 
    151163        idx = 0 
    152         for path, kind, change, base_path, base_rev in chgset.get_changes(): 
     164        old_rev = diff.old_rev 
     165        new_rev = diff.new_rev 
     166        for old_path, new_path, kind, change in repos.get_diffs(**diff): 
     167            print 'delta %d: %s %s delta from %s@%s to %s@%s' \ 
     168                  % (idx, change, kind, old_path, old_rev, new_path, new_rev) 
    153169            info = {'change': change} 
    154             if base_path: 
    155                 info['path.old'] = base_path 
    156                 info['rev.old'] = base_rev 
    157                 info['browser_href.old'] = self.env.href.browser(base_path, 
    158                                                                  rev=base_rev) 
    159             if path: 
    160                 info['path.new'] = path 
    161                 info['rev.new'] = chgset.rev 
    162                 info['browser_href.new'] = self.env.href.browser(path, 
    163                                                                  rev=chgset.rev) 
     170            if old_path: 
     171                info['path.old'] = old_path 
     172                info['rev.old'] = old_rev 
     173                info['browser_href.old'] = self.env.href.browser(old_path, 
     174                                                                 rev=old_rev) 
     175            if new_path: 
     176                info['path.new'] = new_path 
     177                info['rev.new'] = new_rev 
     178                info['browser_href.new'] = self.env.href.browser(new_path, 
     179                                                                 rev=new_rev) 
    164180            if change in (Changeset.COPY, Changeset.EDIT, Changeset.MOVE): 
    165                 edits.append((idx, path, kind, base_path, base_rev)) 
    166             req.hdf['changeset.changes.%d' % idx] = info 
     181                edits.append((idx, old_path, new_path, kind)) 
     182            req.hdf['diff.changes.%d' % idx] = info 
    167183            idx += 1 
    168  
    169         for idx, path, kind, base_path, base_rev in edits: 
    170             old_node = repos.get_node(base_path or path, base_rev) 
    171             new_node = repos.get_node(path, chgset.rev) 
    172  
     184         
     185        for idx, old_path, new_path, kind in edits: 
     186            old_node = repos.get_node(old_path, old_rev) 
     187            new_node = repos.get_node(new_path, new_rev) 
     188             
    173189            # Property changes 
    174190            old_props = old_node.get_properties() 
    175191            new_props = new_node.get_properties() 
     
    183199                for k,v in new_props.items(): 
    184200                    if not k in old_props: 
    185201                        changed_props[k] = {'new': v} 
    186                 req.hdf['changeset.changes.%d.props' % idx] = changed_props 
     202                req.hdf['diff.changes.%d.props' % idx] = changed_props 
    187203 
    188204            if kind == Node.DIRECTORY: 
    189205                continue 
    190206 
    191207            # Content changes 
    192208            default_charset = self.config.get('trac', 'default_charset') 
    193             old_content = old_node.get_content().read() 
     209            old_content = old_node.get_content().read()             
    194210            if mimeview.is_binary(old_content): 
    195211                continue 
    196212            charset = mimeview.get_charset(old_node.content_type) or \ 
     
    217233                                   ignore_blank_lines='-B' in diff_options[1], 
    218234                                   ignore_case='-i' in diff_options[1], 
    219235                                   ignore_space_changes='-b' in diff_options[1]) 
    220                 req.hdf['changeset.changes.%d.diff' % idx] = changes 
     236                req.hdf['diff.changes.%d.diff' % idx] = changes 
    221237 
    222     def _render_diff(self, req, repos, chgset, diff_options): 
     238 
     239    def _render_diff(self, req, repos, diff, chgset, diff_options): 
    223240        """Raw Unified Diff version""" 
    224241        req.send_response(200) 
    225242        req.send_header('Content-Type', 'text/plain;charset=utf-8') 
     
    227244                        'filename=Changeset%s.diff' % req.args.get('rev')) 
    228245        req.end_headers() 
    229246 
    230         for path, kind, change, base_path, base_rev in chgset.get_changes(): 
     247        old_rev = diff.old_rev 
     248        new_rev = diff.new_rev 
     249        print diff 
     250        for old_path, new_path, kind, change in repos.get_diffs(**diff): 
     251            print '.diff delta : %s %s delta from %s@%s to %s@%s' \ 
     252                  % ( change, kind, old_path, old_rev, new_path, new_rev) 
    231253            if change == Changeset.ADD: 
    232254                old_node = None 
    233255            else: 
    234                 old_node = repos.get_node(base_path or path, base_rev) 
     256                old_node = repos.get_node(old_path, old_rev) 
    235257            if change == Changeset.DELETE: 
    236258                new_node = None 
    237259            else: 
    238                 new_node = repos.get_node(path, chgset.rev) 
     260                new_node = repos.get_node(new_path, new_rev) 
    239261 
    240262            # TODO: Property changes 
    241263 
     
    271293                    if option[:2] == '-U': 
    272294                        context = int(option[2:]) 
    273295                        break 
    274                 req.write('Index: ' + path + util.CRLF) 
     296                req.write('Index: ' + new_path + util.CRLF) 
    275297                req.write('=' * 67 + util.CRLF) 
    276298                req.write('--- %s (revision %s)' % old_node_info + 
    277299                          util.CRLF) 
     
    284306                                         ignore_space_changes='-b' in diff_options[1]): 
    285307                    req.write(line + util.CRLF) 
    286308 
    287     def _render_zip(self, req, repos, chgset): 
     309    def _render_zip(self, req, repos, diff, chgset): 
    288310        """ZIP archive with all the added and/or modified files.""" 
     311        new_rev = diff.new_rev 
    289312        req.send_response(200) 
    290313        req.send_header('Content-Type', 'application/zip') 
    291314        req.send_header('Content-Disposition', 
    292                         'filename=Changeset%s.zip' % chgset.rev) 
     315                        'filename=Changeset%s.zip' % new_rev) 
    293316        req.end_headers() 
    294317 
    295318        try: 
     
    300323 
    301324        buf = StringIO() 
    302325        zipfile = ZipFile(buf, 'w', ZIP_DEFLATED) 
    303         for path, kind, change, base_path, base_rev in chgset.get_changes(): 
     326        for old_path, new_path, kind, change in repos.get_diffs(**diff): 
    304327            if kind == Node.FILE and change != Changeset.DELETE: 
    305                 node = repos.get_node(path, chgset.rev) 
     328                node = repos.get_node(new_path, new_rev) 
    306329                zipinfo = ZipInfo() 
    307330                zipinfo.filename = node.path 
    308331                zipinfo.date_time = time.gmtime(node.last_modified)[:6] 
  • trac/Browser.py

     
    7575        }) 
    7676    return links 
    7777 
     78def _anydiff_support(env, req, node):