124 usertempl = '{if(users, " by {join(users, ", ")}")}' |
126 usertempl = '{if(users, " by {join(users, ", ")}")}' |
125 succtempl = '{if(successors, " as ")}{successors}' # Bypass if limitation |
127 succtempl = '{if(successors, " as ")}{successors}' # Bypass if limitation |
126 datetempleq = ' (at {min_date|isodate})' |
128 datetempleq = ' (at {min_date|isodate})' |
127 datetemplnoteq = ' (between {min_date|isodate} and {max_date|isodate})' |
129 datetemplnoteq = ' (between {min_date|isodate} and {max_date|isodate})' |
128 datetempl = '{if(max_date, "{ifeq(min_date, max_date, "%s", "%s")}")}' % (datetempleq, datetemplnoteq) |
130 datetempl = '{if(max_date, "{ifeq(min_date, max_date, "%s", "%s")}")}' % (datetempleq, datetemplnoteq) |
129 newline = '\n' |
|
130 |
131 |
131 optionalusertempl = usertempl |
132 optionalusertempl = usertempl |
132 username = _getusername(ui) |
133 username = _getusername(ui) |
133 if username is not None: |
134 if username is not None: |
134 optionalusertempl = ('{ifeq(join(users, "\0"), "%s", "", "%s")}' |
135 optionalusertempl = ('{ifeq(join(users, "\0"), "%s", "", "%s")}' |
135 % (username, usertempl)) |
136 % (username, usertempl)) |
136 |
137 |
137 # Assemble them |
138 # Assemble them |
138 return { |
139 return { |
139 'obsfate_quiet': verbtempl + succtempl + newline, |
140 'obsfate_quiet': verbtempl + succtempl, |
140 'obsfate': verbtempl + optionalusertempl + succtempl + newline, |
141 'obsfate': verbtempl + optionalusertempl + succtempl, |
141 'obsfate_verbose': verbtempl + usertempl + succtempl + datetempl + newline |
142 'obsfate_verbose': verbtempl + usertempl + succtempl + datetempl, |
142 } |
143 } |
143 |
144 |
144 @eh.templatekw("obsfate") |
145 def obsfatedata(repo, ctx): |
145 def showobsfate(repo, ctx, **args): |
146 """compute the raw data needed for computing obsfate |
|
147 Returns a list of dict |
|
148 """ |
146 if not ctx.obsolete(): |
149 if not ctx.obsolete(): |
147 return '' |
150 return None |
148 |
151 |
149 successorssets, pathcache = closestsuccessors(repo, ctx.node()) |
152 successorssets, pathcache = closestsuccessors(repo, ctx.node()) |
150 |
153 |
151 # closestsuccessors returns an empty list for pruned revisions, remap it |
154 # closestsuccessors returns an empty list for pruned revisions, remap it |
152 # into a list containing en empty list for future processing |
155 # into a list containing en empty list for future processing |
171 fullsuccessorsets.append(([], [])) |
174 fullsuccessorsets.append(([], [])) |
172 |
175 |
173 values = [] |
176 values = [] |
174 for sset, rawmarkers in fullsuccessorsets: |
177 for sset, rawmarkers in fullsuccessorsets: |
175 raw = obshistory.preparesuccessorset(sset, rawmarkers) |
178 raw = obshistory.preparesuccessorset(sset, rawmarkers) |
176 |
179 values.append(raw) |
|
180 |
|
181 return values |
|
182 |
|
183 def obsfatelineprinter(obsfateline, ui): |
|
184 quiet = ui.quiet |
|
185 verbose = ui.verbose |
|
186 normal = not verbose and not quiet |
|
187 |
|
188 # Build the line step by step |
|
189 line = [] |
|
190 |
|
191 # Verb |
|
192 line.append(obsfateline['verb']) |
|
193 |
|
194 # Users |
|
195 if (verbose or normal) and 'users' in obsfateline: |
|
196 users = obsfateline['users'] |
|
197 |
|
198 if normal: |
|
199 username = _getusername(ui) |
|
200 users = [user for user in users if user != username] |
|
201 |
|
202 if users: |
|
203 line.append(" by %s" % ",".join(users)) |
|
204 |
|
205 # Successors |
|
206 successors = obsfateline["successors"] |
|
207 |
|
208 if successors: |
|
209 fmtsuccessors = map(lambda s: s[:12], successors) |
|
210 line.append(" as %s" % ", ".join(fmtsuccessors)) |
|
211 |
|
212 # Date |
|
213 if verbose: |
|
214 min_date = obsfateline['min_date'] |
|
215 max_date = obsfateline['max_date'] |
|
216 |
|
217 if min_date == max_date: |
|
218 fmtmin_date = util.datestr(min_date, '%Y-%m-%d %H:%M %1%2') |
|
219 line.append(" (at %s)" % fmtmin_date) |
|
220 else: |
|
221 fmtmin_date = util.datestr(min_date, '%Y-%m-%d %H:%M %1%2') |
|
222 fmtmax_date = util.datestr(max_date, '%Y-%m-%d %H:%M %1%2') |
|
223 line.append(" (between %s and %s)" % (fmtmin_date, fmtmax_date)) |
|
224 |
|
225 return "".join(line) |
|
226 |
|
227 def obsfateprinter(obsfate, ui, prefix=""): |
|
228 lines = [] |
|
229 for raw in obsfate: |
|
230 lines.append(obsfatelineprinter(raw, ui)) |
|
231 |
|
232 if prefix: |
|
233 lines = [prefix + line for line in lines] |
|
234 |
|
235 return "\n".join(lines) |
|
236 |
|
237 @eh.templatekw("obsfate") |
|
238 def showobsfate(repo, ctx, **args): |
|
239 # Get the needed obsfate data |
|
240 values = obsfatedata(repo, ctx) |
|
241 |
|
242 if values is None: |
|
243 return '' |
|
244 |
|
245 # Format each successorset successors list |
|
246 for raw in values: |
177 # As we can't do something like |
247 # As we can't do something like |
178 # "{join(map(nodeshort, successors), ', '}" in template, manually |
248 # "{join(map(nodeshort, successors), ', '}" in template, manually |
179 # create a correct textual representation |
249 # create a correct textual representation |
180 gen = ', '.join(n[:12] for n in raw['successors']) |
250 gen = ', '.join(n[:12] for n in raw['successors']) |
181 |
251 |
182 makemap = lambda x: {'successor': x} |
252 makemap = lambda x: {'successor': x} |
183 joinfmt = lambda d: "%s" % d['successor'] |
253 joinfmt = lambda d: "%s" % d['successor'] |
184 raw['successors'] = templatekw._hybrid(gen, raw['successors'], makemap, |
254 raw['successors'] = templatekw._hybrid(gen, raw['successors'], makemap, |
185 joinfmt) |
255 joinfmt) |
186 |
256 |
187 values.append(raw) |
257 # And then format them |
188 |
|
189 # Insert default obsfate templates |
258 # Insert default obsfate templates |
190 args['templ'].cache.update(obsfatedefaulttempl(repo.ui)) |
259 args['templ'].cache.update(obsfatedefaulttempl(repo.ui)) |
191 |
260 |
192 if repo.ui.quiet: |
261 if repo.ui.quiet: |
193 name = "obsfate_quiet" |
262 name = "obsfate_quiet" |
196 elif repo.ui.debugflag: |
265 elif repo.ui.debugflag: |
197 name = "obsfate_debug" |
266 name = "obsfate_debug" |
198 else: |
267 else: |
199 name = "obsfate" |
268 name = "obsfate" |
200 |
269 |
201 return templatekw.showlist(name, values, args, separator=' + ') |
270 # Format a single value |
|
271 def fmt(d): |
|
272 nargs = args.copy() |
|
273 nargs.update(d[name]) |
|
274 return args['templ'](name, **nargs) |
|
275 |
|
276 # Generate a good enough string representation using templater |
|
277 gen = [] |
|
278 for d in values: |
|
279 chunk = fmt({name: d}) |
|
280 chunkstr = [] |
|
281 |
|
282 # Empty the generator |
|
283 try: |
|
284 while True: |
|
285 chunkstr.append(chunk.next()) |
|
286 except StopIteration: |
|
287 pass |
|
288 |
|
289 gen.append("".join(chunkstr)) |
|
290 gen = "; ".join(gen) |
|
291 |
|
292 return templatekw._hybrid(gen, values, lambda x: {name: x}, fmt) |
|
293 |
|
294 # Check if we can hook directly on the changeset_printer |
|
295 if util.safehasattr(cmdutil.changeset_printer, '_exthook'): |
|
296 @eh.wrapfunction(cmdutil.changeset_printer, '_exthook') |
|
297 def exthook(original, self, ctx): |
|
298 # Call potential other extensions |
|
299 original(self, ctx) |
|
300 |
|
301 obsfate = obsfatedata(self.repo, ctx) |
|
302 if obsfate is None: |
|
303 return "" |
|
304 |
|
305 output = obsfateprinter(obsfate, self.ui, prefix="obsolete: ") |
|
306 |
|
307 self.ui.write(output, label='log.obsfate') |
|
308 self.ui.write("\n") |
202 |
309 |
203 # copy from mercurial.obsolete with a small change to stop at first known changeset. |
310 # copy from mercurial.obsolete with a small change to stop at first known changeset. |
204 |
311 |
205 def directsuccessorssets(repo, initialnode, cache=None): |
312 def directsuccessorssets(repo, initialnode, cache=None): |
206 """return set of all direct successors of initial nodes |
313 """return set of all direct successors of initial nodes |