Rev 3546: Handle executable bit changes as well. in http://bzr.arbash-meinel.com/branches/bzr/1.7-dev/merge_lca_multi
John Arbash Meinel
john at arbash-meinel.com
Wed Jul 30 00:03:09 BST 2008
At http://bzr.arbash-meinel.com/branches/bzr/1.7-dev/merge_lca_multi
------------------------------------------------------------
revno: 3546
revision-id: john at arbash-meinel.com-20080729230216-xt8zje18edlwsnb7
parent: john at arbash-meinel.com-20080729221933-eecf0fzftxi014wc
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: merge_lca_multi
timestamp: Tue 2008-07-29 18:02:16 -0500
message:
Handle executable bit changes as well.
-------------- next part --------------
=== modified file 'bzrlib/merge.py'
--- a/bzrlib/merge.py 2008-07-29 22:19:33 +0000
+++ b/bzrlib/merge.py 2008-07-29 23:02:16 +0000
@@ -760,15 +760,13 @@
sha1_winner = Merge3Merger._lca_multi_way(
(base_ie.text_sha1, lca_sha1s),
other_ie.text_sha1, this_ie.text_sha1)
- # XXX: This should be tested before we include it, not
- # sure how to actually get a test written for this.
- # exec_winner = Merge3Merger._lca_multi_way(
- # (base_ie.executable, lca_executable),
- # other_ie.executable, this_ie.executable)
+ exec_winner = Merge3Merger._lca_multi_way(
+ (base_ie.executable, lca_executable),
+ other_ie.executable, this_ie.executable)
if (parent_id_winner == 'this' and name_winner == 'this'
- and sha1_winner == 'this'):
- # No kind, parent, name, content change for OTHER, so
- # this node is not considered interesting
+ and sha1_winner == 'this' and exec_winner == 'this'):
+ # No kind, parent, name, exec, or content change for
+ # OTHER, so this node is not considered interesting
continue
if sha1_winner == 'this':
content_changed = False
=== modified file 'bzrlib/tests/test_merge.py'
--- a/bzrlib/tests/test_merge.py 2008-07-29 22:19:33 +0000
+++ b/bzrlib/tests/test_merge.py 2008-07-29 23:02:16 +0000
@@ -1446,7 +1446,8 @@
self.addCleanup(builder.finish_series)
return builder
- def do_merge(self, builder, other_revision_id):
+ def get_wt_from_builder(self, builder):
+ """Get a real WorkingTree from the builder."""
the_branch = builder.get_branch()
wt = the_branch.bzrdir.create_workingtree()
# XXX: This is a little bit ugly, but we are holding the branch
@@ -1456,6 +1457,10 @@
wt._branch = the_branch
wt.lock_write()
self.addCleanup(wt.unlock)
+ return wt
+
+ def do_merge(self, builder, other_revision_id):
+ wt = self.get_wt_from_builder(builder)
merger = _mod_merge.Merger.from_revision_ids(progress.DummyProgress(),
wt, other_revision_id)
merger.merge_type = _mod_merge.Merge3Merger
@@ -1502,16 +1507,82 @@
builder.build_snapshot('D-id', ['B-id', 'C-id'], [])
wt, conflicts = self.do_merge(builder, 'F-id')
self.assertEqual(0, conflicts)
- # The merge should have simply update the contents of 'a'
+ # The merge should simply recognize that the final rename takes
+ # precedence
self.assertEqual('baz', wt.id2path('foo-id'))
+ def test_other_deletes_lca_renames(self):
+ # This test would cause a merge conflict, unless we use the lca trees
+ # to determine the real ancestry
+ # A Path at 'foo'
+ # / \
+ # B C Path renamed to 'bar' in B
+ # |\ /|
+ # | X |
+ # |/ \|
+ # D E Path at 'bar' in D and E
+ # |
+ # F F deletes 'bar'
+ builder = self.get_builder()
+ builder.build_snapshot('A-id', None,
+ [('add', (u'', 'a-root-id', 'directory', None)),
+ ('add', (u'foo', 'foo-id', 'file', 'a\nb\nc\n'))])
+ builder.build_snapshot('C-id', ['A-id'], [])
+ builder.build_snapshot('B-id', ['A-id'],
+ [('rename', ('foo', 'bar'))])
+ builder.build_snapshot('E-id', ['C-id', 'B-id'], # merge the rename
+ [('rename', ('foo', 'bar'))])
+ builder.build_snapshot('F-id', ['E-id'],
+ [('unversion', 'foo-id')])
+ builder.build_snapshot('D-id', ['B-id', 'C-id'], [])
+ wt, conflicts = self.do_merge(builder, 'F-id')
+ self.assertEqual(0, conflicts)
+ self.assertRaises(errors.NoSuchId, wt.id2path, 'foo-id')
+
+ def test_executable_changes(self):
+ # A Path at 'foo'
+ # / \
+ # B C
+ # |\ /|
+ # | X |
+ # |/ \|
+ # D E
+ # |
+ # F Executable bit changed
+ builder = self.get_builder()
+ builder.build_snapshot('A-id', None,
+ [('add', (u'', 'a-root-id', 'directory', None)),
+ ('add', (u'foo', 'foo-id', 'file', 'a\nb\nc\n'))])
+ builder.build_snapshot('C-id', ['A-id'], [])
+ builder.build_snapshot('B-id', ['A-id'], [])
+ builder.build_snapshot('D-id', ['B-id', 'C-id'], [])
+ builder.build_snapshot('E-id', ['C-id', 'B-id'], [])
+ # Have to use a real WT, because BranchBuilder doesn't support exec bit
+ wt = self.get_wt_from_builder(builder)
+ tt = transform.TreeTransform(wt)
+ try:
+ tt.set_executability(True, tt.trans_id_tree_file_id('foo-id'))
+ tt.apply()
+ except:
+ tt.finalize()
+ raise
+ self.assertTrue(wt.is_executable('foo-id'))
+ wt.commit('F-id', rev_id='F-id')
+ # Reset to D, so that we can merge F
+ wt.set_parent_ids(['D-id'])
+ wt.branch.set_last_revision_info(3, 'D-id')
+ wt.revert()
+ self.assertFalse(wt.is_executable('foo-id'))
+ conflicts = wt.merge_from_branch(wt.branch, to_revision='F-id')
+ self.assertEqual(0, conflicts)
+ self.assertTrue(wt.is_executable('foo-id'))
+
# TODO: cases to test
# simple criss-cross LCAS identical, BASE different
# x-x changed from BASE but identical for all LCAs and tips
# should be possible with the same trick of 'not-in-base'
# using a double criss-cross
- # x-x kind-change
# x-x LCAs differ, one in ancestry of other for a given file
# x-x file missing in LCA
# x-x Reverted back to BASE text
More information about the bazaar-commits
mailing list