diff dogdish/dispatcher.py @ 14:cffb6f681b59

things seem to work
author Jeff Hammel <jhammel@mozilla.com>
date Wed, 17 Oct 2012 13:26:22 -0700
parents 71f9f68986b5
children fc5b842de4e9
line wrap: on
line diff
--- a/dogdish/dispatcher.py	Wed Oct 17 10:56:38 2012 -0700
+++ b/dogdish/dispatcher.py	Wed Oct 17 13:26:22 2012 -0700
@@ -6,6 +6,7 @@
 """
 
 import fnmatch
+import hashlib
 import os
 import sys
 from urlparse import urlparse
@@ -23,13 +24,18 @@
         """
         - filename : path to an application.ini file
         """
+        config = ConfigParser()
+        config.read(filename)
+        self.build_id = config.get('App', 'BuildID')
+        self.version = config.get('App', 'Version')
 
 ### request handlers
 
 class Handler(object):
     """abstract handler object for a request"""
 
-    def __init__(self, request):
+    def __init__(self, app, request):
+        self.app = app
         self.request = request
         self.application_path = urlparse(request.application_url)[2]
 
@@ -54,7 +60,7 @@
     body = """<?xml version="1.0"?>
 <updates>
   <update type="minor" appVersion="19.0a1" version="19.0a1" extensionVersion="19.0a1" buildID="20121010114416" licenseURL="http://www.mozilla.com/test/sample-eula.html" detailsURL="http://www.mozilla.com/test/sample-details.html">
-    <patch type="complete" URL="http://update.boot2gecko.org/nightly/b2g_update_2012-10-10_114416.mar%(query)s" hashFunction="SHA512" hashValue="84edb1f53891cf983bc0f6066d31492f43e2d063aaceb05e1c51876f4fde81635afeb7ce3203dee6f65dd59be0cae5c73c49093b625c99acd4118000ad72dda8" size="42924805"/>
+    <patch type="complete" URL="http://update.boot2gecko.org/nightly/%(update)s%(query)s" hashFunction="SHA512" hashValue="%(hash)s" size="%(size)s"/>
   </update>
 </updates>"""
 
@@ -65,20 +71,32 @@
         return request.method == 'GET'
 
     def __call__(self):
+
+        update_path = os.path.join(self.app.directory, self.app.current_update)
         body = self.body
         query = {}
         dogfood_id = self.request.GET.get('dogfood_id')
         if dogfood_id:
             query['dogfooding_prerelease_id'] = dogfood_id
+        application = self.app.updates[self.app.current_update]
+        query['build_id'] = application.build_id
+        query['version'] = application.version
 
         # build query string
         if query:
-            query = '?' + '&'.join(['%s=%s' % (key, value) for key, value in query.items()])
+            query = '?' + '&amp;'.join(['%s=%s' % (key, value) for key, value in query.items()])
         else:
             query = ''
 
+        # compute the hash
+        with file(update_path) as f:
+            sha512 = hashlib.sha512(f.read()).hexdigest()
+
         # template variables
-        variables = dict(query=query)
+        variables = dict(update=self.app.current_update,
+                         size=os.path.getsize(update_path),
+                         hash=sha512,
+                         query=query)
 
         return Response(content_type='text/xml',
                         body=body % variables)
@@ -96,28 +114,40 @@
         for key in self.defaults:
             setattr(self, key, kw.get(key, self.defaults[key]))
         self.handlers = [ Get ]
+
+        # cache
         self.updates = {}
         self.current_update = None
         self.current_stamp = '0000-00-00_000000'
+        self.cached_response = None
 
         # scan directory
         self.scan()
+        assert self.current_update # ensure there is at least one update
 
     def __call__(self, environ, start_response):
         """WSGI application"""
 
         request = Request(environ)
+        new = self.scan()
+        if (not new) and (self.cached_response is not None):
+            return self.cached_response(environ, start_response)
         for h in self.handlers:
             if h.match(request):
-                handler = h(request)
+                handler = h(self, request)
+                res = handler()
+                self.cached_response = res
                 break
         else:
-            handler = exc.HTTPNotFound
-        res = handler()
+            res = exc.HTTPNotFound()
+
         return res(environ, start_response)
 
     def scan(self):
-        """scan the directory for updates"""
+        """
+        scan the directory for updates
+        returns True if new updates are found, False otherwise
+        """
         prefix = 'b2g_update_'
         suffix = '.mar'
         contents = [i for i in os.listdir(self.directory)
@@ -126,7 +156,7 @@
         new = contents.difference(self.updates.keys())
         if not new:
             # directory contents unchanged from cached values
-            return
+            return False
 
         for update in new:
             stamp = update[len(prefix):-len(suffix)]
@@ -138,6 +168,10 @@
                 self.current_update = update
                 self.current_stamp = stamp
 
+        # TODO: could remove old files from the cache if not found in contents
+
+        return True
+
 def main(args=sys.argv[1:]):
     """CLI entry point"""