# HG changeset patch # User Boris Feld # Date 1508072395 -7200 # Node ID 3340d46a5c3f1ac61d133369df0ecc725a1a5267 # Parent 8fbb2678d8e83a65d4874937cf3b5c3257b7b19e bookmark: add methods to binary encode and decode bookmark values Coming new bundle2 parts related to bookmark will use a binary encoding. It encodes a series of '(bookmark, node)' pairs. Bookmark name has a high enough size limit to not be affected by issue5165. (64K length, we are well covered) diff -r 8fbb2678d8e8 -r 3340d46a5c3f mercurial/bookmarks.py --- a/mercurial/bookmarks.py Wed Dec 06 09:25:43 2017 -0500 +++ b/mercurial/bookmarks.py Sun Oct 15 14:59:55 2017 +0200 @@ -8,12 +8,14 @@ from __future__ import absolute_import import errno +import struct from .i18n import _ from .node import ( bin, hex, short, + wdirid, ) from . import ( encoding, @@ -550,6 +552,60 @@ binremotemarks[name] = bin(node) return binremotemarks +_binaryentry = struct.Struct('>20sH') + +def binaryencode(bookmarks): + """encode a '(bookmark, node)' iterable into a binary stream + + the binary format is: + + + + :node: is a 20 bytes binary node, + :bookmark-length: an unsigned short, + :bookmark-name: the name of the bookmark (of length ) + + wdirid (all bits set) will be used as a special value for "missing" + """ + binarydata = [] + for book, node in bookmarks: + if not node: # None or '' + node = wdirid + binarydata.append(_binaryentry.pack(node, len(book))) + binarydata.append(book) + return ''.join(binarydata) + +def binarydecode(stream): + """decode a binary stream into an '(bookmark, node)' iterable + + the binary format is: + + + + :node: is a 20 bytes binary node, + :bookmark-length: an unsigned short, + :bookmark-name: the name of the bookmark (of length )) + + wdirid (all bits set) will be used as a special value for "missing" + """ + entrysize = _binaryentry.size + books = [] + while True: + entry = stream.read(entrysize) + if len(entry) < entrysize: + if entry: + raise error.Abort(_('bad bookmark stream')) + break + node, length = _binaryentry.unpack(entry) + bookmark = stream.read(length) + if len(bookmark) < length: + if entry: + raise error.Abort(_('bad bookmark stream')) + if node == wdirid: + node = None + books.append((bookmark, node)) + return books + def updatefromremote(ui, repo, remotemarks, path, trfunc, explicit=()): ui.debug("checking for updated bookmarks\n") localmarks = repo._bookmarks