/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz

« back to all changes in this revision

Viewing changes to diff.py

  • Committer: Curtis Hovey
  • Date: 2012-02-04 14:05:59 UTC
  • mfrom: (772.2.5 handle-patch)
  • Revision ID: sinzui.is@verizon.net-20120204140559-307aeiy47rieqxsf
Merged bzr-handle-patch gtk3 fix.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
"""
6
6
 
7
7
__copyright__ = "Copyright 2005 Canonical Ltd."
8
 
__author__    = "Scott James Remnant <scott@ubuntu.com>"
 
8
__author__ = "Scott James Remnant <scott@ubuntu.com>"
9
9
 
10
10
 
11
11
from cStringIO import StringIO
12
12
 
13
 
import pygtk
14
 
pygtk.require("2.0")
15
 
import gtk
16
 
import pango
17
13
import os
18
14
import re
19
15
import sys
 
16
import inspect
20
17
try:
21
 
    from xml.etree.ElementTree import Element, SubElement, tostring
 
18
    from xml.etree.ElementTree import (
 
19
        Element,
 
20
        SubElement,
 
21
        tostring,
 
22
        )
 
23
    Element, SubElement, tostring  # Hush PEP8 redefinition.
22
24
except ImportError:
23
 
    from elementtree.ElementTree import Element, SubElement, tostring
 
25
    from elementtree.ElementTree import (
 
26
        Element,
 
27
        SubElement,
 
28
        tostring,
 
29
        )
24
30
 
 
31
from gi.repository import Gtk
 
32
from gi.repository import Pango
25
33
try:
26
 
    import gtksourceview2
 
34
    from gi.repository import GtkSource
27
35
    have_gtksourceview = True
28
36
except ImportError:
29
37
    have_gtksourceview = False
30
38
try:
31
 
    import gconf
 
39
    from gi.repository import GConf
32
40
    have_gconf = True
33
41
except ImportError:
34
42
    have_gconf = False
39
47
    osutils,
40
48
    urlutils,
41
49
    workingtree,
42
 
)
43
 
from bzrlib.diff import show_diff_trees, internal_diff
 
50
    )
 
51
from bzrlib.diff import show_diff_trees
44
52
from bzrlib.patches import parse_patches
45
53
from bzrlib.trace import warning
46
 
from bzrlib.plugins.gtk import _i18n
 
54
from bzrlib.plugins.gtk.dialog import (
 
55
    error_dialog,
 
56
    info_dialog,
 
57
    warning_dialog,
 
58
    )
 
59
from bzrlib.plugins.gtk.i18n import _i18n
47
60
from bzrlib.plugins.gtk.window import Window
48
 
from dialog import error_dialog, info_dialog, warning_dialog
49
61
 
50
62
 
51
63
def fallback_guess_language(slm, content_type):
61
73
    pass
62
74
 
63
75
 
64
 
class DiffFileView(gtk.ScrolledWindow):
 
76
class DiffFileView(Gtk.ScrolledWindow):
65
77
    """Window for displaying diffs from a diff file"""
66
78
 
67
79
    def __init__(self):
68
 
        gtk.ScrolledWindow.__init__(self)
 
80
        super(DiffFileView, self).__init__()
69
81
        self.construct()
70
82
        self._diffs = {}
71
83
 
72
84
    def construct(self):
73
 
        self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
74
 
        self.set_shadow_type(gtk.SHADOW_IN)
 
85
        self.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
 
86
        self.set_shadow_type(Gtk.ShadowType.IN)
75
87
 
76
88
        if have_gtksourceview:
77
 
            self.buffer = gtksourceview2.Buffer()
78
 
            slm = gtksourceview2.LanguageManager()
79
 
            guess_language = getattr(gtksourceview2.LanguageManager, 
80
 
                "guess_language", fallback_guess_language)
81
 
            gsl = guess_language(slm, content_type="text/x-patch")
 
89
            self.buffer = GtkSource.Buffer()
 
90
            lang_manager = GtkSource.LanguageManager.get_default()
 
91
            language = lang_manager.guess_language(None, "text/x-patch")
82
92
            if have_gconf:
83
93
                self.apply_gedit_colors(self.buffer)
84
94
            self.apply_colordiff_colors(self.buffer)
85
 
            self.buffer.set_language(gsl)
 
95
            self.buffer.set_language(language)
86
96
            self.buffer.set_highlight_syntax(True)
87
97
 
88
 
            self.sourceview = gtksourceview2.View(self.buffer)
 
98
            self.sourceview = GtkSource.View(buffer=self.buffer)
89
99
        else:
90
 
            self.buffer = gtk.TextBuffer()
91
 
            self.sourceview = gtk.TextView(self.buffer)
 
100
            self.buffer = Gtk.TextBuffer()
 
101
            self.sourceview = Gtk.TextView(self.buffer)
92
102
 
93
103
        self.sourceview.set_editable(False)
94
 
        self.sourceview.modify_font(pango.FontDescription("Monospace"))
 
104
        self.sourceview.modify_font(Pango.FontDescription("Monospace"))
95
105
        self.add(self.sourceview)
96
106
        self.sourceview.show()
97
107
 
101
111
 
102
112
        This method needs the gconf module.
103
113
 
104
 
        :param buf: a gtksourceview2.Buffer object.
 
114
        :param buf: a GtkSource.Buffer object.
105
115
        """
