comparison mercurial/commands.py @ 6321:55ba3bc5b8fd

tag: allow multiple tags to be added or removed - Example: "hg tag -r 42 build-25 beta-1" will add tags build-25 and beta-1 for rev 42. - The deprecated and undocumented usage "hg tag arg1 arg2" used to emit a warning, then add tag arg1 for rev arg2 (equivalent to "hg tag -r arg2 arg1"). It will now add tags arg1 and arg2 for the current revision. - If one tag triggers an error, no tags are added/removed (all or nothing).
author John Coomes <john.coomes@sun.com>
date Fri, 14 Mar 2008 15:38:56 -0700
parents d99b4e8652b3
children 4b0c9c674707
comparison
equal deleted inserted replaced
6320:9a9b02bcbcf4 6321:55ba3bc5b8fd
2587 for f in changes: 2587 for f in changes:
2588 ui.write(format % repo.pathto(f, cwd)) 2588 ui.write(format % repo.pathto(f, cwd))
2589 if f in copy and (f in added or f in showcopy): 2589 if f in copy and (f in added or f in showcopy):
2590 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end)) 2590 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end))
2591 2591
2592 def tag(ui, repo, name, rev_=None, **opts): 2592 def tag(ui, repo, name1, *names, **opts):
2593 """add a tag for the current or given revision 2593 """add one or more tags for the current or given revision
2594 2594
2595 Name a particular revision using <name>. 2595 Name a particular revision using <name>.
2596 2596
2597 Tags are used to name particular revisions of the repository and are 2597 Tags are used to name particular revisions of the repository and are
2598 very useful to compare different revisions, to go back to significant 2598 very useful to compare different revisions, to go back to significant
2607 necessary. The file '.hg/localtags' is used for local tags (not 2607 necessary. The file '.hg/localtags' is used for local tags (not
2608 shared among repositories). 2608 shared among repositories).
2609 2609
2610 See 'hg help dates' for a list of formats valid for -d/--date. 2610 See 'hg help dates' for a list of formats valid for -d/--date.
2611 """ 2611 """
2612 if name in ['tip', '.', 'null']: 2612
2613 raise util.Abort(_("the name '%s' is reserved") % name) 2613 rev_ = None
2614 if rev_ is not None: 2614 names = (name1,) + names
2615 ui.warn(_("use of 'hg tag NAME [REV]' is deprecated, " 2615 if len(names) != len(dict.fromkeys(names)):
2616 "please use 'hg tag [-r REV] NAME' instead\n")) 2616 raise util.Abort(_('tag names must be unique'))
2617 if opts['rev']: 2617 for n in names:
2618 raise util.Abort(_("use only one form to specify the revision")) 2618 if n in ['tip', '.', 'null']:
2619 raise util.Abort(_('the name \'%s\' is reserved') % n)
2619 if opts['rev'] and opts['remove']: 2620 if opts['rev'] and opts['remove']:
2620 raise util.Abort(_("--rev and --remove are incompatible")) 2621 raise util.Abort(_("--rev and --remove are incompatible"))
2621 if opts['rev']: 2622 if opts['rev']:
2622 rev_ = opts['rev'] 2623 rev_ = opts['rev']
2623 message = opts['message'] 2624 message = opts['message']
2624 if opts['remove']: 2625 if opts['remove']:
2625 tagtype = repo.tagtype(name) 2626 expectedtype = opts['local'] and 'local' or 'global'
2626 2627 for n in names:
2627 if not tagtype: 2628 if not repo.tagtype(n):
2628 raise util.Abort(_('tag %s does not exist') % name) 2629 raise util.Abort(_('tag \'%s\' does not exist') % n)
2629 if opts['local'] and tagtype == 'global': 2630 if repo.tagtype(n) != expectedtype:
2630 raise util.Abort(_('%s tag is global') % name) 2631 raise util.Abort(_('tag \'%s\' is not a %s tag') %
2631 if not opts['local'] and tagtype == 'local': 2632 (n, expectedtype))
2632 raise util.Abort(_('%s tag is local') % name)
2633
2634 rev_ = nullid 2633 rev_ = nullid
2635 if not message: 2634 if not message:
2636 message = _('Removed tag %s') % name 2635 message = _('Removed tag %s') % ', '.join(names)
2637 elif name in repo.tags() and not opts['force']: 2636 elif not opts['force']:
2638 raise util.Abort(_('a tag named %s already exists (use -f to force)') 2637 for n in names:
2639 % name) 2638 if n in repo.tags():
2639 raise util.Abort(_('tag \'%s\' already exists '
2640 '(use -f to force)') % n)
2640 if not rev_ and repo.dirstate.parents()[1] != nullid: 2641 if not rev_ and repo.dirstate.parents()[1] != nullid:
2641 raise util.Abort(_('uncommitted merge - please provide a ' 2642 raise util.Abort(_('uncommitted merge - please provide a '
2642 'specific revision')) 2643 'specific revision'))
2643 r = repo.changectx(rev_).node() 2644 r = repo.changectx(rev_).node()
2644 2645
2645 if not message: 2646 if not message:
2646 message = _('Added tag %s for changeset %s') % (name, short(r)) 2647 message = (_('Added tag %s for changeset %s') %
2648 (', '.join(names), short(r)))
2647 2649
2648 date = opts.get('date') 2650 date = opts.get('date')
2649 if date: 2651 if date:
2650 date = util.parsedate(date) 2652 date = util.parsedate(date)
2651 2653
2652 repo.tag(name, r, message, opts['local'], opts['user'], date) 2654 repo.tag(names, r, message, opts['local'], opts['user'], date)
2653 2655
2654 def tags(ui, repo): 2656 def tags(ui, repo):
2655 """list repository tags 2657 """list repository tags
2656 2658
2657 List the repository tags. 2659 List the repository tags.
3188 ('r', 'rev', '', _('revision to tag')), 3190 ('r', 'rev', '', _('revision to tag')),
3189 ('', 'remove', None, _('remove a tag')), 3191 ('', 'remove', None, _('remove a tag')),
3190 # -l/--local is already there, commitopts cannot be used 3192 # -l/--local is already there, commitopts cannot be used
3191 ('m', 'message', '', _('use <text> as commit message')), 3193 ('m', 'message', '', _('use <text> as commit message')),
3192 ] + commitopts2, 3194 ] + commitopts2,
3193 _('hg tag [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME')), 3195 _('hg tag [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
3194 "tags": (tags, [], _('hg tags')), 3196 "tags": (tags, [], _('hg tags')),
3195 "tip": 3197 "tip":
3196 (tip, 3198 (tip,
3197 [('p', 'patch', None, _('show patch')), 3199 [('p', 'patch', None, _('show patch')),
3198 ] + templateopts, 3200 ] + templateopts,