Commits

Andrew Godwin committed b2e8734

Disk caching, and fix to cache key. Also, small fix to log queries on /tags/ or /branches/ directly.

  • Participants
  • Parent commits e225f72

Comments (0)

Files changed (9)

heechee/repo/__init__.py

             return ("branch", bits[1], "/".join(bits[2:]))
         elif bits[0] == "tags" and len(bits) > 1:
             return ("tag", bits[1], "/".join(bits[2:]))
+        elif bits[0] == "tags" and len(bits) == 1:
+            return ("tags-root", None, None)
+        elif bits[0] == "branches" and len(bits) == 1:
+            return ("branches-root", None, None)
         else:
             raise ValueError("Unknown path format: %r" % path)
 

heechee/repo/hg.py

 
 class Repository(RepositoryBase):
     
-    uuid = "00000000-0000-0000-0000-000000000001"
-    
     def __init__(self, directory):
         super(Repository, self).__init__()
         # Set our repo
                 # Tag mode. Currently, show only the tag's log message.
                 if self.hg_repo[value] != changectx:
                     continue
+            elif type in ["tags-root", "branches-root"]:
+                # We currently show no logs for these.
+                continue
             # Alright, see if our file's in here.
             for changed_path in changectx.files():
                 if changed_path.startswith(subpath):

heechee/tests/__init__.py

 
 import unittest
 
-from heechee.tests.mercurial import MercurialTests, MercurialHydraTests
+from heechee.tests.mercurial import MercurialTests, MercurialHydraTests, MercurialCacheTests
 from heechee.tests.svndiff import SvnDiffTests
 
 if __name__ == '__main__':

heechee/tests/base.py

 class HeecheeTest(unittest.TestCase):
     
     use_hydra = False
+    use_cache = False
     
     def setUp(self):
         "Sets up a target directory and a source repo."
         self.source_dir = tempfile.mkdtemp(suffix="-heechee-src")
         self.target_dir = tempfile.mkdtemp(suffix="-heechee-tgt")
+        
         if self.use_hydra:
             path_pattern = os.path.join(self.source_dir, "%s")
             self.source_dir = os.path.join(self.source_dir, "subdir")
             os.mkdir(self.source_dir)
-            self.init_repo()
-            self.server = subprocess.Popen(
-                ["python", "-m", "heechee.webdav.hydra", "^/([^/]+)", path_pattern],
-                stdout=subprocess.PIPE,
-                stderr=subprocess.PIPE,
-            )
+            args = ["python", "-m", "heechee.webdav.hydra", "^/([^/]+)", path_pattern],
         else:
-            self.init_repo()
-            self.server = subprocess.Popen(
-                ["python", "-m", "heechee.webdav.__init__", self.source_dir],
-                stdout=subprocess.PIPE,
-                stderr=subprocess.PIPE,
-            )
+            args = ["python", "-m", "heechee.webdav.__init__", self.source_dir]
+        
+        if self.use_cache:
+            args.append("--cache")
+        
+        self.init_repo()
+        self.server = subprocess.Popen(
+            args,
+            stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE,
+        )
+        
         # Wait for server to come up
         for i in range(20):
             s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

heechee/tests/mercurial.py

     url_prefix = "subdir/"
 
 
+class MercurialCacheTests(MercurialTests):
+    
+    use_cache = True
+
+
 if __name__ == '__main__':
     unittest.main()

heechee/webdav/__init__.py

 from heechee.webdav.read import ReaderMixin
 from heechee.webdav.storage import FileStorage
 from heechee.webdav.caching.noop import NoopCache
+from heechee.webdav.caching.disk import DiskCache
 
 class DAVRequest(Request):
     """
         """
         Uses the request and the repo to make a cache key.
         """
-        return "%s:%s:%s" % (request.method, str(self.repo.mtime()), md5(request.path + ":" + request.raw_body).hexdigest())
+        return "%s:%s:%s:%s" % (request.method, self.repo.uuid, str(self.repo.mtime()), md5(request.path + ":" + request.raw_body).hexdigest())
     
     def access_check(self, request, accesss_type):
         # Get their status
         help="Repository type, 'hg' or 'git'. Autodetected by default.")
     parser.add_option("--debug", action='store_true', default=False,
         help="Display debug output (warning: there's lots)")
+    parser.add_option("--cache", action='store_true', default=False,
+        help="Turns on simple disk caching.")
 
     options, args = parser.parse_args()
     if len(args) < 1:
         level=options.debug and logging.DEBUG or logging.INFO,
         datefmt="%Y-%m-%d %H:%M:%S",
     )
+    
+    if options.cache:
+        cache = DiskCache()
+        from heechee.webdav.caching.memcached import MemcachedCache
+        cache = MemcachedCache(["127.0.0.1"])
+    else:
+        cache = NoopCache()
 
     from werkzeug import run_simple
     run_simple(
         'localhost',
         options.port,
-        RepositoryServer(get_repository(repopath, options.repo_type)),
+        RepositoryServer(
+            repo = get_repository(repopath, options.repo_type),
+            cache = cache,
+        ),
     )

heechee/webdav/caching/disk.py

+
+try:
+    import cPickle as pickle
+except ImportError:
+    import pickle
+
+try:
+    from hashlib import md5
+except ImportError:
+    from md5 import md5
+
+import os
+
+class DiskCache(object):
+    
+    """
+    Simple disk cache, using hashes of the keys as filenames.
+    Might well have undetected collisions; only for toy/test use.
+    """
+    
+    def __init__(self, path=None):
+        self.path = path or "/tmp/heechee-cache/"
+        if not os.path.isdir(self.path):
+            os.makedirs(self.path)
+    
+    def _file_for_key(self, key):
+        return os.path.join(self.path, md5(key).hexdigest() + ".cache")
+    
+    def __getitem__(self, key):
+        try:
+            fh = open(self._file_for_key(key), "rb")
+        except IOError:
+            raise KeyError("Key %r not found" % key)
+        data = pickle.load(fh)
+        fh.close()
+        return data
+    
+    def __setitem__(self, key, value):
+        fh = open(self._file_for_key(key), "wb")
+        pickle.dump(value, fh)
+        fh.close()

heechee/webdav/caching/memcached.py

+
+try:
+    import cmemcache as memcache
+except ImportError:
+    import memcache
+
+try:
+    from hashlib import md5
+except ImportError:
+    from md5 import md5
+
+class MemcachedCache(object):
+    
+    """
+    Simple disk cache, using hashes of the keys as filenames.
+    Might well have undetected collisions; only for toy/test use.
+    """
+    
+    def __init__(self, servers, timeout=600):
+        """
+        Constructor. 'servers' is a LIST of servers to connect to.
+        """
+        self._cache = memcache.Client(servers)
+        self.timeout = timeout
+    
+    def __getitem__(self, key):
+        #print "cache TRY: %r" % key
+        value = self._cache.get(key)
+        if value is not None:
+            #print "cache HIT"
+            return value
+        else:
+            raise KeyError("No such key %r" % key)
+    
+    def __setitem__(self, key, value):
+        #print "cache SET: %r (%i)" % (key, len(value))
+        self._cache.add(key, value, self.timeout)

heechee/webdav/props.py

         # Try getting a cached copy
         cache_key = self._cache_key(request)
         try:
-            return self.cache[cache_key]
+            return Response(self.cache[cache_key], status = 207)
         except KeyError:
             pass