Commits

Andrew Godwin committed aa65016

Fixes for general stuff, and svn cat, courtesy of jespern

  • Participants
  • Parent commits 8dd124b

Comments (0)

Files changed (7)

File heechee/repo/__init__.py

 """
 
 import os
+import hashlib
 
 from heechee.exceptions import *
 
             return tree_get(tree, path.strip("/").split("/"))
         except PathTraversalError:
             return None
-    
+        
     def _identify_path(self, path):
         """
         Given a path, returns a tuple of (type, value, relative_path).
     def __repr__(self):
         return "<File '%s' in '%s'>" % (self.name, self.parent.get_path())
     
+    def md5(self):
+        return hashlib.md5(self.contents).hexdigest()
+    
     def print_tree(self, indent=0):
         print " "*indent + " - " + self.name
     

File heechee/repo/hg.py

         # Tags
         tags = Directory(name="tags", parent=root)
         for tag in self._tags(revision):
+            # Don't include 'tip' as a tag.
+            if tag == 'tip':
+                continue
+
             self._tree_for_changectx(
                 self.hg_repo.changectx(tag),
                 tag,

File heechee/tests/base.py

 import shutil
 import time
 import socket
+import signal
 try:
     from cStringIO import StringIO
 except ImportError:
         shutil.rmtree(self.source_dir)
         shutil.rmtree(self.target_dir)
         # Kill server, and wait till it dies
-        self.server.kill()
-        self.server.wait()
+        os.kill(self.server.pid, signal.SIGKILL)
+#        self.server.kill()
+#        self.server.wait()
     
     def init_repo(self):
         "Should be overridden to initialise the repository."

File heechee/tests/mercurial.py

         ])
         # Check things are there
         self.assert_contents("checkout/trunk/a", "a\n")
-        self.assert_contents("checkout/tags/tip/a", "a\n")
         self.assert_contents("checkout/branches/branch1/b", "b\n")
         self.assert_contents("checkout/branches/branch1/dir/c", "c\n")
         # Check there's no default branch (it's trunk)
             self.target_cmds("svn ls http://localhost:8080/trunk/"),
             "a\n",
         )
+
+    def test_cat(self):
+        self.assert_equal(
+            self.target_cmds("svn cat http://localhost:8080/trunk/a"),
+            "a\n",
+        )    
     
     def test_update(self):
         # First, get a checkout.

File heechee/webdav/__init__.py

 from heechee.webdav.props import PropsMixin
 from heechee.webdav.report import ReportMixin
 from heechee.webdav.commit import CommitMixin
+from heechee.webdav.read import ReaderMixin
 
 
 class DAVRequest(Request):
         return fromstring(self.input_stream.read(self.content_length))
 
 
-class RepositoryServer(PropsMixin, ReportMixin, CommitMixin):
+class RepositoryServer(PropsMixin, ReportMixin, CommitMixin, ReaderMixin):
     """
     Main WSGI app for serving repositories. Only serves one; you'll need to use
     your own routing/creation logic and the Power Of WSGI to serve more.
         "DELETE",
         "PUT",
         "MKCOL",
+        "GET",
     ])
     
     write_verbs = frozenset([

File heechee/webdav/props.py

 from werkzeug.exceptions import BadRequest, NotFound
 
 from heechee.constants import *
-from heechee.repo import Directory
+from heechee.repo import Directory, File
 
 class PropsMixin(object):
     
         """
         # Find out what properties they want
         tree = request.xml_body
-        
+                        
         try:
             props = [x.tag.split("}")[-1] for x in tree.find(DAV_NS+"prop").getchildren()]
         except AttributeError:
         
         if "!svn" not in request.path:
             # If it doesn't exist, don't show it.
-            if self.repo.get_file(request.path, revision) is None:
+            file_ = self.repo.get_file(request.path, revision)
+
+            if file_ is None:
                 return NotFound()
+
             # Return a response
-            answers = self._props_for_file(request, "", props, top_revision)
+            answers = self._props_for_file(request, "", props, top_revision, isinstance(file_, Directory))
             response = self._propstat_response([(request.path, answers)])
         
         # They're asking for the Version Control Configuration.
             response = self._propstat_response([(request.path, answers)])
         
         # Baseline collections.
-        elif request.path.startswith("/!svn/bc/"):
-            
+        elif request.path.startswith("/!svn/bc/"):            
             parts = request.path.strip("/").split("/")
             revision = parts[2]
             path = "/".join(parts[3:])
             
             # How deep do they want to go?
             if depth == 0:
-                paths = [("", True)]
+                file_ = self.repo.get_file(path, revision)
+                
+                if isinstance(file_, File):
+                    paths = [(path, False)]
+                else:
+                    paths = [("", True)]
             elif depth == 1:
                 paths = [("", True)]
                 for name, item in self.repo.get_file(path, revision).children.items():
                     paths.append((name, isinstance(item, Directory)))
             else:
                 raise BadRequest("Cannot PROPFIND more than 1 deep.")
-        
+                
             response = self._propstat_response([
                 (
                     path,
-                    self._props_for_file(request, "", props, revision, is_dir),
+                    self._props_for_file(request, path, props, revision, is_dir),
                 )
                 for path, is_dir in paths
             ])
                 answers[DAV_NS+"checked-in"] = self._href(request.script_root + "/!svn/ver/%s/%s" % (revision, request.path.strip("/")))
         if "version-name" in props:
             answers[DAV_NS+"version-name"] = revision
+        if "md5-checksum" in props:
+            answers[SVN_DAV_NS+"md5-checksum"] = self.repo.get_file(path, revision).md5()
         return answers
     
     def _propstat_response(self, path_props, href_path=None, status="HTTP/1.1 200 OK"):

File heechee/webdav/read.py

+from lxml.etree import tostring, Element, SubElement
+from werkzeug.wrappers import Response
+from werkzeug.exceptions import BadRequest, NotFound
+
+from heechee.constants import *
+from heechee.repo import File, Directory
+
+class ReaderMixin(object):
+    def GET(self, request):
+        if request.path.startswith("/!svn/bc/"):
+            parts = request.path.strip("/").split("/")
+            revision = parts[2]
+            path = "/".join(parts[3:])
+
+            file_ = self.repo.get_file(path, revision)
+
+            if not file_:
+                raise NotFound()
+
+            return Response(file_.contents, status=200)
+        else:
+            raise BadRequest()
+