##// 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 2589 if f in copy and (f in added or f in showcopy):
2590 2590 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end))
2591 2591
2592 def tag(ui, repo, name, rev_=None, **opts):
2593 """add a tag for the current or given revision
2592 def tag(ui, repo, name1, *names, **opts):
2593 """add one or more tags for the current or given revision
2594 2594
2595 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 2610 See 'hg help dates' for a list of formats valid for -d/--date.
2611 2611 """
2612 if name in ['tip', '.', 'null']:
2613 raise util.Abort(_("the name '%s' is reserved") % name)
2614 if rev_ is not None:
2615 ui.warn(_("use of 'hg tag NAME [REV]' is deprecated, "
2616 "please use 'hg tag [-r REV] NAME' instead\n"))
2617 if opts['rev']:
2618 raise util.Abort(_("use only one form to specify the revision"))
2612
2613 rev_ = None
2614 names = (name1,) + names
2615 if len(names) != len(dict.fromkeys(names)):
2616 raise util.Abort(_('tag names must be unique'))
2617 for n in names:
2618 if n in ['tip', '.', 'null']:
2619 raise util.Abort(_('the name \'%s\' is reserved') % n)
2619 2620 if opts['rev'] and opts['remove']:
2620 2621 raise util.Abort(_("--rev and --remove are incompatible"))
2621 2622 if opts['rev']:
2622 2623 rev_ = opts['rev']
2623 2624 message = opts['message']
2624 2625 if opts['remove']:
2625 tagtype = repo.tagtype(name)
2626
2627 if not tagtype:
2628 raise util.Abort(_('tag %s does not exist') % name)
2629 if opts['local'] and tagtype == 'global':
2630 raise util.Abort(_('%s tag is global') % name)
2631 if not opts['local'] and tagtype == 'local':
2632 raise util.Abort(_('%s tag is local') % name)
2633
2626 expectedtype = opts['local'] and 'local' or 'global'
2627 for n in names:
2628 if not repo.tagtype(n):
2629 raise util.Abort(_('tag \'%s\' does not exist') % n)
2630 if repo.tagtype(n) != expectedtype:
2631 raise util.Abort(_('tag \'%s\' is not a %s tag') %
2632 (n, expectedtype))
2634 2633 rev_ = nullid
2635 2634 if not message:
2636 message = _('Removed tag %s') % name
2637 elif name in repo.tags() and not opts['force']:
2638 raise util.Abort(_('a tag named %s already exists (use -f to force)')
2639 % name)
2635 message = _('Removed tag %s') % ', '.join(names)
2636 elif not opts['force']:
2637 for n in names:
2638 if n in repo.tags():
2639 raise util.Abort(_('tag \'%s\' already exists '
2640 '(use -f to force)') % n)
2640 2641 if not rev_ and repo.dirstate.parents()[1] != nullid:
2641 2642 raise util.Abort(_('uncommitted merge - please provide a '
2642 2643 'specific revision'))
2643 2644 r = repo.changectx(rev_).node()
2644 2645
2645 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 2650 date = opts.get('date')
2649 2651 if date:
2650 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 2656 def tags(ui, repo):
2655 2657 """list repository tags
@@ -3190,7 +3192,7 b' table = {'
3190 3192 # -l/--local is already there, commitopts cannot be used
3191 3193 ('m', 'message', '', _('use <text> as commit message')),
3192 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 3196 "tags": (tags, [], _('hg tags')),
3195 3197 "tip":
3196 3198 (tip,
@@ -124,21 +124,29 b' class localrepository(repo.repository):'
124 124
125 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 128 extra={}):
129 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 136 for c in self.tag_disallowed:
132 if c in name:
137 if c in allchars:
133 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 145 fp.seek(0, 2)
139 146 if prevtags and prevtags[-1] != '\n':
140 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 150 fp.close()
143 151
144 152 prevtags = ''
@@ -151,8 +159,9 b' class localrepository(repo.repository):'
151 159 prevtags = fp.read()
152 160
153 161 # local tags are stored in the current charset
154 writetag(fp, name, None, prevtags)
155 self.hook('tag', node=hex(node), tag=name, local=local)
162 writetags(fp, names, None, prevtags)
163 for name in names:
164 self.hook('tag', node=hex(node), tag=name, local=local)
156 165 return
157 166
158 167 if use_dirstate:
@@ -172,7 +181,7 b' class localrepository(repo.repository):'
172 181 fp.write(prevtags)
173 182
174 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 186 if use_dirstate and '.hgtags' not in self.dirstate:
178 187 self.add(['.hgtags'])
@@ -180,20 +189,24 b' class localrepository(repo.repository):'
180 189 tagnode = self.commit(['.hgtags'], message, user, date, p1=parent,
181 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 195 return tagnode
186 196
187 def tag(self, name, node, message, local, user, date):
188 '''tag a revision with a symbolic name.
197 def tag(self, names, node, message, local, user, date):
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.
191 otherwise, it is stored in the .hgtags file, and a new
200 names is a list of strings or, when adding a single tag, names may be a
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 205 changeset is committed with the change.
193 206
194 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 210 (default False)
198 211
199 212 message: commit message to use if committing
@@ -207,7 +220,7 b' class localrepository(repo.repository):'
207 220 raise util.Abort(_('working copy of .hgtags is changed '
208 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 225 def tags(self):
213 226 '''return a mapping of tag to node'''
@@ -188,7 +188,7 b' list of commands:'
188 188 serve export the repository via HTTP
189 189 showconfig show combined config settings from all hgrc files
190 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 192 tags list repository tags
193 193 tip show the tip revision
194 194 unbundle apply one or more changegroup files
@@ -241,7 +241,7 b' list of commands:'
241 241 serve export the repository via HTTP
242 242 showconfig show combined config settings from all hgrc files
243 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 245 tags list repository tags
246 246 tip show the tip revision
247 247 unbundle apply one or more changegroup files
@@ -80,7 +80,7 b' list of commands:'
80 80 serve export the repository via HTTP
81 81 showconfig show combined config settings from all hgrc files
82 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 84 tags list repository tags
85 85 tip show the tip revision
86 86 unbundle apply one or more changegroup files
@@ -129,7 +129,7 b' use "hg -v help" to show aliases and glo'
129 129 serve export the repository via HTTP
130 130 showconfig show combined config settings from all hgrc files
131 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 133 tags list repository tags
134 134 tip show the tip revision
135 135 unbundle apply one or more changegroup files
@@ -10,11 +10,21 b' hg history'
10 10
11 11 echo foo >> .hgtags
12 12 hg tag -d "1000000 0" "bleah2" || echo "failed"
13 hg tag -d "1000000 0" -r 0 "bleah2" 1 || echo "failed"
14 13
15 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 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 29 cat .hgtags
20 30 cat .hg/localtags
@@ -18,12 +18,26 b' summary: test'
18 18
19 19 abort: working copy of .hgtags is changed (please commit .hgtags manually)
20 20 failed
21 use of 'hg tag NAME [REV]' is deprecated, please use 'hg tag [-r REV] NAME' instead
22 abort: use only one form to specify the revision
21 abort: tag names must be unique
22 failed
23 abort: the name 'tip' is reserved
24 failed
25 abort: tag 'bleah' already exists (use -f to force)
23 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 33 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 bleah
26 34 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 bleah0
35 868cc8fbb43b754ad09fa109885d243fc49adae7 gack
36 868cc8fbb43b754ad09fa109885d243fc49adae7 gawk
37 868cc8fbb43b754ad09fa109885d243fc49adae7 gorp
38 3807bcf62c5614cb6c16436b514d7764ca5f1631 gack
39 0000000000000000000000000000000000000000 gack
40 0000000000000000000000000000000000000000 gorp
27 41 3ecf002a1c572a2f3bb4e665417e60fca65bbd42 bleah1
28 42 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
29 43 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 foobar
@@ -50,7 +50,7 b' summary: Removed tag bar'
50 50
51 51 tip 5:57e1983b4a60
52 52 % remove nonexistent tag
53 abort: tag foobar does not exist
53 abort: tag 'foobar' does not exist
54 54 changeset: 5:57e1983b4a60
55 55 tag: tip
56 56 user: test
@@ -62,7 +62,7 b' bar 0:b40'
62 62 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
63 63 tip 6:b5ff9d142648
64 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 66 tip 6:b5ff9d142648
67 67 bar 0:b409d9da318e
68 68 adding foo
@@ -72,8 +72,8 b' bar 2:72b'
72 72 tip 4:40af5d225513
73 73 bar 2:72b852876a42
74 74 adding foo
75 abort: localtag tag is local
76 abort: globaltag tag is global
75 abort: tag 'localtag' is not a global tag
76 abort: tag 'globaltag' is not a local tag
77 77 tip 1:a0b6fe111088
78 78 localtag 0:bbd179dfa0a7 local
79 79 globaltag 0:bbd179dfa0a7
General Comments 0
You need to be logged in to leave comments. Login now