appending a book. TODO: remove old dir, remove dupes.
authorMarcin Koziej <marcin@lolownia.org>
Tue, 15 May 2012 00:12:52 +0000 (02:12 +0200)
committerMarcin Koziej <marcin@lolownia.org>
Tue, 15 May 2012 00:12:52 +0000 (02:12 +0200)
apps/catalogue/models/book.py
apps/catalogue/tests/__init__.py

index ade9a42..098781d 100755 (executable)
@@ -7,15 +7,19 @@ from django.contrib.sites.models import Site
 from django.db import models, transaction
 from django.template.loader import render_to_string
 from django.utils.translation import ugettext_lazy as _
 from django.db import models, transaction
 from django.template.loader import render_to_string
 from django.utils.translation import ugettext_lazy as _
+from django.conf import settings
 from slughifi import slughifi
 
 from slughifi import slughifi
 
+
 import apiclient
 from catalogue.helpers import cached_in_field
 from catalogue.models import BookPublishRecord, ChunkPublishRecord
 from catalogue.signals import post_publish
 from catalogue.tasks import refresh_instance, book_content_updated
 from catalogue.xml_tools import compile_text, split_xml
 import apiclient
 from catalogue.helpers import cached_in_field
 from catalogue.models import BookPublishRecord, ChunkPublishRecord
 from catalogue.signals import post_publish
 from catalogue.tasks import refresh_instance, book_content_updated
 from catalogue.xml_tools import compile_text, split_xml
-
+import os
+import shutil
+import re
 
 class Book(models.Model):
     """ A document edited on the wiki """
 
 class Book(models.Model):
     """ A document edited on the wiki """
@@ -191,8 +195,90 @@ class Book(models.Model):
             chunk.save()
             number += 1
         assert not other.chunk_set.exists()
             chunk.save()
             number += 1
         assert not other.chunk_set.exists()
+
+        self.append_gallery(other, len_other)
+        
         other.delete()
 
         other.delete()
 
+
+    def append_gallery(self, other, len_other):
+        if self.gallery is None:
+            self.gallery = other.gallery
+            return
+        if other.gallery is None:
+            return
+        
+        def get_prefix(name):
+            m = re.match(r"^([0-9])-", name)
+            if m:
+                return int(m.groups()[0])
+            return None
+        
+        def set_prefix(name, prefix, always=False):
+            m = not always and re.match(r"^([0-9])-", name)
+            return "%1d-%s" % (prefix, m and name[2:] or name)
+
+        files = os.listdir(os.path.join(settings.MEDIA_ROOT,
+                                        settings.IMAGE_DIR, self.gallery))
+        files_other = os.listdir(os.path.join(settings.MEDIA_ROOT,
+                                              settings.IMAGE_DIR, other.gallery))
+
+        prefixes = {}
+        renamed_files = {}
+        renamed_files_other = {}
+        last_pfx = -1
+
+        # check if all elements of my files have a prefix
+        files_prefixed = True
+        for f in files:
+            p = get_prefix(f)
+            if p:
+                if p > last_pfx: last_pfx = p
+            else:
+                files_prefixed = False
+                break
+
+        # if not, add a 0 prefix to them
+        if not files_prefixed:
+            prefixes[0] = 0
+            for f in files:
+                renamed_files[f] = set_prefix(f, 0, True)
+
+        # two cases here - either all are prefixed or not.
+        files_other_prefixed = True
+        for f in files_other:
+            pfx = get_prefix(f)
+            if pfx is not None:
+                if not pfx in prefixes:
+                    last_pfx += 1
+                    prefixes[pfx] = last_pfx
+                renamed_files_other[f] = set_prefix(f, prefixes[pfx])
+            else:
+                # ops, not all files here were prefixed.
+                files_other_prefixed = False
+                break
+
+        # just set a 1- prefix to all of them
+        if not files_other_prefixed:
+            for f in files_other:
+                renamed_files_other[f] = set_prefix(f, 1, True)
+
+        # finally, move / rename files.
+        for frm, to in renamed_files.items():
+            shutil.move(os.path.join(settings.MEDIA_ROOT, settings.IMAGE_DIR, self.gallery, frm),
+                        os.path.join(settings.MEDIA_ROOT, settings.IMAGE_DIR, self.gallery, to))
+        for frm, to in renamed_files_other.items():
+            shutil.move(os.path.join(settings.MEDIA_ROOT, settings.IMAGE_DIR, other.gallery, frm),
+                        os.path.join(settings.MEDIA_ROOT, settings.IMAGE_DIR, self.gallery, to))            
+
+        # and move the gallery starts
+        num_files = len(files)
+        for chunk in self[len(self) - len_other:]:
+            chunk.gallery_start += num_files
+            chunk.save()
+            
+
+
     @transaction.commit_on_success
     def prepend_history(self, other):
         """Prepend history from all the other book's chunks to own."""
     @transaction.commit_on_success
     def prepend_history(self, other):
         """Prepend history from all the other book's chunks to own."""
