Updated API tests.
authorŁukasz Rekucki <lrekucki@gmail.com>
Fri, 25 Sep 2009 15:18:54 +0000 (17:18 +0200)
committerŁukasz Rekucki <lrekucki@gmail.com>
Fri, 25 Sep 2009 15:18:54 +0000 (17:18 +0200)
Handlers refactor.
Addded Toolbar API.

134 files changed:
apps/api/handlers.py [deleted file]
apps/api/handlers/__init__.py [new file with mode: 0644]
apps/api/handlers/library_handlers.py [new file with mode: 0644]
apps/api/handlers/toolbar_handlers.py [new file with mode: 0644]
apps/api/resources.py [new file with mode: 0644]
apps/api/tests/__init__.py
apps/api/tests/data/clean/$meta [new file with mode: 0644]
apps/api/tests/data/clean/.hg/00changelog.i [new file with mode: 0644]
apps/api/tests/data/clean/.hg/dirstate [new file with mode: 0644]
apps/api/tests/data/clean/.hg/requires [new file with mode: 0644]
apps/api/tests/data/clean/.hg/store/00changelog.i [new file with mode: 0644]
apps/api/tests/data/clean/.hg/store/00manifest.i [new file with mode: 0644]
apps/api/tests/data/clean/.hg/store/data/$meta.i [new file with mode: 0644]
apps/api/tests/data/clean/.hg/store/data/.hgignore.i [new file with mode: 0644]
apps/api/tests/data/clean/.hg/store/data/.hgtags.i [new file with mode: 0644]
apps/api/tests/data/clean/.hg/store/fncache [new file with mode: 0644]
apps/api/tests/data/clean/.hg/store/undo [new file with mode: 0644]
apps/api/tests/data/clean/.hg/undo.branch [new file with mode: 0644]
apps/api/tests/data/clean/.hg/undo.dirstate [new file with mode: 0644]
apps/api/tests/data/clean/.hgignore [new file with mode: 0644]
apps/api/tests/data/clean/.hgtags [new file with mode: 0644]
apps/api/tests/data/empty/.hg/00changelog.i [deleted file]
apps/api/tests/data/empty/.hg/branchheads.cache [deleted file]
apps/api/tests/data/empty/.hg/dirstate [deleted file]
apps/api/tests/data/empty/.hg/requires [deleted file]
apps/api/tests/data/empty/.hg/store/00changelog.i [deleted file]
apps/api/tests/data/empty/.hg/store/00manifest.i [deleted file]
apps/api/tests/data/empty/.hg/store/data/.library.i [deleted file]
apps/api/tests/data/empty/.hg/store/fncache [deleted file]
apps/api/tests/data/empty/.hg/store/undo [deleted file]
apps/api/tests/data/empty/.hg/undo.branch [deleted file]
apps/api/tests/data/empty/.hg/undo.dirstate [deleted file]
apps/api/tests/data/empty/.library [deleted file]
apps/api/tests/data/simple/$meta [new file with mode: 0644]
apps/api/tests/data/simple/.hg/00changelog.i [new file with mode: 0644]
apps/api/tests/data/simple/.hg/branch [new file with mode: 0644]
apps/api/tests/data/simple/.hg/branchheads.cache [new file with mode: 0644]
apps/api/tests/data/simple/.hg/dirstate [new file with mode: 0644]
apps/api/tests/data/simple/.hg/requires [new file with mode: 0644]
apps/api/tests/data/simple/.hg/store/00changelog.i [new file with mode: 0644]
apps/api/tests/data/simple/.hg/store/00manifest.i [new file with mode: 0644]
apps/api/tests/data/simple/.hg/store/data/$meta.i [new file with mode: 0644]
apps/api/tests/data/simple/.hg/store/data/.hgignore.i [new file with mode: 0644]
apps/api/tests/data/simple/.hg/store/data/.hgtags.i [new file with mode: 0644]
apps/api/tests/data/simple/.hg/store/data/sample.parts.i [new file with mode: 0644]
apps/api/tests/data/simple/.hg/store/data/sample.xml.i [new file with mode: 0644]
apps/api/tests/data/simple/.hg/store/data/sample__pl.xml.i [new file with mode: 0644]
apps/api/tests/data/simple/.hg/store/fncache [new file with mode: 0644]
apps/api/tests/data/simple/.hg/store/undo [new file with mode: 0644]
apps/api/tests/data/simple/.hg/strip-backup/26716f931d95-backup [new file with mode: 0644]
apps/api/tests/data/simple/.hg/undo.branch [new file with mode: 0644]
apps/api/tests/data/simple/.hg/undo.dirstate [new file with mode: 0644]
apps/api/tests/data/simple/.hgignore [new file with mode: 0644]
apps/api/tests/data/simple/.hgtags [new file with mode: 0644]
apps/api/tests/data/test2/.hg/00changelog.i [deleted file]
apps/api/tests/data/test2/.hg/branch [deleted file]
apps/api/tests/data/test2/.hg/branchheads.cache [deleted file]
apps/api/tests/data/test2/.hg/dirstate [deleted file]
apps/api/tests/data/test2/.hg/requires [deleted file]
apps/api/tests/data/test2/.hg/store/00changelog.i [deleted file]
apps/api/tests/data/test2/.hg/store/00manifest.i [deleted file]
apps/api/tests/data/test2/.hg/store/data/.library.i [deleted file]
apps/api/tests/data/test2/.hg/store/data/pub__testfile.xml.i [deleted file]
apps/api/tests/data/test2/.hg/store/fncache [deleted file]
apps/api/tests/data/test2/.hg/store/undo [deleted file]
apps/api/tests/data/test2/.hg/undo.branch [deleted file]
apps/api/tests/data/test2/.hg/undo.dirstate [deleted file]
apps/api/tests/data/test2/.library [deleted file]
apps/api/tests/data/test2/pub_testfile.xml [deleted file]
apps/api/tests/data/testone/.hg/00changelog.i [deleted file]
apps/api/tests/data/testone/.hg/branchheads.cache [deleted file]
apps/api/tests/data/testone/.hg/dirstate [deleted file]
apps/api/tests/data/testone/.hg/requires [deleted file]
apps/api/tests/data/testone/.hg/store/00changelog.i [deleted file]
apps/api/tests/data/testone/.hg/store/00manifest.i [deleted file]
apps/api/tests/data/testone/.hg/store/data/.library.i [deleted file]
apps/api/tests/data/testone/.hg/store/data/pub__testfile.xml.i [deleted file]
apps/api/tests/data/testone/.hg/store/fncache [deleted file]
apps/api/tests/data/testone/.hg/store/undo [deleted file]
apps/api/tests/data/testone/.hg/undo.branch [deleted file]
apps/api/tests/data/testone/.hg/undo.dirstate [deleted file]
apps/api/tests/data/testone/.library [deleted file]
apps/api/tests/data/testone/pub_testfile.xml [deleted file]
apps/api/urls.py
apps/toolbar/models.py
apps/wysiwyg/__init__.py [new file with mode: 0644]
apps/wysiwyg/models.py [new file with mode: 0644]
apps/wysiwyg/tests.py [new file with mode: 0644]
apps/wysiwyg/urls.py [new file with mode: 0644]
apps/wysiwyg/views.py [new file with mode: 0644]
lib/wlrepo/__init__.py
lib/wlrepo/backend_mercurial.py
lib/wlrepo/mercurial_backend/__init__.py [new file with mode: 0644]
lib/wlrepo/mercurial_backend/document.py [new file with mode: 0644]
lib/wlrepo/mercurial_backend/library.py [new file with mode: 0644]
lib/wlrepo/tests/data/clean/$meta [new file with mode: 0644]
lib/wlrepo/tests/data/clean/.hg/dirstate
lib/wlrepo/tests/data/clean/.hg/store/00changelog.i
lib/wlrepo/tests/data/clean/.hg/store/00manifest.i
lib/wlrepo/tests/data/clean/.hg/store/data/$meta.i [new file with mode: 0644]
lib/wlrepo/tests/data/clean/.hg/store/data/ignored__file.i [deleted file]
lib/wlrepo/tests/data/clean/.hg/store/data/pub__valid__file.xml.i [deleted file]
lib/wlrepo/tests/data/clean/.hg/store/fncache
lib/wlrepo/tests/data/clean/.hg/store/undo
lib/wlrepo/tests/data/clean/.hg/undo.dirstate
lib/wlrepo/tests/data/clean/ignored_file [deleted file]
lib/wlrepo/tests/data/clean/pub_valid_file.xml [deleted file]
lib/wlrepo/tests/data/simple/$meta [new file with mode: 0644]
lib/wlrepo/tests/data/simple/.hg/branch [new file with mode: 0644]
lib/wlrepo/tests/data/simple/.hg/branchheads.cache [new file with mode: 0644]
lib/wlrepo/tests/data/simple/.hg/dirstate
lib/wlrepo/tests/data/simple/.hg/store/00changelog.i
lib/wlrepo/tests/data/simple/.hg/store/00manifest.i
lib/wlrepo/tests/data/simple/.hg/store/data/$meta.i [new file with mode: 0644]
lib/wlrepo/tests/data/simple/.hg/store/data/.hgtags.i [new file with mode: 0644]
lib/wlrepo/tests/data/simple/.hg/store/data/ignored__file.i [deleted file]
lib/wlrepo/tests/data/simple/.hg/store/data/pub__polish__file.xml.i [deleted file]
lib/wlrepo/tests/data/simple/.hg/store/data/pub__valid__file.xml.i [deleted file]
lib/wlrepo/tests/data/simple/.hg/store/data/sample.parts.i [new file with mode: 0644]
lib/wlrepo/tests/data/simple/.hg/store/data/sample.xml.i [new file with mode: 0644]
lib/wlrepo/tests/data/simple/.hg/store/data/sample__pl.xml.i [new file with mode: 0644]
lib/wlrepo/tests/data/simple/.hg/store/fncache
lib/wlrepo/tests/data/simple/.hg/store/undo
lib/wlrepo/tests/data/simple/.hg/strip-backup/26716f931d95-backup [new file with mode: 0644]
lib/wlrepo/tests/data/simple/.hg/undo.dirstate
lib/wlrepo/tests/data/simple/.hgtags [new file with mode: 0644]
lib/wlrepo/tests/data/simple/ignored_file [deleted file]
lib/wlrepo/tests/data/simple/pub_polish_file.xml [deleted file]
lib/wlrepo/tests/data/simple/pub_valid_file.xml [deleted file]
lib/wlrepo/tests/test_mercurial.py
project/settings.py
project/templates/manager/pull_request.html [new file with mode: 0644]
project/templates/toolbar_api/scriptlets.js [new file with mode: 0644]
project/templates/wysiwyg.html [new file with mode: 0644]

diff --git a/apps/api/handlers.py b/apps/api/handlers.py
deleted file mode 100644 (file)
index 9a54ce8..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-from piston.handler import BaseHandler, AnonymousBaseHandler
-from piston.utils import rc, validate
-
-import settings
-import librarian
-import api.forms as forms
-from datetime import date
-
-from django.core.urlresolvers import reverse
-from wlrepo import MercurialLibrary, CabinetNotFound
-
-from librarian import dcparser
-
-#
-# Document List Handlers
-#
-class BasicLibraryHandler(AnonymousBaseHandler):
-    allowed_methods = ('GET',)
-
-    def read(self, request):
-        """Return the list of documents."""
-        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
-        cab = lib.main_cabinet
-
-        document_list = [{
-            'url': reverse('document_view', args=[docid]),
-            'name': docid } for docid in cab.documents() ]
-
-        return {
-            'cabinet': cab.name,
-            'latest_rev': cab.shelf(),
-            'documents' : document_list }
-
-class LibraryHandler(BaseHandler):
-    allowed_methods = ('GET', 'POST')
-    anonymous = BasicLibraryHandler
-
-    def read(self, request):
-        """Return the list of documents."""
-        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
-        cab = lib.main_cabinet
-
-        document_list = [{
-            'url': reverse('document_view', args=[docid]),
-            'name': docid } for docid in cab.documents() ]
-
-        return {
-            'cabinet': cab.name,
-            'latest_rev': cab.shelf(),
-            'documents' : document_list }
-
-    def create(self, request):
-        """Create a new document."""
-        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
-        cab = lib.main_cabinet
-
-        form = forms.DocumentUploadForm(request.POST, request.FILES)
-        if not form.is_valid():
-            return rc.BAD_REQUEST
-
-        f = request.FILES['ocr']
-        data = f.read().decode('utf-8')
-
-        if form.cleaned_data['generate_dc']:
-            data = librarian.wrap_text(data, unicode(date.today()))
-
-        # TODO: what if the file exists ?
-        doc = cab.create(form.cleaned_data['bookname'], initial_data=data)
-        
-        return {
-            'url': reverse('document_view', args=[doc.name]),
-            'name': doc.name,
-            'size': doc.size,
-            'revision': doc.shelf() }
-
-#
-# Document Handlers
-#
-class BasicDocumentHandler(AnonymousBaseHandler):
-    allowed_methods = ('GET',)
-
-    def read(self, request, docid):
-        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
-
-        opts = forms.DocumentGetForm(request.GET)
-        if not opts.is_valid():
-            return rc.BAD_REQUEST
-
-        document = lib.main_cabinet.retrieve(docid)        
-
-        result = {
-            'name': document.name,
-            'size': document.size,
-            'text_url': reverse('doctext_view', args=[docid]),
-            #'dc_url': reverse('docdc_view', docid=document.name),
-            #'parts_url': reverse('docparts_view', docid=document.name),
-            'latest_rev': document.shelf(),          
-        }
-
-        if request.GET.get('with_part', 'no') == 'yes':
-            result['parts'] = document.parts()
-
-        return result   
-
-#
-# Document Meta Data
-#
-class DocumentHandler(BaseHandler):
-    allowed_methods = ('GET', 'PUT')
-    anonymous = BasicDocumentHandler
-    
-    def read(self, request, docid):
-        """Read document's meta data"""        
-        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
-
-        opts = forms.DocumentGetForm(request.GET)
-        if not opts.is_valid():
-            return rc.BAD_REQUEST
-              
-        document = lib.cabinet(docid, request.user.username, \
-                create=opts.cleaned_data['autocabinet'] ).retrieve()
-
-        if not document:
-            return rc.NOT_HERE
-                
-        shared = lib.main_cabinet.retrieve(docid)
-
-        is_shared = document.ancestorof(shared)
-        # is_uptodate = is_shared or shared.ancestorof(document)
-
-        result = {
-            'name': document.name,
-            'size': document.size,
-            'text_url': reverse('doctext_view', args=[docid]),
-            'dc_url': reverse('docdc_view', args=[docid]),
-            'parts_url': reverse('docparts_view', args=[docid]),
-            'latest_rev': document.shelf(),
-            'latest_shared_rev': shared.shelf(),
-            'shared': is_shared,
-            # 'up_to_date': is_uptodate,
-        }
-
-        #if request.GET.get('with_part', 'no') == 'yes':
-        #    result['parts'] = document.parts()
-
-        return result        
-
-#
-# Document Text View
-#
-class DocumentTextHandler(BaseHandler):
-    allowed_methods = ('GET', 'PUT')
-
-    def read(self, request, docid):
-        """Read document as raw text"""
-        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
-        try:
-            # latest rev
-            # comment
-            return lib.document(docid, request.user.username).read()
-        except CabinetNotFound:
-            return rc.NOT_HERE
-
-    def update(self, request, docid):
-        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
-        try:
-            # check latest REV
-            data = request.PUT['contents']
-            lib.document(docid, request.user.username).write(data)
-            return rc.ALL_OK
-        except (CabinetNotFound, KeyError):
-            return rc.NOT_HERE
-
-
-#
-# Dublin Core handlers
-#
-# @requires librarian
-#
-class DocumentDublinCoreHandler(BaseHandler):
-    allowed_methods = ('GET', 'PUT')
-
-    def read(self, request, docid):
-        """Read document as raw text"""
-        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
-        try:
-            doc = lib.document(docid, request.user.username)
-
-            # TODO: RAL:document should support file-like ops
-            bookinfo = dcparser.BookInfo.from_string(doc.read())
-            return bookinfo.serialize()
-        except CabinetNotFound:
-            return rc.NOT_HERE
-
-    def update(self, request, docid):
-        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
-        try:
-            data = request.PUT['contents']
-            lib.document(docid, request.user.username).write(data)
-            return rc.ALL_OK
-        except (CabinetNotFound, KeyError):
-            return rc.NOT_HERE
-
diff --git a/apps/api/handlers/__init__.py b/apps/api/handlers/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/apps/api/handlers/library_handlers.py b/apps/api/handlers/library_handlers.py
new file mode 100644 (file)
index 0000000..b47d41c
--- /dev/null
@@ -0,0 +1,219 @@
+# -*- encoding: utf-8 -*-
+
+__author__= "Łukasz Rekucki"
+__date__ = "$2009-09-25 15:49:50$"
+__doc__ = "Module documentation."
+
+from piston.handler import BaseHandler, AnonymousBaseHandler
+from piston.utils import rc
+
+import settings
+import librarian
+import api.forms as forms
+from datetime import date
+
+from django.core.urlresolvers import reverse
+from wlrepo import MercurialLibrary, RevisionNotFound
+
+from librarian import dcparser
+
+#
+# Document List Handlers
+#
+class BasicLibraryHandler(AnonymousBaseHandler):
+    allowed_methods = ('GET',)
+
+    def read(self, request):
+        """Return the list of documents."""
+        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
+
+        document_list = [{
+            'url': reverse('document_view', args=[docid]),
+            'name': docid } for docid in lib.documents() ]
+
+        return {'documents' : document_list}
+
+class LibraryHandler(BaseHandler):
+    allowed_methods = ('GET', 'POST')
+    anonymous = BasicLibraryHandler
+
+    def read(self, request):
+        """Return the list of documents."""
+        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
+
+        document_list = [{
+            'url': reverse('document_view', args=[docid]),
+            'name': docid } for docid in lib.documents() ]
+
+        return {'documents' : document_list }
+
+    def create(self, request):
+        """Create a new document."""
+        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
+
+        form = forms.DocumentUploadForm(request.POST, request.FILES)
+        if not form.is_valid():
+            return rc.BAD_REQUEST
+
+        f = request.FILES['ocr']
+        data = f.read().decode('utf-8')
+
+        if form.cleaned_data['generate_dc']:
+            data = librarian.wrap_text(data, unicode(date.today()))
+
+        # TODO: what if the file exists ?
+        doc = lib.document_create(form.cleaned_data['bookname'])
+        doc.quickwrite('xml', data, '$AUTO$ XML data uploaded.',
+            user=request.user.username)
+
+        return {
+            'url': reverse('document_view', args=[doc.id]),
+            'name': doc.id,
+            'revision': doc.revision }
+
+#
+# Document Handlers
+#
+class BasicDocumentHandler(AnonymousBaseHandler):
+    allowed_methods = ('GET',)
+
+    def read(self, request, docid):
+        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
+
+        opts = forms.DocumentGetForm(request.GET)
+        if not opts.is_valid():
+            return rc.BAD_REQUEST
+
+        doc = lib.document(docid)
+
+        result = {
+            'name': doc.id,
+            'text_url': reverse('doctext_view', args=[doc.id]),
+            'dc_url': reverse('docdc_view', docid=doc.id),
+            'latest_rev': doc.revision,
+        }
+
+        return result
+
+#
+# Document Meta Data
+#
+class DocumentHandler(BaseHandler):
+    allowed_methods = ('GET', 'PUT')
+    anonymous = BasicDocumentHandler
+
+    def read(self, request, docid):
+        """Read document's meta data"""
+        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
+
+        opts = forms.DocumentGetForm(request.GET)
+        if not opts.is_valid():
+            return rc.BAD_REQUEST
+
+        try:
+            doc = lib.document(docid)
+            udoc = doc.take(request.user.username)
+        except RevisionNotFound:
+            return rc.NOT_HERE
+
+        # is_shared = udoc.ancestorof(doc)
+        # is_uptodate = is_shared or shared.ancestorof(document)
+
+        result = {
+            'name': udoc.id,
+            'text_url': reverse('doctext_view', args=[udoc.id]),
+            'dc_url': reverse('docdc_view', args=[udoc.id]),
+            'parts_url': reverse('docparts_view', args=[udoc.id]),
+            'latest_rev': udoc.revision,
+            'latest_shared_rev': doc.revision,
+            # 'shared': is_shared,
+            # 'up_to_date': is_uptodate,
+        }
+
+        #if request.GET.get('with_part', 'no') == 'yes':
+        #    result['parts'] = document.parts()
+
+        return result
+
+#
+# Document Text View
+#
+class DocumentTextHandler(BaseHandler):
+    allowed_methods = ('GET', 'PUT')
+
+    def read(self, request, docid):
+        """Read document as raw text"""
+        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
+        try:
+            return lib.document(docid, request.user.username).data('xml')
+        except RevisionNotFound:
+            return rc.NOT_HERE
+
+    def update(self, request, docid):
+        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
+        try:
+            data = request.PUT['contents']
+            prev = request.PUT['revision']
+
+            if request.PUT.has_key('message'):
+                msg = u"$USER$ " + request.PUT['message']
+            else:
+                msg = u"$AUTO$ XML content update."
+
+            current = lib.document(docid, request.user.username)
+            orig = lib.document_for_rev(prev)
+
+            if current != orig:
+                return rc.DUPLICATE_ENTRY
+
+            doc.quickwrite('xml', data, msg)
+
+            return rc.ALL_OK
+        except (RevisionNotFound, KeyError):
+            return rc.NOT_HERE
+
+#
+# Dublin Core handlers
+#
+# @requires librarian
+#
+class DocumentDublinCoreHandler(BaseHandler):
+    allowed_methods = ('GET', 'PUT')
+
+    def read(self, request, docid):
+        """Read document as raw text"""
+        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
+        try:
+            doc = lib.document(docid, request.user.username).data('xml')
+            bookinfo = dcparser.BookInfo.from_string(doc.read())
+
+            return bookinfo.serialize()
+        except RevisionNotFound:
+            return rc.NOT_HERE
+
+    def update(self, request, docid):
+        lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
+        try:
+            bi_json = request.PUT['contents']
+            prev = request.PUT['revision']
+            if request.PUT.has_key('message'):
+                msg = u"$USER$ " + request.PUT['message']
+            else:
+                msg = u"$AUTO$ Dublin core update."
+
+            current = lib.document(docid, request.user.username)
+            orig = lib.document_for_rev(prev)
+
+            if current != orig:
+                return rc.DUPLICATE_ENTRY
+
+            xmldoc = parser.WLDocument.from_string(current.data('xml'))
+            document.book_info = dcparser.BookInfo.from_json(bi_json)
+
+            # zapisz
+            current.quickwrite('xml', document.serialize().encode('utf-8'),\
+                message=msg, user=request.user.username)
+
+            return rc.ALL_OK
+        except (RevisionNotFound, KeyError):
+            return rc.NOT_HERE
diff --git a/apps/api/handlers/toolbar_handlers.py b/apps/api/handlers/toolbar_handlers.py
new file mode 100644 (file)
index 0000000..be77359
--- /dev/null
@@ -0,0 +1,32 @@
+# -*- encoding: utf-8 -*-
+
+__author__= "Łukasz Rekucki"
+__date__ = "$2009-09-25 15:55:33$"
+__doc__ = "Module documentation."
+
+from django.views.generic.simple import direct_to_template
+from piston.handler import BaseHandler
+from piston.utils import rc
+
+import settings
+
+import toolbar.models
+
+class ToolbarHandler(BaseHandler):
+    allowed_methods = ('GET',)
+
+    def read(self, request):
+        groups = toolbar.models.ButtonGroup.objects.all()
+        return [ {'name': g.name, 'position': g.position,\
+            'buttons': g.button_set.all()} for g in groups ]
+            
+            
+class ScriptletsHandler(BaseHandler):
+    allowed_methods = ('GET',)
+
+    def read(self, request):
+        scriptlets = toolbar.models.Scriptlet.objects.all()
+
+        return direct_to_template(request, 'toolbar_api/scriptlets.js',
+            extra_context = {'scriptlets': scriptlets },
+            mimetype='text/javascript' )
\ No newline at end of file
diff --git a/apps/api/resources.py b/apps/api/resources.py
new file mode 100644 (file)
index 0000000..d45fa1d
--- /dev/null
@@ -0,0 +1,39 @@
+# -*- encoding: utf-8 -*-
+
+__author__= "Łukasz Rekucki"
+__date__ = "$2009-09-25 15:53:00$"
+__doc__ = "Module documentation."
+
+from piston.resource import Resource
+from api.utils import DjangoAuth
+
+
+
+
+authdata = {'authentication': DjangoAuth()}
+
+#
+# Library resources
+#
+
+import api.handlers.library_handlers as dh
+library_resource = Resource(dh.LibraryHandler, **authdata)
+document_resource = Resource(dh.DocumentHandler, **authdata)
+document_text_resource = Resource(dh.DocumentTextHandler, **authdata)
+document_dc_resource = Resource(dh.DocumentDublinCoreHandler, **authdata)
+
+#
+# Toolbar resources
+#
+import api.handlers.toolbar_handlers as th
+toolbar_buttons = Resource(th.ToolbarHandler, **authdata)
+scriptlets = Resource(th.ScriptletsHandler, **authdata)
+
+__all__ = [
+    'library_resource',
+    'document_resource',
+    'document_text_resource',
+    'document_dc_resource',
+    'toolbar_buttons',
+    'scriptlets'
+]
\ No newline at end of file
index ca575fe..2292e7d 100644 (file)
@@ -1,10 +1,3 @@
-"""
-This file demonstrates two different styles of tests (one doctest and one
-unittest). These will both pass when you run "manage.py test".
-
-Replace these with more appropriate tests for your application.
-"""
-
 from django.test import TestCase
 from django.test.client import Client
 from django.core.urlresolvers import reverse
 from django.test import TestCase
 from django.test.client import Client
 from django.core.urlresolvers import reverse
