Rev 4431: (igc) fix branch & status content filtering issues in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Thu Jun 11 06:22:17 BST 2009


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 4431
revision-id: pqm at pqm.ubuntu.com-20090611052211-b6b2pu471mdja7zz
parent: pqm at pqm.ubuntu.com-20090611022914-p9nxmjfongc8w3va
parent: ian.clatworthy at canonical.com-20090611042353-c9f0zq2s8mab5ddq
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2009-06-11 06:22:11 +0100
message:
  (igc) fix branch & status content filtering issues
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/_dirstate_helpers_c.pyx dirstate_helpers.pyx-20070503201057-u425eni465q4idwn-3
  bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
  bzrlib/dirstate.py             dirstate.py-20060728012006-d6mvoihjb3je9peu-1
  bzrlib/tests/workingtree_implementations/test_content_filters.py test_content_filters-20080424071441-8navsrmrfdxpn90a-1
  bzrlib/tests/workingtree_implementations/test_eol_conversion.py test_eol_conversion.-20090327060429-todzdjmqt3bpv5r8-4
  bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
    ------------------------------------------------------------
    revno: 4427.1.2
    revision-id: ian.clatworthy at canonical.com-20090611042353-c9f0zq2s8mab5ddq
    parent: ian.clatworthy at canonical.com-20090610232948-srfxg31kurqa769c
    parent: ian.clatworthy at canonical.com-20090611042106-fvgk0ybjja0il4uy
    committer: Ian Clatworthy <ian.clatworthy at canonical.com>
    branch nick: integration
    timestamp: Thu 2009-06-11 14:23:53 +1000
    message:
      (igc) fix branch & status content filtering issues
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/_dirstate_helpers_c.pyx dirstate_helpers.pyx-20070503201057-u425eni465q4idwn-3
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
      bzrlib/dirstate.py             dirstate.py-20060728012006-d6mvoihjb3je9peu-1
      bzrlib/tests/workingtree_implementations/test_content_filters.py test_content_filters-20080424071441-8navsrmrfdxpn90a-1
      bzrlib/tests/workingtree_implementations/test_eol_conversion.py test_eol_conversion.-20090327060429-todzdjmqt3bpv5r8-4
      bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
    ------------------------------------------------------------
    revno: 4393.3.10
    revision-id: ian.clatworthy at canonical.com-20090611042106-fvgk0ybjja0il4uy
    parent: ian.clatworthy at canonical.com-20090611034744-m165w1ib895oxdr9
    committer: Ian Clatworthy <ian.clatworthy at canonical.com>
    branch nick: eol-bug
    timestamp: Thu 2009-06-11 14:21:06 +1000
    message:
      add test for non-filtered -> filtered branching
    modified:
      bzrlib/tests/workingtree_implementations/test_content_filters.py test_content_filters-20080424071441-8navsrmrfdxpn90a-1
    ------------------------------------------------------------
    revno: 4393.3.9
    revision-id: ian.clatworthy at canonical.com-20090611034744-m165w1ib895oxdr9
    parent: ian.clatworthy at canonical.com-20090611003808-zv1u2pbbdupoh1m5
    committer: Ian Clatworthy <ian.clatworthy at canonical.com>
    branch nick: eol-bug
    timestamp: Thu 2009-06-11 13:47:44 +1000
    message:
      add test for filtered -> non-filtered branching
    modified:
      bzrlib/tests/workingtree_implementations/test_content_filters.py test_content_filters-20080424071441-8navsrmrfdxpn90a-1
    ------------------------------------------------------------
    revno: 4393.3.8
    revision-id: ian.clatworthy at canonical.com-20090611003808-zv1u2pbbdupoh1m5
    parent: ian.clatworthy at canonical.com-20090610070348-dc6vfh15mk47n3x4
    committer: Ian Clatworthy <ian.clatworthy at canonical.com>
    branch nick: eol-bug
    timestamp: Thu 2009-06-11 10:38:08 +1000
    message:
      first tweak from jam's review
    modified:
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
    ------------------------------------------------------------
    revno: 4393.3.7
    revision-id: ian.clatworthy at canonical.com-20090610070348-dc6vfh15mk47n3x4
    parent: ian.clatworthy at canonical.com-20090610065649-onqtrn93x3ncw0v5
    committer: Ian Clatworthy <ian.clatworthy at canonical.com>
    branch nick: eol-bug
    timestamp: Wed 2009-06-10 17:03:48 +1000
    message:
      add NEWS entry
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
    ------------------------------------------------------------
    revno: 4393.3.6
    revision-id: ian.clatworthy at canonical.com-20090610065649-onqtrn93x3ncw0v5
    parent: ian.clatworthy at canonical.com-20090610064801-svrym90jssgsv9zn
    parent: pqm at pqm.ubuntu.com-20090610010249-5iyq9oics6tysru4
    committer: Ian Clatworthy <ian.clatworthy at canonical.com>
    branch nick: eol-bug
    timestamp: Wed 2009-06-10 16:56:49 +1000
    message:
      merge bzr.dev r4423
    removed:
      bzrlib/util/tests/test_bencode.py test_bencode.py-20070713042202-qjw8rppxaz7ky6i6-1
    added:
      bzrlib/_bencode_pyx.h          _bencode_pyx.h-20090604155331-53bg7d0udmrvz44n-1
      bzrlib/_bencode_pyx.pyx        bencode.pyx-20070806220735-j75g4ebfnado2i60-3
      bzrlib/benchmarks/bench_tags.py bench_tags.py-20070812104202-0q5i0mqkt72hubof-1
      bzrlib/bencode.py              bencode.py-20070806220735-j75g4ebfnado2i60-2
      bzrlib/tests/test_bencode.py   test_bencode.py-20070806225234-s51cnnkh6raytxti-1
      bzrlib/tests/test_chk_serializer.py test_chk_serializer.-20090515105921-urte9wnhknlj5dyp-1
      bzrlib/util/bencode.py         bencode.py-20090609141817-jtvhqq6vyryjoeky-1
    renamed:
      bzrlib/util/bencode.py => bzrlib/util/_bencode_py.py bencode.py-20070220044742-sltr28q21w2wzlxi-1
    modified:
      .bzrignore                     bzrignore-20050311232317-81f7b71efa2db11a
      Makefile                       Makefile-20050805140406-d96e3498bb61c5bb
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/_groupcompress_pyx.pyx  _groupcompress_c.pyx-20080724041824-yelg6ii7c7zxt4z0-1
      bzrlib/benchmarks/__init__.py  __init__.py-20060516064526-eb0d37c78e86065d
      bzrlib/branch.py               branch.py-20050309040759-e4baf4e0d046576e
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
      bzrlib/bundle/serializer/v4.py v10.py-20070611062757-5ggj7k18s9dej0fr-1
      bzrlib/bzrdir.py               bzrdir.py-20060131065624-156dfea39c4387cb
      bzrlib/cache_utf8.py           cache_utf8.py-20060810004311-x4cph46la06h9azm-1
      bzrlib/chk_serializer.py       chk_serializer.py-20081002064345-2tofdfj2eqq01h4b-1
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/foreign.py              foreign.py-20081112170002-olsxmandkk8qyfuq-1
      bzrlib/graph.py                graph_walker.py-20070525030359-y852guab65d4wtn0-1
      bzrlib/groupcompress.py        groupcompress.py-20080705181503-ccbxd6xuy1bdnrpu-8
      bzrlib/index.py                index.py-20070712131115-lolkarso50vjr64s-1
      bzrlib/inventory.py            inventory.py-20050309040759-6648b84ca2005b37
      bzrlib/lock.py                 lock.py-20050527050856-ec090bb51bc03349
      bzrlib/log.py                  log.py-20050505065812-c40ce11702fe5fb1
      bzrlib/mail_client.py          mail_client.py-20070809192806-vuxt3t19srtpjpdn-1
      bzrlib/multiparent.py          __init__.py-20070410133617-n1jdhcc1n1mibarp-1
      bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
      bzrlib/plugins/launchpad/test_register.py test_register.py-20060315182712-40f5dda945c829a8
      bzrlib/progress.py             progress.py-20050610070202-df9faaab791964c0
      bzrlib/python-compat.h         pythoncompat.h-20080924041409-9kvi0fgtuuqp743j-1
      bzrlib/reconcile.py            reweave_inventory.py-20051108164726-1e5e0934febac06e
      bzrlib/remote.py               remote.py-20060720103555-yeeg2x51vn0rbtdp-1
      bzrlib/repofmt/groupcompress_repo.py repofmt.py-20080715094215-wp1qfvoo7093c8qr-1
      bzrlib/repofmt/knitrepo.py     knitrepo.py-20070206081537-pyy4a00xdas0j4pf-1
      bzrlib/repofmt/pack_repo.py    pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
      bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
      bzrlib/serializer.py           serializer.py-20090402143702-wmkh9cfjhwpju0qi-1
      bzrlib/shelf.py                prepare_shelf.py-20081005181341-n74qe6gu1e65ad4v-1
      bzrlib/smart/medium.py         medium.py-20061103051856-rgu2huy59fkz902q-1
      bzrlib/smart/protocol.py       protocol.py-20061108035435-ot0lstk2590yqhzr-1
      bzrlib/smart/repository.py     repository.py-20061128022038-vr5wy5bubyb8xttk-1
      bzrlib/tag.py                  tag.py-20070212110532-91cw79inah2cfozx-1
      bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
      bzrlib/tests/blackbox/test_branch.py test_branch.py-20060524161337-noms9gmcwqqrfi8y-1
      bzrlib/tests/blackbox/test_export.py test_export.py-20051229024010-e6c26658e460fb1c
      bzrlib/tests/blackbox/test_push.py test_push.py-20060329002750-929af230d5d22663
      bzrlib/tests/branch_implementations/test_check.py test_check.py-20080429151303-1sbfclxhddpz0tnj-1
      bzrlib/tests/branch_implementations/test_reconcile.py test_reconcile.py-20080429161555-qlmccuyeyt6pvho7-1
      bzrlib/tests/branch_implementations/test_sprout.py test_sprout.py-20070521151739-b8t8p7axw1h966ws-1
      bzrlib/tests/inventory_implementations/basics.py basics.py-20070903044446-kdjwbiu1p1zi9phs-1
      bzrlib/tests/per_repository/test_fetch.py test_fetch.py-20070814052151-5cxha9slx4c93uog-1
      bzrlib/tests/per_repository/test_iter_reverse_revision_history.py test_iter_reverse_re-20070217015036-spu7j5ggch7pbpyd-1
      bzrlib/tests/per_repository/test_reconcile.py test_reconcile.py-20060223022332-572ef70a3288e369
      bzrlib/tests/per_repository/test_revision.py testrevprops.py-20051013073044-92bc3c68302ce1bf
      bzrlib/tests/per_repository_reference/test_fetch.py test_fetch.py-20090511214909-25pkgmoam913lrji-1
      bzrlib/tests/per_repository_reference/test_initialize.py test_initialize.py-20090527083941-4rz2urcthjet5e2i-1
      bzrlib/tests/test__groupcompress.py test__groupcompress_-20080724145854-koifwb7749cfzrvj-1
      bzrlib/tests/test_config.py    testconfig.py-20051011041908-742d0c15d8d8c8eb
      bzrlib/tests/test_foreign.py   test_foreign.py-20081125004048-ywb901edgp9lluxo-1
      bzrlib/tests/test_graph.py     test_graph_walker.py-20070525030405-enq4r60hhi9xrujc-1
      bzrlib/tests/test_http.py      testhttp.py-20051018020158-b2eef6e867c514d9
      bzrlib/tests/test_mail_client.py test_mail_client.py-20070809192806-vuxt3t19srtpjpdn-2
      bzrlib/tests/test_osutils.py   test_osutils.py-20051201224856-e48ee24c12182989
      bzrlib/tests/test_plugins.py   plugins.py-20050622075746-32002b55e5e943e9
      bzrlib/tests/test_progress.py  test_progress.py-20060308160359-978c397bc79b7fda
      bzrlib/tests/test_remote.py    test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
      bzrlib/tests/test_repository.py test_repository.py-20060131075918-65c555b881612f4d
      bzrlib/tests/test_serializer.py test_serializer.py-20090403213933-q6x117y8t9fbeyoz-1
      bzrlib/tests/test_smart.py     test_smart.py-20061122024551-ol0l0o0oofsu9b3t-2
      bzrlib/tests/test_source.py    test_source.py-20051207061333-a58dea6abecc030d
      bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
      bzrlib/tests/test_ui.py        test_ui.py-20051130162854-458e667a7414af09
      bzrlib/transform.py            transform.py-20060105172343-dd99e54394d91687
      bzrlib/transport/sftp.py       sftp.py-20051019050329-ab48ce71b7e32dfe
      bzrlib/ui/__init__.py          ui.py-20050824083933-8cf663c763ba53a9
      bzrlib/versionedfile.py        versionedfile.py-20060222045106-5039c71ee3b65490
      bzrlib/weave.py                knit.py-20050627021749-759c29984154256b
      setup.py                       setup.py-20050314065409-02f8a0a6e3f9bc70
      bzrlib/util/_bencode_py.py     bencode.py-20070220044742-sltr28q21w2wzlxi-1
    ------------------------------------------------------------
    revno: 4393.3.5
    revision-id: ian.clatworthy at canonical.com-20090610064801-svrym90jssgsv9zn
    parent: ian.clatworthy at canonical.com-20090610062332-gnzrrt3mcgnnf4lr
    committer: Ian Clatworthy <ian.clatworthy at canonical.com>
    branch nick: eol-bug
    timestamp: Wed 2009-06-10 16:48:01 +1000
    message:
      clean-up - just test status for now
    modified:
      bzrlib/tests/workingtree_implementations/test_eol_conversion.py test_eol_conversion.-20090327060429-todzdjmqt3bpv5r8-4
    ------------------------------------------------------------
    revno: 4393.3.4
    revision-id: ian.clatworthy at canonical.com-20090610062332-gnzrrt3mcgnnf4lr
    parent: ian.clatworthy at canonical.com-20090610045737-n7lw7iugfqwvb3rn
    committer: Ian Clatworthy <ian.clatworthy at canonical.com>
    branch nick: eol-bug
    timestamp: Wed 2009-06-10 16:23:32 +1000
    message:
      add eol roundtripping tests
    modified:
      bzrlib/tests/workingtree_implementations/test_eol_conversion.py test_eol_conversion.-20090327060429-todzdjmqt3bpv5r8-4
    ------------------------------------------------------------
    revno: 4393.3.3
    revision-id: ian.clatworthy at canonical.com-20090610045737-n7lw7iugfqwvb3rn
    parent: ian.clatworthy at canonical.com-20090609015210-82yzboxtvreic3xg
    committer: Ian Clatworthy <ian.clatworthy at canonical.com>
    branch nick: eol-bug
    timestamp: Wed 2009-06-10 14:57:37 +1000
    message:
      add round-trip checking to eol tests
    modified:
      bzrlib/tests/workingtree_implementations/test_eol_conversion.py test_eol_conversion.-20090327060429-todzdjmqt3bpv5r8-4
    ------------------------------------------------------------
    revno: 4393.3.2
    revision-id: ian.clatworthy at canonical.com-20090609015210-82yzboxtvreic3xg
    parent: ian.clatworthy at canonical.com-20090601085517-8ex4vw00ini524x9
    committer: Ian Clatworthy <ian.clatworthy at canonical.com>
    branch nick: eol-bug
    timestamp: Tue 2009-06-09 11:52:10 +1000
    message:
      fix pyrex version of _process_entry as well
    modified:
      bzrlib/_dirstate_helpers_c.pyx dirstate_helpers.pyx-20070503201057-u425eni465q4idwn-3
    ------------------------------------------------------------
    revno: 4393.3.1
    revision-id: ian.clatworthy at canonical.com-20090601085517-8ex4vw00ini524x9
    parent: pqm at pqm.ubuntu.com-20090530150110-c87w11jf6sqevh16
    committer: Ian Clatworthy <ian.clatworthy at canonical.com>
    branch nick: eol-bug
    timestamp: Mon 2009-06-01 18:55:17 +1000
    message:
      fix status & commit issue reported by Frits Jalvingh
    modified:
      bzrlib/dirstate.py             dirstate.py-20060728012006-d6mvoihjb3je9peu-1
      bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
