##// END OF EJS Templates
bundle2: part handler for processing .hgtags fnodes mappings...
Gregory Szorc -
r25401:d2920135 default
parent child Browse files
Show More
@@ -1,1362 +1,1384 b''
1 # bundle2.py - generic container format to transmit arbitrary data.
1 # bundle2.py - generic container format to transmit arbitrary data.
2 #
2 #
3 # Copyright 2013 Facebook, Inc.
3 # Copyright 2013 Facebook, Inc.
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 """Handling of the new bundle2 format
7 """Handling of the new bundle2 format
8
8
9 The goal of bundle2 is to act as an atomically packet to transmit a set of
9 The goal of bundle2 is to act as an atomically packet to transmit a set of
10 payloads in an application agnostic way. It consist in a sequence of "parts"
10 payloads in an application agnostic way. It consist in a sequence of "parts"
11 that will be handed to and processed by the application layer.
11 that will be handed to and processed by the application layer.
12
12
13
13
14 General format architecture
14 General format architecture
15 ===========================
15 ===========================
16
16
17 The format is architectured as follow
17 The format is architectured as follow
18
18
19 - magic string
19 - magic string
20 - stream level parameters
20 - stream level parameters
21 - payload parts (any number)
21 - payload parts (any number)
22 - end of stream marker.
22 - end of stream marker.
23
23
24 the Binary format
24 the Binary format
25 ============================
25 ============================
26
26
27 All numbers are unsigned and big-endian.
27 All numbers are unsigned and big-endian.
28
28
29 stream level parameters
29 stream level parameters
30 ------------------------
30 ------------------------
31
31
32 Binary format is as follow
32 Binary format is as follow
33
33
34 :params size: int32
34 :params size: int32
35
35
36 The total number of Bytes used by the parameters
36 The total number of Bytes used by the parameters
37
37
38 :params value: arbitrary number of Bytes
38 :params value: arbitrary number of Bytes
39
39
40 A blob of `params size` containing the serialized version of all stream level
40 A blob of `params size` containing the serialized version of all stream level
41 parameters.
41 parameters.
42
42
43 The blob contains a space separated list of parameters. Parameters with value
43 The blob contains a space separated list of parameters. Parameters with value
44 are stored in the form `<name>=<value>`. Both name and value are urlquoted.
44 are stored in the form `<name>=<value>`. Both name and value are urlquoted.
45
45
46 Empty name are obviously forbidden.
46 Empty name are obviously forbidden.
47
47
48 Name MUST start with a letter. If this first letter is lower case, the
48 Name MUST start with a letter. If this first letter is lower case, the
49 parameter is advisory and can be safely ignored. However when the first
49 parameter is advisory and can be safely ignored. However when the first
50 letter is capital, the parameter is mandatory and the bundling process MUST
50 letter is capital, the parameter is mandatory and the bundling process MUST
51 stop if he is not able to proceed it.
51 stop if he is not able to proceed it.
52
52
53 Stream parameters use a simple textual format for two main reasons:
53 Stream parameters use a simple textual format for two main reasons:
54
54
55 - Stream level parameters should remain simple and we want to discourage any
55 - Stream level parameters should remain simple and we want to discourage any
56 crazy usage.
56 crazy usage.
57 - Textual data allow easy human inspection of a bundle2 header in case of
57 - Textual data allow easy human inspection of a bundle2 header in case of
58 troubles.
58 troubles.
59
59
60 Any Applicative level options MUST go into a bundle2 part instead.
60 Any Applicative level options MUST go into a bundle2 part instead.
61
61
62 Payload part
62 Payload part
63 ------------------------
63 ------------------------
64
64
65 Binary format is as follow
65 Binary format is as follow
66
66
67 :header size: int32
67 :header size: int32
68
68
69 The total number of Bytes used by the part headers. When the header is empty
69 The total number of Bytes used by the part headers. When the header is empty
70 (size = 0) this is interpreted as the end of stream marker.
70 (size = 0) this is interpreted as the end of stream marker.
71
71
72 :header:
72 :header:
73
73
74 The header defines how to interpret the part. It contains two piece of
74 The header defines how to interpret the part. It contains two piece of
75 data: the part type, and the part parameters.
75 data: the part type, and the part parameters.
76
76
77 The part type is used to route an application level handler, that can
77 The part type is used to route an application level handler, that can
78 interpret payload.
78 interpret payload.
79
79
80 Part parameters are passed to the application level handler. They are
80 Part parameters are passed to the application level handler. They are
81 meant to convey information that will help the application level object to
81 meant to convey information that will help the application level object to
82 interpret the part payload.
82 interpret the part payload.
83
83
84 The binary format of the header is has follow
84 The binary format of the header is has follow
85
85
86 :typesize: (one byte)
86 :typesize: (one byte)
87
87
88 :parttype: alphanumerical part name (restricted to [a-zA-Z0-9_:-]*)
88 :parttype: alphanumerical part name (restricted to [a-zA-Z0-9_:-]*)
89
89
90 :partid: A 32bits integer (unique in the bundle) that can be used to refer
90 :partid: A 32bits integer (unique in the bundle) that can be used to refer
91 to this part.
91 to this part.
92
92
93 :parameters:
93 :parameters:
94
94
95 Part's parameter may have arbitrary content, the binary structure is::
95 Part's parameter may have arbitrary content, the binary structure is::
96
96
97 <mandatory-count><advisory-count><param-sizes><param-data>
97 <mandatory-count><advisory-count><param-sizes><param-data>
98
98
99 :mandatory-count: 1 byte, number of mandatory parameters
99 :mandatory-count: 1 byte, number of mandatory parameters
100
100
101 :advisory-count: 1 byte, number of advisory parameters
101 :advisory-count: 1 byte, number of advisory parameters
102
102
103 :param-sizes:
103 :param-sizes:
104
104
105 N couple of bytes, where N is the total number of parameters. Each
105 N couple of bytes, where N is the total number of parameters. Each
106 couple contains (<size-of-key>, <size-of-value) for one parameter.
106 couple contains (<size-of-key>, <size-of-value) for one parameter.
107
107
108 :param-data:
108 :param-data:
109
109
110 A blob of bytes from which each parameter key and value can be
110 A blob of bytes from which each parameter key and value can be
111 retrieved using the list of size couples stored in the previous
111 retrieved using the list of size couples stored in the previous
112 field.
112 field.
113
113
114 Mandatory parameters comes first, then the advisory ones.
114 Mandatory parameters comes first, then the advisory ones.
115
115
116 Each parameter's key MUST be unique within the part.
116 Each parameter's key MUST be unique within the part.
117
117
118 :payload:
118 :payload:
119
119
120 payload is a series of `<chunksize><chunkdata>`.
120 payload is a series of `<chunksize><chunkdata>`.
121
121
122 `chunksize` is an int32, `chunkdata` are plain bytes (as much as
122 `chunksize` is an int32, `chunkdata` are plain bytes (as much as
123 `chunksize` says)` The payload part is concluded by a zero size chunk.
123 `chunksize` says)` The payload part is concluded by a zero size chunk.
124
124
125 The current implementation always produces either zero or one chunk.
125 The current implementation always produces either zero or one chunk.
126 This is an implementation limitation that will ultimately be lifted.
126 This is an implementation limitation that will ultimately be lifted.
127
127
128 `chunksize` can be negative to trigger special case processing. No such
128 `chunksize` can be negative to trigger special case processing. No such
129 processing is in place yet.
129 processing is in place yet.
130
130
131 Bundle processing
131 Bundle processing
132 ============================
132 ============================
133
133
134 Each part is processed in order using a "part handler". Handler are registered
134 Each part is processed in order using a "part handler". Handler are registered
135 for a certain part type.
135 for a certain part type.
136
136
137 The matching of a part to its handler is case insensitive. The case of the
137 The matching of a part to its handler is case insensitive. The case of the
138 part type is used to know if a part is mandatory or advisory. If the Part type
138 part type is used to know if a part is mandatory or advisory. If the Part type
139 contains any uppercase char it is considered mandatory. When no handler is
139 contains any uppercase char it is considered mandatory. When no handler is
140 known for a Mandatory part, the process is aborted and an exception is raised.
140 known for a Mandatory part, the process is aborted and an exception is raised.
141 If the part is advisory and no handler is known, the part is ignored. When the
141 If the part is advisory and no handler is known, the part is ignored. When the
142 process is aborted, the full bundle is still read from the stream to keep the
142 process is aborted, the full bundle is still read from the stream to keep the
143 channel usable. But none of the part read from an abort are processed. In the
143 channel usable. But none of the part read from an abort are processed. In the
144 future, dropping the stream may become an option for channel we do not care to
144 future, dropping the stream may become an option for channel we do not care to
145 preserve.
145 preserve.
146 """
146 """
147
147
148 import errno
148 import errno
149 import sys
149 import sys
150 import util
150 import util
151 import struct
151 import struct
152 import urllib
152 import urllib
153 import string
153 import string
154 import obsolete
154 import obsolete
155 import pushkey
155 import pushkey
156 import url
156 import url
157 import re
157 import re
158
158
159 import changegroup, error
159 import changegroup, error, tags
160 from i18n import _
160 from i18n import _
161
161
162 _pack = struct.pack
162 _pack = struct.pack
163 _unpack = struct.unpack
163 _unpack = struct.unpack
164
164
165 _fstreamparamsize = '>i'
165 _fstreamparamsize = '>i'
166 _fpartheadersize = '>i'
166 _fpartheadersize = '>i'
167 _fparttypesize = '>B'
167 _fparttypesize = '>B'
168 _fpartid = '>I'
168 _fpartid = '>I'
169 _fpayloadsize = '>i'
169 _fpayloadsize = '>i'
170 _fpartparamcount = '>BB'
170 _fpartparamcount = '>BB'
171
171
172 preferedchunksize = 4096
172 preferedchunksize = 4096
173
173
174 _parttypeforbidden = re.compile('[^a-zA-Z0-9_:-]')
174 _parttypeforbidden = re.compile('[^a-zA-Z0-9_:-]')
175
175
176 def outdebug(ui, message):
176 def outdebug(ui, message):
177 """debug regarding output stream (bundling)"""
177 """debug regarding output stream (bundling)"""
178 if ui.configbool('devel', 'bundle2.debug', False):
178 if ui.configbool('devel', 'bundle2.debug', False):
179 ui.debug('bundle2-output: %s\n' % message)
179 ui.debug('bundle2-output: %s\n' % message)
180
180
181 def indebug(ui, message):
181 def indebug(ui, message):
182 """debug on input stream (unbundling)"""
182 """debug on input stream (unbundling)"""
183 if ui.configbool('devel', 'bundle2.debug', False):
183 if ui.configbool('devel', 'bundle2.debug', False):
184 ui.debug('bundle2-input: %s\n' % message)
184 ui.debug('bundle2-input: %s\n' % message)
185
185
186 def validateparttype(parttype):
186 def validateparttype(parttype):
187 """raise ValueError if a parttype contains invalid character"""
187 """raise ValueError if a parttype contains invalid character"""
188 if _parttypeforbidden.search(parttype):
188 if _parttypeforbidden.search(parttype):
189 raise ValueError(parttype)
189 raise ValueError(parttype)
190
190
191 def _makefpartparamsizes(nbparams):
191 def _makefpartparamsizes(nbparams):
192 """return a struct format to read part parameter sizes
192 """return a struct format to read part parameter sizes
193
193
194 The number parameters is variable so we need to build that format
194 The number parameters is variable so we need to build that format
195 dynamically.
195 dynamically.
196 """
196 """
197 return '>'+('BB'*nbparams)
197 return '>'+('BB'*nbparams)
198
198
199 parthandlermapping = {}
199 parthandlermapping = {}
200
200
201 def parthandler(parttype, params=()):
201 def parthandler(parttype, params=()):
202 """decorator that register a function as a bundle2 part handler
202 """decorator that register a function as a bundle2 part handler
203
203
204 eg::
204 eg::
205
205
206 @parthandler('myparttype', ('mandatory', 'param', 'handled'))
206 @parthandler('myparttype', ('mandatory', 'param', 'handled'))
207 def myparttypehandler(...):
207 def myparttypehandler(...):
208 '''process a part of type "my part".'''
208 '''process a part of type "my part".'''
209 ...
209 ...
210 """
210 """
211 validateparttype(parttype)
211 validateparttype(parttype)
212 def _decorator(func):
212 def _decorator(func):
213 lparttype = parttype.lower() # enforce lower case matching.
213 lparttype = parttype.lower() # enforce lower case matching.
214 assert lparttype not in parthandlermapping
214 assert lparttype not in parthandlermapping
215 parthandlermapping[lparttype] = func
215 parthandlermapping[lparttype] = func
216 func.params = frozenset(params)
216 func.params = frozenset(params)
217 return func
217 return func
218 return _decorator
218 return _decorator
219
219
220 class unbundlerecords(object):
220 class unbundlerecords(object):
221 """keep record of what happens during and unbundle
221 """keep record of what happens during and unbundle
222
222
223 New records are added using `records.add('cat', obj)`. Where 'cat' is a
223 New records are added using `records.add('cat', obj)`. Where 'cat' is a
224 category of record and obj is an arbitrary object.
224 category of record and obj is an arbitrary object.
225
225
226 `records['cat']` will return all entries of this category 'cat'.
226 `records['cat']` will return all entries of this category 'cat'.
227
227
228 Iterating on the object itself will yield `('category', obj)` tuples
228 Iterating on the object itself will yield `('category', obj)` tuples
229 for all entries.
229 for all entries.
230
230
231 All iterations happens in chronological order.
231 All iterations happens in chronological order.
232 """
232 """
233
233
234 def __init__(self):
234 def __init__(self):
235 self._categories = {}
235 self._categories = {}
236 self._sequences = []
236 self._sequences = []
237 self._replies = {}
237 self._replies = {}
238
238
239 def add(self, category, entry, inreplyto=None):
239 def add(self, category, entry, inreplyto=None):
240 """add a new record of a given category.
240 """add a new record of a given category.
241
241
242 The entry can then be retrieved in the list returned by
242 The entry can then be retrieved in the list returned by
243 self['category']."""
243 self['category']."""
244 self._categories.setdefault(category, []).append(entry)
244 self._categories.setdefault(category, []).append(entry)
245 self._sequences.append((category, entry))
245 self._sequences.append((category, entry))
246 if inreplyto is not None:
246 if inreplyto is not None:
247 self.getreplies(inreplyto).add(category, entry)
247 self.getreplies(inreplyto).add(category, entry)
248
248
249 def getreplies(self, partid):
249 def getreplies(self, partid):
250 """get the records that are replies to a specific part"""
250 """get the records that are replies to a specific part"""
251 return self._replies.setdefault(partid, unbundlerecords())
251 return self._replies.setdefault(partid, unbundlerecords())
252
252
253 def __getitem__(self, cat):
253 def __getitem__(self, cat):
254 return tuple(self._categories.get(cat, ()))
254 return tuple(self._categories.get(cat, ()))
255
255
256 def __iter__(self):
256 def __iter__(self):
257 return iter(self._sequences)
257 return iter(self._sequences)
258
258
259 def __len__(self):
259 def __len__(self):
260 return len(self._sequences)
260 return len(self._sequences)
261
261
262 def __nonzero__(self):
262 def __nonzero__(self):
263 return bool(self._sequences)
263 return bool(self._sequences)
264
264
265 class bundleoperation(object):
265 class bundleoperation(object):
266 """an object that represents a single bundling process
266 """an object that represents a single bundling process
267
267
268 Its purpose is to carry unbundle-related objects and states.
268 Its purpose is to carry unbundle-related objects and states.
269
269
270 A new object should be created at the beginning of each bundle processing.
270 A new object should be created at the beginning of each bundle processing.
271 The object is to be returned by the processing function.
271 The object is to be returned by the processing function.
272
272
273 The object has very little content now it will ultimately contain:
273 The object has very little content now it will ultimately contain:
274 * an access to the repo the bundle is applied to,
274 * an access to the repo the bundle is applied to,
275 * a ui object,
275 * a ui object,
276 * a way to retrieve a transaction to add changes to the repo,
276 * a way to retrieve a transaction to add changes to the repo,
277 * a way to record the result of processing each part,
277 * a way to record the result of processing each part,
278 * a way to construct a bundle response when applicable.
278 * a way to construct a bundle response when applicable.
279 """
279 """
280
280
281 def __init__(self, repo, transactiongetter, captureoutput=True):
281 def __init__(self, repo, transactiongetter, captureoutput=True):
282 self.repo = repo
282 self.repo = repo
283 self.ui = repo.ui
283 self.ui = repo.ui
284 self.records = unbundlerecords()
284 self.records = unbundlerecords()
285 self.gettransaction = transactiongetter
285 self.gettransaction = transactiongetter
286 self.reply = None
286 self.reply = None
287 self.captureoutput = captureoutput
287 self.captureoutput = captureoutput
288
288
289 class TransactionUnavailable(RuntimeError):
289 class TransactionUnavailable(RuntimeError):
290 pass
290 pass
291
291
292 def _notransaction():
292 def _notransaction():
293 """default method to get a transaction while processing a bundle
293 """default method to get a transaction while processing a bundle
294
294
295 Raise an exception to highlight the fact that no transaction was expected
295 Raise an exception to highlight the fact that no transaction was expected
296 to be created"""
296 to be created"""
297 raise TransactionUnavailable()
297 raise TransactionUnavailable()
298
298
299 def processbundle(repo, unbundler, transactiongetter=None, op=None):
299 def processbundle(repo, unbundler, transactiongetter=None, op=None):
300 """This function process a bundle, apply effect to/from a repo
300 """This function process a bundle, apply effect to/from a repo
301
301
302 It iterates over each part then searches for and uses the proper handling
302 It iterates over each part then searches for and uses the proper handling
303 code to process the part. Parts are processed in order.
303 code to process the part. Parts are processed in order.
304
304
305 This is very early version of this function that will be strongly reworked
305 This is very early version of this function that will be strongly reworked
306 before final usage.
306 before final usage.
307
307
308 Unknown Mandatory part will abort the process.
308 Unknown Mandatory part will abort the process.
309
309
310 It is temporarily possible to provide a prebuilt bundleoperation to the
310 It is temporarily possible to provide a prebuilt bundleoperation to the
311 function. This is used to ensure output is properly propagated in case of
311 function. This is used to ensure output is properly propagated in case of
312 an error during the unbundling. This output capturing part will likely be
312 an error during the unbundling. This output capturing part will likely be
313 reworked and this ability will probably go away in the process.
313 reworked and this ability will probably go away in the process.
314 """
314 """
315 if op is None:
315 if op is None:
316 if transactiongetter is None:
316 if transactiongetter is None:
317 transactiongetter = _notransaction
317 transactiongetter = _notransaction
318 op = bundleoperation(repo, transactiongetter)
318 op = bundleoperation(repo, transactiongetter)
319 # todo:
319 # todo:
320 # - replace this is a init function soon.
320 # - replace this is a init function soon.
321 # - exception catching
321 # - exception catching
322 unbundler.params
322 unbundler.params
323 if repo.ui.debugflag:
323 if repo.ui.debugflag:
324 msg = ['bundle2-input-bundle:']
324 msg = ['bundle2-input-bundle:']
325 if unbundler.params:
325 if unbundler.params:
326 msg.append(' %i params')
326 msg.append(' %i params')
327 if op.gettransaction is None:
327 if op.gettransaction is None:
328 msg.append(' no-transaction')
328 msg.append(' no-transaction')
329 else:
329 else:
330 msg.append(' with-transaction')
330 msg.append(' with-transaction')
331 msg.append('\n')
331 msg.append('\n')
332 repo.ui.debug(''.join(msg))
332 repo.ui.debug(''.join(msg))
333 iterparts = enumerate(unbundler.iterparts())
333 iterparts = enumerate(unbundler.iterparts())
334 part = None
334 part = None
335 nbpart = 0
335 nbpart = 0
336 try:
336 try:
337 for nbpart, part in iterparts:
337 for nbpart, part in iterparts:
338 _processpart(op, part)
338 _processpart(op, part)
339 except BaseException, exc:
339 except BaseException, exc:
340 for nbpart, part in iterparts:
340 for nbpart, part in iterparts:
341 # consume the bundle content
341 # consume the bundle content
342 part.seek(0, 2)
342 part.seek(0, 2)
343 # Small hack to let caller code distinguish exceptions from bundle2
343 # Small hack to let caller code distinguish exceptions from bundle2
344 # processing from processing the old format. This is mostly
344 # processing from processing the old format. This is mostly
345 # needed to handle different return codes to unbundle according to the
345 # needed to handle different return codes to unbundle according to the
346 # type of bundle. We should probably clean up or drop this return code
346 # type of bundle. We should probably clean up or drop this return code
347 # craziness in a future version.
347 # craziness in a future version.
348 exc.duringunbundle2 = True
348 exc.duringunbundle2 = True
349 salvaged = []
349 salvaged = []
350 if op.reply is not None:
350 if op.reply is not None:
351 salvaged = op.reply.salvageoutput()
351 salvaged = op.reply.salvageoutput()
352 exc._bundle2salvagedoutput = salvaged
352 exc._bundle2salvagedoutput = salvaged
353 raise
353 raise
354 finally:
354 finally:
355 repo.ui.debug('bundle2-input-bundle: %i parts total\n' % nbpart)
355 repo.ui.debug('bundle2-input-bundle: %i parts total\n' % nbpart)
356
356
357 return op
357 return op
358
358
359 def _processpart(op, part):
359 def _processpart(op, part):
360 """process a single part from a bundle
360 """process a single part from a bundle
361
361
362 The part is guaranteed to have been fully consumed when the function exits
362 The part is guaranteed to have been fully consumed when the function exits
363 (even if an exception is raised)."""
363 (even if an exception is raised)."""
364 status = 'unknown' # used by debug output
364 status = 'unknown' # used by debug output
365 try:
365 try:
366 try:
366 try:
367 handler = parthandlermapping.get(part.type)
367 handler = parthandlermapping.get(part.type)
368 if handler is None:
368 if handler is None:
369 status = 'unsupported-type'
369 status = 'unsupported-type'
370 raise error.UnsupportedPartError(parttype=part.type)
370 raise error.UnsupportedPartError(parttype=part.type)
371 indebug(op.ui, 'found a handler for part %r' % part.type)
371 indebug(op.ui, 'found a handler for part %r' % part.type)
372 unknownparams = part.mandatorykeys - handler.params
372 unknownparams = part.mandatorykeys - handler.params
373 if unknownparams:
373 if unknownparams:
374 unknownparams = list(unknownparams)
374 unknownparams = list(unknownparams)
375 unknownparams.sort()
375 unknownparams.sort()
376 status = 'unsupported-params (%s)' % unknownparams
376 status = 'unsupported-params (%s)' % unknownparams
377 raise error.UnsupportedPartError(parttype=part.type,
377 raise error.UnsupportedPartError(parttype=part.type,
378 params=unknownparams)
378 params=unknownparams)
379 status = 'supported'
379 status = 'supported'
380 except error.UnsupportedPartError, exc:
380 except error.UnsupportedPartError, exc:
381 if part.mandatory: # mandatory parts
381 if part.mandatory: # mandatory parts
382 raise
382 raise
383 indebug(op.ui, 'ignoring unsupported advisory part %s' % exc)
383 indebug(op.ui, 'ignoring unsupported advisory part %s' % exc)
384 return # skip to part processing
384 return # skip to part processing
385 finally:
385 finally:
386 if op.ui.debugflag:
386 if op.ui.debugflag:
387 msg = ['bundle2-input-part: "%s"' % part.type]
387 msg = ['bundle2-input-part: "%s"' % part.type]
388 if not part.mandatory:
388 if not part.mandatory:
389 msg.append(' (advisory)')
389 msg.append(' (advisory)')
390 nbmp = len(part.mandatorykeys)
390 nbmp = len(part.mandatorykeys)
391 nbap = len(part.params) - nbmp
391 nbap = len(part.params) - nbmp
392 if nbmp or nbap:
392 if nbmp or nbap:
393 msg.append(' (params:')
393 msg.append(' (params:')
394 if nbmp:
394 if nbmp:
395 msg.append(' %i mandatory' % nbmp)
395 msg.append(' %i mandatory' % nbmp)
396 if nbap:
396 if nbap:
397 msg.append(' %i advisory' % nbmp)
397 msg.append(' %i advisory' % nbmp)
398 msg.append(')')
398 msg.append(')')
399 msg.append(' %s\n' % status)
399 msg.append(' %s\n' % status)
400 op.ui.debug(''.join(msg))
400 op.ui.debug(''.join(msg))
401
401
402 # handler is called outside the above try block so that we don't
402 # handler is called outside the above try block so that we don't
403 # risk catching KeyErrors from anything other than the
403 # risk catching KeyErrors from anything other than the
404 # parthandlermapping lookup (any KeyError raised by handler()
404 # parthandlermapping lookup (any KeyError raised by handler()
405 # itself represents a defect of a different variety).
405 # itself represents a defect of a different variety).
406 output = None
406 output = None
407 if op.captureoutput and op.reply is not None:
407 if op.captureoutput and op.reply is not None:
408 op.ui.pushbuffer(error=True, subproc=True)
408 op.ui.pushbuffer(error=True, subproc=True)
409 output = ''
409 output = ''
410 try:
410 try:
411 handler(op, part)
411 handler(op, part)
412 finally:
412 finally:
413 if output is not None:
413 if output is not None:
414 output = op.ui.popbuffer()
414 output = op.ui.popbuffer()
415 if output:
415 if output:
416 outpart = op.reply.newpart('output', data=output,
416 outpart = op.reply.newpart('output', data=output,
417 mandatory=False)
417 mandatory=False)
418 outpart.addparam('in-reply-to', str(part.id), mandatory=False)
418 outpart.addparam('in-reply-to', str(part.id), mandatory=False)
419 finally:
419 finally:
420 # consume the part content to not corrupt the stream.
420 # consume the part content to not corrupt the stream.
421 part.seek(0, 2)
421 part.seek(0, 2)
422
422
423
423
424 def decodecaps(blob):
424 def decodecaps(blob):
425 """decode a bundle2 caps bytes blob into a dictionary
425 """decode a bundle2 caps bytes blob into a dictionary
426
426
427 The blob is a list of capabilities (one per line)
427 The blob is a list of capabilities (one per line)
428 Capabilities may have values using a line of the form::
428 Capabilities may have values using a line of the form::
429
429
430 capability=value1,value2,value3
430 capability=value1,value2,value3
431
431
432 The values are always a list."""
432 The values are always a list."""
433 caps = {}
433 caps = {}
434 for line in blob.splitlines():
434 for line in blob.splitlines():
435 if not line:
435 if not line:
436 continue
436 continue
437 if '=' not in line:
437 if '=' not in line:
438 key, vals = line, ()
438 key, vals = line, ()
439 else:
439 else:
440 key, vals = line.split('=', 1)
440 key, vals = line.split('=', 1)
441 vals = vals.split(',')
441 vals = vals.split(',')
442 key = urllib.unquote(key)
442 key = urllib.unquote(key)
443 vals = [urllib.unquote(v) for v in vals]
443 vals = [urllib.unquote(v) for v in vals]
444 caps[key] = vals
444 caps[key] = vals
445 return caps
445 return caps
446
446
447 def encodecaps(caps):
447 def encodecaps(caps):
448 """encode a bundle2 caps dictionary into a bytes blob"""
448 """encode a bundle2 caps dictionary into a bytes blob"""
449 chunks = []
449 chunks = []
450 for ca in sorted(caps):
450 for ca in sorted(caps):
451 vals = caps[ca]
451 vals = caps[ca]
452 ca = urllib.quote(ca)
452 ca = urllib.quote(ca)
453 vals = [urllib.quote(v) for v in vals]
453 vals = [urllib.quote(v) for v in vals]
454 if vals:
454 if vals:
455 ca = "%s=%s" % (ca, ','.join(vals))
455 ca = "%s=%s" % (ca, ','.join(vals))
456 chunks.append(ca)
456 chunks.append(ca)
457 return '\n'.join(chunks)
457 return '\n'.join(chunks)
458
458
459 class bundle20(object):
459 class bundle20(object):
460 """represent an outgoing bundle2 container
460 """represent an outgoing bundle2 container
461
461
462 Use the `addparam` method to add stream level parameter. and `newpart` to
462 Use the `addparam` method to add stream level parameter. and `newpart` to
463 populate it. Then call `getchunks` to retrieve all the binary chunks of
463 populate it. Then call `getchunks` to retrieve all the binary chunks of
464 data that compose the bundle2 container."""
464 data that compose the bundle2 container."""
465
465
466 _magicstring = 'HG20'
466 _magicstring = 'HG20'
467
467
468 def __init__(self, ui, capabilities=()):
468 def __init__(self, ui, capabilities=()):
469 self.ui = ui
469 self.ui = ui
470 self._params = []
470 self._params = []
471 self._parts = []
471 self._parts = []
472 self.capabilities = dict(capabilities)
472 self.capabilities = dict(capabilities)
473
473
474 @property
474 @property
475 def nbparts(self):
475 def nbparts(self):
476 """total number of parts added to the bundler"""
476 """total number of parts added to the bundler"""
477 return len(self._parts)
477 return len(self._parts)
478
478
479 # methods used to defines the bundle2 content
479 # methods used to defines the bundle2 content
480 def addparam(self, name, value=None):
480 def addparam(self, name, value=None):
481 """add a stream level parameter"""
481 """add a stream level parameter"""
482 if not name:
482 if not name:
483 raise ValueError('empty parameter name')
483 raise ValueError('empty parameter name')
484 if name[0] not in string.letters:
484 if name[0] not in string.letters:
485 raise ValueError('non letter first character: %r' % name)
485 raise ValueError('non letter first character: %r' % name)
486 self._params.append((name, value))
486 self._params.append((name, value))
487
487
488 def addpart(self, part):
488 def addpart(self, part):
489 """add a new part to the bundle2 container
489 """add a new part to the bundle2 container
490
490
491 Parts contains the actual applicative payload."""
491 Parts contains the actual applicative payload."""
492 assert part.id is None
492 assert part.id is None
493 part.id = len(self._parts) # very cheap counter
493 part.id = len(self._parts) # very cheap counter
494 self._parts.append(part)
494 self._parts.append(part)
495
495
496 def newpart(self, typeid, *args, **kwargs):
496 def newpart(self, typeid, *args, **kwargs):
497 """create a new part and add it to the containers
497 """create a new part and add it to the containers
498
498
499 As the part is directly added to the containers. For now, this means
499 As the part is directly added to the containers. For now, this means
500 that any failure to properly initialize the part after calling
500 that any failure to properly initialize the part after calling
501 ``newpart`` should result in a failure of the whole bundling process.
501 ``newpart`` should result in a failure of the whole bundling process.
502
502
503 You can still fall back to manually create and add if you need better
503 You can still fall back to manually create and add if you need better
504 control."""
504 control."""
505 part = bundlepart(typeid, *args, **kwargs)
505 part = bundlepart(typeid, *args, **kwargs)
506 self.addpart(part)
506 self.addpart(part)
507 return part
507 return part
508
508
509 # methods used to generate the bundle2 stream
509 # methods used to generate the bundle2 stream
510 def getchunks(self):
510 def getchunks(self):
511 if self.ui.debugflag:
511 if self.ui.debugflag:
512 msg = ['bundle2-output-bundle: "%s",' % self._magicstring]
512 msg = ['bundle2-output-bundle: "%s",' % self._magicstring]
513 if self._params:
513 if self._params:
514 msg.append(' (%i params)' % len(self._params))
514 msg.append(' (%i params)' % len(self._params))
515 msg.append(' %i parts total\n' % len(self._parts))
515 msg.append(' %i parts total\n' % len(self._parts))
516 self.ui.debug(''.join(msg))
516 self.ui.debug(''.join(msg))
517 outdebug(self.ui, 'start emission of %s stream' % self._magicstring)
517 outdebug(self.ui, 'start emission of %s stream' % self._magicstring)
518 yield self._magicstring
518 yield self._magicstring
519 param = self._paramchunk()
519 param = self._paramchunk()
520 outdebug(self.ui, 'bundle parameter: %s' % param)
520 outdebug(self.ui, 'bundle parameter: %s' % param)
521 yield _pack(_fstreamparamsize, len(param))
521 yield _pack(_fstreamparamsize, len(param))
522 if param:
522 if param:
523 yield param
523 yield param
524
524
525 outdebug(self.ui, 'start of parts')
525 outdebug(self.ui, 'start of parts')
526 for part in self._parts:
526 for part in self._parts:
527 outdebug(self.ui, 'bundle part: "%s"' % part.type)
527 outdebug(self.ui, 'bundle part: "%s"' % part.type)
528 for chunk in part.getchunks(ui=self.ui):
528 for chunk in part.getchunks(ui=self.ui):
529 yield chunk
529 yield chunk
530 outdebug(self.ui, 'end of bundle')
530 outdebug(self.ui, 'end of bundle')
531 yield _pack(_fpartheadersize, 0)
531 yield _pack(_fpartheadersize, 0)
532
532
533 def _paramchunk(self):
533 def _paramchunk(self):
534 """return a encoded version of all stream parameters"""
534 """return a encoded version of all stream parameters"""
535 blocks = []
535 blocks = []
536 for par, value in self._params:
536 for par, value in self._params:
537 par = urllib.quote(par)
537 par = urllib.quote(par)
538 if value is not None:
538 if value is not None:
539 value = urllib.quote(value)
539 value = urllib.quote(value)
540 par = '%s=%s' % (par, value)
540 par = '%s=%s' % (par, value)
541 blocks.append(par)
541 blocks.append(par)
542 return ' '.join(blocks)
542 return ' '.join(blocks)
543
543
544 def salvageoutput(self):
544 def salvageoutput(self):
545 """return a list with a copy of all output parts in the bundle
545 """return a list with a copy of all output parts in the bundle
546
546
547 This is meant to be used during error handling to make sure we preserve
547 This is meant to be used during error handling to make sure we preserve
548 server output"""
548 server output"""
549 salvaged = []
549 salvaged = []
550 for part in self._parts:
550 for part in self._parts:
551 if part.type.startswith('output'):
551 if part.type.startswith('output'):
552 salvaged.append(part.copy())
552 salvaged.append(part.copy())
553 return salvaged
553 return salvaged
554
554
555
555
556 class unpackermixin(object):
556 class unpackermixin(object):
557 """A mixin to extract bytes and struct data from a stream"""
557 """A mixin to extract bytes and struct data from a stream"""
558
558
559 def __init__(self, fp):
559 def __init__(self, fp):
560 self._fp = fp
560 self._fp = fp
561 self._seekable = (util.safehasattr(fp, 'seek') and
561 self._seekable = (util.safehasattr(fp, 'seek') and
562 util.safehasattr(fp, 'tell'))
562 util.safehasattr(fp, 'tell'))
563
563
564 def _unpack(self, format):
564 def _unpack(self, format):
565 """unpack this struct format from the stream"""
565 """unpack this struct format from the stream"""
566 data = self._readexact(struct.calcsize(format))
566 data = self._readexact(struct.calcsize(format))
567 return _unpack(format, data)
567 return _unpack(format, data)
568
568
569 def _readexact(self, size):
569 def _readexact(self, size):
570 """read exactly <size> bytes from the stream"""
570 """read exactly <size> bytes from the stream"""
571 return changegroup.readexactly(self._fp, size)
571 return changegroup.readexactly(self._fp, size)
572
572
573 def seek(self, offset, whence=0):
573 def seek(self, offset, whence=0):
574 """move the underlying file pointer"""
574 """move the underlying file pointer"""
575 if self._seekable:
575 if self._seekable:
576 return self._fp.seek(offset, whence)
576 return self._fp.seek(offset, whence)
577 else:
577 else:
578 raise NotImplementedError(_('File pointer is not seekable'))
578 raise NotImplementedError(_('File pointer is not seekable'))
579
579
580 def tell(self):
580 def tell(self):
581 """return the file offset, or None if file is not seekable"""
581 """return the file offset, or None if file is not seekable"""
582 if self._seekable:
582 if self._seekable:
583 try:
583 try:
584 return self._fp.tell()
584 return self._fp.tell()
585 except IOError, e:
585 except IOError, e:
586 if e.errno == errno.ESPIPE:
586 if e.errno == errno.ESPIPE:
587 self._seekable = False
587 self._seekable = False
588 else:
588 else:
589 raise
589 raise
590 return None
590 return None
591
591
592 def close(self):
592 def close(self):
593 """close underlying file"""
593 """close underlying file"""
594 if util.safehasattr(self._fp, 'close'):
594 if util.safehasattr(self._fp, 'close'):
595 return self._fp.close()
595 return self._fp.close()
596
596
597 def getunbundler(ui, fp, header=None):
597 def getunbundler(ui, fp, header=None):
598 """return a valid unbundler object for a given header"""
598 """return a valid unbundler object for a given header"""
599 if header is None:
599 if header is None:
600 header = changegroup.readexactly(fp, 4)
600 header = changegroup.readexactly(fp, 4)
601 magic, version = header[0:2], header[2:4]
601 magic, version = header[0:2], header[2:4]
602 if magic != 'HG':
602 if magic != 'HG':
603 raise util.Abort(_('not a Mercurial bundle'))
603 raise util.Abort(_('not a Mercurial bundle'))
604 unbundlerclass = formatmap.get(version)
604 unbundlerclass = formatmap.get(version)
605 if unbundlerclass is None:
605 if unbundlerclass is None:
606 raise util.Abort(_('unknown bundle version %s') % version)
606 raise util.Abort(_('unknown bundle version %s') % version)
607 unbundler = unbundlerclass(ui, fp)
607 unbundler = unbundlerclass(ui, fp)
608 indebug(ui, 'start processing of %s stream' % header)
608 indebug(ui, 'start processing of %s stream' % header)
609 return unbundler
609 return unbundler
610
610
611 class unbundle20(unpackermixin):
611 class unbundle20(unpackermixin):
612 """interpret a bundle2 stream
612 """interpret a bundle2 stream
613
613
614 This class is fed with a binary stream and yields parts through its
614 This class is fed with a binary stream and yields parts through its
615 `iterparts` methods."""
615 `iterparts` methods."""
616
616
617 def __init__(self, ui, fp):
617 def __init__(self, ui, fp):
618 """If header is specified, we do not read it out of the stream."""
618 """If header is specified, we do not read it out of the stream."""
619 self.ui = ui
619 self.ui = ui
620 super(unbundle20, self).__init__(fp)
620 super(unbundle20, self).__init__(fp)
621
621
622 @util.propertycache
622 @util.propertycache
623 def params(self):
623 def params(self):
624 """dictionary of stream level parameters"""
624 """dictionary of stream level parameters"""
625 indebug(self.ui, 'reading bundle2 stream parameters')
625 indebug(self.ui, 'reading bundle2 stream parameters')
626 params = {}
626 params = {}
627 paramssize = self._unpack(_fstreamparamsize)[0]
627 paramssize = self._unpack(_fstreamparamsize)[0]
628 if paramssize < 0:
628 if paramssize < 0:
629 raise error.BundleValueError('negative bundle param size: %i'
629 raise error.BundleValueError('negative bundle param size: %i'
630 % paramssize)
630 % paramssize)
631 if paramssize:
631 if paramssize:
632 for p in self._readexact(paramssize).split(' '):
632 for p in self._readexact(paramssize).split(' '):
633 p = p.split('=', 1)
633 p = p.split('=', 1)
634 p = [urllib.unquote(i) for i in p]
634 p = [urllib.unquote(i) for i in p]
635 if len(p) < 2:
635 if len(p) < 2:
636 p.append(None)
636 p.append(None)
637 self._processparam(*p)
637 self._processparam(*p)
638 params[p[0]] = p[1]
638 params[p[0]] = p[1]
639 return params
639 return params
640
640
641 def _processparam(self, name, value):
641 def _processparam(self, name, value):
642 """process a parameter, applying its effect if needed
642 """process a parameter, applying its effect if needed
643
643
644 Parameter starting with a lower case letter are advisory and will be
644 Parameter starting with a lower case letter are advisory and will be
645 ignored when unknown. Those starting with an upper case letter are
645 ignored when unknown. Those starting with an upper case letter are
646 mandatory and will this function will raise a KeyError when unknown.
646 mandatory and will this function will raise a KeyError when unknown.
647
647
648 Note: no option are currently supported. Any input will be either
648 Note: no option are currently supported. Any input will be either
649 ignored or failing.
649 ignored or failing.
650 """
650 """
651 if not name:
651 if not name:
652 raise ValueError('empty parameter name')
652 raise ValueError('empty parameter name')
653 if name[0] not in string.letters:
653 if name[0] not in string.letters:
654 raise ValueError('non letter first character: %r' % name)
654 raise ValueError('non letter first character: %r' % name)
655 # Some logic will be later added here to try to process the option for
655 # Some logic will be later added here to try to process the option for
656 # a dict of known parameter.
656 # a dict of known parameter.
657 if name[0].islower():
657 if name[0].islower():
658 indebug(self.ui, "ignoring unknown parameter %r" % name)
658 indebug(self.ui, "ignoring unknown parameter %r" % name)
659 else:
659 else:
660 raise error.UnsupportedPartError(params=(name,))
660 raise error.UnsupportedPartError(params=(name,))
661
661
662
662
663 def iterparts(self):
663 def iterparts(self):
664 """yield all parts contained in the stream"""
664 """yield all parts contained in the stream"""
665 # make sure param have been loaded
665 # make sure param have been loaded
666 self.params
666 self.params
667 indebug(self.ui, 'start extraction of bundle2 parts')
667 indebug(self.ui, 'start extraction of bundle2 parts')
668 headerblock = self._readpartheader()
668 headerblock = self._readpartheader()
669 while headerblock is not None:
669 while headerblock is not None:
670 part = unbundlepart(self.ui, headerblock, self._fp)
670 part = unbundlepart(self.ui, headerblock, self._fp)
671 yield part
671 yield part
672 part.seek(0, 2)
672 part.seek(0, 2)
673 headerblock = self._readpartheader()
673 headerblock = self._readpartheader()
674 indebug(self.ui, 'end of bundle2 stream')
674 indebug(self.ui, 'end of bundle2 stream')
675
675
676 def _readpartheader(self):
676 def _readpartheader(self):
677 """reads a part header size and return the bytes blob
677 """reads a part header size and return the bytes blob
678
678
679 returns None if empty"""
679 returns None if empty"""
680 headersize = self._unpack(_fpartheadersize)[0]
680 headersize = self._unpack(_fpartheadersize)[0]
681 if headersize < 0:
681 if headersize < 0:
682 raise error.BundleValueError('negative part header size: %i'
682 raise error.BundleValueError('negative part header size: %i'
683 % headersize)
683 % headersize)
684 indebug(self.ui, 'part header size: %i' % headersize)
684 indebug(self.ui, 'part header size: %i' % headersize)
685 if headersize:
685 if headersize:
686 return self._readexact(headersize)
686 return self._readexact(headersize)
687 return None
687 return None
688
688
689 def compressed(self):
689 def compressed(self):
690 return False
690 return False
691
691
692 formatmap = {'20': unbundle20}
692 formatmap = {'20': unbundle20}
693
693
694 class bundlepart(object):
694 class bundlepart(object):
695 """A bundle2 part contains application level payload
695 """A bundle2 part contains application level payload
696
696
697 The part `type` is used to route the part to the application level
697 The part `type` is used to route the part to the application level
698 handler.
698 handler.
699
699
700 The part payload is contained in ``part.data``. It could be raw bytes or a
700 The part payload is contained in ``part.data``. It could be raw bytes or a
701 generator of byte chunks.
701 generator of byte chunks.
702
702
703 You can add parameters to the part using the ``addparam`` method.
703 You can add parameters to the part using the ``addparam`` method.
704 Parameters can be either mandatory (default) or advisory. Remote side
704 Parameters can be either mandatory (default) or advisory. Remote side
705 should be able to safely ignore the advisory ones.
705 should be able to safely ignore the advisory ones.
706
706
707 Both data and parameters cannot be modified after the generation has begun.
707 Both data and parameters cannot be modified after the generation has begun.
708 """
708 """
709
709
710 def __init__(self, parttype, mandatoryparams=(), advisoryparams=(),
710 def __init__(self, parttype, mandatoryparams=(), advisoryparams=(),
711 data='', mandatory=True):
711 data='', mandatory=True):
712 validateparttype(parttype)
712 validateparttype(parttype)
713 self.id = None
713 self.id = None
714 self.type = parttype
714 self.type = parttype
715 self._data = data
715 self._data = data
716 self._mandatoryparams = list(mandatoryparams)
716 self._mandatoryparams = list(mandatoryparams)
717 self._advisoryparams = list(advisoryparams)
717 self._advisoryparams = list(advisoryparams)
718 # checking for duplicated entries
718 # checking for duplicated entries
719 self._seenparams = set()
719 self._seenparams = set()
720 for pname, __ in self._mandatoryparams + self._advisoryparams:
720 for pname, __ in self._mandatoryparams + self._advisoryparams:
721 if pname in self._seenparams:
721 if pname in self._seenparams:
722 raise RuntimeError('duplicated params: %s' % pname)
722 raise RuntimeError('duplicated params: %s' % pname)
723 self._seenparams.add(pname)
723 self._seenparams.add(pname)
724 # status of the part's generation:
724 # status of the part's generation:
725 # - None: not started,
725 # - None: not started,
726 # - False: currently generated,
726 # - False: currently generated,
727 # - True: generation done.
727 # - True: generation done.
728 self._generated = None
728 self._generated = None
729 self.mandatory = mandatory
729 self.mandatory = mandatory
730
730
731 def copy(self):
731 def copy(self):
732 """return a copy of the part
732 """return a copy of the part
733
733
734 The new part have the very same content but no partid assigned yet.
734 The new part have the very same content but no partid assigned yet.
735 Parts with generated data cannot be copied."""
735 Parts with generated data cannot be copied."""
736 assert not util.safehasattr(self.data, 'next')
736 assert not util.safehasattr(self.data, 'next')
737 return self.__class__(self.type, self._mandatoryparams,
737 return self.__class__(self.type, self._mandatoryparams,
738 self._advisoryparams, self._data, self.mandatory)
738 self._advisoryparams, self._data, self.mandatory)
739
739
740 # methods used to defines the part content
740 # methods used to defines the part content
741 def __setdata(self, data):
741 def __setdata(self, data):
742 if self._generated is not None:
742 if self._generated is not None:
743 raise error.ReadOnlyPartError('part is being generated')
743 raise error.ReadOnlyPartError('part is being generated')
744 self._data = data
744 self._data = data
745 def __getdata(self):
745 def __getdata(self):
746 return self._data
746 return self._data
747 data = property(__getdata, __setdata)
747 data = property(__getdata, __setdata)
748
748
749 @property
749 @property
750 def mandatoryparams(self):
750 def mandatoryparams(self):
751 # make it an immutable tuple to force people through ``addparam``
751 # make it an immutable tuple to force people through ``addparam``
752 return tuple(self._mandatoryparams)
752 return tuple(self._mandatoryparams)
753
753
754 @property
754 @property
755 def advisoryparams(self):
755 def advisoryparams(self):
756 # make it an immutable tuple to force people through ``addparam``
756 # make it an immutable tuple to force people through ``addparam``
757 return tuple(self._advisoryparams)
757 return tuple(self._advisoryparams)
758
758
759 def addparam(self, name, value='', mandatory=True):
759 def addparam(self, name, value='', mandatory=True):
760 if self._generated is not None:
760 if self._generated is not None:
761 raise error.ReadOnlyPartError('part is being generated')
761 raise error.ReadOnlyPartError('part is being generated')
762 if name in self._seenparams:
762 if name in self._seenparams:
763 raise ValueError('duplicated params: %s' % name)
763 raise ValueError('duplicated params: %s' % name)
764 self._seenparams.add(name)
764 self._seenparams.add(name)
765 params = self._advisoryparams
765 params = self._advisoryparams
766 if mandatory:
766 if mandatory:
767 params = self._mandatoryparams
767 params = self._mandatoryparams
768 params.append((name, value))
768 params.append((name, value))
769
769
770 # methods used to generates the bundle2 stream
770 # methods used to generates the bundle2 stream
771 def getchunks(self, ui):
771 def getchunks(self, ui):
772 if self._generated is not None:
772 if self._generated is not None:
773 raise RuntimeError('part can only be consumed once')
773 raise RuntimeError('part can only be consumed once')
774 self._generated = False
774 self._generated = False
775
775
776 if ui.debugflag:
776 if ui.debugflag:
777 msg = ['bundle2-output-part: "%s"' % self.type]
777 msg = ['bundle2-output-part: "%s"' % self.type]
778 if not self.mandatory:
778 if not self.mandatory:
779 msg.append(' (advisory)')
779 msg.append(' (advisory)')
780 nbmp = len(self.mandatoryparams)
780 nbmp = len(self.mandatoryparams)
781 nbap = len(self.advisoryparams)
781 nbap = len(self.advisoryparams)
782 if nbmp or nbap:
782 if nbmp or nbap:
783 msg.append(' (params:')
783 msg.append(' (params:')
784 if nbmp:
784 if nbmp:
785 msg.append(' %i mandatory' % nbmp)
785 msg.append(' %i mandatory' % nbmp)
786 if nbap:
786 if nbap:
787 msg.append(' %i advisory' % nbmp)
787 msg.append(' %i advisory' % nbmp)
788 msg.append(')')
788 msg.append(')')
789 if not self.data:
789 if not self.data:
790 msg.append(' empty payload')
790 msg.append(' empty payload')
791 elif util.safehasattr(self.data, 'next'):
791 elif util.safehasattr(self.data, 'next'):
792 msg.append(' streamed payload')
792 msg.append(' streamed payload')
793 else:
793 else:
794 msg.append(' %i bytes payload' % len(self.data))
794 msg.append(' %i bytes payload' % len(self.data))
795 msg.append('\n')
795 msg.append('\n')
796 ui.debug(''.join(msg))
796 ui.debug(''.join(msg))
797
797
798 #### header
798 #### header
799 if self.mandatory:
799 if self.mandatory:
800 parttype = self.type.upper()
800 parttype = self.type.upper()
801 else:
801 else:
802 parttype = self.type.lower()
802 parttype = self.type.lower()
803 outdebug(ui, 'part %s: "%s"' % (self.id, parttype))
803 outdebug(ui, 'part %s: "%s"' % (self.id, parttype))
804 ## parttype
804 ## parttype
805 header = [_pack(_fparttypesize, len(parttype)),
805 header = [_pack(_fparttypesize, len(parttype)),
806 parttype, _pack(_fpartid, self.id),
806 parttype, _pack(_fpartid, self.id),
807 ]
807 ]
808 ## parameters
808 ## parameters
809 # count
809 # count
810 manpar = self.mandatoryparams
810 manpar = self.mandatoryparams
811 advpar = self.advisoryparams
811 advpar = self.advisoryparams
812 header.append(_pack(_fpartparamcount, len(manpar), len(advpar)))
812 header.append(_pack(_fpartparamcount, len(manpar), len(advpar)))
813 # size
813 # size
814 parsizes = []
814 parsizes = []
815 for key, value in manpar:
815 for key, value in manpar:
816 parsizes.append(len(key))
816 parsizes.append(len(key))
817 parsizes.append(len(value))
817 parsizes.append(len(value))
818 for key, value in advpar:
818 for key, value in advpar:
819 parsizes.append(len(key))
819 parsizes.append(len(key))
820 parsizes.append(len(value))
820 parsizes.append(len(value))
821 paramsizes = _pack(_makefpartparamsizes(len(parsizes) / 2), *parsizes)
821 paramsizes = _pack(_makefpartparamsizes(len(parsizes) / 2), *parsizes)
822 header.append(paramsizes)
822 header.append(paramsizes)
823 # key, value
823 # key, value
824 for key, value in manpar:
824 for key, value in manpar:
825 header.append(key)
825 header.append(key)
826 header.append(value)
826 header.append(value)
827 for key, value in advpar:
827 for key, value in advpar:
828 header.append(key)
828 header.append(key)
829 header.append(value)
829 header.append(value)
830 ## finalize header
830 ## finalize header
831 headerchunk = ''.join(header)
831 headerchunk = ''.join(header)
832 outdebug(ui, 'header chunk size: %i' % len(headerchunk))
832 outdebug(ui, 'header chunk size: %i' % len(headerchunk))
833 yield _pack(_fpartheadersize, len(headerchunk))
833 yield _pack(_fpartheadersize, len(headerchunk))
834 yield headerchunk
834 yield headerchunk
835 ## payload
835 ## payload
836 try:
836 try:
837 for chunk in self._payloadchunks():
837 for chunk in self._payloadchunks():
838 outdebug(ui, 'payload chunk size: %i' % len(chunk))
838 outdebug(ui, 'payload chunk size: %i' % len(chunk))
839 yield _pack(_fpayloadsize, len(chunk))
839 yield _pack(_fpayloadsize, len(chunk))
840 yield chunk
840 yield chunk
841 except BaseException, exc:
841 except BaseException, exc:
842 # backup exception data for later
842 # backup exception data for later
843 ui.debug('bundle2-input-stream-interrupt: encoding exception %s'
843 ui.debug('bundle2-input-stream-interrupt: encoding exception %s'
844 % exc)
844 % exc)
845 exc_info = sys.exc_info()
845 exc_info = sys.exc_info()
846 msg = 'unexpected error: %s' % exc
846 msg = 'unexpected error: %s' % exc
847 interpart = bundlepart('error:abort', [('message', msg)],
847 interpart = bundlepart('error:abort', [('message', msg)],
848 mandatory=False)
848 mandatory=False)
849 interpart.id = 0
849 interpart.id = 0
850 yield _pack(_fpayloadsize, -1)
850 yield _pack(_fpayloadsize, -1)
851 for chunk in interpart.getchunks(ui=ui):
851 for chunk in interpart.getchunks(ui=ui):
852 yield chunk
852 yield chunk
853 outdebug(ui, 'closing payload chunk')
853 outdebug(ui, 'closing payload chunk')
854 # abort current part payload
854 # abort current part payload
855 yield _pack(_fpayloadsize, 0)
855 yield _pack(_fpayloadsize, 0)
856 raise exc_info[0], exc_info[1], exc_info[2]
856 raise exc_info[0], exc_info[1], exc_info[2]
857 # end of payload
857 # end of payload
858 outdebug(ui, 'closing payload chunk')
858 outdebug(ui, 'closing payload chunk')
859 yield _pack(_fpayloadsize, 0)
859 yield _pack(_fpayloadsize, 0)
860 self._generated = True
860 self._generated = True
861
861
862 def _payloadchunks(self):
862 def _payloadchunks(self):
863 """yield chunks of a the part payload
863 """yield chunks of a the part payload
864
864
865 Exists to handle the different methods to provide data to a part."""
865 Exists to handle the different methods to provide data to a part."""
866 # we only support fixed size data now.
866 # we only support fixed size data now.
867 # This will be improved in the future.
867 # This will be improved in the future.
868 if util.safehasattr(self.data, 'next'):
868 if util.safehasattr(self.data, 'next'):
869 buff = util.chunkbuffer(self.data)
869 buff = util.chunkbuffer(self.data)
870 chunk = buff.read(preferedchunksize)
870 chunk = buff.read(preferedchunksize)
871 while chunk:
871 while chunk:
872 yield chunk
872 yield chunk
873 chunk = buff.read(preferedchunksize)
873 chunk = buff.read(preferedchunksize)
874 elif len(self.data):
874 elif len(self.data):
875 yield self.data
875 yield self.data
876
876
877
877
878 flaginterrupt = -1
878 flaginterrupt = -1
879
879
880 class interrupthandler(unpackermixin):
880 class interrupthandler(unpackermixin):
881 """read one part and process it with restricted capability
881 """read one part and process it with restricted capability
882
882
883 This allows to transmit exception raised on the producer size during part
883 This allows to transmit exception raised on the producer size during part
884 iteration while the consumer is reading a part.
884 iteration while the consumer is reading a part.
885
885
886 Part processed in this manner only have access to a ui object,"""
886 Part processed in this manner only have access to a ui object,"""
887
887
888 def __init__(self, ui, fp):
888 def __init__(self, ui, fp):
889 super(interrupthandler, self).__init__(fp)
889 super(interrupthandler, self).__init__(fp)
890 self.ui = ui
890 self.ui = ui
891
891
892 def _readpartheader(self):
892 def _readpartheader(self):
893 """reads a part header size and return the bytes blob
893 """reads a part header size and return the bytes blob
894
894
895 returns None if empty"""
895 returns None if empty"""
896 headersize = self._unpack(_fpartheadersize)[0]
896 headersize = self._unpack(_fpartheadersize)[0]
897 if headersize < 0:
897 if headersize < 0:
898 raise error.BundleValueError('negative part header size: %i'
898 raise error.BundleValueError('negative part header size: %i'
899 % headersize)
899 % headersize)
900 indebug(self.ui, 'part header size: %i\n' % headersize)
900 indebug(self.ui, 'part header size: %i\n' % headersize)
901 if headersize:
901 if headersize:
902 return self._readexact(headersize)
902 return self._readexact(headersize)
903 return None
903 return None
904
904
905 def __call__(self):
905 def __call__(self):
906
906
907 self.ui.debug('bundle2-input-stream-interrupt:'
907 self.ui.debug('bundle2-input-stream-interrupt:'
908 ' opening out of band context\n')
908 ' opening out of band context\n')
909 indebug(self.ui, 'bundle2 stream interruption, looking for a part.')
909 indebug(self.ui, 'bundle2 stream interruption, looking for a part.')
910 headerblock = self._readpartheader()
910 headerblock = self._readpartheader()
911 if headerblock is None:
911 if headerblock is None:
912 indebug(self.ui, 'no part found during interruption.')
912 indebug(self.ui, 'no part found during interruption.')
913 return
913 return
914 part = unbundlepart(self.ui, headerblock, self._fp)
914 part = unbundlepart(self.ui, headerblock, self._fp)
915 op = interruptoperation(self.ui)
915 op = interruptoperation(self.ui)
916 _processpart(op, part)
916 _processpart(op, part)
917 self.ui.debug('bundle2-input-stream-interrupt:'
917 self.ui.debug('bundle2-input-stream-interrupt:'
918 ' closing out of band context\n')
918 ' closing out of band context\n')
919
919
920 class interruptoperation(object):
920 class interruptoperation(object):
921 """A limited operation to be use by part handler during interruption
921 """A limited operation to be use by part handler during interruption
922
922
923 It only have access to an ui object.
923 It only have access to an ui object.
924 """
924 """
925
925
926 def __init__(self, ui):
926 def __init__(self, ui):
927 self.ui = ui
927 self.ui = ui
928 self.reply = None
928 self.reply = None
929 self.captureoutput = False
929 self.captureoutput = False
930
930
931 @property
931 @property
932 def repo(self):
932 def repo(self):
933 raise RuntimeError('no repo access from stream interruption')
933 raise RuntimeError('no repo access from stream interruption')
934
934
935 def gettransaction(self):
935 def gettransaction(self):
936 raise TransactionUnavailable('no repo access from stream interruption')
936 raise TransactionUnavailable('no repo access from stream interruption')
937
937
938 class unbundlepart(unpackermixin):
938 class unbundlepart(unpackermixin):
939 """a bundle part read from a bundle"""
939 """a bundle part read from a bundle"""
940
940
941 def __init__(self, ui, header, fp):
941 def __init__(self, ui, header, fp):
942 super(unbundlepart, self).__init__(fp)
942 super(unbundlepart, self).__init__(fp)
943 self.ui = ui
943 self.ui = ui
944 # unbundle state attr
944 # unbundle state attr
945 self._headerdata = header
945 self._headerdata = header
946 self._headeroffset = 0
946 self._headeroffset = 0
947 self._initialized = False
947 self._initialized = False
948 self.consumed = False
948 self.consumed = False
949 # part data
949 # part data
950 self.id = None
950 self.id = None
951 self.type = None
951 self.type = None
952 self.mandatoryparams = None
952 self.mandatoryparams = None
953 self.advisoryparams = None
953 self.advisoryparams = None
954 self.params = None
954 self.params = None
955 self.mandatorykeys = ()
955 self.mandatorykeys = ()
956 self._payloadstream = None
956 self._payloadstream = None
957 self._readheader()
957 self._readheader()
958 self._mandatory = None
958 self._mandatory = None
959 self._chunkindex = [] #(payload, file) position tuples for chunk starts
959 self._chunkindex = [] #(payload, file) position tuples for chunk starts
960 self._pos = 0
960 self._pos = 0
961
961
962 def _fromheader(self, size):
962 def _fromheader(self, size):
963 """return the next <size> byte from the header"""
963 """return the next <size> byte from the header"""
964 offset = self._headeroffset
964 offset = self._headeroffset
965 data = self._headerdata[offset:(offset + size)]
965 data = self._headerdata[offset:(offset + size)]
966 self._headeroffset = offset + size
966 self._headeroffset = offset + size
967 return data
967 return data
968
968
969 def _unpackheader(self, format):
969 def _unpackheader(self, format):
970 """read given format from header
970 """read given format from header
971
971
972 This automatically compute the size of the format to read."""
972 This automatically compute the size of the format to read."""
973 data = self._fromheader(struct.calcsize(format))
973 data = self._fromheader(struct.calcsize(format))
974 return _unpack(format, data)
974 return _unpack(format, data)
975
975
976 def _initparams(self, mandatoryparams, advisoryparams):
976 def _initparams(self, mandatoryparams, advisoryparams):
977 """internal function to setup all logic related parameters"""
977 """internal function to setup all logic related parameters"""
978 # make it read only to prevent people touching it by mistake.
978 # make it read only to prevent people touching it by mistake.
979 self.mandatoryparams = tuple(mandatoryparams)
979 self.mandatoryparams = tuple(mandatoryparams)
980 self.advisoryparams = tuple(advisoryparams)
980 self.advisoryparams = tuple(advisoryparams)
981 # user friendly UI
981 # user friendly UI
982 self.params = dict(self.mandatoryparams)
982 self.params = dict(self.mandatoryparams)
983 self.params.update(dict(self.advisoryparams))
983 self.params.update(dict(self.advisoryparams))
984 self.mandatorykeys = frozenset(p[0] for p in mandatoryparams)
984 self.mandatorykeys = frozenset(p[0] for p in mandatoryparams)
985
985
986 def _payloadchunks(self, chunknum=0):
986 def _payloadchunks(self, chunknum=0):
987 '''seek to specified chunk and start yielding data'''
987 '''seek to specified chunk and start yielding data'''
988 if len(self._chunkindex) == 0:
988 if len(self._chunkindex) == 0:
989 assert chunknum == 0, 'Must start with chunk 0'
989 assert chunknum == 0, 'Must start with chunk 0'
990 self._chunkindex.append((0, super(unbundlepart, self).tell()))
990 self._chunkindex.append((0, super(unbundlepart, self).tell()))
991 else:
991 else:
992 assert chunknum < len(self._chunkindex), \
992 assert chunknum < len(self._chunkindex), \
993 'Unknown chunk %d' % chunknum
993 'Unknown chunk %d' % chunknum
994 super(unbundlepart, self).seek(self._chunkindex[chunknum][1])
994 super(unbundlepart, self).seek(self._chunkindex[chunknum][1])
995
995
996 pos = self._chunkindex[chunknum][0]
996 pos = self._chunkindex[chunknum][0]
997 payloadsize = self._unpack(_fpayloadsize)[0]
997 payloadsize = self._unpack(_fpayloadsize)[0]
998 indebug(self.ui, 'payload chunk size: %i' % payloadsize)
998 indebug(self.ui, 'payload chunk size: %i' % payloadsize)
999 while payloadsize:
999 while payloadsize:
1000 if payloadsize == flaginterrupt:
1000 if payloadsize == flaginterrupt:
1001 # interruption detection, the handler will now read a
1001 # interruption detection, the handler will now read a
1002 # single part and process it.
1002 # single part and process it.
1003 interrupthandler(self.ui, self._fp)()
1003 interrupthandler(self.ui, self._fp)()
1004 elif payloadsize < 0:
1004 elif payloadsize < 0:
1005 msg = 'negative payload chunk size: %i' % payloadsize
1005 msg = 'negative payload chunk size: %i' % payloadsize
1006 raise error.BundleValueError(msg)
1006 raise error.BundleValueError(msg)
1007 else:
1007 else:
1008 result = self._readexact(payloadsize)
1008 result = self._readexact(payloadsize)
1009 chunknum += 1
1009 chunknum += 1
1010 pos += payloadsize
1010 pos += payloadsize
1011 if chunknum == len(self._chunkindex):
1011 if chunknum == len(self._chunkindex):
1012 self._chunkindex.append((pos,
1012 self._chunkindex.append((pos,
1013 super(unbundlepart, self).tell()))
1013 super(unbundlepart, self).tell()))
1014 yield result
1014 yield result
1015 payloadsize = self._unpack(_fpayloadsize)[0]
1015 payloadsize = self._unpack(_fpayloadsize)[0]
1016 indebug(self.ui, 'payload chunk size: %i' % payloadsize)
1016 indebug(self.ui, 'payload chunk size: %i' % payloadsize)
1017
1017
1018 def _findchunk(self, pos):
1018 def _findchunk(self, pos):
1019 '''for a given payload position, return a chunk number and offset'''
1019 '''for a given payload position, return a chunk number and offset'''
1020 for chunk, (ppos, fpos) in enumerate(self._chunkindex):
1020 for chunk, (ppos, fpos) in enumerate(self._chunkindex):
1021 if ppos == pos:
1021 if ppos == pos:
1022 return chunk, 0
1022 return chunk, 0
1023 elif ppos > pos:
1023 elif ppos > pos:
1024 return chunk - 1, pos - self._chunkindex[chunk - 1][0]
1024 return chunk - 1, pos - self._chunkindex[chunk - 1][0]
1025 raise ValueError('Unknown chunk')
1025 raise ValueError('Unknown chunk')
1026
1026
1027 def _readheader(self):
1027 def _readheader(self):
1028 """read the header and setup the object"""
1028 """read the header and setup the object"""
1029 typesize = self._unpackheader(_fparttypesize)[0]
1029 typesize = self._unpackheader(_fparttypesize)[0]
1030 self.type = self._fromheader(typesize)
1030 self.type = self._fromheader(typesize)
1031 indebug(self.ui, 'part type: "%s"' % self.type)
1031 indebug(self.ui, 'part type: "%s"' % self.type)
1032 self.id = self._unpackheader(_fpartid)[0]
1032 self.id = self._unpackheader(_fpartid)[0]
1033 indebug(self.ui, 'part id: "%s"' % self.id)
1033 indebug(self.ui, 'part id: "%s"' % self.id)
1034 # extract mandatory bit from type
1034 # extract mandatory bit from type
1035 self.mandatory = (self.type != self.type.lower())
1035 self.mandatory = (self.type != self.type.lower())
1036 self.type = self.type.lower()
1036 self.type = self.type.lower()
1037 ## reading parameters
1037 ## reading parameters
1038 # param count
1038 # param count
1039 mancount, advcount = self._unpackheader(_fpartparamcount)
1039 mancount, advcount = self._unpackheader(_fpartparamcount)
1040 indebug(self.ui, 'part parameters: %i' % (mancount + advcount))
1040 indebug(self.ui, 'part parameters: %i' % (mancount + advcount))
1041 # param size
1041 # param size
1042 fparamsizes = _makefpartparamsizes(mancount + advcount)
1042 fparamsizes = _makefpartparamsizes(mancount + advcount)
1043 paramsizes = self._unpackheader(fparamsizes)
1043 paramsizes = self._unpackheader(fparamsizes)
1044 # make it a list of couple again
1044 # make it a list of couple again
1045 paramsizes = zip(paramsizes[::2], paramsizes[1::2])
1045 paramsizes = zip(paramsizes[::2], paramsizes[1::2])
1046 # split mandatory from advisory
1046 # split mandatory from advisory
1047 mansizes = paramsizes[:mancount]
1047 mansizes = paramsizes[:mancount]
1048 advsizes = paramsizes[mancount:]
1048 advsizes = paramsizes[mancount:]
1049 # retrieve param value
1049 # retrieve param value
1050 manparams = []
1050 manparams = []
1051 for key, value in mansizes:
1051 for key, value in mansizes:
1052 manparams.append((self._fromheader(key), self._fromheader(value)))
1052 manparams.append((self._fromheader(key), self._fromheader(value)))
1053 advparams = []
1053 advparams = []
1054 for key, value in advsizes:
1054 for key, value in advsizes:
1055 advparams.append((self._fromheader(key), self._fromheader(value)))
1055 advparams.append((self._fromheader(key), self._fromheader(value)))
1056 self._initparams(manparams, advparams)
1056 self._initparams(manparams, advparams)
1057 ## part payload
1057 ## part payload
1058 self._payloadstream = util.chunkbuffer(self._payloadchunks())
1058 self._payloadstream = util.chunkbuffer(self._payloadchunks())
1059 # we read the data, tell it
1059 # we read the data, tell it
1060 self._initialized = True
1060 self._initialized = True
1061
1061
1062 def read(self, size=None):
1062 def read(self, size=None):
1063 """read payload data"""
1063 """read payload data"""
1064 if not self._initialized:
1064 if not self._initialized:
1065 self._readheader()
1065 self._readheader()
1066 if size is None:
1066 if size is None:
1067 data = self._payloadstream.read()
1067 data = self._payloadstream.read()
1068 else:
1068 else:
1069 data = self._payloadstream.read(size)
1069 data = self._payloadstream.read(size)
1070 self._pos += len(data)
1070 self._pos += len(data)
1071 if size is None or len(data) < size:
1071 if size is None or len(data) < size:
1072 if not self.consumed and self._pos:
1072 if not self.consumed and self._pos:
1073 self.ui.debug('bundle2-input-part: total payload size %i\n'
1073 self.ui.debug('bundle2-input-part: total payload size %i\n'
1074 % self._pos)
1074 % self._pos)
1075 self.consumed = True
1075 self.consumed = True
1076 return data
1076 return data
1077
1077
1078 def tell(self):
1078 def tell(self):
1079 return self._pos
1079 return self._pos
1080
1080
1081 def seek(self, offset, whence=0):
1081 def seek(self, offset, whence=0):
1082 if whence == 0:
1082 if whence == 0:
1083 newpos = offset
1083 newpos = offset
1084 elif whence == 1:
1084 elif whence == 1:
1085 newpos = self._pos + offset
1085 newpos = self._pos + offset
1086 elif whence == 2:
1086 elif whence == 2:
1087 if not self.consumed:
1087 if not self.consumed:
1088 self.read()
1088 self.read()
1089 newpos = self._chunkindex[-1][0] - offset
1089 newpos = self._chunkindex[-1][0] - offset
1090 else:
1090 else:
1091 raise ValueError('Unknown whence value: %r' % (whence,))
1091 raise ValueError('Unknown whence value: %r' % (whence,))
1092
1092
1093 if newpos > self._chunkindex[-1][0] and not self.consumed:
1093 if newpos > self._chunkindex[-1][0] and not self.consumed:
1094 self.read()
1094 self.read()
1095 if not 0 <= newpos <= self._chunkindex[-1][0]:
1095 if not 0 <= newpos <= self._chunkindex[-1][0]:
1096 raise ValueError('Offset out of range')
1096 raise ValueError('Offset out of range')
1097
1097
1098 if self._pos != newpos:
1098 if self._pos != newpos:
1099 chunk, internaloffset = self._findchunk(newpos)
1099 chunk, internaloffset = self._findchunk(newpos)
1100 self._payloadstream = util.chunkbuffer(self._payloadchunks(chunk))
1100 self._payloadstream = util.chunkbuffer(self._payloadchunks(chunk))
1101 adjust = self.read(internaloffset)
1101 adjust = self.read(internaloffset)
1102 if len(adjust) != internaloffset:
1102 if len(adjust) != internaloffset:
1103 raise util.Abort(_('Seek failed\n'))
1103 raise util.Abort(_('Seek failed\n'))
1104 self._pos = newpos
1104 self._pos = newpos
1105
1105
1106 # These are only the static capabilities.
1106 # These are only the static capabilities.
1107 # Check the 'getrepocaps' function for the rest.
1107 # Check the 'getrepocaps' function for the rest.
1108 capabilities = {'HG20': (),
1108 capabilities = {'HG20': (),
1109 'listkeys': (),
1109 'listkeys': (),
1110 'pushkey': (),
1110 'pushkey': (),
1111 'digests': tuple(sorted(util.DIGESTS.keys())),
1111 'digests': tuple(sorted(util.DIGESTS.keys())),
1112 'remote-changegroup': ('http', 'https'),
1112 'remote-changegroup': ('http', 'https'),
1113 'hgtagsfnodes': (),
1113 }
1114 }
1114
1115
1115 def getrepocaps(repo, allowpushback=False):
1116 def getrepocaps(repo, allowpushback=False):
1116 """return the bundle2 capabilities for a given repo
1117 """return the bundle2 capabilities for a given repo
1117
1118
1118 Exists to allow extensions (like evolution) to mutate the capabilities.
1119 Exists to allow extensions (like evolution) to mutate the capabilities.
1119 """
1120 """
1120 caps = capabilities.copy()
1121 caps = capabilities.copy()
1121 caps['changegroup'] = tuple(sorted(changegroup.packermap.keys()))
1122 caps['changegroup'] = tuple(sorted(changegroup.packermap.keys()))
1122 if obsolete.isenabled(repo, obsolete.exchangeopt):
1123 if obsolete.isenabled(repo, obsolete.exchangeopt):
1123 supportedformat = tuple('V%i' % v for v in obsolete.formats)
1124 supportedformat = tuple('V%i' % v for v in obsolete.formats)
1124 caps['obsmarkers'] = supportedformat
1125 caps['obsmarkers'] = supportedformat
1125 if allowpushback:
1126 if allowpushback:
1126 caps['pushback'] = ()
1127 caps['pushback'] = ()
1127 return caps
1128 return caps
1128
1129
1129 def bundle2caps(remote):
1130 def bundle2caps(remote):
1130 """return the bundle capabilities of a peer as dict"""
1131 """return the bundle capabilities of a peer as dict"""
1131 raw = remote.capable('bundle2')
1132 raw = remote.capable('bundle2')
1132 if not raw and raw != '':
1133 if not raw and raw != '':
1133 return {}
1134 return {}
1134 capsblob = urllib.unquote(remote.capable('bundle2'))
1135 capsblob = urllib.unquote(remote.capable('bundle2'))
1135 return decodecaps(capsblob)
1136 return decodecaps(capsblob)
1136
1137
1137 def obsmarkersversion(caps):
1138 def obsmarkersversion(caps):
1138 """extract the list of supported obsmarkers versions from a bundle2caps dict
1139 """extract the list of supported obsmarkers versions from a bundle2caps dict
1139 """
1140 """
1140 obscaps = caps.get('obsmarkers', ())
1141 obscaps = caps.get('obsmarkers', ())
1141 return [int(c[1:]) for c in obscaps if c.startswith('V')]
1142 return [int(c[1:]) for c in obscaps if c.startswith('V')]
1142
1143
1143 @parthandler('changegroup', ('version',))
1144 @parthandler('changegroup', ('version',))
1144 def handlechangegroup(op, inpart):
1145 def handlechangegroup(op, inpart):
1145 """apply a changegroup part on the repo
1146 """apply a changegroup part on the repo
1146
1147
1147 This is a very early implementation that will massive rework before being
1148 This is a very early implementation that will massive rework before being
1148 inflicted to any end-user.
1149 inflicted to any end-user.
1149 """
1150 """
1150 # Make sure we trigger a transaction creation
1151 # Make sure we trigger a transaction creation
1151 #
1152 #
1152 # The addchangegroup function will get a transaction object by itself, but
1153 # The addchangegroup function will get a transaction object by itself, but
1153 # we need to make sure we trigger the creation of a transaction object used
1154 # we need to make sure we trigger the creation of a transaction object used
1154 # for the whole processing scope.
1155 # for the whole processing scope.
1155 op.gettransaction()
1156 op.gettransaction()
1156 unpackerversion = inpart.params.get('version', '01')
1157 unpackerversion = inpart.params.get('version', '01')
1157 # We should raise an appropriate exception here
1158 # We should raise an appropriate exception here
1158 unpacker = changegroup.packermap[unpackerversion][1]
1159 unpacker = changegroup.packermap[unpackerversion][1]
1159 cg = unpacker(inpart, 'UN')
1160 cg = unpacker(inpart, 'UN')
1160 # the source and url passed here are overwritten by the one contained in
1161 # the source and url passed here are overwritten by the one contained in
1161 # the transaction.hookargs argument. So 'bundle2' is a placeholder
1162 # the transaction.hookargs argument. So 'bundle2' is a placeholder
1162 ret = changegroup.addchangegroup(op.repo, cg, 'bundle2', 'bundle2')
1163 ret = changegroup.addchangegroup(op.repo, cg, 'bundle2', 'bundle2')
1163 op.records.add('changegroup', {'return': ret})
1164 op.records.add('changegroup', {'return': ret})
1164 if op.reply is not None:
1165 if op.reply is not None:
1165 # This is definitely not the final form of this
1166 # This is definitely not the final form of this
1166 # return. But one need to start somewhere.
1167 # return. But one need to start somewhere.
1167 part = op.reply.newpart('reply:changegroup', mandatory=False)
1168 part = op.reply.newpart('reply:changegroup', mandatory=False)
1168 part.addparam('in-reply-to', str(inpart.id), mandatory=False)
1169 part.addparam('in-reply-to', str(inpart.id), mandatory=False)
1169 part.addparam('return', '%i' % ret, mandatory=False)
1170 part.addparam('return', '%i' % ret, mandatory=False)
1170 assert not inpart.read()
1171 assert not inpart.read()
1171
1172
1172 _remotechangegroupparams = tuple(['url', 'size', 'digests'] +
1173 _remotechangegroupparams = tuple(['url', 'size', 'digests'] +
1173 ['digest:%s' % k for k in util.DIGESTS.keys()])
1174 ['digest:%s' % k for k in util.DIGESTS.keys()])
1174 @parthandler('remote-changegroup', _remotechangegroupparams)
1175 @parthandler('remote-changegroup', _remotechangegroupparams)
1175 def handleremotechangegroup(op, inpart):
1176 def handleremotechangegroup(op, inpart):
1176 """apply a bundle10 on the repo, given an url and validation information
1177 """apply a bundle10 on the repo, given an url and validation information
1177
1178
1178 All the information about the remote bundle to import are given as
1179 All the information about the remote bundle to import are given as
1179 parameters. The parameters include:
1180 parameters. The parameters include:
1180 - url: the url to the bundle10.
1181 - url: the url to the bundle10.
1181 - size: the bundle10 file size. It is used to validate what was
1182 - size: the bundle10 file size. It is used to validate what was
1182 retrieved by the client matches the server knowledge about the bundle.
1183 retrieved by the client matches the server knowledge about the bundle.
1183 - digests: a space separated list of the digest types provided as
1184 - digests: a space separated list of the digest types provided as
1184 parameters.
1185 parameters.
1185 - digest:<digest-type>: the hexadecimal representation of the digest with
1186 - digest:<digest-type>: the hexadecimal representation of the digest with
1186 that name. Like the size, it is used to validate what was retrieved by
1187 that name. Like the size, it is used to validate what was retrieved by
1187 the client matches what the server knows about the bundle.
1188 the client matches what the server knows about the bundle.
1188
1189
1189 When multiple digest types are given, all of them are checked.
1190 When multiple digest types are given, all of them are checked.
1190 """
1191 """
1191 try:
1192 try:
1192 raw_url = inpart.params['url']
1193 raw_url = inpart.params['url']
1193 except KeyError:
1194 except KeyError:
1194 raise util.Abort(_('remote-changegroup: missing "%s" param') % 'url')
1195 raise util.Abort(_('remote-changegroup: missing "%s" param') % 'url')
1195 parsed_url = util.url(raw_url)
1196 parsed_url = util.url(raw_url)
1196 if parsed_url.scheme not in capabilities['remote-changegroup']:
1197 if parsed_url.scheme not in capabilities['remote-changegroup']:
1197 raise util.Abort(_('remote-changegroup does not support %s urls') %
1198 raise util.Abort(_('remote-changegroup does not support %s urls') %
1198 parsed_url.scheme)
1199 parsed_url.scheme)
1199
1200
1200 try:
1201 try:
1201 size = int(inpart.params['size'])
1202 size = int(inpart.params['size'])
1202 except ValueError:
1203 except ValueError:
1203 raise util.Abort(_('remote-changegroup: invalid value for param "%s"')
1204 raise util.Abort(_('remote-changegroup: invalid value for param "%s"')
1204 % 'size')
1205 % 'size')
1205 except KeyError:
1206 except KeyError:
1206 raise util.Abort(_('remote-changegroup: missing "%s" param') % 'size')
1207 raise util.Abort(_('remote-changegroup: missing "%s" param') % 'size')
1207
1208
1208 digests = {}
1209 digests = {}
1209 for typ in inpart.params.get('digests', '').split():
1210 for typ in inpart.params.get('digests', '').split():
1210 param = 'digest:%s' % typ
1211 param = 'digest:%s' % typ
1211 try:
1212 try:
1212 value = inpart.params[param]
1213 value = inpart.params[param]
1213 except KeyError:
1214 except KeyError:
1214 raise util.Abort(_('remote-changegroup: missing "%s" param') %
1215 raise util.Abort(_('remote-changegroup: missing "%s" param') %
1215 param)
1216 param)
1216 digests[typ] = value
1217 digests[typ] = value
1217
1218
1218 real_part = util.digestchecker(url.open(op.ui, raw_url), size, digests)
1219 real_part = util.digestchecker(url.open(op.ui, raw_url), size, digests)
1219
1220
1220 # Make sure we trigger a transaction creation
1221 # Make sure we trigger a transaction creation
1221 #
1222 #
1222 # The addchangegroup function will get a transaction object by itself, but
1223 # The addchangegroup function will get a transaction object by itself, but
1223 # we need to make sure we trigger the creation of a transaction object used
1224 # we need to make sure we trigger the creation of a transaction object used
1224 # for the whole processing scope.
1225 # for the whole processing scope.
1225 op.gettransaction()
1226 op.gettransaction()
1226 import exchange
1227 import exchange
1227 cg = exchange.readbundle(op.repo.ui, real_part, raw_url)
1228 cg = exchange.readbundle(op.repo.ui, real_part, raw_url)
1228 if not isinstance(cg, changegroup.cg1unpacker):
1229 if not isinstance(cg, changegroup.cg1unpacker):
1229 raise util.Abort(_('%s: not a bundle version 1.0') %
1230 raise util.Abort(_('%s: not a bundle version 1.0') %
1230 util.hidepassword(raw_url))
1231 util.hidepassword(raw_url))
1231 ret = changegroup.addchangegroup(op.repo, cg, 'bundle2', 'bundle2')
1232 ret = changegroup.addchangegroup(op.repo, cg, 'bundle2', 'bundle2')
1232 op.records.add('changegroup', {'return': ret})
1233 op.records.add('changegroup', {'return': ret})
1233 if op.reply is not None:
1234 if op.reply is not None:
1234 # This is definitely not the final form of this
1235 # This is definitely not the final form of this
1235 # return. But one need to start somewhere.
1236 # return. But one need to start somewhere.
1236 part = op.reply.newpart('reply:changegroup')
1237 part = op.reply.newpart('reply:changegroup')
1237 part.addparam('in-reply-to', str(inpart.id), mandatory=False)
1238 part.addparam('in-reply-to', str(inpart.id), mandatory=False)
1238 part.addparam('return', '%i' % ret, mandatory=False)
1239 part.addparam('return', '%i' % ret, mandatory=False)
1239 try:
1240 try:
1240 real_part.validate()
1241 real_part.validate()
1241 except util.Abort, e:
1242 except util.Abort, e:
1242 raise util.Abort(_('bundle at %s is corrupted:\n%s') %
1243 raise util.Abort(_('bundle at %s is corrupted:\n%s') %
1243 (util.hidepassword(raw_url), str(e)))
1244 (util.hidepassword(raw_url), str(e)))
1244 assert not inpart.read()
1245 assert not inpart.read()
1245
1246
1246 @parthandler('reply:changegroup', ('return', 'in-reply-to'))
1247 @parthandler('reply:changegroup', ('return', 'in-reply-to'))
1247 def handlereplychangegroup(op, inpart):
1248 def handlereplychangegroup(op, inpart):
1248 ret = int(inpart.params['return'])
1249 ret = int(inpart.params['return'])
1249 replyto = int(inpart.params['in-reply-to'])
1250 replyto = int(inpart.params['in-reply-to'])
1250 op.records.add('changegroup', {'return': ret}, replyto)
1251 op.records.add('changegroup', {'return': ret}, replyto)
1251
1252
1252 @parthandler('check:heads')
1253 @parthandler('check:heads')
1253 def handlecheckheads(op, inpart):
1254 def handlecheckheads(op, inpart):
1254 """check that head of the repo did not change
1255 """check that head of the repo did not change
1255
1256
1256 This is used to detect a push race when using unbundle.
1257 This is used to detect a push race when using unbundle.
1257 This replaces the "heads" argument of unbundle."""
1258 This replaces the "heads" argument of unbundle."""
1258 h = inpart.read(20)
1259 h = inpart.read(20)
1259 heads = []
1260 heads = []
1260 while len(h) == 20:
1261 while len(h) == 20:
1261 heads.append(h)
1262 heads.append(h)
1262 h = inpart.read(20)
1263 h = inpart.read(20)
1263 assert not h
1264 assert not h
1264 if heads != op.repo.heads():
1265 if heads != op.repo.heads():
1265 raise error.PushRaced('repository changed while pushing - '
1266 raise error.PushRaced('repository changed while pushing - '
1266 'please try again')
1267 'please try again')
1267
1268
1268 @parthandler('output')
1269 @parthandler('output')
1269 def handleoutput(op, inpart):
1270 def handleoutput(op, inpart):
1270 """forward output captured on the server to the client"""
1271 """forward output captured on the server to the client"""
1271 for line in inpart.read().splitlines():
1272 for line in inpart.read().splitlines():
1272 op.ui.status(('remote: %s\n' % line))
1273 op.ui.status(('remote: %s\n' % line))
1273
1274
1274 @parthandler('replycaps')
1275 @parthandler('replycaps')
1275 def handlereplycaps(op, inpart):
1276 def handlereplycaps(op, inpart):
1276 """Notify that a reply bundle should be created
1277 """Notify that a reply bundle should be created
1277
1278
1278 The payload contains the capabilities information for the reply"""
1279 The payload contains the capabilities information for the reply"""
1279 caps = decodecaps(inpart.read())
1280 caps = decodecaps(inpart.read())
1280 if op.reply is None:
1281 if op.reply is None:
1281 op.reply = bundle20(op.ui, caps)
1282 op.reply = bundle20(op.ui, caps)
1282
1283
1283 @parthandler('error:abort', ('message', 'hint'))
1284 @parthandler('error:abort', ('message', 'hint'))
1284 def handleerrorabort(op, inpart):
1285 def handleerrorabort(op, inpart):
1285 """Used to transmit abort error over the wire"""
1286 """Used to transmit abort error over the wire"""
1286 raise util.Abort(inpart.params['message'], hint=inpart.params.get('hint'))
1287 raise util.Abort(inpart.params['message'], hint=inpart.params.get('hint'))
1287
1288
1288 @parthandler('error:unsupportedcontent', ('parttype', 'params'))
1289 @parthandler('error:unsupportedcontent', ('parttype', 'params'))
1289 def handleerrorunsupportedcontent(op, inpart):
1290 def handleerrorunsupportedcontent(op, inpart):
1290 """Used to transmit unknown content error over the wire"""
1291 """Used to transmit unknown content error over the wire"""
1291 kwargs = {}
1292 kwargs = {}
1292 parttype = inpart.params.get('parttype')
1293 parttype = inpart.params.get('parttype')
1293 if parttype is not None:
1294 if parttype is not None:
1294 kwargs['parttype'] = parttype
1295 kwargs['parttype'] = parttype
1295 params = inpart.params.get('params')
1296 params = inpart.params.get('params')
1296 if params is not None:
1297 if params is not None:
1297 kwargs['params'] = params.split('\0')
1298 kwargs['params'] = params.split('\0')
1298
1299
1299 raise error.UnsupportedPartError(**kwargs)
1300 raise error.UnsupportedPartError(**kwargs)
1300
1301
1301 @parthandler('error:pushraced', ('message',))
1302 @parthandler('error:pushraced', ('message',))
1302 def handleerrorpushraced(op, inpart):
1303 def handleerrorpushraced(op, inpart):
1303 """Used to transmit push race error over the wire"""
1304 """Used to transmit push race error over the wire"""
1304 raise error.ResponseError(_('push failed:'), inpart.params['message'])
1305 raise error.ResponseError(_('push failed:'), inpart.params['message'])
1305
1306
1306 @parthandler('listkeys', ('namespace',))
1307 @parthandler('listkeys', ('namespace',))
1307 def handlelistkeys(op, inpart):
1308 def handlelistkeys(op, inpart):
1308 """retrieve pushkey namespace content stored in a bundle2"""
1309 """retrieve pushkey namespace content stored in a bundle2"""
1309 namespace = inpart.params['namespace']
1310 namespace = inpart.params['namespace']
1310 r = pushkey.decodekeys(inpart.read())
1311 r = pushkey.decodekeys(inpart.read())
1311 op.records.add('listkeys', (namespace, r))
1312 op.records.add('listkeys', (namespace, r))
1312
1313
1313 @parthandler('pushkey', ('namespace', 'key', 'old', 'new'))
1314 @parthandler('pushkey', ('namespace', 'key', 'old', 'new'))
1314 def handlepushkey(op, inpart):
1315 def handlepushkey(op, inpart):
1315 """process a pushkey request"""
1316 """process a pushkey request"""
1316 dec = pushkey.decode
1317 dec = pushkey.decode
1317 namespace = dec(inpart.params['namespace'])
1318 namespace = dec(inpart.params['namespace'])
1318 key = dec(inpart.params['key'])
1319 key = dec(inpart.params['key'])
1319 old = dec(inpart.params['old'])
1320 old = dec(inpart.params['old'])
1320 new = dec(inpart.params['new'])
1321 new = dec(inpart.params['new'])
1321 ret = op.repo.pushkey(namespace, key, old, new)
1322 ret = op.repo.pushkey(namespace, key, old, new)
1322 record = {'namespace': namespace,
1323 record = {'namespace': namespace,
1323 'key': key,
1324 'key': key,
1324 'old': old,
1325 'old': old,
1325 'new': new}
1326 'new': new}
1326 op.records.add('pushkey', record)
1327 op.records.add('pushkey', record)
1327 if op.reply is not None:
1328 if op.reply is not None:
1328 rpart = op.reply.newpart('reply:pushkey')
1329 rpart = op.reply.newpart('reply:pushkey')
1329 rpart.addparam('in-reply-to', str(inpart.id), mandatory=False)
1330 rpart.addparam('in-reply-to', str(inpart.id), mandatory=False)
1330 rpart.addparam('return', '%i' % ret, mandatory=False)
1331 rpart.addparam('return', '%i' % ret, mandatory=False)
1331
1332
1332 @parthandler('reply:pushkey', ('return', 'in-reply-to'))
1333 @parthandler('reply:pushkey', ('return', 'in-reply-to'))
1333 def handlepushkeyreply(op, inpart):
1334 def handlepushkeyreply(op, inpart):
1334 """retrieve the result of a pushkey request"""
1335 """retrieve the result of a pushkey request"""
1335 ret = int(inpart.params['return'])
1336 ret = int(inpart.params['return'])
1336 partid = int(inpart.params['in-reply-to'])
1337 partid = int(inpart.params['in-reply-to'])
1337 op.records.add('pushkey', {'return': ret}, partid)
1338 op.records.add('pushkey', {'return': ret}, partid)
1338
1339
1339 @parthandler('obsmarkers')
1340 @parthandler('obsmarkers')
1340 def handleobsmarker(op, inpart):
1341 def handleobsmarker(op, inpart):
1341 """add a stream of obsmarkers to the repo"""
1342 """add a stream of obsmarkers to the repo"""
1342 tr = op.gettransaction()
1343 tr = op.gettransaction()
1343 markerdata = inpart.read()
1344 markerdata = inpart.read()
1344 if op.ui.config('experimental', 'obsmarkers-exchange-debug', False):
1345 if op.ui.config('experimental', 'obsmarkers-exchange-debug', False):
1345 op.ui.write(('obsmarker-exchange: %i bytes received\n')
1346 op.ui.write(('obsmarker-exchange: %i bytes received\n')
1346 % len(markerdata))
1347 % len(markerdata))
1347 new = op.repo.obsstore.mergemarkers(tr, markerdata)
1348 new = op.repo.obsstore.mergemarkers(tr, markerdata)
1348 if new:
1349 if new:
1349 op.repo.ui.status(_('%i new obsolescence markers\n') % new)
1350 op.repo.ui.status(_('%i new obsolescence markers\n') % new)
1350 op.records.add('obsmarkers', {'new': new})
1351 op.records.add('obsmarkers', {'new': new})
1351 if op.reply is not None:
1352 if op.reply is not None:
1352 rpart = op.reply.newpart('reply:obsmarkers')
1353 rpart = op.reply.newpart('reply:obsmarkers')
1353 rpart.addparam('in-reply-to', str(inpart.id), mandatory=False)
1354 rpart.addparam('in-reply-to', str(inpart.id), mandatory=False)
1354 rpart.addparam('new', '%i' % new, mandatory=False)
1355 rpart.addparam('new', '%i' % new, mandatory=False)
1355
1356
1356
1357
1357 @parthandler('reply:obsmarkers', ('new', 'in-reply-to'))
1358 @parthandler('reply:obsmarkers', ('new', 'in-reply-to'))
1358 def handlepushkeyreply(op, inpart):
1359 def handlepushkeyreply(op, inpart):
1359 """retrieve the result of a pushkey request"""
1360 """retrieve the result of a pushkey request"""
1360 ret = int(inpart.params['new'])
1361 ret = int(inpart.params['new'])
1361 partid = int(inpart.params['in-reply-to'])
1362 partid = int(inpart.params['in-reply-to'])
1362 op.records.add('obsmarkers', {'new': ret}, partid)
1363 op.records.add('obsmarkers', {'new': ret}, partid)
1364
1365 @parthandler('hgtagsfnodes')
1366 def handlehgtagsfnodes(op, inpart):
1367 """Applies .hgtags fnodes cache entries to the local repo.
1368
1369 Payload is pairs of 20 byte changeset nodes and filenodes.
1370 """
1371 cache = tags.hgtagsfnodescache(op.repo.unfiltered())
1372
1373 count = 0
1374 while True:
1375 node = inpart.read(20)
1376 fnode = inpart.read(20)
1377 if len(node) < 20 or len(fnode) < 20:
1378 op.ui.debug('received incomplete .hgtags fnodes data, ignoring\n')
1379 break
1380 cache.setfnode(node, fnode)
1381 count += 1
1382
1383 cache.write()
1384 op.ui.debug('applied %i hgtags fnodes cache entries\n' % count)
@@ -1,2166 +1,2166 b''
1 > do_push()
1 > do_push()
2 > {
2 > {
3 > user=$1
3 > user=$1
4 > shift
4 > shift
5 > echo "Pushing as user $user"
5 > echo "Pushing as user $user"
6 > echo 'hgrc = """'
6 > echo 'hgrc = """'
7 > sed -n '/\[[ha]/,$p' b/.hg/hgrc | grep -v fakegroups.py
7 > sed -n '/\[[ha]/,$p' b/.hg/hgrc | grep -v fakegroups.py
8 > echo '"""'
8 > echo '"""'
9 > if test -f acl.config; then
9 > if test -f acl.config; then
10 > echo 'acl.config = """'
10 > echo 'acl.config = """'
11 > cat acl.config
11 > cat acl.config
12 > echo '"""'
12 > echo '"""'
13 > fi
13 > fi
14 > # On AIX /etc/profile sets LOGNAME read-only. So
14 > # On AIX /etc/profile sets LOGNAME read-only. So
15 > # LOGNAME=$user hg --cws a --debug push ../b
15 > # LOGNAME=$user hg --cws a --debug push ../b
16 > # fails with "This variable is read only."
16 > # fails with "This variable is read only."
17 > # Use env to work around this.
17 > # Use env to work around this.
18 > env LOGNAME=$user hg --cwd a --debug push ../b
18 > env LOGNAME=$user hg --cwd a --debug push ../b
19 > hg --cwd b rollback
19 > hg --cwd b rollback
20 > hg --cwd b --quiet tip
20 > hg --cwd b --quiet tip
21 > echo
21 > echo
22 > }
22 > }
23
23
24 > init_config()
24 > init_config()
25 > {
25 > {
26 > cat > fakegroups.py <<EOF
26 > cat > fakegroups.py <<EOF
27 > from hgext import acl
27 > from hgext import acl
28 > def fakegetusers(ui, group):
28 > def fakegetusers(ui, group):
29 > try:
29 > try:
30 > return acl._getusersorig(ui, group)
30 > return acl._getusersorig(ui, group)
31 > except:
31 > except:
32 > return ["fred", "betty"]
32 > return ["fred", "betty"]
33 > acl._getusersorig = acl._getusers
33 > acl._getusersorig = acl._getusers
34 > acl._getusers = fakegetusers
34 > acl._getusers = fakegetusers
35 > EOF
35 > EOF
36 > rm -f acl.config
36 > rm -f acl.config
37 > cat > $config <<EOF
37 > cat > $config <<EOF
38 > [hooks]
38 > [hooks]
39 > pretxnchangegroup.acl = python:hgext.acl.hook
39 > pretxnchangegroup.acl = python:hgext.acl.hook
40 > [acl]
40 > [acl]
41 > sources = push
41 > sources = push
42 > [extensions]
42 > [extensions]
43 > f=`pwd`/fakegroups.py
43 > f=`pwd`/fakegroups.py
44 > EOF
44 > EOF
45 > }
45 > }
46
46
47 $ cat << EOF >> $HGRCPATH
47 $ cat << EOF >> $HGRCPATH
48 > [experimental]
48 > [experimental]
49 > # drop me once bundle2 is the default,
49 > # drop me once bundle2 is the default,
50 > # added to get test change early.
50 > # added to get test change early.
51 > bundle2-exp = True
51 > bundle2-exp = True
52 > EOF
52 > EOF
53
53
54 $ hg init a
54 $ hg init a
55 $ cd a
55 $ cd a
56 $ mkdir foo foo/Bar quux
56 $ mkdir foo foo/Bar quux
57 $ echo 'in foo' > foo/file.txt
57 $ echo 'in foo' > foo/file.txt
58 $ echo 'in foo/Bar' > foo/Bar/file.txt
58 $ echo 'in foo/Bar' > foo/Bar/file.txt
59 $ echo 'in quux' > quux/file.py
59 $ echo 'in quux' > quux/file.py
60 $ hg add -q
60 $ hg add -q
61 $ hg ci -m 'add files' -d '1000000 0'
61 $ hg ci -m 'add files' -d '1000000 0'
62 $ echo >> foo/file.txt
62 $ echo >> foo/file.txt
63 $ hg ci -m 'change foo/file' -d '1000001 0'
63 $ hg ci -m 'change foo/file' -d '1000001 0'
64 $ echo >> foo/Bar/file.txt
64 $ echo >> foo/Bar/file.txt
65 $ hg ci -m 'change foo/Bar/file' -d '1000002 0'
65 $ hg ci -m 'change foo/Bar/file' -d '1000002 0'
66 $ echo >> quux/file.py
66 $ echo >> quux/file.py
67 $ hg ci -m 'change quux/file' -d '1000003 0'
67 $ hg ci -m 'change quux/file' -d '1000003 0'
68 $ hg tip --quiet
68 $ hg tip --quiet
69 3:911600dab2ae
69 3:911600dab2ae
70
70
71 $ cd ..
71 $ cd ..
72 $ hg clone -r 0 a b
72 $ hg clone -r 0 a b
73 adding changesets
73 adding changesets
74 adding manifests
74 adding manifests
75 adding file changes
75 adding file changes
76 added 1 changesets with 3 changes to 3 files
76 added 1 changesets with 3 changes to 3 files
77 updating to branch default
77 updating to branch default
78 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
78 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
79
79
80 $ config=b/.hg/hgrc
80 $ config=b/.hg/hgrc
81
81
82 Extension disabled for lack of a hook
82 Extension disabled for lack of a hook
83
83
84 $ do_push fred
84 $ do_push fred
85 Pushing as user fred
85 Pushing as user fred
86 hgrc = """
86 hgrc = """
87 """
87 """
88 pushing to ../b
88 pushing to ../b
89 query 1; heads
89 query 1; heads
90 searching for changes
90 searching for changes
91 all remote heads known locally
91 all remote heads known locally
92 listing keys for "phases"
92 listing keys for "phases"
93 checking for updated bookmarks
93 checking for updated bookmarks
94 listing keys for "bookmarks"
94 listing keys for "bookmarks"
95 listing keys for "bookmarks"
95 listing keys for "bookmarks"
96 3 changesets found
96 3 changesets found
97 list of changesets:
97 list of changesets:
98 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
98 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
99 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
99 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
100 911600dab2ae7a9baff75958b84fe606851ce955
100 911600dab2ae7a9baff75958b84fe606851ce955
101 bundle2-output-bundle: "HG20", 4 parts total
101 bundle2-output-bundle: "HG20", 4 parts total
102 bundle2-output-part: "replycaps" 93 bytes payload
102 bundle2-output-part: "replycaps" 106 bytes payload
103 bundle2-output-part: "check:heads" streamed payload
103 bundle2-output-part: "check:heads" streamed payload
104 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
104 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
105 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
105 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
106 bundle2-input-bundle: with-transaction
106 bundle2-input-bundle: with-transaction
107 bundle2-input-part: "replycaps" supported
107 bundle2-input-part: "replycaps" supported
108 bundle2-input-part: total payload size 93
108 bundle2-input-part: total payload size 106
109 bundle2-input-part: "check:heads" supported
109 bundle2-input-part: "check:heads" supported
110 bundle2-input-part: total payload size 20
110 bundle2-input-part: total payload size 20
111 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
111 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
112 adding changesets
112 adding changesets
113 add changeset ef1ea85a6374
113 add changeset ef1ea85a6374
114 add changeset f9cafe1212c8
114 add changeset f9cafe1212c8
115 add changeset 911600dab2ae
115 add changeset 911600dab2ae
116 adding manifests
116 adding manifests
117 adding file changes
117 adding file changes
118 adding foo/Bar/file.txt revisions
118 adding foo/Bar/file.txt revisions
119 adding foo/file.txt revisions
119 adding foo/file.txt revisions
120 adding quux/file.py revisions
120 adding quux/file.py revisions
121 added 3 changesets with 3 changes to 3 files
121 added 3 changesets with 3 changes to 3 files
122 bundle2-input-part: total payload size 1606
122 bundle2-input-part: total payload size 1606
123 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
123 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
124 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
124 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
125 bundle2-input-bundle: 3 parts total
125 bundle2-input-bundle: 3 parts total
126 updating the branch cache
126 updating the branch cache
127 bundle2-output-bundle: "HG20", 2 parts total
127 bundle2-output-bundle: "HG20", 2 parts total
128 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
128 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
129 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
129 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
130 bundle2-input-bundle: with-transaction
130 bundle2-input-bundle: with-transaction
131 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
131 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
132 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
132 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
133 bundle2-input-bundle: 1 parts total
133 bundle2-input-bundle: 1 parts total
134 listing keys for "phases"
134 listing keys for "phases"
135 try to push obsolete markers to remote
135 try to push obsolete markers to remote
136 repository tip rolled back to revision 0 (undo push)
136 repository tip rolled back to revision 0 (undo push)
137 0:6675d58eff77
137 0:6675d58eff77
138
138
139
139
140 $ echo '[hooks]' >> $config
140 $ echo '[hooks]' >> $config
141 $ echo 'pretxnchangegroup.acl = python:hgext.acl.hook' >> $config
141 $ echo 'pretxnchangegroup.acl = python:hgext.acl.hook' >> $config
142
142
143 Extension disabled for lack of acl.sources
143 Extension disabled for lack of acl.sources
144
144
145 $ do_push fred
145 $ do_push fred
146 Pushing as user fred
146 Pushing as user fred
147 hgrc = """
147 hgrc = """
148 [hooks]
148 [hooks]
149 pretxnchangegroup.acl = python:hgext.acl.hook
149 pretxnchangegroup.acl = python:hgext.acl.hook
150 """
150 """
151 pushing to ../b
151 pushing to ../b
152 query 1; heads
152 query 1; heads
153 searching for changes
153 searching for changes
154 all remote heads known locally
154 all remote heads known locally
155 listing keys for "phases"
155 listing keys for "phases"
156 checking for updated bookmarks
156 checking for updated bookmarks
157 listing keys for "bookmarks"
157 listing keys for "bookmarks"
158 invalid branchheads cache (served): tip differs
158 invalid branchheads cache (served): tip differs
159 listing keys for "bookmarks"
159 listing keys for "bookmarks"
160 3 changesets found
160 3 changesets found
161 list of changesets:
161 list of changesets:
162 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
162 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
163 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
163 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
164 911600dab2ae7a9baff75958b84fe606851ce955
164 911600dab2ae7a9baff75958b84fe606851ce955
165 bundle2-output-bundle: "HG20", 4 parts total
165 bundle2-output-bundle: "HG20", 4 parts total
166 bundle2-output-part: "replycaps" 93 bytes payload
166 bundle2-output-part: "replycaps" 106 bytes payload
167 bundle2-output-part: "check:heads" streamed payload
167 bundle2-output-part: "check:heads" streamed payload
168 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
168 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
169 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
169 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
170 bundle2-input-bundle: with-transaction
170 bundle2-input-bundle: with-transaction
171 bundle2-input-part: "replycaps" supported
171 bundle2-input-part: "replycaps" supported
172 bundle2-input-part: total payload size 93
172 bundle2-input-part: total payload size 106
173 bundle2-input-part: "check:heads" supported
173 bundle2-input-part: "check:heads" supported
174 bundle2-input-part: total payload size 20
174 bundle2-input-part: total payload size 20
175 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
175 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
176 adding changesets
176 adding changesets
177 add changeset ef1ea85a6374
177 add changeset ef1ea85a6374
178 add changeset f9cafe1212c8
178 add changeset f9cafe1212c8
179 add changeset 911600dab2ae
179 add changeset 911600dab2ae
180 adding manifests
180 adding manifests
181 adding file changes
181 adding file changes
182 adding foo/Bar/file.txt revisions
182 adding foo/Bar/file.txt revisions
183 adding foo/file.txt revisions
183 adding foo/file.txt revisions
184 adding quux/file.py revisions
184 adding quux/file.py revisions
185 added 3 changesets with 3 changes to 3 files
185 added 3 changesets with 3 changes to 3 files
186 calling hook pretxnchangegroup.acl: hgext.acl.hook
186 calling hook pretxnchangegroup.acl: hgext.acl.hook
187 acl: changes have source "push" - skipping
187 acl: changes have source "push" - skipping
188 bundle2-input-part: total payload size 1606
188 bundle2-input-part: total payload size 1606
189 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
189 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
190 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
190 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
191 bundle2-input-bundle: 3 parts total
191 bundle2-input-bundle: 3 parts total
192 updating the branch cache
192 updating the branch cache
193 bundle2-output-bundle: "HG20", 2 parts total
193 bundle2-output-bundle: "HG20", 2 parts total
194 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
194 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
195 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
195 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
196 bundle2-input-bundle: with-transaction
196 bundle2-input-bundle: with-transaction
197 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
197 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
198 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
198 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
199 bundle2-input-bundle: 1 parts total
199 bundle2-input-bundle: 1 parts total
200 listing keys for "phases"
200 listing keys for "phases"
201 try to push obsolete markers to remote
201 try to push obsolete markers to remote
202 repository tip rolled back to revision 0 (undo push)
202 repository tip rolled back to revision 0 (undo push)
203 0:6675d58eff77
203 0:6675d58eff77
204
204
205
205
206 No [acl.allow]/[acl.deny]
206 No [acl.allow]/[acl.deny]
207
207
208 $ echo '[acl]' >> $config
208 $ echo '[acl]' >> $config
209 $ echo 'sources = push' >> $config
209 $ echo 'sources = push' >> $config
210 $ do_push fred
210 $ do_push fred
211 Pushing as user fred
211 Pushing as user fred
212 hgrc = """
212 hgrc = """
213 [hooks]
213 [hooks]
214 pretxnchangegroup.acl = python:hgext.acl.hook
214 pretxnchangegroup.acl = python:hgext.acl.hook
215 [acl]
215 [acl]
216 sources = push
216 sources = push
217 """
217 """
218 pushing to ../b
218 pushing to ../b
219 query 1; heads
219 query 1; heads
220 searching for changes
220 searching for changes
221 all remote heads known locally
221 all remote heads known locally
222 listing keys for "phases"
222 listing keys for "phases"
223 checking for updated bookmarks
223 checking for updated bookmarks
224 listing keys for "bookmarks"
224 listing keys for "bookmarks"
225 invalid branchheads cache (served): tip differs
225 invalid branchheads cache (served): tip differs
226 listing keys for "bookmarks"
226 listing keys for "bookmarks"
227 3 changesets found
227 3 changesets found
228 list of changesets:
228 list of changesets:
229 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
229 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
230 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
230 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
231 911600dab2ae7a9baff75958b84fe606851ce955
231 911600dab2ae7a9baff75958b84fe606851ce955
232 bundle2-output-bundle: "HG20", 4 parts total
232 bundle2-output-bundle: "HG20", 4 parts total
233 bundle2-output-part: "replycaps" 93 bytes payload
233 bundle2-output-part: "replycaps" 106 bytes payload
234 bundle2-output-part: "check:heads" streamed payload
234 bundle2-output-part: "check:heads" streamed payload
235 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
235 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
236 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
236 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
237 bundle2-input-bundle: with-transaction
237 bundle2-input-bundle: with-transaction
238 bundle2-input-part: "replycaps" supported
238 bundle2-input-part: "replycaps" supported
239 bundle2-input-part: total payload size 93
239 bundle2-input-part: total payload size 106
240 bundle2-input-part: "check:heads" supported
240 bundle2-input-part: "check:heads" supported
241 bundle2-input-part: total payload size 20
241 bundle2-input-part: total payload size 20
242 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
242 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
243 adding changesets
243 adding changesets
244 add changeset ef1ea85a6374
244 add changeset ef1ea85a6374
245 add changeset f9cafe1212c8
245 add changeset f9cafe1212c8
246 add changeset 911600dab2ae
246 add changeset 911600dab2ae
247 adding manifests
247 adding manifests
248 adding file changes
248 adding file changes
249 adding foo/Bar/file.txt revisions
249 adding foo/Bar/file.txt revisions
250 adding foo/file.txt revisions
250 adding foo/file.txt revisions
251 adding quux/file.py revisions
251 adding quux/file.py revisions
252 added 3 changesets with 3 changes to 3 files
252 added 3 changesets with 3 changes to 3 files
253 calling hook pretxnchangegroup.acl: hgext.acl.hook
253 calling hook pretxnchangegroup.acl: hgext.acl.hook
254 acl: checking access for user "fred"
254 acl: checking access for user "fred"
255 acl: acl.allow.branches not enabled
255 acl: acl.allow.branches not enabled
256 acl: acl.deny.branches not enabled
256 acl: acl.deny.branches not enabled
257 acl: acl.allow not enabled
257 acl: acl.allow not enabled
258 acl: acl.deny not enabled
258 acl: acl.deny not enabled
259 acl: branch access granted: "ef1ea85a6374" on branch "default"
259 acl: branch access granted: "ef1ea85a6374" on branch "default"
260 acl: path access granted: "ef1ea85a6374"
260 acl: path access granted: "ef1ea85a6374"
261 acl: branch access granted: "f9cafe1212c8" on branch "default"
261 acl: branch access granted: "f9cafe1212c8" on branch "default"
262 acl: path access granted: "f9cafe1212c8"
262 acl: path access granted: "f9cafe1212c8"
263 acl: branch access granted: "911600dab2ae" on branch "default"
263 acl: branch access granted: "911600dab2ae" on branch "default"
264 acl: path access granted: "911600dab2ae"
264 acl: path access granted: "911600dab2ae"
265 bundle2-input-part: total payload size 1606
265 bundle2-input-part: total payload size 1606
266 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
266 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
267 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
267 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
268 bundle2-input-bundle: 3 parts total
268 bundle2-input-bundle: 3 parts total
269 updating the branch cache
269 updating the branch cache
270 bundle2-output-bundle: "HG20", 2 parts total
270 bundle2-output-bundle: "HG20", 2 parts total
271 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
271 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
272 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
272 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
273 bundle2-input-bundle: with-transaction
273 bundle2-input-bundle: with-transaction
274 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
274 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
275 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
275 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
276 bundle2-input-bundle: 1 parts total
276 bundle2-input-bundle: 1 parts total
277 listing keys for "phases"
277 listing keys for "phases"
278 try to push obsolete markers to remote
278 try to push obsolete markers to remote
279 repository tip rolled back to revision 0 (undo push)
279 repository tip rolled back to revision 0 (undo push)
280 0:6675d58eff77
280 0:6675d58eff77
281
281
282
282
283 Empty [acl.allow]
283 Empty [acl.allow]
284
284
285 $ echo '[acl.allow]' >> $config
285 $ echo '[acl.allow]' >> $config
286 $ do_push fred
286 $ do_push fred
287 Pushing as user fred
287 Pushing as user fred
288 hgrc = """
288 hgrc = """
289 [hooks]
289 [hooks]
290 pretxnchangegroup.acl = python:hgext.acl.hook
290 pretxnchangegroup.acl = python:hgext.acl.hook
291 [acl]
291 [acl]
292 sources = push
292 sources = push
293 [acl.allow]
293 [acl.allow]
294 """
294 """
295 pushing to ../b
295 pushing to ../b
296 query 1; heads
296 query 1; heads
297 searching for changes
297 searching for changes
298 all remote heads known locally
298 all remote heads known locally
299 listing keys for "phases"
299 listing keys for "phases"
300 checking for updated bookmarks
300 checking for updated bookmarks
301 listing keys for "bookmarks"
301 listing keys for "bookmarks"
302 invalid branchheads cache (served): tip differs
302 invalid branchheads cache (served): tip differs
303 listing keys for "bookmarks"
303 listing keys for "bookmarks"
304 3 changesets found
304 3 changesets found
305 list of changesets:
305 list of changesets:
306 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
306 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
307 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
307 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
308 911600dab2ae7a9baff75958b84fe606851ce955
308 911600dab2ae7a9baff75958b84fe606851ce955
309 bundle2-output-bundle: "HG20", 4 parts total
309 bundle2-output-bundle: "HG20", 4 parts total
310 bundle2-output-part: "replycaps" 93 bytes payload
310 bundle2-output-part: "replycaps" 106 bytes payload
311 bundle2-output-part: "check:heads" streamed payload
311 bundle2-output-part: "check:heads" streamed payload
312 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
312 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
313 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
313 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
314 bundle2-input-bundle: with-transaction
314 bundle2-input-bundle: with-transaction
315 bundle2-input-part: "replycaps" supported
315 bundle2-input-part: "replycaps" supported
316 bundle2-input-part: total payload size 93
316 bundle2-input-part: total payload size 106
317 bundle2-input-part: "check:heads" supported
317 bundle2-input-part: "check:heads" supported
318 bundle2-input-part: total payload size 20
318 bundle2-input-part: total payload size 20
319 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
319 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
320 adding changesets
320 adding changesets
321 add changeset ef1ea85a6374
321 add changeset ef1ea85a6374
322 add changeset f9cafe1212c8
322 add changeset f9cafe1212c8
323 add changeset 911600dab2ae
323 add changeset 911600dab2ae
324 adding manifests
324 adding manifests
325 adding file changes
325 adding file changes
326 adding foo/Bar/file.txt revisions
326 adding foo/Bar/file.txt revisions
327 adding foo/file.txt revisions
327 adding foo/file.txt revisions
328 adding quux/file.py revisions
328 adding quux/file.py revisions
329 added 3 changesets with 3 changes to 3 files
329 added 3 changesets with 3 changes to 3 files
330 calling hook pretxnchangegroup.acl: hgext.acl.hook
330 calling hook pretxnchangegroup.acl: hgext.acl.hook
331 acl: checking access for user "fred"
331 acl: checking access for user "fred"
332 acl: acl.allow.branches not enabled
332 acl: acl.allow.branches not enabled
333 acl: acl.deny.branches not enabled
333 acl: acl.deny.branches not enabled
334 acl: acl.allow enabled, 0 entries for user fred
334 acl: acl.allow enabled, 0 entries for user fred
335 acl: acl.deny not enabled
335 acl: acl.deny not enabled
336 acl: branch access granted: "ef1ea85a6374" on branch "default"
336 acl: branch access granted: "ef1ea85a6374" on branch "default"
337 error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
337 error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
338 bundle2-input-part: total payload size 1606
338 bundle2-input-part: total payload size 1606
339 bundle2-input-bundle: 3 parts total
339 bundle2-input-bundle: 3 parts total
340 transaction abort!
340 transaction abort!
341 rollback completed
341 rollback completed
342 abort: acl: user "fred" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
342 abort: acl: user "fred" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
343 no rollback information available
343 no rollback information available
344 0:6675d58eff77
344 0:6675d58eff77
345
345
346
346
347 fred is allowed inside foo/
347 fred is allowed inside foo/
348
348
349 $ echo 'foo/** = fred' >> $config
349 $ echo 'foo/** = fred' >> $config
350 $ do_push fred
350 $ do_push fred
351 Pushing as user fred
351 Pushing as user fred
352 hgrc = """
352 hgrc = """
353 [hooks]
353 [hooks]
354 pretxnchangegroup.acl = python:hgext.acl.hook
354 pretxnchangegroup.acl = python:hgext.acl.hook
355 [acl]
355 [acl]
356 sources = push
356 sources = push
357 [acl.allow]
357 [acl.allow]
358 foo/** = fred
358 foo/** = fred
359 """
359 """
360 pushing to ../b
360 pushing to ../b
361 query 1; heads
361 query 1; heads
362 searching for changes
362 searching for changes
363 all remote heads known locally
363 all remote heads known locally
364 listing keys for "phases"
364 listing keys for "phases"
365 checking for updated bookmarks
365 checking for updated bookmarks
366 listing keys for "bookmarks"
366 listing keys for "bookmarks"
367 invalid branchheads cache (served): tip differs
367 invalid branchheads cache (served): tip differs
368 listing keys for "bookmarks"
368 listing keys for "bookmarks"
369 3 changesets found
369 3 changesets found
370 list of changesets:
370 list of changesets:
371 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
371 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
372 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
372 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
373 911600dab2ae7a9baff75958b84fe606851ce955
373 911600dab2ae7a9baff75958b84fe606851ce955
374 bundle2-output-bundle: "HG20", 4 parts total
374 bundle2-output-bundle: "HG20", 4 parts total
375 bundle2-output-part: "replycaps" 93 bytes payload
375 bundle2-output-part: "replycaps" 106 bytes payload
376 bundle2-output-part: "check:heads" streamed payload
376 bundle2-output-part: "check:heads" streamed payload
377 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
377 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
378 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
378 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
379 bundle2-input-bundle: with-transaction
379 bundle2-input-bundle: with-transaction
380 bundle2-input-part: "replycaps" supported
380 bundle2-input-part: "replycaps" supported
381 bundle2-input-part: total payload size 93
381 bundle2-input-part: total payload size 106
382 bundle2-input-part: "check:heads" supported
382 bundle2-input-part: "check:heads" supported
383 bundle2-input-part: total payload size 20
383 bundle2-input-part: total payload size 20
384 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
384 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
385 adding changesets
385 adding changesets
386 add changeset ef1ea85a6374
386 add changeset ef1ea85a6374
387 add changeset f9cafe1212c8
387 add changeset f9cafe1212c8
388 add changeset 911600dab2ae
388 add changeset 911600dab2ae
389 adding manifests
389 adding manifests
390 adding file changes
390 adding file changes
391 adding foo/Bar/file.txt revisions
391 adding foo/Bar/file.txt revisions
392 adding foo/file.txt revisions
392 adding foo/file.txt revisions
393 adding quux/file.py revisions
393 adding quux/file.py revisions
394 added 3 changesets with 3 changes to 3 files
394 added 3 changesets with 3 changes to 3 files
395 calling hook pretxnchangegroup.acl: hgext.acl.hook
395 calling hook pretxnchangegroup.acl: hgext.acl.hook
396 acl: checking access for user "fred"
396 acl: checking access for user "fred"
397 acl: acl.allow.branches not enabled
397 acl: acl.allow.branches not enabled
398 acl: acl.deny.branches not enabled
398 acl: acl.deny.branches not enabled
399 acl: acl.allow enabled, 1 entries for user fred
399 acl: acl.allow enabled, 1 entries for user fred
400 acl: acl.deny not enabled
400 acl: acl.deny not enabled
401 acl: branch access granted: "ef1ea85a6374" on branch "default"
401 acl: branch access granted: "ef1ea85a6374" on branch "default"
402 acl: path access granted: "ef1ea85a6374"
402 acl: path access granted: "ef1ea85a6374"
403 acl: branch access granted: "f9cafe1212c8" on branch "default"
403 acl: branch access granted: "f9cafe1212c8" on branch "default"
404 acl: path access granted: "f9cafe1212c8"
404 acl: path access granted: "f9cafe1212c8"
405 acl: branch access granted: "911600dab2ae" on branch "default"
405 acl: branch access granted: "911600dab2ae" on branch "default"
406 error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
406 error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
407 bundle2-input-part: total payload size 1606
407 bundle2-input-part: total payload size 1606
408 bundle2-input-bundle: 3 parts total
408 bundle2-input-bundle: 3 parts total
409 transaction abort!
409 transaction abort!
410 rollback completed
410 rollback completed
411 abort: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
411 abort: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
412 no rollback information available
412 no rollback information available
413 0:6675d58eff77
413 0:6675d58eff77
414
414
415
415
416 Empty [acl.deny]
416 Empty [acl.deny]
417
417
418 $ echo '[acl.deny]' >> $config
418 $ echo '[acl.deny]' >> $config
419 $ do_push barney
419 $ do_push barney
420 Pushing as user barney
420 Pushing as user barney
421 hgrc = """
421 hgrc = """
422 [hooks]
422 [hooks]
423 pretxnchangegroup.acl = python:hgext.acl.hook
423 pretxnchangegroup.acl = python:hgext.acl.hook
424 [acl]
424 [acl]
425 sources = push
425 sources = push
426 [acl.allow]
426 [acl.allow]
427 foo/** = fred
427 foo/** = fred
428 [acl.deny]
428 [acl.deny]
429 """
429 """
430 pushing to ../b
430 pushing to ../b
431 query 1; heads
431 query 1; heads
432 searching for changes
432 searching for changes
433 all remote heads known locally
433 all remote heads known locally
434 listing keys for "phases"
434 listing keys for "phases"
435 checking for updated bookmarks
435 checking for updated bookmarks
436 listing keys for "bookmarks"
436 listing keys for "bookmarks"
437 invalid branchheads cache (served): tip differs
437 invalid branchheads cache (served): tip differs
438 listing keys for "bookmarks"
438 listing keys for "bookmarks"
439 3 changesets found
439 3 changesets found
440 list of changesets:
440 list of changesets:
441 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
441 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
442 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
442 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
443 911600dab2ae7a9baff75958b84fe606851ce955
443 911600dab2ae7a9baff75958b84fe606851ce955
444 bundle2-output-bundle: "HG20", 4 parts total
444 bundle2-output-bundle: "HG20", 4 parts total
445 bundle2-output-part: "replycaps" 93 bytes payload
445 bundle2-output-part: "replycaps" 106 bytes payload
446 bundle2-output-part: "check:heads" streamed payload
446 bundle2-output-part: "check:heads" streamed payload
447 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
447 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
448 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
448 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
449 bundle2-input-bundle: with-transaction
449 bundle2-input-bundle: with-transaction
450 bundle2-input-part: "replycaps" supported
450 bundle2-input-part: "replycaps" supported
451 bundle2-input-part: total payload size 93
451 bundle2-input-part: total payload size 106
452 bundle2-input-part: "check:heads" supported
452 bundle2-input-part: "check:heads" supported
453 bundle2-input-part: total payload size 20
453 bundle2-input-part: total payload size 20
454 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
454 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
455 adding changesets
455 adding changesets
456 add changeset ef1ea85a6374
456 add changeset ef1ea85a6374
457 add changeset f9cafe1212c8
457 add changeset f9cafe1212c8
458 add changeset 911600dab2ae
458 add changeset 911600dab2ae
459 adding manifests
459 adding manifests
460 adding file changes
460 adding file changes
461 adding foo/Bar/file.txt revisions
461 adding foo/Bar/file.txt revisions
462 adding foo/file.txt revisions
462 adding foo/file.txt revisions
463 adding quux/file.py revisions
463 adding quux/file.py revisions
464 added 3 changesets with 3 changes to 3 files
464 added 3 changesets with 3 changes to 3 files
465 calling hook pretxnchangegroup.acl: hgext.acl.hook
465 calling hook pretxnchangegroup.acl: hgext.acl.hook
466 acl: checking access for user "barney"
466 acl: checking access for user "barney"
467 acl: acl.allow.branches not enabled
467 acl: acl.allow.branches not enabled
468 acl: acl.deny.branches not enabled
468 acl: acl.deny.branches not enabled
469 acl: acl.allow enabled, 0 entries for user barney
469 acl: acl.allow enabled, 0 entries for user barney
470 acl: acl.deny enabled, 0 entries for user barney
470 acl: acl.deny enabled, 0 entries for user barney
471 acl: branch access granted: "ef1ea85a6374" on branch "default"
471 acl: branch access granted: "ef1ea85a6374" on branch "default"
472 error: pretxnchangegroup.acl hook failed: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
472 error: pretxnchangegroup.acl hook failed: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
473 bundle2-input-part: total payload size 1606
473 bundle2-input-part: total payload size 1606
474 bundle2-input-bundle: 3 parts total
474 bundle2-input-bundle: 3 parts total
475 transaction abort!
475 transaction abort!
476 rollback completed
476 rollback completed
477 abort: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
477 abort: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
478 no rollback information available
478 no rollback information available
479 0:6675d58eff77
479 0:6675d58eff77
480
480
481
481
482 fred is allowed inside foo/, but not foo/bar/ (case matters)
482 fred is allowed inside foo/, but not foo/bar/ (case matters)
483
483
484 $ echo 'foo/bar/** = fred' >> $config
484 $ echo 'foo/bar/** = fred' >> $config
485 $ do_push fred
485 $ do_push fred
486 Pushing as user fred
486 Pushing as user fred
487 hgrc = """
487 hgrc = """
488 [hooks]
488 [hooks]
489 pretxnchangegroup.acl = python:hgext.acl.hook
489 pretxnchangegroup.acl = python:hgext.acl.hook
490 [acl]
490 [acl]
491 sources = push
491 sources = push
492 [acl.allow]
492 [acl.allow]
493 foo/** = fred
493 foo/** = fred
494 [acl.deny]
494 [acl.deny]
495 foo/bar/** = fred
495 foo/bar/** = fred
496 """
496 """
497 pushing to ../b
497 pushing to ../b
498 query 1; heads
498 query 1; heads
499 searching for changes
499 searching for changes
500 all remote heads known locally
500 all remote heads known locally
501 listing keys for "phases"
501 listing keys for "phases"
502 checking for updated bookmarks
502 checking for updated bookmarks
503 listing keys for "bookmarks"
503 listing keys for "bookmarks"
504 invalid branchheads cache (served): tip differs
504 invalid branchheads cache (served): tip differs
505 listing keys for "bookmarks"
505 listing keys for "bookmarks"
506 3 changesets found
506 3 changesets found
507 list of changesets:
507 list of changesets:
508 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
508 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
509 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
509 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
510 911600dab2ae7a9baff75958b84fe606851ce955
510 911600dab2ae7a9baff75958b84fe606851ce955
511 bundle2-output-bundle: "HG20", 4 parts total
511 bundle2-output-bundle: "HG20", 4 parts total
512 bundle2-output-part: "replycaps" 93 bytes payload
512 bundle2-output-part: "replycaps" 106 bytes payload
513 bundle2-output-part: "check:heads" streamed payload
513 bundle2-output-part: "check:heads" streamed payload
514 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
514 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
515 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
515 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
516 bundle2-input-bundle: with-transaction
516 bundle2-input-bundle: with-transaction
517 bundle2-input-part: "replycaps" supported
517 bundle2-input-part: "replycaps" supported
518 bundle2-input-part: total payload size 93
518 bundle2-input-part: total payload size 106
519 bundle2-input-part: "check:heads" supported
519 bundle2-input-part: "check:heads" supported
520 bundle2-input-part: total payload size 20
520 bundle2-input-part: total payload size 20
521 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
521 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
522 adding changesets
522 adding changesets
523 add changeset ef1ea85a6374
523 add changeset ef1ea85a6374
524 add changeset f9cafe1212c8
524 add changeset f9cafe1212c8
525 add changeset 911600dab2ae
525 add changeset 911600dab2ae
526 adding manifests
526 adding manifests
527 adding file changes
527 adding file changes
528 adding foo/Bar/file.txt revisions
528 adding foo/Bar/file.txt revisions
529 adding foo/file.txt revisions
529 adding foo/file.txt revisions
530 adding quux/file.py revisions
530 adding quux/file.py revisions
531 added 3 changesets with 3 changes to 3 files
531 added 3 changesets with 3 changes to 3 files
532 calling hook pretxnchangegroup.acl: hgext.acl.hook
532 calling hook pretxnchangegroup.acl: hgext.acl.hook
533 acl: checking access for user "fred"
533 acl: checking access for user "fred"
534 acl: acl.allow.branches not enabled
534 acl: acl.allow.branches not enabled
535 acl: acl.deny.branches not enabled
535 acl: acl.deny.branches not enabled
536 acl: acl.allow enabled, 1 entries for user fred
536 acl: acl.allow enabled, 1 entries for user fred
537 acl: acl.deny enabled, 1 entries for user fred
537 acl: acl.deny enabled, 1 entries for user fred
538 acl: branch access granted: "ef1ea85a6374" on branch "default"
538 acl: branch access granted: "ef1ea85a6374" on branch "default"
539 acl: path access granted: "ef1ea85a6374"
539 acl: path access granted: "ef1ea85a6374"
540 acl: branch access granted: "f9cafe1212c8" on branch "default"
540 acl: branch access granted: "f9cafe1212c8" on branch "default"
541 acl: path access granted: "f9cafe1212c8"
541 acl: path access granted: "f9cafe1212c8"
542 acl: branch access granted: "911600dab2ae" on branch "default"
542 acl: branch access granted: "911600dab2ae" on branch "default"
543 error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
543 error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
544 bundle2-input-part: total payload size 1606
544 bundle2-input-part: total payload size 1606
545 bundle2-input-bundle: 3 parts total
545 bundle2-input-bundle: 3 parts total
546 transaction abort!
546 transaction abort!
547 rollback completed
547 rollback completed
548 abort: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
548 abort: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
549 no rollback information available
549 no rollback information available
550 0:6675d58eff77
550 0:6675d58eff77
551
551
552
552
553 fred is allowed inside foo/, but not foo/Bar/
553 fred is allowed inside foo/, but not foo/Bar/
554
554
555 $ echo 'foo/Bar/** = fred' >> $config
555 $ echo 'foo/Bar/** = fred' >> $config
556 $ do_push fred
556 $ do_push fred
557 Pushing as user fred
557 Pushing as user fred
558 hgrc = """
558 hgrc = """
559 [hooks]
559 [hooks]
560 pretxnchangegroup.acl = python:hgext.acl.hook
560 pretxnchangegroup.acl = python:hgext.acl.hook
561 [acl]
561 [acl]
562 sources = push
562 sources = push
563 [acl.allow]
563 [acl.allow]
564 foo/** = fred
564 foo/** = fred
565 [acl.deny]
565 [acl.deny]
566 foo/bar/** = fred
566 foo/bar/** = fred
567 foo/Bar/** = fred
567 foo/Bar/** = fred
568 """
568 """
569 pushing to ../b
569 pushing to ../b
570 query 1; heads
570 query 1; heads
571 searching for changes
571 searching for changes
572 all remote heads known locally
572 all remote heads known locally
573 listing keys for "phases"
573 listing keys for "phases"
574 checking for updated bookmarks
574 checking for updated bookmarks
575 listing keys for "bookmarks"
575 listing keys for "bookmarks"
576 invalid branchheads cache (served): tip differs
576 invalid branchheads cache (served): tip differs
577 listing keys for "bookmarks"
577 listing keys for "bookmarks"
578 3 changesets found
578 3 changesets found
579 list of changesets:
579 list of changesets:
580 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
580 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
581 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
581 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
582 911600dab2ae7a9baff75958b84fe606851ce955
582 911600dab2ae7a9baff75958b84fe606851ce955
583 bundle2-output-bundle: "HG20", 4 parts total
583 bundle2-output-bundle: "HG20", 4 parts total
584 bundle2-output-part: "replycaps" 93 bytes payload
584 bundle2-output-part: "replycaps" 106 bytes payload
585 bundle2-output-part: "check:heads" streamed payload
585 bundle2-output-part: "check:heads" streamed payload
586 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
586 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
587 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
587 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
588 bundle2-input-bundle: with-transaction
588 bundle2-input-bundle: with-transaction
589 bundle2-input-part: "replycaps" supported
589 bundle2-input-part: "replycaps" supported
590 bundle2-input-part: total payload size 93
590 bundle2-input-part: total payload size 106
591 bundle2-input-part: "check:heads" supported
591 bundle2-input-part: "check:heads" supported
592 bundle2-input-part: total payload size 20
592 bundle2-input-part: total payload size 20
593 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
593 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
594 adding changesets
594 adding changesets
595 add changeset ef1ea85a6374
595 add changeset ef1ea85a6374
596 add changeset f9cafe1212c8
596 add changeset f9cafe1212c8
597 add changeset 911600dab2ae
597 add changeset 911600dab2ae
598 adding manifests
598 adding manifests
599 adding file changes
599 adding file changes
600 adding foo/Bar/file.txt revisions
600 adding foo/Bar/file.txt revisions
601 adding foo/file.txt revisions
601 adding foo/file.txt revisions
602 adding quux/file.py revisions
602 adding quux/file.py revisions
603 added 3 changesets with 3 changes to 3 files
603 added 3 changesets with 3 changes to 3 files
604 calling hook pretxnchangegroup.acl: hgext.acl.hook
604 calling hook pretxnchangegroup.acl: hgext.acl.hook
605 acl: checking access for user "fred"
605 acl: checking access for user "fred"
606 acl: acl.allow.branches not enabled
606 acl: acl.allow.branches not enabled
607 acl: acl.deny.branches not enabled
607 acl: acl.deny.branches not enabled
608 acl: acl.allow enabled, 1 entries for user fred
608 acl: acl.allow enabled, 1 entries for user fred
609 acl: acl.deny enabled, 2 entries for user fred
609 acl: acl.deny enabled, 2 entries for user fred
610 acl: branch access granted: "ef1ea85a6374" on branch "default"
610 acl: branch access granted: "ef1ea85a6374" on branch "default"
611 acl: path access granted: "ef1ea85a6374"
611 acl: path access granted: "ef1ea85a6374"
612 acl: branch access granted: "f9cafe1212c8" on branch "default"
612 acl: branch access granted: "f9cafe1212c8" on branch "default"
613 error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
613 error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
614 bundle2-input-part: total payload size 1606
614 bundle2-input-part: total payload size 1606
615 bundle2-input-bundle: 3 parts total
615 bundle2-input-bundle: 3 parts total
616 transaction abort!
616 transaction abort!
617 rollback completed
617 rollback completed
618 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
618 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
619 no rollback information available
619 no rollback information available
620 0:6675d58eff77
620 0:6675d58eff77
621
621
622
622
623 $ echo 'barney is not mentioned => not allowed anywhere'
623 $ echo 'barney is not mentioned => not allowed anywhere'
624 barney is not mentioned => not allowed anywhere
624 barney is not mentioned => not allowed anywhere
625 $ do_push barney
625 $ do_push barney
626 Pushing as user barney
626 Pushing as user barney
627 hgrc = """
627 hgrc = """
628 [hooks]
628 [hooks]
629 pretxnchangegroup.acl = python:hgext.acl.hook
629 pretxnchangegroup.acl = python:hgext.acl.hook
630 [acl]
630 [acl]
631 sources = push
631 sources = push
632 [acl.allow]
632 [acl.allow]
633 foo/** = fred
633 foo/** = fred
634 [acl.deny]
634 [acl.deny]
635 foo/bar/** = fred
635 foo/bar/** = fred
636 foo/Bar/** = fred
636 foo/Bar/** = fred
637 """
637 """
638 pushing to ../b
638 pushing to ../b
639 query 1; heads
639 query 1; heads
640 searching for changes
640 searching for changes
641 all remote heads known locally
641 all remote heads known locally
642 listing keys for "phases"
642 listing keys for "phases"
643 checking for updated bookmarks
643 checking for updated bookmarks
644 listing keys for "bookmarks"
644 listing keys for "bookmarks"
645 invalid branchheads cache (served): tip differs
645 invalid branchheads cache (served): tip differs
646 listing keys for "bookmarks"
646 listing keys for "bookmarks"
647 3 changesets found
647 3 changesets found
648 list of changesets:
648 list of changesets:
649 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
649 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
650 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
650 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
651 911600dab2ae7a9baff75958b84fe606851ce955
651 911600dab2ae7a9baff75958b84fe606851ce955
652 bundle2-output-bundle: "HG20", 4 parts total
652 bundle2-output-bundle: "HG20", 4 parts total
653 bundle2-output-part: "replycaps" 93 bytes payload
653 bundle2-output-part: "replycaps" 106 bytes payload
654 bundle2-output-part: "check:heads" streamed payload
654 bundle2-output-part: "check:heads" streamed payload
655 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
655 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
656 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
656 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
657 bundle2-input-bundle: with-transaction
657 bundle2-input-bundle: with-transaction
658 bundle2-input-part: "replycaps" supported
658 bundle2-input-part: "replycaps" supported
659 bundle2-input-part: total payload size 93
659 bundle2-input-part: total payload size 106
660 bundle2-input-part: "check:heads" supported
660 bundle2-input-part: "check:heads" supported
661 bundle2-input-part: total payload size 20
661 bundle2-input-part: total payload size 20
662 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
662 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
663 adding changesets
663 adding changesets
664 add changeset ef1ea85a6374
664 add changeset ef1ea85a6374
665 add changeset f9cafe1212c8
665 add changeset f9cafe1212c8
666 add changeset 911600dab2ae
666 add changeset 911600dab2ae
667 adding manifests
667 adding manifests
668 adding file changes
668 adding file changes
669 adding foo/Bar/file.txt revisions
669 adding foo/Bar/file.txt revisions
670 adding foo/file.txt revisions
670 adding foo/file.txt revisions
671 adding quux/file.py revisions
671 adding quux/file.py revisions
672 added 3 changesets with 3 changes to 3 files
672 added 3 changesets with 3 changes to 3 files
673 calling hook pretxnchangegroup.acl: hgext.acl.hook
673 calling hook pretxnchangegroup.acl: hgext.acl.hook
674 acl: checking access for user "barney"
674 acl: checking access for user "barney"
675 acl: acl.allow.branches not enabled
675 acl: acl.allow.branches not enabled
676 acl: acl.deny.branches not enabled
676 acl: acl.deny.branches not enabled
677 acl: acl.allow enabled, 0 entries for user barney
677 acl: acl.allow enabled, 0 entries for user barney
678 acl: acl.deny enabled, 0 entries for user barney
678 acl: acl.deny enabled, 0 entries for user barney
679 acl: branch access granted: "ef1ea85a6374" on branch "default"
679 acl: branch access granted: "ef1ea85a6374" on branch "default"
680 error: pretxnchangegroup.acl hook failed: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
680 error: pretxnchangegroup.acl hook failed: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
681 bundle2-input-part: total payload size 1606
681 bundle2-input-part: total payload size 1606
682 bundle2-input-bundle: 3 parts total
682 bundle2-input-bundle: 3 parts total
683 transaction abort!
683 transaction abort!
684 rollback completed
684 rollback completed
685 abort: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
685 abort: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
686 no rollback information available
686 no rollback information available
687 0:6675d58eff77
687 0:6675d58eff77
688
688
689
689
690 barney is allowed everywhere
690 barney is allowed everywhere
691
691
692 $ echo '[acl.allow]' >> $config
692 $ echo '[acl.allow]' >> $config
693 $ echo '** = barney' >> $config
693 $ echo '** = barney' >> $config
694 $ do_push barney
694 $ do_push barney
695 Pushing as user barney
695 Pushing as user barney
696 hgrc = """
696 hgrc = """
697 [hooks]
697 [hooks]
698 pretxnchangegroup.acl = python:hgext.acl.hook
698 pretxnchangegroup.acl = python:hgext.acl.hook
699 [acl]
699 [acl]
700 sources = push
700 sources = push
701 [acl.allow]
701 [acl.allow]
702 foo/** = fred
702 foo/** = fred
703 [acl.deny]
703 [acl.deny]
704 foo/bar/** = fred
704 foo/bar/** = fred
705 foo/Bar/** = fred
705 foo/Bar/** = fred
706 [acl.allow]
706 [acl.allow]
707 ** = barney
707 ** = barney
708 """
708 """
709 pushing to ../b
709 pushing to ../b
710 query 1; heads
710 query 1; heads
711 searching for changes
711 searching for changes
712 all remote heads known locally
712 all remote heads known locally
713 listing keys for "phases"
713 listing keys for "phases"
714 checking for updated bookmarks
714 checking for updated bookmarks
715 listing keys for "bookmarks"
715 listing keys for "bookmarks"
716 invalid branchheads cache (served): tip differs
716 invalid branchheads cache (served): tip differs
717 listing keys for "bookmarks"
717 listing keys for "bookmarks"
718 3 changesets found
718 3 changesets found
719 list of changesets:
719 list of changesets:
720 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
720 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
721 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
721 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
722 911600dab2ae7a9baff75958b84fe606851ce955
722 911600dab2ae7a9baff75958b84fe606851ce955
723 bundle2-output-bundle: "HG20", 4 parts total
723 bundle2-output-bundle: "HG20", 4 parts total
724 bundle2-output-part: "replycaps" 93 bytes payload
724 bundle2-output-part: "replycaps" 106 bytes payload
725 bundle2-output-part: "check:heads" streamed payload
725 bundle2-output-part: "check:heads" streamed payload
726 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
726 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
727 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
727 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
728 bundle2-input-bundle: with-transaction
728 bundle2-input-bundle: with-transaction
729 bundle2-input-part: "replycaps" supported
729 bundle2-input-part: "replycaps" supported
730 bundle2-input-part: total payload size 93
730 bundle2-input-part: total payload size 106
731 bundle2-input-part: "check:heads" supported
731 bundle2-input-part: "check:heads" supported
732 bundle2-input-part: total payload size 20
732 bundle2-input-part: total payload size 20
733 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
733 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
734 adding changesets
734 adding changesets
735 add changeset ef1ea85a6374
735 add changeset ef1ea85a6374
736 add changeset f9cafe1212c8
736 add changeset f9cafe1212c8
737 add changeset 911600dab2ae
737 add changeset 911600dab2ae
738 adding manifests
738 adding manifests
739 adding file changes
739 adding file changes
740 adding foo/Bar/file.txt revisions
740 adding foo/Bar/file.txt revisions
741 adding foo/file.txt revisions
741 adding foo/file.txt revisions
742 adding quux/file.py revisions
742 adding quux/file.py revisions
743 added 3 changesets with 3 changes to 3 files
743 added 3 changesets with 3 changes to 3 files
744 calling hook pretxnchangegroup.acl: hgext.acl.hook
744 calling hook pretxnchangegroup.acl: hgext.acl.hook
745 acl: checking access for user "barney"
745 acl: checking access for user "barney"
746 acl: acl.allow.branches not enabled
746 acl: acl.allow.branches not enabled
747 acl: acl.deny.branches not enabled
747 acl: acl.deny.branches not enabled
748 acl: acl.allow enabled, 1 entries for user barney
748 acl: acl.allow enabled, 1 entries for user barney
749 acl: acl.deny enabled, 0 entries for user barney
749 acl: acl.deny enabled, 0 entries for user barney
750 acl: branch access granted: "ef1ea85a6374" on branch "default"
750 acl: branch access granted: "ef1ea85a6374" on branch "default"
751 acl: path access granted: "ef1ea85a6374"
751 acl: path access granted: "ef1ea85a6374"
752 acl: branch access granted: "f9cafe1212c8" on branch "default"
752 acl: branch access granted: "f9cafe1212c8" on branch "default"
753 acl: path access granted: "f9cafe1212c8"
753 acl: path access granted: "f9cafe1212c8"
754 acl: branch access granted: "911600dab2ae" on branch "default"
754 acl: branch access granted: "911600dab2ae" on branch "default"
755 acl: path access granted: "911600dab2ae"
755 acl: path access granted: "911600dab2ae"
756 bundle2-input-part: total payload size 1606
756 bundle2-input-part: total payload size 1606
757 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
757 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
758 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
758 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
759 bundle2-input-bundle: 3 parts total
759 bundle2-input-bundle: 3 parts total
760 updating the branch cache
760 updating the branch cache
761 bundle2-output-bundle: "HG20", 2 parts total
761 bundle2-output-bundle: "HG20", 2 parts total
762 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
762 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
763 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
763 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
764 bundle2-input-bundle: with-transaction
764 bundle2-input-bundle: with-transaction
765 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
765 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
766 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
766 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
767 bundle2-input-bundle: 1 parts total
767 bundle2-input-bundle: 1 parts total
768 listing keys for "phases"
768 listing keys for "phases"
769 try to push obsolete markers to remote
769 try to push obsolete markers to remote
770 repository tip rolled back to revision 0 (undo push)
770 repository tip rolled back to revision 0 (undo push)
771 0:6675d58eff77
771 0:6675d58eff77
772
772
773
773
774 wilma can change files with a .txt extension
774 wilma can change files with a .txt extension
775
775
776 $ echo '**/*.txt = wilma' >> $config
776 $ echo '**/*.txt = wilma' >> $config
777 $ do_push wilma
777 $ do_push wilma
778 Pushing as user wilma
778 Pushing as user wilma
779 hgrc = """
779 hgrc = """
780 [hooks]
780 [hooks]
781 pretxnchangegroup.acl = python:hgext.acl.hook
781 pretxnchangegroup.acl = python:hgext.acl.hook
782 [acl]
782 [acl]
783 sources = push
783 sources = push
784 [acl.allow]
784 [acl.allow]
785 foo/** = fred
785 foo/** = fred
786 [acl.deny]
786 [acl.deny]
787 foo/bar/** = fred
787 foo/bar/** = fred
788 foo/Bar/** = fred
788 foo/Bar/** = fred
789 [acl.allow]
789 [acl.allow]
790 ** = barney
790 ** = barney
791 **/*.txt = wilma
791 **/*.txt = wilma
792 """
792 """
793 pushing to ../b
793 pushing to ../b
794 query 1; heads
794 query 1; heads
795 searching for changes
795 searching for changes
796 all remote heads known locally
796 all remote heads known locally
797 listing keys for "phases"
797 listing keys for "phases"
798 checking for updated bookmarks
798 checking for updated bookmarks
799 listing keys for "bookmarks"
799 listing keys for "bookmarks"
800 invalid branchheads cache (served): tip differs
800 invalid branchheads cache (served): tip differs
801 listing keys for "bookmarks"
801 listing keys for "bookmarks"
802 3 changesets found
802 3 changesets found
803 list of changesets:
803 list of changesets:
804 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
804 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
805 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
805 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
806 911600dab2ae7a9baff75958b84fe606851ce955
806 911600dab2ae7a9baff75958b84fe606851ce955
807 bundle2-output-bundle: "HG20", 4 parts total
807 bundle2-output-bundle: "HG20", 4 parts total
808 bundle2-output-part: "replycaps" 93 bytes payload
808 bundle2-output-part: "replycaps" 106 bytes payload
809 bundle2-output-part: "check:heads" streamed payload
809 bundle2-output-part: "check:heads" streamed payload
810 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
810 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
811 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
811 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
812 bundle2-input-bundle: with-transaction
812 bundle2-input-bundle: with-transaction
813 bundle2-input-part: "replycaps" supported
813 bundle2-input-part: "replycaps" supported
814 bundle2-input-part: total payload size 93
814 bundle2-input-part: total payload size 106
815 bundle2-input-part: "check:heads" supported
815 bundle2-input-part: "check:heads" supported
816 bundle2-input-part: total payload size 20
816 bundle2-input-part: total payload size 20
817 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
817 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
818 adding changesets
818 adding changesets
819 add changeset ef1ea85a6374
819 add changeset ef1ea85a6374
820 add changeset f9cafe1212c8
820 add changeset f9cafe1212c8
821 add changeset 911600dab2ae
821 add changeset 911600dab2ae
822 adding manifests
822 adding manifests
823 adding file changes
823 adding file changes
824 adding foo/Bar/file.txt revisions
824 adding foo/Bar/file.txt revisions
825 adding foo/file.txt revisions
825 adding foo/file.txt revisions
826 adding quux/file.py revisions
826 adding quux/file.py revisions
827 added 3 changesets with 3 changes to 3 files
827 added 3 changesets with 3 changes to 3 files
828 calling hook pretxnchangegroup.acl: hgext.acl.hook
828 calling hook pretxnchangegroup.acl: hgext.acl.hook
829 acl: checking access for user "wilma"
829 acl: checking access for user "wilma"
830 acl: acl.allow.branches not enabled
830 acl: acl.allow.branches not enabled
831 acl: acl.deny.branches not enabled
831 acl: acl.deny.branches not enabled
832 acl: acl.allow enabled, 1 entries for user wilma
832 acl: acl.allow enabled, 1 entries for user wilma
833 acl: acl.deny enabled, 0 entries for user wilma
833 acl: acl.deny enabled, 0 entries for user wilma
834 acl: branch access granted: "ef1ea85a6374" on branch "default"
834 acl: branch access granted: "ef1ea85a6374" on branch "default"
835 acl: path access granted: "ef1ea85a6374"
835 acl: path access granted: "ef1ea85a6374"
836 acl: branch access granted: "f9cafe1212c8" on branch "default"
836 acl: branch access granted: "f9cafe1212c8" on branch "default"
837 acl: path access granted: "f9cafe1212c8"
837 acl: path access granted: "f9cafe1212c8"
838 acl: branch access granted: "911600dab2ae" on branch "default"
838 acl: branch access granted: "911600dab2ae" on branch "default"
839 error: pretxnchangegroup.acl hook failed: acl: user "wilma" not allowed on "quux/file.py" (changeset "911600dab2ae")
839 error: pretxnchangegroup.acl hook failed: acl: user "wilma" not allowed on "quux/file.py" (changeset "911600dab2ae")
840 bundle2-input-part: total payload size 1606
840 bundle2-input-part: total payload size 1606
841 bundle2-input-bundle: 3 parts total
841 bundle2-input-bundle: 3 parts total
842 transaction abort!
842 transaction abort!
843 rollback completed
843 rollback completed
844 abort: acl: user "wilma" not allowed on "quux/file.py" (changeset "911600dab2ae")
844 abort: acl: user "wilma" not allowed on "quux/file.py" (changeset "911600dab2ae")
845 no rollback information available
845 no rollback information available
846 0:6675d58eff77
846 0:6675d58eff77
847
847
848
848
849 file specified by acl.config does not exist
849 file specified by acl.config does not exist
850
850
851 $ echo '[acl]' >> $config
851 $ echo '[acl]' >> $config
852 $ echo 'config = ../acl.config' >> $config
852 $ echo 'config = ../acl.config' >> $config
853 $ do_push barney
853 $ do_push barney
854 Pushing as user barney
854 Pushing as user barney
855 hgrc = """
855 hgrc = """
856 [hooks]
856 [hooks]
857 pretxnchangegroup.acl = python:hgext.acl.hook
857 pretxnchangegroup.acl = python:hgext.acl.hook
858 [acl]
858 [acl]
859 sources = push
859 sources = push
860 [acl.allow]
860 [acl.allow]
861 foo/** = fred
861 foo/** = fred
862 [acl.deny]
862 [acl.deny]
863 foo/bar/** = fred
863 foo/bar/** = fred
864 foo/Bar/** = fred
864 foo/Bar/** = fred
865 [acl.allow]
865 [acl.allow]
866 ** = barney
866 ** = barney
867 **/*.txt = wilma
867 **/*.txt = wilma
868 [acl]
868 [acl]
869 config = ../acl.config
869 config = ../acl.config
870 """
870 """
871 pushing to ../b
871 pushing to ../b
872 query 1; heads
872 query 1; heads
873 searching for changes
873 searching for changes
874 all remote heads known locally
874 all remote heads known locally
875 listing keys for "phases"
875 listing keys for "phases"
876 checking for updated bookmarks
876 checking for updated bookmarks
877 listing keys for "bookmarks"
877 listing keys for "bookmarks"
878 invalid branchheads cache (served): tip differs
878 invalid branchheads cache (served): tip differs
879 listing keys for "bookmarks"
879 listing keys for "bookmarks"
880 3 changesets found
880 3 changesets found
881 list of changesets:
881 list of changesets:
882 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
882 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
883 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
883 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
884 911600dab2ae7a9baff75958b84fe606851ce955
884 911600dab2ae7a9baff75958b84fe606851ce955
885 bundle2-output-bundle: "HG20", 4 parts total
885 bundle2-output-bundle: "HG20", 4 parts total
886 bundle2-output-part: "replycaps" 93 bytes payload
886 bundle2-output-part: "replycaps" 106 bytes payload
887 bundle2-output-part: "check:heads" streamed payload
887 bundle2-output-part: "check:heads" streamed payload
888 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
888 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
889 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
889 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
890 bundle2-input-bundle: with-transaction
890 bundle2-input-bundle: with-transaction
891 bundle2-input-part: "replycaps" supported
891 bundle2-input-part: "replycaps" supported
892 bundle2-input-part: total payload size 93
892 bundle2-input-part: total payload size 106
893 bundle2-input-part: "check:heads" supported
893 bundle2-input-part: "check:heads" supported
894 bundle2-input-part: total payload size 20
894 bundle2-input-part: total payload size 20
895 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
895 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
896 adding changesets
896 adding changesets
897 add changeset ef1ea85a6374
897 add changeset ef1ea85a6374
898 add changeset f9cafe1212c8
898 add changeset f9cafe1212c8
899 add changeset 911600dab2ae
899 add changeset 911600dab2ae
900 adding manifests
900 adding manifests
901 adding file changes
901 adding file changes
902 adding foo/Bar/file.txt revisions
902 adding foo/Bar/file.txt revisions
903 adding foo/file.txt revisions
903 adding foo/file.txt revisions
904 adding quux/file.py revisions
904 adding quux/file.py revisions
905 added 3 changesets with 3 changes to 3 files
905 added 3 changesets with 3 changes to 3 files
906 calling hook pretxnchangegroup.acl: hgext.acl.hook
906 calling hook pretxnchangegroup.acl: hgext.acl.hook
907 acl: checking access for user "barney"
907 acl: checking access for user "barney"
908 error: pretxnchangegroup.acl hook raised an exception: [Errno 2] No such file or directory: '../acl.config'
908 error: pretxnchangegroup.acl hook raised an exception: [Errno 2] No such file or directory: '../acl.config'
909 bundle2-input-part: total payload size 1606
909 bundle2-input-part: total payload size 1606
910 bundle2-input-bundle: 3 parts total
910 bundle2-input-bundle: 3 parts total
911 transaction abort!
911 transaction abort!
912 rollback completed
912 rollback completed
913 abort: No such file or directory: ../acl.config
913 abort: No such file or directory: ../acl.config
914 no rollback information available
914 no rollback information available
915 0:6675d58eff77
915 0:6675d58eff77
916
916
917
917
918 betty is allowed inside foo/ by a acl.config file
918 betty is allowed inside foo/ by a acl.config file
919
919
920 $ echo '[acl.allow]' >> acl.config
920 $ echo '[acl.allow]' >> acl.config
921 $ echo 'foo/** = betty' >> acl.config
921 $ echo 'foo/** = betty' >> acl.config
922 $ do_push betty
922 $ do_push betty
923 Pushing as user betty
923 Pushing as user betty
924 hgrc = """
924 hgrc = """
925 [hooks]
925 [hooks]
926 pretxnchangegroup.acl = python:hgext.acl.hook
926 pretxnchangegroup.acl = python:hgext.acl.hook
927 [acl]
927 [acl]
928 sources = push
928 sources = push
929 [acl.allow]
929 [acl.allow]
930 foo/** = fred
930 foo/** = fred
931 [acl.deny]
931 [acl.deny]
932 foo/bar/** = fred
932 foo/bar/** = fred
933 foo/Bar/** = fred
933 foo/Bar/** = fred
934 [acl.allow]
934 [acl.allow]
935 ** = barney
935 ** = barney
936 **/*.txt = wilma
936 **/*.txt = wilma
937 [acl]
937 [acl]
938 config = ../acl.config
938 config = ../acl.config
939 """
939 """
940 acl.config = """
940 acl.config = """
941 [acl.allow]
941 [acl.allow]
942 foo/** = betty
942 foo/** = betty
943 """
943 """
944 pushing to ../b
944 pushing to ../b
945 query 1; heads
945 query 1; heads
946 searching for changes
946 searching for changes
947 all remote heads known locally
947 all remote heads known locally
948 listing keys for "phases"
948 listing keys for "phases"
949 checking for updated bookmarks
949 checking for updated bookmarks
950 listing keys for "bookmarks"
950 listing keys for "bookmarks"
951 invalid branchheads cache (served): tip differs
951 invalid branchheads cache (served): tip differs
952 listing keys for "bookmarks"
952 listing keys for "bookmarks"
953 3 changesets found
953 3 changesets found
954 list of changesets:
954 list of changesets:
955 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
955 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
956 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
956 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
957 911600dab2ae7a9baff75958b84fe606851ce955
957 911600dab2ae7a9baff75958b84fe606851ce955
958 bundle2-output-bundle: "HG20", 4 parts total
958 bundle2-output-bundle: "HG20", 4 parts total
959 bundle2-output-part: "replycaps" 93 bytes payload
959 bundle2-output-part: "replycaps" 106 bytes payload
960 bundle2-output-part: "check:heads" streamed payload
960 bundle2-output-part: "check:heads" streamed payload
961 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
961 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
962 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
962 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
963 bundle2-input-bundle: with-transaction
963 bundle2-input-bundle: with-transaction
964 bundle2-input-part: "replycaps" supported
964 bundle2-input-part: "replycaps" supported
965 bundle2-input-part: total payload size 93
965 bundle2-input-part: total payload size 106
966 bundle2-input-part: "check:heads" supported
966 bundle2-input-part: "check:heads" supported
967 bundle2-input-part: total payload size 20
967 bundle2-input-part: total payload size 20
968 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
968 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
969 adding changesets
969 adding changesets
970 add changeset ef1ea85a6374
970 add changeset ef1ea85a6374
971 add changeset f9cafe1212c8
971 add changeset f9cafe1212c8
972 add changeset 911600dab2ae
972 add changeset 911600dab2ae
973 adding manifests
973 adding manifests
974 adding file changes
974 adding file changes
975 adding foo/Bar/file.txt revisions
975 adding foo/Bar/file.txt revisions
976 adding foo/file.txt revisions
976 adding foo/file.txt revisions
977 adding quux/file.py revisions
977 adding quux/file.py revisions
978 added 3 changesets with 3 changes to 3 files
978 added 3 changesets with 3 changes to 3 files
979 calling hook pretxnchangegroup.acl: hgext.acl.hook
979 calling hook pretxnchangegroup.acl: hgext.acl.hook
980 acl: checking access for user "betty"
980 acl: checking access for user "betty"
981 acl: acl.allow.branches not enabled
981 acl: acl.allow.branches not enabled
982 acl: acl.deny.branches not enabled
982 acl: acl.deny.branches not enabled
983 acl: acl.allow enabled, 1 entries for user betty
983 acl: acl.allow enabled, 1 entries for user betty
984 acl: acl.deny enabled, 0 entries for user betty
984 acl: acl.deny enabled, 0 entries for user betty
985 acl: branch access granted: "ef1ea85a6374" on branch "default"
985 acl: branch access granted: "ef1ea85a6374" on branch "default"
986 acl: path access granted: "ef1ea85a6374"
986 acl: path access granted: "ef1ea85a6374"
987 acl: branch access granted: "f9cafe1212c8" on branch "default"
987 acl: branch access granted: "f9cafe1212c8" on branch "default"
988 acl: path access granted: "f9cafe1212c8"
988 acl: path access granted: "f9cafe1212c8"
989 acl: branch access granted: "911600dab2ae" on branch "default"
989 acl: branch access granted: "911600dab2ae" on branch "default"
990 error: pretxnchangegroup.acl hook failed: acl: user "betty" not allowed on "quux/file.py" (changeset "911600dab2ae")
990 error: pretxnchangegroup.acl hook failed: acl: user "betty" not allowed on "quux/file.py" (changeset "911600dab2ae")
991 bundle2-input-part: total payload size 1606
991 bundle2-input-part: total payload size 1606
992 bundle2-input-bundle: 3 parts total
992 bundle2-input-bundle: 3 parts total
993 transaction abort!
993 transaction abort!
994 rollback completed
994 rollback completed
995 abort: acl: user "betty" not allowed on "quux/file.py" (changeset "911600dab2ae")
995 abort: acl: user "betty" not allowed on "quux/file.py" (changeset "911600dab2ae")
996 no rollback information available
996 no rollback information available
997 0:6675d58eff77
997 0:6675d58eff77
998
998
999
999
1000 acl.config can set only [acl.allow]/[acl.deny]
1000 acl.config can set only [acl.allow]/[acl.deny]
1001
1001
1002 $ echo '[hooks]' >> acl.config
1002 $ echo '[hooks]' >> acl.config
1003 $ echo 'changegroup.acl = false' >> acl.config
1003 $ echo 'changegroup.acl = false' >> acl.config
1004 $ do_push barney
1004 $ do_push barney
1005 Pushing as user barney
1005 Pushing as user barney
1006 hgrc = """
1006 hgrc = """
1007 [hooks]
1007 [hooks]
1008 pretxnchangegroup.acl = python:hgext.acl.hook
1008 pretxnchangegroup.acl = python:hgext.acl.hook
1009 [acl]
1009 [acl]
1010 sources = push
1010 sources = push
1011 [acl.allow]
1011 [acl.allow]
1012 foo/** = fred
1012 foo/** = fred
1013 [acl.deny]
1013 [acl.deny]
1014 foo/bar/** = fred
1014 foo/bar/** = fred
1015 foo/Bar/** = fred
1015 foo/Bar/** = fred
1016 [acl.allow]
1016 [acl.allow]
1017 ** = barney
1017 ** = barney
1018 **/*.txt = wilma
1018 **/*.txt = wilma
1019 [acl]
1019 [acl]
1020 config = ../acl.config
1020 config = ../acl.config
1021 """
1021 """
1022 acl.config = """
1022 acl.config = """
1023 [acl.allow]
1023 [acl.allow]
1024 foo/** = betty
1024 foo/** = betty
1025 [hooks]
1025 [hooks]
1026 changegroup.acl = false
1026 changegroup.acl = false
1027 """
1027 """
1028 pushing to ../b
1028 pushing to ../b
1029 query 1; heads
1029 query 1; heads
1030 searching for changes
1030 searching for changes
1031 all remote heads known locally
1031 all remote heads known locally
1032 listing keys for "phases"
1032 listing keys for "phases"
1033 checking for updated bookmarks
1033 checking for updated bookmarks
1034 listing keys for "bookmarks"
1034 listing keys for "bookmarks"
1035 invalid branchheads cache (served): tip differs
1035 invalid branchheads cache (served): tip differs
1036 listing keys for "bookmarks"
1036 listing keys for "bookmarks"
1037 3 changesets found
1037 3 changesets found
1038 list of changesets:
1038 list of changesets:
1039 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1039 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1040 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1040 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1041 911600dab2ae7a9baff75958b84fe606851ce955
1041 911600dab2ae7a9baff75958b84fe606851ce955
1042 bundle2-output-bundle: "HG20", 4 parts total
1042 bundle2-output-bundle: "HG20", 4 parts total
1043 bundle2-output-part: "replycaps" 93 bytes payload
1043 bundle2-output-part: "replycaps" 106 bytes payload
1044 bundle2-output-part: "check:heads" streamed payload
1044 bundle2-output-part: "check:heads" streamed payload
1045 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1045 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1046 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1046 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1047 bundle2-input-bundle: with-transaction
1047 bundle2-input-bundle: with-transaction
1048 bundle2-input-part: "replycaps" supported
1048 bundle2-input-part: "replycaps" supported
1049 bundle2-input-part: total payload size 93
1049 bundle2-input-part: total payload size 106
1050 bundle2-input-part: "check:heads" supported
1050 bundle2-input-part: "check:heads" supported
1051 bundle2-input-part: total payload size 20
1051 bundle2-input-part: total payload size 20
1052 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1052 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1053 adding changesets
1053 adding changesets
1054 add changeset ef1ea85a6374
1054 add changeset ef1ea85a6374
1055 add changeset f9cafe1212c8
1055 add changeset f9cafe1212c8
1056 add changeset 911600dab2ae
1056 add changeset 911600dab2ae
1057 adding manifests
1057 adding manifests
1058 adding file changes
1058 adding file changes
1059 adding foo/Bar/file.txt revisions
1059 adding foo/Bar/file.txt revisions
1060 adding foo/file.txt revisions
1060 adding foo/file.txt revisions
1061 adding quux/file.py revisions
1061 adding quux/file.py revisions
1062 added 3 changesets with 3 changes to 3 files
1062 added 3 changesets with 3 changes to 3 files
1063 calling hook pretxnchangegroup.acl: hgext.acl.hook
1063 calling hook pretxnchangegroup.acl: hgext.acl.hook
1064 acl: checking access for user "barney"
1064 acl: checking access for user "barney"
1065 acl: acl.allow.branches not enabled
1065 acl: acl.allow.branches not enabled
1066 acl: acl.deny.branches not enabled
1066 acl: acl.deny.branches not enabled
1067 acl: acl.allow enabled, 1 entries for user barney
1067 acl: acl.allow enabled, 1 entries for user barney
1068 acl: acl.deny enabled, 0 entries for user barney
1068 acl: acl.deny enabled, 0 entries for user barney
1069 acl: branch access granted: "ef1ea85a6374" on branch "default"
1069 acl: branch access granted: "ef1ea85a6374" on branch "default"
1070 acl: path access granted: "ef1ea85a6374"
1070 acl: path access granted: "ef1ea85a6374"
1071 acl: branch access granted: "f9cafe1212c8" on branch "default"
1071 acl: branch access granted: "f9cafe1212c8" on branch "default"
1072 acl: path access granted: "f9cafe1212c8"
1072 acl: path access granted: "f9cafe1212c8"
1073 acl: branch access granted: "911600dab2ae" on branch "default"
1073 acl: branch access granted: "911600dab2ae" on branch "default"
1074 acl: path access granted: "911600dab2ae"
1074 acl: path access granted: "911600dab2ae"
1075 bundle2-input-part: total payload size 1606
1075 bundle2-input-part: total payload size 1606
1076 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1076 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1077 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1077 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1078 bundle2-input-bundle: 3 parts total
1078 bundle2-input-bundle: 3 parts total
1079 updating the branch cache
1079 updating the branch cache
1080 bundle2-output-bundle: "HG20", 2 parts total
1080 bundle2-output-bundle: "HG20", 2 parts total
1081 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1081 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1082 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1082 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1083 bundle2-input-bundle: with-transaction
1083 bundle2-input-bundle: with-transaction
1084 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1084 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1085 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1085 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1086 bundle2-input-bundle: 1 parts total
1086 bundle2-input-bundle: 1 parts total
1087 listing keys for "phases"
1087 listing keys for "phases"
1088 try to push obsolete markers to remote
1088 try to push obsolete markers to remote
1089 repository tip rolled back to revision 0 (undo push)
1089 repository tip rolled back to revision 0 (undo push)
1090 0:6675d58eff77
1090 0:6675d58eff77
1091
1091
1092
1092
1093 asterisk
1093 asterisk
1094
1094
1095 $ init_config
1095 $ init_config
1096
1096
1097 asterisk test
1097 asterisk test
1098
1098
1099 $ echo '[acl.allow]' >> $config
1099 $ echo '[acl.allow]' >> $config
1100 $ echo "** = fred" >> $config
1100 $ echo "** = fred" >> $config
1101
1101
1102 fred is always allowed
1102 fred is always allowed
1103
1103
1104 $ do_push fred
1104 $ do_push fred
1105 Pushing as user fred
1105 Pushing as user fred
1106 hgrc = """
1106 hgrc = """
1107 [hooks]
1107 [hooks]
1108 pretxnchangegroup.acl = python:hgext.acl.hook
1108 pretxnchangegroup.acl = python:hgext.acl.hook
1109 [acl]
1109 [acl]
1110 sources = push
1110 sources = push
1111 [extensions]
1111 [extensions]
1112 [acl.allow]
1112 [acl.allow]
1113 ** = fred
1113 ** = fred
1114 """
1114 """
1115 pushing to ../b
1115 pushing to ../b
1116 query 1; heads
1116 query 1; heads
1117 searching for changes
1117 searching for changes
1118 all remote heads known locally
1118 all remote heads known locally
1119 listing keys for "phases"
1119 listing keys for "phases"
1120 checking for updated bookmarks
1120 checking for updated bookmarks
1121 listing keys for "bookmarks"
1121 listing keys for "bookmarks"
1122 invalid branchheads cache (served): tip differs
1122 invalid branchheads cache (served): tip differs
1123 listing keys for "bookmarks"
1123 listing keys for "bookmarks"
1124 3 changesets found
1124 3 changesets found
1125 list of changesets:
1125 list of changesets:
1126 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1126 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1127 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1127 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1128 911600dab2ae7a9baff75958b84fe606851ce955
1128 911600dab2ae7a9baff75958b84fe606851ce955
1129 bundle2-output-bundle: "HG20", 4 parts total
1129 bundle2-output-bundle: "HG20", 4 parts total
1130 bundle2-output-part: "replycaps" 93 bytes payload
1130 bundle2-output-part: "replycaps" 106 bytes payload
1131 bundle2-output-part: "check:heads" streamed payload
1131 bundle2-output-part: "check:heads" streamed payload
1132 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1132 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1133 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1133 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1134 bundle2-input-bundle: with-transaction
1134 bundle2-input-bundle: with-transaction
1135 bundle2-input-part: "replycaps" supported
1135 bundle2-input-part: "replycaps" supported
1136 bundle2-input-part: total payload size 93
1136 bundle2-input-part: total payload size 106
1137 bundle2-input-part: "check:heads" supported
1137 bundle2-input-part: "check:heads" supported
1138 bundle2-input-part: total payload size 20
1138 bundle2-input-part: total payload size 20
1139 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1139 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1140 adding changesets
1140 adding changesets
1141 add changeset ef1ea85a6374
1141 add changeset ef1ea85a6374
1142 add changeset f9cafe1212c8
1142 add changeset f9cafe1212c8
1143 add changeset 911600dab2ae
1143 add changeset 911600dab2ae
1144 adding manifests
1144 adding manifests
1145 adding file changes
1145 adding file changes
1146 adding foo/Bar/file.txt revisions
1146 adding foo/Bar/file.txt revisions
1147 adding foo/file.txt revisions
1147 adding foo/file.txt revisions
1148 adding quux/file.py revisions
1148 adding quux/file.py revisions
1149 added 3 changesets with 3 changes to 3 files
1149 added 3 changesets with 3 changes to 3 files
1150 calling hook pretxnchangegroup.acl: hgext.acl.hook
1150 calling hook pretxnchangegroup.acl: hgext.acl.hook
1151 acl: checking access for user "fred"
1151 acl: checking access for user "fred"
1152 acl: acl.allow.branches not enabled
1152 acl: acl.allow.branches not enabled
1153 acl: acl.deny.branches not enabled
1153 acl: acl.deny.branches not enabled
1154 acl: acl.allow enabled, 1 entries for user fred
1154 acl: acl.allow enabled, 1 entries for user fred
1155 acl: acl.deny not enabled
1155 acl: acl.deny not enabled
1156 acl: branch access granted: "ef1ea85a6374" on branch "default"
1156 acl: branch access granted: "ef1ea85a6374" on branch "default"
1157 acl: path access granted: "ef1ea85a6374"
1157 acl: path access granted: "ef1ea85a6374"
1158 acl: branch access granted: "f9cafe1212c8" on branch "default"
1158 acl: branch access granted: "f9cafe1212c8" on branch "default"
1159 acl: path access granted: "f9cafe1212c8"
1159 acl: path access granted: "f9cafe1212c8"
1160 acl: branch access granted: "911600dab2ae" on branch "default"
1160 acl: branch access granted: "911600dab2ae" on branch "default"
1161 acl: path access granted: "911600dab2ae"
1161 acl: path access granted: "911600dab2ae"
1162 bundle2-input-part: total payload size 1606
1162 bundle2-input-part: total payload size 1606
1163 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1163 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1164 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1164 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1165 bundle2-input-bundle: 3 parts total
1165 bundle2-input-bundle: 3 parts total
1166 updating the branch cache
1166 updating the branch cache
1167 bundle2-output-bundle: "HG20", 2 parts total
1167 bundle2-output-bundle: "HG20", 2 parts total
1168 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1168 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1169 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1169 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1170 bundle2-input-bundle: with-transaction
1170 bundle2-input-bundle: with-transaction
1171 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1171 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1172 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1172 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1173 bundle2-input-bundle: 1 parts total
1173 bundle2-input-bundle: 1 parts total
1174 listing keys for "phases"
1174 listing keys for "phases"
1175 try to push obsolete markers to remote
1175 try to push obsolete markers to remote
1176 repository tip rolled back to revision 0 (undo push)
1176 repository tip rolled back to revision 0 (undo push)
1177 0:6675d58eff77
1177 0:6675d58eff77
1178
1178
1179
1179
1180 $ echo '[acl.deny]' >> $config
1180 $ echo '[acl.deny]' >> $config
1181 $ echo "foo/Bar/** = *" >> $config
1181 $ echo "foo/Bar/** = *" >> $config
1182
1182
1183 no one is allowed inside foo/Bar/
1183 no one is allowed inside foo/Bar/
1184
1184
1185 $ do_push fred
1185 $ do_push fred
1186 Pushing as user fred
1186 Pushing as user fred
1187 hgrc = """
1187 hgrc = """
1188 [hooks]
1188 [hooks]
1189 pretxnchangegroup.acl = python:hgext.acl.hook
1189 pretxnchangegroup.acl = python:hgext.acl.hook
1190 [acl]
1190 [acl]
1191 sources = push
1191 sources = push
1192 [extensions]
1192 [extensions]
1193 [acl.allow]
1193 [acl.allow]
1194 ** = fred
1194 ** = fred
1195 [acl.deny]
1195 [acl.deny]
1196 foo/Bar/** = *
1196 foo/Bar/** = *
1197 """
1197 """
1198 pushing to ../b
1198 pushing to ../b
1199 query 1; heads
1199 query 1; heads
1200 searching for changes
1200 searching for changes
1201 all remote heads known locally
1201 all remote heads known locally
1202 listing keys for "phases"
1202 listing keys for "phases"
1203 checking for updated bookmarks
1203 checking for updated bookmarks
1204 listing keys for "bookmarks"
1204 listing keys for "bookmarks"
1205 invalid branchheads cache (served): tip differs
1205 invalid branchheads cache (served): tip differs
1206 listing keys for "bookmarks"
1206 listing keys for "bookmarks"
1207 3 changesets found
1207 3 changesets found
1208 list of changesets:
1208 list of changesets:
1209 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1209 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1210 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1210 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1211 911600dab2ae7a9baff75958b84fe606851ce955
1211 911600dab2ae7a9baff75958b84fe606851ce955
1212 bundle2-output-bundle: "HG20", 4 parts total
1212 bundle2-output-bundle: "HG20", 4 parts total
1213 bundle2-output-part: "replycaps" 93 bytes payload
1213 bundle2-output-part: "replycaps" 106 bytes payload
1214 bundle2-output-part: "check:heads" streamed payload
1214 bundle2-output-part: "check:heads" streamed payload
1215 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1215 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1216 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1216 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1217 bundle2-input-bundle: with-transaction
1217 bundle2-input-bundle: with-transaction
1218 bundle2-input-part: "replycaps" supported
1218 bundle2-input-part: "replycaps" supported
1219 bundle2-input-part: total payload size 93
1219 bundle2-input-part: total payload size 106
1220 bundle2-input-part: "check:heads" supported
1220 bundle2-input-part: "check:heads" supported
1221 bundle2-input-part: total payload size 20
1221 bundle2-input-part: total payload size 20
1222 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1222 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1223 adding changesets
1223 adding changesets
1224 add changeset ef1ea85a6374
1224 add changeset ef1ea85a6374
1225 add changeset f9cafe1212c8
1225 add changeset f9cafe1212c8
1226 add changeset 911600dab2ae
1226 add changeset 911600dab2ae
1227 adding manifests
1227 adding manifests
1228 adding file changes
1228 adding file changes
1229 adding foo/Bar/file.txt revisions
1229 adding foo/Bar/file.txt revisions
1230 adding foo/file.txt revisions
1230 adding foo/file.txt revisions
1231 adding quux/file.py revisions
1231 adding quux/file.py revisions
1232 added 3 changesets with 3 changes to 3 files
1232 added 3 changesets with 3 changes to 3 files
1233 calling hook pretxnchangegroup.acl: hgext.acl.hook
1233 calling hook pretxnchangegroup.acl: hgext.acl.hook
1234 acl: checking access for user "fred"
1234 acl: checking access for user "fred"
1235 acl: acl.allow.branches not enabled
1235 acl: acl.allow.branches not enabled
1236 acl: acl.deny.branches not enabled
1236 acl: acl.deny.branches not enabled
1237 acl: acl.allow enabled, 1 entries for user fred
1237 acl: acl.allow enabled, 1 entries for user fred
1238 acl: acl.deny enabled, 1 entries for user fred
1238 acl: acl.deny enabled, 1 entries for user fred
1239 acl: branch access granted: "ef1ea85a6374" on branch "default"
1239 acl: branch access granted: "ef1ea85a6374" on branch "default"
1240 acl: path access granted: "ef1ea85a6374"
1240 acl: path access granted: "ef1ea85a6374"
1241 acl: branch access granted: "f9cafe1212c8" on branch "default"
1241 acl: branch access granted: "f9cafe1212c8" on branch "default"
1242 error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1242 error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1243 bundle2-input-part: total payload size 1606
1243 bundle2-input-part: total payload size 1606
1244 bundle2-input-bundle: 3 parts total
1244 bundle2-input-bundle: 3 parts total
1245 transaction abort!
1245 transaction abort!
1246 rollback completed
1246 rollback completed
1247 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1247 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1248 no rollback information available
1248 no rollback information available
1249 0:6675d58eff77
1249 0:6675d58eff77
1250
1250
1251
1251
1252 Groups
1252 Groups
1253
1253
1254 $ init_config
1254 $ init_config
1255
1255
1256 OS-level groups
1256 OS-level groups
1257
1257
1258 $ echo '[acl.allow]' >> $config
1258 $ echo '[acl.allow]' >> $config
1259 $ echo "** = @group1" >> $config
1259 $ echo "** = @group1" >> $config
1260
1260
1261 @group1 is always allowed
1261 @group1 is always allowed
1262
1262
1263 $ do_push fred
1263 $ do_push fred
1264 Pushing as user fred
1264 Pushing as user fred
1265 hgrc = """
1265 hgrc = """
1266 [hooks]
1266 [hooks]
1267 pretxnchangegroup.acl = python:hgext.acl.hook
1267 pretxnchangegroup.acl = python:hgext.acl.hook
1268 [acl]
1268 [acl]
1269 sources = push
1269 sources = push
1270 [extensions]
1270 [extensions]
1271 [acl.allow]
1271 [acl.allow]
1272 ** = @group1
1272 ** = @group1
1273 """
1273 """
1274 pushing to ../b
1274 pushing to ../b
1275 query 1; heads
1275 query 1; heads
1276 searching for changes
1276 searching for changes
1277 all remote heads known locally
1277 all remote heads known locally
1278 listing keys for "phases"
1278 listing keys for "phases"
1279 checking for updated bookmarks
1279 checking for updated bookmarks
1280 listing keys for "bookmarks"
1280 listing keys for "bookmarks"
1281 invalid branchheads cache (served): tip differs
1281 invalid branchheads cache (served): tip differs
1282 listing keys for "bookmarks"
1282 listing keys for "bookmarks"
1283 3 changesets found
1283 3 changesets found
1284 list of changesets:
1284 list of changesets:
1285 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1285 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1286 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1286 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1287 911600dab2ae7a9baff75958b84fe606851ce955
1287 911600dab2ae7a9baff75958b84fe606851ce955
1288 bundle2-output-bundle: "HG20", 4 parts total
1288 bundle2-output-bundle: "HG20", 4 parts total
1289 bundle2-output-part: "replycaps" 93 bytes payload
1289 bundle2-output-part: "replycaps" 106 bytes payload
1290 bundle2-output-part: "check:heads" streamed payload
1290 bundle2-output-part: "check:heads" streamed payload
1291 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1291 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1292 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1292 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1293 bundle2-input-bundle: with-transaction
1293 bundle2-input-bundle: with-transaction
1294 bundle2-input-part: "replycaps" supported
1294 bundle2-input-part: "replycaps" supported
1295 bundle2-input-part: total payload size 93
1295 bundle2-input-part: total payload size 106
1296 bundle2-input-part: "check:heads" supported
1296 bundle2-input-part: "check:heads" supported
1297 bundle2-input-part: total payload size 20
1297 bundle2-input-part: total payload size 20
1298 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1298 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1299 adding changesets
1299 adding changesets
1300 add changeset ef1ea85a6374
1300 add changeset ef1ea85a6374
1301 add changeset f9cafe1212c8
1301 add changeset f9cafe1212c8
1302 add changeset 911600dab2ae
1302 add changeset 911600dab2ae
1303 adding manifests
1303 adding manifests
1304 adding file changes
1304 adding file changes
1305 adding foo/Bar/file.txt revisions
1305 adding foo/Bar/file.txt revisions
1306 adding foo/file.txt revisions
1306 adding foo/file.txt revisions
1307 adding quux/file.py revisions
1307 adding quux/file.py revisions
1308 added 3 changesets with 3 changes to 3 files
1308 added 3 changesets with 3 changes to 3 files
1309 calling hook pretxnchangegroup.acl: hgext.acl.hook
1309 calling hook pretxnchangegroup.acl: hgext.acl.hook
1310 acl: checking access for user "fred"
1310 acl: checking access for user "fred"
1311 acl: acl.allow.branches not enabled
1311 acl: acl.allow.branches not enabled
1312 acl: acl.deny.branches not enabled
1312 acl: acl.deny.branches not enabled
1313 acl: "group1" not defined in [acl.groups]
1313 acl: "group1" not defined in [acl.groups]
1314 acl: acl.allow enabled, 1 entries for user fred
1314 acl: acl.allow enabled, 1 entries for user fred
1315 acl: acl.deny not enabled
1315 acl: acl.deny not enabled
1316 acl: branch access granted: "ef1ea85a6374" on branch "default"
1316 acl: branch access granted: "ef1ea85a6374" on branch "default"
1317 acl: path access granted: "ef1ea85a6374"
1317 acl: path access granted: "ef1ea85a6374"
1318 acl: branch access granted: "f9cafe1212c8" on branch "default"
1318 acl: branch access granted: "f9cafe1212c8" on branch "default"
1319 acl: path access granted: "f9cafe1212c8"
1319 acl: path access granted: "f9cafe1212c8"
1320 acl: branch access granted: "911600dab2ae" on branch "default"
1320 acl: branch access granted: "911600dab2ae" on branch "default"
1321 acl: path access granted: "911600dab2ae"
1321 acl: path access granted: "911600dab2ae"
1322 bundle2-input-part: total payload size 1606
1322 bundle2-input-part: total payload size 1606
1323 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1323 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1324 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1324 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1325 bundle2-input-bundle: 3 parts total
1325 bundle2-input-bundle: 3 parts total
1326 updating the branch cache
1326 updating the branch cache
1327 bundle2-output-bundle: "HG20", 2 parts total
1327 bundle2-output-bundle: "HG20", 2 parts total
1328 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1328 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1329 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1329 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1330 bundle2-input-bundle: with-transaction
1330 bundle2-input-bundle: with-transaction
1331 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1331 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1332 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1332 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1333 bundle2-input-bundle: 1 parts total
1333 bundle2-input-bundle: 1 parts total
1334 listing keys for "phases"
1334 listing keys for "phases"
1335 try to push obsolete markers to remote
1335 try to push obsolete markers to remote
1336 repository tip rolled back to revision 0 (undo push)
1336 repository tip rolled back to revision 0 (undo push)
1337 0:6675d58eff77
1337 0:6675d58eff77
1338
1338
1339
1339
1340 $ echo '[acl.deny]' >> $config
1340 $ echo '[acl.deny]' >> $config
1341 $ echo "foo/Bar/** = @group1" >> $config
1341 $ echo "foo/Bar/** = @group1" >> $config
1342
1342
1343 @group is allowed inside anything but foo/Bar/
1343 @group is allowed inside anything but foo/Bar/
1344
1344
1345 $ do_push fred
1345 $ do_push fred
1346 Pushing as user fred
1346 Pushing as user fred
1347 hgrc = """
1347 hgrc = """
1348 [hooks]
1348 [hooks]
1349 pretxnchangegroup.acl = python:hgext.acl.hook
1349 pretxnchangegroup.acl = python:hgext.acl.hook
1350 [acl]
1350 [acl]
1351 sources = push
1351 sources = push
1352 [extensions]
1352 [extensions]
1353 [acl.allow]
1353 [acl.allow]
1354 ** = @group1
1354 ** = @group1
1355 [acl.deny]
1355 [acl.deny]
1356 foo/Bar/** = @group1
1356 foo/Bar/** = @group1
1357 """
1357 """
1358 pushing to ../b
1358 pushing to ../b
1359 query 1; heads
1359 query 1; heads
1360 searching for changes
1360 searching for changes
1361 all remote heads known locally
1361 all remote heads known locally
1362 listing keys for "phases"
1362 listing keys for "phases"
1363 checking for updated bookmarks
1363 checking for updated bookmarks
1364 listing keys for "bookmarks"
1364 listing keys for "bookmarks"
1365 invalid branchheads cache (served): tip differs
1365 invalid branchheads cache (served): tip differs
1366 listing keys for "bookmarks"
1366 listing keys for "bookmarks"
1367 3 changesets found
1367 3 changesets found
1368 list of changesets:
1368 list of changesets:
1369 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1369 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1370 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1370 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1371 911600dab2ae7a9baff75958b84fe606851ce955
1371 911600dab2ae7a9baff75958b84fe606851ce955
1372 bundle2-output-bundle: "HG20", 4 parts total
1372 bundle2-output-bundle: "HG20", 4 parts total
1373 bundle2-output-part: "replycaps" 93 bytes payload
1373 bundle2-output-part: "replycaps" 106 bytes payload
1374 bundle2-output-part: "check:heads" streamed payload
1374 bundle2-output-part: "check:heads" streamed payload
1375 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1375 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1376 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1376 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1377 bundle2-input-bundle: with-transaction
1377 bundle2-input-bundle: with-transaction
1378 bundle2-input-part: "replycaps" supported
1378 bundle2-input-part: "replycaps" supported
1379 bundle2-input-part: total payload size 93
1379 bundle2-input-part: total payload size 106
1380 bundle2-input-part: "check:heads" supported
1380 bundle2-input-part: "check:heads" supported
1381 bundle2-input-part: total payload size 20
1381 bundle2-input-part: total payload size 20
1382 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1382 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1383 adding changesets
1383 adding changesets
1384 add changeset ef1ea85a6374
1384 add changeset ef1ea85a6374
1385 add changeset f9cafe1212c8
1385 add changeset f9cafe1212c8
1386 add changeset 911600dab2ae
1386 add changeset 911600dab2ae
1387 adding manifests
1387 adding manifests
1388 adding file changes
1388 adding file changes
1389 adding foo/Bar/file.txt revisions
1389 adding foo/Bar/file.txt revisions
1390 adding foo/file.txt revisions
1390 adding foo/file.txt revisions
1391 adding quux/file.py revisions
1391 adding quux/file.py revisions
1392 added 3 changesets with 3 changes to 3 files
1392 added 3 changesets with 3 changes to 3 files
1393 calling hook pretxnchangegroup.acl: hgext.acl.hook
1393 calling hook pretxnchangegroup.acl: hgext.acl.hook
1394 acl: checking access for user "fred"
1394 acl: checking access for user "fred"
1395 acl: acl.allow.branches not enabled
1395 acl: acl.allow.branches not enabled
1396 acl: acl.deny.branches not enabled
1396 acl: acl.deny.branches not enabled
1397 acl: "group1" not defined in [acl.groups]
1397 acl: "group1" not defined in [acl.groups]
1398 acl: acl.allow enabled, 1 entries for user fred
1398 acl: acl.allow enabled, 1 entries for user fred
1399 acl: "group1" not defined in [acl.groups]
1399 acl: "group1" not defined in [acl.groups]
1400 acl: acl.deny enabled, 1 entries for user fred
1400 acl: acl.deny enabled, 1 entries for user fred
1401 acl: branch access granted: "ef1ea85a6374" on branch "default"
1401 acl: branch access granted: "ef1ea85a6374" on branch "default"
1402 acl: path access granted: "ef1ea85a6374"
1402 acl: path access granted: "ef1ea85a6374"
1403 acl: branch access granted: "f9cafe1212c8" on branch "default"
1403 acl: branch access granted: "f9cafe1212c8" on branch "default"
1404 error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1404 error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1405 bundle2-input-part: total payload size 1606
1405 bundle2-input-part: total payload size 1606
1406 bundle2-input-bundle: 3 parts total
1406 bundle2-input-bundle: 3 parts total
1407 transaction abort!
1407 transaction abort!
1408 rollback completed
1408 rollback completed
1409 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1409 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1410 no rollback information available
1410 no rollback information available
1411 0:6675d58eff77
1411 0:6675d58eff77
1412
1412
1413
1413
1414 Invalid group
1414 Invalid group
1415
1415
1416 Disable the fakegroups trick to get real failures
1416 Disable the fakegroups trick to get real failures
1417
1417
1418 $ grep -v fakegroups $config > config.tmp
1418 $ grep -v fakegroups $config > config.tmp
1419 $ mv config.tmp $config
1419 $ mv config.tmp $config
1420 $ echo '[acl.allow]' >> $config
1420 $ echo '[acl.allow]' >> $config
1421 $ echo "** = @unlikelytoexist" >> $config
1421 $ echo "** = @unlikelytoexist" >> $config
1422 $ do_push fred 2>&1 | grep unlikelytoexist
1422 $ do_push fred 2>&1 | grep unlikelytoexist
1423 ** = @unlikelytoexist
1423 ** = @unlikelytoexist
1424 acl: "unlikelytoexist" not defined in [acl.groups]
1424 acl: "unlikelytoexist" not defined in [acl.groups]
1425 error: pretxnchangegroup.acl hook failed: group 'unlikelytoexist' is undefined
1425 error: pretxnchangegroup.acl hook failed: group 'unlikelytoexist' is undefined
1426 abort: group 'unlikelytoexist' is undefined
1426 abort: group 'unlikelytoexist' is undefined
1427
1427
1428
1428
1429 Branch acl tests setup
1429 Branch acl tests setup
1430
1430
1431 $ init_config
1431 $ init_config
1432 $ cd b
1432 $ cd b
1433 $ hg up
1433 $ hg up
1434 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1434 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1435 $ hg branch foobar
1435 $ hg branch foobar
1436 marked working directory as branch foobar
1436 marked working directory as branch foobar
1437 (branches are permanent and global, did you want a bookmark?)
1437 (branches are permanent and global, did you want a bookmark?)
1438 $ hg commit -m 'create foobar'
1438 $ hg commit -m 'create foobar'
1439 $ echo 'foo contents' > abc.txt
1439 $ echo 'foo contents' > abc.txt
1440 $ hg add abc.txt
1440 $ hg add abc.txt
1441 $ hg commit -m 'foobar contents'
1441 $ hg commit -m 'foobar contents'
1442 $ cd ..
1442 $ cd ..
1443 $ hg --cwd a pull ../b
1443 $ hg --cwd a pull ../b
1444 pulling from ../b
1444 pulling from ../b
1445 searching for changes
1445 searching for changes
1446 adding changesets
1446 adding changesets
1447 adding manifests
1447 adding manifests
1448 adding file changes
1448 adding file changes
1449 added 2 changesets with 1 changes to 1 files (+1 heads)
1449 added 2 changesets with 1 changes to 1 files (+1 heads)
1450 (run 'hg heads' to see heads)
1450 (run 'hg heads' to see heads)
1451
1451
1452 Create additional changeset on foobar branch
1452 Create additional changeset on foobar branch
1453
1453
1454 $ cd a
1454 $ cd a
1455 $ hg up -C foobar
1455 $ hg up -C foobar
1456 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1456 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1457 $ echo 'foo contents2' > abc.txt
1457 $ echo 'foo contents2' > abc.txt
1458 $ hg commit -m 'foobar contents2'
1458 $ hg commit -m 'foobar contents2'
1459 $ cd ..
1459 $ cd ..
1460
1460
1461
1461
1462 No branch acls specified
1462 No branch acls specified
1463
1463
1464 $ do_push astro
1464 $ do_push astro
1465 Pushing as user astro
1465 Pushing as user astro
1466 hgrc = """
1466 hgrc = """
1467 [hooks]
1467 [hooks]
1468 pretxnchangegroup.acl = python:hgext.acl.hook
1468 pretxnchangegroup.acl = python:hgext.acl.hook
1469 [acl]
1469 [acl]
1470 sources = push
1470 sources = push
1471 [extensions]
1471 [extensions]
1472 """
1472 """
1473 pushing to ../b
1473 pushing to ../b
1474 query 1; heads
1474 query 1; heads
1475 searching for changes
1475 searching for changes
1476 all remote heads known locally
1476 all remote heads known locally
1477 listing keys for "phases"
1477 listing keys for "phases"
1478 checking for updated bookmarks
1478 checking for updated bookmarks
1479 listing keys for "bookmarks"
1479 listing keys for "bookmarks"
1480 listing keys for "bookmarks"
1480 listing keys for "bookmarks"
1481 4 changesets found
1481 4 changesets found
1482 list of changesets:
1482 list of changesets:
1483 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1483 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1484 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1484 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1485 911600dab2ae7a9baff75958b84fe606851ce955
1485 911600dab2ae7a9baff75958b84fe606851ce955
1486 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1486 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1487 bundle2-output-bundle: "HG20", 5 parts total
1487 bundle2-output-bundle: "HG20", 5 parts total
1488 bundle2-output-part: "replycaps" 93 bytes payload
1488 bundle2-output-part: "replycaps" 106 bytes payload
1489 bundle2-output-part: "check:heads" streamed payload
1489 bundle2-output-part: "check:heads" streamed payload
1490 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1490 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1491 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1491 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1492 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1492 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1493 bundle2-input-bundle: with-transaction
1493 bundle2-input-bundle: with-transaction
1494 bundle2-input-part: "replycaps" supported
1494 bundle2-input-part: "replycaps" supported
1495 bundle2-input-part: total payload size 93
1495 bundle2-input-part: total payload size 106
1496 bundle2-input-part: "check:heads" supported
1496 bundle2-input-part: "check:heads" supported
1497 bundle2-input-part: total payload size 20
1497 bundle2-input-part: total payload size 20
1498 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1498 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1499 adding changesets
1499 adding changesets
1500 add changeset ef1ea85a6374
1500 add changeset ef1ea85a6374
1501 add changeset f9cafe1212c8
1501 add changeset f9cafe1212c8
1502 add changeset 911600dab2ae
1502 add changeset 911600dab2ae
1503 add changeset e8fc755d4d82
1503 add changeset e8fc755d4d82
1504 adding manifests
1504 adding manifests
1505 adding file changes
1505 adding file changes
1506 adding abc.txt revisions
1506 adding abc.txt revisions
1507 adding foo/Bar/file.txt revisions
1507 adding foo/Bar/file.txt revisions
1508 adding foo/file.txt revisions
1508 adding foo/file.txt revisions
1509 adding quux/file.py revisions
1509 adding quux/file.py revisions
1510 added 4 changesets with 4 changes to 4 files (+1 heads)
1510 added 4 changesets with 4 changes to 4 files (+1 heads)
1511 calling hook pretxnchangegroup.acl: hgext.acl.hook
1511 calling hook pretxnchangegroup.acl: hgext.acl.hook
1512 acl: checking access for user "astro"
1512 acl: checking access for user "astro"
1513 acl: acl.allow.branches not enabled
1513 acl: acl.allow.branches not enabled
1514 acl: acl.deny.branches not enabled
1514 acl: acl.deny.branches not enabled
1515 acl: acl.allow not enabled
1515 acl: acl.allow not enabled
1516 acl: acl.deny not enabled
1516 acl: acl.deny not enabled
1517 acl: branch access granted: "ef1ea85a6374" on branch "default"
1517 acl: branch access granted: "ef1ea85a6374" on branch "default"
1518 acl: path access granted: "ef1ea85a6374"
1518 acl: path access granted: "ef1ea85a6374"
1519 acl: branch access granted: "f9cafe1212c8" on branch "default"
1519 acl: branch access granted: "f9cafe1212c8" on branch "default"
1520 acl: path access granted: "f9cafe1212c8"
1520 acl: path access granted: "f9cafe1212c8"
1521 acl: branch access granted: "911600dab2ae" on branch "default"
1521 acl: branch access granted: "911600dab2ae" on branch "default"
1522 acl: path access granted: "911600dab2ae"
1522 acl: path access granted: "911600dab2ae"
1523 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
1523 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
1524 acl: path access granted: "e8fc755d4d82"
1524 acl: path access granted: "e8fc755d4d82"
1525 bundle2-input-part: total payload size 2101
1525 bundle2-input-part: total payload size 2101
1526 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1526 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1527 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1527 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1528 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1528 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1529 pushing key for "phases:e8fc755d4d8217ee5b0c2bb41558c40d43b92c01"
1529 pushing key for "phases:e8fc755d4d8217ee5b0c2bb41558c40d43b92c01"
1530 bundle2-input-bundle: 4 parts total
1530 bundle2-input-bundle: 4 parts total
1531 updating the branch cache
1531 updating the branch cache
1532 bundle2-output-bundle: "HG20", 3 parts total
1532 bundle2-output-bundle: "HG20", 3 parts total
1533 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1533 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1534 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1534 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1535 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1535 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1536 bundle2-input-bundle: with-transaction
1536 bundle2-input-bundle: with-transaction
1537 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1537 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1538 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1538 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1539 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1539 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1540 bundle2-input-bundle: 2 parts total
1540 bundle2-input-bundle: 2 parts total
1541 listing keys for "phases"
1541 listing keys for "phases"
1542 try to push obsolete markers to remote
1542 try to push obsolete markers to remote
1543 repository tip rolled back to revision 2 (undo push)
1543 repository tip rolled back to revision 2 (undo push)
1544 2:fb35475503ef
1544 2:fb35475503ef
1545
1545
1546
1546
1547 Branch acl deny test
1547 Branch acl deny test
1548
1548
1549 $ echo "[acl.deny.branches]" >> $config
1549 $ echo "[acl.deny.branches]" >> $config
1550 $ echo "foobar = *" >> $config
1550 $ echo "foobar = *" >> $config
1551 $ do_push astro
1551 $ do_push astro
1552 Pushing as user astro
1552 Pushing as user astro
1553 hgrc = """
1553 hgrc = """
1554 [hooks]
1554 [hooks]
1555 pretxnchangegroup.acl = python:hgext.acl.hook
1555 pretxnchangegroup.acl = python:hgext.acl.hook
1556 [acl]
1556 [acl]
1557 sources = push
1557 sources = push
1558 [extensions]
1558 [extensions]
1559 [acl.deny.branches]
1559 [acl.deny.branches]
1560 foobar = *
1560 foobar = *
1561 """
1561 """
1562 pushing to ../b
1562 pushing to ../b
1563 query 1; heads
1563 query 1; heads
1564 searching for changes
1564 searching for changes
1565 all remote heads known locally
1565 all remote heads known locally
1566 listing keys for "phases"
1566 listing keys for "phases"
1567 checking for updated bookmarks
1567 checking for updated bookmarks
1568 listing keys for "bookmarks"
1568 listing keys for "bookmarks"
1569 listing keys for "bookmarks"
1569 listing keys for "bookmarks"
1570 4 changesets found
1570 4 changesets found
1571 list of changesets:
1571 list of changesets:
1572 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1572 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1573 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1573 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1574 911600dab2ae7a9baff75958b84fe606851ce955
1574 911600dab2ae7a9baff75958b84fe606851ce955
1575 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1575 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1576 bundle2-output-bundle: "HG20", 5 parts total
1576 bundle2-output-bundle: "HG20", 5 parts total
1577 bundle2-output-part: "replycaps" 93 bytes payload
1577 bundle2-output-part: "replycaps" 106 bytes payload
1578 bundle2-output-part: "check:heads" streamed payload
1578 bundle2-output-part: "check:heads" streamed payload
1579 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1579 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1580 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1580 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1581 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1581 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1582 bundle2-input-bundle: with-transaction
1582 bundle2-input-bundle: with-transaction
1583 bundle2-input-part: "replycaps" supported
1583 bundle2-input-part: "replycaps" supported
1584 bundle2-input-part: total payload size 93
1584 bundle2-input-part: total payload size 106
1585 bundle2-input-part: "check:heads" supported
1585 bundle2-input-part: "check:heads" supported
1586 bundle2-input-part: total payload size 20
1586 bundle2-input-part: total payload size 20
1587 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1587 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1588 adding changesets
1588 adding changesets
1589 add changeset ef1ea85a6374
1589 add changeset ef1ea85a6374
1590 add changeset f9cafe1212c8
1590 add changeset f9cafe1212c8
1591 add changeset 911600dab2ae
1591 add changeset 911600dab2ae
1592 add changeset e8fc755d4d82
1592 add changeset e8fc755d4d82
1593 adding manifests
1593 adding manifests
1594 adding file changes
1594 adding file changes
1595 adding abc.txt revisions
1595 adding abc.txt revisions
1596 adding foo/Bar/file.txt revisions
1596 adding foo/Bar/file.txt revisions
1597 adding foo/file.txt revisions
1597 adding foo/file.txt revisions
1598 adding quux/file.py revisions
1598 adding quux/file.py revisions
1599 added 4 changesets with 4 changes to 4 files (+1 heads)
1599 added 4 changesets with 4 changes to 4 files (+1 heads)
1600 calling hook pretxnchangegroup.acl: hgext.acl.hook
1600 calling hook pretxnchangegroup.acl: hgext.acl.hook
1601 acl: checking access for user "astro"
1601 acl: checking access for user "astro"
1602 acl: acl.allow.branches not enabled
1602 acl: acl.allow.branches not enabled
1603 acl: acl.deny.branches enabled, 1 entries for user astro
1603 acl: acl.deny.branches enabled, 1 entries for user astro
1604 acl: acl.allow not enabled
1604 acl: acl.allow not enabled
1605 acl: acl.deny not enabled
1605 acl: acl.deny not enabled
1606 acl: branch access granted: "ef1ea85a6374" on branch "default"
1606 acl: branch access granted: "ef1ea85a6374" on branch "default"
1607 acl: path access granted: "ef1ea85a6374"
1607 acl: path access granted: "ef1ea85a6374"
1608 acl: branch access granted: "f9cafe1212c8" on branch "default"
1608 acl: branch access granted: "f9cafe1212c8" on branch "default"
1609 acl: path access granted: "f9cafe1212c8"
1609 acl: path access granted: "f9cafe1212c8"
1610 acl: branch access granted: "911600dab2ae" on branch "default"
1610 acl: branch access granted: "911600dab2ae" on branch "default"
1611 acl: path access granted: "911600dab2ae"
1611 acl: path access granted: "911600dab2ae"
1612 error: pretxnchangegroup.acl hook failed: acl: user "astro" denied on branch "foobar" (changeset "e8fc755d4d82")
1612 error: pretxnchangegroup.acl hook failed: acl: user "astro" denied on branch "foobar" (changeset "e8fc755d4d82")
1613 bundle2-input-part: total payload size 2101
1613 bundle2-input-part: total payload size 2101
1614 bundle2-input-bundle: 4 parts total
1614 bundle2-input-bundle: 4 parts total
1615 transaction abort!
1615 transaction abort!
1616 rollback completed
1616 rollback completed
1617 abort: acl: user "astro" denied on branch "foobar" (changeset "e8fc755d4d82")
1617 abort: acl: user "astro" denied on branch "foobar" (changeset "e8fc755d4d82")
1618 no rollback information available
1618 no rollback information available
1619 2:fb35475503ef
1619 2:fb35475503ef
1620
1620
1621
1621
1622 Branch acl empty allow test
1622 Branch acl empty allow test
1623
1623
1624 $ init_config
1624 $ init_config
1625 $ echo "[acl.allow.branches]" >> $config
1625 $ echo "[acl.allow.branches]" >> $config
1626 $ do_push astro
1626 $ do_push astro
1627 Pushing as user astro
1627 Pushing as user astro
1628 hgrc = """
1628 hgrc = """
1629 [hooks]
1629 [hooks]
1630 pretxnchangegroup.acl = python:hgext.acl.hook
1630 pretxnchangegroup.acl = python:hgext.acl.hook
1631 [acl]
1631 [acl]
1632 sources = push
1632 sources = push
1633 [extensions]
1633 [extensions]
1634 [acl.allow.branches]
1634 [acl.allow.branches]
1635 """
1635 """
1636 pushing to ../b
1636 pushing to ../b
1637 query 1; heads
1637 query 1; heads
1638 searching for changes
1638 searching for changes
1639 all remote heads known locally
1639 all remote heads known locally
1640 listing keys for "phases"
1640 listing keys for "phases"
1641 checking for updated bookmarks
1641 checking for updated bookmarks
1642 listing keys for "bookmarks"
1642 listing keys for "bookmarks"
1643 listing keys for "bookmarks"
1643 listing keys for "bookmarks"
1644 4 changesets found
1644 4 changesets found
1645 list of changesets:
1645 list of changesets:
1646 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1646 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1647 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1647 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1648 911600dab2ae7a9baff75958b84fe606851ce955
1648 911600dab2ae7a9baff75958b84fe606851ce955
1649 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1649 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1650 bundle2-output-bundle: "HG20", 5 parts total
1650 bundle2-output-bundle: "HG20", 5 parts total
1651 bundle2-output-part: "replycaps" 93 bytes payload
1651 bundle2-output-part: "replycaps" 106 bytes payload
1652 bundle2-output-part: "check:heads" streamed payload
1652 bundle2-output-part: "check:heads" streamed payload
1653 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1653 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1654 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1654 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1655 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1655 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1656 bundle2-input-bundle: with-transaction
1656 bundle2-input-bundle: with-transaction
1657 bundle2-input-part: "replycaps" supported
1657 bundle2-input-part: "replycaps" supported
1658 bundle2-input-part: total payload size 93
1658 bundle2-input-part: total payload size 106
1659 bundle2-input-part: "check:heads" supported
1659 bundle2-input-part: "check:heads" supported
1660 bundle2-input-part: total payload size 20
1660 bundle2-input-part: total payload size 20
1661 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1661 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1662 adding changesets
1662 adding changesets
1663 add changeset ef1ea85a6374
1663 add changeset ef1ea85a6374
1664 add changeset f9cafe1212c8
1664 add changeset f9cafe1212c8
1665 add changeset 911600dab2ae
1665 add changeset 911600dab2ae
1666 add changeset e8fc755d4d82
1666 add changeset e8fc755d4d82
1667 adding manifests
1667 adding manifests
1668 adding file changes
1668 adding file changes
1669 adding abc.txt revisions
1669 adding abc.txt revisions
1670 adding foo/Bar/file.txt revisions
1670 adding foo/Bar/file.txt revisions
1671 adding foo/file.txt revisions
1671 adding foo/file.txt revisions
1672 adding quux/file.py revisions
1672 adding quux/file.py revisions
1673 added 4 changesets with 4 changes to 4 files (+1 heads)
1673 added 4 changesets with 4 changes to 4 files (+1 heads)
1674 calling hook pretxnchangegroup.acl: hgext.acl.hook
1674 calling hook pretxnchangegroup.acl: hgext.acl.hook
1675 acl: checking access for user "astro"
1675 acl: checking access for user "astro"
1676 acl: acl.allow.branches enabled, 0 entries for user astro
1676 acl: acl.allow.branches enabled, 0 entries for user astro
1677 acl: acl.deny.branches not enabled
1677 acl: acl.deny.branches not enabled
1678 acl: acl.allow not enabled
1678 acl: acl.allow not enabled
1679 acl: acl.deny not enabled
1679 acl: acl.deny not enabled
1680 error: pretxnchangegroup.acl hook failed: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1680 error: pretxnchangegroup.acl hook failed: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1681 bundle2-input-part: total payload size 2101
1681 bundle2-input-part: total payload size 2101
1682 bundle2-input-bundle: 4 parts total
1682 bundle2-input-bundle: 4 parts total
1683 transaction abort!
1683 transaction abort!
1684 rollback completed
1684 rollback completed
1685 abort: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1685 abort: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1686 no rollback information available
1686 no rollback information available
1687 2:fb35475503ef
1687 2:fb35475503ef
1688
1688
1689
1689
1690 Branch acl allow other
1690 Branch acl allow other
1691
1691
1692 $ init_config
1692 $ init_config
1693 $ echo "[acl.allow.branches]" >> $config
1693 $ echo "[acl.allow.branches]" >> $config
1694 $ echo "* = george" >> $config
1694 $ echo "* = george" >> $config
1695 $ do_push astro
1695 $ do_push astro
1696 Pushing as user astro
1696 Pushing as user astro
1697 hgrc = """
1697 hgrc = """
1698 [hooks]
1698 [hooks]
1699 pretxnchangegroup.acl = python:hgext.acl.hook
1699 pretxnchangegroup.acl = python:hgext.acl.hook
1700 [acl]
1700 [acl]
1701 sources = push
1701 sources = push
1702 [extensions]
1702 [extensions]
1703 [acl.allow.branches]
1703 [acl.allow.branches]
1704 * = george
1704 * = george
1705 """
1705 """
1706 pushing to ../b
1706 pushing to ../b
1707 query 1; heads
1707 query 1; heads
1708 searching for changes
1708 searching for changes
1709 all remote heads known locally
1709 all remote heads known locally
1710 listing keys for "phases"
1710 listing keys for "phases"
1711 checking for updated bookmarks
1711 checking for updated bookmarks
1712 listing keys for "bookmarks"
1712 listing keys for "bookmarks"
1713 listing keys for "bookmarks"
1713 listing keys for "bookmarks"
1714 4 changesets found
1714 4 changesets found
1715 list of changesets:
1715 list of changesets:
1716 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1716 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1717 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1717 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1718 911600dab2ae7a9baff75958b84fe606851ce955
1718 911600dab2ae7a9baff75958b84fe606851ce955
1719 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1719 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1720 bundle2-output-bundle: "HG20", 5 parts total
1720 bundle2-output-bundle: "HG20", 5 parts total
1721 bundle2-output-part: "replycaps" 93 bytes payload
1721 bundle2-output-part: "replycaps" 106 bytes payload
1722 bundle2-output-part: "check:heads" streamed payload
1722 bundle2-output-part: "check:heads" streamed payload
1723 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1723 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1724 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1724 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1725 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1725 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1726 bundle2-input-bundle: with-transaction
1726 bundle2-input-bundle: with-transaction
1727 bundle2-input-part: "replycaps" supported
1727 bundle2-input-part: "replycaps" supported
1728 bundle2-input-part: total payload size 93
1728 bundle2-input-part: total payload size 106
1729 bundle2-input-part: "check:heads" supported
1729 bundle2-input-part: "check:heads" supported
1730 bundle2-input-part: total payload size 20
1730 bundle2-input-part: total payload size 20
1731 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1731 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1732 adding changesets
1732 adding changesets
1733 add changeset ef1ea85a6374
1733 add changeset ef1ea85a6374
1734 add changeset f9cafe1212c8
1734 add changeset f9cafe1212c8
1735 add changeset 911600dab2ae
1735 add changeset 911600dab2ae
1736 add changeset e8fc755d4d82
1736 add changeset e8fc755d4d82
1737 adding manifests
1737 adding manifests
1738 adding file changes
1738 adding file changes
1739 adding abc.txt revisions
1739 adding abc.txt revisions
1740 adding foo/Bar/file.txt revisions
1740 adding foo/Bar/file.txt revisions
1741 adding foo/file.txt revisions
1741 adding foo/file.txt revisions
1742 adding quux/file.py revisions
1742 adding quux/file.py revisions
1743 added 4 changesets with 4 changes to 4 files (+1 heads)
1743 added 4 changesets with 4 changes to 4 files (+1 heads)
1744 calling hook pretxnchangegroup.acl: hgext.acl.hook
1744 calling hook pretxnchangegroup.acl: hgext.acl.hook
1745 acl: checking access for user "astro"
1745 acl: checking access for user "astro"
1746 acl: acl.allow.branches enabled, 0 entries for user astro
1746 acl: acl.allow.branches enabled, 0 entries for user astro
1747 acl: acl.deny.branches not enabled
1747 acl: acl.deny.branches not enabled
1748 acl: acl.allow not enabled
1748 acl: acl.allow not enabled
1749 acl: acl.deny not enabled
1749 acl: acl.deny not enabled
1750 error: pretxnchangegroup.acl hook failed: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1750 error: pretxnchangegroup.acl hook failed: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1751 bundle2-input-part: total payload size 2101
1751 bundle2-input-part: total payload size 2101
1752 bundle2-input-bundle: 4 parts total
1752 bundle2-input-bundle: 4 parts total
1753 transaction abort!
1753 transaction abort!
1754 rollback completed
1754 rollback completed
1755 abort: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1755 abort: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1756 no rollback information available
1756 no rollback information available
1757 2:fb35475503ef
1757 2:fb35475503ef
1758
1758
1759 $ do_push george
1759 $ do_push george
1760 Pushing as user george
1760 Pushing as user george
1761 hgrc = """
1761 hgrc = """
1762 [hooks]
1762 [hooks]
1763 pretxnchangegroup.acl = python:hgext.acl.hook
1763 pretxnchangegroup.acl = python:hgext.acl.hook
1764 [acl]
1764 [acl]
1765 sources = push
1765 sources = push
1766 [extensions]
1766 [extensions]
1767 [acl.allow.branches]
1767 [acl.allow.branches]
1768 * = george
1768 * = george
1769 """
1769 """
1770 pushing to ../b
1770 pushing to ../b
1771 query 1; heads
1771 query 1; heads
1772 searching for changes
1772 searching for changes
1773 all remote heads known locally
1773 all remote heads known locally
1774 listing keys for "phases"
1774 listing keys for "phases"
1775 checking for updated bookmarks
1775 checking for updated bookmarks
1776 listing keys for "bookmarks"
1776 listing keys for "bookmarks"
1777 listing keys for "bookmarks"
1777 listing keys for "bookmarks"
1778 4 changesets found
1778 4 changesets found
1779 list of changesets:
1779 list of changesets:
1780 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1780 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1781 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1781 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1782 911600dab2ae7a9baff75958b84fe606851ce955
1782 911600dab2ae7a9baff75958b84fe606851ce955
1783 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1783 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1784 bundle2-output-bundle: "HG20", 5 parts total
1784 bundle2-output-bundle: "HG20", 5 parts total
1785 bundle2-output-part: "replycaps" 93 bytes payload
1785 bundle2-output-part: "replycaps" 106 bytes payload
1786 bundle2-output-part: "check:heads" streamed payload
1786 bundle2-output-part: "check:heads" streamed payload
1787 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1787 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1788 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1788 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1789 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1789 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1790 bundle2-input-bundle: with-transaction
1790 bundle2-input-bundle: with-transaction
1791 bundle2-input-part: "replycaps" supported
1791 bundle2-input-part: "replycaps" supported
1792 bundle2-input-part: total payload size 93
1792 bundle2-input-part: total payload size 106
1793 bundle2-input-part: "check:heads" supported
1793 bundle2-input-part: "check:heads" supported
1794 bundle2-input-part: total payload size 20
1794 bundle2-input-part: total payload size 20
1795 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1795 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1796 adding changesets
1796 adding changesets
1797 add changeset ef1ea85a6374
1797 add changeset ef1ea85a6374
1798 add changeset f9cafe1212c8
1798 add changeset f9cafe1212c8
1799 add changeset 911600dab2ae
1799 add changeset 911600dab2ae
1800 add changeset e8fc755d4d82
1800 add changeset e8fc755d4d82
1801 adding manifests
1801 adding manifests
1802 adding file changes
1802 adding file changes
1803 adding abc.txt revisions
1803 adding abc.txt revisions
1804 adding foo/Bar/file.txt revisions
1804 adding foo/Bar/file.txt revisions
1805 adding foo/file.txt revisions
1805 adding foo/file.txt revisions
1806 adding quux/file.py revisions
1806 adding quux/file.py revisions
1807 added 4 changesets with 4 changes to 4 files (+1 heads)
1807 added 4 changesets with 4 changes to 4 files (+1 heads)
1808 calling hook pretxnchangegroup.acl: hgext.acl.hook
1808 calling hook pretxnchangegroup.acl: hgext.acl.hook
1809 acl: checking access for user "george"
1809 acl: checking access for user "george"
1810 acl: acl.allow.branches enabled, 1 entries for user george
1810 acl: acl.allow.branches enabled, 1 entries for user george
1811 acl: acl.deny.branches not enabled
1811 acl: acl.deny.branches not enabled
1812 acl: acl.allow not enabled
1812 acl: acl.allow not enabled
1813 acl: acl.deny not enabled
1813 acl: acl.deny not enabled
1814 acl: branch access granted: "ef1ea85a6374" on branch "default"
1814 acl: branch access granted: "ef1ea85a6374" on branch "default"
1815 acl: path access granted: "ef1ea85a6374"
1815 acl: path access granted: "ef1ea85a6374"
1816 acl: branch access granted: "f9cafe1212c8" on branch "default"
1816 acl: branch access granted: "f9cafe1212c8" on branch "default"
1817 acl: path access granted: "f9cafe1212c8"
1817 acl: path access granted: "f9cafe1212c8"
1818 acl: branch access granted: "911600dab2ae" on branch "default"
1818 acl: branch access granted: "911600dab2ae" on branch "default"
1819 acl: path access granted: "911600dab2ae"
1819 acl: path access granted: "911600dab2ae"
1820 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
1820 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
1821 acl: path access granted: "e8fc755d4d82"
1821 acl: path access granted: "e8fc755d4d82"
1822 bundle2-input-part: total payload size 2101
1822 bundle2-input-part: total payload size 2101
1823 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1823 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1824 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1824 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1825 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1825 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1826 pushing key for "phases:e8fc755d4d8217ee5b0c2bb41558c40d43b92c01"
1826 pushing key for "phases:e8fc755d4d8217ee5b0c2bb41558c40d43b92c01"
1827 bundle2-input-bundle: 4 parts total
1827 bundle2-input-bundle: 4 parts total
1828 updating the branch cache
1828 updating the branch cache
1829 bundle2-output-bundle: "HG20", 3 parts total
1829 bundle2-output-bundle: "HG20", 3 parts total
1830 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1830 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1831 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1831 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1832 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1832 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1833 bundle2-input-bundle: with-transaction
1833 bundle2-input-bundle: with-transaction
1834 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1834 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1835 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1835 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1836 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1836 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1837 bundle2-input-bundle: 2 parts total
1837 bundle2-input-bundle: 2 parts total
1838 listing keys for "phases"
1838 listing keys for "phases"
1839 try to push obsolete markers to remote
1839 try to push obsolete markers to remote
1840 repository tip rolled back to revision 2 (undo push)
1840 repository tip rolled back to revision 2 (undo push)
1841 2:fb35475503ef
1841 2:fb35475503ef
1842
1842
1843
1843
1844 Branch acl conflicting allow
1844 Branch acl conflicting allow
1845 asterisk ends up applying to all branches and allowing george to
1845 asterisk ends up applying to all branches and allowing george to
1846 push foobar into the remote
1846 push foobar into the remote
1847
1847
1848 $ init_config
1848 $ init_config
1849 $ echo "[acl.allow.branches]" >> $config
1849 $ echo "[acl.allow.branches]" >> $config
1850 $ echo "foobar = astro" >> $config
1850 $ echo "foobar = astro" >> $config
1851 $ echo "* = george" >> $config
1851 $ echo "* = george" >> $config
1852 $ do_push george
1852 $ do_push george
1853 Pushing as user george
1853 Pushing as user george
1854 hgrc = """
1854 hgrc = """
1855 [hooks]
1855 [hooks]
1856 pretxnchangegroup.acl = python:hgext.acl.hook
1856 pretxnchangegroup.acl = python:hgext.acl.hook
1857 [acl]
1857 [acl]
1858 sources = push
1858 sources = push
1859 [extensions]
1859 [extensions]
1860 [acl.allow.branches]
1860 [acl.allow.branches]
1861 foobar = astro
1861 foobar = astro
1862 * = george
1862 * = george
1863 """
1863 """
1864 pushing to ../b
1864 pushing to ../b
1865 query 1; heads
1865 query 1; heads
1866 searching for changes
1866 searching for changes
1867 all remote heads known locally
1867 all remote heads known locally
1868 listing keys for "phases"
1868 listing keys for "phases"
1869 checking for updated bookmarks
1869 checking for updated bookmarks
1870 listing keys for "bookmarks"
1870 listing keys for "bookmarks"
1871 listing keys for "bookmarks"
1871 listing keys for "bookmarks"
1872 4 changesets found
1872 4 changesets found
1873 list of changesets:
1873 list of changesets:
1874 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1874 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1875 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1875 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1876 911600dab2ae7a9baff75958b84fe606851ce955
1876 911600dab2ae7a9baff75958b84fe606851ce955
1877 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1877 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1878 bundle2-output-bundle: "HG20", 5 parts total
1878 bundle2-output-bundle: "HG20", 5 parts total
1879 bundle2-output-part: "replycaps" 93 bytes payload
1879 bundle2-output-part: "replycaps" 106 bytes payload
1880 bundle2-output-part: "check:heads" streamed payload
1880 bundle2-output-part: "check:heads" streamed payload
1881 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1881 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1882 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1882 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1883 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1883 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1884 bundle2-input-bundle: with-transaction
1884 bundle2-input-bundle: with-transaction
1885 bundle2-input-part: "replycaps" supported
1885 bundle2-input-part: "replycaps" supported
1886 bundle2-input-part: total payload size 93
1886 bundle2-input-part: total payload size 106
1887 bundle2-input-part: "check:heads" supported
1887 bundle2-input-part: "check:heads" supported
1888 bundle2-input-part: total payload size 20
1888 bundle2-input-part: total payload size 20
1889 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1889 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1890 adding changesets
1890 adding changesets
1891 add changeset ef1ea85a6374
1891 add changeset ef1ea85a6374
1892 add changeset f9cafe1212c8
1892 add changeset f9cafe1212c8
1893 add changeset 911600dab2ae
1893 add changeset 911600dab2ae
1894 add changeset e8fc755d4d82
1894 add changeset e8fc755d4d82
1895 adding manifests
1895 adding manifests
1896 adding file changes
1896 adding file changes
1897 adding abc.txt revisions
1897 adding abc.txt revisions
1898 adding foo/Bar/file.txt revisions
1898 adding foo/Bar/file.txt revisions
1899 adding foo/file.txt revisions
1899 adding foo/file.txt revisions
1900 adding quux/file.py revisions
1900 adding quux/file.py revisions
1901 added 4 changesets with 4 changes to 4 files (+1 heads)
1901 added 4 changesets with 4 changes to 4 files (+1 heads)
1902 calling hook pretxnchangegroup.acl: hgext.acl.hook
1902 calling hook pretxnchangegroup.acl: hgext.acl.hook
1903 acl: checking access for user "george"
1903 acl: checking access for user "george"
1904 acl: acl.allow.branches enabled, 1 entries for user george
1904 acl: acl.allow.branches enabled, 1 entries for user george
1905 acl: acl.deny.branches not enabled
1905 acl: acl.deny.branches not enabled
1906 acl: acl.allow not enabled
1906 acl: acl.allow not enabled
1907 acl: acl.deny not enabled
1907 acl: acl.deny not enabled
1908 acl: branch access granted: "ef1ea85a6374" on branch "default"
1908 acl: branch access granted: "ef1ea85a6374" on branch "default"
1909 acl: path access granted: "ef1ea85a6374"
1909 acl: path access granted: "ef1ea85a6374"
1910 acl: branch access granted: "f9cafe1212c8" on branch "default"
1910 acl: branch access granted: "f9cafe1212c8" on branch "default"
1911 acl: path access granted: "f9cafe1212c8"
1911 acl: path access granted: "f9cafe1212c8"
1912 acl: branch access granted: "911600dab2ae" on branch "default"
1912 acl: branch access granted: "911600dab2ae" on branch "default"
1913 acl: path access granted: "911600dab2ae"
1913 acl: path access granted: "911600dab2ae"
1914 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
1914 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
1915 acl: path access granted: "e8fc755d4d82"
1915 acl: path access granted: "e8fc755d4d82"
1916 bundle2-input-part: total payload size 2101
1916 bundle2-input-part: total payload size 2101
1917 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1917 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1918 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1918 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1919 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1919 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1920 pushing key for "phases:e8fc755d4d8217ee5b0c2bb41558c40d43b92c01"
1920 pushing key for "phases:e8fc755d4d8217ee5b0c2bb41558c40d43b92c01"
1921 bundle2-input-bundle: 4 parts total
1921 bundle2-input-bundle: 4 parts total
1922 updating the branch cache
1922 updating the branch cache
1923 bundle2-output-bundle: "HG20", 3 parts total
1923 bundle2-output-bundle: "HG20", 3 parts total
1924 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1924 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1925 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1925 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1926 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1926 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1927 bundle2-input-bundle: with-transaction
1927 bundle2-input-bundle: with-transaction
1928 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1928 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1929 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1929 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1930 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1930 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1931 bundle2-input-bundle: 2 parts total
1931 bundle2-input-bundle: 2 parts total
1932 listing keys for "phases"
1932 listing keys for "phases"
1933 try to push obsolete markers to remote
1933 try to push obsolete markers to remote
1934 repository tip rolled back to revision 2 (undo push)
1934 repository tip rolled back to revision 2 (undo push)
1935 2:fb35475503ef
1935 2:fb35475503ef
1936
1936
1937 Branch acl conflicting deny
1937 Branch acl conflicting deny
1938
1938
1939 $ init_config
1939 $ init_config
1940 $ echo "[acl.deny.branches]" >> $config
1940 $ echo "[acl.deny.branches]" >> $config
1941 $ echo "foobar = astro" >> $config
1941 $ echo "foobar = astro" >> $config
1942 $ echo "default = astro" >> $config
1942 $ echo "default = astro" >> $config
1943 $ echo "* = george" >> $config
1943 $ echo "* = george" >> $config
1944 $ do_push george
1944 $ do_push george
1945 Pushing as user george
1945 Pushing as user george
1946 hgrc = """
1946 hgrc = """
1947 [hooks]
1947 [hooks]
1948 pretxnchangegroup.acl = python:hgext.acl.hook
1948 pretxnchangegroup.acl = python:hgext.acl.hook
1949 [acl]
1949 [acl]
1950 sources = push
1950 sources = push
1951 [extensions]
1951 [extensions]
1952 [acl.deny.branches]
1952 [acl.deny.branches]
1953 foobar = astro
1953 foobar = astro
1954 default = astro
1954 default = astro
1955 * = george
1955 * = george
1956 """
1956 """
1957 pushing to ../b
1957 pushing to ../b
1958 query 1; heads
1958 query 1; heads
1959 searching for changes
1959 searching for changes
1960 all remote heads known locally
1960 all remote heads known locally
1961 listing keys for "phases"
1961 listing keys for "phases"
1962 checking for updated bookmarks
1962 checking for updated bookmarks
1963 listing keys for "bookmarks"
1963 listing keys for "bookmarks"
1964 listing keys for "bookmarks"
1964 listing keys for "bookmarks"
1965 4 changesets found
1965 4 changesets found
1966 list of changesets:
1966 list of changesets:
1967 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1967 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1968 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1968 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1969 911600dab2ae7a9baff75958b84fe606851ce955
1969 911600dab2ae7a9baff75958b84fe606851ce955
1970 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1970 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1971 bundle2-output-bundle: "HG20", 5 parts total
1971 bundle2-output-bundle: "HG20", 5 parts total
1972 bundle2-output-part: "replycaps" 93 bytes payload
1972 bundle2-output-part: "replycaps" 106 bytes payload
1973 bundle2-output-part: "check:heads" streamed payload
1973 bundle2-output-part: "check:heads" streamed payload
1974 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1974 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1975 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1975 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1976 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1976 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1977 bundle2-input-bundle: with-transaction
1977 bundle2-input-bundle: with-transaction
1978 bundle2-input-part: "replycaps" supported
1978 bundle2-input-part: "replycaps" supported
1979 bundle2-input-part: total payload size 93
1979 bundle2-input-part: total payload size 106
1980 bundle2-input-part: "check:heads" supported
1980 bundle2-input-part: "check:heads" supported
1981 bundle2-input-part: total payload size 20
1981 bundle2-input-part: total payload size 20
1982 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1982 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1983 adding changesets
1983 adding changesets
1984 add changeset ef1ea85a6374
1984 add changeset ef1ea85a6374
1985 add changeset f9cafe1212c8
1985 add changeset f9cafe1212c8
1986 add changeset 911600dab2ae
1986 add changeset 911600dab2ae
1987 add changeset e8fc755d4d82
1987 add changeset e8fc755d4d82
1988 adding manifests
1988 adding manifests
1989 adding file changes
1989 adding file changes
1990 adding abc.txt revisions
1990 adding abc.txt revisions
1991 adding foo/Bar/file.txt revisions
1991 adding foo/Bar/file.txt revisions
1992 adding foo/file.txt revisions
1992 adding foo/file.txt revisions
1993 adding quux/file.py revisions
1993 adding quux/file.py revisions
1994 added 4 changesets with 4 changes to 4 files (+1 heads)
1994 added 4 changesets with 4 changes to 4 files (+1 heads)
1995 calling hook pretxnchangegroup.acl: hgext.acl.hook
1995 calling hook pretxnchangegroup.acl: hgext.acl.hook
1996 acl: checking access for user "george"
1996 acl: checking access for user "george"
1997 acl: acl.allow.branches not enabled
1997 acl: acl.allow.branches not enabled
1998 acl: acl.deny.branches enabled, 1 entries for user george
1998 acl: acl.deny.branches enabled, 1 entries for user george
1999 acl: acl.allow not enabled
1999 acl: acl.allow not enabled
2000 acl: acl.deny not enabled
2000 acl: acl.deny not enabled
2001 error: pretxnchangegroup.acl hook failed: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2001 error: pretxnchangegroup.acl hook failed: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2002 bundle2-input-part: total payload size 2101
2002 bundle2-input-part: total payload size 2101
2003 bundle2-input-bundle: 4 parts total
2003 bundle2-input-bundle: 4 parts total
2004 transaction abort!
2004 transaction abort!
2005 rollback completed
2005 rollback completed
2006 abort: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2006 abort: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2007 no rollback information available
2007 no rollback information available
2008 2:fb35475503ef
2008 2:fb35475503ef
2009
2009
2010 User 'astro' must not be denied
2010 User 'astro' must not be denied
2011
2011
2012 $ init_config
2012 $ init_config
2013 $ echo "[acl.deny.branches]" >> $config
2013 $ echo "[acl.deny.branches]" >> $config
2014 $ echo "default = !astro" >> $config
2014 $ echo "default = !astro" >> $config
2015 $ do_push astro
2015 $ do_push astro
2016 Pushing as user astro
2016 Pushing as user astro
2017 hgrc = """
2017 hgrc = """
2018 [hooks]
2018 [hooks]
2019 pretxnchangegroup.acl = python:hgext.acl.hook
2019 pretxnchangegroup.acl = python:hgext.acl.hook
2020 [acl]
2020 [acl]
2021 sources = push
2021 sources = push
2022 [extensions]
2022 [extensions]
2023 [acl.deny.branches]
2023 [acl.deny.branches]
2024 default = !astro
2024 default = !astro
2025 """
2025 """
2026 pushing to ../b
2026 pushing to ../b
2027 query 1; heads
2027 query 1; heads
2028 searching for changes
2028 searching for changes
2029 all remote heads known locally
2029 all remote heads known locally
2030 listing keys for "phases"
2030 listing keys for "phases"
2031 checking for updated bookmarks
2031 checking for updated bookmarks
2032 listing keys for "bookmarks"
2032 listing keys for "bookmarks"
2033 listing keys for "bookmarks"
2033 listing keys for "bookmarks"
2034 4 changesets found
2034 4 changesets found
2035 list of changesets:
2035 list of changesets:
2036 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
2036 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
2037 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
2037 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
2038 911600dab2ae7a9baff75958b84fe606851ce955
2038 911600dab2ae7a9baff75958b84fe606851ce955
2039 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
2039 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
2040 bundle2-output-bundle: "HG20", 5 parts total
2040 bundle2-output-bundle: "HG20", 5 parts total
2041 bundle2-output-part: "replycaps" 93 bytes payload
2041 bundle2-output-part: "replycaps" 106 bytes payload
2042 bundle2-output-part: "check:heads" streamed payload
2042 bundle2-output-part: "check:heads" streamed payload
2043 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
2043 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
2044 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2044 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2045 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2045 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2046 bundle2-input-bundle: with-transaction
2046 bundle2-input-bundle: with-transaction
2047 bundle2-input-part: "replycaps" supported
2047 bundle2-input-part: "replycaps" supported
2048 bundle2-input-part: total payload size 93
2048 bundle2-input-part: total payload size 106
2049 bundle2-input-part: "check:heads" supported
2049 bundle2-input-part: "check:heads" supported
2050 bundle2-input-part: total payload size 20
2050 bundle2-input-part: total payload size 20
2051 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
2051 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
2052 adding changesets
2052 adding changesets
2053 add changeset ef1ea85a6374
2053 add changeset ef1ea85a6374
2054 add changeset f9cafe1212c8
2054 add changeset f9cafe1212c8
2055 add changeset 911600dab2ae
2055 add changeset 911600dab2ae
2056 add changeset e8fc755d4d82
2056 add changeset e8fc755d4d82
2057 adding manifests
2057 adding manifests
2058 adding file changes
2058 adding file changes
2059 adding abc.txt revisions
2059 adding abc.txt revisions
2060 adding foo/Bar/file.txt revisions
2060 adding foo/Bar/file.txt revisions
2061 adding foo/file.txt revisions
2061 adding foo/file.txt revisions
2062 adding quux/file.py revisions
2062 adding quux/file.py revisions
2063 added 4 changesets with 4 changes to 4 files (+1 heads)
2063 added 4 changesets with 4 changes to 4 files (+1 heads)
2064 calling hook pretxnchangegroup.acl: hgext.acl.hook
2064 calling hook pretxnchangegroup.acl: hgext.acl.hook
2065 acl: checking access for user "astro"
2065 acl: checking access for user "astro"
2066 acl: acl.allow.branches not enabled
2066 acl: acl.allow.branches not enabled
2067 acl: acl.deny.branches enabled, 0 entries for user astro
2067 acl: acl.deny.branches enabled, 0 entries for user astro
2068 acl: acl.allow not enabled
2068 acl: acl.allow not enabled
2069 acl: acl.deny not enabled
2069 acl: acl.deny not enabled
2070 acl: branch access granted: "ef1ea85a6374" on branch "default"
2070 acl: branch access granted: "ef1ea85a6374" on branch "default"
2071 acl: path access granted: "ef1ea85a6374"
2071 acl: path access granted: "ef1ea85a6374"
2072 acl: branch access granted: "f9cafe1212c8" on branch "default"
2072 acl: branch access granted: "f9cafe1212c8" on branch "default"
2073 acl: path access granted: "f9cafe1212c8"
2073 acl: path access granted: "f9cafe1212c8"
2074 acl: branch access granted: "911600dab2ae" on branch "default"
2074 acl: branch access granted: "911600dab2ae" on branch "default"
2075 acl: path access granted: "911600dab2ae"
2075 acl: path access granted: "911600dab2ae"
2076 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
2076 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
2077 acl: path access granted: "e8fc755d4d82"
2077 acl: path access granted: "e8fc755d4d82"
2078 bundle2-input-part: total payload size 2101
2078 bundle2-input-part: total payload size 2101
2079 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
2079 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
2080 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
2080 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
2081 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
2081 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
2082 pushing key for "phases:e8fc755d4d8217ee5b0c2bb41558c40d43b92c01"
2082 pushing key for "phases:e8fc755d4d8217ee5b0c2bb41558c40d43b92c01"
2083 bundle2-input-bundle: 4 parts total
2083 bundle2-input-bundle: 4 parts total
2084 updating the branch cache
2084 updating the branch cache
2085 bundle2-output-bundle: "HG20", 3 parts total
2085 bundle2-output-bundle: "HG20", 3 parts total
2086 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
2086 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
2087 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
2087 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
2088 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
2088 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
2089 bundle2-input-bundle: with-transaction
2089 bundle2-input-bundle: with-transaction
2090 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
2090 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
2091 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
2091 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
2092 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
2092 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
2093 bundle2-input-bundle: 2 parts total
2093 bundle2-input-bundle: 2 parts total
2094 listing keys for "phases"
2094 listing keys for "phases"
2095 try to push obsolete markers to remote
2095 try to push obsolete markers to remote
2096 repository tip rolled back to revision 2 (undo push)
2096 repository tip rolled back to revision 2 (undo push)
2097 2:fb35475503ef
2097 2:fb35475503ef
2098
2098
2099
2099
2100 Non-astro users must be denied
2100 Non-astro users must be denied
2101
2101
2102 $ do_push george
2102 $ do_push george
2103 Pushing as user george
2103 Pushing as user george
2104 hgrc = """
2104 hgrc = """
2105 [hooks]
2105 [hooks]
2106 pretxnchangegroup.acl = python:hgext.acl.hook
2106 pretxnchangegroup.acl = python:hgext.acl.hook
2107 [acl]
2107 [acl]
2108 sources = push
2108 sources = push
2109 [extensions]
2109 [extensions]
2110 [acl.deny.branches]
2110 [acl.deny.branches]
2111 default = !astro
2111 default = !astro
2112 """
2112 """
2113 pushing to ../b
2113 pushing to ../b
2114 query 1; heads
2114 query 1; heads
2115 searching for changes
2115 searching for changes
2116 all remote heads known locally
2116 all remote heads known locally
2117 listing keys for "phases"
2117 listing keys for "phases"
2118 checking for updated bookmarks
2118 checking for updated bookmarks
2119 listing keys for "bookmarks"
2119 listing keys for "bookmarks"
2120 listing keys for "bookmarks"
2120 listing keys for "bookmarks"
2121 4 changesets found
2121 4 changesets found
2122 list of changesets:
2122 list of changesets:
2123 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
2123 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
2124 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
2124 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
2125 911600dab2ae7a9baff75958b84fe606851ce955
2125 911600dab2ae7a9baff75958b84fe606851ce955
2126 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
2126 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
2127 bundle2-output-bundle: "HG20", 5 parts total
2127 bundle2-output-bundle: "HG20", 5 parts total
2128 bundle2-output-part: "replycaps" 93 bytes payload
2128 bundle2-output-part: "replycaps" 106 bytes payload
2129 bundle2-output-part: "check:heads" streamed payload
2129 bundle2-output-part: "check:heads" streamed payload
2130 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
2130 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
2131 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2131 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2132 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2132 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2133 bundle2-input-bundle: with-transaction
2133 bundle2-input-bundle: with-transaction
2134 bundle2-input-part: "replycaps" supported
2134 bundle2-input-part: "replycaps" supported
2135 bundle2-input-part: total payload size 93
2135 bundle2-input-part: total payload size 106
2136 bundle2-input-part: "check:heads" supported
2136 bundle2-input-part: "check:heads" supported
2137 bundle2-input-part: total payload size 20
2137 bundle2-input-part: total payload size 20
2138 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
2138 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
2139 adding changesets
2139 adding changesets
2140 add changeset ef1ea85a6374
2140 add changeset ef1ea85a6374
2141 add changeset f9cafe1212c8
2141 add changeset f9cafe1212c8
2142 add changeset 911600dab2ae
2142 add changeset 911600dab2ae
2143 add changeset e8fc755d4d82
2143 add changeset e8fc755d4d82
2144 adding manifests
2144 adding manifests
2145 adding file changes
2145 adding file changes
2146 adding abc.txt revisions
2146 adding abc.txt revisions
2147 adding foo/Bar/file.txt revisions
2147 adding foo/Bar/file.txt revisions
2148 adding foo/file.txt revisions
2148 adding foo/file.txt revisions
2149 adding quux/file.py revisions
2149 adding quux/file.py revisions
2150 added 4 changesets with 4 changes to 4 files (+1 heads)
2150 added 4 changesets with 4 changes to 4 files (+1 heads)
2151 calling hook pretxnchangegroup.acl: hgext.acl.hook
2151 calling hook pretxnchangegroup.acl: hgext.acl.hook
2152 acl: checking access for user "george"
2152 acl: checking access for user "george"
2153 acl: acl.allow.branches not enabled
2153 acl: acl.allow.branches not enabled
2154 acl: acl.deny.branches enabled, 1 entries for user george
2154 acl: acl.deny.branches enabled, 1 entries for user george
2155 acl: acl.allow not enabled
2155 acl: acl.allow not enabled
2156 acl: acl.deny not enabled
2156 acl: acl.deny not enabled
2157 error: pretxnchangegroup.acl hook failed: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2157 error: pretxnchangegroup.acl hook failed: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2158 bundle2-input-part: total payload size 2101
2158 bundle2-input-part: total payload size 2101
2159 bundle2-input-bundle: 4 parts total
2159 bundle2-input-bundle: 4 parts total
2160 transaction abort!
2160 transaction abort!
2161 rollback completed
2161 rollback completed
2162 abort: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2162 abort: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2163 no rollback information available
2163 no rollback information available
2164 2:fb35475503ef
2164 2:fb35475503ef
2165
2165
2166
2166
@@ -1,130 +1,130 b''
1 #require serve
1 #require serve
2 $ cat << EOF >> $HGRCPATH
2 $ cat << EOF >> $HGRCPATH
3 > [experimental]
3 > [experimental]
4 > # drop me once bundle2 is the default,
4 > # drop me once bundle2 is the default,
5 > # added to get test change early.
5 > # added to get test change early.
6 > bundle2-exp = True
6 > bundle2-exp = True
7 > EOF
7 > EOF
8
8
9 $ hg init a
9 $ hg init a
10 $ cd a
10 $ cd a
11 $ echo a > a
11 $ echo a > a
12 $ hg ci -Ama -d '1123456789 0'
12 $ hg ci -Ama -d '1123456789 0'
13 adding a
13 adding a
14 $ hg --config server.uncompressed=True serve -p $HGPORT -d --pid-file=hg.pid
14 $ hg --config server.uncompressed=True serve -p $HGPORT -d --pid-file=hg.pid
15 $ cat hg.pid >> $DAEMON_PIDS
15 $ cat hg.pid >> $DAEMON_PIDS
16 $ cd ..
16 $ cd ..
17 $ "$TESTDIR/tinyproxy.py" $HGPORT1 localhost >proxy.log 2>&1 </dev/null &
17 $ "$TESTDIR/tinyproxy.py" $HGPORT1 localhost >proxy.log 2>&1 </dev/null &
18 $ while [ ! -f proxy.pid ]; do sleep 0; done
18 $ while [ ! -f proxy.pid ]; do sleep 0; done
19 $ cat proxy.pid >> $DAEMON_PIDS
19 $ cat proxy.pid >> $DAEMON_PIDS
20
20
21 url for proxy, stream
21 url for proxy, stream
22
22
23 $ http_proxy=http://localhost:$HGPORT1/ hg --config http_proxy.always=True clone --uncompressed http://localhost:$HGPORT/ b
23 $ http_proxy=http://localhost:$HGPORT1/ hg --config http_proxy.always=True clone --uncompressed http://localhost:$HGPORT/ b
24 streaming all changes
24 streaming all changes
25 3 files to transfer, 303 bytes of data
25 3 files to transfer, 303 bytes of data
26 transferred * bytes in * seconds (*/sec) (glob)
26 transferred * bytes in * seconds (*/sec) (glob)
27 searching for changes
27 searching for changes
28 no changes found
28 no changes found
29 updating to branch default
29 updating to branch default
30 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
30 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
31 $ cd b
31 $ cd b
32 $ hg verify
32 $ hg verify
33 checking changesets
33 checking changesets
34 checking manifests
34 checking manifests
35 crosschecking files in changesets and manifests
35 crosschecking files in changesets and manifests
36 checking files
36 checking files
37 1 files, 1 changesets, 1 total revisions
37 1 files, 1 changesets, 1 total revisions
38 $ cd ..
38 $ cd ..
39
39
40 url for proxy, pull
40 url for proxy, pull
41
41
42 $ http_proxy=http://localhost:$HGPORT1/ hg --config http_proxy.always=True clone http://localhost:$HGPORT/ b-pull
42 $ http_proxy=http://localhost:$HGPORT1/ hg --config http_proxy.always=True clone http://localhost:$HGPORT/ b-pull
43 requesting all changes
43 requesting all changes
44 adding changesets
44 adding changesets
45 adding manifests
45 adding manifests
46 adding file changes
46 adding file changes
47 added 1 changesets with 1 changes to 1 files
47 added 1 changesets with 1 changes to 1 files
48 updating to branch default
48 updating to branch default
49 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
49 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
50 $ cd b-pull
50 $ cd b-pull
51 $ hg verify
51 $ hg verify
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 1 files, 1 changesets, 1 total revisions
56 1 files, 1 changesets, 1 total revisions
57 $ cd ..
57 $ cd ..
58
58
59 host:port for proxy
59 host:port for proxy
60
60
61 $ http_proxy=localhost:$HGPORT1 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ c
61 $ http_proxy=localhost:$HGPORT1 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ c
62 requesting all changes
62 requesting all changes
63 adding changesets
63 adding changesets
64 adding manifests
64 adding manifests
65 adding file changes
65 adding file changes
66 added 1 changesets with 1 changes to 1 files
66 added 1 changesets with 1 changes to 1 files
67 updating to branch default
67 updating to branch default
68 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
68 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
69
69
70 proxy url with user name and password
70 proxy url with user name and password
71
71
72 $ http_proxy=http://user:passwd@localhost:$HGPORT1 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ d
72 $ http_proxy=http://user:passwd@localhost:$HGPORT1 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ d
73 requesting all changes
73 requesting all changes
74 adding changesets
74 adding changesets
75 adding manifests
75 adding manifests
76 adding file changes
76 adding file changes
77 added 1 changesets with 1 changes to 1 files
77 added 1 changesets with 1 changes to 1 files
78 updating to branch default
78 updating to branch default
79 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
79 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
80
80
81 url with user name and password
81 url with user name and password
82
82
83 $ http_proxy=http://user:passwd@localhost:$HGPORT1 hg clone --config http_proxy.always=True http://user:passwd@localhost:$HGPORT/ e
83 $ http_proxy=http://user:passwd@localhost:$HGPORT1 hg clone --config http_proxy.always=True http://user:passwd@localhost:$HGPORT/ e
84 requesting all changes
84 requesting all changes
85 adding changesets
85 adding changesets
86 adding manifests
86 adding manifests
87 adding file changes
87 adding file changes
88 added 1 changesets with 1 changes to 1 files
88 added 1 changesets with 1 changes to 1 files
89 updating to branch default
89 updating to branch default
90 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
91
91
92 bad host:port for proxy
92 bad host:port for proxy
93
93
94 $ http_proxy=localhost:$HGPORT2 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ f
94 $ http_proxy=localhost:$HGPORT2 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ f
95 abort: error: Connection refused
95 abort: error: Connection refused
96 [255]
96 [255]
97
97
98 do not use the proxy if it is in the no list
98 do not use the proxy if it is in the no list
99
99
100 $ http_proxy=localhost:$HGPORT1 hg clone --config http_proxy.no=localhost http://localhost:$HGPORT/ g
100 $ http_proxy=localhost:$HGPORT1 hg clone --config http_proxy.no=localhost http://localhost:$HGPORT/ g
101 requesting all changes
101 requesting all changes
102 adding changesets
102 adding changesets
103 adding manifests
103 adding manifests
104 adding file changes
104 adding file changes
105 added 1 changesets with 1 changes to 1 files
105 added 1 changesets with 1 changes to 1 files
106 updating to branch default
106 updating to branch default
107 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
108 $ cat proxy.log
108 $ cat proxy.log
109 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
109 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
110 * - - [*] "GET http://localhost:$HGPORT/?cmd=branchmap HTTP/1.1" - - (glob)
110 * - - [*] "GET http://localhost:$HGPORT/?cmd=branchmap HTTP/1.1" - - (glob)
111 * - - [*] "GET http://localhost:$HGPORT/?cmd=stream_out HTTP/1.1" - - (glob)
111 * - - [*] "GET http://localhost:$HGPORT/?cmd=stream_out HTTP/1.1" - - (glob)
112 * - - [*] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D83180e7845de420a1bb46896fd5fe05294f8d629 (glob)
112 * - - [*] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D83180e7845de420a1bb46896fd5fe05294f8d629 (glob)
113 * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=83180e7845de420a1bb46896fd5fe05294f8d629&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=phase%2Cbookmarks (glob)
113 * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=83180e7845de420a1bb46896fd5fe05294f8d629&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=phase%2Cbookmarks (glob)
114 * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys HTTP/1.1" - - x-hgarg-1:namespace=phases (glob)
114 * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys HTTP/1.1" - - x-hgarg-1:namespace=phases (glob)
115 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
115 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
116 * - - [*] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D (glob)
116 * - - [*] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D (glob)
117 * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=phase%2Cbookmarks (glob)
117 * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=phase%2Cbookmarks (glob)
118 * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys HTTP/1.1" - - x-hgarg-1:namespace=phases (glob)
118 * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys HTTP/1.1" - - x-hgarg-1:namespace=phases (glob)
119 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
119 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
120 * - - [*] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D (glob)
120 * - - [*] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D (glob)
121 * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=phase%2Cbookmarks (glob)
121 * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=phase%2Cbookmarks (glob)
122 * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys HTTP/1.1" - - x-hgarg-1:namespace=phases (glob)
122 * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys HTTP/1.1" - - x-hgarg-1:namespace=phases (glob)
123 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
123 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
124 * - - [*] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D (glob)
124 * - - [*] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D (glob)
125 * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=phase%2Cbookmarks (glob)
125 * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=phase%2Cbookmarks (glob)
126 * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys HTTP/1.1" - - x-hgarg-1:namespace=phases (glob)
126 * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys HTTP/1.1" - - x-hgarg-1:namespace=phases (glob)
127 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
127 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
128 * - - [*] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D (glob)
128 * - - [*] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D (glob)
129 * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=phase%2Cbookmarks (glob)
129 * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=phase%2Cbookmarks (glob)
130 * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys HTTP/1.1" - - x-hgarg-1:namespace=phases (glob)
130 * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys HTTP/1.1" - - x-hgarg-1:namespace=phases (glob)
@@ -1,330 +1,330 b''
1 #require serve
1 #require serve
2
2
3 $ cat << EOF >> $HGRCPATH
3 $ cat << EOF >> $HGRCPATH
4 > [experimental]
4 > [experimental]
5 > # drop me once bundle2 is the default,
5 > # drop me once bundle2 is the default,
6 > # added to get test change early.
6 > # added to get test change early.
7 > bundle2-exp = True
7 > bundle2-exp = True
8 > EOF
8 > EOF
9
9
10 $ hg init test
10 $ hg init test
11 $ cd test
11 $ cd test
12 $ echo foo>foo
12 $ echo foo>foo
13 $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
13 $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
14 $ echo foo>foo.d/foo
14 $ echo foo>foo.d/foo
15 $ echo bar>foo.d/bAr.hg.d/BaR
15 $ echo bar>foo.d/bAr.hg.d/BaR
16 $ echo bar>foo.d/baR.d.hg/bAR
16 $ echo bar>foo.d/baR.d.hg/bAR
17 $ hg commit -A -m 1
17 $ hg commit -A -m 1
18 adding foo
18 adding foo
19 adding foo.d/bAr.hg.d/BaR
19 adding foo.d/bAr.hg.d/BaR
20 adding foo.d/baR.d.hg/bAR
20 adding foo.d/baR.d.hg/bAR
21 adding foo.d/foo
21 adding foo.d/foo
22 $ hg serve -p $HGPORT -d --pid-file=../hg1.pid -E ../error.log
22 $ hg serve -p $HGPORT -d --pid-file=../hg1.pid -E ../error.log
23 $ hg --config server.uncompressed=False serve -p $HGPORT1 -d --pid-file=../hg2.pid
23 $ hg --config server.uncompressed=False serve -p $HGPORT1 -d --pid-file=../hg2.pid
24
24
25 Test server address cannot be reused
25 Test server address cannot be reused
26
26
27 #if windows
27 #if windows
28 $ hg serve -p $HGPORT1 2>&1
28 $ hg serve -p $HGPORT1 2>&1
29 abort: cannot start server at ':$HGPORT1': * (glob)
29 abort: cannot start server at ':$HGPORT1': * (glob)
30 [255]
30 [255]
31 #else
31 #else
32 $ hg serve -p $HGPORT1 2>&1
32 $ hg serve -p $HGPORT1 2>&1
33 abort: cannot start server at ':$HGPORT1': Address already in use
33 abort: cannot start server at ':$HGPORT1': Address already in use
34 [255]
34 [255]
35 #endif
35 #endif
36 $ cd ..
36 $ cd ..
37 $ cat hg1.pid hg2.pid >> $DAEMON_PIDS
37 $ cat hg1.pid hg2.pid >> $DAEMON_PIDS
38
38
39 clone via stream
39 clone via stream
40
40
41 $ hg clone --uncompressed http://localhost:$HGPORT/ copy 2>&1
41 $ hg clone --uncompressed http://localhost:$HGPORT/ copy 2>&1
42 streaming all changes
42 streaming all changes
43 6 files to transfer, 606 bytes of data
43 6 files to transfer, 606 bytes of data
44 transferred * bytes in * seconds (*/sec) (glob)
44 transferred * bytes in * seconds (*/sec) (glob)
45 searching for changes
45 searching for changes
46 no changes found
46 no changes found
47 updating to branch default
47 updating to branch default
48 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
49 $ hg verify -R copy
49 $ hg verify -R copy
50 checking changesets
50 checking changesets
51 checking manifests
51 checking manifests
52 crosschecking files in changesets and manifests
52 crosschecking files in changesets and manifests
53 checking files
53 checking files
54 4 files, 1 changesets, 4 total revisions
54 4 files, 1 changesets, 4 total revisions
55
55
56 try to clone via stream, should use pull instead
56 try to clone via stream, should use pull instead
57
57
58 $ hg clone --uncompressed http://localhost:$HGPORT1/ copy2
58 $ hg clone --uncompressed http://localhost:$HGPORT1/ copy2
59 requesting all changes
59 requesting all changes
60 adding changesets
60 adding changesets
61 adding manifests
61 adding manifests
62 adding file changes
62 adding file changes
63 added 1 changesets with 4 changes to 4 files
63 added 1 changesets with 4 changes to 4 files
64 updating to branch default
64 updating to branch default
65 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
65 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
66
66
67 clone via pull
67 clone via pull
68
68
69 $ hg clone http://localhost:$HGPORT1/ copy-pull
69 $ hg clone http://localhost:$HGPORT1/ copy-pull
70 requesting all changes
70 requesting all changes
71 adding changesets
71 adding changesets
72 adding manifests
72 adding manifests
73 adding file changes
73 adding file changes
74 added 1 changesets with 4 changes to 4 files
74 added 1 changesets with 4 changes to 4 files
75 updating to branch default
75 updating to branch default
76 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
76 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
77 $ hg verify -R copy-pull
77 $ hg verify -R copy-pull
78 checking changesets
78 checking changesets
79 checking manifests
79 checking manifests
80 crosschecking files in changesets and manifests
80 crosschecking files in changesets and manifests
81 checking files
81 checking files
82 4 files, 1 changesets, 4 total revisions
82 4 files, 1 changesets, 4 total revisions
83 $ cd test
83 $ cd test
84 $ echo bar > bar
84 $ echo bar > bar
85 $ hg commit -A -d '1 0' -m 2
85 $ hg commit -A -d '1 0' -m 2
86 adding bar
86 adding bar
87 $ cd ..
87 $ cd ..
88
88
89 clone over http with --update
89 clone over http with --update
90
90
91 $ hg clone http://localhost:$HGPORT1/ updated --update 0
91 $ hg clone http://localhost:$HGPORT1/ updated --update 0
92 requesting all changes
92 requesting all changes
93 adding changesets
93 adding changesets
94 adding manifests
94 adding manifests
95 adding file changes
95 adding file changes
96 added 2 changesets with 5 changes to 5 files
96 added 2 changesets with 5 changes to 5 files
97 updating to branch default
97 updating to branch default
98 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
99 $ hg log -r . -R updated
99 $ hg log -r . -R updated
100 changeset: 0:8b6053c928fe
100 changeset: 0:8b6053c928fe
101 user: test
101 user: test
102 date: Thu Jan 01 00:00:00 1970 +0000
102 date: Thu Jan 01 00:00:00 1970 +0000
103 summary: 1
103 summary: 1
104
104
105 $ rm -rf updated
105 $ rm -rf updated
106
106
107 incoming via HTTP
107 incoming via HTTP
108
108
109 $ hg clone http://localhost:$HGPORT1/ --rev 0 partial
109 $ hg clone http://localhost:$HGPORT1/ --rev 0 partial
110 adding changesets
110 adding changesets
111 adding manifests
111 adding manifests
112 adding file changes
112 adding file changes
113 added 1 changesets with 4 changes to 4 files
113 added 1 changesets with 4 changes to 4 files
114 updating to branch default
114 updating to branch default
115 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
115 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
116 $ cd partial
116 $ cd partial
117 $ touch LOCAL
117 $ touch LOCAL
118 $ hg ci -qAm LOCAL
118 $ hg ci -qAm LOCAL
119 $ hg incoming http://localhost:$HGPORT1/ --template '{desc}\n'
119 $ hg incoming http://localhost:$HGPORT1/ --template '{desc}\n'
120 comparing with http://localhost:$HGPORT1/
120 comparing with http://localhost:$HGPORT1/
121 searching for changes
121 searching for changes
122 2
122 2
123 $ cd ..
123 $ cd ..
124
124
125 pull
125 pull
126
126
127 $ cd copy-pull
127 $ cd copy-pull
128 $ echo '[hooks]' >> .hg/hgrc
128 $ echo '[hooks]' >> .hg/hgrc
129 $ echo "changegroup = python \"$TESTDIR/printenv.py\" changegroup" >> .hg/hgrc
129 $ echo "changegroup = python \"$TESTDIR/printenv.py\" changegroup" >> .hg/hgrc
130 $ hg pull
130 $ hg pull
131 pulling from http://localhost:$HGPORT1/
131 pulling from http://localhost:$HGPORT1/
132 searching for changes
132 searching for changes
133 adding changesets
133 adding changesets
134 adding manifests
134 adding manifests
135 adding file changes
135 adding file changes
136 added 1 changesets with 1 changes to 1 files
136 added 1 changesets with 1 changes to 1 files
137 changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=http://localhost:$HGPORT1/ (glob)
137 changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=http://localhost:$HGPORT1/ (glob)
138 (run 'hg update' to get a working copy)
138 (run 'hg update' to get a working copy)
139 $ cd ..
139 $ cd ..
140
140
141 clone from invalid URL
141 clone from invalid URL
142
142
143 $ hg clone http://localhost:$HGPORT/bad
143 $ hg clone http://localhost:$HGPORT/bad
144 abort: HTTP Error 404: Not Found
144 abort: HTTP Error 404: Not Found
145 [255]
145 [255]
146
146
147 test http authentication
147 test http authentication
148 + use the same server to test server side streaming preference
148 + use the same server to test server side streaming preference
149
149
150 $ cd test
150 $ cd test
151 $ cat << EOT > userpass.py
151 $ cat << EOT > userpass.py
152 > import base64
152 > import base64
153 > from mercurial.hgweb import common
153 > from mercurial.hgweb import common
154 > def perform_authentication(hgweb, req, op):
154 > def perform_authentication(hgweb, req, op):
155 > auth = req.env.get('HTTP_AUTHORIZATION')
155 > auth = req.env.get('HTTP_AUTHORIZATION')
156 > if not auth:
156 > if not auth:
157 > raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, 'who',
157 > raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, 'who',
158 > [('WWW-Authenticate', 'Basic Realm="mercurial"')])
158 > [('WWW-Authenticate', 'Basic Realm="mercurial"')])
159 > if base64.b64decode(auth.split()[1]).split(':', 1) != ['user', 'pass']:
159 > if base64.b64decode(auth.split()[1]).split(':', 1) != ['user', 'pass']:
160 > raise common.ErrorResponse(common.HTTP_FORBIDDEN, 'no')
160 > raise common.ErrorResponse(common.HTTP_FORBIDDEN, 'no')
161 > def extsetup():
161 > def extsetup():
162 > common.permhooks.insert(0, perform_authentication)
162 > common.permhooks.insert(0, perform_authentication)
163 > EOT
163 > EOT
164 $ hg --config extensions.x=userpass.py serve -p $HGPORT2 -d --pid-file=pid \
164 $ hg --config extensions.x=userpass.py serve -p $HGPORT2 -d --pid-file=pid \
165 > --config server.preferuncompressed=True \
165 > --config server.preferuncompressed=True \
166 > --config web.push_ssl=False --config web.allow_push=* -A ../access.log
166 > --config web.push_ssl=False --config web.allow_push=* -A ../access.log
167 $ cat pid >> $DAEMON_PIDS
167 $ cat pid >> $DAEMON_PIDS
168
168
169 $ cat << EOF > get_pass.py
169 $ cat << EOF > get_pass.py
170 > import getpass
170 > import getpass
171 > def newgetpass(arg):
171 > def newgetpass(arg):
172 > return "pass"
172 > return "pass"
173 > getpass.getpass = newgetpass
173 > getpass.getpass = newgetpass
174 > EOF
174 > EOF
175
175
176 $ hg id http://localhost:$HGPORT2/
176 $ hg id http://localhost:$HGPORT2/
177 abort: http authorization required for http://localhost:$HGPORT2/
177 abort: http authorization required for http://localhost:$HGPORT2/
178 [255]
178 [255]
179 $ hg id http://localhost:$HGPORT2/
179 $ hg id http://localhost:$HGPORT2/
180 abort: http authorization required for http://localhost:$HGPORT2/
180 abort: http authorization required for http://localhost:$HGPORT2/
181 [255]
181 [255]
182 $ hg id --config ui.interactive=true --config extensions.getpass=get_pass.py http://user@localhost:$HGPORT2/
182 $ hg id --config ui.interactive=true --config extensions.getpass=get_pass.py http://user@localhost:$HGPORT2/
183 http authorization required for http://localhost:$HGPORT2/
183 http authorization required for http://localhost:$HGPORT2/
184 realm: mercurial
184 realm: mercurial
185 user: user
185 user: user
186 password: 5fed3813f7f5
186 password: 5fed3813f7f5
187 $ hg id http://user:pass@localhost:$HGPORT2/
187 $ hg id http://user:pass@localhost:$HGPORT2/
188 5fed3813f7f5
188 5fed3813f7f5
189 $ echo '[auth]' >> .hg/hgrc
189 $ echo '[auth]' >> .hg/hgrc
190 $ echo 'l.schemes=http' >> .hg/hgrc
190 $ echo 'l.schemes=http' >> .hg/hgrc
191 $ echo 'l.prefix=lo' >> .hg/hgrc
191 $ echo 'l.prefix=lo' >> .hg/hgrc
192 $ echo 'l.username=user' >> .hg/hgrc
192 $ echo 'l.username=user' >> .hg/hgrc
193 $ echo 'l.password=pass' >> .hg/hgrc
193 $ echo 'l.password=pass' >> .hg/hgrc
194 $ hg id http://localhost:$HGPORT2/
194 $ hg id http://localhost:$HGPORT2/
195 5fed3813f7f5
195 5fed3813f7f5
196 $ hg id http://localhost:$HGPORT2/
196 $ hg id http://localhost:$HGPORT2/
197 5fed3813f7f5
197 5fed3813f7f5
198 $ hg id http://user@localhost:$HGPORT2/
198 $ hg id http://user@localhost:$HGPORT2/
199 5fed3813f7f5
199 5fed3813f7f5
200 $ hg clone http://user:pass@localhost:$HGPORT2/ dest 2>&1
200 $ hg clone http://user:pass@localhost:$HGPORT2/ dest 2>&1
201 streaming all changes
201 streaming all changes
202 7 files to transfer, 916 bytes of data
202 7 files to transfer, 916 bytes of data
203 transferred * bytes in * seconds (*/sec) (glob)
203 transferred * bytes in * seconds (*/sec) (glob)
204 searching for changes
204 searching for changes
205 no changes found
205 no changes found
206 updating to branch default
206 updating to branch default
207 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
207 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
208 --pull should override server's preferuncompressed
208 --pull should override server's preferuncompressed
209 $ hg clone --pull http://user:pass@localhost:$HGPORT2/ dest-pull 2>&1
209 $ hg clone --pull http://user:pass@localhost:$HGPORT2/ dest-pull 2>&1
210 requesting all changes
210 requesting all changes
211 adding changesets
211 adding changesets
212 adding manifests
212 adding manifests
213 adding file changes
213 adding file changes
214 added 2 changesets with 5 changes to 5 files
214 added 2 changesets with 5 changes to 5 files
215 updating to branch default
215 updating to branch default
216 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
216 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
217
217
218 $ hg id http://user2@localhost:$HGPORT2/
218 $ hg id http://user2@localhost:$HGPORT2/
219 abort: http authorization required for http://localhost:$HGPORT2/
219 abort: http authorization required for http://localhost:$HGPORT2/
220 [255]
220 [255]
221 $ hg id http://user:pass2@localhost:$HGPORT2/
221 $ hg id http://user:pass2@localhost:$HGPORT2/
222 abort: HTTP Error 403: no
222 abort: HTTP Error 403: no
223 [255]
223 [255]
224
224
225 $ hg -R dest tag -r tip top
225 $ hg -R dest tag -r tip top
226 $ hg -R dest push http://user:pass@localhost:$HGPORT2/
226 $ hg -R dest push http://user:pass@localhost:$HGPORT2/
227 pushing to http://user:***@localhost:$HGPORT2/
227 pushing to http://user:***@localhost:$HGPORT2/
228 searching for changes
228 searching for changes
229 remote: adding changesets
229 remote: adding changesets
230 remote: adding manifests
230 remote: adding manifests
231 remote: adding file changes
231 remote: adding file changes
232 remote: added 1 changesets with 1 changes to 1 files
232 remote: added 1 changesets with 1 changes to 1 files
233 $ hg rollback -q
233 $ hg rollback -q
234
234
235 $ cut -c38- ../access.log
235 $ cut -c38- ../access.log
236 "GET /?cmd=capabilities HTTP/1.1" 200 -
236 "GET /?cmd=capabilities HTTP/1.1" 200 -
237 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
237 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
238 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
238 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
239 "GET /?cmd=capabilities HTTP/1.1" 200 -
239 "GET /?cmd=capabilities HTTP/1.1" 200 -
240 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
240 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
241 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
241 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
242 "GET /?cmd=capabilities HTTP/1.1" 200 -
242 "GET /?cmd=capabilities HTTP/1.1" 200 -
243 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
243 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
244 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
244 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
245 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces
245 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces
246 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks
246 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks
247 "GET /?cmd=capabilities HTTP/1.1" 200 -
247 "GET /?cmd=capabilities HTTP/1.1" 200 -
248 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
248 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
249 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
249 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
250 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces
250 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces
251 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks
251 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks
252 "GET /?cmd=capabilities HTTP/1.1" 200 -
252 "GET /?cmd=capabilities HTTP/1.1" 200 -
253 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
253 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
254 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
254 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
255 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces
255 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces
256 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks
256 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks
257 "GET /?cmd=capabilities HTTP/1.1" 200 -
257 "GET /?cmd=capabilities HTTP/1.1" 200 -
258 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
258 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
259 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
259 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
260 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces
260 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces
261 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks
261 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks
262 "GET /?cmd=capabilities HTTP/1.1" 200 -
262 "GET /?cmd=capabilities HTTP/1.1" 200 -
263 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
263 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
264 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
264 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
265 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces
265 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces
266 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks
266 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks
267 "GET /?cmd=capabilities HTTP/1.1" 200 -
267 "GET /?cmd=capabilities HTTP/1.1" 200 -
268 "GET /?cmd=branchmap HTTP/1.1" 200 -
268 "GET /?cmd=branchmap HTTP/1.1" 200 -
269 "GET /?cmd=stream_out HTTP/1.1" 401 -
269 "GET /?cmd=stream_out HTTP/1.1" 401 -
270 "GET /?cmd=stream_out HTTP/1.1" 200 -
270 "GET /?cmd=stream_out HTTP/1.1" 200 -
271 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D5fed3813f7f5e1824344fdc9cf8f63bb662c292d
271 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D5fed3813f7f5e1824344fdc9cf8f63bb662c292d
272 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phase%2Cbookmarks
272 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phase%2Cbookmarks
273 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases
273 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases
274 "GET /?cmd=capabilities HTTP/1.1" 200 -
274 "GET /?cmd=capabilities HTTP/1.1" 200 -
275 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D
275 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D
276 "GET /?cmd=getbundle HTTP/1.1" 401 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phase%2Cbookmarks
276 "GET /?cmd=getbundle HTTP/1.1" 401 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phase%2Cbookmarks
277 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phase%2Cbookmarks
277 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phase%2Cbookmarks
278 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases
278 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases
279 "GET /?cmd=capabilities HTTP/1.1" 200 -
279 "GET /?cmd=capabilities HTTP/1.1" 200 -
280 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
280 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
281 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
281 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
282 "GET /?cmd=capabilities HTTP/1.1" 200 -
282 "GET /?cmd=capabilities HTTP/1.1" 200 -
283 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
283 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip
284 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
284 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces
285 "GET /?cmd=listkeys HTTP/1.1" 403 - x-hgarg-1:namespace=namespaces
285 "GET /?cmd=listkeys HTTP/1.1" 403 - x-hgarg-1:namespace=namespaces
286 "GET /?cmd=capabilities HTTP/1.1" 200 -
286 "GET /?cmd=capabilities HTTP/1.1" 200 -
287 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872
287 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872
288 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=phases
288 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=phases
289 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases
289 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases
290 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks
290 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks
291 "GET /?cmd=branchmap HTTP/1.1" 200 -
291 "GET /?cmd=branchmap HTTP/1.1" 200 -
292 "GET /?cmd=branchmap HTTP/1.1" 200 -
292 "GET /?cmd=branchmap HTTP/1.1" 200 -
293 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks
293 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks
294 "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=666f726365
294 "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=666f726365
295 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases
295 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases
296
296
297 $ cd ..
297 $ cd ..
298
298
299 clone of serve with repo in root and unserved subrepo (issue2970)
299 clone of serve with repo in root and unserved subrepo (issue2970)
300
300
301 $ hg --cwd test init sub
301 $ hg --cwd test init sub
302 $ echo empty > test/sub/empty
302 $ echo empty > test/sub/empty
303 $ hg --cwd test/sub add empty
303 $ hg --cwd test/sub add empty
304 $ hg --cwd test/sub commit -qm 'add empty'
304 $ hg --cwd test/sub commit -qm 'add empty'
305 $ hg --cwd test/sub tag -r 0 something
305 $ hg --cwd test/sub tag -r 0 something
306 $ echo sub = sub > test/.hgsub
306 $ echo sub = sub > test/.hgsub
307 $ hg --cwd test add .hgsub
307 $ hg --cwd test add .hgsub
308 $ hg --cwd test commit -qm 'add subrepo'
308 $ hg --cwd test commit -qm 'add subrepo'
309 $ hg clone http://localhost:$HGPORT noslash-clone
309 $ hg clone http://localhost:$HGPORT noslash-clone
310 requesting all changes
310 requesting all changes
311 adding changesets
311 adding changesets
312 adding manifests
312 adding manifests
313 adding file changes
313 adding file changes
314 added 3 changesets with 7 changes to 7 files
314 added 3 changesets with 7 changes to 7 files
315 updating to branch default
315 updating to branch default
316 abort: HTTP Error 404: Not Found
316 abort: HTTP Error 404: Not Found
317 [255]
317 [255]
318 $ hg clone http://localhost:$HGPORT/ slash-clone
318 $ hg clone http://localhost:$HGPORT/ slash-clone
319 requesting all changes
319 requesting all changes
320 adding changesets
320 adding changesets
321 adding manifests
321 adding manifests
322 adding file changes
322 adding file changes
323 added 3 changesets with 7 changes to 7 files
323 added 3 changesets with 7 changes to 7 files
324 updating to branch default
324 updating to branch default
325 abort: HTTP Error 404: Not Found
325 abort: HTTP Error 404: Not Found
326 [255]
326 [255]
327
327
328 check error log
328 check error log
329
329
330 $ cat error.log
330 $ cat error.log
@@ -1,512 +1,512 b''
1 This test is a duplicate of 'test-http.t' feel free to factor out
1 This test is a duplicate of 'test-http.t' feel free to factor out
2 parts that are not bundle1/bundle2 specific.
2 parts that are not bundle1/bundle2 specific.
3
3
4 $ cat << EOF >> $HGRCPATH
4 $ cat << EOF >> $HGRCPATH
5 > [experimental]
5 > [experimental]
6 > # This test is dedicated to interaction through old bundle
6 > # This test is dedicated to interaction through old bundle
7 > bundle2-exp = False
7 > bundle2-exp = False
8 > EOF
8 > EOF
9
9
10
10
11 This test tries to exercise the ssh functionality with a dummy script
11 This test tries to exercise the ssh functionality with a dummy script
12
12
13 creating 'remote' repo
13 creating 'remote' repo
14
14
15 $ hg init remote
15 $ hg init remote
16 $ cd remote
16 $ cd remote
17 $ echo this > foo
17 $ echo this > foo
18 $ echo this > fooO
18 $ echo this > fooO
19 $ hg ci -A -m "init" foo fooO
19 $ hg ci -A -m "init" foo fooO
20
20
21 insert a closed branch (issue4428)
21 insert a closed branch (issue4428)
22
22
23 $ hg up null
23 $ hg up null
24 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
24 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
25 $ hg branch closed
25 $ hg branch closed
26 marked working directory as branch closed
26 marked working directory as branch closed
27 (branches are permanent and global, did you want a bookmark?)
27 (branches are permanent and global, did you want a bookmark?)
28 $ hg ci -mc0
28 $ hg ci -mc0
29 $ hg ci --close-branch -mc1
29 $ hg ci --close-branch -mc1
30 $ hg up -q default
30 $ hg up -q default
31
31
32 configure for serving
32 configure for serving
33
33
34 $ cat <<EOF > .hg/hgrc
34 $ cat <<EOF > .hg/hgrc
35 > [server]
35 > [server]
36 > uncompressed = True
36 > uncompressed = True
37 >
37 >
38 > [hooks]
38 > [hooks]
39 > changegroup = python "$TESTDIR/printenv.py" changegroup-in-remote 0 ../dummylog
39 > changegroup = python "$TESTDIR/printenv.py" changegroup-in-remote 0 ../dummylog
40 > EOF
40 > EOF
41 $ cd ..
41 $ cd ..
42
42
43 repo not found error
43 repo not found error
44
44
45 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/nonexistent local
45 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/nonexistent local
46 remote: abort: there is no Mercurial repository here (.hg not found)!
46 remote: abort: there is no Mercurial repository here (.hg not found)!
47 abort: no suitable response from remote hg!
47 abort: no suitable response from remote hg!
48 [255]
48 [255]
49
49
50 non-existent absolute path
50 non-existent absolute path
51
51
52 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy//`pwd`/nonexistent local
52 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy//`pwd`/nonexistent local
53 remote: abort: there is no Mercurial repository here (.hg not found)!
53 remote: abort: there is no Mercurial repository here (.hg not found)!
54 abort: no suitable response from remote hg!
54 abort: no suitable response from remote hg!
55 [255]
55 [255]
56
56
57 clone remote via stream
57 clone remote via stream
58
58
59 $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/remote local-stream
59 $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/remote local-stream
60 streaming all changes
60 streaming all changes
61 4 files to transfer, 615 bytes of data
61 4 files to transfer, 615 bytes of data
62 transferred 615 bytes in * seconds (*) (glob)
62 transferred 615 bytes in * seconds (*) (glob)
63 searching for changes
63 searching for changes
64 no changes found
64 no changes found
65 updating to branch default
65 updating to branch default
66 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
66 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
67 $ cd local-stream
67 $ cd local-stream
68 $ hg verify
68 $ hg verify
69 checking changesets
69 checking changesets
70 checking manifests
70 checking manifests
71 crosschecking files in changesets and manifests
71 crosschecking files in changesets and manifests
72 checking files
72 checking files
73 2 files, 3 changesets, 2 total revisions
73 2 files, 3 changesets, 2 total revisions
74 $ hg branches
74 $ hg branches
75 default 0:1160648e36ce
75 default 0:1160648e36ce
76 $ cd ..
76 $ cd ..
77
77
78 clone bookmarks via stream
78 clone bookmarks via stream
79
79
80 $ hg -R local-stream book mybook
80 $ hg -R local-stream book mybook
81 $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/local-stream stream2
81 $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/local-stream stream2
82 streaming all changes
82 streaming all changes
83 4 files to transfer, 615 bytes of data
83 4 files to transfer, 615 bytes of data
84 transferred 615 bytes in * seconds (*) (glob)
84 transferred 615 bytes in * seconds (*) (glob)
85 searching for changes
85 searching for changes
86 no changes found
86 no changes found
87 updating to branch default
87 updating to branch default
88 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
89 $ cd stream2
89 $ cd stream2
90 $ hg book
90 $ hg book
91 mybook 0:1160648e36ce
91 mybook 0:1160648e36ce
92 $ cd ..
92 $ cd ..
93 $ rm -rf local-stream stream2
93 $ rm -rf local-stream stream2
94
94
95 clone remote via pull
95 clone remote via pull
96
96
97 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local
97 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local
98 requesting all changes
98 requesting all changes
99 adding changesets
99 adding changesets
100 adding manifests
100 adding manifests
101 adding file changes
101 adding file changes
102 added 3 changesets with 2 changes to 2 files
102 added 3 changesets with 2 changes to 2 files
103 updating to branch default
103 updating to branch default
104 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
104 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
105
105
106 verify
106 verify
107
107
108 $ cd local
108 $ cd local
109 $ hg verify
109 $ hg verify
110 checking changesets
110 checking changesets
111 checking manifests
111 checking manifests
112 crosschecking files in changesets and manifests
112 crosschecking files in changesets and manifests
113 checking files
113 checking files
114 2 files, 3 changesets, 2 total revisions
114 2 files, 3 changesets, 2 total revisions
115 $ echo '[hooks]' >> .hg/hgrc
115 $ echo '[hooks]' >> .hg/hgrc
116 $ echo "changegroup = python \"$TESTDIR/printenv.py\" changegroup-in-local 0 ../dummylog" >> .hg/hgrc
116 $ echo "changegroup = python \"$TESTDIR/printenv.py\" changegroup-in-local 0 ../dummylog" >> .hg/hgrc
117
117
118 empty default pull
118 empty default pull
119
119
120 $ hg paths
120 $ hg paths
121 default = ssh://user@dummy/remote
121 default = ssh://user@dummy/remote
122 $ hg pull -e "python \"$TESTDIR/dummyssh\""
122 $ hg pull -e "python \"$TESTDIR/dummyssh\""
123 pulling from ssh://user@dummy/remote
123 pulling from ssh://user@dummy/remote
124 searching for changes
124 searching for changes
125 no changes found
125 no changes found
126
126
127 pull from wrong ssh URL
127 pull from wrong ssh URL
128
128
129 $ hg pull -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/doesnotexist
129 $ hg pull -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/doesnotexist
130 pulling from ssh://user@dummy/doesnotexist
130 pulling from ssh://user@dummy/doesnotexist
131 remote: abort: there is no Mercurial repository here (.hg not found)!
131 remote: abort: there is no Mercurial repository here (.hg not found)!
132 abort: no suitable response from remote hg!
132 abort: no suitable response from remote hg!
133 [255]
133 [255]
134
134
135 local change
135 local change
136
136
137 $ echo bleah > foo
137 $ echo bleah > foo
138 $ hg ci -m "add"
138 $ hg ci -m "add"
139
139
140 updating rc
140 updating rc
141
141
142 $ echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc
142 $ echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc
143 $ echo "[ui]" >> .hg/hgrc
143 $ echo "[ui]" >> .hg/hgrc
144 $ echo "ssh = python \"$TESTDIR/dummyssh\"" >> .hg/hgrc
144 $ echo "ssh = python \"$TESTDIR/dummyssh\"" >> .hg/hgrc
145
145
146 find outgoing
146 find outgoing
147
147
148 $ hg out ssh://user@dummy/remote
148 $ hg out ssh://user@dummy/remote
149 comparing with ssh://user@dummy/remote
149 comparing with ssh://user@dummy/remote
150 searching for changes
150 searching for changes
151 changeset: 3:a28a9d1a809c
151 changeset: 3:a28a9d1a809c
152 tag: tip
152 tag: tip
153 parent: 0:1160648e36ce
153 parent: 0:1160648e36ce
154 user: test
154 user: test
155 date: Thu Jan 01 00:00:00 1970 +0000
155 date: Thu Jan 01 00:00:00 1970 +0000
156 summary: add
156 summary: add
157
157
158
158
159 find incoming on the remote side
159 find incoming on the remote side
160
160
161 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/local
161 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/local
162 comparing with ssh://user@dummy/local
162 comparing with ssh://user@dummy/local
163 searching for changes
163 searching for changes
164 changeset: 3:a28a9d1a809c
164 changeset: 3:a28a9d1a809c
165 tag: tip
165 tag: tip
166 parent: 0:1160648e36ce
166 parent: 0:1160648e36ce
167 user: test
167 user: test
168 date: Thu Jan 01 00:00:00 1970 +0000
168 date: Thu Jan 01 00:00:00 1970 +0000
169 summary: add
169 summary: add
170
170
171
171
172 find incoming on the remote side (using absolute path)
172 find incoming on the remote side (using absolute path)
173
173
174 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/`pwd`"
174 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/`pwd`"
175 comparing with ssh://user@dummy/$TESTTMP/local
175 comparing with ssh://user@dummy/$TESTTMP/local
176 searching for changes
176 searching for changes
177 changeset: 3:a28a9d1a809c
177 changeset: 3:a28a9d1a809c
178 tag: tip
178 tag: tip
179 parent: 0:1160648e36ce
179 parent: 0:1160648e36ce
180 user: test
180 user: test
181 date: Thu Jan 01 00:00:00 1970 +0000
181 date: Thu Jan 01 00:00:00 1970 +0000
182 summary: add
182 summary: add
183
183
184
184
185 push
185 push
186
186
187 $ hg push
187 $ hg push
188 pushing to ssh://user@dummy/remote
188 pushing to ssh://user@dummy/remote
189 searching for changes
189 searching for changes
190 remote: adding changesets
190 remote: adding changesets
191 remote: adding manifests
191 remote: adding manifests
192 remote: adding file changes
192 remote: adding file changes
193 remote: added 1 changesets with 1 changes to 1 files
193 remote: added 1 changesets with 1 changes to 1 files
194 $ cd ../remote
194 $ cd ../remote
195
195
196 check remote tip
196 check remote tip
197
197
198 $ hg tip
198 $ hg tip
199 changeset: 3:a28a9d1a809c
199 changeset: 3:a28a9d1a809c
200 tag: tip
200 tag: tip
201 parent: 0:1160648e36ce
201 parent: 0:1160648e36ce
202 user: test
202 user: test
203 date: Thu Jan 01 00:00:00 1970 +0000
203 date: Thu Jan 01 00:00:00 1970 +0000
204 summary: add
204 summary: add
205
205
206 $ hg verify
206 $ hg verify
207 checking changesets
207 checking changesets
208 checking manifests
208 checking manifests
209 crosschecking files in changesets and manifests
209 crosschecking files in changesets and manifests
210 checking files
210 checking files
211 2 files, 4 changesets, 3 total revisions
211 2 files, 4 changesets, 3 total revisions
212 $ hg cat -r tip foo
212 $ hg cat -r tip foo
213 bleah
213 bleah
214 $ echo z > z
214 $ echo z > z
215 $ hg ci -A -m z z
215 $ hg ci -A -m z z
216 created new head
216 created new head
217
217
218 test pushkeys and bookmarks
218 test pushkeys and bookmarks
219
219
220 $ cd ../local
220 $ cd ../local
221 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote namespaces
221 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote namespaces
222 bookmarks
222 bookmarks
223 namespaces
223 namespaces
224 phases
224 phases
225 $ hg book foo -r 0
225 $ hg book foo -r 0
226 $ hg out -B
226 $ hg out -B
227 comparing with ssh://user@dummy/remote
227 comparing with ssh://user@dummy/remote
228 searching for changed bookmarks
228 searching for changed bookmarks
229 foo 1160648e36ce
229 foo 1160648e36ce
230 $ hg push -B foo
230 $ hg push -B foo
231 pushing to ssh://user@dummy/remote
231 pushing to ssh://user@dummy/remote
232 searching for changes
232 searching for changes
233 no changes found
233 no changes found
234 exporting bookmark foo
234 exporting bookmark foo
235 [1]
235 [1]
236 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote bookmarks
236 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote bookmarks
237 foo 1160648e36cec0054048a7edc4110c6f84fde594
237 foo 1160648e36cec0054048a7edc4110c6f84fde594
238 $ hg book -f foo
238 $ hg book -f foo
239 $ hg push --traceback
239 $ hg push --traceback
240 pushing to ssh://user@dummy/remote
240 pushing to ssh://user@dummy/remote
241 searching for changes
241 searching for changes
242 no changes found
242 no changes found
243 updating bookmark foo
243 updating bookmark foo
244 [1]
244 [1]
245 $ hg book -d foo
245 $ hg book -d foo
246 $ hg in -B
246 $ hg in -B
247 comparing with ssh://user@dummy/remote
247 comparing with ssh://user@dummy/remote
248 searching for changed bookmarks
248 searching for changed bookmarks
249 foo a28a9d1a809c
249 foo a28a9d1a809c
250 $ hg book -f -r 0 foo
250 $ hg book -f -r 0 foo
251 $ hg pull -B foo
251 $ hg pull -B foo
252 pulling from ssh://user@dummy/remote
252 pulling from ssh://user@dummy/remote
253 no changes found
253 no changes found
254 updating bookmark foo
254 updating bookmark foo
255 $ hg book -d foo
255 $ hg book -d foo
256 $ hg push -B foo
256 $ hg push -B foo
257 pushing to ssh://user@dummy/remote
257 pushing to ssh://user@dummy/remote
258 searching for changes
258 searching for changes
259 no changes found
259 no changes found
260 deleting remote bookmark foo
260 deleting remote bookmark foo
261 [1]
261 [1]
262
262
263 a bad, evil hook that prints to stdout
263 a bad, evil hook that prints to stdout
264
264
265 $ cat <<EOF > $TESTTMP/badhook
265 $ cat <<EOF > $TESTTMP/badhook
266 > import sys
266 > import sys
267 > sys.stdout.write("KABOOM\n")
267 > sys.stdout.write("KABOOM\n")
268 > EOF
268 > EOF
269
269
270 $ echo '[hooks]' >> ../remote/.hg/hgrc
270 $ echo '[hooks]' >> ../remote/.hg/hgrc
271 $ echo "changegroup.stdout = python $TESTTMP/badhook" >> ../remote/.hg/hgrc
271 $ echo "changegroup.stdout = python $TESTTMP/badhook" >> ../remote/.hg/hgrc
272 $ echo r > r
272 $ echo r > r
273 $ hg ci -A -m z r
273 $ hg ci -A -m z r
274
274
275 push should succeed even though it has an unexpected response
275 push should succeed even though it has an unexpected response
276
276
277 $ hg push
277 $ hg push
278 pushing to ssh://user@dummy/remote
278 pushing to ssh://user@dummy/remote
279 searching for changes
279 searching for changes
280 remote has heads on branch 'default' that are not known locally: 6c0482d977a3
280 remote has heads on branch 'default' that are not known locally: 6c0482d977a3
281 remote: adding changesets
281 remote: adding changesets
282 remote: adding manifests
282 remote: adding manifests
283 remote: adding file changes
283 remote: adding file changes
284 remote: added 1 changesets with 1 changes to 1 files
284 remote: added 1 changesets with 1 changes to 1 files
285 remote: KABOOM
285 remote: KABOOM
286 $ hg -R ../remote heads
286 $ hg -R ../remote heads
287 changeset: 5:1383141674ec
287 changeset: 5:1383141674ec
288 tag: tip
288 tag: tip
289 parent: 3:a28a9d1a809c
289 parent: 3:a28a9d1a809c
290 user: test
290 user: test
291 date: Thu Jan 01 00:00:00 1970 +0000
291 date: Thu Jan 01 00:00:00 1970 +0000
292 summary: z
292 summary: z
293
293
294 changeset: 4:6c0482d977a3
294 changeset: 4:6c0482d977a3
295 parent: 0:1160648e36ce
295 parent: 0:1160648e36ce
296 user: test
296 user: test
297 date: Thu Jan 01 00:00:00 1970 +0000
297 date: Thu Jan 01 00:00:00 1970 +0000
298 summary: z
298 summary: z
299
299
300
300
301 clone bookmarks
301 clone bookmarks
302
302
303 $ hg -R ../remote bookmark test
303 $ hg -R ../remote bookmark test
304 $ hg -R ../remote bookmarks
304 $ hg -R ../remote bookmarks
305 * test 4:6c0482d977a3
305 * test 4:6c0482d977a3
306 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local-bookmarks
306 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local-bookmarks
307 requesting all changes
307 requesting all changes
308 adding changesets
308 adding changesets
309 adding manifests
309 adding manifests
310 adding file changes
310 adding file changes
311 added 6 changesets with 5 changes to 4 files (+1 heads)
311 added 6 changesets with 5 changes to 4 files (+1 heads)
312 updating to branch default
312 updating to branch default
313 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
313 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
314 $ hg -R local-bookmarks bookmarks
314 $ hg -R local-bookmarks bookmarks
315 test 4:6c0482d977a3
315 test 4:6c0482d977a3
316
316
317 passwords in ssh urls are not supported
317 passwords in ssh urls are not supported
318 (we use a glob here because different Python versions give different
318 (we use a glob here because different Python versions give different
319 results here)
319 results here)
320
320
321 $ hg push ssh://user:erroneouspwd@dummy/remote
321 $ hg push ssh://user:erroneouspwd@dummy/remote
322 pushing to ssh://user:*@dummy/remote (glob)
322 pushing to ssh://user:*@dummy/remote (glob)
323 abort: password in URL not supported!
323 abort: password in URL not supported!
324 [255]
324 [255]
325
325
326 $ cd ..
326 $ cd ..
327
327
328 hide outer repo
328 hide outer repo
329 $ hg init
329 $ hg init
330
330
331 Test remote paths with spaces (issue2983):
331 Test remote paths with spaces (issue2983):
332
332
333 $ hg init --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
333 $ hg init --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
334 $ touch "$TESTTMP/a repo/test"
334 $ touch "$TESTTMP/a repo/test"
335 $ hg -R 'a repo' commit -A -m "test"
335 $ hg -R 'a repo' commit -A -m "test"
336 adding test
336 adding test
337 $ hg -R 'a repo' tag tag
337 $ hg -R 'a repo' tag tag
338 $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
338 $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
339 73649e48688a
339 73649e48688a
340
340
341 $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo#noNoNO"
341 $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo#noNoNO"
342 abort: unknown revision 'noNoNO'!
342 abort: unknown revision 'noNoNO'!
343 [255]
343 [255]
344
344
345 Test (non-)escaping of remote paths with spaces when cloning (issue3145):
345 Test (non-)escaping of remote paths with spaces when cloning (issue3145):
346
346
347 $ hg clone --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
347 $ hg clone --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
348 destination directory: a repo
348 destination directory: a repo
349 abort: destination 'a repo' is not empty
349 abort: destination 'a repo' is not empty
350 [255]
350 [255]
351
351
352 Test hg-ssh using a helper script that will restore PYTHONPATH (which might
352 Test hg-ssh using a helper script that will restore PYTHONPATH (which might
353 have been cleared by a hg.exe wrapper) and invoke hg-ssh with the right
353 have been cleared by a hg.exe wrapper) and invoke hg-ssh with the right
354 parameters:
354 parameters:
355
355
356 $ cat > ssh.sh << EOF
356 $ cat > ssh.sh << EOF
357 > userhost="\$1"
357 > userhost="\$1"
358 > SSH_ORIGINAL_COMMAND="\$2"
358 > SSH_ORIGINAL_COMMAND="\$2"
359 > export SSH_ORIGINAL_COMMAND
359 > export SSH_ORIGINAL_COMMAND
360 > PYTHONPATH="$PYTHONPATH"
360 > PYTHONPATH="$PYTHONPATH"
361 > export PYTHONPATH
361 > export PYTHONPATH
362 > python "$TESTDIR/../contrib/hg-ssh" "$TESTTMP/a repo"
362 > python "$TESTDIR/../contrib/hg-ssh" "$TESTTMP/a repo"
363 > EOF
363 > EOF
364
364
365 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a repo"
365 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a repo"
366 73649e48688a
366 73649e48688a
367
367
368 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a'repo"
368 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a'repo"
369 remote: Illegal repository "$TESTTMP/a'repo" (glob)
369 remote: Illegal repository "$TESTTMP/a'repo" (glob)
370 abort: no suitable response from remote hg!
370 abort: no suitable response from remote hg!
371 [255]
371 [255]
372
372
373 $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo"
373 $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo"
374 remote: Illegal command "hacking -R 'a'\''repo' serve --stdio"
374 remote: Illegal command "hacking -R 'a'\''repo' serve --stdio"
375 abort: no suitable response from remote hg!
375 abort: no suitable response from remote hg!
376 [255]
376 [255]
377
377
378 $ SSH_ORIGINAL_COMMAND="'hg' -R 'a'repo' serve --stdio" python "$TESTDIR/../contrib/hg-ssh"
378 $ SSH_ORIGINAL_COMMAND="'hg' -R 'a'repo' serve --stdio" python "$TESTDIR/../contrib/hg-ssh"
379 Illegal command "'hg' -R 'a'repo' serve --stdio": No closing quotation
379 Illegal command "'hg' -R 'a'repo' serve --stdio": No closing quotation
380 [255]
380 [255]
381
381
382 Test hg-ssh in read-only mode:
382 Test hg-ssh in read-only mode:
383
383
384 $ cat > ssh.sh << EOF
384 $ cat > ssh.sh << EOF
385 > userhost="\$1"
385 > userhost="\$1"
386 > SSH_ORIGINAL_COMMAND="\$2"
386 > SSH_ORIGINAL_COMMAND="\$2"
387 > export SSH_ORIGINAL_COMMAND
387 > export SSH_ORIGINAL_COMMAND
388 > PYTHONPATH="$PYTHONPATH"
388 > PYTHONPATH="$PYTHONPATH"
389 > export PYTHONPATH
389 > export PYTHONPATH
390 > python "$TESTDIR/../contrib/hg-ssh" --read-only "$TESTTMP/remote"
390 > python "$TESTDIR/../contrib/hg-ssh" --read-only "$TESTTMP/remote"
391 > EOF
391 > EOF
392
392
393 $ hg clone --ssh "sh ssh.sh" "ssh://user@dummy/$TESTTMP/remote" read-only-local
393 $ hg clone --ssh "sh ssh.sh" "ssh://user@dummy/$TESTTMP/remote" read-only-local
394 requesting all changes
394 requesting all changes
395 adding changesets
395 adding changesets
396 adding manifests
396 adding manifests
397 adding file changes
397 adding file changes
398 added 6 changesets with 5 changes to 4 files (+1 heads)
398 added 6 changesets with 5 changes to 4 files (+1 heads)
399 updating to branch default
399 updating to branch default
400 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
400 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
401
401
402 $ cd read-only-local
402 $ cd read-only-local
403 $ echo "baz" > bar
403 $ echo "baz" > bar
404 $ hg ci -A -m "unpushable commit" bar
404 $ hg ci -A -m "unpushable commit" bar
405 $ hg push --ssh "sh ../ssh.sh"
405 $ hg push --ssh "sh ../ssh.sh"
406 pushing to ssh://user@dummy/*/remote (glob)
406 pushing to ssh://user@dummy/*/remote (glob)
407 searching for changes
407 searching for changes
408 remote: Permission denied
408 remote: Permission denied
409 remote: abort: pretxnopen.hg-ssh hook failed
409 remote: abort: pretxnopen.hg-ssh hook failed
410 remote: Permission denied
410 remote: Permission denied
411 remote: pushkey-abort: prepushkey.hg-ssh hook failed
411 remote: pushkey-abort: prepushkey.hg-ssh hook failed
412 updating 6c0482d977a3 to public failed!
412 updating 6c0482d977a3 to public failed!
413 [1]
413 [1]
414
414
415 $ cd ..
415 $ cd ..
416
416
417 stderr from remote commands should be printed before stdout from local code (issue4336)
417 stderr from remote commands should be printed before stdout from local code (issue4336)
418
418
419 $ hg clone remote stderr-ordering
419 $ hg clone remote stderr-ordering
420 updating to branch default
420 updating to branch default
421 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
421 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
422 $ cd stderr-ordering
422 $ cd stderr-ordering
423 $ cat >> localwrite.py << EOF
423 $ cat >> localwrite.py << EOF
424 > from mercurial import exchange, extensions
424 > from mercurial import exchange, extensions
425 >
425 >
426 > def wrappedpush(orig, repo, *args, **kwargs):
426 > def wrappedpush(orig, repo, *args, **kwargs):
427 > res = orig(repo, *args, **kwargs)
427 > res = orig(repo, *args, **kwargs)
428 > repo.ui.write('local stdout\n')
428 > repo.ui.write('local stdout\n')
429 > return res
429 > return res
430 >
430 >
431 > def extsetup(ui):
431 > def extsetup(ui):
432 > extensions.wrapfunction(exchange, 'push', wrappedpush)
432 > extensions.wrapfunction(exchange, 'push', wrappedpush)
433 > EOF
433 > EOF
434
434
435 $ cat >> .hg/hgrc << EOF
435 $ cat >> .hg/hgrc << EOF
436 > [paths]
436 > [paths]
437 > default-push = ssh://user@dummy/remote
437 > default-push = ssh://user@dummy/remote
438 > [ui]
438 > [ui]
439 > ssh = python "$TESTDIR/dummyssh"
439 > ssh = python "$TESTDIR/dummyssh"
440 > [extensions]
440 > [extensions]
441 > localwrite = localwrite.py
441 > localwrite = localwrite.py
442 > EOF
442 > EOF
443
443
444 $ echo localwrite > foo
444 $ echo localwrite > foo
445 $ hg commit -m 'testing localwrite'
445 $ hg commit -m 'testing localwrite'
446 $ hg push
446 $ hg push
447 pushing to ssh://user@dummy/remote
447 pushing to ssh://user@dummy/remote
448 searching for changes
448 searching for changes
449 remote: adding changesets
449 remote: adding changesets
450 remote: adding manifests
450 remote: adding manifests
451 remote: adding file changes
451 remote: adding file changes
452 remote: added 1 changesets with 1 changes to 1 files
452 remote: added 1 changesets with 1 changes to 1 files
453 remote: KABOOM
453 remote: KABOOM
454 local stdout
454 local stdout
455
455
456 debug output
456 debug output
457
457
458 $ hg pull --debug ssh://user@dummy/remote
458 $ hg pull --debug ssh://user@dummy/remote
459 pulling from ssh://user@dummy/remote
459 pulling from ssh://user@dummy/remote
460 running python "*/dummyssh" user@dummy 'hg -R remote serve --stdio' (glob)
460 running python "*/dummyssh" user@dummy 'hg -R remote serve --stdio' (glob)
461 sending hello command
461 sending hello command
462 sending between command
462 sending between command
463 remote: 271
463 remote: 286
464 remote: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch stream bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024
464 remote: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch stream bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024
465 remote: 1
465 remote: 1
466 preparing listkeys for "bookmarks"
466 preparing listkeys for "bookmarks"
467 sending listkeys command
467 sending listkeys command
468 received listkey for "bookmarks": 45 bytes
468 received listkey for "bookmarks": 45 bytes
469 query 1; heads
469 query 1; heads
470 sending batch command
470 sending batch command
471 searching for changes
471 searching for changes
472 all remote heads known locally
472 all remote heads known locally
473 no changes found
473 no changes found
474 preparing listkeys for "phases"
474 preparing listkeys for "phases"
475 sending listkeys command
475 sending listkeys command
476 received listkey for "phases": 15 bytes
476 received listkey for "phases": 15 bytes
477 checking for updated bookmarks
477 checking for updated bookmarks
478
478
479 $ cd ..
479 $ cd ..
480
480
481 $ cat dummylog
481 $ cat dummylog
482 Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio
482 Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio
483 Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio
483 Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio
484 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
484 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
485 Got arguments 1:user@dummy 2:hg -R local-stream serve --stdio
485 Got arguments 1:user@dummy 2:hg -R local-stream serve --stdio
486 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
486 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
487 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
487 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
488 Got arguments 1:user@dummy 2:hg -R doesnotexist serve --stdio
488 Got arguments 1:user@dummy 2:hg -R doesnotexist serve --stdio
489 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
489 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
490 Got arguments 1:user@dummy 2:hg -R local serve --stdio
490 Got arguments 1:user@dummy 2:hg -R local serve --stdio
491 Got arguments 1:user@dummy 2:hg -R $TESTTMP/local serve --stdio
491 Got arguments 1:user@dummy 2:hg -R $TESTTMP/local serve --stdio
492 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
492 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
493 changegroup-in-remote hook: HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
493 changegroup-in-remote hook: HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
494 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
494 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
495 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
495 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
496 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
496 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
497 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
497 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
498 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
498 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
499 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
499 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
500 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
500 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
501 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
501 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
502 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
502 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
503 changegroup-in-remote hook: HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
503 changegroup-in-remote hook: HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
504 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
504 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
505 Got arguments 1:user@dummy 2:hg init 'a repo'
505 Got arguments 1:user@dummy 2:hg init 'a repo'
506 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
506 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
507 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
507 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
508 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
508 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
509 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
509 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
510 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
510 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
511 changegroup-in-remote hook: HG_NODE=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
511 changegroup-in-remote hook: HG_NODE=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
512 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
512 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
@@ -1,510 +1,510 b''
1 $ cat << EOF >> $HGRCPATH
1 $ cat << EOF >> $HGRCPATH
2 > [experimental]
2 > [experimental]
3 > # drop me once bundle2 is the default,
3 > # drop me once bundle2 is the default,
4 > # added to get test change early.
4 > # added to get test change early.
5 > bundle2-exp = True
5 > bundle2-exp = True
6 > EOF
6 > EOF
7
7
8
8
9 This test tries to exercise the ssh functionality with a dummy script
9 This test tries to exercise the ssh functionality with a dummy script
10
10
11 creating 'remote' repo
11 creating 'remote' repo
12
12
13 $ hg init remote
13 $ hg init remote
14 $ cd remote
14 $ cd remote
15 $ echo this > foo
15 $ echo this > foo
16 $ echo this > fooO
16 $ echo this > fooO
17 $ hg ci -A -m "init" foo fooO
17 $ hg ci -A -m "init" foo fooO
18
18
19 insert a closed branch (issue4428)
19 insert a closed branch (issue4428)
20
20
21 $ hg up null
21 $ hg up null
22 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
22 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
23 $ hg branch closed
23 $ hg branch closed
24 marked working directory as branch closed
24 marked working directory as branch closed
25 (branches are permanent and global, did you want a bookmark?)
25 (branches are permanent and global, did you want a bookmark?)
26 $ hg ci -mc0
26 $ hg ci -mc0
27 $ hg ci --close-branch -mc1
27 $ hg ci --close-branch -mc1
28 $ hg up -q default
28 $ hg up -q default
29
29
30 configure for serving
30 configure for serving
31
31
32 $ cat <<EOF > .hg/hgrc
32 $ cat <<EOF > .hg/hgrc
33 > [server]
33 > [server]
34 > uncompressed = True
34 > uncompressed = True
35 >
35 >
36 > [hooks]
36 > [hooks]
37 > changegroup = python "$TESTDIR/printenv.py" changegroup-in-remote 0 ../dummylog
37 > changegroup = python "$TESTDIR/printenv.py" changegroup-in-remote 0 ../dummylog
38 > EOF
38 > EOF
39 $ cd ..
39 $ cd ..
40
40
41 repo not found error
41 repo not found error
42
42
43 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/nonexistent local
43 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/nonexistent local
44 remote: abort: there is no Mercurial repository here (.hg not found)!
44 remote: abort: there is no Mercurial repository here (.hg not found)!
45 abort: no suitable response from remote hg!
45 abort: no suitable response from remote hg!
46 [255]
46 [255]
47
47
48 non-existent absolute path
48 non-existent absolute path
49
49
50 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy//`pwd`/nonexistent local
50 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy//`pwd`/nonexistent local
51 remote: abort: there is no Mercurial repository here (.hg not found)!
51 remote: abort: there is no Mercurial repository here (.hg not found)!
52 abort: no suitable response from remote hg!
52 abort: no suitable response from remote hg!
53 [255]
53 [255]
54
54
55 clone remote via stream
55 clone remote via stream
56
56
57 $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/remote local-stream
57 $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/remote local-stream
58 streaming all changes
58 streaming all changes
59 4 files to transfer, 615 bytes of data
59 4 files to transfer, 615 bytes of data
60 transferred 615 bytes in * seconds (*) (glob)
60 transferred 615 bytes in * seconds (*) (glob)
61 searching for changes
61 searching for changes
62 no changes found
62 no changes found
63 updating to branch default
63 updating to branch default
64 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
64 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
65 $ cd local-stream
65 $ cd local-stream
66 $ hg verify
66 $ hg verify
67 checking changesets
67 checking changesets
68 checking manifests
68 checking manifests
69 crosschecking files in changesets and manifests
69 crosschecking files in changesets and manifests
70 checking files
70 checking files
71 2 files, 3 changesets, 2 total revisions
71 2 files, 3 changesets, 2 total revisions
72 $ hg branches
72 $ hg branches
73 default 0:1160648e36ce
73 default 0:1160648e36ce
74 $ cd ..
74 $ cd ..
75
75
76 clone bookmarks via stream
76 clone bookmarks via stream
77
77
78 $ hg -R local-stream book mybook
78 $ hg -R local-stream book mybook
79 $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/local-stream stream2
79 $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/local-stream stream2
80 streaming all changes
80 streaming all changes
81 4 files to transfer, 615 bytes of data
81 4 files to transfer, 615 bytes of data
82 transferred 615 bytes in * seconds (*) (glob)
82 transferred 615 bytes in * seconds (*) (glob)
83 searching for changes
83 searching for changes
84 no changes found
84 no changes found
85 updating to branch default
85 updating to branch default
86 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
86 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 $ cd stream2
87 $ cd stream2
88 $ hg book
88 $ hg book
89 mybook 0:1160648e36ce
89 mybook 0:1160648e36ce
90 $ cd ..
90 $ cd ..
91 $ rm -rf local-stream stream2
91 $ rm -rf local-stream stream2
92
92
93 clone remote via pull
93 clone remote via pull
94
94
95 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local
95 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local
96 requesting all changes
96 requesting all changes
97 adding changesets
97 adding changesets
98 adding manifests
98 adding manifests
99 adding file changes
99 adding file changes
100 added 3 changesets with 2 changes to 2 files
100 added 3 changesets with 2 changes to 2 files
101 updating to branch default
101 updating to branch default
102 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
102 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
103
103
104 verify
104 verify
105
105
106 $ cd local
106 $ cd local
107 $ hg verify
107 $ hg verify
108 checking changesets
108 checking changesets
109 checking manifests
109 checking manifests
110 crosschecking files in changesets and manifests
110 crosschecking files in changesets and manifests
111 checking files
111 checking files
112 2 files, 3 changesets, 2 total revisions
112 2 files, 3 changesets, 2 total revisions
113 $ echo '[hooks]' >> .hg/hgrc
113 $ echo '[hooks]' >> .hg/hgrc
114 $ echo "changegroup = python \"$TESTDIR/printenv.py\" changegroup-in-local 0 ../dummylog" >> .hg/hgrc
114 $ echo "changegroup = python \"$TESTDIR/printenv.py\" changegroup-in-local 0 ../dummylog" >> .hg/hgrc
115
115
116 empty default pull
116 empty default pull
117
117
118 $ hg paths
118 $ hg paths
119 default = ssh://user@dummy/remote
119 default = ssh://user@dummy/remote
120 $ hg pull -e "python \"$TESTDIR/dummyssh\""
120 $ hg pull -e "python \"$TESTDIR/dummyssh\""
121 pulling from ssh://user@dummy/remote
121 pulling from ssh://user@dummy/remote
122 searching for changes
122 searching for changes
123 no changes found
123 no changes found
124
124
125 pull from wrong ssh URL
125 pull from wrong ssh URL
126
126
127 $ hg pull -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/doesnotexist
127 $ hg pull -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/doesnotexist
128 pulling from ssh://user@dummy/doesnotexist
128 pulling from ssh://user@dummy/doesnotexist
129 remote: abort: there is no Mercurial repository here (.hg not found)!
129 remote: abort: there is no Mercurial repository here (.hg not found)!
130 abort: no suitable response from remote hg!
130 abort: no suitable response from remote hg!
131 [255]
131 [255]
132
132
133 local change
133 local change
134
134
135 $ echo bleah > foo
135 $ echo bleah > foo
136 $ hg ci -m "add"
136 $ hg ci -m "add"
137
137
138 updating rc
138 updating rc
139
139
140 $ echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc
140 $ echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc
141 $ echo "[ui]" >> .hg/hgrc
141 $ echo "[ui]" >> .hg/hgrc
142 $ echo "ssh = python \"$TESTDIR/dummyssh\"" >> .hg/hgrc
142 $ echo "ssh = python \"$TESTDIR/dummyssh\"" >> .hg/hgrc
143
143
144 find outgoing
144 find outgoing
145
145
146 $ hg out ssh://user@dummy/remote
146 $ hg out ssh://user@dummy/remote
147 comparing with ssh://user@dummy/remote
147 comparing with ssh://user@dummy/remote
148 searching for changes
148 searching for changes
149 changeset: 3:a28a9d1a809c
149 changeset: 3:a28a9d1a809c
150 tag: tip
150 tag: tip
151 parent: 0:1160648e36ce
151 parent: 0:1160648e36ce
152 user: test
152 user: test
153 date: Thu Jan 01 00:00:00 1970 +0000
153 date: Thu Jan 01 00:00:00 1970 +0000
154 summary: add
154 summary: add
155
155
156
156
157 find incoming on the remote side
157 find incoming on the remote side
158
158
159 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/local
159 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/local
160 comparing with ssh://user@dummy/local
160 comparing with ssh://user@dummy/local
161 searching for changes
161 searching for changes
162 changeset: 3:a28a9d1a809c
162 changeset: 3:a28a9d1a809c
163 tag: tip
163 tag: tip
164 parent: 0:1160648e36ce
164 parent: 0:1160648e36ce
165 user: test
165 user: test
166 date: Thu Jan 01 00:00:00 1970 +0000
166 date: Thu Jan 01 00:00:00 1970 +0000
167 summary: add
167 summary: add
168
168
169
169
170 find incoming on the remote side (using absolute path)
170 find incoming on the remote side (using absolute path)
171
171
172 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/`pwd`"
172 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/`pwd`"
173 comparing with ssh://user@dummy/$TESTTMP/local
173 comparing with ssh://user@dummy/$TESTTMP/local
174 searching for changes
174 searching for changes
175 changeset: 3:a28a9d1a809c
175 changeset: 3:a28a9d1a809c
176 tag: tip
176 tag: tip
177 parent: 0:1160648e36ce
177 parent: 0:1160648e36ce
178 user: test
178 user: test
179 date: Thu Jan 01 00:00:00 1970 +0000
179 date: Thu Jan 01 00:00:00 1970 +0000
180 summary: add
180 summary: add
181
181
182
182
183 push
183 push
184
184
185 $ hg push
185 $ hg push
186 pushing to ssh://user@dummy/remote
186 pushing to ssh://user@dummy/remote
187 searching for changes
187 searching for changes
188 remote: adding changesets
188 remote: adding changesets
189 remote: adding manifests
189 remote: adding manifests
190 remote: adding file changes
190 remote: adding file changes
191 remote: added 1 changesets with 1 changes to 1 files
191 remote: added 1 changesets with 1 changes to 1 files
192 $ cd ../remote
192 $ cd ../remote
193
193
194 check remote tip
194 check remote tip
195
195
196 $ hg tip
196 $ hg tip
197 changeset: 3:a28a9d1a809c
197 changeset: 3:a28a9d1a809c
198 tag: tip
198 tag: tip
199 parent: 0:1160648e36ce
199 parent: 0:1160648e36ce
200 user: test
200 user: test
201 date: Thu Jan 01 00:00:00 1970 +0000
201 date: Thu Jan 01 00:00:00 1970 +0000
202 summary: add
202 summary: add
203
203
204 $ hg verify
204 $ hg verify
205 checking changesets
205 checking changesets
206 checking manifests
206 checking manifests
207 crosschecking files in changesets and manifests
207 crosschecking files in changesets and manifests
208 checking files
208 checking files
209 2 files, 4 changesets, 3 total revisions
209 2 files, 4 changesets, 3 total revisions
210 $ hg cat -r tip foo
210 $ hg cat -r tip foo
211 bleah
211 bleah
212 $ echo z > z
212 $ echo z > z
213 $ hg ci -A -m z z
213 $ hg ci -A -m z z
214 created new head
214 created new head
215
215
216 test pushkeys and bookmarks
216 test pushkeys and bookmarks
217
217
218 $ cd ../local
218 $ cd ../local
219 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote namespaces
219 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote namespaces
220 bookmarks
220 bookmarks
221 namespaces
221 namespaces
222 phases
222 phases
223 $ hg book foo -r 0
223 $ hg book foo -r 0
224 $ hg out -B
224 $ hg out -B
225 comparing with ssh://user@dummy/remote
225 comparing with ssh://user@dummy/remote
226 searching for changed bookmarks
226 searching for changed bookmarks
227 foo 1160648e36ce
227 foo 1160648e36ce
228 $ hg push -B foo
228 $ hg push -B foo
229 pushing to ssh://user@dummy/remote
229 pushing to ssh://user@dummy/remote
230 searching for changes
230 searching for changes
231 no changes found
231 no changes found
232 exporting bookmark foo
232 exporting bookmark foo
233 [1]
233 [1]
234 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote bookmarks
234 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote bookmarks
235 foo 1160648e36cec0054048a7edc4110c6f84fde594
235 foo 1160648e36cec0054048a7edc4110c6f84fde594
236 $ hg book -f foo
236 $ hg book -f foo
237 $ hg push --traceback
237 $ hg push --traceback
238 pushing to ssh://user@dummy/remote
238 pushing to ssh://user@dummy/remote
239 searching for changes
239 searching for changes
240 no changes found
240 no changes found
241 updating bookmark foo
241 updating bookmark foo
242 [1]
242 [1]
243 $ hg book -d foo
243 $ hg book -d foo
244 $ hg in -B
244 $ hg in -B
245 comparing with ssh://user@dummy/remote
245 comparing with ssh://user@dummy/remote
246 searching for changed bookmarks
246 searching for changed bookmarks
247 foo a28a9d1a809c
247 foo a28a9d1a809c
248 $ hg book -f -r 0 foo
248 $ hg book -f -r 0 foo
249 $ hg pull -B foo
249 $ hg pull -B foo
250 pulling from ssh://user@dummy/remote
250 pulling from ssh://user@dummy/remote
251 no changes found
251 no changes found
252 updating bookmark foo
252 updating bookmark foo
253 $ hg book -d foo
253 $ hg book -d foo
254 $ hg push -B foo
254 $ hg push -B foo
255 pushing to ssh://user@dummy/remote
255 pushing to ssh://user@dummy/remote
256 searching for changes
256 searching for changes
257 no changes found
257 no changes found
258 deleting remote bookmark foo
258 deleting remote bookmark foo
259 [1]
259 [1]
260
260
261 a bad, evil hook that prints to stdout
261 a bad, evil hook that prints to stdout
262
262
263 $ cat <<EOF > $TESTTMP/badhook
263 $ cat <<EOF > $TESTTMP/badhook
264 > import sys
264 > import sys
265 > sys.stdout.write("KABOOM\n")
265 > sys.stdout.write("KABOOM\n")
266 > EOF
266 > EOF
267
267
268 $ echo '[hooks]' >> ../remote/.hg/hgrc
268 $ echo '[hooks]' >> ../remote/.hg/hgrc
269 $ echo "changegroup.stdout = python $TESTTMP/badhook" >> ../remote/.hg/hgrc
269 $ echo "changegroup.stdout = python $TESTTMP/badhook" >> ../remote/.hg/hgrc
270 $ echo r > r
270 $ echo r > r
271 $ hg ci -A -m z r
271 $ hg ci -A -m z r
272
272
273 push should succeed even though it has an unexpected response
273 push should succeed even though it has an unexpected response
274
274
275 $ hg push
275 $ hg push
276 pushing to ssh://user@dummy/remote
276 pushing to ssh://user@dummy/remote
277 searching for changes
277 searching for changes
278 remote has heads on branch 'default' that are not known locally: 6c0482d977a3
278 remote has heads on branch 'default' that are not known locally: 6c0482d977a3
279 remote: adding changesets
279 remote: adding changesets
280 remote: adding manifests
280 remote: adding manifests
281 remote: adding file changes
281 remote: adding file changes
282 remote: added 1 changesets with 1 changes to 1 files
282 remote: added 1 changesets with 1 changes to 1 files
283 remote: KABOOM
283 remote: KABOOM
284 $ hg -R ../remote heads
284 $ hg -R ../remote heads
285 changeset: 5:1383141674ec
285 changeset: 5:1383141674ec
286 tag: tip
286 tag: tip
287 parent: 3:a28a9d1a809c
287 parent: 3:a28a9d1a809c
288 user: test
288 user: test
289 date: Thu Jan 01 00:00:00 1970 +0000
289 date: Thu Jan 01 00:00:00 1970 +0000
290 summary: z
290 summary: z
291
291
292 changeset: 4:6c0482d977a3
292 changeset: 4:6c0482d977a3
293 parent: 0:1160648e36ce
293 parent: 0:1160648e36ce
294 user: test
294 user: test
295 date: Thu Jan 01 00:00:00 1970 +0000
295 date: Thu Jan 01 00:00:00 1970 +0000
296 summary: z
296 summary: z
297
297
298
298
299 clone bookmarks
299 clone bookmarks
300
300
301 $ hg -R ../remote bookmark test
301 $ hg -R ../remote bookmark test
302 $ hg -R ../remote bookmarks
302 $ hg -R ../remote bookmarks
303 * test 4:6c0482d977a3
303 * test 4:6c0482d977a3
304 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local-bookmarks
304 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local-bookmarks
305 requesting all changes
305 requesting all changes
306 adding changesets
306 adding changesets
307 adding manifests
307 adding manifests
308 adding file changes
308 adding file changes
309 added 6 changesets with 5 changes to 4 files (+1 heads)
309 added 6 changesets with 5 changes to 4 files (+1 heads)
310 updating to branch default
310 updating to branch default
311 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
311 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
312 $ hg -R local-bookmarks bookmarks
312 $ hg -R local-bookmarks bookmarks
313 test 4:6c0482d977a3
313 test 4:6c0482d977a3
314
314
315 passwords in ssh urls are not supported
315 passwords in ssh urls are not supported
316 (we use a glob here because different Python versions give different
316 (we use a glob here because different Python versions give different
317 results here)
317 results here)
318
318
319 $ hg push ssh://user:erroneouspwd@dummy/remote
319 $ hg push ssh://user:erroneouspwd@dummy/remote
320 pushing to ssh://user:*@dummy/remote (glob)
320 pushing to ssh://user:*@dummy/remote (glob)
321 abort: password in URL not supported!
321 abort: password in URL not supported!
322 [255]
322 [255]
323
323
324 $ cd ..
324 $ cd ..
325
325
326 hide outer repo
326 hide outer repo
327 $ hg init
327 $ hg init
328
328
329 Test remote paths with spaces (issue2983):
329 Test remote paths with spaces (issue2983):
330
330
331 $ hg init --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
331 $ hg init --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
332 $ touch "$TESTTMP/a repo/test"
332 $ touch "$TESTTMP/a repo/test"
333 $ hg -R 'a repo' commit -A -m "test"
333 $ hg -R 'a repo' commit -A -m "test"
334 adding test
334 adding test
335 $ hg -R 'a repo' tag tag
335 $ hg -R 'a repo' tag tag
336 $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
336 $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
337 73649e48688a
337 73649e48688a
338
338
339 $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo#noNoNO"
339 $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo#noNoNO"
340 abort: unknown revision 'noNoNO'!
340 abort: unknown revision 'noNoNO'!
341 [255]
341 [255]
342
342
343 Test (non-)escaping of remote paths with spaces when cloning (issue3145):
343 Test (non-)escaping of remote paths with spaces when cloning (issue3145):
344
344
345 $ hg clone --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
345 $ hg clone --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
346 destination directory: a repo
346 destination directory: a repo
347 abort: destination 'a repo' is not empty
347 abort: destination 'a repo' is not empty
348 [255]
348 [255]
349
349
350 Test hg-ssh using a helper script that will restore PYTHONPATH (which might
350 Test hg-ssh using a helper script that will restore PYTHONPATH (which might
351 have been cleared by a hg.exe wrapper) and invoke hg-ssh with the right
351 have been cleared by a hg.exe wrapper) and invoke hg-ssh with the right
352 parameters:
352 parameters:
353
353
354 $ cat > ssh.sh << EOF
354 $ cat > ssh.sh << EOF
355 > userhost="\$1"
355 > userhost="\$1"
356 > SSH_ORIGINAL_COMMAND="\$2"
356 > SSH_ORIGINAL_COMMAND="\$2"
357 > export SSH_ORIGINAL_COMMAND
357 > export SSH_ORIGINAL_COMMAND
358 > PYTHONPATH="$PYTHONPATH"
358 > PYTHONPATH="$PYTHONPATH"
359 > export PYTHONPATH
359 > export PYTHONPATH
360 > python "$TESTDIR/../contrib/hg-ssh" "$TESTTMP/a repo"
360 > python "$TESTDIR/../contrib/hg-ssh" "$TESTTMP/a repo"
361 > EOF
361 > EOF
362
362
363 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a repo"
363 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a repo"
364 73649e48688a
364 73649e48688a
365
365
366 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a'repo"
366 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a'repo"
367 remote: Illegal repository "$TESTTMP/a'repo" (glob)
367 remote: Illegal repository "$TESTTMP/a'repo" (glob)
368 abort: no suitable response from remote hg!
368 abort: no suitable response from remote hg!
369 [255]
369 [255]
370
370
371 $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo"
371 $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo"
372 remote: Illegal command "hacking -R 'a'\''repo' serve --stdio"
372 remote: Illegal command "hacking -R 'a'\''repo' serve --stdio"
373 abort: no suitable response from remote hg!
373 abort: no suitable response from remote hg!
374 [255]
374 [255]
375
375
376 $ SSH_ORIGINAL_COMMAND="'hg' -R 'a'repo' serve --stdio" python "$TESTDIR/../contrib/hg-ssh"
376 $ SSH_ORIGINAL_COMMAND="'hg' -R 'a'repo' serve --stdio" python "$TESTDIR/../contrib/hg-ssh"
377 Illegal command "'hg' -R 'a'repo' serve --stdio": No closing quotation
377 Illegal command "'hg' -R 'a'repo' serve --stdio": No closing quotation
378 [255]
378 [255]
379
379
380 Test hg-ssh in read-only mode:
380 Test hg-ssh in read-only mode:
381
381
382 $ cat > ssh.sh << EOF
382 $ cat > ssh.sh << EOF
383 > userhost="\$1"
383 > userhost="\$1"
384 > SSH_ORIGINAL_COMMAND="\$2"
384 > SSH_ORIGINAL_COMMAND="\$2"
385 > export SSH_ORIGINAL_COMMAND
385 > export SSH_ORIGINAL_COMMAND
386 > PYTHONPATH="$PYTHONPATH"
386 > PYTHONPATH="$PYTHONPATH"
387 > export PYTHONPATH
387 > export PYTHONPATH
388 > python "$TESTDIR/../contrib/hg-ssh" --read-only "$TESTTMP/remote"
388 > python "$TESTDIR/../contrib/hg-ssh" --read-only "$TESTTMP/remote"
389 > EOF
389 > EOF
390
390
391 $ hg clone --ssh "sh ssh.sh" "ssh://user@dummy/$TESTTMP/remote" read-only-local
391 $ hg clone --ssh "sh ssh.sh" "ssh://user@dummy/$TESTTMP/remote" read-only-local
392 requesting all changes
392 requesting all changes
393 adding changesets
393 adding changesets
394 adding manifests
394 adding manifests
395 adding file changes
395 adding file changes
396 added 6 changesets with 5 changes to 4 files (+1 heads)
396 added 6 changesets with 5 changes to 4 files (+1 heads)
397 updating to branch default
397 updating to branch default
398 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
398 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
399
399
400 $ cd read-only-local
400 $ cd read-only-local
401 $ echo "baz" > bar
401 $ echo "baz" > bar
402 $ hg ci -A -m "unpushable commit" bar
402 $ hg ci -A -m "unpushable commit" bar
403 $ hg push --ssh "sh ../ssh.sh"
403 $ hg push --ssh "sh ../ssh.sh"
404 pushing to ssh://user@dummy/*/remote (glob)
404 pushing to ssh://user@dummy/*/remote (glob)
405 searching for changes
405 searching for changes
406 abort: pretxnopen.hg-ssh hook failed
406 abort: pretxnopen.hg-ssh hook failed
407 remote: Permission denied
407 remote: Permission denied
408 [255]
408 [255]
409
409
410 $ cd ..
410 $ cd ..
411
411
412 stderr from remote commands should be printed before stdout from local code (issue4336)
412 stderr from remote commands should be printed before stdout from local code (issue4336)
413
413
414 $ hg clone remote stderr-ordering
414 $ hg clone remote stderr-ordering
415 updating to branch default
415 updating to branch default
416 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
416 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
417 $ cd stderr-ordering
417 $ cd stderr-ordering
418 $ cat >> localwrite.py << EOF
418 $ cat >> localwrite.py << EOF
419 > from mercurial import exchange, extensions
419 > from mercurial import exchange, extensions
420 >
420 >
421 > def wrappedpush(orig, repo, *args, **kwargs):
421 > def wrappedpush(orig, repo, *args, **kwargs):
422 > res = orig(repo, *args, **kwargs)
422 > res = orig(repo, *args, **kwargs)
423 > repo.ui.write('local stdout\n')
423 > repo.ui.write('local stdout\n')
424 > return res
424 > return res
425 >
425 >
426 > def extsetup(ui):
426 > def extsetup(ui):
427 > extensions.wrapfunction(exchange, 'push', wrappedpush)
427 > extensions.wrapfunction(exchange, 'push', wrappedpush)
428 > EOF
428 > EOF
429
429
430 $ cat >> .hg/hgrc << EOF
430 $ cat >> .hg/hgrc << EOF
431 > [paths]
431 > [paths]
432 > default-push = ssh://user@dummy/remote
432 > default-push = ssh://user@dummy/remote
433 > [ui]
433 > [ui]
434 > ssh = python "$TESTDIR/dummyssh"
434 > ssh = python "$TESTDIR/dummyssh"
435 > [extensions]
435 > [extensions]
436 > localwrite = localwrite.py
436 > localwrite = localwrite.py
437 > EOF
437 > EOF
438
438
439 $ echo localwrite > foo
439 $ echo localwrite > foo
440 $ hg commit -m 'testing localwrite'
440 $ hg commit -m 'testing localwrite'
441 $ hg push
441 $ hg push
442 pushing to ssh://user@dummy/remote
442 pushing to ssh://user@dummy/remote
443 searching for changes
443 searching for changes
444 remote: adding changesets
444 remote: adding changesets
445 remote: adding manifests
445 remote: adding manifests
446 remote: adding file changes
446 remote: adding file changes
447 remote: added 1 changesets with 1 changes to 1 files
447 remote: added 1 changesets with 1 changes to 1 files
448 remote: KABOOM
448 remote: KABOOM
449 local stdout
449 local stdout
450
450
451 debug output
451 debug output
452
452
453 $ hg pull --debug ssh://user@dummy/remote
453 $ hg pull --debug ssh://user@dummy/remote
454 pulling from ssh://user@dummy/remote
454 pulling from ssh://user@dummy/remote
455 running python "*/dummyssh" user@dummy 'hg -R remote serve --stdio' (glob)
455 running python "*/dummyssh" user@dummy 'hg -R remote serve --stdio' (glob)
456 sending hello command
456 sending hello command
457 sending between command
457 sending between command
458 remote: 271
458 remote: 286
459 remote: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch stream bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024
459 remote: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch stream bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024
460 remote: 1
460 remote: 1
461 query 1; heads
461 query 1; heads
462 sending batch command
462 sending batch command
463 searching for changes
463 searching for changes
464 all remote heads known locally
464 all remote heads known locally
465 no changes found
465 no changes found
466 sending getbundle command
466 sending getbundle command
467 bundle2-input-bundle: with-transaction
467 bundle2-input-bundle: with-transaction
468 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
468 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
469 bundle2-input-part: total payload size 45
469 bundle2-input-part: total payload size 45
470 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
470 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
471 bundle2-input-bundle: 1 parts total
471 bundle2-input-bundle: 1 parts total
472 checking for updated bookmarks
472 checking for updated bookmarks
473 preparing listkeys for "phases"
473 preparing listkeys for "phases"
474 sending listkeys command
474 sending listkeys command
475 received listkey for "phases": 15 bytes
475 received listkey for "phases": 15 bytes
476
476
477 $ cd ..
477 $ cd ..
478
478
479 $ cat dummylog
479 $ cat dummylog
480 Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio
480 Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio
481 Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio
481 Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio
482 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
482 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
483 Got arguments 1:user@dummy 2:hg -R local-stream serve --stdio
483 Got arguments 1:user@dummy 2:hg -R local-stream serve --stdio
484 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
484 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
485 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
485 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
486 Got arguments 1:user@dummy 2:hg -R doesnotexist serve --stdio
486 Got arguments 1:user@dummy 2:hg -R doesnotexist serve --stdio
487 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
487 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
488 Got arguments 1:user@dummy 2:hg -R local serve --stdio
488 Got arguments 1:user@dummy 2:hg -R local serve --stdio
489 Got arguments 1:user@dummy 2:hg -R $TESTTMP/local serve --stdio
489 Got arguments 1:user@dummy 2:hg -R $TESTTMP/local serve --stdio
490 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
490 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
491 changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
491 changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
492 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
492 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
493 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
493 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
494 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
494 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
495 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
495 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
496 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
496 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
497 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
497 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
498 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
498 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
499 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
499 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
500 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
500 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
501 changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
501 changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
502 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
502 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
503 Got arguments 1:user@dummy 2:hg init 'a repo'
503 Got arguments 1:user@dummy 2:hg init 'a repo'
504 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
504 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
505 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
505 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
506 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
506 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
507 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
507 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
508 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
508 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
509 changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
509 changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:ssh:127.0.0.1 (glob)
510 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
510 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
General Comments 0
You need to be logged in to leave comments. Login now