276 |
276 |
277 self._tag(name, node, message, local, user, date) |
277 self._tag(name, node, message, local, user, date) |
278 |
278 |
279 def tags(self): |
279 def tags(self): |
280 '''return a mapping of tag to node''' |
280 '''return a mapping of tag to node''' |
281 if not self.tagscache: |
281 if self.tagscache: |
282 self.tagscache = {} |
282 return self.tagscache |
283 |
283 |
284 def parsetag(line, context): |
284 globaltags = {} |
285 if not line: |
285 |
286 return |
286 def readtags(lines, fn): |
|
287 filetags = {} |
|
288 count = 0 |
|
289 |
|
290 def warn(msg): |
|
291 self.ui.warn(_("%s, line %s: %s\n") % (fn, count, msg)) |
|
292 |
|
293 for l in lines: |
|
294 count += 1 |
|
295 if not l: |
|
296 continue |
287 s = l.split(" ", 1) |
297 s = l.split(" ", 1) |
288 if len(s) != 2: |
298 if len(s) != 2: |
289 self.ui.warn(_("%s: cannot parse entry\n") % context) |
299 warn(_("cannot parse entry")) |
290 return |
300 continue |
291 node, key = s |
301 node, key = s |
292 key = util.tolocal(key.strip()) # stored in UTF-8 |
302 key = util.tolocal(key.strip()) # stored in UTF-8 |
293 try: |
303 try: |
294 bin_n = bin(node) |
304 bin_n = bin(node) |
295 except TypeError: |
305 except TypeError: |
296 self.ui.warn(_("%s: node '%s' is not well formed\n") % |
306 warn(_("node '%s' is not well formed") % node) |
297 (context, node)) |
307 continue |
298 return |
|
299 if bin_n not in self.changelog.nodemap: |
308 if bin_n not in self.changelog.nodemap: |
300 self.ui.warn(_("%s: tag '%s' refers to unknown node\n") % |
309 warn(_("tag '%s' refers to unknown node") % key) |
301 (context, key)) |
310 continue |
302 return |
311 |
303 self.tagscache[key] = bin_n |
312 h = {} |
304 |
313 if key in filetags: |
305 # read the tags file from each head, ending with the tip, |
314 n, h = filetags[key] |
306 # and add each tag found to the map, with "newer" ones |
315 h[n] = True |
307 # taking precedence |
316 filetags[key] = (bin_n, h) |
308 f = None |
317 |
309 for rev, node, fnode in self._hgtagsnodes(): |
318 for k,nh in filetags.items(): |
310 f = (f and f.filectx(fnode) or |
319 if k not in globaltags: |
311 self.filectx('.hgtags', fileid=fnode)) |
320 globaltags[k] = nh |
312 count = 0 |
321 continue |
313 for l in f.data().splitlines(): |
322 # we prefer the global tag if: |
314 count += 1 |
323 # it supercedes us OR |
315 parsetag(l, _("%s, line %d") % (str(f), count)) |
324 # mutual supercedes and it has a higher rank |
316 |
325 # otherwise we win because we're tip-most |
317 try: |
326 an, ah = nh |
318 f = self.opener("localtags") |
327 bn, bh = globaltags[k] |
319 count = 0 |
328 if bn != an and an in bh and \ |
320 for l in f: |
329 (bn not in ah or len(bh) > len(ah)): |
321 # localtags are stored in the local character set |
330 an = bn |
322 # while the internal tag table is stored in UTF-8 |
331 ah.update(bh) |
323 l = util.fromlocal(l) |
332 globaltags[k] = an, ah |
324 count += 1 |
333 |
325 parsetag(l, _("localtags, line %d") % count) |
334 # read the tags file from each head, ending with the tip |
326 except IOError: |
335 f = None |
327 pass |
336 for rev, node, fnode in self._hgtagsnodes(): |
328 |
337 f = (f and f.filectx(fnode) or |
329 self.tagscache['tip'] = self.changelog.tip() |
338 self.filectx('.hgtags', fileid=fnode)) |
|
339 readtags(f.data().splitlines(), f) |
|
340 |
|
341 try: |
|
342 data = util.fromlocal(self.opener("localtags").read()) |
|
343 # localtags are stored in the local character set |
|
344 # while the internal tag table is stored in UTF-8 |
|
345 readtags(data.splitlines(), "localtags") |
|
346 except IOError: |
|
347 pass |
|
348 |
|
349 self.tagscache = {} |
|
350 for k,nh in globaltags.items(): |
|
351 n = nh[0] |
|
352 if n != nullid: |
|
353 self.tagscache[k] = n |
|
354 self.tagscache['tip'] = self.changelog.tip() |
330 |
355 |
331 return self.tagscache |
356 return self.tagscache |
332 |
357 |
333 def _hgtagsnodes(self): |
358 def _hgtagsnodes(self): |
334 heads = self.heads() |
359 heads = self.heads() |