Rev 5423: Prepare for more ways to handle orphans. in file:///home/vila/src/bzr/bugs/323111-orphans/

Vincent Ladeuil v.ladeuil+lp at free.fr
Thu Sep 16 10:06:56 BST 2010


At file:///home/vila/src/bzr/bugs/323111-orphans/

------------------------------------------------------------
revno: 5423
revision-id: v.ladeuil+lp at free.fr-20100916090656-acrq9cza0gi1447f
parent: v.ladeuil+lp at free.fr-20100913101409-tnv06tbqmne2cjis
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: orphan-config-option
timestamp: Thu 2010-09-16 11:06:56 +0200
message:
  Prepare for more ways to handle orphans.
  
  * bzrlib/transform.py:
  (TreeTransformBase._get_potential_orphans): Factored out from
  conflict_pass.
  (new_orphan): Thunk to move_orphan.
  (orphaning_registry): First rough definition.
  (conflict_pass): Be ready for orphan handlings that don't move the
  orphans out of the way.
-------------- next part --------------
=== modified file 'bzrlib/tests/test_transform.py'
--- a/bzrlib/tests/test_transform.py	2010-09-13 10:14:09 +0000
+++ b/bzrlib/tests/test_transform.py	2010-09-16 09:06:56 +0000
@@ -3267,7 +3267,7 @@
         self.addCleanup(tt.finalize)
         self.assertRaises(NotImplementedError, tt.new_orphan, 'foo', 'bar')
 
-    def test_new_orphan(self):
+    def test_new_orphan_created(self):
         wt = self.make_branch_and_tree('.')
         self.build_tree(['dir/', 'dir/foo'])
         wt.add(['dir'], ['dir-id'])

=== modified file 'bzrlib/transform.py'
--- a/bzrlib/transform.py	2010-09-13 10:14:09 +0000
+++ b/bzrlib/transform.py	2010-09-16 09:06:56 +0000
@@ -22,6 +22,7 @@
 from bzrlib import (
     errors,
     lazy_import,
+    registry,
     )
 lazy_import.lazy_import(globals(), """
 from bzrlib import (
@@ -797,6 +798,35 @@
         """
         raise NotImplementedError(self.new_orphan)
 
+    def _get_potential_orphans(self, dir_id):
+        """Find the potential orphans in a directory.
+
+        A directory can't be safely deleted if there are versioned files in it.
+        If all the contained files are unversioned then they can be orphaned.
+
+        The 'None' return value means that the directory contains at least one
+        versioned file and should not be deleted.
+
+        :param dir_id: The directory trans id.
+
+        :return: A list of the orphan trans ids or None if at least one
+             versioned file is present.
+        """
+        orphans = []
+        dont_delete = False
+        # Find the potential orphans, stop if one item should be kept
+        for c in self.by_parent()[dir_id]:
+            if self.final_file_id(c) is None:
+                orphans.append(c)
+            else:
+                dont_delete = True
+                break
+        if dont_delete:
+            return None
+        else:
+            return orphans
+
+
     def _affected_ids(self):
         """Return the set of transform ids affected by the transform"""
         trans_ids = set(self._removed_id)
@@ -1310,19 +1340,39 @@
         delete_any(self._limbo_name(trans_id))
 
     def new_orphan(self, trans_id, parent_id):
-        """See TreeTransformBase.new_orphan."""
-        # Add the orphan dir if it doesn't exist
-        orphan_dir = 'bzr-orphans'
-        od_id = self.trans_id_tree_path(orphan_dir)
-        if self.final_kind(od_id) is None:
-            self.create_directory(od_id)
-        parent_path = self._tree_id_paths[parent_id]
-        # Find a name that doesn't exist yet in the orphan dir
-        actual_name = self.final_name(trans_id)
-        new_name = self._available_backup_name(actual_name, od_id)
-        self.adjust_path(new_name, od_id, trans_id)
-        trace.warning('%s has been orphaned in %s'
-                      % (joinpath(parent_path, actual_name), orphan_dir))
+        move_orphan(self, trans_id, parent_id)
+
+
+def move_orphan(tt, orphan_id, parent_id):
+    """See TreeTransformBase.new_orphan.
+
+    This creates a new orphan in the `bzr-orphans` dir at the root of the
+    `TreeTransform`.
+
+    :param tt: The TreeTransform orphaning `trans_id`.
+
+    :param orphan_id: The trans id that should be orphaned.
+
+    :param parent_id: The orphan parent trans id.
+    """
+    # Add the orphan dir if it doesn't exist
+    orphan_dir = 'bzr-orphans'
+    od_id = tt.trans_id_tree_path(orphan_dir)
+    if tt.final_kind(od_id) is None:
+        tt.create_directory(od_id)
+    parent_path = tt._tree_id_paths[parent_id]
+    # Find a name that doesn't exist yet in the orphan dir
+    actual_name = tt.final_name(orphan_id)
+    new_name = tt._available_backup_name(actual_name, od_id)
+    tt.adjust_path(new_name, od_id, orphan_id)
+    trace.warning('%s has been orphaned in %s'
+                  % (joinpath(parent_path, actual_name), orphan_dir))
+
+
+orphaning_registry = registry.Registry()
+orphaning_registry.register('bzr-orphans', move_orphan,
+                            'Move orphans into the bzr-orphans directory.')
+orphaning_registry._set_default_key('bzr-orphans')
 
 
 class TreeTransform(DiskTreeTransform):
@@ -2859,20 +2909,16 @@
         elif c_type == 'missing parent':
             trans_id = conflict[1]
             if trans_id in tt._removed_contents:
-                orphans = []
-                empty = True
-                # Find the potential orphans, stop if one item should be kept
-                for c in tt.by_parent()[trans_id]:
-                    if tt.final_file_id(c) is None:
-                        orphans.append(c)
-                    else:
-                        empty = False
-                        break
-                if empty:
+                orphans = tt._get_potential_orphans(trans_id)
+                if orphans:
                     # All children are orphans
                     for o in orphans:
-                        tt.new_orphan(o, trans_id)
-                else:
+                        try:
+                            tt.new_orphan(o, trans_id)
+                        except OrphaningForbidden:
+                            orphans = None
+                            break
+                if orphans is None:
                     # Cancel the directory deletion
                     tt.cancel_deletion(trans_id)
                     new_conflicts.add(('deleting parent', 'Not deleting',



More information about the bazaar-commits mailing list