106
116
        GEDIT_SCHEME_PATH = '/apps/gedit-2/preferences/editor/colors/scheme'
 
117
        GEDIT_USER_STYLES_PATH = os.path.expanduser('~/.gnome2/gedit/styles')
107
118
 
108
 
        client = gconf.client_get_default()
 
119
        client = GConf.Client.get_default()
109
120
        style_scheme_name = client.get_string(GEDIT_SCHEME_PATH)
110
121
        if style_scheme_name is not None:
111
 
            style_scheme = gtksourceview2.StyleSchemeManager().get_scheme(style_scheme_name)
112
 
            
113
 
            buf.set_style_scheme(style_scheme)
 
122
            style_scheme_mgr = GtkSource.StyleSchemeManager()
 
123
            style_scheme_mgr.append_search_path(GEDIT_USER_STYLES_PATH)
 
124
 
 
125
            style_scheme = style_scheme_mgr.get_scheme(style_scheme_name)
 
126
 
 
127
            if style_scheme is not None:
 
128
                buf.set_style_scheme(style_scheme)
114
129
 
115
130
    @classmethod
116
131
    def apply_colordiff_colors(klass, buf):
118
133
 
119
134
        Both ~/.colordiffrc and ~/.colordiffrc.bzr-gtk are read.
120
135
 
121
 
        :param buf: a "Diff" gtksourceview2.Buffer object.
 
136
        :param buf: a "Diff" GtkSource.Buffer object.