@@ -21,8 +14,6 @@ import tempfile
 
 REPO_TEMPLATES = join(dirname(__file__), 'data')
 
 
 REPO_TEMPLATES = join(dirname(__file__), 'data')
 
-
-
 def temprepo(name):
     from functools import wraps
 
 def temprepo(name):
     from functools import wraps
 
@@ -32,7 +23,7 @@ def temprepo(name):
         def decorated(self, *args, **kwargs):
             clean = False
             try:
         def decorated(self, *args, **kwargs):
             clean = False
             try:
-                temp = tempfile.mkdtemp("", "testdir_" )
+                temp = tempfile.mkdtemp("-test", func.__name__)
                 shutil.copytree(join(REPO_TEMPLATES, name), join(temp, 'repo'), False)
                 settings.REPOSITORY_PATH = join(temp, 'repo')
                 func(self, *args, **kwargs)
                 shutil.copytree(join(REPO_TEMPLATES, name), join(temp, 'repo'), False)
                 settings.REPOSITORY_PATH = join(temp, 'repo')
                 func(self, *args, **kwargs)
@@ -43,7 +34,7 @@ def temprepo(name):
                     print self.response
                     print "<<<"
 
                     print self.response
                     print "<<<"
 
-                shutil.rmtree(temp, True)
+                shutil.rmtree(temp, True)
                 settings.REPOSITORY_PATH = ''
            
         return decorated
                 settings.REPOSITORY_PATH = ''
            
         return decorated
@@ -57,27 +48,23 @@ class SimpleTest(TestCase):
         u = User.objects.create_user('admin', 'test@localhost', 'admin')
         u.save()        
 
         u = User.objects.create_user('admin', 'test@localhost', 'admin')
         u.save()        
 
-    @temprepo('empty')
+    @temprepo('clean')
     def test_documents_get_anonymous(self):
         self.response = self.client.get( reverse("document_list_view") )
     def test_documents_get_anonymous(self):
         self.response = self.client.get( reverse("document_list_view") )
-        self.assert_json_response({
-            u'latest_rev': u'e56b2a7e06a97d7c3697fc4295974e0f20a66190',
-            u'documents': [],
-            u'cabinet': u'default',
-        }, exclude=['latest_shared_rev'])
+        self.assert_json_response({            
+            u'documents': [],            
+        })
 
 
-    @temprepo('empty')
+    @temprepo('clean')
     def test_documents_get_with_login(self):
         self.assertTrue(self.client.login(username='admin', password='admin'))
         
         self.response = self.client.get( reverse("document_list_view") )
     def test_documents_get_with_login(self):
         self.assertTrue(self.client.login(username='admin', password='admin'))
         
         self.response = self.client.get( reverse("document_list_view") )
-        self.assert_json_response({            
-            u'latest_rev': u'e56b2a7e06a97d7c3697fc4295974e0f20a66190',
-            u'documents': [],
-            u'cabinet': u'default',
+        self.assert_json_response({                        
+            u'documents': [],            
         })    
 
         })    
 
-    @temprepo('empty')
+    @temprepo('clean')
     def test_documents_post(self):
         self.assertTrue(self.client.login(username='admin', password='admin'))
 
     def test_documents_post(self):
         self.assertTrue(self.client.login(username='admin', password='admin'))
 
@@ -85,8 +72,8 @@ class SimpleTest(TestCase):
         infile.write('0123456789')
         infile.flush()
         infile.seek(0)
         infile.write('0123456789')
         infile.flush()
         infile.seek(0)
-        
-        self.response = self.client.post( reverse("document_list_view"),               
+
+        self.response = self.client.post( reverse("document_list_view"),
         data = {
              'bookname': 'testbook',
              'ocr': infile,
         data = {
              'bookname': 'testbook',
              'ocr': infile,
@@ -94,15 +81,15 @@ class SimpleTest(TestCase):
         })
 
         infile.close()
         })
 
         infile.close()
-        
-        result = self.assert_json_response({
+
+        self.assert_json_response({
             'url': reverse('document_view', args=['testbook']),
             'name': 'testbook',
             'url': reverse('document_view', args=['testbook']),
             'name': 'testbook',
-            'size': 10,
+            'size': 10,
             # can't test revision number, 'cause it's random
         },)
 
             # can't test revision number, 'cause it's random
         },)
 
-    @temprepo('empty')        
+    @temprepo('clean')
     def test_document_creation(self):
         self.assertTrue(self.client.login(username='admin', password='admin'))
 
     def test_document_creation(self):
         self.assertTrue(self.client.login(username='admin', password='admin'))
 
@@ -117,73 +104,82 @@ class SimpleTest(TestCase):
              'ocr': infile,
              'generate_dc': False,
         })
              'ocr': infile,
              'generate_dc': False,
         })
-        
+
         r = self.assert_json_response({
             'url': reverse('document_view', args=['testbook']),
         r = self.assert_json_response({
             'url': reverse('document_view', args=['testbook']),
-            'name': 'testbook',
-            'size': 15,
+            'name': 'testbook',            
             # can't test revision number, 'cause it's random
         })
 
         created_rev = r['revision']
 
         self.response = self.client.get( \
             # can't test revision number, 'cause it's random
         })
 
         created_rev = r['revision']
 
         self.response = self.client.get( \
-            reverse("document_view", args=["testbook"])+'?autocabinet=true' )
+            reverse("document_view", args=["testbook"]) )
 
         result = self.assert_json_response({
             u'latest_shared_rev': created_rev,
 
         result = self.assert_json_response({
             u'latest_shared_rev': created_rev,
-            u'size': 15,
+            u'size': 15,
         })
 
 
         })
 
 
-    @temprepo('testone')
+    @temprepo('simple')
     def test_document_meta_get_with_login(self):
         self.assertTrue(self.client.login(username='admin', password='admin'))
 
         self.response = self.client.get( reverse("document_list_view") )
         self.assert_json_response({
     def test_document_meta_get_with_login(self):
         self.assertTrue(self.client.login(username='admin', password='admin'))
 
         self.response = self.client.get( reverse("document_list_view") )
         self.assert_json_response({
-            u'latest_rev': u'f94a263812dbe46a3a13d5209bb119988d0078d5',
-            u'documents': [{u'url': u'/api/documents/testfile', u'name': u'testfile'}],
-            u'cabinet': u'default',
+            u'latest_rev': u'f94a263812dbe46a3a13d5209bb119988d0078d5',
+            u'documents': [{u'url': u'/api/documents/sample', u'name': u'sample'},
+                {u'url': u'/api/documents/sample_pl', u'name': u'sample_pl'}],
         })
 
         self.response = self.client.get( \
         })
 
         self.response = self.client.get( \
-            reverse("document_view", args=['testfile'])+'?autocabinet=true' )
+            reverse("document_view", args=['sample']) )
 
         self.assert_json_response({
 
         self.assert_json_response({
-            u'latest_shared_rev': u'f94a263812dbe46a3a13d5209bb119988d0078d5',
-            u'text_url': reverse("doctext_view", args=[u'testfile']),
-            u'dc_url': reverse("docdc_view", args=[u'testfile']),
-            u'parts_url': reverse("docparts_view", args=[u'testfile']),
-            u'name': u'testfile',
-            u'size': 20,
+            #u'latest_shared_rev': u'f94a263812dbe46a3a13d5209bb119988d0078d5',
+            u'text_url': reverse("doctext_view", args=[u'sample']),
+            u'dc_url': reverse("docdc_view", args=[u'sample']),
+            # u'parts_url': reverse("docparts_view", args=[u'sample']),
+            u'name': u'sample',
+            u'size': 20,
         })
         })
-        
-        
-    @temprepo('test2')
-    def test_document_text_with_login(self):
-        self.assertTrue(self.client.login(username='admin', password='admin'))
-        
-        self.response = self.client.get( \
-            reverse("doctext_view", args=['testfile']) )
-
-        self.assertEqual(self.response.status_code, 200)
-        self.assertEqual(self.response.content, "Test file contents.\n")
 
 
 
 
-    @temprepo('test2')
-    def test_document_text_update(self):
+    @temprepo('simple')
+    def test_document_text_with_login(self):
         self.assertTrue(self.client.login(username='admin', password='admin'))
         self.assertTrue(self.client.login(username='admin', password='admin'))
-        TEXT = u"Ala ma kota i psa"
-        
-        self.response = self.client.put( \
-            reverse("doctext_view", args=['testfile']), {'contents': TEXT })
-        self.assertEqual(self.response.status_code, 200)
 
         self.response = self.client.get( \
 
         self.response = self.client.get( \
-            reverse("doctext_view", args=['testfile']) )
+            reverse("document_view", args=['sample']) )
+
+        resp = self.assert_json_response({
+            #u'latest_shared_rev': u'f94a263812dbe46a3a13d5209bb119988d0078d5',
+            u'text_url': reverse("doctext_view", args=[u'sample']),
+            u'dc_url': reverse("docdc_view", args=[u'sample']),
+            # u'parts_url': reverse("docparts_view", args=[u'sample']),
+            u'name': u'sample',
+            # u'size': 20,
+        })
+
+        self.response = self.client.get(resp['text_url'])
         self.assertEqual(self.response.status_code, 200)
         self.assertEqual(self.response.status_code, 200)
-        self.assertEqual(self.response.content, TEXT)
+        self.assertEqual(self.response.content, "Ala ma kota\n")
+#
+#
+#    @temprepo('simple')
+#    def test_document_text_update(self):
+#        self.assertTrue(self.client.login(username='admin', password='admin'))
+#        TEXT = u"Ala ma kota i psa"
+#
+#        self.response = self.client.put( \
+#            reverse("doctext_view", args=['testfile']), {'contents': TEXT })
+#        self.assertEqual(self.response.status_code, 200)
+#
+#        self.response = self.client.get( \
+#            reverse("doctext_view", args=['testfile']) )
+#        self.assertEqual(self.response.status_code, 200)
+#        self.assertEqual(self.response.content, TEXT)
 
     def assert_json_response(self, must_have={}, exclude=[]):
         self.assertEqual(self.response.status_code, 200)
 
     def assert_json_response(self, must_have={}, exclude=[]):
         self.assertEqual(self.response.status_code, 200)
