The unified diff between revisions [b5d299ba..] and [0ab83940..] is displayed below. It can also be downloaded as a raw diff.

#
#
# add_file "templates/choosedb.html"
#  content [f5ff719c96f6fc77e0a5ee87e580f665c31045e0]
#
# patch "handlers.py"
#  from [40025bb9507077ea448d3bb4d4a56fe707e6d658]
#    to [b926e4cef8392d53d202fd2b2a3c1516e3926647]
#
# patch "render.py"
#  from [b93fcb701c8361ee69bdffaf507de225768315b0]
#    to [42ef0a569ef15c1531cc61f651915fb3ab72b991]
#
# patch "urls.py"
#  from [c3d91fe05c4521342fab6d19176aae9c9ef42ea7]
#    to [6b5de415d1379a5445ab81002426e91c61213df9]
#
# patch "viewmtn.py"
#  from [4711109e7e0e383a480fde9fae671de24ce92401]
#    to [b21dfade3155090e53a021f01d797d8ea0f0c99c]
#
============================================================
--- templates/choosedb.html	f5ff719c96f6fc77e0a5ee87e580f665c31045e0
+++ templates/choosedb.html	f5ff719c96f6fc77e0a5ee87e580f665c31045e0
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+<title>ViewMTN: $(page_title)</title>
+<link rel="stylesheet" href="$static_join('viewmtn.css')" type="text/css" media="screen" />
+<link rel="stylesheet" href="$static_join('highlight.css')" type="text/css" media="screen" />
+</head>
+<body>
+
+<div id="menuBar">
+  <strong>ViewMTN &mdash; choose database to access</strong>
+</div>
+
+<p>
+    Welcome to this ViewMTN installation. Please select the <a href="http://www.monotone.ca/monotone/">Monotone</a>
+    database you wish to access from the table below.
+</p>
+
+<table class="pretty">
+<tr><th>Database</th><th>Description</th></tr>
+#for db in $databases
+<tr>
+  <td valign="top">
+      <a href="$nodb_join($db.name)/">$db.name</a>
+  </td>
+  <td>
+    $db.description
+  </td>
+</tr>
+#end for
+</table>
+
+<div id="footer">
+  ViewMTN $version<br />
+</div>
+
+</body>
+</html>
============================================================
--- handlers.py	40025bb9507077ea448d3bb4d4a56fe707e6d658
+++ handlers.py	b926e4cef8392d53d202fd2b2a3c1516e3926647
@@ -760,13 +760,23 @@ class Databases(object):
         databases = []
         keys = ctxt.db_summary.keys()
         keys.sort()
-	for k in keys:
+        for k in keys:
             databases.append ({'name':k, 'description':ctxt.db_summary[k]})
         ctxt.render('databases.html',
                     page_title="Change database",
                     databases=databases)
-

+class ChooseDatabase(object):
+    def GET(self, factory):
+        databases = []
+        keys = factory.db_summary.keys()
+        keys.sort()
+        for k in keys:
+            databases.append ({'name':k, 'description':factory.db_summary[k]})
+        factory.renderer.render(factory, 'choosedb.html',
+                                page_title="Change database",
+                                databases=databases)
+
 class MimeIcon(object):
     def GET(self, type, sub_type):
         if not mimeicon:
============================================================
--- render.py	b93fcb701c8361ee69bdffaf507de225768315b0
+++ render.py	42ef0a569ef15c1531cc61f651915fb3ab72b991
@@ -161,8 +161,8 @@ class Renderer(object):
         self.load_templates()
         terms = self.terms.copy()
         terms.update(kwargs)
-        terms['link'] = ctxt.link
-        terms['perdb_join'] = ctxt.perdb_join
-        terms['nodb_join'] = ctxt.nodb_join
-        terms['static_join'] = ctxt.static_join
+        terms['link'] = getattr(ctxt, 'link', None)
+        terms['perdb_join'] = getattr(ctxt, 'perdb_join', None)
+        terms['nodb_join'] = getattr(ctxt, 'nodb_join', None)
+        terms['static_join'] = getattr(ctxt, 'static_join', None)
         web.render(template, terms)
============================================================
--- urls.py	c3d91fe05c4521342fab6d19176aae9c9ef42ea7
+++ urls.py	6b5de415d1379a5445ab81002426e91c61213df9
@@ -9,7 +9,6 @@ from mtn import revision_re

 from mtn import revision_re

-#
 # these are the same, regardless of which database the user wishes
 # to view. These handles do not receive a RequestContext instance
 # as their first argument.
@@ -18,6 +17,11 @@ common_urls = (
     r'mimeicon/([A-Za-z0-9][a-z0-9\-\+\.]*)/([A-Za-z0-9][a-z0-9\-\+\.]*)', 'MimeIcon',
 )

