Rev 3160: Handle conflicts in parent file kind gracefully (abentley) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Thu Jan 3 17:08:16 GMT 2008


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

------------------------------------------------------------
revno: 3160
revision-id:pqm at pqm.ubuntu.com-20080103170805-t22jan69n4n5kkub
parent: pqm at pqm.ubuntu.com-20080103160106-v6qfwv4ta8sorx1q
parent: aaron.bentley at utoronto.ca-20071225041750-t6chr3pmgnebvqcz
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2008-01-03 17:08:05 +0000
message:
  Handle conflicts in parent file kind gracefully (abentley)
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/conflicts.py            conflicts.py-20051001061850-78ef952ba63d2b42
  bzrlib/help_topics/en/conflicts.txt conflicts.txt-20070723221841-ns3jvwxdb4okn6fk-1
  bzrlib/tests/test_conflicts.py test_conflicts.py-20051006031059-e2dad9bbeaa5891f
  bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
  bzrlib/transform.py            transform.py-20060105172343-dd99e54394d91687
    ------------------------------------------------------------
    revno: 3144.4.2
    revision-id:aaron.bentley at utoronto.ca-20071225041750-t6chr3pmgnebvqcz
    parent: aaron.bentley at utoronto.ca-20071224231849-iig4ougav7ybldzj
    committer: Aaron Bentley <aaron.bentley at utoronto.ca>
    branch nick: resolve-parent-kind
    timestamp: Mon 2007-12-24 23:17:50 -0500
    message:
      Handle non-directory parent conflicts (abentley, #177390)
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/conflicts.py            conflicts.py-20051001061850-78ef952ba63d2b42
      bzrlib/help_topics/en/conflicts.txt conflicts.txt-20070723221841-ns3jvwxdb4okn6fk-1
      bzrlib/tests/test_conflicts.py test_conflicts.py-20051006031059-e2dad9bbeaa5891f
      bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
      bzrlib/transform.py            transform.py-20060105172343-dd99e54394d91687
    ------------------------------------------------------------
    revno: 3144.4.1
    revision-id:aaron.bentley at utoronto.ca-20071224231849-iig4ougav7ybldzj
    parent: pqm at pqm.ubuntu.com-20071222080058-lra6luc153ex60w4
    committer: Aaron Bentley <aaron.bentley at utoronto.ca>
    branch nick: resolve-parent-kind
    timestamp: Mon 2007-12-24 18:18:49 -0500
    message:
      Handle trying to list parents of a non-directory
    modified:
      bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
      bzrlib/transform.py            transform.py-20060105172343-dd99e54394d91687
=== modified file 'NEWS'
--- a/NEWS	2008-01-03 10:38:22 +0000
+++ b/NEWS	2008-01-03 17:08:05 +0000
@@ -94,6 +94,9 @@
      user:pass embedded in the urls.
      (Vincent Ladeuil, #177643)
 
+   * Files inside non-directories are now handled like other conflict types.
+     (Aaron Bentley, #177390)
+
    * ``reconfigure`` is able to convert trees into lightweight checkouts.
      (Aaron Bentley)
 

=== modified file 'bzrlib/conflicts.py'
--- a/bzrlib/conflicts.py	2007-11-23 20:59:07 +0000
+++ b/bzrlib/conflicts.py	2007-12-25 04:17:50 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005 Aaron Bentley, Canonical Ltd
+# Copyright (C) 2005, 2007 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
@@ -515,6 +515,16 @@
              "%(action)s."
 
 
+class NonDirectoryParent(HandledConflict):
+    """An attempt to add files to a directory that is not a director or
+    an attempt to change the kind of a directory with files.
+    """
+
+    typestring = 'non-directory parent'
+
+    format = "Conflict: %(path)s is not a directory, but has files in it."\
+             "  %(action)s."
+
 ctype = {}
 
 
@@ -527,4 +537,4 @@
 
 register_types(ContentsConflict, TextConflict, PathConflict, DuplicateID,
                DuplicateEntry, ParentLoop, UnversionedParent, MissingParent,
-               DeletingParent,)
+               DeletingParent, NonDirectoryParent)

=== modified file 'bzrlib/help_topics/en/conflicts.txt'
--- a/bzrlib/help_topics/en/conflicts.txt	2007-12-09 22:35:10 +0000
+++ b/bzrlib/help_topics/en/conflicts.txt	2007-12-25 04:17:50 +0000
@@ -173,6 +173,29 @@
 You can rename the directories if you like, and once you have, run "bzr resolve
 FILE" to mark the conflict as resolved.
 
+Non-directory parent
+--------------------
+
+Typical message::
+
+  Conflict: FILE.new is not a directory, but has files in it.
+  Created directory.
+
+This happens when one side has added files to a directory, and the othe side
+has changed the directory into a file or symlink.  For example::
+
+  $ bzr init
+  $ bzr mkdir a
+  $ bzr commit -m "BASE"
+  $ bzr branch . ../other
+  $ rmdir a
+  $ touch a
+  $ bzr commit -m "THIS"
+  $ bzr mkdir ../other/a/b
+  $ bzr commit ../other -m "OTHER"
+  $ bzr merge ../other
+
+
 MalformedTransform
 ------------------
 

=== modified file 'bzrlib/tests/test_conflicts.py'
--- a/bzrlib/tests/test_conflicts.py	2007-11-23 20:19:57 +0000
+++ b/bzrlib/tests/test_conflicts.py	2007-12-25 04:17:50 +0000
@@ -26,6 +26,7 @@
     DuplicateID,
     DuplicateEntry,
     MissingParent,
+    NonDirectoryParent,
     ParentLoop,
     PathConflict,
     TextConflict,
@@ -56,6 +57,7 @@
     ParentLoop('Cancelled move', u'p\xe5the', u'p\xe5th2e',
                None, '\xc3\xaed2e'),
     UnversionedParent('Versioned directory', u'p\xe5thf', '\xc3\xaedf'),
+    NonDirectoryParent('Created directory', u'p\xe5thg', '\xc3\xaedg'),
 ])
 
 

