##// END OF EJS Templates
# User Dan Villiom Podlaski Christiansen <danchr@gmail.com>...
# User Dan Villiom Podlaski Christiansen <danchr@gmail.com> # Date 1289564504 -3600 # Node ID b75264c15cc888cf38c3c7b8f619801e3c2589c7 # Parent 89b2e5d940f669e590096c6be70eee61c9172fff revsets: overload the branch() revset to also take a branch name. This should only change semantics in the specific case of a tag/branch conflict where the tag wasn't done on the branch with the same name. Previously, branch(whatever) would resolve to the branch of the tag in that case, whereas now it will resolve to the branch of the name. The previous behaviour, while documented, seemed very counter-intuitive to me. An alternate approach would be to introduce a new revset such as branchname() or namedbranch(). While this would retain backwards compatibility, the distinction between it and branch() would not be readily apparent to users. The most intuitive behaviour would be to have branch(x) require 'x' to be a branch name, and something like branchof(x) or samebranch(x) do what branch(x) currently does. Unfortunately, our backwards compatibility guarantees prevent us from doing that. Please note that while 'hg tag' guards against shadowing a branch, 'hg branch' does not. Besides, even if it did, that wouldn't solve the issue of conversions with such tags and branches...

File last commit:

r13663:d16c99f1 default
r13750:7eb82f88 default
Show More
bookmarks.py
204 lines | 5.8 KiB | text/x-python | PythonLexer
# Mercurial bookmark support code
#
# Copyright 2008 David Soria Parra <dsp@php.net>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from mercurial.i18n import _
from mercurial.node import nullid, nullrev, bin, hex, short
from mercurial import encoding, util
import os
def valid(mark):
for c in (':', '\0', '\n', '\r'):
if c in mark:
return False
return True
def read(repo):
'''Parse .hg/bookmarks file and return a dictionary
Bookmarks are stored as {HASH}\\s{NAME}\\n (localtags format) values
in the .hg/bookmarks file.
Read the file and return a (name=>nodeid) dictionary
'''
try:
bookmarks = {}
for line in repo.opener('bookmarks'):
sha, refspec = line.strip().split(' ', 1)
refspec = encoding.tolocal(refspec)
bookmarks[refspec] = repo.changelog.lookup(sha)
except:
pass
return bookmarks
def readcurrent(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
'''
mark = None
if os.path.exists(repo.join('bookmarks.current')):
file = repo.opener('bookmarks.current')
# No readline() in posixfile_nt, reading everything is cheap
mark = encoding.tolocal((file.readlines() or [''])[0])
if mark == '' or mark not in repo._bookmarks:
mark = None
file.close()
return mark
def write(repo):
'''Write bookmarks
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.
'''
refs = repo._bookmarks
try:
bms = repo.opener('bookmarks').read()
except IOError:
bms = ''
repo.opener('undo.bookmarks', 'w').write(bms)
if repo._bookmarkcurrent not in refs:
setcurrent(repo, None)
for mark in refs.keys():
if not valid(mark):
raise util.Abort(_("bookmark '%s' contains illegal "
"character" % mark))
wlock = repo.wlock()
try:
file = repo.opener('bookmarks', 'w', atomictemp=True)
for refspec, node in refs.iteritems():
file.write("%s %s\n" % (hex(node), encoding.fromlocal(refspec)))
file.rename()
# touch 00changelog.i so hgweb reloads bookmarks (no lock needed)
try:
os.utime(repo.sjoin('00changelog.i'), None)
except OSError:
pass
finally:
wlock.release()
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>).
The name is recorded in .hg/bookmarks.current
'''
current = repo._bookmarkcurrent
if current == mark:
return
if mark not in repo._bookmarks:
mark = ''
if not valid(mark):
raise util.Abort(_("bookmark '%s' contains illegal "
"character" % mark))
wlock = repo.wlock()
try:
file = repo.opener('bookmarks.current', 'w', atomictemp=True)
file.write(mark)
file.rename()
finally:
wlock.release()
repo._bookmarkcurrent = mark
def updatecurrentbookmark(repo, oldnode, curbranch):
try:
update(repo, oldnode, repo.branchtags()[curbranch])
except KeyError:
if curbranch == "default": # no default branch!
update(repo, oldnode, repo.lookup("tip"))
else:
raise util.Abort(_("branch %s not found") % curbranch)
def update(repo, parents, node):
marks = repo._bookmarks
update = False
mark = repo._bookmarkcurrent
if mark and marks[mark] in parents:
old = repo[marks[mark]]
new = repo[node]
if new in old.descendants():
marks[mark] = new.node()
update = True
if update:
write(repo)
def listbookmarks(repo):
# We may try to list bookmarks on a repo type that does not
# support it (e.g., statichttprepository).
if not hasattr(repo, '_bookmarks'):
return {}
d = {}
for k, v in repo._bookmarks.iteritems():
d[k] = hex(v)
return d
def pushbookmark(repo, key, old, new):
w = repo.wlock()
try:
marks = repo._bookmarks
if hex(marks.get(key, '')) != old:
return False
if new == '':
del marks[key]
else:
if new not in repo:
return False
marks[key] = repo[new].node()
write(repo)
return True
finally:
w.release()
def updatefromremote(ui, repo, remote):
ui.debug("checking for updated bookmarks\n")
rb = remote.listkeys('bookmarks')
changed = False
for k in rb.keys():
if k in repo._bookmarks:
nr, nl = rb[k], repo._bookmarks[k]
if nr in repo:
cr = repo[nr]
cl = repo[nl]
if cl.rev() >= cr.rev():
continue
if cr in cl.descendants():
repo._bookmarks[k] = cr.node()
changed = True
ui.status(_("updating bookmark %s\n") % k)
else:
ui.warn(_("not updating divergent"
" bookmark %s\n") % k)
if changed:
write(repo)
def diff(ui, repo, remote):
ui.status(_("searching for changed bookmarks\n"))
lmarks = repo.listkeys('bookmarks')
rmarks = remote.listkeys('bookmarks')
diff = sorted(set(rmarks) - set(lmarks))
for k in diff:
ui.write(" %-25s %s\n" % (k, rmarks[k][:12]))
if len(diff) <= 0:
ui.status(_("no changed bookmarks found\n"))
return 1
return 0