diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -2653,35 +2653,8 @@ def tag(ui, repo, name, rev_=None, **opt else: r = hex(repo.changelog.tip()) - disallowed = (revrangesep, '\r', '\n') - for c in disallowed: - if c in name: - raise util.Abort(_("%s cannot be used in a tag name") % repr(c)) - - repo.hook('pretag', throw=True, node=r, tag=name, - local=int(not not opts['local'])) - - if opts['local']: - repo.opener("localtags", "a").write("%s %s\n" % (r, name)) - repo.hook('tag', node=r, tag=name, local=1) - return - - for x in repo.changes(): - if ".hgtags" in x: - raise util.Abort(_("working copy of .hgtags is changed " - "(please commit .hgtags manually)")) - - repo.wfile(".hgtags", "ab").write("%s %s\n" % (r, name)) - if repo.dirstate.state(".hgtags") == '?': - repo.add([".hgtags"]) - - message = (opts['message'] or - _("Added tag %s for changeset %s") % (name, r)) - try: - repo.commit([".hgtags"], message, opts['user'], opts['date']) - repo.hook('tag', node=r, tag=name, local=0) - except ValueError, inst: - raise util.Abort(str(inst)) + repo.tag(name, r, opts['local'], opts['message'], opts['user'], + opts['date']) def tags(ui, repo): """list repository tags diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -162,6 +162,52 @@ class localrepository(object): r = runhook(hname, cmd) or r return r + tag_disallowed = ':\r\n' + + def tag(self, name, node, local=False, message=None, user=None, date=None): + '''tag a revision with a symbolic name. + + if local is True, the tag is stored in a per-repository file. + otherwise, it is stored in the .hgtags file, and a new + changeset is committed with the change. + + keyword arguments: + + local: whether to store tag in non-version-controlled file + (default False) + + message: commit message to use if committing + + user: name of user to use if committing + + date: date tuple to use if committing''' + + for c in self.tag_disallowed: + if c in name: + raise util.Abort(_('%r cannot be used in a tag name') % c) + + self.hook('pretag', throw=True, node=node, tag=name, local=local) + + if local: + self.opener('localtags', 'a').write('%s %s\n' % (node, name)) + self.hook('tag', node=node, tag=name, local=local) + return + + for x in self.changes(): + if '.hgtags' in x: + raise util.Abort(_('working copy of .hgtags is changed ' + '(please commit .hgtags manually)')) + + self.wfile('.hgtags', 'ab').write('%s %s\n' % (node, name)) + if self.dirstate.state('.hgtags') == '?': + self.add(['.hgtags']) + + if not message: + message = _('Added tag %s for changeset %s') % (name, node) + + self.commit(['.hgtags'], message, user, date) + self.hook('tag', node=node, tag=name, local=local) + def tags(self): '''return a mapping of tag to node''' if not self.tagscache: diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -378,6 +378,13 @@ def system(cmd, environ={}, cwd=None, on if command fails and onerr is None, return status. if ui object, print error message and return status, else raise onerr object as exception.''' + def py2shell(val): + 'convert python object into string that is useful to shell' + if val in (None, False): + return '0' + if val == True: + return '1' + return str(val) oldenv = {} for k in environ: oldenv[k] = os.environ.get(k) @@ -385,7 +392,7 @@ def system(cmd, environ={}, cwd=None, on oldcwd = os.getcwd() try: for k, v in environ.iteritems(): - os.environ[k] = str(v) + os.environ[k] = py2shell(v) if cwd is not None and oldcwd != cwd: os.chdir(cwd) rc = os.system(cmd)