diff --git a/apps/api/tests/data/clean/$meta b/apps/api/tests/data/clean/$meta
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/apps/api/tests/data/clean/.hg/00changelog.i b/apps/api/tests/data/clean/.hg/00changelog.i
new file mode 100644 (file)
index 0000000..d3a8311
Binary files /dev/null and b/apps/api/tests/data/clean/.hg/00changelog.i differ
diff --git a/apps/api/tests/data/clean/.hg/dirstate b/apps/api/tests/data/clean/.hg/dirstate
new file mode 100644 (file)
index 0000000..417cb6b
Binary files /dev/null and b/apps/api/tests/data/clean/.hg/dirstate differ
diff --git a/apps/api/tests/data/clean/.hg/requires b/apps/api/tests/data/clean/.hg/requires
new file mode 100644 (file)
index 0000000..5175383
--- /dev/null
@@ -0,0 +1,3 @@
+revlogv1
+store
+fncache
diff --git a/apps/api/tests/data/clean/.hg/store/00changelog.i b/apps/api/tests/data/clean/.hg/store/00changelog.i
new file mode 100644 (file)
index 0000000..671cfac
Binary files /dev/null and b/apps/api/tests/data/clean/.hg/store/00changelog.i differ
diff --git a/apps/api/tests/data/clean/.hg/store/00manifest.i b/apps/api/tests/data/clean/.hg/store/00manifest.i
new file mode 100644 (file)
index 0000000..6f5dfeb
Binary files /dev/null and b/apps/api/tests/data/clean/.hg/store/00manifest.i differ
diff --git a/apps/api/tests/data/clean/.hg/store/data/$meta.i b/apps/api/tests/data/clean/.hg/store/data/$meta.i
new file mode 100644 (file)
index 0000000..2431023
Binary files /dev/null and b/apps/api/tests/data/clean/.hg/store/data/$meta.i differ
diff --git a/apps/api/tests/data/clean/.hg/store/data/.hgignore.i b/apps/api/tests/data/clean/.hg/store/data/.hgignore.i
new file mode 100644 (file)
index 0000000..2431023
Binary files /dev/null and b/apps/api/tests/data/clean/.hg/store/data/.hgignore.i differ
diff --git a/apps/api/tests/data/clean/.hg/store/data/.hgtags.i b/apps/api/tests/data/clean/.hg/store/data/.hgtags.i
new file mode 100644 (file)
index 0000000..74da238
Binary files /dev/null and b/apps/api/tests/data/clean/.hg/store/data/.hgtags.i differ
diff --git a/apps/api/tests/data/clean/.hg/store/fncache b/apps/api/tests/data/clean/.hg/store/fncache
new file mode 100644 (file)
index 0000000..3a7e320
--- /dev/null
@@ -0,0 +1,3 @@
+data/$meta.i
+data/.hgignore.i
+data/.hgtags.i
diff --git a/apps/api/tests/data/clean/.hg/store/undo b/apps/api/tests/data/clean/.hg/store/undo
new file mode 100644 (file)
index 0000000..c86109f
Binary files /dev/null and b/apps/api/tests/data/clean/.hg/store/undo differ
diff --git a/apps/api/tests/data/clean/.hg/undo.branch b/apps/api/tests/data/clean/.hg/undo.branch
new file mode 100644 (file)
index 0000000..331d858
--- /dev/null
@@ -0,0 +1 @@
+default
\ No newline at end of file
diff --git a/apps/api/tests/data/clean/.hg/undo.dirstate b/apps/api/tests/data/clean/.hg/undo.dirstate
new file mode 100644 (file)
index 0000000..f2fcbe2
Binary files /dev/null and b/apps/api/tests/data/clean/.hg/undo.dirstate differ
diff --git a/apps/api/tests/data/clean/.hgignore b/apps/api/tests/data/clean/.hgignore
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/apps/api/tests/data/clean/.hgtags b/apps/api/tests/data/clean/.hgtags
new file mode 100644 (file)
index 0000000..0b06113
--- /dev/null
@@ -0,0 +1 @@
+d5e516ebd357bca24c6afb737e97db3b3d4f111a $branchbase
diff --git a/apps/api/tests/data/empty/.hg/00changelog.i b/apps/api/tests/data/empty/.hg/00changelog.i
deleted file mode 100644 (file)
index d3a8311..0000000
Binary files a/apps/api/tests/data/empty/.hg/00changelog.i and /dev/null differ
diff --git a/apps/api/tests/data/empty/.hg/branchheads.cache b/apps/api/tests/data/empty/.hg/branchheads.cache
deleted file mode 100644 (file)
index 022ec46..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-e56b2a7e06a97d7c3697fc4295974e0f20a66190 0
-e56b2a7e06a97d7c3697fc4295974e0f20a66190 default
diff --git a/apps/api/tests/data/empty/.hg/dirstate b/apps/api/tests/data/empty/.hg/dirstate
deleted file mode 100644 (file)
index 3996f89..0000000
Binary files a/apps/api/tests/data/empty/.hg/dirstate and /dev/null differ
diff --git a/apps/api/tests/data/empty/.hg/requires b/apps/api/tests/data/empty/.hg/requires
deleted file mode 100644 (file)
index 5175383..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-revlogv1
-store
-fncache
diff --git a/apps/api/tests/data/empty/.hg/store/00changelog.i b/apps/api/tests/data/empty/.hg/store/00changelog.i
deleted file mode 100644 (file)
index f636141..0000000
Binary files a/apps/api/tests/data/empty/.hg/store/00changelog.i and /dev/null differ
diff --git a/apps/api/tests/data/empty/.hg/store/00manifest.i b/apps/api/tests/data/empty/.hg/store/00manifest.i
deleted file mode 100644 (file)
index 267c71a..0000000
Binary files a/apps/api/tests/data/empty/.hg/store/00manifest.i and /dev/null differ
diff --git a/apps/api/tests/data/empty/.hg/store/data/.library.i b/apps/api/tests/data/empty/.hg/store/data/.library.i
deleted file mode 100644 (file)
index 2431023..0000000
Binary files a/apps/api/tests/data/empty/.hg/store/data/.library.i and /dev/null differ
diff --git a/apps/api/tests/data/empty/.hg/store/fncache b/apps/api/tests/data/empty/.hg/store/fncache
deleted file mode 100644 (file)
index d4a556e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-data/.library.i
diff --git a/apps/api/tests/data/empty/.hg/store/undo b/apps/api/tests/data/empty/.hg/store/undo
deleted file mode 100644 (file)
index 33dec7f..0000000
Binary files a/apps/api/tests/data/empty/.hg/store/undo and /dev/null differ
diff --git a/apps/api/tests/data/empty/.hg/undo.branch b/apps/api/tests/data/empty/.hg/undo.branch
deleted file mode 100644 (file)
index 331d858..0000000
+++ /dev/null
@@ -1 +0,0 @@
-default
\ No newline at end of file
diff --git a/apps/api/tests/data/empty/.hg/undo.dirstate b/apps/api/tests/data/empty/.hg/undo.dirstate
deleted file mode 100644 (file)
index ebf59c6..0000000
Binary files a/apps/api/tests/data/empty/.hg/undo.dirstate and /dev/null differ
diff --git a/apps/api/tests/data/empty/.library b/apps/api/tests/data/empty/.library
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/apps/api/tests/data/simple/$meta b/apps/api/tests/data/simple/$meta
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/apps/api/tests/data/simple/.hg/00changelog.i b/apps/api/tests/data/simple/.hg/00changelog.i
new file mode 100644 (file)
index 0000000..d3a8311
Binary files /dev/null and b/apps/api/tests/data/simple/.hg/00changelog.i differ
diff --git a/apps/api/tests/data/simple/.hg/branch b/apps/api/tests/data/simple/.hg/branch
new file mode 100644 (file)
index 0000000..4ad96d5
--- /dev/null
@@ -0,0 +1 @@
+default
diff --git a/apps/api/tests/data/simple/.hg/branchheads.cache b/apps/api/tests/data/simple/.hg/branchheads.cache
new file mode 100644 (file)
index 0000000..713758b
--- /dev/null
@@ -0,0 +1,4 @@
+65046aefea667e38c7a01d7ca62412d7e81f68bc 2
+d5e516ebd357bca24c6afb737e97db3b3d4f111a default
+00e4aa6f4f53f31020e4d3e0579cb3c0fa0bd056 $doc:sample
+65046aefea667e38c7a01d7ca62412d7e81f68bc $doc:sample_pl
diff --git a/apps/api/tests/data/simple/.hg/dirstate b/apps/api/tests/data/simple/.hg/dirstate
new file mode 100644 (file)
index 0000000..46fefca
Binary files /dev/null and b/apps/api/tests/data/simple/.hg/dirstate differ
diff --git a/apps/api/tests/data/simple/.hg/requires b/apps/api/tests/data/simple/.hg/requires
new file mode 100644 (file)
index 0000000..5175383
--- /dev/null
@@ -0,0 +1,3 @@
+revlogv1
+store
+fncache
diff --git a/apps/api/tests/data/simple/.hg/store/00changelog.i b/apps/api/tests/data/simple/.hg/store/00changelog.i
new file mode 100644 (file)
index 0000000..f245154
Binary files /dev/null and b/apps/api/tests/data/simple/.hg/store/00changelog.i differ
diff --git a/apps/api/tests/data/simple/.hg/store/00manifest.i b/apps/api/tests/data/simple/.hg/store/00manifest.i
new file mode 100644 (file)
index 0000000..fd65f61
Binary files /dev/null and b/apps/api/tests/data/simple/.hg/store/00manifest.i differ
diff --git a/apps/api/tests/data/simple/.hg/store/data/$meta.i b/apps/api/tests/data/simple/.hg/store/data/$meta.i
new file mode 100644 (file)
index 0000000..2431023
Binary files /dev/null and b/apps/api/tests/data/simple/.hg/store/data/$meta.i differ
diff --git a/apps/api/tests/data/simple/.hg/store/data/.hgignore.i b/apps/api/tests/data/simple/.hg/store/data/.hgignore.i
new file mode 100644 (file)
index 0000000..2431023
Binary files /dev/null and b/apps/api/tests/data/simple/.hg/store/data/.hgignore.i differ
diff --git a/apps/api/tests/data/simple/.hg/store/data/.hgtags.i b/apps/api/tests/data/simple/.hg/store/data/.hgtags.i
new file mode 100644 (file)
index 0000000..6c3fcf2
Binary files /dev/null and b/apps/api/tests/data/simple/.hg/store/data/.hgtags.i differ
diff --git a/apps/api/tests/data/simple/.hg/store/data/sample.parts.i b/apps/api/tests/data/simple/.hg/store/data/sample.parts.i
new file mode 100644 (file)
index 0000000..a6bdf46
Binary files /dev/null and b/apps/api/tests/data/simple/.hg/store/data/sample.parts.i differ
diff --git a/apps/api/tests/data/simple/.hg/store/data/sample.xml.i b/apps/api/tests/data/simple/.hg/store/data/sample.xml.i
new file mode 100644 (file)
index 0000000..b115f4d
Binary files /dev/null and b/apps/api/tests/data/simple/.hg/store/data/sample.xml.i differ
diff --git a/apps/api/tests/data/simple/.hg/store/data/sample__pl.xml.i b/apps/api/tests/data/simple/.hg/store/data/sample__pl.xml.i
new file mode 100644 (file)
index 0000000..920c574
Binary files /dev/null and b/apps/api/tests/data/simple/.hg/store/data/sample__pl.xml.i differ
diff --git a/apps/api/tests/data/simple/.hg/store/fncache b/apps/api/tests/data/simple/.hg/store/fncache
new file mode 100644 (file)
index 0000000..c228181
--- /dev/null
@@ -0,0 +1,6 @@
+data/$meta.i
+data/.hgignore.i
+data/sample.parts.i
+data/sample.xml.i
+data/sample_pl.xml.i
+data/.hgtags.i
diff --git a/apps/api/tests/data/simple/.hg/store/undo b/apps/api/tests/data/simple/.hg/store/undo
new file mode 100644 (file)
index 0000000..3ad8b32
Binary files /dev/null and b/apps/api/tests/data/simple/.hg/store/undo differ
diff --git a/apps/api/tests/data/simple/.hg/strip-backup/26716f931d95-backup b/apps/api/tests/data/simple/.hg/strip-backup/26716f931d95-backup
new file mode 100644 (file)
index 0000000..424de92
Binary files /dev/null and b/apps/api/tests/data/simple/.hg/strip-backup/26716f931d95-backup differ
diff --git a/apps/api/tests/data/simple/.hg/undo.branch b/apps/api/tests/data/simple/.hg/undo.branch
new file mode 100644 (file)
index 0000000..331d858
--- /dev/null
@@ -0,0 +1 @@
+default
\ No newline at end of file
diff --git a/apps/api/tests/data/simple/.hg/undo.dirstate b/apps/api/tests/data/simple/.hg/undo.dirstate
new file mode 100644 (file)
index 0000000..310d941
Binary files /dev/null and b/apps/api/tests/data/simple/.hg/undo.dirstate differ
diff --git a/apps/api/tests/data/simple/.hgignore b/apps/api/tests/data/simple/.hgignore
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/apps/api/tests/data/simple/.hgtags b/apps/api/tests/data/simple/.hgtags
new file mode 100644 (file)
index 0000000..0b06113
--- /dev/null
@@ -0,0 +1 @@
+d5e516ebd357bca24c6afb737e97db3b3d4f111a $branchbase
diff --git a/apps/api/tests/data/test2/.hg/00changelog.i b/apps/api/tests/data/test2/.hg/00changelog.i
deleted file mode 100644 (file)
index d3a8311..0000000
Binary files a/apps/api/tests/data/test2/.hg/00changelog.i and /dev/null differ
diff --git a/apps/api/tests/data/test2/.hg/branch b/apps/api/tests/data/test2/.hg/branch
deleted file mode 100644 (file)
index 4ad96d5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-default
diff --git a/apps/api/tests/data/test2/.hg/branchheads.cache b/apps/api/tests/data/test2/.hg/branchheads.cache
deleted file mode 100644 (file)
index 650c9b0..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-93618f13c33aab5a3d049e0860cd3d21a457cd7d 2
-f94a263812dbe46a3a13d5209bb119988d0078d5 default
-93618f13c33aab5a3d049e0860cd3d21a457cd7d personal_admin_file_testfile
diff --git a/apps/api/tests/data/test2/.hg/dirstate b/apps/api/tests/data/test2/.hg/dirstate
deleted file mode 100644 (file)
index cc53c86..0000000
Binary files a/apps/api/tests/data/test2/.hg/dirstate and /dev/null differ
diff --git a/apps/api/tests/data/test2/.hg/requires b/apps/api/tests/data/test2/.hg/requires
deleted file mode 100644 (file)
index 5175383..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-revlogv1
-store
-fncache
diff --git a/apps/api/tests/data/test2/.hg/store/00changelog.i b/apps/api/tests/data/test2/.hg/store/00changelog.i
deleted file mode 100644 (file)
index 4d3d86a..0000000
Binary files a/apps/api/tests/data/test2/.hg/store/00changelog.i and /dev/null differ
diff --git a/apps/api/tests/data/test2/.hg/store/00manifest.i b/apps/api/tests/data/test2/.hg/store/00manifest.i
deleted file mode 100644 (file)
index de39968..0000000
Binary files a/apps/api/tests/data/test2/.hg/store/00manifest.i and /dev/null differ
diff --git a/apps/api/tests/data/test2/.hg/store/data/.library.i b/apps/api/tests/data/test2/.hg/store/data/.library.i
deleted file mode 100644 (file)
index 2431023..0000000
Binary files a/apps/api/tests/data/test2/.hg/store/data/.library.i and /dev/null differ
diff --git a/apps/api/tests/data/test2/.hg/store/data/pub__testfile.xml.i b/apps/api/tests/data/test2/.hg/store/data/pub__testfile.xml.i
deleted file mode 100644 (file)
index ca41781..0000000
Binary files a/apps/api/tests/data/test2/.hg/store/data/pub__testfile.xml.i and /dev/null differ
diff --git a/apps/api/tests/data/test2/.hg/store/fncache b/apps/api/tests/data/test2/.hg/store/fncache
deleted file mode 100644 (file)
index d55636d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-data/.library.i
-data/pub_testfile.xml.i
diff --git a/apps/api/tests/data/test2/.hg/store/undo b/apps/api/tests/data/test2/.hg/store/undo
deleted file mode 100644 (file)
index 33e8207..0000000
Binary files a/apps/api/tests/data/test2/.hg/store/undo and /dev/null differ
diff --git a/apps/api/tests/data/test2/.hg/undo.branch b/apps/api/tests/data/test2/.hg/undo.branch
deleted file mode 100644 (file)
index 998eac4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-personal_admin_file_testfile
\ No newline at end of file
diff --git a/apps/api/tests/data/test2/.hg/undo.dirstate b/apps/api/tests/data/test2/.hg/undo.dirstate
deleted file mode 100644 (file)
index 431d58a..0000000
Binary files a/apps/api/tests/data/test2/.hg/undo.dirstate and /dev/null differ
diff --git a/apps/api/tests/data/test2/.library b/apps/api/tests/data/test2/.library
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/apps/api/tests/data/test2/pub_testfile.xml b/apps/api/tests/data/test2/pub_testfile.xml
deleted file mode 100644 (file)
index 57873f2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Test file contents.
diff --git a/apps/api/tests/data/testone/.hg/00changelog.i b/apps/api/tests/data/testone/.hg/00changelog.i
deleted file mode 100644 (file)
index d3a8311..0000000
Binary files a/apps/api/tests/data/testone/.hg/00changelog.i and /dev/null differ
diff --git a/apps/api/tests/data/testone/.hg/branchheads.cache b/apps/api/tests/data/testone/.hg/branchheads.cache
deleted file mode 100644 (file)
index 6087023..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-f94a263812dbe46a3a13d5209bb119988d0078d5 1
-f94a263812dbe46a3a13d5209bb119988d0078d5 default
diff --git a/apps/api/tests/data/testone/.hg/dirstate b/apps/api/tests/data/testone/.hg/dirstate
deleted file mode 100644 (file)
index e146f18..0000000
Binary files a/apps/api/tests/data/testone/.hg/dirstate and /dev/null differ
diff --git a/apps/api/tests/data/testone/.hg/requires b/apps/api/tests/data/testone/.hg/requires
deleted file mode 100644 (file)
index 5175383..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-revlogv1
-store
-fncache
diff --git a/apps/api/tests/data/testone/.hg/store/00changelog.i b/apps/api/tests/data/testone/.hg/store/00changelog.i
deleted file mode 100644 (file)
index c466ccb..0000000
Binary files a/apps/api/tests/data/testone/.hg/store/00changelog.i and /dev/null differ
diff --git a/apps/api/tests/data/testone/.hg/store/00manifest.i b/apps/api/tests/data/testone/.hg/store/00manifest.i
deleted file mode 100644 (file)
index 0239a8f..0000000
Binary files a/apps/api/tests/data/testone/.hg/store/00manifest.i and /dev/null differ
diff --git a/apps/api/tests/data/testone/.hg/store/data/.library.i b/apps/api/tests/data/testone/.hg/store/data/.library.i
deleted file mode 100644 (file)
index 2431023..0000000
Binary files a/apps/api/tests/data/testone/.hg/store/data/.library.i and /dev/null differ
diff --git a/apps/api/tests/data/testone/.hg/store/data/pub__testfile.xml.i b/apps/api/tests/data/testone/.hg/store/data/pub__testfile.xml.i
deleted file mode 100644 (file)
index ca41781..0000000
Binary files a/apps/api/tests/data/testone/.hg/store/data/pub__testfile.xml.i and /dev/null differ
diff --git a/apps/api/tests/data/testone/.hg/store/fncache b/apps/api/tests/data/testone/.hg/store/fncache
deleted file mode 100644 (file)
index d55636d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-data/.library.i
-data/pub_testfile.xml.i
diff --git a/apps/api/tests/data/testone/.hg/store/undo b/apps/api/tests/data/testone/.hg/store/undo
deleted file mode 100644 (file)
index 0dbe30a..0000000
Binary files a/apps/api/tests/data/testone/.hg/store/undo and /dev/null differ
diff --git a/apps/api/tests/data/testone/.hg/undo.branch b/apps/api/tests/data/testone/.hg/undo.branch
deleted file mode 100644 (file)
index 331d858..0000000
+++ /dev/null
@@ -1 +0,0 @@
-default
\ No newline at end of file
diff --git a/apps/api/tests/data/testone/.hg/undo.dirstate b/apps/api/tests/data/testone/.hg/undo.dirstate
deleted file mode 100644 (file)
index a2fe683..0000000
Binary files a/apps/api/tests/data/testone/.hg/undo.dirstate and /dev/null differ
diff --git a/apps/api/tests/data/testone/.library b/apps/api/tests/data/testone/.library
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/apps/api/tests/data/testone/pub_testfile.xml b/apps/api/tests/data/testone/pub_testfile.xml
deleted file mode 100644 (file)
index 57873f2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Test file contents.
index 913acb7..de09605 100644 (file)
@@ -2,24 +2,21 @@ __author__="lreqc"
 __date__ ="$2009-09-17 16:16:54$"
 
 from django.conf.urls.defaults import *
 __date__ ="$2009-09-17 16:16:54$"
 
 from django.conf.urls.defaults import *
