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