##// END OF EJS Templates
tag: allow multiple tags to be added or removed...
John Coomes -
r6321:55ba3bc5 default
parent child Browse files
Show More
@@ -2589,8 +2589,8 b' def status(ui, repo, *pats, **opts):'
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
@@ -2609,47 +2609,49 b' def tag(ui, repo, name, rev_=None, **opt'
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
@@ -3190,7 +3192,7 b' table = {'
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,
@@ -124,21 +124,29 b' class localrepository(repo.repository):'
124
124
125 tag_disallowed = ':\r\n'
125 tag_disallowed = ':\r\n'
126
126
127 def _tag(self, name, node, message, local, user, date, parent=None,
127 def _tag(self, names, node, message, local, user, date, parent=None,
128 extra={}):
128 extra={}):
129 use_dirstate = parent is None
129 use_dirstate = parent is None
130
130
131 if isinstance(names, str):
132 allchars = names
133 names = (names,)
134 else:
135 allchars = ''.join(names)
131 for c in self.tag_disallowed:
136 for c in self.tag_disallowed:
132 if c in name:
137 if c in allchars:
133 raise util.Abort(_('%r cannot be used in a tag name') % c)
138 raise util.Abort(_('%r cannot be used in a tag name') % c)
134
139
135 self.hook('pretag', throw=True, node=hex(node), tag=name, local=local)
140 for name in names:
141 self.hook('pretag', throw=True, node=hex(node), tag=name,
142 local=local)
136
143
137 def writetag(fp, name, munge, prevtags):
144 def writetags(fp, names, munge, prevtags):
138 fp.seek(0, 2)
145 fp.seek(0, 2)
139 if prevtags and prevtags[-1] != '\n':
146 if prevtags and prevtags[-1] != '\n':
140 fp.write('\n')
147 fp.write('\n')
141 fp.write('%s %s\n' % (hex(node), munge and munge(name) or name))
148 for name in names:
149 fp.write('%s %s\n' % (hex(node), munge and munge(name) or name))
142 fp.close()
150 fp.close()
143
151
144 prevtags = ''
152 prevtags = ''
@@ -151,8 +159,9 b' class localrepository(repo.repository):'
151 prevtags = fp.read()
159 prevtags = fp.read()
152
160
153 # local tags are stored in the current charset
161 # local tags are stored in the current charset
154 writetag(fp, name, None, prevtags)
162 writetags(fp, names, None, prevtags)
155 self.hook('tag', node=hex(node), tag=name, local=local)
163 for name in names:
164 self.hook('tag', node=hex(node), tag=name, local=local)
156 return
165 return
157
166
158 if use_dirstate:
167 if use_dirstate:
@@ -172,7 +181,7 b' class localrepository(repo.repository):'
172 fp.write(prevtags)
181 fp.write(prevtags)
173
182
174 # committed tags are stored in UTF-8
183 # committed tags are stored in UTF-8
175 writetag(fp, name, util.fromlocal, prevtags)
184 writetags(fp, names, util.fromlocal, prevtags)
176
185
177 if use_dirstate and '.hgtags' not in self.dirstate:
186 if use_dirstate and '.hgtags' not in self.dirstate:
178 self.add(['.hgtags'])
187 self.add(['.hgtags'])
@@ -180,20 +189,24 b' class localrepository(repo.repository):'
180 tagnode = self.commit(['.hgtags'], message, user, date, p1=parent,
189 tagnode = self.commit(['.hgtags'], message, user, date, p1=parent,
181 extra=extra)
190 extra=extra)
182
191
183 self.hook('tag', node=hex(node), tag=name, local=local)
192 for name in names:
193 self.hook('tag', node=hex(node), tag=name, local=local)
184
194
185 return tagnode
195 return tagnode
186
196
187 def tag(self, name, node, message, local, user, date):
197 def tag(self, names, node, message, local, user, date):
188 '''tag a revision with a symbolic name.
198 '''tag a revision with one or more symbolic names.
189
199
190 if local is True, the tag is stored in a per-repository file.
200 names is a list of strings or, when adding a single tag, names may be a
191 otherwise, it is stored in the .hgtags file, and a new
201 string.
202
203 if local is True, the tags are stored in a per-repository file.
204 otherwise, they are stored in the .hgtags file, and a new
192 changeset is committed with the change.
205 changeset is committed with the change.
193
206
194 keyword arguments:
207 keyword arguments:
195
208
196 local: whether to store tag in non-version-controlled file
209 local: whether to store tags in non-version-controlled file
197 (default False)
210 (default False)
198
211
199 message: commit message to use if committing
212 message: commit message to use if committing
@@ -207,7 +220,7 b' class localrepository(repo.repository):'
207 raise util.Abort(_('working copy of .hgtags is changed '
220 raise util.Abort(_('working copy of .hgtags is changed '
208 '(please commit .hgtags manually)'))
221 '(please commit .hgtags manually)'))
209
222
210 self._tag(name, node, message, local, user, date)
223 self._tag(names, node, message, local, user, date)
211
224
212 def tags(self):
225 def tags(self):
213 '''return a mapping of tag to node'''
226 '''return a mapping of tag to node'''
@@ -188,7 +188,7 b' list of commands:'
188 serve export the repository via HTTP
188 serve export the repository via HTTP
189 showconfig show combined config settings from all hgrc files
189 showconfig show combined config settings from all hgrc files
190 status show changed files in the working directory
190 status show changed files in the working directory
191 tag add a tag for the current or given revision
191 tag add one or more tags for the current or given revision
192 tags list repository tags
192 tags list repository tags
193 tip show the tip revision
193 tip show the tip revision
194 unbundle apply one or more changegroup files
194 unbundle apply one or more changegroup files
@@ -241,7 +241,7 b' list of commands:'
241 serve export the repository via HTTP
241 serve export the repository via HTTP
242 showconfig show combined config settings from all hgrc files
242 showconfig show combined config settings from all hgrc files
243 status show changed files in the working directory
243 status show changed files in the working directory
244 tag add a tag for the current or given revision
244 tag add one or more tags for the current or given revision
245 tags list repository tags
245 tags list repository tags
246 tip show the tip revision
246 tip show the tip revision
247 unbundle apply one or more changegroup files
247 unbundle apply one or more changegroup files
@@ -80,7 +80,7 b' list of commands:'
80 serve export the repository via HTTP
80 serve export the repository via HTTP
81 showconfig show combined config settings from all hgrc files
81 showconfig show combined config settings from all hgrc files
82 status show changed files in the working directory
82 status show changed files in the working directory
83 tag add a tag for the current or given revision
83 tag add one or more tags for the current or given revision
84 tags list repository tags
84 tags list repository tags
85 tip show the tip revision
85 tip show the tip revision
86 unbundle apply one or more changegroup files
86 unbundle apply one or more changegroup files
@@ -129,7 +129,7 b' use "hg -v help" to show aliases and glo'
129 serve export the repository via HTTP
129 serve export the repository via HTTP
130 showconfig show combined config settings from all hgrc files
130 showconfig show combined config settings from all hgrc files
131 status show changed files in the working directory
131 status show changed files in the working directory
132 tag add a tag for the current or given revision
132 tag add one or more tags for the current or given revision
133 tags list repository tags
133 tags list repository tags
134 tip show the tip revision
134 tip show the tip revision
135 unbundle apply one or more changegroup files
135 unbundle apply one or more changegroup files
@@ -10,11 +10,21 b' hg history'
10
10
11 echo foo >> .hgtags
11 echo foo >> .hgtags
12 hg tag -d "1000000 0" "bleah2" || echo "failed"
12 hg tag -d "1000000 0" "bleah2" || echo "failed"
13 hg tag -d "1000000 0" -r 0 "bleah2" 1 || echo "failed"
14
13
15 hg revert .hgtags
14 hg revert .hgtags
15 hg tag -d "1000000 0" -r 0 x y z y y z || echo "failed"
16 hg tag -d "1000000 0" tap nada dot tip null . || echo "failed"
17 hg tag -d "1000000 0" "bleah" || echo "failed"
18 hg tag -d "1000000 0" "blecch" "bleah" || echo "failed"
19
20 hg tag -d "1000000 0" --remove "blecch" || echo "failed"
21 hg tag -d "1000000 0" --remove "bleah" "blecch" "blough" || echo "failed"
22
16 hg tag -d "1000000 0" -r 0 "bleah0"
23 hg tag -d "1000000 0" -r 0 "bleah0"
17 hg tag -l -d "1000000 0" "bleah1" 1
24 hg tag -l -d "1000000 0" -r 1 "bleah1"
25 hg tag -d "1000000 0" gack gawk gorp
26 hg tag -d "1000000 0" -f gack
27 hg tag -d "1000000 0" --remove gack gorp
18
28
19 cat .hgtags
29 cat .hgtags
20 cat .hg/localtags
30 cat .hg/localtags
@@ -18,12 +18,26 b' summary: test'
18
18
19 abort: working copy of .hgtags is changed (please commit .hgtags manually)
19 abort: working copy of .hgtags is changed (please commit .hgtags manually)
20 failed
20 failed
21 use of 'hg tag NAME [REV]' is deprecated, please use 'hg tag [-r REV] NAME' instead
21 abort: tag names must be unique
22 abort: use only one form to specify the revision
22 failed
23 abort: the name 'tip' is reserved
24 failed
25 abort: tag 'bleah' already exists (use -f to force)
23 failed
26 failed
24 use of 'hg tag NAME [REV]' is deprecated, please use 'hg tag [-r REV] NAME' instead
27 abort: tag 'bleah' already exists (use -f to force)
28 failed
29 abort: tag 'blecch' does not exist
30 failed
31 abort: tag 'blecch' does not exist
32 failed
25 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 bleah
33 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 bleah
26 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 bleah0
34 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 bleah0
35 868cc8fbb43b754ad09fa109885d243fc49adae7 gack
36 868cc8fbb43b754ad09fa109885d243fc49adae7 gawk
37 868cc8fbb43b754ad09fa109885d243fc49adae7 gorp
38 3807bcf62c5614cb6c16436b514d7764ca5f1631 gack
39 0000000000000000000000000000000000000000 gack
40 0000000000000000000000000000000000000000 gorp
27 3ecf002a1c572a2f3bb4e665417e60fca65bbd42 bleah1
41 3ecf002a1c572a2f3bb4e665417e60fca65bbd42 bleah1
28 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
42 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
29 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 foobar
43 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 foobar
@@ -50,7 +50,7 b' summary: Removed tag bar'
50
50
51 tip 5:57e1983b4a60
51 tip 5:57e1983b4a60
52 % remove nonexistent tag
52 % remove nonexistent tag
53 abort: tag foobar does not exist
53 abort: tag 'foobar' does not exist
54 changeset: 5:57e1983b4a60
54 changeset: 5:57e1983b4a60
55 tag: tip
55 tag: tip
56 user: test
56 user: test
@@ -62,7 +62,7 b' bar 0:b40'
62 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
62 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
63 tip 6:b5ff9d142648
63 tip 6:b5ff9d142648
64 bar 0:b409d9da318e
64 bar 0:b409d9da318e
65 abort: a tag named bar already exists (use -f to force)
65 abort: tag 'bar' already exists (use -f to force)
66 tip 6:b5ff9d142648
66 tip 6:b5ff9d142648
67 bar 0:b409d9da318e
67 bar 0:b409d9da318e
68 adding foo
68 adding foo
@@ -72,8 +72,8 b' bar 2:72b'
72 tip 4:40af5d225513
72 tip 4:40af5d225513
73 bar 2:72b852876a42
73 bar 2:72b852876a42
74 adding foo
74 adding foo
75 abort: localtag tag is local
75 abort: tag 'localtag' is not a global tag
76 abort: globaltag tag is global
76 abort: tag 'globaltag' is not a local tag
77 tip 1:a0b6fe111088
77 tip 1:a0b6fe111088
78 localtag 0:bbd179dfa0a7 local
78 localtag 0:bbd179dfa0a7 local
79 globaltag 0:bbd179dfa0a7
79 globaltag 0:bbd179dfa0a7
General Comments 0
You need to be logged in to leave comments. Login now