index 600dbd2..91c3f81 100755 (executable)
@@ -1,10 +1,12 @@
-from os.path import abspath, dirname, join
+from os.path import abspath, dirname, join, basename, exists
+from os import makedirs, listdir
 from nose.tools import *
 from mock import patch
 from django.test import TestCase
 from django.contrib.auth.models import User
 from catalogue.models import Book, BookPublishRecord
 from nose.tools import *
 from mock import patch
 from django.test import TestCase
 from django.contrib.auth.models import User
 from catalogue.models import Book, BookPublishRecord
-
+from tempfile import mkdtemp
+from django.conf import settings
 
 def get_fixture(path):
     f_path = join(dirname(abspath(__file__)), 'files', path)
 
 def get_fixture(path):
     f_path = join(dirname(abspath(__file__)), 'files', path)
@@ -82,3 +84,131 @@ class ManipulationTests(TestCase):
         self.assertEqual(
                 Book.objects.get(slug='book3').materialize(),
                 'I survived!')
         self.assertEqual(
                 Book.objects.get(slug='book3').materialize(),
                 'I survived!')
+
+
+class GalleryAppendTests(TestCase):
+    def setUp(self):
+        self.user = User.objects.create(username='tester')
+        self.book1 = Book.create(self.user, 'book 1', slug='book1')
+        self.book1.chunk_set.create(number=2, title='Second chunk',
+                slug='book 1 / 2')
+        c=self.book1[0]
+        c.gallery_start=0
+        c=self.book1[1]
+        c.gallery_start=2
+        
+        self.scandir = join(settings.MEDIA_ROOT, settings.IMAGE_DIR)
+        if not exists(self.scandir):
+            makedirs(self.scandir)
+
+    def make_gallery(self, book, files):
+        d = mkdtemp('gallery', dir=self.scandir)
+        for named, cont in files.items():
+            f = open(join(d, named), 'w')
+            f.write(cont)
+            f.close()
+        book.gallery = basename(d)
+
+
+    def test_both_indexed(self):
+        self.book2 = Book.create(self.user, 'book 2', slug='book2')
+        self.book2.chunk_set.create(number=2, title='Second chunk of second book',
+                slug='book 2 / 2')
+        c = self.book2[0]
+        c.gallery_start = 0
+        c = self.book2[1]
+        c.gallery_start = 2
+        import nose.tools; nose.tools.set_trace()
+        self.make_gallery(self.book1, {
+            '1-0001_1l' : 'aa',
+            '1-0001_2r' : 'bb',
+            '1-0002_1l' : 'cc',
+            '1-0002_2r' : 'dd',
+            })
+
+        self.make_gallery(self.book2, {
+            '1-0001_1l' : 'ee',
+            '1-0001_2r' : 'ff',
+            '2-0002_1l' : 'gg',
+            '2-0002_2r' : 'hh',
+            })
+
+        self.book1.append(self.book2)
+
+        files = listdir(join(self.scandir, self.book1.gallery))
+        self.assertEqual(files, [
+            '1-0001_1l',
+            '1-0001_2r',
+            '1-0002_1l',
+            '1-0002_2r',
+            '2-0001_1l',
+            '2-0001_2r',
+            '3-0002_1l',
+            '3-0002_2r',
+            ])        
+
+        self.assertEqual((4, 6), (self.book1[2].gallery_start, self.book1[3].gallery_start))
+        
+        
+    def test_none_indexed(self):
+        self.book2 = Book.create(self.user, 'book 2', slug='book2')
+        self.make_gallery(self.book1, {
+            '0001_1l' : 'aa',
+            '0001_2r' : 'bb',
+            '0002_1l' : 'cc',
+            '0002_2r' : 'dd',
+            })
+
+        self.make_gallery(self.book2, {
+            '0001_1l' : 'ee',
+            '0001_2r' : 'ff',
+            '0002_1l' : 'gg',
+            '0002_2r' : 'hh',
+            })
+
+        self.book1.append(self.book2)
+
+        files = listdir(join(self.scandir, self.book1.gallery))
+        print files
+        self.assertEqual(files, [
+            '0-0001_1l',
+            '0-0001_2r',
+            '0-0002_1l',
+            '0-0002_2r',
+            '1-0001_1l',
+            '1-0001_2r',
+            '1-0002_1l',
+            '1-0002_2r',
+            ])        
+
+
+    def test_none_indexed(self):
+        self.book2 = Book.create(self.user, 'book 2', slug='book2')
+        self.make_gallery(self.book1, {
+            '1-0001_1l' : 'aa',
+            '1-0001_2r' : 'bb',
+            '1002_1l' : 'cc',
+            '1002_2r' : 'dd',
+            })
+
+        self.make_gallery(self.book2, {
+            '0001_1l' : 'ee',
+            '0001_2r' : 'ff',
+            '0002_1l' : 'gg',
+            '0002_2r' : 'hh',
+            })
+
+        self.book1.append(self.book2)
+
+        files = listdir(join(self.scandir, self.book1.gallery))
+        print files
+        self.assertEqual(files, [
+            '0-1-0001_1l',
+            '0-1-0001_2r',
+            '0-1002_1l',
+            '0-1002_2r',
+            '1-0001_1l',
+            '1-0001_2r',
+            '1-0002_1l',
+            '1-0002_2r',
+            ])