=== modified file 'NEWS'
--- a/NEWS	2009-06-11 00:47:41 +0000
+++ b/NEWS	2009-06-11 05:22:11 +0000
@@ -81,6 +81,9 @@
   the fetched revisions, not in the stacked-on ancestry.
   (John Arbash Meinel)
 
+* Fix status and commit to work with content filtered trees, addressing
+  numerous bad bugs with line-ending support. (Ian Clatworthy, #362030)
+
 * Fix problem of "directory not empty" when contending for a lock over
   sftp.  (Martin Pool, #340352)
 

=== modified file 'bzrlib/_dirstate_helpers_c.pyx'
--- a/bzrlib/_dirstate_helpers_c.pyx	2009-03-23 14:59:43 +0000
+++ b/bzrlib/_dirstate_helpers_c.pyx	2009-06-09 01:52:10 +0000
@@ -1140,19 +1140,17 @@
                     if source_minikind != c'f':
                         content_change = 1
                     else:
-                        # If the size is the same, check the sha:
-                        if target_details[2] == source_details[2]:
-                            if link_or_sha1 is None:
-                                # Stat cache miss:
-                                statvalue, link_or_sha1 = \
-                                    self.state._sha1_provider.stat_and_sha1(
-                                    path_info[4])
-                                self.state._observed_sha1(entry, link_or_sha1,
-                                    statvalue)
-                            content_change = (link_or_sha1 != source_details[1])
-                        else:
-                            # Size changed, so must be different
-                            content_change = 1
+                        # Check the sha. We can't just rely on the size as
+                        # content filtering may mean differ sizes actually
+                        # map to the same content
+                        if link_or_sha1 is None:
+                            # Stat cache miss:
+                            statvalue, link_or_sha1 = \
+                                self.state._sha1_provider.stat_and_sha1(
+                                path_info[4])
+                            self.state._observed_sha1(entry, link_or_sha1,
+                                statvalue)
+                        content_change = (link_or_sha1 != source_details[1])
                     # Target details is updated at update_entry time
                     if self.use_filesystem_for_exec:
                         # We don't need S_ISREG here, because we are sure

=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py	2009-06-10 03:56:49 +0000
+++ b/bzrlib/builtins.py	2009-06-11 04:23:53 +0000
@@ -1112,6 +1112,9 @@
 
         accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
             from_location)
+        if (accelerator_tree is not None and
+            accelerator_tree.supports_content_filtering()):
+            accelerator_tree = None
         revision = _get_one_revision('branch', revision)
         br_from.lock_read()
         try:

=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py	2009-05-06 05:36:28 +0000
+++ b/bzrlib/dirstate.py	2009-06-01 08:55:17 +0000
@@ -3062,19 +3062,17 @@
                     if source_minikind != 'f':
                         content_change = True
                     else:
-                        # If the size is the same, check the sha:
-                        if target_details[2] == source_details[2]:
-                            if link_or_sha1 is None:
-                                # Stat cache miss:
-                                statvalue, link_or_sha1 = \
-                                    self.state._sha1_provider.stat_and_sha1(
-                                    path_info[4])
-                                self.state._observed_sha1(entry, link_or_sha1,
-                                    statvalue)
-                            content_change = (link_or_sha1 != source_details[1])
-                        else:
-                            # Size changed, so must be different
-                            content_change = True
+                        # Check the sha. We can't just rely on the size as
+                        # content filtering may mean differ sizes actually
+                        # map to the same content
+                        if link_or_sha1 is None:
+                            # Stat cache miss:
+                            statvalue, link_or_sha1 = \
+                                self.state._sha1_provider.stat_and_sha1(
+                                path_info[4])
+                            self.state._observed_sha1(entry, link_or_sha1,
+                                statvalue)
+                        content_change = (link_or_sha1 != source_details[1])
                     # Target details is updated at update_entry time
                     if self.use_filesystem_for_exec:
                         # We don't need S_ISREG here, because we are sure

=== modified file 'bzrlib/tests/workingtree_implementations/test_content_filters.py'
--- a/bzrlib/tests/workingtree_implementations/test_content_filters.py	2009-03-23 14:59:43 +0000
+++ b/bzrlib/tests/workingtree_implementations/test_content_filters.py	2009-06-11 04:21:06 +0000
@@ -17,6 +17,7 @@
 """Tests for content filtering conformance"""
 
 from bzrlib.filters import ContentFilter
+from bzrlib.workingtree import WorkingTree
 from bzrlib.tests.workingtree_implementations import TestCaseWithWorkingTree
 
 
@@ -44,8 +45,8 @@
 
 class TestWorkingTreeWithContentFilters(TestCaseWithWorkingTree):
 
-    def create_cf_tree(self, txt_reader, txt_writer):
-        tree = self.make_branch_and_tree('.')
+    def create_cf_tree(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)]
@@ -53,8 +54,8 @@
                 return []
         tree._content_filter_stack = _content_filter_stack
         self.build_tree_contents([
-            ('file1.txt', 'Foo Txt'),
-            ('file2.bin', 'Foo Bin')])
+            (dir + '/file1.txt', 'Foo Txt'),
+            (dir + '/file2.bin', 'Foo Bin')])
         tree.add(['file1.txt', 'file2.bin'])
         tree.commit('commit raw content')
         txt_fileid = tree.path2id('file1.txt')
