##// END OF EJS Templates
doc: add note about pattern rooted/unrooted cases to "hgignore" and "patterns"...
doc: add note about pattern rooted/unrooted cases to "hgignore" and "patterns" each help topics describe that patterns are "not rooted" and "rooted" in themselves, but not describe about each other. so, this may causes misunderstanding about "rooted"-ness of patterns.

File last commit:

r16276:6b16ded5 stable
r16504:e3c7ca15 stable
Show More
bookmarks.py
242 lines | 7.1 KiB | text/x-python | PythonLexer
Matt Mackall
bookmarks: move basic io to core
r13350 # 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 _
Alexander Solovyov
remove unused imports and variables
r14064 from mercurial.node import hex
Benoit Boissinot
bookmarks: be more restrictive in our Exception catching
r14027 from mercurial import encoding, error, util
import errno, os
Matt Mackall
bookmarks: move basic io to core
r13350
David Soria Parra
bookmarks: forbid \0 \r \n : in bookmark names (BC)...
r13425 def valid(mark):
for c in (':', '\0', '\n', '\r'):
if c in mark:
return False
return True
Matt Mackall
bookmarks: move read methods to core
r13351 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
'''
Benoit Boissinot
bookmarks: be more restrictive in our Exception catching
r14027 bookmarks = {}
Matt Mackall
bookmarks: move read methods to core
r13351 try:
for line in repo.opener('bookmarks'):
Pierre-Yves David
bookmarks: more robust parsing of bookmarks file
r14845 line = line.strip()
Matt Mackall
bookmarks: simplify warning code
r14848 if not line:
continue
Pierre-Yves David
bookmarks: more robust parsing of bookmarks file
r14845 if ' ' not in line:
Matt Mackall
bookmarks: simplify warning code
r14848 repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n') % line)
Pierre-Yves David
bookmarks: more robust parsing of bookmarks file
r14845 continue
Matt Mackall
bookmarks: drop superfluous strip
r14847 sha, refspec = line.split(' ', 1)
Matt Mackall
bookmarks: move read methods to core
r13351 refspec = encoding.tolocal(refspec)
Benoit Boissinot
bookmarks: be more restrictive in our Exception catching
r14027 try:
bookmarks[refspec] = repo.changelog.lookup(sha)
except error.RepoLookupError:
pass
except IOError, inst:
if inst.errno != errno.ENOENT:
raise
Matt Mackall
bookmarks: move read methods to core
r13351 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
Benoit Boissinot
bookmarks: be more restrictive in our Exception catching
r14027 try:
Matt Mackall
bookmarks: move read methods to core
r13351 file = repo.opener('bookmarks.current')
Benoit Boissinot
bookmarks: be more restrictive in our Exception catching
r14027 except IOError, inst:
if inst.errno != errno.ENOENT:
raise
return None
try:
Matt Mackall
bookmarks: move read methods to core
r13351 # No readline() in posixfile_nt, reading everything is cheap
David Soria Parra
bookmarks: read current bookmark as utf-8 and convert it to local
r13381 mark = encoding.tolocal((file.readlines() or [''])[0])
Benoit Boissinot
bookmarks: discard current bookmark if absent from the bookmarks (issue2692)...
r13627 if mark == '' or mark not in repo._bookmarks:
Matt Mackall
bookmarks: move read methods to core
r13351 mark = None
Benoit Boissinot
bookmarks: be more restrictive in our Exception catching
r14027 finally:
Matt Mackall
bookmarks: move read methods to core
r13351 file.close()
return mark
Matt Mackall
bookmarks: move basic io to core
r13350 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
if repo._bookmarkcurrent not in refs:
setcurrent(repo, None)
David Soria Parra
bookmarks: forbid \0 \r \n : in bookmark names (BC)...
r13425 for mark in refs.keys():
if not valid(mark):
raise util.Abort(_("bookmark '%s' contains illegal "
"character" % mark))
Matt Mackall
bookmarks: backout locking change in 12dea4d998ec...
r15908 wlock = repo.wlock()
Matt Mackall
bookmarks: move basic io to core
r13350 try:
David Soria Parra
bookmarks: forbid \0 \r \n : in bookmark names (BC)...
r13425
Matt Mackall
bookmarks: move basic io to core
r13350 file = repo.opener('bookmarks', 'w', atomictemp=True)
for refspec, node in refs.iteritems():
file.write("%s %s\n" % (hex(node), encoding.fromlocal(refspec)))
Greg Ward
atomictempfile: make close() consistent with other file-like objects....
r15057 file.close()
Matt Mackall
bookmarks: move basic io to core
r13350
# touch 00changelog.i so hgweb reloads bookmarks (no lock needed)
try:
os.utime(repo.sjoin('00changelog.i'), None)
except OSError:
pass
finally:
Matt Mackall
bookmarks: backout locking change in 12dea4d998ec...
r15908 wlock.release()
Matt Mackall
bookmarks: move basic io to core
r13350
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
David Soria Parra
bookmarks: remove API limitation in setcurrent...
r13647 if mark not in repo._bookmarks:
Matt Mackall
bookmarks: move basic io to core
r13350 mark = ''
David Soria Parra
bookmarks: forbid \0 \r \n : in bookmark names (BC)...
r13425 if not valid(mark):
raise util.Abort(_("bookmark '%s' contains illegal "
"character" % mark))
Matt Mackall
bookmarks: backout locking change in 12dea4d998ec...
r15908 wlock = repo.wlock()
Matt Mackall
bookmarks: move basic io to core
r13350 try:
file = repo.opener('bookmarks.current', 'w', atomictemp=True)
LUO Zheng
bookmarks: recognize the current bookmark when the local encoding isn't UTF-8...
r14559 file.write(encoding.fromlocal(mark))
Greg Ward
atomictempfile: make close() consistent with other file-like objects....
r15057 file.close()
Matt Mackall
bookmarks: move basic io to core
r13350 finally:
Matt Mackall
bookmarks: backout locking change in 12dea4d998ec...
r15908 wlock.release()
Matt Mackall
bookmarks: move basic io to core
r13350 repo._bookmarkcurrent = mark
Matt Mackall
bookmarks: move update into core
r13352
Idan Kamara
update: delete bookmarks.current when explicitly updating to a rev (issue3276)
r16191 def unsetcurrent(repo):
wlock = repo.wlock()
try:
Gilles Moris
bookmarks: restore python 2.4 compatibility...
r16194 try:
util.unlink(repo.join('bookmarks.current'))
repo._bookmarkcurrent = None
except OSError, inst:
if inst.errno != errno.ENOENT:
raise
Idan Kamara
update: delete bookmarks.current when explicitly updating to a rev (issue3276)
r16191 finally:
wlock.release()
David Soria Parra
bundle: update current bookmark to most recent revision on current branch...
r13663 def updatecurrentbookmark(repo, oldnode, curbranch):
try:
Kevin Bullock
bookmarks: update and updatecurrentbookmark return status...
r15621 return update(repo, oldnode, repo.branchtags()[curbranch])
David Soria Parra
bundle: update current bookmark to most recent revision on current branch...
r13663 except KeyError:
if curbranch == "default": # no default branch!
Kevin Bullock
bookmarks: update and updatecurrentbookmark return status...
r15621 return update(repo, oldnode, repo.lookup("tip"))
David Soria Parra
bundle: update current bookmark to most recent revision on current branch...
r13663 else:
raise util.Abort(_("branch %s not found") % curbranch)
Matt Mackall
bookmarks: move update into core
r13352 def update(repo, parents, node):
marks = repo._bookmarks
update = False
David Soria Parra
bookmarks: make track.current=True default behaviour and remove option (BC)
r13416 mark = repo._bookmarkcurrent
if mark and marks[mark] in parents:
David Soria Parra
bookmarks: restrict moving a bookmark to its descendants (issue1502)...
r13478 old = repo[marks[mark]]
new = repo[node]
if new in old.descendants():
marks[mark] = new.node()
update = True
Matt Mackall
bookmarks: move update into core
r13352 if update:
Augie Fackler
bookmarks: delegate writing to the repo just like reading...
r15237 repo._writebookmarks(marks)
Kevin Bullock
bookmarks: update and updatecurrentbookmark return status...
r15621 return update
Matt Mackall
bookmarks: move pushkey functions into core
r13353
def listbookmarks(repo):
# We may try to list bookmarks on a repo type that does not
# support it (e.g., statichttprepository).
Augie Fackler
bookmarks: use getattr instead of hasattr
r14946 marks = getattr(repo, '_bookmarks', {})
Matt Mackall
bookmarks: move pushkey functions into core
r13353
d = {}
Augie Fackler
bookmarks: use getattr instead of hasattr
r14946 for k, v in marks.iteritems():
Matt Mackall
bookmarks: shadow divergent bookmarks of foo with foo@n
r15613 # don't expose local divergent bookmarks
Kevin Bullock
bookmarks: clone non-divergent bookmarks with @ in them
r16276 if '@' not in k or k.endswith('@'):
Matt Mackall
bookmarks: shadow divergent bookmarks of foo with foo@n
r15613 d[k] = hex(v)
Matt Mackall
bookmarks: move pushkey functions into core
r13353 return d
def pushbookmark(repo, key, old, new):
Matt Mackall
bookmarks: backout locking change in 12dea4d998ec...
r15908 w = repo.wlock()
Matt Mackall
bookmarks: move pushkey functions into core
r13353 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:
Matt Mackall
bookmarks: backout locking change in 12dea4d998ec...
r15908 w.release()
Matt Mackall
bookmarks: move diff to core
r13354
Matt Mackall
bookmarks: mark divergent bookmarks with book@pathalias when source in [paths]
r15614 def updatefromremote(ui, repo, remote, path):
David Soria Parra
bookmarks: separate bookmarks update code from localrepo's pull....
r13646 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:
Matt Mackall
bookmarks: mark divergent bookmarks with book@pathalias when source in [paths]
r15614 # find a unique @ suffix
Matt Mackall
bookmarks: shadow divergent bookmarks of foo with foo@n
r15613 for x in range(1, 100):
n = '%s@%d' % (k, x)
if n not in repo._bookmarks:
break
Matt Mackall
bookmarks: mark divergent bookmarks with book@pathalias when source in [paths]
r15614 # try to use an @pathalias suffix
# if an @pathalias already exists, we overwrite (update) it
for p, u in ui.configitems("paths"):
if path == u:
n = '%s@%s' % (k, p)
Matt Mackall
bookmarks: shadow divergent bookmarks of foo with foo@n
r15613 repo._bookmarks[n] = cr.node()
changed = True
ui.warn(_("divergent bookmark %s stored as %s\n") % (k, n))
David Soria Parra
bookmarks: separate bookmarks update code from localrepo's pull....
r13646 if changed:
write(repo)
Matt Mackall
bookmarks: move diff to core
r13354 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:
David Soria Parra
bookmarks: respect --debug during incoming/outgoing
r15984 mark = ui.debugflag and rmarks[k] or rmarks[k][:12]
ui.write(" %-25s %s\n" % (k, mark))
Matt Mackall
bookmarks: move diff to core
r13354
if len(diff) <= 0:
ui.status(_("no changed bookmarks found\n"))
return 1
return 0