Rev 4634: Merge more-tests into more-auto-resolvable-conflicts in file:///home/vila/src/bzr/experimental/conflict-manager/

Vincent Ladeuil v.ladeuil+lp at free.fr
Fri Nov 12 09:34:21 GMT 2010


At file:///home/vila/src/bzr/experimental/conflict-manager/

------------------------------------------------------------
revno: 4634 [merge]
revision-id: v.ladeuil+lp at free.fr-20101112093420-qo3p7d4anu0itoiw
parent: v.ladeuil+lp at free.fr-20101107165509-u0prupat7hihzcz9
parent: v.ladeuil+lp at free.fr-20101112093418-ges0dyaprq1lddwv
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: more-auto-resolvable-conflicts
timestamp: Fri 2010-11-12 10:34:20 +0100
message:
  Merge more-tests into more-auto-resolvable-conflicts
modified:
  bzrlib/cmd_test_script.py      cmd_test_script.py-20101020120519-7hst41avona524nn-1
  bzrlib/commit.py               commit.py-20050511101309-79ec1a0168e0e825
  bzrlib/conflicts.py            conflicts.py-20051001061850-78ef952ba63d2b42
  bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
  bzrlib/tests/blackbox/test_resolve.py test_resolve.py-20101103145514-ygpa369r69hhxsmi-1
  bzrlib/tests/blackbox/test_script.py test_script.py-20101013135628-rw9f11dgkgx09fnq-1
  bzrlib/tests/blackbox/test_tags.py test_tags.py-20070116132048-5h4qak2cm22jlb9e-1
  bzrlib/tests/script.py         script.py-20090901081155-yk3tiy1nunxg16ne-1
  bzrlib/tests/test_conflicts.py test_conflicts.py-20051006031059-e2dad9bbeaa5891f
  bzrlib/tests/test_script.py    test_script.py-20090901081156-y90z4w2t62fv7e7b-1
  bzrlib/transform.py            transform.py-20060105172343-dd99e54394d91687
  doc/developers/testing.txt     testing.txt-20080812140359-i70zzh6v2z7grqex-1
  doc/en/release-notes/bzr-2.2.txt bzr2.2.txt-20101008081016-21wd86gpfhllpue3-39
  doc/en/release-notes/bzr-2.3.txt NEWS-20050323055033-4e00b5db738777ff
  doc/en/whats-new/whats-new-in-2.3.txt whatsnewin2.3.txt-20100818072501-x2h25r7jbnknvy30-1
  setup.py                       setup.py-20050314065409-02f8a0a6e3f9bc70
-------------- next part --------------
=== modified file 'bzrlib/cmd_test_script.py'
--- a/bzrlib/cmd_test_script.py	2010-11-05 20:54:32 +0000
+++ b/bzrlib/cmd_test_script.py	2010-11-08 10:53:53 +0000
@@ -16,13 +16,16 @@
 
 """Front-end command for shell-like test scripts.
 
-See developers/testing.html for more explanations.
+See doc/developers/testing.txt for more explanations.
 This module should be importable even if testtools aren't available.
 """
 
 import os
 
-from bzrlib import commands
+from bzrlib import (
+    commands,
+    option,
+    )
 
 
 class cmd_test_script(commands.Command):
@@ -30,9 +33,13 @@
 
     hidden = True
     takes_args = ['infile']
+    takes_options = [
+        option.Option('null-output',
+                       help='Null command outputs match any output.'),
+        ]
 
     @commands.display_command
-    def run(self, infile):
+    def run(self, infile, null_output=False):
         # local imports to defer testtools dependency
         from bzrlib import tests
         from bzrlib.tests.script import TestCaseWithTransportAndScript
@@ -48,7 +55,8 @@
             script = None # Set before running
 
             def test_it(self):
-                self.run_script(script)
+                self.run_script(script,
+                                null_output_matches_anything=null_output)
 
         runner = tests.TextTestRunner(stream=self.outf)
         test = Test('test_it')

=== modified file 'bzrlib/commit.py'
--- a/bzrlib/commit.py	2010-10-15 16:43:03 +0000
+++ b/bzrlib/commit.py	2010-11-10 02:01:33 +0000
@@ -380,7 +380,9 @@
         self.pb_stage_count = 0
         self.pb_stage_total = 5
         if self.bound_branch:
