Rev 5079: (spiv) Merge lp:bzr/2.1, including fix for #192859. in file:///home/pqm/archives/thelove/bzr/2.2/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Tue Aug 17 07:13:35 BST 2010


At file:///home/pqm/archives/thelove/bzr/2.2/

------------------------------------------------------------
revno: 5079 [merge]
revision-id: pqm at pqm.ubuntu.com-20100817061333-p2k4garabeuwbqt7
parent: pqm at pqm.ubuntu.com-20100817021423-wegvm3ai25d0h0sb
parent: andrew.bennetts at canonical.com-20100817045544-jhviyesrz5kdo5x6
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: 2.2
timestamp: Tue 2010-08-17 07:13:33 +0100
message:
  (spiv) Merge lp:bzr/2.1, including fix for #192859.
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/inventory.py            inventory.py-20050309040759-6648b84ca2005b37
  bzrlib/mutabletree.py          mutabletree.py-20060906023413-4wlkalbdpsxi2r4y-2
  bzrlib/tests/per_workingtree/test_symlinks.py test_symlinks.py-20100715135626-4lw38d8njbzyec6l-1
  bzrlib/workingtree.py          workingtree.py-20050511021032-29b6ec0a681e02e3
=== modified file 'NEWS'
--- a/NEWS	2010-08-17 02:14:23 +0000
+++ b/NEWS	2010-08-17 04:55:44 +0000
@@ -17,12 +17,21 @@
 Bug Fixes
 *********
 