@@ -104,3 +105,57 @@
             filtered=False).read())
         self.assertEqual('Foo Bin', tree.get_file(bin_fileid,
             filtered=False).read())
+
+    def test_branch_source_filtered_target_not(self):
+        # Create a source branch with content filtering
+        source, txt_fileid, bin_fileid = self.create_cf_tree(
+            txt_reader=_uppercase, txt_writer=_lowercase, dir='source')
+        if not source.supports_content_filtering():
+            return
+        self.assertFileEqual("Foo Txt", 'source/file1.txt')
+        basis = source.basis_tree()
+        basis.lock_read()
+        self.addCleanup(basis.unlock)
+        self.assertEqual("FOO TXT", basis.get_file_text(txt_fileid))
+
+        # Now branch it
+        self.run_bzr('branch source target')
+        target = WorkingTree.open('target')
+        # Even though the content in source and target are different
+        # due to different filters, iter_changes should be clean
+        self.assertFileEqual("FOO TXT", 'target/file1.txt')
+        changes = target.changes_from(source.basis_tree())
+        self.assertFalse(changes.has_changed())
+
+    def test_branch_source_not_filtered_target_is(self):
+        # Create a source branch with content filtering
+        source, txt_fileid, bin_fileid = self.create_cf_tree(
+            txt_reader=None, txt_writer=None, dir='source')
+        if not source.supports_content_filtering():
+            return
+        self.assertFileEqual("Foo Txt", 'source/file1.txt')
+        basis = source.basis_tree()
+        basis.lock_read()
+        self.addCleanup(basis.unlock)
+        self.assertEqual("Foo Txt", basis.get_file_text(txt_fileid))
+
+        # Patch in a custom, symmetric content filter stack
+        self.real_content_filter_stack = WorkingTree._content_filter_stack
+        def restore_real_content_filter_stack():
+            WorkingTree._content_filter_stack = self.real_content_filter_stack
+        self.addCleanup(restore_real_content_filter_stack)
+        def _content_filter_stack(tree, path=None, file_id=None):
+            if path.endswith('.txt'):
+                return [ContentFilter(_swapcase, _swapcase)]
+            else:
+                return []
+        WorkingTree._content_filter_stack = _content_filter_stack
+
+        # Now branch it
+        self.run_bzr('branch source target')
+        target = WorkingTree.open('target')
+        # Even though the content in source and target are different
+        # due to different filters, iter_changes should be clean
+        self.assertFileEqual("fOO tXT", 'target/file1.txt')
+        changes = target.changes_from(source.basis_tree())
+        self.assertFalse(changes.has_changed())

