[PATCH 1 of 8] localrepo: move bookmarks to core
dsp at php.net
dsp at php.net
Sun Jan 16 16:57:37 CST 2011
# HG changeset patch
# User David Soria Parra <dsp at php.net>
# Date 1295218241 -3600
# Node ID 365ba79250901d16cc59bc18780fab4d156a948e
# Parent 20a54bdf232832d3d6c4e4a43361dc84ec73dca0
localrepo: move bookmarks to core
diff --git a/hgext/bookmarks.py b/hgext/bookmarks.py
--- a/hgext/bookmarks.py
+++ b/hgext/bookmarks.py
@@ -261,7 +261,7 @@
if mark == '':
mark = None
file.close()
- return mark
+ return encoding.tolocal(mark)
def rollback(self, *args):
if os.path.exists(self.join('undo.bookmarks')):
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -500,7 +500,140 @@
bheads = [b for b in bheads if b not in reachable]
partial[branch] = bheads
+ def _bookmarkspull(self, remote):
+ self.ui.debug("checking for updated bookmarks\n")
+ rb = remote.listkeys('bookmarks')
+ changed = False
+ donotupdate = []
+ 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()
+ changed = True
+ self.ui.status(_("updating bookmark %s\n") % k)
+ else:
+ self.ui.warn(_("not updating divergent"
+ " bookmark %s\n") % k)
+ donotupdate.append(k)
+ else:
+ try:
+ self.bookmarks[k] = self.changelog.lookup(rb[k])
+ changed = True
+ self.ui.status(_("importing bookmark %s\n") % k)
+ except:
+ self.ui.warn(_("cannot import bookmark %s. referenced"
+ " revision is not in repository\n") % k)
+
+ k = self.bookmarkcurrent
+ if k not in donotupdate:
+ branch = self.dirstate.branch()
+ n = self[branch].node()
+ cl = self[k]
+ if cl.rev() and n in cl.descendants():
+ self.bookmarks[k] = n
+ changed = True
+
+ if changed:
+ self.writebookmarks()
+
+ def _bookmarkspush(self, remote):
+ self.ui.debug("checking for updated bookmarks\n")
+ rb = remote.listkeys('bookmarks')
+ 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 in cr.descendants():
+ r = remote.pushkey('bookmarks', k, nr, nl)
+ if r:
+ self.ui.status(_("updating bookmark %s\n") % k)
+ else:
+ self.ui.warn(_('updating bookmark %s'
+ ' failed!\n') % k)
+
+ def _bookmarksupdate(self, node):
+ mark = self.bookmarkcurrent
+ if mark and self.bookmarks[mark] in self.dirstate.parents():
+ self.bookmarks[mark] = node
+ self.writebookmarks()
+
+ @propertycache
+ def bookmarks(self):
+ '''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
+ '''
+ bookmarks = {}
+ if os.path.exists(self.join('bookmarks')):
+ for line in self.opener('bookmarks'):
+ sha, name = line.strip().split(' ', 1)
+ ref = encoding.tolocal(name)
+ bookmarks[ref] = self.changelog.lookup(sha)
+ return bookmarks
+
+ @propertycache
+ def bookmarkcurrent(self):
+ mark = None
+ if os.path.exists(self.join('bookmarks.current')):
+ file = self.opener('bookmarks.current')
+ # No readline() in posixfile_nt, reading everything is cheap
+ mark = encoding.tolocal((file.readlines() or [''])[0])
+ if mark == '':
+ mark = None
+ file.close()
+ return mark
+
+ def writebookmarks(self):
+ '''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 = self.bookmarks
+ try:
+ bms = self.opener('bookmarks').read()
+ except IOError:
+ bms = ''
+ self.opener('undo.bookmarks', 'w').write(bms)
+
+ wlock = self.wlock()
+ try:
+ file = self.opener('bookmarks', 'w', atomictemp=True)
+ for ref, node in refs.iteritems():
+ file.write("%s %s\n" % (hex(node), encoding.fromlocal(ref)))
+ file.rename()
+
+ mark = self.bookmarkcurrent
+ if mark not in refs:
+ mark = ''
+ file = self.opener('bookmarks.current', 'w', atomictemp=True)
+ file.write(encoding.fromlocal(mark))
+ file.rename()
+ # touch 00changelog.i so hgweb reloads bookmarks (no lock needed)
+ try:
+ os.utime(self.sjoin('00changelog.i'), None)
+ except OSError:
+ pass
+
+ finally:
+ wlock.release()
+
def lookup(self, key):
+ if key in self.bookmarks:
+ return self.bookmarks[key]
if isinstance(key, int):
return self.changelog.node(key)
elif key == '.':
@@ -691,6 +824,8 @@
try:
wlock = self.wlock()
lock = self.lock()
+ if os.path.exists(self.join('undo.bookmarks')):
+ util.rename(self.join('undo.bookmarks'), self.join('bookmarks'))
if os.path.exists(self.sjoin("undo")):
try:
args = self.opener("undo.desc", "r").read().splitlines()
@@ -733,7 +868,7 @@
self._branchcachetip = None
def invalidate(self):
- for a in ("changelog", "manifest"):
+ for a in ("changelog", "manifest", "_bookmarks", "_bookmarkcurrent"):
if a in self.__dict__:
delattr(self, a)
self.invalidatecaches()
@@ -977,6 +1112,9 @@
_('note: commit message saved in %s\n') % msgfn)
raise
+ # update bookmarks
+ self._bookmarksupdate(ret)
+
# update dirstate and mergestate
for f in changes[0] + changes[1]:
self.dirstate.normal(f)
@@ -1300,8 +1438,11 @@
"other repository doesn't support "
"changegroupsubset."))
cg = remote.changegroupsubset(fetch, heads, 'pull')
+
return self.addchangegroup(cg, 'pull', remote.url(), lock=lock)
finally:
+ if remote.capable('pushkey'):
+ self._bookmarkspull(remote)
lock.release()
def push(self, remote, force=False, revs=None, newbranch=False):
@@ -1341,10 +1482,12 @@
remote_heads = ['force']
# ssh: return remote's addchangegroup()
# http: return remote's addchangegroup() or 0 for error
- return remote.unbundle(cg, remote_heads, 'push')
+ ret = remote.unbundle(cg, remote_heads, 'push')
else:
# we return an integer indicating remote head count change
- return remote.addchangegroup(cg, 'push', self.url(), lock=lock)
+ ret = remote.addchangegroup(cg, 'push', self.url(), lock=lock)
+
+ return ret
finally:
if lock is not None:
lock.release()
More information about the Mercurial-devel
mailing list