+* ``bzr add SYMLINK/FILE`` now works properly when the symlink points to a
+  previously-unversioned directory within the tree: the directory is
+  marked versioned too.  
+  (Martin Pool, #192859)
+
 * CommitBuilder now uses the committer instead of _config.username to generate
   the revision-id.  (Aaron Bentley, #614404)
 
 * Cope with Microsoft FTP server that returns reply '250 Directory
   created' when mkdir succeeds.  (Martin Pool, #224373)
 
+* Fix ``AttributeError on parent.children`` when adding a file under a 
+  directory that was a symlink in the previous commit.
+  (Martin Pool, #192859)
+
 Improvements
 ************
 
@@ -1087,6 +1096,11 @@
 Bug Fixes
 *********
 
+* ``bzr add SYMLINK/FILE`` now works properly when the symlink points to a
+  previously-unversioned directory within the tree: the directory is
+  marked versioned too.  
+  (Martin Pool, #192859)
+
 * Configuration files in ``${BZR_HOME}`` are now written in an atomic
   way which should help avoid problems with concurrent writers.
   (Vincent Ladeuil, #525571)
@@ -1094,6 +1108,10 @@
 * Don't traceback trying to unversion children files of an already
   unversioned directory.  (Vincent Ladeuil, #494221)
 
+* Fix ``AttributeError on parent.children`` when adding a file under a 
+  directory that was a symlink in the previous commit.
+  (Martin Pool, #192859)
+
 * Prevent ``CHKMap.apply_delta`` from generating non-canonical CHK maps,
   which can result in "missing referenced chk root keys" errors when
   fetching from repositories with affected revisions.
@@ -1604,6 +1622,11 @@
   history no longer crash when deleted files are involved.
   (Vincent Ladeuil, John Arbash Meinel, #375898)
 
+* ``bzr add SYMLINK/FILE`` now works properly when the symlink points to a
+  previously-unversioned directory within the tree: the directory is
+  marked versioned too.  
+  (Martin Pool, #192859)
+
 * ``bzr commit SYMLINK`` now works, rather than trying to commit the
   target of the symlink.
   (Martin Pool, John Arbash Meinel, #128562)
@@ -1619,6 +1642,10 @@
 * Don't traceback trying to unversion children files of an already
   unversioned directory.  (Vincent Ladeuil, #494221)
 
+* Fix ``AttributeError on parent.children`` when adding a file under a 
+  directory that was a symlink in the previous commit.
+  (Martin Pool, #192859)
+
 * Prevent ``CHKMap.apply_delta`` from generating non-canonical CHK maps,
   which can result in "missing referenced chk root keys" errors when
   fetching from repositories with affected revisions.

=== modified file 'bzrlib/inventory.py'
--- a/bzrlib/inventory.py	2010-05-11 07:52:16 +0000
+++ b/bzrlib/inventory.py	2010-08-16 03:43:35 +0000
@@ -1282,9 +1282,6 @@
     def add(self, entry):
         """Add entry to inventory.
 
-        To add  a file to a branch ready to be committed, use Branch.add,
-        which calls this.
-
         :return: entry
         """
         if entry.file_id in self._byid:

=== modified file 'bzrlib/mutabletree.py'
--- a/bzrlib/mutabletree.py	2010-07-21 09:58:42 +0000
+++ b/bzrlib/mutabletree.py	2010-08-16 03:43:35 +0000
@@ -32,6 +32,7 @@
     hooks,
     osutils,
     revisiontree,
+    inventory,
     symbol_versioning,
     trace,
     tree,
@@ -415,6 +416,10 @@
             for c in self.conflicts():
                 conflicts_related.update(c.associated_filenames())
 
+        # expand any symlinks in the directory part, while leaving the
+        # filename alone
+        file_list = map(osutils.normalizepath, file_list)
+
         # validate user file paths and convert all paths to tree
         # relative : it's cheaper to make a tree relative path an abspath
         # than to convert an abspath to tree relative, and it's cheaper to
@@ -719,6 +724,17 @@
         file_id or None to generate a new file id
     :returns: None
     """
+    # if the parent exists, but isn't a directory, we have to do the
+    # kind change now -- really the inventory shouldn't pretend to know
+    # the kind of wt files, but it does.
+    if parent_ie.kind != 'directory':
+        # nb: this relies on someone else checking that the path we're using
+        # doesn't contain symlinks.
+        new_parent_ie = inventory.make_entry('directory', parent_ie.name,
+            parent_ie.parent_id, parent_ie.file_id)
+        del inv[parent_ie.file_id]
+        inv.add(new_parent_ie)
+        parent_ie = new_parent_ie
     file_id = file_id_callback(inv, parent_ie, path, kind)
     entry = inv.make_entry(kind, path.base_path, parent_ie.file_id,
         file_id=file_id)

=== modified file 'bzrlib/tests/per_workingtree/test_symlinks.py'
--- a/bzrlib/tests/per_workingtree/test_symlinks.py	2010-07-16 10:48:51 +0000
+++ b/bzrlib/tests/per_workingtree/test_symlinks.py	2010-08-17 02:28:46 +0000
@@ -15,12 +15,13 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
 """Test symlink support.
-
-See eg <https://bugs.launchpad.net/bzr/+bug/192859>
 """
 
+import os
+
 from bzrlib import (
     builtins,
+    osutils,
     tests,
     workingtree,
     )
@@ -29,6 +30,8 @@
 
 class TestSmartAddTree(TestCaseWithWorkingTree):
 
+    # See eg <https://bugs.launchpad.net/bzr/+bug/192859>
+
     _test_needs_features = [tests.SymlinkFeature]
 
     def test_smart_add_symlink(self):
@@ -53,6 +56,80 @@
         self.assertEqual('symlink',
             tree.kind(tree.path2id('link')))
 
+    def test_add_file_under_symlink(self):
+        # similar to 
+        # https://bugs.launchpad.net/bzr/+bug/192859/comments/3
+        tree = self.make_branch_and_tree('tree')
+        self.build_tree_contents([
+            ('tree/link@', 'dir'),
+            ('tree/dir/',),
+            ('tree/dir/file', 'content'),
+            ])
+        self.assertEquals(
+            tree.smart_add(['tree/link/file']),
+            ([u'dir', u'dir/file'], {}))
+        # should add the actual parent directory, not the apparent parent
+        # (which is actually a symlink)
+        self.assertTrue(tree.path2id('dir/file'))
+        self.assertTrue(tree.path2id('dir'))
+        self.assertIs(None, tree.path2id('link'))
+        self.assertIs(None, tree.path2id('link/file'))
+
+
+class TestKindChanges(TestCaseWithWorkingTree):
+
+    _test_needs_features = [tests.SymlinkFeature]
+
+    def test_symlink_changes_to_dir(self):
+        # <https://bugs.launchpad.net/bzr/+bug/192859>:
+        # we had some past problems with the workingtree remembering for too
+        # long what kind of object was at a particular name; we really
+        # shouldn't do that.  Operating on the dirstate through passing
+        # inventory deltas rather than mutating the inventory largely avoids
+        # that.
+        tree = self.make_branch_and_tree('tree')
+        self.build_tree_contents([
+            ('tree/a@', 'target')])
+        tree.smart_add(['tree/a'])
+        tree.commit('add symlink')
+        os.unlink('tree/a')
+        self.build_tree_contents([
+            ('tree/a/',),
+            ('tree/a/f', 'content'),
+            ])
+        tree.smart_add(['tree/a/f'])
+        tree.commit('change to dir')
+        tree.lock_read()
+        self.addCleanup(tree.unlock)
+        self.assertEquals([], list(tree.iter_changes(tree.basis_tree())))
+        self.assertEquals(
+            ['a', 'a/f'], sorted(info[0] for info in tree.list_files()))
+
+    def test_dir_changes_to_symlink(self):
+        # <https://bugs.launchpad.net/bzr/+bug/192859>:
+        # we had some past problems with the workingtree remembering for too
+        # long what kind of object was at a particular name; we really
+        # shouldn't do that.  Operating on the dirstate through passing
+        # inventory deltas rather than mutating the inventory largely avoids
+        # that.
+        tree = self.make_branch_and_tree('tree')
+        self.build_tree_contents([
+            ('tree/a/',),
+            ('tree/a/file', 'content'),
+            ])
+        tree.smart_add(['tree/a'])
+        tree.commit('add dir')
+        osutils.rmtree('tree/a')
+        self.build_tree_contents([
+            ('tree/a@', 'target'),
+            ])
+        tree.commit('change to symlink')
+
+
+class TestOpenTree(TestCaseWithWorkingTree):
+
+    _test_needs_features = [tests.SymlinkFeature]
+
     def test_open_containing_through_symlink(self):
         self.make_test_tree()
         self.check_open_containing('link/content', 'tree', 'content')

=== modified file 'bzrlib/workingtree.py'
--- a/bzrlib/workingtree.py	2010-07-06 19:48:05 +0000
+++ b/bzrlib/workingtree.py	2010-08-17 02:28:46 +0000
@@ -1209,13 +1209,18 @@
                 # absolute path
                 fap = from_dir_abspath + '/' + f
 
-                f_ie = inv.get_child(from_dir_id, f)
+                dir_ie = inv[from_dir_id]
+                if dir_ie.kind == 'directory':
+                    f_ie = dir_ie.children.get(f)
+                else:
+                    f_ie = None
                 if f_ie:
                     c = 'V'
                 elif self.is_ignored(fp[1:]):
                     c = 'I'
                 else:
-                    # we may not have found this file, because of a unicode issue
+                    # we may not have found this file, because of a unicode
+                    # issue, or because the directory was actually a symlink.
                     f_norm, can_access = osutils.normalized_filename(f)
                     if f == f_norm or not can_access:
                         # No change, so treat this file normally




More information about the bazaar-commits mailing list