=== modified file 'bzrlib/tests/workingtree_implementations/test_eol_conversion.py'
--- a/bzrlib/tests/workingtree_implementations/test_eol_conversion.py	2009-04-02 04:12:11 +0000
+++ b/bzrlib/tests/workingtree_implementations/test_eol_conversion.py	2009-06-10 06:48:01 +0000
@@ -17,8 +17,9 @@
 """Tests for eol conversion."""
 
 import sys
+from cStringIO import StringIO
 
-from bzrlib import rules
+from bzrlib import rules, status
 from bzrlib.tests import TestSkipped
 from bzrlib.tests.workingtree_implementations import TestCaseWithWorkingTree
 from bzrlib.workingtree import WorkingTree
@@ -29,6 +30,13 @@
 _sample_text_on_win  = """hello\r\nworld\r\n"""
 _sample_text_on_unix = """hello\nworld\n"""
 _sample_binary       = """hello\nworld\r\n\x00"""
+_sample_clean_lf     = _sample_text_on_unix
+_sample_clean_crlf   = _sample_text_on_win
+
+
+# Lists of formats for each storage policy
+_LF_IN_REPO = ['native', 'lf', 'crlf']
+_CRLF_IN_REPO = [ '%s-with-crlf-in-repo' % (f,) for f in _LF_IN_REPO]
 
 
 class TestEolConversion(TestCaseWithWorkingTree):
