Edgewall Software

Ticket #5842: mimeview_patch_fix.patch

File mimeview_patch_fix.patch, 13.8 KB (added by datallah@…, 4 years ago)

Ugly patch for 0.10.4 to fix rendering of patch files (backport of 0.11 code)

  • patch.py

    old new  
    1515# Author: Christopher Lenz <cmlenz@gmx.de> 
    1616#         Ludvig Strigeus 
    1717 
     18import os 
    1819from trac.core import * 
    1920from trac.mimeview.api import content_to_unicode, IHTMLPreviewRenderer, Mimeview 
    2021from trac.util.html import escape, Markup 
     
    3233 
    3334    diff_cs = """ 
    3435<?cs include:'macros.cs' ?> 
    35 <div class="diff"><ul class="entries"><?cs 
    36  each:file = diff.files ?><li class="entry"> 
    37   <h2><?cs var:file.filename ?></h2> 
    38   <table class="inline" summary="Differences" cellspacing="0"> 
    39    <colgroup><col class="lineno" /><col class="lineno" /><col class="content" /></colgroup> 
    40    <thead><tr> 
    41     <th><?cs var:file.oldrev ?></th> 
    42     <th><?cs var:file.newrev ?></th> 
    43     <th>&nbsp;</th> 
    44    </tr></thead><?cs 
    45    each:change = file.diff ?><?cs 
    46     call:diff_display(change, diff.style) ?><?cs 
    47     if:name(change) < len(file.diff) - 1 ?> 
    48      <tbody class="skipped"> 
    49       <tr><th>&hellip;</th><th>&hellip;</th><td>&nbsp;</td></tr> 
    50      </tbody><?cs 
    51     /if ?><?cs 
    52    /each ?> 
    53   </table> 
    54  </li><?cs /each ?> 
    55 </ul></div> 
     36<div class="diff"> 
     37 <ul class="entries"> 
     38  <?cs each:item = diff.files ?> 
     39   <?cs if:len(item.diffs) ?> 
     40    <li class="entry"> 
     41     <h2><?cs var:item.new.path ?></h2> 
     42      <table class="inline" summary="Differences" cellspacing="0"> 
     43       <colgroup><col class="lineno" /><col class="lineno" /><col class="content" /></colgroup> 
     44        <thead><tr> 
     45         <th><?cs var:item.old.shortrev ?></th> 
     46         <th><?cs var:item.new.shortrev ?></th> 
     47         <th>&nbsp;</th> 
     48        </tr></thead> 
     49        <?cs each:blocks = item.diffs ?> 
     50         <?cs each:block = blocks ?> 
     51          <tbody class="<?cs var:block.type ?>"> 
     52           <?cs if block.type == 'unmod'?> 
     53            <?cs each:line = block.base.lines ?> 
     54             <tr> 
     55              <th><?cs var:#block.base.offset + name(line) + 1 ?></th> 
     56              <th><?cs var:#block.changed.offset + name(line) + 1 ?></th> 
     57              <td class="l"><span><?cs var:line ?></span>&nbsp;</td> 
     58             </tr> 
     59            <?cs /each ?> 
     60           <?cs elif block.type == 'add'?> 
     61            <?cs each:line = block.changed.lines ?> 
     62             <tr<?cs call:diff_line_class(block.changed, line) ?>> 
     63              <th>&nbsp;</th> 
     64              <th><?cs var:#block.changed.offset + name(line) + 1 ?></th> 
     65              <td class="r"><ins><?cs var:line ?></ins>&nbsp;</td> 
     66             </tr> 
     67            <?cs /each ?> 
     68           <?cs elif block.type == 'rem'?> 
     69            <?cs each:line = block.base.lines ?> 
     70             <tr<?cs call:diff_line_class(block.base, line) ?>> 
     71              <th><?cs var:#block.base.offset + name(line) + 1 ?></th> 
     72              <th>&nbsp;</th> 
     73              <td class="l"><del><?cs var:line ?></del>&nbsp;</td> 
     74             </tr> 
     75            <?cs /each ?> 
     76           <?cs elif block.type == 'mod'?> 
     77             <!--! First show the "old" lines --> 
     78            <?cs each:line = block.base.lines ?> 
     79             <tr<?cs if:name(line) == 0 ?> class="first"<?cs /if ?>> 
     80              <th><?cs var:#block.base.offset + name(line) + 1 ?></th> 
     81              <th>&nbsp;</th> 
     82              <td class="l"><span><?cs var:line ?></span>&nbsp;</td> 
     83             </tr> 
     84            <?cs /each ?> 
     85            <?cs each:line = block.changed.lines ?> 
     86             <tr<?cs if:name(line) + 1 == len(block.changed.lines) ?> class="last"<?cs /if ?>> 
     87              <th>&nbsp;</th> 
     88              <th><?cs var:#block.changed.offset + name(line) + 1 ?></th> 
     89              <td class="r"><span><?cs var:line ?></span>&nbsp;</td> 
     90             </tr> 
     91            <?cs /each ?> 
     92           <?cs /if ?> 
     93          </tbody> 
     94          <?cs if:name(blocks) < len(item.diffs) - 1 ?> 
     95           <tbody class="skipped"> 
     96            <tr><th>&hellip;</th><th>&hellip;</th><td>&nbsp;</td></tr> 
     97           </tbody> 
     98          <?cs /if ?> 
     99        <?cs /each ?> 
     100       <?cs /each ?> 
     101      </table> 
     102    </li> 
     103   <?cs /if ?> 
     104  <?cs /each ?> 
     105 </ul> 
     106</div> 
    56107""" # diff_cs 
    57108 
    58109    # IHTMLPreviewRenderer methods 
     
    109160            div, mod = divmod(len(match.group(0)), 2) 
    110161            return div * '&nbsp; ' + mod * '&nbsp;' 
    111162 
    112         output = [] 
    113         filename, groups = None, None 
     163        comments = [] 
     164        changes = [] 
    114165        lines = iter(difflines) 
    115166        try: 
    116167            line = lines.next() 
    117168            while True: 
    118169                if not line.startswith('--- '): 
     170                    if not line.startswith('Index: ') and line != '='*67:  
     171                        comments.append(line)  
    119172                    line = lines.next() 
    120173                    continue 
    121174 
     175                oldpath = oldrev = newpath = newrev = '' 
     176 
    122177                # Base filename/version 
    123                 words = line.split(None, 2) 
    124                 filename, fromrev = words[1], 'old' 
    125                 groups, blocks = None, None 
     178                oldinfo = line.split(None, 2)  
     179                if len(oldinfo) > 1:  
     180                    oldpath = oldinfo[1]  
     181                    if len(oldinfo) > 2:  
     182                        oldrev = oldinfo[2]  
    126183 
    127184                # Changed filename/version 
    128185                line = lines.next() 
    129186                if not line.startswith('+++ '): 
    130187                    return None 
    131188 
    132                 words = line.split(None, 2) 
    133                 if len(words[1]) < len(filename): 
    134                     # Always use the shortest filename for display 
    135                     filename = words[1] 
     189                newinfo = line.split(None, 2)  
     190                if len(newinfo) > 1:  
     191                    newpath = newinfo[1]  
     192                    if len(newinfo) > 2:  
     193                        newrev = newinfo[2]  
     194  
     195                shortrev = ('old', 'new')  
     196                if oldpath or newpath:  
     197                    sep = re.compile(r'([/.~\\])')  
     198                    commonprefix = ''.join(os.path.commonprefix(  
     199                        [sep.split(newpath), sep.split(oldpath)]))  
     200                    commonsuffix = ''.join(os.path.commonprefix(  
     201                        [sep.split(newpath)[::-1],  
     202                         sep.split(oldpath)[::-1]])[::-1])  
     203                    if len(commonprefix) > len(commonsuffix):  
     204                        common = commonprefix  
     205                    elif commonsuffix:  
     206                        common = commonsuffix.lstrip('/')  
     207                        a = oldpath[:-len(commonsuffix)]  
     208                        b = newpath[:-len(commonsuffix)]  
     209                        if len(a) < 4 and len(b) < 4:  
     210                            shortrev = (a, b)  
     211                    else:  
     212                        common = '(a) %s vs. (b) %s' % (oldpath, newpath)  
     213                        shortrev = ('a', 'b')  
     214                else:  
     215                    common = ''  
     216  
    136217                groups = [] 
    137                 output.append({'filename' : filename, 'oldrev' : fromrev, 
    138                                'newrev' : 'new', 'diff' : groups}) 
    139  
    140                 for line in lines: 
    141                     # @@ -333,10 +329,8 @@ 
    142                     r = re.match(r'@@ -(\d+),(\d+) \+(\d+),(\d+) @@', line) 
     218                changes.append({'change': 'edit', 'props': [],  
     219                                'comments': '\n'.join(comments),  
     220                                'diffs': groups,  
     221                                'old': {'path': common,  
     222                                        'rev': ' '.join(oldinfo[1:]),  
     223                                        'shortrev': shortrev[0]},  
     224                                'new': {'path': common,  
     225                                        'rev': ' '.join(newinfo[1:]),  
     226                                        'shortrev': shortrev[1]}})  
     227                comments = []  
     228                line = lines.next()  
     229                while line:  
     230                    # "@@ -333,10 +329,8 @@" or "@@ -1 +1 @@"  
     231                    r = re.match(r'@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@',  
     232                                 line)  
    143233                    if not r: 
    144234                        break 
    145235                    blocks = [] 
    146236                    groups.append(blocks) 
    147                     fromline,fromend,toline,toend = map(int, r.groups()) 
    148                     last_type = None 
     237                    fromline, fromend, toline, toend = [int(x or 1)  
     238                                                        for x in r.groups()]  
     239                    last_type = last_change = extra = None 
    149240 
    150241                    fromend += fromline 
    151242                    toend += toline 
    152  
    153                     while fromline < fromend or toline < toend: 
    154                         line = lines.next() 
     243                    line = lines.next()  
     244                    while fromline < fromend or toline < toend or extra:  
    155245 
    156246                        # First character is the command 
    157247                        command = ' ' 
     
    160250                        # Make a new block? 
    161251                        if (command == ' ') != last_type: 
    162252                            last_type = command == ' ' 
    163                             blocks.append({'type': last_type and 'unmod' or 'mod', 
    164                                            'base.offset': fromline - 1, 
    165                                            'base.lines': [], 
    166                                            'changed.offset': toline - 1, 
    167                                            'changed.lines': []}) 
     253                            kind = last_type and 'unmod' or 'mod'  
     254                            block = {'type': kind,  
     255                                     'base': {'offset': fromline - 1,  
     256                                              'lines': []},  
     257                                     'changed': {'offset': toline - 1,  
     258                                                 'lines': []}}  
     259                            blocks.append(block)  
     260                        else:  
     261                            block = blocks[-1]  
    168262                        if command == ' ': 
    169                             blocks[-1]['changed.lines'].append(line) 
    170                             blocks[-1]['base.lines'].append(line) 
    171                             fromline += 1 
    172                             toline += 1 
     263                            sides = ['base', 'changed']  
    173264                        elif command == '+': 
    174                             blocks[-1]['changed.lines'].append(line) 
    175                             toline += 1 
     265                            last_side = 'changed'  
     266                            sides = [last_side]  
    176267                        elif command == '-': 
    177                             blocks[-1]['base.lines'].append(line) 
    178                             fromline += 1 
     268                            last_side = 'base'  
     269                            sides = [last_side]  
     270                        elif command == '\\' and last_side:  
     271                            meta = block[last_side].setdefault('meta', {})  
     272                            meta[len(block[last_side]['lines'])] = True  
     273                            sides = [last_side]  
    179274                        else: 
    180275                            return None 
    181                 line = lines.next() 
     276                        for side in sides:  
     277                            if side == 'base':  
     278                                fromline += 1  
     279                            else:  
     280                                toline += 1  
     281                            block[side]['lines'].append(line)  
     282                        line = lines.next()  
     283                        extra = line and line[0] == '\\'  
    182284        except StopIteration: 
    183285            pass 
    184286 
    185287        # Go through all groups/blocks and mark up intraline changes, and 
    186288        # convert to html 
    187         for o in output: 
    188             for group in o['diff']: 
     289        for o in changes: 
     290            for group in o['diffs']: 
    189291                for b in group: 
    190                     f, t = b['base.lines'], b['changed.lines'] 
     292                    base, changed = b['base'], b['changed']  
     293                    f, t = base['lines'], changed['lines']  
    191294                    if b['type'] == 'mod': 
    192295                        if len(f) == 0: 
    193296                            b['type'] = 'add' 
     
    197300                            _markup_intraline_change(f, t) 
    198301                    for i in xrange(len(f)): 
    199302                        line = f[i].expandtabs(tabwidth) 
    200                         line = escape(line) 
    201                         line = '<del>'.join([space_re.sub(htmlify, seg) 
    202                                              for seg in line.split('\0')]) 
    203                         line = line.replace('\1', '</del>') 
    204                         f[i] = Markup(line) 
     303                        line = escape(line, quotes=False)  
     304                        line = '<del>'.join([space_re.sub(htmlify, seg)  
     305                                             for seg in line.split('\0')])  
     306                        line = line.replace('\1', '</del>')  
     307                        f[i] = Markup(line)  
     308                        if 'meta' in base and i in base['meta']:  
     309                            f[i] = Markup('<em>%s</em>') % f[i]  
    205310                    for i in xrange(len(t)): 
    206311                        line = t[i].expandtabs(tabwidth) 
    207                         line = escape(line) 
    208                         line = '<ins>'.join([space_re.sub(htmlify, seg) 
    209                                              for seg in line.split('\0')]) 
    210                         line = line.replace('\1', '</ins>') 
    211                         t[i] = Markup(line) 
    212         return output 
     312                        line = escape(line, quotes=False)  
     313                        line = '<ins>'.join([space_re.sub(htmlify, seg)  
     314                                             for seg in line.split('\0')])  
     315                        line = line.replace('\1', '</ins>')  
     316                        t[i] = Markup(line)  
     317                        if 'meta' in changed and i in changed['meta']:  
     318                            t[i] = Markup('<em>%s</em>') % t[i]  
     319        return changes