=== modified file 'bzrlib/tests/test_transform.py'
--- a/bzrlib/tests/test_transform.py	2007-12-21 04:12:31 +0000
+++ b/bzrlib/tests/test_transform.py	2007-12-25 04:17:50 +0000
@@ -27,7 +27,8 @@
     )
 from bzrlib.bzrdir import BzrDir
 from bzrlib.conflicts import (DuplicateEntry, DuplicateID, MissingParent,
-                              UnversionedParent, ParentLoop, DeletingParent,)
+                              UnversionedParent, ParentLoop, DeletingParent,
+                              NonDirectoryParent)
 from bzrlib.errors import (DuplicateKey, MalformedTransform, NoSuchFile,
                            ReusingTransform, CantMoveRoot, 
                            PathsNotVersionedError, ExistingLimbo,
@@ -623,6 +624,61 @@
         self.assertEqual(conflicts_s[6], 'Conflict moving oz/emeraldcity into'
                                          ' oz/emeraldcity.  Cancelled move.')
 
+    def prepare_wrong_parent_kind(self):
+        tt, root = self.get_transform()
+        tt.new_file('parent', root, 'contents', 'parent-id')
+        tt.apply()
+        tt, root = self.get_transform()
+        parent_id = tt.trans_id_file_id('parent-id')
+        tt.new_file('child,', parent_id, 'contents2', 'file-id')
+        return tt
+
+    def test_find_conflicts_wrong_parent_kind(self):
+        tt = self.prepare_wrong_parent_kind()
+        tt.find_conflicts()
+
+    def test_resolve_conflicts_wrong_existing_parent_kind(self):
+        tt = self.prepare_wrong_parent_kind()
+        raw_conflicts = resolve_conflicts(tt)
+        self.assertEqual(set([('non-directory parent', 'Created directory',
+                         'new-3')]), raw_conflicts)
+        cooked_conflicts = cook_conflicts(raw_conflicts, tt)
+        self.assertEqual([NonDirectoryParent('Created directory', 'parent.new',
+        'parent-id')], cooked_conflicts)
+        tt.apply()
+        self.assertEqual(None, self.wt.path2id('parent'))
+        self.assertEqual('parent-id', self.wt.path2id('parent.new'))
+
+    def test_resolve_conflicts_wrong_new_parent_kind(self):
+        tt, root = self.get_transform()
+        parent_id = tt.new_directory('parent', root, 'parent-id')
+        tt.new_file('child,', parent_id, 'contents2', 'file-id')
+        tt.apply()
+        tt, root = self.get_transform()
+        parent_id = tt.trans_id_file_id('parent-id')
+        tt.delete_contents(parent_id)
+        tt.create_file('contents', parent_id)
+        raw_conflicts = resolve_conflicts(tt)
+        self.assertEqual(set([('non-directory parent', 'Created directory',
+                         'new-3')]), raw_conflicts)
+        tt.apply()
+        self.assertEqual(None, self.wt.path2id('parent'))
+        self.assertEqual('parent-id', self.wt.path2id('parent.new'))
+
+    def test_resolve_conflicts_wrong_parent_kind_unversioned(self):
+        tt, root = self.get_transform()
+        parent_id = tt.new_directory('parent', root)
+        tt.new_file('child,', parent_id, 'contents2')
+        tt.apply()
+        tt, root = self.get_transform()
+        parent_id = tt.trans_id_tree_path('parent')
+        tt.delete_contents(parent_id)
+        tt.create_file('contents', parent_id)
+        resolve_conflicts(tt)
+        tt.apply()
+        self.assertIs(None, self.wt.path2id('parent'))
+        self.assertIs(None, self.wt.path2id('parent.new'))
+
     def test_moving_versioned_directories(self):
         create, root = self.get_transform()
         kansas = create.new_directory('kansas', root, 'kansas-id')

=== modified file 'bzrlib/transform.py'
--- a/bzrlib/transform.py	2007-12-21 04:12:31 +0000
+++ b/bzrlib/transform.py	2007-12-25 04:17:50 +0000
@@ -658,7 +658,10 @@
                         self.tree_kind(t) == 'directory'])
         for trans_id in self._removed_id:
             file_id = self.tree_file_id(trans_id)
