##// END OF EJS Templates
clone: warn when streaming was requested but couldn't be performed...
Siddharth Agarwal -
r32259:076f1ff4 default
parent child Browse files
Show More
@@ -1,397 +1,407
1 # streamclone.py - producing and consuming streaming repository data
1 # streamclone.py - producing and consuming streaming repository data
2 #
2 #
3 # Copyright 2015 Gregory Szorc <gregory.szorc@gmail.com>
3 # Copyright 2015 Gregory Szorc <gregory.szorc@gmail.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 struct
10 import struct
11
11
12 from .i18n import _
12 from .i18n import _
13 from . import (
13 from . import (
14 branchmap,
14 branchmap,
15 error,
15 error,
16 store,
16 store,
17 util,
17 util,
18 )
18 )
19
19
20 def canperformstreamclone(pullop, bailifbundle2supported=False):
20 def canperformstreamclone(pullop, bailifbundle2supported=False):
21 """Whether it is possible to perform a streaming clone as part of pull.
21 """Whether it is possible to perform a streaming clone as part of pull.
22
22
23 ``bailifbundle2supported`` will cause the function to return False if
23 ``bailifbundle2supported`` will cause the function to return False if
24 bundle2 stream clones are supported. It should only be called by the
24 bundle2 stream clones are supported. It should only be called by the
25 legacy stream clone code path.
25 legacy stream clone code path.
26
26
27 Returns a tuple of (supported, requirements). ``supported`` is True if
27 Returns a tuple of (supported, requirements). ``supported`` is True if
28 streaming clone is supported and False otherwise. ``requirements`` is
28 streaming clone is supported and False otherwise. ``requirements`` is
29 a set of repo requirements from the remote, or ``None`` if stream clone
29 a set of repo requirements from the remote, or ``None`` if stream clone
30 isn't supported.
30 isn't supported.
31 """
31 """
32 repo = pullop.repo
32 repo = pullop.repo
33 remote = pullop.remote
33 remote = pullop.remote
34
34
35 bundle2supported = False
35 bundle2supported = False
36 if pullop.canusebundle2:
36 if pullop.canusebundle2:
37 if 'v1' in pullop.remotebundle2caps.get('stream', []):
37 if 'v1' in pullop.remotebundle2caps.get('stream', []):
38 bundle2supported = True
38 bundle2supported = True
39 # else
39 # else
40 # Server doesn't support bundle2 stream clone or doesn't support
40 # Server doesn't support bundle2 stream clone or doesn't support
41 # the versions we support. Fall back and possibly allow legacy.
41 # the versions we support. Fall back and possibly allow legacy.
42
42
43 # Ensures legacy code path uses available bundle2.
43 # Ensures legacy code path uses available bundle2.
44 if bailifbundle2supported and bundle2supported:
44 if bailifbundle2supported and bundle2supported:
45 return False, None
45 return False, None
46 # Ensures bundle2 doesn't try to do a stream clone if it isn't supported.
46 # Ensures bundle2 doesn't try to do a stream clone if it isn't supported.
47 #elif not bailifbundle2supported and not bundle2supported:
47 #elif not bailifbundle2supported and not bundle2supported:
48 # return False, None
48 # return False, None
49
49
50 # Streaming clone only works on empty repositories.
50 # Streaming clone only works on empty repositories.
51 if len(repo):
51 if len(repo):
52 return False, None
52 return False, None
53
53
54 # Streaming clone only works if all data is being requested.
54 # Streaming clone only works if all data is being requested.
55 if pullop.heads:
55 if pullop.heads:
56 return False, None
56 return False, None
57
57
58 streamrequested = pullop.streamclonerequested
58 streamrequested = pullop.streamclonerequested
59
59
60 # If we don't have a preference, let the server decide for us. This
60 # If we don't have a preference, let the server decide for us. This
61 # likely only comes into play in LANs.
61 # likely only comes into play in LANs.
62 if streamrequested is None:
62 if streamrequested is None:
63 # The server can advertise whether to prefer streaming clone.
63 # The server can advertise whether to prefer streaming clone.
64 streamrequested = remote.capable('stream-preferred')
64 streamrequested = remote.capable('stream-preferred')
65
65
66 if not streamrequested:
66 if not streamrequested:
67 return False, None
67 return False, None
68
68
69 # In order for stream clone to work, the client has to support all the
69 # In order for stream clone to work, the client has to support all the
70 # requirements advertised by the server.
70 # requirements advertised by the server.
71 #
71 #
72 # The server advertises its requirements via the "stream" and "streamreqs"
72 # The server advertises its requirements via the "stream" and "streamreqs"
73 # capability. "stream" (a value-less capability) is advertised if and only
73 # capability. "stream" (a value-less capability) is advertised if and only
74 # if the only requirement is "revlogv1." Else, the "streamreqs" capability
74 # if the only requirement is "revlogv1." Else, the "streamreqs" capability
75 # is advertised and contains a comma-delimited list of requirements.
75 # is advertised and contains a comma-delimited list of requirements.
76 requirements = set()
76 requirements = set()
77 if remote.capable('stream'):
77 if remote.capable('stream'):
78 requirements.add('revlogv1')
78 requirements.add('revlogv1')
79 else:
79 else:
80 streamreqs = remote.capable('streamreqs')
80 streamreqs = remote.capable('streamreqs')
81 # This is weird and shouldn't happen with modern servers.
81 # This is weird and shouldn't happen with modern servers.
82 if not streamreqs:
82 if not streamreqs:
83 pullop.repo.ui.warn(_(
84 'warning: stream clone requested but server has them '
85 'disabled\n'))
83 return False, None
86 return False, None
84
87
85 streamreqs = set(streamreqs.split(','))
88 streamreqs = set(streamreqs.split(','))
86 # Server requires something we don't support. Bail.
89 # Server requires something we don't support. Bail.
87 if streamreqs - repo.supportedformats:
90 missingreqs = streamreqs - repo.supportedformats
91 if missingreqs:
92 pullop.repo.ui.warn(_(
93 'warning: stream clone requested but client is missing '
94 'requirements: %s\n') % ', '.join(sorted(missingreqs)))
95 pullop.repo.ui.warn(
96 _('(see https://www.mercurial-scm.org/wiki/MissingRequirement '
97 'for more information)\n'))
88 return False, None
98 return False, None
89 requirements = streamreqs
99 requirements = streamreqs
90
100
91 return True, requirements
101 return True, requirements
92
102
93 def maybeperformlegacystreamclone(pullop):
103 def maybeperformlegacystreamclone(pullop):
94 """Possibly perform a legacy stream clone operation.
104 """Possibly perform a legacy stream clone operation.
95
105
96 Legacy stream clones are performed as part of pull but before all other
106 Legacy stream clones are performed as part of pull but before all other
97 operations.
107 operations.
98
108
99 A legacy stream clone will not be performed if a bundle2 stream clone is
109 A legacy stream clone will not be performed if a bundle2 stream clone is
100 supported.
110 supported.
101 """
111 """
102 supported, requirements = canperformstreamclone(pullop)
112 supported, requirements = canperformstreamclone(pullop)
103
113
104 if not supported:
114 if not supported:
105 return
115 return
106
116
107 repo = pullop.repo
117 repo = pullop.repo
108 remote = pullop.remote
118 remote = pullop.remote
109
119
110 # Save remote branchmap. We will use it later to speed up branchcache
120 # Save remote branchmap. We will use it later to speed up branchcache
111 # creation.
121 # creation.
112 rbranchmap = None
122 rbranchmap = None
113 if remote.capable('branchmap'):
123 if remote.capable('branchmap'):
114 rbranchmap = remote.branchmap()
124 rbranchmap = remote.branchmap()
115
125
116 repo.ui.status(_('streaming all changes\n'))
126 repo.ui.status(_('streaming all changes\n'))
117
127
118 fp = remote.stream_out()
128 fp = remote.stream_out()
119 l = fp.readline()
129 l = fp.readline()
120 try:
130 try:
121 resp = int(l)
131 resp = int(l)
122 except ValueError:
132 except ValueError:
123 raise error.ResponseError(
133 raise error.ResponseError(
124 _('unexpected response from remote server:'), l)
134 _('unexpected response from remote server:'), l)
125 if resp == 1:
135 if resp == 1:
126 raise error.Abort(_('operation forbidden by server'))
136 raise error.Abort(_('operation forbidden by server'))
127 elif resp == 2:
137 elif resp == 2:
128 raise error.Abort(_('locking the remote repository failed'))
138 raise error.Abort(_('locking the remote repository failed'))
129 elif resp != 0:
139 elif resp != 0:
130 raise error.Abort(_('the server sent an unknown error code'))
140 raise error.Abort(_('the server sent an unknown error code'))
131
141
132 l = fp.readline()
142 l = fp.readline()
133 try:
143 try:
134 filecount, bytecount = map(int, l.split(' ', 1))
144 filecount, bytecount = map(int, l.split(' ', 1))
135 except (ValueError, TypeError):
145 except (ValueError, TypeError):
136 raise error.ResponseError(
146 raise error.ResponseError(
137 _('unexpected response from remote server:'), l)
147 _('unexpected response from remote server:'), l)
138
148
139 with repo.lock():
149 with repo.lock():
140 consumev1(repo, fp, filecount, bytecount)
150 consumev1(repo, fp, filecount, bytecount)
141
151
142 # new requirements = old non-format requirements +
152 # new requirements = old non-format requirements +
143 # new format-related remote requirements
153 # new format-related remote requirements
144 # requirements from the streamed-in repository
154 # requirements from the streamed-in repository
145 repo.requirements = requirements | (
155 repo.requirements = requirements | (
146 repo.requirements - repo.supportedformats)
156 repo.requirements - repo.supportedformats)
147 repo._applyopenerreqs()
157 repo._applyopenerreqs()
148 repo._writerequirements()
158 repo._writerequirements()
149
159
150 if rbranchmap:
160 if rbranchmap:
151 branchmap.replacecache(repo, rbranchmap)
161 branchmap.replacecache(repo, rbranchmap)
152
162
153 repo.invalidate()
163 repo.invalidate()
154
164
155 def allowservergeneration(ui):
165 def allowservergeneration(ui):
156 """Whether streaming clones are allowed from the server."""
166 """Whether streaming clones are allowed from the server."""
157 return ui.configbool('server', 'uncompressed', True, untrusted=True)
167 return ui.configbool('server', 'uncompressed', True, untrusted=True)
158
168
159 # This is it's own function so extensions can override it.
169 # This is it's own function so extensions can override it.
160 def _walkstreamfiles(repo):
170 def _walkstreamfiles(repo):
161 return repo.store.walk()
171 return repo.store.walk()
162
172
163 def generatev1(repo):
173 def generatev1(repo):
164 """Emit content for version 1 of a streaming clone.
174 """Emit content for version 1 of a streaming clone.
165
175
166 This returns a 3-tuple of (file count, byte size, data iterator).
176 This returns a 3-tuple of (file count, byte size, data iterator).
167
177
168 The data iterator consists of N entries for each file being transferred.
178 The data iterator consists of N entries for each file being transferred.
169 Each file entry starts as a line with the file name and integer size
179 Each file entry starts as a line with the file name and integer size
170 delimited by a null byte.
180 delimited by a null byte.
171
181
172 The raw file data follows. Following the raw file data is the next file
182 The raw file data follows. Following the raw file data is the next file
173 entry, or EOF.
183 entry, or EOF.
174
184
175 When used on the wire protocol, an additional line indicating protocol
185 When used on the wire protocol, an additional line indicating protocol
176 success will be prepended to the stream. This function is not responsible
186 success will be prepended to the stream. This function is not responsible
177 for adding it.
187 for adding it.
178
188
179 This function will obtain a repository lock to ensure a consistent view of
189 This function will obtain a repository lock to ensure a consistent view of
180 the store is captured. It therefore may raise LockError.
190 the store is captured. It therefore may raise LockError.
181 """
191 """
182 entries = []
192 entries = []
183 total_bytes = 0
193 total_bytes = 0
184 # Get consistent snapshot of repo, lock during scan.
194 # Get consistent snapshot of repo, lock during scan.
185 with repo.lock():
195 with repo.lock():
186 repo.ui.debug('scanning\n')
196 repo.ui.debug('scanning\n')
187 for name, ename, size in _walkstreamfiles(repo):
197 for name, ename, size in _walkstreamfiles(repo):
188 if size:
198 if size:
189 entries.append((name, size))
199 entries.append((name, size))
190 total_bytes += size
200 total_bytes += size
191
201
192 repo.ui.debug('%d files, %d bytes to transfer\n' %
202 repo.ui.debug('%d files, %d bytes to transfer\n' %
193 (len(entries), total_bytes))
203 (len(entries), total_bytes))
194
204
195 svfs = repo.svfs
205 svfs = repo.svfs
196 oldaudit = svfs.mustaudit
206 oldaudit = svfs.mustaudit
197 debugflag = repo.ui.debugflag
207 debugflag = repo.ui.debugflag
198 svfs.mustaudit = False
208 svfs.mustaudit = False
199
209
200 def emitrevlogdata():
210 def emitrevlogdata():
201 try:
211 try:
202 for name, size in entries:
212 for name, size in entries:
203 if debugflag:
213 if debugflag:
204 repo.ui.debug('sending %s (%d bytes)\n' % (name, size))
214 repo.ui.debug('sending %s (%d bytes)\n' % (name, size))
205 # partially encode name over the wire for backwards compat
215 # partially encode name over the wire for backwards compat
206 yield '%s\0%d\n' % (store.encodedir(name), size)
216 yield '%s\0%d\n' % (store.encodedir(name), size)
207 if size <= 65536:
217 if size <= 65536:
208 with svfs(name, 'rb') as fp:
218 with svfs(name, 'rb') as fp:
209 yield fp.read(size)
219 yield fp.read(size)
210 else:
220 else:
211 for chunk in util.filechunkiter(svfs(name), limit=size):
221 for chunk in util.filechunkiter(svfs(name), limit=size):
212 yield chunk
222 yield chunk
213 finally:
223 finally:
214 svfs.mustaudit = oldaudit
224 svfs.mustaudit = oldaudit
215
225
216 return len(entries), total_bytes, emitrevlogdata()
226 return len(entries), total_bytes, emitrevlogdata()
217
227
218 def generatev1wireproto(repo):
228 def generatev1wireproto(repo):
219 """Emit content for version 1 of streaming clone suitable for the wire.
229 """Emit content for version 1 of streaming clone suitable for the wire.
220
230
221 This is the data output from ``generatev1()`` with a header line
231 This is the data output from ``generatev1()`` with a header line
222 indicating file count and byte size.
232 indicating file count and byte size.
223 """
233 """
224 filecount, bytecount, it = generatev1(repo)
234 filecount, bytecount, it = generatev1(repo)
225 yield '%d %d\n' % (filecount, bytecount)
235 yield '%d %d\n' % (filecount, bytecount)
226 for chunk in it:
236 for chunk in it:
227 yield chunk
237 yield chunk
228
238
229 def generatebundlev1(repo, compression='UN'):
239 def generatebundlev1(repo, compression='UN'):
230 """Emit content for version 1 of a stream clone bundle.
240 """Emit content for version 1 of a stream clone bundle.
231
241
232 The first 4 bytes of the output ("HGS1") denote this as stream clone
242 The first 4 bytes of the output ("HGS1") denote this as stream clone
233 bundle version 1.
243 bundle version 1.
234
244
235 The next 2 bytes indicate the compression type. Only "UN" is currently
245 The next 2 bytes indicate the compression type. Only "UN" is currently
236 supported.
246 supported.
237
247
238 The next 16 bytes are two 64-bit big endian unsigned integers indicating
248 The next 16 bytes are two 64-bit big endian unsigned integers indicating
239 file count and byte count, respectively.
249 file count and byte count, respectively.
240
250
241 The next 2 bytes is a 16-bit big endian unsigned short declaring the length
251 The next 2 bytes is a 16-bit big endian unsigned short declaring the length
242 of the requirements string, including a trailing \0. The following N bytes
252 of the requirements string, including a trailing \0. The following N bytes
243 are the requirements string, which is ASCII containing a comma-delimited
253 are the requirements string, which is ASCII containing a comma-delimited
244 list of repo requirements that are needed to support the data.
254 list of repo requirements that are needed to support the data.
245
255
246 The remaining content is the output of ``generatev1()`` (which may be
256 The remaining content is the output of ``generatev1()`` (which may be
247 compressed in the future).
257 compressed in the future).
248
258
249 Returns a tuple of (requirements, data generator).
259 Returns a tuple of (requirements, data generator).
250 """
260 """
251 if compression != 'UN':
261 if compression != 'UN':
252 raise ValueError('we do not support the compression argument yet')
262 raise ValueError('we do not support the compression argument yet')
253
263
254 requirements = repo.requirements & repo.supportedformats
264 requirements = repo.requirements & repo.supportedformats
255 requires = ','.join(sorted(requirements))
265 requires = ','.join(sorted(requirements))
256
266
257 def gen():
267 def gen():
258 yield 'HGS1'
268 yield 'HGS1'
259 yield compression
269 yield compression
260
270
261 filecount, bytecount, it = generatev1(repo)
271 filecount, bytecount, it = generatev1(repo)
262 repo.ui.status(_('writing %d bytes for %d files\n') %
272 repo.ui.status(_('writing %d bytes for %d files\n') %
263 (bytecount, filecount))
273 (bytecount, filecount))
264
274
265 yield struct.pack('>QQ', filecount, bytecount)
275 yield struct.pack('>QQ', filecount, bytecount)
266 yield struct.pack('>H', len(requires) + 1)
276 yield struct.pack('>H', len(requires) + 1)
267 yield requires + '\0'
277 yield requires + '\0'
268
278
269 # This is where we'll add compression in the future.
279 # This is where we'll add compression in the future.
270 assert compression == 'UN'
280 assert compression == 'UN'
271
281
272 seen = 0
282 seen = 0
273 repo.ui.progress(_('bundle'), 0, total=bytecount, unit=_('bytes'))
283 repo.ui.progress(_('bundle'), 0, total=bytecount, unit=_('bytes'))
274
284
275 for chunk in it:
285 for chunk in it:
276 seen += len(chunk)
286 seen += len(chunk)
277 repo.ui.progress(_('bundle'), seen, total=bytecount,
287 repo.ui.progress(_('bundle'), seen, total=bytecount,
278 unit=_('bytes'))
288 unit=_('bytes'))
279 yield chunk
289 yield chunk
280
290
281 repo.ui.progress(_('bundle'), None)
291 repo.ui.progress(_('bundle'), None)
282
292
283 return requirements, gen()
293 return requirements, gen()
284
294
285 def consumev1(repo, fp, filecount, bytecount):
295 def consumev1(repo, fp, filecount, bytecount):
286 """Apply the contents from version 1 of a streaming clone file handle.
296 """Apply the contents from version 1 of a streaming clone file handle.
287
297
288 This takes the output from "stream_out" and applies it to the specified
298 This takes the output from "stream_out" and applies it to the specified
289 repository.
299 repository.
290
300
291 Like "stream_out," the status line added by the wire protocol is not
301 Like "stream_out," the status line added by the wire protocol is not
292 handled by this function.
302 handled by this function.
293 """
303 """
294 with repo.lock():
304 with repo.lock():
295 repo.ui.status(_('%d files to transfer, %s of data\n') %
305 repo.ui.status(_('%d files to transfer, %s of data\n') %
296 (filecount, util.bytecount(bytecount)))
306 (filecount, util.bytecount(bytecount)))
297 handled_bytes = 0
307 handled_bytes = 0
298 repo.ui.progress(_('clone'), 0, total=bytecount, unit=_('bytes'))
308 repo.ui.progress(_('clone'), 0, total=bytecount, unit=_('bytes'))
299 start = util.timer()
309 start = util.timer()
300
310
301 # TODO: get rid of (potential) inconsistency
311 # TODO: get rid of (potential) inconsistency
302 #
312 #
303 # If transaction is started and any @filecache property is
313 # If transaction is started and any @filecache property is
304 # changed at this point, it causes inconsistency between
314 # changed at this point, it causes inconsistency between
305 # in-memory cached property and streamclone-ed file on the
315 # in-memory cached property and streamclone-ed file on the
306 # disk. Nested transaction prevents transaction scope "clone"
316 # disk. Nested transaction prevents transaction scope "clone"
307 # below from writing in-memory changes out at the end of it,
317 # below from writing in-memory changes out at the end of it,
308 # even though in-memory changes are discarded at the end of it
318 # even though in-memory changes are discarded at the end of it
309 # regardless of transaction nesting.
319 # regardless of transaction nesting.
310 #
320 #
311 # But transaction nesting can't be simply prohibited, because
321 # But transaction nesting can't be simply prohibited, because
312 # nesting occurs also in ordinary case (e.g. enabling
322 # nesting occurs also in ordinary case (e.g. enabling
313 # clonebundles).
323 # clonebundles).
314
324
315 with repo.transaction('clone'):
325 with repo.transaction('clone'):
316 with repo.svfs.backgroundclosing(repo.ui, expectedcount=filecount):
326 with repo.svfs.backgroundclosing(repo.ui, expectedcount=filecount):
317 for i in xrange(filecount):
327 for i in xrange(filecount):
318 # XXX doesn't support '\n' or '\r' in filenames
328 # XXX doesn't support '\n' or '\r' in filenames
319 l = fp.readline()
329 l = fp.readline()
320 try:
330 try:
321 name, size = l.split('\0', 1)
331 name, size = l.split('\0', 1)
322 size = int(size)
332 size = int(size)
323 except (ValueError, TypeError):
333 except (ValueError, TypeError):
324 raise error.ResponseError(
334 raise error.ResponseError(
325 _('unexpected response from remote server:'), l)
335 _('unexpected response from remote server:'), l)
326 if repo.ui.debugflag:
336 if repo.ui.debugflag:
327 repo.ui.debug('adding %s (%s)\n' %
337 repo.ui.debug('adding %s (%s)\n' %
328 (name, util.bytecount(size)))
338 (name, util.bytecount(size)))
329 # for backwards compat, name was partially encoded
339 # for backwards compat, name was partially encoded
330 path = store.decodedir(name)
340 path = store.decodedir(name)
331 with repo.svfs(path, 'w', backgroundclose=True) as ofp:
341 with repo.svfs(path, 'w', backgroundclose=True) as ofp:
332 for chunk in util.filechunkiter(fp, limit=size):
342 for chunk in util.filechunkiter(fp, limit=size):
333 handled_bytes += len(chunk)
343 handled_bytes += len(chunk)
334 repo.ui.progress(_('clone'), handled_bytes,
344 repo.ui.progress(_('clone'), handled_bytes,
335 total=bytecount, unit=_('bytes'))
345 total=bytecount, unit=_('bytes'))
336 ofp.write(chunk)
346 ofp.write(chunk)
337
347
338 # force @filecache properties to be reloaded from
348 # force @filecache properties to be reloaded from
339 # streamclone-ed file at next access
349 # streamclone-ed file at next access
340 repo.invalidate(clearfilecache=True)
350 repo.invalidate(clearfilecache=True)
341
351
342 elapsed = util.timer() - start
352 elapsed = util.timer() - start
343 if elapsed <= 0:
353 if elapsed <= 0:
344 elapsed = 0.001
354 elapsed = 0.001
345 repo.ui.progress(_('clone'), None)
355 repo.ui.progress(_('clone'), None)
346 repo.ui.status(_('transferred %s in %.1f seconds (%s/sec)\n') %
356 repo.ui.status(_('transferred %s in %.1f seconds (%s/sec)\n') %
347 (util.bytecount(bytecount), elapsed,
357 (util.bytecount(bytecount), elapsed,
348 util.bytecount(bytecount / elapsed)))
358 util.bytecount(bytecount / elapsed)))
349
359
350 def readbundle1header(fp):
360 def readbundle1header(fp):
351 compression = fp.read(2)
361 compression = fp.read(2)
352 if compression != 'UN':
362 if compression != 'UN':
353 raise error.Abort(_('only uncompressed stream clone bundles are '
363 raise error.Abort(_('only uncompressed stream clone bundles are '
354 'supported; got %s') % compression)
364 'supported; got %s') % compression)
355
365
356 filecount, bytecount = struct.unpack('>QQ', fp.read(16))
366 filecount, bytecount = struct.unpack('>QQ', fp.read(16))
357 requireslen = struct.unpack('>H', fp.read(2))[0]
367 requireslen = struct.unpack('>H', fp.read(2))[0]
358 requires = fp.read(requireslen)
368 requires = fp.read(requireslen)
359
369
360 if not requires.endswith('\0'):
370 if not requires.endswith('\0'):
361 raise error.Abort(_('malformed stream clone bundle: '
371 raise error.Abort(_('malformed stream clone bundle: '
362 'requirements not properly encoded'))
372 'requirements not properly encoded'))
363
373
364 requirements = set(requires.rstrip('\0').split(','))
374 requirements = set(requires.rstrip('\0').split(','))
365
375
366 return filecount, bytecount, requirements
376 return filecount, bytecount, requirements
367
377
368 def applybundlev1(repo, fp):
378 def applybundlev1(repo, fp):
369 """Apply the content from a stream clone bundle version 1.
379 """Apply the content from a stream clone bundle version 1.
370
380
371 We assume the 4 byte header has been read and validated and the file handle
381 We assume the 4 byte header has been read and validated and the file handle
372 is at the 2 byte compression identifier.
382 is at the 2 byte compression identifier.
373 """
383 """
374 if len(repo):
384 if len(repo):
375 raise error.Abort(_('cannot apply stream clone bundle on non-empty '
385 raise error.Abort(_('cannot apply stream clone bundle on non-empty '
376 'repo'))
386 'repo'))
377
387
378 filecount, bytecount, requirements = readbundle1header(fp)
388 filecount, bytecount, requirements = readbundle1header(fp)
379 missingreqs = requirements - repo.supportedformats
389 missingreqs = requirements - repo.supportedformats
380 if missingreqs:
390 if missingreqs:
381 raise error.Abort(_('unable to apply stream clone: '
391 raise error.Abort(_('unable to apply stream clone: '
382 'unsupported format: %s') %
392 'unsupported format: %s') %
383 ', '.join(sorted(missingreqs)))
393 ', '.join(sorted(missingreqs)))
384
394
385 consumev1(repo, fp, filecount, bytecount)
395 consumev1(repo, fp, filecount, bytecount)
386
396
387 class streamcloneapplier(object):
397 class streamcloneapplier(object):
388 """Class to manage applying streaming clone bundles.
398 """Class to manage applying streaming clone bundles.
389
399
390 We need to wrap ``applybundlev1()`` in a dedicated type to enable bundle
400 We need to wrap ``applybundlev1()`` in a dedicated type to enable bundle
391 readers to perform bundle type-specific functionality.
401 readers to perform bundle type-specific functionality.
392 """
402 """
393 def __init__(self, fh):
403 def __init__(self, fh):
394 self._fh = fh
404 self._fh = fh
395
405
396 def apply(self, repo):
406 def apply(self, repo):
397 return applybundlev1(repo, self._fh)
407 return applybundlev1(repo, self._fh)
@@ -1,364 +1,367
1 #require serve
1 #require serve
2
2
3 This test is a duplicate of 'test-http.t', feel free to factor out
3 This test is a duplicate of 'test-http.t', feel free to factor out
4 parts that are not bundle1/bundle2 specific.
4 parts that are not bundle1/bundle2 specific.
5
5
6 $ cat << EOF >> $HGRCPATH
6 $ cat << EOF >> $HGRCPATH
7 > [devel]
7 > [devel]
8 > # This test is dedicated to interaction through old bundle
8 > # This test is dedicated to interaction through old bundle
9 > legacy.exchange = bundle1
9 > legacy.exchange = bundle1
10 > EOF
10 > EOF
11
11
12 $ hg init test
12 $ hg init test
13 $ cd test
13 $ cd test
14 $ echo foo>foo
14 $ echo foo>foo
15 $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
15 $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
16 $ echo foo>foo.d/foo
16 $ echo foo>foo.d/foo
17 $ echo bar>foo.d/bAr.hg.d/BaR
17 $ echo bar>foo.d/bAr.hg.d/BaR
18 $ echo bar>foo.d/baR.d.hg/bAR
18 $ echo bar>foo.d/baR.d.hg/bAR
19 $ hg commit -A -m 1
19 $ hg commit -A -m 1
20 adding foo
20 adding foo
21 adding foo.d/bAr.hg.d/BaR
21 adding foo.d/bAr.hg.d/BaR
22 adding foo.d/baR.d.hg/bAR
22 adding foo.d/baR.d.hg/bAR
23 adding foo.d/foo
23 adding foo.d/foo
24 $ hg serve -p $HGPORT -d --pid-file=../hg1.pid -E ../error.log
24 $ hg serve -p $HGPORT -d --pid-file=../hg1.pid -E ../error.log
25 $ hg serve --config server.uncompressed=False -p $HGPORT1 -d --pid-file=../hg2.pid
25 $ hg serve --config server.uncompressed=False -p $HGPORT1 -d --pid-file=../hg2.pid
26
26
27 Test server address cannot be reused
27 Test server address cannot be reused
28
28
29 #if windows
29 #if windows
30 $ hg serve -p $HGPORT1 2>&1
30 $ hg serve -p $HGPORT1 2>&1
31 abort: cannot start server at 'localhost:$HGPORT1': * (glob)
31 abort: cannot start server at 'localhost:$HGPORT1': * (glob)
32 [255]
32 [255]
33 #else
33 #else
34 $ hg serve -p $HGPORT1 2>&1
34 $ hg serve -p $HGPORT1 2>&1
35 abort: cannot start server at 'localhost:$HGPORT1': Address already in use
35 abort: cannot start server at 'localhost:$HGPORT1': Address already in use
36 [255]
36 [255]
37 #endif
37 #endif
38 $ cd ..
38 $ cd ..
39 $ cat hg1.pid hg2.pid >> $DAEMON_PIDS
39 $ cat hg1.pid hg2.pid >> $DAEMON_PIDS
40
40
41 clone via stream
41 clone via stream
42
42
43 $ hg clone --uncompressed http://localhost:$HGPORT/ copy 2>&1
43 $ hg clone --uncompressed http://localhost:$HGPORT/ copy 2>&1
44 streaming all changes
44 streaming all changes
45 6 files to transfer, 606 bytes of data
45 6 files to transfer, 606 bytes of data
46 transferred * bytes in * seconds (*/sec) (glob)
46 transferred * bytes in * seconds (*/sec) (glob)
47 searching for changes
47 searching for changes
48 no changes found
48 no changes found
49 updating to branch default
49 updating to branch default
50 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
50 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
51 $ hg verify -R copy
51 $ hg verify -R copy
52 checking changesets
52 checking changesets
53 checking manifests
53 checking manifests
54 crosschecking files in changesets and manifests
54 crosschecking files in changesets and manifests
55 checking files
55 checking files
56 4 files, 1 changesets, 4 total revisions
56 4 files, 1 changesets, 4 total revisions
57
57
58 try to clone via stream, should use pull instead
58 try to clone via stream, should use pull instead
59
59
60 $ hg clone --uncompressed http://localhost:$HGPORT1/ copy2
60 $ hg clone --uncompressed http://localhost:$HGPORT1/ copy2
61 warning: stream clone requested but server has them disabled
61 requesting all changes
62 requesting all changes
62 adding changesets
63 adding changesets
63 adding manifests
64 adding manifests
64 adding file changes
65 adding file changes
65 added 1 changesets with 4 changes to 4 files
66 added 1 changesets with 4 changes to 4 files
66 updating to branch default
67 updating to branch default
67 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
68 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
68
69
69 try to clone via stream but missing requirements, so should use pull instead
70 try to clone via stream but missing requirements, so should use pull instead
70
71
71 $ cat > $TESTTMP/removesupportedformat.py << EOF
72 $ cat > $TESTTMP/removesupportedformat.py << EOF
72 > from mercurial import localrepo
73 > from mercurial import localrepo
73 > def extsetup(ui):
74 > def extsetup(ui):
74 > localrepo.localrepository.supportedformats.remove('generaldelta')
75 > localrepo.localrepository.supportedformats.remove('generaldelta')
75 > EOF
76 > EOF
76
77
77 $ hg clone --config extensions.rsf=$TESTTMP/removesupportedformat.py --uncompressed http://localhost:$HGPORT/ copy3
78 $ hg clone --config extensions.rsf=$TESTTMP/removesupportedformat.py --uncompressed http://localhost:$HGPORT/ copy3
79 warning: stream clone requested but client is missing requirements: generaldelta
80 (see https://www.mercurial-scm.org/wiki/MissingRequirement for more information)
78 requesting all changes
81 requesting all changes
79 adding changesets
82 adding changesets
80 adding manifests
83 adding manifests
81 adding file changes
84 adding file changes
82 added 1 changesets with 4 changes to 4 files
85 added 1 changesets with 4 changes to 4 files
83 updating to branch default
86 updating to branch default
84 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
85
88
86 clone via pull
89 clone via pull
87
90
88 $ hg clone http://localhost:$HGPORT1/ copy-pull
91 $ hg clone http://localhost:$HGPORT1/ copy-pull
89 requesting all changes
92 requesting all changes
90 adding changesets
93 adding changesets
91 adding manifests
94 adding manifests
92 adding file changes
95 adding file changes
93 added 1 changesets with 4 changes to 4 files
96 added 1 changesets with 4 changes to 4 files
94 updating to branch default
97 updating to branch default
95 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
98 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
96 $ hg verify -R copy-pull
99 $ hg verify -R copy-pull
97 checking changesets
100 checking changesets
98 checking manifests
101 checking manifests
99 crosschecking files in changesets and manifests
102 crosschecking files in changesets and manifests
100 checking files
103 checking files
101 4 files, 1 changesets, 4 total revisions
104 4 files, 1 changesets, 4 total revisions
102 $ cd test
105 $ cd test
103 $ echo bar > bar
106 $ echo bar > bar
104 $ hg commit -A -d '1 0' -m 2
107 $ hg commit -A -d '1 0' -m 2
105 adding bar
108 adding bar
106 $ cd ..
109 $ cd ..
107
110
108 clone over http with --update
111 clone over http with --update
109
112
110 $ hg clone http://localhost:$HGPORT1/ updated --update 0
113 $ hg clone http://localhost:$HGPORT1/ updated --update 0
111 requesting all changes
114 requesting all changes
112 adding changesets
115 adding changesets
113 adding manifests
116 adding manifests
114 adding file changes
117 adding file changes
115 added 2 changesets with 5 changes to 5 files
118 added 2 changesets with 5 changes to 5 files
116 updating to branch default
119 updating to branch default
117 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
120 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
118 $ hg log -r . -R updated
121 $ hg log -r . -R updated
119 changeset: 0:8b6053c928fe
122 changeset: 0:8b6053c928fe
120 user: test
123 user: test
121 date: Thu Jan 01 00:00:00 1970 +0000
124 date: Thu Jan 01 00:00:00 1970 +0000
122 summary: 1
125 summary: 1
123
126
124 $ rm -rf updated
127 $ rm -rf updated
125
128
126 incoming via HTTP
129 incoming via HTTP
127
130
128 $ hg clone http://localhost:$HGPORT1/ --rev 0 partial
131 $ hg clone http://localhost:$HGPORT1/ --rev 0 partial
129 adding changesets
132 adding changesets
130 adding manifests
133 adding manifests
131 adding file changes
134 adding file changes
132 added 1 changesets with 4 changes to 4 files
135 added 1 changesets with 4 changes to 4 files
133 updating to branch default
136 updating to branch default
134 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
137 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
135 $ cd partial
138 $ cd partial
136 $ touch LOCAL
139 $ touch LOCAL
137 $ hg ci -qAm LOCAL
140 $ hg ci -qAm LOCAL
138 $ hg incoming http://localhost:$HGPORT1/ --template '{desc}\n'
141 $ hg incoming http://localhost:$HGPORT1/ --template '{desc}\n'
139 comparing with http://localhost:$HGPORT1/
142 comparing with http://localhost:$HGPORT1/
140 searching for changes
143 searching for changes
141 2
144 2
142 $ cd ..
145 $ cd ..
143
146
144 pull
147 pull
145
148
146 $ cd copy-pull
149 $ cd copy-pull
147 $ cat >> .hg/hgrc <<EOF
150 $ cat >> .hg/hgrc <<EOF
148 > [hooks]
151 > [hooks]
149 > changegroup = sh -c "printenv.py changegroup"
152 > changegroup = sh -c "printenv.py changegroup"
150 > EOF
153 > EOF
151 $ hg pull
154 $ hg pull
152 pulling from http://localhost:$HGPORT1/
155 pulling from http://localhost:$HGPORT1/
153 searching for changes
156 searching for changes
154 adding changesets
157 adding changesets
155 adding manifests
158 adding manifests
156 adding file changes
159 adding file changes
157 added 1 changesets with 1 changes to 1 files
160 added 1 changesets with 1 changes to 1 files
158 changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=http://localhost:$HGPORT1/
161 changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=http://localhost:$HGPORT1/
159 (run 'hg update' to get a working copy)
162 (run 'hg update' to get a working copy)
160 $ cd ..
163 $ cd ..
161
164
162 clone from invalid URL
165 clone from invalid URL
163
166
164 $ hg clone http://localhost:$HGPORT/bad
167 $ hg clone http://localhost:$HGPORT/bad
165 abort: HTTP Error 404: Not Found
168 abort: HTTP Error 404: Not Found
166 [255]
169 [255]
167
170
168 test http authentication
171 test http authentication
169 + use the same server to test server side streaming preference
172 + use the same server to test server side streaming preference
170
173
171 $ cd test
174 $ cd test
172 $ cat << EOT > userpass.py
175 $ cat << EOT > userpass.py
173 > import base64
176 > import base64
174 > from mercurial.hgweb import common
177 > from mercurial.hgweb import common
175 > def perform_authentication(hgweb, req, op):
178 > def perform_authentication(hgweb, req, op):
176 > auth = req.env.get('HTTP_AUTHORIZATION')
179 > auth = req.env.get('HTTP_AUTHORIZATION')
177 > if not auth:
180 > if not auth:
178 > raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, 'who',
181 > raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, 'who',
179 > [('WWW-Authenticate', 'Basic Realm="mercurial"')])
182 > [('WWW-Authenticate', 'Basic Realm="mercurial"')])
180 > if base64.b64decode(auth.split()[1]).split(':', 1) != ['user', 'pass']:
183 > if base64.b64decode(auth.split()[1]).split(':', 1) != ['user', 'pass']:
181 > raise common.ErrorResponse(common.HTTP_FORBIDDEN, 'no')
184 > raise common.ErrorResponse(common.HTTP_FORBIDDEN, 'no')
182 > def extsetup():
185 > def extsetup():
183 > common.permhooks.insert(0, perform_authentication)
186 > common.permhooks.insert(0, perform_authentication)
184 > EOT
187 > EOT
185 $ hg serve --config extensions.x=userpass.py -p $HGPORT2 -d --pid-file=pid \
188 $ hg serve --config extensions.x=userpass.py -p $HGPORT2 -d --pid-file=pid \
186 > --config server.preferuncompressed=True \
189 > --config server.preferuncompressed=True \
187 > --config web.push_ssl=False --config web.allow_push=* -A ../access.log
190 > --config web.push_ssl=False --config web.allow_push=* -A ../access.log
188 $ cat pid >> $DAEMON_PIDS
191 $ cat pid >> $DAEMON_PIDS
189
192
190 $ cat << EOF > get_pass.py
193 $ cat << EOF > get_pass.py
191 > import getpass
194 > import getpass
192 > def newgetpass(arg):
195 > def newgetpass(arg):
193 > return "pass"
196 > return "pass"
194 > getpass.getpass = newgetpass
197 > getpass.getpass = newgetpass
195 > EOF
198 > EOF
196
199
197 $ hg id http://localhost:$HGPORT2/
200 $ hg id http://localhost:$HGPORT2/
198 abort: http authorization required for http://localhost:$HGPORT2/
201 abort: http authorization required for http://localhost:$HGPORT2/
199 [255]
202 [255]
200 $ hg id http://localhost:$HGPORT2/
203 $ hg id http://localhost:$HGPORT2/
201 abort: http authorization required for http://localhost:$HGPORT2/
204 abort: http authorization required for http://localhost:$HGPORT2/
202 [255]
205 [255]
203 $ hg id --config ui.interactive=true --config extensions.getpass=get_pass.py http://user@localhost:$HGPORT2/
206 $ hg id --config ui.interactive=true --config extensions.getpass=get_pass.py http://user@localhost:$HGPORT2/
204 http authorization required for http://localhost:$HGPORT2/
207 http authorization required for http://localhost:$HGPORT2/
205 realm: mercurial
208 realm: mercurial
206 user: user
209 user: user
207 password: 5fed3813f7f5
210 password: 5fed3813f7f5
208 $ hg id http://user:pass@localhost:$HGPORT2/
211 $ hg id http://user:pass@localhost:$HGPORT2/
209 5fed3813f7f5
212 5fed3813f7f5
210 $ echo '[auth]' >> .hg/hgrc
213 $ echo '[auth]' >> .hg/hgrc
211 $ echo 'l.schemes=http' >> .hg/hgrc
214 $ echo 'l.schemes=http' >> .hg/hgrc
212 $ echo 'l.prefix=lo' >> .hg/hgrc
215 $ echo 'l.prefix=lo' >> .hg/hgrc
213 $ echo 'l.username=user' >> .hg/hgrc
216 $ echo 'l.username=user' >> .hg/hgrc
214 $ echo 'l.password=pass' >> .hg/hgrc
217 $ echo 'l.password=pass' >> .hg/hgrc
215 $ hg id http://localhost:$HGPORT2/
218 $ hg id http://localhost:$HGPORT2/
216 5fed3813f7f5
219 5fed3813f7f5
217 $ hg id http://localhost:$HGPORT2/
220 $ hg id http://localhost:$HGPORT2/
218 5fed3813f7f5
221 5fed3813f7f5
219 $ hg id http://user@localhost:$HGPORT2/
222 $ hg id http://user@localhost:$HGPORT2/
220 5fed3813f7f5
223 5fed3813f7f5
221 $ hg clone http://user:pass@localhost:$HGPORT2/ dest 2>&1
224 $ hg clone http://user:pass@localhost:$HGPORT2/ dest 2>&1
222 streaming all changes
225 streaming all changes
223 7 files to transfer, 916 bytes of data
226 7 files to transfer, 916 bytes of data
224 transferred * bytes in * seconds (*/sec) (glob)
227 transferred * bytes in * seconds (*/sec) (glob)
225 searching for changes
228 searching for changes
226 no changes found
229 no changes found
227 updating to branch default
230 updating to branch default
228 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
231 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
229 --pull should override server's preferuncompressed
232 --pull should override server's preferuncompressed
230 $ hg clone --pull http://user:pass@localhost:$HGPORT2/ dest-pull 2>&1
233 $ hg clone --pull http://user:pass@localhost:$HGPORT2/ dest-pull 2>&1
231 requesting all changes
234 requesting all changes
232 adding changesets
235 adding changesets
233 adding manifests
236 adding manifests
234 adding file changes
237 adding file changes
235 added 2 changesets with 5 changes to 5 files
238 added 2 changesets with 5 changes to 5 files
236 updating to branch default
239 updating to branch default
237 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
240 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
238
241
239 $ hg id http://user2@localhost:$HGPORT2/
242 $ hg id http://user2@localhost:$HGPORT2/
240 abort: http authorization required for http://localhost:$HGPORT2/
243 abort: http authorization required for http://localhost:$HGPORT2/
241 [255]
244 [255]
242 $ hg id http://user:pass2@localhost:$HGPORT2/
245 $ hg id http://user:pass2@localhost:$HGPORT2/
243 abort: HTTP Error 403: no
246 abort: HTTP Error 403: no
244 [255]
247 [255]
245
248
246 $ hg -R dest tag -r tip top
249 $ hg -R dest tag -r tip top
247 $ hg -R dest push http://user:pass@localhost:$HGPORT2/
250 $ hg -R dest push http://user:pass@localhost:$HGPORT2/
248 pushing to http://user:***@localhost:$HGPORT2/
251 pushing to http://user:***@localhost:$HGPORT2/
249 searching for changes
252 searching for changes
250 remote: adding changesets
253 remote: adding changesets
251 remote: adding manifests
254 remote: adding manifests
252 remote: adding file changes
255 remote: adding file changes
253 remote: added 1 changesets with 1 changes to 1 files
256 remote: added 1 changesets with 1 changes to 1 files
254 $ hg rollback -q
257 $ hg rollback -q
255
258
256 $ sed 's/.*] "/"/' < ../access.log
259 $ sed 's/.*] "/"/' < ../access.log
257 "GET /?cmd=capabilities HTTP/1.1" 200 -
260 "GET /?cmd=capabilities HTTP/1.1" 200 -
258 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
261 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
259 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
262 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
260 "GET /?cmd=capabilities HTTP/1.1" 200 -
263 "GET /?cmd=capabilities HTTP/1.1" 200 -
261 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
264 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
262 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
265 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
263 "GET /?cmd=capabilities HTTP/1.1" 200 -
266 "GET /?cmd=capabilities HTTP/1.1" 200 -
264 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
267 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
265 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
268 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
266 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
269 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
267 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
270 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
268 "GET /?cmd=capabilities HTTP/1.1" 200 -
271 "GET /?cmd=capabilities HTTP/1.1" 200 -
269 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
272 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
270 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
273 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
271 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
274 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
272 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
275 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
273 "GET /?cmd=capabilities HTTP/1.1" 200 -
276 "GET /?cmd=capabilities HTTP/1.1" 200 -
274 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
277 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
275 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
278 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
276 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
279 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
277 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
280 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
278 "GET /?cmd=capabilities HTTP/1.1" 200 -
281 "GET /?cmd=capabilities HTTP/1.1" 200 -
279 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
282 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
280 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
283 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
281 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
284 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
282 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
285 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
283 "GET /?cmd=capabilities HTTP/1.1" 200 -
286 "GET /?cmd=capabilities HTTP/1.1" 200 -
284 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
287 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
285 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
288 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
286 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
289 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
287 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
290 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
288 "GET /?cmd=capabilities HTTP/1.1" 200 -
291 "GET /?cmd=capabilities HTTP/1.1" 200 -
289 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
292 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
290 "GET /?cmd=stream_out HTTP/1.1" 401 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
293 "GET /?cmd=stream_out HTTP/1.1" 401 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
291 "GET /?cmd=stream_out HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
294 "GET /?cmd=stream_out HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
292 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
295 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
293 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
296 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
294 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
297 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
295 "GET /?cmd=capabilities HTTP/1.1" 200 -
298 "GET /?cmd=capabilities HTTP/1.1" 200 -
296 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
299 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
297 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
300 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
298 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
301 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
299 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
302 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
300 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
303 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
301 "GET /?cmd=capabilities HTTP/1.1" 200 -
304 "GET /?cmd=capabilities HTTP/1.1" 200 -
302 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
305 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
303 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
306 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
304 "GET /?cmd=capabilities HTTP/1.1" 200 -
307 "GET /?cmd=capabilities HTTP/1.1" 200 -
305 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
308 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
306 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
309 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
307 "GET /?cmd=listkeys HTTP/1.1" 403 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
310 "GET /?cmd=listkeys HTTP/1.1" 403 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
308 "GET /?cmd=capabilities HTTP/1.1" 200 -
311 "GET /?cmd=capabilities HTTP/1.1" 200 -
309 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872 x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
312 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872 x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
310 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
313 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
311 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
314 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
312 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
315 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
313 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
316 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
314 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
317 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
315 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
318 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
316 "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=686173686564+5eb5abfefeea63c80dd7553bcc3783f37e0c5524* (glob)
319 "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=686173686564+5eb5abfefeea63c80dd7553bcc3783f37e0c5524* (glob)
317 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
320 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
318
321
319 $ cd ..
322 $ cd ..
320
323
321 clone of serve with repo in root and unserved subrepo (issue2970)
324 clone of serve with repo in root and unserved subrepo (issue2970)
322
325
323 $ hg --cwd test init sub
326 $ hg --cwd test init sub
324 $ echo empty > test/sub/empty
327 $ echo empty > test/sub/empty
325 $ hg --cwd test/sub add empty
328 $ hg --cwd test/sub add empty
326 $ hg --cwd test/sub commit -qm 'add empty'
329 $ hg --cwd test/sub commit -qm 'add empty'
327 $ hg --cwd test/sub tag -r 0 something
330 $ hg --cwd test/sub tag -r 0 something
328 $ echo sub = sub > test/.hgsub
331 $ echo sub = sub > test/.hgsub
329 $ hg --cwd test add .hgsub
332 $ hg --cwd test add .hgsub
330 $ hg --cwd test commit -qm 'add subrepo'
333 $ hg --cwd test commit -qm 'add subrepo'
331 $ hg clone http://localhost:$HGPORT noslash-clone
334 $ hg clone http://localhost:$HGPORT noslash-clone
332 requesting all changes
335 requesting all changes
333 adding changesets
336 adding changesets
334 adding manifests
337 adding manifests
335 adding file changes
338 adding file changes
336 added 3 changesets with 7 changes to 7 files
339 added 3 changesets with 7 changes to 7 files
337 updating to branch default
340 updating to branch default
338 abort: HTTP Error 404: Not Found
341 abort: HTTP Error 404: Not Found
339 [255]
342 [255]
340 $ hg clone http://localhost:$HGPORT/ slash-clone
343 $ hg clone http://localhost:$HGPORT/ slash-clone
341 requesting all changes
344 requesting all changes
342 adding changesets
345 adding changesets
343 adding manifests
346 adding manifests
344 adding file changes
347 adding file changes
345 added 3 changesets with 7 changes to 7 files
348 added 3 changesets with 7 changes to 7 files
346 updating to branch default
349 updating to branch default
347 abort: HTTP Error 404: Not Found
350 abort: HTTP Error 404: Not Found
348 [255]
351 [255]
349
352
350 check error log
353 check error log
351
354
352 $ cat error.log
355 $ cat error.log
353
356
354 Check error reporting while pulling/cloning
357 Check error reporting while pulling/cloning
355
358
356 $ $RUNTESTDIR/killdaemons.py
359 $ $RUNTESTDIR/killdaemons.py
357 $ hg -R test serve -p $HGPORT -d --pid-file=hg3.pid -E error.log --config extensions.crash=${TESTDIR}/crashgetbundler.py
360 $ hg -R test serve -p $HGPORT -d --pid-file=hg3.pid -E error.log --config extensions.crash=${TESTDIR}/crashgetbundler.py
358 $ cat hg3.pid >> $DAEMON_PIDS
361 $ cat hg3.pid >> $DAEMON_PIDS
359 $ hg clone http://localhost:$HGPORT/ abort-clone
362 $ hg clone http://localhost:$HGPORT/ abort-clone
360 requesting all changes
363 requesting all changes
361 abort: remote error:
364 abort: remote error:
362 this is an exercise
365 this is an exercise
363 [255]
366 [255]
364 $ cat error.log
367 $ cat error.log
@@ -1,413 +1,416
1 #require killdaemons serve
1 #require killdaemons serve
2
2
3 $ hg init test
3 $ hg init test
4 $ cd test
4 $ cd test
5 $ echo foo>foo
5 $ echo foo>foo
6 $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
6 $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
7 $ echo foo>foo.d/foo
7 $ echo foo>foo.d/foo
8 $ echo bar>foo.d/bAr.hg.d/BaR
8 $ echo bar>foo.d/bAr.hg.d/BaR
9 $ echo bar>foo.d/baR.d.hg/bAR
9 $ echo bar>foo.d/baR.d.hg/bAR
10 $ hg commit -A -m 1
10 $ hg commit -A -m 1
11 adding foo
11 adding foo
12 adding foo.d/bAr.hg.d/BaR
12 adding foo.d/bAr.hg.d/BaR
13 adding foo.d/baR.d.hg/bAR
13 adding foo.d/baR.d.hg/bAR
14 adding foo.d/foo
14 adding foo.d/foo
15 $ hg serve -p $HGPORT -d --pid-file=../hg1.pid -E ../error.log
15 $ hg serve -p $HGPORT -d --pid-file=../hg1.pid -E ../error.log
16 $ hg serve --config server.uncompressed=False -p $HGPORT1 -d --pid-file=../hg2.pid
16 $ hg serve --config server.uncompressed=False -p $HGPORT1 -d --pid-file=../hg2.pid
17
17
18 Test server address cannot be reused
18 Test server address cannot be reused
19
19
20 #if windows
20 #if windows
21 $ hg serve -p $HGPORT1 2>&1
21 $ hg serve -p $HGPORT1 2>&1
22 abort: cannot start server at 'localhost:$HGPORT1': * (glob)
22 abort: cannot start server at 'localhost:$HGPORT1': * (glob)
23 [255]
23 [255]
24 #else
24 #else
25 $ hg serve -p $HGPORT1 2>&1
25 $ hg serve -p $HGPORT1 2>&1
26 abort: cannot start server at 'localhost:$HGPORT1': Address already in use
26 abort: cannot start server at 'localhost:$HGPORT1': Address already in use
27 [255]
27 [255]
28 #endif
28 #endif
29 $ cd ..
29 $ cd ..
30 $ cat hg1.pid hg2.pid >> $DAEMON_PIDS
30 $ cat hg1.pid hg2.pid >> $DAEMON_PIDS
31
31
32 clone via stream
32 clone via stream
33
33
34 $ hg clone --uncompressed http://localhost:$HGPORT/ copy 2>&1
34 $ hg clone --uncompressed http://localhost:$HGPORT/ copy 2>&1
35 streaming all changes
35 streaming all changes
36 6 files to transfer, 606 bytes of data
36 6 files to transfer, 606 bytes of data
37 transferred * bytes in * seconds (*/sec) (glob)
37 transferred * bytes in * seconds (*/sec) (glob)
38 searching for changes
38 searching for changes
39 no changes found
39 no changes found
40 updating to branch default
40 updating to branch default
41 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
41 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 $ hg verify -R copy
42 $ hg verify -R copy
43 checking changesets
43 checking changesets
44 checking manifests
44 checking manifests
45 crosschecking files in changesets and manifests
45 crosschecking files in changesets and manifests
46 checking files
46 checking files
47 4 files, 1 changesets, 4 total revisions
47 4 files, 1 changesets, 4 total revisions
48
48
49 try to clone via stream, should use pull instead
49 try to clone via stream, should use pull instead
50
50
51 $ hg clone --uncompressed http://localhost:$HGPORT1/ copy2
51 $ hg clone --uncompressed http://localhost:$HGPORT1/ copy2
52 warning: stream clone requested but server has them disabled
52 requesting all changes
53 requesting all changes
53 adding changesets
54 adding changesets
54 adding manifests
55 adding manifests
55 adding file changes
56 adding file changes
56 added 1 changesets with 4 changes to 4 files
57 added 1 changesets with 4 changes to 4 files
57 updating to branch default
58 updating to branch default
58 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
59 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
59
60
60 try to clone via stream but missing requirements, so should use pull instead
61 try to clone via stream but missing requirements, so should use pull instead
61
62
62 $ cat > $TESTTMP/removesupportedformat.py << EOF
63 $ cat > $TESTTMP/removesupportedformat.py << EOF
63 > from mercurial import localrepo
64 > from mercurial import localrepo
64 > def extsetup(ui):
65 > def extsetup(ui):
65 > localrepo.localrepository.supportedformats.remove('generaldelta')
66 > localrepo.localrepository.supportedformats.remove('generaldelta')
66 > EOF
67 > EOF
67
68
68 $ hg clone --config extensions.rsf=$TESTTMP/removesupportedformat.py --uncompressed http://localhost:$HGPORT/ copy3
69 $ hg clone --config extensions.rsf=$TESTTMP/removesupportedformat.py --uncompressed http://localhost:$HGPORT/ copy3
70 warning: stream clone requested but client is missing requirements: generaldelta
71 (see https://www.mercurial-scm.org/wiki/MissingRequirement for more information)
69 requesting all changes
72 requesting all changes
70 adding changesets
73 adding changesets
71 adding manifests
74 adding manifests
72 adding file changes
75 adding file changes
73 added 1 changesets with 4 changes to 4 files
76 added 1 changesets with 4 changes to 4 files
74 updating to branch default
77 updating to branch default
75 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
78 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
76
79
77 clone via pull
80 clone via pull
78
81
79 $ hg clone http://localhost:$HGPORT1/ copy-pull
82 $ hg clone http://localhost:$HGPORT1/ copy-pull
80 requesting all changes
83 requesting all changes
81 adding changesets
84 adding changesets
82 adding manifests
85 adding manifests
83 adding file changes
86 adding file changes
84 added 1 changesets with 4 changes to 4 files
87 added 1 changesets with 4 changes to 4 files
85 updating to branch default
88 updating to branch default
86 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
89 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 $ hg verify -R copy-pull
90 $ hg verify -R copy-pull
88 checking changesets
91 checking changesets
89 checking manifests
92 checking manifests
90 crosschecking files in changesets and manifests
93 crosschecking files in changesets and manifests
91 checking files
94 checking files
92 4 files, 1 changesets, 4 total revisions
95 4 files, 1 changesets, 4 total revisions
93 $ cd test
96 $ cd test
94 $ echo bar > bar
97 $ echo bar > bar
95 $ hg commit -A -d '1 0' -m 2
98 $ hg commit -A -d '1 0' -m 2
96 adding bar
99 adding bar
97 $ cd ..
100 $ cd ..
98
101
99 clone over http with --update
102 clone over http with --update
100
103
101 $ hg clone http://localhost:$HGPORT1/ updated --update 0
104 $ hg clone http://localhost:$HGPORT1/ updated --update 0
102 requesting all changes
105 requesting all changes
103 adding changesets
106 adding changesets
104 adding manifests
107 adding manifests
105 adding file changes
108 adding file changes
106 added 2 changesets with 5 changes to 5 files
109 added 2 changesets with 5 changes to 5 files
107 updating to branch default
110 updating to branch default
108 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
111 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 $ hg log -r . -R updated
112 $ hg log -r . -R updated
110 changeset: 0:8b6053c928fe
113 changeset: 0:8b6053c928fe
111 user: test
114 user: test
112 date: Thu Jan 01 00:00:00 1970 +0000
115 date: Thu Jan 01 00:00:00 1970 +0000
113 summary: 1
116 summary: 1
114
117
115 $ rm -rf updated
118 $ rm -rf updated
116
119
117 incoming via HTTP
120 incoming via HTTP
118
121
119 $ hg clone http://localhost:$HGPORT1/ --rev 0 partial
122 $ hg clone http://localhost:$HGPORT1/ --rev 0 partial
120 adding changesets
123 adding changesets
121 adding manifests
124 adding manifests
122 adding file changes
125 adding file changes
123 added 1 changesets with 4 changes to 4 files
126 added 1 changesets with 4 changes to 4 files
124 updating to branch default
127 updating to branch default
125 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
128 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
126 $ cd partial
129 $ cd partial
127 $ touch LOCAL
130 $ touch LOCAL
128 $ hg ci -qAm LOCAL
131 $ hg ci -qAm LOCAL
129 $ hg incoming http://localhost:$HGPORT1/ --template '{desc}\n'
132 $ hg incoming http://localhost:$HGPORT1/ --template '{desc}\n'
130 comparing with http://localhost:$HGPORT1/
133 comparing with http://localhost:$HGPORT1/
131 searching for changes
134 searching for changes
132 2
135 2
133 $ cd ..
136 $ cd ..
134
137
135 pull
138 pull
136
139
137 $ cd copy-pull
140 $ cd copy-pull
138 $ cat >> .hg/hgrc <<EOF
141 $ cat >> .hg/hgrc <<EOF
139 > [hooks]
142 > [hooks]
140 > changegroup = sh -c "printenv.py changegroup"
143 > changegroup = sh -c "printenv.py changegroup"
141 > EOF
144 > EOF
142 $ hg pull
145 $ hg pull
143 pulling from http://localhost:$HGPORT1/
146 pulling from http://localhost:$HGPORT1/
144 searching for changes
147 searching for changes
145 adding changesets
148 adding changesets
146 adding manifests
149 adding manifests
147 adding file changes
150 adding file changes
148 added 1 changesets with 1 changes to 1 files
151 added 1 changesets with 1 changes to 1 files
149 changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=http://localhost:$HGPORT1/
152 changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=http://localhost:$HGPORT1/
150 (run 'hg update' to get a working copy)
153 (run 'hg update' to get a working copy)
151 $ cd ..
154 $ cd ..
152
155
153 clone from invalid URL
156 clone from invalid URL
154
157
155 $ hg clone http://localhost:$HGPORT/bad
158 $ hg clone http://localhost:$HGPORT/bad
156 abort: HTTP Error 404: Not Found
159 abort: HTTP Error 404: Not Found
157 [255]
160 [255]
158
161
159 test http authentication
162 test http authentication
160 + use the same server to test server side streaming preference
163 + use the same server to test server side streaming preference
161
164
162 $ cd test
165 $ cd test
163 $ cat << EOT > userpass.py
166 $ cat << EOT > userpass.py
164 > import base64
167 > import base64
165 > from mercurial.hgweb import common
168 > from mercurial.hgweb import common
166 > def perform_authentication(hgweb, req, op):
169 > def perform_authentication(hgweb, req, op):
167 > auth = req.env.get('HTTP_AUTHORIZATION')
170 > auth = req.env.get('HTTP_AUTHORIZATION')
168 > if not auth:
171 > if not auth:
169 > raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, 'who',
172 > raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, 'who',
170 > [('WWW-Authenticate', 'Basic Realm="mercurial"')])
173 > [('WWW-Authenticate', 'Basic Realm="mercurial"')])
171 > if base64.b64decode(auth.split()[1]).split(':', 1) != ['user', 'pass']:
174 > if base64.b64decode(auth.split()[1]).split(':', 1) != ['user', 'pass']:
172 > raise common.ErrorResponse(common.HTTP_FORBIDDEN, 'no')
175 > raise common.ErrorResponse(common.HTTP_FORBIDDEN, 'no')
173 > def extsetup():
176 > def extsetup():
174 > common.permhooks.insert(0, perform_authentication)
177 > common.permhooks.insert(0, perform_authentication)
175 > EOT
178 > EOT
176 $ hg serve --config extensions.x=userpass.py -p $HGPORT2 -d --pid-file=pid \
179 $ hg serve --config extensions.x=userpass.py -p $HGPORT2 -d --pid-file=pid \
177 > --config server.preferuncompressed=True \
180 > --config server.preferuncompressed=True \
178 > --config web.push_ssl=False --config web.allow_push=* -A ../access.log
181 > --config web.push_ssl=False --config web.allow_push=* -A ../access.log
179 $ cat pid >> $DAEMON_PIDS
182 $ cat pid >> $DAEMON_PIDS
180
183
181 $ cat << EOF > get_pass.py
184 $ cat << EOF > get_pass.py
182 > import getpass
185 > import getpass
183 > def newgetpass(arg):
186 > def newgetpass(arg):
184 > return "pass"
187 > return "pass"
185 > getpass.getpass = newgetpass
188 > getpass.getpass = newgetpass
186 > EOF
189 > EOF
187
190
188 $ hg id http://localhost:$HGPORT2/
191 $ hg id http://localhost:$HGPORT2/
189 abort: http authorization required for http://localhost:$HGPORT2/
192 abort: http authorization required for http://localhost:$HGPORT2/
190 [255]
193 [255]
191 $ hg id http://localhost:$HGPORT2/
194 $ hg id http://localhost:$HGPORT2/
192 abort: http authorization required for http://localhost:$HGPORT2/
195 abort: http authorization required for http://localhost:$HGPORT2/
193 [255]
196 [255]
194 $ hg id --config ui.interactive=true --config extensions.getpass=get_pass.py http://user@localhost:$HGPORT2/
197 $ hg id --config ui.interactive=true --config extensions.getpass=get_pass.py http://user@localhost:$HGPORT2/
195 http authorization required for http://localhost:$HGPORT2/
198 http authorization required for http://localhost:$HGPORT2/
196 realm: mercurial
199 realm: mercurial
197 user: user
200 user: user
198 password: 5fed3813f7f5
201 password: 5fed3813f7f5
199 $ hg id http://user:pass@localhost:$HGPORT2/
202 $ hg id http://user:pass@localhost:$HGPORT2/
200 5fed3813f7f5
203 5fed3813f7f5
201 $ echo '[auth]' >> .hg/hgrc
204 $ echo '[auth]' >> .hg/hgrc
202 $ echo 'l.schemes=http' >> .hg/hgrc
205 $ echo 'l.schemes=http' >> .hg/hgrc
203 $ echo 'l.prefix=lo' >> .hg/hgrc
206 $ echo 'l.prefix=lo' >> .hg/hgrc
204 $ echo 'l.username=user' >> .hg/hgrc
207 $ echo 'l.username=user' >> .hg/hgrc
205 $ echo 'l.password=pass' >> .hg/hgrc
208 $ echo 'l.password=pass' >> .hg/hgrc
206 $ hg id http://localhost:$HGPORT2/
209 $ hg id http://localhost:$HGPORT2/
207 5fed3813f7f5
210 5fed3813f7f5
208 $ hg id http://localhost:$HGPORT2/
211 $ hg id http://localhost:$HGPORT2/
209 5fed3813f7f5
212 5fed3813f7f5
210 $ hg id http://user@localhost:$HGPORT2/
213 $ hg id http://user@localhost:$HGPORT2/
211 5fed3813f7f5
214 5fed3813f7f5
212 $ hg clone http://user:pass@localhost:$HGPORT2/ dest 2>&1
215 $ hg clone http://user:pass@localhost:$HGPORT2/ dest 2>&1
213 streaming all changes
216 streaming all changes
214 7 files to transfer, 916 bytes of data
217 7 files to transfer, 916 bytes of data
215 transferred * bytes in * seconds (*/sec) (glob)
218 transferred * bytes in * seconds (*/sec) (glob)
216 searching for changes
219 searching for changes
217 no changes found
220 no changes found
218 updating to branch default
221 updating to branch default
219 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
222 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
220 --pull should override server's preferuncompressed
223 --pull should override server's preferuncompressed
221 $ hg clone --pull http://user:pass@localhost:$HGPORT2/ dest-pull 2>&1
224 $ hg clone --pull http://user:pass@localhost:$HGPORT2/ dest-pull 2>&1
222 requesting all changes
225 requesting all changes
223 adding changesets
226 adding changesets
224 adding manifests
227 adding manifests
225 adding file changes
228 adding file changes
226 added 2 changesets with 5 changes to 5 files
229 added 2 changesets with 5 changes to 5 files
227 updating to branch default
230 updating to branch default
228 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
231 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
229
232
230 $ hg id http://user2@localhost:$HGPORT2/
233 $ hg id http://user2@localhost:$HGPORT2/
231 abort: http authorization required for http://localhost:$HGPORT2/
234 abort: http authorization required for http://localhost:$HGPORT2/
232 [255]
235 [255]
233 $ hg id http://user:pass2@localhost:$HGPORT2/
236 $ hg id http://user:pass2@localhost:$HGPORT2/
234 abort: HTTP Error 403: no
237 abort: HTTP Error 403: no
235 [255]
238 [255]
236
239
237 $ hg -R dest tag -r tip top
240 $ hg -R dest tag -r tip top
238 $ hg -R dest push http://user:pass@localhost:$HGPORT2/
241 $ hg -R dest push http://user:pass@localhost:$HGPORT2/
239 pushing to http://user:***@localhost:$HGPORT2/
242 pushing to http://user:***@localhost:$HGPORT2/
240 searching for changes
243 searching for changes
241 remote: adding changesets
244 remote: adding changesets
242 remote: adding manifests
245 remote: adding manifests
243 remote: adding file changes
246 remote: adding file changes
244 remote: added 1 changesets with 1 changes to 1 files
247 remote: added 1 changesets with 1 changes to 1 files
245 $ hg rollback -q
248 $ hg rollback -q
246
249
247 $ sed 's/.*] "/"/' < ../access.log
250 $ sed 's/.*] "/"/' < ../access.log
248 "GET /?cmd=capabilities HTTP/1.1" 200 -
251 "GET /?cmd=capabilities HTTP/1.1" 200 -
249 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
252 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
250 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
253 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
251 "GET /?cmd=capabilities HTTP/1.1" 200 -
254 "GET /?cmd=capabilities HTTP/1.1" 200 -
252 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
255 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
253 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
256 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
254 "GET /?cmd=capabilities HTTP/1.1" 200 -
257 "GET /?cmd=capabilities HTTP/1.1" 200 -
255 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
258 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
256 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
259 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
257 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
260 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
258 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
261 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
259 "GET /?cmd=capabilities HTTP/1.1" 200 -
262 "GET /?cmd=capabilities HTTP/1.1" 200 -
260 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
263 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
261 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
264 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
262 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
265 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
263 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
266 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
264 "GET /?cmd=capabilities HTTP/1.1" 200 -
267 "GET /?cmd=capabilities HTTP/1.1" 200 -
265 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
268 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
266 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
269 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
267 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
270 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
268 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
271 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
269 "GET /?cmd=capabilities HTTP/1.1" 200 -
272 "GET /?cmd=capabilities HTTP/1.1" 200 -
270 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
273 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
271 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
274 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
272 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
275 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
273 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
276 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
274 "GET /?cmd=capabilities HTTP/1.1" 200 -
277 "GET /?cmd=capabilities HTTP/1.1" 200 -
275 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
278 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
276 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
279 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
277 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
280 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
278 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
281 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
279 "GET /?cmd=capabilities HTTP/1.1" 200 -
282 "GET /?cmd=capabilities HTTP/1.1" 200 -
280 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
283 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
281 "GET /?cmd=stream_out HTTP/1.1" 401 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
284 "GET /?cmd=stream_out HTTP/1.1" 401 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
282 "GET /?cmd=stream_out HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
285 "GET /?cmd=stream_out HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
283 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
286 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
284 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phases%2Cbookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
287 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phases%2Cbookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
285 "GET /?cmd=capabilities HTTP/1.1" 200 -
288 "GET /?cmd=capabilities HTTP/1.1" 200 -
286 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
289 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
287 "GET /?cmd=getbundle HTTP/1.1" 401 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phases%2Cbookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
290 "GET /?cmd=getbundle HTTP/1.1" 401 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phases%2Cbookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
288 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phases%2Cbookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
291 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phases%2Cbookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
289 "GET /?cmd=capabilities HTTP/1.1" 200 -
292 "GET /?cmd=capabilities HTTP/1.1" 200 -
290 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
293 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
291 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
294 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
292 "GET /?cmd=capabilities HTTP/1.1" 200 -
295 "GET /?cmd=capabilities HTTP/1.1" 200 -
293 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
296 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
294 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
297 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
295 "GET /?cmd=listkeys HTTP/1.1" 403 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
298 "GET /?cmd=listkeys HTTP/1.1" 403 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
296 "GET /?cmd=capabilities HTTP/1.1" 200 -
299 "GET /?cmd=capabilities HTTP/1.1" 200 -
297 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872 x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
300 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872 x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
298 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
301 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
299 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
302 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
300 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
303 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
301 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
304 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
302 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
305 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
303 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
306 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
304 "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=666f726365* (glob)
307 "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=666f726365* (glob)
305 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
308 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
306
309
307 $ cd ..
310 $ cd ..
308
311
309 clone of serve with repo in root and unserved subrepo (issue2970)
312 clone of serve with repo in root and unserved subrepo (issue2970)
310
313
311 $ hg --cwd test init sub
314 $ hg --cwd test init sub
312 $ echo empty > test/sub/empty
315 $ echo empty > test/sub/empty
313 $ hg --cwd test/sub add empty
316 $ hg --cwd test/sub add empty
314 $ hg --cwd test/sub commit -qm 'add empty'
317 $ hg --cwd test/sub commit -qm 'add empty'
315 $ hg --cwd test/sub tag -r 0 something
318 $ hg --cwd test/sub tag -r 0 something
316 $ echo sub = sub > test/.hgsub
319 $ echo sub = sub > test/.hgsub
317 $ hg --cwd test add .hgsub
320 $ hg --cwd test add .hgsub
318 $ hg --cwd test commit -qm 'add subrepo'
321 $ hg --cwd test commit -qm 'add subrepo'
319 $ hg clone http://localhost:$HGPORT noslash-clone
322 $ hg clone http://localhost:$HGPORT noslash-clone
320 requesting all changes
323 requesting all changes
321 adding changesets
324 adding changesets
322 adding manifests
325 adding manifests
323 adding file changes
326 adding file changes
324 added 3 changesets with 7 changes to 7 files
327 added 3 changesets with 7 changes to 7 files
325 updating to branch default
328 updating to branch default
326 abort: HTTP Error 404: Not Found
329 abort: HTTP Error 404: Not Found
327 [255]
330 [255]
328 $ hg clone http://localhost:$HGPORT/ slash-clone
331 $ hg clone http://localhost:$HGPORT/ slash-clone
329 requesting all changes
332 requesting all changes
330 adding changesets
333 adding changesets
331 adding manifests
334 adding manifests
332 adding file changes
335 adding file changes
333 added 3 changesets with 7 changes to 7 files
336 added 3 changesets with 7 changes to 7 files
334 updating to branch default
337 updating to branch default
335 abort: HTTP Error 404: Not Found
338 abort: HTTP Error 404: Not Found
336 [255]
339 [255]
337
340
338 check error log
341 check error log
339
342
340 $ cat error.log
343 $ cat error.log
341
344
342 check abort error reporting while pulling/cloning
345 check abort error reporting while pulling/cloning
343
346
344 $ $RUNTESTDIR/killdaemons.py
347 $ $RUNTESTDIR/killdaemons.py
345 $ hg -R test serve -p $HGPORT -d --pid-file=hg3.pid -E error.log --config extensions.crash=${TESTDIR}/crashgetbundler.py
348 $ hg -R test serve -p $HGPORT -d --pid-file=hg3.pid -E error.log --config extensions.crash=${TESTDIR}/crashgetbundler.py
346 $ cat hg3.pid >> $DAEMON_PIDS
349 $ cat hg3.pid >> $DAEMON_PIDS
347 $ hg clone http://localhost:$HGPORT/ abort-clone
350 $ hg clone http://localhost:$HGPORT/ abort-clone
348 requesting all changes
351 requesting all changes
349 remote: abort: this is an exercise
352 remote: abort: this is an exercise
350 abort: pull failed on remote
353 abort: pull failed on remote
351 [255]
354 [255]
352 $ cat error.log
355 $ cat error.log
353
356
354 corrupt cookies file should yield a warning
357 corrupt cookies file should yield a warning
355
358
356 $ cat > $TESTTMP/cookies.txt << EOF
359 $ cat > $TESTTMP/cookies.txt << EOF
357 > bad format
360 > bad format
358 > EOF
361 > EOF
359
362
360 $ hg --config auth.cookiefile=$TESTTMP/cookies.txt id http://localhost:$HGPORT/
363 $ hg --config auth.cookiefile=$TESTTMP/cookies.txt id http://localhost:$HGPORT/
361 (error loading cookie file $TESTTMP/cookies.txt: '*/cookies.txt' does not look like a Netscape format cookies file; continuing without cookies) (glob)
364 (error loading cookie file $TESTTMP/cookies.txt: '*/cookies.txt' does not look like a Netscape format cookies file; continuing without cookies) (glob)
362 56f9bc90cce6
365 56f9bc90cce6
363
366
364 $ killdaemons.py
367 $ killdaemons.py
365
368
366 Create dummy authentication handler that looks for cookies. It doesn't do anything
369 Create dummy authentication handler that looks for cookies. It doesn't do anything
367 useful. It just raises an HTTP 500 with details about the Cookie request header.
370 useful. It just raises an HTTP 500 with details about the Cookie request header.
368 We raise HTTP 500 because its message is printed in the abort message.
371 We raise HTTP 500 because its message is printed in the abort message.
369
372
370 $ cat > cookieauth.py << EOF
373 $ cat > cookieauth.py << EOF
371 > from mercurial import util
374 > from mercurial import util
372 > from mercurial.hgweb import common
375 > from mercurial.hgweb import common
373 > def perform_authentication(hgweb, req, op):
376 > def perform_authentication(hgweb, req, op):
374 > cookie = req.env.get('HTTP_COOKIE')
377 > cookie = req.env.get('HTTP_COOKIE')
375 > if not cookie:
378 > if not cookie:
376 > raise common.ErrorResponse(common.HTTP_SERVER_ERROR, 'no-cookie')
379 > raise common.ErrorResponse(common.HTTP_SERVER_ERROR, 'no-cookie')
377 > raise common.ErrorResponse(common.HTTP_SERVER_ERROR, 'Cookie: %s' % cookie)
380 > raise common.ErrorResponse(common.HTTP_SERVER_ERROR, 'Cookie: %s' % cookie)
378 > def extsetup():
381 > def extsetup():
379 > common.permhooks.insert(0, perform_authentication)
382 > common.permhooks.insert(0, perform_authentication)
380 > EOF
383 > EOF
381
384
382 $ hg serve --config extensions.cookieauth=cookieauth.py -R test -p $HGPORT -d --pid-file=pid
385 $ hg serve --config extensions.cookieauth=cookieauth.py -R test -p $HGPORT -d --pid-file=pid
383 $ cat pid > $DAEMON_PIDS
386 $ cat pid > $DAEMON_PIDS
384
387
385 Request without cookie sent should fail due to lack of cookie
388 Request without cookie sent should fail due to lack of cookie
386
389
387 $ hg id http://localhost:$HGPORT
390 $ hg id http://localhost:$HGPORT
388 abort: HTTP Error 500: no-cookie
391 abort: HTTP Error 500: no-cookie
389 [255]
392 [255]
390
393
391 Populate a cookies file
394 Populate a cookies file
392
395
393 $ cat > cookies.txt << EOF
396 $ cat > cookies.txt << EOF
394 > # HTTP Cookie File
397 > # HTTP Cookie File
395 > # Expiration is 2030-01-01 at midnight
398 > # Expiration is 2030-01-01 at midnight
396 > .example.com TRUE / FALSE 1893456000 hgkey examplevalue
399 > .example.com TRUE / FALSE 1893456000 hgkey examplevalue
397 > EOF
400 > EOF
398
401
399 Should not send a cookie for another domain
402 Should not send a cookie for another domain
400
403
401 $ hg --config auth.cookiefile=cookies.txt id http://localhost:$HGPORT/
404 $ hg --config auth.cookiefile=cookies.txt id http://localhost:$HGPORT/
402 abort: HTTP Error 500: no-cookie
405 abort: HTTP Error 500: no-cookie
403 [255]
406 [255]
404
407
405 Add a cookie entry for our test server and verify it is sent
408 Add a cookie entry for our test server and verify it is sent
406
409
407 $ cat >> cookies.txt << EOF
410 $ cat >> cookies.txt << EOF
408 > localhost.local FALSE / FALSE 1893456000 hgkey localhostvalue
411 > localhost.local FALSE / FALSE 1893456000 hgkey localhostvalue
409 > EOF
412 > EOF
410
413
411 $ hg --config auth.cookiefile=cookies.txt id http://localhost:$HGPORT/
414 $ hg --config auth.cookiefile=cookies.txt id http://localhost:$HGPORT/
412 abort: HTTP Error 500: Cookie: hgkey=localhostvalue
415 abort: HTTP Error 500: Cookie: hgkey=localhostvalue
413 [255]
416 [255]
General Comments 0
You need to be logged in to leave comments. Login now