##// END OF EJS Templates
debugcommands: use command executor for invoking commands...
Gregory Szorc -
r37670:fe8c6f9f default
parent child Browse files
Show More
@@ -1,3117 +1,3119
1 # debugcommands.py - command processing for debug* commands
1 # debugcommands.py - command processing for debug* commands
2 #
2 #
3 # Copyright 2005-2016 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2016 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import codecs
10 import codecs
11 import collections
11 import collections
12 import difflib
12 import difflib
13 import errno
13 import errno
14 import operator
14 import operator
15 import os
15 import os
16 import random
16 import random
17 import re
17 import re
18 import socket
18 import socket
19 import ssl
19 import ssl
20 import stat
20 import stat
21 import string
21 import string
22 import subprocess
22 import subprocess
23 import sys
23 import sys
24 import tempfile
24 import tempfile
25 import time
25 import time
26
26
27 from .i18n import _
27 from .i18n import _
28 from .node import (
28 from .node import (
29 bin,
29 bin,
30 hex,
30 hex,
31 nullhex,
31 nullhex,
32 nullid,
32 nullid,
33 nullrev,
33 nullrev,
34 short,
34 short,
35 )
35 )
36 from .thirdparty import (
36 from .thirdparty import (
37 cbor,
37 cbor,
38 )
38 )
39 from . import (
39 from . import (
40 bundle2,
40 bundle2,
41 changegroup,
41 changegroup,
42 cmdutil,
42 cmdutil,
43 color,
43 color,
44 context,
44 context,
45 dagparser,
45 dagparser,
46 dagutil,
46 dagutil,
47 encoding,
47 encoding,
48 error,
48 error,
49 exchange,
49 exchange,
50 extensions,
50 extensions,
51 filemerge,
51 filemerge,
52 fileset,
52 fileset,
53 formatter,
53 formatter,
54 hg,
54 hg,
55 httppeer,
55 httppeer,
56 localrepo,
56 localrepo,
57 lock as lockmod,
57 lock as lockmod,
58 logcmdutil,
58 logcmdutil,
59 merge as mergemod,
59 merge as mergemod,
60 obsolete,
60 obsolete,
61 obsutil,
61 obsutil,
62 phases,
62 phases,
63 policy,
63 policy,
64 pvec,
64 pvec,
65 pycompat,
65 pycompat,
66 registrar,
66 registrar,
67 repair,
67 repair,
68 revlog,
68 revlog,
69 revset,
69 revset,
70 revsetlang,
70 revsetlang,
71 scmutil,
71 scmutil,
72 setdiscovery,
72 setdiscovery,
73 simplemerge,
73 simplemerge,
74 smartset,
74 smartset,
75 sshpeer,
75 sshpeer,
76 sslutil,
76 sslutil,
77 streamclone,
77 streamclone,
78 templater,
78 templater,
79 treediscovery,
79 treediscovery,
80 upgrade,
80 upgrade,
81 url as urlmod,
81 url as urlmod,
82 util,
82 util,
83 vfs as vfsmod,
83 vfs as vfsmod,
84 wireprotoframing,
84 wireprotoframing,
85 wireprotoserver,
85 wireprotoserver,
86 )
86 )
87 from .utils import (
87 from .utils import (
88 dateutil,
88 dateutil,
89 procutil,
89 procutil,
90 stringutil,
90 stringutil,
91 )
91 )
92
92
93 release = lockmod.release
93 release = lockmod.release
94
94
95 command = registrar.command()
95 command = registrar.command()
96
96
97 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
97 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
98 def debugancestor(ui, repo, *args):
98 def debugancestor(ui, repo, *args):
99 """find the ancestor revision of two revisions in a given index"""
99 """find the ancestor revision of two revisions in a given index"""
100 if len(args) == 3:
100 if len(args) == 3:
101 index, rev1, rev2 = args
101 index, rev1, rev2 = args
102 r = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False), index)
102 r = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False), index)
103 lookup = r.lookup
103 lookup = r.lookup
104 elif len(args) == 2:
104 elif len(args) == 2:
105 if not repo:
105 if not repo:
106 raise error.Abort(_('there is no Mercurial repository here '
106 raise error.Abort(_('there is no Mercurial repository here '
107 '(.hg not found)'))
107 '(.hg not found)'))
108 rev1, rev2 = args
108 rev1, rev2 = args
109 r = repo.changelog
109 r = repo.changelog
110 lookup = repo.lookup
110 lookup = repo.lookup
111 else:
111 else:
112 raise error.Abort(_('either two or three arguments required'))
112 raise error.Abort(_('either two or three arguments required'))
113 a = r.ancestor(lookup(rev1), lookup(rev2))
113 a = r.ancestor(lookup(rev1), lookup(rev2))
114 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
114 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
115
115
116 @command('debugapplystreamclonebundle', [], 'FILE')
116 @command('debugapplystreamclonebundle', [], 'FILE')
117 def debugapplystreamclonebundle(ui, repo, fname):
117 def debugapplystreamclonebundle(ui, repo, fname):
118 """apply a stream clone bundle file"""
118 """apply a stream clone bundle file"""
119 f = hg.openpath(ui, fname)
119 f = hg.openpath(ui, fname)
120 gen = exchange.readbundle(ui, f, fname)
120 gen = exchange.readbundle(ui, f, fname)
121 gen.apply(repo)
121 gen.apply(repo)
122
122
123 @command('debugbuilddag',
123 @command('debugbuilddag',
124 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
124 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
125 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
125 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
126 ('n', 'new-file', None, _('add new file at each rev'))],
126 ('n', 'new-file', None, _('add new file at each rev'))],
127 _('[OPTION]... [TEXT]'))
127 _('[OPTION]... [TEXT]'))
128 def debugbuilddag(ui, repo, text=None,
128 def debugbuilddag(ui, repo, text=None,
129 mergeable_file=False,
129 mergeable_file=False,
130 overwritten_file=False,
130 overwritten_file=False,
131 new_file=False):
131 new_file=False):
132 """builds a repo with a given DAG from scratch in the current empty repo
132 """builds a repo with a given DAG from scratch in the current empty repo
133
133
134 The description of the DAG is read from stdin if not given on the
134 The description of the DAG is read from stdin if not given on the
135 command line.
135 command line.
136
136
137 Elements:
137 Elements:
138
138
139 - "+n" is a linear run of n nodes based on the current default parent
139 - "+n" is a linear run of n nodes based on the current default parent
140 - "." is a single node based on the current default parent
140 - "." is a single node based on the current default parent
141 - "$" resets the default parent to null (implied at the start);
141 - "$" resets the default parent to null (implied at the start);
142 otherwise the default parent is always the last node created
142 otherwise the default parent is always the last node created
143 - "<p" sets the default parent to the backref p
143 - "<p" sets the default parent to the backref p
144 - "*p" is a fork at parent p, which is a backref
144 - "*p" is a fork at parent p, which is a backref
145 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
145 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
146 - "/p2" is a merge of the preceding node and p2
146 - "/p2" is a merge of the preceding node and p2
147 - ":tag" defines a local tag for the preceding node
147 - ":tag" defines a local tag for the preceding node
148 - "@branch" sets the named branch for subsequent nodes
148 - "@branch" sets the named branch for subsequent nodes
149 - "#...\\n" is a comment up to the end of the line
149 - "#...\\n" is a comment up to the end of the line
150
150
151 Whitespace between the above elements is ignored.
151 Whitespace between the above elements is ignored.
152
152
153 A backref is either
153 A backref is either
154
154
155 - a number n, which references the node curr-n, where curr is the current
155 - a number n, which references the node curr-n, where curr is the current
156 node, or
156 node, or
157 - the name of a local tag you placed earlier using ":tag", or
157 - the name of a local tag you placed earlier using ":tag", or
158 - empty to denote the default parent.
158 - empty to denote the default parent.
159
159
160 All string valued-elements are either strictly alphanumeric, or must
160 All string valued-elements are either strictly alphanumeric, or must
161 be enclosed in double quotes ("..."), with "\\" as escape character.
161 be enclosed in double quotes ("..."), with "\\" as escape character.
162 """
162 """
163
163
164 if text is None:
164 if text is None:
165 ui.status(_("reading DAG from stdin\n"))
165 ui.status(_("reading DAG from stdin\n"))
166 text = ui.fin.read()
166 text = ui.fin.read()
167
167
168 cl = repo.changelog
168 cl = repo.changelog
169 if len(cl) > 0:
169 if len(cl) > 0:
170 raise error.Abort(_('repository is not empty'))
170 raise error.Abort(_('repository is not empty'))
171
171
172 # determine number of revs in DAG
172 # determine number of revs in DAG
173 total = 0
173 total = 0
174 for type, data in dagparser.parsedag(text):
174 for type, data in dagparser.parsedag(text):
175 if type == 'n':
175 if type == 'n':
176 total += 1
176 total += 1
177
177
178 if mergeable_file:
178 if mergeable_file:
179 linesperrev = 2
179 linesperrev = 2
180 # make a file with k lines per rev
180 # make a file with k lines per rev
181 initialmergedlines = ['%d' % i for i in xrange(0, total * linesperrev)]
181 initialmergedlines = ['%d' % i for i in xrange(0, total * linesperrev)]
182 initialmergedlines.append("")
182 initialmergedlines.append("")
183
183
184 tags = []
184 tags = []
185
185
186 wlock = lock = tr = None
186 wlock = lock = tr = None
187 try:
187 try:
188 wlock = repo.wlock()
188 wlock = repo.wlock()
189 lock = repo.lock()
189 lock = repo.lock()
190 tr = repo.transaction("builddag")
190 tr = repo.transaction("builddag")
191
191
192 at = -1
192 at = -1
193 atbranch = 'default'
193 atbranch = 'default'
194 nodeids = []
194 nodeids = []
195 id = 0
195 id = 0
196 ui.progress(_('building'), id, unit=_('revisions'), total=total)
196 ui.progress(_('building'), id, unit=_('revisions'), total=total)
197 for type, data in dagparser.parsedag(text):
197 for type, data in dagparser.parsedag(text):
198 if type == 'n':
198 if type == 'n':
199 ui.note(('node %s\n' % pycompat.bytestr(data)))
199 ui.note(('node %s\n' % pycompat.bytestr(data)))
200 id, ps = data
200 id, ps = data
201
201
202 files = []
202 files = []
203 filecontent = {}
203 filecontent = {}
204
204
205 p2 = None
205 p2 = None
206 if mergeable_file:
206 if mergeable_file:
207 fn = "mf"
207 fn = "mf"
208 p1 = repo[ps[0]]
208 p1 = repo[ps[0]]
209 if len(ps) > 1:
209 if len(ps) > 1:
210 p2 = repo[ps[1]]
210 p2 = repo[ps[1]]
211 pa = p1.ancestor(p2)
211 pa = p1.ancestor(p2)
212 base, local, other = [x[fn].data() for x in (pa, p1,
212 base, local, other = [x[fn].data() for x in (pa, p1,
213 p2)]
213 p2)]
214 m3 = simplemerge.Merge3Text(base, local, other)
214 m3 = simplemerge.Merge3Text(base, local, other)
215 ml = [l.strip() for l in m3.merge_lines()]
215 ml = [l.strip() for l in m3.merge_lines()]
216 ml.append("")
216 ml.append("")
217 elif at > 0:
217 elif at > 0:
218 ml = p1[fn].data().split("\n")
218 ml = p1[fn].data().split("\n")
219 else:
219 else:
220 ml = initialmergedlines
220 ml = initialmergedlines
221 ml[id * linesperrev] += " r%i" % id
221 ml[id * linesperrev] += " r%i" % id
222 mergedtext = "\n".join(ml)
222 mergedtext = "\n".join(ml)
223 files.append(fn)
223 files.append(fn)
224 filecontent[fn] = mergedtext
224 filecontent[fn] = mergedtext
225
225
226 if overwritten_file:
226 if overwritten_file:
227 fn = "of"
227 fn = "of"
228 files.append(fn)
228 files.append(fn)
229 filecontent[fn] = "r%i\n" % id
229 filecontent[fn] = "r%i\n" % id
230
230
231 if new_file:
231 if new_file:
232 fn = "nf%i" % id
232 fn = "nf%i" % id
233 files.append(fn)
233 files.append(fn)
234 filecontent[fn] = "r%i\n" % id
234 filecontent[fn] = "r%i\n" % id
235 if len(ps) > 1:
235 if len(ps) > 1:
236 if not p2:
236 if not p2:
237 p2 = repo[ps[1]]
237 p2 = repo[ps[1]]
238 for fn in p2:
238 for fn in p2:
239 if fn.startswith("nf"):
239 if fn.startswith("nf"):
240 files.append(fn)
240 files.append(fn)
241 filecontent[fn] = p2[fn].data()
241 filecontent[fn] = p2[fn].data()
242
242
243 def fctxfn(repo, cx, path):
243 def fctxfn(repo, cx, path):
244 if path in filecontent:
244 if path in filecontent:
245 return context.memfilectx(repo, cx, path,
245 return context.memfilectx(repo, cx, path,
246 filecontent[path])
246 filecontent[path])
247 return None
247 return None
248
248
249 if len(ps) == 0 or ps[0] < 0:
249 if len(ps) == 0 or ps[0] < 0:
250 pars = [None, None]
250 pars = [None, None]
251 elif len(ps) == 1:
251 elif len(ps) == 1:
252 pars = [nodeids[ps[0]], None]
252 pars = [nodeids[ps[0]], None]
253 else:
253 else:
254 pars = [nodeids[p] for p in ps]
254 pars = [nodeids[p] for p in ps]
255 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
255 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
256 date=(id, 0),
256 date=(id, 0),
257 user="debugbuilddag",
257 user="debugbuilddag",
258 extra={'branch': atbranch})
258 extra={'branch': atbranch})
259 nodeid = repo.commitctx(cx)
259 nodeid = repo.commitctx(cx)
260 nodeids.append(nodeid)
260 nodeids.append(nodeid)
261 at = id
261 at = id
262 elif type == 'l':
262 elif type == 'l':
263 id, name = data
263 id, name = data
264 ui.note(('tag %s\n' % name))
264 ui.note(('tag %s\n' % name))
265 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
265 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
266 elif type == 'a':
266 elif type == 'a':
267 ui.note(('branch %s\n' % data))
267 ui.note(('branch %s\n' % data))
268 atbranch = data
268 atbranch = data
269 ui.progress(_('building'), id, unit=_('revisions'), total=total)
269 ui.progress(_('building'), id, unit=_('revisions'), total=total)
270 tr.close()
270 tr.close()
271
271
272 if tags:
272 if tags:
273 repo.vfs.write("localtags", "".join(tags))
273 repo.vfs.write("localtags", "".join(tags))
274 finally:
274 finally:
275 ui.progress(_('building'), None)
275 ui.progress(_('building'), None)
276 release(tr, lock, wlock)
276 release(tr, lock, wlock)
277
277
278 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
278 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
279 indent_string = ' ' * indent
279 indent_string = ' ' * indent
280 if all:
280 if all:
281 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
281 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
282 % indent_string)
282 % indent_string)
283
283
284 def showchunks(named):
284 def showchunks(named):
285 ui.write("\n%s%s\n" % (indent_string, named))
285 ui.write("\n%s%s\n" % (indent_string, named))
286 for deltadata in gen.deltaiter():
286 for deltadata in gen.deltaiter():
287 node, p1, p2, cs, deltabase, delta, flags = deltadata
287 node, p1, p2, cs, deltabase, delta, flags = deltadata
288 ui.write("%s%s %s %s %s %s %d\n" %
288 ui.write("%s%s %s %s %s %s %d\n" %
289 (indent_string, hex(node), hex(p1), hex(p2),
289 (indent_string, hex(node), hex(p1), hex(p2),
290 hex(cs), hex(deltabase), len(delta)))
290 hex(cs), hex(deltabase), len(delta)))
291
291
292 chunkdata = gen.changelogheader()
292 chunkdata = gen.changelogheader()
293 showchunks("changelog")
293 showchunks("changelog")
294 chunkdata = gen.manifestheader()
294 chunkdata = gen.manifestheader()
295 showchunks("manifest")
295 showchunks("manifest")
296 for chunkdata in iter(gen.filelogheader, {}):
296 for chunkdata in iter(gen.filelogheader, {}):
297 fname = chunkdata['filename']
297 fname = chunkdata['filename']
298 showchunks(fname)
298 showchunks(fname)
299 else:
299 else:
300 if isinstance(gen, bundle2.unbundle20):
300 if isinstance(gen, bundle2.unbundle20):
301 raise error.Abort(_('use debugbundle2 for this file'))
301 raise error.Abort(_('use debugbundle2 for this file'))
302 chunkdata = gen.changelogheader()
302 chunkdata = gen.changelogheader()
303 for deltadata in gen.deltaiter():
303 for deltadata in gen.deltaiter():
304 node, p1, p2, cs, deltabase, delta, flags = deltadata
304 node, p1, p2, cs, deltabase, delta, flags = deltadata
305 ui.write("%s%s\n" % (indent_string, hex(node)))
305 ui.write("%s%s\n" % (indent_string, hex(node)))
306
306
307 def _debugobsmarkers(ui, part, indent=0, **opts):
307 def _debugobsmarkers(ui, part, indent=0, **opts):
308 """display version and markers contained in 'data'"""
308 """display version and markers contained in 'data'"""
309 opts = pycompat.byteskwargs(opts)
309 opts = pycompat.byteskwargs(opts)
310 data = part.read()
310 data = part.read()
311 indent_string = ' ' * indent
311 indent_string = ' ' * indent
312 try:
312 try:
313 version, markers = obsolete._readmarkers(data)
313 version, markers = obsolete._readmarkers(data)
314 except error.UnknownVersion as exc:
314 except error.UnknownVersion as exc:
315 msg = "%sunsupported version: %s (%d bytes)\n"
315 msg = "%sunsupported version: %s (%d bytes)\n"
316 msg %= indent_string, exc.version, len(data)
316 msg %= indent_string, exc.version, len(data)
317 ui.write(msg)
317 ui.write(msg)
318 else:
318 else:
319 msg = "%sversion: %d (%d bytes)\n"
319 msg = "%sversion: %d (%d bytes)\n"
320 msg %= indent_string, version, len(data)
320 msg %= indent_string, version, len(data)
321 ui.write(msg)
321 ui.write(msg)
322 fm = ui.formatter('debugobsolete', opts)
322 fm = ui.formatter('debugobsolete', opts)
323 for rawmarker in sorted(markers):
323 for rawmarker in sorted(markers):
324 m = obsutil.marker(None, rawmarker)
324 m = obsutil.marker(None, rawmarker)
325 fm.startitem()
325 fm.startitem()
326 fm.plain(indent_string)
326 fm.plain(indent_string)
327 cmdutil.showmarker(fm, m)
327 cmdutil.showmarker(fm, m)
328 fm.end()
328 fm.end()
329
329
330 def _debugphaseheads(ui, data, indent=0):
330 def _debugphaseheads(ui, data, indent=0):
331 """display version and markers contained in 'data'"""
331 """display version and markers contained in 'data'"""
332 indent_string = ' ' * indent
332 indent_string = ' ' * indent
333 headsbyphase = phases.binarydecode(data)
333 headsbyphase = phases.binarydecode(data)
334 for phase in phases.allphases:
334 for phase in phases.allphases:
335 for head in headsbyphase[phase]:
335 for head in headsbyphase[phase]:
336 ui.write(indent_string)
336 ui.write(indent_string)
337 ui.write('%s %s\n' % (hex(head), phases.phasenames[phase]))
337 ui.write('%s %s\n' % (hex(head), phases.phasenames[phase]))
338
338
339 def _quasirepr(thing):
339 def _quasirepr(thing):
340 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
340 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
341 return '{%s}' % (
341 return '{%s}' % (
342 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing)))
342 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing)))
343 return pycompat.bytestr(repr(thing))
343 return pycompat.bytestr(repr(thing))
344
344
345 def _debugbundle2(ui, gen, all=None, **opts):
345 def _debugbundle2(ui, gen, all=None, **opts):
346 """lists the contents of a bundle2"""
346 """lists the contents of a bundle2"""
347 if not isinstance(gen, bundle2.unbundle20):
347 if not isinstance(gen, bundle2.unbundle20):
348 raise error.Abort(_('not a bundle2 file'))
348 raise error.Abort(_('not a bundle2 file'))
349 ui.write(('Stream params: %s\n' % _quasirepr(gen.params)))
349 ui.write(('Stream params: %s\n' % _quasirepr(gen.params)))
350 parttypes = opts.get(r'part_type', [])
350 parttypes = opts.get(r'part_type', [])
351 for part in gen.iterparts():
351 for part in gen.iterparts():
352 if parttypes and part.type not in parttypes:
352 if parttypes and part.type not in parttypes:
353 continue
353 continue
354 ui.write('%s -- %s\n' % (part.type, _quasirepr(part.params)))
354 ui.write('%s -- %s\n' % (part.type, _quasirepr(part.params)))
355 if part.type == 'changegroup':
355 if part.type == 'changegroup':
356 version = part.params.get('version', '01')
356 version = part.params.get('version', '01')
357 cg = changegroup.getunbundler(version, part, 'UN')
357 cg = changegroup.getunbundler(version, part, 'UN')
358 if not ui.quiet:
358 if not ui.quiet:
359 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
359 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
360 if part.type == 'obsmarkers':
360 if part.type == 'obsmarkers':
361 if not ui.quiet:
361 if not ui.quiet:
362 _debugobsmarkers(ui, part, indent=4, **opts)
362 _debugobsmarkers(ui, part, indent=4, **opts)
363 if part.type == 'phase-heads':
363 if part.type == 'phase-heads':
364 if not ui.quiet:
364 if not ui.quiet:
365 _debugphaseheads(ui, part, indent=4)
365 _debugphaseheads(ui, part, indent=4)
366
366
367 @command('debugbundle',
367 @command('debugbundle',
368 [('a', 'all', None, _('show all details')),
368 [('a', 'all', None, _('show all details')),
369 ('', 'part-type', [], _('show only the named part type')),
369 ('', 'part-type', [], _('show only the named part type')),
370 ('', 'spec', None, _('print the bundlespec of the bundle'))],
370 ('', 'spec', None, _('print the bundlespec of the bundle'))],
371 _('FILE'),
371 _('FILE'),
372 norepo=True)
372 norepo=True)
373 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
373 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
374 """lists the contents of a bundle"""
374 """lists the contents of a bundle"""
375 with hg.openpath(ui, bundlepath) as f:
375 with hg.openpath(ui, bundlepath) as f:
376 if spec:
376 if spec:
377 spec = exchange.getbundlespec(ui, f)
377 spec = exchange.getbundlespec(ui, f)
378 ui.write('%s\n' % spec)
378 ui.write('%s\n' % spec)
379 return
379 return
380
380
381 gen = exchange.readbundle(ui, f, bundlepath)
381 gen = exchange.readbundle(ui, f, bundlepath)
382 if isinstance(gen, bundle2.unbundle20):
382 if isinstance(gen, bundle2.unbundle20):
383 return _debugbundle2(ui, gen, all=all, **opts)
383 return _debugbundle2(ui, gen, all=all, **opts)
384 _debugchangegroup(ui, gen, all=all, **opts)
384 _debugchangegroup(ui, gen, all=all, **opts)
385
385
386 @command('debugcapabilities',
386 @command('debugcapabilities',
387 [], _('PATH'),
387 [], _('PATH'),
388 norepo=True)
388 norepo=True)
389 def debugcapabilities(ui, path, **opts):
389 def debugcapabilities(ui, path, **opts):
390 """lists the capabilities of a remote peer"""
390 """lists the capabilities of a remote peer"""
391 opts = pycompat.byteskwargs(opts)
391 opts = pycompat.byteskwargs(opts)
392 peer = hg.peer(ui, opts, path)
392 peer = hg.peer(ui, opts, path)
393 caps = peer.capabilities()
393 caps = peer.capabilities()
394 ui.write(('Main capabilities:\n'))
394 ui.write(('Main capabilities:\n'))
395 for c in sorted(caps):
395 for c in sorted(caps):
396 ui.write((' %s\n') % c)
396 ui.write((' %s\n') % c)
397 b2caps = bundle2.bundle2caps(peer)
397 b2caps = bundle2.bundle2caps(peer)
398 if b2caps:
398 if b2caps:
399 ui.write(('Bundle2 capabilities:\n'))
399 ui.write(('Bundle2 capabilities:\n'))
400 for key, values in sorted(b2caps.iteritems()):
400 for key, values in sorted(b2caps.iteritems()):
401 ui.write((' %s\n') % key)
401 ui.write((' %s\n') % key)
402 for v in values:
402 for v in values:
403 ui.write((' %s\n') % v)
403 ui.write((' %s\n') % v)
404
404
405 @command('debugcheckstate', [], '')
405 @command('debugcheckstate', [], '')
406 def debugcheckstate(ui, repo):
406 def debugcheckstate(ui, repo):
407 """validate the correctness of the current dirstate"""
407 """validate the correctness of the current dirstate"""
408 parent1, parent2 = repo.dirstate.parents()
408 parent1, parent2 = repo.dirstate.parents()
409 m1 = repo[parent1].manifest()
409 m1 = repo[parent1].manifest()
410 m2 = repo[parent2].manifest()
410 m2 = repo[parent2].manifest()
411 errors = 0
411 errors = 0
412 for f in repo.dirstate:
412 for f in repo.dirstate:
413 state = repo.dirstate[f]
413 state = repo.dirstate[f]
414 if state in "nr" and f not in m1:
414 if state in "nr" and f not in m1:
415 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
415 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
416 errors += 1
416 errors += 1
417 if state in "a" and f in m1:
417 if state in "a" and f in m1:
418 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
418 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
419 errors += 1
419 errors += 1
420 if state in "m" and f not in m1 and f not in m2:
420 if state in "m" and f not in m1 and f not in m2:
421 ui.warn(_("%s in state %s, but not in either manifest\n") %
421 ui.warn(_("%s in state %s, but not in either manifest\n") %
422 (f, state))
422 (f, state))
423 errors += 1
423 errors += 1
424 for f in m1:
424 for f in m1:
425 state = repo.dirstate[f]
425 state = repo.dirstate[f]
426 if state not in "nrm":
426 if state not in "nrm":
427 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
427 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
428 errors += 1
428 errors += 1
429 if errors:
429 if errors:
430 error = _(".hg/dirstate inconsistent with current parent's manifest")
430 error = _(".hg/dirstate inconsistent with current parent's manifest")
431 raise error.Abort(error)
431 raise error.Abort(error)
432
432
433 @command('debugcolor',
433 @command('debugcolor',
434 [('', 'style', None, _('show all configured styles'))],
434 [('', 'style', None, _('show all configured styles'))],
435 'hg debugcolor')
435 'hg debugcolor')
436 def debugcolor(ui, repo, **opts):
436 def debugcolor(ui, repo, **opts):
437 """show available color, effects or style"""
437 """show available color, effects or style"""
438 ui.write(('color mode: %s\n') % ui._colormode)
438 ui.write(('color mode: %s\n') % ui._colormode)
439 if opts.get(r'style'):
439 if opts.get(r'style'):
440 return _debugdisplaystyle(ui)
440 return _debugdisplaystyle(ui)
441 else:
441 else:
442 return _debugdisplaycolor(ui)
442 return _debugdisplaycolor(ui)
443
443
444 def _debugdisplaycolor(ui):
444 def _debugdisplaycolor(ui):
445 ui = ui.copy()
445 ui = ui.copy()
446 ui._styles.clear()
446 ui._styles.clear()
447 for effect in color._activeeffects(ui).keys():
447 for effect in color._activeeffects(ui).keys():
448 ui._styles[effect] = effect
448 ui._styles[effect] = effect
449 if ui._terminfoparams:
449 if ui._terminfoparams:
450 for k, v in ui.configitems('color'):
450 for k, v in ui.configitems('color'):
451 if k.startswith('color.'):
451 if k.startswith('color.'):
452 ui._styles[k] = k[6:]
452 ui._styles[k] = k[6:]
453 elif k.startswith('terminfo.'):
453 elif k.startswith('terminfo.'):
454 ui._styles[k] = k[9:]
454 ui._styles[k] = k[9:]
455 ui.write(_('available colors:\n'))
455 ui.write(_('available colors:\n'))
456 # sort label with a '_' after the other to group '_background' entry.
456 # sort label with a '_' after the other to group '_background' entry.
457 items = sorted(ui._styles.items(),
457 items = sorted(ui._styles.items(),
458 key=lambda i: ('_' in i[0], i[0], i[1]))
458 key=lambda i: ('_' in i[0], i[0], i[1]))
459 for colorname, label in items:
459 for colorname, label in items:
460 ui.write(('%s\n') % colorname, label=label)
460 ui.write(('%s\n') % colorname, label=label)
461
461
462 def _debugdisplaystyle(ui):
462 def _debugdisplaystyle(ui):
463 ui.write(_('available style:\n'))
463 ui.write(_('available style:\n'))
464 width = max(len(s) for s in ui._styles)
464 width = max(len(s) for s in ui._styles)
465 for label, effects in sorted(ui._styles.items()):
465 for label, effects in sorted(ui._styles.items()):
466 ui.write('%s' % label, label=label)
466 ui.write('%s' % label, label=label)
467 if effects:
467 if effects:
468 # 50
468 # 50
469 ui.write(': ')
469 ui.write(': ')
470 ui.write(' ' * (max(0, width - len(label))))
470 ui.write(' ' * (max(0, width - len(label))))
471 ui.write(', '.join(ui.label(e, e) for e in effects.split()))
471 ui.write(', '.join(ui.label(e, e) for e in effects.split()))
472 ui.write('\n')
472 ui.write('\n')
473
473
474 @command('debugcreatestreamclonebundle', [], 'FILE')
474 @command('debugcreatestreamclonebundle', [], 'FILE')
475 def debugcreatestreamclonebundle(ui, repo, fname):
475 def debugcreatestreamclonebundle(ui, repo, fname):
476 """create a stream clone bundle file
476 """create a stream clone bundle file
477
477
478 Stream bundles are special bundles that are essentially archives of
478 Stream bundles are special bundles that are essentially archives of
479 revlog files. They are commonly used for cloning very quickly.
479 revlog files. They are commonly used for cloning very quickly.
480 """
480 """
481 # TODO we may want to turn this into an abort when this functionality
481 # TODO we may want to turn this into an abort when this functionality
482 # is moved into `hg bundle`.
482 # is moved into `hg bundle`.
483 if phases.hassecret(repo):
483 if phases.hassecret(repo):
484 ui.warn(_('(warning: stream clone bundle will contain secret '
484 ui.warn(_('(warning: stream clone bundle will contain secret '
485 'revisions)\n'))
485 'revisions)\n'))
486
486
487 requirements, gen = streamclone.generatebundlev1(repo)
487 requirements, gen = streamclone.generatebundlev1(repo)
488 changegroup.writechunks(ui, gen, fname)
488 changegroup.writechunks(ui, gen, fname)
489
489
490 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
490 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
491
491
492 @command('debugdag',
492 @command('debugdag',
493 [('t', 'tags', None, _('use tags as labels')),
493 [('t', 'tags', None, _('use tags as labels')),
494 ('b', 'branches', None, _('annotate with branch names')),
494 ('b', 'branches', None, _('annotate with branch names')),
495 ('', 'dots', None, _('use dots for runs')),
495 ('', 'dots', None, _('use dots for runs')),
496 ('s', 'spaces', None, _('separate elements by spaces'))],
496 ('s', 'spaces', None, _('separate elements by spaces'))],
497 _('[OPTION]... [FILE [REV]...]'),
497 _('[OPTION]... [FILE [REV]...]'),
498 optionalrepo=True)
498 optionalrepo=True)
499 def debugdag(ui, repo, file_=None, *revs, **opts):
499 def debugdag(ui, repo, file_=None, *revs, **opts):
500 """format the changelog or an index DAG as a concise textual description
500 """format the changelog or an index DAG as a concise textual description
501
501
502 If you pass a revlog index, the revlog's DAG is emitted. If you list
502 If you pass a revlog index, the revlog's DAG is emitted. If you list
503 revision numbers, they get labeled in the output as rN.
503 revision numbers, they get labeled in the output as rN.
504
504
505 Otherwise, the changelog DAG of the current repo is emitted.
505 Otherwise, the changelog DAG of the current repo is emitted.
506 """
506 """
507 spaces = opts.get(r'spaces')
507 spaces = opts.get(r'spaces')
508 dots = opts.get(r'dots')
508 dots = opts.get(r'dots')
509 if file_:
509 if file_:
510 rlog = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False),
510 rlog = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False),
511 file_)
511 file_)
512 revs = set((int(r) for r in revs))
512 revs = set((int(r) for r in revs))
513 def events():
513 def events():
514 for r in rlog:
514 for r in rlog:
515 yield 'n', (r, list(p for p in rlog.parentrevs(r)
515 yield 'n', (r, list(p for p in rlog.parentrevs(r)
516 if p != -1))
516 if p != -1))
517 if r in revs:
517 if r in revs:
518 yield 'l', (r, "r%i" % r)
518 yield 'l', (r, "r%i" % r)
519 elif repo:
519 elif repo:
520 cl = repo.changelog
520 cl = repo.changelog
521 tags = opts.get(r'tags')
521 tags = opts.get(r'tags')
522 branches = opts.get(r'branches')
522 branches = opts.get(r'branches')
523 if tags:
523 if tags:
524 labels = {}
524 labels = {}
525 for l, n in repo.tags().items():
525 for l, n in repo.tags().items():
526 labels.setdefault(cl.rev(n), []).append(l)
526 labels.setdefault(cl.rev(n), []).append(l)
527 def events():
527 def events():
528 b = "default"
528 b = "default"
529 for r in cl:
529 for r in cl:
530 if branches:
530 if branches:
531 newb = cl.read(cl.node(r))[5]['branch']
531 newb = cl.read(cl.node(r))[5]['branch']
532 if newb != b:
532 if newb != b:
533 yield 'a', newb
533 yield 'a', newb
534 b = newb
534 b = newb
535 yield 'n', (r, list(p for p in cl.parentrevs(r)
535 yield 'n', (r, list(p for p in cl.parentrevs(r)
536 if p != -1))
536 if p != -1))
537 if tags:
537 if tags:
538 ls = labels.get(r)
538 ls = labels.get(r)
539 if ls:
539 if ls:
540 for l in ls:
540 for l in ls:
541 yield 'l', (r, l)
541 yield 'l', (r, l)
542 else:
542 else:
543 raise error.Abort(_('need repo for changelog dag'))
543 raise error.Abort(_('need repo for changelog dag'))
544
544
545 for line in dagparser.dagtextlines(events(),
545 for line in dagparser.dagtextlines(events(),
546 addspaces=spaces,
546 addspaces=spaces,
547 wraplabels=True,
547 wraplabels=True,
548 wrapannotations=True,
548 wrapannotations=True,
549 wrapnonlinear=dots,
549 wrapnonlinear=dots,
550 usedots=dots,
550 usedots=dots,
551 maxlinewidth=70):
551 maxlinewidth=70):
552 ui.write(line)
552 ui.write(line)
553 ui.write("\n")
553 ui.write("\n")
554
554
555 @command('debugdata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
555 @command('debugdata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
556 def debugdata(ui, repo, file_, rev=None, **opts):
556 def debugdata(ui, repo, file_, rev=None, **opts):
557 """dump the contents of a data file revision"""
557 """dump the contents of a data file revision"""
558 opts = pycompat.byteskwargs(opts)
558 opts = pycompat.byteskwargs(opts)
559 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
559 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
560 if rev is not None:
560 if rev is not None:
561 raise error.CommandError('debugdata', _('invalid arguments'))
561 raise error.CommandError('debugdata', _('invalid arguments'))
562 file_, rev = None, file_
562 file_, rev = None, file_
563 elif rev is None:
563 elif rev is None:
564 raise error.CommandError('debugdata', _('invalid arguments'))
564 raise error.CommandError('debugdata', _('invalid arguments'))
565 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
565 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
566 try:
566 try:
567 ui.write(r.revision(r.lookup(rev), raw=True))
567 ui.write(r.revision(r.lookup(rev), raw=True))
568 except KeyError:
568 except KeyError:
569 raise error.Abort(_('invalid revision identifier %s') % rev)
569 raise error.Abort(_('invalid revision identifier %s') % rev)
570
570
571 @command('debugdate',
571 @command('debugdate',
572 [('e', 'extended', None, _('try extended date formats'))],
572 [('e', 'extended', None, _('try extended date formats'))],
573 _('[-e] DATE [RANGE]'),
573 _('[-e] DATE [RANGE]'),
574 norepo=True, optionalrepo=True)
574 norepo=True, optionalrepo=True)
575 def debugdate(ui, date, range=None, **opts):
575 def debugdate(ui, date, range=None, **opts):
576 """parse and display a date"""
576 """parse and display a date"""
577 if opts[r"extended"]:
577 if opts[r"extended"]:
578 d = dateutil.parsedate(date, util.extendeddateformats)
578 d = dateutil.parsedate(date, util.extendeddateformats)
579 else:
579 else:
580 d = dateutil.parsedate(date)
580 d = dateutil.parsedate(date)
581 ui.write(("internal: %d %d\n") % d)
581 ui.write(("internal: %d %d\n") % d)
582 ui.write(("standard: %s\n") % dateutil.datestr(d))
582 ui.write(("standard: %s\n") % dateutil.datestr(d))
583 if range:
583 if range:
584 m = dateutil.matchdate(range)
584 m = dateutil.matchdate(range)
585 ui.write(("match: %s\n") % m(d[0]))
585 ui.write(("match: %s\n") % m(d[0]))
586
586
587 @command('debugdeltachain',
587 @command('debugdeltachain',
588 cmdutil.debugrevlogopts + cmdutil.formatteropts,
588 cmdutil.debugrevlogopts + cmdutil.formatteropts,
589 _('-c|-m|FILE'),
589 _('-c|-m|FILE'),
590 optionalrepo=True)
590 optionalrepo=True)
591 def debugdeltachain(ui, repo, file_=None, **opts):
591 def debugdeltachain(ui, repo, file_=None, **opts):
592 """dump information about delta chains in a revlog
592 """dump information about delta chains in a revlog
593
593
594 Output can be templatized. Available template keywords are:
594 Output can be templatized. Available template keywords are:
595
595
596 :``rev``: revision number
596 :``rev``: revision number
597 :``chainid``: delta chain identifier (numbered by unique base)
597 :``chainid``: delta chain identifier (numbered by unique base)
598 :``chainlen``: delta chain length to this revision
598 :``chainlen``: delta chain length to this revision
599 :``prevrev``: previous revision in delta chain
599 :``prevrev``: previous revision in delta chain
600 :``deltatype``: role of delta / how it was computed
600 :``deltatype``: role of delta / how it was computed
601 :``compsize``: compressed size of revision
601 :``compsize``: compressed size of revision
602 :``uncompsize``: uncompressed size of revision
602 :``uncompsize``: uncompressed size of revision
603 :``chainsize``: total size of compressed revisions in chain
603 :``chainsize``: total size of compressed revisions in chain
604 :``chainratio``: total chain size divided by uncompressed revision size
604 :``chainratio``: total chain size divided by uncompressed revision size
605 (new delta chains typically start at ratio 2.00)
605 (new delta chains typically start at ratio 2.00)
606 :``lindist``: linear distance from base revision in delta chain to end
606 :``lindist``: linear distance from base revision in delta chain to end
607 of this revision
607 of this revision
608 :``extradist``: total size of revisions not part of this delta chain from
608 :``extradist``: total size of revisions not part of this delta chain from
609 base of delta chain to end of this revision; a measurement
609 base of delta chain to end of this revision; a measurement
610 of how much extra data we need to read/seek across to read
610 of how much extra data we need to read/seek across to read
611 the delta chain for this revision
611 the delta chain for this revision
612 :``extraratio``: extradist divided by chainsize; another representation of
612 :``extraratio``: extradist divided by chainsize; another representation of
613 how much unrelated data is needed to load this delta chain
613 how much unrelated data is needed to load this delta chain
614
614
615 If the repository is configured to use the sparse read, additional keywords
615 If the repository is configured to use the sparse read, additional keywords
616 are available:
616 are available:
617
617
618 :``readsize``: total size of data read from the disk for a revision
618 :``readsize``: total size of data read from the disk for a revision
619 (sum of the sizes of all the blocks)
619 (sum of the sizes of all the blocks)
620 :``largestblock``: size of the largest block of data read from the disk
620 :``largestblock``: size of the largest block of data read from the disk
621 :``readdensity``: density of useful bytes in the data read from the disk
621 :``readdensity``: density of useful bytes in the data read from the disk
622 :``srchunks``: in how many data hunks the whole revision would be read
622 :``srchunks``: in how many data hunks the whole revision would be read
623
623
624 The sparse read can be enabled with experimental.sparse-read = True
624 The sparse read can be enabled with experimental.sparse-read = True
625 """
625 """
626 opts = pycompat.byteskwargs(opts)
626 opts = pycompat.byteskwargs(opts)
627 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
627 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
628 index = r.index
628 index = r.index
629 generaldelta = r.version & revlog.FLAG_GENERALDELTA
629 generaldelta = r.version & revlog.FLAG_GENERALDELTA
630 withsparseread = getattr(r, '_withsparseread', False)
630 withsparseread = getattr(r, '_withsparseread', False)
631
631
632 def revinfo(rev):
632 def revinfo(rev):
633 e = index[rev]
633 e = index[rev]
634 compsize = e[1]
634 compsize = e[1]
635 uncompsize = e[2]
635 uncompsize = e[2]
636 chainsize = 0
636 chainsize = 0
637
637
638 if generaldelta:
638 if generaldelta:
639 if e[3] == e[5]:
639 if e[3] == e[5]:
640 deltatype = 'p1'
640 deltatype = 'p1'
641 elif e[3] == e[6]:
641 elif e[3] == e[6]:
642 deltatype = 'p2'
642 deltatype = 'p2'
643 elif e[3] == rev - 1:
643 elif e[3] == rev - 1:
644 deltatype = 'prev'
644 deltatype = 'prev'
645 elif e[3] == rev:
645 elif e[3] == rev:
646 deltatype = 'base'
646 deltatype = 'base'
647 else:
647 else:
648 deltatype = 'other'
648 deltatype = 'other'
649 else:
649 else:
650 if e[3] == rev:
650 if e[3] == rev:
651 deltatype = 'base'
651 deltatype = 'base'
652 else:
652 else:
653 deltatype = 'prev'
653 deltatype = 'prev'
654
654
655 chain = r._deltachain(rev)[0]
655 chain = r._deltachain(rev)[0]
656 for iterrev in chain:
656 for iterrev in chain:
657 e = index[iterrev]
657 e = index[iterrev]
658 chainsize += e[1]
658 chainsize += e[1]
659
659
660 return compsize, uncompsize, deltatype, chain, chainsize
660 return compsize, uncompsize, deltatype, chain, chainsize
661
661
662 fm = ui.formatter('debugdeltachain', opts)
662 fm = ui.formatter('debugdeltachain', opts)
663
663
664 fm.plain(' rev chain# chainlen prev delta '
664 fm.plain(' rev chain# chainlen prev delta '
665 'size rawsize chainsize ratio lindist extradist '
665 'size rawsize chainsize ratio lindist extradist '
666 'extraratio')
666 'extraratio')
667 if withsparseread:
667 if withsparseread:
668 fm.plain(' readsize largestblk rddensity srchunks')
668 fm.plain(' readsize largestblk rddensity srchunks')
669 fm.plain('\n')
669 fm.plain('\n')
670
670
671 chainbases = {}
671 chainbases = {}
672 for rev in r:
672 for rev in r:
673 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
673 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
674 chainbase = chain[0]
674 chainbase = chain[0]
675 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
675 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
676 start = r.start
676 start = r.start
677 length = r.length
677 length = r.length
678 basestart = start(chainbase)
678 basestart = start(chainbase)
679 revstart = start(rev)
679 revstart = start(rev)
680 lineardist = revstart + comp - basestart
680 lineardist = revstart + comp - basestart
681 extradist = lineardist - chainsize
681 extradist = lineardist - chainsize
682 try:
682 try:
683 prevrev = chain[-2]
683 prevrev = chain[-2]
684 except IndexError:
684 except IndexError:
685 prevrev = -1
685 prevrev = -1
686
686
687 chainratio = float(chainsize) / float(uncomp)
687 chainratio = float(chainsize) / float(uncomp)
688 extraratio = float(extradist) / float(chainsize)
688 extraratio = float(extradist) / float(chainsize)
689
689
690 fm.startitem()
690 fm.startitem()
691 fm.write('rev chainid chainlen prevrev deltatype compsize '
691 fm.write('rev chainid chainlen prevrev deltatype compsize '
692 'uncompsize chainsize chainratio lindist extradist '
692 'uncompsize chainsize chainratio lindist extradist '
693 'extraratio',
693 'extraratio',
694 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
694 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
695 rev, chainid, len(chain), prevrev, deltatype, comp,
695 rev, chainid, len(chain), prevrev, deltatype, comp,
696 uncomp, chainsize, chainratio, lineardist, extradist,
696 uncomp, chainsize, chainratio, lineardist, extradist,
697 extraratio,
697 extraratio,
698 rev=rev, chainid=chainid, chainlen=len(chain),
698 rev=rev, chainid=chainid, chainlen=len(chain),
699 prevrev=prevrev, deltatype=deltatype, compsize=comp,
699 prevrev=prevrev, deltatype=deltatype, compsize=comp,
700 uncompsize=uncomp, chainsize=chainsize,
700 uncompsize=uncomp, chainsize=chainsize,
701 chainratio=chainratio, lindist=lineardist,
701 chainratio=chainratio, lindist=lineardist,
702 extradist=extradist, extraratio=extraratio)
702 extradist=extradist, extraratio=extraratio)
703 if withsparseread:
703 if withsparseread:
704 readsize = 0
704 readsize = 0
705 largestblock = 0
705 largestblock = 0
706 srchunks = 0
706 srchunks = 0
707
707
708 for revschunk in revlog._slicechunk(r, chain):
708 for revschunk in revlog._slicechunk(r, chain):
709 srchunks += 1
709 srchunks += 1
710 blkend = start(revschunk[-1]) + length(revschunk[-1])
710 blkend = start(revschunk[-1]) + length(revschunk[-1])
711 blksize = blkend - start(revschunk[0])
711 blksize = blkend - start(revschunk[0])
712
712
713 readsize += blksize
713 readsize += blksize
714 if largestblock < blksize:
714 if largestblock < blksize:
715 largestblock = blksize
715 largestblock = blksize
716
716
717 readdensity = float(chainsize) / float(readsize)
717 readdensity = float(chainsize) / float(readsize)
718
718
719 fm.write('readsize largestblock readdensity srchunks',
719 fm.write('readsize largestblock readdensity srchunks',
720 ' %10d %10d %9.5f %8d',
720 ' %10d %10d %9.5f %8d',
721 readsize, largestblock, readdensity, srchunks,
721 readsize, largestblock, readdensity, srchunks,
722 readsize=readsize, largestblock=largestblock,
722 readsize=readsize, largestblock=largestblock,
723 readdensity=readdensity, srchunks=srchunks)
723 readdensity=readdensity, srchunks=srchunks)
724
724
725 fm.plain('\n')
725 fm.plain('\n')
726
726
727 fm.end()
727 fm.end()
728
728
729 @command('debugdirstate|debugstate',
729 @command('debugdirstate|debugstate',
730 [('', 'nodates', None, _('do not display the saved mtime')),
730 [('', 'nodates', None, _('do not display the saved mtime')),
731 ('', 'datesort', None, _('sort by saved mtime'))],
731 ('', 'datesort', None, _('sort by saved mtime'))],
732 _('[OPTION]...'))
732 _('[OPTION]...'))
733 def debugstate(ui, repo, **opts):
733 def debugstate(ui, repo, **opts):
734 """show the contents of the current dirstate"""
734 """show the contents of the current dirstate"""
735
735
736 nodates = opts.get(r'nodates')
736 nodates = opts.get(r'nodates')
737 datesort = opts.get(r'datesort')
737 datesort = opts.get(r'datesort')
738
738
739 timestr = ""
739 timestr = ""
740 if datesort:
740 if datesort:
741 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
741 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
742 else:
742 else:
743 keyfunc = None # sort by filename
743 keyfunc = None # sort by filename
744 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
744 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
745 if ent[3] == -1:
745 if ent[3] == -1:
746 timestr = 'unset '
746 timestr = 'unset '
747 elif nodates:
747 elif nodates:
748 timestr = 'set '
748 timestr = 'set '
749 else:
749 else:
750 timestr = time.strftime(r"%Y-%m-%d %H:%M:%S ",
750 timestr = time.strftime(r"%Y-%m-%d %H:%M:%S ",
751 time.localtime(ent[3]))
751 time.localtime(ent[3]))
752 timestr = encoding.strtolocal(timestr)
752 timestr = encoding.strtolocal(timestr)
753 if ent[1] & 0o20000:
753 if ent[1] & 0o20000:
754 mode = 'lnk'
754 mode = 'lnk'
755 else:
755 else:
756 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
756 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
757 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
757 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
758 for f in repo.dirstate.copies():
758 for f in repo.dirstate.copies():
759 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
759 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
760
760
761 @command('debugdiscovery',
761 @command('debugdiscovery',
762 [('', 'old', None, _('use old-style discovery')),
762 [('', 'old', None, _('use old-style discovery')),
763 ('', 'nonheads', None,
763 ('', 'nonheads', None,
764 _('use old-style discovery with non-heads included')),
764 _('use old-style discovery with non-heads included')),
765 ('', 'rev', [], 'restrict discovery to this set of revs'),
765 ('', 'rev', [], 'restrict discovery to this set of revs'),
766 ] + cmdutil.remoteopts,
766 ] + cmdutil.remoteopts,
767 _('[--rev REV] [OTHER]'))
767 _('[--rev REV] [OTHER]'))
768 def debugdiscovery(ui, repo, remoteurl="default", **opts):
768 def debugdiscovery(ui, repo, remoteurl="default", **opts):
769 """runs the changeset discovery protocol in isolation"""
769 """runs the changeset discovery protocol in isolation"""
770 opts = pycompat.byteskwargs(opts)
770 opts = pycompat.byteskwargs(opts)
771 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
771 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
772 remote = hg.peer(repo, opts, remoteurl)
772 remote = hg.peer(repo, opts, remoteurl)
773 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
773 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
774
774
775 # make sure tests are repeatable
775 # make sure tests are repeatable
776 random.seed(12323)
776 random.seed(12323)
777
777
778 def doit(pushedrevs, remoteheads, remote=remote):
778 def doit(pushedrevs, remoteheads, remote=remote):
779 if opts.get('old'):
779 if opts.get('old'):
780 if not util.safehasattr(remote, 'branches'):
780 if not util.safehasattr(remote, 'branches'):
781 # enable in-client legacy support
781 # enable in-client legacy support
782 remote = localrepo.locallegacypeer(remote.local())
782 remote = localrepo.locallegacypeer(remote.local())
783 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
783 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
784 force=True)
784 force=True)
785 common = set(common)
785 common = set(common)
786 if not opts.get('nonheads'):
786 if not opts.get('nonheads'):
787 ui.write(("unpruned common: %s\n") %
787 ui.write(("unpruned common: %s\n") %
788 " ".join(sorted(short(n) for n in common)))
788 " ".join(sorted(short(n) for n in common)))
789 dag = dagutil.revlogdag(repo.changelog)
789 dag = dagutil.revlogdag(repo.changelog)
790 all = dag.ancestorset(dag.internalizeall(common))
790 all = dag.ancestorset(dag.internalizeall(common))
791 common = dag.externalizeall(dag.headsetofconnecteds(all))
791 common = dag.externalizeall(dag.headsetofconnecteds(all))
792 else:
792 else:
793 nodes = None
793 nodes = None
794 if pushedrevs:
794 if pushedrevs:
795 revs = scmutil.revrange(repo, pushedrevs)
795 revs = scmutil.revrange(repo, pushedrevs)
796 nodes = [repo[r].node() for r in revs]
796 nodes = [repo[r].node() for r in revs]
797 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote,
797 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote,
798 ancestorsof=nodes)
798 ancestorsof=nodes)
799 common = set(common)
799 common = set(common)
800 rheads = set(hds)
800 rheads = set(hds)
801 lheads = set(repo.heads())
801 lheads = set(repo.heads())
802 ui.write(("common heads: %s\n") %
802 ui.write(("common heads: %s\n") %
803 " ".join(sorted(short(n) for n in common)))
803 " ".join(sorted(short(n) for n in common)))
804 if lheads <= common:
804 if lheads <= common:
805 ui.write(("local is subset\n"))
805 ui.write(("local is subset\n"))
806 elif rheads <= common:
806 elif rheads <= common:
807 ui.write(("remote is subset\n"))
807 ui.write(("remote is subset\n"))
808
808
809 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
809 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
810 localrevs = opts['rev']
810 localrevs = opts['rev']
811 doit(localrevs, remoterevs)
811 doit(localrevs, remoterevs)
812
812
813 _chunksize = 4 << 10
813 _chunksize = 4 << 10
814
814
815 @command('debugdownload',
815 @command('debugdownload',
816 [
816 [
817 ('o', 'output', '', _('path')),
817 ('o', 'output', '', _('path')),
818 ],
818 ],
819 optionalrepo=True)
819 optionalrepo=True)
820 def debugdownload(ui, repo, url, output=None, **opts):
820 def debugdownload(ui, repo, url, output=None, **opts):
821 """download a resource using Mercurial logic and config
821 """download a resource using Mercurial logic and config
822 """
822 """
823 fh = urlmod.open(ui, url, output)
823 fh = urlmod.open(ui, url, output)
824
824
825 dest = ui
825 dest = ui
826 if output:
826 if output:
827 dest = open(output, "wb", _chunksize)
827 dest = open(output, "wb", _chunksize)
828 try:
828 try:
829 data = fh.read(_chunksize)
829 data = fh.read(_chunksize)
830 while data:
830 while data:
831 dest.write(data)
831 dest.write(data)
832 data = fh.read(_chunksize)
832 data = fh.read(_chunksize)
833 finally:
833 finally:
834 if output:
834 if output:
835 dest.close()
835 dest.close()
836
836
837 @command('debugextensions', cmdutil.formatteropts, [], norepo=True)
837 @command('debugextensions', cmdutil.formatteropts, [], norepo=True)
838 def debugextensions(ui, **opts):
838 def debugextensions(ui, **opts):
839 '''show information about active extensions'''
839 '''show information about active extensions'''
840 opts = pycompat.byteskwargs(opts)
840 opts = pycompat.byteskwargs(opts)
841 exts = extensions.extensions(ui)
841 exts = extensions.extensions(ui)
842 hgver = util.version()
842 hgver = util.version()
843 fm = ui.formatter('debugextensions', opts)
843 fm = ui.formatter('debugextensions', opts)
844 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
844 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
845 isinternal = extensions.ismoduleinternal(extmod)
845 isinternal = extensions.ismoduleinternal(extmod)
846 extsource = pycompat.fsencode(extmod.__file__)
846 extsource = pycompat.fsencode(extmod.__file__)
847 if isinternal:
847 if isinternal:
848 exttestedwith = [] # never expose magic string to users
848 exttestedwith = [] # never expose magic string to users
849 else:
849 else:
850 exttestedwith = getattr(extmod, 'testedwith', '').split()
850 exttestedwith = getattr(extmod, 'testedwith', '').split()
851 extbuglink = getattr(extmod, 'buglink', None)
851 extbuglink = getattr(extmod, 'buglink', None)
852
852
853 fm.startitem()
853 fm.startitem()
854
854
855 if ui.quiet or ui.verbose:
855 if ui.quiet or ui.verbose:
856 fm.write('name', '%s\n', extname)
856 fm.write('name', '%s\n', extname)
857 else:
857 else:
858 fm.write('name', '%s', extname)
858 fm.write('name', '%s', extname)
859 if isinternal or hgver in exttestedwith:
859 if isinternal or hgver in exttestedwith:
860 fm.plain('\n')
860 fm.plain('\n')
861 elif not exttestedwith:
861 elif not exttestedwith:
862 fm.plain(_(' (untested!)\n'))
862 fm.plain(_(' (untested!)\n'))
863 else:
863 else:
864 lasttestedversion = exttestedwith[-1]
864 lasttestedversion = exttestedwith[-1]
865 fm.plain(' (%s!)\n' % lasttestedversion)
865 fm.plain(' (%s!)\n' % lasttestedversion)
866
866
867 fm.condwrite(ui.verbose and extsource, 'source',
867 fm.condwrite(ui.verbose and extsource, 'source',
868 _(' location: %s\n'), extsource or "")
868 _(' location: %s\n'), extsource or "")
869
869
870 if ui.verbose:
870 if ui.verbose:
871 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
871 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
872 fm.data(bundled=isinternal)
872 fm.data(bundled=isinternal)
873
873
874 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
874 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
875 _(' tested with: %s\n'),
875 _(' tested with: %s\n'),
876 fm.formatlist(exttestedwith, name='ver'))
876 fm.formatlist(exttestedwith, name='ver'))
877
877
878 fm.condwrite(ui.verbose and extbuglink, 'buglink',
878 fm.condwrite(ui.verbose and extbuglink, 'buglink',
879 _(' bug reporting: %s\n'), extbuglink or "")
879 _(' bug reporting: %s\n'), extbuglink or "")
880
880
881 fm.end()
881 fm.end()
882
882
883 @command('debugfileset',
883 @command('debugfileset',
884 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
884 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
885 _('[-r REV] FILESPEC'))
885 _('[-r REV] FILESPEC'))
886 def debugfileset(ui, repo, expr, **opts):
886 def debugfileset(ui, repo, expr, **opts):
887 '''parse and apply a fileset specification'''
887 '''parse and apply a fileset specification'''
888 ctx = scmutil.revsingle(repo, opts.get(r'rev'), None)
888 ctx = scmutil.revsingle(repo, opts.get(r'rev'), None)
889 if ui.verbose:
889 if ui.verbose:
890 tree = fileset.parse(expr)
890 tree = fileset.parse(expr)
891 ui.note(fileset.prettyformat(tree), "\n")
891 ui.note(fileset.prettyformat(tree), "\n")
892
892
893 for f in ctx.getfileset(expr):
893 for f in ctx.getfileset(expr):
894 ui.write("%s\n" % f)
894 ui.write("%s\n" % f)
895
895
896 @command('debugformat',
896 @command('debugformat',
897 [] + cmdutil.formatteropts,
897 [] + cmdutil.formatteropts,
898 _(''))
898 _(''))
899 def debugformat(ui, repo, **opts):
899 def debugformat(ui, repo, **opts):
900 """display format information about the current repository
900 """display format information about the current repository
901
901
902 Use --verbose to get extra information about current config value and
902 Use --verbose to get extra information about current config value and
903 Mercurial default."""
903 Mercurial default."""
904 opts = pycompat.byteskwargs(opts)
904 opts = pycompat.byteskwargs(opts)
905 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
905 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
906 maxvariantlength = max(len('format-variant'), maxvariantlength)
906 maxvariantlength = max(len('format-variant'), maxvariantlength)
907
907
908 def makeformatname(name):
908 def makeformatname(name):
909 return '%s:' + (' ' * (maxvariantlength - len(name)))
909 return '%s:' + (' ' * (maxvariantlength - len(name)))
910
910
911 fm = ui.formatter('debugformat', opts)
911 fm = ui.formatter('debugformat', opts)
912 if fm.isplain():
912 if fm.isplain():
913 def formatvalue(value):
913 def formatvalue(value):
914 if util.safehasattr(value, 'startswith'):
914 if util.safehasattr(value, 'startswith'):
915 return value
915 return value
916 if value:
916 if value:
917 return 'yes'
917 return 'yes'
918 else:
918 else:
919 return 'no'
919 return 'no'
920 else:
920 else:
921 formatvalue = pycompat.identity
921 formatvalue = pycompat.identity
922
922
923 fm.plain('format-variant')
923 fm.plain('format-variant')
924 fm.plain(' ' * (maxvariantlength - len('format-variant')))
924 fm.plain(' ' * (maxvariantlength - len('format-variant')))
925 fm.plain(' repo')
925 fm.plain(' repo')
926 if ui.verbose:
926 if ui.verbose:
927 fm.plain(' config default')
927 fm.plain(' config default')
928 fm.plain('\n')
928 fm.plain('\n')
929 for fv in upgrade.allformatvariant:
929 for fv in upgrade.allformatvariant:
930 fm.startitem()
930 fm.startitem()
931 repovalue = fv.fromrepo(repo)
931 repovalue = fv.fromrepo(repo)
932 configvalue = fv.fromconfig(repo)
932 configvalue = fv.fromconfig(repo)
933
933
934 if repovalue != configvalue:
934 if repovalue != configvalue:
935 namelabel = 'formatvariant.name.mismatchconfig'
935 namelabel = 'formatvariant.name.mismatchconfig'
936 repolabel = 'formatvariant.repo.mismatchconfig'
936 repolabel = 'formatvariant.repo.mismatchconfig'
937 elif repovalue != fv.default:
937 elif repovalue != fv.default:
938 namelabel = 'formatvariant.name.mismatchdefault'
938 namelabel = 'formatvariant.name.mismatchdefault'
939 repolabel = 'formatvariant.repo.mismatchdefault'
939 repolabel = 'formatvariant.repo.mismatchdefault'
940 else:
940 else:
941 namelabel = 'formatvariant.name.uptodate'
941 namelabel = 'formatvariant.name.uptodate'
942 repolabel = 'formatvariant.repo.uptodate'
942 repolabel = 'formatvariant.repo.uptodate'
943
943
944 fm.write('name', makeformatname(fv.name), fv.name,
944 fm.write('name', makeformatname(fv.name), fv.name,
945 label=namelabel)
945 label=namelabel)
946 fm.write('repo', ' %3s', formatvalue(repovalue),
946 fm.write('repo', ' %3s', formatvalue(repovalue),
947 label=repolabel)
947 label=repolabel)
948 if fv.default != configvalue:
948 if fv.default != configvalue:
949 configlabel = 'formatvariant.config.special'
949 configlabel = 'formatvariant.config.special'
950 else:
950 else:
951 configlabel = 'formatvariant.config.default'
951 configlabel = 'formatvariant.config.default'
952 fm.condwrite(ui.verbose, 'config', ' %6s', formatvalue(configvalue),
952 fm.condwrite(ui.verbose, 'config', ' %6s', formatvalue(configvalue),
953 label=configlabel)
953 label=configlabel)
954 fm.condwrite(ui.verbose, 'default', ' %7s', formatvalue(fv.default),
954 fm.condwrite(ui.verbose, 'default', ' %7s', formatvalue(fv.default),
955 label='formatvariant.default')
955 label='formatvariant.default')
956 fm.plain('\n')
956 fm.plain('\n')
957 fm.end()
957 fm.end()
958
958
959 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
959 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
960 def debugfsinfo(ui, path="."):
960 def debugfsinfo(ui, path="."):
961 """show information detected about current filesystem"""
961 """show information detected about current filesystem"""
962 ui.write(('path: %s\n') % path)
962 ui.write(('path: %s\n') % path)
963 ui.write(('mounted on: %s\n') % (util.getfsmountpoint(path) or '(unknown)'))
963 ui.write(('mounted on: %s\n') % (util.getfsmountpoint(path) or '(unknown)'))
964 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
964 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
965 ui.write(('fstype: %s\n') % (util.getfstype(path) or '(unknown)'))
965 ui.write(('fstype: %s\n') % (util.getfstype(path) or '(unknown)'))
966 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
966 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
967 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
967 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
968 casesensitive = '(unknown)'
968 casesensitive = '(unknown)'
969 try:
969 try:
970 with tempfile.NamedTemporaryFile(prefix='.debugfsinfo', dir=path) as f:
970 with tempfile.NamedTemporaryFile(prefix='.debugfsinfo', dir=path) as f:
971 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
971 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
972 except OSError:
972 except OSError:
973 pass
973 pass
974 ui.write(('case-sensitive: %s\n') % casesensitive)
974 ui.write(('case-sensitive: %s\n') % casesensitive)
975
975
976 @command('debuggetbundle',
976 @command('debuggetbundle',
977 [('H', 'head', [], _('id of head node'), _('ID')),
977 [('H', 'head', [], _('id of head node'), _('ID')),
978 ('C', 'common', [], _('id of common node'), _('ID')),
978 ('C', 'common', [], _('id of common node'), _('ID')),
979 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
979 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
980 _('REPO FILE [-H|-C ID]...'),
980 _('REPO FILE [-H|-C ID]...'),
981 norepo=True)
981 norepo=True)
982 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
982 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
983 """retrieves a bundle from a repo
983 """retrieves a bundle from a repo
984
984
985 Every ID must be a full-length hex node id string. Saves the bundle to the
985 Every ID must be a full-length hex node id string. Saves the bundle to the
986 given file.
986 given file.
987 """
987 """
988 opts = pycompat.byteskwargs(opts)
988 opts = pycompat.byteskwargs(opts)
989 repo = hg.peer(ui, opts, repopath)
989 repo = hg.peer(ui, opts, repopath)
990 if not repo.capable('getbundle'):
990 if not repo.capable('getbundle'):
991 raise error.Abort("getbundle() not supported by target repository")
991 raise error.Abort("getbundle() not supported by target repository")
992 args = {}
992 args = {}
993 if common:
993 if common:
994 args[r'common'] = [bin(s) for s in common]
994 args[r'common'] = [bin(s) for s in common]
995 if head:
995 if head:
996 args[r'heads'] = [bin(s) for s in head]
996 args[r'heads'] = [bin(s) for s in head]
997 # TODO: get desired bundlecaps from command line.
997 # TODO: get desired bundlecaps from command line.
998 args[r'bundlecaps'] = None
998 args[r'bundlecaps'] = None
999 bundle = repo.getbundle('debug', **args)
999 bundle = repo.getbundle('debug', **args)
1000
1000
1001 bundletype = opts.get('type', 'bzip2').lower()
1001 bundletype = opts.get('type', 'bzip2').lower()
1002 btypes = {'none': 'HG10UN',
1002 btypes = {'none': 'HG10UN',
1003 'bzip2': 'HG10BZ',
1003 'bzip2': 'HG10BZ',
1004 'gzip': 'HG10GZ',
1004 'gzip': 'HG10GZ',
1005 'bundle2': 'HG20'}
1005 'bundle2': 'HG20'}
1006 bundletype = btypes.get(bundletype)
1006 bundletype = btypes.get(bundletype)
1007 if bundletype not in bundle2.bundletypes:
1007 if bundletype not in bundle2.bundletypes:
1008 raise error.Abort(_('unknown bundle type specified with --type'))
1008 raise error.Abort(_('unknown bundle type specified with --type'))
1009 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1009 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1010
1010
1011 @command('debugignore', [], '[FILE]')
1011 @command('debugignore', [], '[FILE]')
1012 def debugignore(ui, repo, *files, **opts):
1012 def debugignore(ui, repo, *files, **opts):
1013 """display the combined ignore pattern and information about ignored files
1013 """display the combined ignore pattern and information about ignored files
1014
1014
1015 With no argument display the combined ignore pattern.
1015 With no argument display the combined ignore pattern.
1016
1016
1017 Given space separated file names, shows if the given file is ignored and
1017 Given space separated file names, shows if the given file is ignored and
1018 if so, show the ignore rule (file and line number) that matched it.
1018 if so, show the ignore rule (file and line number) that matched it.
1019 """
1019 """
1020 ignore = repo.dirstate._ignore
1020 ignore = repo.dirstate._ignore
1021 if not files:
1021 if not files:
1022 # Show all the patterns
1022 # Show all the patterns
1023 ui.write("%s\n" % pycompat.byterepr(ignore))
1023 ui.write("%s\n" % pycompat.byterepr(ignore))
1024 else:
1024 else:
1025 m = scmutil.match(repo[None], pats=files)
1025 m = scmutil.match(repo[None], pats=files)
1026 for f in m.files():
1026 for f in m.files():
1027 nf = util.normpath(f)
1027 nf = util.normpath(f)
1028 ignored = None
1028 ignored = None
1029 ignoredata = None
1029 ignoredata = None
1030 if nf != '.':
1030 if nf != '.':
1031 if ignore(nf):
1031 if ignore(nf):
1032 ignored = nf
1032 ignored = nf
1033 ignoredata = repo.dirstate._ignorefileandline(nf)
1033 ignoredata = repo.dirstate._ignorefileandline(nf)
1034 else:
1034 else:
1035 for p in util.finddirs(nf):
1035 for p in util.finddirs(nf):
1036 if ignore(p):
1036 if ignore(p):
1037 ignored = p
1037 ignored = p
1038 ignoredata = repo.dirstate._ignorefileandline(p)
1038 ignoredata = repo.dirstate._ignorefileandline(p)
1039 break
1039 break
1040 if ignored:
1040 if ignored:
1041 if ignored == nf:
1041 if ignored == nf:
1042 ui.write(_("%s is ignored\n") % m.uipath(f))
1042 ui.write(_("%s is ignored\n") % m.uipath(f))
1043 else:
1043 else:
1044 ui.write(_("%s is ignored because of "
1044 ui.write(_("%s is ignored because of "
1045 "containing folder %s\n")
1045 "containing folder %s\n")
1046 % (m.uipath(f), ignored))
1046 % (m.uipath(f), ignored))
1047 ignorefile, lineno, line = ignoredata
1047 ignorefile, lineno, line = ignoredata
1048 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
1048 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
1049 % (ignorefile, lineno, line))
1049 % (ignorefile, lineno, line))
1050 else:
1050 else:
1051 ui.write(_("%s is not ignored\n") % m.uipath(f))
1051 ui.write(_("%s is not ignored\n") % m.uipath(f))
1052
1052
1053 @command('debugindex', cmdutil.debugrevlogopts +
1053 @command('debugindex', cmdutil.debugrevlogopts +
1054 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1054 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1055 _('[-f FORMAT] -c|-m|FILE'),
1055 _('[-f FORMAT] -c|-m|FILE'),
1056 optionalrepo=True)
1056 optionalrepo=True)
1057 def debugindex(ui, repo, file_=None, **opts):
1057 def debugindex(ui, repo, file_=None, **opts):
1058 """dump the contents of an index file"""
1058 """dump the contents of an index file"""
1059 opts = pycompat.byteskwargs(opts)
1059 opts = pycompat.byteskwargs(opts)
1060 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1060 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1061 format = opts.get('format', 0)
1061 format = opts.get('format', 0)
1062 if format not in (0, 1):
1062 if format not in (0, 1):
1063 raise error.Abort(_("unknown format %d") % format)
1063 raise error.Abort(_("unknown format %d") % format)
1064
1064
1065 if ui.debugflag:
1065 if ui.debugflag:
1066 shortfn = hex
1066 shortfn = hex
1067 else:
1067 else:
1068 shortfn = short
1068 shortfn = short
1069
1069
1070 # There might not be anything in r, so have a sane default
1070 # There might not be anything in r, so have a sane default
1071 idlen = 12
1071 idlen = 12
1072 for i in r:
1072 for i in r:
1073 idlen = len(shortfn(r.node(i)))
1073 idlen = len(shortfn(r.node(i)))
1074 break
1074 break
1075
1075
1076 if format == 0:
1076 if format == 0:
1077 if ui.verbose:
1077 if ui.verbose:
1078 ui.write((" rev offset length linkrev"
1078 ui.write((" rev offset length linkrev"
1079 " %s %s p2\n") % ("nodeid".ljust(idlen),
1079 " %s %s p2\n") % ("nodeid".ljust(idlen),
1080 "p1".ljust(idlen)))
1080 "p1".ljust(idlen)))
1081 else:
1081 else:
1082 ui.write((" rev linkrev %s %s p2\n") % (
1082 ui.write((" rev linkrev %s %s p2\n") % (
1083 "nodeid".ljust(idlen), "p1".ljust(idlen)))
1083 "nodeid".ljust(idlen), "p1".ljust(idlen)))
1084 elif format == 1:
1084 elif format == 1:
1085 if ui.verbose:
1085 if ui.verbose:
1086 ui.write((" rev flag offset length size link p1"
1086 ui.write((" rev flag offset length size link p1"
1087 " p2 %s\n") % "nodeid".rjust(idlen))
1087 " p2 %s\n") % "nodeid".rjust(idlen))
1088 else:
1088 else:
1089 ui.write((" rev flag size link p1 p2 %s\n") %
1089 ui.write((" rev flag size link p1 p2 %s\n") %
1090 "nodeid".rjust(idlen))
1090 "nodeid".rjust(idlen))
1091
1091
1092 for i in r:
1092 for i in r:
1093 node = r.node(i)
1093 node = r.node(i)
1094 if format == 0:
1094 if format == 0:
1095 try:
1095 try:
1096 pp = r.parents(node)
1096 pp = r.parents(node)
1097 except Exception:
1097 except Exception:
1098 pp = [nullid, nullid]
1098 pp = [nullid, nullid]
1099 if ui.verbose:
1099 if ui.verbose:
1100 ui.write("% 6d % 9d % 7d % 7d %s %s %s\n" % (
1100 ui.write("% 6d % 9d % 7d % 7d %s %s %s\n" % (
1101 i, r.start(i), r.length(i), r.linkrev(i),
1101 i, r.start(i), r.length(i), r.linkrev(i),
1102 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
1102 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
1103 else:
1103 else:
1104 ui.write("% 6d % 7d %s %s %s\n" % (
1104 ui.write("% 6d % 7d %s %s %s\n" % (
1105 i, r.linkrev(i), shortfn(node), shortfn(pp[0]),
1105 i, r.linkrev(i), shortfn(node), shortfn(pp[0]),
1106 shortfn(pp[1])))
1106 shortfn(pp[1])))
1107 elif format == 1:
1107 elif format == 1:
1108 pr = r.parentrevs(i)
1108 pr = r.parentrevs(i)
1109 if ui.verbose:
1109 if ui.verbose:
1110 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n" % (
1110 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n" % (
1111 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1111 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1112 r.linkrev(i), pr[0], pr[1], shortfn(node)))
1112 r.linkrev(i), pr[0], pr[1], shortfn(node)))
1113 else:
1113 else:
1114 ui.write("% 6d %04x % 8d % 6d % 6d % 6d %s\n" % (
1114 ui.write("% 6d %04x % 8d % 6d % 6d % 6d %s\n" % (
1115 i, r.flags(i), r.rawsize(i), r.linkrev(i), pr[0], pr[1],
1115 i, r.flags(i), r.rawsize(i), r.linkrev(i), pr[0], pr[1],
1116 shortfn(node)))
1116 shortfn(node)))
1117
1117
1118 @command('debugindexdot', cmdutil.debugrevlogopts,
1118 @command('debugindexdot', cmdutil.debugrevlogopts,
1119 _('-c|-m|FILE'), optionalrepo=True)
1119 _('-c|-m|FILE'), optionalrepo=True)
1120 def debugindexdot(ui, repo, file_=None, **opts):
1120 def debugindexdot(ui, repo, file_=None, **opts):
1121 """dump an index DAG as a graphviz dot file"""
1121 """dump an index DAG as a graphviz dot file"""
1122 opts = pycompat.byteskwargs(opts)
1122 opts = pycompat.byteskwargs(opts)
1123 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
1123 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
1124 ui.write(("digraph G {\n"))
1124 ui.write(("digraph G {\n"))
1125 for i in r:
1125 for i in r:
1126 node = r.node(i)
1126 node = r.node(i)
1127 pp = r.parents(node)
1127 pp = r.parents(node)
1128 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1128 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1129 if pp[1] != nullid:
1129 if pp[1] != nullid:
1130 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1130 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1131 ui.write("}\n")
1131 ui.write("}\n")
1132
1132
1133 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
1133 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
1134 def debuginstall(ui, **opts):
1134 def debuginstall(ui, **opts):
1135 '''test Mercurial installation
1135 '''test Mercurial installation
1136
1136
1137 Returns 0 on success.
1137 Returns 0 on success.
1138 '''
1138 '''
1139 opts = pycompat.byteskwargs(opts)
1139 opts = pycompat.byteskwargs(opts)
1140
1140
1141 def writetemp(contents):
1141 def writetemp(contents):
1142 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1142 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1143 f = os.fdopen(fd, r"wb")
1143 f = os.fdopen(fd, r"wb")
1144 f.write(contents)
1144 f.write(contents)
1145 f.close()
1145 f.close()
1146 return name
1146 return name
1147
1147
1148 problems = 0
1148 problems = 0
1149
1149
1150 fm = ui.formatter('debuginstall', opts)
1150 fm = ui.formatter('debuginstall', opts)
1151 fm.startitem()
1151 fm.startitem()
1152
1152
1153 # encoding
1153 # encoding
1154 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
1154 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
1155 err = None
1155 err = None
1156 try:
1156 try:
1157 codecs.lookup(pycompat.sysstr(encoding.encoding))
1157 codecs.lookup(pycompat.sysstr(encoding.encoding))
1158 except LookupError as inst:
1158 except LookupError as inst:
1159 err = stringutil.forcebytestr(inst)
1159 err = stringutil.forcebytestr(inst)
1160 problems += 1
1160 problems += 1
1161 fm.condwrite(err, 'encodingerror', _(" %s\n"
1161 fm.condwrite(err, 'encodingerror', _(" %s\n"
1162 " (check that your locale is properly set)\n"), err)
1162 " (check that your locale is properly set)\n"), err)
1163
1163
1164 # Python
1164 # Python
1165 fm.write('pythonexe', _("checking Python executable (%s)\n"),
1165 fm.write('pythonexe', _("checking Python executable (%s)\n"),
1166 pycompat.sysexecutable)
1166 pycompat.sysexecutable)
1167 fm.write('pythonver', _("checking Python version (%s)\n"),
1167 fm.write('pythonver', _("checking Python version (%s)\n"),
1168 ("%d.%d.%d" % sys.version_info[:3]))
1168 ("%d.%d.%d" % sys.version_info[:3]))
1169 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
1169 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
1170 os.path.dirname(pycompat.fsencode(os.__file__)))
1170 os.path.dirname(pycompat.fsencode(os.__file__)))
1171
1171
1172 security = set(sslutil.supportedprotocols)
1172 security = set(sslutil.supportedprotocols)
1173 if sslutil.hassni:
1173 if sslutil.hassni:
1174 security.add('sni')
1174 security.add('sni')
1175
1175
1176 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
1176 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
1177 fm.formatlist(sorted(security), name='protocol',
1177 fm.formatlist(sorted(security), name='protocol',
1178 fmt='%s', sep=','))
1178 fmt='%s', sep=','))
1179
1179
1180 # These are warnings, not errors. So don't increment problem count. This
1180 # These are warnings, not errors. So don't increment problem count. This
1181 # may change in the future.
1181 # may change in the future.
1182 if 'tls1.2' not in security:
1182 if 'tls1.2' not in security:
1183 fm.plain(_(' TLS 1.2 not supported by Python install; '
1183 fm.plain(_(' TLS 1.2 not supported by Python install; '
1184 'network connections lack modern security\n'))
1184 'network connections lack modern security\n'))
1185 if 'sni' not in security:
1185 if 'sni' not in security:
1186 fm.plain(_(' SNI not supported by Python install; may have '
1186 fm.plain(_(' SNI not supported by Python install; may have '
1187 'connectivity issues with some servers\n'))
1187 'connectivity issues with some servers\n'))
1188
1188
1189 # TODO print CA cert info
1189 # TODO print CA cert info
1190
1190
1191 # hg version
1191 # hg version
1192 hgver = util.version()
1192 hgver = util.version()
1193 fm.write('hgver', _("checking Mercurial version (%s)\n"),
1193 fm.write('hgver', _("checking Mercurial version (%s)\n"),
1194 hgver.split('+')[0])
1194 hgver.split('+')[0])
1195 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
1195 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
1196 '+'.join(hgver.split('+')[1:]))
1196 '+'.join(hgver.split('+')[1:]))
1197
1197
1198 # compiled modules
1198 # compiled modules
1199 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
1199 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
1200 policy.policy)
1200 policy.policy)
1201 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
1201 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
1202 os.path.dirname(pycompat.fsencode(__file__)))
1202 os.path.dirname(pycompat.fsencode(__file__)))
1203
1203
1204 if policy.policy in ('c', 'allow'):
1204 if policy.policy in ('c', 'allow'):
1205 err = None
1205 err = None
1206 try:
1206 try:
1207 from .cext import (
1207 from .cext import (
1208 base85,
1208 base85,
1209 bdiff,
1209 bdiff,
1210 mpatch,
1210 mpatch,
1211 osutil,
1211 osutil,
1212 )
1212 )
1213 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1213 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1214 except Exception as inst:
1214 except Exception as inst:
1215 err = stringutil.forcebytestr(inst)
1215 err = stringutil.forcebytestr(inst)
1216 problems += 1
1216 problems += 1
1217 fm.condwrite(err, 'extensionserror', " %s\n", err)
1217 fm.condwrite(err, 'extensionserror', " %s\n", err)
1218
1218
1219 compengines = util.compengines._engines.values()
1219 compengines = util.compengines._engines.values()
1220 fm.write('compengines', _('checking registered compression engines (%s)\n'),
1220 fm.write('compengines', _('checking registered compression engines (%s)\n'),
1221 fm.formatlist(sorted(e.name() for e in compengines),
1221 fm.formatlist(sorted(e.name() for e in compengines),
1222 name='compengine', fmt='%s', sep=', '))
1222 name='compengine', fmt='%s', sep=', '))
1223 fm.write('compenginesavail', _('checking available compression engines '
1223 fm.write('compenginesavail', _('checking available compression engines '
1224 '(%s)\n'),
1224 '(%s)\n'),
1225 fm.formatlist(sorted(e.name() for e in compengines
1225 fm.formatlist(sorted(e.name() for e in compengines
1226 if e.available()),
1226 if e.available()),
1227 name='compengine', fmt='%s', sep=', '))
1227 name='compengine', fmt='%s', sep=', '))
1228 wirecompengines = util.compengines.supportedwireengines(util.SERVERROLE)
1228 wirecompengines = util.compengines.supportedwireengines(util.SERVERROLE)
1229 fm.write('compenginesserver', _('checking available compression engines '
1229 fm.write('compenginesserver', _('checking available compression engines '
1230 'for wire protocol (%s)\n'),
1230 'for wire protocol (%s)\n'),
1231 fm.formatlist([e.name() for e in wirecompengines
1231 fm.formatlist([e.name() for e in wirecompengines
1232 if e.wireprotosupport()],
1232 if e.wireprotosupport()],
1233 name='compengine', fmt='%s', sep=', '))
1233 name='compengine', fmt='%s', sep=', '))
1234 re2 = 'missing'
1234 re2 = 'missing'
1235 if util._re2:
1235 if util._re2:
1236 re2 = 'available'
1236 re2 = 'available'
1237 fm.plain(_('checking "re2" regexp engine (%s)\n') % re2)
1237 fm.plain(_('checking "re2" regexp engine (%s)\n') % re2)
1238 fm.data(re2=bool(util._re2))
1238 fm.data(re2=bool(util._re2))
1239
1239
1240 # templates
1240 # templates
1241 p = templater.templatepaths()
1241 p = templater.templatepaths()
1242 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
1242 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
1243 fm.condwrite(not p, '', _(" no template directories found\n"))
1243 fm.condwrite(not p, '', _(" no template directories found\n"))
1244 if p:
1244 if p:
1245 m = templater.templatepath("map-cmdline.default")
1245 m = templater.templatepath("map-cmdline.default")
1246 if m:
1246 if m:
1247 # template found, check if it is working
1247 # template found, check if it is working
1248 err = None
1248 err = None
1249 try:
1249 try:
1250 templater.templater.frommapfile(m)
1250 templater.templater.frommapfile(m)
1251 except Exception as inst:
1251 except Exception as inst:
1252 err = stringutil.forcebytestr(inst)
1252 err = stringutil.forcebytestr(inst)
1253 p = None
1253 p = None
1254 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
1254 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
1255 else:
1255 else:
1256 p = None
1256 p = None
1257 fm.condwrite(p, 'defaulttemplate',
1257 fm.condwrite(p, 'defaulttemplate',
1258 _("checking default template (%s)\n"), m)
1258 _("checking default template (%s)\n"), m)
1259 fm.condwrite(not m, 'defaulttemplatenotfound',
1259 fm.condwrite(not m, 'defaulttemplatenotfound',
1260 _(" template '%s' not found\n"), "default")
1260 _(" template '%s' not found\n"), "default")
1261 if not p:
1261 if not p:
1262 problems += 1
1262 problems += 1
1263 fm.condwrite(not p, '',
1263 fm.condwrite(not p, '',
1264 _(" (templates seem to have been installed incorrectly)\n"))
1264 _(" (templates seem to have been installed incorrectly)\n"))
1265
1265
1266 # editor
1266 # editor
1267 editor = ui.geteditor()
1267 editor = ui.geteditor()
1268 editor = util.expandpath(editor)
1268 editor = util.expandpath(editor)
1269 editorbin = procutil.shellsplit(editor)[0]
1269 editorbin = procutil.shellsplit(editor)[0]
1270 fm.write('editor', _("checking commit editor... (%s)\n"), editorbin)
1270 fm.write('editor', _("checking commit editor... (%s)\n"), editorbin)
1271 cmdpath = procutil.findexe(editorbin)
1271 cmdpath = procutil.findexe(editorbin)
1272 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
1272 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
1273 _(" No commit editor set and can't find %s in PATH\n"
1273 _(" No commit editor set and can't find %s in PATH\n"
1274 " (specify a commit editor in your configuration"
1274 " (specify a commit editor in your configuration"
1275 " file)\n"), not cmdpath and editor == 'vi' and editorbin)
1275 " file)\n"), not cmdpath and editor == 'vi' and editorbin)
1276 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
1276 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
1277 _(" Can't find editor '%s' in PATH\n"
1277 _(" Can't find editor '%s' in PATH\n"
1278 " (specify a commit editor in your configuration"
1278 " (specify a commit editor in your configuration"
1279 " file)\n"), not cmdpath and editorbin)
1279 " file)\n"), not cmdpath and editorbin)
1280 if not cmdpath and editor != 'vi':
1280 if not cmdpath and editor != 'vi':
1281 problems += 1
1281 problems += 1
1282
1282
1283 # check username
1283 # check username
1284 username = None
1284 username = None
1285 err = None
1285 err = None
1286 try:
1286 try:
1287 username = ui.username()
1287 username = ui.username()
1288 except error.Abort as e:
1288 except error.Abort as e:
1289 err = stringutil.forcebytestr(e)
1289 err = stringutil.forcebytestr(e)
1290 problems += 1
1290 problems += 1
1291
1291
1292 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
1292 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
1293 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
1293 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
1294 " (specify a username in your configuration file)\n"), err)
1294 " (specify a username in your configuration file)\n"), err)
1295
1295
1296 fm.condwrite(not problems, '',
1296 fm.condwrite(not problems, '',
1297 _("no problems detected\n"))
1297 _("no problems detected\n"))
1298 if not problems:
1298 if not problems:
1299 fm.data(problems=problems)
1299 fm.data(problems=problems)
1300 fm.condwrite(problems, 'problems',
1300 fm.condwrite(problems, 'problems',
1301 _("%d problems detected,"
1301 _("%d problems detected,"
1302 " please check your install!\n"), problems)
1302 " please check your install!\n"), problems)
1303 fm.end()
1303 fm.end()
1304
1304
1305 return problems
1305 return problems
1306
1306
1307 @command('debugknown', [], _('REPO ID...'), norepo=True)
1307 @command('debugknown', [], _('REPO ID...'), norepo=True)
1308 def debugknown(ui, repopath, *ids, **opts):
1308 def debugknown(ui, repopath, *ids, **opts):
1309 """test whether node ids are known to a repo
1309 """test whether node ids are known to a repo
1310
1310
1311 Every ID must be a full-length hex node id string. Returns a list of 0s
1311 Every ID must be a full-length hex node id string. Returns a list of 0s
1312 and 1s indicating unknown/known.
1312 and 1s indicating unknown/known.
1313 """
1313 """
1314 opts = pycompat.byteskwargs(opts)
1314 opts = pycompat.byteskwargs(opts)
1315 repo = hg.peer(ui, opts, repopath)
1315 repo = hg.peer(ui, opts, repopath)
1316 if not repo.capable('known'):
1316 if not repo.capable('known'):
1317 raise error.Abort("known() not supported by target repository")
1317 raise error.Abort("known() not supported by target repository")
1318 flags = repo.known([bin(s) for s in ids])
1318 flags = repo.known([bin(s) for s in ids])
1319 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1319 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1320
1320
1321 @command('debuglabelcomplete', [], _('LABEL...'))
1321 @command('debuglabelcomplete', [], _('LABEL...'))
1322 def debuglabelcomplete(ui, repo, *args):
1322 def debuglabelcomplete(ui, repo, *args):
1323 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1323 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1324 debugnamecomplete(ui, repo, *args)
1324 debugnamecomplete(ui, repo, *args)
1325
1325
1326 @command('debuglocks',
1326 @command('debuglocks',
1327 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
1327 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
1328 ('W', 'force-wlock', None,
1328 ('W', 'force-wlock', None,
1329 _('free the working state lock (DANGEROUS)')),
1329 _('free the working state lock (DANGEROUS)')),
1330 ('s', 'set-lock', None, _('set the store lock until stopped')),
1330 ('s', 'set-lock', None, _('set the store lock until stopped')),
1331 ('S', 'set-wlock', None,
1331 ('S', 'set-wlock', None,
1332 _('set the working state lock until stopped'))],
1332 _('set the working state lock until stopped'))],
1333 _('[OPTION]...'))
1333 _('[OPTION]...'))
1334 def debuglocks(ui, repo, **opts):
1334 def debuglocks(ui, repo, **opts):
1335 """show or modify state of locks
1335 """show or modify state of locks
1336
1336
1337 By default, this command will show which locks are held. This
1337 By default, this command will show which locks are held. This
1338 includes the user and process holding the lock, the amount of time
1338 includes the user and process holding the lock, the amount of time
1339 the lock has been held, and the machine name where the process is
1339 the lock has been held, and the machine name where the process is
1340 running if it's not local.
1340 running if it's not local.
1341
1341
1342 Locks protect the integrity of Mercurial's data, so should be
1342 Locks protect the integrity of Mercurial's data, so should be
1343 treated with care. System crashes or other interruptions may cause
1343 treated with care. System crashes or other interruptions may cause
1344 locks to not be properly released, though Mercurial will usually
1344 locks to not be properly released, though Mercurial will usually
1345 detect and remove such stale locks automatically.
1345 detect and remove such stale locks automatically.
1346
1346
1347 However, detecting stale locks may not always be possible (for
1347 However, detecting stale locks may not always be possible (for
1348 instance, on a shared filesystem). Removing locks may also be
1348 instance, on a shared filesystem). Removing locks may also be
1349 blocked by filesystem permissions.
1349 blocked by filesystem permissions.
1350
1350
1351 Setting a lock will prevent other commands from changing the data.
1351 Setting a lock will prevent other commands from changing the data.
1352 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
1352 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
1353 The set locks are removed when the command exits.
1353 The set locks are removed when the command exits.
1354
1354
1355 Returns 0 if no locks are held.
1355 Returns 0 if no locks are held.
1356
1356
1357 """
1357 """
1358
1358
1359 if opts.get(r'force_lock'):
1359 if opts.get(r'force_lock'):
1360 repo.svfs.unlink('lock')
1360 repo.svfs.unlink('lock')
1361 if opts.get(r'force_wlock'):
1361 if opts.get(r'force_wlock'):
1362 repo.vfs.unlink('wlock')
1362 repo.vfs.unlink('wlock')
1363 if opts.get(r'force_lock') or opts.get(r'force_wlock'):
1363 if opts.get(r'force_lock') or opts.get(r'force_wlock'):
1364 return 0
1364 return 0
1365
1365
1366 locks = []
1366 locks = []
1367 try:
1367 try:
1368 if opts.get(r'set_wlock'):
1368 if opts.get(r'set_wlock'):
1369 try:
1369 try:
1370 locks.append(repo.wlock(False))
1370 locks.append(repo.wlock(False))
1371 except error.LockHeld:
1371 except error.LockHeld:
1372 raise error.Abort(_('wlock is already held'))
1372 raise error.Abort(_('wlock is already held'))
1373 if opts.get(r'set_lock'):
1373 if opts.get(r'set_lock'):
1374 try:
1374 try:
1375 locks.append(repo.lock(False))
1375 locks.append(repo.lock(False))
1376 except error.LockHeld:
1376 except error.LockHeld:
1377 raise error.Abort(_('lock is already held'))
1377 raise error.Abort(_('lock is already held'))
1378 if len(locks):
1378 if len(locks):
1379 ui.promptchoice(_("ready to release the lock (y)? $$ &Yes"))
1379 ui.promptchoice(_("ready to release the lock (y)? $$ &Yes"))
1380 return 0
1380 return 0
1381 finally:
1381 finally:
1382 release(*locks)
1382 release(*locks)
1383
1383
1384 now = time.time()
1384 now = time.time()
1385 held = 0
1385 held = 0
1386
1386
1387 def report(vfs, name, method):
1387 def report(vfs, name, method):
1388 # this causes stale locks to get reaped for more accurate reporting
1388 # this causes stale locks to get reaped for more accurate reporting
1389 try:
1389 try:
1390 l = method(False)
1390 l = method(False)
1391 except error.LockHeld:
1391 except error.LockHeld:
1392 l = None
1392 l = None
1393
1393
1394 if l:
1394 if l:
1395 l.release()
1395 l.release()
1396 else:
1396 else:
1397 try:
1397 try:
1398 st = vfs.lstat(name)
1398 st = vfs.lstat(name)
1399 age = now - st[stat.ST_MTIME]
1399 age = now - st[stat.ST_MTIME]
1400 user = util.username(st.st_uid)
1400 user = util.username(st.st_uid)
1401 locker = vfs.readlock(name)
1401 locker = vfs.readlock(name)
1402 if ":" in locker:
1402 if ":" in locker:
1403 host, pid = locker.split(':')
1403 host, pid = locker.split(':')
1404 if host == socket.gethostname():
1404 if host == socket.gethostname():
1405 locker = 'user %s, process %s' % (user, pid)
1405 locker = 'user %s, process %s' % (user, pid)
1406 else:
1406 else:
1407 locker = 'user %s, process %s, host %s' \
1407 locker = 'user %s, process %s, host %s' \
1408 % (user, pid, host)
1408 % (user, pid, host)
1409 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
1409 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
1410 return 1
1410 return 1
1411 except OSError as e:
1411 except OSError as e:
1412 if e.errno != errno.ENOENT:
1412 if e.errno != errno.ENOENT:
1413 raise
1413 raise
1414
1414
1415 ui.write(("%-6s free\n") % (name + ":"))
1415 ui.write(("%-6s free\n") % (name + ":"))
1416 return 0
1416 return 0
1417
1417
1418 held += report(repo.svfs, "lock", repo.lock)
1418 held += report(repo.svfs, "lock", repo.lock)
1419 held += report(repo.vfs, "wlock", repo.wlock)
1419 held += report(repo.vfs, "wlock", repo.wlock)
1420
1420
1421 return held
1421 return held
1422
1422
1423 @command('debugmergestate', [], '')
1423 @command('debugmergestate', [], '')
1424 def debugmergestate(ui, repo, *args):
1424 def debugmergestate(ui, repo, *args):
1425 """print merge state
1425 """print merge state
1426
1426
1427 Use --verbose to print out information about whether v1 or v2 merge state
1427 Use --verbose to print out information about whether v1 or v2 merge state
1428 was chosen."""
1428 was chosen."""
1429 def _hashornull(h):
1429 def _hashornull(h):
1430 if h == nullhex:
1430 if h == nullhex:
1431 return 'null'
1431 return 'null'
1432 else:
1432 else:
1433 return h
1433 return h
1434
1434
1435 def printrecords(version):
1435 def printrecords(version):
1436 ui.write(('* version %d records\n') % version)
1436 ui.write(('* version %d records\n') % version)
1437 if version == 1:
1437 if version == 1:
1438 records = v1records
1438 records = v1records
1439 else:
1439 else:
1440 records = v2records
1440 records = v2records
1441
1441
1442 for rtype, record in records:
1442 for rtype, record in records:
1443 # pretty print some record types
1443 # pretty print some record types
1444 if rtype == 'L':
1444 if rtype == 'L':
1445 ui.write(('local: %s\n') % record)
1445 ui.write(('local: %s\n') % record)
1446 elif rtype == 'O':
1446 elif rtype == 'O':
1447 ui.write(('other: %s\n') % record)
1447 ui.write(('other: %s\n') % record)
1448 elif rtype == 'm':
1448 elif rtype == 'm':
1449 driver, mdstate = record.split('\0', 1)
1449 driver, mdstate = record.split('\0', 1)
1450 ui.write(('merge driver: %s (state "%s")\n')
1450 ui.write(('merge driver: %s (state "%s")\n')
1451 % (driver, mdstate))
1451 % (driver, mdstate))
1452 elif rtype in 'FDC':
1452 elif rtype in 'FDC':
1453 r = record.split('\0')
1453 r = record.split('\0')
1454 f, state, hash, lfile, afile, anode, ofile = r[0:7]
1454 f, state, hash, lfile, afile, anode, ofile = r[0:7]
1455 if version == 1:
1455 if version == 1:
1456 onode = 'not stored in v1 format'
1456 onode = 'not stored in v1 format'
1457 flags = r[7]
1457 flags = r[7]
1458 else:
1458 else:
1459 onode, flags = r[7:9]
1459 onode, flags = r[7:9]
1460 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
1460 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
1461 % (f, rtype, state, _hashornull(hash)))
1461 % (f, rtype, state, _hashornull(hash)))
1462 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
1462 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
1463 ui.write((' ancestor path: %s (node %s)\n')
1463 ui.write((' ancestor path: %s (node %s)\n')
1464 % (afile, _hashornull(anode)))
1464 % (afile, _hashornull(anode)))
1465 ui.write((' other path: %s (node %s)\n')
1465 ui.write((' other path: %s (node %s)\n')
1466 % (ofile, _hashornull(onode)))
1466 % (ofile, _hashornull(onode)))
1467 elif rtype == 'f':
1467 elif rtype == 'f':
1468 filename, rawextras = record.split('\0', 1)
1468 filename, rawextras = record.split('\0', 1)
1469 extras = rawextras.split('\0')
1469 extras = rawextras.split('\0')
1470 i = 0
1470 i = 0
1471 extrastrings = []
1471 extrastrings = []
1472 while i < len(extras):
1472 while i < len(extras):
1473 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
1473 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
1474 i += 2
1474 i += 2
1475
1475
1476 ui.write(('file extras: %s (%s)\n')
1476 ui.write(('file extras: %s (%s)\n')
1477 % (filename, ', '.join(extrastrings)))
1477 % (filename, ', '.join(extrastrings)))
1478 elif rtype == 'l':
1478 elif rtype == 'l':
1479 labels = record.split('\0', 2)
1479 labels = record.split('\0', 2)
1480 labels = [l for l in labels if len(l) > 0]
1480 labels = [l for l in labels if len(l) > 0]
1481 ui.write(('labels:\n'))
1481 ui.write(('labels:\n'))
1482 ui.write((' local: %s\n' % labels[0]))
1482 ui.write((' local: %s\n' % labels[0]))
1483 ui.write((' other: %s\n' % labels[1]))
1483 ui.write((' other: %s\n' % labels[1]))
1484 if len(labels) > 2:
1484 if len(labels) > 2:
1485 ui.write((' base: %s\n' % labels[2]))
1485 ui.write((' base: %s\n' % labels[2]))
1486 else:
1486 else:
1487 ui.write(('unrecognized entry: %s\t%s\n')
1487 ui.write(('unrecognized entry: %s\t%s\n')
1488 % (rtype, record.replace('\0', '\t')))
1488 % (rtype, record.replace('\0', '\t')))
1489
1489
1490 # Avoid mergestate.read() since it may raise an exception for unsupported
1490 # Avoid mergestate.read() since it may raise an exception for unsupported
1491 # merge state records. We shouldn't be doing this, but this is OK since this
1491 # merge state records. We shouldn't be doing this, but this is OK since this
1492 # command is pretty low-level.
1492 # command is pretty low-level.
1493 ms = mergemod.mergestate(repo)
1493 ms = mergemod.mergestate(repo)
1494
1494
1495 # sort so that reasonable information is on top
1495 # sort so that reasonable information is on top
1496 v1records = ms._readrecordsv1()
1496 v1records = ms._readrecordsv1()
1497 v2records = ms._readrecordsv2()
1497 v2records = ms._readrecordsv2()
1498 order = 'LOml'
1498 order = 'LOml'
1499 def key(r):
1499 def key(r):
1500 idx = order.find(r[0])
1500 idx = order.find(r[0])
1501 if idx == -1:
1501 if idx == -1:
1502 return (1, r[1])
1502 return (1, r[1])
1503 else:
1503 else:
1504 return (0, idx)
1504 return (0, idx)
1505 v1records.sort(key=key)
1505 v1records.sort(key=key)
1506 v2records.sort(key=key)
1506 v2records.sort(key=key)
1507
1507
1508 if not v1records and not v2records:
1508 if not v1records and not v2records:
1509 ui.write(('no merge state found\n'))
1509 ui.write(('no merge state found\n'))
1510 elif not v2records:
1510 elif not v2records:
1511 ui.note(('no version 2 merge state\n'))
1511 ui.note(('no version 2 merge state\n'))
1512 printrecords(1)
1512 printrecords(1)
1513 elif ms._v1v2match(v1records, v2records):
1513 elif ms._v1v2match(v1records, v2records):
1514 ui.note(('v1 and v2 states match: using v2\n'))
1514 ui.note(('v1 and v2 states match: using v2\n'))
1515 printrecords(2)
1515 printrecords(2)
1516 else:
1516 else:
1517 ui.note(('v1 and v2 states mismatch: using v1\n'))
1517 ui.note(('v1 and v2 states mismatch: using v1\n'))
1518 printrecords(1)
1518 printrecords(1)
1519 if ui.verbose:
1519 if ui.verbose:
1520 printrecords(2)
1520 printrecords(2)
1521
1521
1522 @command('debugnamecomplete', [], _('NAME...'))
1522 @command('debugnamecomplete', [], _('NAME...'))
1523 def debugnamecomplete(ui, repo, *args):
1523 def debugnamecomplete(ui, repo, *args):
1524 '''complete "names" - tags, open branch names, bookmark names'''
1524 '''complete "names" - tags, open branch names, bookmark names'''
1525
1525
1526 names = set()
1526 names = set()
1527 # since we previously only listed open branches, we will handle that
1527 # since we previously only listed open branches, we will handle that
1528 # specially (after this for loop)
1528 # specially (after this for loop)
1529 for name, ns in repo.names.iteritems():
1529 for name, ns in repo.names.iteritems():
1530 if name != 'branches':
1530 if name != 'branches':
1531 names.update(ns.listnames(repo))
1531 names.update(ns.listnames(repo))
1532 names.update(tag for (tag, heads, tip, closed)
1532 names.update(tag for (tag, heads, tip, closed)
1533 in repo.branchmap().iterbranches() if not closed)
1533 in repo.branchmap().iterbranches() if not closed)
1534 completions = set()
1534 completions = set()
1535 if not args:
1535 if not args:
1536 args = ['']
1536 args = ['']
1537 for a in args:
1537 for a in args:
1538 completions.update(n for n in names if n.startswith(a))
1538 completions.update(n for n in names if n.startswith(a))
1539 ui.write('\n'.join(sorted(completions)))
1539 ui.write('\n'.join(sorted(completions)))
1540 ui.write('\n')
1540 ui.write('\n')
1541
1541
1542 @command('debugobsolete',
1542 @command('debugobsolete',
1543 [('', 'flags', 0, _('markers flag')),
1543 [('', 'flags', 0, _('markers flag')),
1544 ('', 'record-parents', False,
1544 ('', 'record-parents', False,
1545 _('record parent information for the precursor')),
1545 _('record parent information for the precursor')),
1546 ('r', 'rev', [], _('display markers relevant to REV')),
1546 ('r', 'rev', [], _('display markers relevant to REV')),
1547 ('', 'exclusive', False, _('restrict display to markers only '
1547 ('', 'exclusive', False, _('restrict display to markers only '
1548 'relevant to REV')),
1548 'relevant to REV')),
1549 ('', 'index', False, _('display index of the marker')),
1549 ('', 'index', False, _('display index of the marker')),
1550 ('', 'delete', [], _('delete markers specified by indices')),
1550 ('', 'delete', [], _('delete markers specified by indices')),
1551 ] + cmdutil.commitopts2 + cmdutil.formatteropts,
1551 ] + cmdutil.commitopts2 + cmdutil.formatteropts,
1552 _('[OBSOLETED [REPLACEMENT ...]]'))
1552 _('[OBSOLETED [REPLACEMENT ...]]'))
1553 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
1553 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
1554 """create arbitrary obsolete marker
1554 """create arbitrary obsolete marker
1555
1555
1556 With no arguments, displays the list of obsolescence markers."""
1556 With no arguments, displays the list of obsolescence markers."""
1557
1557
1558 opts = pycompat.byteskwargs(opts)
1558 opts = pycompat.byteskwargs(opts)
1559
1559
1560 def parsenodeid(s):
1560 def parsenodeid(s):
1561 try:
1561 try:
1562 # We do not use revsingle/revrange functions here to accept
1562 # We do not use revsingle/revrange functions here to accept
1563 # arbitrary node identifiers, possibly not present in the
1563 # arbitrary node identifiers, possibly not present in the
1564 # local repository.
1564 # local repository.
1565 n = bin(s)
1565 n = bin(s)
1566 if len(n) != len(nullid):
1566 if len(n) != len(nullid):
1567 raise TypeError()
1567 raise TypeError()
1568 return n
1568 return n
1569 except TypeError:
1569 except TypeError:
1570 raise error.Abort('changeset references must be full hexadecimal '
1570 raise error.Abort('changeset references must be full hexadecimal '
1571 'node identifiers')
1571 'node identifiers')
1572
1572
1573 if opts.get('delete'):
1573 if opts.get('delete'):
1574 indices = []
1574 indices = []
1575 for v in opts.get('delete'):
1575 for v in opts.get('delete'):
1576 try:
1576 try:
1577 indices.append(int(v))
1577 indices.append(int(v))
1578 except ValueError:
1578 except ValueError:
1579 raise error.Abort(_('invalid index value: %r') % v,
1579 raise error.Abort(_('invalid index value: %r') % v,
1580 hint=_('use integers for indices'))
1580 hint=_('use integers for indices'))
1581
1581
1582 if repo.currenttransaction():
1582 if repo.currenttransaction():
1583 raise error.Abort(_('cannot delete obsmarkers in the middle '
1583 raise error.Abort(_('cannot delete obsmarkers in the middle '
1584 'of transaction.'))
1584 'of transaction.'))
1585
1585
1586 with repo.lock():
1586 with repo.lock():
1587 n = repair.deleteobsmarkers(repo.obsstore, indices)
1587 n = repair.deleteobsmarkers(repo.obsstore, indices)
1588 ui.write(_('deleted %i obsolescence markers\n') % n)
1588 ui.write(_('deleted %i obsolescence markers\n') % n)
1589
1589
1590 return
1590 return
1591
1591
1592 if precursor is not None:
1592 if precursor is not None:
1593 if opts['rev']:
1593 if opts['rev']:
1594 raise error.Abort('cannot select revision when creating marker')
1594 raise error.Abort('cannot select revision when creating marker')
1595 metadata = {}
1595 metadata = {}
1596 metadata['user'] = opts['user'] or ui.username()
1596 metadata['user'] = opts['user'] or ui.username()
1597 succs = tuple(parsenodeid(succ) for succ in successors)
1597 succs = tuple(parsenodeid(succ) for succ in successors)
1598 l = repo.lock()
1598 l = repo.lock()
1599 try:
1599 try:
1600 tr = repo.transaction('debugobsolete')
1600 tr = repo.transaction('debugobsolete')
1601 try:
1601 try:
1602 date = opts.get('date')
1602 date = opts.get('date')
1603 if date:
1603 if date:
1604 date = dateutil.parsedate(date)
1604 date = dateutil.parsedate(date)
1605 else:
1605 else:
1606 date = None
1606 date = None
1607 prec = parsenodeid(precursor)
1607 prec = parsenodeid(precursor)
1608 parents = None
1608 parents = None
1609 if opts['record_parents']:
1609 if opts['record_parents']:
1610 if prec not in repo.unfiltered():
1610 if prec not in repo.unfiltered():
1611 raise error.Abort('cannot used --record-parents on '
1611 raise error.Abort('cannot used --record-parents on '
1612 'unknown changesets')
1612 'unknown changesets')
1613 parents = repo.unfiltered()[prec].parents()
1613 parents = repo.unfiltered()[prec].parents()
1614 parents = tuple(p.node() for p in parents)
1614 parents = tuple(p.node() for p in parents)
1615 repo.obsstore.create(tr, prec, succs, opts['flags'],
1615 repo.obsstore.create(tr, prec, succs, opts['flags'],
1616 parents=parents, date=date,
1616 parents=parents, date=date,
1617 metadata=metadata, ui=ui)
1617 metadata=metadata, ui=ui)
1618 tr.close()
1618 tr.close()
1619 except ValueError as exc:
1619 except ValueError as exc:
1620 raise error.Abort(_('bad obsmarker input: %s') %
1620 raise error.Abort(_('bad obsmarker input: %s') %
1621 pycompat.bytestr(exc))
1621 pycompat.bytestr(exc))
1622 finally:
1622 finally:
1623 tr.release()
1623 tr.release()
1624 finally:
1624 finally:
1625 l.release()
1625 l.release()
1626 else:
1626 else:
1627 if opts['rev']:
1627 if opts['rev']:
1628 revs = scmutil.revrange(repo, opts['rev'])
1628 revs = scmutil.revrange(repo, opts['rev'])
1629 nodes = [repo[r].node() for r in revs]
1629 nodes = [repo[r].node() for r in revs]
1630 markers = list(obsutil.getmarkers(repo, nodes=nodes,
1630 markers = list(obsutil.getmarkers(repo, nodes=nodes,
1631 exclusive=opts['exclusive']))
1631 exclusive=opts['exclusive']))
1632 markers.sort(key=lambda x: x._data)
1632 markers.sort(key=lambda x: x._data)
1633 else:
1633 else:
1634 markers = obsutil.getmarkers(repo)
1634 markers = obsutil.getmarkers(repo)
1635
1635
1636 markerstoiter = markers
1636 markerstoiter = markers
1637 isrelevant = lambda m: True
1637 isrelevant = lambda m: True
1638 if opts.get('rev') and opts.get('index'):
1638 if opts.get('rev') and opts.get('index'):
1639 markerstoiter = obsutil.getmarkers(repo)
1639 markerstoiter = obsutil.getmarkers(repo)
1640 markerset = set(markers)
1640 markerset = set(markers)
1641 isrelevant = lambda m: m in markerset
1641 isrelevant = lambda m: m in markerset
1642
1642
1643 fm = ui.formatter('debugobsolete', opts)
1643 fm = ui.formatter('debugobsolete', opts)
1644 for i, m in enumerate(markerstoiter):
1644 for i, m in enumerate(markerstoiter):
1645 if not isrelevant(m):
1645 if not isrelevant(m):
1646 # marker can be irrelevant when we're iterating over a set
1646 # marker can be irrelevant when we're iterating over a set
1647 # of markers (markerstoiter) which is bigger than the set
1647 # of markers (markerstoiter) which is bigger than the set
1648 # of markers we want to display (markers)
1648 # of markers we want to display (markers)
1649 # this can happen if both --index and --rev options are
1649 # this can happen if both --index and --rev options are
1650 # provided and thus we need to iterate over all of the markers
1650 # provided and thus we need to iterate over all of the markers
1651 # to get the correct indices, but only display the ones that
1651 # to get the correct indices, but only display the ones that
1652 # are relevant to --rev value
1652 # are relevant to --rev value
1653 continue
1653 continue
1654 fm.startitem()
1654 fm.startitem()
1655 ind = i if opts.get('index') else None
1655 ind = i if opts.get('index') else None
1656 cmdutil.showmarker(fm, m, index=ind)
1656 cmdutil.showmarker(fm, m, index=ind)
1657 fm.end()
1657 fm.end()
1658
1658
1659 @command('debugpathcomplete',
1659 @command('debugpathcomplete',
1660 [('f', 'full', None, _('complete an entire path')),
1660 [('f', 'full', None, _('complete an entire path')),
1661 ('n', 'normal', None, _('show only normal files')),
1661 ('n', 'normal', None, _('show only normal files')),
1662 ('a', 'added', None, _('show only added files')),
1662 ('a', 'added', None, _('show only added files')),
1663 ('r', 'removed', None, _('show only removed files'))],
1663 ('r', 'removed', None, _('show only removed files'))],
1664 _('FILESPEC...'))
1664 _('FILESPEC...'))
1665 def debugpathcomplete(ui, repo, *specs, **opts):
1665 def debugpathcomplete(ui, repo, *specs, **opts):
1666 '''complete part or all of a tracked path
1666 '''complete part or all of a tracked path
1667
1667
1668 This command supports shells that offer path name completion. It
1668 This command supports shells that offer path name completion. It
1669 currently completes only files already known to the dirstate.
1669 currently completes only files already known to the dirstate.
1670
1670
1671 Completion extends only to the next path segment unless
1671 Completion extends only to the next path segment unless
1672 --full is specified, in which case entire paths are used.'''
1672 --full is specified, in which case entire paths are used.'''
1673
1673
1674 def complete(path, acceptable):
1674 def complete(path, acceptable):
1675 dirstate = repo.dirstate
1675 dirstate = repo.dirstate
1676 spec = os.path.normpath(os.path.join(pycompat.getcwd(), path))
1676 spec = os.path.normpath(os.path.join(pycompat.getcwd(), path))
1677 rootdir = repo.root + pycompat.ossep
1677 rootdir = repo.root + pycompat.ossep
1678 if spec != repo.root and not spec.startswith(rootdir):
1678 if spec != repo.root and not spec.startswith(rootdir):
1679 return [], []
1679 return [], []
1680 if os.path.isdir(spec):
1680 if os.path.isdir(spec):
1681 spec += '/'
1681 spec += '/'
1682 spec = spec[len(rootdir):]
1682 spec = spec[len(rootdir):]
1683 fixpaths = pycompat.ossep != '/'
1683 fixpaths = pycompat.ossep != '/'
1684 if fixpaths:
1684 if fixpaths:
1685 spec = spec.replace(pycompat.ossep, '/')
1685 spec = spec.replace(pycompat.ossep, '/')
1686 speclen = len(spec)
1686 speclen = len(spec)
1687 fullpaths = opts[r'full']
1687 fullpaths = opts[r'full']
1688 files, dirs = set(), set()
1688 files, dirs = set(), set()
1689 adddir, addfile = dirs.add, files.add
1689 adddir, addfile = dirs.add, files.add
1690 for f, st in dirstate.iteritems():
1690 for f, st in dirstate.iteritems():
1691 if f.startswith(spec) and st[0] in acceptable:
1691 if f.startswith(spec) and st[0] in acceptable:
1692 if fixpaths:
1692 if fixpaths:
1693 f = f.replace('/', pycompat.ossep)
1693 f = f.replace('/', pycompat.ossep)
1694 if fullpaths:
1694 if fullpaths:
1695 addfile(f)
1695 addfile(f)
1696 continue
1696 continue
1697 s = f.find(pycompat.ossep, speclen)
1697 s = f.find(pycompat.ossep, speclen)
1698 if s >= 0:
1698 if s >= 0:
1699 adddir(f[:s])
1699 adddir(f[:s])
1700 else:
1700 else:
1701 addfile(f)
1701 addfile(f)
1702 return files, dirs
1702 return files, dirs
1703
1703
1704 acceptable = ''
1704 acceptable = ''
1705 if opts[r'normal']:
1705 if opts[r'normal']:
1706 acceptable += 'nm'
1706 acceptable += 'nm'
1707 if opts[r'added']:
1707 if opts[r'added']:
1708 acceptable += 'a'
1708 acceptable += 'a'
1709 if opts[r'removed']:
1709 if opts[r'removed']:
1710 acceptable += 'r'
1710 acceptable += 'r'
1711 cwd = repo.getcwd()
1711 cwd = repo.getcwd()
1712 if not specs:
1712 if not specs:
1713 specs = ['.']
1713 specs = ['.']
1714
1714
1715 files, dirs = set(), set()
1715 files, dirs = set(), set()
1716 for spec in specs:
1716 for spec in specs:
1717 f, d = complete(spec, acceptable or 'nmar')
1717 f, d = complete(spec, acceptable or 'nmar')
1718 files.update(f)
1718 files.update(f)
1719 dirs.update(d)
1719 dirs.update(d)
1720 files.update(dirs)
1720 files.update(dirs)
1721 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
1721 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
1722 ui.write('\n')
1722 ui.write('\n')
1723
1723
1724 @command('debugpeer', [], _('PATH'), norepo=True)
1724 @command('debugpeer', [], _('PATH'), norepo=True)
1725 def debugpeer(ui, path):
1725 def debugpeer(ui, path):
1726 """establish a connection to a peer repository"""
1726 """establish a connection to a peer repository"""
1727 # Always enable peer request logging. Requires --debug to display
1727 # Always enable peer request logging. Requires --debug to display
1728 # though.
1728 # though.
1729 overrides = {
1729 overrides = {
1730 ('devel', 'debug.peer-request'): True,
1730 ('devel', 'debug.peer-request'): True,
1731 }
1731 }
1732
1732
1733 with ui.configoverride(overrides):
1733 with ui.configoverride(overrides):
1734 peer = hg.peer(ui, {}, path)
1734 peer = hg.peer(ui, {}, path)
1735
1735
1736 local = peer.local() is not None
1736 local = peer.local() is not None
1737 canpush = peer.canpush()
1737 canpush = peer.canpush()
1738
1738
1739 ui.write(_('url: %s\n') % peer.url())
1739 ui.write(_('url: %s\n') % peer.url())
1740 ui.write(_('local: %s\n') % (_('yes') if local else _('no')))
1740 ui.write(_('local: %s\n') % (_('yes') if local else _('no')))
1741 ui.write(_('pushable: %s\n') % (_('yes') if canpush else _('no')))
1741 ui.write(_('pushable: %s\n') % (_('yes') if canpush else _('no')))
1742
1742
1743 @command('debugpickmergetool',
1743 @command('debugpickmergetool',
1744 [('r', 'rev', '', _('check for files in this revision'), _('REV')),
1744 [('r', 'rev', '', _('check for files in this revision'), _('REV')),
1745 ('', 'changedelete', None, _('emulate merging change and delete')),
1745 ('', 'changedelete', None, _('emulate merging change and delete')),
1746 ] + cmdutil.walkopts + cmdutil.mergetoolopts,
1746 ] + cmdutil.walkopts + cmdutil.mergetoolopts,
1747 _('[PATTERN]...'),
1747 _('[PATTERN]...'),
1748 inferrepo=True)
1748 inferrepo=True)
1749 def debugpickmergetool(ui, repo, *pats, **opts):
1749 def debugpickmergetool(ui, repo, *pats, **opts):
1750 """examine which merge tool is chosen for specified file
1750 """examine which merge tool is chosen for specified file
1751
1751
1752 As described in :hg:`help merge-tools`, Mercurial examines
1752 As described in :hg:`help merge-tools`, Mercurial examines
1753 configurations below in this order to decide which merge tool is
1753 configurations below in this order to decide which merge tool is
1754 chosen for specified file.
1754 chosen for specified file.
1755
1755
1756 1. ``--tool`` option
1756 1. ``--tool`` option
1757 2. ``HGMERGE`` environment variable
1757 2. ``HGMERGE`` environment variable
1758 3. configurations in ``merge-patterns`` section
1758 3. configurations in ``merge-patterns`` section
1759 4. configuration of ``ui.merge``
1759 4. configuration of ``ui.merge``
1760 5. configurations in ``merge-tools`` section
1760 5. configurations in ``merge-tools`` section
1761 6. ``hgmerge`` tool (for historical reason only)
1761 6. ``hgmerge`` tool (for historical reason only)
1762 7. default tool for fallback (``:merge`` or ``:prompt``)
1762 7. default tool for fallback (``:merge`` or ``:prompt``)
1763
1763
1764 This command writes out examination result in the style below::
1764 This command writes out examination result in the style below::
1765
1765
1766 FILE = MERGETOOL
1766 FILE = MERGETOOL
1767
1767
1768 By default, all files known in the first parent context of the
1768 By default, all files known in the first parent context of the
1769 working directory are examined. Use file patterns and/or -I/-X
1769 working directory are examined. Use file patterns and/or -I/-X
1770 options to limit target files. -r/--rev is also useful to examine
1770 options to limit target files. -r/--rev is also useful to examine
1771 files in another context without actual updating to it.
1771 files in another context without actual updating to it.
1772
1772
1773 With --debug, this command shows warning messages while matching
1773 With --debug, this command shows warning messages while matching
1774 against ``merge-patterns`` and so on, too. It is recommended to
1774 against ``merge-patterns`` and so on, too. It is recommended to
1775 use this option with explicit file patterns and/or -I/-X options,
1775 use this option with explicit file patterns and/or -I/-X options,
1776 because this option increases amount of output per file according
1776 because this option increases amount of output per file according
1777 to configurations in hgrc.
1777 to configurations in hgrc.
1778
1778
1779 With -v/--verbose, this command shows configurations below at
1779 With -v/--verbose, this command shows configurations below at
1780 first (only if specified).
1780 first (only if specified).
1781
1781
1782 - ``--tool`` option
1782 - ``--tool`` option
1783 - ``HGMERGE`` environment variable
1783 - ``HGMERGE`` environment variable
1784 - configuration of ``ui.merge``
1784 - configuration of ``ui.merge``
1785
1785
1786 If merge tool is chosen before matching against
1786 If merge tool is chosen before matching against
1787 ``merge-patterns``, this command can't show any helpful
1787 ``merge-patterns``, this command can't show any helpful
1788 information, even with --debug. In such case, information above is
1788 information, even with --debug. In such case, information above is
1789 useful to know why a merge tool is chosen.
1789 useful to know why a merge tool is chosen.
1790 """
1790 """
1791 opts = pycompat.byteskwargs(opts)
1791 opts = pycompat.byteskwargs(opts)
1792 overrides = {}
1792 overrides = {}
1793 if opts['tool']:
1793 if opts['tool']:
1794 overrides[('ui', 'forcemerge')] = opts['tool']
1794 overrides[('ui', 'forcemerge')] = opts['tool']
1795 ui.note(('with --tool %r\n') % (pycompat.bytestr(opts['tool'])))
1795 ui.note(('with --tool %r\n') % (pycompat.bytestr(opts['tool'])))
1796
1796
1797 with ui.configoverride(overrides, 'debugmergepatterns'):
1797 with ui.configoverride(overrides, 'debugmergepatterns'):
1798 hgmerge = encoding.environ.get("HGMERGE")
1798 hgmerge = encoding.environ.get("HGMERGE")
1799 if hgmerge is not None:
1799 if hgmerge is not None:
1800 ui.note(('with HGMERGE=%r\n') % (pycompat.bytestr(hgmerge)))
1800 ui.note(('with HGMERGE=%r\n') % (pycompat.bytestr(hgmerge)))
1801 uimerge = ui.config("ui", "merge")
1801 uimerge = ui.config("ui", "merge")
1802 if uimerge:
1802 if uimerge:
1803 ui.note(('with ui.merge=%r\n') % (pycompat.bytestr(uimerge)))
1803 ui.note(('with ui.merge=%r\n') % (pycompat.bytestr(uimerge)))
1804
1804
1805 ctx = scmutil.revsingle(repo, opts.get('rev'))
1805 ctx = scmutil.revsingle(repo, opts.get('rev'))
1806 m = scmutil.match(ctx, pats, opts)
1806 m = scmutil.match(ctx, pats, opts)
1807 changedelete = opts['changedelete']
1807 changedelete = opts['changedelete']
1808 for path in ctx.walk(m):
1808 for path in ctx.walk(m):
1809 fctx = ctx[path]
1809 fctx = ctx[path]
1810 try:
1810 try:
1811 if not ui.debugflag:
1811 if not ui.debugflag:
1812 ui.pushbuffer(error=True)
1812 ui.pushbuffer(error=True)
1813 tool, toolpath = filemerge._picktool(repo, ui, path,
1813 tool, toolpath = filemerge._picktool(repo, ui, path,
1814 fctx.isbinary(),
1814 fctx.isbinary(),
1815 'l' in fctx.flags(),
1815 'l' in fctx.flags(),
1816 changedelete)
1816 changedelete)
1817 finally:
1817 finally:
1818 if not ui.debugflag:
1818 if not ui.debugflag:
1819 ui.popbuffer()
1819 ui.popbuffer()
1820 ui.write(('%s = %s\n') % (path, tool))
1820 ui.write(('%s = %s\n') % (path, tool))
1821
1821
1822 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
1822 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
1823 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1823 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1824 '''access the pushkey key/value protocol
1824 '''access the pushkey key/value protocol
1825
1825
1826 With two args, list the keys in the given namespace.
1826 With two args, list the keys in the given namespace.
1827
1827
1828 With five args, set a key to new if it currently is set to old.
1828 With five args, set a key to new if it currently is set to old.
1829 Reports success or failure.
1829 Reports success or failure.
1830 '''
1830 '''
1831
1831
1832 target = hg.peer(ui, {}, repopath)
1832 target = hg.peer(ui, {}, repopath)
1833 if keyinfo:
1833 if keyinfo:
1834 key, old, new = keyinfo
1834 key, old, new = keyinfo
1835 with target.commandexecutor() as e:
1835 with target.commandexecutor() as e:
1836 r = e.callcommand('pushkey', {
1836 r = e.callcommand('pushkey', {
1837 'namespace': namespace,
1837 'namespace': namespace,
1838 'key': key,
1838 'key': key,
1839 'old': old,
1839 'old': old,
1840 'new': new,
1840 'new': new,
1841 }).result()
1841 }).result()
1842
1842
1843 ui.status(pycompat.bytestr(r) + '\n')
1843 ui.status(pycompat.bytestr(r) + '\n')
1844 return not r
1844 return not r
1845 else:
1845 else:
1846 for k, v in sorted(target.listkeys(namespace).iteritems()):
1846 for k, v in sorted(target.listkeys(namespace).iteritems()):
1847 ui.write("%s\t%s\n" % (stringutil.escapestr(k),
1847 ui.write("%s\t%s\n" % (stringutil.escapestr(k),
1848 stringutil.escapestr(v)))
1848 stringutil.escapestr(v)))
1849
1849
1850 @command('debugpvec', [], _('A B'))
1850 @command('debugpvec', [], _('A B'))
1851 def debugpvec(ui, repo, a, b=None):
1851 def debugpvec(ui, repo, a, b=None):
1852 ca = scmutil.revsingle(repo, a)
1852 ca = scmutil.revsingle(repo, a)
1853 cb = scmutil.revsingle(repo, b)
1853 cb = scmutil.revsingle(repo, b)
1854 pa = pvec.ctxpvec(ca)
1854 pa = pvec.ctxpvec(ca)
1855 pb = pvec.ctxpvec(cb)
1855 pb = pvec.ctxpvec(cb)
1856 if pa == pb:
1856 if pa == pb:
1857 rel = "="
1857 rel = "="
1858 elif pa > pb:
1858 elif pa > pb:
1859 rel = ">"
1859 rel = ">"
1860 elif pa < pb:
1860 elif pa < pb:
1861 rel = "<"
1861 rel = "<"
1862 elif pa | pb:
1862 elif pa | pb:
1863 rel = "|"
1863 rel = "|"
1864 ui.write(_("a: %s\n") % pa)
1864 ui.write(_("a: %s\n") % pa)
1865 ui.write(_("b: %s\n") % pb)
1865 ui.write(_("b: %s\n") % pb)
1866 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
1866 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
1867 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
1867 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
1868 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
1868 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
1869 pa.distance(pb), rel))
1869 pa.distance(pb), rel))
1870
1870
1871 @command('debugrebuilddirstate|debugrebuildstate',
1871 @command('debugrebuilddirstate|debugrebuildstate',
1872 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
1872 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
1873 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
1873 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
1874 'the working copy parent')),
1874 'the working copy parent')),
1875 ],
1875 ],
1876 _('[-r REV]'))
1876 _('[-r REV]'))
1877 def debugrebuilddirstate(ui, repo, rev, **opts):
1877 def debugrebuilddirstate(ui, repo, rev, **opts):
1878 """rebuild the dirstate as it would look like for the given revision
1878 """rebuild the dirstate as it would look like for the given revision
1879
1879
1880 If no revision is specified the first current parent will be used.
1880 If no revision is specified the first current parent will be used.
1881
1881
1882 The dirstate will be set to the files of the given revision.
1882 The dirstate will be set to the files of the given revision.
1883 The actual working directory content or existing dirstate
1883 The actual working directory content or existing dirstate
1884 information such as adds or removes is not considered.
1884 information such as adds or removes is not considered.
1885
1885
1886 ``minimal`` will only rebuild the dirstate status for files that claim to be
1886 ``minimal`` will only rebuild the dirstate status for files that claim to be
1887 tracked but are not in the parent manifest, or that exist in the parent
1887 tracked but are not in the parent manifest, or that exist in the parent
1888 manifest but are not in the dirstate. It will not change adds, removes, or
1888 manifest but are not in the dirstate. It will not change adds, removes, or
1889 modified files that are in the working copy parent.
1889 modified files that are in the working copy parent.
1890
1890
1891 One use of this command is to make the next :hg:`status` invocation
1891 One use of this command is to make the next :hg:`status` invocation
1892 check the actual file content.
1892 check the actual file content.
1893 """
1893 """
1894 ctx = scmutil.revsingle(repo, rev)
1894 ctx = scmutil.revsingle(repo, rev)
1895 with repo.wlock():
1895 with repo.wlock():
1896 dirstate = repo.dirstate
1896 dirstate = repo.dirstate
1897 changedfiles = None
1897 changedfiles = None
1898 # See command doc for what minimal does.
1898 # See command doc for what minimal does.
1899 if opts.get(r'minimal'):
1899 if opts.get(r'minimal'):
1900 manifestfiles = set(ctx.manifest().keys())
1900 manifestfiles = set(ctx.manifest().keys())
1901 dirstatefiles = set(dirstate)
1901 dirstatefiles = set(dirstate)
1902 manifestonly = manifestfiles - dirstatefiles
1902 manifestonly = manifestfiles - dirstatefiles
1903 dsonly = dirstatefiles - manifestfiles
1903 dsonly = dirstatefiles - manifestfiles
1904 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
1904 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
1905 changedfiles = manifestonly | dsnotadded
1905 changedfiles = manifestonly | dsnotadded
1906
1906
1907 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
1907 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
1908
1908
1909 @command('debugrebuildfncache', [], '')
1909 @command('debugrebuildfncache', [], '')
1910 def debugrebuildfncache(ui, repo):
1910 def debugrebuildfncache(ui, repo):
1911 """rebuild the fncache file"""
1911 """rebuild the fncache file"""
1912 repair.rebuildfncache(ui, repo)
1912 repair.rebuildfncache(ui, repo)
1913
1913
1914 @command('debugrename',
1914 @command('debugrename',
1915 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1915 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1916 _('[-r REV] FILE'))
1916 _('[-r REV] FILE'))
1917 def debugrename(ui, repo, file1, *pats, **opts):
1917 def debugrename(ui, repo, file1, *pats, **opts):
1918 """dump rename information"""
1918 """dump rename information"""
1919
1919
1920 opts = pycompat.byteskwargs(opts)
1920 opts = pycompat.byteskwargs(opts)
1921 ctx = scmutil.revsingle(repo, opts.get('rev'))
1921 ctx = scmutil.revsingle(repo, opts.get('rev'))
1922 m = scmutil.match(ctx, (file1,) + pats, opts)
1922 m = scmutil.match(ctx, (file1,) + pats, opts)
1923 for abs in ctx.walk(m):
1923 for abs in ctx.walk(m):
1924 fctx = ctx[abs]
1924 fctx = ctx[abs]
1925 o = fctx.filelog().renamed(fctx.filenode())
1925 o = fctx.filelog().renamed(fctx.filenode())
1926 rel = m.rel(abs)
1926 rel = m.rel(abs)
1927 if o:
1927 if o:
1928 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1928 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1929 else:
1929 else:
1930 ui.write(_("%s not renamed\n") % rel)
1930 ui.write(_("%s not renamed\n") % rel)
1931
1931
1932 @command('debugrevlog', cmdutil.debugrevlogopts +
1932 @command('debugrevlog', cmdutil.debugrevlogopts +
1933 [('d', 'dump', False, _('dump index data'))],
1933 [('d', 'dump', False, _('dump index data'))],
1934 _('-c|-m|FILE'),
1934 _('-c|-m|FILE'),
1935 optionalrepo=True)
1935 optionalrepo=True)
1936 def debugrevlog(ui, repo, file_=None, **opts):
1936 def debugrevlog(ui, repo, file_=None, **opts):
1937 """show data and statistics about a revlog"""
1937 """show data and statistics about a revlog"""
1938 opts = pycompat.byteskwargs(opts)
1938 opts = pycompat.byteskwargs(opts)
1939 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1939 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1940
1940
1941 if opts.get("dump"):
1941 if opts.get("dump"):
1942 numrevs = len(r)
1942 numrevs = len(r)
1943 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
1943 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
1944 " rawsize totalsize compression heads chainlen\n"))
1944 " rawsize totalsize compression heads chainlen\n"))
1945 ts = 0
1945 ts = 0
1946 heads = set()
1946 heads = set()
1947
1947
1948 for rev in xrange(numrevs):
1948 for rev in xrange(numrevs):
1949 dbase = r.deltaparent(rev)
1949 dbase = r.deltaparent(rev)
1950 if dbase == -1:
1950 if dbase == -1:
1951 dbase = rev
1951 dbase = rev
1952 cbase = r.chainbase(rev)
1952 cbase = r.chainbase(rev)
1953 clen = r.chainlen(rev)
1953 clen = r.chainlen(rev)
1954 p1, p2 = r.parentrevs(rev)
1954 p1, p2 = r.parentrevs(rev)
1955 rs = r.rawsize(rev)
1955 rs = r.rawsize(rev)
1956 ts = ts + rs
1956 ts = ts + rs
1957 heads -= set(r.parentrevs(rev))
1957 heads -= set(r.parentrevs(rev))
1958 heads.add(rev)
1958 heads.add(rev)
1959 try:
1959 try:
1960 compression = ts / r.end(rev)
1960 compression = ts / r.end(rev)
1961 except ZeroDivisionError:
1961 except ZeroDivisionError:
1962 compression = 0
1962 compression = 0
1963 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
1963 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
1964 "%11d %5d %8d\n" %
1964 "%11d %5d %8d\n" %
1965 (rev, p1, p2, r.start(rev), r.end(rev),
1965 (rev, p1, p2, r.start(rev), r.end(rev),
1966 r.start(dbase), r.start(cbase),
1966 r.start(dbase), r.start(cbase),
1967 r.start(p1), r.start(p2),
1967 r.start(p1), r.start(p2),
1968 rs, ts, compression, len(heads), clen))
1968 rs, ts, compression, len(heads), clen))
1969 return 0
1969 return 0
1970
1970
1971 v = r.version
1971 v = r.version
1972 format = v & 0xFFFF
1972 format = v & 0xFFFF
1973 flags = []
1973 flags = []
1974 gdelta = False
1974 gdelta = False
1975 if v & revlog.FLAG_INLINE_DATA:
1975 if v & revlog.FLAG_INLINE_DATA:
1976 flags.append('inline')
1976 flags.append('inline')
1977 if v & revlog.FLAG_GENERALDELTA:
1977 if v & revlog.FLAG_GENERALDELTA:
1978 gdelta = True
1978 gdelta = True
1979 flags.append('generaldelta')
1979 flags.append('generaldelta')
1980 if not flags:
1980 if not flags:
1981 flags = ['(none)']
1981 flags = ['(none)']
1982
1982
1983 nummerges = 0
1983 nummerges = 0
1984 numfull = 0
1984 numfull = 0
1985 numprev = 0
1985 numprev = 0
1986 nump1 = 0
1986 nump1 = 0
1987 nump2 = 0
1987 nump2 = 0
1988 numother = 0
1988 numother = 0
1989 nump1prev = 0
1989 nump1prev = 0
1990 nump2prev = 0
1990 nump2prev = 0
1991 chainlengths = []
1991 chainlengths = []
1992 chainbases = []
1992 chainbases = []
1993 chainspans = []
1993 chainspans = []
1994
1994
1995 datasize = [None, 0, 0]
1995 datasize = [None, 0, 0]
1996 fullsize = [None, 0, 0]
1996 fullsize = [None, 0, 0]
1997 deltasize = [None, 0, 0]
1997 deltasize = [None, 0, 0]
1998 chunktypecounts = {}
1998 chunktypecounts = {}
1999 chunktypesizes = {}
1999 chunktypesizes = {}
2000
2000
2001 def addsize(size, l):
2001 def addsize(size, l):
2002 if l[0] is None or size < l[0]:
2002 if l[0] is None or size < l[0]:
2003 l[0] = size
2003 l[0] = size
2004 if size > l[1]:
2004 if size > l[1]:
2005 l[1] = size
2005 l[1] = size
2006 l[2] += size
2006 l[2] += size
2007
2007
2008 numrevs = len(r)
2008 numrevs = len(r)
2009 for rev in xrange(numrevs):
2009 for rev in xrange(numrevs):
2010 p1, p2 = r.parentrevs(rev)
2010 p1, p2 = r.parentrevs(rev)
2011 delta = r.deltaparent(rev)
2011 delta = r.deltaparent(rev)
2012 if format > 0:
2012 if format > 0:
2013 addsize(r.rawsize(rev), datasize)
2013 addsize(r.rawsize(rev), datasize)
2014 if p2 != nullrev:
2014 if p2 != nullrev:
2015 nummerges += 1
2015 nummerges += 1
2016 size = r.length(rev)
2016 size = r.length(rev)
2017 if delta == nullrev:
2017 if delta == nullrev:
2018 chainlengths.append(0)
2018 chainlengths.append(0)
2019 chainbases.append(r.start(rev))
2019 chainbases.append(r.start(rev))
2020 chainspans.append(size)
2020 chainspans.append(size)
2021 numfull += 1
2021 numfull += 1
2022 addsize(size, fullsize)
2022 addsize(size, fullsize)
2023 else:
2023 else:
2024 chainlengths.append(chainlengths[delta] + 1)
2024 chainlengths.append(chainlengths[delta] + 1)
2025 baseaddr = chainbases[delta]
2025 baseaddr = chainbases[delta]
2026 revaddr = r.start(rev)
2026 revaddr = r.start(rev)
2027 chainbases.append(baseaddr)
2027 chainbases.append(baseaddr)
2028 chainspans.append((revaddr - baseaddr) + size)
2028 chainspans.append((revaddr - baseaddr) + size)
2029 addsize(size, deltasize)
2029 addsize(size, deltasize)
2030 if delta == rev - 1:
2030 if delta == rev - 1:
2031 numprev += 1
2031 numprev += 1
2032 if delta == p1:
2032 if delta == p1:
2033 nump1prev += 1
2033 nump1prev += 1
2034 elif delta == p2:
2034 elif delta == p2:
2035 nump2prev += 1
2035 nump2prev += 1
2036 elif delta == p1:
2036 elif delta == p1:
2037 nump1 += 1
2037 nump1 += 1
2038 elif delta == p2:
2038 elif delta == p2:
2039 nump2 += 1
2039 nump2 += 1
2040 elif delta != nullrev:
2040 elif delta != nullrev:
2041 numother += 1
2041 numother += 1
2042
2042
2043 # Obtain data on the raw chunks in the revlog.
2043 # Obtain data on the raw chunks in the revlog.
2044 segment = r._getsegmentforrevs(rev, rev)[1]
2044 segment = r._getsegmentforrevs(rev, rev)[1]
2045 if segment:
2045 if segment:
2046 chunktype = bytes(segment[0:1])
2046 chunktype = bytes(segment[0:1])
2047 else:
2047 else:
2048 chunktype = 'empty'
2048 chunktype = 'empty'
2049
2049
2050 if chunktype not in chunktypecounts:
2050 if chunktype not in chunktypecounts:
2051 chunktypecounts[chunktype] = 0
2051 chunktypecounts[chunktype] = 0
2052 chunktypesizes[chunktype] = 0
2052 chunktypesizes[chunktype] = 0
2053
2053
2054 chunktypecounts[chunktype] += 1
2054 chunktypecounts[chunktype] += 1
2055 chunktypesizes[chunktype] += size
2055 chunktypesizes[chunktype] += size
2056
2056
2057 # Adjust size min value for empty cases
2057 # Adjust size min value for empty cases
2058 for size in (datasize, fullsize, deltasize):
2058 for size in (datasize, fullsize, deltasize):
2059 if size[0] is None:
2059 if size[0] is None:
2060 size[0] = 0
2060 size[0] = 0
2061
2061
2062 numdeltas = numrevs - numfull
2062 numdeltas = numrevs - numfull
2063 numoprev = numprev - nump1prev - nump2prev
2063 numoprev = numprev - nump1prev - nump2prev
2064 totalrawsize = datasize[2]
2064 totalrawsize = datasize[2]
2065 datasize[2] /= numrevs
2065 datasize[2] /= numrevs
2066 fulltotal = fullsize[2]
2066 fulltotal = fullsize[2]
2067 fullsize[2] /= numfull
2067 fullsize[2] /= numfull
2068 deltatotal = deltasize[2]
2068 deltatotal = deltasize[2]
2069 if numrevs - numfull > 0:
2069 if numrevs - numfull > 0:
2070 deltasize[2] /= numrevs - numfull
2070 deltasize[2] /= numrevs - numfull
2071 totalsize = fulltotal + deltatotal
2071 totalsize = fulltotal + deltatotal
2072 avgchainlen = sum(chainlengths) / numrevs
2072 avgchainlen = sum(chainlengths) / numrevs
2073 maxchainlen = max(chainlengths)
2073 maxchainlen = max(chainlengths)
2074 maxchainspan = max(chainspans)
2074 maxchainspan = max(chainspans)
2075 compratio = 1
2075 compratio = 1
2076 if totalsize:
2076 if totalsize:
2077 compratio = totalrawsize / totalsize
2077 compratio = totalrawsize / totalsize
2078
2078
2079 basedfmtstr = '%%%dd\n'
2079 basedfmtstr = '%%%dd\n'
2080 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2080 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2081
2081
2082 def dfmtstr(max):
2082 def dfmtstr(max):
2083 return basedfmtstr % len(str(max))
2083 return basedfmtstr % len(str(max))
2084 def pcfmtstr(max, padding=0):
2084 def pcfmtstr(max, padding=0):
2085 return basepcfmtstr % (len(str(max)), ' ' * padding)
2085 return basepcfmtstr % (len(str(max)), ' ' * padding)
2086
2086
2087 def pcfmt(value, total):
2087 def pcfmt(value, total):
2088 if total:
2088 if total:
2089 return (value, 100 * float(value) / total)
2089 return (value, 100 * float(value) / total)
2090 else:
2090 else:
2091 return value, 100.0
2091 return value, 100.0
2092
2092
2093 ui.write(('format : %d\n') % format)
2093 ui.write(('format : %d\n') % format)
2094 ui.write(('flags : %s\n') % ', '.join(flags))
2094 ui.write(('flags : %s\n') % ', '.join(flags))
2095
2095
2096 ui.write('\n')
2096 ui.write('\n')
2097 fmt = pcfmtstr(totalsize)
2097 fmt = pcfmtstr(totalsize)
2098 fmt2 = dfmtstr(totalsize)
2098 fmt2 = dfmtstr(totalsize)
2099 ui.write(('revisions : ') + fmt2 % numrevs)
2099 ui.write(('revisions : ') + fmt2 % numrevs)
2100 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2100 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2101 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2101 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2102 ui.write(('revisions : ') + fmt2 % numrevs)
2102 ui.write(('revisions : ') + fmt2 % numrevs)
2103 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2103 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2104 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2104 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2105 ui.write(('revision size : ') + fmt2 % totalsize)
2105 ui.write(('revision size : ') + fmt2 % totalsize)
2106 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2106 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2107 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2107 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2108
2108
2109 def fmtchunktype(chunktype):
2109 def fmtchunktype(chunktype):
2110 if chunktype == 'empty':
2110 if chunktype == 'empty':
2111 return ' %s : ' % chunktype
2111 return ' %s : ' % chunktype
2112 elif chunktype in pycompat.bytestr(string.ascii_letters):
2112 elif chunktype in pycompat.bytestr(string.ascii_letters):
2113 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
2113 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
2114 else:
2114 else:
2115 return ' 0x%s : ' % hex(chunktype)
2115 return ' 0x%s : ' % hex(chunktype)
2116
2116
2117 ui.write('\n')
2117 ui.write('\n')
2118 ui.write(('chunks : ') + fmt2 % numrevs)
2118 ui.write(('chunks : ') + fmt2 % numrevs)
2119 for chunktype in sorted(chunktypecounts):
2119 for chunktype in sorted(chunktypecounts):
2120 ui.write(fmtchunktype(chunktype))
2120 ui.write(fmtchunktype(chunktype))
2121 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
2121 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
2122 ui.write(('chunks size : ') + fmt2 % totalsize)
2122 ui.write(('chunks size : ') + fmt2 % totalsize)
2123 for chunktype in sorted(chunktypecounts):
2123 for chunktype in sorted(chunktypecounts):
2124 ui.write(fmtchunktype(chunktype))
2124 ui.write(fmtchunktype(chunktype))
2125 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
2125 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
2126
2126
2127 ui.write('\n')
2127 ui.write('\n')
2128 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
2128 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
2129 ui.write(('avg chain length : ') + fmt % avgchainlen)
2129 ui.write(('avg chain length : ') + fmt % avgchainlen)
2130 ui.write(('max chain length : ') + fmt % maxchainlen)
2130 ui.write(('max chain length : ') + fmt % maxchainlen)
2131 ui.write(('max chain reach : ') + fmt % maxchainspan)
2131 ui.write(('max chain reach : ') + fmt % maxchainspan)
2132 ui.write(('compression ratio : ') + fmt % compratio)
2132 ui.write(('compression ratio : ') + fmt % compratio)
2133
2133
2134 if format > 0:
2134 if format > 0:
2135 ui.write('\n')
2135 ui.write('\n')
2136 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2136 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2137 % tuple(datasize))
2137 % tuple(datasize))
2138 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2138 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2139 % tuple(fullsize))
2139 % tuple(fullsize))
2140 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2140 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2141 % tuple(deltasize))
2141 % tuple(deltasize))
2142
2142
2143 if numdeltas > 0:
2143 if numdeltas > 0:
2144 ui.write('\n')
2144 ui.write('\n')
2145 fmt = pcfmtstr(numdeltas)
2145 fmt = pcfmtstr(numdeltas)
2146 fmt2 = pcfmtstr(numdeltas, 4)
2146 fmt2 = pcfmtstr(numdeltas, 4)
2147 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2147 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2148 if numprev > 0:
2148 if numprev > 0:
2149 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2149 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2150 numprev))
2150 numprev))
2151 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2151 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2152 numprev))
2152 numprev))
2153 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2153 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2154 numprev))
2154 numprev))
2155 if gdelta:
2155 if gdelta:
2156 ui.write(('deltas against p1 : ')
2156 ui.write(('deltas against p1 : ')
2157 + fmt % pcfmt(nump1, numdeltas))
2157 + fmt % pcfmt(nump1, numdeltas))
2158 ui.write(('deltas against p2 : ')
2158 ui.write(('deltas against p2 : ')
2159 + fmt % pcfmt(nump2, numdeltas))
2159 + fmt % pcfmt(nump2, numdeltas))
2160 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2160 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2161 numdeltas))
2161 numdeltas))
2162
2162
2163 @command('debugrevspec',
2163 @command('debugrevspec',
2164 [('', 'optimize', None,
2164 [('', 'optimize', None,
2165 _('print parsed tree after optimizing (DEPRECATED)')),
2165 _('print parsed tree after optimizing (DEPRECATED)')),
2166 ('', 'show-revs', True, _('print list of result revisions (default)')),
2166 ('', 'show-revs', True, _('print list of result revisions (default)')),
2167 ('s', 'show-set', None, _('print internal representation of result set')),
2167 ('s', 'show-set', None, _('print internal representation of result set')),
2168 ('p', 'show-stage', [],
2168 ('p', 'show-stage', [],
2169 _('print parsed tree at the given stage'), _('NAME')),
2169 _('print parsed tree at the given stage'), _('NAME')),
2170 ('', 'no-optimized', False, _('evaluate tree without optimization')),
2170 ('', 'no-optimized', False, _('evaluate tree without optimization')),
2171 ('', 'verify-optimized', False, _('verify optimized result')),
2171 ('', 'verify-optimized', False, _('verify optimized result')),
2172 ],
2172 ],
2173 ('REVSPEC'))
2173 ('REVSPEC'))
2174 def debugrevspec(ui, repo, expr, **opts):
2174 def debugrevspec(ui, repo, expr, **opts):
2175 """parse and apply a revision specification
2175 """parse and apply a revision specification
2176
2176
2177 Use -p/--show-stage option to print the parsed tree at the given stages.
2177 Use -p/--show-stage option to print the parsed tree at the given stages.
2178 Use -p all to print tree at every stage.
2178 Use -p all to print tree at every stage.
2179
2179
2180 Use --no-show-revs option with -s or -p to print only the set
2180 Use --no-show-revs option with -s or -p to print only the set
2181 representation or the parsed tree respectively.
2181 representation or the parsed tree respectively.
2182
2182
2183 Use --verify-optimized to compare the optimized result with the unoptimized
2183 Use --verify-optimized to compare the optimized result with the unoptimized
2184 one. Returns 1 if the optimized result differs.
2184 one. Returns 1 if the optimized result differs.
2185 """
2185 """
2186 opts = pycompat.byteskwargs(opts)
2186 opts = pycompat.byteskwargs(opts)
2187 aliases = ui.configitems('revsetalias')
2187 aliases = ui.configitems('revsetalias')
2188 stages = [
2188 stages = [
2189 ('parsed', lambda tree: tree),
2189 ('parsed', lambda tree: tree),
2190 ('expanded', lambda tree: revsetlang.expandaliases(tree, aliases,
2190 ('expanded', lambda tree: revsetlang.expandaliases(tree, aliases,
2191 ui.warn)),
2191 ui.warn)),
2192 ('concatenated', revsetlang.foldconcat),
2192 ('concatenated', revsetlang.foldconcat),
2193 ('analyzed', revsetlang.analyze),
2193 ('analyzed', revsetlang.analyze),
2194 ('optimized', revsetlang.optimize),
2194 ('optimized', revsetlang.optimize),
2195 ]
2195 ]
2196 if opts['no_optimized']:
2196 if opts['no_optimized']:
2197 stages = stages[:-1]
2197 stages = stages[:-1]
2198 if opts['verify_optimized'] and opts['no_optimized']:
2198 if opts['verify_optimized'] and opts['no_optimized']:
2199 raise error.Abort(_('cannot use --verify-optimized with '
2199 raise error.Abort(_('cannot use --verify-optimized with '
2200 '--no-optimized'))
2200 '--no-optimized'))
2201 stagenames = set(n for n, f in stages)
2201 stagenames = set(n for n, f in stages)
2202
2202
2203 showalways = set()
2203 showalways = set()
2204 showchanged = set()
2204 showchanged = set()
2205 if ui.verbose and not opts['show_stage']:
2205 if ui.verbose and not opts['show_stage']:
2206 # show parsed tree by --verbose (deprecated)
2206 # show parsed tree by --verbose (deprecated)
2207 showalways.add('parsed')
2207 showalways.add('parsed')
2208 showchanged.update(['expanded', 'concatenated'])
2208 showchanged.update(['expanded', 'concatenated'])
2209 if opts['optimize']:
2209 if opts['optimize']:
2210 showalways.add('optimized')
2210 showalways.add('optimized')
2211 if opts['show_stage'] and opts['optimize']:
2211 if opts['show_stage'] and opts['optimize']:
2212 raise error.Abort(_('cannot use --optimize with --show-stage'))
2212 raise error.Abort(_('cannot use --optimize with --show-stage'))
2213 if opts['show_stage'] == ['all']:
2213 if opts['show_stage'] == ['all']:
2214 showalways.update(stagenames)
2214 showalways.update(stagenames)
2215 else:
2215 else:
2216 for n in opts['show_stage']:
2216 for n in opts['show_stage']:
2217 if n not in stagenames:
2217 if n not in stagenames:
2218 raise error.Abort(_('invalid stage name: %s') % n)
2218 raise error.Abort(_('invalid stage name: %s') % n)
2219 showalways.update(opts['show_stage'])
2219 showalways.update(opts['show_stage'])
2220
2220
2221 treebystage = {}
2221 treebystage = {}
2222 printedtree = None
2222 printedtree = None
2223 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
2223 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
2224 for n, f in stages:
2224 for n, f in stages:
2225 treebystage[n] = tree = f(tree)
2225 treebystage[n] = tree = f(tree)
2226 if n in showalways or (n in showchanged and tree != printedtree):
2226 if n in showalways or (n in showchanged and tree != printedtree):
2227 if opts['show_stage'] or n != 'parsed':
2227 if opts['show_stage'] or n != 'parsed':
2228 ui.write(("* %s:\n") % n)
2228 ui.write(("* %s:\n") % n)
2229 ui.write(revsetlang.prettyformat(tree), "\n")
2229 ui.write(revsetlang.prettyformat(tree), "\n")
2230 printedtree = tree
2230 printedtree = tree
2231
2231
2232 if opts['verify_optimized']:
2232 if opts['verify_optimized']:
2233 arevs = revset.makematcher(treebystage['analyzed'])(repo)
2233 arevs = revset.makematcher(treebystage['analyzed'])(repo)
2234 brevs = revset.makematcher(treebystage['optimized'])(repo)
2234 brevs = revset.makematcher(treebystage['optimized'])(repo)
2235 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2235 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2236 ui.write(("* analyzed set:\n"), smartset.prettyformat(arevs), "\n")
2236 ui.write(("* analyzed set:\n"), smartset.prettyformat(arevs), "\n")
2237 ui.write(("* optimized set:\n"), smartset.prettyformat(brevs), "\n")
2237 ui.write(("* optimized set:\n"), smartset.prettyformat(brevs), "\n")
2238 arevs = list(arevs)
2238 arevs = list(arevs)
2239 brevs = list(brevs)
2239 brevs = list(brevs)
2240 if arevs == brevs:
2240 if arevs == brevs:
2241 return 0
2241 return 0
2242 ui.write(('--- analyzed\n'), label='diff.file_a')
2242 ui.write(('--- analyzed\n'), label='diff.file_a')
2243 ui.write(('+++ optimized\n'), label='diff.file_b')
2243 ui.write(('+++ optimized\n'), label='diff.file_b')
2244 sm = difflib.SequenceMatcher(None, arevs, brevs)
2244 sm = difflib.SequenceMatcher(None, arevs, brevs)
2245 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2245 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2246 if tag in ('delete', 'replace'):
2246 if tag in ('delete', 'replace'):
2247 for c in arevs[alo:ahi]:
2247 for c in arevs[alo:ahi]:
2248 ui.write('-%s\n' % c, label='diff.deleted')
2248 ui.write('-%s\n' % c, label='diff.deleted')
2249 if tag in ('insert', 'replace'):
2249 if tag in ('insert', 'replace'):
2250 for c in brevs[blo:bhi]:
2250 for c in brevs[blo:bhi]:
2251 ui.write('+%s\n' % c, label='diff.inserted')
2251 ui.write('+%s\n' % c, label='diff.inserted')
2252 if tag == 'equal':
2252 if tag == 'equal':
2253 for c in arevs[alo:ahi]:
2253 for c in arevs[alo:ahi]:
2254 ui.write(' %s\n' % c)
2254 ui.write(' %s\n' % c)
2255 return 1
2255 return 1
2256
2256
2257 func = revset.makematcher(tree)
2257 func = revset.makematcher(tree)
2258 revs = func(repo)
2258 revs = func(repo)
2259 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2259 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2260 ui.write(("* set:\n"), smartset.prettyformat(revs), "\n")
2260 ui.write(("* set:\n"), smartset.prettyformat(revs), "\n")
2261 if not opts['show_revs']:
2261 if not opts['show_revs']:
2262 return
2262 return
2263 for c in revs:
2263 for c in revs:
2264 ui.write("%d\n" % c)
2264 ui.write("%d\n" % c)
2265
2265
2266 @command('debugserve', [
2266 @command('debugserve', [
2267 ('', 'sshstdio', False, _('run an SSH server bound to process handles')),
2267 ('', 'sshstdio', False, _('run an SSH server bound to process handles')),
2268 ('', 'logiofd', '', _('file descriptor to log server I/O to')),
2268 ('', 'logiofd', '', _('file descriptor to log server I/O to')),
2269 ('', 'logiofile', '', _('file to log server I/O to')),
2269 ('', 'logiofile', '', _('file to log server I/O to')),
2270 ], '')
2270 ], '')
2271 def debugserve(ui, repo, **opts):
2271 def debugserve(ui, repo, **opts):
2272 """run a server with advanced settings
2272 """run a server with advanced settings
2273
2273
2274 This command is similar to :hg:`serve`. It exists partially as a
2274 This command is similar to :hg:`serve`. It exists partially as a
2275 workaround to the fact that ``hg serve --stdio`` must have specific
2275 workaround to the fact that ``hg serve --stdio`` must have specific
2276 arguments for security reasons.
2276 arguments for security reasons.
2277 """
2277 """
2278 opts = pycompat.byteskwargs(opts)
2278 opts = pycompat.byteskwargs(opts)
2279
2279
2280 if not opts['sshstdio']:
2280 if not opts['sshstdio']:
2281 raise error.Abort(_('only --sshstdio is currently supported'))
2281 raise error.Abort(_('only --sshstdio is currently supported'))
2282
2282
2283 logfh = None
2283 logfh = None
2284
2284
2285 if opts['logiofd'] and opts['logiofile']:
2285 if opts['logiofd'] and opts['logiofile']:
2286 raise error.Abort(_('cannot use both --logiofd and --logiofile'))
2286 raise error.Abort(_('cannot use both --logiofd and --logiofile'))
2287
2287
2288 if opts['logiofd']:
2288 if opts['logiofd']:
2289 # Line buffered because output is line based.
2289 # Line buffered because output is line based.
2290 logfh = os.fdopen(int(opts['logiofd']), r'ab', 1)
2290 logfh = os.fdopen(int(opts['logiofd']), r'ab', 1)
2291 elif opts['logiofile']:
2291 elif opts['logiofile']:
2292 logfh = open(opts['logiofile'], 'ab', 1)
2292 logfh = open(opts['logiofile'], 'ab', 1)
2293
2293
2294 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
2294 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
2295 s.serve_forever()
2295 s.serve_forever()
2296
2296
2297 @command('debugsetparents', [], _('REV1 [REV2]'))
2297 @command('debugsetparents', [], _('REV1 [REV2]'))
2298 def debugsetparents(ui, repo, rev1, rev2=None):
2298 def debugsetparents(ui, repo, rev1, rev2=None):
2299 """manually set the parents of the current working directory
2299 """manually set the parents of the current working directory
2300
2300
2301 This is useful for writing repository conversion tools, but should
2301 This is useful for writing repository conversion tools, but should
2302 be used with care. For example, neither the working directory nor the
2302 be used with care. For example, neither the working directory nor the
2303 dirstate is updated, so file status may be incorrect after running this
2303 dirstate is updated, so file status may be incorrect after running this
2304 command.
2304 command.
2305
2305
2306 Returns 0 on success.
2306 Returns 0 on success.
2307 """
2307 """
2308
2308
2309 node1 = scmutil.revsingle(repo, rev1).node()
2309 node1 = scmutil.revsingle(repo, rev1).node()
2310 node2 = scmutil.revsingle(repo, rev2, 'null').node()
2310 node2 = scmutil.revsingle(repo, rev2, 'null').node()
2311
2311
2312 with repo.wlock():
2312 with repo.wlock():
2313 repo.setparents(node1, node2)
2313 repo.setparents(node1, node2)
2314
2314
2315 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
2315 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
2316 def debugssl(ui, repo, source=None, **opts):
2316 def debugssl(ui, repo, source=None, **opts):
2317 '''test a secure connection to a server
2317 '''test a secure connection to a server
2318
2318
2319 This builds the certificate chain for the server on Windows, installing the
2319 This builds the certificate chain for the server on Windows, installing the
2320 missing intermediates and trusted root via Windows Update if necessary. It
2320 missing intermediates and trusted root via Windows Update if necessary. It
2321 does nothing on other platforms.
2321 does nothing on other platforms.
2322
2322
2323 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
2323 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
2324 that server is used. See :hg:`help urls` for more information.
2324 that server is used. See :hg:`help urls` for more information.
2325
2325
2326 If the update succeeds, retry the original operation. Otherwise, the cause
2326 If the update succeeds, retry the original operation. Otherwise, the cause
2327 of the SSL error is likely another issue.
2327 of the SSL error is likely another issue.
2328 '''
2328 '''
2329 if not pycompat.iswindows:
2329 if not pycompat.iswindows:
2330 raise error.Abort(_('certificate chain building is only possible on '
2330 raise error.Abort(_('certificate chain building is only possible on '
2331 'Windows'))
2331 'Windows'))
2332
2332
2333 if not source:
2333 if not source:
2334 if not repo:
2334 if not repo:
2335 raise error.Abort(_("there is no Mercurial repository here, and no "
2335 raise error.Abort(_("there is no Mercurial repository here, and no "
2336 "server specified"))
2336 "server specified"))
2337 source = "default"
2337 source = "default"
2338
2338
2339 source, branches = hg.parseurl(ui.expandpath(source))
2339 source, branches = hg.parseurl(ui.expandpath(source))
2340 url = util.url(source)
2340 url = util.url(source)
2341 addr = None
2341 addr = None
2342
2342
2343 defaultport = {'https': 443, 'ssh': 22}
2343 defaultport = {'https': 443, 'ssh': 22}
2344 if url.scheme in defaultport:
2344 if url.scheme in defaultport:
2345 try:
2345 try:
2346 addr = (url.host, int(url.port or defaultport[url.scheme]))
2346 addr = (url.host, int(url.port or defaultport[url.scheme]))
2347 except ValueError:
2347 except ValueError:
2348 raise error.Abort(_("malformed port number in URL"))
2348 raise error.Abort(_("malformed port number in URL"))
2349 else:
2349 else:
2350 raise error.Abort(_("only https and ssh connections are supported"))
2350 raise error.Abort(_("only https and ssh connections are supported"))
2351
2351
2352 from . import win32
2352 from . import win32
2353
2353
2354 s = ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_TLS,
2354 s = ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_TLS,
2355 cert_reqs=ssl.CERT_NONE, ca_certs=None)
2355 cert_reqs=ssl.CERT_NONE, ca_certs=None)
2356
2356
2357 try:
2357 try:
2358 s.connect(addr)
2358 s.connect(addr)
2359 cert = s.getpeercert(True)
2359 cert = s.getpeercert(True)
2360
2360
2361 ui.status(_('checking the certificate chain for %s\n') % url.host)
2361 ui.status(_('checking the certificate chain for %s\n') % url.host)
2362
2362
2363 complete = win32.checkcertificatechain(cert, build=False)
2363 complete = win32.checkcertificatechain(cert, build=False)
2364
2364
2365 if not complete:
2365 if not complete:
2366 ui.status(_('certificate chain is incomplete, updating... '))
2366 ui.status(_('certificate chain is incomplete, updating... '))
2367
2367
2368 if not win32.checkcertificatechain(cert):
2368 if not win32.checkcertificatechain(cert):
2369 ui.status(_('failed.\n'))
2369 ui.status(_('failed.\n'))
2370 else:
2370 else:
2371 ui.status(_('done.\n'))
2371 ui.status(_('done.\n'))
2372 else:
2372 else:
2373 ui.status(_('full certificate chain is available\n'))
2373 ui.status(_('full certificate chain is available\n'))
2374 finally:
2374 finally:
2375 s.close()
2375 s.close()
2376
2376
2377 @command('debugsub',
2377 @command('debugsub',
2378 [('r', 'rev', '',
2378 [('r', 'rev', '',
2379 _('revision to check'), _('REV'))],
2379 _('revision to check'), _('REV'))],
2380 _('[-r REV] [REV]'))
2380 _('[-r REV] [REV]'))
2381 def debugsub(ui, repo, rev=None):
2381 def debugsub(ui, repo, rev=None):
2382 ctx = scmutil.revsingle(repo, rev, None)
2382 ctx = scmutil.revsingle(repo, rev, None)
2383 for k, v in sorted(ctx.substate.items()):
2383 for k, v in sorted(ctx.substate.items()):
2384 ui.write(('path %s\n') % k)
2384 ui.write(('path %s\n') % k)
2385 ui.write((' source %s\n') % v[0])
2385 ui.write((' source %s\n') % v[0])
2386 ui.write((' revision %s\n') % v[1])
2386 ui.write((' revision %s\n') % v[1])
2387
2387
2388 @command('debugsuccessorssets',
2388 @command('debugsuccessorssets',
2389 [('', 'closest', False, _('return closest successors sets only'))],
2389 [('', 'closest', False, _('return closest successors sets only'))],
2390 _('[REV]'))
2390 _('[REV]'))
2391 def debugsuccessorssets(ui, repo, *revs, **opts):
2391 def debugsuccessorssets(ui, repo, *revs, **opts):
2392 """show set of successors for revision
2392 """show set of successors for revision
2393
2393
2394 A successors set of changeset A is a consistent group of revisions that
2394 A successors set of changeset A is a consistent group of revisions that
2395 succeed A. It contains non-obsolete changesets only unless closests
2395 succeed A. It contains non-obsolete changesets only unless closests
2396 successors set is set.
2396 successors set is set.
2397
2397
2398 In most cases a changeset A has a single successors set containing a single
2398 In most cases a changeset A has a single successors set containing a single
2399 successor (changeset A replaced by A').
2399 successor (changeset A replaced by A').
2400
2400
2401 A changeset that is made obsolete with no successors are called "pruned".
2401 A changeset that is made obsolete with no successors are called "pruned".
2402 Such changesets have no successors sets at all.
2402 Such changesets have no successors sets at all.
2403
2403
2404 A changeset that has been "split" will have a successors set containing
2404 A changeset that has been "split" will have a successors set containing
2405 more than one successor.
2405 more than one successor.
2406
2406
2407 A changeset that has been rewritten in multiple different ways is called
2407 A changeset that has been rewritten in multiple different ways is called
2408 "divergent". Such changesets have multiple successor sets (each of which
2408 "divergent". Such changesets have multiple successor sets (each of which
2409 may also be split, i.e. have multiple successors).
2409 may also be split, i.e. have multiple successors).
2410
2410
2411 Results are displayed as follows::
2411 Results are displayed as follows::
2412
2412
2413 <rev1>
2413 <rev1>
2414 <successors-1A>
2414 <successors-1A>
2415 <rev2>
2415 <rev2>
2416 <successors-2A>
2416 <successors-2A>
2417 <successors-2B1> <successors-2B2> <successors-2B3>
2417 <successors-2B1> <successors-2B2> <successors-2B3>
2418
2418
2419 Here rev2 has two possible (i.e. divergent) successors sets. The first
2419 Here rev2 has two possible (i.e. divergent) successors sets. The first
2420 holds one element, whereas the second holds three (i.e. the changeset has
2420 holds one element, whereas the second holds three (i.e. the changeset has
2421 been split).
2421 been split).
2422 """
2422 """
2423 # passed to successorssets caching computation from one call to another
2423 # passed to successorssets caching computation from one call to another
2424 cache = {}
2424 cache = {}
2425 ctx2str = bytes
2425 ctx2str = bytes
2426 node2str = short
2426 node2str = short
2427 for rev in scmutil.revrange(repo, revs):
2427 for rev in scmutil.revrange(repo, revs):
2428 ctx = repo[rev]
2428 ctx = repo[rev]
2429 ui.write('%s\n'% ctx2str(ctx))
2429 ui.write('%s\n'% ctx2str(ctx))
2430 for succsset in obsutil.successorssets(repo, ctx.node(),
2430 for succsset in obsutil.successorssets(repo, ctx.node(),
2431 closest=opts[r'closest'],
2431 closest=opts[r'closest'],
2432 cache=cache):
2432 cache=cache):
2433 if succsset:
2433 if succsset:
2434 ui.write(' ')
2434 ui.write(' ')
2435 ui.write(node2str(succsset[0]))
2435 ui.write(node2str(succsset[0]))
2436 for node in succsset[1:]:
2436 for node in succsset[1:]:
2437 ui.write(' ')
2437 ui.write(' ')
2438 ui.write(node2str(node))
2438 ui.write(node2str(node))
2439 ui.write('\n')
2439 ui.write('\n')
2440
2440
2441 @command('debugtemplate',
2441 @command('debugtemplate',
2442 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
2442 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
2443 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
2443 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
2444 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
2444 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
2445 optionalrepo=True)
2445 optionalrepo=True)
2446 def debugtemplate(ui, repo, tmpl, **opts):
2446 def debugtemplate(ui, repo, tmpl, **opts):
2447 """parse and apply a template
2447 """parse and apply a template
2448
2448
2449 If -r/--rev is given, the template is processed as a log template and
2449 If -r/--rev is given, the template is processed as a log template and
2450 applied to the given changesets. Otherwise, it is processed as a generic
2450 applied to the given changesets. Otherwise, it is processed as a generic
2451 template.
2451 template.
2452
2452
2453 Use --verbose to print the parsed tree.
2453 Use --verbose to print the parsed tree.
2454 """
2454 """
2455 revs = None
2455 revs = None
2456 if opts[r'rev']:
2456 if opts[r'rev']:
2457 if repo is None:
2457 if repo is None:
2458 raise error.RepoError(_('there is no Mercurial repository here '
2458 raise error.RepoError(_('there is no Mercurial repository here '
2459 '(.hg not found)'))
2459 '(.hg not found)'))
2460 revs = scmutil.revrange(repo, opts[r'rev'])
2460 revs = scmutil.revrange(repo, opts[r'rev'])
2461
2461
2462 props = {}
2462 props = {}
2463 for d in opts[r'define']:
2463 for d in opts[r'define']:
2464 try:
2464 try:
2465 k, v = (e.strip() for e in d.split('=', 1))
2465 k, v = (e.strip() for e in d.split('=', 1))
2466 if not k or k == 'ui':
2466 if not k or k == 'ui':
2467 raise ValueError
2467 raise ValueError
2468 props[k] = v
2468 props[k] = v
2469 except ValueError:
2469 except ValueError:
2470 raise error.Abort(_('malformed keyword definition: %s') % d)
2470 raise error.Abort(_('malformed keyword definition: %s') % d)
2471
2471
2472 if ui.verbose:
2472 if ui.verbose:
2473 aliases = ui.configitems('templatealias')
2473 aliases = ui.configitems('templatealias')
2474 tree = templater.parse(tmpl)
2474 tree = templater.parse(tmpl)
2475 ui.note(templater.prettyformat(tree), '\n')
2475 ui.note(templater.prettyformat(tree), '\n')
2476 newtree = templater.expandaliases(tree, aliases)
2476 newtree = templater.expandaliases(tree, aliases)
2477 if newtree != tree:
2477 if newtree != tree:
2478 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
2478 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
2479
2479
2480 if revs is None:
2480 if revs is None:
2481 tres = formatter.templateresources(ui, repo)
2481 tres = formatter.templateresources(ui, repo)
2482 t = formatter.maketemplater(ui, tmpl, resources=tres)
2482 t = formatter.maketemplater(ui, tmpl, resources=tres)
2483 ui.write(t.renderdefault(props))
2483 ui.write(t.renderdefault(props))
2484 else:
2484 else:
2485 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
2485 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
2486 for r in revs:
2486 for r in revs:
2487 displayer.show(repo[r], **pycompat.strkwargs(props))
2487 displayer.show(repo[r], **pycompat.strkwargs(props))
2488 displayer.close()
2488 displayer.close()
2489
2489
2490 @command('debuguigetpass', [
2490 @command('debuguigetpass', [
2491 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2491 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2492 ], _('[-p TEXT]'), norepo=True)
2492 ], _('[-p TEXT]'), norepo=True)
2493 def debuguigetpass(ui, prompt=''):
2493 def debuguigetpass(ui, prompt=''):
2494 """show prompt to type password"""
2494 """show prompt to type password"""
2495 r = ui.getpass(prompt)
2495 r = ui.getpass(prompt)
2496 ui.write(('respose: %s\n') % r)
2496 ui.write(('respose: %s\n') % r)
2497
2497
2498 @command('debuguiprompt', [
2498 @command('debuguiprompt', [
2499 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2499 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2500 ], _('[-p TEXT]'), norepo=True)
2500 ], _('[-p TEXT]'), norepo=True)
2501 def debuguiprompt(ui, prompt=''):
2501 def debuguiprompt(ui, prompt=''):
2502 """show plain prompt"""
2502 """show plain prompt"""
2503 r = ui.prompt(prompt)
2503 r = ui.prompt(prompt)
2504 ui.write(('response: %s\n') % r)
2504 ui.write(('response: %s\n') % r)
2505
2505
2506 @command('debugupdatecaches', [])
2506 @command('debugupdatecaches', [])
2507 def debugupdatecaches(ui, repo, *pats, **opts):
2507 def debugupdatecaches(ui, repo, *pats, **opts):
2508 """warm all known caches in the repository"""
2508 """warm all known caches in the repository"""
2509 with repo.wlock(), repo.lock():
2509 with repo.wlock(), repo.lock():
2510 repo.updatecaches(full=True)
2510 repo.updatecaches(full=True)
2511
2511
2512 @command('debugupgraderepo', [
2512 @command('debugupgraderepo', [
2513 ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
2513 ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
2514 ('', 'run', False, _('performs an upgrade')),
2514 ('', 'run', False, _('performs an upgrade')),
2515 ])
2515 ])
2516 def debugupgraderepo(ui, repo, run=False, optimize=None):
2516 def debugupgraderepo(ui, repo, run=False, optimize=None):
2517 """upgrade a repository to use different features
2517 """upgrade a repository to use different features
2518
2518
2519 If no arguments are specified, the repository is evaluated for upgrade
2519 If no arguments are specified, the repository is evaluated for upgrade
2520 and a list of problems and potential optimizations is printed.
2520 and a list of problems and potential optimizations is printed.
2521
2521
2522 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
2522 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
2523 can be influenced via additional arguments. More details will be provided
2523 can be influenced via additional arguments. More details will be provided
2524 by the command output when run without ``--run``.
2524 by the command output when run without ``--run``.
2525
2525
2526 During the upgrade, the repository will be locked and no writes will be
2526 During the upgrade, the repository will be locked and no writes will be
2527 allowed.
2527 allowed.
2528
2528
2529 At the end of the upgrade, the repository may not be readable while new
2529 At the end of the upgrade, the repository may not be readable while new
2530 repository data is swapped in. This window will be as long as it takes to
2530 repository data is swapped in. This window will be as long as it takes to
2531 rename some directories inside the ``.hg`` directory. On most machines, this
2531 rename some directories inside the ``.hg`` directory. On most machines, this
2532 should complete almost instantaneously and the chances of a consumer being
2532 should complete almost instantaneously and the chances of a consumer being
2533 unable to access the repository should be low.
2533 unable to access the repository should be low.
2534 """
2534 """
2535 return upgrade.upgraderepo(ui, repo, run=run, optimize=optimize)
2535 return upgrade.upgraderepo(ui, repo, run=run, optimize=optimize)
2536
2536
2537 @command('debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'),
2537 @command('debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'),
2538 inferrepo=True)
2538 inferrepo=True)
2539 def debugwalk(ui, repo, *pats, **opts):
2539 def debugwalk(ui, repo, *pats, **opts):
2540 """show how files match on given patterns"""
2540 """show how files match on given patterns"""
2541 opts = pycompat.byteskwargs(opts)
2541 opts = pycompat.byteskwargs(opts)
2542 m = scmutil.match(repo[None], pats, opts)
2542 m = scmutil.match(repo[None], pats, opts)
2543 ui.write(('matcher: %r\n' % m))
2543 ui.write(('matcher: %r\n' % m))
2544 items = list(repo[None].walk(m))
2544 items = list(repo[None].walk(m))
2545 if not items:
2545 if not items:
2546 return
2546 return
2547 f = lambda fn: fn
2547 f = lambda fn: fn
2548 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
2548 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
2549 f = lambda fn: util.normpath(fn)
2549 f = lambda fn: util.normpath(fn)
2550 fmt = 'f %%-%ds %%-%ds %%s' % (
2550 fmt = 'f %%-%ds %%-%ds %%s' % (
2551 max([len(abs) for abs in items]),
2551 max([len(abs) for abs in items]),
2552 max([len(m.rel(abs)) for abs in items]))
2552 max([len(m.rel(abs)) for abs in items]))
2553 for abs in items:
2553 for abs in items:
2554 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2554 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2555 ui.write("%s\n" % line.rstrip())
2555 ui.write("%s\n" % line.rstrip())
2556
2556
2557 @command('debugwhyunstable', [], _('REV'))
2557 @command('debugwhyunstable', [], _('REV'))
2558 def debugwhyunstable(ui, repo, rev):
2558 def debugwhyunstable(ui, repo, rev):
2559 """explain instabilities of a changeset"""
2559 """explain instabilities of a changeset"""
2560 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
2560 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
2561 dnodes = ''
2561 dnodes = ''
2562 if entry.get('divergentnodes'):
2562 if entry.get('divergentnodes'):
2563 dnodes = ' '.join('%s (%s)' % (ctx.hex(), ctx.phasestr())
2563 dnodes = ' '.join('%s (%s)' % (ctx.hex(), ctx.phasestr())
2564 for ctx in entry['divergentnodes']) + ' '
2564 for ctx in entry['divergentnodes']) + ' '
2565 ui.write('%s: %s%s %s\n' % (entry['instability'], dnodes,
2565 ui.write('%s: %s%s %s\n' % (entry['instability'], dnodes,
2566 entry['reason'], entry['node']))
2566 entry['reason'], entry['node']))
2567
2567
2568 @command('debugwireargs',
2568 @command('debugwireargs',
2569 [('', 'three', '', 'three'),
2569 [('', 'three', '', 'three'),
2570 ('', 'four', '', 'four'),
2570 ('', 'four', '', 'four'),
2571 ('', 'five', '', 'five'),
2571 ('', 'five', '', 'five'),
2572 ] + cmdutil.remoteopts,
2572 ] + cmdutil.remoteopts,
2573 _('REPO [OPTIONS]... [ONE [TWO]]'),
2573 _('REPO [OPTIONS]... [ONE [TWO]]'),
2574 norepo=True)
2574 norepo=True)
2575 def debugwireargs(ui, repopath, *vals, **opts):
2575 def debugwireargs(ui, repopath, *vals, **opts):
2576 opts = pycompat.byteskwargs(opts)
2576 opts = pycompat.byteskwargs(opts)
2577 repo = hg.peer(ui, opts, repopath)
2577 repo = hg.peer(ui, opts, repopath)
2578 for opt in cmdutil.remoteopts:
2578 for opt in cmdutil.remoteopts:
2579 del opts[opt[1]]
2579 del opts[opt[1]]
2580 args = {}
2580 args = {}
2581 for k, v in opts.iteritems():
2581 for k, v in opts.iteritems():
2582 if v:
2582 if v:
2583 args[k] = v
2583 args[k] = v
2584 args = pycompat.strkwargs(args)
2584 args = pycompat.strkwargs(args)
2585 # run twice to check that we don't mess up the stream for the next command
2585 # run twice to check that we don't mess up the stream for the next command
2586 res1 = repo.debugwireargs(*vals, **args)
2586 res1 = repo.debugwireargs(*vals, **args)
2587 res2 = repo.debugwireargs(*vals, **args)
2587 res2 = repo.debugwireargs(*vals, **args)
2588 ui.write("%s\n" % res1)
2588 ui.write("%s\n" % res1)
2589 if res1 != res2:
2589 if res1 != res2:
2590 ui.warn("%s\n" % res2)
2590 ui.warn("%s\n" % res2)
2591
2591
2592 def _parsewirelangblocks(fh):
2592 def _parsewirelangblocks(fh):
2593 activeaction = None
2593 activeaction = None
2594 blocklines = []
2594 blocklines = []
2595
2595
2596 for line in fh:
2596 for line in fh:
2597 line = line.rstrip()
2597 line = line.rstrip()
2598 if not line:
2598 if not line:
2599 continue
2599 continue
2600
2600
2601 if line.startswith(b'#'):
2601 if line.startswith(b'#'):
2602 continue
2602 continue
2603
2603
2604 if not line.startswith(' '):
2604 if not line.startswith(' '):
2605 # New block. Flush previous one.
2605 # New block. Flush previous one.
2606 if activeaction:
2606 if activeaction:
2607 yield activeaction, blocklines
2607 yield activeaction, blocklines
2608
2608
2609 activeaction = line
2609 activeaction = line
2610 blocklines = []
2610 blocklines = []
2611 continue
2611 continue
2612
2612
2613 # Else we start with an indent.
2613 # Else we start with an indent.
2614
2614
2615 if not activeaction:
2615 if not activeaction:
2616 raise error.Abort(_('indented line outside of block'))
2616 raise error.Abort(_('indented line outside of block'))
2617
2617
2618 blocklines.append(line)
2618 blocklines.append(line)
2619
2619
2620 # Flush last block.
2620 # Flush last block.
2621 if activeaction:
2621 if activeaction:
2622 yield activeaction, blocklines
2622 yield activeaction, blocklines
2623
2623
2624 @command('debugwireproto',
2624 @command('debugwireproto',
2625 [
2625 [
2626 ('', 'localssh', False, _('start an SSH server for this repo')),
2626 ('', 'localssh', False, _('start an SSH server for this repo')),
2627 ('', 'peer', '', _('construct a specific version of the peer')),
2627 ('', 'peer', '', _('construct a specific version of the peer')),
2628 ('', 'noreadstderr', False, _('do not read from stderr of the remote')),
2628 ('', 'noreadstderr', False, _('do not read from stderr of the remote')),
2629 ] + cmdutil.remoteopts,
2629 ] + cmdutil.remoteopts,
2630 _('[PATH]'),
2630 _('[PATH]'),
2631 optionalrepo=True)
2631 optionalrepo=True)
2632 def debugwireproto(ui, repo, path=None, **opts):
2632 def debugwireproto(ui, repo, path=None, **opts):
2633 """send wire protocol commands to a server
2633 """send wire protocol commands to a server
2634
2634
2635 This command can be used to issue wire protocol commands to remote
2635 This command can be used to issue wire protocol commands to remote
2636 peers and to debug the raw data being exchanged.
2636 peers and to debug the raw data being exchanged.
2637
2637
2638 ``--localssh`` will start an SSH server against the current repository
2638 ``--localssh`` will start an SSH server against the current repository
2639 and connect to that. By default, the connection will perform a handshake
2639 and connect to that. By default, the connection will perform a handshake
2640 and establish an appropriate peer instance.
2640 and establish an appropriate peer instance.
2641
2641
2642 ``--peer`` can be used to bypass the handshake protocol and construct a
2642 ``--peer`` can be used to bypass the handshake protocol and construct a
2643 peer instance using the specified class type. Valid values are ``raw``,
2643 peer instance using the specified class type. Valid values are ``raw``,
2644 ``http2``, ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending
2644 ``http2``, ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending
2645 raw data payloads and don't support higher-level command actions.
2645 raw data payloads and don't support higher-level command actions.
2646
2646
2647 ``--noreadstderr`` can be used to disable automatic reading from stderr
2647 ``--noreadstderr`` can be used to disable automatic reading from stderr
2648 of the peer (for SSH connections only). Disabling automatic reading of
2648 of the peer (for SSH connections only). Disabling automatic reading of
2649 stderr is useful for making output more deterministic.
2649 stderr is useful for making output more deterministic.
2650
2650
2651 Commands are issued via a mini language which is specified via stdin.
2651 Commands are issued via a mini language which is specified via stdin.
2652 The language consists of individual actions to perform. An action is
2652 The language consists of individual actions to perform. An action is
2653 defined by a block. A block is defined as a line with no leading
2653 defined by a block. A block is defined as a line with no leading
2654 space followed by 0 or more lines with leading space. Blocks are
2654 space followed by 0 or more lines with leading space. Blocks are
2655 effectively a high-level command with additional metadata.
2655 effectively a high-level command with additional metadata.
2656
2656
2657 Lines beginning with ``#`` are ignored.
2657 Lines beginning with ``#`` are ignored.
2658
2658
2659 The following sections denote available actions.
2659 The following sections denote available actions.
2660
2660
2661 raw
2661 raw
2662 ---
2662 ---
2663
2663
2664 Send raw data to the server.
2664 Send raw data to the server.
2665
2665
2666 The block payload contains the raw data to send as one atomic send
2666 The block payload contains the raw data to send as one atomic send
2667 operation. The data may not actually be delivered in a single system
2667 operation. The data may not actually be delivered in a single system
2668 call: it depends on the abilities of the transport being used.
2668 call: it depends on the abilities of the transport being used.
2669
2669
2670 Each line in the block is de-indented and concatenated. Then, that
2670 Each line in the block is de-indented and concatenated. Then, that
2671 value is evaluated as a Python b'' literal. This allows the use of
2671 value is evaluated as a Python b'' literal. This allows the use of
2672 backslash escaping, etc.
2672 backslash escaping, etc.
2673
2673
2674 raw+
2674 raw+
2675 ----
2675 ----
2676
2676
2677 Behaves like ``raw`` except flushes output afterwards.
2677 Behaves like ``raw`` except flushes output afterwards.
2678
2678
2679 command <X>
2679 command <X>
2680 -----------
2680 -----------
2681
2681
2682 Send a request to run a named command, whose name follows the ``command``
2682 Send a request to run a named command, whose name follows the ``command``
2683 string.
2683 string.
2684
2684
2685 Arguments to the command are defined as lines in this block. The format of
2685 Arguments to the command are defined as lines in this block. The format of
2686 each line is ``<key> <value>``. e.g.::
2686 each line is ``<key> <value>``. e.g.::
2687
2687
2688 command listkeys
2688 command listkeys
2689 namespace bookmarks
2689 namespace bookmarks
2690
2690
2691 If the value begins with ``eval:``, it will be interpreted as a Python
2691 If the value begins with ``eval:``, it will be interpreted as a Python
2692 literal expression. Otherwise values are interpreted as Python b'' literals.
2692 literal expression. Otherwise values are interpreted as Python b'' literals.
2693 This allows sending complex types and encoding special byte sequences via
2693 This allows sending complex types and encoding special byte sequences via
2694 backslash escaping.
2694 backslash escaping.
2695
2695
2696 The following arguments have special meaning:
2696 The following arguments have special meaning:
2697
2697
2698 ``PUSHFILE``
2698 ``PUSHFILE``
2699 When defined, the *push* mechanism of the peer will be used instead
2699 When defined, the *push* mechanism of the peer will be used instead
2700 of the static request-response mechanism and the content of the
2700 of the static request-response mechanism and the content of the
2701 file specified in the value of this argument will be sent as the
2701 file specified in the value of this argument will be sent as the
2702 command payload.
2702 command payload.
2703
2703
2704 This can be used to submit a local bundle file to the remote.
2704 This can be used to submit a local bundle file to the remote.
2705
2705
2706 batchbegin
2706 batchbegin
2707 ----------
2707 ----------
2708
2708
2709 Instruct the peer to begin a batched send.
2709 Instruct the peer to begin a batched send.
2710
2710
2711 All ``command`` blocks are queued for execution until the next
2711 All ``command`` blocks are queued for execution until the next
2712 ``batchsubmit`` block.
2712 ``batchsubmit`` block.
2713
2713
2714 batchsubmit
2714 batchsubmit
2715 -----------
2715 -----------
2716
2716
2717 Submit previously queued ``command`` blocks as a batch request.
2717 Submit previously queued ``command`` blocks as a batch request.
2718
2718
2719 This action MUST be paired with a ``batchbegin`` action.
2719 This action MUST be paired with a ``batchbegin`` action.
2720
2720
2721 httprequest <method> <path>
2721 httprequest <method> <path>
2722 ---------------------------
2722 ---------------------------
2723
2723
2724 (HTTP peer only)
2724 (HTTP peer only)
2725
2725
2726 Send an HTTP request to the peer.
2726 Send an HTTP request to the peer.
2727
2727
2728 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
2728 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
2729
2729
2730 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
2730 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
2731 headers to add to the request. e.g. ``Accept: foo``.
2731 headers to add to the request. e.g. ``Accept: foo``.
2732
2732
2733 The following arguments are special:
2733 The following arguments are special:
2734
2734
2735 ``BODYFILE``
2735 ``BODYFILE``
2736 The content of the file defined as the value to this argument will be
2736 The content of the file defined as the value to this argument will be
2737 transferred verbatim as the HTTP request body.
2737 transferred verbatim as the HTTP request body.
2738
2738
2739 ``frame <type> <flags> <payload>``
2739 ``frame <type> <flags> <payload>``
2740 Send a unified protocol frame as part of the request body.
2740 Send a unified protocol frame as part of the request body.
2741
2741
2742 All frames will be collected and sent as the body to the HTTP
2742 All frames will be collected and sent as the body to the HTTP
2743 request.
2743 request.
2744
2744
2745 close
2745 close
2746 -----
2746 -----
2747
2747
2748 Close the connection to the server.
2748 Close the connection to the server.
2749
2749
2750 flush
2750 flush
2751 -----
2751 -----
2752
2752
2753 Flush data written to the server.
2753 Flush data written to the server.
2754
2754
2755 readavailable
2755 readavailable
2756 -------------
2756 -------------
2757
2757
2758 Close the write end of the connection and read all available data from
2758 Close the write end of the connection and read all available data from
2759 the server.
2759 the server.
2760
2760
2761 If the connection to the server encompasses multiple pipes, we poll both
2761 If the connection to the server encompasses multiple pipes, we poll both
2762 pipes and read available data.
2762 pipes and read available data.
2763
2763
2764 readline
2764 readline
2765 --------
2765 --------
2766
2766
2767 Read a line of output from the server. If there are multiple output
2767 Read a line of output from the server. If there are multiple output
2768 pipes, reads only the main pipe.
2768 pipes, reads only the main pipe.
2769
2769
2770 ereadline
2770 ereadline
2771 ---------
2771 ---------
2772
2772
2773 Like ``readline``, but read from the stderr pipe, if available.
2773 Like ``readline``, but read from the stderr pipe, if available.
2774
2774
2775 read <X>
2775 read <X>
2776 --------
2776 --------
2777
2777
2778 ``read()`` N bytes from the server's main output pipe.
2778 ``read()`` N bytes from the server's main output pipe.
2779
2779
2780 eread <X>
2780 eread <X>
2781 ---------
2781 ---------
2782
2782
2783 ``read()`` N bytes from the server's stderr pipe, if available.
2783 ``read()`` N bytes from the server's stderr pipe, if available.
2784
2784
2785 Specifying Unified Frame-Based Protocol Frames
2785 Specifying Unified Frame-Based Protocol Frames
2786 ----------------------------------------------
2786 ----------------------------------------------
2787
2787
2788 It is possible to emit a *Unified Frame-Based Protocol* by using special
2788 It is possible to emit a *Unified Frame-Based Protocol* by using special
2789 syntax.
2789 syntax.
2790
2790
2791 A frame is composed as a type, flags, and payload. These can be parsed
2791 A frame is composed as a type, flags, and payload. These can be parsed
2792 from a string of the form:
2792 from a string of the form:
2793
2793
2794 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
2794 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
2795
2795
2796 ``request-id`` and ``stream-id`` are integers defining the request and
2796 ``request-id`` and ``stream-id`` are integers defining the request and
2797 stream identifiers.
2797 stream identifiers.
2798
2798
2799 ``type`` can be an integer value for the frame type or the string name
2799 ``type`` can be an integer value for the frame type or the string name
2800 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
2800 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
2801 ``command-name``.
2801 ``command-name``.
2802
2802
2803 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
2803 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
2804 components. Each component (and there can be just one) can be an integer
2804 components. Each component (and there can be just one) can be an integer
2805 or a flag name for stream flags or frame flags, respectively. Values are
2805 or a flag name for stream flags or frame flags, respectively. Values are
2806 resolved to integers and then bitwise OR'd together.
2806 resolved to integers and then bitwise OR'd together.
2807
2807
2808 ``payload`` represents the raw frame payload. If it begins with
2808 ``payload`` represents the raw frame payload. If it begins with
2809 ``cbor:``, the following string is evaluated as Python code and the
2809 ``cbor:``, the following string is evaluated as Python code and the
2810 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
2810 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
2811 as a Python byte string literal.
2811 as a Python byte string literal.
2812 """
2812 """
2813 opts = pycompat.byteskwargs(opts)
2813 opts = pycompat.byteskwargs(opts)
2814
2814
2815 if opts['localssh'] and not repo:
2815 if opts['localssh'] and not repo:
2816 raise error.Abort(_('--localssh requires a repository'))
2816 raise error.Abort(_('--localssh requires a repository'))
2817
2817
2818 if opts['peer'] and opts['peer'] not in ('raw', 'http2', 'ssh1', 'ssh2'):
2818 if opts['peer'] and opts['peer'] not in ('raw', 'http2', 'ssh1', 'ssh2'):
2819 raise error.Abort(_('invalid value for --peer'),
2819 raise error.Abort(_('invalid value for --peer'),
2820 hint=_('valid values are "raw", "ssh1", and "ssh2"'))
2820 hint=_('valid values are "raw", "ssh1", and "ssh2"'))
2821
2821
2822 if path and opts['localssh']:
2822 if path and opts['localssh']:
2823 raise error.Abort(_('cannot specify --localssh with an explicit '
2823 raise error.Abort(_('cannot specify --localssh with an explicit '
2824 'path'))
2824 'path'))
2825
2825
2826 if ui.interactive():
2826 if ui.interactive():
2827 ui.write(_('(waiting for commands on stdin)\n'))
2827 ui.write(_('(waiting for commands on stdin)\n'))
2828
2828
2829 blocks = list(_parsewirelangblocks(ui.fin))
2829 blocks = list(_parsewirelangblocks(ui.fin))
2830
2830
2831 proc = None
2831 proc = None
2832 stdin = None
2832 stdin = None
2833 stdout = None
2833 stdout = None
2834 stderr = None
2834 stderr = None
2835 opener = None
2835 opener = None
2836
2836
2837 if opts['localssh']:
2837 if opts['localssh']:
2838 # We start the SSH server in its own process so there is process
2838 # We start the SSH server in its own process so there is process
2839 # separation. This prevents a whole class of potential bugs around
2839 # separation. This prevents a whole class of potential bugs around
2840 # shared state from interfering with server operation.
2840 # shared state from interfering with server operation.
2841 args = procutil.hgcmd() + [
2841 args = procutil.hgcmd() + [
2842 '-R', repo.root,
2842 '-R', repo.root,
2843 'debugserve', '--sshstdio',
2843 'debugserve', '--sshstdio',
2844 ]
2844 ]
2845 proc = subprocess.Popen(args, stdin=subprocess.PIPE,
2845 proc = subprocess.Popen(args, stdin=subprocess.PIPE,
2846 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
2846 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
2847 bufsize=0)
2847 bufsize=0)
2848
2848
2849 stdin = proc.stdin
2849 stdin = proc.stdin
2850 stdout = proc.stdout
2850 stdout = proc.stdout
2851 stderr = proc.stderr
2851 stderr = proc.stderr
2852
2852
2853 # We turn the pipes into observers so we can log I/O.
2853 # We turn the pipes into observers so we can log I/O.
2854 if ui.verbose or opts['peer'] == 'raw':
2854 if ui.verbose or opts['peer'] == 'raw':
2855 stdin = util.makeloggingfileobject(ui, proc.stdin, b'i',
2855 stdin = util.makeloggingfileobject(ui, proc.stdin, b'i',
2856 logdata=True)
2856 logdata=True)
2857 stdout = util.makeloggingfileobject(ui, proc.stdout, b'o',
2857 stdout = util.makeloggingfileobject(ui, proc.stdout, b'o',
2858 logdata=True)
2858 logdata=True)
2859 stderr = util.makeloggingfileobject(ui, proc.stderr, b'e',
2859 stderr = util.makeloggingfileobject(ui, proc.stderr, b'e',
2860 logdata=True)
2860 logdata=True)
2861
2861
2862 # --localssh also implies the peer connection settings.
2862 # --localssh also implies the peer connection settings.
2863
2863
2864 url = 'ssh://localserver'
2864 url = 'ssh://localserver'
2865 autoreadstderr = not opts['noreadstderr']
2865 autoreadstderr = not opts['noreadstderr']
2866
2866
2867 if opts['peer'] == 'ssh1':
2867 if opts['peer'] == 'ssh1':
2868 ui.write(_('creating ssh peer for wire protocol version 1\n'))
2868 ui.write(_('creating ssh peer for wire protocol version 1\n'))
2869 peer = sshpeer.sshv1peer(ui, url, proc, stdin, stdout, stderr,
2869 peer = sshpeer.sshv1peer(ui, url, proc, stdin, stdout, stderr,
2870 None, autoreadstderr=autoreadstderr)
2870 None, autoreadstderr=autoreadstderr)
2871 elif opts['peer'] == 'ssh2':
2871 elif opts['peer'] == 'ssh2':
2872 ui.write(_('creating ssh peer for wire protocol version 2\n'))
2872 ui.write(_('creating ssh peer for wire protocol version 2\n'))
2873 peer = sshpeer.sshv2peer(ui, url, proc, stdin, stdout, stderr,
2873 peer = sshpeer.sshv2peer(ui, url, proc, stdin, stdout, stderr,
2874 None, autoreadstderr=autoreadstderr)
2874 None, autoreadstderr=autoreadstderr)
2875 elif opts['peer'] == 'raw':
2875 elif opts['peer'] == 'raw':
2876 ui.write(_('using raw connection to peer\n'))
2876 ui.write(_('using raw connection to peer\n'))
2877 peer = None
2877 peer = None
2878 else:
2878 else:
2879 ui.write(_('creating ssh peer from handshake results\n'))
2879 ui.write(_('creating ssh peer from handshake results\n'))
2880 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr,
2880 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr,
2881 autoreadstderr=autoreadstderr)
2881 autoreadstderr=autoreadstderr)
2882
2882
2883 elif path:
2883 elif path:
2884 # We bypass hg.peer() so we can proxy the sockets.
2884 # We bypass hg.peer() so we can proxy the sockets.
2885 # TODO consider not doing this because we skip
2885 # TODO consider not doing this because we skip
2886 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
2886 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
2887 u = util.url(path)
2887 u = util.url(path)
2888 if u.scheme != 'http':
2888 if u.scheme != 'http':
2889 raise error.Abort(_('only http:// paths are currently supported'))
2889 raise error.Abort(_('only http:// paths are currently supported'))
2890
2890
2891 url, authinfo = u.authinfo()
2891 url, authinfo = u.authinfo()
2892 openerargs = {
2892 openerargs = {
2893 r'useragent': b'Mercurial debugwireproto',
2893 r'useragent': b'Mercurial debugwireproto',
2894 }
2894 }
2895
2895
2896 # Turn pipes/sockets into observers so we can log I/O.
2896 # Turn pipes/sockets into observers so we can log I/O.
2897 if ui.verbose:
2897 if ui.verbose:
2898 openerargs.update({
2898 openerargs.update({
2899 r'loggingfh': ui,
2899 r'loggingfh': ui,
2900 r'loggingname': b's',
2900 r'loggingname': b's',
2901 r'loggingopts': {
2901 r'loggingopts': {
2902 r'logdata': True,
2902 r'logdata': True,
2903 r'logdataapis': False,
2903 r'logdataapis': False,
2904 },
2904 },
2905 })
2905 })
2906
2906
2907 if ui.debugflag:
2907 if ui.debugflag:
2908 openerargs[r'loggingopts'][r'logdataapis'] = True
2908 openerargs[r'loggingopts'][r'logdataapis'] = True
2909
2909
2910 # Don't send default headers when in raw mode. This allows us to
2910 # Don't send default headers when in raw mode. This allows us to
2911 # bypass most of the behavior of our URL handling code so we can
2911 # bypass most of the behavior of our URL handling code so we can
2912 # have near complete control over what's sent on the wire.
2912 # have near complete control over what's sent on the wire.
2913 if opts['peer'] == 'raw':
2913 if opts['peer'] == 'raw':
2914 openerargs[r'sendaccept'] = False
2914 openerargs[r'sendaccept'] = False
2915
2915
2916 opener = urlmod.opener(ui, authinfo, **openerargs)
2916 opener = urlmod.opener(ui, authinfo, **openerargs)
2917
2917
2918 if opts['peer'] == 'http2':
2918 if opts['peer'] == 'http2':
2919 ui.write(_('creating http peer for wire protocol version 2\n'))
2919 ui.write(_('creating http peer for wire protocol version 2\n'))
2920 # We go through makepeer() because we need an API descriptor for
2920 # We go through makepeer() because we need an API descriptor for
2921 # the peer instance to be useful.
2921 # the peer instance to be useful.
2922 with ui.configoverride({
2922 with ui.configoverride({
2923 ('experimental', 'httppeer.advertise-v2'): True}):
2923 ('experimental', 'httppeer.advertise-v2'): True}):
2924 peer = httppeer.makepeer(ui, path, opener=opener)
2924 peer = httppeer.makepeer(ui, path, opener=opener)
2925
2925
2926 if not isinstance(peer, httppeer.httpv2peer):
2926 if not isinstance(peer, httppeer.httpv2peer):
2927 raise error.Abort(_('could not instantiate HTTP peer for '
2927 raise error.Abort(_('could not instantiate HTTP peer for '
2928 'wire protocol version 2'),
2928 'wire protocol version 2'),
2929 hint=_('the server may not have the feature '
2929 hint=_('the server may not have the feature '
2930 'enabled or is not allowing this '
2930 'enabled or is not allowing this '
2931 'client version'))
2931 'client version'))
2932
2932
2933 elif opts['peer'] == 'raw':
2933 elif opts['peer'] == 'raw':
2934 ui.write(_('using raw connection to peer\n'))
2934 ui.write(_('using raw connection to peer\n'))
2935 peer = None
2935 peer = None
2936 elif opts['peer']:
2936 elif opts['peer']:
2937 raise error.Abort(_('--peer %s not supported with HTTP peers') %
2937 raise error.Abort(_('--peer %s not supported with HTTP peers') %
2938 opts['peer'])
2938 opts['peer'])
2939 else:
2939 else:
2940 peer = httppeer.makepeer(ui, path, opener=opener)
2940 peer = httppeer.makepeer(ui, path, opener=opener)
2941
2941
2942 # We /could/ populate stdin/stdout with sock.makefile()...
2942 # We /could/ populate stdin/stdout with sock.makefile()...
2943 else:
2943 else:
2944 raise error.Abort(_('unsupported connection configuration'))
2944 raise error.Abort(_('unsupported connection configuration'))
2945
2945
2946 batchedcommands = None
2946 batchedcommands = None
2947
2947
2948 # Now perform actions based on the parsed wire language instructions.
2948 # Now perform actions based on the parsed wire language instructions.
2949 for action, lines in blocks:
2949 for action, lines in blocks:
2950 if action in ('raw', 'raw+'):
2950 if action in ('raw', 'raw+'):
2951 if not stdin:
2951 if not stdin:
2952 raise error.Abort(_('cannot call raw/raw+ on this peer'))
2952 raise error.Abort(_('cannot call raw/raw+ on this peer'))
2953
2953
2954 # Concatenate the data together.
2954 # Concatenate the data together.
2955 data = ''.join(l.lstrip() for l in lines)
2955 data = ''.join(l.lstrip() for l in lines)
2956 data = stringutil.unescapestr(data)
2956 data = stringutil.unescapestr(data)
2957 stdin.write(data)
2957 stdin.write(data)
2958
2958
2959 if action == 'raw+':
2959 if action == 'raw+':
2960 stdin.flush()
2960 stdin.flush()
2961 elif action == 'flush':
2961 elif action == 'flush':
2962 if not stdin:
2962 if not stdin:
2963 raise error.Abort(_('cannot call flush on this peer'))
2963 raise error.Abort(_('cannot call flush on this peer'))
2964 stdin.flush()
2964 stdin.flush()
2965 elif action.startswith('command'):
2965 elif action.startswith('command'):
2966 if not peer:
2966 if not peer:
2967 raise error.Abort(_('cannot send commands unless peer instance '
2967 raise error.Abort(_('cannot send commands unless peer instance '
2968 'is available'))
2968 'is available'))
2969
2969
2970 command = action.split(' ', 1)[1]
2970 command = action.split(' ', 1)[1]
2971
2971
2972 args = {}
2972 args = {}
2973 for line in lines:
2973 for line in lines:
2974 # We need to allow empty values.
2974 # We need to allow empty values.
2975 fields = line.lstrip().split(' ', 1)
2975 fields = line.lstrip().split(' ', 1)
2976 if len(fields) == 1:
2976 if len(fields) == 1:
2977 key = fields[0]
2977 key = fields[0]
2978 value = ''
2978 value = ''
2979 else:
2979 else:
2980 key, value = fields
2980 key, value = fields
2981
2981
2982 if value.startswith('eval:'):
2982 if value.startswith('eval:'):
2983 value = stringutil.evalpythonliteral(value[5:])
2983 value = stringutil.evalpythonliteral(value[5:])
2984 else:
2984 else:
2985 value = stringutil.unescapestr(value)
2985 value = stringutil.unescapestr(value)
2986
2986
2987 args[key] = value
2987 args[key] = value
2988
2988
2989 if batchedcommands is not None:
2989 if batchedcommands is not None:
2990 batchedcommands.append((command, args))
2990 batchedcommands.append((command, args))
2991 continue
2991 continue
2992
2992
2993 ui.status(_('sending %s command\n') % command)
2993 ui.status(_('sending %s command\n') % command)
2994
2994
2995 if 'PUSHFILE' in args:
2995 if 'PUSHFILE' in args:
2996 with open(args['PUSHFILE'], r'rb') as fh:
2996 with open(args['PUSHFILE'], r'rb') as fh:
2997 del args['PUSHFILE']
2997 del args['PUSHFILE']
2998 res, output = peer._callpush(command, fh,
2998 res, output = peer._callpush(command, fh,
2999 **pycompat.strkwargs(args))
2999 **pycompat.strkwargs(args))
3000 ui.status(_('result: %s\n') % stringutil.escapestr(res))
3000 ui.status(_('result: %s\n') % stringutil.escapestr(res))
3001 ui.status(_('remote output: %s\n') %
3001 ui.status(_('remote output: %s\n') %
3002 stringutil.escapestr(output))
3002 stringutil.escapestr(output))
3003 else:
3003 else:
3004 res = peer._call(command, **pycompat.strkwargs(args))
3004 with peer.commandexecutor() as e:
3005 res = e.callcommand(command, args).result()
3006
3005 ui.status(_('response: %s\n') % stringutil.pprint(res))
3007 ui.status(_('response: %s\n') % stringutil.pprint(res))
3006
3008
3007 elif action == 'batchbegin':
3009 elif action == 'batchbegin':
3008 if batchedcommands is not None:
3010 if batchedcommands is not None:
3009 raise error.Abort(_('nested batchbegin not allowed'))
3011 raise error.Abort(_('nested batchbegin not allowed'))
3010
3012
3011 batchedcommands = []
3013 batchedcommands = []
3012 elif action == 'batchsubmit':
3014 elif action == 'batchsubmit':
3013 # There is a batching API we could go through. But it would be
3015 # There is a batching API we could go through. But it would be
3014 # difficult to normalize requests into function calls. It is easier
3016 # difficult to normalize requests into function calls. It is easier
3015 # to bypass this layer and normalize to commands + args.
3017 # to bypass this layer and normalize to commands + args.
3016 ui.status(_('sending batch with %d sub-commands\n') %
3018 ui.status(_('sending batch with %d sub-commands\n') %
3017 len(batchedcommands))
3019 len(batchedcommands))
3018 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
3020 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
3019 ui.status(_('response #%d: %s\n') %
3021 ui.status(_('response #%d: %s\n') %
3020 (i, stringutil.escapestr(chunk)))
3022 (i, stringutil.escapestr(chunk)))
3021
3023
3022 batchedcommands = None
3024 batchedcommands = None
3023
3025
3024 elif action.startswith('httprequest '):
3026 elif action.startswith('httprequest '):
3025 if not opener:
3027 if not opener:
3026 raise error.Abort(_('cannot use httprequest without an HTTP '
3028 raise error.Abort(_('cannot use httprequest without an HTTP '
3027 'peer'))
3029 'peer'))
3028
3030
3029 request = action.split(' ', 2)
3031 request = action.split(' ', 2)
3030 if len(request) != 3:
3032 if len(request) != 3:
3031 raise error.Abort(_('invalid httprequest: expected format is '
3033 raise error.Abort(_('invalid httprequest: expected format is '
3032 '"httprequest <method> <path>'))
3034 '"httprequest <method> <path>'))
3033
3035
3034 method, httppath = request[1:]
3036 method, httppath = request[1:]
3035 headers = {}
3037 headers = {}
3036 body = None
3038 body = None
3037 frames = []
3039 frames = []
3038 for line in lines:
3040 for line in lines:
3039 line = line.lstrip()
3041 line = line.lstrip()
3040 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
3042 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
3041 if m:
3043 if m:
3042 headers[m.group(1)] = m.group(2)
3044 headers[m.group(1)] = m.group(2)
3043 continue
3045 continue
3044
3046
3045 if line.startswith(b'BODYFILE '):
3047 if line.startswith(b'BODYFILE '):
3046 with open(line.split(b' ', 1), 'rb') as fh:
3048 with open(line.split(b' ', 1), 'rb') as fh:
3047 body = fh.read()
3049 body = fh.read()
3048 elif line.startswith(b'frame '):
3050 elif line.startswith(b'frame '):
3049 frame = wireprotoframing.makeframefromhumanstring(
3051 frame = wireprotoframing.makeframefromhumanstring(
3050 line[len(b'frame '):])
3052 line[len(b'frame '):])
3051
3053
3052 frames.append(frame)
3054 frames.append(frame)
3053 else:
3055 else:
3054 raise error.Abort(_('unknown argument to httprequest: %s') %
3056 raise error.Abort(_('unknown argument to httprequest: %s') %
3055 line)
3057 line)
3056
3058
3057 url = path + httppath
3059 url = path + httppath
3058
3060
3059 if frames:
3061 if frames:
3060 body = b''.join(bytes(f) for f in frames)
3062 body = b''.join(bytes(f) for f in frames)
3061
3063
3062 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
3064 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
3063
3065
3064 # urllib.Request insists on using has_data() as a proxy for
3066 # urllib.Request insists on using has_data() as a proxy for
3065 # determining the request method. Override that to use our
3067 # determining the request method. Override that to use our
3066 # explicitly requested method.
3068 # explicitly requested method.
3067 req.get_method = lambda: method
3069 req.get_method = lambda: method
3068
3070
3069 try:
3071 try:
3070 res = opener.open(req)
3072 res = opener.open(req)
3071 body = res.read()
3073 body = res.read()
3072 except util.urlerr.urlerror as e:
3074 except util.urlerr.urlerror as e:
3073 e.read()
3075 e.read()
3074 continue
3076 continue
3075
3077
3076 if res.headers.get('Content-Type') == 'application/mercurial-cbor':
3078 if res.headers.get('Content-Type') == 'application/mercurial-cbor':
3077 ui.write(_('cbor> %s\n') % stringutil.pprint(cbor.loads(body)))
3079 ui.write(_('cbor> %s\n') % stringutil.pprint(cbor.loads(body)))
3078
3080
3079 elif action == 'close':
3081 elif action == 'close':
3080 peer.close()
3082 peer.close()
3081 elif action == 'readavailable':
3083 elif action == 'readavailable':
3082 if not stdout or not stderr:
3084 if not stdout or not stderr:
3083 raise error.Abort(_('readavailable not available on this peer'))
3085 raise error.Abort(_('readavailable not available on this peer'))
3084
3086
3085 stdin.close()
3087 stdin.close()
3086 stdout.read()
3088 stdout.read()
3087 stderr.read()
3089 stderr.read()
3088
3090
3089 elif action == 'readline':
3091 elif action == 'readline':
3090 if not stdout:
3092 if not stdout:
3091 raise error.Abort(_('readline not available on this peer'))
3093 raise error.Abort(_('readline not available on this peer'))
3092 stdout.readline()
3094 stdout.readline()
3093 elif action == 'ereadline':
3095 elif action == 'ereadline':
3094 if not stderr:
3096 if not stderr:
3095 raise error.Abort(_('ereadline not available on this peer'))
3097 raise error.Abort(_('ereadline not available on this peer'))
3096 stderr.readline()
3098 stderr.readline()
3097 elif action.startswith('read '):
3099 elif action.startswith('read '):
3098 count = int(action.split(' ', 1)[1])
3100 count = int(action.split(' ', 1)[1])
3099 if not stdout:
3101 if not stdout:
3100 raise error.Abort(_('read not available on this peer'))
3102 raise error.Abort(_('read not available on this peer'))
3101 stdout.read(count)
3103 stdout.read(count)
3102 elif action.startswith('eread '):
3104 elif action.startswith('eread '):
3103 count = int(action.split(' ', 1)[1])
3105 count = int(action.split(' ', 1)[1])
3104 if not stderr:
3106 if not stderr:
3105 raise error.Abort(_('eread not available on this peer'))
3107 raise error.Abort(_('eread not available on this peer'))
3106 stderr.read(count)
3108 stderr.read(count)
3107 else:
3109 else:
3108 raise error.Abort(_('unknown action: %s') % action)
3110 raise error.Abort(_('unknown action: %s') % action)
3109
3111
3110 if batchedcommands is not None:
3112 if batchedcommands is not None:
3111 raise error.Abort(_('unclosed "batchbegin" request'))
3113 raise error.Abort(_('unclosed "batchbegin" request'))
3112
3114
3113 if peer:
3115 if peer:
3114 peer.close()
3116 peer.close()
3115
3117
3116 if proc:
3118 if proc:
3117 proc.kill()
3119 proc.kill()
@@ -1,335 +1,335
1 $ . $TESTDIR/wireprotohelpers.sh
1 $ . $TESTDIR/wireprotohelpers.sh
2
2
3 $ cat >> $HGRCPATH << EOF
3 $ cat >> $HGRCPATH << EOF
4 > [web]
4 > [web]
5 > push_ssl = false
5 > push_ssl = false
6 > allow_push = *
6 > allow_push = *
7 > EOF
7 > EOF
8
8
9 $ hg init server
9 $ hg init server
10 $ cd server
10 $ cd server
11 $ touch a
11 $ touch a
12 $ hg -q commit -A -m initial
12 $ hg -q commit -A -m initial
13 $ cd ..
13 $ cd ..
14
14
15 $ hg serve -R server -p $HGPORT -d --pid-file hg.pid
15 $ hg serve -R server -p $HGPORT -d --pid-file hg.pid
16 $ cat hg.pid >> $DAEMON_PIDS
16 $ cat hg.pid >> $DAEMON_PIDS
17
17
18 compression formats are advertised in compression capability
18 compression formats are advertised in compression capability
19
19
20 #if zstd
20 #if zstd
21 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=zstd,zlib$' > /dev/null
21 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=zstd,zlib$' > /dev/null
22 #else
22 #else
23 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=zlib$' > /dev/null
23 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=zlib$' > /dev/null
24 #endif
24 #endif
25
25
26 $ killdaemons.py
26 $ killdaemons.py
27
27
28 server.compressionengines can replace engines list wholesale
28 server.compressionengines can replace engines list wholesale
29
29
30 $ hg serve --config server.compressionengines=none -R server -p $HGPORT -d --pid-file hg.pid
30 $ hg serve --config server.compressionengines=none -R server -p $HGPORT -d --pid-file hg.pid
31 $ cat hg.pid > $DAEMON_PIDS
31 $ cat hg.pid > $DAEMON_PIDS
32 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=none$' > /dev/null
32 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=none$' > /dev/null
33
33
34 $ killdaemons.py
34 $ killdaemons.py
35
35
36 Order of engines can also change
36 Order of engines can also change
37
37
38 $ hg serve --config server.compressionengines=none,zlib -R server -p $HGPORT -d --pid-file hg.pid
38 $ hg serve --config server.compressionengines=none,zlib -R server -p $HGPORT -d --pid-file hg.pid
39 $ cat hg.pid > $DAEMON_PIDS
39 $ cat hg.pid > $DAEMON_PIDS
40 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=none,zlib$' > /dev/null
40 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=none,zlib$' > /dev/null
41
41
42 $ killdaemons.py
42 $ killdaemons.py
43
43
44 Start a default server again
44 Start a default server again
45
45
46 $ hg serve -R server -p $HGPORT -d --pid-file hg.pid
46 $ hg serve -R server -p $HGPORT -d --pid-file hg.pid
47 $ cat hg.pid > $DAEMON_PIDS
47 $ cat hg.pid > $DAEMON_PIDS
48
48
49 Server should send application/mercurial-0.1 to clients if no Accept is used
49 Server should send application/mercurial-0.1 to clients if no Accept is used
50
50
51 $ get-with-headers.py --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
51 $ get-with-headers.py --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
52 200 Script output follows
52 200 Script output follows
53 content-type: application/mercurial-0.1
53 content-type: application/mercurial-0.1
54 date: $HTTP_DATE$
54 date: $HTTP_DATE$
55 server: testing stub value
55 server: testing stub value
56 transfer-encoding: chunked
56 transfer-encoding: chunked
57
57
58 Server should send application/mercurial-0.1 when client says it wants it
58 Server should send application/mercurial-0.1 when client says it wants it
59
59
60 $ get-with-headers.py --hgproto '0.1' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
60 $ get-with-headers.py --hgproto '0.1' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
61 200 Script output follows
61 200 Script output follows
62 content-type: application/mercurial-0.1
62 content-type: application/mercurial-0.1
63 date: $HTTP_DATE$
63 date: $HTTP_DATE$
64 server: testing stub value
64 server: testing stub value
65 transfer-encoding: chunked
65 transfer-encoding: chunked
66
66
67 Server should send application/mercurial-0.2 when client says it wants it
67 Server should send application/mercurial-0.2 when client says it wants it
68
68
69 $ get-with-headers.py --hgproto '0.2' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
69 $ get-with-headers.py --hgproto '0.2' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
70 200 Script output follows
70 200 Script output follows
71 content-type: application/mercurial-0.2
71 content-type: application/mercurial-0.2
72 date: $HTTP_DATE$
72 date: $HTTP_DATE$
73 server: testing stub value
73 server: testing stub value
74 transfer-encoding: chunked
74 transfer-encoding: chunked
75
75
76 $ get-with-headers.py --hgproto '0.1 0.2' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
76 $ get-with-headers.py --hgproto '0.1 0.2' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
77 200 Script output follows
77 200 Script output follows
78 content-type: application/mercurial-0.2
78 content-type: application/mercurial-0.2
79 date: $HTTP_DATE$
79 date: $HTTP_DATE$
80 server: testing stub value
80 server: testing stub value
81 transfer-encoding: chunked
81 transfer-encoding: chunked
82
82
83 Requesting a compression format that server doesn't support results will fall back to 0.1
83 Requesting a compression format that server doesn't support results will fall back to 0.1
84
84
85 $ get-with-headers.py --hgproto '0.2 comp=aa' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
85 $ get-with-headers.py --hgproto '0.2 comp=aa' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
86 200 Script output follows
86 200 Script output follows
87 content-type: application/mercurial-0.1
87 content-type: application/mercurial-0.1
88 date: $HTTP_DATE$
88 date: $HTTP_DATE$
89 server: testing stub value
89 server: testing stub value
90 transfer-encoding: chunked
90 transfer-encoding: chunked
91
91
92 #if zstd
92 #if zstd
93 zstd is used if available
93 zstd is used if available
94
94
95 $ get-with-headers.py --hgproto '0.2 comp=zstd' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
95 $ get-with-headers.py --hgproto '0.2 comp=zstd' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
96 $ f --size --hexdump --bytes 36 --sha1 resp
96 $ f --size --hexdump --bytes 36 --sha1 resp
97 resp: size=248, sha1=4d8d8f87fb82bd542ce52881fdc94f850748
97 resp: size=248, sha1=4d8d8f87fb82bd542ce52881fdc94f850748
98 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
98 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
99 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 7a 73 74 64 |t follows...zstd|
99 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 7a 73 74 64 |t follows...zstd|
100 0020: 28 b5 2f fd |(./.|
100 0020: 28 b5 2f fd |(./.|
101
101
102 #endif
102 #endif
103
103
104 application/mercurial-0.2 is not yet used on non-streaming responses
104 application/mercurial-0.2 is not yet used on non-streaming responses
105
105
106 $ get-with-headers.py --hgproto '0.2' $LOCALIP:$HGPORT '?cmd=heads' -
106 $ get-with-headers.py --hgproto '0.2' $LOCALIP:$HGPORT '?cmd=heads' -
107 200 Script output follows
107 200 Script output follows
108 content-length: 41
108 content-length: 41
109 content-type: application/mercurial-0.1
109 content-type: application/mercurial-0.1
110 date: $HTTP_DATE$
110 date: $HTTP_DATE$
111 server: testing stub value
111 server: testing stub value
112
112
113 e93700bd72895c5addab234c56d4024b487a362f
113 e93700bd72895c5addab234c56d4024b487a362f
114
114
115 Now test protocol preference usage
115 Now test protocol preference usage
116
116
117 $ killdaemons.py
117 $ killdaemons.py
118 $ hg serve --config server.compressionengines=none,zlib -R server -p $HGPORT -d --pid-file hg.pid
118 $ hg serve --config server.compressionengines=none,zlib -R server -p $HGPORT -d --pid-file hg.pid
119 $ cat hg.pid > $DAEMON_PIDS
119 $ cat hg.pid > $DAEMON_PIDS
120
120
121 No Accept will send 0.1+zlib, even though "none" is preferred b/c "none" isn't supported on 0.1
121 No Accept will send 0.1+zlib, even though "none" is preferred b/c "none" isn't supported on 0.1
122
122
123 $ get-with-headers.py --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' Content-Type
123 $ get-with-headers.py --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' Content-Type
124 200 Script output follows
124 200 Script output follows
125 content-type: application/mercurial-0.1
125 content-type: application/mercurial-0.1
126
126
127 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
127 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
128 $ f --size --hexdump --bytes 28 --sha1 resp
128 $ f --size --hexdump --bytes 28 --sha1 resp
129 resp: size=227, sha1=35a4c074da74f32f5440da3cbf04
129 resp: size=227, sha1=35a4c074da74f32f5440da3cbf04
130 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
130 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
131 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 78 |t follows..x|
131 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 78 |t follows..x|
132
132
133 Explicit 0.1 will send zlib because "none" isn't supported on 0.1
133 Explicit 0.1 will send zlib because "none" isn't supported on 0.1
134
134
135 $ get-with-headers.py --hgproto '0.1' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
135 $ get-with-headers.py --hgproto '0.1' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
136 $ f --size --hexdump --bytes 28 --sha1 resp
136 $ f --size --hexdump --bytes 28 --sha1 resp
137 resp: size=227, sha1=35a4c074da74f32f5440da3cbf04
137 resp: size=227, sha1=35a4c074da74f32f5440da3cbf04
138 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
138 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
139 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 78 |t follows..x|
139 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 78 |t follows..x|
140
140
141 0.2 with no compression will get "none" because that is server's preference
141 0.2 with no compression will get "none" because that is server's preference
142 (spec says ZL and UN are implicitly supported)
142 (spec says ZL and UN are implicitly supported)
143
143
144 $ get-with-headers.py --hgproto '0.2' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
144 $ get-with-headers.py --hgproto '0.2' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
145 $ f --size --hexdump --bytes 32 --sha1 resp
145 $ f --size --hexdump --bytes 32 --sha1 resp
146 resp: size=432, sha1=ac931b412ec185a02e0e5bcff98dac83
146 resp: size=432, sha1=ac931b412ec185a02e0e5bcff98dac83
147 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
147 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
148 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 6e 6f 6e 65 |t follows...none|
148 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 6e 6f 6e 65 |t follows...none|
149
149
150 Client receives server preference even if local order doesn't match
150 Client receives server preference even if local order doesn't match
151
151
152 $ get-with-headers.py --hgproto '0.2 comp=zlib,none' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
152 $ get-with-headers.py --hgproto '0.2 comp=zlib,none' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
153 $ f --size --hexdump --bytes 32 --sha1 resp
153 $ f --size --hexdump --bytes 32 --sha1 resp
154 resp: size=432, sha1=ac931b412ec185a02e0e5bcff98dac83
154 resp: size=432, sha1=ac931b412ec185a02e0e5bcff98dac83
155 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
155 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
156 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 6e 6f 6e 65 |t follows...none|
156 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 6e 6f 6e 65 |t follows...none|
157
157
158 Client receives only supported format even if not server preferred format
158 Client receives only supported format even if not server preferred format
159
159
160 $ get-with-headers.py --hgproto '0.2 comp=zlib' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
160 $ get-with-headers.py --hgproto '0.2 comp=zlib' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
161 $ f --size --hexdump --bytes 33 --sha1 resp
161 $ f --size --hexdump --bytes 33 --sha1 resp
162 resp: size=232, sha1=a1c727f0c9693ca15742a75c30419bc36
162 resp: size=232, sha1=a1c727f0c9693ca15742a75c30419bc36
163 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
163 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
164 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 7a 6c 69 62 |t follows...zlib|
164 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 7a 6c 69 62 |t follows...zlib|
165 0020: 78 |x|
165 0020: 78 |x|
166
166
167 $ killdaemons.py
167 $ killdaemons.py
168 $ cd ..
168 $ cd ..
169
169
170 Test listkeys for listing namespaces
170 Test listkeys for listing namespaces
171
171
172 $ hg init empty
172 $ hg init empty
173 $ hg -R empty serve -p $HGPORT -d --pid-file hg.pid
173 $ hg -R empty serve -p $HGPORT -d --pid-file hg.pid
174 $ cat hg.pid > $DAEMON_PIDS
174 $ cat hg.pid > $DAEMON_PIDS
175
175
176 $ hg --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
176 $ hg --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
177 > command listkeys
177 > command listkeys
178 > namespace namespaces
178 > namespace namespaces
179 > EOF
179 > EOF
180 s> GET /?cmd=capabilities HTTP/1.1\r\n
180 s> GET /?cmd=capabilities HTTP/1.1\r\n
181 s> Accept-Encoding: identity\r\n
181 s> Accept-Encoding: identity\r\n
182 s> accept: application/mercurial-0.1\r\n
182 s> accept: application/mercurial-0.1\r\n
183 s> host: $LOCALIP:$HGPORT\r\n (glob)
183 s> host: $LOCALIP:$HGPORT\r\n (glob)
184 s> user-agent: Mercurial debugwireproto\r\n
184 s> user-agent: Mercurial debugwireproto\r\n
185 s> \r\n
185 s> \r\n
186 s> makefile('rb', None)
186 s> makefile('rb', None)
187 s> HTTP/1.1 200 Script output follows\r\n
187 s> HTTP/1.1 200 Script output follows\r\n
188 s> Server: testing stub value\r\n
188 s> Server: testing stub value\r\n
189 s> Date: $HTTP_DATE$\r\n
189 s> Date: $HTTP_DATE$\r\n
190 s> Content-Type: application/mercurial-0.1\r\n
190 s> Content-Type: application/mercurial-0.1\r\n
191 s> Content-Length: *\r\n (glob)
191 s> Content-Length: *\r\n (glob)
192 s> \r\n
192 s> \r\n
193 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
193 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
194 sending listkeys command
194 sending listkeys command
195 s> GET /?cmd=listkeys HTTP/1.1\r\n
195 s> GET /?cmd=listkeys HTTP/1.1\r\n
196 s> Accept-Encoding: identity\r\n
196 s> Accept-Encoding: identity\r\n
197 s> vary: X-HgArg-1,X-HgProto-1\r\n
197 s> vary: X-HgArg-1,X-HgProto-1\r\n
198 s> x-hgarg-1: namespace=namespaces\r\n
198 s> x-hgarg-1: namespace=namespaces\r\n
199 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
199 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
200 s> accept: application/mercurial-0.1\r\n
200 s> accept: application/mercurial-0.1\r\n
201 s> host: $LOCALIP:$HGPORT\r\n (glob)
201 s> host: $LOCALIP:$HGPORT\r\n (glob)
202 s> user-agent: Mercurial debugwireproto\r\n
202 s> user-agent: Mercurial debugwireproto\r\n
203 s> \r\n
203 s> \r\n
204 s> makefile('rb', None)
204 s> makefile('rb', None)
205 s> HTTP/1.1 200 Script output follows\r\n
205 s> HTTP/1.1 200 Script output follows\r\n
206 s> Server: testing stub value\r\n
206 s> Server: testing stub value\r\n
207 s> Date: $HTTP_DATE$\r\n
207 s> Date: $HTTP_DATE$\r\n
208 s> Content-Type: application/mercurial-0.1\r\n
208 s> Content-Type: application/mercurial-0.1\r\n
209 s> Content-Length: 30\r\n
209 s> Content-Length: 30\r\n
210 s> \r\n
210 s> \r\n
211 s> bookmarks\t\n
211 s> bookmarks\t\n
212 s> namespaces\t\n
212 s> namespaces\t\n
213 s> phases\t
213 s> phases\t
214 response: b'bookmarks\t\nnamespaces\t\nphases\t'
214 response: {b'bookmarks': b'', b'namespaces': b'', b'phases': b''}
215
215
216 Same thing, but with "httprequest" command
216 Same thing, but with "httprequest" command
217
217
218 $ hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT << EOF
218 $ hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT << EOF
219 > httprequest GET ?cmd=listkeys
219 > httprequest GET ?cmd=listkeys
220 > user-agent: test
220 > user-agent: test
221 > x-hgarg-1: namespace=namespaces
221 > x-hgarg-1: namespace=namespaces
222 > EOF
222 > EOF
223 using raw connection to peer
223 using raw connection to peer
224 s> GET /?cmd=listkeys HTTP/1.1\r\n
224 s> GET /?cmd=listkeys HTTP/1.1\r\n
225 s> Accept-Encoding: identity\r\n
225 s> Accept-Encoding: identity\r\n
226 s> user-agent: test\r\n
226 s> user-agent: test\r\n
227 s> x-hgarg-1: namespace=namespaces\r\n
227 s> x-hgarg-1: namespace=namespaces\r\n
228 s> host: $LOCALIP:$HGPORT\r\n (glob)
228 s> host: $LOCALIP:$HGPORT\r\n (glob)
229 s> \r\n
229 s> \r\n
230 s> makefile('rb', None)
230 s> makefile('rb', None)
231 s> HTTP/1.1 200 Script output follows\r\n
231 s> HTTP/1.1 200 Script output follows\r\n
232 s> Server: testing stub value\r\n
232 s> Server: testing stub value\r\n
233 s> Date: $HTTP_DATE$\r\n
233 s> Date: $HTTP_DATE$\r\n
234 s> Content-Type: application/mercurial-0.1\r\n
234 s> Content-Type: application/mercurial-0.1\r\n
235 s> Content-Length: 30\r\n
235 s> Content-Length: 30\r\n
236 s> \r\n
236 s> \r\n
237 s> bookmarks\t\n
237 s> bookmarks\t\n
238 s> namespaces\t\n
238 s> namespaces\t\n
239 s> phases\t
239 s> phases\t
240
240
241 Client with HTTPv2 enabled advertises that and gets old capabilities response from old server
241 Client with HTTPv2 enabled advertises that and gets old capabilities response from old server
242
242
243 $ hg --config experimental.httppeer.advertise-v2=true --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
243 $ hg --config experimental.httppeer.advertise-v2=true --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
244 > command heads
244 > command heads
245 > EOF
245 > EOF
246 s> GET /?cmd=capabilities HTTP/1.1\r\n
246 s> GET /?cmd=capabilities HTTP/1.1\r\n
247 s> Accept-Encoding: identity\r\n
247 s> Accept-Encoding: identity\r\n
248 s> vary: X-HgProto-1,X-HgUpgrade-1\r\n
248 s> vary: X-HgProto-1,X-HgUpgrade-1\r\n
249 s> x-hgproto-1: cbor\r\n
249 s> x-hgproto-1: cbor\r\n
250 s> x-hgupgrade-1: exp-http-v2-0001\r\n
250 s> x-hgupgrade-1: exp-http-v2-0001\r\n
251 s> accept: application/mercurial-0.1\r\n
251 s> accept: application/mercurial-0.1\r\n
252 s> host: $LOCALIP:$HGPORT\r\n (glob)
252 s> host: $LOCALIP:$HGPORT\r\n (glob)
253 s> user-agent: Mercurial debugwireproto\r\n
253 s> user-agent: Mercurial debugwireproto\r\n
254 s> \r\n
254 s> \r\n
255 s> makefile('rb', None)
255 s> makefile('rb', None)
256 s> HTTP/1.1 200 Script output follows\r\n
256 s> HTTP/1.1 200 Script output follows\r\n
257 s> Server: testing stub value\r\n
257 s> Server: testing stub value\r\n
258 s> Date: $HTTP_DATE$\r\n
258 s> Date: $HTTP_DATE$\r\n
259 s> Content-Type: application/mercurial-0.1\r\n
259 s> Content-Type: application/mercurial-0.1\r\n
260 s> Content-Length: 458\r\n
260 s> Content-Length: 458\r\n
261 s> \r\n
261 s> \r\n
262 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
262 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
263 sending heads command
263 sending heads command
264 s> GET /?cmd=heads HTTP/1.1\r\n
264 s> GET /?cmd=heads HTTP/1.1\r\n
265 s> Accept-Encoding: identity\r\n
265 s> Accept-Encoding: identity\r\n
266 s> vary: X-HgProto-1\r\n
266 s> vary: X-HgProto-1\r\n
267 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
267 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
268 s> accept: application/mercurial-0.1\r\n
268 s> accept: application/mercurial-0.1\r\n
269 s> host: $LOCALIP:$HGPORT\r\n (glob)
269 s> host: $LOCALIP:$HGPORT\r\n (glob)
270 s> user-agent: Mercurial debugwireproto\r\n
270 s> user-agent: Mercurial debugwireproto\r\n
271 s> \r\n
271 s> \r\n
272 s> makefile('rb', None)
272 s> makefile('rb', None)
273 s> HTTP/1.1 200 Script output follows\r\n
273 s> HTTP/1.1 200 Script output follows\r\n
274 s> Server: testing stub value\r\n
274 s> Server: testing stub value\r\n
275 s> Date: $HTTP_DATE$\r\n
275 s> Date: $HTTP_DATE$\r\n
276 s> Content-Type: application/mercurial-0.1\r\n
276 s> Content-Type: application/mercurial-0.1\r\n
277 s> Content-Length: 41\r\n
277 s> Content-Length: 41\r\n
278 s> \r\n
278 s> \r\n
279 s> 0000000000000000000000000000000000000000\n
279 s> 0000000000000000000000000000000000000000\n
280 response: b'0000000000000000000000000000000000000000\n'
280 response: [b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00']
281
281
282 $ killdaemons.py
282 $ killdaemons.py
283 $ enablehttpv2 empty
283 $ enablehttpv2 empty
284 $ hg -R empty serve -p $HGPORT -d --pid-file hg.pid
284 $ hg -R empty serve -p $HGPORT -d --pid-file hg.pid
285 $ cat hg.pid > $DAEMON_PIDS
285 $ cat hg.pid > $DAEMON_PIDS
286
286
287 Client with HTTPv2 enabled automatically upgrades if the server supports it
287 Client with HTTPv2 enabled automatically upgrades if the server supports it
288
288
289 $ hg --config experimental.httppeer.advertise-v2=true --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
289 $ hg --config experimental.httppeer.advertise-v2=true --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
290 > command heads
290 > command heads
291 > EOF
291 > EOF
292 s> GET /?cmd=capabilities HTTP/1.1\r\n
292 s> GET /?cmd=capabilities HTTP/1.1\r\n
293 s> Accept-Encoding: identity\r\n
293 s> Accept-Encoding: identity\r\n
294 s> vary: X-HgProto-1,X-HgUpgrade-1\r\n
294 s> vary: X-HgProto-1,X-HgUpgrade-1\r\n
295 s> x-hgproto-1: cbor\r\n
295 s> x-hgproto-1: cbor\r\n
296 s> x-hgupgrade-1: exp-http-v2-0001\r\n
296 s> x-hgupgrade-1: exp-http-v2-0001\r\n
297 s> accept: application/mercurial-0.1\r\n
297 s> accept: application/mercurial-0.1\r\n
298 s> host: $LOCALIP:$HGPORT\r\n (glob)
298 s> host: $LOCALIP:$HGPORT\r\n (glob)
299 s> user-agent: Mercurial debugwireproto\r\n
299 s> user-agent: Mercurial debugwireproto\r\n
300 s> \r\n
300 s> \r\n
301 s> makefile('rb', None)
301 s> makefile('rb', None)
302 s> HTTP/1.1 200 OK\r\n
302 s> HTTP/1.1 200 OK\r\n
303 s> Server: testing stub value\r\n
303 s> Server: testing stub value\r\n
304 s> Date: $HTTP_DATE$\r\n
304 s> Date: $HTTP_DATE$\r\n
305 s> Content-Type: application/mercurial-cbor\r\n
305 s> Content-Type: application/mercurial-cbor\r\n
306 s> Content-Length: *\r\n (glob)
306 s> Content-Length: *\r\n (glob)
307 s> \r\n
307 s> \r\n
308 s> \xa3Dapis\xa1Pexp-http-v2-0001\xa2Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibGapibaseDapi/Nv1capabilitiesY\x01\xcabatch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
308 s> \xa3Dapis\xa1Pexp-http-v2-0001\xa2Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibGapibaseDapi/Nv1capabilitiesY\x01\xcabatch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
309 sending heads command
309 sending heads command
310 s> POST /api/exp-http-v2-0001/ro/heads HTTP/1.1\r\n
310 s> POST /api/exp-http-v2-0001/ro/heads HTTP/1.1\r\n
311 s> Accept-Encoding: identity\r\n
311 s> Accept-Encoding: identity\r\n
312 s> accept: application/mercurial-exp-framing-0003\r\n
312 s> accept: application/mercurial-exp-framing-0003\r\n
313 s> content-type: application/mercurial-exp-framing-0003\r\n
313 s> content-type: application/mercurial-exp-framing-0003\r\n
314 s> content-length: 20\r\n
314 s> content-length: 20\r\n
315 s> host: $LOCALIP:$HGPORT\r\n (glob)
315 s> host: $LOCALIP:$HGPORT\r\n (glob)
316 s> user-agent: Mercurial debugwireproto\r\n
316 s> user-agent: Mercurial debugwireproto\r\n
317 s> \r\n
317 s> \r\n
318 s> \x0c\x00\x00\x01\x00\x01\x01\x11\xa1DnameEheads
318 s> \x0c\x00\x00\x01\x00\x01\x01\x11\xa1DnameEheads
319 s> makefile('rb', None)
319 s> makefile('rb', None)
320 s> HTTP/1.1 200 OK\r\n
320 s> HTTP/1.1 200 OK\r\n
321 s> Server: testing stub value\r\n
321 s> Server: testing stub value\r\n
322 s> Date: $HTTP_DATE$\r\n
322 s> Date: $HTTP_DATE$\r\n
323 s> Content-Type: application/mercurial-exp-framing-0003\r\n
323 s> Content-Type: application/mercurial-exp-framing-0003\r\n
324 s> Transfer-Encoding: chunked\r\n
324 s> Transfer-Encoding: chunked\r\n
325 s> \r\n
325 s> \r\n
326 s> 1e\r\n
326 s> 1e\r\n
327 s> \x16\x00\x00\x01\x00\x02\x01F
327 s> \x16\x00\x00\x01\x00\x02\x01F
328 s> \x81T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
328 s> \x81T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
329 s> \r\n
329 s> \r\n
330 received frame(size=22; request=1; stream=2; streamflags=stream-begin; type=bytes-response; flags=eos|cbor)
330 received frame(size=22; request=1; stream=2; streamflags=stream-begin; type=bytes-response; flags=eos|cbor)
331 s> 0\r\n
331 s> 0\r\n
332 s> \r\n
332 s> \r\n
333 response: [[b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00']]
333 response: [[b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00']]
334
334
335 $ killdaemons.py
335 $ killdaemons.py
@@ -1,2167 +1,2167
1 $ cat > hgrc-sshv2 << EOF
1 $ cat > hgrc-sshv2 << EOF
2 > %include $HGRCPATH
2 > %include $HGRCPATH
3 > [experimental]
3 > [experimental]
4 > sshpeer.advertise-v2 = true
4 > sshpeer.advertise-v2 = true
5 > sshserver.support-v2 = true
5 > sshserver.support-v2 = true
6 > EOF
6 > EOF
7
7
8 Helper function to run protocol tests against multiple protocol versions.
8 Helper function to run protocol tests against multiple protocol versions.
9 This is easier than using #testcases because managing differences between
9 This is easier than using #testcases because managing differences between
10 protocols with inline conditional output is hard to read.
10 protocols with inline conditional output is hard to read.
11
11
12 $ debugwireproto() {
12 $ debugwireproto() {
13 > commands=`cat -`
13 > commands=`cat -`
14 > echo 'testing ssh1'
14 > echo 'testing ssh1'
15 > echo "${commands}" | hg --verbose debugwireproto --localssh
15 > echo "${commands}" | hg --verbose debugwireproto --localssh
16 > echo ""
16 > echo ""
17 > echo 'testing ssh2'
17 > echo 'testing ssh2'
18 > echo "${commands}" | HGRCPATH=$TESTTMP/hgrc-sshv2 hg --verbose debugwireproto --localssh
18 > echo "${commands}" | HGRCPATH=$TESTTMP/hgrc-sshv2 hg --verbose debugwireproto --localssh
19 > }
19 > }
20
20
21 $ cat >> $HGRCPATH << EOF
21 $ cat >> $HGRCPATH << EOF
22 > [ui]
22 > [ui]
23 > ssh = $PYTHON "$TESTDIR/dummyssh"
23 > ssh = $PYTHON "$TESTDIR/dummyssh"
24 > [devel]
24 > [devel]
25 > debug.peer-request = true
25 > debug.peer-request = true
26 > [extensions]
26 > [extensions]
27 > sshprotoext = $TESTDIR/sshprotoext.py
27 > sshprotoext = $TESTDIR/sshprotoext.py
28 > EOF
28 > EOF
29
29
30 $ hg init server
30 $ hg init server
31 $ cd server
31 $ cd server
32 $ echo 0 > foo
32 $ echo 0 > foo
33 $ hg -q add foo
33 $ hg -q add foo
34 $ hg commit -m initial
34 $ hg commit -m initial
35
35
36 A no-op connection performs a handshake
36 A no-op connection performs a handshake
37
37
38 $ hg debugwireproto --localssh << EOF
38 $ hg debugwireproto --localssh << EOF
39 > EOF
39 > EOF
40 creating ssh peer from handshake results
40 creating ssh peer from handshake results
41
41
42 Raw peers don't perform any activity
42 Raw peers don't perform any activity
43
43
44 $ hg debugwireproto --localssh --peer raw << EOF
44 $ hg debugwireproto --localssh --peer raw << EOF
45 > EOF
45 > EOF
46 using raw connection to peer
46 using raw connection to peer
47 $ hg debugwireproto --localssh --peer ssh1 << EOF
47 $ hg debugwireproto --localssh --peer ssh1 << EOF
48 > EOF
48 > EOF
49 creating ssh peer for wire protocol version 1
49 creating ssh peer for wire protocol version 1
50 $ hg debugwireproto --localssh --peer ssh2 << EOF
50 $ hg debugwireproto --localssh --peer ssh2 << EOF
51 > EOF
51 > EOF
52 creating ssh peer for wire protocol version 2
52 creating ssh peer for wire protocol version 2
53
53
54 Test a normal behaving server, for sanity
54 Test a normal behaving server, for sanity
55
55
56 $ cd ..
56 $ cd ..
57
57
58 $ hg --debug debugpeer ssh://user@dummy/server
58 $ hg --debug debugpeer ssh://user@dummy/server
59 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
59 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
60 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
60 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
61 devel-peer-request: hello
61 devel-peer-request: hello
62 sending hello command
62 sending hello command
63 devel-peer-request: between
63 devel-peer-request: between
64 devel-peer-request: pairs: 81 bytes
64 devel-peer-request: pairs: 81 bytes
65 sending between command
65 sending between command
66 remote: 413
66 remote: 413
67 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
67 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
68 remote: 1
68 remote: 1
69 devel-peer-request: protocaps
69 devel-peer-request: protocaps
70 devel-peer-request: caps: * bytes (glob)
70 devel-peer-request: caps: * bytes (glob)
71 sending protocaps command
71 sending protocaps command
72 url: ssh://user@dummy/server
72 url: ssh://user@dummy/server
73 local: no
73 local: no
74 pushable: yes
74 pushable: yes
75
75
76 Server should answer the "hello" command in isolation
76 Server should answer the "hello" command in isolation
77
77
78 $ hg -R server debugwireproto --localssh --peer raw << EOF
78 $ hg -R server debugwireproto --localssh --peer raw << EOF
79 > raw
79 > raw
80 > hello\n
80 > hello\n
81 > readline
81 > readline
82 > readline
82 > readline
83 > EOF
83 > EOF
84 using raw connection to peer
84 using raw connection to peer
85 i> write(6) -> 6:
85 i> write(6) -> 6:
86 i> hello\n
86 i> hello\n
87 o> readline() -> 4:
87 o> readline() -> 4:
88 o> 413\n
88 o> 413\n
89 o> readline() -> 413:
89 o> readline() -> 413:
90 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
90 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
91
91
92 `hg debugserve --sshstdio` works
92 `hg debugserve --sshstdio` works
93
93
94 $ cd server
94 $ cd server
95 $ hg debugserve --sshstdio << EOF
95 $ hg debugserve --sshstdio << EOF
96 > hello
96 > hello
97 > EOF
97 > EOF
98 413
98 413
99 capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
99 capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
100
100
101 I/O logging works
101 I/O logging works
102
102
103 $ hg debugserve --sshstdio --logiofd 1 << EOF
103 $ hg debugserve --sshstdio --logiofd 1 << EOF
104 > hello
104 > hello
105 > EOF
105 > EOF
106 o> write(4) -> 4:
106 o> write(4) -> 4:
107 o> 413\n
107 o> 413\n
108 o> write(413) -> 413:
108 o> write(413) -> 413:
109 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
109 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
110 413
110 413
111 capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
111 capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
112 o> flush() -> None
112 o> flush() -> None
113
113
114 $ hg debugserve --sshstdio --logiofile $TESTTMP/io << EOF
114 $ hg debugserve --sshstdio --logiofile $TESTTMP/io << EOF
115 > hello
115 > hello
116 > EOF
116 > EOF
117 413
117 413
118 capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
118 capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
119
119
120 $ cat $TESTTMP/io
120 $ cat $TESTTMP/io
121 o> write(4) -> 4:
121 o> write(4) -> 4:
122 o> 413\n
122 o> 413\n
123 o> write(413) -> 413:
123 o> write(413) -> 413:
124 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
124 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
125 o> flush() -> None
125 o> flush() -> None
126
126
127 $ cd ..
127 $ cd ..
128
128
129 >=0.9.1 clients send a "hello" + "between" for the null range as part of handshake.
129 >=0.9.1 clients send a "hello" + "between" for the null range as part of handshake.
130 Server should reply with capabilities and should send "1\n\n" as a successful
130 Server should reply with capabilities and should send "1\n\n" as a successful
131 reply with empty response to the "between".
131 reply with empty response to the "between".
132
132
133 $ hg -R server debugwireproto --localssh --peer raw << EOF
133 $ hg -R server debugwireproto --localssh --peer raw << EOF
134 > raw
134 > raw
135 > hello\n
135 > hello\n
136 > readline
136 > readline
137 > readline
137 > readline
138 > raw
138 > raw
139 > between\n
139 > between\n
140 > pairs 81\n
140 > pairs 81\n
141 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
141 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
142 > readline
142 > readline
143 > readline
143 > readline
144 > EOF
144 > EOF
145 using raw connection to peer
145 using raw connection to peer
146 i> write(6) -> 6:
146 i> write(6) -> 6:
147 i> hello\n
147 i> hello\n
148 o> readline() -> 4:
148 o> readline() -> 4:
149 o> 413\n
149 o> 413\n
150 o> readline() -> 413:
150 o> readline() -> 413:
151 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
151 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
152 i> write(98) -> 98:
152 i> write(98) -> 98:
153 i> between\n
153 i> between\n
154 i> pairs 81\n
154 i> pairs 81\n
155 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
155 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
156 o> readline() -> 2:
156 o> readline() -> 2:
157 o> 1\n
157 o> 1\n
158 o> readline() -> 1:
158 o> readline() -> 1:
159 o> \n
159 o> \n
160
160
161 SSH banner is not printed by default, ignored by clients
161 SSH banner is not printed by default, ignored by clients
162
162
163 $ SSHSERVERMODE=banner hg debugpeer ssh://user@dummy/server
163 $ SSHSERVERMODE=banner hg debugpeer ssh://user@dummy/server
164 url: ssh://user@dummy/server
164 url: ssh://user@dummy/server
165 local: no
165 local: no
166 pushable: yes
166 pushable: yes
167
167
168 --debug will print the banner
168 --debug will print the banner
169
169
170 $ SSHSERVERMODE=banner hg --debug debugpeer ssh://user@dummy/server
170 $ SSHSERVERMODE=banner hg --debug debugpeer ssh://user@dummy/server
171 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
171 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
172 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
172 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
173 devel-peer-request: hello
173 devel-peer-request: hello
174 sending hello command
174 sending hello command
175 devel-peer-request: between
175 devel-peer-request: between
176 devel-peer-request: pairs: 81 bytes
176 devel-peer-request: pairs: 81 bytes
177 sending between command
177 sending between command
178 remote: banner: line 0
178 remote: banner: line 0
179 remote: banner: line 1
179 remote: banner: line 1
180 remote: banner: line 2
180 remote: banner: line 2
181 remote: banner: line 3
181 remote: banner: line 3
182 remote: banner: line 4
182 remote: banner: line 4
183 remote: banner: line 5
183 remote: banner: line 5
184 remote: banner: line 6
184 remote: banner: line 6
185 remote: banner: line 7
185 remote: banner: line 7
186 remote: banner: line 8
186 remote: banner: line 8
187 remote: banner: line 9
187 remote: banner: line 9
188 remote: 413
188 remote: 413
189 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
189 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
190 remote: 1
190 remote: 1
191 devel-peer-request: protocaps
191 devel-peer-request: protocaps
192 devel-peer-request: caps: * bytes (glob)
192 devel-peer-request: caps: * bytes (glob)
193 sending protocaps command
193 sending protocaps command
194 url: ssh://user@dummy/server
194 url: ssh://user@dummy/server
195 local: no
195 local: no
196 pushable: yes
196 pushable: yes
197
197
198 And test the banner with the raw protocol
198 And test the banner with the raw protocol
199
199
200 $ SSHSERVERMODE=banner hg -R server debugwireproto --localssh --peer raw << EOF
200 $ SSHSERVERMODE=banner hg -R server debugwireproto --localssh --peer raw << EOF
201 > raw
201 > raw
202 > hello\n
202 > hello\n
203 > readline
203 > readline
204 > readline
204 > readline
205 > readline
205 > readline
206 > readline
206 > readline
207 > readline
207 > readline
208 > readline
208 > readline
209 > readline
209 > readline
210 > readline
210 > readline
211 > readline
211 > readline
212 > readline
212 > readline
213 > readline
213 > readline
214 > readline
214 > readline
215 > raw
215 > raw
216 > between\n
216 > between\n
217 > pairs 81\n
217 > pairs 81\n
218 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
218 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
219 > readline
219 > readline
220 > readline
220 > readline
221 > EOF
221 > EOF
222 using raw connection to peer
222 using raw connection to peer
223 i> write(6) -> 6:
223 i> write(6) -> 6:
224 i> hello\n
224 i> hello\n
225 o> readline() -> 15:
225 o> readline() -> 15:
226 o> banner: line 0\n
226 o> banner: line 0\n
227 o> readline() -> 15:
227 o> readline() -> 15:
228 o> banner: line 1\n
228 o> banner: line 1\n
229 o> readline() -> 15:
229 o> readline() -> 15:
230 o> banner: line 2\n
230 o> banner: line 2\n
231 o> readline() -> 15:
231 o> readline() -> 15:
232 o> banner: line 3\n
232 o> banner: line 3\n
233 o> readline() -> 15:
233 o> readline() -> 15:
234 o> banner: line 4\n
234 o> banner: line 4\n
235 o> readline() -> 15:
235 o> readline() -> 15:
236 o> banner: line 5\n
236 o> banner: line 5\n
237 o> readline() -> 15:
237 o> readline() -> 15:
238 o> banner: line 6\n
238 o> banner: line 6\n
239 o> readline() -> 15:
239 o> readline() -> 15:
240 o> banner: line 7\n
240 o> banner: line 7\n
241 o> readline() -> 15:
241 o> readline() -> 15:
242 o> banner: line 8\n
242 o> banner: line 8\n
243 o> readline() -> 15:
243 o> readline() -> 15:
244 o> banner: line 9\n
244 o> banner: line 9\n
245 o> readline() -> 4:
245 o> readline() -> 4:
246 o> 413\n
246 o> 413\n
247 o> readline() -> 413:
247 o> readline() -> 413:
248 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
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 i> write(98) -> 98:
249 i> write(98) -> 98:
250 i> between\n
250 i> between\n
251 i> pairs 81\n
251 i> pairs 81\n
252 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
252 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
253 o> readline() -> 2:
253 o> readline() -> 2:
254 o> 1\n
254 o> 1\n
255 o> readline() -> 1:
255 o> readline() -> 1:
256 o> \n
256 o> \n
257
257
258 Connecting to a <0.9.1 server that doesn't support the hello command.
258 Connecting to a <0.9.1 server that doesn't support the hello command.
259 The client should refuse, as we dropped support for connecting to such
259 The client should refuse, as we dropped support for connecting to such
260 servers.
260 servers.
261
261
262 $ SSHSERVERMODE=no-hello hg --debug debugpeer ssh://user@dummy/server
262 $ SSHSERVERMODE=no-hello hg --debug debugpeer ssh://user@dummy/server
263 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
263 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
264 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
264 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
265 devel-peer-request: hello
265 devel-peer-request: hello
266 sending hello command
266 sending hello command
267 devel-peer-request: between
267 devel-peer-request: between
268 devel-peer-request: pairs: 81 bytes
268 devel-peer-request: pairs: 81 bytes
269 sending between command
269 sending between command
270 remote: 0
270 remote: 0
271 remote: 1
271 remote: 1
272 abort: no suitable response from remote hg!
272 abort: no suitable response from remote hg!
273 [255]
273 [255]
274
274
275 Sending an unknown command to the server results in an empty response to that command
275 Sending an unknown command to the server results in an empty response to that command
276
276
277 $ hg -R server debugwireproto --localssh --peer raw << EOF
277 $ hg -R server debugwireproto --localssh --peer raw << EOF
278 > raw
278 > raw
279 > pre-hello\n
279 > pre-hello\n
280 > readline
280 > readline
281 > raw
281 > raw
282 > hello\n
282 > hello\n
283 > readline
283 > readline
284 > raw
284 > raw
285 > between\n
285 > between\n
286 > pairs 81\n
286 > pairs 81\n
287 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
287 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
288 > readline
288 > readline
289 > readline
289 > readline
290 > EOF
290 > EOF
291 using raw connection to peer
291 using raw connection to peer
292 i> write(10) -> 10:
292 i> write(10) -> 10:
293 i> pre-hello\n
293 i> pre-hello\n
294 o> readline() -> 2:
294 o> readline() -> 2:
295 o> 0\n
295 o> 0\n
296 i> write(6) -> 6:
296 i> write(6) -> 6:
297 i> hello\n
297 i> hello\n
298 o> readline() -> 4:
298 o> readline() -> 4:
299 o> 413\n
299 o> 413\n
300 i> write(98) -> 98:
300 i> write(98) -> 98:
301 i> between\n
301 i> between\n
302 i> pairs 81\n
302 i> pairs 81\n
303 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
303 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
304 o> readline() -> 413:
304 o> readline() -> 413:
305 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
305 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
306 o> readline() -> 2:
306 o> readline() -> 2:
307 o> 1\n
307 o> 1\n
308
308
309 $ hg --config sshpeer.mode=extra-handshake-commands --config sshpeer.handshake-mode=pre-no-args --debug debugpeer ssh://user@dummy/server
309 $ hg --config sshpeer.mode=extra-handshake-commands --config sshpeer.handshake-mode=pre-no-args --debug debugpeer ssh://user@dummy/server
310 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
310 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
311 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
311 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
312 sending no-args command
312 sending no-args command
313 devel-peer-request: hello
313 devel-peer-request: hello
314 sending hello command
314 sending hello command
315 devel-peer-request: between
315 devel-peer-request: between
316 devel-peer-request: pairs: 81 bytes
316 devel-peer-request: pairs: 81 bytes
317 sending between command
317 sending between command
318 remote: 0
318 remote: 0
319 remote: 413
319 remote: 413
320 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
320 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
321 remote: 1
321 remote: 1
322 devel-peer-request: protocaps
322 devel-peer-request: protocaps
323 devel-peer-request: caps: * bytes (glob)
323 devel-peer-request: caps: * bytes (glob)
324 sending protocaps command
324 sending protocaps command
325 url: ssh://user@dummy/server
325 url: ssh://user@dummy/server
326 local: no
326 local: no
327 pushable: yes
327 pushable: yes
328
328
329 Send multiple unknown commands before hello
329 Send multiple unknown commands before hello
330
330
331 $ hg -R server debugwireproto --localssh --peer raw << EOF
331 $ hg -R server debugwireproto --localssh --peer raw << EOF
332 > raw
332 > raw
333 > unknown1\n
333 > unknown1\n
334 > readline
334 > readline
335 > raw
335 > raw
336 > unknown2\n
336 > unknown2\n
337 > readline
337 > readline
338 > raw
338 > raw
339 > unknown3\n
339 > unknown3\n
340 > readline
340 > readline
341 > raw
341 > raw
342 > hello\n
342 > hello\n
343 > readline
343 > readline
344 > readline
344 > readline
345 > raw
345 > raw
346 > between\n
346 > between\n
347 > pairs 81\n
347 > pairs 81\n
348 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
348 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
349 > readline
349 > readline
350 > readline
350 > readline
351 > EOF
351 > EOF
352 using raw connection to peer
352 using raw connection to peer
353 i> write(9) -> 9:
353 i> write(9) -> 9:
354 i> unknown1\n
354 i> unknown1\n
355 o> readline() -> 2:
355 o> readline() -> 2:
356 o> 0\n
356 o> 0\n
357 i> write(9) -> 9:
357 i> write(9) -> 9:
358 i> unknown2\n
358 i> unknown2\n
359 o> readline() -> 2:
359 o> readline() -> 2:
360 o> 0\n
360 o> 0\n
361 i> write(9) -> 9:
361 i> write(9) -> 9:
362 i> unknown3\n
362 i> unknown3\n
363 o> readline() -> 2:
363 o> readline() -> 2:
364 o> 0\n
364 o> 0\n
365 i> write(6) -> 6:
365 i> write(6) -> 6:
366 i> hello\n
366 i> hello\n
367 o> readline() -> 4:
367 o> readline() -> 4:
368 o> 413\n
368 o> 413\n
369 o> readline() -> 413:
369 o> readline() -> 413:
370 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
370 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
371 i> write(98) -> 98:
371 i> write(98) -> 98:
372 i> between\n
372 i> between\n
373 i> pairs 81\n
373 i> pairs 81\n
374 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
374 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
375 o> readline() -> 2:
375 o> readline() -> 2:
376 o> 1\n
376 o> 1\n
377 o> readline() -> 1:
377 o> readline() -> 1:
378 o> \n
378 o> \n
379
379
380 $ hg --config sshpeer.mode=extra-handshake-commands --config sshpeer.handshake-mode=pre-multiple-no-args --debug debugpeer ssh://user@dummy/server
380 $ hg --config sshpeer.mode=extra-handshake-commands --config sshpeer.handshake-mode=pre-multiple-no-args --debug debugpeer ssh://user@dummy/server
381 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
381 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
382 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
382 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
383 sending unknown1 command
383 sending unknown1 command
384 sending unknown2 command
384 sending unknown2 command
385 sending unknown3 command
385 sending unknown3 command
386 devel-peer-request: hello
386 devel-peer-request: hello
387 sending hello command
387 sending hello command
388 devel-peer-request: between
388 devel-peer-request: between
389 devel-peer-request: pairs: 81 bytes
389 devel-peer-request: pairs: 81 bytes
390 sending between command
390 sending between command
391 remote: 0
391 remote: 0
392 remote: 0
392 remote: 0
393 remote: 0
393 remote: 0
394 remote: 413
394 remote: 413
395 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
395 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
396 remote: 1
396 remote: 1
397 devel-peer-request: protocaps
397 devel-peer-request: protocaps
398 devel-peer-request: caps: * bytes (glob)
398 devel-peer-request: caps: * bytes (glob)
399 sending protocaps command
399 sending protocaps command
400 url: ssh://user@dummy/server
400 url: ssh://user@dummy/server
401 local: no
401 local: no
402 pushable: yes
402 pushable: yes
403
403
404 Send an unknown command before hello that has arguments
404 Send an unknown command before hello that has arguments
405
405
406 $ cd server
406 $ cd server
407
407
408 $ hg debugwireproto --localssh --peer raw << EOF
408 $ hg debugwireproto --localssh --peer raw << EOF
409 > raw
409 > raw
410 > with-args\n
410 > with-args\n
411 > foo 13\n
411 > foo 13\n
412 > value for foo\n
412 > value for foo\n
413 > bar 13\n
413 > bar 13\n
414 > value for bar\n
414 > value for bar\n
415 > readline
415 > readline
416 > readline
416 > readline
417 > readline
417 > readline
418 > readline
418 > readline
419 > readline
419 > readline
420 > raw
420 > raw
421 > hello\n
421 > hello\n
422 > readline
422 > readline
423 > readline
423 > readline
424 > raw
424 > raw
425 > between\n
425 > between\n
426 > pairs 81\n
426 > pairs 81\n
427 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
427 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
428 > readline
428 > readline
429 > readline
429 > readline
430 > EOF
430 > EOF
431 using raw connection to peer
431 using raw connection to peer
432 i> write(52) -> 52:
432 i> write(52) -> 52:
433 i> with-args\n
433 i> with-args\n
434 i> foo 13\n
434 i> foo 13\n
435 i> value for foo\n
435 i> value for foo\n
436 i> bar 13\n
436 i> bar 13\n
437 i> value for bar\n
437 i> value for bar\n
438 o> readline() -> 2:
438 o> readline() -> 2:
439 o> 0\n
439 o> 0\n
440 o> readline() -> 2:
440 o> readline() -> 2:
441 o> 0\n
441 o> 0\n
442 o> readline() -> 2:
442 o> readline() -> 2:
443 o> 0\n
443 o> 0\n
444 o> readline() -> 2:
444 o> readline() -> 2:
445 o> 0\n
445 o> 0\n
446 o> readline() -> 2:
446 o> readline() -> 2:
447 o> 0\n
447 o> 0\n
448 i> write(6) -> 6:
448 i> write(6) -> 6:
449 i> hello\n
449 i> hello\n
450 o> readline() -> 4:
450 o> readline() -> 4:
451 o> 413\n
451 o> 413\n
452 o> readline() -> 413:
452 o> readline() -> 413:
453 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
453 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
454 i> write(98) -> 98:
454 i> write(98) -> 98:
455 i> between\n
455 i> between\n
456 i> pairs 81\n
456 i> pairs 81\n
457 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
457 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
458 o> readline() -> 2:
458 o> readline() -> 2:
459 o> 1\n
459 o> 1\n
460 o> readline() -> 1:
460 o> readline() -> 1:
461 o> \n
461 o> \n
462
462
463 Send an unknown command having an argument that looks numeric
463 Send an unknown command having an argument that looks numeric
464
464
465 $ hg debugwireproto --localssh --peer raw << EOF
465 $ hg debugwireproto --localssh --peer raw << EOF
466 > raw
466 > raw
467 > unknown\n
467 > unknown\n
468 > foo 1\n
468 > foo 1\n
469 > 0\n
469 > 0\n
470 > readline
470 > readline
471 > readline
471 > readline
472 > readline
472 > readline
473 > raw
473 > raw
474 > hello\n
474 > hello\n
475 > readline
475 > readline
476 > readline
476 > readline
477 > raw
477 > raw
478 > between\n
478 > between\n
479 > pairs 81\n
479 > pairs 81\n
480 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
480 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
481 > readline
481 > readline
482 > readline
482 > readline
483 > EOF
483 > EOF
484 using raw connection to peer
484 using raw connection to peer
485 i> write(16) -> 16:
485 i> write(16) -> 16:
486 i> unknown\n
486 i> unknown\n
487 i> foo 1\n
487 i> foo 1\n
488 i> 0\n
488 i> 0\n
489 o> readline() -> 2:
489 o> readline() -> 2:
490 o> 0\n
490 o> 0\n
491 o> readline() -> 2:
491 o> readline() -> 2:
492 o> 0\n
492 o> 0\n
493 o> readline() -> 2:
493 o> readline() -> 2:
494 o> 0\n
494 o> 0\n
495 i> write(6) -> 6:
495 i> write(6) -> 6:
496 i> hello\n
496 i> hello\n
497 o> readline() -> 4:
497 o> readline() -> 4:
498 o> 413\n
498 o> 413\n
499 o> readline() -> 413:
499 o> readline() -> 413:
500 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
500 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
501 i> write(98) -> 98:
501 i> write(98) -> 98:
502 i> between\n
502 i> between\n
503 i> pairs 81\n
503 i> pairs 81\n
504 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
504 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
505 o> readline() -> 2:
505 o> readline() -> 2:
506 o> 1\n
506 o> 1\n
507 o> readline() -> 1:
507 o> readline() -> 1:
508 o> \n
508 o> \n
509
509
510 $ hg debugwireproto --localssh --peer raw << EOF
510 $ hg debugwireproto --localssh --peer raw << EOF
511 > raw
511 > raw
512 > unknown\n
512 > unknown\n
513 > foo 1\n
513 > foo 1\n
514 > 1\n
514 > 1\n
515 > readline
515 > readline
516 > readline
516 > readline
517 > readline
517 > readline
518 > raw
518 > raw
519 > hello\n
519 > hello\n
520 > readline
520 > readline
521 > readline
521 > readline
522 > raw
522 > raw
523 > between\n
523 > between\n
524 > pairs 81\n
524 > pairs 81\n
525 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
525 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
526 > readline
526 > readline
527 > readline
527 > readline
528 > EOF
528 > EOF
529 using raw connection to peer
529 using raw connection to peer
530 i> write(16) -> 16:
530 i> write(16) -> 16:
531 i> unknown\n
531 i> unknown\n
532 i> foo 1\n
532 i> foo 1\n
533 i> 1\n
533 i> 1\n
534 o> readline() -> 2:
534 o> readline() -> 2:
535 o> 0\n
535 o> 0\n
536 o> readline() -> 2:
536 o> readline() -> 2:
537 o> 0\n
537 o> 0\n
538 o> readline() -> 2:
538 o> readline() -> 2:
539 o> 0\n
539 o> 0\n
540 i> write(6) -> 6:
540 i> write(6) -> 6:
541 i> hello\n
541 i> hello\n
542 o> readline() -> 4:
542 o> readline() -> 4:
543 o> 413\n
543 o> 413\n
544 o> readline() -> 413:
544 o> readline() -> 413:
545 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
545 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
546 i> write(98) -> 98:
546 i> write(98) -> 98:
547 i> between\n
547 i> between\n
548 i> pairs 81\n
548 i> pairs 81\n
549 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
549 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
550 o> readline() -> 2:
550 o> readline() -> 2:
551 o> 1\n
551 o> 1\n
552 o> readline() -> 1:
552 o> readline() -> 1:
553 o> \n
553 o> \n
554
554
555 When sending a dict argument value, it is serialized to
555 When sending a dict argument value, it is serialized to
556 "<arg> <item count>" followed by "<key> <len>\n<value>" for each item
556 "<arg> <item count>" followed by "<key> <len>\n<value>" for each item
557 in the dict.
557 in the dict.
558
558
559 Dictionary value for unknown command
559 Dictionary value for unknown command
560
560
561 $ hg debugwireproto --localssh --peer raw << EOF
561 $ hg debugwireproto --localssh --peer raw << EOF
562 > raw
562 > raw
563 > unknown\n
563 > unknown\n
564 > dict 3\n
564 > dict 3\n
565 > key1 3\n
565 > key1 3\n
566 > foo\n
566 > foo\n
567 > key2 3\n
567 > key2 3\n
568 > bar\n
568 > bar\n
569 > key3 3\n
569 > key3 3\n
570 > baz\n
570 > baz\n
571 > readline
571 > readline
572 > readline
572 > readline
573 > readline
573 > readline
574 > readline
574 > readline
575 > readline
575 > readline
576 > readline
576 > readline
577 > readline
577 > readline
578 > readline
578 > readline
579 > raw
579 > raw
580 > hello\n
580 > hello\n
581 > readline
581 > readline
582 > readline
582 > readline
583 > EOF
583 > EOF
584 using raw connection to peer
584 using raw connection to peer
585 i> write(48) -> 48:
585 i> write(48) -> 48:
586 i> unknown\n
586 i> unknown\n
587 i> dict 3\n
587 i> dict 3\n
588 i> key1 3\n
588 i> key1 3\n
589 i> foo\n
589 i> foo\n
590 i> key2 3\n
590 i> key2 3\n
591 i> bar\n
591 i> bar\n
592 i> key3 3\n
592 i> key3 3\n
593 i> baz\n
593 i> baz\n
594 o> readline() -> 2:
594 o> readline() -> 2:
595 o> 0\n
595 o> 0\n
596 o> readline() -> 2:
596 o> readline() -> 2:
597 o> 0\n
597 o> 0\n
598 o> readline() -> 2:
598 o> readline() -> 2:
599 o> 0\n
599 o> 0\n
600 o> readline() -> 2:
600 o> readline() -> 2:
601 o> 0\n
601 o> 0\n
602 o> readline() -> 2:
602 o> readline() -> 2:
603 o> 0\n
603 o> 0\n
604 o> readline() -> 2:
604 o> readline() -> 2:
605 o> 0\n
605 o> 0\n
606 o> readline() -> 2:
606 o> readline() -> 2:
607 o> 0\n
607 o> 0\n
608 o> readline() -> 2:
608 o> readline() -> 2:
609 o> 0\n
609 o> 0\n
610 i> write(6) -> 6:
610 i> write(6) -> 6:
611 i> hello\n
611 i> hello\n
612 o> readline() -> 4:
612 o> readline() -> 4:
613 o> 413\n
613 o> 413\n
614 o> readline() -> 413:
614 o> readline() -> 413:
615 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
615 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
616
616
617 Incomplete dictionary send
617 Incomplete dictionary send
618
618
619 $ hg debugwireproto --localssh --peer raw << EOF
619 $ hg debugwireproto --localssh --peer raw << EOF
620 > raw
620 > raw
621 > unknown\n
621 > unknown\n
622 > dict 3\n
622 > dict 3\n
623 > key1 3\n
623 > key1 3\n
624 > foo\n
624 > foo\n
625 > readline
625 > readline
626 > readline
626 > readline
627 > readline
627 > readline
628 > readline
628 > readline
629 > EOF
629 > EOF
630 using raw connection to peer
630 using raw connection to peer
631 i> write(26) -> 26:
631 i> write(26) -> 26:
632 i> unknown\n
632 i> unknown\n
633 i> dict 3\n
633 i> dict 3\n
634 i> key1 3\n
634 i> key1 3\n
635 i> foo\n
635 i> foo\n
636 o> readline() -> 2:
636 o> readline() -> 2:
637 o> 0\n
637 o> 0\n
638 o> readline() -> 2:
638 o> readline() -> 2:
639 o> 0\n
639 o> 0\n
640 o> readline() -> 2:
640 o> readline() -> 2:
641 o> 0\n
641 o> 0\n
642 o> readline() -> 2:
642 o> readline() -> 2:
643 o> 0\n
643 o> 0\n
644
644
645 Incomplete value send
645 Incomplete value send
646
646
647 $ hg debugwireproto --localssh --peer raw << EOF
647 $ hg debugwireproto --localssh --peer raw << EOF
648 > raw
648 > raw
649 > unknown\n
649 > unknown\n
650 > dict 3\n
650 > dict 3\n
651 > key1 3\n
651 > key1 3\n
652 > fo
652 > fo
653 > readline
653 > readline
654 > readline
654 > readline
655 > readline
655 > readline
656 > EOF
656 > EOF
657 using raw connection to peer
657 using raw connection to peer
658 i> write(24) -> 24:
658 i> write(24) -> 24:
659 i> unknown\n
659 i> unknown\n
660 i> dict 3\n
660 i> dict 3\n
661 i> key1 3\n
661 i> key1 3\n
662 i> fo
662 i> fo
663 o> readline() -> 2:
663 o> readline() -> 2:
664 o> 0\n
664 o> 0\n
665 o> readline() -> 2:
665 o> readline() -> 2:
666 o> 0\n
666 o> 0\n
667 o> readline() -> 2:
667 o> readline() -> 2:
668 o> 0\n
668 o> 0\n
669
669
670 Send a command line with spaces
670 Send a command line with spaces
671
671
672 $ hg debugwireproto --localssh --peer raw << EOF
672 $ hg debugwireproto --localssh --peer raw << EOF
673 > raw
673 > raw
674 > unknown withspace\n
674 > unknown withspace\n
675 > readline
675 > readline
676 > raw
676 > raw
677 > hello\n
677 > hello\n
678 > readline
678 > readline
679 > readline
679 > readline
680 > raw
680 > raw
681 > between\n
681 > between\n
682 > pairs 81\n
682 > pairs 81\n
683 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
683 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
684 > readline
684 > readline
685 > readline
685 > readline
686 > EOF
686 > EOF
687 using raw connection to peer
687 using raw connection to peer
688 i> write(18) -> 18:
688 i> write(18) -> 18:
689 i> unknown withspace\n
689 i> unknown withspace\n
690 o> readline() -> 2:
690 o> readline() -> 2:
691 o> 0\n
691 o> 0\n
692 i> write(6) -> 6:
692 i> write(6) -> 6:
693 i> hello\n
693 i> hello\n
694 o> readline() -> 4:
694 o> readline() -> 4:
695 o> 413\n
695 o> 413\n
696 o> readline() -> 413:
696 o> readline() -> 413:
697 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
697 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
698 i> write(98) -> 98:
698 i> write(98) -> 98:
699 i> between\n
699 i> between\n
700 i> pairs 81\n
700 i> pairs 81\n
701 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
701 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
702 o> readline() -> 2:
702 o> readline() -> 2:
703 o> 1\n
703 o> 1\n
704 o> readline() -> 1:
704 o> readline() -> 1:
705 o> \n
705 o> \n
706
706
707 $ hg debugwireproto --localssh --peer raw << EOF
707 $ hg debugwireproto --localssh --peer raw << EOF
708 > raw
708 > raw
709 > unknown with multiple spaces\n
709 > unknown with multiple spaces\n
710 > readline
710 > readline
711 > raw
711 > raw
712 > hello\n
712 > hello\n
713 > readline
713 > readline
714 > readline
714 > readline
715 > raw
715 > raw
716 > between\n
716 > between\n
717 > pairs 81\n
717 > pairs 81\n
718 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
718 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
719 > readline
719 > readline
720 > EOF
720 > EOF
721 using raw connection to peer
721 using raw connection to peer
722 i> write(29) -> 29:
722 i> write(29) -> 29:
723 i> unknown with multiple spaces\n
723 i> unknown with multiple spaces\n
724 o> readline() -> 2:
724 o> readline() -> 2:
725 o> 0\n
725 o> 0\n
726 i> write(6) -> 6:
726 i> write(6) -> 6:
727 i> hello\n
727 i> hello\n
728 o> readline() -> 4:
728 o> readline() -> 4:
729 o> 413\n
729 o> 413\n
730 o> readline() -> 413:
730 o> readline() -> 413:
731 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
731 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
732 i> write(98) -> 98:
732 i> write(98) -> 98:
733 i> between\n
733 i> between\n
734 i> pairs 81\n
734 i> pairs 81\n
735 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
735 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
736 o> readline() -> 2:
736 o> readline() -> 2:
737 o> 1\n
737 o> 1\n
738
738
739 $ hg debugwireproto --localssh --peer raw << EOF
739 $ hg debugwireproto --localssh --peer raw << EOF
740 > raw
740 > raw
741 > unknown with spaces\n
741 > unknown with spaces\n
742 > key 10\n
742 > key 10\n
743 > some value\n
743 > some value\n
744 > readline
744 > readline
745 > readline
745 > readline
746 > readline
746 > readline
747 > raw
747 > raw
748 > hello\n
748 > hello\n
749 > readline
749 > readline
750 > readline
750 > readline
751 > raw
751 > raw
752 > between\n
752 > between\n
753 > pairs 81\n
753 > pairs 81\n
754 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
754 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
755 > readline
755 > readline
756 > readline
756 > readline
757 > EOF
757 > EOF
758 using raw connection to peer
758 using raw connection to peer
759 i> write(38) -> 38:
759 i> write(38) -> 38:
760 i> unknown with spaces\n
760 i> unknown with spaces\n
761 i> key 10\n
761 i> key 10\n
762 i> some value\n
762 i> some value\n
763 o> readline() -> 2:
763 o> readline() -> 2:
764 o> 0\n
764 o> 0\n
765 o> readline() -> 2:
765 o> readline() -> 2:
766 o> 0\n
766 o> 0\n
767 o> readline() -> 2:
767 o> readline() -> 2:
768 o> 0\n
768 o> 0\n
769 i> write(6) -> 6:
769 i> write(6) -> 6:
770 i> hello\n
770 i> hello\n
771 o> readline() -> 4:
771 o> readline() -> 4:
772 o> 413\n
772 o> 413\n
773 o> readline() -> 413:
773 o> readline() -> 413:
774 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
774 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
775 i> write(98) -> 98:
775 i> write(98) -> 98:
776 i> between\n
776 i> between\n
777 i> pairs 81\n
777 i> pairs 81\n
778 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
778 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
779 o> readline() -> 2:
779 o> readline() -> 2:
780 o> 1\n
780 o> 1\n
781 o> readline() -> 1:
781 o> readline() -> 1:
782 o> \n
782 o> \n
783 Send an unknown command after the "between"
783 Send an unknown command after the "between"
784
784
785 $ hg debugwireproto --localssh --peer raw << EOF
785 $ hg debugwireproto --localssh --peer raw << EOF
786 > raw
786 > raw
787 > hello\n
787 > hello\n
788 > readline
788 > readline
789 > readline
789 > readline
790 > raw
790 > raw
791 > between\n
791 > between\n
792 > pairs 81\n
792 > pairs 81\n
793 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000unknown
793 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000unknown
794 > readline
794 > readline
795 > readline
795 > readline
796 > EOF
796 > EOF
797 using raw connection to peer
797 using raw connection to peer
798 i> write(6) -> 6:
798 i> write(6) -> 6:
799 i> hello\n
799 i> hello\n
800 o> readline() -> 4:
800 o> readline() -> 4:
801 o> 413\n
801 o> 413\n
802 o> readline() -> 413:
802 o> readline() -> 413:
803 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
803 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
804 i> write(105) -> 105:
804 i> write(105) -> 105:
805 i> between\n
805 i> between\n
806 i> pairs 81\n
806 i> pairs 81\n
807 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000unknown
807 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000unknown
808 o> readline() -> 2:
808 o> readline() -> 2:
809 o> 1\n
809 o> 1\n
810 o> readline() -> 1:
810 o> readline() -> 1:
811 o> \n
811 o> \n
812
812
813 And one with arguments
813 And one with arguments
814
814
815 $ hg debugwireproto --localssh --peer raw << EOF
815 $ hg debugwireproto --localssh --peer raw << EOF
816 > raw
816 > raw
817 > hello\n
817 > hello\n
818 > between\n
818 > between\n
819 > pairs 81\n
819 > pairs 81\n
820 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
820 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
821 > readline
821 > readline
822 > readline
822 > readline
823 > readline
823 > readline
824 > readline
824 > readline
825 > raw
825 > raw
826 > unknown\n
826 > unknown\n
827 > foo 5\n
827 > foo 5\n
828 > \nvalue\n
828 > \nvalue\n
829 > bar 3\n
829 > bar 3\n
830 > baz\n
830 > baz\n
831 > readline
831 > readline
832 > readline
832 > readline
833 > readline
833 > readline
834 > EOF
834 > EOF
835 using raw connection to peer
835 using raw connection to peer
836 i> write(104) -> 104:
836 i> write(104) -> 104:
837 i> hello\n
837 i> hello\n
838 i> between\n
838 i> between\n
839 i> pairs 81\n
839 i> pairs 81\n
840 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
840 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
841 o> readline() -> 4:
841 o> readline() -> 4:
842 o> 413\n
842 o> 413\n
843 o> readline() -> 413:
843 o> readline() -> 413:
844 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
844 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
845 o> readline() -> 2:
845 o> readline() -> 2:
846 o> 1\n
846 o> 1\n
847 o> readline() -> 1:
847 o> readline() -> 1:
848 o> \n
848 o> \n
849 i> write(31) -> 31:
849 i> write(31) -> 31:
850 i> unknown\n
850 i> unknown\n
851 i> foo 5\n
851 i> foo 5\n
852 i> \n
852 i> \n
853 i> value\n
853 i> value\n
854 i> bar 3\n
854 i> bar 3\n
855 i> baz\n
855 i> baz\n
856 o> readline() -> 2:
856 o> readline() -> 2:
857 o> 0\n
857 o> 0\n
858 o> readline() -> 2:
858 o> readline() -> 2:
859 o> 0\n
859 o> 0\n
860 o> readline() -> 0:
860 o> readline() -> 0:
861
861
862 Send a valid command before the handshake
862 Send a valid command before the handshake
863
863
864 $ hg debugwireproto --localssh --peer raw << EOF
864 $ hg debugwireproto --localssh --peer raw << EOF
865 > raw
865 > raw
866 > heads\n
866 > heads\n
867 > readline
867 > readline
868 > raw
868 > raw
869 > hello\n
869 > hello\n
870 > between\n
870 > between\n
871 > pairs 81\n
871 > pairs 81\n
872 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
872 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
873 > readline
873 > readline
874 > readline
874 > readline
875 > readline
875 > readline
876 > readline
876 > readline
877 > EOF
877 > EOF
878 using raw connection to peer
878 using raw connection to peer
879 i> write(6) -> 6:
879 i> write(6) -> 6:
880 i> heads\n
880 i> heads\n
881 o> readline() -> 3:
881 o> readline() -> 3:
882 o> 41\n
882 o> 41\n
883 i> write(104) -> 104:
883 i> write(104) -> 104:
884 i> hello\n
884 i> hello\n
885 i> between\n
885 i> between\n
886 i> pairs 81\n
886 i> pairs 81\n
887 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
887 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
888 o> readline() -> 41:
888 o> readline() -> 41:
889 o> 68986213bd4485ea51533535e3fc9e78007a711f\n
889 o> 68986213bd4485ea51533535e3fc9e78007a711f\n
890 o> readline() -> 4:
890 o> readline() -> 4:
891 o> 413\n
891 o> 413\n
892 o> readline() -> 413:
892 o> readline() -> 413:
893 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
893 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
894 o> readline() -> 2:
894 o> readline() -> 2:
895 o> 1\n
895 o> 1\n
896
896
897 And a variation that doesn't send the between command
897 And a variation that doesn't send the between command
898
898
899 $ hg debugwireproto --localssh --peer raw << EOF
899 $ hg debugwireproto --localssh --peer raw << EOF
900 > raw
900 > raw
901 > heads\n
901 > heads\n
902 > readline
902 > readline
903 > raw
903 > raw
904 > hello\n
904 > hello\n
905 > readline
905 > readline
906 > readline
906 > readline
907 > EOF
907 > EOF
908 using raw connection to peer
908 using raw connection to peer
909 i> write(6) -> 6:
909 i> write(6) -> 6:
910 i> heads\n
910 i> heads\n
911 o> readline() -> 3:
911 o> readline() -> 3:
912 o> 41\n
912 o> 41\n
913 i> write(6) -> 6:
913 i> write(6) -> 6:
914 i> hello\n
914 i> hello\n
915 o> readline() -> 41:
915 o> readline() -> 41:
916 o> 68986213bd4485ea51533535e3fc9e78007a711f\n
916 o> 68986213bd4485ea51533535e3fc9e78007a711f\n
917 o> readline() -> 4:
917 o> readline() -> 4:
918 o> 413\n
918 o> 413\n
919
919
920 Send an upgrade request to a server that doesn't support that command
920 Send an upgrade request to a server that doesn't support that command
921
921
922 $ hg debugwireproto --localssh --peer raw << EOF
922 $ hg debugwireproto --localssh --peer raw << EOF
923 > raw
923 > raw
924 > upgrade 2e82ab3f-9ce3-4b4e-8f8c-6fd1c0e9e23a proto=irrelevant1%2Cirrelevant2\n
924 > upgrade 2e82ab3f-9ce3-4b4e-8f8c-6fd1c0e9e23a proto=irrelevant1%2Cirrelevant2\n
925 > readline
925 > readline
926 > raw
926 > raw
927 > hello\n
927 > hello\n
928 > between\n
928 > between\n
929 > pairs 81\n
929 > pairs 81\n
930 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
930 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
931 > readline
931 > readline
932 > readline
932 > readline
933 > readline
933 > readline
934 > readline
934 > readline
935 > EOF
935 > EOF
936 using raw connection to peer
936 using raw connection to peer
937 i> write(77) -> 77:
937 i> write(77) -> 77:
938 i> upgrade 2e82ab3f-9ce3-4b4e-8f8c-6fd1c0e9e23a proto=irrelevant1%2Cirrelevant2\n
938 i> upgrade 2e82ab3f-9ce3-4b4e-8f8c-6fd1c0e9e23a proto=irrelevant1%2Cirrelevant2\n
939 o> readline() -> 2:
939 o> readline() -> 2:
940 o> 0\n
940 o> 0\n
941 i> write(104) -> 104:
941 i> write(104) -> 104:
942 i> hello\n
942 i> hello\n
943 i> between\n
943 i> between\n
944 i> pairs 81\n
944 i> pairs 81\n
945 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
945 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
946 o> readline() -> 4:
946 o> readline() -> 4:
947 o> 413\n
947 o> 413\n
948 o> readline() -> 413:
948 o> readline() -> 413:
949 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
949 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
950 o> readline() -> 2:
950 o> readline() -> 2:
951 o> 1\n
951 o> 1\n
952 o> readline() -> 1:
952 o> readline() -> 1:
953 o> \n
953 o> \n
954
954
955 $ cd ..
955 $ cd ..
956
956
957 $ hg --config experimental.sshpeer.advertise-v2=true --debug debugpeer ssh://user@dummy/server
957 $ hg --config experimental.sshpeer.advertise-v2=true --debug debugpeer ssh://user@dummy/server
958 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
958 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
959 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
959 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
960 sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
960 sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
961 devel-peer-request: hello
961 devel-peer-request: hello
962 sending hello command
962 sending hello command
963 devel-peer-request: between
963 devel-peer-request: between
964 devel-peer-request: pairs: 81 bytes
964 devel-peer-request: pairs: 81 bytes
965 sending between command
965 sending between command
966 remote: 0
966 remote: 0
967 remote: 413
967 remote: 413
968 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
968 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
969 remote: 1
969 remote: 1
970 devel-peer-request: protocaps
970 devel-peer-request: protocaps
971 devel-peer-request: caps: * bytes (glob)
971 devel-peer-request: caps: * bytes (glob)
972 sending protocaps command
972 sending protocaps command
973 url: ssh://user@dummy/server
973 url: ssh://user@dummy/server
974 local: no
974 local: no
975 pushable: yes
975 pushable: yes
976
976
977 Enable version 2 support on server. We need to do this in hgrc because we can't
977 Enable version 2 support on server. We need to do this in hgrc because we can't
978 use --config with `hg serve --stdio`.
978 use --config with `hg serve --stdio`.
979
979
980 $ cat >> server/.hg/hgrc << EOF
980 $ cat >> server/.hg/hgrc << EOF
981 > [experimental]
981 > [experimental]
982 > sshserver.support-v2 = true
982 > sshserver.support-v2 = true
983 > EOF
983 > EOF
984
984
985 Send an upgrade request to a server that supports upgrade
985 Send an upgrade request to a server that supports upgrade
986
986
987 $ cd server
987 $ cd server
988
988
989 $ hg debugwireproto --localssh --peer raw << EOF
989 $ hg debugwireproto --localssh --peer raw << EOF
990 > raw
990 > raw
991 > upgrade this-is-some-token proto=exp-ssh-v2-0001\n
991 > upgrade this-is-some-token proto=exp-ssh-v2-0001\n
992 > hello\n
992 > hello\n
993 > between\n
993 > between\n
994 > pairs 81\n
994 > pairs 81\n
995 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
995 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
996 > readline
996 > readline
997 > readline
997 > readline
998 > readline
998 > readline
999 > EOF
999 > EOF
1000 using raw connection to peer
1000 using raw connection to peer
1001 i> write(153) -> 153:
1001 i> write(153) -> 153:
1002 i> upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1002 i> upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1003 i> hello\n
1003 i> hello\n
1004 i> between\n
1004 i> between\n
1005 i> pairs 81\n
1005 i> pairs 81\n
1006 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1006 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1007 o> readline() -> 44:
1007 o> readline() -> 44:
1008 o> upgraded this-is-some-token exp-ssh-v2-0001\n
1008 o> upgraded this-is-some-token exp-ssh-v2-0001\n
1009 o> readline() -> 4:
1009 o> readline() -> 4:
1010 o> 412\n
1010 o> 412\n
1011 o> readline() -> 413:
1011 o> readline() -> 413:
1012 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1012 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1013
1013
1014 $ cd ..
1014 $ cd ..
1015
1015
1016 $ hg --config experimental.sshpeer.advertise-v2=true --debug debugpeer ssh://user@dummy/server
1016 $ hg --config experimental.sshpeer.advertise-v2=true --debug debugpeer ssh://user@dummy/server
1017 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
1017 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
1018 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
1018 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
1019 sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
1019 sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
1020 devel-peer-request: hello
1020 devel-peer-request: hello
1021 sending hello command
1021 sending hello command
1022 devel-peer-request: between
1022 devel-peer-request: between
1023 devel-peer-request: pairs: 81 bytes
1023 devel-peer-request: pairs: 81 bytes
1024 sending between command
1024 sending between command
1025 protocol upgraded to exp-ssh-v2-0001
1025 protocol upgraded to exp-ssh-v2-0001
1026 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1026 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1027 devel-peer-request: protocaps
1027 devel-peer-request: protocaps
1028 devel-peer-request: caps: * bytes (glob)
1028 devel-peer-request: caps: * bytes (glob)
1029 sending protocaps command
1029 sending protocaps command
1030 url: ssh://user@dummy/server
1030 url: ssh://user@dummy/server
1031 local: no
1031 local: no
1032 pushable: yes
1032 pushable: yes
1033
1033
1034 Verify the peer has capabilities
1034 Verify the peer has capabilities
1035
1035
1036 $ hg --config experimental.sshpeer.advertise-v2=true --debug debugcapabilities ssh://user@dummy/server
1036 $ hg --config experimental.sshpeer.advertise-v2=true --debug debugcapabilities ssh://user@dummy/server
1037 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
1037 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
1038 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
1038 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
1039 sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
1039 sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
1040 devel-peer-request: hello
1040 devel-peer-request: hello
1041 sending hello command
1041 sending hello command
1042 devel-peer-request: between
1042 devel-peer-request: between
1043 devel-peer-request: pairs: 81 bytes
1043 devel-peer-request: pairs: 81 bytes
1044 sending between command
1044 sending between command
1045 protocol upgraded to exp-ssh-v2-0001
1045 protocol upgraded to exp-ssh-v2-0001
1046 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1046 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1047 devel-peer-request: protocaps
1047 devel-peer-request: protocaps
1048 devel-peer-request: caps: * bytes (glob)
1048 devel-peer-request: caps: * bytes (glob)
1049 sending protocaps command
1049 sending protocaps command
1050 Main capabilities:
1050 Main capabilities:
1051 batch
1051 batch
1052 branchmap
1052 branchmap
1053 $USUAL_BUNDLE2_CAPS_SERVER$
1053 $USUAL_BUNDLE2_CAPS_SERVER$
1054 changegroupsubset
1054 changegroupsubset
1055 getbundle
1055 getbundle
1056 known
1056 known
1057 lookup
1057 lookup
1058 protocaps
1058 protocaps
1059 pushkey
1059 pushkey
1060 streamreqs=generaldelta,revlogv1
1060 streamreqs=generaldelta,revlogv1
1061 unbundle=HG10GZ,HG10BZ,HG10UN
1061 unbundle=HG10GZ,HG10BZ,HG10UN
1062 unbundlehash
1062 unbundlehash
1063 Bundle2 capabilities:
1063 Bundle2 capabilities:
1064 HG20
1064 HG20
1065 bookmarks
1065 bookmarks
1066 changegroup
1066 changegroup
1067 01
1067 01
1068 02
1068 02
1069 digests
1069 digests
1070 md5
1070 md5
1071 sha1
1071 sha1
1072 sha512
1072 sha512
1073 error
1073 error
1074 abort
1074 abort
1075 unsupportedcontent
1075 unsupportedcontent
1076 pushraced
1076 pushraced
1077 pushkey
1077 pushkey
1078 hgtagsfnodes
1078 hgtagsfnodes
1079 listkeys
1079 listkeys
1080 phases
1080 phases
1081 heads
1081 heads
1082 pushkey
1082 pushkey
1083 remote-changegroup
1083 remote-changegroup
1084 http
1084 http
1085 https
1085 https
1086 rev-branch-cache
1086 rev-branch-cache
1087
1087
1088 Command after upgrade to version 2 is processed
1088 Command after upgrade to version 2 is processed
1089
1089
1090 $ cd server
1090 $ cd server
1091
1091
1092 $ hg debugwireproto --localssh --peer raw << EOF
1092 $ hg debugwireproto --localssh --peer raw << EOF
1093 > raw
1093 > raw
1094 > upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1094 > upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1095 > hello\n
1095 > hello\n
1096 > between\n
1096 > between\n
1097 > pairs 81\n
1097 > pairs 81\n
1098 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1098 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1099 > readline
1099 > readline
1100 > readline
1100 > readline
1101 > readline
1101 > readline
1102 > raw
1102 > raw
1103 > hello\n
1103 > hello\n
1104 > readline
1104 > readline
1105 > readline
1105 > readline
1106 > EOF
1106 > EOF
1107 using raw connection to peer
1107 using raw connection to peer
1108 i> write(153) -> 153:
1108 i> write(153) -> 153:
1109 i> upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1109 i> upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1110 i> hello\n
1110 i> hello\n
1111 i> between\n
1111 i> between\n
1112 i> pairs 81\n
1112 i> pairs 81\n
1113 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1113 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1114 o> readline() -> 44:
1114 o> readline() -> 44:
1115 o> upgraded this-is-some-token exp-ssh-v2-0001\n
1115 o> upgraded this-is-some-token exp-ssh-v2-0001\n
1116 o> readline() -> 4:
1116 o> readline() -> 4:
1117 o> 412\n
1117 o> 412\n
1118 o> readline() -> 413:
1118 o> readline() -> 413:
1119 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1119 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1120 i> write(6) -> 6:
1120 i> write(6) -> 6:
1121 i> hello\n
1121 i> hello\n
1122 o> readline() -> 4:
1122 o> readline() -> 4:
1123 o> 397\n
1123 o> 397\n
1124 o> readline() -> 397:
1124 o> readline() -> 397:
1125 o> capabilities: branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1125 o> capabilities: branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1126
1126
1127 Multiple upgrades is not allowed
1127 Multiple upgrades is not allowed
1128
1128
1129 $ hg debugwireproto --localssh --peer raw << EOF
1129 $ hg debugwireproto --localssh --peer raw << EOF
1130 > raw
1130 > raw
1131 > upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1131 > upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1132 > hello\n
1132 > hello\n
1133 > between\n
1133 > between\n
1134 > pairs 81\n
1134 > pairs 81\n
1135 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1135 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1136 > readline
1136 > readline
1137 > readline
1137 > readline
1138 > readline
1138 > readline
1139 > raw
1139 > raw
1140 > upgrade another-token proto=irrelevant\n
1140 > upgrade another-token proto=irrelevant\n
1141 > hello\n
1141 > hello\n
1142 > readline
1142 > readline
1143 > readavailable
1143 > readavailable
1144 > EOF
1144 > EOF
1145 using raw connection to peer
1145 using raw connection to peer
1146 i> write(153) -> 153:
1146 i> write(153) -> 153:
1147 i> upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1147 i> upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1148 i> hello\n
1148 i> hello\n
1149 i> between\n
1149 i> between\n
1150 i> pairs 81\n
1150 i> pairs 81\n
1151 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1151 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1152 o> readline() -> 44:
1152 o> readline() -> 44:
1153 o> upgraded this-is-some-token exp-ssh-v2-0001\n
1153 o> upgraded this-is-some-token exp-ssh-v2-0001\n
1154 o> readline() -> 4:
1154 o> readline() -> 4:
1155 o> 412\n
1155 o> 412\n
1156 o> readline() -> 413:
1156 o> readline() -> 413:
1157 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1157 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1158 i> write(45) -> 45:
1158 i> write(45) -> 45:
1159 i> upgrade another-token proto=irrelevant\n
1159 i> upgrade another-token proto=irrelevant\n
1160 i> hello\n
1160 i> hello\n
1161 o> readline() -> 1:
1161 o> readline() -> 1:
1162 o> \n
1162 o> \n
1163 o> read(-1) -> 0:
1163 o> read(-1) -> 0:
1164 e> read(-1) -> 42:
1164 e> read(-1) -> 42:
1165 e> cannot upgrade protocols multiple times\n
1165 e> cannot upgrade protocols multiple times\n
1166 e> -\n
1166 e> -\n
1167
1167
1168 Malformed upgrade request line (not exactly 3 space delimited tokens)
1168 Malformed upgrade request line (not exactly 3 space delimited tokens)
1169
1169
1170 $ hg debugwireproto --localssh --peer raw << EOF
1170 $ hg debugwireproto --localssh --peer raw << EOF
1171 > raw
1171 > raw
1172 > upgrade\n
1172 > upgrade\n
1173 > readline
1173 > readline
1174 > EOF
1174 > EOF
1175 using raw connection to peer
1175 using raw connection to peer
1176 i> write(8) -> 8:
1176 i> write(8) -> 8:
1177 i> upgrade\n
1177 i> upgrade\n
1178 o> readline() -> 2:
1178 o> readline() -> 2:
1179 o> 0\n
1179 o> 0\n
1180
1180
1181 $ hg debugwireproto --localssh --peer raw << EOF
1181 $ hg debugwireproto --localssh --peer raw << EOF
1182 > raw
1182 > raw
1183 > upgrade token\n
1183 > upgrade token\n
1184 > readline
1184 > readline
1185 > EOF
1185 > EOF
1186 using raw connection to peer
1186 using raw connection to peer
1187 i> write(14) -> 14:
1187 i> write(14) -> 14:
1188 i> upgrade token\n
1188 i> upgrade token\n
1189 o> readline() -> 2:
1189 o> readline() -> 2:
1190 o> 0\n
1190 o> 0\n
1191
1191
1192 $ hg debugwireproto --localssh --peer raw << EOF
1192 $ hg debugwireproto --localssh --peer raw << EOF
1193 > raw
1193 > raw
1194 > upgrade token foo=bar extra-token\n
1194 > upgrade token foo=bar extra-token\n
1195 > readline
1195 > readline
1196 > EOF
1196 > EOF
1197 using raw connection to peer
1197 using raw connection to peer
1198 i> write(34) -> 34:
1198 i> write(34) -> 34:
1199 i> upgrade token foo=bar extra-token\n
1199 i> upgrade token foo=bar extra-token\n
1200 o> readline() -> 2:
1200 o> readline() -> 2:
1201 o> 0\n
1201 o> 0\n
1202
1202
1203 Upgrade request to unsupported protocol is ignored
1203 Upgrade request to unsupported protocol is ignored
1204
1204
1205 $ hg debugwireproto --localssh --peer raw << EOF
1205 $ hg debugwireproto --localssh --peer raw << EOF
1206 > raw
1206 > raw
1207 > upgrade this-is-some-token proto=unknown1,unknown2\n
1207 > upgrade this-is-some-token proto=unknown1,unknown2\n
1208 > readline
1208 > readline
1209 > raw
1209 > raw
1210 > hello\n
1210 > hello\n
1211 > readline
1211 > readline
1212 > readline
1212 > readline
1213 > raw
1213 > raw
1214 > between\n
1214 > between\n
1215 > pairs 81\n
1215 > pairs 81\n
1216 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1216 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1217 > readline
1217 > readline
1218 > readline
1218 > readline
1219 > EOF
1219 > EOF
1220 using raw connection to peer
1220 using raw connection to peer
1221 i> write(51) -> 51:
1221 i> write(51) -> 51:
1222 i> upgrade this-is-some-token proto=unknown1,unknown2\n
1222 i> upgrade this-is-some-token proto=unknown1,unknown2\n
1223 o> readline() -> 2:
1223 o> readline() -> 2:
1224 o> 0\n
1224 o> 0\n
1225 i> write(6) -> 6:
1225 i> write(6) -> 6:
1226 i> hello\n
1226 i> hello\n
1227 o> readline() -> 4:
1227 o> readline() -> 4:
1228 o> 413\n
1228 o> 413\n
1229 o> readline() -> 413:
1229 o> readline() -> 413:
1230 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1230 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1231 i> write(98) -> 98:
1231 i> write(98) -> 98:
1232 i> between\n
1232 i> between\n
1233 i> pairs 81\n
1233 i> pairs 81\n
1234 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1234 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1235 o> readline() -> 2:
1235 o> readline() -> 2:
1236 o> 1\n
1236 o> 1\n
1237 o> readline() -> 1:
1237 o> readline() -> 1:
1238 o> \n
1238 o> \n
1239
1239
1240 Upgrade request must be followed by hello + between
1240 Upgrade request must be followed by hello + between
1241
1241
1242 $ hg debugwireproto --localssh --peer raw << EOF
1242 $ hg debugwireproto --localssh --peer raw << EOF
1243 > raw
1243 > raw
1244 > upgrade token proto=exp-ssh-v2-0001\n
1244 > upgrade token proto=exp-ssh-v2-0001\n
1245 > invalid\n
1245 > invalid\n
1246 > readline
1246 > readline
1247 > readavailable
1247 > readavailable
1248 > EOF
1248 > EOF
1249 using raw connection to peer
1249 using raw connection to peer
1250 i> write(44) -> 44:
1250 i> write(44) -> 44:
1251 i> upgrade token proto=exp-ssh-v2-0001\n
1251 i> upgrade token proto=exp-ssh-v2-0001\n
1252 i> invalid\n
1252 i> invalid\n
1253 o> readline() -> 1:
1253 o> readline() -> 1:
1254 o> \n
1254 o> \n
1255 o> read(-1) -> 0:
1255 o> read(-1) -> 0:
1256 e> read(-1) -> 46:
1256 e> read(-1) -> 46:
1257 e> malformed handshake protocol: missing hello\n
1257 e> malformed handshake protocol: missing hello\n
1258 e> -\n
1258 e> -\n
1259
1259
1260 $ hg debugwireproto --localssh --peer raw << EOF
1260 $ hg debugwireproto --localssh --peer raw << EOF
1261 > raw
1261 > raw
1262 > upgrade token proto=exp-ssh-v2-0001\n
1262 > upgrade token proto=exp-ssh-v2-0001\n
1263 > hello\n
1263 > hello\n
1264 > invalid\n
1264 > invalid\n
1265 > readline
1265 > readline
1266 > readavailable
1266 > readavailable
1267 > EOF
1267 > EOF
1268 using raw connection to peer
1268 using raw connection to peer
1269 i> write(50) -> 50:
1269 i> write(50) -> 50:
1270 i> upgrade token proto=exp-ssh-v2-0001\n
1270 i> upgrade token proto=exp-ssh-v2-0001\n
1271 i> hello\n
1271 i> hello\n
1272 i> invalid\n
1272 i> invalid\n
1273 o> readline() -> 1:
1273 o> readline() -> 1:
1274 o> \n
1274 o> \n
1275 o> read(-1) -> 0:
1275 o> read(-1) -> 0:
1276 e> read(-1) -> 48:
1276 e> read(-1) -> 48:
1277 e> malformed handshake protocol: missing between\n
1277 e> malformed handshake protocol: missing between\n
1278 e> -\n
1278 e> -\n
1279
1279
1280 $ hg debugwireproto --localssh --peer raw << EOF
1280 $ hg debugwireproto --localssh --peer raw << EOF
1281 > raw
1281 > raw
1282 > upgrade token proto=exp-ssh-v2-0001\n
1282 > upgrade token proto=exp-ssh-v2-0001\n
1283 > hello\n
1283 > hello\n
1284 > between\n
1284 > between\n
1285 > invalid\n
1285 > invalid\n
1286 > readline
1286 > readline
1287 > readavailable
1287 > readavailable
1288 > EOF
1288 > EOF
1289 using raw connection to peer
1289 using raw connection to peer
1290 i> write(58) -> 58:
1290 i> write(58) -> 58:
1291 i> upgrade token proto=exp-ssh-v2-0001\n
1291 i> upgrade token proto=exp-ssh-v2-0001\n
1292 i> hello\n
1292 i> hello\n
1293 i> between\n
1293 i> between\n
1294 i> invalid\n
1294 i> invalid\n
1295 o> readline() -> 1:
1295 o> readline() -> 1:
1296 o> \n
1296 o> \n
1297 o> read(-1) -> 0:
1297 o> read(-1) -> 0:
1298 e> read(-1) -> 49:
1298 e> read(-1) -> 49:
1299 e> malformed handshake protocol: missing pairs 81\n
1299 e> malformed handshake protocol: missing pairs 81\n
1300 e> -\n
1300 e> -\n
1301
1301
1302 Legacy commands are not exposed to version 2 of protocol
1302 Legacy commands are not exposed to version 2 of protocol
1303
1303
1304 TODO re-enable these once we're back to actually using v2 commands
1304 TODO re-enable these once we're back to actually using v2 commands
1305
1305
1306 $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF
1306 $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF
1307 > command branches
1307 > command branches
1308 > nodes 0000000000000000000000000000000000000000
1308 > nodes 0000000000000000000000000000000000000000
1309 > EOF
1309 > EOF
1310 creating ssh peer from handshake results
1310 creating ssh peer from handshake results
1311 sending branches command
1311 sending branches command
1312 response:
1312 response:
1313
1313
1314 $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF
1314 $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF
1315 > command changegroup
1315 > command changegroup
1316 > roots 0000000000000000000000000000000000000000
1316 > roots 0000000000000000000000000000000000000000
1317 > EOF
1317 > EOF
1318 creating ssh peer from handshake results
1318 creating ssh peer from handshake results
1319 sending changegroup command
1319 sending changegroup command
1320 response:
1320 response:
1321
1321
1322 $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF
1322 $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF
1323 > command changegroupsubset
1323 > command changegroupsubset
1324 > bases 0000000000000000000000000000000000000000
1324 > bases 0000000000000000000000000000000000000000
1325 > heads 0000000000000000000000000000000000000000
1325 > heads 0000000000000000000000000000000000000000
1326 > EOF
1326 > EOF
1327 creating ssh peer from handshake results
1327 creating ssh peer from handshake results
1328 sending changegroupsubset command
1328 sending changegroupsubset command
1329 response:
1329 response:
1330
1330
1331 $ cd ..
1331 $ cd ..
1332
1332
1333 Test listkeys for listing namespaces
1333 Test listkeys for listing namespaces
1334
1334
1335 $ hg init empty
1335 $ hg init empty
1336 $ cd empty
1336 $ cd empty
1337 $ debugwireproto << EOF
1337 $ debugwireproto << EOF
1338 > command listkeys
1338 > command listkeys
1339 > namespace namespaces
1339 > namespace namespaces
1340 > EOF
1340 > EOF
1341 testing ssh1
1341 testing ssh1
1342 creating ssh peer from handshake results
1342 creating ssh peer from handshake results
1343 i> write(104) -> 104:
1343 i> write(104) -> 104:
1344 i> hello\n
1344 i> hello\n
1345 i> between\n
1345 i> between\n
1346 i> pairs 81\n
1346 i> pairs 81\n
1347 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1347 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1348 i> flush() -> None
1348 i> flush() -> None
1349 o> readline() -> 4:
1349 o> readline() -> 4:
1350 o> 413\n
1350 o> 413\n
1351 o> readline() -> 413:
1351 o> readline() -> 413:
1352 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1352 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1353 o> readline() -> 2:
1353 o> readline() -> 2:
1354 o> 1\n
1354 o> 1\n
1355 o> readline() -> 1:
1355 o> readline() -> 1:
1356 o> \n
1356 o> \n
1357 sending listkeys command
1357 sending listkeys command
1358 i> write(9) -> 9:
1358 i> write(9) -> 9:
1359 i> listkeys\n
1359 i> listkeys\n
1360 i> write(13) -> 13:
1360 i> write(13) -> 13:
1361 i> namespace 10\n
1361 i> namespace 10\n
1362 i> write(10) -> 10: namespaces
1362 i> write(10) -> 10: namespaces
1363 i> flush() -> None
1363 i> flush() -> None
1364 o> bufferedreadline() -> 3:
1364 o> bufferedreadline() -> 3:
1365 o> 30\n
1365 o> 30\n
1366 o> bufferedread(30) -> 30:
1366 o> bufferedread(30) -> 30:
1367 o> bookmarks\t\n
1367 o> bookmarks\t\n
1368 o> namespaces\t\n
1368 o> namespaces\t\n
1369 o> phases\t
1369 o> phases\t
1370 response: b'bookmarks\t\nnamespaces\t\nphases\t'
1370 response: {b'bookmarks': b'', b'namespaces': b'', b'phases': b''}
1371
1371
1372 testing ssh2
1372 testing ssh2
1373 creating ssh peer from handshake results
1373 creating ssh peer from handshake results
1374 i> write(171) -> 171:
1374 i> write(171) -> 171:
1375 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1375 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1376 i> hello\n
1376 i> hello\n
1377 i> between\n
1377 i> between\n
1378 i> pairs 81\n
1378 i> pairs 81\n
1379 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1379 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1380 i> flush() -> None
1380 i> flush() -> None
1381 o> readline() -> 62:
1381 o> readline() -> 62:
1382 o> upgraded * exp-ssh-v2-0001\n (glob)
1382 o> upgraded * exp-ssh-v2-0001\n (glob)
1383 o> readline() -> 4:
1383 o> readline() -> 4:
1384 o> 412\n
1384 o> 412\n
1385 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
1385 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
1386 o> read(1) -> 1:
1386 o> read(1) -> 1:
1387 o> \n
1387 o> \n
1388 sending listkeys command
1388 sending listkeys command
1389 i> write(9) -> 9:
1389 i> write(9) -> 9:
1390 i> listkeys\n
1390 i> listkeys\n
1391 i> write(13) -> 13:
1391 i> write(13) -> 13:
1392 i> namespace 10\n
1392 i> namespace 10\n
1393 i> write(10) -> 10: namespaces
1393 i> write(10) -> 10: namespaces
1394 i> flush() -> None
1394 i> flush() -> None
1395 o> bufferedreadline() -> 3:
1395 o> bufferedreadline() -> 3:
1396 o> 30\n
1396 o> 30\n
1397 o> bufferedread(30) -> 30:
1397 o> bufferedread(30) -> 30:
1398 o> bookmarks\t\n
1398 o> bookmarks\t\n
1399 o> namespaces\t\n
1399 o> namespaces\t\n
1400 o> phases\t
1400 o> phases\t
1401 response: b'bookmarks\t\nnamespaces\t\nphases\t'
1401 response: {b'bookmarks': b'', b'namespaces': b'', b'phases': b''}
1402
1402
1403 $ cd ..
1403 $ cd ..
1404
1404
1405 Test listkeys for bookmarks
1405 Test listkeys for bookmarks
1406
1406
1407 $ hg init bookmarkrepo
1407 $ hg init bookmarkrepo
1408 $ cd bookmarkrepo
1408 $ cd bookmarkrepo
1409 $ echo 0 > foo
1409 $ echo 0 > foo
1410 $ hg add foo
1410 $ hg add foo
1411 $ hg -q commit -m initial
1411 $ hg -q commit -m initial
1412 $ echo 1 > foo
1412 $ echo 1 > foo
1413 $ hg commit -m second
1413 $ hg commit -m second
1414
1414
1415 With no bookmarks set
1415 With no bookmarks set
1416
1416
1417 $ debugwireproto << EOF
1417 $ debugwireproto << EOF
1418 > command listkeys
1418 > command listkeys
1419 > namespace bookmarks
1419 > namespace bookmarks
1420 > EOF
1420 > EOF
1421 testing ssh1
1421 testing ssh1
1422 creating ssh peer from handshake results
1422 creating ssh peer from handshake results
1423 i> write(104) -> 104:
1423 i> write(104) -> 104:
1424 i> hello\n
1424 i> hello\n
1425 i> between\n
1425 i> between\n
1426 i> pairs 81\n
1426 i> pairs 81\n
1427 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1427 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1428 i> flush() -> None
1428 i> flush() -> None
1429 o> readline() -> 4:
1429 o> readline() -> 4:
1430 o> 413\n
1430 o> 413\n
1431 o> readline() -> 413:
1431 o> readline() -> 413:
1432 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1432 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1433 o> readline() -> 2:
1433 o> readline() -> 2:
1434 o> 1\n
1434 o> 1\n
1435 o> readline() -> 1:
1435 o> readline() -> 1:
1436 o> \n
1436 o> \n
1437 sending listkeys command
1437 sending listkeys command
1438 i> write(9) -> 9:
1438 i> write(9) -> 9:
1439 i> listkeys\n
1439 i> listkeys\n
1440 i> write(12) -> 12:
1440 i> write(12) -> 12:
1441 i> namespace 9\n
1441 i> namespace 9\n
1442 i> write(9) -> 9: bookmarks
1442 i> write(9) -> 9: bookmarks
1443 i> flush() -> None
1443 i> flush() -> None
1444 o> bufferedreadline() -> 2:
1444 o> bufferedreadline() -> 2:
1445 o> 0\n
1445 o> 0\n
1446 response: b''
1446 response: {}
1447
1447
1448 testing ssh2
1448 testing ssh2
1449 creating ssh peer from handshake results
1449 creating ssh peer from handshake results
1450 i> write(171) -> 171:
1450 i> write(171) -> 171:
1451 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1451 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1452 i> hello\n
1452 i> hello\n
1453 i> between\n
1453 i> between\n
1454 i> pairs 81\n
1454 i> pairs 81\n
1455 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1455 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1456 i> flush() -> None
1456 i> flush() -> None
1457 o> readline() -> 62:
1457 o> readline() -> 62:
1458 o> upgraded * exp-ssh-v2-0001\n (glob)
1458 o> upgraded * exp-ssh-v2-0001\n (glob)
1459 o> readline() -> 4:
1459 o> readline() -> 4:
1460 o> 412\n
1460 o> 412\n
1461 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
1461 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
1462 o> read(1) -> 1:
1462 o> read(1) -> 1:
1463 o> \n
1463 o> \n
1464 sending listkeys command
1464 sending listkeys command
1465 i> write(9) -> 9:
1465 i> write(9) -> 9:
1466 i> listkeys\n
1466 i> listkeys\n
1467 i> write(12) -> 12:
1467 i> write(12) -> 12:
1468 i> namespace 9\n
1468 i> namespace 9\n
1469 i> write(9) -> 9: bookmarks
1469 i> write(9) -> 9: bookmarks
1470 i> flush() -> None
1470 i> flush() -> None
1471 o> bufferedreadline() -> 2:
1471 o> bufferedreadline() -> 2:
1472 o> 0\n
1472 o> 0\n
1473 response: b''
1473 response: {}
1474
1474
1475 With a single bookmark set
1475 With a single bookmark set
1476
1476
1477 $ hg book -r 0 bookA
1477 $ hg book -r 0 bookA
1478 $ debugwireproto << EOF
1478 $ debugwireproto << EOF
1479 > command listkeys
1479 > command listkeys
1480 > namespace bookmarks
1480 > namespace bookmarks
1481 > EOF
1481 > EOF
1482 testing ssh1
1482 testing ssh1
1483 creating ssh peer from handshake results
1483 creating ssh peer from handshake results
1484 i> write(104) -> 104:
1484 i> write(104) -> 104:
1485 i> hello\n
1485 i> hello\n
1486 i> between\n
1486 i> between\n
1487 i> pairs 81\n
1487 i> pairs 81\n
1488 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1488 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1489 i> flush() -> None
1489 i> flush() -> None
1490 o> readline() -> 4:
1490 o> readline() -> 4:
1491 o> 413\n
1491 o> 413\n
1492 o> readline() -> 413:
1492 o> readline() -> 413:
1493 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1493 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1494 o> readline() -> 2:
1494 o> readline() -> 2:
1495 o> 1\n
1495 o> 1\n
1496 o> readline() -> 1:
1496 o> readline() -> 1:
1497 o> \n
1497 o> \n
1498 sending listkeys command
1498 sending listkeys command
1499 i> write(9) -> 9:
1499 i> write(9) -> 9:
1500 i> listkeys\n
1500 i> listkeys\n
1501 i> write(12) -> 12:
1501 i> write(12) -> 12:
1502 i> namespace 9\n
1502 i> namespace 9\n
1503 i> write(9) -> 9: bookmarks
1503 i> write(9) -> 9: bookmarks
1504 i> flush() -> None
1504 i> flush() -> None
1505 o> bufferedreadline() -> 3:
1505 o> bufferedreadline() -> 3:
1506 o> 46\n
1506 o> 46\n
1507 o> bufferedread(46) -> 46: bookA\t68986213bd4485ea51533535e3fc9e78007a711f
1507 o> bufferedread(46) -> 46: bookA\t68986213bd4485ea51533535e3fc9e78007a711f
1508 response: b'bookA\t68986213bd4485ea51533535e3fc9e78007a711f'
1508 response: {b'bookA': b'68986213bd4485ea51533535e3fc9e78007a711f'}
1509
1509
1510 testing ssh2
1510 testing ssh2
1511 creating ssh peer from handshake results
1511 creating ssh peer from handshake results
1512 i> write(171) -> 171:
1512 i> write(171) -> 171:
1513 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1513 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1514 i> hello\n
1514 i> hello\n
1515 i> between\n
1515 i> between\n
1516 i> pairs 81\n
1516 i> pairs 81\n
1517 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1517 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1518 i> flush() -> None
1518 i> flush() -> None
1519 o> readline() -> 62:
1519 o> readline() -> 62:
1520 o> upgraded * exp-ssh-v2-0001\n (glob)
1520 o> upgraded * exp-ssh-v2-0001\n (glob)
1521 o> readline() -> 4:
1521 o> readline() -> 4:
1522 o> 412\n
1522 o> 412\n
1523 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
1523 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
1524 o> read(1) -> 1:
1524 o> read(1) -> 1:
1525 o> \n
1525 o> \n
1526 sending listkeys command
1526 sending listkeys command
1527 i> write(9) -> 9:
1527 i> write(9) -> 9:
1528 i> listkeys\n
1528 i> listkeys\n
1529 i> write(12) -> 12:
1529 i> write(12) -> 12:
1530 i> namespace 9\n
1530 i> namespace 9\n
1531 i> write(9) -> 9: bookmarks
1531 i> write(9) -> 9: bookmarks
1532 i> flush() -> None
1532 i> flush() -> None
1533 o> bufferedreadline() -> 3:
1533 o> bufferedreadline() -> 3:
1534 o> 46\n
1534 o> 46\n
1535 o> bufferedread(46) -> 46: bookA\t68986213bd4485ea51533535e3fc9e78007a711f
1535 o> bufferedread(46) -> 46: bookA\t68986213bd4485ea51533535e3fc9e78007a711f
1536 response: b'bookA\t68986213bd4485ea51533535e3fc9e78007a711f'
1536 response: {b'bookA': b'68986213bd4485ea51533535e3fc9e78007a711f'}
1537
1537
1538 With multiple bookmarks set
1538 With multiple bookmarks set
1539
1539
1540 $ hg book -r 1 bookB
1540 $ hg book -r 1 bookB
1541 $ debugwireproto << EOF
1541 $ debugwireproto << EOF
1542 > command listkeys
1542 > command listkeys
1543 > namespace bookmarks
1543 > namespace bookmarks
1544 > EOF
1544 > EOF
1545 testing ssh1
1545 testing ssh1
1546 creating ssh peer from handshake results
1546 creating ssh peer from handshake results
1547 i> write(104) -> 104:
1547 i> write(104) -> 104:
1548 i> hello\n
1548 i> hello\n
1549 i> between\n
1549 i> between\n
1550 i> pairs 81\n
1550 i> pairs 81\n
1551 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1551 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1552 i> flush() -> None
1552 i> flush() -> None
1553 o> readline() -> 4:
1553 o> readline() -> 4:
1554 o> 413\n
1554 o> 413\n
1555 o> readline() -> 413:
1555 o> readline() -> 413:
1556 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1556 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1557 o> readline() -> 2:
1557 o> readline() -> 2:
1558 o> 1\n
1558 o> 1\n
1559 o> readline() -> 1:
1559 o> readline() -> 1:
1560 o> \n
1560 o> \n
1561 sending listkeys command
1561 sending listkeys command
1562 i> write(9) -> 9:
1562 i> write(9) -> 9:
1563 i> listkeys\n
1563 i> listkeys\n
1564 i> write(12) -> 12:
1564 i> write(12) -> 12:
1565 i> namespace 9\n
1565 i> namespace 9\n
1566 i> write(9) -> 9: bookmarks
1566 i> write(9) -> 9: bookmarks
1567 i> flush() -> None
1567 i> flush() -> None
1568 o> bufferedreadline() -> 3:
1568 o> bufferedreadline() -> 3:
1569 o> 93\n
1569 o> 93\n
1570 o> bufferedread(93) -> 93:
1570 o> bufferedread(93) -> 93:
1571 o> bookA\t68986213bd4485ea51533535e3fc9e78007a711f\n
1571 o> bookA\t68986213bd4485ea51533535e3fc9e78007a711f\n
1572 o> bookB\t1880f3755e2e52e3199e0ee5638128b08642f34d
1572 o> bookB\t1880f3755e2e52e3199e0ee5638128b08642f34d
1573 response: b'bookA\t68986213bd4485ea51533535e3fc9e78007a711f\nbookB\t1880f3755e2e52e3199e0ee5638128b08642f34d'
1573 response: {b'bookA': b'68986213bd4485ea51533535e3fc9e78007a711f', b'bookB': b'1880f3755e2e52e3199e0ee5638128b08642f34d'}
1574
1574
1575 testing ssh2
1575 testing ssh2
1576 creating ssh peer from handshake results
1576 creating ssh peer from handshake results
1577 i> write(171) -> 171:
1577 i> write(171) -> 171:
1578 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1578 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1579 i> hello\n
1579 i> hello\n
1580 i> between\n
1580 i> between\n
1581 i> pairs 81\n
1581 i> pairs 81\n
1582 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1582 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1583 i> flush() -> None
1583 i> flush() -> None
1584 o> readline() -> 62:
1584 o> readline() -> 62:
1585 o> upgraded * exp-ssh-v2-0001\n (glob)
1585 o> upgraded * exp-ssh-v2-0001\n (glob)
1586 o> readline() -> 4:
1586 o> readline() -> 4:
1587 o> 412\n
1587 o> 412\n
1588 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
1588 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
1589 o> read(1) -> 1:
1589 o> read(1) -> 1:
1590 o> \n
1590 o> \n
1591 sending listkeys command
1591 sending listkeys command
1592 i> write(9) -> 9:
1592 i> write(9) -> 9:
1593 i> listkeys\n
1593 i> listkeys\n
1594 i> write(12) -> 12:
1594 i> write(12) -> 12:
1595 i> namespace 9\n
1595 i> namespace 9\n
1596 i> write(9) -> 9: bookmarks
1596 i> write(9) -> 9: bookmarks
1597 i> flush() -> None
1597 i> flush() -> None
1598 o> bufferedreadline() -> 3:
1598 o> bufferedreadline() -> 3:
1599 o> 93\n
1599 o> 93\n
1600 o> bufferedread(93) -> 93:
1600 o> bufferedread(93) -> 93:
1601 o> bookA\t68986213bd4485ea51533535e3fc9e78007a711f\n
1601 o> bookA\t68986213bd4485ea51533535e3fc9e78007a711f\n
1602 o> bookB\t1880f3755e2e52e3199e0ee5638128b08642f34d
1602 o> bookB\t1880f3755e2e52e3199e0ee5638128b08642f34d
1603 response: b'bookA\t68986213bd4485ea51533535e3fc9e78007a711f\nbookB\t1880f3755e2e52e3199e0ee5638128b08642f34d'
1603 response: {b'bookA': b'68986213bd4485ea51533535e3fc9e78007a711f', b'bookB': b'1880f3755e2e52e3199e0ee5638128b08642f34d'}
1604
1604
1605 Test pushkey for bookmarks
1605 Test pushkey for bookmarks
1606
1606
1607 $ debugwireproto << EOF
1607 $ debugwireproto << EOF
1608 > command pushkey
1608 > command pushkey
1609 > namespace bookmarks
1609 > namespace bookmarks
1610 > key remote
1610 > key remote
1611 > old
1611 > old
1612 > new 68986213bd4485ea51533535e3fc9e78007a711f
1612 > new 68986213bd4485ea51533535e3fc9e78007a711f
1613 > EOF
1613 > EOF
1614 testing ssh1
1614 testing ssh1
1615 creating ssh peer from handshake results
1615 creating ssh peer from handshake results
1616 i> write(104) -> 104:
1616 i> write(104) -> 104:
1617 i> hello\n
1617 i> hello\n
1618 i> between\n
1618 i> between\n
1619 i> pairs 81\n
1619 i> pairs 81\n
1620 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1620 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1621 i> flush() -> None
1621 i> flush() -> None
1622 o> readline() -> 4:
1622 o> readline() -> 4:
1623 o> 413\n
1623 o> 413\n
1624 o> readline() -> 413:
1624 o> readline() -> 413:
1625 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1625 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1626 o> readline() -> 2:
1626 o> readline() -> 2:
1627 o> 1\n
1627 o> 1\n
1628 o> readline() -> 1:
1628 o> readline() -> 1:
1629 o> \n
1629 o> \n
1630 sending pushkey command
1630 sending pushkey command
1631 i> write(8) -> 8:
1631 i> write(8) -> 8:
1632 i> pushkey\n
1632 i> pushkey\n
1633 i> write(6) -> 6:
1633 i> write(6) -> 6:
1634 i> key 6\n
1634 i> key 6\n
1635 i> write(6) -> 6: remote
1635 i> write(6) -> 6: remote
1636 i> write(12) -> 12:
1636 i> write(12) -> 12:
1637 i> namespace 9\n
1637 i> namespace 9\n
1638 i> write(9) -> 9: bookmarks
1638 i> write(9) -> 9: bookmarks
1639 i> write(7) -> 7:
1639 i> write(7) -> 7:
1640 i> new 40\n
1640 i> new 40\n
1641 i> write(40) -> 40: 68986213bd4485ea51533535e3fc9e78007a711f
1641 i> write(40) -> 40: 68986213bd4485ea51533535e3fc9e78007a711f
1642 i> write(6) -> 6:
1642 i> write(6) -> 6:
1643 i> old 0\n
1643 i> old 0\n
1644 i> flush() -> None
1644 i> flush() -> None
1645 o> bufferedreadline() -> 2:
1645 o> bufferedreadline() -> 2:
1646 o> 2\n
1646 o> 2\n
1647 o> bufferedread(2) -> 2:
1647 o> bufferedread(2) -> 2:
1648 o> 1\n
1648 o> 1\n
1649 response: b'1\n'
1649 response: True
1650
1650
1651 testing ssh2
1651 testing ssh2
1652 creating ssh peer from handshake results
1652 creating ssh peer from handshake results
1653 i> write(171) -> 171:
1653 i> write(171) -> 171:
1654 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1654 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1655 i> hello\n
1655 i> hello\n
1656 i> between\n
1656 i> between\n
1657 i> pairs 81\n
1657 i> pairs 81\n
1658 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1658 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1659 i> flush() -> None
1659 i> flush() -> None
1660 o> readline() -> 62:
1660 o> readline() -> 62:
1661 o> upgraded * exp-ssh-v2-0001\n (glob)
1661 o> upgraded * exp-ssh-v2-0001\n (glob)
1662 o> readline() -> 4:
1662 o> readline() -> 4:
1663 o> 412\n
1663 o> 412\n
1664 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
1664 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
1665 o> read(1) -> 1:
1665 o> read(1) -> 1:
1666 o> \n
1666 o> \n
1667 sending pushkey command
1667 sending pushkey command
1668 i> write(8) -> 8:
1668 i> write(8) -> 8:
1669 i> pushkey\n
1669 i> pushkey\n
1670 i> write(6) -> 6:
1670 i> write(6) -> 6:
1671 i> key 6\n
1671 i> key 6\n
1672 i> write(6) -> 6: remote
1672 i> write(6) -> 6: remote
1673 i> write(12) -> 12:
1673 i> write(12) -> 12:
1674 i> namespace 9\n
1674 i> namespace 9\n
1675 i> write(9) -> 9: bookmarks
1675 i> write(9) -> 9: bookmarks
1676 i> write(7) -> 7:
1676 i> write(7) -> 7:
1677 i> new 40\n
1677 i> new 40\n
1678 i> write(40) -> 40: 68986213bd4485ea51533535e3fc9e78007a711f
1678 i> write(40) -> 40: 68986213bd4485ea51533535e3fc9e78007a711f
1679 i> write(6) -> 6:
1679 i> write(6) -> 6:
1680 i> old 0\n
1680 i> old 0\n
1681 i> flush() -> None
1681 i> flush() -> None
1682 o> bufferedreadline() -> 2:
1682 o> bufferedreadline() -> 2:
1683 o> 2\n
1683 o> 2\n
1684 o> bufferedread(2) -> 2:
1684 o> bufferedread(2) -> 2:
1685 o> 1\n
1685 o> 1\n
1686 response: b'1\n'
1686 response: True
1687
1687
1688 $ hg bookmarks
1688 $ hg bookmarks
1689 bookA 0:68986213bd44
1689 bookA 0:68986213bd44
1690 bookB 1:1880f3755e2e
1690 bookB 1:1880f3755e2e
1691 remote 0:68986213bd44
1691 remote 0:68986213bd44
1692
1692
1693 $ cd ..
1693 $ cd ..
1694
1694
1695 Test listkeys for phases
1695 Test listkeys for phases
1696
1696
1697 $ hg init phasesrepo
1697 $ hg init phasesrepo
1698 $ cd phasesrepo
1698 $ cd phasesrepo
1699
1699
1700 Phases on empty repo
1700 Phases on empty repo
1701
1701
1702 $ debugwireproto << EOF
1702 $ debugwireproto << EOF
1703 > command listkeys
1703 > command listkeys
1704 > namespace phases
1704 > namespace phases
1705 > EOF
1705 > EOF
1706 testing ssh1
1706 testing ssh1
1707 creating ssh peer from handshake results
1707 creating ssh peer from handshake results
1708 i> write(104) -> 104:
1708 i> write(104) -> 104:
1709 i> hello\n
1709 i> hello\n
1710 i> between\n
1710 i> between\n
1711 i> pairs 81\n
1711 i> pairs 81\n
1712 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1712 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1713 i> flush() -> None
1713 i> flush() -> None
1714 o> readline() -> 4:
1714 o> readline() -> 4:
1715 o> 413\n
1715 o> 413\n
1716 o> readline() -> 413:
1716 o> readline() -> 413:
1717 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1717 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1718 o> readline() -> 2:
1718 o> readline() -> 2:
1719 o> 1\n
1719 o> 1\n
1720 o> readline() -> 1:
1720 o> readline() -> 1:
1721 o> \n
1721 o> \n
1722 sending listkeys command
1722 sending listkeys command
1723 i> write(9) -> 9:
1723 i> write(9) -> 9:
1724 i> listkeys\n
1724 i> listkeys\n
1725 i> write(12) -> 12:
1725 i> write(12) -> 12:
1726 i> namespace 6\n
1726 i> namespace 6\n
1727 i> write(6) -> 6: phases
1727 i> write(6) -> 6: phases
1728 i> flush() -> None
1728 i> flush() -> None
1729 o> bufferedreadline() -> 3:
1729 o> bufferedreadline() -> 3:
1730 o> 15\n
1730 o> 15\n
1731 o> bufferedread(15) -> 15: publishing\tTrue
1731 o> bufferedread(15) -> 15: publishing\tTrue
1732 response: b'publishing\tTrue'
1732 response: {b'publishing': b'True'}
1733
1733
1734 testing ssh2
1734 testing ssh2
1735 creating ssh peer from handshake results
1735 creating ssh peer from handshake results
1736 i> write(171) -> 171:
1736 i> write(171) -> 171:
1737 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1737 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1738 i> hello\n
1738 i> hello\n
1739 i> between\n
1739 i> between\n
1740 i> pairs 81\n
1740 i> pairs 81\n
1741 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1741 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1742 i> flush() -> None
1742 i> flush() -> None
1743 o> readline() -> 62:
1743 o> readline() -> 62:
1744 o> upgraded * exp-ssh-v2-0001\n (glob)
1744 o> upgraded * exp-ssh-v2-0001\n (glob)
1745 o> readline() -> 4:
1745 o> readline() -> 4:
1746 o> 412\n
1746 o> 412\n
1747 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
1747 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
1748 o> read(1) -> 1:
1748 o> read(1) -> 1:
1749 o> \n
1749 o> \n
1750 sending listkeys command
1750 sending listkeys command
1751 i> write(9) -> 9:
1751 i> write(9) -> 9:
1752 i> listkeys\n
1752 i> listkeys\n
1753 i> write(12) -> 12:
1753 i> write(12) -> 12:
1754 i> namespace 6\n
1754 i> namespace 6\n
1755 i> write(6) -> 6: phases
1755 i> write(6) -> 6: phases
1756 i> flush() -> None
1756 i> flush() -> None
1757 o> bufferedreadline() -> 3:
1757 o> bufferedreadline() -> 3:
1758 o> 15\n
1758 o> 15\n
1759 o> bufferedread(15) -> 15: publishing\tTrue
1759 o> bufferedread(15) -> 15: publishing\tTrue
1760 response: b'publishing\tTrue'
1760 response: {b'publishing': b'True'}
1761
1761
1762 Create some commits
1762 Create some commits
1763
1763
1764 $ echo 0 > foo
1764 $ echo 0 > foo
1765 $ hg add foo
1765 $ hg add foo
1766 $ hg -q commit -m initial
1766 $ hg -q commit -m initial
1767 $ hg phase --public
1767 $ hg phase --public
1768 $ echo 1 > foo
1768 $ echo 1 > foo
1769 $ hg commit -m 'head 1 commit 1'
1769 $ hg commit -m 'head 1 commit 1'
1770 $ echo 2 > foo
1770 $ echo 2 > foo
1771 $ hg commit -m 'head 1 commit 2'
1771 $ hg commit -m 'head 1 commit 2'
1772 $ hg -q up 0
1772 $ hg -q up 0
1773 $ echo 1a > foo
1773 $ echo 1a > foo
1774 $ hg commit -m 'head 2 commit 1'
1774 $ hg commit -m 'head 2 commit 1'
1775 created new head
1775 created new head
1776 $ echo 2a > foo
1776 $ echo 2a > foo
1777 $ hg commit -m 'head 2 commit 2'
1777 $ hg commit -m 'head 2 commit 2'
1778
1778
1779 Two draft heads
1779 Two draft heads
1780
1780
1781 $ debugwireproto << EOF
1781 $ debugwireproto << EOF
1782 > command listkeys
1782 > command listkeys
1783 > namespace phases
1783 > namespace phases
1784 > EOF
1784 > EOF
1785 testing ssh1
1785 testing ssh1
1786 creating ssh peer from handshake results
1786 creating ssh peer from handshake results
1787 i> write(104) -> 104:
1787 i> write(104) -> 104:
1788 i> hello\n
1788 i> hello\n
1789 i> between\n
1789 i> between\n
1790 i> pairs 81\n
1790 i> pairs 81\n
1791 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1791 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1792 i> flush() -> None
1792 i> flush() -> None
1793 o> readline() -> 4:
1793 o> readline() -> 4:
1794 o> 413\n
1794 o> 413\n
1795 o> readline() -> 413:
1795 o> readline() -> 413:
1796 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1796 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1797 o> readline() -> 2:
1797 o> readline() -> 2:
1798 o> 1\n
1798 o> 1\n
1799 o> readline() -> 1:
1799 o> readline() -> 1:
1800 o> \n
1800 o> \n
1801 sending listkeys command
1801 sending listkeys command
1802 i> write(9) -> 9:
1802 i> write(9) -> 9:
1803 i> listkeys\n
1803 i> listkeys\n
1804 i> write(12) -> 12:
1804 i> write(12) -> 12:
1805 i> namespace 6\n
1805 i> namespace 6\n
1806 i> write(6) -> 6: phases
1806 i> write(6) -> 6: phases
1807 i> flush() -> None
1807 i> flush() -> None
1808 o> bufferedreadline() -> 4:
1808 o> bufferedreadline() -> 4:
1809 o> 101\n
1809 o> 101\n
1810 o> bufferedread(101) -> 101:
1810 o> bufferedread(101) -> 101:
1811 o> 20b8a89289d80036e6c4e87c2083e3bea1586637\t1\n
1811 o> 20b8a89289d80036e6c4e87c2083e3bea1586637\t1\n
1812 o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n
1812 o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n
1813 o> publishing\tTrue
1813 o> publishing\tTrue
1814 response: b'20b8a89289d80036e6c4e87c2083e3bea1586637\t1\nc4750011d906c18ea2f0527419cbc1a544435150\t1\npublishing\tTrue'
1814 response: {b'20b8a89289d80036e6c4e87c2083e3bea1586637': b'1', b'c4750011d906c18ea2f0527419cbc1a544435150': b'1', b'publishing': b'True'}
1815
1815
1816 testing ssh2
1816 testing ssh2
1817 creating ssh peer from handshake results
1817 creating ssh peer from handshake results
1818 i> write(171) -> 171:
1818 i> write(171) -> 171:
1819 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1819 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1820 i> hello\n
1820 i> hello\n
1821 i> between\n
1821 i> between\n
1822 i> pairs 81\n
1822 i> pairs 81\n
1823 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1823 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1824 i> flush() -> None
1824 i> flush() -> None
1825 o> readline() -> 62:
1825 o> readline() -> 62:
1826 o> upgraded * exp-ssh-v2-0001\n (glob)
1826 o> upgraded * exp-ssh-v2-0001\n (glob)
1827 o> readline() -> 4:
1827 o> readline() -> 4:
1828 o> 412\n
1828 o> 412\n
1829 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
1829 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
1830 o> read(1) -> 1:
1830 o> read(1) -> 1:
1831 o> \n
1831 o> \n
1832 sending listkeys command
1832 sending listkeys command
1833 i> write(9) -> 9:
1833 i> write(9) -> 9:
1834 i> listkeys\n
1834 i> listkeys\n
1835 i> write(12) -> 12:
1835 i> write(12) -> 12:
1836 i> namespace 6\n
1836 i> namespace 6\n
1837 i> write(6) -> 6: phases
1837 i> write(6) -> 6: phases
1838 i> flush() -> None
1838 i> flush() -> None
1839 o> bufferedreadline() -> 4:
1839 o> bufferedreadline() -> 4:
1840 o> 101\n
1840 o> 101\n
1841 o> bufferedread(101) -> 101:
1841 o> bufferedread(101) -> 101:
1842 o> 20b8a89289d80036e6c4e87c2083e3bea1586637\t1\n
1842 o> 20b8a89289d80036e6c4e87c2083e3bea1586637\t1\n
1843 o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n
1843 o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n
1844 o> publishing\tTrue
1844 o> publishing\tTrue
1845 response: b'20b8a89289d80036e6c4e87c2083e3bea1586637\t1\nc4750011d906c18ea2f0527419cbc1a544435150\t1\npublishing\tTrue'
1845 response: {b'20b8a89289d80036e6c4e87c2083e3bea1586637': b'1', b'c4750011d906c18ea2f0527419cbc1a544435150': b'1', b'publishing': b'True'}
1846
1846
1847 Single draft head
1847 Single draft head
1848
1848
1849 $ hg phase --public -r 2
1849 $ hg phase --public -r 2
1850 $ debugwireproto << EOF
1850 $ debugwireproto << EOF
1851 > command listkeys
1851 > command listkeys
1852 > namespace phases
1852 > namespace phases
1853 > EOF
1853 > EOF
1854 testing ssh1
1854 testing ssh1
1855 creating ssh peer from handshake results
1855 creating ssh peer from handshake results
1856 i> write(104) -> 104:
1856 i> write(104) -> 104:
1857 i> hello\n
1857 i> hello\n
1858 i> between\n
1858 i> between\n
1859 i> pairs 81\n
1859 i> pairs 81\n
1860 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1860 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1861 i> flush() -> None
1861 i> flush() -> None
1862 o> readline() -> 4:
1862 o> readline() -> 4:
1863 o> 413\n
1863 o> 413\n
1864 o> readline() -> 413:
1864 o> readline() -> 413:
1865 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1865 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1866 o> readline() -> 2:
1866 o> readline() -> 2:
1867 o> 1\n
1867 o> 1\n
1868 o> readline() -> 1:
1868 o> readline() -> 1:
1869 o> \n
1869 o> \n
1870 sending listkeys command
1870 sending listkeys command
1871 i> write(9) -> 9:
1871 i> write(9) -> 9:
1872 i> listkeys\n
1872 i> listkeys\n
1873 i> write(12) -> 12:
1873 i> write(12) -> 12:
1874 i> namespace 6\n
1874 i> namespace 6\n
1875 i> write(6) -> 6: phases
1875 i> write(6) -> 6: phases
1876 i> flush() -> None
1876 i> flush() -> None
1877 o> bufferedreadline() -> 3:
1877 o> bufferedreadline() -> 3:
1878 o> 58\n
1878 o> 58\n
1879 o> bufferedread(58) -> 58:
1879 o> bufferedread(58) -> 58:
1880 o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n
1880 o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n
1881 o> publishing\tTrue
1881 o> publishing\tTrue
1882 response: b'c4750011d906c18ea2f0527419cbc1a544435150\t1\npublishing\tTrue'
1882 response: {b'c4750011d906c18ea2f0527419cbc1a544435150': b'1', b'publishing': b'True'}
1883
1883
1884 testing ssh2
1884 testing ssh2
1885 creating ssh peer from handshake results
1885 creating ssh peer from handshake results
1886 i> write(171) -> 171:
1886 i> write(171) -> 171:
1887 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1887 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1888 i> hello\n
1888 i> hello\n
1889 i> between\n
1889 i> between\n
1890 i> pairs 81\n
1890 i> pairs 81\n
1891 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1891 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1892 i> flush() -> None
1892 i> flush() -> None
1893 o> readline() -> 62:
1893 o> readline() -> 62:
1894 o> upgraded * exp-ssh-v2-0001\n (glob)
1894 o> upgraded * exp-ssh-v2-0001\n (glob)
1895 o> readline() -> 4:
1895 o> readline() -> 4:
1896 o> 412\n
1896 o> 412\n
1897 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
1897 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
1898 o> read(1) -> 1:
1898 o> read(1) -> 1:
1899 o> \n
1899 o> \n
1900 sending listkeys command
1900 sending listkeys command
1901 i> write(9) -> 9:
1901 i> write(9) -> 9:
1902 i> listkeys\n
1902 i> listkeys\n
1903 i> write(12) -> 12:
1903 i> write(12) -> 12:
1904 i> namespace 6\n
1904 i> namespace 6\n
1905 i> write(6) -> 6: phases
1905 i> write(6) -> 6: phases
1906 i> flush() -> None
1906 i> flush() -> None
1907 o> bufferedreadline() -> 3:
1907 o> bufferedreadline() -> 3:
1908 o> 58\n
1908 o> 58\n
1909 o> bufferedread(58) -> 58:
1909 o> bufferedread(58) -> 58:
1910 o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n
1910 o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n
1911 o> publishing\tTrue
1911 o> publishing\tTrue
1912 response: b'c4750011d906c18ea2f0527419cbc1a544435150\t1\npublishing\tTrue'
1912 response: {b'c4750011d906c18ea2f0527419cbc1a544435150': b'1', b'publishing': b'True'}
1913
1913
1914 All public heads
1914 All public heads
1915
1915
1916 $ hg phase --public -r 4
1916 $ hg phase --public -r 4
1917 $ debugwireproto << EOF
1917 $ debugwireproto << EOF
1918 > command listkeys
1918 > command listkeys
1919 > namespace phases
1919 > namespace phases
1920 > EOF
1920 > EOF
1921 testing ssh1
1921 testing ssh1
1922 creating ssh peer from handshake results
1922 creating ssh peer from handshake results
1923 i> write(104) -> 104:
1923 i> write(104) -> 104:
1924 i> hello\n
1924 i> hello\n
1925 i> between\n
1925 i> between\n
1926 i> pairs 81\n
1926 i> pairs 81\n
1927 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1927 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1928 i> flush() -> None
1928 i> flush() -> None
1929 o> readline() -> 4:
1929 o> readline() -> 4:
1930 o> 413\n
1930 o> 413\n
1931 o> readline() -> 413:
1931 o> readline() -> 413:
1932 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1932 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1933 o> readline() -> 2:
1933 o> readline() -> 2:
1934 o> 1\n
1934 o> 1\n
1935 o> readline() -> 1:
1935 o> readline() -> 1:
1936 o> \n
1936 o> \n
1937 sending listkeys command
1937 sending listkeys command
1938 i> write(9) -> 9:
1938 i> write(9) -> 9:
1939 i> listkeys\n
1939 i> listkeys\n
1940 i> write(12) -> 12:
1940 i> write(12) -> 12:
1941 i> namespace 6\n
1941 i> namespace 6\n
1942 i> write(6) -> 6: phases
1942 i> write(6) -> 6: phases
1943 i> flush() -> None
1943 i> flush() -> None
1944 o> bufferedreadline() -> 3:
1944 o> bufferedreadline() -> 3:
1945 o> 15\n
1945 o> 15\n
1946 o> bufferedread(15) -> 15: publishing\tTrue
1946 o> bufferedread(15) -> 15: publishing\tTrue
1947 response: b'publishing\tTrue'
1947 response: {b'publishing': b'True'}
1948
1948
1949 testing ssh2
1949 testing ssh2
1950 creating ssh peer from handshake results
1950 creating ssh peer from handshake results
1951 i> write(171) -> 171:
1951 i> write(171) -> 171:
1952 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1952 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1953 i> hello\n
1953 i> hello\n
1954 i> between\n
1954 i> between\n
1955 i> pairs 81\n
1955 i> pairs 81\n
1956 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1956 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1957 i> flush() -> None
1957 i> flush() -> None
1958 o> readline() -> 62:
1958 o> readline() -> 62:
1959 o> upgraded * exp-ssh-v2-0001\n (glob)
1959 o> upgraded * exp-ssh-v2-0001\n (glob)
1960 o> readline() -> 4:
1960 o> readline() -> 4:
1961 o> 412\n
1961 o> 412\n
1962 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
1962 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
1963 o> read(1) -> 1:
1963 o> read(1) -> 1:
1964 o> \n
1964 o> \n
1965 sending listkeys command
1965 sending listkeys command
1966 i> write(9) -> 9:
1966 i> write(9) -> 9:
1967 i> listkeys\n
1967 i> listkeys\n
1968 i> write(12) -> 12:
1968 i> write(12) -> 12:
1969 i> namespace 6\n
1969 i> namespace 6\n
1970 i> write(6) -> 6: phases
1970 i> write(6) -> 6: phases
1971 i> flush() -> None
1971 i> flush() -> None
1972 o> bufferedreadline() -> 3:
1972 o> bufferedreadline() -> 3:
1973 o> 15\n
1973 o> 15\n
1974 o> bufferedread(15) -> 15: publishing\tTrue
1974 o> bufferedread(15) -> 15: publishing\tTrue
1975 response: b'publishing\tTrue'
1975 response: {b'publishing': b'True'}
1976
1976
1977 Setting public phase via pushkey
1977 Setting public phase via pushkey
1978
1978
1979 $ hg phase --draft --force -r .
1979 $ hg phase --draft --force -r .
1980
1980
1981 $ debugwireproto << EOF
1981 $ debugwireproto << EOF
1982 > command pushkey
1982 > command pushkey
1983 > namespace phases
1983 > namespace phases
1984 > key 7127240a084fd9dc86fe8d1f98e26229161ec82b
1984 > key 7127240a084fd9dc86fe8d1f98e26229161ec82b
1985 > old 1
1985 > old 1
1986 > new 0
1986 > new 0
1987 > EOF
1987 > EOF
1988 testing ssh1
1988 testing ssh1
1989 creating ssh peer from handshake results
1989 creating ssh peer from handshake results
1990 i> write(104) -> 104:
1990 i> write(104) -> 104:
1991 i> hello\n
1991 i> hello\n
1992 i> between\n
1992 i> between\n
1993 i> pairs 81\n
1993 i> pairs 81\n
1994 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1994 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1995 i> flush() -> None
1995 i> flush() -> None
1996 o> readline() -> 4:
1996 o> readline() -> 4:
1997 o> 413\n
1997 o> 413\n
1998 o> readline() -> 413:
1998 o> readline() -> 413:
1999 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1999 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
2000 o> readline() -> 2:
2000 o> readline() -> 2:
2001 o> 1\n
2001 o> 1\n
2002 o> readline() -> 1:
2002 o> readline() -> 1:
2003 o> \n
2003 o> \n
2004 sending pushkey command
2004 sending pushkey command
2005 i> write(8) -> 8:
2005 i> write(8) -> 8:
2006 i> pushkey\n
2006 i> pushkey\n
2007 i> write(7) -> 7:
2007 i> write(7) -> 7:
2008 i> key 40\n
2008 i> key 40\n
2009 i> write(40) -> 40: 7127240a084fd9dc86fe8d1f98e26229161ec82b
2009 i> write(40) -> 40: 7127240a084fd9dc86fe8d1f98e26229161ec82b
2010 i> write(12) -> 12:
2010 i> write(12) -> 12:
2011 i> namespace 6\n
2011 i> namespace 6\n
2012 i> write(6) -> 6: phases
2012 i> write(6) -> 6: phases
2013 i> write(6) -> 6:
2013 i> write(6) -> 6:
2014 i> new 1\n
2014 i> new 1\n
2015 i> write(1) -> 1: 0
2015 i> write(1) -> 1: 0
2016 i> write(6) -> 6:
2016 i> write(6) -> 6:
2017 i> old 1\n
2017 i> old 1\n
2018 i> write(1) -> 1: 1
2018 i> write(1) -> 1: 1
2019 i> flush() -> None
2019 i> flush() -> None
2020 o> bufferedreadline() -> 2:
2020 o> bufferedreadline() -> 2:
2021 o> 2\n
2021 o> 2\n
2022 o> bufferedread(2) -> 2:
2022 o> bufferedread(2) -> 2:
2023 o> 1\n
2023 o> 1\n
2024 response: b'1\n'
2024 response: True
2025
2025
2026 testing ssh2
2026 testing ssh2
2027 creating ssh peer from handshake results
2027 creating ssh peer from handshake results
2028 i> write(171) -> 171:
2028 i> write(171) -> 171:
2029 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
2029 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
2030 i> hello\n
2030 i> hello\n
2031 i> between\n
2031 i> between\n
2032 i> pairs 81\n
2032 i> pairs 81\n
2033 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
2033 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
2034 i> flush() -> None
2034 i> flush() -> None
2035 o> readline() -> 62:
2035 o> readline() -> 62:
2036 o> upgraded * exp-ssh-v2-0001\n (glob)
2036 o> upgraded * exp-ssh-v2-0001\n (glob)
2037 o> readline() -> 4:
2037 o> readline() -> 4:
2038 o> 412\n
2038 o> 412\n
2039 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
2039 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
2040 o> read(1) -> 1:
2040 o> read(1) -> 1:
2041 o> \n
2041 o> \n
2042 sending pushkey command
2042 sending pushkey command
2043 i> write(8) -> 8:
2043 i> write(8) -> 8:
2044 i> pushkey\n
2044 i> pushkey\n
2045 i> write(7) -> 7:
2045 i> write(7) -> 7:
2046 i> key 40\n
2046 i> key 40\n
2047 i> write(40) -> 40: 7127240a084fd9dc86fe8d1f98e26229161ec82b
2047 i> write(40) -> 40: 7127240a084fd9dc86fe8d1f98e26229161ec82b
2048 i> write(12) -> 12:
2048 i> write(12) -> 12:
2049 i> namespace 6\n
2049 i> namespace 6\n
2050 i> write(6) -> 6: phases
2050 i> write(6) -> 6: phases
2051 i> write(6) -> 6:
2051 i> write(6) -> 6:
2052 i> new 1\n
2052 i> new 1\n
2053 i> write(1) -> 1: 0
2053 i> write(1) -> 1: 0
2054 i> write(6) -> 6:
2054 i> write(6) -> 6:
2055 i> old 1\n
2055 i> old 1\n
2056 i> write(1) -> 1: 1
2056 i> write(1) -> 1: 1
2057 i> flush() -> None
2057 i> flush() -> None
2058 o> bufferedreadline() -> 2:
2058 o> bufferedreadline() -> 2:
2059 o> 2\n
2059 o> 2\n
2060 o> bufferedread(2) -> 2:
2060 o> bufferedread(2) -> 2:
2061 o> 1\n
2061 o> 1\n
2062 response: b'1\n'
2062 response: True
2063
2063
2064 $ hg phase .
2064 $ hg phase .
2065 4: public
2065 4: public
2066
2066
2067 $ cd ..
2067 $ cd ..
2068
2068
2069 Test batching of requests
2069 Test batching of requests
2070
2070
2071 $ hg init batching
2071 $ hg init batching
2072 $ cd batching
2072 $ cd batching
2073 $ echo 0 > foo
2073 $ echo 0 > foo
2074 $ hg add foo
2074 $ hg add foo
2075 $ hg -q commit -m initial
2075 $ hg -q commit -m initial
2076 $ hg phase --public
2076 $ hg phase --public
2077 $ echo 1 > foo
2077 $ echo 1 > foo
2078 $ hg commit -m 'commit 1'
2078 $ hg commit -m 'commit 1'
2079 $ hg -q up 0
2079 $ hg -q up 0
2080 $ echo 2 > foo
2080 $ echo 2 > foo
2081 $ hg commit -m 'commit 2'
2081 $ hg commit -m 'commit 2'
2082 created new head
2082 created new head
2083 $ hg book -r 1 bookA
2083 $ hg book -r 1 bookA
2084 $ hg book -r 2 bookB
2084 $ hg book -r 2 bookB
2085
2085
2086 $ debugwireproto << EOF
2086 $ debugwireproto << EOF
2087 > batchbegin
2087 > batchbegin
2088 > command heads
2088 > command heads
2089 > command listkeys
2089 > command listkeys
2090 > namespace bookmarks
2090 > namespace bookmarks
2091 > command listkeys
2091 > command listkeys
2092 > namespace phases
2092 > namespace phases
2093 > batchsubmit
2093 > batchsubmit
2094 > EOF
2094 > EOF
2095 testing ssh1
2095 testing ssh1
2096 creating ssh peer from handshake results
2096 creating ssh peer from handshake results
2097 i> write(104) -> 104:
2097 i> write(104) -> 104:
2098 i> hello\n
2098 i> hello\n
2099 i> between\n
2099 i> between\n
2100 i> pairs 81\n
2100 i> pairs 81\n
2101 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
2101 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
2102 i> flush() -> None
2102 i> flush() -> None
2103 o> readline() -> 4:
2103 o> readline() -> 4:
2104 o> 413\n
2104 o> 413\n
2105 o> readline() -> 413:
2105 o> readline() -> 413:
2106 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
2106 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
2107 o> readline() -> 2:
2107 o> readline() -> 2:
2108 o> 1\n
2108 o> 1\n
2109 o> readline() -> 1:
2109 o> readline() -> 1:
2110 o> \n
2110 o> \n
2111 sending batch with 3 sub-commands
2111 sending batch with 3 sub-commands
2112 i> write(6) -> 6:
2112 i> write(6) -> 6:
2113 i> batch\n
2113 i> batch\n
2114 i> write(4) -> 4:
2114 i> write(4) -> 4:
2115 i> * 0\n
2115 i> * 0\n
2116 i> write(8) -> 8:
2116 i> write(8) -> 8:
2117 i> cmds 61\n
2117 i> cmds 61\n
2118 i> write(61) -> 61: heads ;listkeys namespace=bookmarks;listkeys namespace=phases
2118 i> write(61) -> 61: heads ;listkeys namespace=bookmarks;listkeys namespace=phases
2119 i> flush() -> None
2119 i> flush() -> None
2120 o> bufferedreadline() -> 4:
2120 o> bufferedreadline() -> 4:
2121 o> 278\n
2121 o> 278\n
2122 o> bufferedread(278) -> 278:
2122 o> bufferedread(278) -> 278:
2123 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2123 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2124 o> ;bookA\t4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2124 o> ;bookA\t4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2125 o> bookB\tbfebe6bd38eebc6f8202e419c1171268987ea6a6;4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\t1\n
2125 o> bookB\tbfebe6bd38eebc6f8202e419c1171268987ea6a6;4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\t1\n
2126 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6\t1\n
2126 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6\t1\n
2127 o> publishing\tTrue
2127 o> publishing\tTrue
2128 response #0: bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2128 response #0: bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2129 response #1: bookA\t4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\nbookB\tbfebe6bd38eebc6f8202e419c1171268987ea6a6
2129 response #1: bookA\t4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\nbookB\tbfebe6bd38eebc6f8202e419c1171268987ea6a6
2130 response #2: 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\t1\nbfebe6bd38eebc6f8202e419c1171268987ea6a6\t1\npublishing\tTrue
2130 response #2: 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\t1\nbfebe6bd38eebc6f8202e419c1171268987ea6a6\t1\npublishing\tTrue
2131
2131
2132 testing ssh2
2132 testing ssh2
2133 creating ssh peer from handshake results
2133 creating ssh peer from handshake results
2134 i> write(171) -> 171:
2134 i> write(171) -> 171:
2135 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
2135 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
2136 i> hello\n
2136 i> hello\n
2137 i> between\n
2137 i> between\n
2138 i> pairs 81\n
2138 i> pairs 81\n
2139 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
2139 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
2140 i> flush() -> None
2140 i> flush() -> None
2141 o> readline() -> 62:
2141 o> readline() -> 62:
2142 o> upgraded * exp-ssh-v2-0001\n (glob)
2142 o> upgraded * exp-ssh-v2-0001\n (glob)
2143 o> readline() -> 4:
2143 o> readline() -> 4:
2144 o> 412\n
2144 o> 412\n
2145 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
2145 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
2146 o> read(1) -> 1:
2146 o> read(1) -> 1:
2147 o> \n
2147 o> \n
2148 sending batch with 3 sub-commands
2148 sending batch with 3 sub-commands
2149 i> write(6) -> 6:
2149 i> write(6) -> 6:
2150 i> batch\n
2150 i> batch\n
2151 i> write(4) -> 4:
2151 i> write(4) -> 4:
2152 i> * 0\n
2152 i> * 0\n
2153 i> write(8) -> 8:
2153 i> write(8) -> 8:
2154 i> cmds 61\n
2154 i> cmds 61\n
2155 i> write(61) -> 61: heads ;listkeys namespace=bookmarks;listkeys namespace=phases
2155 i> write(61) -> 61: heads ;listkeys namespace=bookmarks;listkeys namespace=phases
2156 i> flush() -> None
2156 i> flush() -> None
2157 o> bufferedreadline() -> 4:
2157 o> bufferedreadline() -> 4:
2158 o> 278\n
2158 o> 278\n
2159 o> bufferedread(278) -> 278:
2159 o> bufferedread(278) -> 278:
2160 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2160 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2161 o> ;bookA\t4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2161 o> ;bookA\t4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2162 o> bookB\tbfebe6bd38eebc6f8202e419c1171268987ea6a6;4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\t1\n
2162 o> bookB\tbfebe6bd38eebc6f8202e419c1171268987ea6a6;4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\t1\n
2163 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6\t1\n
2163 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6\t1\n
2164 o> publishing\tTrue
2164 o> publishing\tTrue
2165 response #0: bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2165 response #0: bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2166 response #1: bookA\t4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\nbookB\tbfebe6bd38eebc6f8202e419c1171268987ea6a6
2166 response #1: bookA\t4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\nbookB\tbfebe6bd38eebc6f8202e419c1171268987ea6a6
2167 response #2: 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\t1\nbfebe6bd38eebc6f8202e419c1171268987ea6a6\t1\npublishing\tTrue
2167 response #2: 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\t1\nbfebe6bd38eebc6f8202e419c1171268987ea6a6\t1\npublishing\tTrue
General Comments 0
You need to be logged in to leave comments. Login now