##// END OF EJS Templates
Unified DAG generation for hg and git...
marcink -
r2380:0c7dc340 beta
parent child Browse files
Show More
@@ -0,0 +1,127 b''
1 """
2 Modified mercurial DAG graph functions that re-uses VCS structure
3
4 It allows to have a shared codebase for DAG generation for hg and git repos
5 """
6
7 nullrev = -1
8
9
10 def grandparent(parentrev_func, lowestrev, roots, head):
11 """
12 Return all ancestors of head in roots which revision is
13 greater or equal to lowestrev.
14 """
15 pending = set([head])
16 seen = set()
17 kept = set()
18 llowestrev = max(nullrev, lowestrev)
19 while pending:
20 r = pending.pop()
21 if r >= llowestrev and r not in seen:
22 if r in roots:
23 kept.add(r)
24 else:
25 pending.update([p for p in parentrev_func(r)])
26 seen.add(r)
27 return sorted(kept)
28
29
30 def _dagwalker(repo, revs, alias):
31 if not revs:
32 return
33
34 if alias == 'hg':
35 cl = repo._repo.changelog.parentrevs
36 repo = repo
37 elif alias == 'git':
38 def cl(rev):
39 return [x.revision for x in repo[rev].parents()]
40 repo = repo
41
42 lowestrev = min(revs)
43 gpcache = {}
44
45 knownrevs = set(revs)
46 for rev in revs:
47 ctx = repo[rev]
48 parents = sorted(set([p.revision for p in ctx.parents
49 if p.revision in knownrevs]))
50 mpars = [p.revision for p in ctx.parents if
51 p.revision != nullrev and p.revision not in parents]
52
53 for mpar in mpars:
54 gp = gpcache.get(mpar)
55 if gp is None:
56 gp = gpcache[mpar] = grandparent(cl, lowestrev, revs, mpar)
57 if not gp:
58 parents.append(mpar)
59 else:
60 parents.extend(g for g in gp if g not in parents)
61
62 yield (ctx.revision, 'C', ctx, parents)
63
64
65 def _colored(dag):
66 """annotates a DAG with colored edge information
67
68 For each DAG node this function emits tuples::
69
70 (id, type, data, (col, color), [(col, nextcol, color)])
71
72 with the following new elements:
73
74 - Tuple (col, color) with column and color index for the current node
75 - A list of tuples indicating the edges between the current node and its
76 parents.
77 """
78 seen = []
79 colors = {}
80 newcolor = 1
81
82 getconf = lambda rev: {}
83
84 for (cur, type, data, parents) in dag:
85
86 # Compute seen and next
87 if cur not in seen:
88 seen.append(cur) # new head
89 colors[cur] = newcolor
90 newcolor += 1
91
92 col = seen.index(cur)
93 color = colors.pop(cur)
94 next = seen[:]
95
96 # Add parents to next
97 addparents = [p for p in parents if p not in next]
98 next[col:col + 1] = addparents
99
100 # Set colors for the parents
101 for i, p in enumerate(addparents):
102 if not i:
103 colors[p] = color
104 else:
105 colors[p] = newcolor
106 newcolor += 1
107
108 # Add edges to the graph
109 edges = []
110 for ecol, eid in enumerate(seen):
111 if eid in next:
112 bconf = getconf(eid)
113 edges.append((
114 ecol, next.index(eid), colors[eid],
115 bconf.get('width', -1),
116 bconf.get('color', '')))
117 elif eid == cur:
118 for p in parents:
119 bconf = getconf(p)
120 edges.append((
121 ecol, next.index(p), color,
122 bconf.get('width', -1),
123 bconf.get('color', '')))
124
125 # Yield and move on
126 yield (cur, type, data, (col, color), edges)
127 seen = next
@@ -26,7 +26,6 b''
26 import logging
26 import logging
27 import traceback
27 import traceback
28
28
29 from mercurial import graphmod
30 from pylons import request, url, session, tmpl_context as c
29 from pylons import request, url, session, tmpl_context as c
31 from pylons.controllers.util import redirect
30 from pylons.controllers.util import redirect
32 from pylons.i18n.translation import _
31 from pylons.i18n.translation import _
@@ -36,7 +35,7 b' from rhodecode.lib.auth import LoginRequ'
36 from rhodecode.lib.base import BaseRepoController, render
35 from rhodecode.lib.base import BaseRepoController, render
37 from rhodecode.lib.helpers import RepoPage
36 from rhodecode.lib.helpers import RepoPage
38 from rhodecode.lib.compat import json
37 from rhodecode.lib.compat import json
39
38 from rhodecode.lib.graphmod import _colored, _dagwalker
40 from rhodecode.lib.vcs.exceptions import RepositoryError, ChangesetDoesNotExistError
39 from rhodecode.lib.vcs.exceptions import RepositoryError, ChangesetDoesNotExistError
41
40
42 log = logging.getLogger(__name__)
41 log = logging.getLogger(__name__)
@@ -117,18 +116,9 b' class ChangelogController(BaseRepoContro'
117 data = []
116 data = []
118 revs = [x.revision for x in collection]
117 revs = [x.revision for x in collection]
119
118
120 if repo.alias == 'git':
119 dag = _dagwalker(repo, revs, repo.alias)
121 for _ in revs:
120 dag = _colored(dag)
122 vtx = [0, 1]
121 for (id, type, ctx, vtx, edges) in dag:
123 edges = [[0, 0, 1]]
124 data.append(['', vtx, edges])
125
126 elif repo.alias == 'hg':
127 dag = graphmod.dagwalker(repo._repo, revs)
128 c.dag = graphmod.colored(dag, repo._repo)
129 for (id, type, ctx, vtx, edges) in c.dag:
130 if type != graphmod.CHANGESET:
131 continue
132 data.append(['', vtx, edges])
122 data.append(['', vtx, edges])
133
123
134 c.jsdata = json.dumps(data)
124 c.jsdata = json.dumps(data)
General Comments 0
You need to be logged in to leave comments. Login now