108 # be easy. The iteration will have to be done using both input revision and |
108 # be easy. The iteration will have to be done using both input revision and |
109 # parents (see cl.ancestors function + a few tweaks) but only revisions |
109 # parents (see cl.ancestors function + a few tweaks) but only revisions |
110 # parts of the initial set should be emitted. |
110 # parts of the initial set should be emitted. |
111 groups = [([], unblocked)] |
111 groups = [([], unblocked)] |
112 for current in revs: |
112 for current in revs: |
113 # Look for a subgroup blocked, waiting for the current revision. |
113 if True: |
114 matching = [i for i, g in enumerate(groups) if current in g[1]] |
114 # Seek for a subgroup blocked, waiting for the current revision. |
115 |
115 matching = [i for i, g in enumerate(groups) if current in g[1]] |
116 if matching: |
116 |
117 # The main idea is to gather together all sets that await on the |
117 if matching: |
118 # same revision. |
118 # The main idea is to gather together all sets that await on |
|
119 # the same revision. |
|
120 # |
|
121 # This merging is done at the time we are about to add this |
|
122 # common awaited to the subgroup for simplicity purpose. Such |
|
123 # merge could happen sooner when we update the "blocked" set of |
|
124 # revision. |
|
125 # |
|
126 # We also always keep the oldest subgroup first. We can |
|
127 # probably improve the behavior by having the longuest set |
|
128 # first. That way, graph algorythms could minimise the length |
|
129 # of parallele lines their draw. This is currently not done. |
|
130 targetidx = matching.pop(0) |
|
131 trevs, tparents = groups[targetidx] |
|
132 for i in matching: |
|
133 gr = groups[i] |
|
134 trevs.extend(gr[0]) |
|
135 tparents |= gr[1] |
|
136 # delete all merged subgroups (but the one we keep) (starting |
|
137 # from the last subgroup for performance and sanity reason) |
|
138 for i in reversed(matching): |
|
139 del groups[i] |
|
140 else: |
|
141 # This is a new head. We create a new subgroup for it. |
|
142 targetidx = len(groups) |
|
143 groups.append(([], set([current]))) |
|
144 |
|
145 gr = groups[targetidx] |
|
146 |
|
147 # We now adds the current nodes to this subgroups. This is done |
|
148 # after the subgroup merging because all elements from a subgroup |
|
149 # that relied on this rev must preceed it. |
119 # |
150 # |
120 # This merging is done at the time we are about to add this common |
151 # we also update the <parents> set to includes the parents on the |
121 # awaited to the subgroup for simplicity purpose. Such merge could |
152 # new nodes. |
122 # happen sooner when we update the "blocked" set of revision. |
153 gr[0].append(current) |
|
154 gr[1].remove(current) |
|
155 gr[1].update([p for p in parentsfunc(current) if p > nullrev]) |
|
156 |
|
157 # Look for a subgroup to display |
123 # |
158 # |
124 # We also always keep the oldest subgroup first. We can probably |
159 # When unblocked is empty (if clause), We are not waiting over any |
125 # improve the behavior by having the longuest set first. That way, |
160 # revision during the first iteration (if no priority was given) or |
126 # graph algorythms could minimise the length of parallele lines |
161 # if we outputed a whole disconnected sets of the graph (reached a |
127 # their draw. This is currently not done. |
162 # root). In that case we arbitrarily takes the oldest known |
128 targetidx = matching.pop(0) |
163 # subgroup. The heuristique could probably be better. |
129 trevs, tparents = groups[targetidx] |
164 # |
130 for i in matching: |
165 # Otherwise (elif clause) this mean we have some emitted revision. |
131 gr = groups[i] |
166 # if the subgroup awaits on the same revision that the outputed |
132 trevs.extend(gr[0]) |
167 # ones, we can safely output it. |
133 tparents |= gr[1] |
168 if not unblocked: |
134 # delete all merged subgroups (but the one we keep) |
169 if len(groups) > 1: # display other subset |
135 # (starting from the last subgroup for performance and sanity reason) |
170 targetidx = 1 |
136 for i in reversed(matching): |
171 gr = groups[1] |
137 del groups[i] |
172 elif not gr[1] & unblocked: |
138 else: |
173 gr = None |
139 # This is a new head. We create a new subgroup for it. |
174 |
140 targetidx = len(groups) |
175 if gr is not None: |
141 groups.append(([], set([current]))) |
176 # update the set of awaited revisions with the one from the |
142 |
177 # subgroup |
143 gr = groups[targetidx] |
178 unblocked |= gr[1] |
144 |
179 # output all revisions in the subgroup |
145 # We now adds the current nodes to this subgroups. This is done after |
180 for r in gr[0]: |
146 # the subgroup merging because all elements from a subgroup that relied |
181 yield r |
147 # on this rev must preceed it. |
182 # delete the subgroup that you just output |
148 # |
183 # unless it is groups[0] in which case you just empty it. |
149 # we also update the <parents> set to includes the parents on the |
184 if targetidx: |
150 # new nodes. |
185 del groups[targetidx] |
151 gr[0].append(current) |
186 else: |
152 gr[1].remove(current) |
187 gr[0][:] = [] |
153 gr[1].update([p for p in parentsfunc(current) if p > nullrev]) |
|
154 |
|
155 # Look for a subgroup to display |
|
156 # |
|
157 # When unblocked is empty (if clause), We are not waiting over any |
|
158 # revision during the first iteration (if no priority was given) or if |
|
159 # we outputed a whole disconnected sets of the graph (reached a root). |
|
160 # In that case we arbitrarily takes the oldest known subgroup. The |
|
161 # heuristique could probably be better. |
|
162 # |
|
163 # Otherwise (elif clause) this mean we have some emitted revision. if |
|
164 # the subgroup awaits on the same revision that the outputed ones, we |
|
165 # can safely output it. |
|
166 if not unblocked: |
|
167 if len(groups) > 1: # display other subset |
|
168 targetidx = 1 |
|
169 gr = groups[1] |
|
170 elif not gr[1] & unblocked: |
|
171 gr = None |
|
172 |
|
173 if gr is not None: |
|
174 # update the set of awaited revisions with the one from the |
|
175 # subgroup |
|
176 unblocked |= gr[1] |
|
177 # output all revisions in the subgroup |
|
178 for r in gr[0]: |
|
179 yield r |
|
180 # delete the subgroup that you just output |
|
181 # unless it is groups[0] in which case you just empty it. |
|
182 if targetidx: |
|
183 del groups[targetidx] |
|
184 else: |
|
185 gr[0][:] = [] |
|
186 |
188 |
187 def dagwalker(repo, revs): |
189 def dagwalker(repo, revs): |
188 """cset DAG generator yielding (id, CHANGESET, ctx, [parentids]) tuples |
190 """cset DAG generator yielding (id, CHANGESET, ctx, [parentids]) tuples |
189 |
191 |
190 This generator function walks through revisions (which should be ordered |
192 This generator function walks through revisions (which should be ordered |