647 won't call this unless they have registered a custom hook or are |
647 won't call this unless they have registered a custom hook or are |
648 replacing code that is expected to call a hook. |
648 replacing code that is expected to call a hook. |
649 """ |
649 """ |
650 return hook.hook(self.ui, self, name, throw, **args) |
650 return hook.hook(self.ui, self, name, throw, **args) |
651 |
651 |
652 @unfilteredmethod |
|
653 def _tag(self, names, node, message, local, user, date, extra=None, |
|
654 editor=False): |
|
655 if isinstance(names, str): |
|
656 names = (names,) |
|
657 |
|
658 branches = self.branchmap() |
|
659 for name in names: |
|
660 self.hook('pretag', throw=True, node=hex(node), tag=name, |
|
661 local=local) |
|
662 if name in branches: |
|
663 self.ui.warn(_("warning: tag %s conflicts with existing" |
|
664 " branch name\n") % name) |
|
665 |
|
666 def writetags(fp, names, munge, prevtags): |
|
667 fp.seek(0, 2) |
|
668 if prevtags and prevtags[-1] != '\n': |
|
669 fp.write('\n') |
|
670 for name in names: |
|
671 if munge: |
|
672 m = munge(name) |
|
673 else: |
|
674 m = name |
|
675 |
|
676 if (self._tagscache.tagtypes and |
|
677 name in self._tagscache.tagtypes): |
|
678 old = self.tags().get(name, nullid) |
|
679 fp.write('%s %s\n' % (hex(old), m)) |
|
680 fp.write('%s %s\n' % (hex(node), m)) |
|
681 fp.close() |
|
682 |
|
683 prevtags = '' |
|
684 if local: |
|
685 try: |
|
686 fp = self.vfs('localtags', 'r+') |
|
687 except IOError: |
|
688 fp = self.vfs('localtags', 'a') |
|
689 else: |
|
690 prevtags = fp.read() |
|
691 |
|
692 # local tags are stored in the current charset |
|
693 writetags(fp, names, None, prevtags) |
|
694 for name in names: |
|
695 self.hook('tag', node=hex(node), tag=name, local=local) |
|
696 return |
|
697 |
|
698 try: |
|
699 fp = self.wvfs('.hgtags', 'rb+') |
|
700 except IOError as e: |
|
701 if e.errno != errno.ENOENT: |
|
702 raise |
|
703 fp = self.wvfs('.hgtags', 'ab') |
|
704 else: |
|
705 prevtags = fp.read() |
|
706 |
|
707 # committed tags are stored in UTF-8 |
|
708 writetags(fp, names, encoding.fromlocal, prevtags) |
|
709 |
|
710 fp.close() |
|
711 |
|
712 self.invalidatecaches() |
|
713 |
|
714 if '.hgtags' not in self.dirstate: |
|
715 self[None].add(['.hgtags']) |
|
716 |
|
717 m = matchmod.exact(self.root, '', ['.hgtags']) |
|
718 tagnode = self.commit(message, user, date, extra=extra, match=m, |
|
719 editor=editor) |
|
720 |
|
721 for name in names: |
|
722 self.hook('tag', node=hex(node), tag=name, local=local) |
|
723 |
|
724 return tagnode |
|
725 |
|
726 def tag(self, names, node, message, local, user, date, editor=False): |
652 def tag(self, names, node, message, local, user, date, editor=False): |
727 '''tag a revision with one or more symbolic names. |
653 '''tag a revision with one or more symbolic names. |
728 |
654 |
729 names is a list of strings or, when adding a single tag, names may be a |
655 names is a list of strings or, when adding a single tag, names may be a |
730 string. |
656 string. |
749 if any(self.status(match=m, unknown=True, ignored=True)): |
675 if any(self.status(match=m, unknown=True, ignored=True)): |
750 raise error.Abort(_('working copy of .hgtags is changed'), |
676 raise error.Abort(_('working copy of .hgtags is changed'), |
751 hint=_('please commit .hgtags manually')) |
677 hint=_('please commit .hgtags manually')) |
752 |
678 |
753 self.tags() # instantiate the cache |
679 self.tags() # instantiate the cache |
754 self._tag(names, node, message, local, user, date, editor=editor) |
680 tagsmod._tag(self.unfiltered(), names, node, message, local, user, date, |
|
681 editor=editor) |
755 |
682 |
756 @filteredpropertycache |
683 @filteredpropertycache |
757 def _tagscache(self): |
684 def _tagscache(self): |
758 '''Returns a tagscache object that contains various tags related |
685 '''Returns a tagscache object that contains various tags related |
759 caches.''' |
686 caches.''' |