##// END OF EJS Templates
bookmarks: merge _findtags method into core
bookmarks: merge _findtags method into core

File last commit:

r13360:bab5490e default
r13360:bab5490e default
Show More
bookmarks.py
360 lines | 13.5 KiB | text/x-python | PythonLexer
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 # Mercurial extension to provide the 'hg bookmark' command
#
# Copyright 2008 David Soria Parra <dsp@php.net>
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Joel Rosdahl
bookmarks: Avoid long lines
r7252
Cédric Duval
extensions: improve the consistency of synopses...
r8894 '''track a line of development with movable markers
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239
Martin Geisler
bookmarks: wrap docstrings at 70 characters
r9251 Bookmarks are local movable markers to changesets. Every bookmark
points to a changeset identified by its hash. If you commit a
changeset that is based on a changeset that has a bookmark on it, the
bookmark shifts to the new changeset.
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239
Martin Geisler
Use our custom hg reStructuredText role some more...
r11193 It is possible to use bookmark names in every revision lookup (e.g.
:hg:`merge`, :hg:`update`).
David Soria Parra
bookmarks: more git-like branches...
r7481
Martin Geisler
bookmarks: wrap docstrings at 70 characters
r9251 By default, when several bookmarks point to the same changeset, they
will all move forward together. It is possible to obtain a more
git-like experience by adding the following configuration option to
Brodie Rao
help: refer to user configuration file more consistently...
r12083 your configuration file::
David Soria Parra
bookmarks: more git-like branches...
r7481
Cédric Duval
bookmarks: help improvements...
r8892 [bookmarks]
track.current = True
David Soria Parra
bookmarks: more git-like branches...
r7481
Martin Geisler
bookmarks: wrap docstrings at 70 characters
r9251 This will cause Mercurial to track the bookmark that you are currently
using, and only update it. This is similar to git's approach to
branching.
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 '''
Joel Rosdahl
bookmarks: Avoid long lines
r7252
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 from mercurial.i18n import _
Augie Fackler
bookmarks: add revset for referencing bookmarks
r12714 from mercurial.node import nullid, nullrev, bin, hex, short
David Soria Parra
bookmarks: Add -B option to incoming/outgoing to compare bookmarks...
r11431 from mercurial import util, commands, repair, extensions, pushkey, hg, url
Matt Mackall
bookmarks: move revset support to core
r13359 from mercurial import encoding
Matt Mackall
bookmarks: move basic io to core
r13350 from mercurial import bookmarks
Matt Mackall
bookmarks; clean up imports and function wrapping
r7638 import os
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239
Joel Rosdahl
bookmarks: Rename --move to --rename...
r7255 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False, rename=None):
Cédric Duval
extensions: improve the consistency of synopses...
r8894 '''track a line of development with movable markers
Joel Rosdahl
bookmarks: Remove trailing space
r7250
Martin Geisler
bookmarks: wrap docstrings at 70 characters
r9251 Bookmarks are pointers to certain commits that move when
committing. Bookmarks are local. They can be renamed, copied and
Martin Geisler
Use hg role in help strings
r10973 deleted. It is possible to use bookmark names in :hg:`merge` and
:hg:`update` to merge and update respectively to a given bookmark.
Joel Rosdahl
bookmarks: Remove trailing space
r7250
Martin Geisler
Use hg role in help strings
r10973 You can use :hg:`bookmark NAME` to set a bookmark on the working
Martin Geisler
bookmarks: wrap docstrings at 70 characters
r9251 directory's parent revision with the given name. If you specify
a revision using -r REV (where REV may be an existing bookmark),
the bookmark is assigned to that revision.
Kevin Bullock
bookmarks: add paragraph on pushing and pulling to help...
r12772
Bookmarks can be pushed and pulled between repositories (see :hg:`help
push` and :hg:`help pull`). This requires the bookmark extension to be
enabled for both the local and remote repositories.
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 '''
hexfn = ui.debugflag and hex or short
Nicolas Dumazet
bookmarks: turn repo._bookmarks into a propertycache
r10105 marks = repo._bookmarks
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 cur = repo.changectx('.').node()
Joel Rosdahl
bookmarks: Rename --move to --rename...
r7255 if rename:
if rename not in marks:
Joel Rosdahl
bookmarks: Fix spelling and grammar
r7251 raise util.Abort(_("a bookmark of this name does not exist"))
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 if mark in marks and not force:
raise util.Abort(_("a bookmark of the same name already exists"))
Joel Rosdahl
bookmarks: Require new bookmark name when renaming
r7254 if mark is None:
raise util.Abort(_("new bookmark name required"))
Joel Rosdahl
bookmarks: Rename --move to --rename...
r7255 marks[mark] = marks[rename]
del marks[rename]
Nicolas Dumazet
bookmarks: repo._bookmarkcurrent should be a propertycache
r10107 if repo._bookmarkcurrent == rename:
Matt Mackall
bookmarks: move basic io to core
r13350 bookmarks.setcurrent(repo, mark)
bookmarks.write(repo)
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 return
Joel Rosdahl
bookmarks: Remove trailing space
r7250
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 if delete:
Martin Geisler
use 'x is None' instead of 'x == None'...
r8527 if mark is None:
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 raise util.Abort(_("bookmark name required"))
if mark not in marks:
Joel Rosdahl
bookmarks: Fix spelling and grammar
r7251 raise util.Abort(_("a bookmark of this name does not exist"))
Nicolas Dumazet
bookmarks: repo._bookmarkcurrent should be a propertycache
r10107 if mark == repo._bookmarkcurrent:
Matt Mackall
bookmarks: move basic io to core
r13350 bookmarks.setcurrent(repo, None)
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 del marks[mark]
Matt Mackall
bookmarks: move basic io to core
r13350 bookmarks.write(repo)
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 return
Martin Geisler
code style: prefer 'is' and 'is not' tests with singletons
r13031 if mark is not None:
Joel Rosdahl
bookmarks: Correctly reject newlines in bookmark names...
r7259 if "\n" in mark:
raise util.Abort(_("bookmark name cannot contain newlines"))
Joel Rosdahl
bookmarks: Strip bookmark names of whitespace, just like tag names
r7260 mark = mark.strip()
Idan Kamara
bookmarks: don't allow name to contain whitespaces only
r11704 if not mark:
raise util.Abort(_("bookmark names cannot consist entirely of "
"whitespace"))
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 if mark in marks and not force:
raise util.Abort(_("a bookmark of the same name already exists"))
Joel Rosdahl
bookmarks: Remove trailing space
r7250 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 and not force):
Joel Rosdahl
bookmarks: Avoid long lines
r7252 raise util.Abort(
_("a bookmark cannot have the name of an existing branch"))
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 if rev:
marks[mark] = repo.lookup(rev)
else:
marks[mark] = repo.changectx('.').node()
Matt Mackall
bookmarks: move basic io to core
r13350 bookmarks.setcurrent(repo, mark)
bookmarks.write(repo)
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 return
Martin Geisler
use 'x is None' instead of 'x == None'...
r8527 if mark is None:
Joel Rosdahl
bookmarks: Require a bookmark name when a revision is specified
r7258 if rev:
raise util.Abort(_("bookmark name required"))
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 if len(marks) == 0:
Benoit Boissinot
i18n: mark more strings for translation
r10510 ui.status(_("no bookmarks set\n"))
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 else:
for bmark, n in marks.iteritems():
David Soria Parra
bookmarks: more git-like branches...
r7481 if ui.configbool('bookmarks', 'track.current'):
Nicolas Dumazet
bookmarks: repo._bookmarkcurrent should be a propertycache
r10107 current = repo._bookmarkcurrent
Brodie Rao
bookmark: make use of output labeling
r10820 if bmark == current and n == cur:
prefix, label = '*', 'bookmarks.current'
else:
prefix, label = ' ', ''
David Soria Parra
bookmarks: more git-like branches...
r7481 else:
Brodie Rao
bookmark: make use of output labeling
r10820 if n == cur:
prefix, label = '*', 'bookmarks.current'
else:
prefix, label = ' ', ''
David Soria Parra
bookmarks: more git-like branches...
r7481
Steve Losh
bookmarks: support --quiet
r9459 if ui.quiet:
Brodie Rao
bookmark: make use of output labeling
r10820 ui.write("%s\n" % bmark, label=label)
Steve Losh
bookmarks: support --quiet
r9459 else:
ui.write(" %s %-25s %d:%s\n" % (
Brodie Rao
bookmark: make use of output labeling
r10820 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
label=label)
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 return
def _revstostrip(changelog, node):
srev = changelog.rev(node)
tostrip = [srev]
saveheads = []
Benoit Boissinot
bookmarks: fix strip handling
r7283 for r in xrange(srev, len(changelog)):
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 parents = changelog.parentrevs(r)
if parents[0] in tostrip or parents[1] in tostrip:
tostrip.append(r)
if parents[1] != nullrev:
for p in parents:
Benoit Boissinot
bookmarks: fix strip handling
r7283 if p not in tostrip and p > srev:
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 saveheads.append(p)
return [r for r in tostrip if r not in saveheads]
Matt Mackall
bookmarks; clean up imports and function wrapping
r7638 def strip(oldstrip, ui, repo, node, backup="all"):
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 """Strip bookmarks if revisions are stripped using
the mercurial.strip method. This usually happens during
qpush and qpop"""
revisions = _revstostrip(repo.changelog, node)
Nicolas Dumazet
bookmarks: turn repo._bookmarks into a propertycache
r10105 marks = repo._bookmarks
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 update = []
Dirkjan Ochtman
use dict.iteritems() rather than dict.items()...
r7622 for mark, n in marks.iteritems():
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 if repo.changelog.rev(n) in revisions:
update.append(mark)
Benoit Boissinot
remove unused variables
r7280 oldstrip(ui, repo, node, backup)
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 if len(update) > 0:
for m in update:
marks[m] = repo.changectx('.').node()
Matt Mackall
bookmarks: move basic io to core
r13350 bookmarks.write(repo)
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239
def reposetup(ui, repo):
Alexander Solovyov
bookmarks: use API to determine if repo is local
r9643 if not repo.local():
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 return
class bookmark_repo(repo.__class__):
def lookup(self, key):
Paul Molodowitch
bookmarks: better fix for issue2016 (lookup infinite recursion)...
r12747 if key in self._bookmarks:
key = self._bookmarks[key]
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 return super(bookmark_repo, self).lookup(key)
Matt Mackall
bookmarks: pull known bookmarks from server that are newer
r11373 def pull(self, remote, heads=None, force=False):
result = super(bookmark_repo, self).pull(remote, heads, force)
self.ui.debug("checking for updated bookmarks\n")
rb = remote.listkeys('bookmarks')
Martin Geisler
bookmarks: replace var used as a Boolean with a Boolean
r11774 changed = False
Matt Mackall
bookmarks: pull known bookmarks from server that are newer
r11373 for k in rb.keys():
if k in self._bookmarks:
nr, nl = rb[k], self._bookmarks[k]
if nr in self:
cr = self[nr]
cl = self[nl]
if cl.rev() >= cr.rev():
continue
if cr in cl.descendants():
self._bookmarks[k] = cr.node()
Martin Geisler
bookmarks: replace var used as a Boolean with a Boolean
r11774 changed = True
Matt Mackall
bookmarks: pull known bookmarks from server that are newer
r11373 self.ui.status(_("updating bookmark %s\n") % k)
else:
self.ui.warn(_("not updating divergent"
" bookmark %s\n") % k)
Martin Geisler
bookmarks: replace var used as a Boolean with a Boolean
r11774 if changed:
Matt Mackall
bookmarks: move basic io to core
r13350 bookmarks.write(repo)
Matt Mackall
bookmarks: pull known bookmarks from server that are newer
r11373
return result
Matt Mackall
bookmarks: update known bookmarks on the target on push
r11374 def push(self, remote, force=False, revs=None, newbranch=False):
result = super(bookmark_repo, self).push(remote, force, revs,
newbranch)
self.ui.debug("checking for updated bookmarks\n")
rb = remote.listkeys('bookmarks')
for k in rb.keys():
if k in self._bookmarks:
Matt Mackall
pushkey: use UTF-8
r13050 nr, nl = rb[k], hex(self._bookmarks[k])
Matt Mackall
bookmarks: update known bookmarks on the target on push
r11374 if nr in self:
cr = self[nr]
cl = self[nl]
if cl in cr.descendants():
r = remote.pushkey('bookmarks', k, nr, nl)
if r:
self.ui.status(_("updating bookmark %s\n") % k)
else:
David Soria Parra
bookmarks: Use error message consistently...
r11434 self.ui.warn(_('updating bookmark %s'
' failed!\n') % k)
Matt Mackall
bookmarks: update known bookmarks on the target on push
r11374
return result
Matt Mackall
addchangegroup: pass in lock to release it before changegroup hook is called...
r11442 def addchangegroup(self, *args, **kwargs):
result = super(bookmark_repo, self).addchangegroup(*args, **kwargs)
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 if result > 1:
# We have more heads than before
return result
Isaac Jurado
bookmarks: Change references to "repo" by references to "self" (issue1611)...
r8944 node = self.changelog.tip()
Matt Mackall
dirstate: warn on invalid parents rather than aborting...
r13032 parents = self.dirstate.parents()
Matt Mackall
bookmarks: move update into core
r13352 bookmarks.update(self, parents, node)
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 return result
repo.__class__ = bookmark_repo
Matt Mackall
bookmarks: add support for pull --bookmark to import remote bookmarks
r11378 def pull(oldpull, ui, repo, source="default", **opts):
# translate bookmark args to rev args for actual pull
if opts.get('bookmark'):
# this is an unpleasant hack as pull will do this internally
source, branches = hg.parseurl(ui.expandpath(source),
opts.get('branch'))
other = hg.repository(hg.remoteui(repo, opts), source)
rb = other.listkeys('bookmarks')
for b in opts['bookmark']:
if b not in rb:
raise util.Abort(_('remote bookmark %s not found!') % b)
opts.setdefault('rev', []).append(b)
result = oldpull(ui, repo, source, **opts)
# update specified bookmarks
if opts.get('bookmark'):
for b in opts['bookmark']:
# explicit pull overrides local bookmark if any
ui.status(_("importing bookmark %s\n") % b)
repo._bookmarks[b] = repo[rb[b]].node()
Matt Mackall
bookmarks: move basic io to core
r13350 bookmarks.write(repo)
Matt Mackall
bookmarks: add support for pull --bookmark to import remote bookmarks
r11378
return result
Matt Mackall
bookmarks: add support for push --bookmark to export bookmarks
r11379 def push(oldpush, ui, repo, dest=None, **opts):
dopush = True
if opts.get('bookmark'):
dopush = False
for b in opts['bookmark']:
if b in repo._bookmarks:
dopush = True
opts.setdefault('rev', []).append(b)
result = 0
if dopush:
result = oldpush(ui, repo, dest, **opts)
if opts.get('bookmark'):
# this is an unpleasant hack as push will do this internally
dest = ui.expandpath(dest or 'default-push', dest or 'default')
dest, branches = hg.parseurl(dest, opts.get('branch'))
other = hg.repository(hg.remoteui(repo, opts), dest)
rb = other.listkeys('bookmarks')
for b in opts['bookmark']:
# explicit push overrides remote bookmark if any
if b in repo._bookmarks:
ui.status(_("exporting bookmark %s\n") % b)
new = repo[b].hex()
David Soria Parra
bookmarks: Check if the bookmark to delete exists on the remote
r11994 elif b in rb:
Matt Mackall
bookmarks: add support for push --bookmark to export bookmarks
r11379 ui.status(_("deleting remote bookmark %s\n") % b)
new = '' # delete
David Soria Parra
bookmarks: Check if the bookmark to delete exists on the remote
r11994 else:
Martin Geisler
bookmarks: break long line found by check-code
r12146 ui.warn(_('bookmark %s does not exist on the local '
'or remote repository!\n') % b)
David Soria Parra
bookmarks: Check if the bookmark to delete exists on the remote
r11994 return 2
Matt Mackall
bookmarks: add support for push --bookmark to export bookmarks
r11379 old = rb.get(b, '')
r = other.pushkey('bookmarks', b, old, new)
if not r:
ui.warn(_('updating bookmark %s failed!\n') % b)
if not result:
result = 2
return result
David Soria Parra
bookmarks: Add -B option to incoming/outgoing to compare bookmarks...
r11431 def incoming(oldincoming, ui, repo, source="default", **opts):
if opts.get('bookmarks'):
source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
other = hg.repository(hg.remoteui(repo, opts), source)
ui.status(_('comparing with %s\n') % url.hidepassword(source))
Matt Mackall
bookmarks: move diff to core
r13354 return bookmarks.diff(ui, repo, other)
David Soria Parra
bookmarks: Add -B option to incoming/outgoing to compare bookmarks...
r11431 else:
Matt Mackall
bookmarks: fix in/out return values
r11444 return oldincoming(ui, repo, source, **opts)
David Soria Parra
bookmarks: Add -B option to incoming/outgoing to compare bookmarks...
r11431
Matt Mackall
bookmarks: fix bogus cut and paste for outgoing
r11443 def outgoing(oldoutgoing, ui, repo, dest=None, **opts):
David Soria Parra
bookmarks: Add -B option to incoming/outgoing to compare bookmarks...
r11431 if opts.get('bookmarks'):
Matt Mackall
bookmarks: fix bogus cut and paste for outgoing
r11443 dest = ui.expandpath(dest or 'default-push', dest or 'default')
dest, branches = hg.parseurl(dest, opts.get('branch'))
other = hg.repository(hg.remoteui(repo, opts), dest)
ui.status(_('comparing with %s\n') % url.hidepassword(dest))
Matt Mackall
bookmarks: move diff to core
r13354 return bookmarks.diff(ui, other, repo)
David Soria Parra
bookmarks: Add -B option to incoming/outgoing to compare bookmarks...
r11431 else:
Matt Mackall
bookmarks: fix in/out return values
r11444 return oldoutgoing(ui, repo, dest, **opts)
David Soria Parra
bookmarks: Add -B option to incoming/outgoing to compare bookmarks...
r11431
Matt Mackall
bookmarks; clean up imports and function wrapping
r7638 def uisetup(ui):
extensions.wrapfunction(repair, "strip", strip)
if ui.configbool('bookmarks', 'track.current'):
extensions.wrapcommand(commands.table, 'update', updatecurbookmark)
Matt Mackall
bookmarks: add support for pull --bookmark to import remote bookmarks
r11378
entry = extensions.wrapcommand(commands.table, 'pull', pull)
entry[1].append(('B', 'bookmark', [],
Will Maier
bookmarks: set VALUE in push/pull
r12302 _("bookmark to import"),
_('BOOKMARK')))
Matt Mackall
bookmarks: add support for push --bookmark to export bookmarks
r11379 entry = extensions.wrapcommand(commands.table, 'push', push)
entry[1].append(('B', 'bookmark', [],
Will Maier
bookmarks: set VALUE in push/pull
r12302 _("bookmark to export"),
_('BOOKMARK')))
David Soria Parra
bookmarks: Add -B option to incoming/outgoing to compare bookmarks...
r11431 entry = extensions.wrapcommand(commands.table, 'incoming', incoming)
entry[1].append(('B', 'bookmarks', False,
_("compare bookmark")))
entry = extensions.wrapcommand(commands.table, 'outgoing', outgoing)
entry[1].append(('B', 'bookmarks', False,
_("compare bookmark")))
Matt Mackall
bookmarks: add support for pull --bookmark to import remote bookmarks
r11378
David Soria Parra
bookmarks: more git-like branches...
r7481 def updatecurbookmark(orig, ui, repo, *args, **opts):
'''Set the current bookmark
If the user updates to a bookmark we update the .hg/bookmarks.current
file.
'''
res = orig(ui, repo, *args, **opts)
rev = opts['rev']
if not rev and len(args) > 0:
rev = args[0]
Matt Mackall
bookmarks: move basic io to core
r13350 bookmarks.setcurrent(repo, rev)
David Soria Parra
bookmarks: more git-like branches...
r7481 return res
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 cmdtable = {
"bookmarks":
(bookmark,
[('f', 'force', False, _('force')),
FUJIWARA Katsunori
help: show value requirement and multiple occurrence of options...
r11321 ('r', 'rev', '', _('revision'), _('REV')),
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 ('d', 'delete', False, _('delete a given bookmark')),
FUJIWARA Katsunori
help: show value requirement and multiple occurrence of options...
r11321 ('m', 'rename', '', _('rename a given bookmark'), _('NAME'))],
Benoit Allard
bookmarks: change NAME to REV
r7818 _('hg bookmarks [-f] [-d] [-m NAME] [-r REV] [NAME]')),
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 }
Brodie Rao
color: colorize based on output labels instead of parsing output...
r10826
colortable = {'bookmarks.current': 'green'}