#1769: joining a document's history
authorRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Mon, 24 Oct 2011 15:00:04 +0000 (17:00 +0200)
committerRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Mon, 24 Oct 2011 15:00:04 +0000 (17:00 +0200)
apps/catalogue/models/book.py
apps/catalogue/tests/__init__.py
apps/dvcs/models.py
apps/dvcs/tests/__init__.py

index 94a9833..2a0d552 100755 (executable)
@@ -4,7 +4,7 @@
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 from django.contrib.sites.models import Site
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 from django.contrib.sites.models import Site
-from django.db import models
+from django.db import models, transaction
 from django.template.loader import render_to_string
 from django.utils.translation import ugettext_lazy as _
 from slughifi import slughifi
 from django.template.loader import render_to_string
 from django.utils.translation import ugettext_lazy as _
 from slughifi import slughifi
@@ -80,6 +80,7 @@ class Book(models.Model):
         return self.public or request.user.is_authenticated()
 
     @classmethod
         return self.public or request.user.is_authenticated()
 
     @classmethod
+    @transaction.commit_on_success
     def create(cls, creator, text, *args, **kwargs):
         b = cls.objects.create(*args, **kwargs)
         b.chunk_set.all().update(creator=creator)
     def create(cls, creator, text, *args, **kwargs):
         b = cls.objects.create(*args, **kwargs)
         b.chunk_set.all().update(creator=creator)
@@ -91,6 +92,7 @@ class Book(models.Model):
         return self.chunk_set.reverse()[0].split(*args, **kwargs)
 
     @classmethod
         return self.chunk_set.reverse()[0].split(*args, **kwargs)
 
     @classmethod
+    @transaction.commit_on_success
     def import_xml_text(cls, text=u'', previous_book=None,
                 commit_args=None, **kwargs):
         """Imports a book from XML, splitting it into chunks as necessary."""
     def import_xml_text(cls, text=u'', previous_book=None,
                 commit_args=None, **kwargs):
         """Imports a book from XML, splitting it into chunks as necessary."""
@@ -137,6 +139,7 @@ class Book(models.Model):
             i += 1
         return new_slug
 
             i += 1
         return new_slug
 
+    @transaction.commit_on_success
     def append(self, other, slugs=None, titles=None):
         """Add all chunks of another book to self."""
         assert self != other
     def append(self, other, slugs=None, titles=None):
         """Add all chunks of another book to self."""
         assert self != other
@@ -184,6 +187,22 @@ class Book(models.Model):
         assert not other.chunk_set.exists()
         other.delete()
 
         assert not other.chunk_set.exists()
         other.delete()
 
+    @transaction.commit_on_success
+    def prepend_history(self, other):
+        """Prepend history from all the other book's chunks to own."""
+        assert self != other
+
+        for i in range(len(self), len(other)):
+            title = u"pusta część %d" % i
+            chunk = self.add(slughifi(title), title)
+            chunk.commit('')
+
+        for i in range(len(other)):
+            self[i].prepend_history(other[i])
+
+        assert not other.chunk_set.exists()
+        other.delete()
+
 
     # State & cache
     # =============
 
     # State & cache
     # =============
index 9d0f36f..b03701f 100755 (executable)
@@ -57,3 +57,16 @@ class ManipulationTests(TestCase):
             self.book1.append(Book.objects.get(pk=self.book1.pk))
         self.assertEqual(Book.objects.all().count(), 2)
         self.assertEqual(len(self.book1), 1)
             self.book1.append(Book.objects.get(pk=self.book1.pk))
         self.assertEqual(Book.objects.all().count(), 2)
         self.assertEqual(len(self.book1), 1)
+
+    def test_prepend_history(self):
+        self.book1.prepend_history(self.book2)
+        self.assertEqual(Book.objects.all().count(), 1)
+        self.assertEqual(len(self.book1), 1)
+        self.assertEqual(self.book1.materialize(), 'book 1')
+
+    def test_prepend_history_to_self(self):
+        with self.assertRaises(AssertionError):
+            self.book1.prepend_history(self.book1)
+        self.assertEqual(Book.objects.all().count(), 2)
+        self.assertEqual(self.book1.materialize(), 'book 1')
+        self.assertEqual(self.book2.materialize(), 'book 2')
index bb79627..3991efc 100644 (file)
@@ -4,7 +4,7 @@ import os.path
 from django.contrib.auth.models import User
 from django.core.files.base import ContentFile
 from django.core.files.storage import FileSystemStorage
 from django.contrib.auth.models import User
 from django.core.files.base import ContentFile
 from django.core.files.storage import FileSystemStorage
-from django.db import models
+from django.db import models, transaction
 from django.db.models.base import ModelBase
 from django.utils.translation import ugettext_lazy as _
 from mercurial import mdiff, simplemerge
 from django.db.models.base import ModelBase
 from django.utils.translation import ugettext_lazy as _
 from mercurial import mdiff, simplemerge
@@ -324,3 +324,14 @@ class Document(models.Model):
             return changes.order_by('-created_at')[0]
         else:
             return None
             return changes.order_by('-created_at')[0]
         else:
             return None
+
+    @transaction.commit_on_success
+    def prepend_history(self, other):
+        """Takes over the the other document's history and prepends to own."""
+
+        assert self != other
+        other_revs = other.change_set.all().count()
+        self.change_set.all().update(revision=models.F('revision') + other_revs)
+        other.change_set.all().update(tree=self)
+        assert not other.change_set.exists()
+        other.delete()
index 1809a18..868f00a 100755 (executable)
@@ -157,3 +157,22 @@ class DocumentModelTests(TestCase):
         c3 = doc.commit(description="Commit B1", text=text_b1, parent=c1)
         c4 = doc.commit(description="Commit C1", text=text_c1, parent=c1)
         self.assertTextEqual(doc.materialize(), text_merged)
         c3 = doc.commit(description="Commit B1", text=text_b1, parent=c1)
         c4 = doc.commit(description="Commit C1", text=text_c1, parent=c1)
         self.assertTextEqual(doc.materialize(), text_merged)
+
+
+    def test_prepend_history(self):
+        doc1 = ADocument.objects.create()
+        doc2 = ADocument.objects.create()
+        doc1.commit(text='Commit 1')
+        doc2.commit(text='Commit 2')
+        doc2.prepend_history(doc1)
+        self.assertEqual(ADocument.objects.all().count(), 1)
+        self.assertTextEqual(doc2.at_revision(1).materialize(), 'Commit 1')
+        self.assertTextEqual(doc2.materialize(), 'Commit 2')
+
+    def test_prepend_to_self(self):
+        doc = ADocument.objects.create()
+        doc.commit(text='Commit 1')
+        with self.assertRaises(AssertionError):
+            doc.prepend_history(doc)
+        self.assertTextEqual(doc.materialize(), 'Commit 1')
+