/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: Vincent Ladeuil
  • Date: 2008-06-10 15:25:47 UTC
  • mto: This revision was merged to the branch mainline in revision 504.
  • Revision ID: v.ladeuil+lp@free.fr-20080610152547-dwmil1p8pd0mfpnl
Fix third failing test (thanks to jam).

* tests/test_commit.py:
(TestPendingRevisions.test_pending_revisions_multi_merge): Fix
provided by jam: bzr we now filter the pending merges so that only
the 'heads()' are included. We just ensure that the pending merges
contain the unique tips for the ancestries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
41
41
from bzrlib.errors import NoSuchFile
42
42
from bzrlib.patches import parse_patches
43
43
from bzrlib.trace import warning
 
44
from bzrlib.plugins.gtk import _i18n
44
45
from bzrlib.plugins.gtk.window import Window
45
46
from dialog import error_dialog, info_dialog, warning_dialog
46
47
 
327
328
        """
328
329
        # The diffs of the  selected file: a scrollable source or
329
330
        # text view
 
331
 
 
332
    def set_diff_text_sections(self, sections):
330
333
        self.diff_view = DiffFileView()
331
334
        self.diff_view.show()
332
335
        self.pack2(self.diff_view)
333
 
        self.model.append(None, [ "Complete Diff", "" ])
334
 
        self.diff_view._diffs[None] = ''.join(lines)
335
 
        for patch in parse_patches(lines):
336
 
            oldname = patch.oldname.split('\t')[0]
337
 
            newname = patch.newname.split('\t')[0]
 
336
        for oldname, newname, patch in sections:
 
337
            self.diff_view._diffs[newname] = str(patch)
 
338
            if newname is None:
 
339
                newname = ''
338
340
            self.model.append(None, [oldname, newname])
339
 
            self.diff_view._diffs[newname] = str(patch)
340
341
        self.diff_view.show_diff(None)
341
342
 
342
343
    def set_diff(self, rev_tree, parent_tree):
412
413
    differences between two revisions on a branch.
413
414
    """
414
415
 
415
 
    def __init__(self, parent=None):
 
416
    def __init__(self, parent=None, operations=None):
416
417
        Window.__init__(self, parent)
417
418
        self.set_border_width(0)
418
419
        self.set_title("bzrk diff")
423
424
        width = int(monitor.width * 0.66)
424
425
        height = int(monitor.height * 0.66)
425
426
        self.set_default_size(width, height)
426
 
 
427
 
        self.construct()
428
 
 
429
 
    def construct(self):
 
427
        self.construct(operations)
 
428
 
 
429
    def construct(self, operations):
430
430
        """Construct the window contents."""
431
431
        self.vbox = gtk.VBox()
432
432
        self.add(self.vbox)
433
433
        self.vbox.show()
434
 
        hbox = self._get_button_bar()
 
434
        hbox = self._get_button_bar(operations)
435
435
        if hbox is not None:
436
436
            self.vbox.pack_start(hbox, expand=False, fill=True)
437
437
        self.diff = DiffWidget()
438
438
        self.vbox.add(self.diff)
439
439
        self.diff.show_all()
440
440
 
441
 
    def _get_button_bar(self):
 
441
    def _get_button_bar(self, operations):
442
442
        """Return a button bar to use.
443
443
 
444
444
        :return: None, meaning that no button bar will be used.
445
445
        """
446
 
        return None
447
 
 
448
 
    def set_diff_text(self, description, lines):
449
 
        """Set the diff from a text.
450
 
 
451
 
        The diff must be in unified diff format, and will be parsed to
452
 
        determine filenames.
453
 
        """
454
 
        self.diff.set_diff_text(lines)
455
 
        self.set_title(description + " - bzrk diff")
 
446
        if operations is None:
 
447
            return None
 
448
        hbox = gtk.HButtonBox()
 
449
        hbox.set_layout(gtk.BUTTONBOX_START)
 
450
        for title, method in operations:
 
451
            merge_button = gtk.Button(title)
 
452
            merge_button.show()
 
453
            merge_button.set_relief(gtk.RELIEF_NONE)
 
454
            merge_button.connect("clicked", method)
 
