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 | 8 | from __future__ import absolute_import |
|
9 | 9 | |
|
10 | import collections | |
|
10 | 11 | import os |
|
11 | 12 | import struct |
|
12 | 13 | import weakref |
@@ -252,7 +253,7 b' class cg1unpacker(object):' | |||
|
252 | 253 | pos = next |
|
253 | 254 | yield closechunk() |
|
254 | 255 | |
|
255 | def _unpackmanifests(self, repo, revmap, trp, prog): | |
|
256 | def _unpackmanifests(self, repo, revmap, trp, prog, addrevisioncb=None): | |
|
256 | 257 | self.callback = prog.increment |
|
257 | 258 | # no need to check for empty manifest group here: |
|
258 | 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 | 261 | # be empty during the pull |
|
261 | 262 | self.manifestheader() |
|
262 | 263 | deltas = self.deltaiter() |
|
263 |
repo.manifestlog.getstorage(b'') |
|
|
264 | storage = repo.manifestlog.getstorage(b'') | |
|
265 | storage.addgroup(deltas, revmap, trp, addrevisioncb=addrevisioncb) | |
|
264 | 266 | prog.complete() |
|
265 | 267 | self.callback = None |
|
266 | 268 | |
@@ -369,6 +371,13 b' class cg1unpacker(object):' | |||
|
369 | 371 | efilesset = None |
|
370 | 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 | 381 | # pull off the manifest group |
|
373 | 382 | repo.ui.status(_(b"adding manifests\n")) |
|
374 | 383 | # We know that we'll never have more manifests than we had |
@@ -376,7 +385,24 b' class cg1unpacker(object):' | |||
|
376 | 385 | progress = repo.ui.makeprogress( |
|
377 | 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 | 407 | needfiles = {} |
|
382 | 408 | if repo.ui.configbool(b'server', b'validate'): |
@@ -390,12 +416,37 b' class cg1unpacker(object):' | |||
|
390 | 416 | for f, n in pycompat.iteritems(mfest): |
|
391 | 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 | 430 | # process the files |
|
394 | 431 | repo.ui.status(_(b"adding file changes\n")) |
|
395 | 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 | 450 | # making sure the value exists |
|
400 | 451 | tr.changes.setdefault(b'changegroup-count-changesets', 0) |
|
401 | 452 | tr.changes.setdefault(b'changegroup-count-revisions', 0) |
@@ -559,14 +610,18 b' class cg3unpacker(cg2unpacker):' | |||
|
559 | 610 | node, p1, p2, deltabase, cs, flags = headertuple |
|
560 | 611 | return node, p1, p2, deltabase, cs, flags |
|
561 | 612 | |
|
562 | def _unpackmanifests(self, repo, revmap, trp, prog): | |
|
563 |
super(cg3unpacker, self)._unpackmanifests( |
|
|
613 | def _unpackmanifests(self, repo, revmap, trp, prog, addrevisioncb=None): | |
|
614 | super(cg3unpacker, self)._unpackmanifests( | |
|
615 | repo, revmap, trp, prog, addrevisioncb=addrevisioncb | |
|
616 | ) | |
|
564 | 617 | for chunkdata in iter(self.filelogheader, {}): |
|
565 | 618 | # If we get here, there are directory manifests in the changegroup |
|
566 | 619 | d = chunkdata[b"filename"] |
|
567 | 620 | repo.ui.debug(b"adding %s revisions\n" % d) |
|
568 | 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 | 625 | raise error.Abort(_(b"received dir revlog group is empty")) |
|
571 | 626 | |
|
572 | 627 | |
@@ -1793,7 +1848,15 b' def makestream(' | |||
|
1793 | 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 | 1860 | revisions = 0 |
|
1798 | 1861 | files = 0 |
|
1799 | 1862 | progress = repo.ui.makeprogress( |
@@ -1808,7 +1871,13 b' def _addchangegroupfiles(repo, source, r' | |||
|
1808 | 1871 | o = len(fl) |
|
1809 | 1872 | try: |
|
1810 | 1873 | deltas = source.deltaiter() |
|
1811 |
|
|
|
1874 | added = fl.addgroup( | |
|
1875 | deltas, | |
|
1876 | revmap, | |
|
1877 | trp, | |
|
1878 | addrevisioncb=addrevisioncb, | |
|
1879 | ) | |
|
1880 | if not added: | |
|
1812 | 1881 | raise error.Abort(_(b"received file revlog group is empty")) |
|
1813 | 1882 | except error.CensoredBaseError as e: |
|
1814 | 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 | 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 | 271 | $ hg ci --amend -m 'copy a to j, v2' |
|
272 | 272 | saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-*-amend.hg (glob) |
|
273 | 273 | $ hg debugsidedata -c -v -- -1 |
|
274 | 1 sidedata entries (missing-correct-output !) | |
|
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' |
|
|
274 | 1 sidedata entries | |
|
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' | |
|
277 | 277 | #endif |
|
278 | 278 | $ hg showcopies --config experimental.copies.read-from=filelog-only |
|
279 | a -> j (sidedata missing-correct-output !) | |
|
280 | a -> j (no-sidedata !) | |
|
279 | a -> j | |
|
281 | 280 | The entries should be written to extras even if they're empty (so the client |
|
282 | 281 | won't have to fall back to reading from filelogs) |
|
283 | 282 | $ echo x >> j |
@@ -355,8 +354,7 b' with no fallback.' | |||
|
355 | 354 | saved backup bundle to $TESTTMP/rebase-rename/.hg/strip-backup/*-*-rebase.hg (glob) |
|
356 | 355 | $ hg st --change . --copies |
|
357 | 356 | A b |
|
358 | a (sidedata missing-correct-output !) | |
|
359 | a (no-sidedata !) | |
|
357 | a | |
|
360 | 358 | R a |
|
361 | 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 | 8 | # This software may be used and distributed according to the terms of the |
|
6 | 9 | # GNU General Public License version 2 or any later version. |
@@ -10,79 +13,38 b' from __future__ import absolute_import' | |||
|
10 | 13 | import hashlib |
|
11 | 14 | import struct |
|
12 | 15 | |
|
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 | |
|
16 | from mercurial.revlogutils import sidedata as sidedatamod | |
|
26 | 17 | |
|
27 | 18 | |
|
28 | def wrapaddrevision( | |
|
29 | orig, self, text, transaction, link, p1, p2, *args, **kwargs | |
|
30 | ): | |
|
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) | |
|
19 | def compute_sidedata_1(repo, revlog, rev, sidedata, text=None): | |
|
20 | sidedata = sidedata.copy() | |
|
21 | if text is None: | |
|
22 | text = revlog.revision(rev) | |
|
23 | sidedata[sidedatamod.SD_TEST1] = struct.pack('>I', len(text)) | |
|
24 | return sidedata | |
|
41 | 25 | |
|
42 | 26 | |
|
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 | |
|
27 | def compute_sidedata_2(repo, revlog, rev, sidedata, text=None): | |
|
28 | sidedata = sidedata.copy() | |
|
29 | if text is None: | |
|
30 | text = revlog.revision(rev) | |
|
31 | sha256 = hashlib.sha256(text).digest() | |
|
32 | sidedata[sidedatamod.SD_TEST2] = struct.pack('>32s', sha256) | |
|
33 | return sidedata | |
|
57 | 34 | |
|
58 | 35 | |
|
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 | ) | |
|
36 | def reposetup(ui, repo): | |
|
37 | # Sidedata keys happen to be the same as the categories, easier for testing. | |
|
38 | for kind in (b'changelog', b'manifest', b'filelog'): | |
|
39 | repo.register_sidedata_computer( | |
|
40 | kind, | |
|
41 | sidedatamod.SD_TEST1, | |
|
42 | (sidedatamod.SD_TEST1,), | |
|
43 | compute_sidedata_1, | |
|
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 | 9 | # This software may be used and distributed according to the terms of the |
|
6 | 10 | # GNU General Public License version 2 or any later version. |
@@ -10,19 +14,38 b' from __future__ import absolute_import' | |||
|
10 | 14 | import hashlib |
|
11 | 15 | import struct |
|
12 | 16 | |
|
13 | from mercurial.node import ( | |
|
14 | nullid, | |
|
15 | nullrev, | |
|
16 | ) | |
|
17 | 17 | from mercurial import ( |
|
18 | 18 | extensions, |
|
19 | requirements, | |
|
20 | 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 | 51 | def wrapaddrevision( |
@@ -31,58 +54,35 b' def wrapaddrevision(' | |||
|
31 | 54 | if kwargs.get('sidedata') is None: |
|
32 | 55 | kwargs['sidedata'] = {} |
|
33 | 56 | 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) | |
|
57 | sd = compute_sidedata_1(None, self, None, sd, text=text) | |
|
58 | kwargs['sidedata'] = compute_sidedata_2(None, self, None, sd, text=text) | |
|
40 | 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 | 62 | def extsetup(ui): |
|
84 | 63 | extensions.wrapfunction(revlog.revlog, 'addrevision', wrapaddrevision) |
|
85 | extensions.wrapfunction(revlog.revlog, '_revisiondata', wrap_revisiondata) | |
|
86 | extensions.wrapfunction( | |
|
87 | upgrade_engine, 'getsidedatacompanion', wrapgetsidedatacompanion | |
|
88 | ) | |
|
64 | ||
|
65 | ||
|
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, | |
|
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 | 9 | # This software may be used and distributed according to the terms of the |
|
6 | 10 | # GNU General Public License version 2 or any later version. |
|
7 | 11 | |
|
8 | 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 | 14 | from mercurial.revlogutils import sidedata |
|
26 | 15 | |
|
27 | 16 | |
|
28 | def wrapaddrevision( | |
|
29 | orig, self, text, transaction, link, p1, p2, *args, **kwargs | |
|
30 | ): | |
|
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 | ) | |
|
17 | def reposetup(ui, repo): | |
|
18 | repo.register_wanted_sidedata(sidedata.SD_TEST2) | |
|
19 | repo.register_wanted_sidedata(sidedata.SD_TEST3) |
@@ -1,6 +1,6 b'' | |||
|
1 | 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 | 5 | # This software may be used and distributed according to the terms of the |
|
6 | 6 | # GNU General Public License version 2 or any later version. |
@@ -47,11 +47,12 b' def wrap_revisiondata(orig, self, nodeor' | |||
|
47 | 47 | if self.version & 0xFFFF != 2: |
|
48 | 48 | return text, sd |
|
49 | 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 | 52 | raise RuntimeError('text size mismatch') |
|
52 |
expected = sd |
|
|
53 | expected = sd.get(sidedata.SD_TEST2) | |
|
53 | 54 | got = hashlib.sha256(text).digest() |
|
54 | if got != expected: | |
|
55 | if expected is not None and got != expected: | |
|
55 | 56 | raise RuntimeError('sha256 mismatch') |
|
56 | 57 | return text, sd |
|
57 | 58 | |
@@ -86,3 +87,10 b' def extsetup(ui):' | |||
|
86 | 87 | extensions.wrapfunction( |
|
87 | 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