-            self.pb_stage_total += 1
+            # 2 extra stages: "Uploading data to master branch" and "Merging
+            # tags to master branch"
+            self.pb_stage_total += 2
         self.pb.show_pct = False
         self.pb.show_spinner = False
         self.pb.show_eta = False
@@ -450,6 +452,15 @@
         # and now do the commit locally.
         self.branch.set_last_revision_info(new_revno, self.rev_id)
 
+        # Merge local tags to remote
+        if self.bound_branch:
+            self._set_progress_stage("Merging tags to master branch")
+            tag_conflicts = self.branch.tags.merge_to(self.master_branch.tags)
+            if tag_conflicts:
+                warning_lines = ['    ' + name for name, _, _ in tag_conflicts]
+                note("Conflicting tags in bound branch:\n" +
+                    "\n".join(warning_lines))
+
         # Make the working tree be up to date with the branch. This
         # includes automatic changes scheduled to be made to the tree, such
         # as updating its basis and unversioning paths that were missing.

=== modified file 'bzrlib/conflicts.py'
--- a/bzrlib/conflicts.py	2010-11-07 16:09:43 +0000
+++ b/bzrlib/conflicts.py	2010-11-10 16:24:31 +0000
@@ -626,6 +626,37 @@
     def associated_filenames(self):
         return [self.path + suffix for suffix in CONFLICT_SUFFIXES]
 
