175 fp.write(updateold % (old, tag)) |
175 fp.write(updateold % (old, tag)) |
176 fp.write(updatenew % (new, tag)) |
176 fp.write(updatenew % (new, tag)) |
177 |
177 |
178 |
178 |
179 def findglobaltags(ui, repo): |
179 def findglobaltags(ui, repo): |
180 '''Find global tags in a repo: return a tagsmap |
180 """Find global tags in a repo: return a tagsmap |
181 |
181 |
182 tagsmap: tag name to (node, hist) 2-tuples. |
182 tagsmap: tag name to (node, hist) 2-tuples. |
183 |
183 |
184 The tags cache is read and updated as a side-effect of calling. |
184 The tags cache is read and updated as a side-effect of calling. |
185 ''' |
185 """ |
186 (heads, tagfnode, valid, cachetags, shouldwrite) = _readtagcache(ui, repo) |
186 (heads, tagfnode, valid, cachetags, shouldwrite) = _readtagcache(ui, repo) |
187 if cachetags is not None: |
187 if cachetags is not None: |
188 assert not shouldwrite |
188 assert not shouldwrite |
189 # XXX is this really 100% correct? are there oddball special |
189 # XXX is this really 100% correct? are there oddball special |
190 # cases where a global tag should outrank a local tag but won't, |
190 # cases where a global tag should outrank a local tag but won't, |
265 |
265 |
266 _updatetags(filetags, alltags, b'local', tagtypes) |
266 _updatetags(filetags, alltags, b'local', tagtypes) |
267 |
267 |
268 |
268 |
269 def _readtaghist(ui, repo, lines, fn, recode=None, calcnodelines=False): |
269 def _readtaghist(ui, repo, lines, fn, recode=None, calcnodelines=False): |
270 '''Read tag definitions from a file (or any source of lines). |
270 """Read tag definitions from a file (or any source of lines). |
271 |
271 |
272 This function returns two sortdicts with similar information: |
272 This function returns two sortdicts with similar information: |
273 |
273 |
274 - the first dict, bintaghist, contains the tag information as expected by |
274 - the first dict, bintaghist, contains the tag information as expected by |
275 the _readtags function, i.e. a mapping from tag name to (node, hist): |
275 the _readtags function, i.e. a mapping from tag name to (node, hist): |
281 [hexnode, line number] pairs, ordered from the oldest to the newest node. |
281 [hexnode, line number] pairs, ordered from the oldest to the newest node. |
282 |
282 |
283 When calcnodelines is False the hextaglines dict is not calculated (an |
283 When calcnodelines is False the hextaglines dict is not calculated (an |
284 empty dict is returned). This is done to improve this function's |
284 empty dict is returned). This is done to improve this function's |
285 performance in cases where the line numbers are not needed. |
285 performance in cases where the line numbers are not needed. |
286 ''' |
286 """ |
287 |
287 |
288 bintaghist = util.sortdict() |
288 bintaghist = util.sortdict() |
289 hextaglines = util.sortdict() |
289 hextaglines = util.sortdict() |
290 count = 0 |
290 count = 0 |
291 |
291 |
323 bintaghist[name].append(nodebin) |
323 bintaghist[name].append(nodebin) |
324 return bintaghist, hextaglines |
324 return bintaghist, hextaglines |
325 |
325 |
326 |
326 |
327 def _readtags(ui, repo, lines, fn, recode=None, calcnodelines=False): |
327 def _readtags(ui, repo, lines, fn, recode=None, calcnodelines=False): |
328 '''Read tag definitions from a file (or any source of lines). |
328 """Read tag definitions from a file (or any source of lines). |
329 |
329 |
330 Returns a mapping from tag name to (node, hist). |
330 Returns a mapping from tag name to (node, hist). |
331 |
331 |
332 "node" is the node id from the last line read for that name. "hist" |
332 "node" is the node id from the last line read for that name. "hist" |
333 is the list of node ids previously associated with it (in file order). |
333 is the list of node ids previously associated with it (in file order). |
334 All node ids are binary, not hex. |
334 All node ids are binary, not hex. |
335 ''' |
335 """ |
336 filetags, nodelines = _readtaghist( |
336 filetags, nodelines = _readtaghist( |
337 ui, repo, lines, fn, recode=recode, calcnodelines=calcnodelines |
337 ui, repo, lines, fn, recode=recode, calcnodelines=calcnodelines |
338 ) |
338 ) |
339 # util.sortdict().__setitem__ is much slower at replacing then inserting |
339 # util.sortdict().__setitem__ is much slower at replacing then inserting |
340 # new entries. The difference can matter if there are thousands of tags. |
340 # new entries. The difference can matter if there are thousands of tags. |
388 filename = b'%s-%s' % (filename, repo.filtername) |
388 filename = b'%s-%s' % (filename, repo.filtername) |
389 return filename |
389 return filename |
390 |
390 |
391 |
391 |
392 def _readtagcache(ui, repo): |
392 def _readtagcache(ui, repo): |
393 '''Read the tag cache. |
393 """Read the tag cache. |
394 |
394 |
395 Returns a tuple (heads, fnodes, validinfo, cachetags, shouldwrite). |
395 Returns a tuple (heads, fnodes, validinfo, cachetags, shouldwrite). |
396 |
396 |
397 If the cache is completely up-to-date, "cachetags" is a dict of the |
397 If the cache is completely up-to-date, "cachetags" is a dict of the |
398 form returned by _readtags() and "heads", "fnodes", and "validinfo" are |
398 form returned by _readtags() and "heads", "fnodes", and "validinfo" are |
404 when writing the tags cache. "fnodes" is a mapping from head to .hgtags |
404 when writing the tags cache. "fnodes" is a mapping from head to .hgtags |
405 filenode. "shouldwrite" is True. |
405 filenode. "shouldwrite" is True. |
406 |
406 |
407 If the cache is not up to date, the caller is responsible for reading tag |
407 If the cache is not up to date, the caller is responsible for reading tag |
408 info from each returned head. (See findglobaltags().) |
408 info from each returned head. (See findglobaltags().) |
409 ''' |
409 """ |
410 try: |
410 try: |
411 cachefile = repo.cachevfs(_filename(repo), b'r') |
411 cachefile = repo.cachevfs(_filename(repo), b'r') |
412 # force reading the file for static-http |
412 # force reading the file for static-http |
413 cachelines = iter(cachefile) |
413 cachelines = iter(cachefile) |
414 except IOError: |
414 except IOError: |
547 except (OSError, IOError): |
547 except (OSError, IOError): |
548 pass |
548 pass |
549 |
549 |
550 |
550 |
551 def tag(repo, names, node, message, local, user, date, editor=False): |
551 def tag(repo, names, node, message, local, user, date, editor=False): |
552 '''tag a revision with one or more symbolic names. |
552 """tag a revision with one or more symbolic names. |
553 |
553 |
554 names is a list of strings or, when adding a single tag, names may be a |
554 names is a list of strings or, when adding a single tag, names may be a |
555 string. |
555 string. |
556 |
556 |
557 if local is True, the tags are stored in a per-repository file. |
557 if local is True, the tags are stored in a per-repository file. |
565 |
565 |
566 message: commit message to use if committing |
566 message: commit message to use if committing |
567 |
567 |
568 user: name of user to use if committing |
568 user: name of user to use if committing |
569 |
569 |
570 date: date tuple to use if committing''' |
570 date: date tuple to use if committing""" |
571 |
571 |
572 if not local: |
572 if not local: |
573 m = matchmod.exact([b'.hgtags']) |
573 m = matchmod.exact([b'.hgtags']) |
574 st = repo.status(match=m, unknown=True, ignored=True) |
574 st = repo.status(match=m, unknown=True, ignored=True) |
575 if any( |
575 if any( |