changeset 35273:a1e70c1dbec0

bookmark: use the 'bookmarks' bundle2 part to push bookmark update (issue5165) We use the new binary parts we introduced earlier to exchange bookmark. The payload is a bit more compact since we use binary and the length of bookmarks is no longer constrained to 255. .. fix:: Issue 5165 Bookmark, whose name is longer than 255, can again be exchanged again between 4.4+ client and servers.
author Boris Feld <boris.feld@octobus.net>
date Tue, 17 Oct 2017 12:38:13 +0200
parents ae79d878702b
children 1f30cbac34b6
files mercurial/exchange.py tests/test-bookmarks-pushpull.t tests/test-bundle2-exchange.t tests/test-hook.t
diffstat 4 files changed, 65 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/exchange.py	Tue Oct 17 12:37:39 2017 +0200
+++ b/mercurial/exchange.py	Tue Oct 17 12:38:13 2017 +0200
@@ -897,9 +897,45 @@
     if 'bookmarks' in pushop.stepsdone:
         return
     b2caps = bundle2.bundle2caps(pushop.remote)
-    if 'pushkey' in b2caps:
+
+    legacy = pushop.repo.ui.configlist('devel', 'legacy.exchange')
+    legacybooks = 'bookmarks' in legacy
+
+    if not legacybooks and 'bookmarks' in b2caps:
+        return _pushb2bookmarkspart(pushop, bundler)
+    elif 'pushkey' in b2caps:
         return _pushb2bookmarkspushkey(pushop, bundler)
 
+def _bmaction(old, new):
+    """small utility for bookmark pushing"""
+    if not old:
+        return 'export'
+    elif not new:
+        return 'delete'
+    return 'update'
+
+def _pushb2bookmarkspart(pushop, bundler):
+    pushop.stepsdone.add('bookmarks')
+    if not pushop.outbookmarks:
+        return
+
+    allactions = []
+    data = []
+    for book, old, new in pushop.outbookmarks:
+        new = bin(new)
+        data.append((book, new))
+        allactions.append((book, _bmaction(old, new)))
+    checkdata = bookmod.binaryencode(data)
+    bundler.newpart('bookmarks', data=checkdata)
+
+    def handlereply(op):
+        ui = pushop.ui
+        # if success
+        for book, action in allactions:
+            ui.status(bookmsgmap[action][0] % book)
+
+    return handlereply
+
 def _pushb2bookmarkspushkey(pushop, bundler):
     pushop.stepsdone.add('bookmarks')
     part2book = []
--- a/tests/test-bookmarks-pushpull.t	Tue Oct 17 12:37:39 2017 +0200
+++ b/tests/test-bookmarks-pushpull.t	Tue Oct 17 12:38:13 2017 +0200
@@ -1,4 +1,12 @@
 #testcases b2-pushkey b2-binary
+
+#if b2-pushkey
+  $ cat << EOF >> $HGRCPATH
+  > [devel]
+  > legacy.exchange=bookmarks
+  > EOF
+#endif
+
 #require serve
 
   $ cat << EOF >> $HGRCPATH
@@ -250,10 +258,11 @@
   bundle2-output: header chunk size: 19
   bundle2-output: payload chunk size: 48
   bundle2-output: closing payload chunk
-  bundle2-output: bundle part: "pushkey"
-  bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
-  bundle2-output: part 3: "PUSHKEY"
-  bundle2-output: header chunk size: 90
+  bundle2-output: bundle part: "bookmarks"
+  bundle2-output-part: "bookmarks" 23 bytes payload
+  bundle2-output: part 3: "BOOKMARKS"
+  bundle2-output: header chunk size: 16
+  bundle2-output: payload chunk size: 23
   bundle2-output: closing payload chunk
   bundle2-output: end of bundle
   bundle2-input: start processing of HG20 stream
@@ -287,40 +296,29 @@
   bundle2-input: payload chunk size: 48
   bundle2-input: payload chunk size: 0
   bundle2-input-part: total payload size 48
-  bundle2-input: part header size: 90
-  bundle2-input: part type: "PUSHKEY"
+  bundle2-input: part header size: 16
+  bundle2-input: part type: "BOOKMARKS"
   bundle2-input: part id: "3"
-  bundle2-input: part parameters: 4
-  bundle2-input: found a handler for part pushkey
-  bundle2-input-part: "pushkey" (params: 4 mandatory) supported
-  pushing key for "bookmarks:W"
+  bundle2-input: part parameters: 0
+  bundle2-input: found a handler for part bookmarks
+  bundle2-input-part: "bookmarks" supported
+  bundle2-input: payload chunk size: 23
   bundle2-input: payload chunk size: 0
+  bundle2-input-part: total payload size 23
   bundle2-input: part header size: 0
   bundle2-input: end of bundle2 stream
   bundle2-input-bundle: 3 parts total
   running hook txnclose-bookmark.test: sh $TESTTMP/hook.sh
   test-hook-bookmark: W:  0000000000000000000000000000000000000000 -> 
-  bundle2-output-bundle: "HG20", 1 parts total
+  bundle2-output-bundle: "HG20", 0 parts total
   bundle2-output: start emission of HG20 stream
   bundle2-output: bundle parameter: 
   bundle2-output: start of parts
