Rev 4857: (andrew) Merge lp:bzr/2.0 into lp:bzr. in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Thu Dec 3 05:08:08 GMT 2009
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 4857 [merge]
revision-id: pqm at pqm.ubuntu.com-20091203050805-s70sybyrsrbbs10c
parent: pqm at pqm.ubuntu.com-20091203015454-c4ya8tkb3o084ae3
parent: andrew.bennetts at canonical.com-20091203022454-m2gyhbcdqi1t7ujz
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2009-12-03 05:08:05 +0000
message:
(andrew) Merge lp:bzr/2.0 into lp:bzr.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/merge.py merge.py-20050513021216-953b65a438527106
bzrlib/push.py push.py-20080606021927-5fe39050e8xne9un-1
bzrlib/tests/blackbox/test_push.py test_push.py-20060329002750-929af230d5d22663
bzrlib/tests/per_workingtree/test_content_filters.py test_content_filters-20080424071441-8navsrmrfdxpn90a-1
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
=== modified file 'NEWS'
--- a/NEWS 2009-12-02 18:10:32 +0000
+++ b/NEWS 2009-12-03 02:24:54 +0000
@@ -104,7 +104,13 @@
Bug Fixes
*********
-* Fix for shell completion and short options. (Benoît PIERRE)
+
+* ``bzr push --use-existing-dir`` no longer crashes if the directory
+ exists but contains an invalid ``.bzr`` directory.
+ (Andrew Bennetts, #423563)
+
+* Content filters are now applied correctly after pull, merge and switch.
+ (Ian Clatworthy, #385879)
* Improve "Binary files differ" hunk handling. (Aaron Bentley, #436325)
@@ -344,6 +350,21 @@
start reading 'inventories', etc.) This can have a significant impact on
peak memory for initial copies (~200MB). (John Arbash Meinel)
+Improvements
+************
+
+Documentation
+*************
+
+API Changes
+***********
+
+Internals
+*********
+
+Testing
+*******
+
bzr 2.0.2
#########
=== modified file 'bzrlib/branch.py'
--- a/bzrlib/branch.py 2009-12-02 17:50:30 +0000
+++ b/bzrlib/branch.py 2009-12-03 02:24:54 +0000
@@ -1285,16 +1285,9 @@
# clone call. Or something. 20090224 RBC/spiv.
if revision_id is None:
revision_id = self.last_revision()
- try:
- dir_to = self.bzrdir.clone_on_transport(to_transport,
- revision_id=revision_id, stacked_on=stacked_on,
- create_prefix=create_prefix, use_existing_dir=use_existing_dir)
- except errors.FileExists:
- if not use_existing_dir:
- raise
- except errors.NoSuchFile:
- if not create_prefix:
- raise
+ dir_to = self.bzrdir.clone_on_transport(to_transport,
+ revision_id=revision_id, stacked_on=stacked_on,
+ create_prefix=create_prefix, use_existing_dir=use_existing_dir)
return dir_to.open_branch()
def create_checkout(self, to_location, revision_id=None,
=== modified file 'bzrlib/merge.py'
--- a/bzrlib/merge.py 2009-10-06 14:40:37 +0000
+++ b/bzrlib/merge.py 2009-12-03 02:24:54 +0000
@@ -1150,8 +1150,22 @@
self.tt.delete_contents(trans_id)
if file_id in self.other_tree:
# OTHER changed the file
+ wt = self.this_tree
+ if wt.supports_content_filtering():
+ # We get the path from the working tree if it exists.
+ # That fails though when OTHER is adding a file, so
+ # we fall back to the other tree to find the path if
+ # it doesn't exist locally.
+ try:
+ filter_tree_path = wt.id2path(file_id)
+ except errors.NoSuchId:
+ filter_tree_path = self.other_tree.id2path(file_id)
+ else:
+ # Skip the id2path lookup for older formats
+ filter_tree_path = None
transform.create_from_tree(self.tt, trans_id,
- self.other_tree, file_id)
+ self.other_tree, file_id,
+ filter_tree_path=filter_tree_path)
if not file_in_this:
self.tt.version_file(file_id, trans_id)
return "modified"
@@ -1244,12 +1258,26 @@
('THIS', self.this_tree, this_lines)]
if not no_base:
data.append(('BASE', self.base_tree, base_lines))
+
+ # We need to use the actual path in the working tree of the file here,
+ # ignoring the conflict suffixes
+ wt = self.this_tree
+ if wt.supports_content_filtering():
+ try:
+ filter_tree_path = wt.id2path(file_id)
+ except errors.NoSuchId:
+ # file has been deleted
+ filter_tree_path = None
+ else:
+ # Skip the id2path lookup for older formats
+ filter_tree_path = None
+
versioned = False
file_group = []
for suffix, tree, lines in data:
if file_id in tree:
trans_id = self._conflict_file(name, parent_id, tree, file_id,
- suffix, lines)
+ suffix, lines, filter_tree_path)
file_group.append(trans_id)
if set_version and not versioned:
self.tt.version_file(file_id, trans_id)
@@ -1257,11 +1285,12 @@
return file_group
def _conflict_file(self, name, parent_id, tree, file_id, suffix,
- lines=None):
+ lines=None, filter_tree_path=None):
"""Emit a single conflict file."""
name = name + '.' + suffix
trans_id = self.tt.create_path(name, parent_id)
- transform.create_from_tree(self.tt, trans_id, tree, file_id, lines)
+ transform.create_from_tree(self.tt, trans_id, tree, file_id, lines,
+ filter_tree_path)
return trans_id
def merge_executable(self, file_id, file_status):
=== modified file 'bzrlib/push.py'
--- a/bzrlib/push.py 2009-07-18 21:09:00 +0000
+++ b/bzrlib/push.py 2009-11-25 06:10:00 +0000
@@ -90,12 +90,19 @@
br_to = br_from.create_clone_on_transport(to_transport,
revision_id=revision_id, stacked_on=stacked_on,
create_prefix=create_prefix, use_existing_dir=use_existing_dir)
- except errors.FileExists:
+ except errors.FileExists, err:
+ if err.path.endswith('/.bzr'):
+ raise errors.BzrCommandError(
+ "Target directory %s already contains a .bzr directory, "
+ "but it is not valid." % (location,))
if not use_existing_dir:
raise errors.BzrCommandError("Target directory %s"
- " already exists, but does not have a valid .bzr"
+ " already exists, but does not have a .bzr"
" directory. Supply --use-existing-dir to push"
" there anyway." % location)
+ # This shouldn't occur, but if it does the FileExists error will be
+ # more informative than an UnboundLocalError for br_to.
+ raise
except errors.NoSuchFile:
if not create_prefix:
raise errors.BzrCommandError("Parent directory of %s"
=== modified file 'bzrlib/tests/blackbox/test_push.py'
--- a/bzrlib/tests/blackbox/test_push.py 2009-10-02 11:35:02 +0000
+++ b/bzrlib/tests/blackbox/test_push.py 2009-12-03 02:24:54 +0000
@@ -335,6 +335,17 @@
# The push should have created target/a
self.failUnlessExists('target/a')
+ def test_push_use_existing_into_empty_bzrdir(self):
+ """'bzr push --use-existing-dir' into a dir with an empty .bzr dir
+ fails.
+ """
+ tree = self.create_simple_tree()
+ self.build_tree(['target/', 'target/.bzr/'])
+ self.run_bzr_error(
+ ['Target directory ../target already contains a .bzr directory, '
+ 'but it is not valid.'],
+ 'push ../target --use-existing-dir', working_dir='tree')
+
def test_push_onto_repo(self):
"""We should be able to 'bzr push' into an existing bzrdir."""
tree = self.create_simple_tree()
=== modified file 'bzrlib/tests/per_workingtree/test_content_filters.py'
--- a/bzrlib/tests/per_workingtree/test_content_filters.py 2009-10-28 01:16:10 +0000
+++ b/bzrlib/tests/per_workingtree/test_content_filters.py 2009-10-28 23:34:13 +0000
@@ -18,7 +18,9 @@
import os
+from bzrlib.bzrdir import BzrDir
from bzrlib.filters import ContentFilter
+from bzrlib.switch import switch
from bzrlib.workingtree import WorkingTree
from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
@@ -83,6 +85,38 @@
bin_fileid = tree.path2id('file2.bin')
return tree, txt_fileid, bin_fileid
+ def create_cf_tree_with_two_revisions(self, txt_reader, txt_writer,
+ dir='.'):
+ tree = self.make_branch_and_tree(dir)
+ def _content_filter_stack(path=None, file_id=None):
+ if path.endswith('.txt'):
+ return [ContentFilter(txt_reader, txt_writer)]
+ else:
+ return []
+ tree._content_filter_stack = _content_filter_stack
+ self.build_tree_contents([
+ (dir + '/file1.txt', 'Foo Txt'),
+ (dir + '/file2.bin', 'Foo Bin'),
+ (dir + '/file3.txt', 'Bar Txt'),
+ ])
+ tree.add(['file1.txt', 'file2.bin', 'file3.txt'])
+ tree.commit('commit raw content')
+ fileid_1 = tree.path2id('file1.txt')
+ fileid_2 = tree.path2id('file2.bin')
+ fileid_3 = tree.path2id('file3.txt')
+ # Commit another revision with various changes. We make sure
+ # the change includes a modification, an addition and a deletion.
+ # Renames are more complex and need a separate set of tests later.
+ self.build_tree_contents([
+ (dir + '/file1.txt', 'Foo ROCKS!'),
+ (dir + '/file4.txt', 'Hello World'),
+ ])
+ tree.add(['file4.txt'])
+ tree.remove(['file3.txt'], keep_files=False)
+ tree.commit("change, add and rename stuff")
+ fileid_4 = tree.path2id('file4.txt')
+ return tree, fileid_1, fileid_2, fileid_3, fileid_4
+
def patch_in_content_filter(self):
# Patch in a custom, symmetric content filter stack. It's pretty gross
# that we need to monkey-patch a class method to do this, bit it's
@@ -222,6 +256,89 @@
# that will be expensive to compute, so it's acceptable to just return
# None.
+ def test_content_filtering_applied_on_pull(self):
+ # Create a source branch with two revisions
+ source, fileid_1, fileid_2, fileid_3, fileid_4 = \
+ self.create_cf_tree_with_two_revisions(txt_reader=None,
+ txt_writer=None, dir='source')
+ if not source.supports_content_filtering():
+ return
+ self.assertFileEqual("Foo ROCKS!", 'source/file1.txt')
+ self.assert_basis_content("Foo ROCKS!", source, fileid_1)
+
+ # Now patch in content filtering and branch from revision 1
+ self.patch_in_content_filter()
+ self.run_bzr('branch -r1 source target')
+ target = WorkingTree.open('target')
+ self.assert_basis_content("Foo Txt", target, fileid_1)
+ self.assertFileEqual("fOO tXT", 'target/file1.txt')
+ self.assert_basis_content("Foo Bin", target, fileid_2)
+ self.assertFileEqual("Foo Bin", 'target/file2.bin')
+ self.assert_basis_content("Bar Txt", target, fileid_3)
+ self.assertFileEqual("bAR tXT", 'target/file3.txt')
+
+ # Pull the latter change and check the target tree is updated
+ self.run_bzr('pull -d target')
+ self.assert_basis_content("Foo ROCKS!", target, fileid_1)
+ self.assertFileEqual("fOO rocks!", 'target/file1.txt')
+ self.assert_basis_content("Foo Bin", target, fileid_2)
+ self.assert_basis_content("Hello World", target, fileid_4)
+ self.assertFileEqual("hELLO wORLD", 'target/file4.txt')
+
+ def test_content_filtering_applied_on_merge(self):
+ # Create a source branch with two revisions
+ source, fileid_1, fileid_2, fileid_3, fileid_4 = \
+ self.create_cf_tree_with_two_revisions(txt_reader=None,
+ txt_writer=None, dir='source')
+ if not source.supports_content_filtering():
+ return
+ self.assert_basis_content("Foo ROCKS!", source, fileid_1)
+ self.assertFileEqual("Foo ROCKS!", 'source/file1.txt')
+ self.assert_basis_content("Foo Bin", source, fileid_2)
+ self.assert_basis_content("Hello World", source, fileid_4)
+ self.assertFileEqual("Hello World", 'source/file4.txt')
+
+ # Now patch in content filtering and branch from revision 1
+ self.patch_in_content_filter()
+ self.run_bzr('branch -r1 source target')
+ target = WorkingTree.open('target')
+ self.assert_basis_content("Foo Txt", target, fileid_1)
+ self.assertFileEqual("fOO tXT", 'target/file1.txt')
+ self.assertFileEqual("Foo Bin", 'target/file2.bin')
+ self.assertFileEqual("bAR tXT", 'target/file3.txt')
+
+ # Merge the latter change and check the target tree is updated
+ self.run_bzr('merge -d target source')
+ self.assertFileEqual("fOO rocks!", 'target/file1.txt')
+ self.assertFileEqual("hELLO wORLD", 'target/file4.txt')
+
+ # Commit the merge and check the right content is stored
+ target.commit("merge file1.txt changes from source")
+ self.assert_basis_content("Foo ROCKS!", target, fileid_1)
+ self.assert_basis_content("Hello World", target, fileid_4)
+
+ def test_content_filtering_applied_on_switch(self):
+ # Create a source branch with two revisions
+ source, fileid_1, fileid_2, fileid_3, fileid_4 = \
+ self.create_cf_tree_with_two_revisions(txt_reader=None,
+ txt_writer=None, dir='branch-a')
+ if not source.supports_content_filtering():
+ return
+
+ # Now patch in content filtering and branch from revision 1
+ self.patch_in_content_filter()
+ self.run_bzr('branch -r1 branch-a branch-b')
+
+ # Now create a lightweight checkout referring to branch-b
+ self.run_bzr('checkout --lightweight branch-b checkout')
+ self.assertFileEqual("fOO tXT", 'checkout/file1.txt')
+
+ # Switch it to branch-b and check the tree is updated
+ checkout_control_dir = BzrDir.open_containing('checkout')[0]
+ switch(checkout_control_dir, source.branch)
+ self.assertFileEqual("fOO rocks!", 'checkout/file1.txt')
+ self.assertFileEqual("hELLO wORLD", 'checkout/file4.txt')
+
def test_content_filtering_applied_on_revert_delete(self):
# Create a source branch with content filtering
source, txt_fileid, bin_fileid = self.create_cf_tree(
=== modified file 'bzrlib/transform.py'
--- a/bzrlib/transform.py 2009-11-10 19:45:43 +0000
+++ b/bzrlib/transform.py 2009-12-03 02:24:54 +0000
@@ -2430,8 +2430,14 @@
tt.create_directory(trans_id)
-def create_from_tree(tt, trans_id, tree, file_id, bytes=None):
- """Create new file contents according to tree contents."""
+def create_from_tree(tt, trans_id, tree, file_id, bytes=None,
+ filter_tree_path=None):
+ """Create new file contents according to tree contents.
+
+ :param filter_tree_path: the tree path to use to lookup
+ content filters to apply to the bytes output in the working tree.
+ This only applies if the working tree supports content filtering.
+ """
kind = tree.kind(file_id)
if kind == 'directory':
tt.create_directory(trans_id)
@@ -2442,6 +2448,11 @@
bytes = tree_file.readlines()
finally:
tree_file.close()
+ wt = tt._tree
+ if wt.supports_content_filtering() and filter_tree_path is not None:
+ filters = wt._content_filter_stack(filter_tree_path)
+ bytes = filtered_output_bytes(bytes, filters,
+ ContentFilterContext(filter_tree_path, tree))
tt.create_file(bytes, trans_id)
elif kind == "symlink":
tt.create_symlink(tree.get_symlink_target(file_id), trans_id)
More information about the bazaar-commits
mailing list