<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sun, Nov 13, 2016 at 2:30 AM, Stanislau Hlebik <span dir="ltr"><<a href="mailto:stash@fb.com" target="_blank">stash@fb.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"># HG changeset patch<br>
# User Stanislau Hlebik <<a href="mailto:stash@fb.com">stash@fb.com</a>><br>
# Date 1479032456 28800<br>
# Sun Nov 13 02:20:56 2016 -0800<br>
# Branch stable<br>
# Node ID 8b6ab3b8df3aae90ac72d7fa4603e7<wbr>d5b4ab55e9<br>
# Parent 0917ce41b232a5fc2a6e503cbad158<wbr>79e037a2f9<br>
bookmarks: introduce binary encoding<br>
<br>
Bookmarks binary encoding will be used for `bookmarks` bundle2 part.<br>
The format is: <4 bytes - bookmark size, big-endian><bookmark><br>
<1 byte - 0 if node is empty 1 otherwise><20 bytes node><br>
BookmarksEncodeError and BookmarksDecodeError maybe thrown if input is<br>
incorrect.<br></blockquote><div><br></div><div>I'm pretty happy with this series up until and including this patch.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
diff --git a/mercurial/bookmarks.py b/mercurial/bookmarks.py<br>
--- a/mercurial/bookmarks.py<br>
+++ b/mercurial/bookmarks.py<br>
@@ -8,7 +8,9 @@<br>
from __future__ import absolute_import<br>
<br>
import errno<br>
+import io<br>
import os<br>
+import struct<br>
<br>
from .i18n import _<br>
from .node import (<br>
@@ -23,6 +25,71 @@<br>
util,<br>
)<br>
<br>
+_NONEMPTYNODE = struct.pack('?', False)<br>
+_EMPTYNODE = struct.pack('?', True)<br>
+<br>
+def _unpackbookmarksize(stream):<br>
+ """Returns 0 if stream is empty.<br>
+ """<br>
+<br>
+ intstruct = struct.Struct('>i')<br>
+ expectedsize = intstruct.size<br>
+ encodedbookmarksize = stream.read(expectedsize)<br>
+ if not encodedbookmarksize:<br>
+ return 0<br>
+ if len(encodedbookmarksize) != expectedsize:<br>
+ raise ValueError(<br>
+ _('cannot decode bookmark size: '<br>
+ 'expected size: %d, actual size: %d') %<br>
+ (expectedsize, len(encodedbookmarksize)))<br>
+ return intstruct.unpack(<wbr>encodedbookmarksize)[0]<br>
+<br>
+def encodebookmarks(bookmarks):<br>
+ """Encodes bookmark to node mapping to the byte string.<br>
+<br>
+ Format: <4 bytes - bookmark size><bookmark><br>
+ <1 byte - 0 if node is empty 1 otherwise><20 bytes node><br>
+ Node may be 20 byte binary string or empty<br>
+ """<br>
+<br>
+ intstruct = struct.Struct('>i')<br>
+ for bookmark, node in sorted(bookmarks.iteritems()):<br>
+ yield intstruct.pack(len(bookmark))<br>
+ yield encoding.fromlocal(bookmark)<br>
+ if node:<br>
+ if len(node) != 20:<br>
+ raise ValueError(_('node must be 20 or bytes long'))<br>
+ yield _NONEMPTYNODE<br>
+ yield node<br>
+ else:<br>
+ yield _EMPTYNODE<br>
+<br>
+def decodebookmarks(buf):<br>
+ """Decodes buffer into bookmark to node mapping.<br>
+<br>
+ Node is either 20 bytes or empty.<br>
+ """<br>
+<br>
+ stream = io.BytesIO(buf)<br>
+ bookmarks = {}<br>
+ bookmarksize = _unpackbookmarksize(stream)<br>
+ boolstruct = struct.Struct('?')<br>
+ while bookmarksize:<br>
+ bookmark = stream.read(bookmarksize)<br>
+ if len(bookmark) != bookmarksize:<br>
+ raise ValueError(<br>
+ _('cannot decode bookmark: expected size: %d, '<br>
+ 'actual size: %d') % (bookmarksize, len(bookmark)))<br>
+ bookmark = encoding.tolocal(bookmark)<br>
+ packedemptynodeflag = stream.read(boolstruct.size)<br>
+ emptynode = boolstruct.unpack(<wbr>packedemptynodeflag)[0]<br>
+ node = ''<br>
+ if not emptynode:<br>
+ node = stream.read(20)<br>
+ bookmarks[bookmark] = node<br>
+ bookmarksize = _unpackbookmarksize(stream)<br>
+ return bookmarks<br>
+<br>
def _getbkfile(repo):<br>
"""Hook so that extensions that mess with the store can hook bm storage.<br>
<br>
______________________________<wbr>_________________<br>
Mercurial-devel mailing list<br>
<a href="mailto:Mercurial-devel@mercurial-scm.org">Mercurial-devel@mercurial-scm.<wbr>org</a><br>
<a href="https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel" rel="noreferrer" target="_blank">https://www.mercurial-scm.org/<wbr>mailman/listinfo/mercurial-<wbr>devel</a><br>
</blockquote></div><br></div></div>