+    def _resolve(self, tt, winner_suffix):
+        """Resolve the conflict by copying one of .THIS or .OTHER into file.
+
+        :param tt: The TreeTransform where the conflict is resolved.
+        :param winner_suffix: Either 'THIS' or 'OTHER'
+
+        The resolution is symmetric, when taking THIS, item.THIS is renamed
+        into item and vice-versa. This takes one of the files as a whole
+        ignoring every difference that could have been merged cleanly.
+        """
+        # To avoid useless copies, we switch item and item.winner_suffix, only
+        # item will exist after the conflict has been resolved anyway.
+        item_tid = tt.trans_id_file_id(self.file_id)
+        item_parent_tid = tt.get_tree_parent(item_tid)
+        winner_path = self.path + '.' + winner_suffix
+        winner_tid = tt.trans_id_tree_path(winner_path)
+        winner_parent_tid = tt.get_tree_parent(winner_tid)
+        # Switch the paths to preserve the content
+        tt.adjust_path(self.path, winner_parent_tid, winner_tid)
+        tt.adjust_path(winner_path, item_parent_tid, item_tid)
+        # Associate the file_id to the right content
+        tt.unversion_file(item_tid)
+        tt.version_file(self.file_id, winner_tid)
+        tt.apply()
+
+    def action_take_this(self, tree):
+        self._resolve_with_cleanups(tree, 'THIS')
+
+    def action_take_other(self, tree):
+        self._resolve_with_cleanups(tree, 'OTHER')
+
 
 class HandledConflict(Conflict):
     """A path problem that has been provisionally resolved.

=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py	2010-09-16 09:52:29 +0000
+++ b/bzrlib/osutils.py	2010-11-06 02:32:43 +0000
@@ -967,7 +967,6 @@
     # they tend to happen very early in startup when we can't check config
     # files etc, and also we want to report all failures but not spam the user
     # with 10 warnings.
-    from bzrlib import trace
     exception_str = str(exception)
     if exception_str not in _extension_load_failures:
         trace.mutter("failed to load compiled extension: %s" % exception_str)
@@ -1875,7 +1874,10 @@
         s = os.stat(src)
         chown(dst, s.st_uid, s.st_gid)
     except OSError, e:
-        trace.warning("Unable to copy ownership from '%s' to '%s': IOError: %s." % (src, dst, e))
+        trace.warning(
+            'Unable to copy ownership from "%s" to "%s". '
+            'You may want to set it manually.', src, dst)
+        trace.log_exception_quietly()
 
 
 def path_prefix_key(path):

=== modified file 'bzrlib/tests/blackbox/test_resolve.py'
--- a/bzrlib/tests/blackbox/test_resolve.py	2010-11-07 16:09:43 +0000
+++ b/bzrlib/tests/blackbox/test_resolve.py	2010-11-10 18:17:06 +0000
@@ -91,48 +91,3 @@
         self.build_tree_contents([('tree/file', 'a\n')])
         note = self.run_bzr('resolve', working_dir='tree')[1]
         self.assertContainsRe(note, 'All conflicts resolved.')
-
-
-class TestResolveSilentlyIgnore(script.TestCaseWithTransportAndScript):
-
-    def test_bug_646961(self):
-        self.run_script("""\
-            $ bzr init base
-            Created a standalone tree (format: 2a)
-            $ cd base
-            $ echo >file1
-            $ bzr add
-            adding file1
-            $ bzr ci -m "stuff"
-            2>Committing to: .../base/
-            2>added file1
-            2>Committed revision 1.
-            $ cd ..
-            $ bzr branch base branch
-            2>Branched 1 revision(s).
-            $ cd base
-            $ echo "1" >> file1
-            $ bzr ci -m "branch 1"
-            2>Committing to: .../base/
-            2>modified file1
-            2>Committed revision 2.
-            $ cd ../branch
-            $ echo "2" >> file1
-            $ bzr ci -m "branch 2"
-            2>Committing to: .../branch/
-            2>modified file1
-            2>Committed revision 2.
-            $ cd ../base
-            $ bzr merge ../branch
-            2> M  file1
-            2>Text conflict in file1
-            2>1 conflicts encountered.
-            # The following succeeds silently without resolving the conflict
-            $ bzr resolve file1 --take-other
-            2>0 conflict(s) resolved, 1 remaining
-            # The following wil fail when --take-other is implemented
-            # for text conflicts
-            $ bzr conflicts
-            Text conflict in file1
-            """)
-

=== modified file 'bzrlib/tests/blackbox/test_script.py'
--- a/bzrlib/tests/blackbox/test_script.py	2010-10-13 13:57:22 +0000
+++ b/bzrlib/tests/blackbox/test_script.py	2010-11-08 10:53:53 +0000
@@ -50,6 +50,16 @@
         self.assertEquals('OK', out_lines[-1])
         self.assertEquals('', err)
 
+    def test_null_output(self):
+        self.build_tree_contents([('script', '''
+$ echo hello world
+''')])
+        out, err = self.run_bzr(['test-script', 'script', '--null-output'])
+        out_lines = out.splitlines()
+        self.assertStartsWith(out_lines[-3], 'Ran 1 test in ')
+        self.assertEquals('OK', out_lines[-1])
+        self.assertEquals('', err)
+
     def test_failing_script(self):
         self.build_tree_contents([('script', '''
 $ echo hello foo

=== modified file 'bzrlib/tests/blackbox/test_tags.py'
--- a/bzrlib/tests/blackbox/test_tags.py	2010-10-11 15:18:38 +0000
+++ b/bzrlib/tests/blackbox/test_tags.py	2010-11-10 02:01:33 +0000
@@ -17,6 +17,7 @@
 """Tests for commands related to tags"""
 
 from bzrlib import (
+    branchbuilder,
     bzrdir,
     tag,
     )
@@ -24,7 +25,10 @@
     Branch,
     )
 from bzrlib.bzrdir import BzrDir
-from bzrlib.tests import TestCaseWithTransport
+from bzrlib.tests import (
+    script,
+    TestCaseWithTransport,
+    )
 from bzrlib.repository import (
     Repository,
     )
@@ -33,14 +37,6 @@
 
 class TestTagging(TestCaseWithTransport):
 
-    # as of 0.14, the default format doesn't do tags so we need to use a
-    # specific format
-
-    def make_branch_and_tree(self, relpath):
-        format = bzrdir.format_registry.make_bzrdir('dirstate-with-subtree')
-        return TestCaseWithTransport.make_branch_and_tree(self, relpath,
-            format=format)
-
     def test_tag_command_help(self):
         out, err = self.run_bzr('help tag')
         self.assertContainsRe(out, 'Create, remove or modify a tag')
@@ -123,6 +119,57 @@
         b3 = Branch.open('branch3')
         self.assertEquals(b3.tags.lookup_tag('tag1'), 'first-revid')
 
+    def make_master_and_checkout(self):
+        builder = self.make_branch_builder('master')
+        builder.build_commit(message='Initial commit.', rev_id='rev-1')
+        master = builder.get_branch()
+        child = master.create_checkout(self.get_url('child'))
+        return master, child
+
+    def make_fork(self, branch):
+        fork = branch.create_clone_on_transport(self.get_transport('fork'))
+        builder = branchbuilder.BranchBuilder(branch=fork)
+        builder.build_commit(message='Commit in fork.', rev_id='fork-1')
+        return fork
+
+    def test_commit_in_heavyweight_checkout_copies_tags_to_master(self):
+        master, child = self.make_master_and_checkout()
+        fork = self.make_fork(master)
+        fork.tags.set_tag('new-tag', fork.last_revision())
+        script.run_script(self, """
+            $ cd child
+            $ bzr merge ../fork
+            $ bzr commit -m "Merge fork."
+            2>Committing to: .../master/
+            2>Committed revision 2.
+            """, null_output_matches_anything=True)
+        # Merge copied the tag to child and commit propagated it to master
+        self.assertEqual(
+            {'new-tag': fork.last_revision()}, child.branch.tags.get_tag_dict())
+        self.assertEqual(
+            {'new-tag': fork.last_revision()}, master.tags.get_tag_dict())
+
+    def test_commit_in_heavyweight_checkout_reports_tag_conflict(self):
+        master, child = self.make_master_and_checkout()
+        fork = self.make_fork(master)
+        fork.tags.set_tag('new-tag', fork.last_revision())
+        master_r1 = master.last_revision()
+        master.tags.set_tag('new-tag', master_r1)
+        script.run_script(self, """
+            $ cd child
+            $ bzr merge ../fork
+            $ bzr commit -m "Merge fork."
+            2>Committing to: .../master/
+            2>Conflicting tags in bound branch:
+            2>    new-tag
+            2>Committed revision 2.
+            """, null_output_matches_anything=True)
+        # Merge copied the tag to child.  master's conflicting tag is unchanged.
+        self.assertEqual(
+            {'new-tag': fork.last_revision()}, child.branch.tags.get_tag_dict())
+        self.assertEqual(
+            {'new-tag': master_r1}, master.tags.get_tag_dict())
+
     def test_list_tags(self):
         tree1 = self.make_branch_and_tree('branch1')
         tree1.commit(allow_pointless=True, message='revision 1',

=== modified file 'bzrlib/tests/script.py'
--- a/bzrlib/tests/script.py	2010-10-28 00:06:59 +0000
+++ b/bzrlib/tests/script.py	2010-11-08 09:58:04 +0000
@@ -196,7 +196,7 @@
         self.output_checker = doctest.OutputChecker()
         self.check_options = doctest.ELLIPSIS
 
-    def run_script(self, test_case, text):
+    def run_script(self, test_case, text, null_output_matches_anything=False):
         """Run a shell-like script as a test.
 
         :param test_case: A TestCase instance that should provide the fail(),