-from piston.resource import Resource
 
 
-from api.handlers import *
-from api.utils import TextEmitter, DjangoAuth
-
-authdata = {'authentication': DjangoAuth()}
+from api.resources import *
 
 FORMAT_EXT = r"\.(?P<emitter_format>xml|json|yaml)$"
 
 
 FORMAT_EXT = r"\.(?P<emitter_format>xml|json|yaml)$"
 
-library_resource = Resource(LibraryHandler, **authdata)
-document_resource = Resource(DocumentHandler, **authdata)
-document_text_resource = Resource(DocumentTextHandler, **authdata)
-document_dc_resource = Resource(DocumentDublinCoreHandler, **authdata)
-
 urlpatterns = patterns('',
 #    url(r'^hello$', hello_resource, {'emitter_format': 'json'}),
 #    url(r'^hello\.(?P<emitter_format>.+)$', hello_resource),
 
 urlpatterns = patterns('',
 #    url(r'^hello$', hello_resource, {'emitter_format': 'json'}),
 #    url(r'^hello\.(?P<emitter_format>.+)$', hello_resource),
 
+    # Toolbar
+    url(r'^toolbar/buttons$', toolbar_buttons, {'emitter_format': 'json'}),
+
+    # Toolbar
+    url(r'^toolbar/scriptlets$', scriptlets, {'emitter_format': 'json'}),
+    
     # Documents
     url(r'^documents$', library_resource,
         {'emitter_format': 'json'}, name="document_list_view"),
     # Documents
     url(r'^documents$', library_resource,
         {'emitter_format': 'json'}, name="document_list_view"),
index d1f4952..0414622 100644 (file)
@@ -14,6 +14,26 @@ class ButtonGroup(models.Model):
     def __unicode__(self):
         return self.name
 
     def __unicode__(self):
         return self.name
 
+
+#class ButtonGroupManager(models.Manager):
+#
+#    def with_buttons(self):
+#        from django.db import connection
+#        cursor = connection.cursor()
+#        cursor.execute("""
+#            SELECT g.name, g.slug, CONCAT(b.slug),
+#            FROM toolbar_buttongroup as g LEFT JOIN toolbar_button as b
+#
+#            WHERE p.id = r.poll_id
+#            GROUP BY 1, 2, 3
+#            ORDER BY 3 DESC""")
+#        result_list = []
+#        for row in cursor.fetchall():
+#            p = self.model(id=row[0], question=row[1], poll_date=row[2])
+#            p.num_responses = row[3]
+#            result_list.append(p)
+#        return result_list
+
 class Button(models.Model):
     label = models.CharField(max_length=32)
     slug = models.SlugField(unique=True) #unused
 class Button(models.Model):
     label = models.CharField(max_length=32)
     slug = models.SlugField(unique=True) #unused
diff --git a/apps/wysiwyg/__init__.py b/apps/wysiwyg/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/apps/wysiwyg/models.py b/apps/wysiwyg/models.py
new file mode 100644 (file)
index 0000000..71a8362
--- /dev/null
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
diff --git a/apps/wysiwyg/tests.py b/apps/wysiwyg/tests.py
new file mode 100644 (file)
index 0000000..2247054
--- /dev/null
@@ -0,0 +1,23 @@
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+    def test_basic_addition(self):
+        """
+        Tests that 1 + 1 always equals 2.
+        """
+        self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
diff --git a/apps/wysiwyg/urls.py b/apps/wysiwyg/urls.py
new file mode 100644 (file)
index 0000000..ca19ea9
--- /dev/null
@@ -0,0 +1,12 @@
+# -*- encoding: utf-8 -*-
+
+__author__= "Łukasz Rekucki"
+__date__ = "$2009-09-23 15:57:38$"
+__doc__ = "Module documentation."
+
+from django.conf.urls.defaults import *
+
+
+urlpatterns = patterns('',
+    (r'^$', 'wysiwyg.views.index'),
+)
diff --git a/apps/wysiwyg/views.py b/apps/wysiwyg/views.py
new file mode 100644 (file)
index 0000000..e588c49
--- /dev/null
@@ -0,0 +1,5 @@
+# Create your views here.
+from django.views.generic.simple import direct_to_template
+
+def index(request):
+    return direct_to_template(request, 'wysiwyg.html', extra_context={})
\ No newline at end of file
index 1c1335e..cbc0c2c 100644 (file)
@@ -1,7 +1,6 @@
 # -*- encoding: utf-8 -*-
 __author__="Łukasz Rekucki"
 __date__ ="$2009-09-18 10:49:24$"
 # -*- encoding: utf-8 -*-
 __author__="Łukasz Rekucki"
 __date__ ="$2009-09-18 10:49:24$"
-
 __doc__ = """Main module for the Repository Abstraction Layer"""
 
 class Library(object):
 __doc__ = """Main module for the Repository Abstraction Layer"""
 
 class Library(object):
@@ -9,157 +8,107 @@ class Library(object):
     def __init__(self, create=False):
         """Open an existing library, or create a new one. By default, fails if
         the library doesn't exist."""
     def __init__(self, create=False):
         """Open an existing library, or create a new one. By default, fails if
         the library doesn't exist."""
-        self.create = create     
-        
-    def main_cabinet(self):
-        """Return the "main" cabinet of the library."""
-        pass
+        self.create = create      
 
 
-    def cabinets(self):
-        """List all cabinets in the library."""
+    def documents(self):
+        """List all documents in the library."""
         pass
 
         pass
 
-    def cabinet(self, document, user, create=False):
-        """Open a cabinet belonging to the _user_ for a given _document_.
-        If the _document_ is actually a sub-document, it's parent's cabinet is
-        opened istead.
-        
-        If the cabinet doesn't exists and create is False (the default), a 
-        CabinetNotFound exception is raised.
-        
-        If create is True, a new cabinet is created if it doesn't exist yet."""
+    def document_for_rev(self, rev):
+        """Retrieve a document in the specified revision."""
         pass
 
         pass
 
-
-    def document(self, docid, user, part=None, shelve=None):
+    def document(self, docid, user=None):
+        """Retrieve a document from a library."""
         pass
 
         pass
 
+    def get_revision(self, revid):
+        """Retrieve a handle to a specified revision."""
+        return None
 
 
-class Cabinet(object):
+    def document_create(self, docid):
+        """Create a new document. The document will have it's own branch."""
+        
+
+class Document(object):
+    """A class representing a document package boundled with a revision."""
 
 
-    def __init__(self, library, name=None, doc=None, user=None):
+    def __init__(self, library, revision):
+        """_library_ should be an instance of a Library."""
         self._library = library
         self._library = library
-        if name:
-            self._name = name
-            self._maindoc = ''
-            self._user = self._document = None
-        elif doc and user:
-            self._user = user
-            self._document = doc
-            self._name = user + ':' + doc
-            self._maindoc = doc
+        if isinstance(revision, Revision):
+            self._revision = revision
         else:
         else:
-            raise ValueError("You must provide either name or doc and user.")
+            self._revision = library.get_revision(revision)
 
 
-        print "new cab:", self._name, self._user, self._document
-
-    @property
-    def username(self):
-        return self._user
 
 
-    def __str__(self):
-        return "Cabinet(%s)" % self._name
-
-    def parts(self):
-        """Lists all parts in this cabinet."""
+    def take(self, user):
+        """Make a user copy of the document. This is persistant."""
         pass
         pass
-    
-    def retrieve(self, part='xml', shelve=None):
-        """Retrieve a document from a given shelve in the cabinet. If no
-        part is given, the main document is retrieved. If no shelve is given,
-        the top-most shelve is used.
 
 
-        If parts is a list, all the given parts are retrieved atomicly. Use None
-        as the name for the main document"""
+    def giveback(self):
+        """Informs the library, that the user no longer needs this document.
+        Should be called on the user version of document. If not, it doesn nothing."""
+       
+    def data(self, entry):
+        """Returns the specified entry as a file-like object."""
         pass
 
         pass
 
-    def create(self, name, initial_data=''):
-        """Create a new part in the cabinet with the given name."""
-        pass
-
-    @property
-    def maindoc_name(self):
-        return self._maindoc
-
     @property
     def library(self):
         return self._library
 
     @property
     @property
     def library(self):
         return self._library
 
     @property
-    def name(self):
-        return self._name
-
-    def shelf(self, selector=None):
-        pass
-
-class Document(object):
-    def __init__(self, cabinet, name):
-        self._cabinet = cabinet
-        self._name = name
-
-    def read(self):
-        pass
-
-    def write(self, data):
-        pass
-
-    @property
-    def cabinet(self):
-        return self._cabinet
+    def revision(self):
+        return self._revision
 
     @property
 
     @property
-    def library(self):
-        return self._cabinet.library
+    def id(self):
+        return self._revision.document_name
 
     @property
 
     @property
-    def name(self):
-        return self._name
-
-    def shelf(self):
-        return self._cabinet.shelf()
-
-    @property
-    def size(self):
-        raise NotImplemented()
-
-    @property
-    def parts(self):
-        raise NotImplemented()
+    def owner(self):
+        return self._revision.user_name
     
     def parentof(self, other):
     
     def parentof(self, other):
-        return self.shelf().parentof(other.shelf())
+        return self._revision.parentof(other._revision)
 
     def ancestorof(self, other):
 
     def ancestorof(self, other):
-        return self.shelf().ancestorof(other.shelf())
+        return self._revision.ancestorof(other._revision)
 
 
 
 
-class Shelf(object):
+class Revision(object):
 
     def __init__(self, lib):
         self._library = lib
 
 
     def __init__(self, lib):
         self._library = lib
 
-
     def parentof(self, other):
         return False
 
     def ancestorof(self, other):
         return False
     def parentof(self, other):
         return False
 
     def ancestorof(self, other):
         return False
-    
+
+    @property
+    def document_name(self):
+        raise ValueError()
+
+    @property
+    def user_name(self):
+        raise ValueError()
+
 #
 # Exception classes
 #
 
 #
 # Exception classes
 #
 
-class LibraryException(Exception):
-    
+class LibraryException(Exception):    
     def __init__(self, msg, cause=None):
         Exception.__init__(self, msg)
         self.cause = cause
 
     def __init__(self, msg, cause=None):
         Exception.__init__(self, msg)
         self.cause = cause
 
-class CabinetNotFound(LibraryException):
-    def __init__(self, cabname):
-        LibraryException.__init__(self, "Cabinet '%s' not found." % cabname)
+class RevisionNotFound(LibraryException):
+    def __init__(self, rev):
+        LibraryException.__init__(self, "Revision %r not found." % rev)
     pass
 
     pass
 
-
 # import backends to local namespace
 # import backends to local namespace
-from backend_mercurial import MercurialLibrary
\ No newline at end of file
+from mercurial_backend.library import MercurialLibrary
\ No newline at end of file
index a082b8b..35e4442 100644 (file)
-# -*- encoding: utf-8 -*-
-
-__author__ = "Łukasz Rekucki"
-__date__ = "$2009-09-18 10:49:24$"
-
-__doc__ = """RAL implementation over Mercurial"""
-
-import mercurial
-from mercurial import localrepo as hglrepo
-from mercurial import ui as hgui
-from mercurial.node import nullid
-import re
-import wlrepo
-
-FILTER = re.compile(r"^pub_(.+)\.xml$", re.UNICODE)
-
-def default_filter(name):
-    m = FILTER.match(name)    
-    if m is not None:
-        return name, m.group(1)
-    return None
-
-class MercurialLibrary(wlrepo.Library):
-
-    def __init__(self, path, maincabinet="default", ** kwargs):
-        super(wlrepo.Library, self).__init__( ** kwargs)
-
-        self._hgui = hgui.ui()
-        self._hgui.config('ui', 'quiet', 'true')
-        self._hgui.config('ui', 'interactive', 'false')
-
-        import os.path        
-        self._ospath = self._sanitize_string(os.path.realpath(path))
-        
-        maincabinet = self._sanitize_string(maincabinet)
-
-        if os.path.isdir(path):
-            try:
-                self._hgrepo = hglrepo.localrepository(self._hgui, path)
-            except mercurial.error.RepoError:
-                raise wlrepo.LibraryException("[HGLibrary] Not a valid repository at path '%s'." % path)
-        elif kwargs.get('create', False):
-            os.makedirs(path)
-            try:
-                self._hgrepo = hglrepo.localrepository(self._hgui, path, create=1)
-            except mercurial.error.RepoError:
-                raise wlrepo.LibraryException("[HGLibrary] Can't create a repository on path '%s'." % path)
-        else:
-            raise wlrepo.LibraryException("[HGLibrary] Can't open a library on path '%s'." % path)
-
-        # fetch the main cabinet
-        lock = self._hgrepo.lock()
-        try:
-            btags = self._hgrepo.branchtags()
-            
-            if not self._has_branch(maincabinet):
-                raise wlrepo.LibraryException("[HGLibrary] No branch named '%s' to init main cabinet" % maincabinet)
-        
-            self._maincab = MercurialCabinet(self, maincabinet)
-        finally:
-            lock.release()
-
-    @property
-    def ospath(self):
-        return self._ospath
-
-    @property
-    def main_cabinet(self):
-        return self._maincab
-
-    def document(self, docid, user, part=None, shelve=None):
-        return self.cabinet(docid, user, create=False).retrieve(part=part, shelve=shelve)
-
-    def cabinet(self, docid, user, create=False):
-        docid = self._sanitize_string(docid)
-        user = self._sanitize_string(user)
-        
-        bname = self._bname(user, docid)
-
-        lock = self._lock(True)
-        try:
-            if self._has_branch(bname):
-                return MercurialCabinet(self, doc=docid, user=user)
-
-            if not create:
-                raise wlrepo.CabinetNotFound(bname)
-
-            # check if the docid exists in the main cabinet
-            needs_touch = not self._maincab.exists(docid)            
-            cab = MercurialCabinet(self, doc=docid, user=user)
-
-            name, fileid = cab._filename(None)
-
-            def cleanup_action(l):
-                if needs_touch:                    
-                    l._fileopener()(fileid, "w").write('')
-                    l._fileadd(fileid)
-                
-                garbage = [fid for (fid, did) in l._filelist() if not did.startswith(docid)]                
-                l._filesrm(garbage)
-                print "removed: ", garbage
-
-            # create the branch
-            self._create_branch(bname, before_commit=cleanup_action)
-            return MercurialCabinet(self, doc=docid, user=user)
-        finally:
-            lock.release()
-            
-    #
-    # Private methods
-    #
-
-    #
-    # Locking
-    #
-    def _lock(self, write_mode=False):
-        return self._hgrepo.wlock() # no support for read/write mode yet
-
-    def _transaction(self, write_mode, action):
-        lock = self._lock(write_mode)
-        try:
-            return action(self)
-        finally:
-            lock.release()
-            
-    #
-    # Basic repo manipulation
-    #   
-
-    def _checkout(self, rev, force=True):
-        return MergeStatus(mercurial.merge.update(self._hgrepo, rev, False, force, None))
-
-    def _merge(self, rev):
-        """ Merge the revision into current working directory """
-        return MergeStatus(mercurial.merge.update(self._hgrepo, rev, True, False, None))
-    
-    def _common_ancestor(self, revA, revB):
-        return self._hgrepo[revA].ancestor(self.repo[revB])
-
-    def _commit(self, message, user=u"library"):
-        return self._hgrepo.commit(text=message, user=user)
-
-
-    def _fileexists(self, fileid):
-        return (fileid in self._hgrepo[None])
-
-    def _fileadd(self, fileid):
-        return self._hgrepo.add([fileid])
-    
-    def _filesadd(self, fileid_list):
-        return self._hgrepo.add(fileid_list)
-
-    def _filerm(self, fileid):
-        return self._hgrepo.remove([fileid])
-
-    def _filesrm(self, fileid_list):
-        return self._hgrepo.remove(fileid_list)
-
-    def _filelist(self, filter=default_filter):
-        for name in  self._hgrepo[None]:
-            result = filter(name)
-            if result is None: continue
-            
-            yield result
-
-    def _fileopener(self):
-        return self._hgrepo.wopener
-
-    def _filectx(self, fileid, branchid):
-        return self._hgrepo.filectx(fileid, changeid=branchid)
-
-    def _changectx(self, nodeid):
-        return self._hgrepo.changectx(nodeid)
-    
-    #
-    # BASIC BRANCH routines
-    #
-
-    def _bname(self, user, docid):
-        """Returns a branch name for a given document and user."""
-        docid = self._sanitize_string(docid)
-        uname = self._sanitize_string(user)
-        return "personal_" + uname + "_file_" + docid;
-
-    def _has_branch(self, name):
-        return self._hgrepo.branchmap().has_key(self._sanitize_string(name))
-
-    def _branch_tip(self, name):
-        name = self._sanitize_string(name)
-        return self._hgrepo.branchtags()[name]
-
-    def _create_branch(self, name, parent=None, before_commit=None):        
-        name = self._sanitize_string(name)
-
-        if self._has_branch(name): return # just exit
-
-        if parent is None:
-            parent = self._maincab
-
-        parentrev = parent._hgtip()
-
-        self._checkout(parentrev)
-        self._hgrepo.dirstate.setbranch(name)
-
-        if before_commit: before_commit(self)
-
-        self._commit("[AUTO] Initial commit for branch '%s'." % name, user='library')
-        
-        # revert back to main
-        self._checkout(self._maincab._hgtip())
-        return self._branch_tip(name)
-
-    def _switch_to_branch(self, branchname):
-        current = self._hgrepo[None].branch()
-
-        if current == branchname:
-            return current # quick exit
-        
-        self._checkout(self._branch_tip(branchname))
-        return branchname        
-
-    def shelf(self, nodeid=None):
-        if nodeid is None:
-            nodeid = self._maincab._name
-        return MercurialShelf(self, self._changectx(nodeid))   
-
-
-    #
-    # Utils
-    #
-
-    @staticmethod
-    def _sanitize_string(s):        
-        if isinstance(s, unicode):
-            s = s.encode('utf-8')
-        return s
-
-class MercurialCabinet(wlrepo.Cabinet):
-    
-    def __init__(self, library, branchname=None, doc=None, user=None):
-        if doc and user:
-            super(MercurialCabinet, self).__init__(library, doc=doc, user=user)
-            self._branchname = library._bname(user=user, docid=doc)
-        elif branchname:
-            super(MercurialCabinet, self).__init__(library, name=branchname)
-            self._branchname = branchname
-        else:
-            raise ValueError("Provide either doc/user or branchname")
-
-    def shelf(self):
-        return self._library.shelf(self._branchname)
-
-    def parts(self):
-        return self._execute_in_branch(action=lambda l, c: (e[1] for e in l._filelist()))
-
-    def retrieve(self, part=None, shelf=None):
-        name, fileid = self._filename(part)
-
-        print "Retrieving document %s from cab %s" % (name, self._name)
-
-        if fileid is None:
-            raise wlrepo.LibraryException("Can't retrieve main document from main cabinet.")
-
-        def retrieve_action(l,c):
-            if l._fileexists(fileid):
-                return MercurialDocument(c, name=name, fileid=fileid)
-            print "File %s not found " % fileid
-            return None
-                
-        return self._execute_in_branch(retrieve_action)        
-
-    def create(self, name, initial_data):
-        name, fileid = self._filename(name)
-
-        if name is None:
-            raise ValueError("Can't create main doc for maincabinet.")
-
-        def create_action(l, c):
-            if l._fileexists(fileid):
-                raise wlrepo.LibraryException("Can't create document '%s' in cabinet '%s' - it already exists" % (fileid, c.name))
-
-            fd = l._fileopener()(fileid, "w")
-            fd.write(initial_data)
-            fd.close()
-            l._fileadd(fileid)            
-            l._commit("File '%s' created." % fileid)            
-            return MercurialDocument(c, fileid=fileid, name=name)           
-
-        return self._execute_in_branch(create_action)
-
-    def exists(self, part=None, shelf=None):
-        name, filepath = self._filename(part)
-
-        if filepath is None: return False
-        return self._execute_in_branch(lambda l, c: l._fileexists(filepath))
-    
-    def _execute_in_branch(self, action, write=False):
-        def switch_action(library):
-            old = library._switch_to_branch(self._branchname)
-            try:
-                return action(library, self)
-            finally:
-                library._switch_to_branch(old)
-
-        return self._library._transaction(write_mode=write, action=switch_action)
-
-
-    def _filename(self, docid):
-        return self._partname(docid, 'xml')
-    
-    def _partname(self, docid, part):
-        docid = self._library._sanitize_string(part)
-        part = self._library._sanitize_string(part)
-
-        if part is None:
-            part = 'xml'
-
-        if self._maindoc == '' and docid is None:
-            return None
-            
-        return 'pub_' + docid + '.' + part
-            
-    def _fileopener(self):
-        return self._library._fileopener()
-
-    def _hgtip(self):
-        return self._library._branch_tip(self._branchname)
-
-    def _filectx(self, fileid):
-        return self._library._filectx(fileid, self._branchname)
-
-    def ismain(self):
-        return (self._library.main_cabinet == self)
-
-class MercurialDocument(wlrepo.Document):
-
-    def __init__(self, cabinet, docid):
-        super(MercurialDocument, self).__init__(cabinet, name=docid)
-        self._opener = self._cabinet._fileopener()
-        self._docid = docid
-        self._ctxs = {}
-
-    def _ctx(self, part):
-        if not self._ctxs.has_key(part):            
-            self._ctxs[part] = self._cabinet._filectx(self._fileid())
-        return self._ctxs[part]
-
-    def _fileid(self, part='xml'):
-        return self._cabinet._partname(self._docid, part)
-
-    def read(self, part='xml'):       
-        return self._opener(self._ctx(part).path(), "r").read()
-
-    def write(self, data, part='xml'):
-        return self._opener(self._ctx(part).path(), "w").write(data)
-
-    def commit(self, message, user):
-        """Commit all parts of the document."""
-        self.library._fileadd(self._fileid)
-        self.library._commit(self._fileid, message, user)
-
-    def update(self):
-        """Update parts of the document."""
-        lock = self.library._lock()
-        try:
-            if self._cabinet.ismain():
-                return True # always up-to-date
-
-            user = self._cabinet.username or 'library'
-            mdoc = self.library.document(self._fileid)
-
-            mshelf = mdoc.shelf()
-            shelf = self.shelf()
-
-            if not mshelf.ancestorof(shelf) and not shelf.parentof(mshelf):
-                shelf.merge_with(mshelf, user=user)
-
-            return True
-        finally:
-            lock.release()            
-
-    def share(self, message):
-        lock = self.library._lock()
-        try:
-            print "sharing from", self._cabinet, self._cabinet.username
-            
-            if self._cabinet.ismain():
-                return True # always shared
-
-            if self._cabinet.username is None:
-                raise ValueError("Can only share documents from personal cabinets.")
-            
-            user = self._cabinet.username
-
-            main = self.library.shelf()
-            local = self.shelf()
-
-            no_changes = True
-
-            # Case 1:
-            #         * local
-            #         |
-            #         * <- can also be here!
-            #        /|
-            #       / |
-            # main *  *
-            #      |  |
-            # The local branch has been recently updated,
-            # so we don't need to update yet again, but we need to
-            # merge down to default branch, even if there was
-            # no commit's since last update
-
-            if main.ancestorof(local):
-                print "case 1"
-                main.merge_with(local, user=user, message=message)
-                no_changes = False
-            # Case 2:
-            #
-            # main *  * local
-            #      |\ |
-            #      | \|
-            #      |  *
-            #      |  |
-            #
-            # Default has no changes, to update from this branch
-            # since the last merge of local to default.
-            elif local.has_common_ancestor(main):
-                print "case 2"
-                if not local.parentof(main):
-                    main.merge_with(local, user=user, message=message)
-                    no_changes = False
-
-            # Case 3:
-            # main *
-            #      |
-            #      * <- this case overlaps with previos one
-            #      |\
-            #      | \
-            #      |  * local
-            #      |  |
-            #
-            # There was a recent merge to the defaul branch and
-            # no changes to local branch recently.
-            #
-            # Use the fact, that user is prepared to see changes, to
-            # update his branch if there are any
-            elif local.ancestorof(main):
-                print "case 3"
-                if not local.parentof(main):
-                    local.merge_with(main, user=user, message='Local branch update.')
-                    no_changes = False
-            else:
-                print "case 4"
-                local.merge_with(main, user=user, message='Local branch update.')
-                local = self.shelf()
-                main.merge_with(local, user=user, message=message)
-
-            print "no_changes: ", no_changes
-            return no_changes
-        finally:
-            lock.release()
-               
-    def shared(self):
-        return self.library.main_cabinet.retrieve(self._name)
-
-    def exists(self, part='xml'):
-        return self._cabinet.exists(self._fileid(part))
-
-    @property
-    def size(self):
-        return self._filectx.size()
-    
-    def shelf(self):
-        return self._cabinet.shelf()
-
-    @property
-    def last_modified(self):
-        return self._filectx.date()
-
-    def __str__(self):
-        return u"Document(%s->%s)" % (self._cabinet.name, self._name)
-
-    def __eq__(self, other):
-        return self._filectx == other._filectx
-
-
-
-class MercurialShelf(wlrepo.Shelf):
-
-    def __init__(self, lib, changectx):
-        super(MercurialShelf, self).__init__(lib)
-
-        if isinstance(changectx, str):
-            self._changectx = lib._changectx(changectx)
-        else:
-            self._changectx = changectx
-
-    @property
-    def _rev(self):
-        return self._changectx.node()
-
-    def __str__(self):
-        return self._changectx.hex()
-
-    def __repr__(self):
-        return "MercurialShelf(%s)" % self._changectx.hex()
-
-    def ancestorof(self, other):
-        nodes = list(other._changectx._parents)
-        while nodes[0].node() != nullid:
-            v = nodes.pop(0)
-            if v == self._changectx:
-                return True
-            nodes.extend( v._parents )
-        return False
-
-    def parentof(self, other):
-        return self._changectx in other._changectx._parents
-
-    def has_common_ancestor(self, other):
-        a = self._changectx.ancestor(other._changectx)
-        # print a, self._changectx.branch(), a.branch()
-
-        return (a.branch() == self._changectx.branch())
-
-    def merge_with(self, other, user, message):
-        lock = self._library._lock(True)
-        try:
-            self._library._checkout(self._changectx.node())
-            self._library._merge(other._changectx.node())
-            self._library._commit(user=user, message=message)
-        finally:
-            lock.release()
-
-    def __eq__(self, other):
-        return self._changectx.node() == other._changectx.node()
-        
-
-class MergeStatus(object):
-    def __init__(self, mstatus):
-        self.updated = mstatus[0]
-        self.merged = mstatus[1]
-        self.removed = mstatus[2]
-        self.unresolved = mstatus[3]
-
-    def isclean(self):
-        return self.unresolved == 0
-
-class UpdateStatus(object):
-
-    def __init__(self, mstatus):
-        self.modified = mstatus[0]
-        self.added = mstatus[1]
-        self.removed = mstatus[2]
-        self.deleted = mstatus[3]
-        self.untracked = mstatus[4]
-        self.ignored = mstatus[5]
-        self.clean = mstatus[6]
-
-    def has_changes(self):
-        return bool(len(self.modified) + len(self.added) + \
-                    len(self.removed) + len(self.deleted))
-
-__all__ = ["MercurialLibrary"]
\ No newline at end of file
+## -*- encoding: utf-8 -*-
+#
+#__author__ = "Łukasz Rekucki"
+#__date__ = "$2009-09-18 10:49:24$"
+#
+#__doc__ = """RAL implementation over Mercurial"""
+#
+#import mercurial
+#from mercurial import localrepo as hglrepo
+#from mercurial import ui as hgui
+#from mercurial.node import nullid
+#import re
+#import wlrepo
+#
+#FILTER = re.compile(r"^pub_(.+)\.xml$", re.UNICODE)
+#
+#def default_filter(name):
+#    m = FILTER.match(name)
+#    if m is not None:
+#        return name, m.group(1)
+#    return None
+#
+#class MercurialLibrary(wlrepo.Library):
+#
+#    def __init__(self, path, maincabinet="default", ** kwargs):
+#        super(wlrepo.Library, self).__init__( ** kwargs)
+#
+#        self._hgui = hgui.ui()
+#        self._hgui.config('ui', 'quiet', 'true')
+#        self._hgui.config('ui', 'interactive', 'false')
+#
+#        import os.path
+#        self._ospath = self._sanitize_string(os.path.realpath(path))
+#
+#        maincabinet = self._sanitize_string(maincabinet)
+#
+#        if os.path.isdir(path):
+#            try:
+#                self._hgrepo = hglrepo.localrepository(self._hgui, path)
+#            except mercurial.error.RepoError:
+#                raise wlrepo.LibraryException("[HGLibrary] Not a valid repository at path '%s'." % path)
+#        elif kwargs.get('create', False):
+#            os.makedirs(path)
+#            try:
+#                self._hgrepo = hglrepo.localrepository(self._hgui, path, create=1)
+#            except mercurial.error.RepoError:
+#                raise wlrepo.LibraryException("[HGLibrary] Can't create a repository on path '%s'." % path)
+#        else:
+#            raise wlrepo.LibraryException("[HGLibrary] Can't open a library on path '%s'." % path)
+#
+#        # fetch the main cabinet
+#        lock = self._hgrepo.lock()
+#        try:
+#            btags = self._hgrepo.branchtags()
+#
+#            if not self._has_branch(maincabinet):
+#                raise wlrepo.LibraryException("[HGLibrary] No branch named '%s' to init main cabinet" % maincabinet)
+#
+#            self._maincab = MercurialCabinet(self, maincabinet)
+#        finally:
+#            lock.release()
+#
+#    @property
+#    def ospath(self):
+#        return self._ospath
+#
+#    @property
+#    def main_cabinet(self):
+#        return self._maincab
+#
+#    def document(self, docid, user, part=None, shelve=None):
+#        return self.cabinet(docid, user, create=False).retrieve(part=part, shelve=shelve)
+#
+#    def cabinet(self, docid, user, create=False):
+#        docid = self._sanitize_string(docid)
+#        user = self._sanitize_string(user)
+#
+#        bname = self._bname(user, docid)
+#
+#        lock = self._lock(True)
+#        try:
+#            if self._has_branch(bname):
+#                return MercurialCabinet(self, doc=docid, user=user)
+#
+#            if not create:
+#                raise wlrepo.CabinetNotFound(bname)
+#
+#            # check if the docid exists in the main cabinet
+#            needs_touch = not self._maincab.exists(docid)
+#            cab = MercurialCabinet(self, doc=docid, user=user)
+#
+#            name, fileid = cab._filename(None)
+#
+#            def cleanup_action(l):
+#                if needs_touch:
+#                    l._fileopener()(fileid, "w").write('')
+#                    l._fileadd(fileid)
+#
+#                garbage = [fid for (fid, did) in l._filelist() if not did.startswith(docid)]
+#                l._filesrm(garbage)
+#                print "removed: ", garbage
+#
+#            # create the branch
+#            self._create_branch(bname, before_commit=cleanup_action)
+#            return MercurialCabinet(self, doc=docid, user=user)
+#        finally:
+#            lock.release()
+#
+#    #
+#    # Private methods
+#    #
+#
+#    #
+#    # Locking
+#    #
+#
+#    def _lock(self, write_mode=False):
+#        return self._hgrepo.wlock() # no support for read/write mode yet
+#
+#    def _transaction(self, write_mode, action):
+#        lock = self._lock(write_mode)
+#        try:
+#            return action(self)
+#        finally:
+#            lock.release()
+#
+#    #
+#    # Basic repo manipulation
+#    #
+#
+#    def _checkout(self, rev, force=True):
+#        return MergeStatus(mercurial.merge.update(self._hgrepo, rev, False, force, None))
+#
+#    def _merge(self, rev):
+#        """ Merge the revision into current working directory """
+#        return MergeStatus(mercurial.merge.update(self._hgrepo, rev, True, False, None))
+#
+#    def _common_ancestor(self, revA, revB):
+#        return self._hgrepo[revA].ancestor(self.repo[revB])
+#
+#    def _commit(self, message, user=u"library"):
+#        return self._hgrepo.commit(text=message, user=user)
+#
+#
+#    def _fileexists(self, fileid):
+#        return (fileid in self._hgrepo[None])
+#
+#    def _fileadd(self, fileid):
+#        return self._hgrepo.add([fileid])
+#
+#    def _filesadd(self, fileid_list):
+#        return self._hgrepo.add(fileid_list)
+#
+#    def _filerm(self, fileid):
+#        return self._hgrepo.remove([fileid])
+#
+#    def _filesrm(self, fileid_list):
+#        return self._hgrepo.remove(fileid_list)
+#
+#    def _filelist(self, filter=default_filter):
+#        for name in  self._hgrepo[None]:
+#            result = filter(name)
+#            if result is None: continue
+#
+#            yield result
+#
+#    def _fileopener(self):
+#        return self._hgrepo.wopener
+#
+#    def _filectx(self, fileid, branchid):
+#        return self._hgrepo.filectx(fileid, changeid=branchid)
+#
+#    def _changectx(self, nodeid):
+#        return self._hgrepo.changectx(nodeid)
+#
+#    #
+#    # BASIC BRANCH routines
+#    #
+#
+#    def _bname(self, user, docid):
+#        """Returns a branch name for a given document and user."""
+#        docid = self._sanitize_string(docid)
+#        uname = self._sanitize_string(user)
+#        return "personal_" + uname + "_file_" + docid;
+#
+#    def _has_branch(self, name):
+#        return self._hgrepo.branchmap().has_key(self._sanitize_string(name))
+#
+#    def _branch_tip(self, name):
+#        name = self._sanitize_string(name)
+#        return self._hgrepo.branchtags()[name]
+#
+#    def _create_branch(self, name, parent=None, before_commit=None):
+#        name = self._sanitize_string(name)
+#
+#        if self._has_branch(name): return # just exit
+#
+#        if parent is None:
+#            parent = self._maincab
+#
+#        parentrev = parent._hgtip()
+#
+#        self._checkout(parentrev)
+#        self._hgrepo.dirstate.setbranch(name)
+#
+#        if before_commit: before_commit(self)
+#
+#        self._commit("[AUTO] Initial commit for branch '%s'." % name, user='library')
+#
+#        # revert back to main
+#        self._checkout(self._maincab._hgtip())
+#        return self._branch_tip(name)
+#
+#    def _switch_to_branch(self, branchname):
+#        current = self._hgrepo[None].branch()
+#
+#        if current == branchname:
+#            return current # quick exit
+#
+#        self._checkout(self._branch_tip(branchname))
+#        return branchname
+#
+#    def shelf(self, nodeid=None):
+#        if nodeid is None:
+#            nodeid = self._maincab._name
+#        return MercurialShelf(self, self._changectx(nodeid))
+#
+#
+#    #
+#    # Utils
+#    #
+#
+#    @staticmethod
+#    def _sanitize_string(s):
+#        if isinstance(s, unicode):
+#            s = s.encode('utf-8')
+#        return s
+#
+#class MercurialCabinet(wlrepo.Cabinet):
+#
+#    def __init__(self, library, branchname=None, doc=None, user=None):
+#        if doc and user:
+#            super(MercurialCabinet, self).__init__(library, doc=doc, user=user)
+#            self._branchname = library._bname(user=user, docid=doc)
+#        elif branchname:
+#            super(MercurialCabinet, self).__init__(library, name=branchname)
+#            self._branchname = branchname
+#        else:
+#            raise ValueError("Provide either doc/user or branchname")
+#
+#    def shelf(self):
+#        return self._library.shelf(self._branchname)
+#
+#    def parts(self):
+#        return self._execute_in_branch(action=lambda l, c: (e[1] for e in l._filelist()))
+#
+#    def retrieve(self, part=None, shelf=None):
+#        name, fileid = self._filename(part)
+#
+#        print "Retrieving document %s from cab %s" % (name, self._name)
+#
+#        if fileid is None:
+#            raise wlrepo.LibraryException("Can't retrieve main document from main cabinet.")
+#
+#        def retrieve_action(l,c):
+#            if l._fileexists(fileid):
+#                return MercurialDocument(c, name=name, fileid=fileid)
+#            print "File %s not found " % fileid
+#            return None
+#
+#        return self._execute_in_branch(retrieve_action)
+#
+#    def create(self, name, initial_data):
+#        name, fileid = self._filename(name)
+#
+#        if name is None:
+#            raise ValueError("Can't create main doc for maincabinet.")
+#
+#        def create_action(l, c):
+#            if l._fileexists(fileid):
+#                raise wlrepo.LibraryException("Can't create document '%s' in cabinet '%s' - it already exists" % (fileid, c.name))
+#
+#            fd = l._fileopener()(fileid, "w")
+#            fd.write(initial_data)
+#            fd.close()
+#            l._fileadd(fileid)
+#            l._commit("File '%s' created." % fileid)
+#            return MercurialDocument(c, fileid=fileid, name=name)
+#
+#        return self._execute_in_branch(create_action)
+#
+#    def exists(self, part=None, shelf=None):
+#        name, filepath = self._filename(part)
+#
+#        if filepath is None: return False
+#        return self._execute_in_branch(lambda l, c: l._fileexists(filepath))
+#
+#    def _execute_in_branch(self, action, write=False):
+#        def switch_action(library):
+#            old = library._switch_to_branch(self._branchname)
+#            try:
+#                return action(library, self)
+#            finally:
+#                library._switch_to_branch(old)
+#
+#        return self._library._transaction(write_mode=write, action=switch_action)
+#
+#
+#    def _filename(self, docid):
+#        return self._partname(docid, 'xml')
+#
+#    def _partname(self, docid, part):
+#        docid = self._library._sanitize_string(part)
+#        part = self._library._sanitize_string(part)
+#
+#        if part is None:
+#            part = 'xml'
+#
+#        if self._maindoc == '' and docid is None:
+#            return None
+#
+#        return 'pub_' + docid + '.' + part
+#
+#    def _fileopener(self):
+#        return self._library._fileopener()
+#
+#    def _hgtip(self):
+#        return self._library._branch_tip(self._branchname)
+#
+#    def _filectx(self, fileid):
+#        return self._library._filectx(fileid, self._branchname)
+#
+#    def ismain(self):
+#        return (self._library.main_cabinet == self)
+#
+#class MercurialDocument(wlrepo.Document):
+#
+#    def __init__(self, cabinet, docid):
+#        super(MercurialDocument, self).__init__(cabinet, name=docid)
+#        self._opener = self._cabinet._fileopener()
+#        self._docid = docid
+#        self._ctxs = {}
+#
+#    def _ctx(self, part):
+#        if not self._ctxs.has_key(part):
+#            self._ctxs[part] = self._cabinet._filectx(self._fileid())
+#        return self._ctxs[part]
+#
+#    def _fileid(self, part='xml'):
+#        return self._cabinet._partname(self._docid, part)
+#
+#    def read(self, part='xml'):
+#        return self._opener(self._ctx(part).path(), "r").read()
+#
+#    def write(self, data, part='xml'):
+#        return self._opener(self._ctx(part).path(), "w").write(data)
+#
+#    def commit(self, message, user):
+#        """Commit all parts of the document."""
+#        self.library._fileadd(self._fileid)
+#        self.library._commit(self._fileid, message, user)
+#
+#    def update(self):
+#        """Update parts of the document."""
+#        lock = self.library._lock()
+#        try:
+#            if self._cabinet.ismain():
+#                return True # always up-to-date
+#
+#            user = self._cabinet.username or 'library'
+#            mdoc = self.library.document(self._fileid)
+#
+#            mshelf = mdoc.shelf()
+#            shelf = self.shelf()
+#
+#            if not mshelf.ancestorof(shelf) and not shelf.parentof(mshelf):
+#                shelf.merge_with(mshelf, user=user)
+#
+#            return True
+#        finally:
+#            lock.release()
+#
+#    def share(self, message):
+#        lock = self.library._lock()
+#        try:
+#            print "sharing from", self._cabinet, self._cabinet.username
+#
+#            if self._cabinet.ismain():
+#                return True # always shared
+#
+#            if self._cabinet.username is None:
+#                raise ValueError("Can only share documents from personal cabinets.")
+#
+#            user = self._cabinet.username
+#
+#            main = self.library.shelf()
+#            local = self.shelf()
+#
+#            no_changes = True
+#
+#            # Case 1:
+#            #         * local
+#            #         |
+#            #         * <- can also be here!
+#            #        /|
+#            #       / |
+#            # main *  *
+#            #      |  |
+#            # The local branch has been recently updated,
+#            # so we don't need to update yet again, but we need to
+#            # merge down to default branch, even if there was
+#            # no commit's since last update
+#
+#            if main.ancestorof(local):
+#                print "case 1"
+#                main.merge_with(local, user=user, message=message)
+#                no_changes = False
+#            # Case 2:
+#            #
+#            # main *  * local
+#            #      |\ |
+#            #      | \|
+#            #      |  *
+#            #      |  |
+#            #
+#            # Default has no changes, to update from this branch
+#            # since the last merge of local to default.
+#            elif local.has_common_ancestor(main):
+#                print "case 2"
+#                if not local.parentof(main):
+#                    main.merge_with(local, user=user, message=message)
+#                    no_changes = False
+#
+#            # Case 3:
+#            # main *
+#            #      |
+#            #      * <- this case overlaps with previos one
+#            #      |\
+#            #      | \
+#            #      |  * local
+#            #      |  |
+#            #
+#            # There was a recent merge to the defaul branch and
+#            # no changes to local branch recently.
+#            #
+#            # Use the fact, that user is prepared to see changes, to
+#            # update his branch if there are any
+#            elif local.ancestorof(main):
+#                print "case 3"
+#                if not local.parentof(main):
+#                    local.merge_with(main, user=user, message='Local branch update.')
+#                    no_changes = False
+#            else:
+#                print "case 4"
+#                local.merge_with(main, user=user, message='Local branch update.')
+#                local = self.shelf()
+#                main.merge_with(local, user=user, message=message)
+#
+#            print "no_changes: ", no_changes
+#            return no_changes
+#        finally:
+#            lock.release()
+#
+#    def shared(self):
+#        return self.library.main_cabinet.retrieve(self._name)
+#
+#    def exists(self, part='xml'):
+#        return self._cabinet.exists(self._fileid(part))
+#
+#    @property
+#    def size(self):
+#        return self._filectx.size()
+#
+#    def shelf(self):
+#        return self._cabinet.shelf()
+#
+#    @property
+#    def last_modified(self):
+#        return self._filectx.date()
+#
+#    def __str__(self):
+#        return u"Document(%s->%s)" % (self._cabinet.name, self._name)
+#
+#    def __eq__(self, other):
+#        return self._filectx == other._filectx
+#
+#
+#
+#class MercurialShelf(wlrepo.Shelf):
+#
+#    def __init__(self, lib, changectx):
+#        super(MercurialShelf, self).__init__(lib)
+#
+#        if isinstance(changectx, str):
+#            self._changectx = lib._changectx(changectx)
+#        else:
+#            self._changectx = changectx
+#
+#    @property
+#    def _rev(self):
+#        return self._changectx.node()
+#
+#    def __str__(self):
+#        return self._changectx.hex()
+#
+#    def __repr__(self):
+#        return "MercurialShelf(%s)" % self._changectx.hex()
+#
+#    def ancestorof(self, other):
+#        nodes = list(other._changectx._parents)
+#        while nodes[0].node() != nullid:
+#            v = nodes.pop(0)
+#            if v == self._changectx:
+#                return True
+#            nodes.extend( v._parents )
+#        return False
+#
+#    def parentof(self, other):
+#        return self._changectx in other._changectx._parents
+#
+#    def has_common_ancestor(self, other):
+#        a = self._changectx.ancestor(other._changectx)
+#        # print a, self._changectx.branch(), a.branch()
+#
+#        return (a.branch() == self._changectx.branch())
+#
+#    def merge_with(self, other, user, message):
+#        lock = self._library._lock(True)
+#        try:
+#            self._library._checkout(self._changectx.node())
+#            self._library._merge(other._changectx.node())
+#            self._library._commit(user=user, message=message)
+#        finally:
+#            lock.release()
+#
+#    def __eq__(self, other):
+#        return self._changectx.node() == other._changectx.node()
+#
+#
+#class MergeStatus(object):
+#    def __init__(self, mstatus):
+#        self.updated = mstatus[0]
+#        self.merged = mstatus[1]
+#        self.removed = mstatus[2]
+#        self.unresolved = mstatus[3]
+#
+#    def isclean(self):
+#        return self.unresolved == 0
+#
+#class UpdateStatus(object):
+#
+#    def __init__(self, mstatus):
+#        self.modified = mstatus[0]
+#        self.added = mstatus[1]
+#        self.removed = mstatus[2]
+#        self.deleted = mstatus[3]
+#        self.untracked = mstatus[4]
+#        self.ignored = mstatus[5]
+#        self.clean = mstatus[6]
+#
+#    def has_changes(self):
+#        return bool(len(self.modified) + len(self.added) + \
+#                    len(self.removed) + len(self.deleted))
+#
+#__all__ = ["MercurialLibrary"]
\ No newline at end of file
diff --git a/lib/wlrepo/mercurial_backend/__init__.py b/lib/wlrepo/mercurial_backend/__init__.py
new file mode 100644 (file)
index 0000000..10a4cf8
--- /dev/null
@@ -0,0 +1,84 @@
+# -*- encoding: utf-8 -*-
+
+__author__= "Łukasz Rekucki"
+__date__ = "$2009-09-25 09:20:22$"
+__doc__ = "Module documentation."
+
+import wlrepo
+
+
+
+class MercurialRevision(wlrepo.Revision):
+
+    def __init__(self, lib, changectx):
+        super(MercurialRevision, self).__init__(lib)
+        self._changectx = changectx
+        
+        branchname = self._changectx.branch()
+        if branchname.startswith("$doc:"):
+            self._docname = branchname[5:]
+            self._username = None
+        elif branchname.startswith("$user:"):
+            idx = branchname.find("$doc:")
+            if(idx < 0):
+                raise ValueError("Revision %s is not a valid document revision." % changectx.hex());
+            self._username = branchname[0:idx]
+            self._docname = branchname[idx+5:]
+        else:
+            raise ValueError("Revision %s is not a valid document revision." % changectx.hex());
+        
+    @property
+    def document_name(self):
+        return self._docname
+
+    @property
+    def user_name(self):
+        return self._username
+
+    def hgrev(self):
+        return self._changectx.node()
+        
+    def hgcontext(self):
+        return self._changectx
+
+    def hgbranch(self):
+        return self._changectx.branch()
+
+    def __unicode__(self):
+        return u"%s" % self._changectx.hex()
+
+    def __repr__(self):
+        return "%s" % self._changectx.hex()
+
+    def ancestorof(self, other):
+        nodes = list(other._changectx._parents)
+        while nodes[0].node() != nullid:
+            v = nodes.pop(0)
+            if v == self._changectx:
+                return True
+            nodes.extend( v._parents )
+        return False
+
+    def parentof(self, other):
+        return self._changectx in other._changectx._parents
+
+    def has_common_ancestor(self, other):
+        a = self._changectx.ancestor(other._changectx)       
+        return (a.branch() == self._changectx.branch())
+
+    def merge_with(self, other, user, message):
+        lock = self._library._lock(True)
+        try:
+            self._library._checkout(self._changectx.node())
+            self._library._merge(other._changectx.node())
+            self._library._commit(user=user, message=message)
+        finally:
+            lock.release()
+
+    def __eq__(self, other):
+        return self._changectx.node() == other._changectx.node()
+
+
+from wlrepo.mercurial_backend.library import MercurialLibrary
+
+
diff --git a/lib/wlrepo/mercurial_backend/document.py b/lib/wlrepo/mercurial_backend/document.py
new file mode 100644 (file)
index 0000000..bced674
--- /dev/null
@@ -0,0 +1,173 @@
+# -*- encoding: utf-8 -*-
+
+__author__ = "Łukasz Rekucki"
+__date__ = "$2009-09-25 09:35:06$"
+__doc__ = "Module documentation."
+
+import wlrepo
+
+class MercurialDocument(wlrepo.Document):
+
+    def data(self, entry):
+        path = self._revision._docname + '.' + entry            
+        return self._library._filectx(path, \
+            self._revision.hgrev()).data()
+
+    def quickwrite(self, entry, data, msg, user=None):
+        user = user or self.owner
+        if user is None:
+            raise ValueError("Can't determine user.")
+        
+        def write(l, r):
+            f = l._fileopen(r(entry), "w+")
+            f.write(data)
+            f.close()
+            l._fileadd(r(entry))
+
+        return self.invoke_and_commit(write, lambda d: (msg, user))
+
+    def invoke_and_commit(self, ops, before_commit):
+        lock = self._library._lock()
+        try:            
+            self._library._checkout(self._revision.hgrev())
+
+            def entry_path(entry):
+                return self.id + '.' + entry
+            
+            ops(self._library, entry_path)
+            message, user = before_commit(self)            
+            self._library._commit(message, user)
+
+            return self._library.document(docid=self.id, user=self.owner)
+        finally:
+            lock.release()            
+
+    # def commit(self, message, user):
+    #    """Make a new commit."""
+    #    self.invoke_and_commit(message, user, lambda *a: True)
+
+    def ismain(self):
+        return self._revision.user_name() is None
+
+    def shared(self):
+        if self.ismain():
+            return self
+        return self._library.document(docid=self._revision.document_name())
+
+
+    def take(self, user):
+        fullid = self._library.fulldocid(self.id, user)
+
+        def take_action(library, resolve):
+            # branch from latest 
+            library._create_branch(fullid, parent=self._revision)            
+
+        if not self._library.has_revision(fullid):
+            self.invoke_and_commit(take_action, \
+                lambda d: ("$AUTO$ File checkout.", user) )
+
+        return self._library.document_for_rev(fullid)
+            
+    def update(self, user):
+        """Update parts of the document."""
+        lock = self.library._lock()
+        try:
+            if self.ismain():
+                # main revision of the document
+                return True
+            
+            if self._revision.has_children():
+                # can't update non-latest revision
+                return False
+
+            sv = self.shared()
+            
+            if not sv.ancestorof(self) and not self.parentof(sv):
+                self._revision.merge_with(sv._revision, user=user)
+
+            return True
+        finally:
+            lock.release()  
+
+    def share(self, message):
+        lock = self.library._lock()
+        try:            
+            if self.ismain():
+                return True # always shared          
+
+            user = self._revision.user_name()
+
+            main = self.shared()._revision
+            local = self._revision
+
+            no_changes = True
+
+            # Case 1:
+            #         * local
+            #         |
+            #         * <- can also be here!
+            #        /|
+            #       / |
+            # main *  *
+            #      |  |
+            # The local branch has been recently updated,
+            # so we don't need to update yet again, but we need to
+            # merge down to default branch, even if there was
+            # no commit's since last update
+
+            if main.ancestorof(local):
+                print "case 1"
+                main.merge_with(local, user=user, message=message)
+                no_changes = False
+            # Case 2:
+            #
+            # main *  * local
+            #      |\ |
+            #      | \|
+            #      |  *
+            #      |  |
+            #
+            # Default has no changes, to update from this branch
+            # since the last merge of local to default.
+            elif local.has_common_ancestor(main):
+                print "case 2"
+                if not local.parentof(main):
+                    main.merge_with(local, user=user, message=message)
+                    no_changes = False
+
+            # Case 3:
+            # main *
+            #      |
+            #      * <- this case overlaps with previos one
+            #      |\
+            #      | \
+            #      |  * local
+            #      |  |
+            #
+            # There was a recent merge to the defaul branch and
+            # no changes to local branch recently.
+            #
+            # Use the fact, that user is prepared to see changes, to
+            # update his branch if there are any
+            elif local.ancestorof(main):
+                print "case 3"
+                if not local.parentof(main):
+                    local.merge_with(main, user=user, message='Local branch update.')
+                    no_changes = False
+            else:
+                print "case 4"
+                local.merge_with(main, user=user, message='Local branch update.')
+                local = self.shelf()
+                main.merge_with(local, user=user, message=message)
+
+            print "no_changes: ", no_changes
+            return no_changes
+        finally:
+            lock.release()     
+
+    def __str__(self):
+        return u"Document(%s:%s)" % (self.name, self.owner)
+
+    def __eq__(self, other):
+        return (self._revision == other._revision) and (self.name == other.name)
+
diff --git a/lib/wlrepo/mercurial_backend/library.py b/lib/wlrepo/mercurial_backend/library.py
new file mode 100644 (file)
index 0000000..219a01d
--- /dev/null
@@ -0,0 +1,250 @@
+# -*- encoding: utf-8 -*-
+
+__author__= "Łukasz Rekucki"
+__date__ = "$2009-09-25 09:33:02$"
+__doc__ = "Module documentation."
+
+import mercurial
+from mercurial import localrepo as hglrepo
+from mercurial import ui as hgui
+from mercurial import error
+import wlrepo
+
+from wlrepo.mercurial_backend.document import MercurialDocument
+from wlrepo.mercurial_backend import MercurialRevision
+
+class MergeStatus(object):
+    def __init__(self, mstatus):
+        self.updated = mstatus[0]
+        self.merged = mstatus[1]
+        self.removed = mstatus[2]
+        self.unresolved = mstatus[3]
+
+    def isclean(self):
+        return self.unresolved == 0
+
+class UpdateStatus(object):
+
+    def __init__(self, mstatus):
+        self.modified = mstatus[0]
+        self.added = mstatus[1]
+        self.removed = mstatus[2]
+        self.deleted = mstatus[3]
+        self.untracked = mstatus[4]
+        self.ignored = mstatus[5]
+        self.clean = mstatus[6]
+
+    def has_changes(self):
+        return bool(len(self.modified) + len(self.added) + \
+                    len(self.removed) + len(self.deleted))
+
+class MercurialLibrary(wlrepo.Library):
+    """Mercurial implementation of the Library API"""
+
+    def __init__(self, path, **kwargs):
+        super(wlrepo.Library, self).__init__( ** kwargs)
+
+        self._revcache = {}
+        self._doccache = {}
+
+        self._hgui = hgui.ui()
+        self._hgui.config('ui', 'quiet', 'true')
+        self._hgui.config('ui', 'interactive', 'false')
+
+        import os.path
+        self._ospath = self._sanitize_string(os.path.realpath(path))        
+
+        if os.path.isdir(path):
+            try:
+                self._hgrepo = hglrepo.localrepository(self._hgui, path)
+            except mercurial.error.RepoError:
+                raise wlrepo.LibraryException("[HGLibrary] Not a valid repository at path '%s'." % path)
+        elif kwargs.get('create', False):
+            os.makedirs(path)
+            try:
+                self._hgrepo = hglrepo.localrepository(self._hgui, path, create=1)
+            except mercurial.error.RepoError:
+                raise wlrepo.LibraryException("[HGLibrary] Can't create a repository on path '%s'." % path)
+        else:
+            raise wlrepo.LibraryException("[HGLibrary] Can't open a library on path '%s'." % path)
+
+
+    def documents(self):
+        return [ key[5:] for key in \
+            self._hgrepo.branchmap() if key.startswith("$doc:") ]
+
+    @property
+    def ospath(self):
+        return self._ospath
+
+    def document_for_rev(self, revision):
+        if revision is None:
+            raise ValueError("Revision can't be None.")
+        
+        if not isinstance(revision, MercurialRevision):
+            rev = self.get_revision(revision)
+        else:
+            rev = revision       
+
+        if not self._doccache.has_key(str(rev)):
+            self._doccache[str(rev)] = MercurialDocument(self, rev)
+
+        # every revision is a document
+        return self._doccache[str(rev)]
+
+    def document(self, docid, user=None):       
+        return self.document_for_rev(self.fulldocid(docid, user))
+
+    def get_revision(self, revid):
+        ctx = self._changectx(revid)
+
+        if ctx is None:
+            raise RevisionNotFound(revid)
+
+        if self._revcache.has_key(ctx):
+            return self._revcache[ctx]
+
+        return MercurialRevision(self, ctx)
+
+    def fulldocid(self, docid, user=None):
+        fulldocid = ''
+        if user is not None:
+            fulldocid += '$user:' + user
+        fulldocid += '$doc:' + docid
+        return fulldocid
+
+
+    def has_revision(self, revid):
+        try:
+            self._hgrepo[revid]
+            return True
+        except error.RepoError:
+            return False
+
+    def document_create(self, docid):
+        # check if it already exists
+        fullid = self.fulldocid(docid)
+
+        if self.has_revision(fullid):
+            raise LibraryException("Document already exists!");
+
+        # doesn't exist
+        self._create_branch(fullid)
+        return self.document_for_rev(fullid)
+
+    #
+    # Private methods
+    #
+
+    #
+    # Locking
+    #
+
+    def _lock(self, write_mode=False):
+        return self._hgrepo.wlock() # no support for read/write mode yet
+
+    def _transaction(self, write_mode, action):
+        lock = self._lock(write_mode)
+        try:
+            return action(self)
+        finally:
+            lock.release()
+
+    #
+    # Basic repo manipulation
+    #
+
+    def _checkout(self, rev, force=True):
+        return MergeStatus(mercurial.merge.update(self._hgrepo, rev, False, force, None))
+
+    def _merge(self, rev):
+        """ Merge the revision into current working directory """
+        return MergeStatus(mercurial.merge.update(self._hgrepo, rev, True, False, None))
+
+    def _common_ancestor(self, revA, revB):
+        return self._hgrepo[revA].ancestor(self.repo[revB])
+
+    def _commit(self, message, user=u"library"):
+        return self._hgrepo.commit(text=message, user=user)
+
+
+    def _fileexists(self, fileid):
+        return (fileid in self._hgrepo[None])
+
+    def _fileadd(self, fileid):
+        return self._hgrepo.add([fileid])
+
+    def _filesadd(self, fileid_list):
+        return self._hgrepo.add(fileid_list)
+
+    def _filerm(self, fileid):
+        return self._hgrepo.remove([fileid])
+
+    def _filesrm(self, fileid_list):
+        return self._hgrepo.remove(fileid_list)   
+
+    def _fileopen(self, path, mode):
+        return self._hgrepo.wopener(path, mode)
+
+    def _filectx(self, fileid, revid):
+        return self._hgrepo.filectx(fileid, changeid=revid)
+
+    def _changectx(self, nodeid):
+        return self._hgrepo.changectx(nodeid)
+
+    #
+    # BASIC BRANCH routines
+    #
+
+    def _bname(self, user, docid):
+        """Returns a branch name for a given document and user."""
+        docid = self._sanitize_string(docid)
+        uname = self._sanitize_string(user)
+        return "personal_" + uname + "_file_" + docid;
+
+    def _has_branch(self, name):
+        return self._hgrepo.branchmap().has_key(self._sanitize_string(name))
+
+    def _branch_tip(self, name):
+        name = self._sanitize_string(name)
+        return self._hgrepo.branchtags()[name]    
+
+    def _create_branch(self, name, parent=None, before_commit=None):
+        name = self._sanitize_string(name)
+
+        if self._has_branch(name): return # just exit
+
+        if parent is None:
+            parentrev = self._hgrepo['$branchbase'].node()
+        else:
+            parentrev = parent.hgrev()
+
+        self._checkout(parentrev)
+        self._hgrepo.dirstate.setbranch(name)
+
+        if before_commit: before_commit(self)
+
+        self._commit("$ADMN$ Initial commit for branch '%s'." % name, user='$library')        
+
+    def _switch_to_branch(self, branchname):
+        current = self._hgrepo[None].branch()
+
+        if current == branchname:
+            return current # quick exit
+
+        self._checkout(self._branch_tip(branchname))
+        return branchname    
+
+    #
+    # Utils
+    #
+
+    @staticmethod
+    def _sanitize_string(s):
+        if isinstance(s, unicode):
+            s = s.encode('utf-8')
+
+        if ' ' in s:
+            raise ValueError('Whitespace is forbidden!')
+
+        return s
\ No newline at end of file
diff --git a/lib/wlrepo/tests/data/clean/$meta b/lib/wlrepo/tests/data/clean/$meta
new file mode 100644 (file)
index 0000000..e69de29
index b0aa1e6..20ad845 100644 (file)
Binary files a/lib/wlrepo/tests/data/clean/.hg/dirstate and b/lib/wlrepo/tests/data/clean/.hg/dirstate differ
index 45c1c46..b6c919d 100644 (file)
Binary files a/lib/wlrepo/tests/data/clean/.hg/store/00changelog.i and b/lib/wlrepo/tests/data/clean/.hg/store/00changelog.i differ
index ed99f61..fb3412d 100644 (file)
Binary files a/lib/wlrepo/tests/data/clean/.hg/store/00manifest.i and b/lib/wlrepo/tests/data/clean/.hg/store/00manifest.i differ
diff --git a/lib/wlrepo/tests/data/clean/.hg/store/data/$meta.i b/lib/wlrepo/tests/data/clean/.hg/store/data/$meta.i
new file mode 100644 (file)
index 0000000..2431023
Binary files /dev/null and b/lib/wlrepo/tests/data/clean/.hg/store/data/$meta.i differ
diff --git a/lib/wlrepo/tests/data/clean/.hg/store/data/ignored__file.i b/lib/wlrepo/tests/data/clean/.hg/store/data/ignored__file.i
deleted file mode 100644 (file)
index a6bdf46..0000000
Binary files a/lib/wlrepo/tests/data/clean/.hg/store/data/ignored__file.i and /dev/null differ
diff --git a/lib/wlrepo/tests/data/clean/.hg/store/data/pub__valid__file.xml.i b/lib/wlrepo/tests/data/clean/.hg/store/data/pub__valid__file.xml.i
deleted file mode 100644 (file)
index a6bdf46..0000000
Binary files a/lib/wlrepo/tests/data/clean/.hg/store/data/pub__valid__file.xml.i and /dev/null differ
index a1607dd..b996e34 100644 (file)
@@ -1,3 +1,2 @@
+data/$meta.i
 data/.hgignore.i
 data/.hgignore.i
-data/ignored_file.i
-data/pub_valid_file.xml.i
index 90d4cb1..d9a46ca 100644 (file)
Binary files a/lib/wlrepo/tests/data/clean/.hg/store/undo and b/lib/wlrepo/tests/data/clean/.hg/store/undo differ
index 1d0af27..59bcbfc 100644 (file)
Binary files a/lib/wlrepo/tests/data/clean/.hg/undo.dirstate and b/lib/wlrepo/tests/data/clean/.hg/undo.dirstate differ
diff --git a/lib/wlrepo/tests/data/clean/ignored_file b/lib/wlrepo/tests/data/clean/ignored_file
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/lib/wlrepo/tests/data/clean/pub_valid_file.xml b/lib/wlrepo/tests/data/clean/pub_valid_file.xml
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/lib/wlrepo/tests/data/simple/$meta b/lib/wlrepo/tests/data/simple/$meta
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/lib/wlrepo/tests/data/simple/.hg/branch b/lib/wlrepo/tests/data/simple/.hg/branch
new file mode 100644 (file)
index 0000000..4ad96d5
--- /dev/null
@@ -0,0 +1 @@
+default
diff --git a/lib/wlrepo/tests/data/simple/.hg/branchheads.cache b/lib/wlrepo/tests/data/simple/.hg/branchheads.cache
new file mode 100644 (file)
index 0000000..713758b
--- /dev/null
@@ -0,0 +1,4 @@
+65046aefea667e38c7a01d7ca62412d7e81f68bc 2
+d5e516ebd357bca24c6afb737e97db3b3d4f111a default
+00e4aa6f4f53f31020e4d3e0579cb3c0fa0bd056 $doc:sample
+65046aefea667e38c7a01d7ca62412d7e81f68bc $doc:sample_pl
index c13e1c1..46fefca 100644 (file)
Binary files a/lib/wlrepo/tests/data/simple/.hg/dirstate and b/lib/wlrepo/tests/data/simple/.hg/dirstate differ
index 35b7cda..f245154 100644 (file)
Binary files a/lib/wlrepo/tests/data/simple/.hg/store/00changelog.i and b/lib/wlrepo/tests/data/simple/.hg/store/00changelog.i differ
index 7eb40cb..fd65f61 100644 (file)
Binary files a/lib/wlrepo/tests/data/simple/.hg/store/00manifest.i and b/lib/wlrepo/tests/data/simple/.hg/store/00manifest.i differ
diff --git a/lib/wlrepo/tests/data/simple/.hg/store/data/$meta.i b/lib/wlrepo/tests/data/simple/.hg/store/data/$meta.i
new file mode 100644 (file)
index 0000000..2431023
Binary files /dev/null and b/lib/wlrepo/tests/data/simple/.hg/store/data/$meta.i differ
diff --git a/lib/wlrepo/tests/data/simple/.hg/store/data/.hgtags.i b/lib/wlrepo/tests/data/simple/.hg/store/data/.hgtags.i
new file mode 100644 (file)
index 0000000..6c3fcf2
Binary files /dev/null and b/lib/wlrepo/tests/data/simple/.hg/store/data/.hgtags.i differ
diff --git a/lib/wlrepo/tests/data/simple/.hg/store/data/ignored__file.i b/lib/wlrepo/tests/data/simple/.hg/store/data/ignored__file.i
deleted file mode 100644 (file)
index a6bdf46..0000000
Binary files a/lib/wlrepo/tests/data/simple/.hg/store/data/ignored__file.i and /dev/null differ
diff --git a/lib/wlrepo/tests/data/simple/.hg/store/data/pub__polish__file.xml.i b/lib/wlrepo/tests/data/simple/.hg/store/data/pub__polish__file.xml.i
deleted file mode 100644 (file)
index 3488bcc..0000000
Binary files a/lib/wlrepo/tests/data/simple/.hg/store/data/pub__polish__file.xml.i and /dev/null differ
diff --git a/lib/wlrepo/tests/data/simple/.hg/store/data/pub__valid__file.xml.i b/lib/wlrepo/tests/data/simple/.hg/store/data/pub__valid__file.xml.i
deleted file mode 100644 (file)
index fd3c7f7..0000000
Binary files a/lib/wlrepo/tests/data/simple/.hg/store/data/pub__valid__file.xml.i and /dev/null differ
diff --git a/lib/wlrepo/tests/data/simple/.hg/store/data/sample.parts.i b/lib/wlrepo/tests/data/simple/.hg/store/data/sample.parts.i
new file mode 100644 (file)
index 0000000..a6bdf46
Binary files /dev/null and b/lib/wlrepo/tests/data/simple/.hg/store/data/sample.parts.i differ
diff --git a/lib/wlrepo/tests/data/simple/.hg/store/data/sample.xml.i b/lib/wlrepo/tests/data/simple/.hg/store/data/sample.xml.i
new file mode 100644 (file)
index 0000000..b115f4d
Binary files /dev/null and b/lib/wlrepo/tests/data/simple/.hg/store/data/sample.xml.i differ
diff --git a/lib/wlrepo/tests/data/simple/.hg/store/data/sample__pl.xml.i b/lib/wlrepo/tests/data/simple/.hg/store/data/sample__pl.xml.i
new file mode 100644 (file)
index 0000000..920c574
Binary files /dev/null and b/lib/wlrepo/tests/data/simple/.hg/store/data/sample__pl.xml.i differ
index 8730267..c228181 100644 (file)
@@ -1,4 +1,6 @@
+data/$meta.i
 data/.hgignore.i
 data/.hgignore.i
-data/ignored_file.i
-data/pub_valid_file.xml.i
-data/pub_polish_file.xml.i
+data/sample.parts.i
+data/sample.xml.i
+data/sample_pl.xml.i
+data/.hgtags.i
index 62ca7e4..3ad8b32 100644 (file)
Binary files a/lib/wlrepo/tests/data/simple/.hg/store/undo and b/lib/wlrepo/tests/data/simple/.hg/store/undo differ
diff --git a/lib/wlrepo/tests/data/simple/.hg/strip-backup/26716f931d95-backup b/lib/wlrepo/tests/data/simple/.hg/strip-backup/26716f931d95-backup
new file mode 100644 (file)
index 0000000..424de92
Binary files /dev/null and b/lib/wlrepo/tests/data/simple/.hg/strip-backup/26716f931d95-backup differ
index fb1041a..310d941 100644 (file)
Binary files a/lib/wlrepo/tests/data/simple/.hg/undo.dirstate and b/lib/wlrepo/tests/data/simple/.hg/undo.dirstate differ
diff --git a/lib/wlrepo/tests/data/simple/.hgtags b/lib/wlrepo/tests/data/simple/.hgtags
new file mode 100644 (file)
index 0000000..0b06113
--- /dev/null
@@ -0,0 +1 @@
+d5e516ebd357bca24c6afb737e97db3b3d4f111a $branchbase
diff --git a/lib/wlrepo/tests/data/simple/ignored_file b/lib/wlrepo/tests/data/simple/ignored_file
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/lib/wlrepo/tests/data/simple/pub_polish_file.xml b/lib/wlrepo/tests/data/simple/pub_polish_file.xml
deleted file mode 100644 (file)
index c7ada58..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Gąska!
diff --git a/lib/wlrepo/tests/data/simple/pub_valid_file.xml b/lib/wlrepo/tests/data/simple/pub_valid_file.xml
deleted file mode 100644 (file)
index 8432188..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Ala ma kota
index 9d37f9f..0978067 100644 (file)
@@ -6,14 +6,11 @@ __doc__ = "Tests for RAL mercurial backend."
 
 from nose.tools import *
 
 
 from nose.tools import *
 
-import wlrepo
 from wlrepo import MercurialLibrary
 from wlrepo import MercurialLibrary
-from wlrepo.backend_mercurial import *
 
 import os, os.path, tempfile
 import shutil
 
 
 import os, os.path, tempfile
 import shutil
 
-
 REPO_TEMPLATES = os.path.join( os.path.dirname(__file__), 'data')
 
 def temprepo(name):
 REPO_TEMPLATES = os.path.join( os.path.dirname(__file__), 'data')
 
 def temprepo(name):
@@ -46,191 +43,200 @@ def temprepo(name):
 def test_opening(library):
     pass
 
 def test_opening(library):
     pass
 
-@temprepo('clean')
-def test_main_cabinet(library):
-    mcab = library.main_cabinet
-    assert_equal(mcab.maindoc_name, '')
-
-    doclist = mcab.parts()
-    assert_equal( list(doclist), ['valid_file'])
-
 @temprepo('simple')
 def test_read_document(library):
 @temprepo('simple')
 def test_read_document(library):
-    doc = library.main_cabinet.retrieve('valid_file')
-    assert_equal(doc.read().strip(), 'Ala ma kota')
+    doc = library.document('sample')
+    assert_equal(doc.data('xml'), 'Ala ma kota\n')
 
 @temprepo('simple')
 def test_read_UTF8_document(library):
 
 @temprepo('simple')
 def test_read_UTF8_document(library):
-    doc = library.main_cabinet.retrieve('polish_file')
-    assert_equal(doc.read().strip(), u'Gąska!'.encode('utf-8'))
+    doc = library.document('sample_pl')
+    assert_equal(doc.data('xml'), u'Gżegżółka\n'.encode('utf-8'))
 
 @temprepo('simple')
 
 @temprepo('simple')
-def test_write_document(library):
-    doc = library.main_cabinet.retrieve('valid_file')
-    assert_equal(doc.read().strip(), 'Ala ma kota')
+def test_change_document(library):
+    doc = library.document('sample')
     STRING = u'Gąski lubią pływać!\n'.encode('utf-8')
     STRING = u'Gąski lubią pływać!\n'.encode('utf-8')
-    doc.write(STRING)
-    assert_equal(doc.read(), STRING)
+    
+    def write_action(library, resolve):
+        f = library._fileopen(resolve('xml'), 'r+')        
+        assert_equal(f.read(), 'Ala ma kota\n')
+        f.seek(0)
+        f.write(STRING)
+        f.flush()
+        f.seek(0)
+        assert_equal(f.read(), STRING)
+
+    def commit_info(document):
+        return ("Document rewrite", "library")
+    
+    ndoc = doc.invoke_and_commit(write_action, commit_info)
+    assert_equal(ndoc.data('xml'), STRING)
+    
 
 @temprepo('simple')
 def test_create_document(library):
 
 @temprepo('simple')
 def test_create_document(library):
-    doc = library.main_cabinet.create("another_file", "Some text")
-    assert_equal( doc.read(), "Some text")
-    assert_true( os.path.isfile( os.path.join(library.ospath, "pub_another_file.xml")) )
-
-@temprepo('branched')
-def test_switch_branch(library):
-    tester_cab = library.cabinet("valid_file", "tester", create=False)
-    assert_equal( list(tester_cab.parts()), ['valid_file'])
-
-@raises(wlrepo.CabinetNotFound)
-@temprepo('branched')
-def test_branch_not_found(library):
-    tester_cab = library.cabinet("ugh", "tester", create=False)
-
-@temprepo('branched')
-def test_no_branches(library):
-    n4 = library.shelf(4)
-    n3 = library.shelf(3)
-    n2 = library.shelf(2)
-    n1 = library.shelf(1)
-    n0 = library.shelf(0)
-
-    assert_true( n3.parentof(n4) )
-    assert_false( n4.parentof(n3) )
-    assert_true( n0.parentof(n1) )
-    assert_false( n1.parentof(n0) )
-    assert_false( n0.parentof(n4) )
-
-# def test_ancestor_of_simple(self):
-    assert_true( n3.ancestorof(n4) )
-    assert_true( n2.ancestorof(n4) )
-    assert_true( n1.ancestorof(n4) )
-    assert_true( n0.ancestorof(n4) )
-
-    assert_true( n2.ancestorof(n3) )
-    assert_true( n1.ancestorof(n3) )
-    assert_true( n0.ancestorof(n3) )
-
-    assert_false( n4.ancestorof(n4) )
-    assert_false( n4.ancestorof(n3) )
-    assert_false( n3.ancestorof(n2) )
-    assert_false( n3.ancestorof(n1) )
-    assert_false( n3.ancestorof(n0) )
-
-# def test_common_ancestor_simple(self):
-    assert_true( n3.has_common_ancestor(n4) )
-    assert_true( n3.has_common_ancestor(n3) )
-    assert_true( n3.has_common_ancestor(n3) )
-
-
-@temprepo('branched2')
-def test_once_branched(library):
-    n7 = library.shelf(7)
-    n6 = library.shelf(6)
-    n5 = library.shelf(5)
-    n4 = library.shelf(4)
-    n3 = library.shelf(3)
-    n2 = library.shelf(2)
-
-    assert_true( n2.parentof(n3) )
-    assert_false( n3.parentof(n2) )
-
-    assert_true( n2.parentof(n5) )
-    assert_false( n5.parentof(n2) )
-
-    assert_false( n2.parentof(n4) )
-    assert_false( n2.parentof(n6) )
-    assert_false( n3.parentof(n5) )
-    assert_false( n5.parentof(n3) )
-
-# def test_ancestorof_branched(self):
-    assert_true( n2.ancestorof(n7) )
-    assert_false( n7.ancestorof(n2) )
-    assert_true( n2.ancestorof(n6) )
-    assert_false( n6.ancestorof(n2) )
-    assert_true( n2.ancestorof(n5) )
-    assert_false( n5.ancestorof(n2) )
-
-    assert_false( n3.ancestorof(n5) )
-    assert_false( n5.ancestorof(n3) )
-    assert_false( n4.ancestorof(n5) )
-    assert_false( n5.ancestorof(n4) )
-    assert_false( n3.ancestorof(n7) )
-    assert_false( n7.ancestorof(n3) )
-    assert_false( n4.ancestorof(n6) )
-    assert_false( n6.ancestorof(n4) )
-
-# def test_common_ancestor_branched(self):
-    assert_true( n2.has_common_ancestor(n4) )
-    assert_true( n2.has_common_ancestor(n7) )
-    assert_true( n2.has_common_ancestor(n6) )
-
-    # cause it's not in the right branch
-    assert_false( n5.has_common_ancestor(n3) )
-    assert_false( n7.has_common_ancestor(n4) )
-
-@temprepo('merged')
-def test_after_merge(library):
-    n8 = library.shelf(8)
-    n7 = library.shelf(7)
-    n6 = library.shelf(6)
-
-    assert_true( n7.parentof(n8) )
-    assert_false( n8.parentof(n7) )
-
-    assert_true( n7.ancestorof(n8) )
-    assert_true( n6.ancestorof(n8) )
-
-
-    assert_true( n7.has_common_ancestor(n8) )
-    # cause it's not in the right branch
-    assert_false( n8.has_common_ancestor(n7) )
-
-@temprepo('merged_with_local_commit')
-def test_after_merge_and_local_commit(library):
-    n9 = library.shelf(9)
-    n8 = library.shelf(8)
-    n7 = library.shelf(7)
-    n6 = library.shelf(6)
-
-    assert_true( n7.parentof(n8) )
-    assert_false( n8.parentof(n7) )
-
-    assert_true( n9.has_common_ancestor(n8) )
-    # cause it's not in the right branch
-    assert_false( n8.has_common_ancestor(n9) )
-
-
-@temprepo('branched2')
-def test_merge_personal_to_default(library):   
-    main = library.shelf(2)
-    print main
-    
-    local = library.shelf(7)
-    print local
+    assert_equal(sorted(library.documents()), sorted(['sample', 'sample_pl']))
 
 
-    document = library.document("ala", "admin")
-    shared = document.shared()
-    assert_true( shared is None )
-    document.share("Here is my copy!")
-
-    assert_equal( document.shelf(), local) # local didn't change
-
-    shared = document.shared()
-    assert_true( shared is not None )
-
-    print library.shelf()
-
-    new_main = shared.shelf()
-    assert_not_equal( new_main, main) # main has new revision
-
-    # check for parents
-    assert_true( main.parentof(new_main) )
-    assert_true( local.parentof(new_main) )
-
-@temprepo('clean')
-def test_create_branch(library):   
-    tester_cab = library.cabinet("anotherone", "tester", create=True)
-    assert_equal( list(tester_cab.parts()), ['anotherone'])
+    doc = library.document_create("creation")
+    doc.quickwrite("xml", "<ala />", "Quick write", user="library")
+    
+    assert_equal(sorted(library.documents()), sorted(['sample', 'sample_pl', 'creation']))
+        
+#
+#@temprepo('branched')
+#def test_switch_branch(library):
+#    tester_cab = library.cabinet("valid_file", "tester", create=False)
+#    assert_equal( list(tester_cab.parts()), ['valid_file'])
+#
+#@raises(wlrepo.CabinetNotFound)
+#@temprepo('branched')
+#def test_branch_not_found(library):
+#    tester_cab = library.cabinet("ugh", "tester", create=False)
+#
+#@temprepo('branched')
+#def test_no_branches(library):
+#    n4 = library.shelf(4)
+#    n3 = library.shelf(3)
+#    n2 = library.shelf(2)
+#    n1 = library.shelf(1)
+#    n0 = library.shelf(0)
+#
+#    assert_true( n3.parentof(n4) )
+#    assert_false( n4.parentof(n3) )
+#    assert_true( n0.parentof(n1) )
+#    assert_false( n1.parentof(n0) )
+#    assert_false( n0.parentof(n4) )
+#
+## def test_ancestor_of_simple(self):
+#    assert_true( n3.ancestorof(n4) )
+#    assert_true( n2.ancestorof(n4) )
+#    assert_true( n1.ancestorof(n4) )
+#    assert_true( n0.ancestorof(n4) )
+#
+#    assert_true( n2.ancestorof(n3) )
+#    assert_true( n1.ancestorof(n3) )
+#    assert_true( n0.ancestorof(n3) )
+#
+#    assert_false( n4.ancestorof(n4) )
+#    assert_false( n4.ancestorof(n3) )
+#    assert_false( n3.ancestorof(n2) )
+#    assert_false( n3.ancestorof(n1) )
+#    assert_false( n3.ancestorof(n0) )
+#
+## def test_common_ancestor_simple(self):
+#    assert_true( n3.has_common_ancestor(n4) )
+#    assert_true( n3.has_common_ancestor(n3) )
+#    assert_true( n3.has_common_ancestor(n3) )
+#
+#
+#@temprepo('branched2')
+#def test_once_branched(library):
+#    n7 = library.shelf(7)
+#    n6 = library.shelf(6)
+#    n5 = library.shelf(5)
+#    n4 = library.shelf(4)
+#    n3 = library.shelf(3)
+#    n2 = library.shelf(2)
+#
+#    assert_true( n2.parentof(n3) )
+#    assert_false( n3.parentof(n2) )
+#
+#    assert_true( n2.parentof(n5) )
+#    assert_false( n5.parentof(n2) )
+#
+#    assert_false( n2.parentof(n4) )
+#    assert_false( n2.parentof(n6) )
+#    assert_false( n3.parentof(n5) )
+#    assert_false( n5.parentof(n3) )
+#
+## def test_ancestorof_branched(self):
+#    assert_true( n2.ancestorof(n7) )
+#    assert_false( n7.ancestorof(n2) )
+#    assert_true( n2.ancestorof(n6) )
+#    assert_false( n6.ancestorof(n2) )
+#    assert_true( n2.ancestorof(n5) )
+#    assert_false( n5.ancestorof(n2) )
+#
+#    assert_false( n3.ancestorof(n5) )
+#    assert_false( n5.ancestorof(n3) )
+#    assert_false( n4.ancestorof(n5) )
+#    assert_false( n5.ancestorof(n4) )
+#    assert_false( n3.ancestorof(n7) )
+#    assert_false( n7.ancestorof(n3) )
+#    assert_false( n4.ancestorof(n6) )
+#    assert_false( n6.ancestorof(n4) )
+#
+## def test_common_ancestor_branched(self):
+#    assert_true( n2.has_common_ancestor(n4) )
+#    assert_true( n2.has_common_ancestor(n7) )
+#    assert_true( n2.has_common_ancestor(n6) )
+#
+#    # cause it's not in the right branch
+#    assert_false( n5.has_common_ancestor(n3) )
+#    assert_false( n7.has_common_ancestor(n4) )
+#
+#@temprepo('merged')
+#def test_after_merge(library):
+#    n8 = library.shelf(8)
+#    n7 = library.shelf(7)
+#    n6 = library.shelf(6)
+#
+#    assert_true( n7.parentof(n8) )
+#    assert_false( n8.parentof(n7) )
+#
+#    assert_true( n7.ancestorof(n8) )
+#    assert_true( n6.ancestorof(n8) )
+#
+#
+#    assert_true( n7.has_common_ancestor(n8) )
+#    # cause it's not in the right branch
+#    assert_false( n8.has_common_ancestor(n7) )
+#
+#@temprepo('merged_with_local_commit')
+#def test_after_merge_and_local_commit(library):
+#    n9 = library.shelf(9)
+#    n8 = library.shelf(8)
+#    n7 = library.shelf(7)
+#    n6 = library.shelf(6)
+#
+#    assert_true( n7.parentof(n8) )
+#    assert_false( n8.parentof(n7) )
+#
+#    assert_true( n9.has_common_ancestor(n8) )
+#    # cause it's not in the right branch
+#    assert_false( n8.has_common_ancestor(n9) )
+#
+#
+#@temprepo('branched2')
+#def test_merge_personal_to_default(library):
+#    main = library.shelf(2)
+#    print main
+#
+#    local = library.shelf(7)
+#    print local
+#
+#    document = library.document("ala", "admin")
+#    shared = document.shared()
+#    assert_true( shared is None )
+#    document.share("Here is my copy!")
+#
+#    assert_equal( document.shelf(), local) # local didn't change
+#
+#    shared = document.shared()
+#    assert_true( shared is not None )
+#
+#    print library.shelf()
+#
+#    new_main = shared.shelf()
+#    assert_not_equal( new_main, main) # main has new revision
+#
+#    # check for parents
+#    assert_true( main.parentof(new_main) )
+#    assert_true( local.parentof(new_main) )
+#
+#@temprepo('clean')
+#def test_create_branch(library):
+#    tester_cab = library.cabinet("anotherone", "tester", create=True)
+#    assert_equal( list(tester_cab.parts()), ['anotherone'])
 
 
index 0e9ba8d..1a06476 100644 (file)
@@ -82,7 +82,7 @@ MIDDLEWARE_CLASSES = (
 ROOT_URLCONF = 'urls'
 
 TEMPLATE_DIRS = (
 ROOT_URLCONF = 'urls'
 
 TEMPLATE_DIRS = (
-    PROJECT_ROOT + '/templates'
+    PROJECT_ROOT + '/templates',    
 )
 
 # CSS and JS files to compress
 )
 
 # CSS and JS files to compress
diff --git a/project/templates/manager/pull_request.html b/project/templates/manager/pull_request.html
new file mode 100644 (file)
index 0000000..c03caab
--- /dev/null
@@ -0,0 +1,7 @@
+{% if objects %}
+    {% for pullreq in objects %}
+    <p>{{ pullreq }}</p>
+    {% endfor %}
+{% else %}
+    <p>Brak żądań</p>
+{% endif %}
diff --git a/project/templates/toolbar_api/scriptlets.js b/project/templates/toolbar_api/scriptlets.js
new file mode 100644 (file)
index 0000000..ae7e2df
--- /dev/null
@@ -0,0 +1,15 @@
+function SciptletCenter() {
+
+    this.scriptlets = {
+        {% for scriptlet in scriptlets %}
+        "{{scriptlet.name}}": function(context, params) {
+            {{scriptlet.code|safe}}
+        },
+        {% endfor %}
+
+        _none: null
+    };
+            
+}
+
+scriptletCenter = new ScriptletCenter();
\ No newline at end of file
diff --git a/project/templates/wysiwyg.html b/project/templates/wysiwyg.html
new file mode 100644 (file)
index 0000000..409e4f2
--- /dev/null
@@ -0,0 +1,92 @@
+{% extends 'base.html' %}
+
+{% block extrahead %}
+<style type="text/css">
+    #loremIpsum {
+        position: relative;        
+    }
+
+    /* #lorepmIpsum * {
+        position: relative;
+    } */
+
+    .element-overlay {
+        position: absolute;
+        opacity: 1;
+        background: green;
+        z-index: 100;
+        padding: 0px;
+    }
+
+    .element-overlay textarea {
+        opacity: 1;
+        background: white;
+        color: black;
+        border: 1px dashed red;
+        margin: 0px;
+        
+        
+        width: 100%;
+        height: 100%;
+    }
+</style>
+{% endblock %}
+
+{% block maincontent %}
+<h1>Wysiwyg editor</h1>
+<div>This part is not editable!</div>
+<div id="loremIpsum">
+
+<p>
+<p>Lorem <b>ipsum</b> dolor sit amet, consectetur adipiscing elit.
+    Suspendisse a urna eu enim rutrum elementum nec sed nibh. Quisque sed tortor
+    nulla, et euismod turpis. Morbi purus nulla, vulputate in vulputate id, gravida
+    id eros. In interdum est tempor est consequat imperdiet. Vivamus vitae ligula quam.
+    Proin nibh quam, tincidunt sit amet auctor eget, laoreet sit amet eros. Cras augue
+    lectus, euismod nec posuere ac, ultricies sed magna. Aliquam a lacinia sapien.
+    Cras imperdiet urna vel dui accumsan mollis. Suspendisse convallis tincidunt ornare.
+    Aenean convallis libero in lectus dictum vestibulum interdum ipsum suscipit.
+    Suspendisse sed justo sapien, eu egestas libero. Sed tincidunt sagittis sollicitudin.
+    Aliquam erat volutpat. Nullam egestas dolor id massa sagittis at sagittis ipsum
+    hendrerit.
+</p>
+
+<p>Phasellus sed purus non orci eleifend posuere ac eu elit. Etiam orci justo, porta vitae varius in, scelerisque sed metus. Phasellus faucibus lorem at metus scelerisque sit amet sollicitudin dolor dignissim. Aliquam eu justo in diam blandit posuere at a diam. Pellentesque tristique sem eu odio gravida eleifend. Phasellus cursus adipiscing metus, nec pharetra enim pharetra ac. Pellentesque faucibus volutpat lorem nec vulputate. Mauris in faucibus ipsum. Nulla ut urna nulla. Sed at tellus nec diam posuere porttitor. Duis faucibus, libero nec rhoncus facilisis, tortor ligula adipiscing massa, nec varius justo ante et magna. Donec orci mauris, ultrices nec blandit vel, lacinia in ante. Maecenas libero mi, pretium id ultricies eget, fringilla sit amet risus. Integer ut ante sem, et condimentum odio. Nam nec est erat. Etiam ut metus ligula. In vel condimentum orci.</p>
+
+<p>Suspendisse potenti. Proin in augue nibh. Curabitur in sollicitudin ipsum. In ut leo vel purus volutpat tempus. Proin ut neque at augue euismod ullamcorper nec ac dui. Vestibulum id quam nunc, eu porta augue. Pellentesque interdum neque eu nulla rhoncus vulputate. Sed viverra diam ac sem consectetur semper. Quisque consectetur fringilla quam, in feugiat nisl vulputate quis. Fusce vel ipsum lectus, eu interdum nunc. Donec luctus libero vitae mauris imperdiet at iaculis magna aliquet. Curabitur ullamcorper, diam nec pulvinar venenatis, nibh ante volutpat mauris, nec tristique lectus sem in urna. Aenean eu malesuada metus. Integer auctor nulla sit amet ligula sollicitudin ut accumsan velit ullamcorper. Donec nec auctor augue.</p>
+
+<p>Maecenas eget lacus vitae velit tincidunt bibendum quis et diam. In ullamcorper condimentum velit, et elementum felis vestibulum facilisis. Donec vitae cursus ipsum. Cras accumsan tincidunt aliquet. Nulla pellentesque mattis magna aliquet hendrerit. Pellentesque pellentesque odio enim. Duis viverra rhoncus tristique. In in risus ligula. Nullam dapibus lacinia facilisis. Ut eu neque neque, tristique laoreet nisl. Aliquam placerat dignissim leo, tristique tempor est vestibulum ut.</p>
+
+<p>Donec semper tempus ante, eget gravida erat varius et. Suspendisse aliquam rutrum nunc ac pulvinar. Aliquam erat volutpat. Nulla consectetur ultricies imperdiet. Nulla tincidunt est vitae augue porttitor a faucibus odio facilisis. In nec nisl odio. Aliquam et libero tortor, eu tincidunt mi. Vivamus suscipit erat sed mi hendrerit fringilla. Integer iaculis tempus nulla, at egestas velit faucibus ut. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum vel massa enim. Aliquam erat volutpat. In ligula tortor, fermentum eu suscipit at, posuere vel nunc. Nullam nibh magna, sollicitudin at semper et, mattis ut quam. Curabitur accumsan semper elit ac posuere. Sed sit amet lorem tortor, vel porttitor justo. Fusce odio metus, bibendum ut bibendum sit amet, luctus a ipsum. </p>
+</div>
+{% endblock %}
+
+{% block extrabody %}
+<script type="text/javascript">
+$(function() {
+    var lorem = $('#loremIpsum');
+    
+    var x = $('#loremIpsum *');
+    
+    x.click( function(event)
+    {
+        var e = $(this);
+        $.log("Overlaying element: ", this);        
+        var p = e.offsetParent();
+        var pos = e.position();
+        var marginTop = parseInt(e.css('margin-top'));
+
+        $.log("Offset: ", pos, p);
+        var overlay = $('<div class="element-overlay"><textarea></textarea></div>');
+        var text = $('textarea', overlay);
+        text.val(e.text());
+                
+        p.prepend(overlay);
+        
+        overlay.css({ top: pos.top+marginTop, left: pos.left, width: e.width(), height: e.height()});
+        
+        return false;
+    })
+});
+</script>
+{% endblock %}
\ No newline at end of file