فهرست منبع

HUE-5482 [home] Handle multiple home/trash directories by merging them into one.

During deletion or executing queries, when we hit MultipleObjectsReturned exception,
this fix will merge all the duplicate directories into one.
krish 10 سال پیش
والد
کامیت
4e62dc8d5a
2فایلهای تغییر یافته به همراه86 افزوده شده و 2 حذف شده
  1. 23 2
      desktop/core/src/desktop/models.py
  2. 63 0
      desktop/core/src/desktop/tests.py

+ 23 - 2
desktop/core/src/desktop/models.py

@@ -965,6 +965,16 @@ class Document2Manager(models.Manager, Document2QueryMixin):
       return self.get(owner=user, parent_directory=None, name=Document2.HOME_DIR, type='directory')
     except Document2.DoesNotExist:
       return self.create_user_directories(user)
+    except Document2.MultipleObjectsReturned:
+      LOG.error('Multiple Home directories detected. Merging all into one.')
+
+      home_dirs = list(self.filter(owner=user, parent_directory=None, name=Document2.HOME_DIR, type='directory').order_by('-last_modified'))
+      parent_home_dir = home_dirs.pop()
+      for dir in home_dirs:
+        dir.children.exclude(name='.Trash').update(parent_directory=parent_home_dir)
+        dir.delete()
+
+      return parent_home_dir
 
   def get_by_path(self, user, path):
     """
@@ -1222,8 +1232,19 @@ class Document2(models.Model):
     return self
 
   def trash(self):
-    trash_dir = Directory.objects.get(name=self.TRASH_DIR, owner=self.owner)
-    self.move(trash_dir, self.owner)
+    try:
+      trash_dir = Directory.objects.get(name=self.TRASH_DIR, owner=self.owner)
+      self.move(trash_dir, self.owner)
+    except Document2.MultipleObjectsReturned:
+      LOG.error('Multiple Trash directories detected. Merging all into one.')
+
+      trash_dirs = list(Directory.objects.filter(name=self.TRASH_DIR, owner=self.owner).order_by('-last_modified'))
+      parent_trash_dir = trash_dirs.pop()
+      for dir in trash_dirs:
+        dir.children.update(parent_directory=parent_trash_dir)
+        dir.delete()
+
+      self.move(parent_trash_dir, self.owner)
 
   # TODO: restore
 

+ 63 - 0
desktop/core/src/desktop/tests.py

@@ -918,6 +918,69 @@ class TestDocument(object):
     test_doc.delete()
     test_dir.delete()
 
+  def test_multiple_home_directories(self):
+    home_dir = Directory.objects.get_home_directory(self.user)
+    test_doc1 = Document2.objects.create(name='test-doc1',
+                                         type='query-hive',
+                                         owner=self.user,
+                                         description='',
+                                         parent_directory=home_dir)
+
+    assert_equal(home_dir.children.count(), 3)
+
+    # Cannot create second home directory directly as it will fail in Document2.validate()
+    second_home_dir = Document2.objects.create(owner=self.user, parent_directory=None, name='second_home_dir', type='directory')
+    Document2.objects.filter(name='second_home_dir').update(name=Document2.HOME_DIR, parent_directory=None)
+    assert_equal(Document2.objects.filter(owner=self.user, name=Document2.HOME_DIR).count(), 2)
+
+    test_doc2 = Document2.objects.create(name='test-doc2',
+                                              type='query-hive',
+                                              owner=self.user,
+                                              description='',
+                                              parent_directory=second_home_dir)
+    assert_equal(second_home_dir.children.count(), 1)
+
+    merged_home_dir = Directory.objects.get_home_directory(self.user)
+    children = merged_home_dir.children.all().order_by('-last_modified')
+    assert_equal(children.count(), 4)
+    assert_equal(test_doc2.name, children[0].name)
+    assert_equal(test_doc1.name, children[1].name)
+
+  def test_multiple_trash_directories(self):
+    home_dir = Directory.objects.get_home_directory(self.user)
+    test_doc1 = Document2.objects.create(name='test-doc1',
+                                         type='query-hive',
+                                         owner=self.user,
+                                         description='',
+                                         parent_directory=home_dir)
+
+    assert_equal(home_dir.children.count(), 3)
+
+    # Cannot create second trash directory directly as it will fail in Document2.validate()
+    Document2.objects.create(owner=self.user, parent_directory=home_dir, name='second_trash_dir', type='directory')
+    Document2.objects.filter(name='second_trash_dir').update(name=Document2.TRASH_DIR)
+    assert_equal(Document2.objects.filter(owner=self.user, name=Document2.TRASH_DIR).count(), 2)
+
+
+    test_doc2 = Document2.objects.create(name='test-doc2',
+                                              type='query-hive',
+                                              owner=self.user,
+                                              description='',
+                                              parent_directory=home_dir)
+    assert_equal(home_dir.children.count(), 5) # Including the second trash
+    assert_raises(Document2.MultipleObjectsReturned, Document2.objects.get, name=Document2.TRASH_DIR)
+
+    test_doc1.trash()
+    assert_equal(home_dir.children.count(), 3) # As trash documents are merged count is back to 3
+    merged_trash_dir = Document2.objects.get(name=Document2.TRASH_DIR)
+
+    test_doc2.trash()
+    children = merged_trash_dir.children.all().order_by('-last_modified')
+    assert_equal(children.count(), 2)
+    assert_equal(test_doc2.name, children[0].name)
+    assert_equal(test_doc1.name, children[1].name)
+
+
   def test_document_copy(self):
     name = 'Test Document2 Copy'