@@ -204,7 +204,12 @@
             attribute used as a jail root.
 
         :param text: A shell-like script (see _script_to_commands for syntax).
+
+        :param null_output_matches_anything: For commands with no specified
+            output, ignore any output that does happen, including output on
+            standard error.
         """
+        self.null_output_matches_anything = null_output_matches_anything
         for cmd, input, output, error in _script_to_commands(text):
             self.run_command(test_case, cmd, input, output, error)
 
@@ -245,6 +250,12 @@
             else:
                 test_case.fail('expected output: %r, but found nothing'
                             % (expected,))
+
+        null_output_matches_anything = getattr(
+            self, 'null_output_matches_anything', False)
+        if null_output_matches_anything and expected is None:
+            return
+
         expected = expected or ''
         matching = self.output_checker.check_output(
             expected, actual, self.check_options)
@@ -473,8 +484,9 @@
         super(TestCaseWithMemoryTransportAndScript, self).setUp()
         self.script_runner = ScriptRunner()
 
-    def run_script(self, script):
-        return self.script_runner.run_script(self, script)
+    def run_script(self, script, null_output_matches_anything=False):
+        return self.script_runner.run_script(self, script, 
+                   null_output_matches_anything=null_output_matches_anything)
 
     def run_command(self, cmd, input, output, error):
         return self.script_runner.run_command(self, cmd, input, output, error)
@@ -502,14 +514,16 @@
         super(TestCaseWithTransportAndScript, self).setUp()
         self.script_runner = ScriptRunner()
 
-    def run_script(self, script):
-        return self.script_runner.run_script(self, script)
+    def run_script(self, script, null_output_matches_anything=False):
+        return self.script_runner.run_script(self, script,
+                   null_output_matches_anything=null_output_matches_anything)
 
     def run_command(self, cmd, input, output, error):
         return self.script_runner.run_command(self, cmd, input, output, error)
 
 
-def run_script(test_case, script_string):
+def run_script(test_case, script_string, null_output_matches_anything=False):
     """Run the given script within a testcase"""
-    return ScriptRunner().run_script(test_case, script_string)
+    return ScriptRunner().run_script(test_case, script_string,
+               null_output_matches_anything=null_output_matches_anything)
 

=== modified file 'bzrlib/tests/test_conflicts.py'
--- a/bzrlib/tests/test_conflicts.py	2010-11-07 16:55:09 +0000
+++ b/bzrlib/tests/test_conflicts.py	2010-11-12 09:34:20 +0000
@@ -26,26 +26,13 @@
     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((
-                TestParametrizedResolveConflicts,
-                )))
-    # Each test class defines its own scenarios. This is needed for
-    # TestResolvePathConflictBefore531967 that verifies that the same tests as
-    # TestResolvePathConflict still pass.
-    for test in tests.iter_suite_tests(sp_tests):
-        tests.apply_scenarios(test, test.scenarios(), result)
-
-    # No parametrization for the remaining tests
-    result.addTests(remaining_tests)
-
-    return result
+from bzrlib.tests import (
+    script,
+    scenarios,
+    )
+
+
+load_tests = scenarios.load_tests_apply_scenarios
 
 
 # TODO: Test commit with some added, and added-but-missing files
@@ -210,11 +197,6 @@
         self.run_script(self.preamble)
 
 
-class TestResolveTextConflicts(TestResolveConflicts):
-    # TBC
-    pass
-
-
 def mirror_scenarios(base_scenarios):
     """Return a list of mirrored scenarios.
 
