[PATCH V2] hgweb: make different kinds of commits look differently on /graph
Anton Shestakov
av6 at dwimlabs.net
Tue Jan 9 11:44:37 UTC 2018
# HG changeset patch
# User Anton Shestakov <av6 at dwimlabs.net>
# Date 1513687285 -28800
# Tue Dec 19 20:41:25 2017 +0800
# Node ID 45845ed18d2e7fa974a0972b80906398b711edfa
# Parent 4c3a4bb31c0e3d9b8920b4c9b64ae930b1fe52ce
hgweb: make different kinds of commits look differently on /graph
Regular hg log -G uses different symbols for some graph nodes, such as commits
that close branches and hidden commits. It also marks the currently checked out
commit with "@". Since hg serve is sometimes used/recommended as a more visual
alternative to CLI, it makes sense to port these features to hgweb.
"graphnode" includes the style of a particular node and also if it's currently
checked out or not, both at the same time. This is different from hg log -G
(which uses templatekw.showgraphnode), where there's only place for one
character, but hgweb doesn't have this limitation, since it uses <canvas> and
not plain text. I'm using one string of 1 or 2 characters in this patch, it's
not the most self-explanatory format, but it's concise, uses the same
characters as hg log -G, and is internal to hgweb (i.e. not used for
json-graph).
I'm more or less fine with how things look visually, but there's still room for
improvement. Feel free to criticise or point me to good-looking graphs of this
kind for inspiration.
diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py
--- a/mercurial/hgweb/webcommands.py
+++ b/mercurial/hgweb/webcommands.py
@@ -13,7 +13,7 @@ import os
import re
from ..i18n import _
-from ..node import hex, short
+from ..node import hex, nullid, short
from .common import (
ErrorResponse,
@@ -1248,6 +1248,24 @@ def graph(web, req, tmpl):
tree = list(item for item in graphmod.colored(dag, web.repo)
if item[1] == graphmod.CHANGESET)
+ def nodecurrent(ctx):
+ wpnodes = web.repo.dirstate.parents()
+ if wpnodes[1] == nullid:
+ wpnodes = wpnodes[:1]
+ if ctx.node() in wpnodes:
+ return '@'
+ return ''
+
+ def nodesymbol(ctx):
+ if ctx.obsolete():
+ return 'x'
+ elif ctx.isunstable():
+ return '*'
+ elif ctx.closesbranch():
+ return '_'
+ else:
+ return 'o'
+
def fulltree():
pos = web.repo[graphtop].rev()
tree = []
@@ -1260,6 +1278,7 @@ def graph(web, req, tmpl):
def jsdata():
return [{'node': pycompat.bytestr(ctx),
+ 'graphnode': nodecurrent(ctx) + nodesymbol(ctx),
'vertex': vtx,
'edges': edges}
for (id, type, ctx, vtx, edges) in fulltree()]
diff --git a/mercurial/templates/static/mercurial.js b/mercurial/templates/static/mercurial.js
--- a/mercurial/templates/static/mercurial.js
+++ b/mercurial/templates/static/mercurial.js
@@ -90,11 +90,68 @@ Graph.prototype = {
},
- vertex: function(x, y, radius, color, parity, cur) {
+ graphNodeCurrent: function(x, y, radius) {
+ this.ctx.lineWidth = 2;
+ this.ctx.beginPath();
+ this.ctx.arc(x, y, radius * 1.75, 0, Math.PI * 2, true);
+ this.ctx.stroke();
+ },
+
+ graphNodeClosing: function(x, y, radius) {
+ this.ctx.fillRect(x - radius, y - 1.5, radius * 2, 3);
+ },
+
+ graphNodeUnstable: function(x, y, radius) {
+ var x30 = radius * Math.cos(Math.PI / 6);
+ var y30 = radius * Math.sin(Math.PI / 6);
+ this.ctx.lineWidth = 2;
this.ctx.beginPath();
- this.setColor(color, 0.25, 0.75);
+ this.ctx.moveTo(x, y - radius);
+ this.ctx.lineTo(x, y + radius);
+ this.ctx.moveTo(x - x30, y - y30);
+ this.ctx.lineTo(x + x30, y + y30);
+ this.ctx.moveTo(x - x30, y + y30);
+ this.ctx.lineTo(x + x30, y - y30);
+ this.ctx.stroke();
+ },
+
+ graphNodeObsolete: function(x, y, radius) {
+ var p45 = radius * Math.cos(Math.PI / 4);
+ this.ctx.lineWidth = 3;
+ this.ctx.beginPath();
+ this.ctx.moveTo(x - p45, y - p45);
+ this.ctx.lineTo(x + p45, y + p45);
+ this.ctx.moveTo(x - p45, y + p45);
+ this.ctx.lineTo(x + p45, y - p45);
+ this.ctx.stroke();
+ },
+
+ graphNodeNormal: function(x, y, radius) {
+ this.ctx.beginPath();
this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
this.ctx.fill();
+ },
+
+ vertex: function(x, y, radius, color, parity, cur) {
+ this.ctx.save();
+ this.setColor(color, 0.25, 0.75);
+ if (cur.graphnode[0] === '@') {
+ this.graphNodeCurrent(x, y, radius);
+ }
+ switch (cur.graphnode.substr(-1)) {
+ case '_':
+ this.graphNodeClosing(x, y, radius);
+ break;
+ case '*':
+ this.graphNodeUnstable(x, y, radius);
+ break;
+ case 'x':
+ this.graphNodeObsolete(x, y, radius);
+ break;
+ default:
+ this.graphNodeNormal(x, y, radius);
+ }
+ this.ctx.restore();
var left = (this.bg_height - this.box_size) + (this.columns + 1) * this.box_size;
var item = document.querySelector('[data-node="' + cur.node + '"]');
diff --git a/tests/test-hgweb-commands.t b/tests/test-hgweb-commands.t
--- a/tests/test-hgweb-commands.t
+++ b/tests/test-hgweb-commands.t
@@ -1822,7 +1822,7 @@ Overviews
</div>
<script>
- var data = [{"edges": [[0, 0, 1, 3, "FF0000"]], "node": "cad8025a2e87", "vertex": [0, 1]}, {"edges": [[0, 0, 1, 3, ""]], "node": "1d22e65f027e", "vertex": [0, 1]}, {"edges": [[0, 0, 1, 3, ""]], "node": "a4f92ed23982", "vertex": [0, 1]}, {"edges": [], "node": "2ef0ac749a14", "vertex": [0, 1]}];
+ var data = [{"edges": [[0, 0, 1, 3, "FF0000"]], "graphnode": "@o", "node": "cad8025a2e87", "vertex": [0, 1]}, {"edges": [[0, 0, 1, 3, ""]], "graphnode": "o", "node": "1d22e65f027e", "vertex": [0, 1]}, {"edges": [[0, 0, 1, 3, ""]], "graphnode": "o", "node": "a4f92ed23982", "vertex": [0, 1]}, {"edges": [], "graphnode": "o", "node": "2ef0ac749a14", "vertex": [0, 1]}];
var graph = new Graph();
graph.scale(39);
graph.render(data);
More information about the Mercurial-devel
mailing list