@@ -74,8 +82,11 @@
         return t, basis
 
     def assertNewContentForSetting(self, wt, eol, expected_unix,
-        expected_win=None):
-        """Clone a working tree and check the convenience content."""
+        expected_win, roundtrip):
+        """Clone a working tree and check the convenience content.
+        
+        If roundtrip is True, status and commit should see no changes.
+        """
         if expected_win is None:
             expected_win = expected_unix
         self.patch_rules_searcher(eol)
@@ -86,100 +97,241 @@
             self.assertEqual(expected_win, content)
         else:
             self.assertEqual(expected_unix, content)
+        # Confirm that status thinks nothing has changed if the text roundtrips
+        if roundtrip:
+            status_io = StringIO()
+            status.show_tree_status(wt2, to_file=status_io)
+            self.assertEqual('', status_io.getvalue())
 
     def assertContent(self, wt, basis, expected_raw, expected_unix,
-        expected_win):
-        """Check the committed content and content in cloned trees."""
+        expected_win, roundtrip_to=None):
+        """Check the committed content and content in cloned trees.
+        
+        :param roundtrip_to: the set of formats (excluding exact) we
+          can round-trip to or None for all
+        """
         basis_content = basis.get_file('file1-id').read()
         self.assertEqual(expected_raw, basis_content)