122
137
        """
123
 
        scheme_manager = gtksourceview2.StyleSchemeManager()
 
138
        scheme_manager = GtkSource.StyleSchemeManager()
124
139
        style_scheme = scheme_manager.get_scheme('colordiff')
125
 
        
 
140
 
126
141
        # if style scheme not found, we'll generate it from colordiffrc
127
142
        # TODO: reload if colordiffrc has changed.
128
143
        if style_scheme is None:
142
157
            if not colors:
143
158
                # ~/.colordiffrc does not exist
144
159
                return
145
 
            
 
160
 
146
161
            mapping = {
147
162
                # map GtkSourceView2 scheme styles to colordiff names
148
163
                # since GSV is richer, accept new names for extra bits,
153
168
                'diff:file': ['file', 'diffstuff'],
154
169
                'diff:special-case': ['specialcase', 'diffstuff'],
155
170
            }
156
 
            
 
171
 
157
172
            converted_colors = {}
158
173
            for name, values in mapping.items():
159
174
                color = None
164
179
                if color is None:
165
180
                    continue
166
181
                converted_colors[name] = color
167
 
            
 
182
 
168
183
            # some xml magic to produce needed style scheme description
169
184
            e_style_scheme = Element('style-scheme')
170
185
            e_style_scheme.set('id', 'colordiff')
174
189
                style = SubElement(e_style_scheme, 'style')
175
190
                style.set('name', name)
176
191
                style.set('foreground', '#%s' % color)
177
 
            
 
192
 
178
193
            scheme_xml = tostring(e_style_scheme, 'UTF-8')
179
 
            if not os.path.exists(os.path.expanduser('~/.local/share/gtksourceview-2.0/styles')):
180
 
                os.makedirs(os.path.expanduser('~/.local/share/gtksourceview-2.0/styles'))
181
 
            file(os.path.expanduser('~/.local/share/gtksourceview-2.0/styles/colordiff.xml'), 'w').write(scheme_xml)
182
 
            
 
194
            if not os.path.exists(os.path.expanduser(
 
195
                '~/.local/share/gtksourceview-2.0/styles')):
 
196
                os.makedirs(os.path.expanduser(
 
197
                    '~/.local/share/gtksourceview-2.0/styles'))
 
198
            file(os.path.expanduser(
 
199
                '~/.local/share/gtksourceview-2.0/styles/colordiff.xml'),
 
200
                'w').write(scheme_xml)
 
201
 
183
202
            scheme_manager.force_rescan()
184
203
            style_scheme = scheme_manager.get_scheme('colordiff')
185
 
        
 
204
 
186
205
        buf.set_style_scheme(style_scheme)
187
206
 
188
207
    @staticmethod
210
229
#        self.parent_tree.lock_read()
211
230
#        self.rev_tree.lock_read()
212
231
#        try:
213
 
#            self.delta = iter_changes_to_status(self.parent_tree, self.rev_tree)
 
232
#            self.delta = iter_changes_to_status(
 
233
#               self.parent_tree, self.rev_tree)
214
234
#            self.path_to_status = {}
215
235
#            self.path_to_diff = {}
216
236
#            source_inv = self.parent_tree.inventory
217
237
#            target_inv = self.rev_tree.inventory
218
238
#            for (file_id, real_path, change_type, display_path) in self.delta:
219
 
#                self.path_to_status[real_path] = u'=== %s %s' % (change_type, display_path)
 
239
#                self.path_to_status[real_path] = u'=== %s %s' % (
 
240
#                    change_type, display_path)
220
241
#                if change_type in ('modified', 'renamed and modified'):
221
242
#                    source_ie = source_inv[file_id]
222
243
#                    target_ie = target_inv[file_id]
224
245
#                    source_ie.diff(internal_diff, *old path, *old_tree,
225
246
#                                   *new_path, target_ie, self.rev_tree,
226
247
#                                   sio)
227
 
#                    self.path_to_diff[real_path] = 
 
248
#                    self.path_to_diff[real_path] =
228
249
#
229
250
#        finally:
230
251
#            self.rev_tree.unlock()
244
265
    """This is the soft and chewy filling for a DiffWindow."""
245
266
 
246
267
    def __init__(self):
247
 
        DiffFileView.__init__(self)
 
268
        super(DiffView, self).__init__()
248
269
        self.rev_tree = None
249
270
        self.parent_tree = None
250
271
 
274
295
        self.buffer.set_text(decoded.encode('UTF-8'))
275
296
 
276
297
 
277
 
class DiffWidget(gtk.HPaned):
 
298
class DiffWidget(Gtk.HPaned):
278
299
    """Diff widget
279
300
 
