# # # rename "branch.psp" # to "headofbranch.psp" # # patch "headofbranch.psp" # from [cf04abf41b3a962e863373fcf65c3e446a15ec97] # to [171bb9e14ee1f1d92f10d27f6c585f9ab321f317] # # patch "index.psp" # from [367c93e86ae0d15d4cd1d6ef5dd010d8d687f667] # to [6af4d628be4f554f4b3eeabefcf6b2247820217c] # # patch "monotone.py" # from [39dcefef2486e93bd971174f5d6ae75c51861fbe] # to [1cd3ca6de2612c55cf63eb87a10a3e3f34f9e90c] # # patch "revision.psp" # from [3c361c7a765988f8db206b5bf5a610a6278fa8c9] # to [3f198ce41986db92a1cc0a0373d92a87ddf8b71f] # ============================================================ --- branch.psp cf04abf41b3a962e863373fcf65c3e446a15ec97 +++ headofbranch.psp 171bb9e14ee1f1d92f10d27f6c585f9ab321f317 @@ -14,10 +14,10 @@ raise Exception("No branch specified.") branch = form['branch'] -# branch.psp +# headofbranch.psp # -# we want to present the user with the HEAD -# id of this branch. +# we want to redirect the user to revision.psp displaying +# the head ID of this branch. # # if more than one HEAD exists, prompt the user # and allow them to choose which one to view ============================================================ --- index.psp 367c93e86ae0d15d4cd1d6ef5dd010d8d687f667 +++ index.psp 6af4d628be4f554f4b3eeabefcf6b2247820217c @@ -41,7 +41,7 @@ <% branches.sort() for branch in branches: - req.write('%s' % (urllib.quote(branch), hq(branch))) + req.write('%s' % (urllib.quote(branch), hq(branch))) %> ============================================================ --- monotone.py 39dcefef2486e93bd971174f5d6ae75c51861fbe +++ monotone.py 1cd3ca6de2612c55cf63eb87a10a3e3f34f9e90c @@ -103,6 +103,14 @@ raise Exception("Unable to retrieve file: %s" % (result['childerr'])) else: return result['fromchild'] + + def annotate(self, id, file): + result = utility.run_command(self.base_command + " annotate --revision=%s %s" % (pipes.quote(id), pipes.quote(file))) + if result['exitcode'] != 0: + raise Exception("Unable to annotate file: %s using command '%s'" % (result['childerr'], result['run_command'])) + else: + return result['fromchild'] + def diff(self, rev_from, rev_to, files=None): command = self.base_command + " diff -r %s -r %s" % (pipes.quote(rev_from), pipes.quote(rev_to)) if files != None: command += ' ' + ' '.join(map(pipes.quote, files)) @@ -134,11 +142,14 @@ map(None, iterator) if entry: rv.append(entry) return rv - def ancestry_graph(self, graphdir, graphuri, id, limit=0): + + def ancestry_graph(self, graphopts, id, limit=0): def dot_escape(s): # kinda paranoid, should probably revise later permitted=string.digits + string.letters + ' -<>-:,address@hidden&.+_~?/' return ''.join(filter(lambda x: x in permitted, s)) + graphdir = graphopts['directory'] + graphuri = graphopts['uri'] graph_id = "%s.%d" % (id, limit) rv = { 'dot_file' : os.path.join(graphdir, graph_id + ".dot"), @@ -153,8 +164,7 @@ if len(missing) == 0: rv['cached'] = True return rv - contents = "digraph ancestry {" - contents += "edge [dir=back];\n" + contents = "digraph ancestry {\nratio=compress\nnodesep=0.1\nranksep=0.2\nedge [dir=back];\n" revisions = {} for attrs in self.ancestry(id, limit): if not attrs.has_key("Revision") or not attrs.has_key("Ancestor"): @@ -166,20 +176,30 @@ if not revisions.has_key(ancestor): revisions[ancestor] = None contents += '"%s"->"%s"\n' % (revision, ancestor) for revision in revisions.keys(): - label = "%s" % (revision) + label = "%s..." % (revision[0:8]) attrs = revisions[revision] if attrs == None: # fill in the gaps; would be nice to clean this up. # shouldn't take long, anyway. attrs = self.ancestry(revision, 1)[0] + if attrs.has_key('Date'): + d = dot_escape(attrs['Date'][0]) + d = d[0:d.find("T")] + label += " on %s" % d if attrs.has_key('Author'): label += "\\n%s" % (dot_escape(attrs['Author'][0])) - if attrs.has_key('Date'): label += "\\n%s" % (dot_escape(attrs['Date'][0])) - opts = 'fontname=Windsor,fontsize=8,shape=box,href="revision.psp?id=%s",label="%s"' % (urllib.quote(revision), label) + #opts = 'fontname=Windsor,fontsize=8,shape=box,href="revision.psp?id=%s",label="%s"' % (urllib.quote(revision), label) + opts = 'label="%s"' % label #revision[0:8] + for opt in graphopts['nodeopts']: + opts += ',%s="%s"' % (opt, graphopts['nodeopts'][opt]) if revision == id: opts += ",color=blue" + opts += ',href="revision.psp?id=%s"' % urllib.quote(revision) + #opts += ',tooltip="by %s at %s on %s"' % (dot_escape(attrs['ChangeLog'][0]), + # dot_escape(attrs['Date'][0]), + # dot_escape(attrs['Branch'][0])) contents += '"%s" [%s]\n' % (revision, opts) contents += "}\n" open(rv['dot_file'], 'w').write(contents) - os.system("/usr/bin/dot -Tcmapx -o %s -Tpng -o %s %s" % (pipes.quote(rv['imagemap_file']), rv['image_file'], rv['dot_file'])) + os.system("%s -Tcmapx -o %s -Tpng -o %s %s" % (graphopts['dot'], pipes.quote(rv['imagemap_file']), rv['image_file'], rv['dot_file'])) rv['cached'] = False return rv ============================================================ --- revision.psp 3c361c7a765988f8db206b5bf5a610a6278fa8c9 +++ revision.psp 3f198ce41986db92a1cc0a0373d92a87ddf8b71f @@ -39,7 +39,7 @@ if ancestry_limit == 0 or ancestry_limit > ancestry_maximum: ancestry_limit = ancestry_maximum -ancestry_graph = mt.ancestry_graph(config.graphdir, config.graphuri, id, ancestry_limit) +ancestry_graph = mt.ancestry_graph(config.graphopts, id, ancestry_limit) req.write(open(ancestry_graph['imagemap_file']).read()) %>