##// END OF EJS Templates
Properly check tag's existence as a local/global tag when removing it.
Osku Salerma -
r5657:47915bf6 default
parent child Browse files
Show More
@@ -2428,8 +2428,15 b' def tag(ui, repo, name, rev_=None, **opt'
2428 rev_ = opts['rev']
2428 rev_ = opts['rev']
2429 message = opts['message']
2429 message = opts['message']
2430 if opts['remove']:
2430 if opts['remove']:
2431 if not name in repo.tags():
2431 tagtype = repo.tagtype(name)
2432
2433 if not tagtype:
2432 raise util.Abort(_('tag %s does not exist') % name)
2434 raise util.Abort(_('tag %s does not exist') % name)
2435 if opts['local'] and tagtype == 'global':
2436 raise util.Abort(_('%s tag is global') % name)
2437 if not opts['local'] and tagtype == 'local':
2438 raise util.Abort(_('%s tag is local') % name)
2439
2433 rev_ = nullid
2440 rev_ = nullid
2434 if not message:
2441 if not message:
2435 message = _('Removed tag %s') % name
2442 message = _('Removed tag %s') % name
@@ -79,6 +79,7 b' class localrepository(repo.repository):'
79 pass
79 pass
80
80
81 self.tagscache = None
81 self.tagscache = None
82 self._tagstypecache = None
82 self.branchcache = None
83 self.branchcache = None
83 self.nodetagscache = None
84 self.nodetagscache = None
84 self.filterpats = {}
85 self.filterpats = {}
@@ -198,8 +199,9 b' class localrepository(repo.repository):'
198 return self.tagscache
199 return self.tagscache
199
200
200 globaltags = {}
201 globaltags = {}
202 tagtypes = {}
201
203
202 def readtags(lines, fn):
204 def readtags(lines, fn, tagtype):
203 filetags = {}
205 filetags = {}
204 count = 0
206 count = 0
205
207
@@ -234,7 +236,9 b' class localrepository(repo.repository):'
234 for k, nh in filetags.items():
236 for k, nh in filetags.items():
235 if k not in globaltags:
237 if k not in globaltags:
236 globaltags[k] = nh
238 globaltags[k] = nh
239 tagtypes[k] = tagtype
237 continue
240 continue
241
238 # we prefer the global tag if:
242 # we prefer the global tag if:
239 # it supercedes us OR
243 # it supercedes us OR
240 # mutual supercedes and it has a higher rank
244 # mutual supercedes and it has a higher rank
@@ -246,31 +250,47 b' class localrepository(repo.repository):'
246 an = bn
250 an = bn
247 ah.extend([n for n in bh if n not in ah])
251 ah.extend([n for n in bh if n not in ah])
248 globaltags[k] = an, ah
252 globaltags[k] = an, ah
253 tagtypes[k] = tagtype
249
254
250 # read the tags file from each head, ending with the tip
255 # read the tags file from each head, ending with the tip
251 f = None
256 f = None
252 for rev, node, fnode in self._hgtagsnodes():
257 for rev, node, fnode in self._hgtagsnodes():
253 f = (f and f.filectx(fnode) or
258 f = (f and f.filectx(fnode) or
254 self.filectx('.hgtags', fileid=fnode))
259 self.filectx('.hgtags', fileid=fnode))
255 readtags(f.data().splitlines(), f)
260 readtags(f.data().splitlines(), f, "global")
256
261
257 try:
262 try:
258 data = util.fromlocal(self.opener("localtags").read())
263 data = util.fromlocal(self.opener("localtags").read())
259 # localtags are stored in the local character set
264 # localtags are stored in the local character set
260 # while the internal tag table is stored in UTF-8
265 # while the internal tag table is stored in UTF-8
261 readtags(data.splitlines(), "localtags")
266 readtags(data.splitlines(), "localtags", "local")
262 except IOError:
267 except IOError:
263 pass
268 pass
264
269
265 self.tagscache = {}
270 self.tagscache = {}
271 self._tagstypecache = {}
266 for k,nh in globaltags.items():
272 for k,nh in globaltags.items():
267 n = nh[0]
273 n = nh[0]
268 if n != nullid:
274 if n != nullid:
269 self.tagscache[k] = n
275 self.tagscache[k] = n
276 self._tagstypecache[k] = tagtypes[k]
270 self.tagscache['tip'] = self.changelog.tip()
277 self.tagscache['tip'] = self.changelog.tip()
271
278
272 return self.tagscache
279 return self.tagscache
273
280
281 def tagtype(self, tagname):
282 '''
283 return the type of the given tag. result can be:
284
285 'local' : a local tag
286 'global' : a global tag
287 None : tag does not exist
288 '''
289
290 self.tags()
291
292 return self._tagstypecache.get(tagname)
293
274 def _hgtagsnodes(self):
294 def _hgtagsnodes(self):
275 heads = self.heads()
295 heads = self.heads()
276 heads.reverse()
296 heads.reverse()
@@ -553,6 +573,7 b' class localrepository(repo.repository):'
553 if hasattr(self, a):
573 if hasattr(self, a):
554 self.__delattr__(a)
574 self.__delattr__(a)
555 self.tagscache = None
575 self.tagscache = None
576 self._tagstypecache = None
556 self.nodetagscache = None
577 self.nodetagscache = None
557
578
558 def _lock(self, lockname, wait, releasefn, acquirefn, desc):
579 def _lock(self, lockname, wait, releasefn, acquirefn, desc):
@@ -126,3 +126,20 b' hg up -qC 0'
126 hg tag -m 'retag rev 0' -fr 0 bar # rev 4 bar -> 0, but bar stays at 2
126 hg tag -m 'retag rev 0' -fr 0 bar # rev 4 bar -> 0, but bar stays at 2
127 echo % bar should still point to rev 2
127 echo % bar should still point to rev 2
128 hg tags
128 hg tags
129
130
131 # test that removing global/local tags does not get confused when trying
132 # to remove a tag of type X which actually only exists as a type Y
133 cd ..
134 hg init t5
135 cd t5
136 echo foo > foo
137 hg add
138 hg ci -m 'add foo' # rev 0
139
140 hg tag -r 0 -l localtag
141 hg tag --remove localtag
142
143 hg tag -r 0 globaltag
144 hg tag --remove -l globaltag
145 exit 0
@@ -71,3 +71,6 b' bar 2:72b'
71 % bar should still point to rev 2
71 % bar should still point to rev 2
72 tip 4:40af5d225513
72 tip 4:40af5d225513
73 bar 2:72b852876a42
73 bar 2:72b852876a42
74 adding foo
75 abort: localtag tag is local
76 abort: globaltag tag is global
General Comments 0
You need to be logged in to leave comments. Login now