@@ -293,34 +275,31 @@
     _this = None
     _other = None
 
-    @staticmethod
-    def scenarios():
-        """Return the scenario list for the conflict type defined by the class.
-
-        Each scenario is of the form:
-        (common, (left_name, left_dict), (right_name, right_dict))
-
-        * common is a dict
-
-        * left_name and right_name are the scenario names that will be combined
-
-        * left_dict and right_dict are the attributes specific to each half of
-          the scenario. They should include at least 'actions' and 'check' and
-          will be available as '_this' and '_other' test instance attributes.
-
-        Daughters classes are free to add their specific attributes as they see
-        fit in any of the three dicts.
-
-        This is a class method so that load_tests can find it.
-
-        '_base_actions' in the common dict, 'actions' and 'check' in the left
-        and right dicts use names that map to methods in the test classes. Some
-        prefixes are added to these names to get the correspong methods (see
-        _get_actions() and _get_check()). The motivation here is to avoid
-        collisions in the class namespace.
-        """
-        # Only concrete classes return actual scenarios
-        return []
+    scenarios = []
+    """The scenario list for the conflict type defined by the class.
+
+    Each scenario is of the form:
+    (common, (left_name, left_dict), (right_name, right_dict))
+
+    * common is a dict
+
+    * left_name and right_name are the scenario names that will be combined
+
+    * left_dict and right_dict are the attributes specific to each half of
+      the scenario. They should include at least 'actions' and 'check' and
+      will be available as '_this' and '_other' test instance attributes.
+
+    Daughters classes are free to add their specific attributes as they see
+    fit in any of the three dicts.
+
+    This is a class method so that load_tests can find it.
+
+    '_base_actions' in the common dict, 'actions' and 'check' in the left
+    and right dicts use names that map to methods in the test classes. Some
+    prefixes are added to these names to get the correspong methods (see
+    _get_actions() and _get_check()). The motivation here is to avoid
+    collisions in the class namespace.
+    """
 
     def setUp(self):
         super(TestParametrizedResolveConflicts, self).setUp()
@@ -388,18 +367,61 @@
         check_other()
 
 
+class TestResolveTextConflicts(TestParametrizedResolveConflicts):
+
+    _conflict_type = conflicts.TextConflict
+
+    # Set by the scenarios
+    # path and file-id for the file involved in the conflict
+    _path = None
+    _file_id = None
+
+    scenarios = mirror_scenarios(
+        [
+            # File modified/deleted
+            (dict(_base_actions='create_file',
+                  _path='file', _file_id='file-id'),
+             ('filed_modified_A',
+              dict(actions='modify_file_A', check='file_has_content_A')),
+             ('file_modified_B',
+              dict(actions='modify_file_B', check='file_has_content_B')),),
+            ])
+
+    def do_create_file(self):
+        return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
+
+    def do_modify_file_A(self):
+        return [('modify', ('file-id', 'trunk content\nfeature A\n'))]
+
+    def do_modify_file_B(self):
+        return [('modify', ('file-id', 'trunk content\nfeature B\n'))]
+
+    def check_file_has_content_A(self):
+        self.assertFileEqual('trunk content\nfeature A\n', 'branch/file')
+
+    def check_file_has_content_B(self):
+        self.assertFileEqual('trunk content\nfeature B\n', 'branch/file')
+
+    def _get_resolve_path_arg(self, wt, action):
+        return self._path
+
+    def assertTextConflict(self, wt, c):
+        self.assertEqual(self._file_id, c.file_id)
+        self.assertEqual(self._path, c.path)
+    _assert_conflict = assertTextConflict
+
+
 class TestResolveContentsConflict(TestParametrizedResolveConflicts):
 
