Rev 5068: (vila) Resolve --take-this or --take-other correctly rename kept file in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Tue Mar 2 08:49:08 GMT 2010
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 5068 [merge]
revision-id: pqm at pqm.ubuntu.com-20100302084907-z4r0yoa4ldspjz82
parent: pqm at pqm.ubuntu.com-20100302064136-g8xdfe3r16ck5p6q
parent: v.ladeuil+lp at free.fr-20100302081739-pjqlb2hqw1lgnybn
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2010-03-02 08:49:07 +0000
message:
(vila) Resolve --take-this or --take-other correctly rename kept file
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/conflicts.py conflicts.py-20051001061850-78ef952ba63d2b42
bzrlib/tests/test_conflicts.py test_conflicts.py-20051006031059-e2dad9bbeaa5891f
=== modified file 'NEWS'
--- a/NEWS 2010-03-02 06:41:36 +0000
+++ b/NEWS 2010-03-02 08:17:39 +0000
@@ -79,6 +79,10 @@
* ``bzr remove-tree`` can now remove multiple working trees.
(Jared Hance, Andrew Bennetts, #253137)
+* ``bzr resolve --take-this`` and ``--take-other`` now correctly renames
+ the kept file on content conflicts where one side deleted the file.
+ (Vincent Ladeuil, #529968)
+
* ``bzr upgrade`` now names backup directory as ``backup.bzr.~N~`` instead
of ``backup.bzr``. This directory is ignored by bzr commands such as
``add``.
=== modified file 'bzrlib/conflicts.py'
--- a/bzrlib/conflicts.py 2010-02-23 07:43:11 +0000
+++ b/bzrlib/conflicts.py 2010-03-02 07:58:53 +0000
@@ -26,6 +26,7 @@
from bzrlib import (
builtins,
+ cleanup,
commands,
errors,
osutils,
@@ -479,16 +480,43 @@
def associated_filenames(self):
return [self.path + suffix for suffix in ('.BASE', '.OTHER')]
- # FIXME: I smell something weird here and it seems we should be able to be
- # more coherent with some other conflict ? bzr *did* a choice there but
- # neither action_take_this nor action_take_other reflect that...
- # -- vila 20091224
+ def _take_it(self, tt, suffix_to_remove):
+ """Resolve the conflict.
+
+ :param tt: The TreeTransform where the conflict is resolved.
+ :param suffix_to_remove: Either 'THIS' or 'OTHER'
+
+ The resolution is symmetric, when taking THIS, OTHER is deleted and
+ item.THIS is renamed into item and vice-versa.
+ """
+ try:
+ # Delete 'item.THIS' or 'item.OTHER' depending on
+ # suffix_to_remove
+ tt.delete_contents(
+ tt.trans_id_tree_path(self.path + '.' + suffix_to_remove))
+ except errors.NoSuchFile:
+ # There are valid cases where 'item.suffix_to_remove' either
+ # never existed or was already deleted (including the case
+ # where the user deleted it)
+ pass
+ # Rename 'item.suffix_to_remove' (note that if
+ # 'item.suffix_to_remove' has been deleted, this is a no-op)
+ this_tid = tt.trans_id_file_id(self.file_id)
+ parent_tid = tt.get_tree_parent(this_tid)
+ tt.adjust_path(self.path, parent_tid, this_tid)
+ tt.apply()
+
+ def _take_it_with_cleanups(self, tree, suffix_to_remove):
+ tt = transform.TreeTransform(tree)
+ op = cleanup.OperationWithCleanups(self._take_it)
+ op.add_cleanup(tt.finalize)
+ op.run_simple(tt, suffix_to_remove)
+
def action_take_this(self, tree):
- tree.remove([self.path + '.OTHER'], force=True, keep_files=False)
+ self._take_it_with_cleanups(tree, 'OTHER')
def action_take_other(self, tree):
- tree.remove([self.path], force=True, keep_files=False)
-
+ self._take_it_with_cleanups(tree, 'THIS')
# FIXME: TextConflict is about a single file-id, there never is a conflict_path
=== modified file 'bzrlib/tests/test_conflicts.py'
--- a/bzrlib/tests/test_conflicts.py 2010-02-23 07:43:11 +0000
+++ b/bzrlib/tests/test_conflicts.py 2010-03-02 07:38:15 +0000
@@ -18,15 +18,32 @@
import os
from bzrlib import (
+ branchbuilder,
bzrdir,
conflicts,
errors,
option,
tests,
+ workingtree,
)
from bzrlib.tests import script
+def load_tests(standard_tests, module, loader):
+ result = loader.suiteClass()
+
+ sp_tests, remaining_tests = tests.split_suite_by_condition(
+ standard_tests, tests.condition_isinstance((
+ TestResolveContentConflicts,
+ )))
+ tests.multiply_tests(sp_tests, content_conflict_scenarios(), result)
+
+ # No parametrization for the remaining tests
+ result.addTests(remaining_tests)
+
+ return result
+
+
# TODO: Test commit with some added, and added-but-missing files
# RBC 20060124 is that not tested in test_commit.py ?
@@ -69,15 +86,15 @@
('hello.sploo.OTHER', 'yellowworld2'),
])
tree.lock_read()
- self.assertEqual(6, len(list(tree.list_files())))
+ self.assertLength(6, list(tree.list_files()))
tree.unlock()
tree_conflicts = tree.conflicts()
- self.assertEqual(2, len(tree_conflicts))
+ self.assertLength(2, tree_conflicts)
self.assertTrue('hello' in tree_conflicts[0].path)
self.assertTrue('hello.sploo' in tree_conflicts[1].path)
conflicts.restore('hello')
conflicts.restore('hello.sploo')
- self.assertEqual(0, len(tree.conflicts()))
+ self.assertLength(0, tree.conflicts())
self.assertFileEqual('hello world2', 'hello')
self.assertFalse(os.path.lexists('hello.sploo'))
self.assertRaises(errors.NotConflicted, conflicts.restore, 'hello')
@@ -192,59 +209,99 @@
pass
-class TestResolveContentConflicts(TestResolveConflicts):
-
- # FIXME: We need to add the reverse case (delete in trunk, modify in
- # branch) but that could wait until the resolution mechanism is implemented.
-
- preamble = """
-$ bzr init trunk
-$ cd trunk
-$ echo 'trunk content' >file
-$ bzr add file
-$ bzr commit -m 'Create trunk'
-
-$ bzr branch . ../branch
-$ cd ../branch
-$ bzr rm file
-$ bzr commit -m 'Delete file'
-
-$ cd ../trunk
-$ echo 'more content' >>file
-$ bzr commit -m 'Modify file'
-
-$ cd ../branch
-$ bzr merge ../trunk
-2>+N file.OTHER
-2>Contents conflict in file
-2>1 conflicts encountered.
-"""
-
- def test_take_this(self):
- self.run_script("""
-$ bzr rm file.OTHER --force # a simple rm file.OTHER is valid too
-$ bzr resolve file
-$ bzr commit --strict -m 'No more conflicts nor unknown files'
-""")
-
- def test_take_other(self):
- self.run_script("""
-$ bzr mv file.OTHER file
-$ bzr resolve file
-$ bzr commit --strict -m 'No more conflicts nor unknown files'
-""")
+def content_conflict_scenarios():
+ return [('file,None', dict(_this_actions='modify_file',
+ _check_this='file_has_more_content',
+ _other_actions='delete_file',
+ _check_other='file_doesnt_exist',
+ )),
+ ('None,file', dict(_this_actions='delete_file',
+ _check_this='file_doesnt_exist',
+ _other_actions='modify_file',
+ _check_other='file_has_more_content',
+ )),
+ ]
+
+
+class TestResolveContentConflicts(tests.TestCaseWithTransport):
+
+ # Set by load_tests
+ this_actions = None
+ other_actions = None
+
+ def setUp(self):
+ super(TestResolveContentConflicts, self).setUp()
+ builder = self.make_branch_builder('trunk')
+ builder.start_series()
+ # Create an empty trunk
+ builder.build_snapshot('start', None, [
+ ('add', ('', 'root-id', 'directory', ''))])
+ # Add a minimal base content
+ builder.build_snapshot('base', ['start'], [
+ ('add', ('file', 'file-id', 'file', 'trunk content\n'))])
+ # Modify the base content in branch
+ other_actions = self._get_actions(self._other_actions)
+ builder.build_snapshot('other', ['base'], other_actions())
+ # Modify the base content in trunk
+ this_actions = self._get_actions(self._this_actions)
+ builder.build_snapshot('this', ['base'], this_actions())
+ builder.finish_series()
+ self.builder = builder
+
+ def _get_actions(self, name):
+ return getattr(self, 'do_%s' % name)
+
+ def _get_check(self, name):
+ return getattr(self, 'check_%s' % name)
+
+ def do_modify_file(self):
+ return [('modify', ('file-id', 'trunk content\nmore content\n'))]
+
+ def check_file_has_more_content(self):
+ self.assertFileEqual('trunk content\nmore content\n', 'branch/file')
+
+ def do_delete_file(self):
+ return [('unversion', 'file-id')]
+
+ def check_file_doesnt_exist(self):
+ self.failIfExists('branch/file')
+
+ def _merge_other_into_this(self):
+ b = self.builder.get_branch()
+ wt = b.bzrdir.sprout('branch').open_workingtree()
+ wt.merge_from_branch(b, 'other')
+ return wt
+
+ def assertConflict(self, wt, ctype, **kwargs):
+ confs = wt.conflicts()
+ self.assertLength(1, confs)
+ c = confs[0]
+ self.assertIsInstance(c, ctype)
+ sentinel = object() # An impossible value
+ for k, v in kwargs.iteritems():
+ self.assertEqual(v, getattr(c, k, sentinel))
+
+ def check_resolved(self, wt, item, action):
+ conflicts.resolve(wt, [item], action=action)
+ # Check that we don't have any conflicts nor unknown left
+ self.assertLength(0, wt.conflicts())
+ self.assertLength(0, list(wt.unknowns()))
def test_resolve_taking_this(self):
- self.run_script("""
-$ bzr resolve --take-this file
-$ bzr commit --strict -m 'No more conflicts nor unknown files'
-""")
+ wt = self._merge_other_into_this()
+ self.assertConflict(wt, conflicts.ContentsConflict,
+ path='file', file_id='file-id',)
+ self.check_resolved(wt, 'file', 'take_this')
+ check_this = self._get_check(self._check_this)
+ check_this()
def test_resolve_taking_other(self):
- self.run_script("""
-$ bzr resolve --take-other file
-$ bzr commit --strict -m 'No more conflicts nor unknown files'
-""")
+ wt = self._merge_other_into_this()
+ self.assertConflict(wt, conflicts.ContentsConflict,
+ path='file', file_id='file-id',)
+ self.check_resolved(wt, 'file', 'take_other')
+ check_other = self._get_check(self._check_other)
+ check_other()
class TestResolveDuplicateEntry(TestResolveConflicts):
@@ -255,6 +312,7 @@
$ echo 'trunk content' >file
$ bzr add file
$ bzr commit -m 'Create trunk'
+
$ echo 'trunk content too' >file2
$ bzr add file2
$ bzr commit -m 'Add file2 in trunk'
@@ -314,6 +372,7 @@
$ mkdir dir
$ bzr add dir
$ bzr commit -m 'Create trunk'
+
$ echo 'trunk content' >dir/file
$ bzr add dir/file
$ bzr commit -m 'Add dir/file in trunk'
@@ -354,6 +413,7 @@
$ echo 'trunk content' >dir/file
$ bzr add
$ bzr commit -m 'Create trunk'
+
$ echo 'trunk content' >dir/file2
$ bzr add dir/file2
$ bzr commit -m 'Add dir/file2 in branch'
@@ -415,6 +475,7 @@
$ echo 'trunk content' >dir/file
$ bzr add
$ bzr commit -m 'Create trunk'
+
$ bzr rm dir/file --force
$ bzr rm dir --force
$ bzr commit -m 'Remove dir/file'
@@ -474,6 +535,7 @@
$ echo 'Boo!' >file
$ bzr add
$ bzr commit -m 'Create trunk'
+
$ bzr mv file file-in-trunk
$ bzr commit -m 'Renamed to file-in-trunk'
@@ -522,6 +584,7 @@
$ bzr mkdir dir1
$ bzr mkdir dir2
$ bzr commit -m 'Create trunk'
+
$ bzr mv dir2 dir1
$ bzr commit -m 'Moved dir2 into dir1'
More information about the bazaar-commits
mailing list