author | Peter Arrenbrecht <peter.arrenbrecht@gmail.com> |
Sat, 16 May 2009 07:12:12 +0200 | |
changeset 8841 | 94ac080e7af9 |
parent 8840 | d9acbe7b0049 |
child 8842 | acd03a6e2426 |
permissions | -rw-r--r-- |
6691 | 1 |
# Revision graph generator for Mercurial |
2 |
# |
|
3 |
# Copyright 2008 Dirkjan Ochtman <dirkjan@ochtman.nl> |
|
4 |
# Copyright 2007 Joel Rosdahl <joel@rosdahl.net> |
|
5 |
# |
|
8225
46293a0c7e9f
updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents:
7873
diff
changeset
|
6 |
# This software may be used and distributed according to the terms of the |
46293a0c7e9f
updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents:
7873
diff
changeset
|
7 |
# GNU General Public License version 2, incorporated herein by reference. |
6691 | 8 |
|
8840
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
9 |
"""supports walking the history as DAGs suitable for graphical output |
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
10 |
|
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
11 |
The most basic format we use is that of:: |
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
12 |
|
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
13 |
(id, type, data, [parentids]) |
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
14 |
|
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
15 |
The node and parent ids are arbitrary integers which identify a node in the |
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
16 |
context of the graph returned. Type is a constant specifying the node type. |
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
17 |
Data depends on type. |
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
18 |
""" |
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
19 |
|
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
20 |
from mercurial.node import nullrev |
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
21 |
|
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
22 |
CHANGESET = 'C' |
6691 | 23 |
|
8836
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
24 |
def revisions(repo, start, stop): |
8840
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
25 |
"""cset DAG generator yielding (id, CHANGESET, ctx, [parentids]) tuples |
8836
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
26 |
|
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
27 |
This generator function walks through the revision history from revision |
8840
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
28 |
start to revision stop (which must be less than or equal to start). It |
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
29 |
returns a tuple for each node. The node and parent ids are arbitrary |
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
30 |
integers which identify a node in the context of the graph returned. |
8836
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
31 |
""" |
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
32 |
assert start >= stop |
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
33 |
cur = start |
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
34 |
while cur >= stop: |
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
35 |
ctx = repo[cur] |
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
36 |
parents = [p.rev() for p in ctx.parents() if p.rev() != nullrev] |
8840
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
37 |
yield (cur, CHANGESET, ctx, sorted(parents)) |
8836
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
38 |
cur -= 1 |
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
39 |
|
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
40 |
def filerevs(repo, path, start, stop): |
8840
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
41 |
"""file cset DAG generator yielding (id, CHANGESET, ctx, [parentids]) tuples |
8836
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
42 |
|
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
43 |
This generator function walks through the revision history of a single |
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
44 |
file from revision start to revision stop (which must be less than or |
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
45 |
equal to start). |
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
46 |
""" |
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
47 |
assert start >= stop |
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
48 |
filerev = len(repo.file(path)) - 1 |
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
49 |
while filerev >= 0: |
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
50 |
fctx = repo.filectx(path, fileid=filerev) |
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
51 |
parents = [f.linkrev() for f in fctx.parents() if f.path() == path] |
8840
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
52 |
rev = fctx.rev() |
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
53 |
if rev <= start: |
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
54 |
yield (rev, CHANGESET, fctx, sorted(parents)) |
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
55 |
if rev <= stop: |
8836
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
56 |
break |
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
57 |
filerev -= 1 |
11ff34956ee7
graphmod/graphlog: move log walks to graphmod
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8835
diff
changeset
|
58 |
|
8837
d8e3a98018cb
graphmod/graphlog: extract nodelistwalk
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8836
diff
changeset
|
59 |
def nodes(repo, nodes): |
8840
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
60 |
"""cset DAG generator yielding (id, CHANGESET, ctx, [parentids]) tuples |
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
61 |
|
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
62 |
This generator function walks the given nodes. It only returns parents |
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
63 |
that are in nodes, too. |
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
64 |
""" |
8837
d8e3a98018cb
graphmod/graphlog: extract nodelistwalk
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8836
diff
changeset
|
65 |
include = set(nodes) |
d8e3a98018cb
graphmod/graphlog: extract nodelistwalk
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8836
diff
changeset
|
66 |
for node in nodes: |
d8e3a98018cb
graphmod/graphlog: extract nodelistwalk
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8836
diff
changeset
|
67 |
ctx = repo[node] |
d8e3a98018cb
graphmod/graphlog: extract nodelistwalk
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8836
diff
changeset
|
68 |
parents = [p.rev() for p in ctx.parents() if p.node() in include] |
8840
d9acbe7b0049
graphmod/graphlog: make dag walks carry data as type, payload
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8837
diff
changeset
|
69 |
yield (ctx.rev(), CHANGESET, ctx, sorted(parents)) |
8837
d8e3a98018cb
graphmod/graphlog: extract nodelistwalk
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8836
diff
changeset
|
70 |
|
6691 | 71 |
def graph(repo, start_rev, stop_rev): |
72 |
"""incremental revision grapher |
|
73 |
||
74 |
This generator function walks through the revision history from |
|
75 |
revision start_rev to revision stop_rev (which must be less than |
|
76 |
or equal to start_rev) and for each revision emits tuples with the |
|
77 |
following elements: |
|
78 |
||
8835
ec5483efc31f
graphmod: code cleanup and doc fix
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8225
diff
changeset
|
79 |
- Context of the current node |
ec5483efc31f
graphmod: code cleanup and doc fix
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8225
diff
changeset
|
80 |
- Tuple (col, color) with column and color index for the current node |
6691 | 81 |
- Edges; a list of (col, next_col, color) indicating the edges between |
82 |
the current node and its parents. |
|
83 |
""" |
|
84 |
||
7565
5f162f61e479
hgweb: fix problems with empty repositories
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
7280
diff
changeset
|
85 |
if start_rev == nullrev and not stop_rev: |
5f162f61e479
hgweb: fix problems with empty repositories
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
7280
diff
changeset
|
86 |
return |
5f162f61e479
hgweb: fix problems with empty repositories
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
7280
diff
changeset
|
87 |
|
6691 | 88 |
assert start_rev >= stop_rev |
7030
20a5dd5d6dd9
hgweb: let the web graph cope with low revisions/new repositories (issue1293)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
6747
diff
changeset
|
89 |
assert stop_rev >= 0 |
8841
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
90 |
cur = start_rev |
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
91 |
seen = [] |
6691 | 92 |
cl = repo.changelog |
93 |
colors = {} |
|
8841
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
94 |
newcolor = 1 |
6691 | 95 |
|
8841
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
96 |
while cur >= stop_rev: |
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
97 |
# Compute seen and next |
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
98 |
if cur not in seen: |
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
99 |
seen.append(cur) # new head |
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
100 |
colors[cur] = newcolor |
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
101 |
newcolor += 1 |
6691 | 102 |
|
8841
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
103 |
col = seen.index(cur) |
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
104 |
color = colors.pop(cur) |
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
105 |
next = seen[:] |
6691 | 106 |
|
107 |
# Add parents to next_revs |
|
8841
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
108 |
parents = [x for x in cl.parentrevs(cur) if x != nullrev] |
6691 | 109 |
addparents = [p for p in parents if p not in next] |
8841
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
110 |
next[col:col + 1] = addparents |
6691 | 111 |
|
112 |
# Set colors for the parents |
|
113 |
for i, p in enumerate(addparents): |
|
114 |
if not i: |
|
115 |
colors[p] = color |
|
116 |
else: |
|
8841
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
117 |
colors[p] = newcolor |
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
118 |
newcolor += 1 |
6691 | 119 |
|
120 |
# Add edges to the graph |
|
121 |
edges = [] |
|
8841
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
122 |
for ecol, eid in enumerate(seen): |
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
123 |
if eid in next: |
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
124 |
edges.append((ecol, next.index(eid), colors[eid])) |
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
125 |
elif eid == id: |
6691 | 126 |
for p in parents: |
8841
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
127 |
edges.append((ecol, next.index(p), colors[p])) |
6691 | 128 |
|
129 |
# Yield and move on |
|
8841
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
130 |
yield (repo[cur], (col, color), edges) |
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
131 |
seen = next |
94ac080e7af9
graphmod: rename a bunch of vars in graph()
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
8840
diff
changeset
|
132 |
cur -= 1 |