[Zope3-checkins] CVS: Zope3/src/zope/app/browser/fssync - __init__.py:1.2 configure.zcml:1.2 fromFS.pt:1.2

Philipp von Weitershausen philikon at philikon.de
Tue Feb 24 11:49:14 EST 2004


Update of /cvs-repository/Zope3/src/zope/app/browser/fssync
In directory cvs.zope.org:/tmp/cvs-serv25869/src/zope/app/browser/fssync

Added Files:
	__init__.py configure.zcml fromFS.pt 
Log Message:


Created an fssync browser package for general fssync browser views,
which were formerly located in the no longer existing
zope.app.browser.content package.




=== Zope3/src/zope/app/browser/fssync/__init__.py 1.1 => 1.2 ===
--- /dev/null	Tue Feb 24 11:49:14 2004
+++ Zope3/src/zope/app/browser/fssync/__init__.py	Tue Feb 24 11:49:13 2004
@@ -0,0 +1,231 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors.
+# All Rights Reserved.
+# 
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+# 
+##############################################################################
+"""Code for the toFS.snarf view and its inverse, fromFS.snarf.
+
+$Id$
+"""
+import os
+import cgi
+import shutil
+import tempfile
+
+from transaction import get_transaction
+
+from zope.app.publisher.browser import BrowserView
+from zope.app.traversing import getName, getParent, getRoot
+from zope.fssync.snarf import Snarfer, Unsnarfer
+from zope.app.fssync import syncer
+from zope.app.fssync.committer import Committer, Checker
+from zope.fssync.metadata import Metadata
+
+from zope.app.i18n import ZopeMessageIDFactory as _
+
+def snarf_dir(response, dirname):
+    """Helper to snarf a directory to the response."""
+    response.setStatus(200)
+    response.setHeader("Content-Type", "application/x-snarf")
+    snf = Snarfer(response)
+    snf.addtree(dirname)
+    return ""
+
+class SnarfFile(BrowserView):
+    """View returning a snarfed representation of an object tree.
+
+    This applies to any object (for="zope.interface.Interface").
+    """
+
+    def show(self):
+        """Return the snarfed response."""
+        dirname = tempfile.mktemp()
+        try:
+            os.mkdir(dirname)
+            syncer.toFS(self.context,
+                        getName(self.context) or "root",
+                        dirname)
+            return snarf_dir(self.request.response, dirname)
+        finally:
+            if os.path.isdir(dirname):
+                shutil.rmtree(dirname)
+
+class NewMetadata(Metadata):
+    """Subclass of Metadata that sets the 'added' flag in all entries."""
+
+    def getentry(self, file):
+        entry = Metadata.getentry(self, file)
+        if entry:
+            entry["flag"] = "added"
+        return entry
+
+
+class SnarfSubmission(BrowserView):
+    """Base class for the commit and checkin views."""
+
+    def run(self):
+        self.check_content_type()
+        self.set_transaction()
+        self.parse_args()
+        self.set_note()
+        try:
+            self.make_tempdir()
+            self.set_arguments()
+            self.make_metadata()
+            self.unsnarf_body()
+            return self.run_submission()
+        finally:
+            self.remove_tempdir()
+
+    def check_content_type(self):
+        if not self.request.getHeader("Content-Type") == "application/x-snarf":
+            raise ValueError(_("Content-Type is not application/x-snarf"))
+
+    def set_transaction(self):
+        self.txn = get_transaction()
+
+    def parse_args(self):
+        # The query string in the URL didn't get parsed, because we're
+        # getting a POST request with an unrecognized content-type
+        qs = self.request._environ.get("QUERY_STRING")
+        if qs:
+            self.args = cgi.parse_qs(qs)
+        else:
+            self.args = {}
+
+    def get_arg(self, key):
+        value = self.request.get(key)
+        if value is None:
+            values = self.args.get(key)
+            if values is not None:
+                value = " ".join(values)
+        return value
+
+    def set_note(self):
+        note = self.get_arg("note")
+        if note:
+            self.txn.note(note)
+
+    tempdir = None
+
+    def make_tempdir(self):
+        self.tempdir = tempfile.mktemp()
+        os.mkdir(self.tempdir)
+
+    def remove_tempdir(self):
+        if self.tempdir and os.path.exists(self.tempdir):
+            shutil.rmtree(self.tempdir)
+
+    def unsnarf_body(self):
+        fp = self.request.bodyFile
+        fp.seek(0)
+        uns = Unsnarfer(fp)
+        uns.unsnarf(self.tempdir)
+
+    def call_committer(self):
+        c = Committer(syncer.getSerializer, self.metadata,
+                      getAnnotations=syncer.getAnnotations)
+        c.synch(self.container, self.name, self.fspath)
+
+
+class SnarfCheckin(SnarfSubmission):
+    """View for checking a new sub-tree into Zope.
+
+    The input should be a POST request whose data is a snarf archive.
+    This creates a brand new tree and doesn't return anything.
+    """
+
+    def run_submission(self):
+        # XXX need to make sure the top-level name doesn't already
+        # exist, or existing site data can get screwed
+        self.call_committer()
+        return ""
+
+    def set_arguments(self):
+        # Compute self.{name, container, fspath} for checkin()
+        name = self.get_arg("name")
+        if not name:
+            raise ValueError(_("required argument 'name' missing"))
+        src = self.get_arg("src")
+        if not src:
+            src = name
+        self.container = self.context
+        self.name = name
+        self.fspath = os.path.join(self.tempdir, src)
+
+    def make_metadata(self):
+        self.metadata = NewMetadata()
+
+
+class SnarfCommit(SnarfSubmission):
+    """View for committing changes to an existing tree.
+
+    The input should be a POST request whose data is a snarf archive.
+    It returns an updated snarf archive, or a text document with
+    errors.
+    """
+
+    def run_submission(self):
+        self.call_checker()
+        if self.errors:
+            return self.send_errors()
+        else:
+            self.call_committer()
+            self.write_to_filesystem()
+            return self.send_archive()
+
+    def set_arguments(self):
+        # Compute self.{name, container, fspath} for commit()
+        self.name = getName(self.context)
+        self.container = getParent(self.context)
+        if self.container is None and self.name == "":
+            # Hack to get loading the root to work
+            self.container = getRoot(self.context)
+            self.fspath = os.path.join(self.tempdir, "root")
+        else:
+            self.fspath = os.path.join(self.tempdir, self.name)
+
+    def make_metadata(self):
+        self.metadata = Metadata()
+
+    def get_checker(self, raise_on_conflicts=False):
+        return Checker(syncer.getSerializer,
+                       self.metadata,
+                       raise_on_conflicts,
+                       getAnnotations=syncer.getAnnotations)
+
+    def call_checker(self):
+        if self.get_arg("raise"):
+            c = self.get_checker(True)
+        else:
+            c = self.get_checker()
+        c.check(self.container, self.name, self.fspath)
+        self.errors = c.errors()
+
+    def send_errors(self):
+        self.txn.abort()
+        lines = [_("Up-to-date check failed:")]
+        tempdir_sep = os.path.join(self.tempdir, "") # E.g. foo -> foo/
+        for e in self.errors:
+            lines.append(e.replace(tempdir_sep, ""))
+        lines.append("")
+        self.request.response.setHeader("Content-Type", "text/plain")
+        return "\n".join(lines)
+
+    def write_to_filesystem(self):
+        shutil.rmtree(self.tempdir) # Start with clean slate
+        os.mkdir(self.tempdir)
+        syncer.toFS(self.context,
+                    getName(self.context) or "root",
+                    self.tempdir)
+
+    def send_archive(self):
+        return snarf_dir(self.request.response, self.tempdir)


