Show More
@@ -0,0 +1,473 b'' | |||||
|
1 | =========================== | |||
|
2 | Tests for sidedata exchange | |||
|
3 | =========================== | |||
|
4 | ||||
|
5 | Check simple exchange behavior | |||
|
6 | ============================== | |||
|
7 | ||||
|
8 | Pusher and pushed have sidedata enabled | |||
|
9 | --------------------------------------- | |||
|
10 | ||||
|
11 | $ hg init sidedata-source --config format.exp-use-side-data=yes | |||
|
12 | $ cat << EOF >> sidedata-source/.hg/hgrc | |||
|
13 | > [extensions] | |||
|
14 | > testsidedata=$TESTDIR/testlib/ext-sidedata-5.py | |||
|
15 | > EOF | |||
|
16 | $ hg init sidedata-target --config format.exp-use-side-data=yes | |||
|
17 | $ cat << EOF >> sidedata-target/.hg/hgrc | |||
|
18 | > [extensions] | |||
|
19 | > testsidedata=$TESTDIR/testlib/ext-sidedata-5.py | |||
|
20 | > EOF | |||
|
21 | $ cd sidedata-source | |||
|
22 | $ echo a > a | |||
|
23 | $ echo b > b | |||
|
24 | $ echo c > c | |||
|
25 | $ hg commit -Am "initial" | |||
|
26 | adding a | |||
|
27 | adding b | |||
|
28 | adding c | |||
|
29 | $ echo aa > a | |||
|
30 | $ hg commit -m "other" | |||
|
31 | $ hg push -r . ../sidedata-target | |||
|
32 | pushing to ../sidedata-target | |||
|
33 | searching for changes | |||
|
34 | adding changesets | |||
|
35 | adding manifests | |||
|
36 | adding file changes | |||
|
37 | added 2 changesets with 4 changes to 3 files | |||
|
38 | $ hg -R ../sidedata-target debugsidedata -c 0 | |||
|
39 | 2 sidedata entries | |||
|
40 | entry-0001 size 4 | |||
|
41 | entry-0002 size 32 | |||
|
42 | $ hg -R ../sidedata-target debugsidedata -c 1 -v | |||
|
43 | 2 sidedata entries | |||
|
44 | entry-0001 size 4 | |||
|
45 | '\x00\x00\x00:' | |||
|
46 | entry-0002 size 32 | |||
|
47 | '\xa3\xee4v\x99\x85$\x9f\x1f\x8dKe\x0f\xc3\x9d-\xc9\xb5%[\x15=h\xe9\xf2O\xb5\xd9\x1f*\xff\xe5' | |||
|
48 | $ hg -R ../sidedata-target debugsidedata -m 0 | |||
|
49 | 2 sidedata entries | |||
|
50 | entry-0001 size 4 | |||
|
51 | entry-0002 size 32 | |||
|
52 | $ hg -R ../sidedata-target debugsidedata -m 1 -v | |||
|
53 | 2 sidedata entries | |||
|
54 | entry-0001 size 4 | |||
|
55 | '\x00\x00\x00\x81' | |||
|
56 | entry-0002 size 32 | |||
|
57 | '-bL\xc5\xa4uu"#\xac\x1b`,\xc0\xbc\x9d\xf5\xac\xf0\x1d\x89)2\xf8N\xb1\x14m\xce\xd7\xbc\xae' | |||
|
58 | $ hg -R ../sidedata-target debugsidedata a 0 | |||
|
59 | 2 sidedata entries | |||
|
60 | entry-0001 size 4 | |||
|
61 | entry-0002 size 32 | |||
|
62 | $ hg -R ../sidedata-target debugsidedata a 1 -v | |||
|
63 | 2 sidedata entries | |||
|
64 | entry-0001 size 4 | |||
|
65 | '\x00\x00\x00\x03' | |||
|
66 | entry-0002 size 32 | |||
|
67 | '\xd9\xcd\x81UvL5C\xf1\x0f\xad\x8aH\rt17Fo\x8dU!<\x8e\xae\xfc\xd1/\x06\xd4:\x80' | |||
|
68 | $ cd .. | |||
|
69 | ||||
|
70 | Puller and pulled have sidedata enabled | |||
|
71 | --------------------------------------- | |||
|
72 | ||||
|
73 | $ rm -rf sidedata-source sidedata-target | |||
|
74 | $ hg init sidedata-source --config format.exp-use-side-data=yes | |||
|
75 | $ cat << EOF >> sidedata-source/.hg/hgrc | |||
|
76 | > [extensions] | |||
|
77 | > testsidedata=$TESTDIR/testlib/ext-sidedata-5.py | |||
|
78 | > EOF | |||
|
79 | $ hg init sidedata-target --config format.exp-use-side-data=yes | |||
|
80 | $ cat << EOF >> sidedata-target/.hg/hgrc | |||
|
81 | > [extensions] | |||
|
82 | > testsidedata=$TESTDIR/testlib/ext-sidedata-5.py | |||
|
83 | > EOF | |||
|
84 | $ cd sidedata-source | |||
|
85 | $ echo a > a | |||
|
86 | $ echo b > b | |||
|
87 | $ echo c > c | |||
|
88 | $ hg commit -Am "initial" | |||
|
89 | adding a | |||
|
90 | adding b | |||
|
91 | adding c | |||
|
92 | $ echo aa > a | |||
|
93 | $ hg commit -m "other" | |||
|
94 | $ hg pull -R ../sidedata-target ../sidedata-source | |||
|
95 | pulling from ../sidedata-source | |||
|
96 | requesting all changes | |||
|
97 | adding changesets | |||
|
98 | adding manifests | |||
|
99 | adding file changes | |||
|
100 | added 2 changesets with 4 changes to 3 files | |||
|
101 | new changesets 05da661850d7:7ec8b4049447 | |||
|
102 | (run 'hg update' to get a working copy) | |||
|
103 | $ hg -R ../sidedata-target debugsidedata -c 0 | |||
|
104 | 2 sidedata entries | |||
|
105 | entry-0001 size 4 | |||
|
106 | entry-0002 size 32 | |||
|
107 | $ hg -R ../sidedata-target debugsidedata -c 1 -v | |||
|
108 | 2 sidedata entries | |||
|
109 | entry-0001 size 4 | |||
|
110 | '\x00\x00\x00:' | |||
|
111 | entry-0002 size 32 | |||
|
112 | '\xa3\xee4v\x99\x85$\x9f\x1f\x8dKe\x0f\xc3\x9d-\xc9\xb5%[\x15=h\xe9\xf2O\xb5\xd9\x1f*\xff\xe5' | |||
|
113 | $ hg -R ../sidedata-target debugsidedata -m 0 | |||
|
114 | 2 sidedata entries | |||
|
115 | entry-0001 size 4 | |||
|
116 | entry-0002 size 32 | |||
|
117 | $ hg -R ../sidedata-target debugsidedata -m 1 -v | |||
|
118 | 2 sidedata entries | |||
|
119 | entry-0001 size 4 | |||
|
120 | '\x00\x00\x00\x81' | |||
|
121 | entry-0002 size 32 | |||
|
122 | '-bL\xc5\xa4uu"#\xac\x1b`,\xc0\xbc\x9d\xf5\xac\xf0\x1d\x89)2\xf8N\xb1\x14m\xce\xd7\xbc\xae' | |||
|
123 | $ hg -R ../sidedata-target debugsidedata a 0 | |||
|
124 | 2 sidedata entries | |||
|
125 | entry-0001 size 4 | |||
|
126 | entry-0002 size 32 | |||
|
127 | $ hg -R ../sidedata-target debugsidedata a 1 -v | |||
|
128 | 2 sidedata entries | |||
|
129 | entry-0001 size 4 | |||
|
130 | '\x00\x00\x00\x03' | |||
|
131 | entry-0002 size 32 | |||
|
132 | '\xd9\xcd\x81UvL5C\xf1\x0f\xad\x8aH\rt17Fo\x8dU!<\x8e\xae\xfc\xd1/\x06\xd4:\x80' | |||
|
133 | $ cd .. | |||
|
134 | ||||
|
135 | Now on to asymmetric configs. | |||
|
136 | ||||
|
137 | Pusher has sidedata enabled, pushed does not | |||
|
138 | -------------------------------------------- | |||
|
139 | ||||
|
140 | $ rm -rf sidedata-source sidedata-target | |||
|
141 | $ hg init sidedata-source --config format.exp-use-side-data=yes | |||
|
142 | $ cat << EOF >> sidedata-source/.hg/hgrc | |||
|
143 | > [extensions] | |||
|
144 | > testsidedata=$TESTDIR/testlib/ext-sidedata-5.py | |||
|
145 | > EOF | |||
|
146 | $ hg init sidedata-target --config format.exp-use-side-data=no | |||
|
147 | $ cd sidedata-source | |||
|
148 | $ echo a > a | |||
|
149 | $ echo b > b | |||
|
150 | $ echo c > c | |||
|
151 | $ hg commit -Am "initial" | |||
|
152 | adding a | |||
|
153 | adding b | |||
|
154 | adding c | |||
|
155 | $ echo aa > a | |||
|
156 | $ hg commit -m "other" | |||
|
157 | $ hg push -r . ../sidedata-target --traceback | |||
|
158 | pushing to ../sidedata-target | |||
|
159 | searching for changes | |||
|
160 | adding changesets | |||
|
161 | adding manifests | |||
|
162 | adding file changes | |||
|
163 | added 2 changesets with 4 changes to 3 files | |||
|
164 | $ hg -R ../sidedata-target log -G | |||
|
165 | o changeset: 1:7ec8b4049447 | |||
|
166 | | tag: tip | |||
|
167 | | user: test | |||
|
168 | | date: Thu Jan 01 00:00:00 1970 +0000 | |||
|
169 | | summary: other | |||
|
170 | | | |||
|
171 | o changeset: 0:05da661850d7 | |||
|
172 | user: test | |||
|
173 | date: Thu Jan 01 00:00:00 1970 +0000 | |||
|
174 | summary: initial | |||
|
175 | ||||
|
176 | ||||
|
177 | $ hg -R ../sidedata-target debugsidedata -c 0 | |||
|
178 | $ hg -R ../sidedata-target debugsidedata -c 1 -v | |||
|
179 | $ hg -R ../sidedata-target debugsidedata -m 0 | |||
|
180 | $ hg -R ../sidedata-target debugsidedata -m 1 -v | |||
|
181 | $ hg -R ../sidedata-target debugsidedata a 0 | |||
|
182 | $ hg -R ../sidedata-target debugsidedata a 1 -v | |||
|
183 | $ cd .. | |||
|
184 | ||||
|
185 | Pulled has sidedata enabled, puller does not | |||
|
186 | -------------------------------------------- | |||
|
187 | ||||
|
188 | $ rm -rf sidedata-source sidedata-target | |||
|
189 | $ hg init sidedata-source --config format.exp-use-side-data=yes | |||
|
190 | $ cat << EOF >> sidedata-source/.hg/hgrc | |||
|
191 | > [extensions] | |||
|
192 | > testsidedata=$TESTDIR/testlib/ext-sidedata-5.py | |||
|
193 | > EOF | |||
|
194 | $ hg init sidedata-target --config format.exp-use-side-data=no | |||
|
195 | $ cd sidedata-source | |||
|
196 | $ echo a > a | |||
|
197 | $ echo b > b | |||
|
198 | $ echo c > c | |||
|
199 | $ hg commit -Am "initial" | |||
|
200 | adding a | |||
|
201 | adding b | |||
|
202 | adding c | |||
|
203 | $ echo aa > a | |||
|
204 | $ hg commit -m "other" | |||
|
205 | $ hg pull -R ../sidedata-target ../sidedata-source | |||
|
206 | pulling from ../sidedata-source | |||
|
207 | requesting all changes | |||
|
208 | adding changesets | |||
|
209 | adding manifests | |||
|
210 | adding file changes | |||
|
211 | added 2 changesets with 4 changes to 3 files | |||
|
212 | new changesets 05da661850d7:7ec8b4049447 | |||
|
213 | (run 'hg update' to get a working copy) | |||
|
214 | $ hg -R ../sidedata-target log -G | |||
|
215 | o changeset: 1:7ec8b4049447 | |||
|
216 | | tag: tip | |||
|
217 | | user: test | |||
|
218 | | date: Thu Jan 01 00:00:00 1970 +0000 | |||
|
219 | | summary: other | |||
|
220 | | | |||
|
221 | o changeset: 0:05da661850d7 | |||
|
222 | user: test | |||
|
223 | date: Thu Jan 01 00:00:00 1970 +0000 | |||
|
224 | summary: initial | |||
|
225 | ||||
|
226 | ||||
|
227 | $ hg -R ../sidedata-target debugsidedata -c 0 | |||
|
228 | $ hg -R ../sidedata-target debugsidedata -c 1 -v | |||
|
229 | $ hg -R ../sidedata-target debugsidedata -m 0 | |||
|
230 | $ hg -R ../sidedata-target debugsidedata -m 1 -v | |||
|
231 | $ hg -R ../sidedata-target debugsidedata a 0 | |||
|
232 | $ hg -R ../sidedata-target debugsidedata a 1 -v | |||
|
233 | $ cd .. | |||
|
234 | ||||
|
235 | ||||
|
236 | Check sidedata exchange with on-the-fly generation and removal | |||
|
237 | ============================================================== | |||
|
238 | ||||
|
239 | (Push) Target has strict superset of the source | |||
|
240 | ----------------------------------------------- | |||
|
241 | ||||
|
242 | $ hg init source-repo --config format.exp-use-side-data=yes | |||
|
243 | $ hg init target-repo --config format.exp-use-side-data=yes | |||
|
244 | $ cat << EOF >> target-repo/.hg/hgrc | |||
|
245 | > [extensions] | |||
|
246 | > testsidedata=$TESTDIR/testlib/ext-sidedata.py | |||
|
247 | > EOF | |||
|
248 | $ cd source-repo | |||
|
249 | $ echo aaa > a | |||
|
250 | $ hg add a | |||
|
251 | $ hg commit -m a | |||
|
252 | $ echo aaa > b | |||
|
253 | $ hg add b | |||
|
254 | $ hg commit -m b | |||
|
255 | $ echo xxx >> a | |||
|
256 | $ hg commit -m aa | |||
|
257 | ||||
|
258 | No sidedata is generated in the source | |||
|
259 | $ hg debugsidedata -c 0 | |||
|
260 | ||||
|
261 | Check that sidedata capabilities are advertised | |||
|
262 | $ hg debugcapabilities ../target-repo | grep sidedata | |||
|
263 | exp-wanted-sidedata=1,2 | |||
|
264 | ||||
|
265 | We expect the client to abort the push since it's not capable of generating | |||
|
266 | what the server is asking | |||
|
267 | $ hg push -r . ../target-repo | |||
|
268 | pushing to ../target-repo | |||
|
269 | abort: cannot push: required sidedata category not supported by this client: '1' | |||
|
270 | [255] | |||
|
271 | ||||
|
272 | Add the required capabilities | |||
|
273 | $ cat << EOF >> .hg/hgrc | |||
|
274 | > [extensions] | |||
|
275 | > testsidedata2=$TESTDIR/testlib/ext-sidedata-2.py | |||
|
276 | > EOF | |||
|
277 | ||||
|
278 | We expect the target to have sidedata that was generated by the source on push | |||
|
279 | $ hg push -r . ../target-repo | |||
|
280 | pushing to ../target-repo | |||
|
281 | searching for changes | |||
|
282 | adding changesets | |||
|
283 | adding manifests | |||
|
284 | adding file changes | |||
|
285 | added 3 changesets with 3 changes to 2 files | |||
|
286 | $ cd ../target-repo | |||
|
287 | $ hg debugsidedata -c 0 | |||
|
288 | 2 sidedata entries | |||
|
289 | entry-0001 size 4 | |||
|
290 | entry-0002 size 32 | |||
|
291 | $ hg debugsidedata -c 1 -v | |||
|
292 | 2 sidedata entries | |||
|
293 | entry-0001 size 4 | |||
|
294 | '\x00\x00\x006' | |||
|
295 | entry-0002 size 32 | |||
|
296 | '\x98\t\xf9\xc4v\xf0\xc5P\x90\xf7wRf\xe8\xe27e\xfc\xc1\x93\xa4\x96\xd0\x1d\x97\xaaG\x1d\xd7t\xfa\xde' | |||
|
297 | $ hg debugsidedata -m 2 | |||
|
298 | 2 sidedata entries | |||
|
299 | entry-0001 size 4 | |||
|
300 | entry-0002 size 32 | |||
|
301 | $ hg debugsidedata a 1 | |||
|
302 | 2 sidedata entries | |||
|
303 | entry-0001 size 4 | |||
|
304 | entry-0002 size 32 | |||
|
305 | $ cd .. | |||
|
306 | ||||
|
307 | (Push) Difference is not subset/superset | |||
|
308 | ---------------------------------------- | |||
|
309 | ||||
|
310 | Source has one in common, one missing and one more sidedata category with the | |||
|
311 | target. | |||
|
312 | ||||
|
313 | $ rm -rf source-repo target-repo | |||
|
314 | $ hg init source-repo --config format.exp-use-side-data=yes | |||
|
315 | $ cat << EOF >> source-repo/.hg/hgrc | |||
|
316 | > [extensions] | |||
|
317 | > testsidedata3=$TESTDIR/testlib/ext-sidedata-3.py | |||
|
318 | > EOF | |||
|
319 | $ hg init target-repo --config format.exp-use-side-data=yes | |||
|
320 | $ cat << EOF >> target-repo/.hg/hgrc | |||
|
321 | > [extensions] | |||
|
322 | > testsidedata4=$TESTDIR/testlib/ext-sidedata-4.py | |||
|
323 | > EOF | |||
|
324 | $ cd source-repo | |||
|
325 | $ echo aaa > a | |||
|
326 | $ hg add a | |||
|
327 | $ hg commit -m a | |||
|
328 | $ echo aaa > b | |||
|
329 | $ hg add b | |||
|
330 | $ hg commit -m b | |||
|
331 | $ echo xxx >> a | |||
|
332 | $ hg commit -m aa | |||
|
333 | ||||
|
334 | Check that sidedata capabilities are advertised | |||
|
335 | $ hg debugcapabilities . | grep sidedata | |||
|
336 | exp-wanted-sidedata=1,2 | |||
|
337 | $ hg debugcapabilities ../target-repo | grep sidedata | |||
|
338 | exp-wanted-sidedata=2,3 | |||
|
339 | ||||
|
340 | Sidedata is generated in the source, but only the right categories (entry-0001 and entry-0002) | |||
|
341 | $ hg debugsidedata -c 0 | |||
|
342 | 2 sidedata entries | |||
|
343 | entry-0001 size 4 | |||
|
344 | entry-0002 size 32 | |||
|
345 | $ hg debugsidedata -c 1 -v | |||
|
346 | 2 sidedata entries | |||
|
347 | entry-0001 size 4 | |||
|
348 | '\x00\x00\x006' | |||
|
349 | entry-0002 size 32 | |||
|
350 | '\x98\t\xf9\xc4v\xf0\xc5P\x90\xf7wRf\xe8\xe27e\xfc\xc1\x93\xa4\x96\xd0\x1d\x97\xaaG\x1d\xd7t\xfa\xde' | |||
|
351 | $ hg debugsidedata -m 2 | |||
|
352 | 2 sidedata entries | |||
|
353 | entry-0001 size 4 | |||
|
354 | entry-0002 size 32 | |||
|
355 | $ hg debugsidedata a 1 | |||
|
356 | 2 sidedata entries | |||
|
357 | entry-0001 size 4 | |||
|
358 | entry-0002 size 32 | |||
|
359 | ||||
|
360 | ||||
|
361 | We expect the target to have sidedata that was generated by the source on push, | |||
|
362 | and also removed the sidedata categories that are not supported by the target. | |||
|
363 | Namely, we expect entry-0002 (only exchanged) and entry-0003 (generated), | |||
|
364 | but not entry-0001. | |||
|
365 | ||||
|
366 | $ hg push -r . ../target-repo --traceback | |||
|
367 | pushing to ../target-repo | |||
|
368 | searching for changes | |||
|
369 | adding changesets | |||
|
370 | adding manifests | |||
|
371 | adding file changes | |||
|
372 | added 3 changesets with 3 changes to 2 files | |||
|
373 | $ cd ../target-repo | |||
|
374 | $ hg log -G | |||
|
375 | o changeset: 2:40f977031323 | |||
|
376 | | tag: tip | |||
|
377 | | user: test | |||
|
378 | | date: Thu Jan 01 00:00:00 1970 +0000 | |||
|
379 | | summary: aa | |||
|
380 | | | |||
|
381 | o changeset: 1:2707720c6597 | |||
|
382 | | user: test | |||
|
383 | | date: Thu Jan 01 00:00:00 1970 +0000 | |||
|
384 | | summary: b | |||
|
385 | | | |||
|
386 | o changeset: 0:7049e48789d7 | |||
|
387 | user: test | |||
|
388 | date: Thu Jan 01 00:00:00 1970 +0000 | |||
|
389 | summary: a | |||
|
390 | ||||
|
391 | $ hg debugsidedata -c 0 | |||
|
392 | 2 sidedata entries | |||
|
393 | entry-0002 size 32 | |||
|
394 | entry-0003 size 48 | |||
|
395 | $ hg debugsidedata -c 1 -v | |||
|
396 | 2 sidedata entries | |||
|
397 | entry-0002 size 32 | |||
|
398 | '\x98\t\xf9\xc4v\xf0\xc5P\x90\xf7wRf\xe8\xe27e\xfc\xc1\x93\xa4\x96\xd0\x1d\x97\xaaG\x1d\xd7t\xfa\xde' | |||
|
399 | entry-0003 size 48 | |||
|
400 | '\x87\xcf\xdfI/\xb5\xed\xeaC\xc1\xf0S\xf3X\x1c\xcc\x00m\xee\xe6#\xc1\xe3\xcaB8Fk\x82e\xfc\xc01\xf6\xb7\xb9\xb3([\xf6D\xa6\xcf\x9b\xea\x11{\x08' | |||
|
401 | $ hg debugsidedata -m 2 | |||
|
402 | 2 sidedata entries | |||
|
403 | entry-0002 size 32 | |||
|
404 | entry-0003 size 48 | |||
|
405 | $ hg debugsidedata a 1 | |||
|
406 | 2 sidedata entries | |||
|
407 | entry-0002 size 32 | |||
|
408 | entry-0003 size 48 | |||
|
409 | $ cd .. | |||
|
410 | ||||
|
411 | (Pull) Target has strict superset of the source | |||
|
412 | ----------------------------------------------- | |||
|
413 | ||||
|
414 | $ rm -rf source-repo target-repo | |||
|
415 | $ hg init source-repo --config format.exp-use-side-data=yes | |||
|
416 | $ hg init target-repo --config format.exp-use-side-data=yes | |||
|
417 | $ cat << EOF >> target-repo/.hg/hgrc | |||
|
418 | > [extensions] | |||
|
419 | > testsidedata=$TESTDIR/testlib/ext-sidedata.py | |||
|
420 | > EOF | |||
|
421 | $ cd source-repo | |||
|
422 | $ echo aaa > a | |||
|
423 | $ hg add a | |||
|
424 | $ hg commit -m a | |||
|
425 | $ echo aaa > b | |||
|
426 | $ hg add b | |||
|
427 | $ hg commit -m b | |||
|
428 | $ echo xxx >> a | |||
|
429 | $ hg commit -m aa | |||
|
430 | ||||
|
431 | No sidedata is generated in the source | |||
|
432 | $ hg debugsidedata -c 0 | |||
|
433 | ||||
|
434 | Check that sidedata capabilities are advertised | |||
|
435 | $ hg debugcapabilities ../target-repo | grep sidedata | |||
|
436 | exp-wanted-sidedata=1,2 | |||
|
437 | ||||
|
438 | $ cd ../target-repo | |||
|
439 | ||||
|
440 | Add the required capabilities | |||
|
441 | $ cat << EOF >> .hg/hgrc | |||
|
442 | > [extensions] | |||
|
443 | > testsidedata2=$TESTDIR/testlib/ext-sidedata-2.py | |||
|
444 | > EOF | |||
|
445 | ||||
|
446 | We expect the target to have sidedata that it generated on-the-fly during pull | |||
|
447 | $ hg pull -r . ../source-repo --traceback | |||
|
448 | pulling from ../source-repo | |||
|
449 | adding changesets | |||
|
450 | adding manifests | |||
|
451 | adding file changes | |||
|
452 | added 3 changesets with 3 changes to 2 files | |||
|
453 | new changesets 7049e48789d7:40f977031323 | |||
|
454 | (run 'hg update' to get a working copy) | |||
|
455 | $ hg debugsidedata -c 0 --traceback | |||
|
456 | 2 sidedata entries | |||
|
457 | entry-0001 size 4 | |||
|
458 | entry-0002 size 32 | |||
|
459 | $ hg debugsidedata -c 1 -v --traceback | |||
|
460 | 2 sidedata entries | |||
|
461 | entry-0001 size 4 | |||
|
462 | '\x00\x00\x006' | |||
|
463 | entry-0002 size 32 | |||
|
464 | '\x98\t\xf9\xc4v\xf0\xc5P\x90\xf7wRf\xe8\xe27e\xfc\xc1\x93\xa4\x96\xd0\x1d\x97\xaaG\x1d\xd7t\xfa\xde' | |||
|
465 | $ hg debugsidedata -m 2 | |||
|
466 | 2 sidedata entries | |||
|
467 | entry-0001 size 4 | |||
|
468 | entry-0002 size 32 | |||
|
469 | $ hg debugsidedata a 1 | |||
|
470 | 2 sidedata entries | |||
|
471 | entry-0001 size 4 | |||
|
472 | entry-0002 size 32 | |||
|
473 | $ cd .. |
@@ -0,0 +1,81 b'' | |||||
|
1 | # coding: utf8 | |||
|
2 | # ext-sidedata-5.py - small extension to test (differently still) the sidedata | |||
|
3 | # logic | |||
|
4 | # | |||
|
5 | # Simulates a server for a simple sidedata exchange. | |||
|
6 | # | |||
|
7 | # Copyright 2021 Raphaël Gomès <rgomes@octobus.net> | |||
|
8 | # | |||
|
9 | # This software may be used and distributed according to the terms of the | |||
|
10 | # GNU General Public License version 2 or any later version. | |||
|
11 | ||||
|
12 | from __future__ import absolute_import | |||
|
13 | ||||
|
14 | import hashlib | |||
|
15 | import struct | |||
|
16 | ||||
|
17 | from mercurial import ( | |||
|
18 | extensions, | |||
|
19 | revlog, | |||
|
20 | ) | |||
|
21 | ||||
|
22 | ||||
|
23 | from mercurial.revlogutils import sidedata as sidedatamod | |||
|
24 | ||||
|
25 | ||||
|
26 | def compute_sidedata_1(repo, revlog, rev, sidedata, text=None): | |||
|
27 | sidedata = sidedata.copy() | |||
|
28 | if text is None: | |||
|
29 | text = revlog.revision(rev) | |||
|
30 | sidedata[sidedatamod.SD_TEST1] = struct.pack('>I', len(text)) | |||
|
31 | return sidedata | |||
|
32 | ||||
|
33 | ||||
|
34 | def compute_sidedata_2(repo, revlog, rev, sidedata, text=None): | |||
|
35 | sidedata = sidedata.copy() | |||
|
36 | if text is None: | |||
|
37 | text = revlog.revision(rev) | |||
|
38 | sha256 = hashlib.sha256(text).digest() | |||
|
39 | sidedata[sidedatamod.SD_TEST2] = struct.pack('>32s', sha256) | |||
|
40 | return sidedata | |||
|
41 | ||||
|
42 | ||||
|
43 | def reposetup(ui, repo): | |||
|
44 | # Sidedata keys happen to be the same as the categories, easier for testing. | |||
|
45 | for kind in (b'changelog', b'manifest', b'filelog'): | |||
|
46 | repo.register_sidedata_computer( | |||
|
47 | kind, | |||
|
48 | sidedatamod.SD_TEST1, | |||
|
49 | (sidedatamod.SD_TEST1,), | |||
|
50 | compute_sidedata_1, | |||
|
51 | ) | |||
|
52 | repo.register_sidedata_computer( | |||
|
53 | kind, | |||
|
54 | sidedatamod.SD_TEST2, | |||
|
55 | (sidedatamod.SD_TEST2,), | |||
|
56 | compute_sidedata_2, | |||
|
57 | ) | |||
|
58 | ||||
|
59 | # We don't register sidedata computers because we don't care within these | |||
|
60 | # tests | |||
|
61 | repo.register_wanted_sidedata(sidedatamod.SD_TEST1) | |||
|
62 | repo.register_wanted_sidedata(sidedatamod.SD_TEST2) | |||
|
63 | ||||
|
64 | ||||
|
65 | def wrapaddrevision( | |||
|
66 | orig, self, text, transaction, link, p1, p2, *args, **kwargs | |||
|
67 | ): | |||
|
68 | if kwargs.get('sidedata') is None: | |||
|
69 | kwargs['sidedata'] = {} | |||
|
70 | sd = kwargs['sidedata'] | |||
|
71 | ## let's store some arbitrary data just for testing | |||
|
72 | # text length | |||
|
73 | sd[sidedatamod.SD_TEST1] = struct.pack('>I', len(text)) | |||
|
74 | # and sha2 hashes | |||
|
75 | sha256 = hashlib.sha256(text).digest() | |||
|
76 | sd[sidedatamod.SD_TEST2] = struct.pack('>32s', sha256) | |||
|
77 | return orig(self, text, transaction, link, p1, p2, *args, **kwargs) | |||
|
78 | ||||
|
79 | ||||
|
80 | def extsetup(ui): | |||
|
81 | extensions.wrapfunction(revlog.revlog, 'addrevision', wrapaddrevision) |
@@ -7,6 +7,7 b'' | |||||
7 |
|
7 | |||
8 | from __future__ import absolute_import |
|
8 | from __future__ import absolute_import | |
9 |
|
9 | |||
|
10 | import collections | |||
10 | import os |
|
11 | import os | |
11 | import struct |
|
12 | import struct | |
12 | import weakref |
|
13 | import weakref | |
@@ -252,7 +253,7 b' class cg1unpacker(object):' | |||||
252 | pos = next |
|
253 | pos = next | |
253 | yield closechunk() |
|
254 | yield closechunk() | |
254 |
|
255 | |||
255 | def _unpackmanifests(self, repo, revmap, trp, prog): |
|
256 | def _unpackmanifests(self, repo, revmap, trp, prog, addrevisioncb=None): | |
256 | self.callback = prog.increment |
|
257 | self.callback = prog.increment | |
257 | # no need to check for empty manifest group here: |
|
258 | # no need to check for empty manifest group here: | |
258 | # if the result of the merge of 1 and 2 is the same in 3 and 4, |
|
259 | # if the result of the merge of 1 and 2 is the same in 3 and 4, | |
@@ -260,7 +261,8 b' class cg1unpacker(object):' | |||||
260 | # be empty during the pull |
|
261 | # be empty during the pull | |
261 | self.manifestheader() |
|
262 | self.manifestheader() | |
262 | deltas = self.deltaiter() |
|
263 | deltas = self.deltaiter() | |
263 |
repo.manifestlog.getstorage(b'') |
|
264 | storage = repo.manifestlog.getstorage(b'') | |
|
265 | storage.addgroup(deltas, revmap, trp, addrevisioncb=addrevisioncb) | |||
264 | prog.complete() |
|
266 | prog.complete() | |
265 | self.callback = None |
|
267 | self.callback = None | |
266 |
|
268 | |||
@@ -369,6 +371,13 b' class cg1unpacker(object):' | |||||
369 | efilesset = None |
|
371 | efilesset = None | |
370 | self.callback = None |
|
372 | self.callback = None | |
371 |
|
373 | |||
|
374 | # Keep track of the (non-changelog) revlogs we've updated and their | |||
|
375 | # range of new revisions for sidedata rewrite. | |||
|
376 | # TODO do something more efficient than keeping the reference to | |||
|
377 | # the revlogs, especially memory-wise. | |||
|
378 | touched_manifests = {} | |||
|
379 | touched_filelogs = {} | |||
|
380 | ||||
372 | # pull off the manifest group |
|
381 | # pull off the manifest group | |
373 | repo.ui.status(_(b"adding manifests\n")) |
|
382 | repo.ui.status(_(b"adding manifests\n")) | |
374 | # We know that we'll never have more manifests than we had |
|
383 | # We know that we'll never have more manifests than we had | |
@@ -376,7 +385,24 b' class cg1unpacker(object):' | |||||
376 | progress = repo.ui.makeprogress( |
|
385 | progress = repo.ui.makeprogress( | |
377 | _(b'manifests'), unit=_(b'chunks'), total=changesets |
|
386 | _(b'manifests'), unit=_(b'chunks'), total=changesets | |
378 | ) |
|
387 | ) | |
379 | self._unpackmanifests(repo, revmap, trp, progress) |
|
388 | on_manifest_rev = None | |
|
389 | if sidedata_helpers and b'manifest' in sidedata_helpers[1]: | |||
|
390 | ||||
|
391 | def on_manifest_rev(manifest, rev): | |||
|
392 | range = touched_manifests.get(manifest) | |||
|
393 | if not range: | |||
|
394 | touched_manifests[manifest] = (rev, rev) | |||
|
395 | else: | |||
|
396 | assert rev == range[1] + 1 | |||
|
397 | touched_manifests[manifest] = (range[0], rev) | |||
|
398 | ||||
|
399 | self._unpackmanifests( | |||
|
400 | repo, | |||
|
401 | revmap, | |||
|
402 | trp, | |||
|
403 | progress, | |||
|
404 | addrevisioncb=on_manifest_rev, | |||
|
405 | ) | |||
380 |
|
406 | |||
381 | needfiles = {} |
|
407 | needfiles = {} | |
382 | if repo.ui.configbool(b'server', b'validate'): |
|
408 | if repo.ui.configbool(b'server', b'validate'): | |
@@ -390,12 +416,37 b' class cg1unpacker(object):' | |||||
390 | for f, n in pycompat.iteritems(mfest): |
|
416 | for f, n in pycompat.iteritems(mfest): | |
391 | needfiles.setdefault(f, set()).add(n) |
|
417 | needfiles.setdefault(f, set()).add(n) | |
392 |
|
418 | |||
|
419 | on_filelog_rev = None | |||
|
420 | if sidedata_helpers and b'filelog' in sidedata_helpers[1]: | |||
|
421 | ||||
|
422 | def on_filelog_rev(filelog, rev): | |||
|
423 | range = touched_filelogs.get(filelog) | |||
|
424 | if not range: | |||
|
425 | touched_filelogs[filelog] = (rev, rev) | |||
|
426 | else: | |||
|
427 | assert rev == range[1] + 1 | |||
|
428 | touched_filelogs[filelog] = (range[0], rev) | |||
|
429 | ||||
393 | # process the files |
|
430 | # process the files | |
394 | repo.ui.status(_(b"adding file changes\n")) |
|
431 | repo.ui.status(_(b"adding file changes\n")) | |
395 | newrevs, newfiles = _addchangegroupfiles( |
|
432 | newrevs, newfiles = _addchangegroupfiles( | |
396 | repo, self, revmap, trp, efiles, needfiles |
|
433 | repo, | |
|
434 | self, | |||
|
435 | revmap, | |||
|
436 | trp, | |||
|
437 | efiles, | |||
|
438 | needfiles, | |||
|
439 | addrevisioncb=on_filelog_rev, | |||
397 | ) |
|
440 | ) | |
398 |
|
441 | |||
|
442 | if sidedata_helpers: | |||
|
443 | if b'changelog' in sidedata_helpers[1]: | |||
|
444 | cl.rewrite_sidedata(sidedata_helpers, clstart, clend - 1) | |||
|
445 | for mf, (startrev, endrev) in touched_manifests.items(): | |||
|
446 | mf.rewrite_sidedata(sidedata_helpers, startrev, endrev) | |||
|
447 | for fl, (startrev, endrev) in touched_filelogs.items(): | |||
|
448 | fl.rewrite_sidedata(sidedata_helpers, startrev, endrev) | |||
|
449 | ||||
399 | # making sure the value exists |
|
450 | # making sure the value exists | |
400 | tr.changes.setdefault(b'changegroup-count-changesets', 0) |
|
451 | tr.changes.setdefault(b'changegroup-count-changesets', 0) | |
401 | tr.changes.setdefault(b'changegroup-count-revisions', 0) |
|
452 | tr.changes.setdefault(b'changegroup-count-revisions', 0) | |
@@ -559,14 +610,18 b' class cg3unpacker(cg2unpacker):' | |||||
559 | node, p1, p2, deltabase, cs, flags = headertuple |
|
610 | node, p1, p2, deltabase, cs, flags = headertuple | |
560 | return node, p1, p2, deltabase, cs, flags |
|
611 | return node, p1, p2, deltabase, cs, flags | |
561 |
|
612 | |||
562 | def _unpackmanifests(self, repo, revmap, trp, prog): |
|
613 | def _unpackmanifests(self, repo, revmap, trp, prog, addrevisioncb=None): | |
563 |
super(cg3unpacker, self)._unpackmanifests( |
|
614 | super(cg3unpacker, self)._unpackmanifests( | |
|
615 | repo, revmap, trp, prog, addrevisioncb=addrevisioncb | |||
|
616 | ) | |||
564 | for chunkdata in iter(self.filelogheader, {}): |
|
617 | for chunkdata in iter(self.filelogheader, {}): | |
565 | # If we get here, there are directory manifests in the changegroup |
|
618 | # If we get here, there are directory manifests in the changegroup | |
566 | d = chunkdata[b"filename"] |
|
619 | d = chunkdata[b"filename"] | |
567 | repo.ui.debug(b"adding %s revisions\n" % d) |
|
620 | repo.ui.debug(b"adding %s revisions\n" % d) | |
568 | deltas = self.deltaiter() |
|
621 | deltas = self.deltaiter() | |
569 |
if not repo.manifestlog.getstorage(d).addgroup( |
|
622 | if not repo.manifestlog.getstorage(d).addgroup( | |
|
623 | deltas, revmap, trp, addrevisioncb=addrevisioncb | |||
|
624 | ): | |||
570 | raise error.Abort(_(b"received dir revlog group is empty")) |
|
625 | raise error.Abort(_(b"received dir revlog group is empty")) | |
571 |
|
626 | |||
572 |
|
627 | |||
@@ -1793,7 +1848,15 b' def makestream(' | |||||
1793 | return bundler.generate(commonrevs, csets, fastpathlinkrev, source) |
|
1848 | return bundler.generate(commonrevs, csets, fastpathlinkrev, source) | |
1794 |
|
1849 | |||
1795 |
|
1850 | |||
1796 | def _addchangegroupfiles(repo, source, revmap, trp, expectedfiles, needfiles): |
|
1851 | def _addchangegroupfiles( | |
|
1852 | repo, | |||
|
1853 | source, | |||
|
1854 | revmap, | |||
|
1855 | trp, | |||
|
1856 | expectedfiles, | |||
|
1857 | needfiles, | |||
|
1858 | addrevisioncb=None, | |||
|
1859 | ): | |||
1797 | revisions = 0 |
|
1860 | revisions = 0 | |
1798 | files = 0 |
|
1861 | files = 0 | |
1799 | progress = repo.ui.makeprogress( |
|
1862 | progress = repo.ui.makeprogress( | |
@@ -1808,7 +1871,13 b' def _addchangegroupfiles(repo, source, r' | |||||
1808 | o = len(fl) |
|
1871 | o = len(fl) | |
1809 | try: |
|
1872 | try: | |
1810 | deltas = source.deltaiter() |
|
1873 | deltas = source.deltaiter() | |
1811 |
|
|
1874 | added = fl.addgroup( | |
|
1875 | deltas, | |||
|
1876 | revmap, | |||
|
1877 | trp, | |||
|
1878 | addrevisioncb=addrevisioncb, | |||
|
1879 | ) | |||
|
1880 | if not added: | |||
1812 | raise error.Abort(_(b"received file revlog group is empty")) |
|
1881 | raise error.Abort(_(b"received file revlog group is empty")) | |
1813 | except error.CensoredBaseError as e: |
|
1882 | except error.CensoredBaseError as e: | |
1814 | raise error.Abort(_(b"received delta base is censored: %s") % e) |
|
1883 | raise error.Abort(_(b"received delta base is censored: %s") % e) |
@@ -3205,3 +3205,54 b' class revlog(object):' | |||||
3205 | ) |
|
3205 | ) | |
3206 |
|
3206 | |||
3207 | return d |
|
3207 | return d | |
|
3208 | ||||
|
3209 | def rewrite_sidedata(self, helpers, startrev, endrev): | |||
|
3210 | if self.version & 0xFFFF != REVLOGV2: | |||
|
3211 | return | |||
|
3212 | # inline are not yet supported because they suffer from an issue when | |||
|
3213 | # rewriting them (since it's not an append-only operation). | |||
|
3214 | # See issue6485. | |||
|
3215 | assert not self._inline | |||
|
3216 | if not helpers[1] and not helpers[2]: | |||
|
3217 | # Nothing to generate or remove | |||
|
3218 | return | |||
|
3219 | ||||
|
3220 | new_entries = [] | |||
|
3221 | # append the new sidedata | |||
|
3222 | with self._datafp(b'a+') as fp: | |||
|
3223 | # Maybe this bug still exists, see revlog._writeentry | |||
|
3224 | fp.seek(0, os.SEEK_END) | |||
|
3225 | current_offset = fp.tell() | |||
|
3226 | for rev in range(startrev, endrev + 1): | |||
|
3227 | entry = self.index[rev] | |||
|
3228 | new_sidedata = storageutil.run_sidedata_helpers( | |||
|
3229 | store=self, | |||
|
3230 | sidedata_helpers=helpers, | |||
|
3231 | sidedata={}, | |||
|
3232 | rev=rev, | |||
|
3233 | ) | |||
|
3234 | ||||
|
3235 | serialized_sidedata = sidedatautil.serialize_sidedata( | |||
|
3236 | new_sidedata | |||
|
3237 | ) | |||
|
3238 | if entry[8] != 0 or entry[9] != 0: | |||
|
3239 | # rewriting entries that already have sidedata is not | |||
|
3240 | # supported yet, because it introduces garbage data in the | |||
|
3241 | # revlog. | |||
|
3242 | msg = "Rewriting existing sidedata is not supported yet" | |||
|
3243 | raise error.Abort(msg) | |||
|
3244 | entry = entry[:8] | |||
|
3245 | entry += (current_offset, len(serialized_sidedata)) | |||
|
3246 | ||||
|
3247 | fp.write(serialized_sidedata) | |||
|
3248 | new_entries.append(entry) | |||
|
3249 | current_offset += len(serialized_sidedata) | |||
|
3250 | ||||
|
3251 | # rewrite the new index entries | |||
|
3252 | with self._indexfp(b'w+') as fp: | |||
|
3253 | fp.seek(startrev * self._io.size) | |||
|
3254 | for i, entry in enumerate(new_entries): | |||
|
3255 | rev = startrev + i | |||
|
3256 | self.index.replace_sidedata_info(rev, entry[8], entry[9]) | |||
|
3257 | packed = self._io.packentry(entry, self.node, self.version, rev) | |||
|
3258 | fp.write(packed) |
@@ -271,13 +271,12 b' copy information on to the filelog' | |||||
271 | $ hg ci --amend -m 'copy a to j, v2' |
|
271 | $ hg ci --amend -m 'copy a to j, v2' | |
272 | saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-*-amend.hg (glob) |
|
272 | saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-*-amend.hg (glob) | |
273 | $ hg debugsidedata -c -v -- -1 |
|
273 | $ hg debugsidedata -c -v -- -1 | |
274 | 1 sidedata entries (missing-correct-output !) |
|
274 | 1 sidedata entries | |
275 |
entry-0014 size 24 |
|
275 | entry-0014 size 24 | |
276 |
'\x00\x00\x00\x02\x00\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00aj' |
|
276 | '\x00\x00\x00\x02\x00\x00\x00\x00\x01\x00\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x00aj' | |
277 | #endif |
|
277 | #endif | |
278 | $ hg showcopies --config experimental.copies.read-from=filelog-only |
|
278 | $ hg showcopies --config experimental.copies.read-from=filelog-only | |
279 | a -> j (sidedata missing-correct-output !) |
|
279 | a -> j | |
280 | a -> j (no-sidedata !) |
|
|||
281 | The entries should be written to extras even if they're empty (so the client |
|
280 | The entries should be written to extras even if they're empty (so the client | |
282 | won't have to fall back to reading from filelogs) |
|
281 | won't have to fall back to reading from filelogs) | |
283 | $ echo x >> j |
|
282 | $ echo x >> j | |
@@ -355,8 +354,7 b' with no fallback.' | |||||
355 | saved backup bundle to $TESTTMP/rebase-rename/.hg/strip-backup/*-*-rebase.hg (glob) |
|
354 | saved backup bundle to $TESTTMP/rebase-rename/.hg/strip-backup/*-*-rebase.hg (glob) | |
356 | $ hg st --change . --copies |
|
355 | $ hg st --change . --copies | |
357 | A b |
|
356 | A b | |
358 | a (sidedata missing-correct-output !) |
|
357 | a | |
359 | a (no-sidedata !) |
|
|||
360 | R a |
|
358 | R a | |
361 | $ cd .. |
|
359 | $ cd .. | |
362 |
|
360 |
@@ -1,6 +1,9 b'' | |||||
1 | # ext-sidedata.py - small extension to test the sidedata logic |
|
1 | # coding: utf8 | |
|
2 | # ext-sidedata-2.py - small extension to test (differently) the sidedata logic | |||
2 | # |
|
3 | # | |
3 | # Copyright 2019 Pierre-Yves David <pierre-yves.david@octobus.net) |
|
4 | # Simulates a client for a complex sidedata exchange. | |
|
5 | # | |||
|
6 | # Copyright 2021 Raphaël Gomès <rgomes@octobus.net> | |||
4 | # |
|
7 | # | |
5 | # This software may be used and distributed according to the terms of the |
|
8 | # This software may be used and distributed according to the terms of the | |
6 | # GNU General Public License version 2 or any later version. |
|
9 | # GNU General Public License version 2 or any later version. | |
@@ -10,79 +13,38 b' from __future__ import absolute_import' | |||||
10 | import hashlib |
|
13 | import hashlib | |
11 | import struct |
|
14 | import struct | |
12 |
|
15 | |||
13 | from mercurial.node import ( |
|
16 | from mercurial.revlogutils import sidedata as sidedatamod | |
14 | nullid, |
|
|||
15 | nullrev, |
|
|||
16 | ) |
|
|||
17 | from mercurial import ( |
|
|||
18 | extensions, |
|
|||
19 | requirements, |
|
|||
20 | revlog, |
|
|||
21 | ) |
|
|||
22 |
|
||||
23 | from mercurial.upgrade_utils import engine as upgrade_engine |
|
|||
24 |
|
||||
25 | from mercurial.revlogutils import sidedata |
|
|||
26 |
|
17 | |||
27 |
|
18 | |||
28 | def wrapaddrevision( |
|
19 | def compute_sidedata_1(repo, revlog, rev, sidedata, text=None): | |
29 | orig, self, text, transaction, link, p1, p2, *args, **kwargs |
|
20 | sidedata = sidedata.copy() | |
30 | ): |
|
21 | if text is None: | |
31 | if kwargs.get('sidedata') is None: |
|
22 | text = revlog.revision(rev) | |
32 | kwargs['sidedata'] = {} |
|
23 | sidedata[sidedatamod.SD_TEST1] = struct.pack('>I', len(text)) | |
33 | sd = kwargs['sidedata'] |
|
24 | return sidedata | |
34 | ## let's store some arbitrary data just for testing |
|
|||
35 | # text length |
|
|||
36 | sd[sidedata.SD_TEST1] = struct.pack('>I', len(text)) |
|
|||
37 | # and sha2 hashes |
|
|||
38 | sha256 = hashlib.sha256(text).digest() |
|
|||
39 | sd[sidedata.SD_TEST2] = struct.pack('>32s', sha256) |
|
|||
40 | return orig(self, text, transaction, link, p1, p2, *args, **kwargs) |
|
|||
41 |
|
25 | |||
42 |
|
26 | |||
43 | def wrap_revisiondata(orig, self, nodeorrev, *args, **kwargs): |
|
27 | def compute_sidedata_2(repo, revlog, rev, sidedata, text=None): | |
44 | text, sd = orig(self, nodeorrev, *args, **kwargs) |
|
28 | sidedata = sidedata.copy() | |
45 | if getattr(self, 'sidedatanocheck', False): |
|
29 | if text is None: | |
46 | return text, sd |
|
30 | text = revlog.revision(rev) | |
47 | if self.version & 0xFFFF != 2: |
|
31 | sha256 = hashlib.sha256(text).digest() | |
48 | return text, sd |
|
32 | sidedata[sidedatamod.SD_TEST2] = struct.pack('>32s', sha256) | |
49 | if nodeorrev != nullrev and nodeorrev != nullid: |
|
33 | return sidedata | |
50 | if len(text) != struct.unpack('>I', sd[sidedata.SD_TEST1])[0]: |
|
|||
51 | raise RuntimeError('text size mismatch') |
|
|||
52 | expected = sd[sidedata.SD_TEST2] |
|
|||
53 | got = hashlib.sha256(text).digest() |
|
|||
54 | if got != expected: |
|
|||
55 | raise RuntimeError('sha256 mismatch') |
|
|||
56 | return text, sd |
|
|||
57 |
|
34 | |||
58 |
|
35 | |||
59 | def wrapgetsidedatacompanion(orig, srcrepo, dstrepo): |
|
36 | def reposetup(ui, repo): | |
60 | sidedatacompanion = orig(srcrepo, dstrepo) |
|
37 | # Sidedata keys happen to be the same as the categories, easier for testing. | |
61 | addedreqs = dstrepo.requirements - srcrepo.requirements |
|
38 | for kind in (b'changelog', b'manifest', b'filelog'): | |
62 | if requirements.SIDEDATA_REQUIREMENT in addedreqs: |
|
39 | repo.register_sidedata_computer( | |
63 | assert sidedatacompanion is None # deal with composition later |
|
40 | kind, | |
64 |
|
41 | sidedatamod.SD_TEST1, | ||
65 | def sidedatacompanion(revlog, rev): |
|
42 | (sidedatamod.SD_TEST1,), | |
66 | update = {} |
|
43 | compute_sidedata_1, | |
67 | revlog.sidedatanocheck = True |
|
|||
68 | try: |
|
|||
69 | text = revlog.revision(rev) |
|
|||
70 | finally: |
|
|||
71 | del revlog.sidedatanocheck |
|
|||
72 | ## let's store some arbitrary data just for testing |
|
|||
73 | # text length |
|
|||
74 | update[sidedata.SD_TEST1] = struct.pack('>I', len(text)) |
|
|||
75 | # and sha2 hashes |
|
|||
76 | sha256 = hashlib.sha256(text).digest() |
|
|||
77 | update[sidedata.SD_TEST2] = struct.pack('>32s', sha256) |
|
|||
78 | return False, (), update, 0, 0 |
|
|||
79 |
|
||||
80 | return sidedatacompanion |
|
|||
81 |
|
||||
82 |
|
||||
83 | def extsetup(ui): |
|
|||
84 | extensions.wrapfunction(revlog.revlog, 'addrevision', wrapaddrevision) |
|
|||
85 | extensions.wrapfunction(revlog.revlog, '_revisiondata', wrap_revisiondata) |
|
|||
86 | extensions.wrapfunction( |
|
|||
87 | upgrade_engine, 'getsidedatacompanion', wrapgetsidedatacompanion |
|
|||
88 | ) |
|
44 | ) | |
|
45 | repo.register_sidedata_computer( | |||
|
46 | kind, | |||
|
47 | sidedatamod.SD_TEST2, | |||
|
48 | (sidedatamod.SD_TEST2,), | |||
|
49 | compute_sidedata_2, | |||
|
50 | ) |
@@ -1,6 +1,10 b'' | |||||
1 | # ext-sidedata.py - small extension to test the sidedata logic |
|
1 | # coding: utf8 | |
|
2 | # ext-sidedata-3.py - small extension to test (differently still) the sidedata | |||
|
3 | # logic | |||
2 | # |
|
4 | # | |
3 | # Copyright 2019 Pierre-Yves David <pierre-yves.david@octobus.net) |
|
5 | # Simulates a client for a complex sidedata exchange. | |
|
6 | # | |||
|
7 | # Copyright 2021 Raphaël Gomès <rgomes@octobus.net> | |||
4 | # |
|
8 | # | |
5 | # This software may be used and distributed according to the terms of the |
|
9 | # This software may be used and distributed according to the terms of the | |
6 | # GNU General Public License version 2 or any later version. |
|
10 | # GNU General Public License version 2 or any later version. | |
@@ -10,19 +14,38 b' from __future__ import absolute_import' | |||||
10 | import hashlib |
|
14 | import hashlib | |
11 | import struct |
|
15 | import struct | |
12 |
|
16 | |||
13 | from mercurial.node import ( |
|
|||
14 | nullid, |
|
|||
15 | nullrev, |
|
|||
16 | ) |
|
|||
17 | from mercurial import ( |
|
17 | from mercurial import ( | |
18 | extensions, |
|
18 | extensions, | |
19 | requirements, |
|
|||
20 | revlog, |
|
19 | revlog, | |
21 | ) |
|
20 | ) | |
22 |
|
21 | |||
23 |
from mercurial. |
|
22 | from mercurial.revlogutils import sidedata as sidedatamod | |
|
23 | ||||
|
24 | ||||
|
25 | def compute_sidedata_1(repo, revlog, rev, sidedata, text=None): | |||
|
26 | sidedata = sidedata.copy() | |||
|
27 | if text is None: | |||
|
28 | text = revlog.revision(rev) | |||
|
29 | sidedata[sidedatamod.SD_TEST1] = struct.pack('>I', len(text)) | |||
|
30 | return sidedata | |||
|
31 | ||||
24 |
|
32 | |||
25 | from mercurial.revlogutils import sidedata |
|
33 | def compute_sidedata_2(repo, revlog, rev, sidedata, text=None): | |
|
34 | sidedata = sidedata.copy() | |||
|
35 | if text is None: | |||
|
36 | text = revlog.revision(rev) | |||
|
37 | sha256 = hashlib.sha256(text).digest() | |||
|
38 | sidedata[sidedatamod.SD_TEST2] = struct.pack('>32s', sha256) | |||
|
39 | return sidedata | |||
|
40 | ||||
|
41 | ||||
|
42 | def compute_sidedata_3(repo, revlog, rev, sidedata, text=None): | |||
|
43 | sidedata = sidedata.copy() | |||
|
44 | if text is None: | |||
|
45 | text = revlog.revision(rev) | |||
|
46 | sha384 = hashlib.sha384(text).digest() | |||
|
47 | sidedata[sidedatamod.SD_TEST3] = struct.pack('>48s', sha384) | |||
|
48 | return sidedata | |||
26 |
|
49 | |||
27 |
|
50 | |||
28 | def wrapaddrevision( |
|
51 | def wrapaddrevision( | |
@@ -31,58 +54,35 b' def wrapaddrevision(' | |||||
31 | if kwargs.get('sidedata') is None: |
|
54 | if kwargs.get('sidedata') is None: | |
32 | kwargs['sidedata'] = {} |
|
55 | kwargs['sidedata'] = {} | |
33 | sd = kwargs['sidedata'] |
|
56 | sd = kwargs['sidedata'] | |
34 | ## let's store some arbitrary data just for testing |
|
57 | sd = compute_sidedata_1(None, self, None, sd, text=text) | |
35 | # text length |
|
58 | kwargs['sidedata'] = compute_sidedata_2(None, self, None, sd, text=text) | |
36 | sd[sidedata.SD_TEST1] = struct.pack('>I', len(text)) |
|
|||
37 | # and sha2 hashes |
|
|||
38 | sha256 = hashlib.sha256(text).digest() |
|
|||
39 | sd[sidedata.SD_TEST2] = struct.pack('>32s', sha256) |
|
|||
40 | return orig(self, text, transaction, link, p1, p2, *args, **kwargs) |
|
59 | return orig(self, text, transaction, link, p1, p2, *args, **kwargs) | |
41 |
|
60 | |||
42 |
|
61 | |||
43 | def wrap_revisiondata(orig, self, nodeorrev, *args, **kwargs): |
|
|||
44 | text, sd = orig(self, nodeorrev, *args, **kwargs) |
|
|||
45 | if getattr(self, 'sidedatanocheck', False): |
|
|||
46 | return text, sd |
|
|||
47 | if self.version & 0xFFFF != 2: |
|
|||
48 | return text, sd |
|
|||
49 | if nodeorrev != nullrev and nodeorrev != nullid: |
|
|||
50 | if len(text) != struct.unpack('>I', sd[sidedata.SD_TEST1])[0]: |
|
|||
51 | raise RuntimeError('text size mismatch') |
|
|||
52 | expected = sd[sidedata.SD_TEST2] |
|
|||
53 | got = hashlib.sha256(text).digest() |
|
|||
54 | if got != expected: |
|
|||
55 | raise RuntimeError('sha256 mismatch') |
|
|||
56 | return text, sd |
|
|||
57 |
|
||||
58 |
|
||||
59 | def wrapgetsidedatacompanion(orig, srcrepo, dstrepo): |
|
|||
60 | sidedatacompanion = orig(srcrepo, dstrepo) |
|
|||
61 | addedreqs = dstrepo.requirements - srcrepo.requirements |
|
|||
62 | if requirements.SIDEDATA_REQUIREMENT in addedreqs: |
|
|||
63 | assert sidedatacompanion is None # deal with composition later |
|
|||
64 |
|
||||
65 | def sidedatacompanion(revlog, rev): |
|
|||
66 | update = {} |
|
|||
67 | revlog.sidedatanocheck = True |
|
|||
68 | try: |
|
|||
69 | text = revlog.revision(rev) |
|
|||
70 | finally: |
|
|||
71 | del revlog.sidedatanocheck |
|
|||
72 | ## let's store some arbitrary data just for testing |
|
|||
73 | # text length |
|
|||
74 | update[sidedata.SD_TEST1] = struct.pack('>I', len(text)) |
|
|||
75 | # and sha2 hashes |
|
|||
76 | sha256 = hashlib.sha256(text).digest() |
|
|||
77 | update[sidedata.SD_TEST2] = struct.pack('>32s', sha256) |
|
|||
78 | return False, (), update, 0, 0 |
|
|||
79 |
|
||||
80 | return sidedatacompanion |
|
|||
81 |
|
||||
82 |
|
||||
83 | def extsetup(ui): |
|
62 | def extsetup(ui): | |
84 | extensions.wrapfunction(revlog.revlog, 'addrevision', wrapaddrevision) |
|
63 | extensions.wrapfunction(revlog.revlog, 'addrevision', wrapaddrevision) | |
85 | extensions.wrapfunction(revlog.revlog, '_revisiondata', wrap_revisiondata) |
|
64 | ||
86 | extensions.wrapfunction( |
|
65 | ||
87 | upgrade_engine, 'getsidedatacompanion', wrapgetsidedatacompanion |
|
66 | def reposetup(ui, repo): | |
|
67 | # Sidedata keys happen to be the same as the categories, easier for testing. | |||
|
68 | for kind in (b'changelog', b'manifest', b'filelog'): | |||
|
69 | repo.register_sidedata_computer( | |||
|
70 | kind, | |||
|
71 | sidedatamod.SD_TEST1, | |||
|
72 | (sidedatamod.SD_TEST1,), | |||
|
73 | compute_sidedata_1, | |||
88 | ) |
|
74 | ) | |
|
75 | repo.register_sidedata_computer( | |||
|
76 | kind, | |||
|
77 | sidedatamod.SD_TEST2, | |||
|
78 | (sidedatamod.SD_TEST2,), | |||
|
79 | compute_sidedata_2, | |||
|
80 | ) | |||
|
81 | repo.register_sidedata_computer( | |||
|
82 | kind, | |||
|
83 | sidedatamod.SD_TEST3, | |||
|
84 | (sidedatamod.SD_TEST3,), | |||
|
85 | compute_sidedata_3, | |||
|
86 | ) | |||
|
87 | repo.register_wanted_sidedata(sidedatamod.SD_TEST1) | |||
|
88 | repo.register_wanted_sidedata(sidedatamod.SD_TEST2) |
@@ -1,88 +1,19 b'' | |||||
1 | # ext-sidedata.py - small extension to test the sidedata logic |
|
1 | # coding: utf8 | |
|
2 | # ext-sidedata-4.py - small extension to test (differently still) the sidedata | |||
|
3 | # logic | |||
2 | # |
|
4 | # | |
3 | # Copyright 2019 Pierre-Yves David <pierre-yves.david@octobus.net) |
|
5 | # Simulates a server for a complex sidedata exchange. | |
|
6 | # | |||
|
7 | # Copyright 2021 Raphaël Gomès <rgomes@octobus.net> | |||
4 | # |
|
8 | # | |
5 | # This software may be used and distributed according to the terms of the |
|
9 | # This software may be used and distributed according to the terms of the | |
6 | # GNU General Public License version 2 or any later version. |
|
10 | # GNU General Public License version 2 or any later version. | |
7 |
|
11 | |||
8 | from __future__ import absolute_import |
|
12 | from __future__ import absolute_import | |
9 |
|
13 | |||
10 | import hashlib |
|
|||
11 | import struct |
|
|||
12 |
|
||||
13 | from mercurial.node import ( |
|
|||
14 | nullid, |
|
|||
15 | nullrev, |
|
|||
16 | ) |
|
|||
17 | from mercurial import ( |
|
|||
18 | extensions, |
|
|||
19 | requirements, |
|
|||
20 | revlog, |
|
|||
21 | ) |
|
|||
22 |
|
||||
23 | from mercurial.upgrade_utils import engine as upgrade_engine |
|
|||
24 |
|
||||
25 | from mercurial.revlogutils import sidedata |
|
14 | from mercurial.revlogutils import sidedata | |
26 |
|
15 | |||
27 |
|
16 | |||
28 | def wrapaddrevision( |
|
17 | def reposetup(ui, repo): | |
29 | orig, self, text, transaction, link, p1, p2, *args, **kwargs |
|
18 | repo.register_wanted_sidedata(sidedata.SD_TEST2) | |
30 | ): |
|
19 | repo.register_wanted_sidedata(sidedata.SD_TEST3) | |
31 | if kwargs.get('sidedata') is None: |
|
|||
32 | kwargs['sidedata'] = {} |
|
|||
33 | sd = kwargs['sidedata'] |
|
|||
34 | ## let's store some arbitrary data just for testing |
|
|||
35 | # text length |
|
|||
36 | sd[sidedata.SD_TEST1] = struct.pack('>I', len(text)) |
|
|||
37 | # and sha2 hashes |
|
|||
38 | sha256 = hashlib.sha256(text).digest() |
|
|||
39 | sd[sidedata.SD_TEST2] = struct.pack('>32s', sha256) |
|
|||
40 | return orig(self, text, transaction, link, p1, p2, *args, **kwargs) |
|
|||
41 |
|
||||
42 |
|
||||
43 | def wrap_revisiondata(orig, self, nodeorrev, *args, **kwargs): |
|
|||
44 | text, sd = orig(self, nodeorrev, *args, **kwargs) |
|
|||
45 | if getattr(self, 'sidedatanocheck', False): |
|
|||
46 | return text, sd |
|
|||
47 | if self.version & 0xFFFF != 2: |
|
|||
48 | return text, sd |
|
|||
49 | if nodeorrev != nullrev and nodeorrev != nullid: |
|
|||
50 | if len(text) != struct.unpack('>I', sd[sidedata.SD_TEST1])[0]: |
|
|||
51 | raise RuntimeError('text size mismatch') |
|
|||
52 | expected = sd[sidedata.SD_TEST2] |
|
|||
53 | got = hashlib.sha256(text).digest() |
|
|||
54 | if got != expected: |
|
|||
55 | raise RuntimeError('sha256 mismatch') |
|
|||
56 | return text, sd |
|
|||
57 |
|
||||
58 |
|
||||
59 | def wrapgetsidedatacompanion(orig, srcrepo, dstrepo): |
|
|||
60 | sidedatacompanion = orig(srcrepo, dstrepo) |
|
|||
61 | addedreqs = dstrepo.requirements - srcrepo.requirements |
|
|||
62 | if requirements.SIDEDATA_REQUIREMENT in addedreqs: |
|
|||
63 | assert sidedatacompanion is None # deal with composition later |
|
|||
64 |
|
||||
65 | def sidedatacompanion(revlog, rev): |
|
|||
66 | update = {} |
|
|||
67 | revlog.sidedatanocheck = True |
|
|||
68 | try: |
|
|||
69 | text = revlog.revision(rev) |
|
|||
70 | finally: |
|
|||
71 | del revlog.sidedatanocheck |
|
|||
72 | ## let's store some arbitrary data just for testing |
|
|||
73 | # text length |
|
|||
74 | update[sidedata.SD_TEST1] = struct.pack('>I', len(text)) |
|
|||
75 | # and sha2 hashes |
|
|||
76 | sha256 = hashlib.sha256(text).digest() |
|
|||
77 | update[sidedata.SD_TEST2] = struct.pack('>32s', sha256) |
|
|||
78 | return False, (), update, 0, 0 |
|
|||
79 |
|
||||
80 | return sidedatacompanion |
|
|||
81 |
|
||||
82 |
|
||||
83 | def extsetup(ui): |
|
|||
84 | extensions.wrapfunction(revlog.revlog, 'addrevision', wrapaddrevision) |
|
|||
85 | extensions.wrapfunction(revlog.revlog, '_revisiondata', wrap_revisiondata) |
|
|||
86 | extensions.wrapfunction( |
|
|||
87 | upgrade_engine, 'getsidedatacompanion', wrapgetsidedatacompanion |
|
|||
88 | ) |
|
@@ -1,6 +1,6 b'' | |||||
1 | # ext-sidedata.py - small extension to test the sidedata logic |
|
1 | # ext-sidedata.py - small extension to test the sidedata logic | |
2 | # |
|
2 | # | |
3 |
# Copyright 2019 Pierre-Yves David <pierre-yves.david@octobus.net |
|
3 | # Copyright 2019 Pierre-Yves David <pierre-yves.david@octobus.net> | |
4 | # |
|
4 | # | |
5 | # This software may be used and distributed according to the terms of the |
|
5 | # This software may be used and distributed according to the terms of the | |
6 | # GNU General Public License version 2 or any later version. |
|
6 | # GNU General Public License version 2 or any later version. | |
@@ -47,11 +47,12 b' def wrap_revisiondata(orig, self, nodeor' | |||||
47 | if self.version & 0xFFFF != 2: |
|
47 | if self.version & 0xFFFF != 2: | |
48 | return text, sd |
|
48 | return text, sd | |
49 | if nodeorrev != nullrev and nodeorrev != nullid: |
|
49 | if nodeorrev != nullrev and nodeorrev != nullid: | |
50 | if len(text) != struct.unpack('>I', sd[sidedata.SD_TEST1])[0]: |
|
50 | cat1 = sd.get(sidedata.SD_TEST1) | |
|
51 | if cat1 is not None and len(text) != struct.unpack('>I', cat1)[0]: | |||
51 | raise RuntimeError('text size mismatch') |
|
52 | raise RuntimeError('text size mismatch') | |
52 |
expected = sd |
|
53 | expected = sd.get(sidedata.SD_TEST2) | |
53 | got = hashlib.sha256(text).digest() |
|
54 | got = hashlib.sha256(text).digest() | |
54 | if got != expected: |
|
55 | if expected is not None and got != expected: | |
55 | raise RuntimeError('sha256 mismatch') |
|
56 | raise RuntimeError('sha256 mismatch') | |
56 | return text, sd |
|
57 | return text, sd | |
57 |
|
58 | |||
@@ -86,3 +87,10 b' def extsetup(ui):' | |||||
86 | extensions.wrapfunction( |
|
87 | extensions.wrapfunction( | |
87 | upgrade_engine, 'getsidedatacompanion', wrapgetsidedatacompanion |
|
88 | upgrade_engine, 'getsidedatacompanion', wrapgetsidedatacompanion | |
88 | ) |
|
89 | ) | |
|
90 | ||||
|
91 | ||||
|
92 | def reposetup(ui, repo): | |||
|
93 | # We don't register sidedata computers because we don't care within these | |||
|
94 | # tests | |||
|
95 | repo.register_wanted_sidedata(sidedata.SD_TEST1) | |||
|
96 | repo.register_wanted_sidedata(sidedata.SD_TEST2) |
General Comments 0
You need to be logged in to leave comments.
Login now