280
301
    """
 
302
 
 
303
    SHOW_WIDGETS = True
 
304
 
281
305
    def __init__(self):
282
306
        super(DiffWidget, self).__init__()
283
307
 
284
308
        # The file hierarchy: a scrollable treeview
285
 
        scrollwin = gtk.ScrolledWindow()
286
 
        scrollwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
287
 
        scrollwin.set_shadow_type(gtk.SHADOW_IN)
 
309
        scrollwin = Gtk.ScrolledWindow()
 
310
        scrollwin.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
 
311
        scrollwin.set_shadow_type(Gtk.ShadowType.IN)
288
312
        self.pack1(scrollwin)
289
 
        scrollwin.show()
290
 
        
291
 
        self.model = gtk.TreeStore(str, str)
292
 
        self.treeview = gtk.TreeView(self.model)
 
313
        if self.SHOW_WIDGETS:
 
314
            scrollwin.show()
 
315
 
 
316
        self.model = Gtk.TreeStore(str, str)
 
317
        self.treeview = Gtk.TreeView(model=self.model)
293
318
        self.treeview.set_headers_visible(False)
294
319
        self.treeview.set_search_column(1)
295
320
        self.treeview.connect("cursor-changed", self._treeview_cursor_cb)
296
321
        scrollwin.add(self.treeview)
297
 
        self.treeview.show()
 
322
        if self.SHOW_WIDGETS:
 
323
            self.treeview.show()
298
324
 
299
 
        cell = gtk.CellRendererText()
 
325
        cell = Gtk.CellRendererText()
300
326
        cell.set_property("width-chars", 20)
301
 
        column = gtk.TreeViewColumn()
302
 
        column.pack_start(cell, expand=True)
 
327
        column = Gtk.TreeViewColumn()
 
328
        column.pack_start(cell, True)
303
329
        column.add_attribute(cell, "text", 0)
304
330
        self.treeview.append_column(column)
305
331
 
315
341
        if getattr(self, 'diff_view', None) is None:
316
342
            self.diff_view = DiffFileView()
317
343
            self.pack2(self.diff_view)
318
 
        self.diff_view.show()
 
344
        if self.SHOW_WIDGETS:
 
345
            self.diff_view.show()
319
346
        for oldname, newname, patch in sections:
320
347
            self.diff_view._diffs[newname] = str(patch)
321
348
            if newname is None:
332
359
        if getattr(self, 'diff_view', None) is None:
333
360
            self.diff_view = DiffView()
334
361
            self.pack2(self.diff_view)
335
 
        self.diff_view.show()
 
362
        if self.SHOW_WIDGETS:
 
363
            self.diff_view.show()
336
364
        self.diff_view.set_trees(rev_tree, parent_tree)
337
365
        self.rev_tree = rev_tree
338
366
        self.parent_tree = parent_tree
340
368
        self.model.clear()
341
369
        delta = self.rev_tree.changes_from(self.parent_tree)
342
370
 
343
 
        self.model.append(None, [ "Complete Diff", "" ])
 
371
        self.model.append(None, ["Complete Diff", ""])
344
372
 
345
373
        if len(delta.added):
346
 
            titer = self.model.append(None, [ "Added", None ])
 
374
            titer = self.model.append(None, ["Added", None])
347
375
            for path, id, kind in delta.added:
348
 
                self.model.append(titer, [ path, path ])
 
376
                self.model.append(titer, [path, path])
349
377
 
350
378
        if len(delta.removed):
351
 
            titer = self.model.append(None, [ "Removed", None ])
 
379
            titer = self.model.append(None, ["Removed", None])
352
380
            for path, id, kind in delta.removed:
353
 
                self.model.append(titer, [ path, path ])
 
381
                self.model.append(titer, [path, path])
354
382
 
355
383
        if len(delta.renamed):
356
 
            titer = self.model.append(None, [ "Renamed", None ])
 
384
            titer = self.model.append(None, ["Renamed", None])
357
385
            for oldpath, newpath, id, kind, text_modified, meta_modified \
358
386
                    in delta.renamed:
359
 
                self.model.append(titer, [ oldpath, newpath ])
 
387
                self.model.append(titer, [oldpath, newpath])
360
388
 
361
389
        if len(delta.modified):
362
 
            titer = self.model.append(None, [ "Modified", None ])
 
390
            titer = self.model.append(None, ["Modified", None])
363
391
            for path, id, kind, text_modified, meta_modified in delta.modified:
364
 
                self.model.append(titer, [ path, path ])
 
392
                self.model.append(titer, [path, path])
365
393
 
366
394
        self.treeview.expand_all()
367
395
        self.diff_view.show_diff(None)
376
404
                    break
377
405
        if tv_path is None:
378
406
            raise errors.NoSuchFile(file_path)
379
 
        self.treeview.set_cursor(tv_path)
 
407
        self.treeview.set_cursor(tv_path, None, False)
380
408
        self.treeview.scroll_to_cell(tv_path)
381
409
 
382
410
    def _treeview_cursor_cb(self, *args):
383
411
        """Callback for when the treeview cursor changes."""
384
412
        (path, col) = self.treeview.get_cursor()
385
 
        specific_files = [ self.model[path][1] ]
386
 
        if specific_files == [ None ]:
387
 
            return
388
 
        elif specific_files == [ "" ]:
 
413
        if path is None:
 
414
            return
 
415
        specific_files = [self.model[path][1]]
 
416
        if specific_files == [None]:
 
417
            return
 
418
        elif specific_files == [""]:
389
419
            specific_files = None
390
 
        
 
420
 
391
421
        self.diff_view.show_diff(specific_files)
392
 
    
 
422
 
393
423
    def _on_wraplines_toggled(self, widget=None, wrap=False):
394
424
        """Callback for when the wrap lines checkbutton is toggled"""
395
425
        if wrap or widget.get_active():
396
 
            self.diff_view.sourceview.set_wrap_mode(gtk.WRAP_WORD)
 
426
            self.diff_view.sourceview.set_wrap_mode(Gtk.WrapMode.WORD)
397
427
        else:
398
 
            self.diff_view.sourceview.set_wrap_mode(gtk.WRAP_NONE)
 
428
            self.diff_view.sourceview.set_wrap_mode(Gtk.WrapMode.NONE)
 
429
 
399
430
 
400
431
class DiffWindow(Window):
401
432
    """Diff window.
