# # # patch "viewmtn.py" # from [78b92d8c6980db2077c8fb48277b64f5088c74ee] # to [c0e46420ea8ad46d0a3a4c1b80d981e4fd4970c0] # ============================================================ --- viewmtn.py 78b92d8c6980db2077c8fb48277b64f5088c74ee +++ viewmtn.py c0e46420ea8ad46d0a3a4c1b80d981e4fd4970c0 @@ -367,10 +367,6 @@ class Renderer(object): self._templates_loaded = True def render(self, template, **kwargs): - # technically it'd be better to do this before serving the - # request, however this is about the only per-request - # spot that runs for every handler.. - ops.per_request() self.load_templates() terms = self.terms.copy() terms.update(kwargs) @@ -382,8 +378,8 @@ class OperationsFactory(object): self.ops_instances = {} self.default = None if hasattr (config, "dbfiles"): - for name, dbfile in config.dbfiles: - self.ops_instances[name] = mtn.Operations([config.monotone, dbfile]) + for name in config.dbfiles: + self.ops_instances[name] = mtn.Operations([config.monotone, config.dbfiles[name]]) if hasattr (config, "defaultdb"): self.default = config.defaultdb else: @@ -391,17 +387,25 @@ class OperationsFactory(object): self.default = "legacy" def get_ops(self, name): - if not (name is None): - return self.ops.get (name, None) + ops = None + if name is None: + ops = self.ops_instances.get (self.default, None) else: - return self.ops.get (self.default, None) + name = name.rstrip('/') + ops = self.ops_instances.get (name, None) + # technically it'd be better to do this before serving the + # request, however this is about the only per-request + # spot that runs for every handler.. + if not ops is None: + ops.per_request() + return ops # # TODO: try and wrap these globals up in a single global object # renderer = Renderer() op_fact = OperationsFactory() -ops = mtn.Operations([config.monotone, config.dbfile]) +##ops = mtn.Operations([config.monotone, config.dbfile]) mimehelp = sharedmimeinfo.LookupHelper(getattr(config, "mime_map", None)) if config.icon_theme: try: @@ -437,7 +441,7 @@ class Index(object): divisions = BranchDivisions () class Index(object): - def GET(self, *args): + def GET(self, ops): branches = list(ops.branches ()) divisions.calculate_divisions (branches) def division_iter(): @@ -476,7 +480,7 @@ class Tags(object): renderer.render('about.html', page_title="About") class Tags(object): - def GET(self, restrict_branch=None): + def GET(self, ops, restrict_branch=None): # otherwise we couldn't use automate again.. tags = list(ops.tags()) if restrict_branch != None: @@ -505,7 +509,7 @@ class Changes(object): renderer.render('help.html', page_title="Help") class Changes(object): - def __get_last_changes(self, start_from, parent_func, selection_func, n): + def __get_last_changes(self, ops, start_from, parent_func, selection_func, n): """returns at least n revisions that are parents of the revisions in start_from, ordered by time (descending). selection_func is called for each revision, and that revision is only included in the result if the function returns True.""" @@ -550,7 +554,7 @@ class Changes(object): rv = map (lambda x: (x.revision, x.certs), result), revq return rv - def on_our_branch(self, branch, revision): + def on_our_branch(self, ops, branch, revision): rv = False for cert in ops.certs(revision): if cert[4] == 'name' and cert[5] == 'branch': @@ -558,7 +562,7 @@ class Changes(object): rv = True return rv - def for_template(self, revs, pathinfo=None, constrain_diff_to=None): + def for_template(self, ops, revs, pathinfo=None, constrain_diff_to=None): rv = [] for rev, certs in revs: rev_branch = "" @@ -611,20 +615,21 @@ class Changes(object): previous_to = previous_from + per_page return (from_change, to_change, next_from, next_to, previous_from, previous_to) - def branch_get_last_changes(self, branch, from_change, to_change): + def branch_get_last_changes(self, ops, branch, from_change, to_change): heads = [t for t in ops.heads(branch.name)] if not heads: return web.notfound() - changed, new_starting_point = self.__get_last_changes(heads, + changed, new_starting_point = self.__get_last_changes(ops, + heads, lambda r: ops.parents(r), - lambda r: self.on_our_branch(branch, r), + lambda r: self.on_our_branch(ops, branch, r), to_change) return changed, new_starting_point - def Branch_GET(self, branch, from_change, to_change, template_name): + def Branch_GET(self, ops, branch, from_change, to_change, template_name): branch = mtn.Branch(branch) from_change, to_change, next_from, next_to, previous_from, previous_to = self.determine_bounds(from_change, to_change) - changed, new_starting_point = self.branch_get_last_changes(branch, from_change, to_change) + changed, new_starting_point = self.branch_get_last_changes(ops, branch, from_change, to_change) changed = changed[from_change:to_change] if len(changed) != to_change - from_change: next_from, next_to = None, None @@ -639,9 +644,9 @@ class Changes(object): previous_to=previous_to, next_from=next_from, next_to=next_to, - display_revs=self.for_template(changed)) + display_revs=self.for_template(ops, changed)) - def file_get_last_changes(self, from_change, to_change, revision, path): + def file_get_last_changes(self, ops, from_change, to_change, revision, path): def content_changed_fn(start_revision, start_path, in_revision, pathinfo): uniq = set() parents = list(ops.parents(in_revision)) @@ -660,15 +665,16 @@ class Changes(object): pathinfo = {} # not just the starting revision! we might not have changed 'path' in the starting rev.. start_at = content_changed_fn(revision, path, revision, pathinfo) - changed, new_starting_point = self.__get_last_changes(start_at, + changed, new_starting_point = self.__get_last_changes(ops, + start_at, lambda r: content_changed_fn(revision, path, r, pathinfo), lambda r: True, to_change) return changed, new_starting_point, pathinfo - def File_GET(self, from_change, to_change, revision, path, template_name): + def File_GET(self, ops, from_change, to_change, revision, path, template_name): from_change, to_change, next_from, next_to, previous_from, previous_to = self.determine_bounds(from_change, to_change) - changed, new_starting_point, pathinfo = self.file_get_last_changes(from_change, to_change, revision, path) + changed, new_starting_point, pathinfo = self.file_get_last_changes(ops, from_change, to_change, revision, path) changed = changed[from_change:to_change] if len(changed) != to_change - from_change: next_from, next_to = None, None @@ -684,18 +690,18 @@ class Changes(object): previous_to=previous_to, next_from=next_from, next_to=next_to, - display_revs=self.for_template(changed, pathinfo=pathinfo, constrain_diff_to=revision)) + display_revs=self.for_template(ops, changed, pathinfo=pathinfo, constrain_diff_to=revision)) class HTMLBranchChanges(Changes): - def GET(self, branch, from_change, to_change): - Changes.Branch_GET(self, branch, from_change, to_change, "branchchanges.html") + def GET(self, ops, branch, from_change, to_change): + Changes.Branch_GET(self, ops, branch, from_change, to_change, "branchchanges.html") class RSSBranchChanges(Changes): - def GET(self, branch, from_change, to_change): - Changes.Branch_GET(self, branch, from_change, to_change, "branchchangesrss.html") + def GET(self, ops, branch, from_change, to_change): + Changes.Branch_GET(self, ops, branch, from_change, to_change, "branchchangesrss.html") class RevisionPage(object): - def get_fileid(self, revision, filename): + def get_fileid(self, ops, revision, filename): rv = None for stanza in ops.get_manifest_of(revision): if stanza[0] != 'file': @@ -703,13 +709,15 @@ class RevisionPage(object): if stanza[1] == filename: rv = stanza[3] return rv - def exists(self, revision): + + def exists(self, ops, revision): try: certs = [t for t in ops.certs(revision)] return True except mtn.MonotoneException: return False - def branches_for_rev(self, revisions_val): + + def branches_for_rev(self, ops, revisions_val): rv = [] for stanza in ops.certs(revisions_val): if stanza[4] == 'name' and stanza[5] == 'branch': @@ -717,27 +725,27 @@ class RevisionFileChanges(Changes, Revis return rv class RevisionFileChanges(Changes, RevisionPage): - def GET(self, from_change, to_change, revision, path): + def GET(self, ops, from_change, to_change, revision, path): revision = mtn.Revision(revision) - if not self.exists(revision): + if not self.exists(ops, revision): return web.notfound() - Changes.File_GET(self, from_change, to_change, revision, path, "revisionfilechanges.html") + Changes.File_GET(self, ops, from_change, to_change, revision, path, "revisionfilechanges.html") class RevisionFileChangesRSS(Changes, RevisionPage): - def GET(self, from_change, to_change, revision, path): + def GET(self, ops, from_change, to_change, revision, path): revision = mtn.Revision(revision) - if not self.exists(revision): + if not self.exists(ops, revision): return web.notfound() - Changes.File_GET(self, from_change, to_change, revision, path, "revisionfilechangesrss.html") + Changes.File_GET(self, ops, from_change, to_change, revision, path, "revisionfilechangesrss.html") class RevisionInfo(RevisionPage): - def GET(self, revision): + def GET(self, ops, revision): revision = mtn.Revision(revision) - if not self.exists(revision): + if not self.exists(ops, revision): return web.notfound() certs = ops.certs(revision) revisions = ops.get_revision(revision) - output_png, output_imagemap = ancestry_graph(revision) + output_png, output_imagemap = ancestry_graph(ops, revision) if os.access(output_imagemap, os.R_OK): imagemap = open(output_imagemap).read().replace('\\n', ' by ') imageuri = dynamic_join('revision/graph/' + revision) @@ -752,12 +760,12 @@ class RevisionDiff(RevisionPage): revisions=revisions_for_template(revision, revisions)) class RevisionDiff(RevisionPage): - def GET(self, revision_from, revision_to, filename=None): + def GET(self, ops, revision_from, revision_to, filename=None): revision_from = mtn.Revision(revision_from) revision_to = mtn.Revision(revision_to) - if not self.exists(revision_from): + if not self.exists(ops, revision_from): return web.notfound() - if not self.exists(revision_to): + if not self.exists(ops, revision_to): return web.notfound() if filename != None: files = [filename] @@ -775,12 +783,12 @@ class RevisionRawDiff(RevisionPage): files=files) class RevisionRawDiff(RevisionPage): - def GET(self, revision_from, revision_to, filename=None): + def GET(self, ops, revision_from, revision_to, filename=None): revision_from = mtn.Revision(revision_from) revision_to = mtn.Revision(revision_to) - if not self.exists(revision_from): + if not self.exists(ops, revision_from): return web.notfound() - if not self.exists(revision_to): + if not self.exists(ops, revision_to): return web.notfound() if filename != None: files = [filename] @@ -793,12 +801,12 @@ class RevisionFile(RevisionPage): sys.stdout.flush() class RevisionFile(RevisionPage): - def GET(self, revision, filename): + def GET(self, ops, revision, filename): revision = mtn.Revision(revision) - if not self.exists(revision): + if not self.exists(ops, revision): return web.notfound() language = filename.rsplit('.', 1)[-1] - fileid = RevisionPage.get_fileid(self, revision, filename) + fileid = RevisionPage.get_fileid(self, ops, revision, filename) if not fileid: return web.notfound() contents = ops.get_file(fileid) @@ -826,12 +834,12 @@ class RevisionDownloadFile(RevisionPage) contents=syntax.highlight(contents, language)) class RevisionDownloadFile(RevisionPage): - def GET(self, revision, filename): + def GET(self, ops, revision, filename): web.header('Content-Disposition', 'attachment; filename=%s' % filename) revision = mtn.Revision(revision) - if not self.exists(revision): + if not self.exists(ops, revision): return web.notfound() - fileid = RevisionPage.get_fileid(self, revision, filename) + fileid = RevisionPage.get_fileid(self, ops, revision, filename) if not fileid: return web.notfound() for idx, data in enumerate(ops.get_file(fileid)): @@ -842,11 +850,11 @@ class RevisionTar(RevisionPage): sys.stdout.flush() class RevisionTar(RevisionPage): - def GET(self, revision): + def GET(self, ops, revision): # we'll output in the USTAR tar format; documentation taken from: # http://en.wikipedia.org/wiki/Tar_%28file_format%29 revision = mtn.Revision(revision) - if not self.exists(revision): + if not self.exists(ops, revision): return web.notfound() filename = "%s.tar" % revision web.header('Content-Disposition', 'attachment; filename=%s' % filename) @@ -886,11 +894,11 @@ class RevisionBrowse(RevisionPage): tarobj.addfile(ti, filecontents) class RevisionBrowse(RevisionPage): - def GET(self, revision, path): + def GET(self, ops, revision, path): revision = mtn.Revision(revision) - if not self.exists(revision): + if not self.exists(ops, revision): return web.notfound() - branches = RevisionPage.branches_for_rev(self, revision) + branches = RevisionPage.branches_for_rev(self, ops, revision) revisions = ops.get_revision(revision) def components(path): @@ -1036,7 +1044,7 @@ class RevisionBrowse(RevisionPage): mime_icon=mime_icon, entries=info_for_manifest(cut_manifest_to_subdir())) -def ancestry_dot(revision): +def ancestry_dot(ops, revision): def dot_escape(s): # kinda paranoid, should probably revise later permitted=string.digits + string.letters + ' -<>-:,address@hidden&.+_~?/' @@ -1172,8 +1180,8 @@ digraph ancestry { graph += '}' return graph -def ancestry_graph(revision): - dot_data = ancestry_dot(revision) +def ancestry_graph(ops, revision): + dot_data = ancestry_dot(ops, revision) # okay, let's output the graph graph_sha = sha.new(dot_data).hexdigest() if not os.access(config.graphopts['directory'], os.R_OK): @@ -1195,8 +1203,8 @@ class RevisionGraph(object): return output_png, output_imagemap class RevisionGraph(object): - def GET(self, revision): - output_png, output_imagemap = ancestry_graph(revision) + def GET(self, ops, revision): + output_png, output_imagemap = ancestry_graph(ops, revision) if os.access(output_png, os.R_OK): web.header('Content-Type', 'image/png') sys.stdout.write(open(output_png).read()) @@ -1214,13 +1222,13 @@ class Json(object): revdate = common.parse_timecert(cert[7]) rv['ago'] = common.ago(revdate) - def BranchLink(self, for_branch): + def BranchLink(self, ops, for_branch): rv = { 'type' : 'branch', 'branch' : for_branch, } branch = mtn.Branch(for_branch) - changes, new_starting_point = Changes().branch_get_last_changes(branch, 0, 1) + changes, new_starting_point = Changes().branch_get_last_changes(ops, branch, 0, 1) if len(changes) < 1: return web.notfound() if not changes: @@ -1230,7 +1238,7 @@ class Json(object): self.fill_from_certs(rv, certs) return rv - def RevisionLink(self, revision_id): + def RevisionLink(self, ops, revision_id): rv = { 'type' : 'revision', 'revision_id' : revision_id, @@ -1240,19 +1248,19 @@ class Json(object): self.fill_from_certs(rv, certs) return rv - def GET(self, method, encoded_args): + def GET(self, ops, method, encoded_args): writer = json.JsonWriter() if not encoded_args.startswith('js_'): return web.notfound() args = json.read(binascii.unhexlify((encoded_args[3:]))) if hasattr(self, method): - rv = getattr(self, method)(*args) + rv = getattr(self, method)(ops, *args) else: return web.notfound() print writer.write(rv) class BranchHead(object): - def GET(self, head_method, proxy_to, branch, extra_path): + def GET(self, ops, head_method, proxy_to, branch, extra_path): branch = mtn.Branch(branch) valid = ('browse', 'file', 'downloadfile', 'info', 'tar', 'graph') if not proxy_to in valid: @@ -1355,7 +1363,6 @@ def per_request_wrapper(func, *args, **k web.wsgi.runfcgi(func, None) def per_request_wrapper(func, *args, **kwargs): - ops.per_request() return func(*args, **kwargs) if __name__ == '__main__': @@ -1377,10 +1384,11 @@ if __name__ == '__main__': class PerDBClosure(object): def GET (self, *args, **kwargs): db, other_args = args[0], args[1:] - print >>sys.stderr, "-> selected db", db - the_cls.GET (*other_args, **kwargs) + ops = op_fact.get_ops (db) + if ops is None: + return web.notfound() + return the_cls.GET (ops, *other_args, **kwargs) rv = PerDBClosure - print >>sys.stderr, rv return rv for url, fn in grouper (2, perdb_urls):