# # # 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 @@ + + + + +ViewMTN: $(page_title) + + + + + + + +

+ Welcome to this ViewMTN installation. Please select the Monotone + database you wish to access from the table below. +

+ + + +#for db in $databases + + + + +#end for +
DatabaseDescription
+ $db.name + + $db.description +
+ + + + + ============================================================ --- 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()