404
435
    differences between two revisions on a branch.
405
436
    """
406
437
 
 
438
    SHOW_WIDGETS = True
 
439
 
407
440
    def __init__(self, parent=None, operations=None):
408
 
        Window.__init__(self, parent)
 
441
        super(DiffWindow, self).__init__(parent=parent)
409
442
        self.set_border_width(0)
410
 
        self.set_title("bzrk diff")
 
443
        self.set_title("bzr diff")
411
444
 
412
445
        # Use two thirds of the screen by default
413
446
        screen = self.get_screen()
419
452
 
420
453
    def construct(self, operations):
421
454
        """Construct the window contents."""
422
 
        self.vbox = gtk.VBox()
 
455
        self.vbox = Gtk.VBox()
423
456
        self.add(self.vbox)
424
 
        self.vbox.show()
 
457
        if self.SHOW_WIDGETS:
 
458
            self.vbox.show()
425
459
        self.diff = DiffWidget()
426
460
        self.vbox.pack_end(self.diff, True, True, 0)
427
 
        self.diff.show_all()
 
461
        if self.SHOW_WIDGETS:
 
462
            self.diff.show_all()
428
463
        # Build after DiffWidget to connect signals
429
464
        menubar = self._get_menu_bar()
430
465
        self.vbox.pack_start(menubar, False, False, 0)
431
466
        hbox = self._get_button_bar(operations)
432
467
        if hbox is not None:
433
468
            self.vbox.pack_start(hbox, False, True, 0)
434
 
        
435
 
    
 
469
 
436
470
    def _get_menu_bar(self):
437
 
        menubar = gtk.MenuBar()
 
471
        menubar = Gtk.MenuBar()
438
472
        # View menu
439
 
        mb_view = gtk.MenuItem(_i18n("_View"))
440
 
        mb_view_menu = gtk.Menu()
441
 
        mb_view_wrapsource = gtk.CheckMenuItem(_i18n("Wrap _Long Lines"))
 
473
        mb_view = Gtk.MenuItem.new_with_mnemonic(_i18n("_View"))
 
474
        mb_view_menu = Gtk.Menu()
 
475
        mb_view_wrapsource = Gtk.CheckMenuItem.new_with_mnemonic(
 
476
            _i18n("Wrap _Long Lines"))
442
477
        mb_view_wrapsource.connect('activate', self.diff._on_wraplines_toggled)
443
 
        mb_view_wrapsource.show()
444
478
        mb_view_menu.append(mb_view_wrapsource)
445
 
        mb_view.show()
446
479
        mb_view.set_submenu(mb_view_menu)
447
 
        mb_view.show()
448
480
        menubar.append(mb_view)
449
 
        menubar.show()
 
481
        if self.SHOW_WIDGETS:
 
482
            menubar.show_all()
450
483
        return menubar
451
 
    
 
484
 
452
485
    def _get_button_bar(self, operations):
453
486
        """Return a button bar to use.
454
487
 