-    _conflict_type = conflicts.ContentsConflict,
+    _conflict_type = conflicts.ContentsConflict
 
-    # Set by load_tests from scenarios()
+    # Set by the scenarios
     # path and file-id for the file involved in the conflict
     _path = None
     _file_id = None
 
-    @staticmethod
-    def scenarios():
-        base_scenarios = [
+    scenarios = mirror_scenarios(
+        [
             # File modified/deleted
             (dict(_base_actions='create_file',
                   _path='file', _file_id='file-id'),
@@ -407,8 +429,7 @@
               dict(actions='modify_file', check='file_has_more_content')),
              ('file_deleted',
               dict(actions='delete_file', check='file_doesnt_exist')),),
-            ]
-        return mirror_scenarios(base_scenarios)
+            ])
 
     def do_create_file(self):
         return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
@@ -436,17 +457,16 @@
 
 class TestResolvePathConflict(TestParametrizedResolveConflicts):
 
-    _conflict_type = conflicts.PathConflict,
+    _conflict_type = conflicts.PathConflict
 
     def do_nothing(self):
         return []
 
-    @staticmethod
-    def scenarios():
-        # Each side dict additionally defines:
-        # - path path involved (can be '<deleted>')
-        # - file-id involved
-        base_scenarios = [
+    # Each side dict additionally defines:
+    # - path path involved (can be '<deleted>')
+    # - file-id involved
+    scenarios = mirror_scenarios(
+        [
             # File renamed/deleted
             (dict(_base_actions='create_file'),
              ('file_renamed',
@@ -483,8 +503,7 @@
              ('dir_renamed2',
               dict(actions='rename_dir2', check='dir_renamed2',
                    path='new-dir2', file_id='dir-id')),),
-        ]
-        return mirror_scenarios(base_scenarios)
+            ])
 
     def do_create_file(self):
         return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
@@ -568,14 +587,10 @@
 
 class TestResolveDuplicateEntry(TestParametrizedResolveConflicts):
 
-    _conflict_type = conflicts.DuplicateEntry,
+    _conflict_type = conflicts.DuplicateEntry
 
-    @staticmethod
-    def scenarios():
-        # Each side dict additionally defines:
-        # - path involved
-        # - file-id involved
-        base_scenarios = [
+    scenarios = mirror_scenarios(
+        [
             # File created with different file-ids
             (dict(_base_actions='nothing'),
              ('filea_created',
@@ -584,8 +599,7 @@
              ('fileb_created',
               dict(actions='create_file_b', check='file_content_b',
                    path='file', file_id='file-b-id')),),
-            ]
-        return mirror_scenarios(base_scenarios)
+            ])
 
     def do_nothing(self):
         return []
@@ -794,19 +808,18 @@
 
 class TestResolveParentLoop(TestParametrizedResolveConflicts):
 
-    _conflict_type = conflicts.ParentLoop,
+    _conflict_type = conflicts.ParentLoop
 
     _this_args = None
     _other_args = None
 
-    @staticmethod
-    def scenarios():
-        # Each side dict additionally defines:
-        # - dir_id: the directory being moved
-        # - target_id: The target directory
-        # - xfail: whether the test is expected to fail if the action is
-        #     involved as 'other'
-        base_scenarios = [
+    # Each side dict additionally defines:
+    # - dir_id: the directory being moved
+    # - target_id: The target directory
+    # - xfail: whether the test is expected to fail if the action is
+    #   involved as 'other'
+    scenarios = mirror_scenarios(
+        [
             # Dirs moved into each other
             (dict(_base_actions='create_dir1_dir2'),
              ('dir1_into_dir2',
@@ -823,8 +836,7 @@
              ('dir3_into_dir2',
               dict(actions='move_dir3_into_dir2', check='dir3_4_moved',
                    dir_id='dir3-id', target_id='dir2-id', xfail=True))),
-            ]
-        return mirror_scenarios(base_scenarios)
+            ])
 
     def do_create_dir1_dir2(self):
         return [('add', ('dir1', 'dir1-id', 'directory', '')),

=== modified file 'bzrlib/tests/test_script.py'
--- a/bzrlib/tests/test_script.py	2010-10-27 23:27:41 +0000
+++ b/bzrlib/tests/test_script.py	2010-11-08 09:58:04 +0000
@@ -186,6 +186,14 @@
             $ echo foo
             """)
 
+    def test_null_output_matches_option(self):
+        """If you want null output to be a wild card, you can pass 
+        null_output_matches_anything to run_script"""
+        self.run_script(
+            """
+            $ echo foo
+            """, null_output_matches_anything=True)
+
     def test_ellipsis_everything(self):
         """A simple ellipsis matches everything."""
         self.run_script("""

=== modified file 'bzrlib/transform.py'
--- a/bzrlib/transform.py	2010-11-07 15:56:46 +0000
+++ b/bzrlib/transform.py	2010-11-10 16:24:31 +0000
@@ -130,7 +130,7 @@
             self._new_root = self.trans_id_tree_file_id(root_id)
         else:
             self._new_root = None
-        # Indictor of whether the transform has been applied
+        # Indicator of whether the transform has been applied
         self._done = False
         # A progress bar
         self._pb = pb

=== modified file 'doc/developers/testing.txt'
--- a/doc/developers/testing.txt	2010-11-05 20:54:32 +0000
+++ b/doc/developers/testing.txt	2010-11-08 09:58:04 +0000
@@ -367,8 +367,9 @@
 The execution stops as soon as an expected output or an expected error is not
 matched.
 
-When no output is specified, any ouput from the command is accepted
-and execution continue.
+If output occurs and no output is expected, the execution stops and the
+test fails.  If unexpected output occurs on the standard error, then
+execution stops and the test fails.
 
 If an error occurs and no expected error is specified, the execution stops.
 
@@ -447,11 +448,11 @@
     def test_unshelve_keep(self):
         # some setup here
         script.run_script(self, '''
-            $ bzr add file
-            $ bzr shelve --all -m Foo
+            $ bzr add -q file
+            $ bzr shelve -q --all -m Foo
             $ bzr shelve --list
             1: Foo
-            $ bzr unshelve --keep
+            $ bzr unshelve -q --keep
             $ bzr shelve --list
             1: Foo
             $ cat file
@@ -471,6 +472,19 @@
             yes
             """)
 
+To avoid having to specify "-q" for all commands whose output is
+irrelevant, the run_script() method may be passed the keyword argument
+``null_output_matches_anything=True``.  For example::
+
+    def test_ignoring_null_output(self):
+        self.run_script("""
+            $ bzr init
+            $ bzr ci -m 'first revision' --unchanged
+            $ bzr log --line
+            1: ...
+            """, null_output_matches_anything=True)
+           
+
 Import tariff tests
 -------------------
 

=== modified file 'doc/en/release-notes/bzr-2.2.txt'
--- a/doc/en/release-notes/bzr-2.2.txt	2010-10-22 02:45:15 +0000
+++ b/doc/en/release-notes/bzr-2.2.txt	2010-11-10 02:01:33 +0000
@@ -19,9 +19,36 @@
 Bug Fixes
 *********
 
+* ``bzr resolve --take-other <file>`` will not crash anymore if ``<file>``
+  is involved in a text conflict (but the conflict is still not
+  resolved). (Vincent Ladeuil, #646961)
+
+* Commit in a bound branch or heavyweight checkout now propagates tags
+  (e.g. from a merge) to the master branch (and informs the user if there
+  is a conflict).  (Andrew Bennetts, #603395)
+  
+* Correctly set the Content-Type header when http POSTing to comply
+  with stricter web frameworks. (Vincent Ladeuil, #655100)
+
+* ``NotBranchError`` no longer allows errors from calling
+  ``bzrdir.open_repository()`` to propagate.  This is unhelpful at best,
+  and at worst can trigger infinite loops in callers.  (Andrew Bennetts)
+  
+* Skip tests that needs a bzr source tree when there isn't one. This is
+  needed to succesfully run the test suite for installed versions.
+  (Vincent Ladeuil, #644855).
+
+* Skip the tests that requires respecting the chmod bits when running as
+  root. Including the one that wasn't present in 2.1.
+  (Vincent Ladeuil, #646133)
+
 * Using bzr with `lp:` urls behind an http proxy should work.
   (Robert Collins, #558343)
 
+* Windows installers no longer requires the Microsoft vcredist to be
+  installed.
+  (Martin [gz], Gary van der Merwe, #632465)
+
 Improvements
 ************
 
@@ -44,14 +71,6 @@
 * Fix tests that failed when run under ``LANG=C``.
   (Andrew Bennetts, #632387)
 
-* Skip tests that needs a bzr source tree when there isn't one. This is
-  needed to succesfully run the test suite for installed versions.
-  (Vincent Ladeuil, #644855).
-
-* Skip the tests that requires respecting the chmod bits when running as
-  root. Including the one that wasn't present in 2.1.
-  (Vincent Ladeuil, #646133)
-
 
 bzr 2.2.1
 #########

=== modified file 'doc/en/release-notes/bzr-2.3.txt'
--- a/doc/en/release-notes/bzr-2.3.txt	2010-11-07 16:55:09 +0000
+++ b/doc/en/release-notes/bzr-2.3.txt	2010-11-12 09:34:20 +0000
@@ -31,6 +31,11 @@
   options matching a given regular expression is now controlled via the
   ``--all`` option.  (Vincent Ladeuil, bug #670251)
 
+* ``bzr resolve`` now accepts ``--take-this`` and ``--take-other`` actions
+  for text conflicts. This *replace* the whole file with the content
+  designated by the action. This will *ignore* all differences that would
+  have been merge cleanly otherwise. (Vincent Ladeuil, #638451)
+
 * ``bzr resolve`` now reports the number of conflicts resolved and the
   number of remaining conflicts. This provides a better feedback about the
   whole resolution process. (Vincent Ladeuil)
@@ -41,6 +46,9 @@
 .. Fixes for situations where bzr would previously crash or give incorrect
    or undesirable results.
 
+* Better message if there is an error while setting ownership of
+  ``.bazaar`` directory. (Parth Malwankar, #657553)
+
 * ``bzr resolve --take-other <file>`` will not crash anymore if ``<file>``
   is involved in a text conflict (but the conflict is still not
   resolved). (Vincent Ladeuil, #646961)
@@ -71,6 +79,11 @@
    suite.  This can include new facilities for writing tests, fixes to 
    spurious test failures and changes to the way things should be tested.
 
+* Add a null_output_matches_anything keyword argument with default False to
+  bzrlib.tests.script.ScriptRunner.run_script to specify that the command
+  output should not be checked (as opposed to expecting an empty output).
+  (Neil Martinsen-Burrell, #662509)
+
 * Blank output section in scriptrunner tests no longer match any output.
   Instead, use '...' as a wildcard if you don't care about the output.
   (Martin Pool, #637830)

=== modified file 'doc/en/whats-new/whats-new-in-2.3.txt'
--- a/doc/en/whats-new/whats-new-in-2.3.txt	2010-11-07 16:09:43 +0000
+++ b/doc/en/whats-new/whats-new-in-2.3.txt	2010-11-10 16:24:31 +0000
@@ -111,6 +111,12 @@
   default behaviour is specified (if needed) by setting the variable to
   ``conflict``.  (Vincent Ladeuil, #323111)
 
+* ``bzr resolve --take-this`` and ``bzr resolve --take-other`` can now be
+  used for text conflicts. This will ignore the differences that was merged
+  cleanly and replace the file with its content in the current branch
+  (``--take-this``) or with its content in the merged branch
+  (``--take-other``). (Vincent Ladeuil, #638451)
+
 * ``bzr resolve`` now provides more feedback about the conflicts just
   resolved and the remaining ones. (Vincent Ladeuil)
 

=== modified file 'setup.py'
--- a/setup.py	2010-11-06 10:55:58 +0000
+++ b/setup.py	2010-11-10 11:15:50 +0000
@@ -692,7 +692,8 @@
     dll_excludes.extend(["MSWSOCK.dll",
                          "MSVCP60.dll",
                          "MSVCP90.dll",
-                         "powrprof.dll"])
+                         "powrprof.dll",
+                         "SHFOLDER.dll"])
     options_list = {"py2exe": {"packages": packages + list(additional_packages),
                                "includes": includes,
                                "excludes": excludes,



More information about the bazaar-commits mailing list