comparison mercurial/bookmarks.py @ 35257:3340d46a5c3f

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)
author Boris Feld <boris.feld@octobus.net>
date Sun, 15 Oct 2017 14:59:55 +0200
parents ee5f0d047b41
children b9a0de08110e
comparison
equal deleted inserted replaced
35256:8fbb2678d8e8 35257:3340d46a5c3f
6 # GNU General Public License version 2 or any later version. 6 # GNU General Public License version 2 or any later version.
7 7
8 from __future__ import absolute_import 8 from __future__ import absolute_import
9 9
10 import errno 10 import errno
11 import struct
11 12
12 from .i18n import _ 13 from .i18n import _
13 from .node import ( 14 from .node import (
14 bin, 15 bin,
15 hex, 16 hex,
16 short, 17 short,
18 wdirid,
17 ) 19 )
18 from . import ( 20 from . import (
19 encoding, 21 encoding,
20 error, 22 error,
21 lock as lockmod, 23 lock as lockmod,
548 binremotemarks = {} 550 binremotemarks = {}
549 for name, node in marks.items(): 551 for name, node in marks.items():
550 binremotemarks[name] = bin(node) 552 binremotemarks[name] = bin(node)
551 return binremotemarks 553 return binremotemarks
552 554
555 _binaryentry = struct.Struct('>20sH')
556
557 def binaryencode(bookmarks):
558 """encode a '(bookmark, node)' iterable into a binary stream
559
560 the binary format is:
561
562 <node><bookmark-length><bookmark-name>
563
564 :node: is a 20 bytes binary node,
565 :bookmark-length: an unsigned short,
566 :bookmark-name: the name of the bookmark (of length <bookmark-length>)
567
568 wdirid (all bits set) will be used as a special value for "missing"
569 """
570 binarydata = []
571 for book, node in bookmarks:
572 if not node: # None or ''
573 node = wdirid
574 binarydata.append(_binaryentry.pack(node, len(book)))
575 binarydata.append(book)
576 return ''.join(binarydata)
577
578 def binarydecode(stream):
579 """decode a binary stream into an '(bookmark, node)' iterable
580
581 the binary format is:
582
583 <node><bookmark-length><bookmark-name>
584
585 :node: is a 20 bytes binary node,
586 :bookmark-length: an unsigned short,
587 :bookmark-name: the name of the bookmark (of length <bookmark-length>))
588
589 wdirid (all bits set) will be used as a special value for "missing"
590 """
591 entrysize = _binaryentry.size
592 books = []
593 while True:
594 entry = stream.read(entrysize)
595 if len(entry) < entrysize:
596 if entry:
597 raise error.Abort(_('bad bookmark stream'))
598 break
599 node, length = _binaryentry.unpack(entry)
600 bookmark = stream.read(length)
601 if len(bookmark) < length:
602 if entry:
603 raise error.Abort(_('bad bookmark stream'))
604 if node == wdirid:
605 node = None
606 books.append((bookmark, node))
607 return books
608
553 def updatefromremote(ui, repo, remotemarks, path, trfunc, explicit=()): 609 def updatefromremote(ui, repo, remotemarks, path, trfunc, explicit=()):
554 ui.debug("checking for updated bookmarks\n") 610 ui.debug("checking for updated bookmarks\n")
555 localmarks = repo._bookmarks 611 localmarks = repo._bookmarks
556 (addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same 612 (addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same
557 ) = comparebookmarks(repo, remotemarks, localmarks) 613 ) = comparebookmarks(repo, remotemarks, localmarks)