456
489
        """
457
490
        if operations is None:
458
491
            return None
459
 
        hbox = gtk.HButtonBox()
460
 
        hbox.set_layout(gtk.BUTTONBOX_START)
 
492
        hbox = Gtk.HButtonBox()
 
493
        hbox.set_layout(Gtk.ButtonBoxStyle.START)
461
494
        for title, method in operations:
462
 
            merge_button = gtk.Button(title)
463
 
            merge_button.show()
464
 
            merge_button.set_relief(gtk.RELIEF_NONE)
 
495
            merge_button = Gtk.Button(title)
 
496
            if self.SHOW_WIDGETS:
 
497
                merge_button.show()
 
498
            merge_button.set_relief(Gtk.ReliefStyle.NONE)
465
499
            merge_button.connect("clicked", method)
466
 
            hbox.pack_start(merge_button, expand=False, fill=True)
467
 
        hbox.show()
 
500
            hbox.pack_start(merge_button, False, True, 0)
 
501
        if self.SHOW_WIDGETS:
 
502
            hbox.show()
468
503
        return hbox
469
504
 
470
505
    def _get_merge_target(self):
471
 
        d = gtk.FileChooserDialog('Merge branch', self,
472
 
                                  gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
473
 
                                  buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK,
474
 
                                           gtk.STOCK_CANCEL,
475
 
                                           gtk.RESPONSE_CANCEL,))
 
506
        d = Gtk.FileChooserDialog('Merge branch', self,
 
507
                                  Gtk.FileChooserAction.SELECT_FOLDER,
 
508
                                  buttons=(Gtk.STOCK_OK, Gtk.ResponseType.OK,
 
509
                                           Gtk.STOCK_CANCEL,
 
510
                                           Gtk.ResponseType.CANCEL,))
476
511
        try:
477
512
            result = d.run()
478
 
            if result != gtk.RESPONSE_OK:
 
513
            if result != Gtk.ResponseType.OK:
479
514
                raise SelectCancelled()
480
515
            return d.get_current_folder_uri()
481
516
        finally:
495
530
        error_dialog('Error', str(e))
496
531
 
497
532
    def _get_save_path(self, basename):
498
 
        d = gtk.FileChooserDialog('Save As', self,
499
 
                                  gtk.FILE_CHOOSER_ACTION_SAVE,
500
 
                                  buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK,
501
 
                                           gtk.STOCK_CANCEL,
502
 
                                           gtk.RESPONSE_CANCEL,))
 
533
        d = Gtk.FileChooserDialog('Save As', self,
 
534
                                  Gtk.FileChooserAction.SAVE,
 
535
                                  buttons=(Gtk.STOCK_OK, Gtk.ResponseType.OK,
 
536
                                           Gtk.STOCK_CANCEL,
 
537
                                           Gtk.ResponseType.CANCEL,))
503
538
        d.set_current_name(basename)
504
539
        try:
505
540
            result = d.run()
506
 
            if result != gtk.RESPONSE_OK:
 
541
            if result != Gtk.ResponseType.OK:
507
542
                raise SelectCancelled()
508
543
            return urlutils.local_path_from_url(d.get_uri())
509
544
        finally:
524
559
 
525
560
class DiffController(object):
526
561
 
527
 
    def __init__(self, path, patch, window=None):
 
562
    def __init__(self, path, patch, window=None, allow_dirty=False):
528
563
        self.path = path
529
564
        self.patch = patch
 
565
        self.allow_dirty = allow_dirty
530
566
        if window is None:
531
567
            window = DiffWindow(operations=self._provide_operations())
532
568
            self.initialize_window(window)
538
574
 
539
575
    def get_diff_sections(self):
540
576
        yield "Complete Diff", None, ''.join(self.patch)
541
 
        for patch in parse_patches(self.patch):
 
577
        # allow_dirty was added to parse_patches in bzrlib 2.2b1
 
578
        if 'allow_dirty' in inspect.getargspec(parse_patches).args:
 
579
            patches = parse_patches(self.patch, allow_dirty=self.allow_dirty)
 
580
        else:
 
581
            patches = parse_patches(self.patch)
 
582
        for patch in patches:
542
583
            oldname = patch.oldname.split('\t')[0]
543
584
            newname = patch.newname.split('\t')[0]
544
585
            yield oldname, newname, str(patch)
565
606
class MergeDirectiveController(DiffController):
566
607
 
567
608
    def __init__(self, path, directive, window=None):
568
 
        DiffController.__init__(self, path, directive.patch.splitlines(True),
569
 
                                window)
 
609
        super(MergeDirectiveController, self).__init__(
 
610
            path, directive.patch.splitlines(True), window)
570
611
        self.directive = directive
571
612
        self.merge_target = None
572
613