-  bundle2-output: bundle part: "reply:pushkey"
-  bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
-  bundle2-output: part 0: "REPLY:PUSHKEY"
-  bundle2-output: header chunk size: 43
-  bundle2-output: closing payload chunk
   bundle2-output: end of bundle
   bundle2-input: start processing of HG20 stream
   bundle2-input: reading bundle2 stream parameters
   bundle2-input-bundle: no-transaction
   bundle2-input: start extraction of bundle2 parts
-  bundle2-input: part header size: 43
-  bundle2-input: part type: "REPLY:PUSHKEY"
-  bundle2-input: part id: "0"
-  bundle2-input: part parameters: 2
-  bundle2-input: found a handler for part reply:pushkey
-  bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
-  bundle2-input: payload chunk size: 0
   bundle2-input: part header size: 0
   bundle2-input: end of bundle2 stream
   bundle2-input-bundle: 0 parts total
@@ -1088,8 +1086,7 @@
   pushing to $TESTTMP/issue4455-dest (glob)
   searching for changes
   no changes found
-  pushkey-abort: prepushkey hook exited with status 1
-  abort: exporting bookmark @ failed!
+  abort: prepushkey hook exited with status 1
   [255]
 
 #endif
@@ -1128,8 +1125,8 @@
   pushing to ssh://user@dummy/issue4455-dest
   searching for changes
   no changes found
-  remote: pushkey-abort: prepushkey hook exited with status 1
-  abort: exporting bookmark @ failed!
+  remote: prepushkey hook exited with status 1
+  abort: push failed on remote
   [255]
 
 #endif
@@ -1168,8 +1165,8 @@
   pushing to ssh://user@dummy/issue4455-dest
   searching for changes
   no changes found
-  remote: pushkey-abort: prepushkey hook exited with status 1
-  abort: exporting bookmark @ failed!
+  remote: prepushkey hook exited with status 1
+  abort: push failed on remote
   [255]
 
 #endif
--- a/tests/test-bundle2-exchange.t	Tue Oct 17 12:37:39 2017 +0200
+++ b/tests/test-bundle2-exchange.t	Tue Oct 17 12:38:13 2017 +0200
@@ -253,9 +253,6 @@
   remote: added 1 changesets with 0 changes to 0 files (-1 heads)
   remote: 1 new obsolescence markers
   remote: pre-close-tip:eea13746799a public book_eea1
-  remote: pushkey: lock state after "bookmarks"
-  remote: lock:  free
-  remote: wlock: free
   remote: postclose-tip:eea13746799a public book_eea1
   remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_NODE_LAST=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_PHASES_MOVED=1 HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_TXNNAME=push HG_URL=file:$TESTTMP/other
   updating bookmark book_eea1
@@ -339,9 +336,6 @@
   remote: added 1 changesets with 1 changes to 1 files
   remote: 1 new obsolescence markers
   remote: pre-close-tip:5fddd98957c8 draft book_5fdd
-  remote: pushkey: lock state after "bookmarks"
-  remote: lock:  free
-  remote: wlock: free
   remote: postclose-tip:5fddd98957c8 draft book_5fdd
   remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_NODE_LAST=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_TXNNAME=serve HG_URL=remote:ssh:$LOCALIP
   updating bookmark book_5fdd
@@ -390,9 +384,6 @@
   remote: added 1 changesets with 1 changes to 1 files
   remote: 1 new obsolescence markers
   remote: pre-close-tip:32af7686d403 public book_32af
-  remote: pushkey: lock state after "bookmarks"
-  remote: lock:  free
-  remote: wlock: free
   remote: postclose-tip:32af7686d403 public book_32af
   remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=32af7686d403cf45b5d95f2d70cebea587ac806a HG_NODE_LAST=32af7686d403cf45b5d95f2d70cebea587ac806a HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_TXNNAME=serve HG_URL=remote:http:$LOCALIP: (glob)
   updating bookmark book_32af
--- a/tests/test-hook.t	Tue Oct 17 12:37:39 2017 +0200
+++ b/tests/test-hook.t	Tue Oct 17 12:38:13 2017 +0200
@@ -244,7 +244,6 @@
   no changes found
   pretxnopen hook: HG_HOOKNAME=pretxnopen HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=push
   pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=pretxnclose HG_HOOKTYPE=pretxnclose HG_PENDING=$TESTTMP/a HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_TXNNAME=push HG_URL=file:$TESTTMP/a
-  pushkey hook: HG_HOOKNAME=pushkey HG_HOOKTYPE=pushkey HG_KEY=foo HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_RET=1
   txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=txnclose HG_HOOKTYPE=txnclose HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_TXNNAME=push HG_URL=file:$TESTTMP/a
   exporting bookmark foo
   [1]
@@ -281,9 +280,8 @@
   listkeys hook: HG_HOOKNAME=listkeys HG_HOOKTYPE=listkeys HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'}
   no changes found
   pretxnopen hook: HG_HOOKNAME=pretxnopen HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=push
-  prepushkey.forbid hook: HG_BUNDLE2=1 HG_HOOKNAME=prepushkey HG_HOOKTYPE=prepushkey HG_KEY=baz HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
-  pushkey-abort: prepushkey hook exited with status 1
-  abort: exporting bookmark baz failed!
+  prepushkey.forbid hook: HG_BUNDLE2=1 HG_HOOKNAME=prepushkey HG_HOOKTYPE=prepushkey HG_KEY=baz HG_NAMESPACE=bookmark HG_NEW=0000000000000000000000000000000000000000 HG_PUSHKEYCOMPAT=1 HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
+  abort: prepushkey hook exited with status 1
   [255]
   $ cd ../a