=== Zope3/src/zope/app/browser/fssync/configure.zcml 1.1 => 1.2 ===
--- /dev/null	Tue Feb 24 11:49:14 2004
+++ Zope3/src/zope/app/browser/fssync/configure.zcml	Tue Feb 24 11:49:14 2004
@@ -0,0 +1,31 @@
+<zope:configure
+   xmlns="http://namespaces.zope.org/browser"
+   xmlns:zope="http://namespaces.zope.org/zope">
+
+  <!-- toFS.snarf and fromFS.snarf views, for new fssync tools -->
+
+  <!-- fssync checkout, update -->
+  <page
+      for="zope.interface.Interface"
+      name="toFS.snarf"
+      permission="zope.ManageServices"
+      class=".SnarfFile"
+      attribute="show" />
+
+  <!-- fssync commit -->
+  <page
+      for="zope.interface.Interface"
+      name="fromFS.snarf"
+      permission="zope.ManageServices"
+      class=".SnarfCommit"
+      attribute="run" />
+
+  <!-- fssync checkin -->
+  <page
+      for="zope.interface.Interface"
+      name="checkin.snarf"
+      permission="zope.ManageServices"
+      class=".SnarfCheckin"
+      attribute="run" />
+
+</zope:configure>


=== Zope3/src/zope/app/browser/fssync/fromFS.pt 1.1 => 1.2 ===
--- /dev/null	Tue Feb 24 11:49:14 2004
+++ Zope3/src/zope/app/browser/fssync/fromFS.pt	Tue Feb 24 11:49:14 2004
@@ -0,0 +1,26 @@
+<html metal:use-macro="views/standard_macros/page">
+<body>
+<div metal:fill-slot="body">
+
+  <h1 i18n:translate="">Commit Action</h1>
+
+  <div tal:define="status view/update"
+       tal:condition="status"
+       i18n:translate="">
+  Commit results:
+  <pre tal:content="status" i18n:name="results">
+    Status from update method goes here.
+  </pre>
+  </div>
+
+  <p i18n:translate="">Upload a zipfile in the following form</p>
+
+  <form method="post" action="@@fromFS.html" enctype="multipart/form-data">
+    <input type="file" name="zipfile" size="40" />
+    <input type="submit" value="Upload"
+           i18n:attributes="value upload-button"/>
+  </form>
+
+</div>
+</body>
+</html>




More information about the Zope3-Checkins mailing list