##// END OF EJS Templates
bookmarks: use reST syntax for literal block
bookmarks: use reST syntax for literal block

File last commit:

r9202:82de0bb0 default
r9202:82de0bb0 default
Show More
bookmarks.py
330 lines | 11.4 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
# GNU General Public License version 2, incorporated herein by reference.
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: wrapped docstrings at 78 characters
r9053 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
bookmarks: wrapped docstrings at 78 characters
r9053 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: wrapped docstrings at 78 characters
r9053 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
Martin Geisler
bookmarks: use reST syntax for literal block
r9202 adding the following configuration option to your .hgrc::
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: wrapped docstrings at 78 characters
r9053 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 _
Matt Mackall
bookmarks; clean up imports and function wrapping
r7638 from mercurial.node import nullid, nullrev, hex, short
from mercurial import util, commands, localrepo, repair, extensions
import os
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239
def parse(repo):
'''Parse .hg/bookmarks file and return a dictionary
Joel Rosdahl
bookmarks: Remove trailing space
r7250
Martin Geisler
bookmarks: escape literal backslashes in docstring
r7789 Bookmarks are stored as {HASH}\\s{NAME}\\n (localtags format) values
Joel Rosdahl
bookmarks: Avoid long lines
r7252 in the .hg/bookmarks file. They are read by the parse() method and
returned as a dictionary with name => hash values.
Joel Rosdahl
bookmarks: Remove trailing space
r7250
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 The parsed dictionary is cached until a write() operation is done.
'''
try:
if repo._bookmarks:
return repo._bookmarks
repo._bookmarks = {}
for line in repo.opener('bookmarks'):
sha, refspec = line.strip().split(' ', 1)
repo._bookmarks[refspec] = repo.lookup(sha)
except:
pass
return repo._bookmarks
def write(repo, refs):
'''Write bookmarks
Joel Rosdahl
bookmarks: Remove trailing space
r7250
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 Write the given bookmark => hash dictionary to the .hg/bookmarks file
in a format equal to those of localtags.
We also store a backup of the previous state in undo.bookmarks that
can be copied back on rollback.
'''
Joel Rosdahl
bookmarks: Only save undo.bookmarks if bookmarks exist...
r7253 if os.path.exists(repo.join('bookmarks')):
util.copyfile(repo.join('bookmarks'), repo.join('undo.bookmarks'))
David Soria Parra
bookmarks: more git-like branches...
r7481 if current(repo) not in refs:
setcurrent(repo, None)
Matt Mackall
bookmarks: add appropriate locking (issue1691)...
r8862 wlock = repo.wlock()
try:
file = repo.opener('bookmarks', 'w', atomictemp=True)
for refspec, node in refs.iteritems():
file.write("%s %s\n" % (hex(node), refspec))
file.rename()
finally:
wlock.release()
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239
David Soria Parra
bookmarks: more git-like branches...
r7481 def current(repo):
'''Get the current bookmark
If we use gittishsh branches we have a current bookmark that
we are on. This function returns the name of the bookmark. It
is stored in .hg/bookmarks.current
'''
if repo._bookmarkcurrent:
return repo._bookmarkcurrent
mark = None
if os.path.exists(repo.join('bookmarks.current')):
file = repo.opener('bookmarks.current')
Patrick Mezard
bookmarks: work around missing posixfile_nt.readline()
r7666 # No readline() in posixfile_nt, reading everything is cheap
mark = (file.readlines() or [''])[0]
David Soria Parra
bookmarks: more git-like branches...
r7481 if mark == '':
mark = None
file.close()
repo._bookmarkcurrent = mark
return mark
def setcurrent(repo, mark):
'''Set the name of the bookmark that we are currently on
Set the name of the bookmark that we are on (hg update <bookmark>).
Wagner Bruna
bookmarks: fix typo
r8087 The name is recorded in .hg/bookmarks.current
David Soria Parra
bookmarks: more git-like branches...
r7481 '''
David Soria Parra
bookmarks: do not overwrite bookmarks.current if not necessary...
r7484 if current(repo) == mark:
David Soria Parra
bookmarks: more git-like branches...
r7481 return
David Soria Parra
bookmarks: do not overwrite bookmarks.current if not necessary...
r7484
David Soria Parra
bookmarks: more git-like branches...
r7481 refs = parse(repo)
David Soria Parra
bookmarks: do not overwrite bookmarks.current if not necessary...
r7484
Benoit Boissinot
bookmarks: this is a comment, not a string
r7491 # do not update if we do update to a rev equal to the current bookmark
Alex Unden
bookmarks: fixes bug where a deleted bookmark may still be treated as current when track.current option is set
r7817 if (mark and mark not in refs and
David Soria Parra
bookmarks: do not overwrite bookmarks.current if not necessary...
r7484 current(repo) and refs[current(repo)] == repo.changectx('.').node()):
return
David Soria Parra
bookmarks: more git-like branches...
r7481 if mark not in refs:
mark = ''
Matt Mackall
bookmarks: add appropriate locking (issue1691)...
r8862 wlock = repo.wlock()
try:
file = repo.opener('bookmarks.current', 'w', atomictemp=True)
file.write(mark)
file.rename()
finally:
wlock.release()
David Soria Parra
bookmarks: more git-like branches...
r7481 repo._bookmarkcurrent = mark
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: wrapped docstrings at 78 characters
r9053 Bookmarks are pointers to certain commits that move when committing.
Bookmarks are local. They can be renamed, copied and 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
Abderrahim Kitouni
bookmarks: update docstring
r8725 You can use 'hg bookmark NAME' to set a bookmark on the working
Martin Geisler
bookmarks: wrapped docstrings at 78 characters
r9053 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.
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 '''
hexfn = ui.debugflag and hex or short
marks = parse(repo)
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]
David Soria Parra
bookmarks: set the current bookmark to the new name if we rename the current bookmark...
r7550 if current(repo) == rename:
setcurrent(repo, mark)
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 write(repo, marks)
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"))
Alex Unden
bookmarks: fixes bug where a deleted bookmark may still be treated as current when track.current option is set
r7817 if mark == current(repo):
setcurrent(repo, None)
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 del marks[mark]
write(repo, marks)
return
if mark != 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()
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()
David Soria Parra
bookmarks: Set current bookmark if we create a new one on the tip...
r7816 setcurrent(repo, mark)
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 write(repo, marks)
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:
ui.status("no bookmarks set\n")
else:
for bmark, n in marks.iteritems():
David Soria Parra
bookmarks: more git-like branches...
r7481 if ui.configbool('bookmarks', 'track.current'):
prefix = (bmark == current(repo) and n == cur) and '*' or ' '
else:
prefix = (n == cur) and '*' or ' '
Joel Rosdahl
bookmarks: Avoid long lines
r7252 ui.write(" %s %-25s %d:%s\n" % (
prefix, bmark, repo.changelog.rev(n), hexfn(n)))
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)
marks = parse(repo)
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()
write(repo, marks)
def reposetup(ui, repo):
Matt Mackall
bookmarks; clean up imports and function wrapping
r7638 if not isinstance(repo, localrepo.localrepository):
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 return
# init a bookmark cache as otherwise we would get a infinite reading
# in lookup()
repo._bookmarks = None
David Soria Parra
bookmarks: more git-like branches...
r7481 repo._bookmarkcurrent = None
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239
class bookmark_repo(repo.__class__):
def rollback(self):
if os.path.exists(self.join('undo.bookmarks')):
util.rename(self.join('undo.bookmarks'), self.join('bookmarks'))
Joel Rosdahl
bookmarks: Remove trailing space
r7250 return super(bookmark_repo, self).rollback()
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239
def lookup(self, key):
if self._bookmarks is None:
self._bookmarks = parse(self)
if key in self._bookmarks:
key = self._bookmarks[key]
return super(bookmark_repo, self).lookup(key)
def commit(self, *k, **kw):
"""Add a revision to the repository and
move the bookmark"""
Matt Mackall
bookmarks: add appropriate locking (issue1691)...
r8862 wlock = self.wlock() # do both commit and bookmark with lock held
try:
node = super(bookmark_repo, self).commit(*k, **kw)
if node is None:
return None
Isaac Jurado
bookmarks: Change references to "repo" by references to "self" (issue1611)...
r8944 parents = self.changelog.parents(node)
Matt Mackall
bookmarks: add appropriate locking (issue1691)...
r8862 if parents[1] == nullid:
parents = (parents[0],)
Isaac Jurado
bookmarks: Change references to "repo" by references to "self" (issue1611)...
r8944 marks = parse(self)
Matt Mackall
bookmarks: add appropriate locking (issue1691)...
r8862 update = False
for mark, n in marks.items():
if ui.configbool('bookmarks', 'track.current'):
Isaac Jurado
bookmarks: Change references to "repo" by references to "self" (issue1611)...
r8944 if mark == current(self) and n in parents:
Matt Mackall
bookmarks: add appropriate locking (issue1691)...
r8862 marks[mark] = node
update = True
else:
if n in parents:
marks[mark] = node
update = True
if update:
Isaac Jurado
bookmarks: Change references to "repo" by references to "self" (issue1611)...
r8944 write(self, marks)
Matt Mackall
bookmarks: add appropriate locking (issue1691)...
r8862 return node
finally:
wlock.release()
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239
def addchangegroup(self, source, srctype, url, emptyok=False):
Isaac Jurado
bookmarks: Change references to "repo" by references to "self" (issue1611)...
r8944 parents = self.dirstate.parents()
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239
Joel Rosdahl
bookmarks: Avoid long lines
r7252 result = super(bookmark_repo, self).addchangegroup(
source, srctype, url, emptyok)
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()
marks = parse(self)
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 update = False
for mark, n in marks.items():
David Soria Parra
bookmarks: Use dirstate to determine the current node in addchangegroup...
r7316 if n in parents:
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 marks[mark] = node
update = True
if update:
Isaac Jurado
bookmarks: Change references to "repo" by references to "self" (issue1611)...
r8944 write(self, marks)
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 return result
Greg Ward
localrepo: factor _findtags() out of tags() (issue548)....
r9145 def _findtags(self):
Martin Geisler
bookmarks: Include bookmarks in tags.
r7480 """Merge bookmarks with normal tags"""
Greg Ward
localrepo: factor _findtags() out of tags() (issue548)....
r9145 (tags, tagtypes) = super(bookmark_repo, self)._findtags()
tags.update(parse(self))
return (tags, tagtypes)
Martin Geisler
bookmarks: Include bookmarks in tags.
r7480
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 repo.__class__ = bookmark_repo
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)
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]
setcurrent(repo, rev)
return res
David Soria Parra
Bookmarks: Add the bookmarks extension...
r7239 cmdtable = {
"bookmarks":
(bookmark,
[('f', 'force', False, _('force')),
('r', 'rev', '', _('revision')),
('d', 'delete', False, _('delete a given bookmark')),
Joel Rosdahl
bookmarks: Rename --move to --rename...
r7255 ('m', 'rename', '', _('rename a given bookmark'))],
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 }