Mercurial > hg
comparison hgext/graphlog.py @ 5938:9ed100559851
graphlog: add filelog revision grapher
Graph a filelog's DAG, e.g.: hg glog mercurial/util.py
author | Steve Borho <steve@borho.org> |
---|---|
date | Fri, 25 Jan 2008 10:28:21 -0600 |
parents | 8d4fac0a9df7 |
children | 7b222815a462 |
comparison
equal
deleted
inserted
replaced
5937:d8878742a924 | 5938:9ed100559851 |
---|---|
3 # Copyright 2007 Joel Rosdahl <joel@rosdahl.net> | 3 # Copyright 2007 Joel Rosdahl <joel@rosdahl.net> |
4 # | 4 # |
5 # This software may be used and distributed according to the terms of | 5 # This software may be used and distributed according to the terms of |
6 # the GNU General Public License, incorporated herein by reference. | 6 # the GNU General Public License, incorporated herein by reference. |
7 | 7 |
8 import os | |
8 import sys | 9 import sys |
9 from mercurial.cmdutil import revrange, show_changeset | 10 from mercurial.cmdutil import revrange, show_changeset |
10 from mercurial.i18n import _ | 11 from mercurial.i18n import _ |
11 from mercurial.node import nullid, nullrev | 12 from mercurial.node import nullid, nullrev |
12 from mercurial.util import Abort | 13 from mercurial.util import Abort, canonpath |
13 | 14 |
14 def revision_grapher(repo, start_rev, stop_rev): | 15 def revision_grapher(repo, start_rev, stop_rev): |
15 """incremental revision grapher | 16 """incremental revision grapher |
16 | 17 |
17 This generator function walks through the revision history from | 18 This generator function walks through the revision history from |
60 n_columns_diff = len(next_revs) - len(revs) | 61 n_columns_diff = len(next_revs) - len(revs) |
61 yield (curr_rev, node, rev_index, edges, len(revs), n_columns_diff) | 62 yield (curr_rev, node, rev_index, edges, len(revs), n_columns_diff) |
62 | 63 |
63 revs = next_revs | 64 revs = next_revs |
64 curr_rev -= 1 | 65 curr_rev -= 1 |
66 | |
67 def filelog_grapher(repo, path, start_rev, stop_rev): | |
68 """incremental file log grapher | |
69 | |
70 This generator function walks through the revision history of a | |
71 single file from revision start_rev to revision stop_rev (which must | |
72 be less than or equal to start_rev) and for each revision emits | |
73 tuples with the following elements: | |
74 | |
75 - Current revision. | |
76 - Current node. | |
77 - Column of the current node in the set of ongoing edges. | |
78 - Edges; a list of (col, next_col) indicating the edges between | |
79 the current node and its parents. | |
80 - Number of columns (ongoing edges) in the current revision. | |
81 - The difference between the number of columns (ongoing edges) | |
82 in the next revision and the number of columns (ongoing edges) | |
83 in the current revision. That is: -1 means one column removed; | |
84 0 means no columns added or removed; 1 means one column added. | |
85 """ | |
86 | |
87 assert start_rev >= stop_rev | |
88 curr_rev = start_rev | |
89 revs = [] | |
90 filerev = repo.file(path).count() - 1 | |
91 while filerev >= 0: | |
92 fctx = repo.filectx(path, fileid=filerev) | |
93 | |
94 # Compute revs and next_revs. | |
95 if filerev not in revs: | |
96 revs.append(filerev) | |
97 rev_index = revs.index(filerev) | |
98 next_revs = revs[:] | |
99 | |
100 # Add parents to next_revs. | |
101 parents = [f.filerev() for f in fctx.parents()] | |
102 parents_to_add = [] | |
103 for parent in parents: | |
104 if parent not in next_revs: | |
105 parents_to_add.append(parent) | |
106 parents_to_add.sort() | |
107 next_revs[rev_index:rev_index + 1] = parents_to_add | |
108 | |
109 edges = [] | |
110 for parent in parents: | |
111 edges.append((rev_index, next_revs.index(parent))) | |
112 | |
113 changerev = fctx.linkrev() | |
114 if changerev <= start_rev: | |
115 node = repo.changelog.node(changerev) | |
116 n_columns_diff = len(next_revs) - len(revs) | |
117 yield (changerev, node, rev_index, edges, len(revs), n_columns_diff) | |
118 if changerev <= stop_rev: | |
119 break | |
120 revs = next_revs | |
121 filerev -= 1 | |
65 | 122 |
66 def get_rev_parents(repo, rev): | 123 def get_rev_parents(repo, rev): |
67 return [x for x in repo.changelog.parentrevs(rev) if x != nullrev] | 124 return [x for x in repo.changelog.parentrevs(rev) if x != nullrev] |
68 | 125 |
69 def fix_long_right_edges(edges): | 126 def fix_long_right_edges(edges): |
139 revs = revrange(repo, rev_opt) | 196 revs = revrange(repo, rev_opt) |
140 return (max(revs), min(revs)) | 197 return (max(revs), min(revs)) |
141 else: | 198 else: |
142 return (repo.changelog.count() - 1, 0) | 199 return (repo.changelog.count() - 1, 0) |
143 | 200 |
144 def graphlog(ui, repo, **opts): | 201 def graphlog(ui, repo, path=None, **opts): |
145 """show revision history alongside an ASCII revision graph | 202 """show revision history alongside an ASCII revision graph |
146 | 203 |
147 Print a revision history alongside a revision graph drawn with | 204 Print a revision history alongside a revision graph drawn with |
148 ASCII characters. | 205 ASCII characters. |
149 | 206 |
155 (start_rev, stop_rev) = get_revs(repo, opts["rev"]) | 212 (start_rev, stop_rev) = get_revs(repo, opts["rev"]) |
156 stop_rev = max(stop_rev, start_rev - limit + 1) | 213 stop_rev = max(stop_rev, start_rev - limit + 1) |
157 if start_rev == nullrev: | 214 if start_rev == nullrev: |
158 return | 215 return |
159 cs_printer = show_changeset(ui, repo, opts) | 216 cs_printer = show_changeset(ui, repo, opts) |
160 grapher = revision_grapher(repo, start_rev, stop_rev) | 217 if path: |
218 cpath = canonpath(repo.root, os.getcwd(), path) | |
219 grapher = filelog_grapher(repo, cpath, start_rev, stop_rev) | |
220 else: | |
221 grapher = revision_grapher(repo, start_rev, stop_rev) | |
161 repo_parents = repo.dirstate.parents() | 222 repo_parents = repo.dirstate.parents() |
162 prev_n_columns_diff = 0 | 223 prev_n_columns_diff = 0 |
163 prev_node_index = 0 | 224 prev_node_index = 0 |
164 | 225 |
165 for (rev, node, node_index, edges, n_columns, n_columns_diff) in grapher: | 226 for (rev, node, node_index, edges, n_columns, n_columns_diff) in grapher: |
259 [('l', 'limit', '', _('limit number of changes displayed')), | 320 [('l', 'limit', '', _('limit number of changes displayed')), |
260 ('p', 'patch', False, _('show patch')), | 321 ('p', 'patch', False, _('show patch')), |
261 ('r', 'rev', [], _('show the specified revision or range')), | 322 ('r', 'rev', [], _('show the specified revision or range')), |
262 ('', 'style', '', _('display using template map file')), | 323 ('', 'style', '', _('display using template map file')), |
263 ('', 'template', '', _('display with template'))], | 324 ('', 'template', '', _('display with template'))], |
264 _('hg glog [OPTION]...')), | 325 _('hg glog [OPTION] [FILE]...')), |
265 } | 326 } |