Rev 5053: (vila) Merge 2.1 into 2.2 including fixes for #262450, #373898, in file:///home/pqm/archives/thelove/bzr/2.2/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Thu Apr 15 17:46:52 BST 2010
At file:///home/pqm/archives/thelove/bzr/2.2/
------------------------------------------------------------
revno: 5053 [merge]
revision-id: pqm at pqm.ubuntu.com-20100415164645-foqjrnwr68mv4miw
parent: pqm at pqm.ubuntu.com-20100414084133-ka1xi7y837y85x85
parent: v.ladeuil+lp at free.fr-20100415145017-3jhbks4pqlm8r3tj
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: 2.2
timestamp: Thu 2010-04-15 17:46:45 +0100
message:
(vila) Merge 2.1 into 2.2 including fixes for #262450, #373898,
#498409
added:
bzrlib/tests/commands/test_revert.py test_revert.py-20100309150314-zqzie40mnu7vcfhg-1
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/lock.py lock.py-20050527050856-ec090bb51bc03349
bzrlib/merge.py merge.py-20050513021216-953b65a438527106
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/commands/__init__.py __init__.py-20070520095518-ecfl8531fxgjeycj-1
bzrlib/tests/per_workingtree/test_merge_from_branch.py test_merge_from_bran-20060904034200-12jxyk2zlhpufxe1-1
bzrlib/transport/__init__.py transport.py-20050711165921-4978aa7ce1285ad5
doc/developers/testing.txt testing.txt-20080812140359-i70zzh6v2z7grqex-1
=== modified file 'NEWS'
--- a/NEWS 2010-04-14 04:26:53 +0000
+++ b/NEWS 2010-04-15 14:50:17 +0000
@@ -792,12 +792,34 @@
tests that 'failed' - they're all just failures.
(Martin Pool)
+bzr 2.0.6
+#########
+
+:2.0.6: NOT RELEASED YET
+
+Bug Fixes
+*********
+
+* ``bzr revert`` now only takes write lock on working tree, instead of on
+ both working tree and branch.
+ (Danny van Heumen, #498409)
+
+* ``bzr upgrade`` now creates the ``backup.bzr`` directory with the same
+ permissions as ``.bzr`` directory on a POSIX OS.
+ (Parth Malwankar, #262450)
+
+* Additional merges after an unrelated branch has been merged with its
+ history no longer crash when deleted files are involved.
+ (Vincent Ladeuil, John Arbash Meinel, #375898)
bzr 2.0.5
#########
-:Codename:
-:2.0.5: NOT RELEASED YET
+:2.0.5: 2010-03-23
+
+This fifth release in our 2.0 series addresses several user-inconvenience
+bugs. None are critical, but upgrading is recommended for all users on
+earlier 2.0 releases.
Bug Fixes
*********
@@ -826,9 +848,6 @@
* Handle renames correctly when there are files or directories that
differ only in case. (Chris Jones, Martin Pool, #368931)
-* Fixed CHM generation by moving the NEWS section template into
- a separate file. (Ian Clatworthy, #524184)
-
* If ``bzr push --create-prefix`` triggers an unexpected ``NoSuchFile``
error, report that error rather than failing with an unhelpful
``UnboundLocalError``.
@@ -848,6 +867,10 @@
* Added ``location-alias`` help topic.
(Andrew Bennetts, #337834)
+* Fixed CHM generation by moving the NEWS section template into
+ a separate file. (Ian Clatworthy, #524184)
+
+
bzr 2.0.4
#########
=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py 2010-04-13 09:19:53 +0000
+++ b/bzrlib/builtins.py 2010-04-15 14:50:17 +0000
@@ -4193,7 +4193,7 @@
def run(self, revision=None, no_backup=False, file_list=None,
forget_merges=None):
tree, file_list = tree_files(file_list)
- tree.lock_write()
+ tree.lock_tree_write()
self.add_cleanup(tree.unlock)
if forget_merges:
tree.set_parent_ids(tree.get_parent_ids()[:1])
=== modified file 'bzrlib/lock.py'
--- a/bzrlib/lock.py 2010-02-10 17:52:08 +0000
+++ b/bzrlib/lock.py 2010-04-15 14:50:17 +0000
@@ -84,7 +84,7 @@
return self.lock_url == other.lock_url and self.details == other.details
def __repr__(self):
- return '%s(%s%s)' % (self.__class__.__name__,
+ return '%s(%s, %s)' % (self.__class__.__name__,
self.lock_url, self.details)
=== modified file 'bzrlib/merge.py'
--- a/bzrlib/merge.py 2010-04-06 11:29:06 +0000
+++ b/bzrlib/merge.py 2010-04-15 14:50:17 +0000
@@ -1042,21 +1042,38 @@
other_root = self.tt.trans_id_file_id(other_root_file_id)
if other_root == self.tt.root:
return
+ if self.other_tree.inventory.root.file_id in self.this_tree.inventory:
+ # the other tree's root is a non-root in the current tree (as when
+ # a previously unrelated branch is merged into another)
+ return
try:
self.tt.final_kind(other_root)
+ other_root_is_present = True
except errors.NoSuchFile:
- return
- if self.this_tree.has_id(self.other_tree.inventory.root.file_id):
- # the other tree's root is a non-root in the current tree
- return
- self.reparent_children(self.other_tree.inventory.root, self.tt.root)
- self.tt.cancel_creation(other_root)
- self.tt.cancel_versioning(other_root)
-
- def reparent_children(self, ie, target):
- for thing, child in ie.children.iteritems():
+ # other_root doesn't have a physical representation. We still need
+ # to move any references to the actual root of the tree.
+ other_root_is_present = False
+ # 'other_tree.inventory.root' is not present in this tree. We are
+ # calling adjust_path for children which *want* to be present with a
+ # correct place to go.
+ for thing, child in self.other_tree.inventory.root.children.iteritems():
trans_id = self.tt.trans_id_file_id(child.file_id)
- self.tt.adjust_path(self.tt.final_name(trans_id), target, trans_id)
+ if not other_root_is_present:
+ # FIXME: Make final_kind returns None instead of raising
+ # NoSuchFile to avoid the ugly construct below -- vila 20100402
+ try:
+ self.tt.final_kind(trans_id)
+ # The item exist in the final tree and has a defined place
+ # to go already.
+ continue
+ except errors.NoSuchFile, e:
+ pass
+ # Move the item into the root
+ self.tt.adjust_path(self.tt.final_name(trans_id),
+ self.tt.root, trans_id)
+ if other_root_is_present:
+ self.tt.cancel_creation(other_root)
+ self.tt.cancel_versioning(other_root)
def write_modified(self, results):
modified_hashes = {}
=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py 2010-04-11 19:40:23 +0000
+++ b/bzrlib/tests/__init__.py 2010-04-15 14:50:17 +0000
@@ -4435,3 +4435,27 @@
return result
except ImportError:
pass
+
+class _PosixPermissionsFeature(Feature):
+
+ def _probe(self):
+ def has_perms():
+ # create temporary file and check if specified perms are maintained.
+ import tempfile
+
+ write_perms = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
+ f = tempfile.mkstemp(prefix='bzr_perms_chk_')
+ fd, name = f
+ os.close(fd)
+ os.chmod(name, write_perms)
+
+ read_perms = os.stat(name).st_mode & 0777
+ os.unlink(name)
+ return (write_perms == read_perms)
+
+ return (os.name == 'posix') and has_perms()
+
+ def feature_name(self):
+ return 'POSIX permissions support'
+
+posix_permissions_feature = _PosixPermissionsFeature()
=== modified file 'bzrlib/tests/commands/__init__.py'
--- a/bzrlib/tests/commands/__init__.py 2009-03-23 14:59:43 +0000
+++ b/bzrlib/tests/commands/__init__.py 2010-04-15 08:50:40 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2007 Canonical Ltd
+# Copyright (C) 2007-2010 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -41,6 +41,7 @@
'bzrlib.tests.commands.test_pull',
'bzrlib.tests.commands.test_push',
'bzrlib.tests.commands.test_update',
+ 'bzrlib.tests.commands.test_revert',
]
# add the tests for the sub modules
suite.addTests(loader.loadTestsFromModuleNames(testmod_names))
=== added file 'bzrlib/tests/commands/test_revert.py'
--- a/bzrlib/tests/commands/test_revert.py 1970-01-01 00:00:00 +0000
+++ b/bzrlib/tests/commands/test_revert.py 2010-04-15 14:50:17 +0000
@@ -0,0 +1,61 @@
+# Copyright (C) 2010 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+import os
+from bzrlib import (
+ branch,
+ builtins,
+ errors,
+ lock,
+ )
+from bzrlib.tests import (
+ transport_util,
+ TestCaseInTempDir,
+ )
+
+
+class TestRevert(TestCaseInTempDir):
+
+ def setUp(self):
+ super(TestRevert, self).setUp()
+
+ def test_revert_tree_write_lock_and_branch_read_lock(self):
+
+ # install lock hooks to find out about cmd_revert's locking actions
+ locks_acquired = []
+ locks_released = []
+ lock.Lock.hooks.install_named_hook('lock_acquired',
+ locks_acquired.append, None)
+ lock.Lock.hooks.install_named_hook('lock_released',
+ locks_released.append, None)
+
+ # execute the revert command (There is nothing to actually revert,
+ # but locks are acquired either way.)
+ revert = builtins.cmd_revert()
+ revert.run()
+
+ # make sure that only one lock is acquired and released.
+ self.assertLength(1, locks_acquired)
+ self.assertLength(1, locks_released)
+
+ # make sure that the nonces are the same, since otherwise
+ # this would not be the same lock.
+ self.assertEqual(locks_acquired[0].details, locks_released[0].details)
+
+ # make sure that the locks are checkout locks.
+ self.assertEndsWith(locks_acquired[0].lock_url, "/checkout/lock")
+ self.assertEndsWith(locks_released[0].lock_url, "/checkout/lock")
+
=== modified file 'bzrlib/tests/per_workingtree/test_merge_from_branch.py'
--- a/bzrlib/tests/per_workingtree/test_merge_from_branch.py 2009-07-10 07:14:02 +0000
+++ b/bzrlib/tests/per_workingtree/test_merge_from_branch.py 2010-04-01 14:06:48 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2006 Canonical Ltd
+# Copyright (C) 2006-2010 Canonical Ltd
# Authors: Robert Collins <robert.collins at canonical.com>
#
# This program is free software; you can redistribute it and/or modify
@@ -20,13 +20,14 @@
import os
from bzrlib import (
+ branchbuilder,
errors,
merge
)
-from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
-
-
-class TestMergeFromBranch(TestCaseWithWorkingTree):
+from bzrlib.tests import per_workingtree
+
+
+class TestMergeFromBranch(per_workingtree.TestCaseWithWorkingTree):
def create_two_trees_for_merging(self):
"""Create two trees that can be merged from.
@@ -114,3 +115,103 @@
self.tt.create_file('qux', trans_id)
this.merge_from_branch(other.branch, merge_type=QuxMerge)
self.assertEqual('qux', this.get_file_text('foo-id'))
+
+
+class TestMergedBranch(per_workingtree.TestCaseWithWorkingTree):
+
+ def make_branch_builder(self, relpath, format=None):
+ if format is None:
+ format = self.bzrdir_format
+ builder = branchbuilder.BranchBuilder(self.get_transport(),
+ format=format)
+ return builder
+
+ def make_inner_branch(self):
+ bld_inner = self.make_branch_builder('inner')
+ bld_inner.start_series()
+ bld_inner.build_snapshot(
+ '1', None,
+ [('add', ('', 'inner-root-id', 'directory', '')),
+ ('add', ('dir', 'dir-id', 'directory', '')),
+ ('add', ('dir/file1', 'file1-id', 'file', 'file1 content\n')),
+ ('add', ('file3', 'file3-id', 'file', 'file3 content\n')),
+ ])
+ bld_inner.build_snapshot(
+ '3', ['1'], [('modify', ('file3-id', 'new file3 contents\n')),])
+ bld_inner.build_snapshot(
+ '2', ['1'],
+ [('add', ('dir/file2', 'file2-id', 'file', 'file2 content\n')),
+ ])
+ bld_inner.finish_series()
+ br = bld_inner.get_branch()
+ return br
+
+ def assertTreeLayout(self, expected, tree):
+ tree.lock_read()
+ try:
+ actual = [e[0] for e in tree.list_files()]
+ # list_files doesn't guarantee order
+ actual = sorted(actual)
+ self.assertEqual(expected, actual)
+ finally:
+ tree.unlock()
+
+ def make_outer_tree(self):
+ outer = self.make_branch_and_tree('outer')
+ self.build_tree_contents([('outer/foo', 'foo')])
+ outer.add('foo', 'foo-id')
+ outer.commit('added foo')
+ inner = self.make_inner_branch()
+ outer.merge_from_branch(inner, to_revision='1', from_revision='null:')
+ outer.commit('merge inner branch')
+ outer.mkdir('dir-outer', 'dir-outer-id')
+ outer.move(['dir', 'file3'], to_dir='dir-outer')
+ outer.commit('rename imported dir and file3 to dir-outer')
+ return outer, inner
+
+ def test_file1_deleted_in_dir(self):
+ outer, inner = self.make_outer_tree()
+ outer.remove(['dir-outer/dir/file1'], keep_files=False)
+ outer.commit('delete file1')
+ outer.merge_from_branch(inner)
+ outer.commit('merge the rest')
+ self.assertTreeLayout(['dir-outer',
+ 'dir-outer/dir',
+ 'dir-outer/dir/file2',
+ 'dir-outer/file3',
+ 'foo'],
+ outer)
+
+ def test_file3_deleted_in_root(self):
+ # Reproduce bug #375898
+ outer, inner = self.make_outer_tree()
+ outer.remove(['dir-outer/file3'], keep_files=False)
+ outer.commit('delete file3')
+ outer.merge_from_branch(inner)
+ outer.commit('merge the rest')
+ self.assertTreeLayout(['dir-outer',
+ 'dir-outer/dir',
+ 'dir-outer/dir/file1',
+ 'dir-outer/dir/file2',
+ 'foo'],
+ outer)
+
+
+ def test_file3_in_root_conflicted(self):
+ outer, inner = self.make_outer_tree()
+ outer.remove(['dir-outer/file3'], keep_files=False)
+ outer.commit('delete file3')
+ nb_conflicts = outer.merge_from_branch(inner, to_revision='3')
+ self.assertEqual(4, nb_conflicts)
+ self.assertTreeLayout(['dir-outer',
+ 'dir-outer/dir',
+ 'dir-outer/dir/file1',
+ # Ideally th conflict helpers should be in
+ # dir-outer/dir but since we can't easily find
+ # back the file3 -> outer-dir/dir rename, root
+ # is good enough -- vila 20100401
+ 'file3.BASE',
+ 'file3.OTHER',
+ 'foo'],
+ outer)
+
=== modified file 'bzrlib/transport/__init__.py'
--- a/bzrlib/transport/__init__.py 2010-03-17 05:36:11 +0000
+++ b/bzrlib/transport/__init__.py 2010-04-15 14:50:17 +0000
@@ -1065,7 +1065,6 @@
# use mask to ensure that bits other than rwx are ignored.
stat = self.stat(from_relpath)
target.mkdir('.', stat.st_mode & 0777)
-
source.copy_tree_to_transport(target)
def copy_tree_to_transport(self, to_transport):
=== modified file 'doc/developers/testing.txt'
--- a/doc/developers/testing.txt 2010-03-18 06:25:23 +0000
+++ b/doc/developers/testing.txt 2010-04-15 14:50:17 +0000
@@ -458,25 +458,40 @@
Testing locking behaviour
-------------------------
-You may want to write tests that particular objects are or aren't locked
-during particular operations: see for example `bug 498409`__.
-
- __ https://launchpad.net/bugs/498409
-
-The `TestCase` base class registers hooks that record lock actions into
-``._lock_actions`` in this format::
-
- [
- ('acquired', LockResult(file:///tmp/testbzr-J2pcy2.tmp/.bzr/branch-lockc4au55ppz8wdym11z1aq)),
- ('released', LockResult(file:///tmp/testbzr-J2pcy2.tmp/.bzr/branch-lockc4au55ppz8wdym11z1aq)),
- ('acquired', LockResult(file:///tmp/testbzr-J2pcy2.tmp/.bzr/repository/lockyxb3rn4sw1oyx1jzkt45)),
- ('released', LockResult(file:///tmp/testbzr-J2pcy2.tmp/.bzr/repository/lockyxb3rn4sw1oyx1jzkt45)),
- ('acquired', LockResult(file:///tmp/testbzr-J2pcy2.tmp/.bzr/branch/lockh8c6t28rcjdkgxtndbje)),
- ('released', LockResult(file:///tmp/testbzr-J2pcy2.tmp/.bzr/branch/lockh8c6t28rcjdkgxtndbje)),
- ...
-
-Alternatively you can register your own hooks to make custom assertions:
-see `TestCase._check_locks` for an example.
+In order to test the locking behaviour of commands, it is possible to install
+a hook that is called when a write lock is: acquired, released or broken.
+(Read locks also exist, they cannot be discovered in this way.)
+
+A hook can be installed by calling bzrlib.lock.Lock.hooks.install_named_hook.
+The three valid hooks are: `lock_acquired`, `lock_released` and `lock_broken`.
+
+Example::
+
+ locks_acquired = []
+ locks_released = []
+
+ lock.Lock.hooks.install_named_hook('lock_acquired',
+ locks_acquired.append, None)
+ lock.Lock.hooks.install_named_hook('lock_released',
+ locks_released.append, None)
+
+`locks_acquired` will now receive a LockResult instance for all locks acquired
+since the time the hook is installed.
+
+The last part of the `lock_url` allows you to identify the type of object that is locked.
+
+- BzrDir: `/branch-lock`
+- Working tree: `/checkout/lock`
+- Branch: `/branch/lock`
+- Repository: `/repository/lock`
+
+To test if a lock is a write lock on a working tree, one can do the following::
+
+ self.assertEndsWith(locks_acquired[0].lock_url, "/checkout/lock")
+
+See bzrlib/tests/commands/test_revert.py for an example of how to use this for
+testing locks.
+
Skipping tests
--------------
More information about the bazaar-commits
mailing list