-        self.assertNewContentForSetting(wt, None, expected_raw)
+
+        # No setting and exact should always roundtrip
+        self.assertNewContentForSetting(wt, None,
+            expected_raw, expected_raw, roundtrip=True)
+        self.assertNewContentForSetting(wt, 'exact',
+            expected_raw, expected_raw, roundtrip=True)
+
+        # Roundtripping is otherwise dependent on whether the original
+        # text is clean - mixed line endings will prevent it. It also
+        # depends on whether the format in the repository is being changed.
+        if roundtrip_to is None:
+            roundtrip_to = _LF_IN_REPO + _CRLF_IN_REPO
         self.assertNewContentForSetting(wt, 'native',
-            expected_unix, expected_win)
+            expected_unix, expected_win, 'native' in roundtrip_to)
         self.assertNewContentForSetting(wt, 'lf',
-            expected_unix, expected_unix)
+            expected_unix, expected_unix, 'lf' in roundtrip_to)
         self.assertNewContentForSetting(wt, 'crlf',
-            expected_win, expected_win)
+            expected_win, expected_win, 'crlf' in roundtrip_to)
         self.assertNewContentForSetting(wt, 'native-with-crlf-in-repo',
-            expected_unix, expected_win)
+            expected_unix, expected_win,
+            'native-with-crlf-in-repo' in roundtrip_to)
         self.assertNewContentForSetting(wt, 'lf-with-crlf-in-repo',
-            expected_unix, expected_unix)
+            expected_unix, expected_unix,
+            'lf-with-crlf-in-repo' in roundtrip_to)
         self.assertNewContentForSetting(wt, 'crlf-with-crlf-in-repo',
-            expected_win, expected_win)
-        self.assertNewContentForSetting(wt, 'exact', expected_raw)
-
-    def test_eol_no_rules(self):
-        wt, basis = self.prepare_tree(_sample_text)
-        self.assertContent(wt, basis, _sample_text,
-            _sample_text_on_unix, _sample_text_on_win)
-
-    def test_eol_native(self):
-        wt, basis = self.prepare_tree(_sample_text, eol='native')
-        self.assertContent(wt, basis, _sample_text_on_unix,
-            _sample_text_on_unix, _sample_text_on_win)
+            expected_win, expected_win,
+            'crlf-with-crlf-in-repo' in roundtrip_to)
+
+    # Test binary files. These always roundtrip.
+
+    def test_eol_no_rules_binary(self):
+        wt, basis = self.prepare_tree(_sample_binary)
+        self.assertContent(wt, basis, _sample_binary, _sample_binary,
+            _sample_binary)
+
+    def test_eol_exact_binary(self):
+        wt, basis = self.prepare_tree(_sample_binary, eol='exact')
+        self.assertContent(wt, basis, _sample_binary, _sample_binary,
+            _sample_binary)
 
     def test_eol_native_binary(self):
         wt, basis = self.prepare_tree(_sample_binary, eol='native')
         self.assertContent(wt, basis, _sample_binary, _sample_binary,
             _sample_binary)
 
-    def test_eol_lf(self):
-        wt, basis = self.prepare_tree(_sample_text, eol='lf')
-        self.assertContent(wt, basis, _sample_text_on_unix,
-            _sample_text_on_unix, _sample_text_on_win)
-
     def test_eol_lf_binary(self):
         wt, basis = self.prepare_tree(_sample_binary, eol='lf')
         self.assertContent(wt, basis, _sample_binary, _sample_binary,
             _sample_binary)
 
-    def test_eol_crlf(self):
-        wt, basis = self.prepare_tree(_sample_text, eol='crlf')
-        self.assertContent(wt, basis, _sample_text_on_unix,
-            _sample_text_on_unix, _sample_text_on_win)
-
     def test_eol_crlf_binary(self):
         wt, basis = self.prepare_tree(_sample_binary, eol='crlf')
         self.assertContent(wt, basis, _sample_binary, _sample_binary,
             _sample_binary)
 
-    def test_eol_native_with_crlf_in_repo(self):
-        wt, basis = self.prepare_tree(_sample_text,
-            eol='native-with-crlf-in-repo')
-        self.assertContent(wt, basis, _sample_text_on_win,
-            _sample_text_on_unix, _sample_text_on_win)
-
     def test_eol_native_with_crlf_in_repo_binary(self):
         wt, basis = self.prepare_tree(_sample_binary,
             eol='native-with-crlf-in-repo')
         self.assertContent(wt, basis, _sample_binary, _sample_binary,
             _sample_binary)
 
-    def test_eol_lf_with_crlf_in_repo(self):
-        wt, basis = self.prepare_tree(_sample_text, eol='lf-with-crlf-in-repo')
-        self.assertContent(wt, basis, _sample_text_on_win,
-            _sample_text_on_unix, _sample_text_on_win)
-
     def test_eol_lf_with_crlf_in_repo_binary(self):
