[Pkg-bazaar-commits] ./bzr-gtk/unstable r492: Allow saving from patch window, refactoring, testing.
Aaron Bentley
aaron at aaronbentley.com
Fri Apr 10 07:50:32 UTC 2009
------------------------------------------------------------
revno: 492
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: bzr-gtk
timestamp: Wed 2008-05-21 22:33:40 -0400
message:
Allow saving from patch window, refactoring, testing.
modified:
__init__.py
diff.py
tests/test_diff.py
------------------------------------------------------------
revno: 487.2.1
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: save-patch
timestamp: Thu 2008-05-08 20:16:51 +1200
message:
Refactor merge directive window into MergeController
modified:
__init__.py
diff.py
------------------------------------------------------------
revno: 487.2.2
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: save-patch
timestamp: Thu 2008-05-08 20:45:15 +1200
message:
Unify MergeDirectiveWindow and DiffWindow
modified:
__init__.py
diff.py
------------------------------------------------------------
revno: 487.2.3
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: save-patch
timestamp: Thu 2008-05-08 21:56:34 +1200
message:
Much refactoring
modified:
diff.py
------------------------------------------------------------
revno: 487.2.4
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: save-patch
timestamp: Fri 2008-05-09 11:23:47 +1200
message:
Add tests for DiffController
modified:
tests/test_diff.py
------------------------------------------------------------
revno: 487.2.5
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: save-patch
timestamp: Fri 2008-05-09 15:34:41 +1200
message:
Test successful merge
modified:
diff.py
tests/test_diff.py
------------------------------------------------------------
revno: 487.2.6
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: save-patch
timestamp: Fri 2008-05-09 15:41:19 +1200
message:
Ensure MergeController sets pending merges and updates files
modified:
tests/test_diff.py
------------------------------------------------------------
revno: 487.2.7
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: save-patch
timestamp: Sat 2008-05-10 15:23:00 +1200
message:
Add more merge tests
modified:
diff.py
tests/test_diff.py
------------------------------------------------------------
revno: 487.2.8
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: save-patch
timestamp: Mon 2008-05-12 16:21:45 -0400
message:
Update error handling to use window
modified:
diff.py
tests/test_diff.py
-------------- next part --------------
=== modified file '__init__.py'
--- a/__init__.py 2008-05-22 02:22:38 +0000
+++ b/__init__.py 2008-05-22 02:33:40 +0000
@@ -705,8 +705,8 @@
def run(self, path):
try:
- from bzrlib.plugins.gtk.diff import (DiffWindow,
- MergeDirectiveWindow)
+ from bzrlib.plugins.gtk.diff import (DiffController,
+ MergeDirectiveController)
if path == '-':
lines = sys.stdin.readlines()
else:
@@ -715,11 +715,10 @@
try:
directive = merge_directive.MergeDirective.from_lines(lines)
except errors.NotAMergeDirective:
- window = DiffWindow()
- window.set_diff_text(path, lines)
+ controller = DiffController(path, lines)
else:
- window = MergeDirectiveWindow(directive, path)
- window.set_diff_text(path, directive.patch.splitlines(True))
+ controller = MergeDirectiveController(path, directive)
+ window = controller.window
window.show()
gtk = self.open_display()
window.connect("destroy", gtk.main_quit)
=== modified file 'diff.py'
--- a/diff.py 2008-05-05 18:16:46 +0000
+++ b/diff.py 2008-05-22 02:33:40 +0000
@@ -328,16 +328,16 @@
"""
# The diffs of the selected file: a scrollable source or
# text view
+
+ def set_diff_text_sections(self, sections):
self.diff_view = DiffFileView()
self.diff_view.show()
self.pack2(self.diff_view)
- self.model.append(None, [ "Complete Diff", "" ])
- self.diff_view._diffs[None] = ''.join(lines)
- for patch in parse_patches(lines):
- oldname = patch.oldname.split('\t')[0]
- newname = patch.newname.split('\t')[0]
+ for oldname, newname, patch in sections:
+ self.diff_view._diffs[newname] = str(patch)
+ if newname is None:
+ newname = ''
self.model.append(None, [oldname, newname])
- self.diff_view._diffs[newname] = str(patch)
self.diff_view.show_diff(None)
def set_diff(self, rev_tree, parent_tree):
@@ -413,7 +413,7 @@
differences between two revisions on a branch.
"""
- def __init__(self, parent=None):
+ def __init__(self, parent=None, operations=None):
Window.__init__(self, parent)
self.set_border_width(0)
self.set_title("bzrk diff")
@@ -424,36 +424,79 @@
width = int(monitor.width * 0.66)
height = int(monitor.height * 0.66)
self.set_default_size(width, height)
-
- self.construct()
-
- def construct(self):
+ self.construct(operations)
+
+ def construct(self, operations):
"""Construct the window contents."""
self.vbox = gtk.VBox()
self.add(self.vbox)
self.vbox.show()
- hbox = self._get_button_bar()
+ hbox = self._get_button_bar(operations)
if hbox is not None:
self.vbox.pack_start(hbox, expand=False, fill=True)
self.diff = DiffWidget()
self.vbox.add(self.diff)
self.diff.show_all()
- def _get_button_bar(self):
+ def _get_button_bar(self, operations):
"""Return a button bar to use.
:return: None, meaning that no button bar will be used.
"""
- return None
-
- def set_diff_text(self, description, lines):
- """Set the diff from a text.
-
- The diff must be in unified diff format, and will be parsed to
- determine filenames.
- """
- self.diff.set_diff_text(lines)
- self.set_title(description + " - bzrk diff")
+ if operations is None:
+ return None
+ hbox = gtk.HButtonBox()
+ hbox.set_layout(gtk.BUTTONBOX_START)
+ for title, method in operations:
+ merge_button = gtk.Button(title)
+ merge_button.show()
+ merge_button.set_relief(gtk.RELIEF_NONE)
+ merge_button.connect("clicked", method)
+ hbox.pack_start(merge_button, expand=False, fill=True)
+ hbox.show()
+ return hbox
+
+ def _get_merge_target(self):
+ d = gtk.FileChooserDialog('Merge branch', self,
+ gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
+ buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK,
+ gtk.STOCK_CANCEL,
+ gtk.RESPONSE_CANCEL,))
+ try:
+ result = d.run()
+ if result != gtk.RESPONSE_OK:
+ raise SelectCancelled()
+ return d.get_current_folder_uri()
+ finally:
+ d.destroy()
+
+ def _merge_successful(self):
+ # No conflicts found.
+ info_dialog(_i18n('Merge successful'),
+ _i18n('All changes applied successfully.'))
+
+ def _conflicts(self):
+ warning_dialog(_i18n('Conflicts encountered'),
+ _i18n('Please resolve the conflicts manually'
+ ' before committing.'))
+
+ def _handle_error(self, e):
+ error_dialog('Error', str(e))
+
+ def _get_save_path(self, basename):
+ d = gtk.FileChooserDialog('Save As', self,
+ gtk.FILE_CHOOSER_ACTION_SAVE,
+ buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK,
+ gtk.STOCK_CANCEL,
+ gtk.RESPONSE_CANCEL,))
+ d.set_current_name(basename)
+ try:
+ result = d.run()
+ if result != gtk.RESPONSE_OK:
+ raise SelectCancelled()
+ return urlutils.local_path_from_url(d.get_uri())
+ finally:
+ d.destroy()
def set_diff(self, description, rev_tree, parent_tree):
"""Set the differences showed by this window.
@@ -468,38 +511,64 @@
self.diff.set_file(file_path)
-class MergeDirectiveWindow(DiffWindow):
-
- def __init__(self, directive, path):
- DiffWindow.__init__(self, None)
- self._merge_target = None
+class DiffController(object):
+
+ def __init__(self, path, patch, window=None):
+ self.path = path
+ self.patch = patch
+ if window is None:
+ window = DiffWindow(operations=self._provide_operations())
+ self.initialize_window(window)
+ self.window = window
+
+ def initialize_window(self, window):
+ window.diff.set_diff_text_sections(self.get_diff_sections())
+ window.set_title(self.path + " - diff")
+
+ def get_diff_sections(self):
+ yield "Complete Diff", None, ''.join(self.patch)
+ for patch in parse_patches(self.patch):
+ oldname = patch.oldname.split('\t')[0]
+ newname = patch.newname.split('\t')[0]
+ yield oldname, newname, str(patch)
+
+ def perform_save(self, window):
+ try:
+ save_path = self.window._get_save_path(osutils.basename(self.path))
+ except SelectCancelled:
+ return
+ source = open(self.path, 'rb')
+ try:
+ target = open(save_path, 'wb')
+ try:
+ osutils.pumpfile(source, target)
+ finally:
+ target.close()
+ finally:
+ source.close()
+
+ def _provide_operations(self):
+ return [('Save', self.perform_save)]
+
+
+class MergeDirectiveController(DiffController):
+
+ def __init__(self, path, directive, window=None):
+ DiffController.__init__(self, path, directive.patch.splitlines(True),
+ window)
self.directive = directive
- self.path = path
-
- def _get_button_bar(self):
- """The button bar has only the Merge button"""
- merge_button = gtk.Button('Merge')
- merge_button.show()
- merge_button.set_relief(gtk.RELIEF_NONE)
- merge_button.connect("clicked", self.perform_merge)
-
- save_button = gtk.Button('Save')
- save_button.show()
- save_button.set_relief(gtk.RELIEF_NONE)
- save_button.connect("clicked", self.perform_save)
-
- hbox = gtk.HButtonBox()
- hbox.set_layout(gtk.BUTTONBOX_START)
- hbox.pack_start(merge_button, expand=False, fill=True)
- hbox.pack_start(save_button, expand=False, fill=True)
- hbox.show()
- return hbox
+ self.merge_target = None
+
+ def _provide_operations(self):
+ return [('Merge', self.perform_merge), ('Save', self.perform_save)]
def perform_merge(self, window):
- try:
- tree = self._get_merge_target()
- except SelectCancelled:
- return
+ if self.merge_target is None:
+ try:
+ self.merge_target = self.window._get_merge_target()
+ except SelectCancelled:
+ return
+ tree = workingtree.WorkingTree.open(self.merge_target)
tree.lock_write()
try:
try:
@@ -510,64 +579,16 @@
conflict_count = merger.do_merge()
merger.set_pending()
if conflict_count == 0:
- # No conflicts found.
- info_dialog(_i18n('Merge successful'),
- _i18n('All changes applied successfully.'))
+ self.window._merge_successful()
else:
+ self.window._conflicts()
# There are conflicts to be resolved.
- warning_dialog(_i18n('Conflicts encountered'),
- _i18n('Please resolve the conflicts manually'
- ' before committing.'))
- self.destroy()
+ self.window.destroy()
except Exception, e:
- error_dialog('Error', str(e))
+ self.window._handle_error(e)
finally:
tree.unlock()
- def _get_merge_target(self):
- if self._merge_target is not None:
- return self._merge_target
- d = gtk.FileChooserDialog('Merge branch', self,
- gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
- buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK,
- gtk.STOCK_CANCEL,
- gtk.RESPONSE_CANCEL,))
- try:
- result = d.run()
- if result != gtk.RESPONSE_OK:
- raise SelectCancelled()
- uri = d.get_current_folder_uri()
- finally:
- d.destroy()
- return workingtree.WorkingTree.open(uri)
-
- def perform_save(self, window):
- d = gtk.FileChooserDialog('Save As', self,
- gtk.FILE_CHOOSER_ACTION_SAVE,
- buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK,
- gtk.STOCK_CANCEL,
- gtk.RESPONSE_CANCEL,))
- d.set_current_name(osutils.basename(self.path))
- try:
- try:
- result = d.run()
- if result != gtk.RESPONSE_OK:
- raise SelectCancelled()
- uri = d.get_uri()
- finally:
- d.destroy()
- except SelectCancelled:
- return
- source = open(self.path, 'rb')
- try:
- target = open(urlutils.local_path_from_url(uri), 'wb')
- try:
- target.write(source.read())
- finally:
- target.close()
- finally:
- source.close()
-
def iter_changes_to_status(source, target):
"""Determine the differences between trees.
=== modified file 'tests/test_diff.py'
--- a/tests/test_diff.py 2008-03-11 13:18:28 +0000
+++ b/tests/test_diff.py 2008-05-12 20:21:45 +0000
@@ -18,10 +18,33 @@
from cStringIO import StringIO
import os
-from bzrlib import tests
-
-from bzrlib.plugins.gtk.diff import DiffView, iter_changes_to_status
-
+from bzrlib import errors, tests
+from bzrlib.merge_directive import MergeDirective
+
+from bzrlib.plugins.gtk.diff import (
+ DiffController,
+ DiffView,
+ iter_changes_to_status,
+ MergeDirectiveController,
+ )
+eg_diff = """\
+=== modified file 'tests/test_diff.py'
+--- tests/test_diff.py 2008-03-11 13:18:28 +0000
++++ tests/test_diff.py 2008-05-08 22:44:02 +0000
+@@ -20,7 +20,11 @@
+
+ from bzrlib import tests
+
+-from bzrlib.plugins.gtk.diff import DiffView, iter_changes_to_status
++from bzrlib.plugins.gtk.diff import (
++ DiffController,
++ DiffView,
++ iter_changes_to_status,
++ )
+
+
+ class TestDiffViewSimple(tests.TestCase):
+"""
class TestDiffViewSimple(tests.TestCase):
@@ -69,6 +92,122 @@
)
+class MockDiffWidget(object):
+
+ def set_diff_text_sections(self, sections):
+ self.sections = list(sections)
+
+
+class MockWindow(object):
+ def __init__(self):
+ self.diff = MockDiffWidget()
+ self.merge_successful = False
+
+ def set_title(self, title):
+ self.title = title
+
+ def _get_save_path(self, basename):
+ return 'save-path'
+
+ def _get_merge_target(self):
+ return 'this'
+
+ def destroy(self):
+ pass
+
+ def _merge_successful(self):
+ self.merge_successful = True
+
+ def _conflicts(self):
+ self.conflicts = True
+
+ def _handle_error(self, e):
+ self.handled_error = e
+
+
+class TestDiffController(tests.TestCaseWithTransport):
+
+ def get_controller(self):
+ window = MockWindow()
+ return DiffController('load-path', eg_diff.splitlines(True), window)
+
+ def test_get_diff_sections(self):
+ controller = self.get_controller()
+ controller = DiffController('.', eg_diff.splitlines(True),
+ controller.window)
+ sections = list(controller.get_diff_sections())
+ self.assertEqual('Complete Diff', sections[0][0])
+ self.assertIs(None, sections[0][1])
+ self.assertEqual(eg_diff, sections[0][2])
+
+ self.assertEqual('tests/test_diff.py', sections[1][0])
+ self.assertEqual('tests/test_diff.py', sections[1][1])
+ self.assertEqual(''.join(eg_diff.splitlines(True)[1:]),
+ sections[1][2])
+
+ def test_initialize_window(self):
+ controller = self.get_controller()
+ controller.initialize_window(controller.window)
+ self.assertEqual(2, len(controller.window.diff.sections))
+ self.assertEqual('load-path - diff', controller.window.title)
+
+ def test_perform_save(self):
+ self.build_tree_contents([('load-path', 'foo')])
+ controller = self.get_controller()
+ controller.perform_save(None)
+ self.assertFileEqual('foo', 'save-path')
+
+
+class TestMergeDirectiveController(tests.TestCaseWithTransport):
+
+ def make_this_other_directive(self):
+ this = self.make_branch_and_tree('this')
+ this.commit('first commit')
+ other = this.bzrdir.sprout('other').open_workingtree()
+ self.build_tree_contents([('other/foo', 'bar')])
+ other.add('foo')
+ other.commit('second commit')
+ other.lock_write()
+ try:
+ directive = MergeDirective.from_objects(other.branch.repository,
+ other.last_revision(), 0,
+ 0, 'this')
+ finally:
+ other.unlock()
+ return this, other, directive
+
+ def make_merged_window(self, directive):
+ window = MockWindow()
+ controller = MergeDirectiveController('directive', directive, window)
+ controller.perform_merge(window)
+ return window
+
+ def test_perform_merge_success(self):
+ this, other, directive = self.make_this_other_directive()
+ window = self.make_merged_window(directive)
+ self.assertTrue(window.merge_successful)
+ self.assertEqual(other.last_revision(), this.get_parent_ids()[1])
+ self.assertFileEqual('bar', 'this/foo')
+
+ def test_perform_merge_conflicts(self):
+ this, other, directive = self.make_this_other_directive()
+ self.build_tree_contents([('this/foo', 'bar')])
+ this.add('foo')
+ this.commit('message')
+ window = self.make_merged_window(directive)
+ self.assertFalse(window.merge_successful)
+ self.assertTrue(window.conflicts)
+ self.assertEqual(other.last_revision(), this.get_parent_ids()[1])
+ self.assertFileEqual('bar', 'this/foo')
+
+ def test_perform_merge_uncommitted_changes(self):
+ this, other, directive = self.make_this_other_directive()
+ self.build_tree_contents([('this/foo', 'bar')])
+ this.add('foo')
+ window = self.make_merged_window(directive)
+ self.assertIsInstance(window.handled_error, errors.UncommittedChanges)
+
+
class Test_IterChangesToStatus(tests.TestCaseWithTransport):
def assertStatusEqual(self, expected, tree):
More information about the Pkg-bazaar-commits
mailing list