455
            hbox.pack_start(merge_button, expand=False, fill=True)
 
456
        hbox.show()
 
457
        return hbox
 
458
 
 
459
    def _get_merge_target(self):
 
460
        d = gtk.FileChooserDialog('Merge branch', self,
 
461
                                  gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
 
462
                                  buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK,
 
463
                                           gtk.STOCK_CANCEL,
 
464
                                           gtk.RESPONSE_CANCEL,))
 
465
        try:
 
466
            result = d.run()
 
467
            if result != gtk.RESPONSE_OK:
 
468
                raise SelectCancelled()
 
469
            return d.get_current_folder_uri()
 
470
        finally:
 
471
            d.destroy()
 
472
 
 
473
    def _merge_successful(self):
 
474
        # No conflicts found.
 
475
        info_dialog(_i18n('Merge successful'),
 
476
                    _i18n('All changes applied successfully.'))
 
477
 
 
478
    def _conflicts(self):
 
479
        warning_dialog(_i18n('Conflicts encountered'),
 
480
                       _i18n('Please resolve the conflicts manually'
 
481
                             ' before committing.'))
 
482
 
 
483
    def _handle_error(self, e):
 
484
        error_dialog('Error', str(e))
 
485
 
 
486
    def _get_save_path(self, basename):
 
487
        d = gtk.FileChooserDialog('Save As', self,
 
488
                                  gtk.FILE_CHOOSER_ACTION_SAVE,
 
489
                                  buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK,
 
490
                                           gtk.STOCK_CANCEL,
 
491
                                           gtk.RESPONSE_CANCEL,))
 
492
        d.set_current_name(basename)
 
493
        try:
 
494
            result = d.run()
 
495
            if result != gtk.RESPONSE_OK:
 
496
                raise SelectCancelled()
 
497
            return urlutils.local_path_from_url(d.get_uri())
 
498
        finally:
 
499
            d.destroy()
456
500
 
457
501
    def set_diff(self, description, rev_tree, parent_tree):
