Properly check tag's existence as a local/global tag when removing it.
--- a/mercurial/commands.py Tue Dec 18 14:01:34 2007 -0600
+++ b/mercurial/commands.py Sun Dec 09 16:32:05 2007 +0900
@@ -2428,8 +2428,15 @@
rev_ = opts['rev']
message = opts['message']
if opts['remove']:
- if not name in repo.tags():
+ tagtype = repo.tagtype(name)
+
+ if not tagtype:
raise util.Abort(_('tag %s does not exist') % name)
+ if opts['local'] and tagtype == 'global':
+ raise util.Abort(_('%s tag is global') % name)
+ if not opts['local'] and tagtype == 'local':
+ raise util.Abort(_('%s tag is local') % name)
+
rev_ = nullid
if not message:
message = _('Removed tag %s') % name
--- a/mercurial/localrepo.py Tue Dec 18 14:01:34 2007 -0600
+++ b/mercurial/localrepo.py Sun Dec 09 16:32:05 2007 +0900
@@ -79,6 +79,7 @@
pass
self.tagscache = None
+ self._tagstypecache = None
self.branchcache = None
self.nodetagscache = None
self.filterpats = {}
@@ -198,8 +199,9 @@
return self.tagscache
globaltags = {}
+ tagtypes = {}
- def readtags(lines, fn):
+ def readtags(lines, fn, tagtype):
filetags = {}
count = 0
@@ -234,7 +236,9 @@
for k, nh in filetags.items():
if k not in globaltags:
globaltags[k] = nh
+ tagtypes[k] = tagtype
continue
+
# we prefer the global tag if:
# it supercedes us OR
# mutual supercedes and it has a higher rank
@@ -246,31 +250,47 @@
an = bn
ah.extend([n for n in bh if n not in ah])
globaltags[k] = an, ah
+ tagtypes[k] = tagtype
# read the tags file from each head, ending with the tip
f = None
for rev, node, fnode in self._hgtagsnodes():
f = (f and f.filectx(fnode) or
self.filectx('.hgtags', fileid=fnode))
- readtags(f.data().splitlines(), f)
+ readtags(f.data().splitlines(), f, "global")
try:
data = util.fromlocal(self.opener("localtags").read())
# localtags are stored in the local character set
# while the internal tag table is stored in UTF-8
- readtags(data.splitlines(), "localtags")
+ readtags(data.splitlines(), "localtags", "local")
except IOError:
pass
self.tagscache = {}
+ self._tagstypecache = {}
for k,nh in globaltags.items():
n = nh[0]
if n != nullid:
self.tagscache[k] = n
+ self._tagstypecache[k] = tagtypes[k]
self.tagscache['tip'] = self.changelog.tip()
return self.tagscache
+ def tagtype(self, tagname):
+ '''
+ return the type of the given tag. result can be:
+
+ 'local' : a local tag
+ 'global' : a global tag
+ None : tag does not exist
+ '''
+
+ self.tags()
+
+ return self._tagstypecache.get(tagname)
+
def _hgtagsnodes(self):
heads = self.heads()
heads.reverse()
@@ -553,6 +573,7 @@
if hasattr(self, a):
self.__delattr__(a)
self.tagscache = None
+ self._tagstypecache = None
self.nodetagscache = None
def _lock(self, lockname, wait, releasefn, acquirefn, desc):
--- a/tests/test-tags Tue Dec 18 14:01:34 2007 -0600
+++ b/tests/test-tags Sun Dec 09 16:32:05 2007 +0900
@@ -126,3 +126,20 @@
hg tag -m 'retag rev 0' -fr 0 bar # rev 4 bar -> 0, but bar stays at 2
echo % bar should still point to rev 2
hg tags
+
+
+# test that removing global/local tags does not get confused when trying
+# to remove a tag of type X which actually only exists as a type Y
+cd ..
+hg init t5
+cd t5
+echo foo > foo
+hg add
+hg ci -m 'add foo' # rev 0
+
+hg tag -r 0 -l localtag
+hg tag --remove localtag
+
+hg tag -r 0 globaltag
+hg tag --remove -l globaltag
+exit 0
--- a/tests/test-tags.out Tue Dec 18 14:01:34 2007 -0600
+++ b/tests/test-tags.out Sun Dec 09 16:32:05 2007 +0900
@@ -71,3 +71,6 @@
% bar should still point to rev 2
tip 4:40af5d225513
bar 2:72b852876a42
+adding foo
+abort: localtag tag is local
+abort: globaltag tag is global