+# URLs to install if there is no default database
+nodefault_urls = (
+    r'$', 'ChooseDatabase',
+)
+
 #
 # all of these should have GET handler that takes a per-DB context as an argument.
 # They get a RequestContext instance as their first argument to methods, eg. GET
============================================================
--- viewmtn.py	4711109e7e0e383a480fde9fae671de24ce92401
+++ viewmtn.py	b21dfade3155090e53a021f01d797d8ea0f0c99c
@@ -14,7 +14,7 @@ import mtn, handlers, links, branchdiv
 from urlparse import urljoin
 import web
 import mtn, handlers, links, branchdiv
-from urls import common_urls, perdb_urls
+from urls import common_urls, perdb_urls, nodefault_urls
 from render import Renderer
 import config

@@ -31,12 +31,10 @@ class RequestContext(object):
         # make sure that any unread automate output is flushed away
         if not self.ops is None:
             self.ops.per_request()
-        self.nodb_join = lambda path: urljoin(config.dynamic_uri_path, path)
         if self.dbname is None:
             self.perdb_join = self.nodb_join
         else:
             self.perdb_join = lambda path: urljoin(config.dynamic_uri_path, urllib.quote(self.dbname) + '/' + path)
-        self.static_join = lambda path: urljoin(config.static_uri_path, path)

     def link (self, *args, **kwargs):
         kwargs['ctxt'] = self
@@ -52,6 +50,8 @@ class RequestContextFactory(object):
         self.dbstore = { 'ops' : {}, 'branchdivs' : {}, 'dbdescr' : {}}
         self.db_summary = {}
         self.default = None
+        self.nodb_join = lambda path: urljoin(config.dynamic_uri_path, path)
+        self.static_join = lambda path: urljoin(config.static_uri_path, path)
         # has the user specified a dbfiles hash? if so, use it
         if hasattr (config, "dbfiles"):
             # is dbfiles a function? if so, call it..
@@ -73,7 +73,6 @@ class RequestContextFactory(object):
             self.add_to_store(None, ops=mtn.Operations([config.monotone, config.dbfile]),
                                     branchdivs=branchdiv.BranchDivisions(),
                                     dbdescr="")
-            self.default = None
             have_multidb = False
         self.renderer = Renderer(have_multidb=have_multidb)

@@ -96,6 +95,8 @@ class RequestContextFactory(object):
             return RequestContext(dbname=name,
                                   ops=ops,
                                   dbdescr=dbdescr,
+                                  nodb_join=self.nodb_join,
+                                  static_join=self.static_join,
                                   branchdivs=branchdivs,
                                   renderer=self.renderer,
                                   db_summary=self.db_summary)
@@ -128,22 +129,45 @@ if __name__ == '__main__':
                     return handler.GET (ctxt, *other_args, **kwargs)
             return PerDBClosure

-        for url, fn in grouper (2, common_urls):
-            url = r'^/' + url
-            if hasattr(handlers, fn):
-                fvars[fn] = getattr(handlers, fn)
-                urls += (url, fn)
-            else:
-                print >>sys.stderr, "*** URL defined for non-existant handler %s: %s" % (fn, url)
-
-        for url, fn in grouper (2, perdb_urls):
-            if hasattr(handlers, fn):
-                url = r'^/([A-Za-z]+/)?' + url
-                urls += (url, fn)
-                fvars[fn] = per_db_closure (getattr(handlers, fn)())
-            else:
-                print >>sys.stderr, "*** URL defined for non-existant handler %s: %s" % (fn, url)
-
+        def nodefault_closure (handler):
+            class NoDefaultClosure(object):
+                def GET (self, *args, **kwargs):
+                    return handler.GET (factory, *args, **kwargs)
+            return NoDefaultClosure
+
+        def assemble(prefix, url_def, url_fn, the_fn_fn):
+            urls = ()
+            for url, fn in grouper (2, url_def):
+                if hasattr(handlers, fn):
+                    the_fn = getattr(handlers, fn)
+                    if url_fn:
+                        url = url_fn(url)
+                    if the_fn_fn:
+                        the_fn = the_fn_fn(the_fn)
+                    mangled = prefix + '_' + fn
+                    urls += (url, mangled)
+                    fvars[mangled] = the_fn
+                else:
+                    print >>sys.stderr, "*** URL defined for non-existant handler %s: %s'" % (fn, url)
+            return urls
+
+        urls += assemble('c',
+                         common_urls,
+                         lambda u: r'^/' + u,
+                         None)
+        if factory.default is None:
+            urls += assemble('n',
+                             nodefault_urls,
+                             lambda u: r'^/' + u,
+                             lambda f: nodefault_closure(f()))
+        urls += assemble('d',
+                         perdb_urls,
+                         lambda u: r'^/([A-Za-z]+/)?' + u,
+                         lambda f: per_db_closure(f()))
+
+        # import pprint
+        # pp = pprint.PrettyPrinter()
+        # pp.pprint(urls)
         return urls, fvars

     urls, fvars = assemble_urls()