Mon Sep 19 02:50:04 UTC 2005 Alberto Bertogli <albertogli@telpin.com.ar>
* Implement annotate.
Finally!
diff -rN -u old-darcsweb/darcsweb.cgi new-darcsweb/darcsweb.cgi
--- old-darcsweb/darcsweb.cgi 2015-04-15 14:37:09.000000000 +0000
+++ new-darcsweb/darcsweb.cgi 2015-04-15 14:37:09.000000000 +0000
@@ -261,11 +261,23 @@
realf = filter_file(config.repodir + '/_darcs/current/' + f)
+ if f and h:
+ print """
+| <a href="%(myreponame)s;a=annotate;f=%(fname)s;h=%(hash)s">annotate</a>
+ """ % {
+ 'myreponame': config.myreponame,
+ 'hash': h,
+ 'fname': f
+ }
+ elif f:
+ print """
+| <a href="%(myreponame)s;a=annotate;f=%(fname)s">annotate</a>
+ """ % { "myreponame": config.myreponame, 'fname': f }
+
if f and os.path.isfile(realf):
print """
| <a href="%(myreponame)s;a=headblob;f=%(fname)s">headblob</a>
""" % { "myreponame": config.myreponame, 'fname': f }
- # TODO: annotate, when it's implemented
if f and os.path.isdir(realf):
print """
@@ -336,6 +348,15 @@
print """
<a class="link" href="%(myreponame)s;a=plainblob;f=%(fname)s">plain</a>
""" % { "myreponame": config.myreponame, "fname": f }
+ elif f and h and action == "annotate":
+ # same for annotate
+ print """
+<a href="%(myreponame)s;a=annotate_plain;f=%(fname)s;h=%(hash)s">plain</a>
+ """ % {
+ "myreponame": config.myreponame,
+ "fname": f,
+ "hash": h
+ }
print '<br/>'
print '</div>'
@@ -631,6 +652,92 @@
cmd += ' "%s"' % fname
return run_darcs(cmd)
+
+class Annotate:
+ def __init__(self):
+ self.fname = ""
+ self.creator_hash = ""
+ self.created_as = ""
+ self.lastchange_hash = ""
+ self.lastchange_author = ""
+ self.lastchange_name = ""
+ self.lines = []
+
+ class Line:
+ def __init__(self):
+ self.text = ""
+ self.phash = None
+ self.pauthor = None
+
+def parse_annotate(src):
+ import xml.dom.minidom
+
+ annotate = Annotate()
+ dom = xml.dom.minidom.parse(src)
+
+ file = dom.getElementsByTagName("file")[0]
+ annotate.fname = file.getAttribute("name")
+
+ createinfo = dom.getElementsByTagName("created_as")[0]
+ annotate.created_as = createinfo.getAttribute("original_name")
+
+ creator = createinfo.getElementsByTagName("patch")[0]
+ annotate.creator_hash = creator.getAttribute("hash")
+
+ mod = dom.getElementsByTagName("modified")[0]
+ lastpatch = mod.getElementsByTagName("patch")[0]
+ annotate.lastchange_hash = lastpatch.getAttribute("hash")
+ annotate.lastchange_author = lastpatch.getAttribute("author")
+
+ lastname = lastpatch.getElementsByTagName("name")[0]
+ lastname = lastname.childNodes[0].wholeText
+ annotate.lastchange_name = lastname
+
+ file = dom.getElementsByTagName("file")[0]
+
+ for l in file.childNodes:
+ # we're only intrested in normal and added lines
+ if l.nodeName not in ["normal_line", "added_line"]:
+ continue
+ line = Annotate.Line()
+
+ if l.nodeName == "normal_line":
+ patch = l.getElementsByTagName("patch")[0]
+ phash = patch.getAttribute("hash")
+ pauthor = patch.getAttribute("author")
+ else:
+ # added lines inherit the creation from the annotate
+ # patch
+ phash = annotate.lastchange_hash
+ pauthor = annotate.lastchange_author
+
+ text = ""
+ for node in l.childNodes:
+ if node.nodeType == node.TEXT_NODE:
+ text += node.wholeText
+
+ # strip all "\n"s at the beginning; because the way darcs
+ # formats the xml output it makes the DOM parser to add "\n"s
+ # in front of it
+ text = text.lstrip("\n")
+
+ line.text = text
+ line.phash = phash
+ line.pauthor = pauthor
+ annotate.lines.append(line)
+
+ return annotate
+
+def get_annotate(fname, hash = None):
+ cmd = 'annotate --xml-output'
+ if hash:
+ cmd += ' --match="hash %s"' % hash
+ cmd += ' %s' % fname
+ out = run_darcs(cmd)
+ return parse_annotate(out)
+
+
+
#
# specific html functions
#
@@ -829,6 +936,39 @@
count += 1
print '</div>'
+def print_annotate(ann):
+ print '<div class="page_body">'
+ if isbinary(ann.fname):
+ print """
+<i>This is a binary file and it's contents will not be displayed.</i>
+</div>
+ """
+ return
+
+ count = 1
+ for l in ann.lines:
+ text = fixu8(escape(l.text))
+ text = text.rstrip()
+
+ link = "%(myrname)s;a=commit;h=%(hash)s" % {
+ 'myrname': config.myreponame,
+ 'hash': l.phash
+ }
+ print """\
+<div class="pre">\
+<a href="%(link)s" class="linenr">%(c)4d</a> \
+<a href="%(link)s" class="line">%(text)s</a>\
+</div>
+ """ % {
+ 'c': count,
+ 'text': text,
+ 'link': link
+ }
+
+ count += 1
+
+ print '</div>'
+
#
# available actions
@@ -1165,7 +1305,8 @@
print """
<td class="link">
<a href="%(myreponame)s;a=filediff;h=%(hash)s;f=%(file)s">diff</a> |
- <a href="%(myreponame)s;a=filehistory;f=%(file)s">history</a>
+ <a href="%(myreponame)s;a=filehistory;f=%(file)s">history</a> |
+ <a href="%(myreponame)s;a=annotate;h=%(hash)s;f=%(file)s">annotate</a>
</td>
""" % {
'myreponame': config.myreponame,
@@ -1246,7 +1387,8 @@
<td><a class="list" href="%(myrname)s;a=headblob;f=%(fullf)s">%(f)s</a></td>
<td class="link">
<a href="%(myrname)s;a=filehistory;f=%(fullf)s">history</a> |
- <a href="%(myrname)s;a=headblob;f=%(fullf)s">headblob</a>
+ <a href="%(myrname)s;a=headblob;f=%(fullf)s">headblob</a> |
+ <a href="%(myrname)s;a=annotate;f=%(fullf)s">annotate</a>
</td>
""" % {
'myrname': config.myreponame,
@@ -1278,7 +1420,6 @@
print '</b></div>'
- # TODO: when we have annotate, put some links around here.
print_blob(fname)
print_footer()
@@ -1290,6 +1431,36 @@
sys.stdout.write(l)
+def do_annotate(fname, phash):
+ print_header()
+ ann = get_annotate(fname, phash)
+ print_navbar(f = fname, h = ann.lastchange_hash)
+
+
+ print """
+<div>
+ <a class="title" href="%(myreponame)s;a=commit;h=%(hash)s">%(name)s</a>
+</div>
+<div class="page_path"><b>
+ Annotate for file %(fname)s
+</b></div>
+ """ % {
+ 'myreponame': config.myreponame,
+ 'hash': ann.lastchange_hash,
+ 'name': ann.lastchange_name,
+ 'fname': fname,
+ }
+
+ print_annotate(ann)
+ print_footer()
+
+def do_annotate_plain(fname, phash):
+ print_plain_header()
+ ann = get_annotate(fname, phash)
+ for l in ann.lines:
+ sys.stdout.write(l.text)
+
+
def do_shortlog(topi):
print_header()
print_navbar()
@@ -1587,6 +1758,20 @@
fname = filter_file(form["f"].value)
do_darcs_fileheaddiff(phash, fname)
+elif action == "annotate":
+ fname = filter_file(form["f"].value)
+ if form.has_key("h"):
+ phash = filter_hash(form["h"].value)
+ else:
+ phash = None
+ do_annotate(fname, phash)
+elif action == "annotate_plain":
+ fname = filter_file(form["f"].value)
+ if form.has_key("h"):
+ phash = filter_hash(form["h"].value)
+ else:
+ phash = None
+ do_annotate_plain(fname, phash)
elif action == "shortlog":
if form.has_key("topi"):
@@ -1633,3 +1818,4 @@
do_die()
+
diff -rN -u old-darcsweb/style.css new-darcsweb/style.css
--- old-darcsweb/style.css 2015-04-15 14:37:09.000000000 +0000
+++ new-darcsweb/style.css 2015-04-15 14:37:09.000000000 +0000
@@ -125,6 +125,16 @@
color:#880000;
}
+a.line {
+ text-decoration:none;
+ color:#000000;
+}
+
+a.line:hover {
+ text-decoration:none;
+ color:#880000;
+}
+
table {
padding:8px 4px;
}