-            if self._tree.inventory[file_id].kind == 'directory':
+            if file_id is not None:
+                if self._tree.inventory[file_id].kind == 'directory':
+                    parents.append(trans_id)
+            elif self.tree_kind(trans_id) == 'directory':
                 parents.append(trans_id)
 
         for parent_id in parents:
@@ -674,7 +677,7 @@
         try:
             children = os.listdir(self._tree.abspath(path))
         except OSError, e:
-            if e.errno != errno.ENOENT and e.errno != errno.ESRCH:
+            if e.errno not in (errno.ENOENT, errno.ESRCH, errno.ENOTDIR):
                 raise
             return
             
@@ -982,8 +985,8 @@
                         file_id = self._tree.get_root_id()
                     else:
                         file_id = self.tree_file_id(trans_id)
-                    assert file_id is not None
-                    inventory_delta.append((path, None, file_id, None))
+                    if file_id is not None:
+                        inventory_delta.append((path, None, file_id, None))
         finally:
             child_pb.finished()
 
@@ -1490,6 +1493,10 @@
     for child in tt.iter_tree_children(old_parent):
         tt.adjust_path(tt.final_name(child), new_parent, child)
 
+def _reparent_transform_children(tt, old_parent, new_parent):
+    by_parent = tt.by_parent()
+    for child in by_parent[old_parent]:
+        tt.adjust_path(tt.final_name(child), new_parent, child)
 
 def _content_match(tree, entry, file_id, kind, target_path):
     if entry.kind != kind:
@@ -1878,6 +1885,16 @@
         elif c_type == 'unversioned parent':
             tt.version_file(tt.inactive_file_id(conflict[1]), conflict[1])
             new_conflicts.add((c_type, 'Versioned directory', conflict[1]))
+        elif c_type == 'non-directory parent':
+            parent_id = conflict[1]
+            parent_parent = tt.final_parent(parent_id)
+            parent_name = tt.final_name(parent_id)
+            parent_file_id = tt.final_file_id(parent_id)
+            new_parent_id = tt.new_directory(parent_name + '.new',
+                parent_parent, parent_file_id)
+            _reparent_transform_children(tt, parent_id, new_parent_id)
+            tt.unversion_file(parent_id)
+            new_conflicts.add((c_type, 'Created directory', new_parent_id))
     return new_conflicts
 
 




More information about the bazaar-commits mailing list