##// END OF EJS Templates
debugcommands: support for triggering push protocol...
Gregory Szorc -
r36551:5faeabb0 default
parent child Browse files
Show More
This diff has been collapsed as it changes many lines, (1676 lines changed) Show them Hide them
@@ -0,0 +1,1676 b''
1 $ cat > hgrc-sshv2 << EOF
2 > %include $HGRCPATH
3 > [experimental]
4 > sshpeer.advertise-v2 = true
5 > sshserver.support-v2 = true
6 > EOF
7
8 $ debugwireproto() {
9 > commands=`cat -`
10 > echo 'testing ssh1'
11 > tip=`hg log -r tip -T '{node}'`
12 > echo "${commands}" | hg --verbose debugwireproto --localssh --noreadstderr
13 > if [ -n "$1" ]; then
14 > hg --config extensions.strip= strip --no-backup -r "all() - ::${tip}"
15 > fi
16 > echo ""
17 > echo 'testing ssh2'
18 > echo "${commands}" | HGRCPATH=$TESTTMP/hgrc-sshv2 hg --verbose debugwireproto --localssh --noreadstderr
19 > if [ -n "$1" ]; then
20 > hg --config extensions.strip= strip --no-backup -r "all() - ::${tip}"
21 > fi
22 > }
23
24 Generate some bundle files
25
26 $ hg init repo
27 $ cd repo
28 $ echo 0 > foo
29 $ hg -q commit -A -m initial
30 $ hg bundle --all -t none-v1 ../initial.v1.hg
31 1 changesets found
32 $ cd ..
33
34 Test pushing bundle1 payload to a server with bundle1 disabled
35
36 $ hg init no-bundle1
37 $ cd no-bundle1
38 $ cat > .hg/hgrc << EOF
39 > [server]
40 > bundle1 = false
41 > EOF
42
43 $ debugwireproto << EOF
44 > command unbundle
45 > # This is "force" in hex.
46 > heads 666f726365
47 > PUSHFILE ../initial.v1.hg
48 > EOF
49 testing ssh1
50 creating ssh peer from handshake results
51 i> write(104) -> None:
52 i> hello\n
53 i> between\n
54 i> pairs 81\n
55 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
56 i> flush() -> None
57 o> readline() -> 4:
58 o> 384\n
59 o> readline() -> 384:
60 o> capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
61 o> readline() -> 2:
62 o> 1\n
63 o> readline() -> 1:
64 o> \n
65 sending unbundle command
66 i> write(9) -> None:
67 i> unbundle\n
68 i> write(9) -> None:
69 i> heads 10\n
70 i> write(10) -> None: 666f726365
71 i> flush() -> None
72 o> readline() -> 2:
73 o> 0\n
74 i> write(4) -> None:
75 i> 426\n
76 i> write(426) -> None:
77 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
78 i> test\n
79 i> 0 0\n
80 i> foo\n
81 i> \n
82 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
83 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
84 i> \x00\x00\x00\x00\x00\x00\x00\x00
85 i> write(2) -> None:
86 i> 0\n
87 i> flush() -> None
88 o> readline() -> 2:
89 o> 0\n
90 e> read(-1) -> 115:
91 e> abort: incompatible Mercurial client; bundle2 required\n
92 e> (see https://www.mercurial-scm.org/wiki/IncompatibleClient)\n
93 remote: abort: incompatible Mercurial client; bundle2 required
94 remote: (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
95 o> read(0) -> 0:
96 o> readline() -> 2:
97 o> 1\n
98 o> read(1) -> 1: 0
99 result: 0
100 remote output:
101
102 testing ssh2
103 creating ssh peer from handshake results
104 i> write(171) -> None:
105 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
106 i> hello\n
107 i> between\n
108 i> pairs 81\n
109 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
110 i> flush() -> None
111 o> readline() -> 62:
112 o> upgraded * exp-ssh-v2-0001\n (glob)
113 o> readline() -> 4:
114 o> 383\n
115 o> read(383) -> 383: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
116 o> read(1) -> 1:
117 o> \n
118 sending unbundle command
119 i> write(9) -> None:
120 i> unbundle\n
121 i> write(9) -> None:
122 i> heads 10\n
123 i> write(10) -> None: 666f726365
124 i> flush() -> None
125 o> readline() -> 2:
126 o> 0\n
127 i> write(4) -> None:
128 i> 426\n
129 i> write(426) -> None:
130 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
131 i> test\n
132 i> 0 0\n
133 i> foo\n
134 i> \n
135 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
136 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
137 i> \x00\x00\x00\x00\x00\x00\x00\x00
138 i> write(2) -> None:
139 i> 0\n
140 i> flush() -> None
141 o> readline() -> 2:
142 o> 0\n
143 e> read(-1) -> 115:
144 e> abort: incompatible Mercurial client; bundle2 required\n
145 e> (see https://www.mercurial-scm.org/wiki/IncompatibleClient)\n
146 remote: abort: incompatible Mercurial client; bundle2 required
147 remote: (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
148 o> read(0) -> 0:
149 o> readline() -> 2:
150 o> 1\n
151 o> read(1) -> 1: 0
152 result: 0
153 remote output:
154
155 $ cd ..
156
157 Create a pretxnchangegroup hook that fails. Give it multiple modes of printing
158 output so we can test I/O capture and behavior.
159
160 Test pushing to a server that has a pretxnchangegroup Python hook that fails
161
162 $ cat > $TESTTMP/failhook << EOF
163 > from __future__ import print_function
164 > import sys
165 > def hook1line(ui, repo, **kwargs):
166 > ui.write('ui.write 1 line\n')
167 > return 1
168 > def hook2lines(ui, repo, **kwargs):
169 > ui.write('ui.write 2 lines 1\n')
170 > ui.write('ui.write 2 lines 2\n')
171 > return 1
172 > def hook1lineflush(ui, repo, **kwargs):
173 > ui.write('ui.write 1 line flush\n')
174 > ui.flush()
175 > return 1
176 > def hookmultiflush(ui, repo, **kwargs):
177 > ui.write('ui.write 1st\n')
178 > ui.flush()
179 > ui.write('ui.write 2nd\n')
180 > ui.flush()
181 > return 1
182 > def hookwriteandwriteerr(ui, repo, **kwargs):
183 > ui.write('ui.write 1\n')
184 > ui.write_err('ui.write_err 1\n')
185 > ui.write('ui.write 2\n')
186 > ui.write_err('ui.write_err 2\n')
187 > return 1
188 > def hookprintstdout(ui, repo, **kwargs):
189 > print('printed line')
190 > return 1
191 > def hookprintandwrite(ui, repo, **kwargs):
192 > print('print 1')
193 > ui.write('ui.write 1\n')
194 > print('print 2')
195 > ui.write('ui.write 2\n')
196 > return 1
197 > def hookprintstderrandstdout(ui, repo, **kwargs):
198 > print('stdout 1')
199 > print('stderr 1', file=sys.stderr)
200 > print('stdout 2')
201 > print('stderr 2', file=sys.stderr)
202 > return 1
203 > EOF
204
205 $ hg init failrepo
206 $ cd failrepo
207
208 ui.write() in hook is redirected to stderr
209
210 $ cat > .hg/hgrc << EOF
211 > [hooks]
212 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hook1line
213 > EOF
214
215 $ debugwireproto << EOF
216 > command unbundle
217 > # This is "force" in hex.
218 > heads 666f726365
219 > PUSHFILE ../initial.v1.hg
220 > EOF
221 testing ssh1
222 creating ssh peer from handshake results
223 i> write(104) -> None:
224 i> hello\n
225 i> between\n
226 i> pairs 81\n
227 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
228 i> flush() -> None
229 o> readline() -> 4:
230 o> 384\n
231 o> readline() -> 384:
232 o> capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
233 o> readline() -> 2:
234 o> 1\n
235 o> readline() -> 1:
236 o> \n
237 sending unbundle command
238 i> write(9) -> None:
239 i> unbundle\n
240 i> write(9) -> None:
241 i> heads 10\n
242 i> write(10) -> None: 666f726365
243 i> flush() -> None
244 o> readline() -> 2:
245 o> 0\n
246 i> write(4) -> None:
247 i> 426\n
248 i> write(426) -> None:
249 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
250 i> test\n
251 i> 0 0\n
252 i> foo\n
253 i> \n
254 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
255 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
256 i> \x00\x00\x00\x00\x00\x00\x00\x00
257 i> write(2) -> None:
258 i> 0\n
259 i> flush() -> None
260 o> readline() -> 2:
261 o> 0\n
262 e> read(-1) -> 196:
263 e> adding changesets\n
264 e> adding manifests\n
265 e> adding file changes\n
266 e> added 1 changesets with 1 changes to 1 files\n
267 e> ui.write 1 line\n
268 e> transaction abort!\n
269 e> rollback completed\n
270 e> abort: pretxnchangegroup.fail hook failed\n
271 remote: adding changesets
272 remote: adding manifests
273 remote: adding file changes
274 remote: added 1 changesets with 1 changes to 1 files
275 remote: ui.write 1 line
276 remote: transaction abort!
277 remote: rollback completed
278 remote: abort: pretxnchangegroup.fail hook failed
279 o> read(0) -> 0:
280 o> readline() -> 2:
281 o> 1\n
282 o> read(1) -> 1: 0
283 result: 0
284 remote output:
285
286 testing ssh2
287 creating ssh peer from handshake results
288 i> write(171) -> None:
289 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
290 i> hello\n
291 i> between\n
292 i> pairs 81\n
293 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
294 i> flush() -> None
295 o> readline() -> 62:
296 o> upgraded * exp-ssh-v2-0001\n (glob)
297 o> readline() -> 4:
298 o> 383\n
299 o> read(383) -> 383: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
300 o> read(1) -> 1:
301 o> \n
302 sending unbundle command
303 i> write(9) -> None:
304 i> unbundle\n
305 i> write(9) -> None:
306 i> heads 10\n
307 i> write(10) -> None: 666f726365
308 i> flush() -> None
309 o> readline() -> 2:
310 o> 0\n
311 i> write(4) -> None:
312 i> 426\n
313 i> write(426) -> None:
314 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
315 i> test\n
316 i> 0 0\n
317 i> foo\n
318 i> \n
319 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
320 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
321 i> \x00\x00\x00\x00\x00\x00\x00\x00
322 i> write(2) -> None:
323 i> 0\n
324 i> flush() -> None
325 o> readline() -> 2:
326 o> 0\n
327 e> read(-1) -> 196:
328 e> adding changesets\n
329 e> adding manifests\n
330 e> adding file changes\n
331 e> added 1 changesets with 1 changes to 1 files\n
332 e> ui.write 1 line\n
333 e> transaction abort!\n
334 e> rollback completed\n
335 e> abort: pretxnchangegroup.fail hook failed\n
336 remote: adding changesets
337 remote: adding manifests
338 remote: adding file changes
339 remote: added 1 changesets with 1 changes to 1 files
340 remote: ui.write 1 line
341 remote: transaction abort!
342 remote: rollback completed
343 remote: abort: pretxnchangegroup.fail hook failed
344 o> read(0) -> 0:
345 o> readline() -> 2:
346 o> 1\n
347 o> read(1) -> 1: 0
348 result: 0
349 remote output:
350
351 And a variation that writes multiple lines using ui.write
352
353 $ cat > .hg/hgrc << EOF
354 > [hooks]
355 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hook2lines
356 > EOF
357
358 $ debugwireproto << EOF
359 > command unbundle
360 > # This is "force" in hex.
361 > heads 666f726365
362 > PUSHFILE ../initial.v1.hg
363 > EOF
364 testing ssh1
365 creating ssh peer from handshake results
366 i> write(104) -> None:
367 i> hello\n
368 i> between\n
369 i> pairs 81\n
370 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
371 i> flush() -> None
372 o> readline() -> 4:
373 o> 384\n
374 o> readline() -> 384:
375 o> capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
376 o> readline() -> 2:
377 o> 1\n
378 o> readline() -> 1:
379 o> \n
380 sending unbundle command
381 i> write(9) -> None:
382 i> unbundle\n
383 i> write(9) -> None:
384 i> heads 10\n
385 i> write(10) -> None: 666f726365
386 i> flush() -> None
387 o> readline() -> 2:
388 o> 0\n
389 i> write(4) -> None:
390 i> 426\n
391 i> write(426) -> None:
392 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
393 i> test\n
394 i> 0 0\n
395 i> foo\n
396 i> \n
397 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
398 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
399 i> \x00\x00\x00\x00\x00\x00\x00\x00
400 i> write(2) -> None:
401 i> 0\n
402 i> flush() -> None
403 o> readline() -> 2:
404 o> 0\n
405 e> read(-1) -> 218:
406 e> adding changesets\n
407 e> adding manifests\n
408 e> adding file changes\n
409 e> added 1 changesets with 1 changes to 1 files\n
410 e> ui.write 2 lines 1\n
411 e> ui.write 2 lines 2\n
412 e> transaction abort!\n
413 e> rollback completed\n
414 e> abort: pretxnchangegroup.fail hook failed\n
415 remote: adding changesets
416 remote: adding manifests
417 remote: adding file changes
418 remote: added 1 changesets with 1 changes to 1 files
419 remote: ui.write 2 lines 1
420 remote: ui.write 2 lines 2
421 remote: transaction abort!
422 remote: rollback completed
423 remote: abort: pretxnchangegroup.fail hook failed
424 o> read(0) -> 0:
425 o> readline() -> 2:
426 o> 1\n
427 o> read(1) -> 1: 0
428 result: 0
429 remote output:
430
431 testing ssh2
432 creating ssh peer from handshake results
433 i> write(171) -> None:
434 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
435 i> hello\n
436 i> between\n
437 i> pairs 81\n
438 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
439 i> flush() -> None
440 o> readline() -> 62:
441 o> upgraded * exp-ssh-v2-0001\n (glob)
442 o> readline() -> 4:
443 o> 383\n
444 o> read(383) -> 383: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
445 o> read(1) -> 1:
446 o> \n
447 sending unbundle command
448 i> write(9) -> None:
449 i> unbundle\n
450 i> write(9) -> None:
451 i> heads 10\n
452 i> write(10) -> None: 666f726365
453 i> flush() -> None
454 o> readline() -> 2:
455 o> 0\n
456 i> write(4) -> None:
457 i> 426\n
458 i> write(426) -> None:
459 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
460 i> test\n
461 i> 0 0\n
462 i> foo\n
463 i> \n
464 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
465 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
466 i> \x00\x00\x00\x00\x00\x00\x00\x00
467 i> write(2) -> None:
468 i> 0\n
469 i> flush() -> None
470 o> readline() -> 2:
471 o> 0\n
472 e> read(-1) -> 218:
473 e> adding changesets\n
474 e> adding manifests\n
475 e> adding file changes\n
476 e> added 1 changesets with 1 changes to 1 files\n
477 e> ui.write 2 lines 1\n
478 e> ui.write 2 lines 2\n
479 e> transaction abort!\n
480 e> rollback completed\n
481 e> abort: pretxnchangegroup.fail hook failed\n
482 remote: adding changesets
483 remote: adding manifests
484 remote: adding file changes
485 remote: added 1 changesets with 1 changes to 1 files
486 remote: ui.write 2 lines 1
487 remote: ui.write 2 lines 2
488 remote: transaction abort!
489 remote: rollback completed
490 remote: abort: pretxnchangegroup.fail hook failed
491 o> read(0) -> 0:
492 o> readline() -> 2:
493 o> 1\n
494 o> read(1) -> 1: 0
495 result: 0
496 remote output:
497
498 And a variation that does a ui.flush() after writing output
499
500 $ cat > .hg/hgrc << EOF
501 > [hooks]
502 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hook1lineflush
503 > EOF
504
505 $ debugwireproto << EOF
506 > command unbundle
507 > # This is "force" in hex.
508 > heads 666f726365
509 > PUSHFILE ../initial.v1.hg
510 > EOF
511 testing ssh1
512 creating ssh peer from handshake results
513 i> write(104) -> None:
514 i> hello\n
515 i> between\n
516 i> pairs 81\n
517 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
518 i> flush() -> None
519 o> readline() -> 4:
520 o> 384\n
521 o> readline() -> 384:
522 o> capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
523 o> readline() -> 2:
524 o> 1\n
525 o> readline() -> 1:
526 o> \n
527 sending unbundle command
528 i> write(9) -> None:
529 i> unbundle\n
530 i> write(9) -> None:
531 i> heads 10\n
532 i> write(10) -> None: 666f726365
533 i> flush() -> None
534 o> readline() -> 2:
535 o> 0\n
536 i> write(4) -> None:
537 i> 426\n
538 i> write(426) -> None:
539 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
540 i> test\n
541 i> 0 0\n
542 i> foo\n
543 i> \n
544 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
545 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
546 i> \x00\x00\x00\x00\x00\x00\x00\x00
547 i> write(2) -> None:
548 i> 0\n
549 i> flush() -> None
550 o> readline() -> 2:
551 o> 0\n
552 e> read(-1) -> 202:
553 e> adding changesets\n
554 e> adding manifests\n
555 e> adding file changes\n
556 e> added 1 changesets with 1 changes to 1 files\n
557 e> ui.write 1 line flush\n
558 e> transaction abort!\n
559 e> rollback completed\n
560 e> abort: pretxnchangegroup.fail hook failed\n
561 remote: adding changesets
562 remote: adding manifests
563 remote: adding file changes
564 remote: added 1 changesets with 1 changes to 1 files
565 remote: ui.write 1 line flush
566 remote: transaction abort!
567 remote: rollback completed
568 remote: abort: pretxnchangegroup.fail hook failed
569 o> read(0) -> 0:
570 o> readline() -> 2:
571 o> 1\n
572 o> read(1) -> 1: 0
573 result: 0
574 remote output:
575
576 testing ssh2
577 creating ssh peer from handshake results
578 i> write(171) -> None:
579 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
580 i> hello\n
581 i> between\n
582 i> pairs 81\n
583 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
584 i> flush() -> None
585 o> readline() -> 62:
586 o> upgraded * exp-ssh-v2-0001\n (glob)
587 o> readline() -> 4:
588 o> 383\n
589 o> read(383) -> 383: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
590 o> read(1) -> 1:
591 o> \n
592 sending unbundle command
593 i> write(9) -> None:
594 i> unbundle\n
595 i> write(9) -> None:
596 i> heads 10\n
597 i> write(10) -> None: 666f726365
598 i> flush() -> None
599 o> readline() -> 2:
600 o> 0\n
601 i> write(4) -> None:
602 i> 426\n
603 i> write(426) -> None:
604 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
605 i> test\n
606 i> 0 0\n
607 i> foo\n
608 i> \n
609 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
610 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
611 i> \x00\x00\x00\x00\x00\x00\x00\x00
612 i> write(2) -> None:
613 i> 0\n
614 i> flush() -> None
615 o> readline() -> 2:
616 o> 0\n
617 e> read(-1) -> 202:
618 e> adding changesets\n
619 e> adding manifests\n
620 e> adding file changes\n
621 e> added 1 changesets with 1 changes to 1 files\n
622 e> ui.write 1 line flush\n
623 e> transaction abort!\n
624 e> rollback completed\n
625 e> abort: pretxnchangegroup.fail hook failed\n
626 remote: adding changesets
627 remote: adding manifests
628 remote: adding file changes
629 remote: added 1 changesets with 1 changes to 1 files
630 remote: ui.write 1 line flush
631 remote: transaction abort!
632 remote: rollback completed
633 remote: abort: pretxnchangegroup.fail hook failed
634 o> read(0) -> 0:
635 o> readline() -> 2:
636 o> 1\n
637 o> read(1) -> 1: 0
638 result: 0
639 remote output:
640
641 Multiple writes + flush
642
643 $ cat > .hg/hgrc << EOF
644 > [hooks]
645 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hookmultiflush
646 > EOF
647
648 $ debugwireproto << EOF
649 > command unbundle
650 > # This is "force" in hex.
651 > heads 666f726365
652 > PUSHFILE ../initial.v1.hg
653 > EOF
654 testing ssh1
655 creating ssh peer from handshake results
656 i> write(104) -> None:
657 i> hello\n
658 i> between\n
659 i> pairs 81\n
660 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
661 i> flush() -> None
662 o> readline() -> 4:
663 o> 384\n
664 o> readline() -> 384:
665 o> capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
666 o> readline() -> 2:
667 o> 1\n
668 o> readline() -> 1:
669 o> \n
670 sending unbundle command
671 i> write(9) -> None:
672 i> unbundle\n
673 i> write(9) -> None:
674 i> heads 10\n
675 i> write(10) -> None: 666f726365
676 i> flush() -> None
677 o> readline() -> 2:
678 o> 0\n
679 i> write(4) -> None:
680 i> 426\n
681 i> write(426) -> None:
682 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
683 i> test\n
684 i> 0 0\n
685 i> foo\n
686 i> \n
687 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
688 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
689 i> \x00\x00\x00\x00\x00\x00\x00\x00
690 i> write(2) -> None:
691 i> 0\n
692 i> flush() -> None
693 o> readline() -> 2:
694 o> 0\n
695 e> read(-1) -> 206:
696 e> adding changesets\n
697 e> adding manifests\n
698 e> adding file changes\n
699 e> added 1 changesets with 1 changes to 1 files\n
700 e> ui.write 1st\n
701 e> ui.write 2nd\n
702 e> transaction abort!\n
703 e> rollback completed\n
704 e> abort: pretxnchangegroup.fail hook failed\n
705 remote: adding changesets
706 remote: adding manifests
707 remote: adding file changes
708 remote: added 1 changesets with 1 changes to 1 files
709 remote: ui.write 1st
710 remote: ui.write 2nd
711 remote: transaction abort!
712 remote: rollback completed
713 remote: abort: pretxnchangegroup.fail hook failed
714 o> read(0) -> 0:
715 o> readline() -> 2:
716 o> 1\n
717 o> read(1) -> 1: 0
718 result: 0
719 remote output:
720
721 testing ssh2
722 creating ssh peer from handshake results
723 i> write(171) -> None:
724 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
725 i> hello\n
726 i> between\n
727 i> pairs 81\n
728 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
729 i> flush() -> None
730 o> readline() -> 62:
731 o> upgraded * exp-ssh-v2-0001\n (glob)
732 o> readline() -> 4:
733 o> 383\n
734 o> read(383) -> 383: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
735 o> read(1) -> 1:
736 o> \n
737 sending unbundle command
738 i> write(9) -> None:
739 i> unbundle\n
740 i> write(9) -> None:
741 i> heads 10\n
742 i> write(10) -> None: 666f726365
743 i> flush() -> None
744 o> readline() -> 2:
745 o> 0\n
746 i> write(4) -> None:
747 i> 426\n
748 i> write(426) -> None:
749 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
750 i> test\n
751 i> 0 0\n
752 i> foo\n
753 i> \n
754 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
755 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
756 i> \x00\x00\x00\x00\x00\x00\x00\x00
757 i> write(2) -> None:
758 i> 0\n
759 i> flush() -> None
760 o> readline() -> 2:
761 o> 0\n
762 e> read(-1) -> 206:
763 e> adding changesets\n
764 e> adding manifests\n
765 e> adding file changes\n
766 e> added 1 changesets with 1 changes to 1 files\n
767 e> ui.write 1st\n
768 e> ui.write 2nd\n
769 e> transaction abort!\n
770 e> rollback completed\n
771 e> abort: pretxnchangegroup.fail hook failed\n
772 remote: adding changesets
773 remote: adding manifests
774 remote: adding file changes
775 remote: added 1 changesets with 1 changes to 1 files
776 remote: ui.write 1st
777 remote: ui.write 2nd
778 remote: transaction abort!
779 remote: rollback completed
780 remote: abort: pretxnchangegroup.fail hook failed
781 o> read(0) -> 0:
782 o> readline() -> 2:
783 o> 1\n
784 o> read(1) -> 1: 0
785 result: 0
786 remote output:
787
788 ui.write() + ui.write_err() output is captured
789
790 $ cat > .hg/hgrc << EOF
791 > [hooks]
792 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hookwriteandwriteerr
793 > EOF
794
795 $ debugwireproto << EOF
796 > command unbundle
797 > # This is "force" in hex.
798 > heads 666f726365
799 > PUSHFILE ../initial.v1.hg
800 > EOF
801 testing ssh1
802 creating ssh peer from handshake results
803 i> write(104) -> None:
804 i> hello\n
805 i> between\n
806 i> pairs 81\n
807 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
808 i> flush() -> None
809 o> readline() -> 4:
810 o> 384\n
811 o> readline() -> 384:
812 o> capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
813 o> readline() -> 2:
814 o> 1\n
815 o> readline() -> 1:
816 o> \n
817 sending unbundle command
818 i> write(9) -> None:
819 i> unbundle\n
820 i> write(9) -> None:
821 i> heads 10\n
822 i> write(10) -> None: 666f726365
823 i> flush() -> None
824 o> readline() -> 2:
825 o> 0\n
826 i> write(4) -> None:
827 i> 426\n
828 i> write(426) -> None:
829 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
830 i> test\n
831 i> 0 0\n
832 i> foo\n
833 i> \n
834 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
835 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
836 i> \x00\x00\x00\x00\x00\x00\x00\x00
837 i> write(2) -> None:
838 i> 0\n
839 i> flush() -> None
840 o> readline() -> 2:
841 o> 0\n
842 e> read(-1) -> 232:
843 e> adding changesets\n
844 e> adding manifests\n
845 e> adding file changes\n
846 e> added 1 changesets with 1 changes to 1 files\n
847 e> ui.write 1\n
848 e> ui.write_err 1\n
849 e> ui.write 2\n
850 e> ui.write_err 2\n
851 e> transaction abort!\n
852 e> rollback completed\n
853 e> abort: pretxnchangegroup.fail hook failed\n
854 remote: adding changesets
855 remote: adding manifests
856 remote: adding file changes
857 remote: added 1 changesets with 1 changes to 1 files
858 remote: ui.write 1
859 remote: ui.write_err 1
860 remote: ui.write 2
861 remote: ui.write_err 2
862 remote: transaction abort!
863 remote: rollback completed
864 remote: abort: pretxnchangegroup.fail hook failed
865 o> read(0) -> 0:
866 o> readline() -> 2:
867 o> 1\n
868 o> read(1) -> 1: 0
869 result: 0
870 remote output:
871
872 testing ssh2
873 creating ssh peer from handshake results
874 i> write(171) -> None:
875 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
876 i> hello\n
877 i> between\n
878 i> pairs 81\n
879 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
880 i> flush() -> None
881 o> readline() -> 62:
882 o> upgraded * exp-ssh-v2-0001\n (glob)
883 o> readline() -> 4:
884 o> 383\n
885 o> read(383) -> 383: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
886 o> read(1) -> 1:
887 o> \n
888 sending unbundle command
889 i> write(9) -> None:
890 i> unbundle\n
891 i> write(9) -> None:
892 i> heads 10\n
893 i> write(10) -> None: 666f726365
894 i> flush() -> None
895 o> readline() -> 2:
896 o> 0\n
897 i> write(4) -> None:
898 i> 426\n
899 i> write(426) -> None:
900 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
901 i> test\n
902 i> 0 0\n
903 i> foo\n
904 i> \n
905 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
906 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
907 i> \x00\x00\x00\x00\x00\x00\x00\x00
908 i> write(2) -> None:
909 i> 0\n
910 i> flush() -> None
911 o> readline() -> 2:
912 o> 0\n
913 e> read(-1) -> 232:
914 e> adding changesets\n
915 e> adding manifests\n
916 e> adding file changes\n
917 e> added 1 changesets with 1 changes to 1 files\n
918 e> ui.write 1\n
919 e> ui.write_err 1\n
920 e> ui.write 2\n
921 e> ui.write_err 2\n
922 e> transaction abort!\n
923 e> rollback completed\n
924 e> abort: pretxnchangegroup.fail hook failed\n
925 remote: adding changesets
926 remote: adding manifests
927 remote: adding file changes
928 remote: added 1 changesets with 1 changes to 1 files
929 remote: ui.write 1
930 remote: ui.write_err 1
931 remote: ui.write 2
932 remote: ui.write_err 2
933 remote: transaction abort!
934 remote: rollback completed
935 remote: abort: pretxnchangegroup.fail hook failed
936 o> read(0) -> 0:
937 o> readline() -> 2:
938 o> 1\n
939 o> read(1) -> 1: 0
940 result: 0
941 remote output:
942
943 print() output is captured
944
945 $ cat > .hg/hgrc << EOF
946 > [hooks]
947 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hookprintstdout
948 > EOF
949
950 $ debugwireproto << EOF
951 > command unbundle
952 > # This is "force" in hex.
953 > heads 666f726365
954 > PUSHFILE ../initial.v1.hg
955 > EOF
956 testing ssh1
957 creating ssh peer from handshake results
958 i> write(104) -> None:
959 i> hello\n
960 i> between\n
961 i> pairs 81\n
962 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
963 i> flush() -> None
964 o> readline() -> 4:
965 o> 384\n
966 o> readline() -> 384:
967 o> capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
968 o> readline() -> 2:
969 o> 1\n
970 o> readline() -> 1:
971 o> \n
972 sending unbundle command
973 i> write(9) -> None:
974 i> unbundle\n
975 i> write(9) -> None:
976 i> heads 10\n
977 i> write(10) -> None: 666f726365
978 i> flush() -> None
979 o> readline() -> 2:
980 o> 0\n
981 i> write(4) -> None:
982 i> 426\n
983 i> write(426) -> None:
984 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
985 i> test\n
986 i> 0 0\n
987 i> foo\n
988 i> \n
989 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
990 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
991 i> \x00\x00\x00\x00\x00\x00\x00\x00
992 i> write(2) -> None:
993 i> 0\n
994 i> flush() -> None
995 o> readline() -> 2:
996 o> 0\n
997 e> read(-1) -> 193:
998 e> adding changesets\n
999 e> adding manifests\n
1000 e> adding file changes\n
1001 e> added 1 changesets with 1 changes to 1 files\n
1002 e> printed line\n
1003 e> transaction abort!\n
1004 e> rollback completed\n
1005 e> abort: pretxnchangegroup.fail hook failed\n
1006 remote: adding changesets
1007 remote: adding manifests
1008 remote: adding file changes
1009 remote: added 1 changesets with 1 changes to 1 files
1010 remote: printed line
1011 remote: transaction abort!
1012 remote: rollback completed
1013 remote: abort: pretxnchangegroup.fail hook failed
1014 o> read(0) -> 0:
1015 o> readline() -> 2:
1016 o> 1\n
1017 o> read(1) -> 1: 0
1018 result: 0
1019 remote output:
1020
1021 testing ssh2
1022 creating ssh peer from handshake results
1023 i> write(171) -> None:
1024 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1025 i> hello\n
1026 i> between\n
1027 i> pairs 81\n
1028 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1029 i> flush() -> None
1030 o> readline() -> 62:
1031 o> upgraded * exp-ssh-v2-0001\n (glob)
1032 o> readline() -> 4:
1033 o> 383\n
1034 o> read(383) -> 383: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1035 o> read(1) -> 1:
1036 o> \n
1037 sending unbundle command
1038 i> write(9) -> None:
1039 i> unbundle\n
1040 i> write(9) -> None:
1041 i> heads 10\n
1042 i> write(10) -> None: 666f726365
1043 i> flush() -> None
1044 o> readline() -> 2:
1045 o> 0\n
1046 i> write(4) -> None:
1047 i> 426\n
1048 i> write(426) -> None:
1049 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1050 i> test\n
1051 i> 0 0\n
1052 i> foo\n
1053 i> \n
1054 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1055 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1056 i> \x00\x00\x00\x00\x00\x00\x00\x00
1057 i> write(2) -> None:
1058 i> 0\n
1059 i> flush() -> None
1060 o> readline() -> 2:
1061 o> 0\n
1062 e> read(-1) -> 193:
1063 e> adding changesets\n
1064 e> adding manifests\n
1065 e> adding file changes\n
1066 e> added 1 changesets with 1 changes to 1 files\n
1067 e> printed line\n
1068 e> transaction abort!\n
1069 e> rollback completed\n
1070 e> abort: pretxnchangegroup.fail hook failed\n
1071 remote: adding changesets
1072 remote: adding manifests
1073 remote: adding file changes
1074 remote: added 1 changesets with 1 changes to 1 files
1075 remote: printed line
1076 remote: transaction abort!
1077 remote: rollback completed
1078 remote: abort: pretxnchangegroup.fail hook failed
1079 o> read(0) -> 0:
1080 o> readline() -> 2:
1081 o> 1\n
1082 o> read(1) -> 1: 0
1083 result: 0
1084 remote output:
1085
1086 Mixed print() and ui.write() are both captured
1087
1088 $ cat > .hg/hgrc << EOF
1089 > [hooks]
1090 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hookprintandwrite
1091 > EOF
1092
1093 $ debugwireproto << EOF
1094 > command unbundle
1095 > # This is "force" in hex.
1096 > heads 666f726365
1097 > PUSHFILE ../initial.v1.hg
1098 > EOF
1099 testing ssh1
1100 creating ssh peer from handshake results
1101 i> write(104) -> None:
1102 i> hello\n
1103 i> between\n
1104 i> pairs 81\n
1105 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1106 i> flush() -> None
1107 o> readline() -> 4:
1108 o> 384\n
1109 o> readline() -> 384:
1110 o> capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1111 o> readline() -> 2:
1112 o> 1\n
1113 o> readline() -> 1:
1114 o> \n
1115 sending unbundle command
1116 i> write(9) -> None:
1117 i> unbundle\n
1118 i> write(9) -> None:
1119 i> heads 10\n
1120 i> write(10) -> None: 666f726365
1121 i> flush() -> None
1122 o> readline() -> 2:
1123 o> 0\n
1124 i> write(4) -> None:
1125 i> 426\n
1126 i> write(426) -> None:
1127 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1128 i> test\n
1129 i> 0 0\n
1130 i> foo\n
1131 i> \n
1132 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1133 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1134 i> \x00\x00\x00\x00\x00\x00\x00\x00
1135 i> write(2) -> None:
1136 i> 0\n
1137 i> flush() -> None
1138 o> readline() -> 2:
1139 o> 0\n
1140 e> read(-1) -> 218:
1141 e> adding changesets\n
1142 e> adding manifests\n
1143 e> adding file changes\n
1144 e> added 1 changesets with 1 changes to 1 files\n
1145 e> ui.write 1\n
1146 e> ui.write 2\n
1147 e> print 1\n
1148 e> print 2\n
1149 e> transaction abort!\n
1150 e> rollback completed\n
1151 e> abort: pretxnchangegroup.fail hook failed\n
1152 remote: adding changesets
1153 remote: adding manifests
1154 remote: adding file changes
1155 remote: added 1 changesets with 1 changes to 1 files
1156 remote: ui.write 1
1157 remote: ui.write 2
1158 remote: print 1
1159 remote: print 2
1160 remote: transaction abort!
1161 remote: rollback completed
1162 remote: abort: pretxnchangegroup.fail hook failed
1163 o> read(0) -> 0:
1164 o> readline() -> 2:
1165 o> 1\n
1166 o> read(1) -> 1: 0
1167 result: 0
1168 remote output:
1169
1170 testing ssh2
1171 creating ssh peer from handshake results
1172 i> write(171) -> None:
1173 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1174 i> hello\n
1175 i> between\n
1176 i> pairs 81\n
1177 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1178 i> flush() -> None
1179 o> readline() -> 62:
1180 o> upgraded * exp-ssh-v2-0001\n (glob)
1181 o> readline() -> 4:
1182 o> 383\n
1183 o> read(383) -> 383: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1184 o> read(1) -> 1:
1185 o> \n
1186 sending unbundle command
1187 i> write(9) -> None:
1188 i> unbundle\n
1189 i> write(9) -> None:
1190 i> heads 10\n
1191 i> write(10) -> None: 666f726365
1192 i> flush() -> None
1193 o> readline() -> 2:
1194 o> 0\n
1195 i> write(4) -> None:
1196 i> 426\n
1197 i> write(426) -> None:
1198 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1199 i> test\n
1200 i> 0 0\n
1201 i> foo\n
1202 i> \n
1203 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1204 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1205 i> \x00\x00\x00\x00\x00\x00\x00\x00
1206 i> write(2) -> None:
1207 i> 0\n
1208 i> flush() -> None
1209 o> readline() -> 2:
1210 o> 0\n
1211 e> read(-1) -> 218:
1212 e> adding changesets\n
1213 e> adding manifests\n
1214 e> adding file changes\n
1215 e> added 1 changesets with 1 changes to 1 files\n
1216 e> ui.write 1\n
1217 e> ui.write 2\n
1218 e> print 1\n
1219 e> print 2\n
1220 e> transaction abort!\n
1221 e> rollback completed\n
1222 e> abort: pretxnchangegroup.fail hook failed\n
1223 remote: adding changesets
1224 remote: adding manifests
1225 remote: adding file changes
1226 remote: added 1 changesets with 1 changes to 1 files
1227 remote: ui.write 1
1228 remote: ui.write 2
1229 remote: print 1
1230 remote: print 2
1231 remote: transaction abort!
1232 remote: rollback completed
1233 remote: abort: pretxnchangegroup.fail hook failed
1234 o> read(0) -> 0:
1235 o> readline() -> 2:
1236 o> 1\n
1237 o> read(1) -> 1: 0
1238 result: 0
1239 remote output:
1240
1241 print() to stdout and stderr both get captured
1242
1243 $ cat > .hg/hgrc << EOF
1244 > [hooks]
1245 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hookprintstderrandstdout
1246 > EOF
1247
1248 $ debugwireproto << EOF
1249 > command unbundle
1250 > # This is "force" in hex.
1251 > heads 666f726365
1252 > PUSHFILE ../initial.v1.hg
1253 > EOF
1254 testing ssh1
1255 creating ssh peer from handshake results
1256 i> write(104) -> None:
1257 i> hello\n
1258 i> between\n
1259 i> pairs 81\n
1260 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1261 i> flush() -> None
1262 o> readline() -> 4:
1263 o> 384\n
1264 o> readline() -> 384:
1265 o> capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1266 o> readline() -> 2:
1267 o> 1\n
1268 o> readline() -> 1:
1269 o> \n
1270 sending unbundle command
1271 i> write(9) -> None:
1272 i> unbundle\n
1273 i> write(9) -> None:
1274 i> heads 10\n
1275 i> write(10) -> None: 666f726365
1276 i> flush() -> None
1277 o> readline() -> 2:
1278 o> 0\n
1279 i> write(4) -> None:
1280 i> 426\n
1281 i> write(426) -> None:
1282 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1283 i> test\n
1284 i> 0 0\n
1285 i> foo\n
1286 i> \n
1287 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1288 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1289 i> \x00\x00\x00\x00\x00\x00\x00\x00
1290 i> write(2) -> None:
1291 i> 0\n
1292 i> flush() -> None
1293 o> readline() -> 2:
1294 o> 0\n
1295 e> read(-1) -> 216:
1296 e> adding changesets\n
1297 e> adding manifests\n
1298 e> adding file changes\n
1299 e> added 1 changesets with 1 changes to 1 files\n
1300 e> stderr 1\n
1301 e> stderr 2\n
1302 e> stdout 1\n
1303 e> stdout 2\n
1304 e> transaction abort!\n
1305 e> rollback completed\n
1306 e> abort: pretxnchangegroup.fail hook failed\n
1307 remote: adding changesets
1308 remote: adding manifests
1309 remote: adding file changes
1310 remote: added 1 changesets with 1 changes to 1 files
1311 remote: stderr 1
1312 remote: stderr 2
1313 remote: stdout 1
1314 remote: stdout 2
1315 remote: transaction abort!
1316 remote: rollback completed
1317 remote: abort: pretxnchangegroup.fail hook failed
1318 o> read(0) -> 0:
1319 o> readline() -> 2:
1320 o> 1\n
1321 o> read(1) -> 1: 0
1322 result: 0
1323 remote output:
1324
1325 testing ssh2
1326 creating ssh peer from handshake results
1327 i> write(171) -> None:
1328 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1329 i> hello\n
1330 i> between\n
1331 i> pairs 81\n
1332 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1333 i> flush() -> None
1334 o> readline() -> 62:
1335 o> upgraded * exp-ssh-v2-0001\n (glob)
1336 o> readline() -> 4:
1337 o> 383\n
1338 o> read(383) -> 383: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1339 o> read(1) -> 1:
1340 o> \n
1341 sending unbundle command
1342 i> write(9) -> None:
1343 i> unbundle\n
1344 i> write(9) -> None:
1345 i> heads 10\n
1346 i> write(10) -> None: 666f726365
1347 i> flush() -> None
1348 o> readline() -> 2:
1349 o> 0\n
1350 i> write(4) -> None:
1351 i> 426\n
1352 i> write(426) -> None:
1353 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1354 i> test\n
1355 i> 0 0\n
1356 i> foo\n
1357 i> \n
1358 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1359 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1360 i> \x00\x00\x00\x00\x00\x00\x00\x00
1361 i> write(2) -> None:
1362 i> 0\n
1363 i> flush() -> None
1364 o> readline() -> 2:
1365 o> 0\n
1366 e> read(-1) -> 216:
1367 e> adding changesets\n
1368 e> adding manifests\n
1369 e> adding file changes\n
1370 e> added 1 changesets with 1 changes to 1 files\n
1371 e> stderr 1\n
1372 e> stderr 2\n
1373 e> stdout 1\n
1374 e> stdout 2\n
1375 e> transaction abort!\n
1376 e> rollback completed\n
1377 e> abort: pretxnchangegroup.fail hook failed\n
1378 remote: adding changesets
1379 remote: adding manifests
1380 remote: adding file changes
1381 remote: added 1 changesets with 1 changes to 1 files
1382 remote: stderr 1
1383 remote: stderr 2
1384 remote: stdout 1
1385 remote: stdout 2
1386 remote: transaction abort!
1387 remote: rollback completed
1388 remote: abort: pretxnchangegroup.fail hook failed
1389 o> read(0) -> 0:
1390 o> readline() -> 2:
1391 o> 1\n
1392 o> read(1) -> 1: 0
1393 result: 0
1394 remote output:
1395
1396 $ cd ..
1397
1398 Pushing a bundle1 with no output
1399
1400 $ hg init simplerepo
1401 $ cd simplerepo
1402
1403 $ debugwireproto 1 << EOF
1404 > command unbundle
1405 > # This is "force" in hex.
1406 > heads 666f726365
1407 > PUSHFILE ../initial.v1.hg
1408 > EOF
1409 testing ssh1
1410 creating ssh peer from handshake results
1411 i> write(104) -> None:
1412 i> hello\n
1413 i> between\n
1414 i> pairs 81\n
1415 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1416 i> flush() -> None
1417 o> readline() -> 4:
1418 o> 384\n
1419 o> readline() -> 384:
1420 o> capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1421 o> readline() -> 2:
1422 o> 1\n
1423 o> readline() -> 1:
1424 o> \n
1425 sending unbundle command
1426 i> write(9) -> None:
1427 i> unbundle\n
1428 i> write(9) -> None:
1429 i> heads 10\n
1430 i> write(10) -> None: 666f726365
1431 i> flush() -> None
1432 o> readline() -> 2:
1433 o> 0\n
1434 i> write(4) -> None:
1435 i> 426\n
1436 i> write(426) -> None:
1437 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1438 i> test\n
1439 i> 0 0\n
1440 i> foo\n
1441 i> \n
1442 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1443 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1444 i> \x00\x00\x00\x00\x00\x00\x00\x00
1445 i> write(2) -> None:
1446 i> 0\n
1447 i> flush() -> None
1448 o> readline() -> 2:
1449 o> 0\n
1450 e> read(-1) -> 100:
1451 e> adding changesets\n
1452 e> adding manifests\n
1453 e> adding file changes\n
1454 e> added 1 changesets with 1 changes to 1 files\n
1455 remote: adding changesets
1456 remote: adding manifests
1457 remote: adding file changes
1458 remote: added 1 changesets with 1 changes to 1 files
1459 o> read(0) -> 0:
1460 o> readline() -> 2:
1461 o> 1\n
1462 o> read(1) -> 1: 1
1463 result: 1
1464 remote output:
1465
1466 testing ssh2
1467 creating ssh peer from handshake results
1468 i> write(171) -> None:
1469 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1470 i> hello\n
1471 i> between\n
1472 i> pairs 81\n
1473 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1474 i> flush() -> None
1475 o> readline() -> 62:
1476 o> upgraded * exp-ssh-v2-0001\n (glob)
1477 o> readline() -> 4:
1478 o> 383\n
1479 o> read(383) -> 383: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1480 o> read(1) -> 1:
1481 o> \n
1482 sending unbundle command
1483 i> write(9) -> None:
1484 i> unbundle\n
1485 i> write(9) -> None:
1486 i> heads 10\n
1487 i> write(10) -> None: 666f726365
1488 i> flush() -> None
1489 o> readline() -> 2:
1490 o> 0\n
1491 i> write(4) -> None:
1492 i> 426\n
1493 i> write(426) -> None:
1494 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1495 i> test\n
1496 i> 0 0\n
1497 i> foo\n
1498 i> \n
1499 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1500 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1501 i> \x00\x00\x00\x00\x00\x00\x00\x00
1502 i> write(2) -> None:
1503 i> 0\n
1504 i> flush() -> None
1505 o> readline() -> 2:
1506 o> 0\n
1507 e> read(-1) -> 100:
1508 e> adding changesets\n
1509 e> adding manifests\n
1510 e> adding file changes\n
1511 e> added 1 changesets with 1 changes to 1 files\n
1512 remote: adding changesets
1513 remote: adding manifests
1514 remote: adding file changes
1515 remote: added 1 changesets with 1 changes to 1 files
1516 o> read(0) -> 0:
1517 o> readline() -> 2:
1518 o> 1\n
1519 o> read(1) -> 1: 1
1520 result: 1
1521 remote output:
1522
1523 $ cd ..
1524
1525 Pushing a bundle1 with ui.write() and ui.write_err()
1526
1527 $ cat > $TESTTMP/hook << EOF
1528 > def hookuiwrite(ui, repo, **kwargs):
1529 > ui.write('ui.write 1\n')
1530 > ui.write_err('ui.write_err 1\n')
1531 > ui.write('ui.write 2\n')
1532 > ui.write_err('ui.write_err 2\n')
1533 > EOF
1534
1535 $ hg init uiwriterepo
1536 $ cd uiwriterepo
1537 $ cat > .hg/hgrc << EOF
1538 > [hooks]
1539 > pretxnchangegroup.hook = python:$TESTTMP/hook:hookuiwrite
1540 > EOF
1541
1542 $ debugwireproto 1 << EOF
1543 > command unbundle
1544 > # This is "force" in hex.
1545 > heads 666f726365
1546 > PUSHFILE ../initial.v1.hg
1547 > EOF
1548 testing ssh1
1549 creating ssh peer from handshake results
1550 i> write(104) -> None:
1551 i> hello\n
1552 i> between\n
1553 i> pairs 81\n
1554 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1555 i> flush() -> None
1556 o> readline() -> 4:
1557 o> 384\n
1558 o> readline() -> 384:
1559 o> capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1560 o> readline() -> 2:
1561 o> 1\n
1562 o> readline() -> 1:
1563 o> \n
1564 sending unbundle command
1565 i> write(9) -> None:
1566 i> unbundle\n
1567 i> write(9) -> None:
1568 i> heads 10\n
1569 i> write(10) -> None: 666f726365
1570 i> flush() -> None
1571 o> readline() -> 2:
1572 o> 0\n
1573 i> write(4) -> None:
1574 i> 426\n
1575 i> write(426) -> None:
1576 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1577 i> test\n
1578 i> 0 0\n
1579 i> foo\n
1580 i> \n
1581 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1582 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1583 i> \x00\x00\x00\x00\x00\x00\x00\x00
1584 i> write(2) -> None:
1585 i> 0\n
1586 i> flush() -> None
1587 o> readline() -> 2:
1588 o> 0\n
1589 e> read(-1) -> 152:
1590 e> adding changesets\n
1591 e> adding manifests\n
1592 e> adding file changes\n
1593 e> added 1 changesets with 1 changes to 1 files\n
1594 e> ui.write 1\n
1595 e> ui.write_err 1\n
1596 e> ui.write 2\n
1597 e> ui.write_err 2\n
1598 remote: adding changesets
1599 remote: adding manifests
1600 remote: adding file changes
1601 remote: added 1 changesets with 1 changes to 1 files
1602 remote: ui.write 1
1603 remote: ui.write_err 1
1604 remote: ui.write 2
1605 remote: ui.write_err 2
1606 o> read(0) -> 0:
1607 o> readline() -> 2:
1608 o> 1\n
1609 o> read(1) -> 1: 1
1610 result: 1
1611 remote output:
1612
1613 testing ssh2
1614 creating ssh peer from handshake results
1615 i> write(171) -> None:
1616 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1617 i> hello\n
1618 i> between\n
1619 i> pairs 81\n
1620 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1621 i> flush() -> None
1622 o> readline() -> 62:
1623 o> upgraded * exp-ssh-v2-0001\n (glob)
1624 o> readline() -> 4:
1625 o> 383\n
1626 o> read(383) -> 383: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1627 o> read(1) -> 1:
1628 o> \n
1629 sending unbundle command
1630 i> write(9) -> None:
1631 i> unbundle\n
1632 i> write(9) -> None:
1633 i> heads 10\n
1634 i> write(10) -> None: 666f726365
1635 i> flush() -> None
1636 o> readline() -> 2:
1637 o> 0\n
1638 i> write(4) -> None:
1639 i> 426\n
1640 i> write(426) -> None:
1641 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1642 i> test\n
1643 i> 0 0\n
1644 i> foo\n
1645 i> \n
1646 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1647 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1648 i> \x00\x00\x00\x00\x00\x00\x00\x00
1649 i> write(2) -> None:
1650 i> 0\n
1651 i> flush() -> None
1652 o> readline() -> 2:
1653 o> 0\n
1654 e> read(-1) -> 152:
1655 e> adding changesets\n
1656 e> adding manifests\n
1657 e> adding file changes\n
1658 e> added 1 changesets with 1 changes to 1 files\n
1659 e> ui.write 1\n
1660 e> ui.write_err 1\n
1661 e> ui.write 2\n
1662 e> ui.write_err 2\n
1663 remote: adding changesets
1664 remote: adding manifests
1665 remote: adding file changes
1666 remote: added 1 changesets with 1 changes to 1 files
1667 remote: ui.write 1
1668 remote: ui.write_err 1
1669 remote: ui.write 2
1670 remote: ui.write_err 2
1671 o> read(0) -> 0:
1672 o> readline() -> 2:
1673 o> 1\n
1674 o> read(1) -> 1: 1
1675 result: 1
1676 remote output:
@@ -1,2811 +1,2837 b''
1 1 # debugcommands.py - command processing for debug* commands
2 2 #
3 3 # Copyright 2005-2016 Matt Mackall <mpm@selenic.com>
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.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import codecs
11 11 import collections
12 12 import difflib
13 13 import errno
14 14 import operator
15 15 import os
16 16 import random
17 17 import socket
18 18 import ssl
19 19 import string
20 20 import subprocess
21 21 import sys
22 22 import tempfile
23 23 import time
24 24
25 25 from .i18n import _
26 26 from .node import (
27 27 bin,
28 28 hex,
29 29 nullhex,
30 30 nullid,
31 31 nullrev,
32 32 short,
33 33 )
34 34 from . import (
35 35 bundle2,
36 36 changegroup,
37 37 cmdutil,
38 38 color,
39 39 context,
40 40 dagparser,
41 41 dagutil,
42 42 encoding,
43 43 error,
44 44 exchange,
45 45 extensions,
46 46 filemerge,
47 47 fileset,
48 48 formatter,
49 49 hg,
50 50 localrepo,
51 51 lock as lockmod,
52 52 logcmdutil,
53 53 merge as mergemod,
54 54 obsolete,
55 55 obsutil,
56 56 phases,
57 57 policy,
58 58 pvec,
59 59 pycompat,
60 60 registrar,
61 61 repair,
62 62 revlog,
63 63 revset,
64 64 revsetlang,
65 65 scmutil,
66 66 setdiscovery,
67 67 simplemerge,
68 68 smartset,
69 69 sshpeer,
70 70 sslutil,
71 71 streamclone,
72 72 templater,
73 73 treediscovery,
74 74 upgrade,
75 75 url as urlmod,
76 76 util,
77 77 vfs as vfsmod,
78 78 wireprotoserver,
79 79 )
80 80
81 81 release = lockmod.release
82 82
83 83 command = registrar.command()
84 84
85 85 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
86 86 def debugancestor(ui, repo, *args):
87 87 """find the ancestor revision of two revisions in a given index"""
88 88 if len(args) == 3:
89 89 index, rev1, rev2 = args
90 90 r = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False), index)
91 91 lookup = r.lookup
92 92 elif len(args) == 2:
93 93 if not repo:
94 94 raise error.Abort(_('there is no Mercurial repository here '
95 95 '(.hg not found)'))
96 96 rev1, rev2 = args
97 97 r = repo.changelog
98 98 lookup = repo.lookup
99 99 else:
100 100 raise error.Abort(_('either two or three arguments required'))
101 101 a = r.ancestor(lookup(rev1), lookup(rev2))
102 102 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
103 103
104 104 @command('debugapplystreamclonebundle', [], 'FILE')
105 105 def debugapplystreamclonebundle(ui, repo, fname):
106 106 """apply a stream clone bundle file"""
107 107 f = hg.openpath(ui, fname)
108 108 gen = exchange.readbundle(ui, f, fname)
109 109 gen.apply(repo)
110 110
111 111 @command('debugbuilddag',
112 112 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
113 113 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
114 114 ('n', 'new-file', None, _('add new file at each rev'))],
115 115 _('[OPTION]... [TEXT]'))
116 116 def debugbuilddag(ui, repo, text=None,
117 117 mergeable_file=False,
118 118 overwritten_file=False,
119 119 new_file=False):
120 120 """builds a repo with a given DAG from scratch in the current empty repo
121 121
122 122 The description of the DAG is read from stdin if not given on the
123 123 command line.
124 124
125 125 Elements:
126 126
127 127 - "+n" is a linear run of n nodes based on the current default parent
128 128 - "." is a single node based on the current default parent
129 129 - "$" resets the default parent to null (implied at the start);
130 130 otherwise the default parent is always the last node created
131 131 - "<p" sets the default parent to the backref p
132 132 - "*p" is a fork at parent p, which is a backref
133 133 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
134 134 - "/p2" is a merge of the preceding node and p2
135 135 - ":tag" defines a local tag for the preceding node
136 136 - "@branch" sets the named branch for subsequent nodes
137 137 - "#...\\n" is a comment up to the end of the line
138 138
139 139 Whitespace between the above elements is ignored.
140 140
141 141 A backref is either
142 142
143 143 - a number n, which references the node curr-n, where curr is the current
144 144 node, or
145 145 - the name of a local tag you placed earlier using ":tag", or
146 146 - empty to denote the default parent.
147 147
148 148 All string valued-elements are either strictly alphanumeric, or must
149 149 be enclosed in double quotes ("..."), with "\\" as escape character.
150 150 """
151 151
152 152 if text is None:
153 153 ui.status(_("reading DAG from stdin\n"))
154 154 text = ui.fin.read()
155 155
156 156 cl = repo.changelog
157 157 if len(cl) > 0:
158 158 raise error.Abort(_('repository is not empty'))
159 159
160 160 # determine number of revs in DAG
161 161 total = 0
162 162 for type, data in dagparser.parsedag(text):
163 163 if type == 'n':
164 164 total += 1
165 165
166 166 if mergeable_file:
167 167 linesperrev = 2
168 168 # make a file with k lines per rev
169 169 initialmergedlines = ['%d' % i for i in xrange(0, total * linesperrev)]
170 170 initialmergedlines.append("")
171 171
172 172 tags = []
173 173
174 174 wlock = lock = tr = None
175 175 try:
176 176 wlock = repo.wlock()
177 177 lock = repo.lock()
178 178 tr = repo.transaction("builddag")
179 179
180 180 at = -1
181 181 atbranch = 'default'
182 182 nodeids = []
183 183 id = 0
184 184 ui.progress(_('building'), id, unit=_('revisions'), total=total)
185 185 for type, data in dagparser.parsedag(text):
186 186 if type == 'n':
187 187 ui.note(('node %s\n' % pycompat.bytestr(data)))
188 188 id, ps = data
189 189
190 190 files = []
191 191 filecontent = {}
192 192
193 193 p2 = None
194 194 if mergeable_file:
195 195 fn = "mf"
196 196 p1 = repo[ps[0]]
197 197 if len(ps) > 1:
198 198 p2 = repo[ps[1]]
199 199 pa = p1.ancestor(p2)
200 200 base, local, other = [x[fn].data() for x in (pa, p1,
201 201 p2)]
202 202 m3 = simplemerge.Merge3Text(base, local, other)
203 203 ml = [l.strip() for l in m3.merge_lines()]
204 204 ml.append("")
205 205 elif at > 0:
206 206 ml = p1[fn].data().split("\n")
207 207 else:
208 208 ml = initialmergedlines
209 209 ml[id * linesperrev] += " r%i" % id
210 210 mergedtext = "\n".join(ml)
211 211 files.append(fn)
212 212 filecontent[fn] = mergedtext
213 213
214 214 if overwritten_file:
215 215 fn = "of"
216 216 files.append(fn)
217 217 filecontent[fn] = "r%i\n" % id
218 218
219 219 if new_file:
220 220 fn = "nf%i" % id
221 221 files.append(fn)
222 222 filecontent[fn] = "r%i\n" % id
223 223 if len(ps) > 1:
224 224 if not p2:
225 225 p2 = repo[ps[1]]
226 226 for fn in p2:
227 227 if fn.startswith("nf"):
228 228 files.append(fn)
229 229 filecontent[fn] = p2[fn].data()
230 230
231 231 def fctxfn(repo, cx, path):
232 232 if path in filecontent:
233 233 return context.memfilectx(repo, cx, path,
234 234 filecontent[path])
235 235 return None
236 236
237 237 if len(ps) == 0 or ps[0] < 0:
238 238 pars = [None, None]
239 239 elif len(ps) == 1:
240 240 pars = [nodeids[ps[0]], None]
241 241 else:
242 242 pars = [nodeids[p] for p in ps]
243 243 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
244 244 date=(id, 0),
245 245 user="debugbuilddag",
246 246 extra={'branch': atbranch})
247 247 nodeid = repo.commitctx(cx)
248 248 nodeids.append(nodeid)
249 249 at = id
250 250 elif type == 'l':
251 251 id, name = data
252 252 ui.note(('tag %s\n' % name))
253 253 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
254 254 elif type == 'a':
255 255 ui.note(('branch %s\n' % data))
256 256 atbranch = data
257 257 ui.progress(_('building'), id, unit=_('revisions'), total=total)
258 258 tr.close()
259 259
260 260 if tags:
261 261 repo.vfs.write("localtags", "".join(tags))
262 262 finally:
263 263 ui.progress(_('building'), None)
264 264 release(tr, lock, wlock)
265 265
266 266 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
267 267 indent_string = ' ' * indent
268 268 if all:
269 269 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
270 270 % indent_string)
271 271
272 272 def showchunks(named):
273 273 ui.write("\n%s%s\n" % (indent_string, named))
274 274 for deltadata in gen.deltaiter():
275 275 node, p1, p2, cs, deltabase, delta, flags = deltadata
276 276 ui.write("%s%s %s %s %s %s %d\n" %
277 277 (indent_string, hex(node), hex(p1), hex(p2),
278 278 hex(cs), hex(deltabase), len(delta)))
279 279
280 280 chunkdata = gen.changelogheader()
281 281 showchunks("changelog")
282 282 chunkdata = gen.manifestheader()
283 283 showchunks("manifest")
284 284 for chunkdata in iter(gen.filelogheader, {}):
285 285 fname = chunkdata['filename']
286 286 showchunks(fname)
287 287 else:
288 288 if isinstance(gen, bundle2.unbundle20):
289 289 raise error.Abort(_('use debugbundle2 for this file'))
290 290 chunkdata = gen.changelogheader()
291 291 for deltadata in gen.deltaiter():
292 292 node, p1, p2, cs, deltabase, delta, flags = deltadata
293 293 ui.write("%s%s\n" % (indent_string, hex(node)))
294 294
295 295 def _debugobsmarkers(ui, part, indent=0, **opts):
296 296 """display version and markers contained in 'data'"""
297 297 opts = pycompat.byteskwargs(opts)
298 298 data = part.read()
299 299 indent_string = ' ' * indent
300 300 try:
301 301 version, markers = obsolete._readmarkers(data)
302 302 except error.UnknownVersion as exc:
303 303 msg = "%sunsupported version: %s (%d bytes)\n"
304 304 msg %= indent_string, exc.version, len(data)
305 305 ui.write(msg)
306 306 else:
307 307 msg = "%sversion: %d (%d bytes)\n"
308 308 msg %= indent_string, version, len(data)
309 309 ui.write(msg)
310 310 fm = ui.formatter('debugobsolete', opts)
311 311 for rawmarker in sorted(markers):
312 312 m = obsutil.marker(None, rawmarker)
313 313 fm.startitem()
314 314 fm.plain(indent_string)
315 315 cmdutil.showmarker(fm, m)
316 316 fm.end()
317 317
318 318 def _debugphaseheads(ui, data, indent=0):
319 319 """display version and markers contained in 'data'"""
320 320 indent_string = ' ' * indent
321 321 headsbyphase = phases.binarydecode(data)
322 322 for phase in phases.allphases:
323 323 for head in headsbyphase[phase]:
324 324 ui.write(indent_string)
325 325 ui.write('%s %s\n' % (hex(head), phases.phasenames[phase]))
326 326
327 327 def _quasirepr(thing):
328 328 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
329 329 return '{%s}' % (
330 330 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing)))
331 331 return pycompat.bytestr(repr(thing))
332 332
333 333 def _debugbundle2(ui, gen, all=None, **opts):
334 334 """lists the contents of a bundle2"""
335 335 if not isinstance(gen, bundle2.unbundle20):
336 336 raise error.Abort(_('not a bundle2 file'))
337 337 ui.write(('Stream params: %s\n' % _quasirepr(gen.params)))
338 338 parttypes = opts.get(r'part_type', [])
339 339 for part in gen.iterparts():
340 340 if parttypes and part.type not in parttypes:
341 341 continue
342 342 ui.write('%s -- %s\n' % (part.type, _quasirepr(part.params)))
343 343 if part.type == 'changegroup':
344 344 version = part.params.get('version', '01')
345 345 cg = changegroup.getunbundler(version, part, 'UN')
346 346 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
347 347 if part.type == 'obsmarkers':
348 348 _debugobsmarkers(ui, part, indent=4, **opts)
349 349 if part.type == 'phase-heads':
350 350 _debugphaseheads(ui, part, indent=4)
351 351
352 352 @command('debugbundle',
353 353 [('a', 'all', None, _('show all details')),
354 354 ('', 'part-type', [], _('show only the named part type')),
355 355 ('', 'spec', None, _('print the bundlespec of the bundle'))],
356 356 _('FILE'),
357 357 norepo=True)
358 358 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
359 359 """lists the contents of a bundle"""
360 360 with hg.openpath(ui, bundlepath) as f:
361 361 if spec:
362 362 spec = exchange.getbundlespec(ui, f)
363 363 ui.write('%s\n' % spec)
364 364 return
365 365
366 366 gen = exchange.readbundle(ui, f, bundlepath)
367 367 if isinstance(gen, bundle2.unbundle20):
368 368 return _debugbundle2(ui, gen, all=all, **opts)
369 369 _debugchangegroup(ui, gen, all=all, **opts)
370 370
371 371 @command('debugcapabilities',
372 372 [], _('PATH'),
373 373 norepo=True)
374 374 def debugcapabilities(ui, path, **opts):
375 375 """lists the capabilities of a remote peer"""
376 376 opts = pycompat.byteskwargs(opts)
377 377 peer = hg.peer(ui, opts, path)
378 378 caps = peer.capabilities()
379 379 ui.write(('Main capabilities:\n'))
380 380 for c in sorted(caps):
381 381 ui.write((' %s\n') % c)
382 382 b2caps = bundle2.bundle2caps(peer)
383 383 if b2caps:
384 384 ui.write(('Bundle2 capabilities:\n'))
385 385 for key, values in sorted(b2caps.iteritems()):
386 386 ui.write((' %s\n') % key)
387 387 for v in values:
388 388 ui.write((' %s\n') % v)
389 389
390 390 @command('debugcheckstate', [], '')
391 391 def debugcheckstate(ui, repo):
392 392 """validate the correctness of the current dirstate"""
393 393 parent1, parent2 = repo.dirstate.parents()
394 394 m1 = repo[parent1].manifest()
395 395 m2 = repo[parent2].manifest()
396 396 errors = 0
397 397 for f in repo.dirstate:
398 398 state = repo.dirstate[f]
399 399 if state in "nr" and f not in m1:
400 400 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
401 401 errors += 1
402 402 if state in "a" and f in m1:
403 403 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
404 404 errors += 1
405 405 if state in "m" and f not in m1 and f not in m2:
406 406 ui.warn(_("%s in state %s, but not in either manifest\n") %
407 407 (f, state))
408 408 errors += 1
409 409 for f in m1:
410 410 state = repo.dirstate[f]
411 411 if state not in "nrm":
412 412 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
413 413 errors += 1
414 414 if errors:
415 415 error = _(".hg/dirstate inconsistent with current parent's manifest")
416 416 raise error.Abort(error)
417 417
418 418 @command('debugcolor',
419 419 [('', 'style', None, _('show all configured styles'))],
420 420 'hg debugcolor')
421 421 def debugcolor(ui, repo, **opts):
422 422 """show available color, effects or style"""
423 423 ui.write(('color mode: %s\n') % ui._colormode)
424 424 if opts.get(r'style'):
425 425 return _debugdisplaystyle(ui)
426 426 else:
427 427 return _debugdisplaycolor(ui)
428 428
429 429 def _debugdisplaycolor(ui):
430 430 ui = ui.copy()
431 431 ui._styles.clear()
432 432 for effect in color._activeeffects(ui).keys():
433 433 ui._styles[effect] = effect
434 434 if ui._terminfoparams:
435 435 for k, v in ui.configitems('color'):
436 436 if k.startswith('color.'):
437 437 ui._styles[k] = k[6:]
438 438 elif k.startswith('terminfo.'):
439 439 ui._styles[k] = k[9:]
440 440 ui.write(_('available colors:\n'))
441 441 # sort label with a '_' after the other to group '_background' entry.
442 442 items = sorted(ui._styles.items(),
443 443 key=lambda i: ('_' in i[0], i[0], i[1]))
444 444 for colorname, label in items:
445 445 ui.write(('%s\n') % colorname, label=label)
446 446
447 447 def _debugdisplaystyle(ui):
448 448 ui.write(_('available style:\n'))
449 449 width = max(len(s) for s in ui._styles)
450 450 for label, effects in sorted(ui._styles.items()):
451 451 ui.write('%s' % label, label=label)
452 452 if effects:
453 453 # 50
454 454 ui.write(': ')
455 455 ui.write(' ' * (max(0, width - len(label))))
456 456 ui.write(', '.join(ui.label(e, e) for e in effects.split()))
457 457 ui.write('\n')
458 458
459 459 @command('debugcreatestreamclonebundle', [], 'FILE')
460 460 def debugcreatestreamclonebundle(ui, repo, fname):
461 461 """create a stream clone bundle file
462 462
463 463 Stream bundles are special bundles that are essentially archives of
464 464 revlog files. They are commonly used for cloning very quickly.
465 465 """
466 466 # TODO we may want to turn this into an abort when this functionality
467 467 # is moved into `hg bundle`.
468 468 if phases.hassecret(repo):
469 469 ui.warn(_('(warning: stream clone bundle will contain secret '
470 470 'revisions)\n'))
471 471
472 472 requirements, gen = streamclone.generatebundlev1(repo)
473 473 changegroup.writechunks(ui, gen, fname)
474 474
475 475 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
476 476
477 477 @command('debugdag',
478 478 [('t', 'tags', None, _('use tags as labels')),
479 479 ('b', 'branches', None, _('annotate with branch names')),
480 480 ('', 'dots', None, _('use dots for runs')),
481 481 ('s', 'spaces', None, _('separate elements by spaces'))],
482 482 _('[OPTION]... [FILE [REV]...]'),
483 483 optionalrepo=True)
484 484 def debugdag(ui, repo, file_=None, *revs, **opts):
485 485 """format the changelog or an index DAG as a concise textual description
486 486
487 487 If you pass a revlog index, the revlog's DAG is emitted. If you list
488 488 revision numbers, they get labeled in the output as rN.
489 489
490 490 Otherwise, the changelog DAG of the current repo is emitted.
491 491 """
492 492 spaces = opts.get(r'spaces')
493 493 dots = opts.get(r'dots')
494 494 if file_:
495 495 rlog = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False),
496 496 file_)
497 497 revs = set((int(r) for r in revs))
498 498 def events():
499 499 for r in rlog:
500 500 yield 'n', (r, list(p for p in rlog.parentrevs(r)
501 501 if p != -1))
502 502 if r in revs:
503 503 yield 'l', (r, "r%i" % r)
504 504 elif repo:
505 505 cl = repo.changelog
506 506 tags = opts.get(r'tags')
507 507 branches = opts.get(r'branches')
508 508 if tags:
509 509 labels = {}
510 510 for l, n in repo.tags().items():
511 511 labels.setdefault(cl.rev(n), []).append(l)
512 512 def events():
513 513 b = "default"
514 514 for r in cl:
515 515 if branches:
516 516 newb = cl.read(cl.node(r))[5]['branch']
517 517 if newb != b:
518 518 yield 'a', newb
519 519 b = newb
520 520 yield 'n', (r, list(p for p in cl.parentrevs(r)
521 521 if p != -1))
522 522 if tags:
523 523 ls = labels.get(r)
524 524 if ls:
525 525 for l in ls:
526 526 yield 'l', (r, l)
527 527 else:
528 528 raise error.Abort(_('need repo for changelog dag'))
529 529
530 530 for line in dagparser.dagtextlines(events(),
531 531 addspaces=spaces,
532 532 wraplabels=True,
533 533 wrapannotations=True,
534 534 wrapnonlinear=dots,
535 535 usedots=dots,
536 536 maxlinewidth=70):
537 537 ui.write(line)
538 538 ui.write("\n")
539 539
540 540 @command('debugdata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
541 541 def debugdata(ui, repo, file_, rev=None, **opts):
542 542 """dump the contents of a data file revision"""
543 543 opts = pycompat.byteskwargs(opts)
544 544 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
545 545 if rev is not None:
546 546 raise error.CommandError('debugdata', _('invalid arguments'))
547 547 file_, rev = None, file_
548 548 elif rev is None:
549 549 raise error.CommandError('debugdata', _('invalid arguments'))
550 550 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
551 551 try:
552 552 ui.write(r.revision(r.lookup(rev), raw=True))
553 553 except KeyError:
554 554 raise error.Abort(_('invalid revision identifier %s') % rev)
555 555
556 556 @command('debugdate',
557 557 [('e', 'extended', None, _('try extended date formats'))],
558 558 _('[-e] DATE [RANGE]'),
559 559 norepo=True, optionalrepo=True)
560 560 def debugdate(ui, date, range=None, **opts):
561 561 """parse and display a date"""
562 562 if opts[r"extended"]:
563 563 d = util.parsedate(date, util.extendeddateformats)
564 564 else:
565 565 d = util.parsedate(date)
566 566 ui.write(("internal: %d %d\n") % d)
567 567 ui.write(("standard: %s\n") % util.datestr(d))
568 568 if range:
569 569 m = util.matchdate(range)
570 570 ui.write(("match: %s\n") % m(d[0]))
571 571
572 572 @command('debugdeltachain',
573 573 cmdutil.debugrevlogopts + cmdutil.formatteropts,
574 574 _('-c|-m|FILE'),
575 575 optionalrepo=True)
576 576 def debugdeltachain(ui, repo, file_=None, **opts):
577 577 """dump information about delta chains in a revlog
578 578
579 579 Output can be templatized. Available template keywords are:
580 580
581 581 :``rev``: revision number
582 582 :``chainid``: delta chain identifier (numbered by unique base)
583 583 :``chainlen``: delta chain length to this revision
584 584 :``prevrev``: previous revision in delta chain
585 585 :``deltatype``: role of delta / how it was computed
586 586 :``compsize``: compressed size of revision
587 587 :``uncompsize``: uncompressed size of revision
588 588 :``chainsize``: total size of compressed revisions in chain
589 589 :``chainratio``: total chain size divided by uncompressed revision size
590 590 (new delta chains typically start at ratio 2.00)
591 591 :``lindist``: linear distance from base revision in delta chain to end
592 592 of this revision
593 593 :``extradist``: total size of revisions not part of this delta chain from
594 594 base of delta chain to end of this revision; a measurement
595 595 of how much extra data we need to read/seek across to read
596 596 the delta chain for this revision
597 597 :``extraratio``: extradist divided by chainsize; another representation of
598 598 how much unrelated data is needed to load this delta chain
599 599
600 600 If the repository is configured to use the sparse read, additional keywords
601 601 are available:
602 602
603 603 :``readsize``: total size of data read from the disk for a revision
604 604 (sum of the sizes of all the blocks)
605 605 :``largestblock``: size of the largest block of data read from the disk
606 606 :``readdensity``: density of useful bytes in the data read from the disk
607 607 :``srchunks``: in how many data hunks the whole revision would be read
608 608
609 609 The sparse read can be enabled with experimental.sparse-read = True
610 610 """
611 611 opts = pycompat.byteskwargs(opts)
612 612 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
613 613 index = r.index
614 614 generaldelta = r.version & revlog.FLAG_GENERALDELTA
615 615 withsparseread = getattr(r, '_withsparseread', False)
616 616
617 617 def revinfo(rev):
618 618 e = index[rev]
619 619 compsize = e[1]
620 620 uncompsize = e[2]
621 621 chainsize = 0
622 622
623 623 if generaldelta:
624 624 if e[3] == e[5]:
625 625 deltatype = 'p1'
626 626 elif e[3] == e[6]:
627 627 deltatype = 'p2'
628 628 elif e[3] == rev - 1:
629 629 deltatype = 'prev'
630 630 elif e[3] == rev:
631 631 deltatype = 'base'
632 632 else:
633 633 deltatype = 'other'
634 634 else:
635 635 if e[3] == rev:
636 636 deltatype = 'base'
637 637 else:
638 638 deltatype = 'prev'
639 639
640 640 chain = r._deltachain(rev)[0]
641 641 for iterrev in chain:
642 642 e = index[iterrev]
643 643 chainsize += e[1]
644 644
645 645 return compsize, uncompsize, deltatype, chain, chainsize
646 646
647 647 fm = ui.formatter('debugdeltachain', opts)
648 648
649 649 fm.plain(' rev chain# chainlen prev delta '
650 650 'size rawsize chainsize ratio lindist extradist '
651 651 'extraratio')
652 652 if withsparseread:
653 653 fm.plain(' readsize largestblk rddensity srchunks')
654 654 fm.plain('\n')
655 655
656 656 chainbases = {}
657 657 for rev in r:
658 658 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
659 659 chainbase = chain[0]
660 660 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
661 661 start = r.start
662 662 length = r.length
663 663 basestart = start(chainbase)
664 664 revstart = start(rev)
665 665 lineardist = revstart + comp - basestart
666 666 extradist = lineardist - chainsize
667 667 try:
668 668 prevrev = chain[-2]
669 669 except IndexError:
670 670 prevrev = -1
671 671
672 672 chainratio = float(chainsize) / float(uncomp)
673 673 extraratio = float(extradist) / float(chainsize)
674 674
675 675 fm.startitem()
676 676 fm.write('rev chainid chainlen prevrev deltatype compsize '
677 677 'uncompsize chainsize chainratio lindist extradist '
678 678 'extraratio',
679 679 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
680 680 rev, chainid, len(chain), prevrev, deltatype, comp,
681 681 uncomp, chainsize, chainratio, lineardist, extradist,
682 682 extraratio,
683 683 rev=rev, chainid=chainid, chainlen=len(chain),
684 684 prevrev=prevrev, deltatype=deltatype, compsize=comp,
685 685 uncompsize=uncomp, chainsize=chainsize,
686 686 chainratio=chainratio, lindist=lineardist,
687 687 extradist=extradist, extraratio=extraratio)
688 688 if withsparseread:
689 689 readsize = 0
690 690 largestblock = 0
691 691 srchunks = 0
692 692
693 693 for revschunk in revlog._slicechunk(r, chain):
694 694 srchunks += 1
695 695 blkend = start(revschunk[-1]) + length(revschunk[-1])
696 696 blksize = blkend - start(revschunk[0])
697 697
698 698 readsize += blksize
699 699 if largestblock < blksize:
700 700 largestblock = blksize
701 701
702 702 readdensity = float(chainsize) / float(readsize)
703 703
704 704 fm.write('readsize largestblock readdensity srchunks',
705 705 ' %10d %10d %9.5f %8d',
706 706 readsize, largestblock, readdensity, srchunks,
707 707 readsize=readsize, largestblock=largestblock,
708 708 readdensity=readdensity, srchunks=srchunks)
709 709
710 710 fm.plain('\n')
711 711
712 712 fm.end()
713 713
714 714 @command('debugdirstate|debugstate',
715 715 [('', 'nodates', None, _('do not display the saved mtime')),
716 716 ('', 'datesort', None, _('sort by saved mtime'))],
717 717 _('[OPTION]...'))
718 718 def debugstate(ui, repo, **opts):
719 719 """show the contents of the current dirstate"""
720 720
721 721 nodates = opts.get(r'nodates')
722 722 datesort = opts.get(r'datesort')
723 723
724 724 timestr = ""
725 725 if datesort:
726 726 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
727 727 else:
728 728 keyfunc = None # sort by filename
729 729 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
730 730 if ent[3] == -1:
731 731 timestr = 'unset '
732 732 elif nodates:
733 733 timestr = 'set '
734 734 else:
735 735 timestr = time.strftime(r"%Y-%m-%d %H:%M:%S ",
736 736 time.localtime(ent[3]))
737 737 timestr = encoding.strtolocal(timestr)
738 738 if ent[1] & 0o20000:
739 739 mode = 'lnk'
740 740 else:
741 741 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
742 742 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
743 743 for f in repo.dirstate.copies():
744 744 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
745 745
746 746 @command('debugdiscovery',
747 747 [('', 'old', None, _('use old-style discovery')),
748 748 ('', 'nonheads', None,
749 749 _('use old-style discovery with non-heads included')),
750 750 ('', 'rev', [], 'restrict discovery to this set of revs'),
751 751 ] + cmdutil.remoteopts,
752 752 _('[--rev REV] [OTHER]'))
753 753 def debugdiscovery(ui, repo, remoteurl="default", **opts):
754 754 """runs the changeset discovery protocol in isolation"""
755 755 opts = pycompat.byteskwargs(opts)
756 756 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
757 757 remote = hg.peer(repo, opts, remoteurl)
758 758 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
759 759
760 760 # make sure tests are repeatable
761 761 random.seed(12323)
762 762
763 763 def doit(pushedrevs, remoteheads, remote=remote):
764 764 if opts.get('old'):
765 765 if not util.safehasattr(remote, 'branches'):
766 766 # enable in-client legacy support
767 767 remote = localrepo.locallegacypeer(remote.local())
768 768 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
769 769 force=True)
770 770 common = set(common)
771 771 if not opts.get('nonheads'):
772 772 ui.write(("unpruned common: %s\n") %
773 773 " ".join(sorted(short(n) for n in common)))
774 774 dag = dagutil.revlogdag(repo.changelog)
775 775 all = dag.ancestorset(dag.internalizeall(common))
776 776 common = dag.externalizeall(dag.headsetofconnecteds(all))
777 777 else:
778 778 nodes = None
779 779 if pushedrevs:
780 780 revs = scmutil.revrange(repo, pushedrevs)
781 781 nodes = [repo[r].node() for r in revs]
782 782 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote,
783 783 ancestorsof=nodes)
784 784 common = set(common)
785 785 rheads = set(hds)
786 786 lheads = set(repo.heads())
787 787 ui.write(("common heads: %s\n") %
788 788 " ".join(sorted(short(n) for n in common)))
789 789 if lheads <= common:
790 790 ui.write(("local is subset\n"))
791 791 elif rheads <= common:
792 792 ui.write(("remote is subset\n"))
793 793
794 794 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
795 795 localrevs = opts['rev']
796 796 doit(localrevs, remoterevs)
797 797
798 798 _chunksize = 4 << 10
799 799
800 800 @command('debugdownload',
801 801 [
802 802 ('o', 'output', '', _('path')),
803 803 ],
804 804 optionalrepo=True)
805 805 def debugdownload(ui, repo, url, output=None, **opts):
806 806 """download a resource using Mercurial logic and config
807 807 """
808 808 fh = urlmod.open(ui, url, output)
809 809
810 810 dest = ui
811 811 if output:
812 812 dest = open(output, "wb", _chunksize)
813 813 try:
814 814 data = fh.read(_chunksize)
815 815 while data:
816 816 dest.write(data)
817 817 data = fh.read(_chunksize)
818 818 finally:
819 819 if output:
820 820 dest.close()
821 821
822 822 @command('debugextensions', cmdutil.formatteropts, [], norepo=True)
823 823 def debugextensions(ui, **opts):
824 824 '''show information about active extensions'''
825 825 opts = pycompat.byteskwargs(opts)
826 826 exts = extensions.extensions(ui)
827 827 hgver = util.version()
828 828 fm = ui.formatter('debugextensions', opts)
829 829 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
830 830 isinternal = extensions.ismoduleinternal(extmod)
831 831 extsource = pycompat.fsencode(extmod.__file__)
832 832 if isinternal:
833 833 exttestedwith = [] # never expose magic string to users
834 834 else:
835 835 exttestedwith = getattr(extmod, 'testedwith', '').split()
836 836 extbuglink = getattr(extmod, 'buglink', None)
837 837
838 838 fm.startitem()
839 839
840 840 if ui.quiet or ui.verbose:
841 841 fm.write('name', '%s\n', extname)
842 842 else:
843 843 fm.write('name', '%s', extname)
844 844 if isinternal or hgver in exttestedwith:
845 845 fm.plain('\n')
846 846 elif not exttestedwith:
847 847 fm.plain(_(' (untested!)\n'))
848 848 else:
849 849 lasttestedversion = exttestedwith[-1]
850 850 fm.plain(' (%s!)\n' % lasttestedversion)
851 851
852 852 fm.condwrite(ui.verbose and extsource, 'source',
853 853 _(' location: %s\n'), extsource or "")
854 854
855 855 if ui.verbose:
856 856 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
857 857 fm.data(bundled=isinternal)
858 858
859 859 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
860 860 _(' tested with: %s\n'),
861 861 fm.formatlist(exttestedwith, name='ver'))
862 862
863 863 fm.condwrite(ui.verbose and extbuglink, 'buglink',
864 864 _(' bug reporting: %s\n'), extbuglink or "")
865 865
866 866 fm.end()
867 867
868 868 @command('debugfileset',
869 869 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
870 870 _('[-r REV] FILESPEC'))
871 871 def debugfileset(ui, repo, expr, **opts):
872 872 '''parse and apply a fileset specification'''
873 873 ctx = scmutil.revsingle(repo, opts.get(r'rev'), None)
874 874 if ui.verbose:
875 875 tree = fileset.parse(expr)
876 876 ui.note(fileset.prettyformat(tree), "\n")
877 877
878 878 for f in ctx.getfileset(expr):
879 879 ui.write("%s\n" % f)
880 880
881 881 @command('debugformat',
882 882 [] + cmdutil.formatteropts,
883 883 _(''))
884 884 def debugformat(ui, repo, **opts):
885 885 """display format information about the current repository
886 886
887 887 Use --verbose to get extra information about current config value and
888 888 Mercurial default."""
889 889 opts = pycompat.byteskwargs(opts)
890 890 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
891 891 maxvariantlength = max(len('format-variant'), maxvariantlength)
892 892
893 893 def makeformatname(name):
894 894 return '%s:' + (' ' * (maxvariantlength - len(name)))
895 895
896 896 fm = ui.formatter('debugformat', opts)
897 897 if fm.isplain():
898 898 def formatvalue(value):
899 899 if util.safehasattr(value, 'startswith'):
900 900 return value
901 901 if value:
902 902 return 'yes'
903 903 else:
904 904 return 'no'
905 905 else:
906 906 formatvalue = pycompat.identity
907 907
908 908 fm.plain('format-variant')
909 909 fm.plain(' ' * (maxvariantlength - len('format-variant')))
910 910 fm.plain(' repo')
911 911 if ui.verbose:
912 912 fm.plain(' config default')
913 913 fm.plain('\n')
914 914 for fv in upgrade.allformatvariant:
915 915 fm.startitem()
916 916 repovalue = fv.fromrepo(repo)
917 917 configvalue = fv.fromconfig(repo)
918 918
919 919 if repovalue != configvalue:
920 920 namelabel = 'formatvariant.name.mismatchconfig'
921 921 repolabel = 'formatvariant.repo.mismatchconfig'
922 922 elif repovalue != fv.default:
923 923 namelabel = 'formatvariant.name.mismatchdefault'
924 924 repolabel = 'formatvariant.repo.mismatchdefault'
925 925 else:
926 926 namelabel = 'formatvariant.name.uptodate'
927 927 repolabel = 'formatvariant.repo.uptodate'
928 928
929 929 fm.write('name', makeformatname(fv.name), fv.name,
930 930 label=namelabel)
931 931 fm.write('repo', ' %3s', formatvalue(repovalue),
932 932 label=repolabel)
933 933 if fv.default != configvalue:
934 934 configlabel = 'formatvariant.config.special'
935 935 else:
936 936 configlabel = 'formatvariant.config.default'
937 937 fm.condwrite(ui.verbose, 'config', ' %6s', formatvalue(configvalue),
938 938 label=configlabel)
939 939 fm.condwrite(ui.verbose, 'default', ' %7s', formatvalue(fv.default),
940 940 label='formatvariant.default')
941 941 fm.plain('\n')
942 942 fm.end()
943 943
944 944 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
945 945 def debugfsinfo(ui, path="."):
946 946 """show information detected about current filesystem"""
947 947 ui.write(('path: %s\n') % path)
948 948 ui.write(('mounted on: %s\n') % (util.getfsmountpoint(path) or '(unknown)'))
949 949 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
950 950 ui.write(('fstype: %s\n') % (util.getfstype(path) or '(unknown)'))
951 951 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
952 952 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
953 953 casesensitive = '(unknown)'
954 954 try:
955 955 with tempfile.NamedTemporaryFile(prefix='.debugfsinfo', dir=path) as f:
956 956 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
957 957 except OSError:
958 958 pass
959 959 ui.write(('case-sensitive: %s\n') % casesensitive)
960 960
961 961 @command('debuggetbundle',
962 962 [('H', 'head', [], _('id of head node'), _('ID')),
963 963 ('C', 'common', [], _('id of common node'), _('ID')),
964 964 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
965 965 _('REPO FILE [-H|-C ID]...'),
966 966 norepo=True)
967 967 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
968 968 """retrieves a bundle from a repo
969 969
970 970 Every ID must be a full-length hex node id string. Saves the bundle to the
971 971 given file.
972 972 """
973 973 opts = pycompat.byteskwargs(opts)
974 974 repo = hg.peer(ui, opts, repopath)
975 975 if not repo.capable('getbundle'):
976 976 raise error.Abort("getbundle() not supported by target repository")
977 977 args = {}
978 978 if common:
979 979 args[r'common'] = [bin(s) for s in common]
980 980 if head:
981 981 args[r'heads'] = [bin(s) for s in head]
982 982 # TODO: get desired bundlecaps from command line.
983 983 args[r'bundlecaps'] = None
984 984 bundle = repo.getbundle('debug', **args)
985 985
986 986 bundletype = opts.get('type', 'bzip2').lower()
987 987 btypes = {'none': 'HG10UN',
988 988 'bzip2': 'HG10BZ',
989 989 'gzip': 'HG10GZ',
990 990 'bundle2': 'HG20'}
991 991 bundletype = btypes.get(bundletype)
992 992 if bundletype not in bundle2.bundletypes:
993 993 raise error.Abort(_('unknown bundle type specified with --type'))
994 994 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
995 995
996 996 @command('debugignore', [], '[FILE]')
997 997 def debugignore(ui, repo, *files, **opts):
998 998 """display the combined ignore pattern and information about ignored files
999 999
1000 1000 With no argument display the combined ignore pattern.
1001 1001
1002 1002 Given space separated file names, shows if the given file is ignored and
1003 1003 if so, show the ignore rule (file and line number) that matched it.
1004 1004 """
1005 1005 ignore = repo.dirstate._ignore
1006 1006 if not files:
1007 1007 # Show all the patterns
1008 1008 ui.write("%s\n" % repr(ignore))
1009 1009 else:
1010 1010 m = scmutil.match(repo[None], pats=files)
1011 1011 for f in m.files():
1012 1012 nf = util.normpath(f)
1013 1013 ignored = None
1014 1014 ignoredata = None
1015 1015 if nf != '.':
1016 1016 if ignore(nf):
1017 1017 ignored = nf
1018 1018 ignoredata = repo.dirstate._ignorefileandline(nf)
1019 1019 else:
1020 1020 for p in util.finddirs(nf):
1021 1021 if ignore(p):
1022 1022 ignored = p
1023 1023 ignoredata = repo.dirstate._ignorefileandline(p)
1024 1024 break
1025 1025 if ignored:
1026 1026 if ignored == nf:
1027 1027 ui.write(_("%s is ignored\n") % m.uipath(f))
1028 1028 else:
1029 1029 ui.write(_("%s is ignored because of "
1030 1030 "containing folder %s\n")
1031 1031 % (m.uipath(f), ignored))
1032 1032 ignorefile, lineno, line = ignoredata
1033 1033 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
1034 1034 % (ignorefile, lineno, line))
1035 1035 else:
1036 1036 ui.write(_("%s is not ignored\n") % m.uipath(f))
1037 1037
1038 1038 @command('debugindex', cmdutil.debugrevlogopts +
1039 1039 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1040 1040 _('[-f FORMAT] -c|-m|FILE'),
1041 1041 optionalrepo=True)
1042 1042 def debugindex(ui, repo, file_=None, **opts):
1043 1043 """dump the contents of an index file"""
1044 1044 opts = pycompat.byteskwargs(opts)
1045 1045 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1046 1046 format = opts.get('format', 0)
1047 1047 if format not in (0, 1):
1048 1048 raise error.Abort(_("unknown format %d") % format)
1049 1049
1050 1050 generaldelta = r.version & revlog.FLAG_GENERALDELTA
1051 1051 if generaldelta:
1052 1052 basehdr = ' delta'
1053 1053 else:
1054 1054 basehdr = ' base'
1055 1055
1056 1056 if ui.debugflag:
1057 1057 shortfn = hex
1058 1058 else:
1059 1059 shortfn = short
1060 1060
1061 1061 # There might not be anything in r, so have a sane default
1062 1062 idlen = 12
1063 1063 for i in r:
1064 1064 idlen = len(shortfn(r.node(i)))
1065 1065 break
1066 1066
1067 1067 if format == 0:
1068 1068 ui.write((" rev offset length " + basehdr + " linkrev"
1069 1069 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
1070 1070 elif format == 1:
1071 1071 ui.write((" rev flag offset length"
1072 1072 " size " + basehdr + " link p1 p2"
1073 1073 " %s\n") % "nodeid".rjust(idlen))
1074 1074
1075 1075 for i in r:
1076 1076 node = r.node(i)
1077 1077 if generaldelta:
1078 1078 base = r.deltaparent(i)
1079 1079 else:
1080 1080 base = r.chainbase(i)
1081 1081 if format == 0:
1082 1082 try:
1083 1083 pp = r.parents(node)
1084 1084 except Exception:
1085 1085 pp = [nullid, nullid]
1086 1086 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1087 1087 i, r.start(i), r.length(i), base, r.linkrev(i),
1088 1088 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
1089 1089 elif format == 1:
1090 1090 pr = r.parentrevs(i)
1091 1091 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1092 1092 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1093 1093 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
1094 1094
1095 1095 @command('debugindexdot', cmdutil.debugrevlogopts,
1096 1096 _('-c|-m|FILE'), optionalrepo=True)
1097 1097 def debugindexdot(ui, repo, file_=None, **opts):
1098 1098 """dump an index DAG as a graphviz dot file"""
1099 1099 opts = pycompat.byteskwargs(opts)
1100 1100 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
1101 1101 ui.write(("digraph G {\n"))
1102 1102 for i in r:
1103 1103 node = r.node(i)
1104 1104 pp = r.parents(node)
1105 1105 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1106 1106 if pp[1] != nullid:
1107 1107 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1108 1108 ui.write("}\n")
1109 1109
1110 1110 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
1111 1111 def debuginstall(ui, **opts):
1112 1112 '''test Mercurial installation
1113 1113
1114 1114 Returns 0 on success.
1115 1115 '''
1116 1116 opts = pycompat.byteskwargs(opts)
1117 1117
1118 1118 def writetemp(contents):
1119 1119 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1120 1120 f = os.fdopen(fd, pycompat.sysstr("wb"))
1121 1121 f.write(contents)
1122 1122 f.close()
1123 1123 return name
1124 1124
1125 1125 problems = 0
1126 1126
1127 1127 fm = ui.formatter('debuginstall', opts)
1128 1128 fm.startitem()
1129 1129
1130 1130 # encoding
1131 1131 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
1132 1132 err = None
1133 1133 try:
1134 1134 codecs.lookup(pycompat.sysstr(encoding.encoding))
1135 1135 except LookupError as inst:
1136 1136 err = util.forcebytestr(inst)
1137 1137 problems += 1
1138 1138 fm.condwrite(err, 'encodingerror', _(" %s\n"
1139 1139 " (check that your locale is properly set)\n"), err)
1140 1140
1141 1141 # Python
1142 1142 fm.write('pythonexe', _("checking Python executable (%s)\n"),
1143 1143 pycompat.sysexecutable)
1144 1144 fm.write('pythonver', _("checking Python version (%s)\n"),
1145 1145 ("%d.%d.%d" % sys.version_info[:3]))
1146 1146 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
1147 1147 os.path.dirname(pycompat.fsencode(os.__file__)))
1148 1148
1149 1149 security = set(sslutil.supportedprotocols)
1150 1150 if sslutil.hassni:
1151 1151 security.add('sni')
1152 1152
1153 1153 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
1154 1154 fm.formatlist(sorted(security), name='protocol',
1155 1155 fmt='%s', sep=','))
1156 1156
1157 1157 # These are warnings, not errors. So don't increment problem count. This
1158 1158 # may change in the future.
1159 1159 if 'tls1.2' not in security:
1160 1160 fm.plain(_(' TLS 1.2 not supported by Python install; '
1161 1161 'network connections lack modern security\n'))
1162 1162 if 'sni' not in security:
1163 1163 fm.plain(_(' SNI not supported by Python install; may have '
1164 1164 'connectivity issues with some servers\n'))
1165 1165
1166 1166 # TODO print CA cert info
1167 1167
1168 1168 # hg version
1169 1169 hgver = util.version()
1170 1170 fm.write('hgver', _("checking Mercurial version (%s)\n"),
1171 1171 hgver.split('+')[0])
1172 1172 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
1173 1173 '+'.join(hgver.split('+')[1:]))
1174 1174
1175 1175 # compiled modules
1176 1176 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
1177 1177 policy.policy)
1178 1178 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
1179 1179 os.path.dirname(pycompat.fsencode(__file__)))
1180 1180
1181 1181 if policy.policy in ('c', 'allow'):
1182 1182 err = None
1183 1183 try:
1184 1184 from .cext import (
1185 1185 base85,
1186 1186 bdiff,
1187 1187 mpatch,
1188 1188 osutil,
1189 1189 )
1190 1190 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1191 1191 except Exception as inst:
1192 1192 err = util.forcebytestr(inst)
1193 1193 problems += 1
1194 1194 fm.condwrite(err, 'extensionserror', " %s\n", err)
1195 1195
1196 1196 compengines = util.compengines._engines.values()
1197 1197 fm.write('compengines', _('checking registered compression engines (%s)\n'),
1198 1198 fm.formatlist(sorted(e.name() for e in compengines),
1199 1199 name='compengine', fmt='%s', sep=', '))
1200 1200 fm.write('compenginesavail', _('checking available compression engines '
1201 1201 '(%s)\n'),
1202 1202 fm.formatlist(sorted(e.name() for e in compengines
1203 1203 if e.available()),
1204 1204 name='compengine', fmt='%s', sep=', '))
1205 1205 wirecompengines = util.compengines.supportedwireengines(util.SERVERROLE)
1206 1206 fm.write('compenginesserver', _('checking available compression engines '
1207 1207 'for wire protocol (%s)\n'),
1208 1208 fm.formatlist([e.name() for e in wirecompengines
1209 1209 if e.wireprotosupport()],
1210 1210 name='compengine', fmt='%s', sep=', '))
1211 1211 re2 = 'missing'
1212 1212 if util._re2:
1213 1213 re2 = 'available'
1214 1214 fm.plain(_('checking "re2" regexp engine (%s)\n') % re2)
1215 1215 fm.data(re2=bool(util._re2))
1216 1216
1217 1217 # templates
1218 1218 p = templater.templatepaths()
1219 1219 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
1220 1220 fm.condwrite(not p, '', _(" no template directories found\n"))
1221 1221 if p:
1222 1222 m = templater.templatepath("map-cmdline.default")
1223 1223 if m:
1224 1224 # template found, check if it is working
1225 1225 err = None
1226 1226 try:
1227 1227 templater.templater.frommapfile(m)
1228 1228 except Exception as inst:
1229 1229 err = util.forcebytestr(inst)
1230 1230 p = None
1231 1231 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
1232 1232 else:
1233 1233 p = None
1234 1234 fm.condwrite(p, 'defaulttemplate',
1235 1235 _("checking default template (%s)\n"), m)
1236 1236 fm.condwrite(not m, 'defaulttemplatenotfound',
1237 1237 _(" template '%s' not found\n"), "default")
1238 1238 if not p:
1239 1239 problems += 1
1240 1240 fm.condwrite(not p, '',
1241 1241 _(" (templates seem to have been installed incorrectly)\n"))
1242 1242
1243 1243 # editor
1244 1244 editor = ui.geteditor()
1245 1245 editor = util.expandpath(editor)
1246 1246 editorbin = util.shellsplit(editor)[0]
1247 1247 fm.write('editor', _("checking commit editor... (%s)\n"), editorbin)
1248 1248 cmdpath = util.findexe(editorbin)
1249 1249 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
1250 1250 _(" No commit editor set and can't find %s in PATH\n"
1251 1251 " (specify a commit editor in your configuration"
1252 1252 " file)\n"), not cmdpath and editor == 'vi' and editorbin)
1253 1253 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
1254 1254 _(" Can't find editor '%s' in PATH\n"
1255 1255 " (specify a commit editor in your configuration"
1256 1256 " file)\n"), not cmdpath and editorbin)
1257 1257 if not cmdpath and editor != 'vi':
1258 1258 problems += 1
1259 1259
1260 1260 # check username
1261 1261 username = None
1262 1262 err = None
1263 1263 try:
1264 1264 username = ui.username()
1265 1265 except error.Abort as e:
1266 1266 err = util.forcebytestr(e)
1267 1267 problems += 1
1268 1268
1269 1269 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
1270 1270 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
1271 1271 " (specify a username in your configuration file)\n"), err)
1272 1272
1273 1273 fm.condwrite(not problems, '',
1274 1274 _("no problems detected\n"))
1275 1275 if not problems:
1276 1276 fm.data(problems=problems)
1277 1277 fm.condwrite(problems, 'problems',
1278 1278 _("%d problems detected,"
1279 1279 " please check your install!\n"), problems)
1280 1280 fm.end()
1281 1281
1282 1282 return problems
1283 1283
1284 1284 @command('debugknown', [], _('REPO ID...'), norepo=True)
1285 1285 def debugknown(ui, repopath, *ids, **opts):
1286 1286 """test whether node ids are known to a repo
1287 1287
1288 1288 Every ID must be a full-length hex node id string. Returns a list of 0s
1289 1289 and 1s indicating unknown/known.
1290 1290 """
1291 1291 opts = pycompat.byteskwargs(opts)
1292 1292 repo = hg.peer(ui, opts, repopath)
1293 1293 if not repo.capable('known'):
1294 1294 raise error.Abort("known() not supported by target repository")
1295 1295 flags = repo.known([bin(s) for s in ids])
1296 1296 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1297 1297
1298 1298 @command('debuglabelcomplete', [], _('LABEL...'))
1299 1299 def debuglabelcomplete(ui, repo, *args):
1300 1300 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1301 1301 debugnamecomplete(ui, repo, *args)
1302 1302
1303 1303 @command('debuglocks',
1304 1304 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
1305 1305 ('W', 'force-wlock', None,
1306 1306 _('free the working state lock (DANGEROUS)')),
1307 1307 ('s', 'set-lock', None, _('set the store lock until stopped')),
1308 1308 ('S', 'set-wlock', None,
1309 1309 _('set the working state lock until stopped'))],
1310 1310 _('[OPTION]...'))
1311 1311 def debuglocks(ui, repo, **opts):
1312 1312 """show or modify state of locks
1313 1313
1314 1314 By default, this command will show which locks are held. This
1315 1315 includes the user and process holding the lock, the amount of time
1316 1316 the lock has been held, and the machine name where the process is
1317 1317 running if it's not local.
1318 1318
1319 1319 Locks protect the integrity of Mercurial's data, so should be
1320 1320 treated with care. System crashes or other interruptions may cause
1321 1321 locks to not be properly released, though Mercurial will usually
1322 1322 detect and remove such stale locks automatically.
1323 1323
1324 1324 However, detecting stale locks may not always be possible (for
1325 1325 instance, on a shared filesystem). Removing locks may also be
1326 1326 blocked by filesystem permissions.
1327 1327
1328 1328 Setting a lock will prevent other commands from changing the data.
1329 1329 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
1330 1330 The set locks are removed when the command exits.
1331 1331
1332 1332 Returns 0 if no locks are held.
1333 1333
1334 1334 """
1335 1335
1336 1336 if opts.get(r'force_lock'):
1337 1337 repo.svfs.unlink('lock')
1338 1338 if opts.get(r'force_wlock'):
1339 1339 repo.vfs.unlink('wlock')
1340 1340 if opts.get(r'force_lock') or opts.get(r'force_wlock'):
1341 1341 return 0
1342 1342
1343 1343 locks = []
1344 1344 try:
1345 1345 if opts.get(r'set_wlock'):
1346 1346 try:
1347 1347 locks.append(repo.wlock(False))
1348 1348 except error.LockHeld:
1349 1349 raise error.Abort(_('wlock is already held'))
1350 1350 if opts.get(r'set_lock'):
1351 1351 try:
1352 1352 locks.append(repo.lock(False))
1353 1353 except error.LockHeld:
1354 1354 raise error.Abort(_('lock is already held'))
1355 1355 if len(locks):
1356 1356 ui.promptchoice(_("ready to release the lock (y)? $$ &Yes"))
1357 1357 return 0
1358 1358 finally:
1359 1359 release(*locks)
1360 1360
1361 1361 now = time.time()
1362 1362 held = 0
1363 1363
1364 1364 def report(vfs, name, method):
1365 1365 # this causes stale locks to get reaped for more accurate reporting
1366 1366 try:
1367 1367 l = method(False)
1368 1368 except error.LockHeld:
1369 1369 l = None
1370 1370
1371 1371 if l:
1372 1372 l.release()
1373 1373 else:
1374 1374 try:
1375 1375 stat = vfs.lstat(name)
1376 1376 age = now - stat.st_mtime
1377 1377 user = util.username(stat.st_uid)
1378 1378 locker = vfs.readlock(name)
1379 1379 if ":" in locker:
1380 1380 host, pid = locker.split(':')
1381 1381 if host == socket.gethostname():
1382 1382 locker = 'user %s, process %s' % (user, pid)
1383 1383 else:
1384 1384 locker = 'user %s, process %s, host %s' \
1385 1385 % (user, pid, host)
1386 1386 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
1387 1387 return 1
1388 1388 except OSError as e:
1389 1389 if e.errno != errno.ENOENT:
1390 1390 raise
1391 1391
1392 1392 ui.write(("%-6s free\n") % (name + ":"))
1393 1393 return 0
1394 1394
1395 1395 held += report(repo.svfs, "lock", repo.lock)
1396 1396 held += report(repo.vfs, "wlock", repo.wlock)
1397 1397
1398 1398 return held
1399 1399
1400 1400 @command('debugmergestate', [], '')
1401 1401 def debugmergestate(ui, repo, *args):
1402 1402 """print merge state
1403 1403
1404 1404 Use --verbose to print out information about whether v1 or v2 merge state
1405 1405 was chosen."""
1406 1406 def _hashornull(h):
1407 1407 if h == nullhex:
1408 1408 return 'null'
1409 1409 else:
1410 1410 return h
1411 1411
1412 1412 def printrecords(version):
1413 1413 ui.write(('* version %d records\n') % version)
1414 1414 if version == 1:
1415 1415 records = v1records
1416 1416 else:
1417 1417 records = v2records
1418 1418
1419 1419 for rtype, record in records:
1420 1420 # pretty print some record types
1421 1421 if rtype == 'L':
1422 1422 ui.write(('local: %s\n') % record)
1423 1423 elif rtype == 'O':
1424 1424 ui.write(('other: %s\n') % record)
1425 1425 elif rtype == 'm':
1426 1426 driver, mdstate = record.split('\0', 1)
1427 1427 ui.write(('merge driver: %s (state "%s")\n')
1428 1428 % (driver, mdstate))
1429 1429 elif rtype in 'FDC':
1430 1430 r = record.split('\0')
1431 1431 f, state, hash, lfile, afile, anode, ofile = r[0:7]
1432 1432 if version == 1:
1433 1433 onode = 'not stored in v1 format'
1434 1434 flags = r[7]
1435 1435 else:
1436 1436 onode, flags = r[7:9]
1437 1437 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
1438 1438 % (f, rtype, state, _hashornull(hash)))
1439 1439 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
1440 1440 ui.write((' ancestor path: %s (node %s)\n')
1441 1441 % (afile, _hashornull(anode)))
1442 1442 ui.write((' other path: %s (node %s)\n')
1443 1443 % (ofile, _hashornull(onode)))
1444 1444 elif rtype == 'f':
1445 1445 filename, rawextras = record.split('\0', 1)
1446 1446 extras = rawextras.split('\0')
1447 1447 i = 0
1448 1448 extrastrings = []
1449 1449 while i < len(extras):
1450 1450 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
1451 1451 i += 2
1452 1452
1453 1453 ui.write(('file extras: %s (%s)\n')
1454 1454 % (filename, ', '.join(extrastrings)))
1455 1455 elif rtype == 'l':
1456 1456 labels = record.split('\0', 2)
1457 1457 labels = [l for l in labels if len(l) > 0]
1458 1458 ui.write(('labels:\n'))
1459 1459 ui.write((' local: %s\n' % labels[0]))
1460 1460 ui.write((' other: %s\n' % labels[1]))
1461 1461 if len(labels) > 2:
1462 1462 ui.write((' base: %s\n' % labels[2]))
1463 1463 else:
1464 1464 ui.write(('unrecognized entry: %s\t%s\n')
1465 1465 % (rtype, record.replace('\0', '\t')))
1466 1466
1467 1467 # Avoid mergestate.read() since it may raise an exception for unsupported
1468 1468 # merge state records. We shouldn't be doing this, but this is OK since this
1469 1469 # command is pretty low-level.
1470 1470 ms = mergemod.mergestate(repo)
1471 1471
1472 1472 # sort so that reasonable information is on top
1473 1473 v1records = ms._readrecordsv1()
1474 1474 v2records = ms._readrecordsv2()
1475 1475 order = 'LOml'
1476 1476 def key(r):
1477 1477 idx = order.find(r[0])
1478 1478 if idx == -1:
1479 1479 return (1, r[1])
1480 1480 else:
1481 1481 return (0, idx)
1482 1482 v1records.sort(key=key)
1483 1483 v2records.sort(key=key)
1484 1484
1485 1485 if not v1records and not v2records:
1486 1486 ui.write(('no merge state found\n'))
1487 1487 elif not v2records:
1488 1488 ui.note(('no version 2 merge state\n'))
1489 1489 printrecords(1)
1490 1490 elif ms._v1v2match(v1records, v2records):
1491 1491 ui.note(('v1 and v2 states match: using v2\n'))
1492 1492 printrecords(2)
1493 1493 else:
1494 1494 ui.note(('v1 and v2 states mismatch: using v1\n'))
1495 1495 printrecords(1)
1496 1496 if ui.verbose:
1497 1497 printrecords(2)
1498 1498
1499 1499 @command('debugnamecomplete', [], _('NAME...'))
1500 1500 def debugnamecomplete(ui, repo, *args):
1501 1501 '''complete "names" - tags, open branch names, bookmark names'''
1502 1502
1503 1503 names = set()
1504 1504 # since we previously only listed open branches, we will handle that
1505 1505 # specially (after this for loop)
1506 1506 for name, ns in repo.names.iteritems():
1507 1507 if name != 'branches':
1508 1508 names.update(ns.listnames(repo))
1509 1509 names.update(tag for (tag, heads, tip, closed)
1510 1510 in repo.branchmap().iterbranches() if not closed)
1511 1511 completions = set()
1512 1512 if not args:
1513 1513 args = ['']
1514 1514 for a in args:
1515 1515 completions.update(n for n in names if n.startswith(a))
1516 1516 ui.write('\n'.join(sorted(completions)))
1517 1517 ui.write('\n')
1518 1518
1519 1519 @command('debugobsolete',
1520 1520 [('', 'flags', 0, _('markers flag')),
1521 1521 ('', 'record-parents', False,
1522 1522 _('record parent information for the precursor')),
1523 1523 ('r', 'rev', [], _('display markers relevant to REV')),
1524 1524 ('', 'exclusive', False, _('restrict display to markers only '
1525 1525 'relevant to REV')),
1526 1526 ('', 'index', False, _('display index of the marker')),
1527 1527 ('', 'delete', [], _('delete markers specified by indices')),
1528 1528 ] + cmdutil.commitopts2 + cmdutil.formatteropts,
1529 1529 _('[OBSOLETED [REPLACEMENT ...]]'))
1530 1530 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
1531 1531 """create arbitrary obsolete marker
1532 1532
1533 1533 With no arguments, displays the list of obsolescence markers."""
1534 1534
1535 1535 opts = pycompat.byteskwargs(opts)
1536 1536
1537 1537 def parsenodeid(s):
1538 1538 try:
1539 1539 # We do not use revsingle/revrange functions here to accept
1540 1540 # arbitrary node identifiers, possibly not present in the
1541 1541 # local repository.
1542 1542 n = bin(s)
1543 1543 if len(n) != len(nullid):
1544 1544 raise TypeError()
1545 1545 return n
1546 1546 except TypeError:
1547 1547 raise error.Abort('changeset references must be full hexadecimal '
1548 1548 'node identifiers')
1549 1549
1550 1550 if opts.get('delete'):
1551 1551 indices = []
1552 1552 for v in opts.get('delete'):
1553 1553 try:
1554 1554 indices.append(int(v))
1555 1555 except ValueError:
1556 1556 raise error.Abort(_('invalid index value: %r') % v,
1557 1557 hint=_('use integers for indices'))
1558 1558
1559 1559 if repo.currenttransaction():
1560 1560 raise error.Abort(_('cannot delete obsmarkers in the middle '
1561 1561 'of transaction.'))
1562 1562
1563 1563 with repo.lock():
1564 1564 n = repair.deleteobsmarkers(repo.obsstore, indices)
1565 1565 ui.write(_('deleted %i obsolescence markers\n') % n)
1566 1566
1567 1567 return
1568 1568
1569 1569 if precursor is not None:
1570 1570 if opts['rev']:
1571 1571 raise error.Abort('cannot select revision when creating marker')
1572 1572 metadata = {}
1573 1573 metadata['user'] = opts['user'] or ui.username()
1574 1574 succs = tuple(parsenodeid(succ) for succ in successors)
1575 1575 l = repo.lock()
1576 1576 try:
1577 1577 tr = repo.transaction('debugobsolete')
1578 1578 try:
1579 1579 date = opts.get('date')
1580 1580 if date:
1581 1581 date = util.parsedate(date)
1582 1582 else:
1583 1583 date = None
1584 1584 prec = parsenodeid(precursor)
1585 1585 parents = None
1586 1586 if opts['record_parents']:
1587 1587 if prec not in repo.unfiltered():
1588 1588 raise error.Abort('cannot used --record-parents on '
1589 1589 'unknown changesets')
1590 1590 parents = repo.unfiltered()[prec].parents()
1591 1591 parents = tuple(p.node() for p in parents)
1592 1592 repo.obsstore.create(tr, prec, succs, opts['flags'],
1593 1593 parents=parents, date=date,
1594 1594 metadata=metadata, ui=ui)
1595 1595 tr.close()
1596 1596 except ValueError as exc:
1597 1597 raise error.Abort(_('bad obsmarker input: %s') %
1598 1598 pycompat.bytestr(exc))
1599 1599 finally:
1600 1600 tr.release()
1601 1601 finally:
1602 1602 l.release()
1603 1603 else:
1604 1604 if opts['rev']:
1605 1605 revs = scmutil.revrange(repo, opts['rev'])
1606 1606 nodes = [repo[r].node() for r in revs]
1607 1607 markers = list(obsutil.getmarkers(repo, nodes=nodes,
1608 1608 exclusive=opts['exclusive']))
1609 1609 markers.sort(key=lambda x: x._data)
1610 1610 else:
1611 1611 markers = obsutil.getmarkers(repo)
1612 1612
1613 1613 markerstoiter = markers
1614 1614 isrelevant = lambda m: True
1615 1615 if opts.get('rev') and opts.get('index'):
1616 1616 markerstoiter = obsutil.getmarkers(repo)
1617 1617 markerset = set(markers)
1618 1618 isrelevant = lambda m: m in markerset
1619 1619
1620 1620 fm = ui.formatter('debugobsolete', opts)
1621 1621 for i, m in enumerate(markerstoiter):
1622 1622 if not isrelevant(m):
1623 1623 # marker can be irrelevant when we're iterating over a set
1624 1624 # of markers (markerstoiter) which is bigger than the set
1625 1625 # of markers we want to display (markers)
1626 1626 # this can happen if both --index and --rev options are
1627 1627 # provided and thus we need to iterate over all of the markers
1628 1628 # to get the correct indices, but only display the ones that
1629 1629 # are relevant to --rev value
1630 1630 continue
1631 1631 fm.startitem()
1632 1632 ind = i if opts.get('index') else None
1633 1633 cmdutil.showmarker(fm, m, index=ind)
1634 1634 fm.end()
1635 1635
1636 1636 @command('debugpathcomplete',
1637 1637 [('f', 'full', None, _('complete an entire path')),
1638 1638 ('n', 'normal', None, _('show only normal files')),
1639 1639 ('a', 'added', None, _('show only added files')),
1640 1640 ('r', 'removed', None, _('show only removed files'))],
1641 1641 _('FILESPEC...'))
1642 1642 def debugpathcomplete(ui, repo, *specs, **opts):
1643 1643 '''complete part or all of a tracked path
1644 1644
1645 1645 This command supports shells that offer path name completion. It
1646 1646 currently completes only files already known to the dirstate.
1647 1647
1648 1648 Completion extends only to the next path segment unless
1649 1649 --full is specified, in which case entire paths are used.'''
1650 1650
1651 1651 def complete(path, acceptable):
1652 1652 dirstate = repo.dirstate
1653 1653 spec = os.path.normpath(os.path.join(pycompat.getcwd(), path))
1654 1654 rootdir = repo.root + pycompat.ossep
1655 1655 if spec != repo.root and not spec.startswith(rootdir):
1656 1656 return [], []
1657 1657 if os.path.isdir(spec):
1658 1658 spec += '/'
1659 1659 spec = spec[len(rootdir):]
1660 1660 fixpaths = pycompat.ossep != '/'
1661 1661 if fixpaths:
1662 1662 spec = spec.replace(pycompat.ossep, '/')
1663 1663 speclen = len(spec)
1664 1664 fullpaths = opts[r'full']
1665 1665 files, dirs = set(), set()
1666 1666 adddir, addfile = dirs.add, files.add
1667 1667 for f, st in dirstate.iteritems():
1668 1668 if f.startswith(spec) and st[0] in acceptable:
1669 1669 if fixpaths:
1670 1670 f = f.replace('/', pycompat.ossep)
1671 1671 if fullpaths:
1672 1672 addfile(f)
1673 1673 continue
1674 1674 s = f.find(pycompat.ossep, speclen)
1675 1675 if s >= 0:
1676 1676 adddir(f[:s])
1677 1677 else:
1678 1678 addfile(f)
1679 1679 return files, dirs
1680 1680
1681 1681 acceptable = ''
1682 1682 if opts[r'normal']:
1683 1683 acceptable += 'nm'
1684 1684 if opts[r'added']:
1685 1685 acceptable += 'a'
1686 1686 if opts[r'removed']:
1687 1687 acceptable += 'r'
1688 1688 cwd = repo.getcwd()
1689 1689 if not specs:
1690 1690 specs = ['.']
1691 1691
1692 1692 files, dirs = set(), set()
1693 1693 for spec in specs:
1694 1694 f, d = complete(spec, acceptable or 'nmar')
1695 1695 files.update(f)
1696 1696 dirs.update(d)
1697 1697 files.update(dirs)
1698 1698 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
1699 1699 ui.write('\n')
1700 1700
1701 1701 @command('debugpeer', [], _('PATH'), norepo=True)
1702 1702 def debugpeer(ui, path):
1703 1703 """establish a connection to a peer repository"""
1704 1704 # Always enable peer request logging. Requires --debug to display
1705 1705 # though.
1706 1706 overrides = {
1707 1707 ('devel', 'debug.peer-request'): True,
1708 1708 }
1709 1709
1710 1710 with ui.configoverride(overrides):
1711 1711 peer = hg.peer(ui, {}, path)
1712 1712
1713 1713 local = peer.local() is not None
1714 1714 canpush = peer.canpush()
1715 1715
1716 1716 ui.write(_('url: %s\n') % peer.url())
1717 1717 ui.write(_('local: %s\n') % (_('yes') if local else _('no')))
1718 1718 ui.write(_('pushable: %s\n') % (_('yes') if canpush else _('no')))
1719 1719
1720 1720 @command('debugpickmergetool',
1721 1721 [('r', 'rev', '', _('check for files in this revision'), _('REV')),
1722 1722 ('', 'changedelete', None, _('emulate merging change and delete')),
1723 1723 ] + cmdutil.walkopts + cmdutil.mergetoolopts,
1724 1724 _('[PATTERN]...'),
1725 1725 inferrepo=True)
1726 1726 def debugpickmergetool(ui, repo, *pats, **opts):
1727 1727 """examine which merge tool is chosen for specified file
1728 1728
1729 1729 As described in :hg:`help merge-tools`, Mercurial examines
1730 1730 configurations below in this order to decide which merge tool is
1731 1731 chosen for specified file.
1732 1732
1733 1733 1. ``--tool`` option
1734 1734 2. ``HGMERGE`` environment variable
1735 1735 3. configurations in ``merge-patterns`` section
1736 1736 4. configuration of ``ui.merge``
1737 1737 5. configurations in ``merge-tools`` section
1738 1738 6. ``hgmerge`` tool (for historical reason only)
1739 1739 7. default tool for fallback (``:merge`` or ``:prompt``)
1740 1740
1741 1741 This command writes out examination result in the style below::
1742 1742
1743 1743 FILE = MERGETOOL
1744 1744
1745 1745 By default, all files known in the first parent context of the
1746 1746 working directory are examined. Use file patterns and/or -I/-X
1747 1747 options to limit target files. -r/--rev is also useful to examine
1748 1748 files in another context without actual updating to it.
1749 1749
1750 1750 With --debug, this command shows warning messages while matching
1751 1751 against ``merge-patterns`` and so on, too. It is recommended to
1752 1752 use this option with explicit file patterns and/or -I/-X options,
1753 1753 because this option increases amount of output per file according
1754 1754 to configurations in hgrc.
1755 1755
1756 1756 With -v/--verbose, this command shows configurations below at
1757 1757 first (only if specified).
1758 1758
1759 1759 - ``--tool`` option
1760 1760 - ``HGMERGE`` environment variable
1761 1761 - configuration of ``ui.merge``
1762 1762
1763 1763 If merge tool is chosen before matching against
1764 1764 ``merge-patterns``, this command can't show any helpful
1765 1765 information, even with --debug. In such case, information above is
1766 1766 useful to know why a merge tool is chosen.
1767 1767 """
1768 1768 opts = pycompat.byteskwargs(opts)
1769 1769 overrides = {}
1770 1770 if opts['tool']:
1771 1771 overrides[('ui', 'forcemerge')] = opts['tool']
1772 1772 ui.note(('with --tool %r\n') % (opts['tool']))
1773 1773
1774 1774 with ui.configoverride(overrides, 'debugmergepatterns'):
1775 1775 hgmerge = encoding.environ.get("HGMERGE")
1776 1776 if hgmerge is not None:
1777 1777 ui.note(('with HGMERGE=%r\n') % (hgmerge))
1778 1778 uimerge = ui.config("ui", "merge")
1779 1779 if uimerge:
1780 1780 ui.note(('with ui.merge=%r\n') % (uimerge))
1781 1781
1782 1782 ctx = scmutil.revsingle(repo, opts.get('rev'))
1783 1783 m = scmutil.match(ctx, pats, opts)
1784 1784 changedelete = opts['changedelete']
1785 1785 for path in ctx.walk(m):
1786 1786 fctx = ctx[path]
1787 1787 try:
1788 1788 if not ui.debugflag:
1789 1789 ui.pushbuffer(error=True)
1790 1790 tool, toolpath = filemerge._picktool(repo, ui, path,
1791 1791 fctx.isbinary(),
1792 1792 'l' in fctx.flags(),
1793 1793 changedelete)
1794 1794 finally:
1795 1795 if not ui.debugflag:
1796 1796 ui.popbuffer()
1797 1797 ui.write(('%s = %s\n') % (path, tool))
1798 1798
1799 1799 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
1800 1800 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1801 1801 '''access the pushkey key/value protocol
1802 1802
1803 1803 With two args, list the keys in the given namespace.
1804 1804
1805 1805 With five args, set a key to new if it currently is set to old.
1806 1806 Reports success or failure.
1807 1807 '''
1808 1808
1809 1809 target = hg.peer(ui, {}, repopath)
1810 1810 if keyinfo:
1811 1811 key, old, new = keyinfo
1812 1812 r = target.pushkey(namespace, key, old, new)
1813 1813 ui.status(str(r) + '\n')
1814 1814 return not r
1815 1815 else:
1816 1816 for k, v in sorted(target.listkeys(namespace).iteritems()):
1817 1817 ui.write("%s\t%s\n" % (util.escapestr(k),
1818 1818 util.escapestr(v)))
1819 1819
1820 1820 @command('debugpvec', [], _('A B'))
1821 1821 def debugpvec(ui, repo, a, b=None):
1822 1822 ca = scmutil.revsingle(repo, a)
1823 1823 cb = scmutil.revsingle(repo, b)
1824 1824 pa = pvec.ctxpvec(ca)
1825 1825 pb = pvec.ctxpvec(cb)
1826 1826 if pa == pb:
1827 1827 rel = "="
1828 1828 elif pa > pb:
1829 1829 rel = ">"
1830 1830 elif pa < pb:
1831 1831 rel = "<"
1832 1832 elif pa | pb:
1833 1833 rel = "|"
1834 1834 ui.write(_("a: %s\n") % pa)
1835 1835 ui.write(_("b: %s\n") % pb)
1836 1836 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
1837 1837 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
1838 1838 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
1839 1839 pa.distance(pb), rel))
1840 1840
1841 1841 @command('debugrebuilddirstate|debugrebuildstate',
1842 1842 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
1843 1843 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
1844 1844 'the working copy parent')),
1845 1845 ],
1846 1846 _('[-r REV]'))
1847 1847 def debugrebuilddirstate(ui, repo, rev, **opts):
1848 1848 """rebuild the dirstate as it would look like for the given revision
1849 1849
1850 1850 If no revision is specified the first current parent will be used.
1851 1851
1852 1852 The dirstate will be set to the files of the given revision.
1853 1853 The actual working directory content or existing dirstate
1854 1854 information such as adds or removes is not considered.
1855 1855
1856 1856 ``minimal`` will only rebuild the dirstate status for files that claim to be
1857 1857 tracked but are not in the parent manifest, or that exist in the parent
1858 1858 manifest but are not in the dirstate. It will not change adds, removes, or
1859 1859 modified files that are in the working copy parent.
1860 1860
1861 1861 One use of this command is to make the next :hg:`status` invocation
1862 1862 check the actual file content.
1863 1863 """
1864 1864 ctx = scmutil.revsingle(repo, rev)
1865 1865 with repo.wlock():
1866 1866 dirstate = repo.dirstate
1867 1867 changedfiles = None
1868 1868 # See command doc for what minimal does.
1869 1869 if opts.get(r'minimal'):
1870 1870 manifestfiles = set(ctx.manifest().keys())
1871 1871 dirstatefiles = set(dirstate)
1872 1872 manifestonly = manifestfiles - dirstatefiles
1873 1873 dsonly = dirstatefiles - manifestfiles
1874 1874 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
1875 1875 changedfiles = manifestonly | dsnotadded
1876 1876
1877 1877 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
1878 1878
1879 1879 @command('debugrebuildfncache', [], '')
1880 1880 def debugrebuildfncache(ui, repo):
1881 1881 """rebuild the fncache file"""
1882 1882 repair.rebuildfncache(ui, repo)
1883 1883
1884 1884 @command('debugrename',
1885 1885 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1886 1886 _('[-r REV] FILE'))
1887 1887 def debugrename(ui, repo, file1, *pats, **opts):
1888 1888 """dump rename information"""
1889 1889
1890 1890 opts = pycompat.byteskwargs(opts)
1891 1891 ctx = scmutil.revsingle(repo, opts.get('rev'))
1892 1892 m = scmutil.match(ctx, (file1,) + pats, opts)
1893 1893 for abs in ctx.walk(m):
1894 1894 fctx = ctx[abs]
1895 1895 o = fctx.filelog().renamed(fctx.filenode())
1896 1896 rel = m.rel(abs)
1897 1897 if o:
1898 1898 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1899 1899 else:
1900 1900 ui.write(_("%s not renamed\n") % rel)
1901 1901
1902 1902 @command('debugrevlog', cmdutil.debugrevlogopts +
1903 1903 [('d', 'dump', False, _('dump index data'))],
1904 1904 _('-c|-m|FILE'),
1905 1905 optionalrepo=True)
1906 1906 def debugrevlog(ui, repo, file_=None, **opts):
1907 1907 """show data and statistics about a revlog"""
1908 1908 opts = pycompat.byteskwargs(opts)
1909 1909 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1910 1910
1911 1911 if opts.get("dump"):
1912 1912 numrevs = len(r)
1913 1913 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
1914 1914 " rawsize totalsize compression heads chainlen\n"))
1915 1915 ts = 0
1916 1916 heads = set()
1917 1917
1918 1918 for rev in xrange(numrevs):
1919 1919 dbase = r.deltaparent(rev)
1920 1920 if dbase == -1:
1921 1921 dbase = rev
1922 1922 cbase = r.chainbase(rev)
1923 1923 clen = r.chainlen(rev)
1924 1924 p1, p2 = r.parentrevs(rev)
1925 1925 rs = r.rawsize(rev)
1926 1926 ts = ts + rs
1927 1927 heads -= set(r.parentrevs(rev))
1928 1928 heads.add(rev)
1929 1929 try:
1930 1930 compression = ts / r.end(rev)
1931 1931 except ZeroDivisionError:
1932 1932 compression = 0
1933 1933 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
1934 1934 "%11d %5d %8d\n" %
1935 1935 (rev, p1, p2, r.start(rev), r.end(rev),
1936 1936 r.start(dbase), r.start(cbase),
1937 1937 r.start(p1), r.start(p2),
1938 1938 rs, ts, compression, len(heads), clen))
1939 1939 return 0
1940 1940
1941 1941 v = r.version
1942 1942 format = v & 0xFFFF
1943 1943 flags = []
1944 1944 gdelta = False
1945 1945 if v & revlog.FLAG_INLINE_DATA:
1946 1946 flags.append('inline')
1947 1947 if v & revlog.FLAG_GENERALDELTA:
1948 1948 gdelta = True
1949 1949 flags.append('generaldelta')
1950 1950 if not flags:
1951 1951 flags = ['(none)']
1952 1952
1953 1953 nummerges = 0
1954 1954 numfull = 0
1955 1955 numprev = 0
1956 1956 nump1 = 0
1957 1957 nump2 = 0
1958 1958 numother = 0
1959 1959 nump1prev = 0
1960 1960 nump2prev = 0
1961 1961 chainlengths = []
1962 1962 chainbases = []
1963 1963 chainspans = []
1964 1964
1965 1965 datasize = [None, 0, 0]
1966 1966 fullsize = [None, 0, 0]
1967 1967 deltasize = [None, 0, 0]
1968 1968 chunktypecounts = {}
1969 1969 chunktypesizes = {}
1970 1970
1971 1971 def addsize(size, l):
1972 1972 if l[0] is None or size < l[0]:
1973 1973 l[0] = size
1974 1974 if size > l[1]:
1975 1975 l[1] = size
1976 1976 l[2] += size
1977 1977
1978 1978 numrevs = len(r)
1979 1979 for rev in xrange(numrevs):
1980 1980 p1, p2 = r.parentrevs(rev)
1981 1981 delta = r.deltaparent(rev)
1982 1982 if format > 0:
1983 1983 addsize(r.rawsize(rev), datasize)
1984 1984 if p2 != nullrev:
1985 1985 nummerges += 1
1986 1986 size = r.length(rev)
1987 1987 if delta == nullrev:
1988 1988 chainlengths.append(0)
1989 1989 chainbases.append(r.start(rev))
1990 1990 chainspans.append(size)
1991 1991 numfull += 1
1992 1992 addsize(size, fullsize)
1993 1993 else:
1994 1994 chainlengths.append(chainlengths[delta] + 1)
1995 1995 baseaddr = chainbases[delta]
1996 1996 revaddr = r.start(rev)
1997 1997 chainbases.append(baseaddr)
1998 1998 chainspans.append((revaddr - baseaddr) + size)
1999 1999 addsize(size, deltasize)
2000 2000 if delta == rev - 1:
2001 2001 numprev += 1
2002 2002 if delta == p1:
2003 2003 nump1prev += 1
2004 2004 elif delta == p2:
2005 2005 nump2prev += 1
2006 2006 elif delta == p1:
2007 2007 nump1 += 1
2008 2008 elif delta == p2:
2009 2009 nump2 += 1
2010 2010 elif delta != nullrev:
2011 2011 numother += 1
2012 2012
2013 2013 # Obtain data on the raw chunks in the revlog.
2014 2014 segment = r._getsegmentforrevs(rev, rev)[1]
2015 2015 if segment:
2016 2016 chunktype = bytes(segment[0:1])
2017 2017 else:
2018 2018 chunktype = 'empty'
2019 2019
2020 2020 if chunktype not in chunktypecounts:
2021 2021 chunktypecounts[chunktype] = 0
2022 2022 chunktypesizes[chunktype] = 0
2023 2023
2024 2024 chunktypecounts[chunktype] += 1
2025 2025 chunktypesizes[chunktype] += size
2026 2026
2027 2027 # Adjust size min value for empty cases
2028 2028 for size in (datasize, fullsize, deltasize):
2029 2029 if size[0] is None:
2030 2030 size[0] = 0
2031 2031
2032 2032 numdeltas = numrevs - numfull
2033 2033 numoprev = numprev - nump1prev - nump2prev
2034 2034 totalrawsize = datasize[2]
2035 2035 datasize[2] /= numrevs
2036 2036 fulltotal = fullsize[2]
2037 2037 fullsize[2] /= numfull
2038 2038 deltatotal = deltasize[2]
2039 2039 if numrevs - numfull > 0:
2040 2040 deltasize[2] /= numrevs - numfull
2041 2041 totalsize = fulltotal + deltatotal
2042 2042 avgchainlen = sum(chainlengths) / numrevs
2043 2043 maxchainlen = max(chainlengths)
2044 2044 maxchainspan = max(chainspans)
2045 2045 compratio = 1
2046 2046 if totalsize:
2047 2047 compratio = totalrawsize / totalsize
2048 2048
2049 2049 basedfmtstr = '%%%dd\n'
2050 2050 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2051 2051
2052 2052 def dfmtstr(max):
2053 2053 return basedfmtstr % len(str(max))
2054 2054 def pcfmtstr(max, padding=0):
2055 2055 return basepcfmtstr % (len(str(max)), ' ' * padding)
2056 2056
2057 2057 def pcfmt(value, total):
2058 2058 if total:
2059 2059 return (value, 100 * float(value) / total)
2060 2060 else:
2061 2061 return value, 100.0
2062 2062
2063 2063 ui.write(('format : %d\n') % format)
2064 2064 ui.write(('flags : %s\n') % ', '.join(flags))
2065 2065
2066 2066 ui.write('\n')
2067 2067 fmt = pcfmtstr(totalsize)
2068 2068 fmt2 = dfmtstr(totalsize)
2069 2069 ui.write(('revisions : ') + fmt2 % numrevs)
2070 2070 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2071 2071 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2072 2072 ui.write(('revisions : ') + fmt2 % numrevs)
2073 2073 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2074 2074 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2075 2075 ui.write(('revision size : ') + fmt2 % totalsize)
2076 2076 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2077 2077 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2078 2078
2079 2079 def fmtchunktype(chunktype):
2080 2080 if chunktype == 'empty':
2081 2081 return ' %s : ' % chunktype
2082 2082 elif chunktype in pycompat.bytestr(string.ascii_letters):
2083 2083 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
2084 2084 else:
2085 2085 return ' 0x%s : ' % hex(chunktype)
2086 2086
2087 2087 ui.write('\n')
2088 2088 ui.write(('chunks : ') + fmt2 % numrevs)
2089 2089 for chunktype in sorted(chunktypecounts):
2090 2090 ui.write(fmtchunktype(chunktype))
2091 2091 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
2092 2092 ui.write(('chunks size : ') + fmt2 % totalsize)
2093 2093 for chunktype in sorted(chunktypecounts):
2094 2094 ui.write(fmtchunktype(chunktype))
2095 2095 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
2096 2096
2097 2097 ui.write('\n')
2098 2098 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
2099 2099 ui.write(('avg chain length : ') + fmt % avgchainlen)
2100 2100 ui.write(('max chain length : ') + fmt % maxchainlen)
2101 2101 ui.write(('max chain reach : ') + fmt % maxchainspan)
2102 2102 ui.write(('compression ratio : ') + fmt % compratio)
2103 2103
2104 2104 if format > 0:
2105 2105 ui.write('\n')
2106 2106 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2107 2107 % tuple(datasize))
2108 2108 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2109 2109 % tuple(fullsize))
2110 2110 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2111 2111 % tuple(deltasize))
2112 2112
2113 2113 if numdeltas > 0:
2114 2114 ui.write('\n')
2115 2115 fmt = pcfmtstr(numdeltas)
2116 2116 fmt2 = pcfmtstr(numdeltas, 4)
2117 2117 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2118 2118 if numprev > 0:
2119 2119 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2120 2120 numprev))
2121 2121 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2122 2122 numprev))
2123 2123 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2124 2124 numprev))
2125 2125 if gdelta:
2126 2126 ui.write(('deltas against p1 : ')
2127 2127 + fmt % pcfmt(nump1, numdeltas))
2128 2128 ui.write(('deltas against p2 : ')
2129 2129 + fmt % pcfmt(nump2, numdeltas))
2130 2130 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2131 2131 numdeltas))
2132 2132
2133 2133 @command('debugrevspec',
2134 2134 [('', 'optimize', None,
2135 2135 _('print parsed tree after optimizing (DEPRECATED)')),
2136 2136 ('', 'show-revs', True, _('print list of result revisions (default)')),
2137 2137 ('s', 'show-set', None, _('print internal representation of result set')),
2138 2138 ('p', 'show-stage', [],
2139 2139 _('print parsed tree at the given stage'), _('NAME')),
2140 2140 ('', 'no-optimized', False, _('evaluate tree without optimization')),
2141 2141 ('', 'verify-optimized', False, _('verify optimized result')),
2142 2142 ],
2143 2143 ('REVSPEC'))
2144 2144 def debugrevspec(ui, repo, expr, **opts):
2145 2145 """parse and apply a revision specification
2146 2146
2147 2147 Use -p/--show-stage option to print the parsed tree at the given stages.
2148 2148 Use -p all to print tree at every stage.
2149 2149
2150 2150 Use --no-show-revs option with -s or -p to print only the set
2151 2151 representation or the parsed tree respectively.
2152 2152
2153 2153 Use --verify-optimized to compare the optimized result with the unoptimized
2154 2154 one. Returns 1 if the optimized result differs.
2155 2155 """
2156 2156 opts = pycompat.byteskwargs(opts)
2157 2157 aliases = ui.configitems('revsetalias')
2158 2158 stages = [
2159 2159 ('parsed', lambda tree: tree),
2160 2160 ('expanded', lambda tree: revsetlang.expandaliases(tree, aliases,
2161 2161 ui.warn)),
2162 2162 ('concatenated', revsetlang.foldconcat),
2163 2163 ('analyzed', revsetlang.analyze),
2164 2164 ('optimized', revsetlang.optimize),
2165 2165 ]
2166 2166 if opts['no_optimized']:
2167 2167 stages = stages[:-1]
2168 2168 if opts['verify_optimized'] and opts['no_optimized']:
2169 2169 raise error.Abort(_('cannot use --verify-optimized with '
2170 2170 '--no-optimized'))
2171 2171 stagenames = set(n for n, f in stages)
2172 2172
2173 2173 showalways = set()
2174 2174 showchanged = set()
2175 2175 if ui.verbose and not opts['show_stage']:
2176 2176 # show parsed tree by --verbose (deprecated)
2177 2177 showalways.add('parsed')
2178 2178 showchanged.update(['expanded', 'concatenated'])
2179 2179 if opts['optimize']:
2180 2180 showalways.add('optimized')
2181 2181 if opts['show_stage'] and opts['optimize']:
2182 2182 raise error.Abort(_('cannot use --optimize with --show-stage'))
2183 2183 if opts['show_stage'] == ['all']:
2184 2184 showalways.update(stagenames)
2185 2185 else:
2186 2186 for n in opts['show_stage']:
2187 2187 if n not in stagenames:
2188 2188 raise error.Abort(_('invalid stage name: %s') % n)
2189 2189 showalways.update(opts['show_stage'])
2190 2190
2191 2191 treebystage = {}
2192 2192 printedtree = None
2193 2193 tree = revsetlang.parse(expr, lookup=repo.__contains__)
2194 2194 for n, f in stages:
2195 2195 treebystage[n] = tree = f(tree)
2196 2196 if n in showalways or (n in showchanged and tree != printedtree):
2197 2197 if opts['show_stage'] or n != 'parsed':
2198 2198 ui.write(("* %s:\n") % n)
2199 2199 ui.write(revsetlang.prettyformat(tree), "\n")
2200 2200 printedtree = tree
2201 2201
2202 2202 if opts['verify_optimized']:
2203 2203 arevs = revset.makematcher(treebystage['analyzed'])(repo)
2204 2204 brevs = revset.makematcher(treebystage['optimized'])(repo)
2205 2205 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2206 2206 ui.write(("* analyzed set:\n"), smartset.prettyformat(arevs), "\n")
2207 2207 ui.write(("* optimized set:\n"), smartset.prettyformat(brevs), "\n")
2208 2208 arevs = list(arevs)
2209 2209 brevs = list(brevs)
2210 2210 if arevs == brevs:
2211 2211 return 0
2212 2212 ui.write(('--- analyzed\n'), label='diff.file_a')
2213 2213 ui.write(('+++ optimized\n'), label='diff.file_b')
2214 2214 sm = difflib.SequenceMatcher(None, arevs, brevs)
2215 2215 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2216 2216 if tag in ('delete', 'replace'):
2217 2217 for c in arevs[alo:ahi]:
2218 2218 ui.write('-%s\n' % c, label='diff.deleted')
2219 2219 if tag in ('insert', 'replace'):
2220 2220 for c in brevs[blo:bhi]:
2221 2221 ui.write('+%s\n' % c, label='diff.inserted')
2222 2222 if tag == 'equal':
2223 2223 for c in arevs[alo:ahi]:
2224 2224 ui.write(' %s\n' % c)
2225 2225 return 1
2226 2226
2227 2227 func = revset.makematcher(tree)
2228 2228 revs = func(repo)
2229 2229 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2230 2230 ui.write(("* set:\n"), smartset.prettyformat(revs), "\n")
2231 2231 if not opts['show_revs']:
2232 2232 return
2233 2233 for c in revs:
2234 2234 ui.write("%d\n" % c)
2235 2235
2236 2236 @command('debugserve', [
2237 2237 ('', 'sshstdio', False, _('run an SSH server bound to process handles')),
2238 2238 ('', 'logiofd', '', _('file descriptor to log server I/O to')),
2239 2239 ('', 'logiofile', '', _('file to log server I/O to')),
2240 2240 ], '')
2241 2241 def debugserve(ui, repo, **opts):
2242 2242 """run a server with advanced settings
2243 2243
2244 2244 This command is similar to :hg:`serve`. It exists partially as a
2245 2245 workaround to the fact that ``hg serve --stdio`` must have specific
2246 2246 arguments for security reasons.
2247 2247 """
2248 2248 opts = pycompat.byteskwargs(opts)
2249 2249
2250 2250 if not opts['sshstdio']:
2251 2251 raise error.Abort(_('only --sshstdio is currently supported'))
2252 2252
2253 2253 logfh = None
2254 2254
2255 2255 if opts['logiofd'] and opts['logiofile']:
2256 2256 raise error.Abort(_('cannot use both --logiofd and --logiofile'))
2257 2257
2258 2258 if opts['logiofd']:
2259 2259 # Line buffered because output is line based.
2260 2260 logfh = os.fdopen(int(opts['logiofd']), 'ab', 1)
2261 2261 elif opts['logiofile']:
2262 2262 logfh = open(opts['logiofile'], 'ab', 1)
2263 2263
2264 2264 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
2265 2265 s.serve_forever()
2266 2266
2267 2267 @command('debugsetparents', [], _('REV1 [REV2]'))
2268 2268 def debugsetparents(ui, repo, rev1, rev2=None):
2269 2269 """manually set the parents of the current working directory
2270 2270
2271 2271 This is useful for writing repository conversion tools, but should
2272 2272 be used with care. For example, neither the working directory nor the
2273 2273 dirstate is updated, so file status may be incorrect after running this
2274 2274 command.
2275 2275
2276 2276 Returns 0 on success.
2277 2277 """
2278 2278
2279 2279 r1 = scmutil.revsingle(repo, rev1).node()
2280 2280 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2281 2281
2282 2282 with repo.wlock():
2283 2283 repo.setparents(r1, r2)
2284 2284
2285 2285 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
2286 2286 def debugssl(ui, repo, source=None, **opts):
2287 2287 '''test a secure connection to a server
2288 2288
2289 2289 This builds the certificate chain for the server on Windows, installing the
2290 2290 missing intermediates and trusted root via Windows Update if necessary. It
2291 2291 does nothing on other platforms.
2292 2292
2293 2293 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
2294 2294 that server is used. See :hg:`help urls` for more information.
2295 2295
2296 2296 If the update succeeds, retry the original operation. Otherwise, the cause
2297 2297 of the SSL error is likely another issue.
2298 2298 '''
2299 2299 if not pycompat.iswindows:
2300 2300 raise error.Abort(_('certificate chain building is only possible on '
2301 2301 'Windows'))
2302 2302
2303 2303 if not source:
2304 2304 if not repo:
2305 2305 raise error.Abort(_("there is no Mercurial repository here, and no "
2306 2306 "server specified"))
2307 2307 source = "default"
2308 2308
2309 2309 source, branches = hg.parseurl(ui.expandpath(source))
2310 2310 url = util.url(source)
2311 2311 addr = None
2312 2312
2313 2313 defaultport = {'https': 443, 'ssh': 22}
2314 2314 if url.scheme in defaultport:
2315 2315 try:
2316 2316 addr = (url.host, int(url.port or defaultport[url.scheme]))
2317 2317 except ValueError:
2318 2318 raise error.Abort(_("malformed port number in URL"))
2319 2319 else:
2320 2320 raise error.Abort(_("only https and ssh connections are supported"))
2321 2321
2322 2322 from . import win32
2323 2323
2324 2324 s = ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_TLS,
2325 2325 cert_reqs=ssl.CERT_NONE, ca_certs=None)
2326 2326
2327 2327 try:
2328 2328 s.connect(addr)
2329 2329 cert = s.getpeercert(True)
2330 2330
2331 2331 ui.status(_('checking the certificate chain for %s\n') % url.host)
2332 2332
2333 2333 complete = win32.checkcertificatechain(cert, build=False)
2334 2334
2335 2335 if not complete:
2336 2336 ui.status(_('certificate chain is incomplete, updating... '))
2337 2337
2338 2338 if not win32.checkcertificatechain(cert):
2339 2339 ui.status(_('failed.\n'))
2340 2340 else:
2341 2341 ui.status(_('done.\n'))
2342 2342 else:
2343 2343 ui.status(_('full certificate chain is available\n'))
2344 2344 finally:
2345 2345 s.close()
2346 2346
2347 2347 @command('debugsub',
2348 2348 [('r', 'rev', '',
2349 2349 _('revision to check'), _('REV'))],
2350 2350 _('[-r REV] [REV]'))
2351 2351 def debugsub(ui, repo, rev=None):
2352 2352 ctx = scmutil.revsingle(repo, rev, None)
2353 2353 for k, v in sorted(ctx.substate.items()):
2354 2354 ui.write(('path %s\n') % k)
2355 2355 ui.write((' source %s\n') % v[0])
2356 2356 ui.write((' revision %s\n') % v[1])
2357 2357
2358 2358 @command('debugsuccessorssets',
2359 2359 [('', 'closest', False, _('return closest successors sets only'))],
2360 2360 _('[REV]'))
2361 2361 def debugsuccessorssets(ui, repo, *revs, **opts):
2362 2362 """show set of successors for revision
2363 2363
2364 2364 A successors set of changeset A is a consistent group of revisions that
2365 2365 succeed A. It contains non-obsolete changesets only unless closests
2366 2366 successors set is set.
2367 2367
2368 2368 In most cases a changeset A has a single successors set containing a single
2369 2369 successor (changeset A replaced by A').
2370 2370
2371 2371 A changeset that is made obsolete with no successors are called "pruned".
2372 2372 Such changesets have no successors sets at all.
2373 2373
2374 2374 A changeset that has been "split" will have a successors set containing
2375 2375 more than one successor.
2376 2376
2377 2377 A changeset that has been rewritten in multiple different ways is called
2378 2378 "divergent". Such changesets have multiple successor sets (each of which
2379 2379 may also be split, i.e. have multiple successors).
2380 2380
2381 2381 Results are displayed as follows::
2382 2382
2383 2383 <rev1>
2384 2384 <successors-1A>
2385 2385 <rev2>
2386 2386 <successors-2A>
2387 2387 <successors-2B1> <successors-2B2> <successors-2B3>
2388 2388
2389 2389 Here rev2 has two possible (i.e. divergent) successors sets. The first
2390 2390 holds one element, whereas the second holds three (i.e. the changeset has
2391 2391 been split).
2392 2392 """
2393 2393 # passed to successorssets caching computation from one call to another
2394 2394 cache = {}
2395 2395 ctx2str = bytes
2396 2396 node2str = short
2397 2397 for rev in scmutil.revrange(repo, revs):
2398 2398 ctx = repo[rev]
2399 2399 ui.write('%s\n'% ctx2str(ctx))
2400 2400 for succsset in obsutil.successorssets(repo, ctx.node(),
2401 2401 closest=opts[r'closest'],
2402 2402 cache=cache):
2403 2403 if succsset:
2404 2404 ui.write(' ')
2405 2405 ui.write(node2str(succsset[0]))
2406 2406 for node in succsset[1:]:
2407 2407 ui.write(' ')
2408 2408 ui.write(node2str(node))
2409 2409 ui.write('\n')
2410 2410
2411 2411 @command('debugtemplate',
2412 2412 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
2413 2413 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
2414 2414 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
2415 2415 optionalrepo=True)
2416 2416 def debugtemplate(ui, repo, tmpl, **opts):
2417 2417 """parse and apply a template
2418 2418
2419 2419 If -r/--rev is given, the template is processed as a log template and
2420 2420 applied to the given changesets. Otherwise, it is processed as a generic
2421 2421 template.
2422 2422
2423 2423 Use --verbose to print the parsed tree.
2424 2424 """
2425 2425 revs = None
2426 2426 if opts[r'rev']:
2427 2427 if repo is None:
2428 2428 raise error.RepoError(_('there is no Mercurial repository here '
2429 2429 '(.hg not found)'))
2430 2430 revs = scmutil.revrange(repo, opts[r'rev'])
2431 2431
2432 2432 props = {}
2433 2433 for d in opts[r'define']:
2434 2434 try:
2435 2435 k, v = (e.strip() for e in d.split('=', 1))
2436 2436 if not k or k == 'ui':
2437 2437 raise ValueError
2438 2438 props[k] = v
2439 2439 except ValueError:
2440 2440 raise error.Abort(_('malformed keyword definition: %s') % d)
2441 2441
2442 2442 if ui.verbose:
2443 2443 aliases = ui.configitems('templatealias')
2444 2444 tree = templater.parse(tmpl)
2445 2445 ui.note(templater.prettyformat(tree), '\n')
2446 2446 newtree = templater.expandaliases(tree, aliases)
2447 2447 if newtree != tree:
2448 2448 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
2449 2449
2450 2450 if revs is None:
2451 2451 tres = formatter.templateresources(ui, repo)
2452 2452 t = formatter.maketemplater(ui, tmpl, resources=tres)
2453 2453 ui.write(t.render(props))
2454 2454 else:
2455 2455 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
2456 2456 for r in revs:
2457 2457 displayer.show(repo[r], **pycompat.strkwargs(props))
2458 2458 displayer.close()
2459 2459
2460 2460 @command('debugupdatecaches', [])
2461 2461 def debugupdatecaches(ui, repo, *pats, **opts):
2462 2462 """warm all known caches in the repository"""
2463 2463 with repo.wlock(), repo.lock():
2464 2464 repo.updatecaches()
2465 2465
2466 2466 @command('debugupgraderepo', [
2467 2467 ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
2468 2468 ('', 'run', False, _('performs an upgrade')),
2469 2469 ])
2470 2470 def debugupgraderepo(ui, repo, run=False, optimize=None):
2471 2471 """upgrade a repository to use different features
2472 2472
2473 2473 If no arguments are specified, the repository is evaluated for upgrade
2474 2474 and a list of problems and potential optimizations is printed.
2475 2475
2476 2476 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
2477 2477 can be influenced via additional arguments. More details will be provided
2478 2478 by the command output when run without ``--run``.
2479 2479
2480 2480 During the upgrade, the repository will be locked and no writes will be
2481 2481 allowed.
2482 2482
2483 2483 At the end of the upgrade, the repository may not be readable while new
2484 2484 repository data is swapped in. This window will be as long as it takes to
2485 2485 rename some directories inside the ``.hg`` directory. On most machines, this
2486 2486 should complete almost instantaneously and the chances of a consumer being
2487 2487 unable to access the repository should be low.
2488 2488 """
2489 2489 return upgrade.upgraderepo(ui, repo, run=run, optimize=optimize)
2490 2490
2491 2491 @command('debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'),
2492 2492 inferrepo=True)
2493 2493 def debugwalk(ui, repo, *pats, **opts):
2494 2494 """show how files match on given patterns"""
2495 2495 opts = pycompat.byteskwargs(opts)
2496 2496 m = scmutil.match(repo[None], pats, opts)
2497 2497 ui.write(('matcher: %r\n' % m))
2498 2498 items = list(repo[None].walk(m))
2499 2499 if not items:
2500 2500 return
2501 2501 f = lambda fn: fn
2502 2502 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
2503 2503 f = lambda fn: util.normpath(fn)
2504 2504 fmt = 'f %%-%ds %%-%ds %%s' % (
2505 2505 max([len(abs) for abs in items]),
2506 2506 max([len(m.rel(abs)) for abs in items]))
2507 2507 for abs in items:
2508 2508 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2509 2509 ui.write("%s\n" % line.rstrip())
2510 2510
2511 2511 @command('debugwireargs',
2512 2512 [('', 'three', '', 'three'),
2513 2513 ('', 'four', '', 'four'),
2514 2514 ('', 'five', '', 'five'),
2515 2515 ] + cmdutil.remoteopts,
2516 2516 _('REPO [OPTIONS]... [ONE [TWO]]'),
2517 2517 norepo=True)
2518 2518 def debugwireargs(ui, repopath, *vals, **opts):
2519 2519 opts = pycompat.byteskwargs(opts)
2520 2520 repo = hg.peer(ui, opts, repopath)
2521 2521 for opt in cmdutil.remoteopts:
2522 2522 del opts[opt[1]]
2523 2523 args = {}
2524 2524 for k, v in opts.iteritems():
2525 2525 if v:
2526 2526 args[k] = v
2527 2527 args = pycompat.strkwargs(args)
2528 2528 # run twice to check that we don't mess up the stream for the next command
2529 2529 res1 = repo.debugwireargs(*vals, **args)
2530 2530 res2 = repo.debugwireargs(*vals, **args)
2531 2531 ui.write("%s\n" % res1)
2532 2532 if res1 != res2:
2533 2533 ui.warn("%s\n" % res2)
2534 2534
2535 2535 def _parsewirelangblocks(fh):
2536 2536 activeaction = None
2537 2537 blocklines = []
2538 2538
2539 2539 for line in fh:
2540 2540 line = line.rstrip()
2541 2541 if not line:
2542 2542 continue
2543 2543
2544 2544 if line.startswith(b'#'):
2545 2545 continue
2546 2546
2547 2547 if not line.startswith(' '):
2548 2548 # New block. Flush previous one.
2549 2549 if activeaction:
2550 2550 yield activeaction, blocklines
2551 2551
2552 2552 activeaction = line
2553 2553 blocklines = []
2554 2554 continue
2555 2555
2556 2556 # Else we start with an indent.
2557 2557
2558 2558 if not activeaction:
2559 2559 raise error.Abort(_('indented line outside of block'))
2560 2560
2561 2561 blocklines.append(line)
2562 2562
2563 2563 # Flush last block.
2564 2564 if activeaction:
2565 2565 yield activeaction, blocklines
2566 2566
2567 2567 @command('debugwireproto',
2568 2568 [
2569 2569 ('', 'localssh', False, _('start an SSH server for this repo')),
2570 2570 ('', 'peer', '', _('construct a specific version of the peer')),
2571 ('', 'noreadstderr', False, _('do not read from stderr of the remote')),
2571 2572 ] + cmdutil.remoteopts,
2572 2573 _('[REPO]'),
2573 2574 optionalrepo=True)
2574 2575 def debugwireproto(ui, repo, **opts):
2575 2576 """send wire protocol commands to a server
2576 2577
2577 2578 This command can be used to issue wire protocol commands to remote
2578 2579 peers and to debug the raw data being exchanged.
2579 2580
2580 2581 ``--localssh`` will start an SSH server against the current repository
2581 2582 and connect to that. By default, the connection will perform a handshake
2582 2583 and establish an appropriate peer instance.
2583 2584
2584 2585 ``--peer`` can be used to bypass the handshake protocol and construct a
2585 2586 peer instance using the specified class type. Valid values are ``raw``,
2586 2587 ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending raw data
2587 2588 payloads and don't support higher-level command actions.
2588 2589
2590 ``--noreadstderr`` can be used to disable automatic reading from stderr
2591 of the peer (for SSH connections only). Disabling automatic reading of
2592 stderr is useful for making output more deterministic.
2593
2589 2594 Commands are issued via a mini language which is specified via stdin.
2590 2595 The language consists of individual actions to perform. An action is
2591 2596 defined by a block. A block is defined as a line with no leading
2592 2597 space followed by 0 or more lines with leading space. Blocks are
2593 2598 effectively a high-level command with additional metadata.
2594 2599
2595 2600 Lines beginning with ``#`` are ignored.
2596 2601
2597 2602 The following sections denote available actions.
2598 2603
2599 2604 raw
2600 2605 ---
2601 2606
2602 2607 Send raw data to the server.
2603 2608
2604 2609 The block payload contains the raw data to send as one atomic send
2605 2610 operation. The data may not actually be delivered in a single system
2606 2611 call: it depends on the abilities of the transport being used.
2607 2612
2608 2613 Each line in the block is de-indented and concatenated. Then, that
2609 2614 value is evaluated as a Python b'' literal. This allows the use of
2610 2615 backslash escaping, etc.
2611 2616
2612 2617 raw+
2613 2618 ----
2614 2619
2615 2620 Behaves like ``raw`` except flushes output afterwards.
2616 2621
2617 2622 command <X>
2618 2623 -----------
2619 2624
2620 2625 Send a request to run a named command, whose name follows the ``command``
2621 2626 string.
2622 2627
2623 2628 Arguments to the command are defined as lines in this block. The format of
2624 2629 each line is ``<key> <value>``. e.g.::
2625 2630
2626 2631 command listkeys
2627 2632 namespace bookmarks
2628 2633
2629 2634 Values are interpreted as Python b'' literals. This allows encoding
2630 2635 special byte sequences via backslash escaping.
2631 2636
2637 The following arguments have special meaning:
2638
2639 ``PUSHFILE``
2640 When defined, the *push* mechanism of the peer will be used instead
2641 of the static request-response mechanism and the content of the
2642 file specified in the value of this argument will be sent as the
2643 command payload.
2644
2645 This can be used to submit a local bundle file to the remote.
2646
2632 2647 batchbegin
2633 2648 ----------
2634 2649
2635 2650 Instruct the peer to begin a batched send.
2636 2651
2637 2652 All ``command`` blocks are queued for execution until the next
2638 2653 ``batchsubmit`` block.
2639 2654
2640 2655 batchsubmit
2641 2656 -----------
2642 2657
2643 2658 Submit previously queued ``command`` blocks as a batch request.
2644 2659
2645 2660 This action MUST be paired with a ``batchbegin`` action.
2646 2661
2647 2662 close
2648 2663 -----
2649 2664
2650 2665 Close the connection to the server.
2651 2666
2652 2667 flush
2653 2668 -----
2654 2669
2655 2670 Flush data written to the server.
2656 2671
2657 2672 readavailable
2658 2673 -------------
2659 2674
2660 2675 Read all available data from the server.
2661 2676
2662 2677 If the connection to the server encompasses multiple pipes, we poll both
2663 2678 pipes and read available data.
2664 2679
2665 2680 readline
2666 2681 --------
2667 2682
2668 2683 Read a line of output from the server. If there are multiple output
2669 2684 pipes, reads only the main pipe.
2670 2685 """
2671 2686 opts = pycompat.byteskwargs(opts)
2672 2687
2673 2688 if opts['localssh'] and not repo:
2674 2689 raise error.Abort(_('--localssh requires a repository'))
2675 2690
2676 2691 if opts['peer'] and opts['peer'] not in ('raw', 'ssh1', 'ssh2'):
2677 2692 raise error.Abort(_('invalid value for --peer'),
2678 2693 hint=_('valid values are "raw", "ssh1", and "ssh2"'))
2679 2694
2680 2695 if ui.interactive():
2681 2696 ui.write(_('(waiting for commands on stdin)\n'))
2682 2697
2683 2698 blocks = list(_parsewirelangblocks(ui.fin))
2684 2699
2685 2700 proc = None
2686 2701
2687 2702 if opts['localssh']:
2688 2703 # We start the SSH server in its own process so there is process
2689 2704 # separation. This prevents a whole class of potential bugs around
2690 2705 # shared state from interfering with server operation.
2691 2706 args = util.hgcmd() + [
2692 2707 '-R', repo.root,
2693 2708 'debugserve', '--sshstdio',
2694 2709 ]
2695 2710 proc = subprocess.Popen(args, stdin=subprocess.PIPE,
2696 2711 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
2697 2712 bufsize=0)
2698 2713
2699 2714 stdin = proc.stdin
2700 2715 stdout = proc.stdout
2701 2716 stderr = proc.stderr
2702 2717
2703 2718 # We turn the pipes into observers so we can log I/O.
2704 2719 if ui.verbose or opts['peer'] == 'raw':
2705 2720 stdin = util.makeloggingfileobject(ui, proc.stdin, b'i',
2706 2721 logdata=True)
2707 2722 stdout = util.makeloggingfileobject(ui, proc.stdout, b'o',
2708 2723 logdata=True)
2709 2724 stderr = util.makeloggingfileobject(ui, proc.stderr, b'e',
2710 2725 logdata=True)
2711 2726
2712 2727 # --localssh also implies the peer connection settings.
2713 2728
2714 2729 url = 'ssh://localserver'
2730 autoreadstderr = not opts['noreadstderr']
2715 2731
2716 2732 if opts['peer'] == 'ssh1':
2717 2733 ui.write(_('creating ssh peer for wire protocol version 1\n'))
2718 2734 peer = sshpeer.sshv1peer(ui, url, proc, stdin, stdout, stderr,
2719 None)
2735 None, autoreadstderr=autoreadstderr)
2720 2736 elif opts['peer'] == 'ssh2':
2721 2737 ui.write(_('creating ssh peer for wire protocol version 2\n'))
2722 2738 peer = sshpeer.sshv2peer(ui, url, proc, stdin, stdout, stderr,
2723 None)
2739 None, autoreadstderr=autoreadstderr)
2724 2740 elif opts['peer'] == 'raw':
2725 2741 ui.write(_('using raw connection to peer\n'))
2726 2742 peer = None
2727 2743 else:
2728 2744 ui.write(_('creating ssh peer from handshake results\n'))
2729 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr)
2745 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr,
2746 autoreadstderr=autoreadstderr)
2730 2747
2731 2748 else:
2732 2749 raise error.Abort(_('only --localssh is currently supported'))
2733 2750
2734 2751 batchedcommands = None
2735 2752
2736 2753 # Now perform actions based on the parsed wire language instructions.
2737 2754 for action, lines in blocks:
2738 2755 if action in ('raw', 'raw+'):
2739 2756 # Concatenate the data together.
2740 2757 data = ''.join(l.lstrip() for l in lines)
2741 2758 data = util.unescapestr(data)
2742 2759 stdin.write(data)
2743 2760
2744 2761 if action == 'raw+':
2745 2762 stdin.flush()
2746 2763 elif action == 'flush':
2747 2764 stdin.flush()
2748 2765 elif action.startswith('command'):
2749 2766 if not peer:
2750 2767 raise error.Abort(_('cannot send commands unless peer instance '
2751 2768 'is available'))
2752 2769
2753 2770 command = action.split(' ', 1)[1]
2754 2771
2755 2772 args = {}
2756 2773 for line in lines:
2757 2774 # We need to allow empty values.
2758 2775 fields = line.lstrip().split(' ', 1)
2759 2776 if len(fields) == 1:
2760 2777 key = fields[0]
2761 2778 value = ''
2762 2779 else:
2763 2780 key, value = fields
2764 2781
2765 2782 args[key] = util.unescapestr(value)
2766 2783
2767 2784 if batchedcommands is not None:
2768 2785 batchedcommands.append((command, args))
2769 2786 continue
2770 2787
2771 2788 ui.status(_('sending %s command\n') % command)
2772 res = peer._call(command, **args)
2773 ui.status(_('response: %s\n') % util.escapedata(res))
2789
2790 if 'PUSHFILE' in args:
2791 with open(args['PUSHFILE'], r'rb') as fh:
2792 del args['PUSHFILE']
2793 res, output = peer._callpush(command, fh, **args)
2794 ui.status(_('result: %s\n') % util.escapedata(res))
2795 ui.status(_('remote output: %s\n') %
2796 util.escapedata(output))
2797 else:
2798 res = peer._call(command, **args)
2799 ui.status(_('response: %s\n') % util.escapedata(res))
2774 2800
2775 2801 elif action == 'batchbegin':
2776 2802 if batchedcommands is not None:
2777 2803 raise error.Abort(_('nested batchbegin not allowed'))
2778 2804
2779 2805 batchedcommands = []
2780 2806 elif action == 'batchsubmit':
2781 2807 # There is a batching API we could go through. But it would be
2782 2808 # difficult to normalize requests into function calls. It is easier
2783 2809 # to bypass this layer and normalize to commands + args.
2784 2810 ui.status(_('sending batch with %d sub-commands\n') %
2785 2811 len(batchedcommands))
2786 2812 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
2787 2813 ui.status(_('response #%d: %s\n') % (i, util.escapedata(chunk)))
2788 2814
2789 2815 batchedcommands = None
2790 2816 elif action == 'close':
2791 2817 peer.close()
2792 2818 elif action == 'readavailable':
2793 2819 fds = util.poll([stdout.fileno(), stderr.fileno()])
2794 2820
2795 2821 if stdout.fileno() in fds:
2796 2822 util.readpipe(stdout)
2797 2823 if stderr.fileno() in fds:
2798 2824 util.readpipe(stderr)
2799 2825 elif action == 'readline':
2800 2826 stdout.readline()
2801 2827 else:
2802 2828 raise error.Abort(_('unknown action: %s') % action)
2803 2829
2804 2830 if batchedcommands is not None:
2805 2831 raise error.Abort(_('unclosed "batchbegin" request'))
2806 2832
2807 2833 if peer:
2808 2834 peer.close()
2809 2835
2810 2836 if proc:
2811 2837 proc.kill()
@@ -1,395 +1,395 b''
1 1 Show all commands except debug commands
2 2 $ hg debugcomplete
3 3 add
4 4 addremove
5 5 annotate
6 6 archive
7 7 backout
8 8 bisect
9 9 bookmarks
10 10 branch
11 11 branches
12 12 bundle
13 13 cat
14 14 clone
15 15 commit
16 16 config
17 17 copy
18 18 diff
19 19 export
20 20 files
21 21 forget
22 22 graft
23 23 grep
24 24 heads
25 25 help
26 26 identify
27 27 import
28 28 incoming
29 29 init
30 30 locate
31 31 log
32 32 manifest
33 33 merge
34 34 outgoing
35 35 parents
36 36 paths
37 37 phase
38 38 pull
39 39 push
40 40 recover
41 41 remove
42 42 rename
43 43 resolve
44 44 revert
45 45 rollback
46 46 root
47 47 serve
48 48 status
49 49 summary
50 50 tag
51 51 tags
52 52 tip
53 53 unbundle
54 54 update
55 55 verify
56 56 version
57 57
58 58 Show all commands that start with "a"
59 59 $ hg debugcomplete a
60 60 add
61 61 addremove
62 62 annotate
63 63 archive
64 64
65 65 Do not show debug commands if there are other candidates
66 66 $ hg debugcomplete d
67 67 diff
68 68
69 69 Show debug commands if there are no other candidates
70 70 $ hg debugcomplete debug
71 71 debugancestor
72 72 debugapplystreamclonebundle
73 73 debugbuilddag
74 74 debugbundle
75 75 debugcapabilities
76 76 debugcheckstate
77 77 debugcolor
78 78 debugcommands
79 79 debugcomplete
80 80 debugconfig
81 81 debugcreatestreamclonebundle
82 82 debugdag
83 83 debugdata
84 84 debugdate
85 85 debugdeltachain
86 86 debugdirstate
87 87 debugdiscovery
88 88 debugdownload
89 89 debugextensions
90 90 debugfileset
91 91 debugformat
92 92 debugfsinfo
93 93 debuggetbundle
94 94 debugignore
95 95 debugindex
96 96 debugindexdot
97 97 debuginstall
98 98 debugknown
99 99 debuglabelcomplete
100 100 debuglocks
101 101 debugmergestate
102 102 debugnamecomplete
103 103 debugobsolete
104 104 debugpathcomplete
105 105 debugpeer
106 106 debugpickmergetool
107 107 debugpushkey
108 108 debugpvec
109 109 debugrebuilddirstate
110 110 debugrebuildfncache
111 111 debugrename
112 112 debugrevlog
113 113 debugrevspec
114 114 debugserve
115 115 debugsetparents
116 116 debugssl
117 117 debugsub
118 118 debugsuccessorssets
119 119 debugtemplate
120 120 debugupdatecaches
121 121 debugupgraderepo
122 122 debugwalk
123 123 debugwireargs
124 124 debugwireproto
125 125
126 126 Do not show the alias of a debug command if there are other candidates
127 127 (this should hide rawcommit)
128 128 $ hg debugcomplete r
129 129 recover
130 130 remove
131 131 rename
132 132 resolve
133 133 revert
134 134 rollback
135 135 root
136 136 Show the alias of a debug command if there are no other candidates
137 137 $ hg debugcomplete rawc
138 138
139 139
140 140 Show the global options
141 141 $ hg debugcomplete --options | sort
142 142 --color
143 143 --config
144 144 --cwd
145 145 --debug
146 146 --debugger
147 147 --encoding
148 148 --encodingmode
149 149 --help
150 150 --hidden
151 151 --noninteractive
152 152 --pager
153 153 --profile
154 154 --quiet
155 155 --repository
156 156 --time
157 157 --traceback
158 158 --verbose
159 159 --version
160 160 -R
161 161 -h
162 162 -q
163 163 -v
164 164 -y
165 165
166 166 Show the options for the "serve" command
167 167 $ hg debugcomplete --options serve | sort
168 168 --accesslog
169 169 --address
170 170 --certificate
171 171 --cmdserver
172 172 --color
173 173 --config
174 174 --cwd
175 175 --daemon
176 176 --daemon-postexec
177 177 --debug
178 178 --debugger
179 179 --encoding
180 180 --encodingmode
181 181 --errorlog
182 182 --help
183 183 --hidden
184 184 --ipv6
185 185 --name
186 186 --noninteractive
187 187 --pager
188 188 --pid-file
189 189 --port
190 190 --prefix
191 191 --profile
192 192 --quiet
193 193 --repository
194 194 --stdio
195 195 --style
196 196 --subrepos
197 197 --templates
198 198 --time
199 199 --traceback
200 200 --verbose
201 201 --version
202 202 --web-conf
203 203 -6
204 204 -A
205 205 -E
206 206 -R
207 207 -S
208 208 -a
209 209 -d
210 210 -h
211 211 -n
212 212 -p
213 213 -q
214 214 -t
215 215 -v
216 216 -y
217 217
218 218 Show an error if we use --options with an ambiguous abbreviation
219 219 $ hg debugcomplete --options s
220 220 hg: command 's' is ambiguous:
221 221 serve showconfig status summary
222 222 [255]
223 223
224 224 Show all commands + options
225 225 $ hg debugcommands
226 226 add: include, exclude, subrepos, dry-run
227 227 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude, template
228 228 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
229 229 commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos
230 230 diff: rev, change, text, git, binary, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, unified, stat, root, include, exclude, subrepos
231 231 export: output, switch-parent, rev, text, git, binary, nodates
232 232 forget: include, exclude
233 233 init: ssh, remotecmd, insecure
234 234 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
235 235 merge: force, rev, preview, abort, tool
236 236 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
237 237 push: force, rev, bookmark, branch, new-branch, pushvars, ssh, remotecmd, insecure
238 238 remove: after, force, subrepos, include, exclude
239 239 serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate, subrepos
240 240 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
241 241 summary: remote
242 242 update: clean, check, merge, date, rev, tool
243 243 addremove: similarity, subrepos, include, exclude, dry-run
244 244 archive: no-decode, prefix, rev, type, subrepos, include, exclude
245 245 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
246 246 bisect: reset, good, bad, skip, extend, command, noupdate
247 247 bookmarks: force, rev, delete, rename, inactive, template
248 248 branch: force, clean, rev
249 249 branches: active, closed, template
250 250 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
251 251 cat: output, rev, decode, include, exclude, template
252 252 config: untrusted, edit, local, global, template
253 253 copy: after, force, include, exclude, dry-run
254 254 debugancestor:
255 255 debugapplystreamclonebundle:
256 256 debugbuilddag: mergeable-file, overwritten-file, new-file
257 257 debugbundle: all, part-type, spec
258 258 debugcapabilities:
259 259 debugcheckstate:
260 260 debugcolor: style
261 261 debugcommands:
262 262 debugcomplete: options
263 263 debugcreatestreamclonebundle:
264 264 debugdag: tags, branches, dots, spaces
265 265 debugdata: changelog, manifest, dir
266 266 debugdate: extended
267 267 debugdeltachain: changelog, manifest, dir, template
268 268 debugdirstate: nodates, datesort
269 269 debugdiscovery: old, nonheads, rev, ssh, remotecmd, insecure
270 270 debugdownload: output
271 271 debugextensions: template
272 272 debugfileset: rev
273 273 debugformat: template
274 274 debugfsinfo:
275 275 debuggetbundle: head, common, type
276 276 debugignore:
277 277 debugindex: changelog, manifest, dir, format
278 278 debugindexdot: changelog, manifest, dir
279 279 debuginstall: template
280 280 debugknown:
281 281 debuglabelcomplete:
282 282 debuglocks: force-lock, force-wlock, set-lock, set-wlock
283 283 debugmergestate:
284 284 debugnamecomplete:
285 285 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
286 286 debugpathcomplete: full, normal, added, removed
287 287 debugpeer:
288 288 debugpickmergetool: rev, changedelete, include, exclude, tool
289 289 debugpushkey:
290 290 debugpvec:
291 291 debugrebuilddirstate: rev, minimal
292 292 debugrebuildfncache:
293 293 debugrename: rev
294 294 debugrevlog: changelog, manifest, dir, dump
295 295 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
296 296 debugserve: sshstdio, logiofd, logiofile
297 297 debugsetparents:
298 298 debugssl:
299 299 debugsub: rev
300 300 debugsuccessorssets: closest
301 301 debugtemplate: rev, define
302 302 debugupdatecaches:
303 303 debugupgraderepo: optimize, run
304 304 debugwalk: include, exclude
305 305 debugwireargs: three, four, five, ssh, remotecmd, insecure
306 debugwireproto: localssh, peer, ssh, remotecmd, insecure
306 debugwireproto: localssh, peer, noreadstderr, ssh, remotecmd, insecure
307 307 files: rev, print0, include, exclude, template, subrepos
308 308 graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run
309 309 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, template, include, exclude
310 310 heads: rev, topo, active, closed, style, template
311 311 help: extension, command, keyword, system
312 312 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
313 313 import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
314 314 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
315 315 locate: rev, print0, fullpath, include, exclude
316 316 manifest: rev, all, template
317 317 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
318 318 parents: rev, style, template
319 319 paths: template
320 320 phase: public, draft, secret, force, rev
321 321 recover:
322 322 rename: after, force, include, exclude, dry-run
323 323 resolve: all, list, mark, unmark, no-status, tool, include, exclude, template
324 324 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
325 325 rollback: dry-run, force
326 326 root:
327 327 tag: force, local, rev, remove, edit, message, date, user
328 328 tags: template
329 329 tip: patch, git, style, template
330 330 unbundle: update
331 331 verify:
332 332 version: template
333 333
334 334 $ hg init a
335 335 $ cd a
336 336 $ echo fee > fee
337 337 $ hg ci -q -Amfee
338 338 $ hg tag fee
339 339 $ mkdir fie
340 340 $ echo dead > fie/dead
341 341 $ echo live > fie/live
342 342 $ hg bookmark fo
343 343 $ hg branch -q fie
344 344 $ hg ci -q -Amfie
345 345 $ echo fo > fo
346 346 $ hg branch -qf default
347 347 $ hg ci -q -Amfo
348 348 $ echo Fum > Fum
349 349 $ hg ci -q -AmFum
350 350 $ hg bookmark Fum
351 351
352 352 Test debugpathcomplete
353 353
354 354 $ hg debugpathcomplete f
355 355 fee
356 356 fie
357 357 fo
358 358 $ hg debugpathcomplete -f f
359 359 fee
360 360 fie/dead
361 361 fie/live
362 362 fo
363 363
364 364 $ hg rm Fum
365 365 $ hg debugpathcomplete -r F
366 366 Fum
367 367
368 368 Test debugnamecomplete
369 369
370 370 $ hg debugnamecomplete
371 371 Fum
372 372 default
373 373 fee
374 374 fie
375 375 fo
376 376 tip
377 377 $ hg debugnamecomplete f
378 378 fee
379 379 fie
380 380 fo
381 381
382 382 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
383 383 used for completions in some shells.
384 384
385 385 $ hg debuglabelcomplete
386 386 Fum
387 387 default
388 388 fee
389 389 fie
390 390 fo
391 391 tip
392 392 $ hg debuglabelcomplete f
393 393 fee
394 394 fie
395 395 fo
General Comments 0
You need to be logged in to leave comments. Login now