458
502
        """Set the differences showed by this window.
467
511
        self.diff.set_file(file_path)
468
512
 
469
513
 
470
 
class MergeDirectiveWindow(DiffWindow):
471
 
 
472
 
    def __init__(self, directive, path):
473
 
        DiffWindow.__init__(self, None)
474
 
        self._merge_target = None
 
514
class DiffController(object):
 
515
 
 
516
    def __init__(self, path, patch, window=None):
 
517
        self.path = path
 
518
        self.patch = patch
 
519
        if window is None:
 
520
            window = DiffWindow(operations=self._provide_operations())
 
521
            self.initialize_window(window)
 
522
        self.window = window
 
523
 
 
524
    def initialize_window(self, window):
 
525
        window.diff.set_diff_text_sections(self.get_diff_sections())
 
526
        window.set_title(self.path + " - diff")
 
527
 
 
528
    def get_diff_sections(self):
 
529
        yield "Complete Diff", None, ''.join(self.patch)
 
530
        for patch in parse_patches(self.patch):
 
531
            oldname = patch.oldname.split('\t')[0]
 
532
            newname = patch.newname.split('\t')[0]
 
533
            yield oldname, newname, str(patch)
 
534
 
 
535
    def perform_save(self, window):
 
536
        try:
 
537
            save_path = self.window._get_save_path(osutils.basename(self.path))
 
538
        except SelectCancelled:
 
539
            return
 
540
        source = open(self.path, 'rb')
 
541
        try:
 
542
            target = open(save_path, 'wb')
 
543
            try:
 
544
                osutils.pumpfile(source, target)
 
545
            finally:
 
546
                target.close()
 
547
        finally:
 
548
            source.close()
 
549
 
 
550
    def _provide_operations(self):
 
551
        return [('Save', self.perform_save)]
 
552
 
 
553
 
 
554
class MergeDirectiveController(DiffController):
 
555
 
 
556
    def __init__(self, path, directive, window=None):
 
557
        DiffController.__init__(self, path, directive.patch.splitlines(True),
 
558
                                window)
475
559
        self.directive = directive
476
 
        self.path = path
477
 
 
478
 
    def _get_button_bar(self):
479
 
        """The button bar has only the Merge button"""
480
 
        merge_button = gtk.Button('Merge')
481
 
        merge_button.show()
482
 
        merge_button.set_relief(gtk.RELIEF_NONE)
483
 
        merge_button.connect("clicked", self.perform_merge)
484
 
 
485
 
        save_button = gtk.Button('Save')
486
 
        save_button.show()
487
 
        save_button.set_relief(gtk.RELIEF_NONE)
488
 
        save_button.connect("clicked", self.perform_save)
489
 
 
490
 
        hbox = gtk.HButtonBox()
491
 
        hbox.set_layout(gtk.BUTTONBOX_START)
492
 
        hbox.pack_start(merge_button, expand=False, fill=True)
493
 
        hbox.pack_start(save_button, expand=False, fill=True)
494
 
        hbox.show()
495
 
        return hbox
 
560
        self.merge_target = None
 
561
 
 
562
    def _provide_operations(self):
 
563
        return [('Merge', self.perform_merge), ('Save', self.perform_save)]
496
564
 
497
565
    def perform_merge(self, window):
498
 
        try:
499
 
            tree = self._get_merge_target()
500
 
        except SelectCancelled:
501
 
            return
 
566
        if self.merge_target is None:
 
567
            try:
 
568
                self.merge_target = self.window._get_merge_target()
 
569
            except SelectCancelled:
 
570
                return
 
571
        tree = workingtree.WorkingTree.open(self.merge_target)
502
572
        tree.lock_write()
503
573
        try:
504
574
            try:
509
579
                conflict_count = merger.do_merge()
510
580
                merger.set_pending()
511
581
                if conflict_count == 0:
512
 
                    # No conflicts found.
513
 
                    info_dialog(_('Merge successful'),
514
 
                                _('All changes applied successfully.'))
 
582
                    self.window._merge_successful()
515
583
                else:
 
584
                    self.window._conflicts()
516
585
                    # There are conflicts to be resolved.
517
 
                    warning_dialog(_('Conflicts encountered'),
518
 
                                   _('Please resolve the conflicts manually'
519
 
                                     ' before committing.'))
520
 
                self.destroy()
 
586
                self.window.destroy()
521
587
            except Exception, e:
522
 
                error_dialog('Error', str(e))
 
588
                self.window._handle_error(e)
523
589
        finally:
524
590
            tree.unlock()
525
591
 
526
 
    def _get_merge_target(self):
527
 
        if self._merge_target is not None:
528
 
            return self._merge_target
529
 
        d = gtk.FileChooserDialog('Merge branch', self,
530
 
                                  gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
531
 
                                  buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK,
532
 
                                           gtk.STOCK_CANCEL,
533
 
                                           gtk.RESPONSE_CANCEL,))
534
 
        try:
535
 
            result = d.run()
536
 
            if result != gtk.RESPONSE_OK:
537
 
                raise SelectCancelled()
538
 
            uri = d.get_current_folder_uri()
539
 
        finally:
540
 
            d.destroy()
541
 
        return workingtree.WorkingTree.open(uri)
542
 
 
543
 
    def perform_save(self, window):
544
 
        d = gtk.FileChooserDialog('Save As', self,
545
 
                                  gtk.FILE_CHOOSER_ACTION_SAVE,
546
 
                                  buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK,
547
 
                                           gtk.STOCK_CANCEL,
548
 
                                           gtk.RESPONSE_CANCEL,))
549
 
        d.set_current_name(osutils.basename(self.path))
550
 
        try:
551
 
            try:
552
 
                result = d.run()
553
 
                if result != gtk.RESPONSE_OK:
554
 
                    raise SelectCancelled()
555
 
                uri = d.get_uri()
556
 
            finally:
557
 
                d.destroy()
558
 
        except SelectCancelled:
559
 
            return
560
 
        source = open(self.path, 'rb')
561
 
        try:
562
 
            target = open(urlutils.local_path_from_url(uri), 'wb')
563
 
            try:
564
 
                target.write(source.read())
565
 
            finally:
566
 
                target.close()
567
 
        finally:
568
 
            source.close()
569
 
 
570
592
 
571
593
def iter_changes_to_status(source, target):
572
594
    """Determine the differences between trees.