-        wt, basis = self.prepare_tree(_sample_binary, eol='lf-with-crlf-in-repo')
+        wt, basis = self.prepare_tree(_sample_binary,
+            eol='lf-with-crlf-in-repo')
         self.assertContent(wt, basis, _sample_binary, _sample_binary,
             _sample_binary)
 
-    def test_eol_crlf_with_crlf_in_repo(self):
-        wt, basis = self.prepare_tree(_sample_text, eol='crlf-with-crlf-in-repo')
-        self.assertContent(wt, basis, _sample_text_on_win,
-            _sample_text_on_unix, _sample_text_on_win)
-
     def test_eol_crlf_with_crlf_in_repo_binary(self):
-        wt, basis = self.prepare_tree(_sample_binary, eol='crlf-with-crlf-in-repo')
+        wt, basis = self.prepare_tree(_sample_binary,
+            eol='crlf-with-crlf-in-repo')
         self.assertContent(wt, basis, _sample_binary, _sample_binary,
             _sample_binary)
 
-    def test_eol_exact(self):
+    # Test text with mixed line endings ("dirty text").
+    # This doesn't roundtrip so status always thinks something has changed.
+
+    def test_eol_no_rules_dirty(self):
+        wt, basis = self.prepare_tree(_sample_text)
+        self.assertContent(wt, basis, _sample_text,
+            _sample_text_on_unix, _sample_text_on_win, roundtrip_to=[])
+
+    def test_eol_exact_dirty(self):
         wt, basis = self.prepare_tree(_sample_text, eol='exact')
         self.assertContent(wt, basis, _sample_text,
-            _sample_text_on_unix, _sample_text_on_win)
-
-    def test_eol_exact_binary(self):
-        wt, basis = self.prepare_tree(_sample_binary, eol='exact')
-        self.assertContent(wt, basis, _sample_binary, _sample_binary,
-            _sample_binary)
+            _sample_text_on_unix, _sample_text_on_win, roundtrip_to=[])
+
+    def test_eol_native_dirty(self):
+        wt, basis = self.prepare_tree(_sample_text, eol='native')
+        self.assertContent(wt, basis, _sample_text_on_unix,
+            _sample_text_on_unix, _sample_text_on_win, roundtrip_to=[])
+
+    def test_eol_lf_dirty(self):
+        wt, basis = self.prepare_tree(_sample_text, eol='lf')
+        self.assertContent(wt, basis, _sample_text_on_unix,
+            _sample_text_on_unix, _sample_text_on_win, roundtrip_to=[])
+
+    def test_eol_crlf_dirty(self):
+        wt, basis = self.prepare_tree(_sample_text, eol='crlf')
+        self.assertContent(wt, basis, _sample_text_on_unix,
+            _sample_text_on_unix, _sample_text_on_win, roundtrip_to=[])
+
+    def test_eol_native_with_crlf_in_repo_dirty(self):
+        wt, basis = self.prepare_tree(_sample_text,
+            eol='native-with-crlf-in-repo')
+        self.assertContent(wt, basis, _sample_text_on_win,
+            _sample_text_on_unix, _sample_text_on_win, roundtrip_to=[])
+
+    def test_eol_lf_with_crlf_in_repo_dirty(self):
+        wt, basis = self.prepare_tree(_sample_text,
+            eol='lf-with-crlf-in-repo')
+        self.assertContent(wt, basis, _sample_text_on_win,
+            _sample_text_on_unix, _sample_text_on_win, roundtrip_to=[])
+
+    def test_eol_crlf_with_crlf_in_repo_dirty(self):
+        wt, basis = self.prepare_tree(_sample_text,
+            eol='crlf-with-crlf-in-repo')
+        self.assertContent(wt, basis, _sample_text_on_win,
+            _sample_text_on_unix, _sample_text_on_win, roundtrip_to=[])
+
+    # Test text with clean line endings, either always lf or always crlf.
+    # This selectively roundtrips (based on what's stored in the repo).
+
+    def test_eol_no_rules_clean_lf(self):
+        wt, basis = self.prepare_tree(_sample_clean_lf)
+        self.assertContent(wt, basis, _sample_clean_lf,
+            _sample_text_on_unix, _sample_text_on_win,
+            roundtrip_to=_LF_IN_REPO)
+
+    def test_eol_no_rules_clean_crlf(self):
+        wt, basis = self.prepare_tree(_sample_clean_crlf)
+        self.assertContent(wt, basis, _sample_clean_crlf,
+            _sample_text_on_unix, _sample_text_on_win,
+            roundtrip_to=_CRLF_IN_REPO)
+
+    def test_eol_exact_clean_lf(self):
+        wt, basis = self.prepare_tree(_sample_clean_lf, eol='exact')
+        self.assertContent(wt, basis, _sample_clean_lf,
+            _sample_text_on_unix, _sample_text_on_win,
+            roundtrip_to=_LF_IN_REPO)
+
+    def test_eol_exact_clean_crlf(self):
+        wt, basis = self.prepare_tree(_sample_clean_crlf, eol='exact')
+        self.assertContent(wt, basis, _sample_clean_crlf,
+            _sample_text_on_unix, _sample_text_on_win,
+            roundtrip_to=_CRLF_IN_REPO)
+
+    def test_eol_native_clean_lf(self):
+        wt, basis = self.prepare_tree(_sample_clean_lf, eol='native')
+        self.assertContent(wt, basis, _sample_text_on_unix,
+            _sample_text_on_unix, _sample_text_on_win,
+            roundtrip_to=_LF_IN_REPO)
+
+    def test_eol_native_clean_crlf(self):
+        wt, basis = self.prepare_tree(_sample_clean_crlf, eol='native')
+        self.assertContent(wt, basis, _sample_text_on_unix,
+            _sample_text_on_unix, _sample_text_on_win,
+            roundtrip_to=_LF_IN_REPO)
+
+    def test_eol_lf_clean_lf(self):
+        wt, basis = self.prepare_tree(_sample_clean_lf, eol='lf')
+        self.assertContent(wt, basis, _sample_text_on_unix,
+            _sample_text_on_unix, _sample_text_on_win,
+            roundtrip_to=_LF_IN_REPO)
+
+    def test_eol_lf_clean_crlf(self):
+        wt, basis = self.prepare_tree(_sample_clean_crlf, eol='lf')
+        self.assertContent(wt, basis, _sample_text_on_unix,
+            _sample_text_on_unix, _sample_text_on_win,
+            roundtrip_to=_LF_IN_REPO)
+
+    def test_eol_crlf_clean_lf(self):
+        wt, basis = self.prepare_tree(_sample_clean_lf, eol='crlf')
+        self.assertContent(wt, basis, _sample_text_on_unix,
+            _sample_text_on_unix, _sample_text_on_win,
+            roundtrip_to=_LF_IN_REPO)
+
+    def test_eol_crlf_clean_crlf(self):
+        wt, basis = self.prepare_tree(_sample_clean_crlf, eol='crlf')
+        self.assertContent(wt, basis, _sample_text_on_unix,
+            _sample_text_on_unix, _sample_text_on_win,
+            roundtrip_to=_LF_IN_REPO)
+
+    def test_eol_native_with_crlf_in_repo_clean_lf(self):
+        wt, basis = self.prepare_tree(_sample_clean_lf,
+            eol='native-with-crlf-in-repo')
+        self.assertContent(wt, basis, _sample_text_on_win,
+            _sample_text_on_unix, _sample_text_on_win,
+            roundtrip_to=_CRLF_IN_REPO)
+
+    def test_eol_native_with_crlf_in_repo_clean_crlf(self):
+        wt, basis = self.prepare_tree(_sample_clean_crlf,
+            eol='native-with-crlf-in-repo')
+        self.assertContent(wt, basis, _sample_text_on_win,
+            _sample_text_on_unix, _sample_text_on_win,
+            roundtrip_to=_CRLF_IN_REPO)
+
+    def test_eol_lf_with_crlf_in_repo_clean_lf(self):
+        wt, basis = self.prepare_tree(_sample_clean_lf,
+            eol='lf-with-crlf-in-repo')
+        self.assertContent(wt, basis, _sample_text_on_win,
+            _sample_text_on_unix, _sample_text_on_win,
+            roundtrip_to=_CRLF_IN_REPO)
+
+    def test_eol_lf_with_crlf_in_repo_clean_crlf(self):
+        wt, basis = self.prepare_tree(_sample_clean_crlf,
+            eol='lf-with-crlf-in-repo')
+        self.assertContent(wt, basis, _sample_text_on_win,
+            _sample_text_on_unix, _sample_text_on_win,
+            roundtrip_to=_CRLF_IN_REPO)
+
+    def test_eol_crlf_with_crlf_in_repo_clean_lf(self):
+        wt, basis = self.prepare_tree(_sample_clean_lf,
+            eol='crlf-with-crlf-in-repo')
+        self.assertContent(wt, basis, _sample_text_on_win,
+            _sample_text_on_unix, _sample_text_on_win,
+            roundtrip_to=_CRLF_IN_REPO)
+
+    def test_eol_crlf_with_crlf_in_repo_clean_crlf(self):
+        wt, basis = self.prepare_tree(_sample_clean_crlf,
+            eol='crlf-with-crlf-in-repo')
+        self.assertContent(wt, basis, _sample_text_on_win,
+            _sample_text_on_unix, _sample_text_on_win,
+            roundtrip_to=_CRLF_IN_REPO)

=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py	2009-06-10 03:56:49 +0000
+++ b/bzrlib/workingtree_4.py	2009-06-11 04:23:53 +0000
@@ -1440,13 +1440,20 @@
                 # Note: do NOT move this logic up higher - using the basis from
                 # the accelerator tree is still desirable because that can save
                 # a minute or more of processing on large trees!
+                # The original tree may not have the same content filters
+                # applied so we can't safely build the inventory delta from
+                # the source tree.
                 if wt.supports_content_filtering():
                     accelerator_tree = None
+                    delta_from_tree = False
+                else:
+                    delta_from_tree = True
                 # delta_from_tree is safe even for DirStateRevisionTrees,
                 # because wt4.apply_inventory_delta does not mutate the input
                 # inventory entries.
                 transform.build_tree(basis, wt, accelerator_tree,
-                                     hardlink=hardlink, delta_from_tree=True)
+                                     hardlink=hardlink,
+                                     delta_from_tree=delta_from_tree)
             finally:
                 basis.unlock()
         finally:




More information about the bazaar-commits mailing list