D4492: wireprotov2: let clients drive delta behavior
indygreg (Gregory Szorc)
phabricator at mercurial-scm.org
Wed Sep 12 13:13:36 EDT 2018
indygreg updated this revision to Diff 10971.
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D4492?vs=10805&id=10971
REVISION DETAIL
https://phab.mercurial-scm.org/D4492
AFFECTED FILES
mercurial/exchangev2.py
mercurial/help/internals/wireprotocolv2.txt
mercurial/wireprotov2server.py
tests/test-http-protocol.t
tests/test-wireproto-command-capabilities.t
tests/test-wireproto-command-filedata.t
tests/test-wireproto-command-manifestdata.t
tests/test-wireproto-exchangev2.t
CHANGE DETAILS
diff --git a/tests/test-wireproto-exchangev2.t b/tests/test-wireproto-exchangev2.t
--- a/tests/test-wireproto-exchangev2.t
+++ b/tests/test-wireproto-exchangev2.t
@@ -82,6 +82,7 @@
'parents',
'revision'
]),
+ 'haveparents': True,
'nodes': [
'\x99/Gy\x02\x9a=\xf8\xd0fm\x00\xbb\x92OicN&A',
'\xa9\x88\xfbCX>\x87\x1d\x1e\xd5u\x0e\xe0t\xc6\xd8@\xbb\xbf\xc8',
@@ -100,6 +101,7 @@
'parents',
'revision'
]),
+ 'haveparents': True,
'nodes': [
'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
'\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc',
@@ -112,6 +114,7 @@
'parents',
'revision'
]),
+ 'haveparents': True,
'nodes': [
'\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16',
'\xb1zk\xd3g=\x9a\xb8\xce\xd5\x81\xa2\t\xf6/=\xa5\xccEx',
@@ -211,6 +214,7 @@
'parents',
'revision'
]),
+ 'haveparents': True,
'nodes': [
'\x99/Gy\x02\x9a=\xf8\xd0fm\x00\xbb\x92OicN&A',
'\xa9\x88\xfbCX>\x87\x1d\x1e\xd5u\x0e\xe0t\xc6\xd8@\xbb\xbf\xc8'
@@ -226,6 +230,7 @@
'parents',
'revision'
]),
+ 'haveparents': True,
'nodes': [
'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
'\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc'
@@ -237,6 +242,7 @@
'parents',
'revision'
]),
+ 'haveparents': True,
'nodes': [
'\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16'
],
@@ -317,6 +323,7 @@
'parents',
'revision'
]),
+ 'haveparents': True,
'nodes': [
'\xec\x80NH\x8c \x88\xc25\t\x9a\x10 u\x13\xbe\xcd\xc3\xdd\xa5',
'\x04\\\x7f9\'\xda\x13\xe7Z\xf8\xf0\xe4\xf0HI\xe4a\xa9x\x0f',
@@ -333,6 +340,7 @@
'parents',
'revision'
]),
+ 'haveparents': True,
'nodes': [
'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
'\xc2\xa2\x05\xc8\xb2\xad\xe2J\xf2`b\xe5<\xd5\xbc8\x01\xd6`\xda'
@@ -344,6 +352,7 @@
'parents',
'revision'
]),
+ 'haveparents': True,
'nodes': [
'\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16',
'\xb1zk\xd3g=\x9a\xb8\xce\xd5\x81\xa2\t\xf6/=\xa5\xccEx',
@@ -498,6 +507,7 @@
'parents',
'revision'
]),
+ 'haveparents': True,
'nodes': [
'\x99/Gy\x02\x9a=\xf8\xd0fm\x00\xbb\x92OicN&A',
'\xa9\x88\xfbCX>\x87\x1d\x1e\xd5u\x0e\xe0t\xc6\xd8@\xbb\xbf\xc8',
@@ -516,6 +526,7 @@
'parents',
'revision'
]),
+ 'haveparents': True,
'nodes': [
'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
'\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc',
@@ -528,6 +539,7 @@
'parents',
'revision'
]),
+ 'haveparents': True,
'nodes': [
'\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16',
'\xb1zk\xd3g=\x9a\xb8\xce\xd5\x81\xa2\t\xf6/=\xa5\xccEx',
diff --git a/tests/test-wireproto-command-manifestdata.t b/tests/test-wireproto-command-manifestdata.t
--- a/tests/test-wireproto-command-manifestdata.t
+++ b/tests/test-wireproto-command-manifestdata.t
@@ -248,6 +248,7 @@
]
Requesting revision data works
+(haveparents defaults to false, so fulltext is emitted)
$ sendhttpv2peer << EOF
> command manifestdata
@@ -278,6 +279,124 @@
s> \xa1FstatusBok
s> \r\n
received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
+ s> 167\r\n
+ s> _\x01\x00\x01\x00\x02\x001
+ s> \xa1Jtotalitems\x01\xa2DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Lrevisionsize\x19\x01$Y\x01$a\x000879345e39377229634b420c639454156726c6b6\n
+ s> b\x00819e258d31a5e1606629f365bb902a1b21ee4216\n
+ s> dir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\n
+ s> dir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\n
+ s> dir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\n
+ s> dir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n
+ s> \r\n
+ received frame(size=351; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
+ s> 8\r\n
+ s> \x00\x00\x00\x01\x00\x02\x002
+ s> \r\n
+ s> 0\r\n
+ s> \r\n
+ received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
+ response: gen[
+ {
+ b'totalitems': 1
+ },
+ {
+ b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0',
+ b'revisionsize': 292
+ },
+ b'a\x000879345e39377229634b420c639454156726c6b6\nb\x00819e258d31a5e1606629f365bb902a1b21ee4216\ndir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\ndir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\ndir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\ndir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n'
+ ]
+
+haveparents=False yields same output
+
+ $ sendhttpv2peer << EOF
+ > command manifestdata
+ > nodes eval:[b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0']
+ > tree eval:b''
+ > fields eval:[b'revision']
+ > haveparents eval:False
+ > EOF
+ creating http peer for wire protocol version 2
+ sending manifestdata command
+ s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
+ s> Accept-Encoding: identity\r\n
+ s> accept: application/mercurial-exp-framing-0005\r\n
+ s> content-type: application/mercurial-exp-framing-0005\r\n
+ s> content-length: 97\r\n
+ s> host: $LOCALIP:$HGPORT\r\n (glob)
+ s> user-agent: Mercurial debugwireproto\r\n
+ s> \r\n
+ s> Y\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa4Ffields\x81HrevisionKhaveparents\xf4Enodes\x81TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Dtree at DnameLmanifestdata
+ s> makefile('rb', None)
+ s> HTTP/1.1 200 OK\r\n
+ s> Server: testing stub value\r\n
+ s> Date: $HTTP_DATE$\r\n
+ s> Content-Type: application/mercurial-exp-framing-0005\r\n
+ s> Transfer-Encoding: chunked\r\n
+ s> \r\n
+ s> 13\r\n
+ s> \x0b\x00\x00\x01\x00\x02\x011
+ s> \xa1FstatusBok
+ s> \r\n
+ received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
+ s> 167\r\n
+ s> _\x01\x00\x01\x00\x02\x001
+ s> \xa1Jtotalitems\x01\xa2DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Lrevisionsize\x19\x01$Y\x01$a\x000879345e39377229634b420c639454156726c6b6\n
+ s> b\x00819e258d31a5e1606629f365bb902a1b21ee4216\n
+ s> dir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\n
+ s> dir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\n
+ s> dir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\n
+ s> dir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n
+ s> \r\n
+ received frame(size=351; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
+ s> 8\r\n
+ s> \x00\x00\x00\x01\x00\x02\x002
+ s> \r\n
+ s> 0\r\n
+ s> \r\n
+ received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
+ response: gen[
+ {
+ b'totalitems': 1
+ },
+ {
+ b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0',
+ b'revisionsize': 292
+ },
+ b'a\x000879345e39377229634b420c639454156726c6b6\nb\x00819e258d31a5e1606629f365bb902a1b21ee4216\ndir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\ndir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\ndir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\ndir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n'
+ ]
+
+haveparents=True will emit delta
+
+ $ sendhttpv2peer << EOF
+ > command manifestdata
+ > nodes eval:[b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0']
+ > tree eval:b''
+ > fields eval:[b'revision']
+ > haveparents eval:True
+ > EOF
+ creating http peer for wire protocol version 2
+ sending manifestdata command
+ s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
+ s> Accept-Encoding: identity\r\n
+ s> accept: application/mercurial-exp-framing-0005\r\n
+ s> content-type: application/mercurial-exp-framing-0005\r\n
+ s> content-length: 97\r\n
+ s> host: $LOCALIP:$HGPORT\r\n (glob)
+ s> user-agent: Mercurial debugwireproto\r\n
+ s> \r\n
+ s> Y\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa4Ffields\x81HrevisionKhaveparents\xf5Enodes\x81TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Dtree at DnameLmanifestdata
+ s> makefile('rb', None)
+ s> HTTP/1.1 200 OK\r\n
+ s> Server: testing stub value\r\n
+ s> Date: $HTTP_DATE$\r\n
+ s> Content-Type: application/mercurial-exp-framing-0005\r\n
+ s> Transfer-Encoding: chunked\r\n
+ s> \r\n
+ s> 13\r\n
+ s> \x0b\x00\x00\x01\x00\x02\x011
+ s> \xa1FstatusBok
+ s> \r\n
+ received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
s> 98\r\n
s> \x90\x00\x00\x01\x00\x02\x001
s> \xa1Jtotalitems\x01\xa3MdeltabasenodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Ideltasize\x187DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0X7\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n
@@ -302,6 +421,8 @@
]
Requesting multiple revisions works
+(haveparents defaults to false, so fulltext is emitted unless a parent
+has been emitted)
$ sendhttpv2peer << EOF
> command manifestdata
@@ -366,6 +487,72 @@
b'\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n'
]
+With haveparents=True, first revision is a delta instead of fulltext
+
+ $ sendhttpv2peer << EOF
+ > command manifestdata
+ > nodes eval:[b'\x1b\x17\x5b\x59\x5f\x02\x2c\xfa\xb5\xb8\x09\xcc\x0e\xd5\x51\xbd\x0b\x3f\xf5\xe4', b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0']
+ > tree eval:b''
+ > fields eval:[b'revision']
+ > haveparents eval:True
+ > EOF
+ creating http peer for wire protocol version 2
+ sending manifestdata command
+ s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
+ s> Accept-Encoding: identity\r\n
+ s> accept: application/mercurial-exp-framing-0005\r\n
+ s> content-type: application/mercurial-exp-framing-0005\r\n
+ s> content-length: 118\r\n
+ s> host: $LOCALIP:$HGPORT\r\n (glob)
+ s> user-agent: Mercurial debugwireproto\r\n
+ s> \r\n
+ s> n\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa4Ffields\x81HrevisionKhaveparents\xf5Enodes\x82T\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Dtree at DnameLmanifestdata
+ s> makefile('rb', None)
+ s> HTTP/1.1 200 OK\r\n
+ s> Server: testing stub value\r\n
+ s> Date: $HTTP_DATE$\r\n
+ s> Content-Type: application/mercurial-exp-framing-0005\r\n
+ s> Transfer-Encoding: chunked\r\n
+ s> \r\n
+ s> 13\r\n
+ s> \x0b\x00\x00\x01\x00\x02\x011
+ s> \xa1FstatusBok
+ s> \r\n
+ received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
+ s> 1ea\r\n
+ s> \xe2\x01\x00\x01\x00\x02\x001
+ s> \xa1Jtotalitems\x02\xa2DnodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Lrevisionsize\x19\x01$Y\x01$a\x002b4eb07319bfa077a40a2f04913659aef0da42da\n
+ s> b\x00819e258d31a5e1606629f365bb902a1b21ee4216\n
+ s> dir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\n
+ s> dir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\n
+ s> dir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\n
+ s> dir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n
+ s> \xa3MdeltabasenodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Ideltasize\x187DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0X7\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n
+ s> \r\n
+ received frame(size=482; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
+ s> 8\r\n
+ s> \x00\x00\x00\x01\x00\x02\x002
+ s> \r\n
+ s> 0\r\n
+ s> \r\n
+ received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
+ response: gen[
+ {
+ b'totalitems': 2
+ },
+ {
+ b'node': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
+ b'revisionsize': 292
+ },
+ b'a\x002b4eb07319bfa077a40a2f04913659aef0da42da\nb\x00819e258d31a5e1606629f365bb902a1b21ee4216\ndir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\ndir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\ndir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\ndir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n',
+ {
+ b'deltabasenode': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
+ b'deltasize': 55,
+ b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0'
+ },
+ b'\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n'
+ ]
+
Revisions are sorted by DAG order, parents first
$ sendhttpv2peer << EOF
diff --git a/tests/test-wireproto-command-filedata.t b/tests/test-wireproto-command-filedata.t
--- a/tests/test-wireproto-command-filedata.t
+++ b/tests/test-wireproto-command-filedata.t
@@ -253,6 +253,7 @@
]
Requesting revision data works
+(haveparents defaults to False, so fulltext is emitted)
$ sendhttpv2peer << EOF
> command filedata
@@ -283,6 +284,114 @@
s> \xa1FstatusBok
s> \r\n
received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
+ s> 42\r\n
+ s> :\x00\x00\x01\x00\x02\x001
+ s> \xa1Jtotalitems\x01\xa2DnodeT\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccLrevisionsize\x03Ca1\n
+ s> \r\n
+ received frame(size=58; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
+ s> 8\r\n
+ s> \x00\x00\x00\x01\x00\x02\x002
+ s> \r\n
+ s> 0\r\n
+ s> \r\n
+ received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
+ response: gen[
+ {
+ b'totalitems': 1
+ },
+ {
+ b'node': b'\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc',
+ b'revisionsize': 3
+ },
+ b'a1\n'
+ ]
+
+haveparents=False should be same as above
+
+ $ sendhttpv2peer << EOF
+ > command filedata
+ > nodes eval:[b'\x9a\x38\x12\x29\x97\xb3\xac\x97\xbe\x2a\x9a\xa2\xe5\x56\x83\x83\x41\xfd\xf2\xcc']
+ > path eval:b'a'
+ > fields eval:[b'revision']
+ > haveparents eval:False
+ > EOF
+ creating http peer for wire protocol version 2
+ sending filedata command
+ s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
+ s> Accept-Encoding: identity\r\n
+ s> accept: application/mercurial-exp-framing-0005\r\n
+ s> content-type: application/mercurial-exp-framing-0005\r\n
+ s> content-length: 94\r\n
+ s> host: $LOCALIP:$HGPORT\r\n (glob)
+ s> user-agent: Mercurial debugwireproto\r\n
+ s> \r\n
+ s> V\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa4Ffields\x81HrevisionKhaveparents\xf4Enodes\x81T\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccDpathAaDnameHfiledata
+ s> makefile('rb', None)
+ s> HTTP/1.1 200 OK\r\n
+ s> Server: testing stub value\r\n
+ s> Date: $HTTP_DATE$\r\n
+ s> Content-Type: application/mercurial-exp-framing-0005\r\n
+ s> Transfer-Encoding: chunked\r\n
+ s> \r\n
+ s> 13\r\n
+ s> \x0b\x00\x00\x01\x00\x02\x011
+ s> \xa1FstatusBok
+ s> \r\n
+ received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
+ s> 42\r\n
+ s> :\x00\x00\x01\x00\x02\x001
+ s> \xa1Jtotalitems\x01\xa2DnodeT\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccLrevisionsize\x03Ca1\n
+ s> \r\n
+ received frame(size=58; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
+ s> 8\r\n
+ s> \x00\x00\x00\x01\x00\x02\x002
+ s> \r\n
+ s> 0\r\n
+ s> \r\n
+ received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
+ response: gen[
+ {
+ b'totalitems': 1
+ },
+ {
+ b'node': b'\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc',
+ b'revisionsize': 3
+ },
+ b'a1\n'
+ ]
+
+haveparents=True should emit a delta
+
+ $ sendhttpv2peer << EOF
+ > command filedata
+ > nodes eval:[b'\x9a\x38\x12\x29\x97\xb3\xac\x97\xbe\x2a\x9a\xa2\xe5\x56\x83\x83\x41\xfd\xf2\xcc']
+ > path eval:b'a'
+ > fields eval:[b'revision']
+ > haveparents eval:True
+ > EOF
+ creating http peer for wire protocol version 2
+ sending filedata command
+ s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
+ s> Accept-Encoding: identity\r\n
+ s> accept: application/mercurial-exp-framing-0005\r\n
+ s> content-type: application/mercurial-exp-framing-0005\r\n
+ s> content-length: 94\r\n
+ s> host: $LOCALIP:$HGPORT\r\n (glob)
+ s> user-agent: Mercurial debugwireproto\r\n
+ s> \r\n
+ s> V\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa4Ffields\x81HrevisionKhaveparents\xf5Enodes\x81T\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccDpathAaDnameHfiledata
+ s> makefile('rb', None)
+ s> HTTP/1.1 200 OK\r\n
+ s> Server: testing stub value\r\n
+ s> Date: $HTTP_DATE$\r\n
+ s> Content-Type: application/mercurial-exp-framing-0005\r\n
+ s> Transfer-Encoding: chunked\r\n
+ s> \r\n
+ s> 13\r\n
+ s> \x0b\x00\x00\x01\x00\x02\x011
+ s> \xa1FstatusBok
+ s> \r\n
+ received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
s> 6e\r\n
s> f\x00\x00\x01\x00\x02\x001
s> \xa1Jtotalitems\x01\xa3MdeltabasenodeT+N\xb0s\x19\xbf\xa0w\xa4\n
@@ -308,7 +417,7 @@
]
Requesting multiple revisions works
-(first revision should be fulltext, subsequents are deltas)
+(first revision is a fulltext since haveparents=False by default)
$ sendhttpv2peer << EOF
> command filedata
@@ -465,13 +574,12 @@
s> \xa1FstatusBok
s> \r\n
received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
- s> a1\r\n
- s> \x99\x00\x00\x01\x00\x02\x001
- s> \xa1Jtotalitems\x01\xa4MdeltabasenodeT+N\xb0s\x19\xbf\xa0w\xa4\n
- s> /\x04\x916Y\xae\xf0\xdaB\xdaIdeltasize\x0fDnodeT\x08y4^97r)cKB\x0cc\x94T\x15g&\xc6\xb6Gparents\x82T+N\xb0s\x19\xbf\xa0w\xa4\n
- s> /\x04\x916Y\xae\xf0\xdaB\xdaT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00O\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03a2\n
+ s> 75\r\n
+ s> m\x00\x00\x01\x00\x02\x001
+ s> \xa1Jtotalitems\x01\xa3DnodeT\x08y4^97r)cKB\x0cc\x94T\x15g&\xc6\xb6Gparents\x82T+N\xb0s\x19\xbf\xa0w\xa4\n
+ s> /\x04\x916Y\xae\xf0\xdaB\xdaT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Lrevisionsize\x03Ca2\n
s> \r\n
- received frame(size=153; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
+ received frame(size=109; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
s> 8\r\n
s> \x00\x00\x00\x01\x00\x02\x002
s> \r\n
@@ -483,15 +591,14 @@
b'totalitems': 1
},
{
- b'deltabasenode': b'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
- b'deltasize': 15,
b'node': b'\x08y4^97r)cKB\x0cc\x94T\x15g&\xc6\xb6',
b'parents': [
b'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
- ]
+ ],
+ b'revisionsize': 3
},
- b'\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03a2\n'
+ b'a2\n'
]
$ cat error.log
diff --git a/tests/test-wireproto-command-capabilities.t b/tests/test-wireproto-command-capabilities.t
--- a/tests/test-wireproto-command-capabilities.t
+++ b/tests/test-wireproto-command-capabilities.t
@@ -212,7 +212,7 @@
s> Content-Type: application/mercurial-cbor\r\n
s> Content-Length: *\r\n (glob)
s> \r\n
- s> \xa3GapibaseDapi/Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xaaIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa3Ffields\xd9\x01\x02\x82GparentsHrevisionInoderange\x82\x81J0123456...\x81Iabcdef...Enodes\x81J0123456...Kpermissions\x81DpullHfiledata\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81J0123456...DpathGfoo.txtKpermissions\x81DpullEheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullLmanifestdata\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81J0123456...Dtree at Kpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyInamespaceBnsCnewCnewColdColdKpermissions\x81DpushKcompression\x81\xa1DnameDzlibQframingmediatypes\x81X&application/mercurial-exp-framing-0005Nrawrepoformats\x82LgeneraldeltaHrevlogv1Nv1capabilitiesY\x01\xc5batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
+ s> \xa3GapibaseDapi/Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xaaIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa3Ffields\xd9\x01\x02\x82GparentsHrevisionInoderange\x82\x81J0123456...\x81Iabcdef...Enodes\x81J0123456...Kpermissions\x81DpullHfiledata\xa2Dargs\xa4Ffields\x82GparentsHrevisionKhaveparents\xf5Enodes\x81J0123456...DpathGfoo.txtKpermissions\x81DpullEheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullLmanifestdata\xa2Dargs\xa4Ffields\x82GparentsHrevisionKhaveparents\xf5Enodes\x81J0123456...Dtree at Kpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyInamespaceBnsCnewCnewColdColdKpermissions\x81DpushKcompression\x81\xa1DnameDzlibQframingmediatypes\x81X&application/mercurial-exp-framing-0005Nrawrepoformats\x82LgeneraldeltaHrevlogv1Nv1capabilitiesY\x01\xc5batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
cbor> {
b'apibase': b'api/',
b'apis': {
@@ -258,6 +258,7 @@
b'parents',
b'revision'
],
+ b'haveparents': True,
b'nodes': [
b'0123456...'
],
@@ -307,6 +308,7 @@
b'parents',
b'revision'
],
+ b'haveparents': True,
b'nodes': [
b'0123456...'
],
@@ -367,7 +369,7 @@
s> Content-Type: application/mercurial-cbor\r\n
s> Content-Length: *\r\n (glob)
s> \r\n
- s> \xa3GapibaseDapi/Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xaaIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa3Ffields\xd9\x01\x02\x82GparentsHrevisionInoderange\x82\x81J0123456...\x81Iabcdef...Enodes\x81J0123456...Kpermissions\x81DpullHfiledata\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81J0123456...DpathGfoo.txtKpermissions\x81DpullEheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullLmanifestdata\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81J0123456...Dtree at Kpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyInamespaceBnsCnewCnewColdColdKpermissions\x81DpushKcompression\x81\xa1DnameDzlibQframingmediatypes\x81X&application/mercurial-exp-framing-0005Nrawrepoformats\x82LgeneraldeltaHrevlogv1Nv1capabilitiesY\x01\xc5batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
+ s> \xa3GapibaseDapi/Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xaaIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa3Ffields\xd9\x01\x02\x82GparentsHrevisionInoderange\x82\x81J0123456...\x81Iabcdef...Enodes\x81J0123456...Kpermissions\x81DpullHfiledata\xa2Dargs\xa4Ffields\x82GparentsHrevisionKhaveparents\xf5Enodes\x81J0123456...DpathGfoo.txtKpermissions\x81DpullEheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullLmanifestdata\xa2Dargs\xa4Ffields\x82GparentsHrevisionKhaveparents\xf5Enodes\x81J0123456...Dtree at Kpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyInamespaceBnsCnewCnewColdColdKpermissions\x81DpushKcompression\x81\xa1DnameDzlibQframingmediatypes\x81X&application/mercurial-exp-framing-0005Nrawrepoformats\x82LgeneraldeltaHrevlogv1Nv1capabilitiesY\x01\xc5batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
sending capabilities command
s> POST /api/exp-http-v2-0001/ro/capabilities HTTP/1.1\r\n
s> Accept-Encoding: identity\r\n
@@ -390,11 +392,11 @@
s> \xa1FstatusBok
s> \r\n
received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
- s> 2f4\r\n
- s> \xec\x02\x00\x01\x00\x02\x001
- s> \xa4Hcommands\xaaIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa3Ffields\xd9\x01\x02\x82GparentsHrevisionInoderange\x82\x81J0123456...\x81Iabcdef...Enodes\x81J0123456...Kpermissions\x81DpullHfiledata\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81J0123456...DpathGfoo.txtKpermissions\x81DpullEheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullLmanifestdata\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81J0123456...Dtree at Kpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyInamespaceBnsCnewCnewColdColdKpermissions\x81DpushKcompression\x81\xa1DnameDzlibQframingmediatypes\x81X&application/mercurial-exp-framing-0005Nrawrepoformats\x82LgeneraldeltaHrevlogv1
+ s> 30e\r\n
+ s> \x06\x03\x00\x01\x00\x02\x001
+ s> \xa4Hcommands\xaaIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa3Ffields\xd9\x01\x02\x82GparentsHrevisionInoderange\x82\x81J0123456...\x81Iabcdef...Enodes\x81J0123456...Kpermissions\x81DpullHfiledata\xa2Dargs\xa4Ffields\x82GparentsHrevisionKhaveparents\xf5Enodes\x81J0123456...DpathGfoo.txtKpermissions\x81DpullEheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullLmanifestdata\xa2Dargs\xa4Ffields\x82GparentsHrevisionKhaveparents\xf5Enodes\x81J0123456...Dtree at Kpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyInamespaceBnsCnewCnewColdColdKpermissions\x81DpushKcompression\x81\xa1DnameDzlibQframingmediatypes\x81X&application/mercurial-exp-framing-0005Nrawrepoformats\x82LgeneraldeltaHrevlogv1
s> \r\n
- received frame(size=748; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
+ received frame(size=774; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
s> 8\r\n
s> \x00\x00\x00\x01\x00\x02\x002
s> \r\n
@@ -444,6 +446,7 @@
b'parents',
b'revision'
],
+ b'haveparents': True,
b'nodes': [
b'0123456...'
],
@@ -493,6 +496,7 @@
b'parents',
b'revision'
],
+ b'haveparents': True,
b'nodes': [
b'0123456...'
],
diff --git a/tests/test-http-protocol.t b/tests/test-http-protocol.t
--- a/tests/test-http-protocol.t
+++ b/tests/test-http-protocol.t
@@ -313,7 +313,7 @@
s> Content-Type: application/mercurial-cbor\r\n
s> Content-Length: *\r\n (glob)
s> \r\n
- s> \xa3GapibaseDapi/Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xaaIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa3Ffields\xd9\x01\x02\x82GparentsHrevisionInoderange\x82\x81J0123456...\x81Iabcdef...Enodes\x81J0123456...Kpermissions\x81DpullHfiledata\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81J0123456...DpathGfoo.txtKpermissions\x81DpullEheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullLmanifestdata\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81J0123456...Dtree at Kpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyInamespaceBnsCnewCnewColdColdKpermissions\x81DpushKcompression\x81\xa1DnameDzlibQframingmediatypes\x81X&application/mercurial-exp-framing-0005Nrawrepoformats\x82LgeneraldeltaHrevlogv1Nv1capabilitiesY\x01\xc5batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
+ s> \xa3GapibaseDapi/Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xaaIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa3Ffields\xd9\x01\x02\x82GparentsHrevisionInoderange\x82\x81J0123456...\x81Iabcdef...Enodes\x81J0123456...Kpermissions\x81DpullHfiledata\xa2Dargs\xa4Ffields\x82GparentsHrevisionKhaveparents\xf5Enodes\x81J0123456...DpathGfoo.txtKpermissions\x81DpullEheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullLmanifestdata\xa2Dargs\xa4Ffields\x82GparentsHrevisionKhaveparents\xf5Enodes\x81J0123456...Dtree at Kpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyInamespaceBnsCnewCnewColdColdKpermissions\x81DpushKcompression\x81\xa1DnameDzlibQframingmediatypes\x81X&application/mercurial-exp-framing-0005Nrawrepoformats\x82LgeneraldeltaHrevlogv1Nv1capabilitiesY\x01\xc5batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
sending heads command
s> POST /api/exp-http-v2-0001/ro/heads HTTP/1.1\r\n
s> Accept-Encoding: identity\r\n
diff --git a/mercurial/wireprotov2server.py b/mercurial/wireprotov2server.py
--- a/mercurial/wireprotov2server.py
+++ b/mercurial/wireprotov2server.py
@@ -415,7 +415,7 @@
return proto.addcapabilities(repo, caps)
-def builddeltarequests(store, nodes):
+def builddeltarequests(store, nodes, haveparents):
"""Build a series of revision delta requests against a backend store.
Returns a list of revision numbers in the order they should be sent
@@ -430,50 +430,69 @@
revs = dagop.linearize({store.rev(n) for n in nodes}, store.parentrevs)
requests = []
+ seenrevs = set()
for rev in revs:
node = store.node(rev)
- parents = store.parents(node)
- deltaparent = store.node(store.deltaparent(rev))
+ parentnodes = store.parents(node)
+ parentrevs = [store.rev(n) for n in parentnodes]
+ deltabaserev = store.deltaparent(rev)
+ deltabasenode = store.node(deltabaserev)
- # There is a delta in storage. That means we can send the delta
- # efficiently.
+ # The choice of whether to send a fulltext revision or a delta and
+ # what delta to send is governed by a few factors.
#
- # But, the delta may be against a revision the receiver doesn't
- # have (e.g. shallow clone or when the delta isn't against a parent
- # revision). For now, we ignore the problem of shallow clone. As
- # long as a delta exists against a parent, we send it.
- # TODO allow arguments to control this behavior, as the receiver
- # may not have the base revision in some scenarios.
- if deltaparent != nullid and deltaparent in parents:
- basenode = deltaparent
+ # To send a delta, we need to ensure the receiver is capable of
+ # decoding it. And that requires the receiver to have the base
+ # revision the delta is against.
+ #
+ # We can only guarantee the receiver has the base revision if
+ # a) we've already sent the revision as part of this group
+ # b) the receiver has indicated they already have the revision.
+ # And the mechanism for "b" is the client indicating they have
+ # parent revisions. So this means we can only send the delta if
+ # it is sent before or it is against a delta and the receiver says
+ # they have a parent.
- # Else there is no delta parent in storage or the delta that is
- # # there isn't suitable. Let's use a delta against a parent
- # revision, if possible.
- #
- # There is room to check if the delta parent is in the ancestry of
- # this node. But there isn't an API on the manifest storage object
- # for that. So ignore this case for now.
+ # We can send storage delta if it is against a revision we've sent
+ # in this group.
+ if deltabaserev != nullrev and deltabaserev in seenrevs:
+ basenode = deltabasenode
+
+ # We can send storage delta if it is against a parent revision and
+ # the receiver indicates they have the parents.
+ elif (deltabaserev != nullrev and deltabaserev in parentrevs
+ and haveparents):
+ basenode = deltabasenode
- elif parents[0] != nullid:
- basenode = parents[0]
- elif parents[1] != nullid:
- basenode = parents[1]
+ # Otherwise the storage delta isn't appropriate. Fall back to
+ # using another delta, if possible.
- # No potential bases to delta against. Send a full revision.
+ # Use p1 if we've emitted it or receiver says they have it.
+ elif parentrevs[0] != nullrev and (
+ parentrevs[0] in seenrevs or haveparents):
+ basenode = parentnodes[0]
+
+ # Use p2 if we've emitted it or receiver says they have it.
+ elif parentrevs[1] != nullrev and (
+ parentrevs[1] in seenrevs or haveparents):
+ basenode = parentnodes[1]
+
+ # Nothing appropriate to delta against. Send the full revision.
else:
basenode = nullid
requests.append(changegroup.revisiondeltarequest(
node=node,
- p1node=parents[0],
- p2node=parents[1],
+ p1node=parentnodes[0],
+ p2node=parentnodes[1],
# Receiver deals with linknode resolution.
linknode=nullid,
basenode=basenode,
))
+ seenrevs.add(rev)
+
return revs, requests
def wireprotocommand(name, args=None, permission='push'):
@@ -674,12 +693,14 @@
@wireprotocommand('filedata',
args={
+ 'haveparents': True,
'nodes': [b'0123456...'],
'fields': [b'parents', b'revision'],
'path': b'foo.txt',
},
permission='pull')
-def filedata(repo, proto, nodes=None, fields=None, path=None):
+def filedata(repo, proto, haveparents=False, nodes=None, fields=None,
+ path=None):
fields = fields or set()
if nodes is None:
@@ -702,7 +723,7 @@
raise error.WireprotoCommandError('unknown file node: %s',
(hex(node),))
- revs, requests = builddeltarequests(store, nodes)
+ revs, requests = builddeltarequests(store, nodes, haveparents)
yield {
b'totalitems': len(revs),
@@ -804,11 +825,13 @@
@wireprotocommand('manifestdata',
args={
'nodes': [b'0123456...'],
+ 'haveparents': True,
'fields': [b'parents', b'revision'],
'tree': b'',
},
permission='pull')
-def manifestdata(repo, proto, nodes=None, fields=None, tree=None):
+def manifestdata(repo, proto, haveparents=False, nodes=None, fields=None,
+ tree=None):
fields = fields or set()
if nodes is None:
@@ -829,7 +852,7 @@
raise error.WireprotoCommandError(
'unknown node: %s', (node,))
- revs, requests = builddeltarequests(store, nodes)
+ revs, requests = builddeltarequests(store, nodes, haveparents)
yield {
b'totalitems': len(revs),
diff --git a/mercurial/help/internals/wireprotocolv2.txt b/mercurial/help/internals/wireprotocolv2.txt
--- a/mercurial/help/internals/wireprotocolv2.txt
+++ b/mercurial/help/internals/wireprotocolv2.txt
@@ -213,6 +213,14 @@
revision
The raw revision data for a file.
+haveparents
+ (bool) Whether the client has the parent revisions of all requested
+ nodes. If set, the server may emit revision data as deltas against
+ any parent revision. If not set, the server MUST only emit deltas for
+ revisions previously emitted by this command.
+
+ False is assumed in the absence of any value.
+
nodes
(array of bytestrings) File nodes whose data to retrieve.
@@ -349,6 +357,14 @@
revision
The raw revision data for the manifest.
+haveparents
+ (bool) Whether the client has the parent revisions of all requested
+ nodes. If set, the server may emit revision data as deltas against
+ any parent revision. If not set, the server MUST only emit deltas for
+ revisions previously emitted by this command.
+
+ False is assumed in the absence of any value.
+
nodes
(array of bytestring) Manifest nodes whose data to retrieve.
@@ -361,7 +377,6 @@
revisions or ranges)
TODO consider recursive expansion of manifests (with path filtering for
narrow use cases)
-TODO more control over whether to emit fulltexts or deltas
The response bytestream starts with a CBOR map describing the data that
follows. It has the following bytestring keys:
diff --git a/mercurial/exchangev2.py b/mercurial/exchangev2.py
--- a/mercurial/exchangev2.py
+++ b/mercurial/exchangev2.py
@@ -283,6 +283,7 @@
b'tree': b'',
b'nodes': batch,
b'fields': {b'parents', b'revision'},
+ b'haveparents': True,
}).result()
# Chomp off header object.
@@ -374,7 +375,8 @@
fs.append((path, e.callcommand(b'filedata', {
b'path': path,
b'nodes': sorted(nodes),
- b'fields': {b'parents', b'revision'}
+ b'fields': {b'parents', b'revision'},
+ b'haveparents': True,
})))
locallinkrevs[path] = {
To: indygreg, #hg-reviewers, durin42
Cc: mercurial-devel
More information about the Mercurial-devel
mailing list