##// END OF EJS Templates
phases: abort the whole push if phases fail to update (BC)...
Pierre-Yves David -
r25502:bd41c193 default
parent child Browse files
Show More
@@ -1,1565 +1,1574 b''
1 # exchange.py - utility to exchange data between repos.
1 # exchange.py - utility to exchange data between repos.
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 import time
8 import time
9 from i18n import _
9 from i18n import _
10 from node import hex, nullid
10 from node import hex, nullid
11 import errno, urllib
11 import errno, urllib
12 import util, scmutil, changegroup, base85, error, store
12 import util, scmutil, changegroup, base85, error, store
13 import discovery, phases, obsolete, bookmarks as bookmod, bundle2, pushkey
13 import discovery, phases, obsolete, bookmarks as bookmod, bundle2, pushkey
14 import lock as lockmod
14 import lock as lockmod
15 import tags
15 import tags
16
16
17 def readbundle(ui, fh, fname, vfs=None):
17 def readbundle(ui, fh, fname, vfs=None):
18 header = changegroup.readexactly(fh, 4)
18 header = changegroup.readexactly(fh, 4)
19
19
20 alg = None
20 alg = None
21 if not fname:
21 if not fname:
22 fname = "stream"
22 fname = "stream"
23 if not header.startswith('HG') and header.startswith('\0'):
23 if not header.startswith('HG') and header.startswith('\0'):
24 fh = changegroup.headerlessfixup(fh, header)
24 fh = changegroup.headerlessfixup(fh, header)
25 header = "HG10"
25 header = "HG10"
26 alg = 'UN'
26 alg = 'UN'
27 elif vfs:
27 elif vfs:
28 fname = vfs.join(fname)
28 fname = vfs.join(fname)
29
29
30 magic, version = header[0:2], header[2:4]
30 magic, version = header[0:2], header[2:4]
31
31
32 if magic != 'HG':
32 if magic != 'HG':
33 raise util.Abort(_('%s: not a Mercurial bundle') % fname)
33 raise util.Abort(_('%s: not a Mercurial bundle') % fname)
34 if version == '10':
34 if version == '10':
35 if alg is None:
35 if alg is None:
36 alg = changegroup.readexactly(fh, 2)
36 alg = changegroup.readexactly(fh, 2)
37 return changegroup.cg1unpacker(fh, alg)
37 return changegroup.cg1unpacker(fh, alg)
38 elif version.startswith('2'):
38 elif version.startswith('2'):
39 return bundle2.getunbundler(ui, fh, header=magic + version)
39 return bundle2.getunbundler(ui, fh, header=magic + version)
40 else:
40 else:
41 raise util.Abort(_('%s: unknown bundle version %s') % (fname, version))
41 raise util.Abort(_('%s: unknown bundle version %s') % (fname, version))
42
42
43 def buildobsmarkerspart(bundler, markers):
43 def buildobsmarkerspart(bundler, markers):
44 """add an obsmarker part to the bundler with <markers>
44 """add an obsmarker part to the bundler with <markers>
45
45
46 No part is created if markers is empty.
46 No part is created if markers is empty.
47 Raises ValueError if the bundler doesn't support any known obsmarker format.
47 Raises ValueError if the bundler doesn't support any known obsmarker format.
48 """
48 """
49 if markers:
49 if markers:
50 remoteversions = bundle2.obsmarkersversion(bundler.capabilities)
50 remoteversions = bundle2.obsmarkersversion(bundler.capabilities)
51 version = obsolete.commonversion(remoteversions)
51 version = obsolete.commonversion(remoteversions)
52 if version is None:
52 if version is None:
53 raise ValueError('bundler do not support common obsmarker format')
53 raise ValueError('bundler do not support common obsmarker format')
54 stream = obsolete.encodemarkers(markers, True, version=version)
54 stream = obsolete.encodemarkers(markers, True, version=version)
55 return bundler.newpart('obsmarkers', data=stream)
55 return bundler.newpart('obsmarkers', data=stream)
56 return None
56 return None
57
57
58 def _canusebundle2(op):
58 def _canusebundle2(op):
59 """return true if a pull/push can use bundle2
59 """return true if a pull/push can use bundle2
60
60
61 Feel free to nuke this function when we drop the experimental option"""
61 Feel free to nuke this function when we drop the experimental option"""
62 return (op.repo.ui.configbool('experimental', 'bundle2-exp', True)
62 return (op.repo.ui.configbool('experimental', 'bundle2-exp', True)
63 and op.remote.capable('bundle2'))
63 and op.remote.capable('bundle2'))
64
64
65
65
66 class pushoperation(object):
66 class pushoperation(object):
67 """A object that represent a single push operation
67 """A object that represent a single push operation
68
68
69 It purpose is to carry push related state and very common operation.
69 It purpose is to carry push related state and very common operation.
70
70
71 A new should be created at the beginning of each push and discarded
71 A new should be created at the beginning of each push and discarded
72 afterward.
72 afterward.
73 """
73 """
74
74
75 def __init__(self, repo, remote, force=False, revs=None, newbranch=False,
75 def __init__(self, repo, remote, force=False, revs=None, newbranch=False,
76 bookmarks=()):
76 bookmarks=()):
77 # repo we push from
77 # repo we push from
78 self.repo = repo
78 self.repo = repo
79 self.ui = repo.ui
79 self.ui = repo.ui
80 # repo we push to
80 # repo we push to
81 self.remote = remote
81 self.remote = remote
82 # force option provided
82 # force option provided
83 self.force = force
83 self.force = force
84 # revs to be pushed (None is "all")
84 # revs to be pushed (None is "all")
85 self.revs = revs
85 self.revs = revs
86 # bookmark explicitly pushed
86 # bookmark explicitly pushed
87 self.bookmarks = bookmarks
87 self.bookmarks = bookmarks
88 # allow push of new branch
88 # allow push of new branch
89 self.newbranch = newbranch
89 self.newbranch = newbranch
90 # did a local lock get acquired?
90 # did a local lock get acquired?
91 self.locallocked = None
91 self.locallocked = None
92 # step already performed
92 # step already performed
93 # (used to check what steps have been already performed through bundle2)
93 # (used to check what steps have been already performed through bundle2)
94 self.stepsdone = set()
94 self.stepsdone = set()
95 # Integer version of the changegroup push result
95 # Integer version of the changegroup push result
96 # - None means nothing to push
96 # - None means nothing to push
97 # - 0 means HTTP error
97 # - 0 means HTTP error
98 # - 1 means we pushed and remote head count is unchanged *or*
98 # - 1 means we pushed and remote head count is unchanged *or*
99 # we have outgoing changesets but refused to push
99 # we have outgoing changesets but refused to push
100 # - other values as described by addchangegroup()
100 # - other values as described by addchangegroup()
101 self.cgresult = None
101 self.cgresult = None
102 # Boolean value for the bookmark push
102 # Boolean value for the bookmark push
103 self.bkresult = None
103 self.bkresult = None
104 # discover.outgoing object (contains common and outgoing data)
104 # discover.outgoing object (contains common and outgoing data)
105 self.outgoing = None
105 self.outgoing = None
106 # all remote heads before the push
106 # all remote heads before the push
107 self.remoteheads = None
107 self.remoteheads = None
108 # testable as a boolean indicating if any nodes are missing locally.
108 # testable as a boolean indicating if any nodes are missing locally.
109 self.incoming = None
109 self.incoming = None
110 # phases changes that must be pushed along side the changesets
110 # phases changes that must be pushed along side the changesets
111 self.outdatedphases = None
111 self.outdatedphases = None
112 # phases changes that must be pushed if changeset push fails
112 # phases changes that must be pushed if changeset push fails
113 self.fallbackoutdatedphases = None
113 self.fallbackoutdatedphases = None
114 # outgoing obsmarkers
114 # outgoing obsmarkers
115 self.outobsmarkers = set()
115 self.outobsmarkers = set()
116 # outgoing bookmarks
116 # outgoing bookmarks
117 self.outbookmarks = []
117 self.outbookmarks = []
118 # transaction manager
118 # transaction manager
119 self.trmanager = None
119 self.trmanager = None
120 # map { pushkey partid -> callback handling failure}
120 # map { pushkey partid -> callback handling failure}
121 # used to handle exception from mandatory pushkey part failure
121 # used to handle exception from mandatory pushkey part failure
122 self.pkfailcb = {}
122 self.pkfailcb = {}
123
123
124 @util.propertycache
124 @util.propertycache
125 def futureheads(self):
125 def futureheads(self):
126 """future remote heads if the changeset push succeeds"""
126 """future remote heads if the changeset push succeeds"""
127 return self.outgoing.missingheads
127 return self.outgoing.missingheads
128
128
129 @util.propertycache
129 @util.propertycache
130 def fallbackheads(self):
130 def fallbackheads(self):
131 """future remote heads if the changeset push fails"""
131 """future remote heads if the changeset push fails"""
132 if self.revs is None:
132 if self.revs is None:
133 # not target to push, all common are relevant
133 # not target to push, all common are relevant
134 return self.outgoing.commonheads
134 return self.outgoing.commonheads
135 unfi = self.repo.unfiltered()
135 unfi = self.repo.unfiltered()
136 # I want cheads = heads(::missingheads and ::commonheads)
136 # I want cheads = heads(::missingheads and ::commonheads)
137 # (missingheads is revs with secret changeset filtered out)
137 # (missingheads is revs with secret changeset filtered out)
138 #
138 #
139 # This can be expressed as:
139 # This can be expressed as:
140 # cheads = ( (missingheads and ::commonheads)
140 # cheads = ( (missingheads and ::commonheads)
141 # + (commonheads and ::missingheads))"
141 # + (commonheads and ::missingheads))"
142 # )
142 # )
143 #
143 #
144 # while trying to push we already computed the following:
144 # while trying to push we already computed the following:
145 # common = (::commonheads)
145 # common = (::commonheads)
146 # missing = ((commonheads::missingheads) - commonheads)
146 # missing = ((commonheads::missingheads) - commonheads)
147 #
147 #
148 # We can pick:
148 # We can pick:
149 # * missingheads part of common (::commonheads)
149 # * missingheads part of common (::commonheads)
150 common = set(self.outgoing.common)
150 common = set(self.outgoing.common)
151 nm = self.repo.changelog.nodemap
151 nm = self.repo.changelog.nodemap
152 cheads = [node for node in self.revs if nm[node] in common]
152 cheads = [node for node in self.revs if nm[node] in common]
153 # and
153 # and
154 # * commonheads parents on missing
154 # * commonheads parents on missing
155 revset = unfi.set('%ln and parents(roots(%ln))',
155 revset = unfi.set('%ln and parents(roots(%ln))',
156 self.outgoing.commonheads,
156 self.outgoing.commonheads,
157 self.outgoing.missing)
157 self.outgoing.missing)
158 cheads.extend(c.node() for c in revset)
158 cheads.extend(c.node() for c in revset)
159 return cheads
159 return cheads
160
160
161 @property
161 @property
162 def commonheads(self):
162 def commonheads(self):
163 """set of all common heads after changeset bundle push"""
163 """set of all common heads after changeset bundle push"""
164 if self.cgresult:
164 if self.cgresult:
165 return self.futureheads
165 return self.futureheads
166 else:
166 else:
167 return self.fallbackheads
167 return self.fallbackheads
168
168
169 # mapping of message used when pushing bookmark
169 # mapping of message used when pushing bookmark
170 bookmsgmap = {'update': (_("updating bookmark %s\n"),
170 bookmsgmap = {'update': (_("updating bookmark %s\n"),
171 _('updating bookmark %s failed!\n')),
171 _('updating bookmark %s failed!\n')),
172 'export': (_("exporting bookmark %s\n"),
172 'export': (_("exporting bookmark %s\n"),
173 _('exporting bookmark %s failed!\n')),
173 _('exporting bookmark %s failed!\n')),
174 'delete': (_("deleting remote bookmark %s\n"),
174 'delete': (_("deleting remote bookmark %s\n"),
175 _('deleting remote bookmark %s failed!\n')),
175 _('deleting remote bookmark %s failed!\n')),
176 }
176 }
177
177
178
178
179 def push(repo, remote, force=False, revs=None, newbranch=False, bookmarks=()):
179 def push(repo, remote, force=False, revs=None, newbranch=False, bookmarks=()):
180 '''Push outgoing changesets (limited by revs) from a local
180 '''Push outgoing changesets (limited by revs) from a local
181 repository to remote. Return an integer:
181 repository to remote. Return an integer:
182 - None means nothing to push
182 - None means nothing to push
183 - 0 means HTTP error
183 - 0 means HTTP error
184 - 1 means we pushed and remote head count is unchanged *or*
184 - 1 means we pushed and remote head count is unchanged *or*
185 we have outgoing changesets but refused to push
185 we have outgoing changesets but refused to push
186 - other values as described by addchangegroup()
186 - other values as described by addchangegroup()
187 '''
187 '''
188 pushop = pushoperation(repo, remote, force, revs, newbranch, bookmarks)
188 pushop = pushoperation(repo, remote, force, revs, newbranch, bookmarks)
189 if pushop.remote.local():
189 if pushop.remote.local():
190 missing = (set(pushop.repo.requirements)
190 missing = (set(pushop.repo.requirements)
191 - pushop.remote.local().supported)
191 - pushop.remote.local().supported)
192 if missing:
192 if missing:
193 msg = _("required features are not"
193 msg = _("required features are not"
194 " supported in the destination:"
194 " supported in the destination:"
195 " %s") % (', '.join(sorted(missing)))
195 " %s") % (', '.join(sorted(missing)))
196 raise util.Abort(msg)
196 raise util.Abort(msg)
197
197
198 # there are two ways to push to remote repo:
198 # there are two ways to push to remote repo:
199 #
199 #
200 # addchangegroup assumes local user can lock remote
200 # addchangegroup assumes local user can lock remote
201 # repo (local filesystem, old ssh servers).
201 # repo (local filesystem, old ssh servers).
202 #
202 #
203 # unbundle assumes local user cannot lock remote repo (new ssh
203 # unbundle assumes local user cannot lock remote repo (new ssh
204 # servers, http servers).
204 # servers, http servers).
205
205
206 if not pushop.remote.canpush():
206 if not pushop.remote.canpush():
207 raise util.Abort(_("destination does not support push"))
207 raise util.Abort(_("destination does not support push"))
208 # get local lock as we might write phase data
208 # get local lock as we might write phase data
209 localwlock = locallock = None
209 localwlock = locallock = None
210 try:
210 try:
211 # bundle2 push may receive a reply bundle touching bookmarks or other
211 # bundle2 push may receive a reply bundle touching bookmarks or other
212 # things requiring the wlock. Take it now to ensure proper ordering.
212 # things requiring the wlock. Take it now to ensure proper ordering.
213 maypushback = pushop.ui.configbool('experimental', 'bundle2.pushback')
213 maypushback = pushop.ui.configbool('experimental', 'bundle2.pushback')
214 if _canusebundle2(pushop) and maypushback:
214 if _canusebundle2(pushop) and maypushback:
215 localwlock = pushop.repo.wlock()
215 localwlock = pushop.repo.wlock()
216 locallock = pushop.repo.lock()
216 locallock = pushop.repo.lock()
217 pushop.locallocked = True
217 pushop.locallocked = True
218 except IOError, err:
218 except IOError, err:
219 pushop.locallocked = False
219 pushop.locallocked = False
220 if err.errno != errno.EACCES:
220 if err.errno != errno.EACCES:
221 raise
221 raise
222 # source repo cannot be locked.
222 # source repo cannot be locked.
223 # We do not abort the push, but just disable the local phase
223 # We do not abort the push, but just disable the local phase
224 # synchronisation.
224 # synchronisation.
225 msg = 'cannot lock source repository: %s\n' % err
225 msg = 'cannot lock source repository: %s\n' % err
226 pushop.ui.debug(msg)
226 pushop.ui.debug(msg)
227 try:
227 try:
228 if pushop.locallocked:
228 if pushop.locallocked:
229 pushop.trmanager = transactionmanager(repo,
229 pushop.trmanager = transactionmanager(repo,
230 'push-response',
230 'push-response',
231 pushop.remote.url())
231 pushop.remote.url())
232 pushop.repo.checkpush(pushop)
232 pushop.repo.checkpush(pushop)
233 lock = None
233 lock = None
234 unbundle = pushop.remote.capable('unbundle')
234 unbundle = pushop.remote.capable('unbundle')
235 if not unbundle:
235 if not unbundle:
236 lock = pushop.remote.lock()
236 lock = pushop.remote.lock()
237 try:
237 try:
238 _pushdiscovery(pushop)
238 _pushdiscovery(pushop)
239 if _canusebundle2(pushop):
239 if _canusebundle2(pushop):
240 _pushbundle2(pushop)
240 _pushbundle2(pushop)
241 _pushchangeset(pushop)
241 _pushchangeset(pushop)
242 _pushsyncphase(pushop)
242 _pushsyncphase(pushop)
243 _pushobsolete(pushop)
243 _pushobsolete(pushop)
244 _pushbookmark(pushop)
244 _pushbookmark(pushop)
245 finally:
245 finally:
246 if lock is not None:
246 if lock is not None:
247 lock.release()
247 lock.release()
248 if pushop.trmanager:
248 if pushop.trmanager:
249 pushop.trmanager.close()
249 pushop.trmanager.close()
250 finally:
250 finally:
251 if pushop.trmanager:
251 if pushop.trmanager:
252 pushop.trmanager.release()
252 pushop.trmanager.release()
253 if locallock is not None:
253 if locallock is not None:
254 locallock.release()
254 locallock.release()
255 if localwlock is not None:
255 if localwlock is not None:
256 localwlock.release()
256 localwlock.release()
257
257
258 return pushop
258 return pushop
259
259
260 # list of steps to perform discovery before push
260 # list of steps to perform discovery before push
261 pushdiscoveryorder = []
261 pushdiscoveryorder = []
262
262
263 # Mapping between step name and function
263 # Mapping between step name and function
264 #
264 #
265 # This exists to help extensions wrap steps if necessary
265 # This exists to help extensions wrap steps if necessary
266 pushdiscoverymapping = {}
266 pushdiscoverymapping = {}
267
267
268 def pushdiscovery(stepname):
268 def pushdiscovery(stepname):
269 """decorator for function performing discovery before push
269 """decorator for function performing discovery before push
270
270
271 The function is added to the step -> function mapping and appended to the
271 The function is added to the step -> function mapping and appended to the
272 list of steps. Beware that decorated function will be added in order (this
272 list of steps. Beware that decorated function will be added in order (this
273 may matter).
273 may matter).
274
274
275 You can only use this decorator for a new step, if you want to wrap a step
275 You can only use this decorator for a new step, if you want to wrap a step
276 from an extension, change the pushdiscovery dictionary directly."""
276 from an extension, change the pushdiscovery dictionary directly."""
277 def dec(func):
277 def dec(func):
278 assert stepname not in pushdiscoverymapping
278 assert stepname not in pushdiscoverymapping
279 pushdiscoverymapping[stepname] = func
279 pushdiscoverymapping[stepname] = func
280 pushdiscoveryorder.append(stepname)
280 pushdiscoveryorder.append(stepname)
281 return func
281 return func
282 return dec
282 return dec
283
283
284 def _pushdiscovery(pushop):
284 def _pushdiscovery(pushop):
285 """Run all discovery steps"""
285 """Run all discovery steps"""
286 for stepname in pushdiscoveryorder:
286 for stepname in pushdiscoveryorder:
287 step = pushdiscoverymapping[stepname]
287 step = pushdiscoverymapping[stepname]
288 step(pushop)
288 step(pushop)
289
289
290 @pushdiscovery('changeset')
290 @pushdiscovery('changeset')
291 def _pushdiscoverychangeset(pushop):
291 def _pushdiscoverychangeset(pushop):
292 """discover the changeset that need to be pushed"""
292 """discover the changeset that need to be pushed"""
293 fci = discovery.findcommonincoming
293 fci = discovery.findcommonincoming
294 commoninc = fci(pushop.repo, pushop.remote, force=pushop.force)
294 commoninc = fci(pushop.repo, pushop.remote, force=pushop.force)
295 common, inc, remoteheads = commoninc
295 common, inc, remoteheads = commoninc
296 fco = discovery.findcommonoutgoing
296 fco = discovery.findcommonoutgoing
297 outgoing = fco(pushop.repo, pushop.remote, onlyheads=pushop.revs,
297 outgoing = fco(pushop.repo, pushop.remote, onlyheads=pushop.revs,
298 commoninc=commoninc, force=pushop.force)
298 commoninc=commoninc, force=pushop.force)
299 pushop.outgoing = outgoing
299 pushop.outgoing = outgoing
300 pushop.remoteheads = remoteheads
300 pushop.remoteheads = remoteheads
301 pushop.incoming = inc
301 pushop.incoming = inc
302
302
303 @pushdiscovery('phase')
303 @pushdiscovery('phase')
304 def _pushdiscoveryphase(pushop):
304 def _pushdiscoveryphase(pushop):
305 """discover the phase that needs to be pushed
305 """discover the phase that needs to be pushed
306
306
307 (computed for both success and failure case for changesets push)"""
307 (computed for both success and failure case for changesets push)"""
308 outgoing = pushop.outgoing
308 outgoing = pushop.outgoing
309 unfi = pushop.repo.unfiltered()
309 unfi = pushop.repo.unfiltered()
310 remotephases = pushop.remote.listkeys('phases')
310 remotephases = pushop.remote.listkeys('phases')
311 publishing = remotephases.get('publishing', False)
311 publishing = remotephases.get('publishing', False)
312 if (pushop.ui.configbool('ui', '_usedassubrepo', False)
312 if (pushop.ui.configbool('ui', '_usedassubrepo', False)
313 and remotephases # server supports phases
313 and remotephases # server supports phases
314 and not pushop.outgoing.missing # no changesets to be pushed
314 and not pushop.outgoing.missing # no changesets to be pushed
315 and publishing):
315 and publishing):
316 # When:
316 # When:
317 # - this is a subrepo push
317 # - this is a subrepo push
318 # - and remote support phase
318 # - and remote support phase
319 # - and no changeset are to be pushed
319 # - and no changeset are to be pushed
320 # - and remote is publishing
320 # - and remote is publishing
321 # We may be in issue 3871 case!
321 # We may be in issue 3871 case!
322 # We drop the possible phase synchronisation done by
322 # We drop the possible phase synchronisation done by
323 # courtesy to publish changesets possibly locally draft
323 # courtesy to publish changesets possibly locally draft
324 # on the remote.
324 # on the remote.
325 remotephases = {'publishing': 'True'}
325 remotephases = {'publishing': 'True'}
326 ana = phases.analyzeremotephases(pushop.repo,
326 ana = phases.analyzeremotephases(pushop.repo,
327 pushop.fallbackheads,
327 pushop.fallbackheads,
328 remotephases)
328 remotephases)
329 pheads, droots = ana
329 pheads, droots = ana
330 extracond = ''
330 extracond = ''
331 if not publishing:
331 if not publishing:
332 extracond = ' and public()'
332 extracond = ' and public()'
333 revset = 'heads((%%ln::%%ln) %s)' % extracond
333 revset = 'heads((%%ln::%%ln) %s)' % extracond
334 # Get the list of all revs draft on remote by public here.
334 # Get the list of all revs draft on remote by public here.
335 # XXX Beware that revset break if droots is not strictly
335 # XXX Beware that revset break if droots is not strictly
336 # XXX root we may want to ensure it is but it is costly
336 # XXX root we may want to ensure it is but it is costly
337 fallback = list(unfi.set(revset, droots, pushop.fallbackheads))
337 fallback = list(unfi.set(revset, droots, pushop.fallbackheads))
338 if not outgoing.missing:
338 if not outgoing.missing:
339 future = fallback
339 future = fallback
340 else:
340 else:
341 # adds changeset we are going to push as draft
341 # adds changeset we are going to push as draft
342 #
342 #
343 # should not be necessary for publishing server, but because of an
343 # should not be necessary for publishing server, but because of an
344 # issue fixed in xxxxx we have to do it anyway.
344 # issue fixed in xxxxx we have to do it anyway.
345 fdroots = list(unfi.set('roots(%ln + %ln::)',
345 fdroots = list(unfi.set('roots(%ln + %ln::)',
346 outgoing.missing, droots))
346 outgoing.missing, droots))
347 fdroots = [f.node() for f in fdroots]
347 fdroots = [f.node() for f in fdroots]
348 future = list(unfi.set(revset, fdroots, pushop.futureheads))
348 future = list(unfi.set(revset, fdroots, pushop.futureheads))
349 pushop.outdatedphases = future
349 pushop.outdatedphases = future
350 pushop.fallbackoutdatedphases = fallback
350 pushop.fallbackoutdatedphases = fallback
351
351
352 @pushdiscovery('obsmarker')
352 @pushdiscovery('obsmarker')
353 def _pushdiscoveryobsmarkers(pushop):
353 def _pushdiscoveryobsmarkers(pushop):
354 if (obsolete.isenabled(pushop.repo, obsolete.exchangeopt)
354 if (obsolete.isenabled(pushop.repo, obsolete.exchangeopt)
355 and pushop.repo.obsstore
355 and pushop.repo.obsstore
356 and 'obsolete' in pushop.remote.listkeys('namespaces')):
356 and 'obsolete' in pushop.remote.listkeys('namespaces')):
357 repo = pushop.repo
357 repo = pushop.repo
358 # very naive computation, that can be quite expensive on big repo.
358 # very naive computation, that can be quite expensive on big repo.
359 # However: evolution is currently slow on them anyway.
359 # However: evolution is currently slow on them anyway.
360 nodes = (c.node() for c in repo.set('::%ln', pushop.futureheads))
360 nodes = (c.node() for c in repo.set('::%ln', pushop.futureheads))
361 pushop.outobsmarkers = pushop.repo.obsstore.relevantmarkers(nodes)
361 pushop.outobsmarkers = pushop.repo.obsstore.relevantmarkers(nodes)
362
362
363 @pushdiscovery('bookmarks')
363 @pushdiscovery('bookmarks')
364 def _pushdiscoverybookmarks(pushop):
364 def _pushdiscoverybookmarks(pushop):
365 ui = pushop.ui
365 ui = pushop.ui
366 repo = pushop.repo.unfiltered()
366 repo = pushop.repo.unfiltered()
367 remote = pushop.remote
367 remote = pushop.remote
368 ui.debug("checking for updated bookmarks\n")
368 ui.debug("checking for updated bookmarks\n")
369 ancestors = ()
369 ancestors = ()
370 if pushop.revs:
370 if pushop.revs:
371 revnums = map(repo.changelog.rev, pushop.revs)
371 revnums = map(repo.changelog.rev, pushop.revs)
372 ancestors = repo.changelog.ancestors(revnums, inclusive=True)
372 ancestors = repo.changelog.ancestors(revnums, inclusive=True)
373 remotebookmark = remote.listkeys('bookmarks')
373 remotebookmark = remote.listkeys('bookmarks')
374
374
375 explicit = set(pushop.bookmarks)
375 explicit = set(pushop.bookmarks)
376
376
377 comp = bookmod.compare(repo, repo._bookmarks, remotebookmark, srchex=hex)
377 comp = bookmod.compare(repo, repo._bookmarks, remotebookmark, srchex=hex)
378 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = comp
378 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = comp
379 for b, scid, dcid in advsrc:
379 for b, scid, dcid in advsrc:
380 if b in explicit:
380 if b in explicit:
381 explicit.remove(b)
381 explicit.remove(b)
382 if not ancestors or repo[scid].rev() in ancestors:
382 if not ancestors or repo[scid].rev() in ancestors:
383 pushop.outbookmarks.append((b, dcid, scid))
383 pushop.outbookmarks.append((b, dcid, scid))
384 # search added bookmark
384 # search added bookmark
385 for b, scid, dcid in addsrc:
385 for b, scid, dcid in addsrc:
386 if b in explicit:
386 if b in explicit:
387 explicit.remove(b)
387 explicit.remove(b)
388 pushop.outbookmarks.append((b, '', scid))
388 pushop.outbookmarks.append((b, '', scid))
389 # search for overwritten bookmark
389 # search for overwritten bookmark
390 for b, scid, dcid in advdst + diverge + differ:
390 for b, scid, dcid in advdst + diverge + differ:
391 if b in explicit:
391 if b in explicit:
392 explicit.remove(b)
392 explicit.remove(b)
393 pushop.outbookmarks.append((b, dcid, scid))
393 pushop.outbookmarks.append((b, dcid, scid))
394 # search for bookmark to delete
394 # search for bookmark to delete
395 for b, scid, dcid in adddst:
395 for b, scid, dcid in adddst:
396 if b in explicit:
396 if b in explicit:
397 explicit.remove(b)
397 explicit.remove(b)
398 # treat as "deleted locally"
398 # treat as "deleted locally"
399 pushop.outbookmarks.append((b, dcid, ''))
399 pushop.outbookmarks.append((b, dcid, ''))
400 # identical bookmarks shouldn't get reported
400 # identical bookmarks shouldn't get reported
401 for b, scid, dcid in same:
401 for b, scid, dcid in same:
402 if b in explicit:
402 if b in explicit:
403 explicit.remove(b)
403 explicit.remove(b)
404
404
405 if explicit:
405 if explicit:
406 explicit = sorted(explicit)
406 explicit = sorted(explicit)
407 # we should probably list all of them
407 # we should probably list all of them
408 ui.warn(_('bookmark %s does not exist on the local '
408 ui.warn(_('bookmark %s does not exist on the local '
409 'or remote repository!\n') % explicit[0])
409 'or remote repository!\n') % explicit[0])
410 pushop.bkresult = 2
410 pushop.bkresult = 2
411
411
412 pushop.outbookmarks.sort()
412 pushop.outbookmarks.sort()
413
413
414 def _pushcheckoutgoing(pushop):
414 def _pushcheckoutgoing(pushop):
415 outgoing = pushop.outgoing
415 outgoing = pushop.outgoing
416 unfi = pushop.repo.unfiltered()
416 unfi = pushop.repo.unfiltered()
417 if not outgoing.missing:
417 if not outgoing.missing:
418 # nothing to push
418 # nothing to push
419 scmutil.nochangesfound(unfi.ui, unfi, outgoing.excluded)
419 scmutil.nochangesfound(unfi.ui, unfi, outgoing.excluded)
420 return False
420 return False
421 # something to push
421 # something to push
422 if not pushop.force:
422 if not pushop.force:
423 # if repo.obsstore == False --> no obsolete
423 # if repo.obsstore == False --> no obsolete
424 # then, save the iteration
424 # then, save the iteration
425 if unfi.obsstore:
425 if unfi.obsstore:
426 # this message are here for 80 char limit reason
426 # this message are here for 80 char limit reason
427 mso = _("push includes obsolete changeset: %s!")
427 mso = _("push includes obsolete changeset: %s!")
428 mst = {"unstable": _("push includes unstable changeset: %s!"),
428 mst = {"unstable": _("push includes unstable changeset: %s!"),
429 "bumped": _("push includes bumped changeset: %s!"),
429 "bumped": _("push includes bumped changeset: %s!"),
430 "divergent": _("push includes divergent changeset: %s!")}
430 "divergent": _("push includes divergent changeset: %s!")}
431 # If we are to push if there is at least one
431 # If we are to push if there is at least one
432 # obsolete or unstable changeset in missing, at
432 # obsolete or unstable changeset in missing, at
433 # least one of the missinghead will be obsolete or
433 # least one of the missinghead will be obsolete or
434 # unstable. So checking heads only is ok
434 # unstable. So checking heads only is ok
435 for node in outgoing.missingheads:
435 for node in outgoing.missingheads:
436 ctx = unfi[node]
436 ctx = unfi[node]
437 if ctx.obsolete():
437 if ctx.obsolete():
438 raise util.Abort(mso % ctx)
438 raise util.Abort(mso % ctx)
439 elif ctx.troubled():
439 elif ctx.troubled():
440 raise util.Abort(mst[ctx.troubles()[0]] % ctx)
440 raise util.Abort(mst[ctx.troubles()[0]] % ctx)
441 newbm = pushop.ui.configlist('bookmarks', 'pushing')
441 newbm = pushop.ui.configlist('bookmarks', 'pushing')
442 discovery.checkheads(unfi, pushop.remote, outgoing,
442 discovery.checkheads(unfi, pushop.remote, outgoing,
443 pushop.remoteheads,
443 pushop.remoteheads,
444 pushop.newbranch,
444 pushop.newbranch,
445 bool(pushop.incoming),
445 bool(pushop.incoming),
446 newbm)
446 newbm)
447 return True
447 return True
448
448
449 # List of names of steps to perform for an outgoing bundle2, order matters.
449 # List of names of steps to perform for an outgoing bundle2, order matters.
450 b2partsgenorder = []
450 b2partsgenorder = []
451
451
452 # Mapping between step name and function
452 # Mapping between step name and function
453 #
453 #
454 # This exists to help extensions wrap steps if necessary
454 # This exists to help extensions wrap steps if necessary
455 b2partsgenmapping = {}
455 b2partsgenmapping = {}
456
456
457 def b2partsgenerator(stepname, idx=None):
457 def b2partsgenerator(stepname, idx=None):
458 """decorator for function generating bundle2 part
458 """decorator for function generating bundle2 part
459
459
460 The function is added to the step -> function mapping and appended to the
460 The function is added to the step -> function mapping and appended to the
461 list of steps. Beware that decorated functions will be added in order
461 list of steps. Beware that decorated functions will be added in order
462 (this may matter).
462 (this may matter).
463
463
464 You can only use this decorator for new steps, if you want to wrap a step
464 You can only use this decorator for new steps, if you want to wrap a step
465 from an extension, attack the b2partsgenmapping dictionary directly."""
465 from an extension, attack the b2partsgenmapping dictionary directly."""
466 def dec(func):
466 def dec(func):
467 assert stepname not in b2partsgenmapping
467 assert stepname not in b2partsgenmapping
468 b2partsgenmapping[stepname] = func
468 b2partsgenmapping[stepname] = func
469 if idx is None:
469 if idx is None:
470 b2partsgenorder.append(stepname)
470 b2partsgenorder.append(stepname)
471 else:
471 else:
472 b2partsgenorder.insert(idx, stepname)
472 b2partsgenorder.insert(idx, stepname)
473 return func
473 return func
474 return dec
474 return dec
475
475
476 @b2partsgenerator('changeset')
476 @b2partsgenerator('changeset')
477 def _pushb2ctx(pushop, bundler):
477 def _pushb2ctx(pushop, bundler):
478 """handle changegroup push through bundle2
478 """handle changegroup push through bundle2
479
479
480 addchangegroup result is stored in the ``pushop.cgresult`` attribute.
480 addchangegroup result is stored in the ``pushop.cgresult`` attribute.
481 """
481 """
482 if 'changesets' in pushop.stepsdone:
482 if 'changesets' in pushop.stepsdone:
483 return
483 return
484 pushop.stepsdone.add('changesets')
484 pushop.stepsdone.add('changesets')
485 # Send known heads to the server for race detection.
485 # Send known heads to the server for race detection.
486 if not _pushcheckoutgoing(pushop):
486 if not _pushcheckoutgoing(pushop):
487 return
487 return
488 pushop.repo.prepushoutgoinghooks(pushop.repo,
488 pushop.repo.prepushoutgoinghooks(pushop.repo,
489 pushop.remote,
489 pushop.remote,
490 pushop.outgoing)
490 pushop.outgoing)
491 if not pushop.force:
491 if not pushop.force:
492 bundler.newpart('check:heads', data=iter(pushop.remoteheads))
492 bundler.newpart('check:heads', data=iter(pushop.remoteheads))
493 b2caps = bundle2.bundle2caps(pushop.remote)
493 b2caps = bundle2.bundle2caps(pushop.remote)
494 version = None
494 version = None
495 cgversions = b2caps.get('changegroup')
495 cgversions = b2caps.get('changegroup')
496 if not cgversions: # 3.1 and 3.2 ship with an empty value
496 if not cgversions: # 3.1 and 3.2 ship with an empty value
497 cg = changegroup.getlocalchangegroupraw(pushop.repo, 'push',
497 cg = changegroup.getlocalchangegroupraw(pushop.repo, 'push',
498 pushop.outgoing)
498 pushop.outgoing)
499 else:
499 else:
500 cgversions = [v for v in cgversions if v in changegroup.packermap]
500 cgversions = [v for v in cgversions if v in changegroup.packermap]
501 if not cgversions:
501 if not cgversions:
502 raise ValueError(_('no common changegroup version'))
502 raise ValueError(_('no common changegroup version'))
503 version = max(cgversions)
503 version = max(cgversions)
504 cg = changegroup.getlocalchangegroupraw(pushop.repo, 'push',
504 cg = changegroup.getlocalchangegroupraw(pushop.repo, 'push',
505 pushop.outgoing,
505 pushop.outgoing,
506 version=version)
506 version=version)
507 cgpart = bundler.newpart('changegroup', data=cg)
507 cgpart = bundler.newpart('changegroup', data=cg)
508 if version is not None:
508 if version is not None:
509 cgpart.addparam('version', version)
509 cgpart.addparam('version', version)
510 def handlereply(op):
510 def handlereply(op):
511 """extract addchangegroup returns from server reply"""
511 """extract addchangegroup returns from server reply"""
512 cgreplies = op.records.getreplies(cgpart.id)
512 cgreplies = op.records.getreplies(cgpart.id)
513 assert len(cgreplies['changegroup']) == 1
513 assert len(cgreplies['changegroup']) == 1
514 pushop.cgresult = cgreplies['changegroup'][0]['return']
514 pushop.cgresult = cgreplies['changegroup'][0]['return']
515 return handlereply
515 return handlereply
516
516
517 @b2partsgenerator('phase')
517 @b2partsgenerator('phase')
518 def _pushb2phases(pushop, bundler):
518 def _pushb2phases(pushop, bundler):
519 """handle phase push through bundle2"""
519 """handle phase push through bundle2"""
520 if 'phases' in pushop.stepsdone:
520 if 'phases' in pushop.stepsdone:
521 return
521 return
522 b2caps = bundle2.bundle2caps(pushop.remote)
522 b2caps = bundle2.bundle2caps(pushop.remote)
523 if not 'pushkey' in b2caps:
523 if not 'pushkey' in b2caps:
524 return
524 return
525 pushop.stepsdone.add('phases')
525 pushop.stepsdone.add('phases')
526 part2node = []
526 part2node = []
527
528 def handlefailure(pushop, exc):
529 targetid = int(exc.partid)
530 for partid, node in part2node:
531 if partid == targetid:
532 raise error.Abort(_('updating %s to public failed') % node)
533
527 enc = pushkey.encode
534 enc = pushkey.encode
528 for newremotehead in pushop.outdatedphases:
535 for newremotehead in pushop.outdatedphases:
529 part = bundler.newpart('pushkey', mandatory=False)
536 part = bundler.newpart('pushkey')
530 part.addparam('namespace', enc('phases'))
537 part.addparam('namespace', enc('phases'))
531 part.addparam('key', enc(newremotehead.hex()))
538 part.addparam('key', enc(newremotehead.hex()))
532 part.addparam('old', enc(str(phases.draft)))
539 part.addparam('old', enc(str(phases.draft)))
533 part.addparam('new', enc(str(phases.public)))
540 part.addparam('new', enc(str(phases.public)))
534 part2node.append((part.id, newremotehead))
541 part2node.append((part.id, newremotehead))
542 pushop.pkfailcb[part.id] = handlefailure
543
535 def handlereply(op):
544 def handlereply(op):
536 for partid, node in part2node:
545 for partid, node in part2node:
537 partrep = op.records.getreplies(partid)
546 partrep = op.records.getreplies(partid)
538 results = partrep['pushkey']
547 results = partrep['pushkey']
539 assert len(results) <= 1
548 assert len(results) <= 1
540 msg = None
549 msg = None
541 if not results:
550 if not results:
542 msg = _('server ignored update of %s to public!\n') % node
551 msg = _('server ignored update of %s to public!\n') % node
543 elif not int(results[0]['return']):
552 elif not int(results[0]['return']):
544 msg = _('updating %s to public failed!\n') % node
553 msg = _('updating %s to public failed!\n') % node
545 if msg is not None:
554 if msg is not None:
546 pushop.ui.warn(msg)
555 pushop.ui.warn(msg)
547 return handlereply
556 return handlereply
548
557
549 @b2partsgenerator('obsmarkers')
558 @b2partsgenerator('obsmarkers')
550 def _pushb2obsmarkers(pushop, bundler):
559 def _pushb2obsmarkers(pushop, bundler):
551 if 'obsmarkers' in pushop.stepsdone:
560 if 'obsmarkers' in pushop.stepsdone:
552 return
561 return
553 remoteversions = bundle2.obsmarkersversion(bundler.capabilities)
562 remoteversions = bundle2.obsmarkersversion(bundler.capabilities)
554 if obsolete.commonversion(remoteversions) is None:
563 if obsolete.commonversion(remoteversions) is None:
555 return
564 return
556 pushop.stepsdone.add('obsmarkers')
565 pushop.stepsdone.add('obsmarkers')
557 if pushop.outobsmarkers:
566 if pushop.outobsmarkers:
558 markers = sorted(pushop.outobsmarkers)
567 markers = sorted(pushop.outobsmarkers)
559 buildobsmarkerspart(bundler, markers)
568 buildobsmarkerspart(bundler, markers)
560
569
561 @b2partsgenerator('bookmarks')
570 @b2partsgenerator('bookmarks')
562 def _pushb2bookmarks(pushop, bundler):
571 def _pushb2bookmarks(pushop, bundler):
563 """handle phase push through bundle2"""
572 """handle phase push through bundle2"""
564 if 'bookmarks' in pushop.stepsdone:
573 if 'bookmarks' in pushop.stepsdone:
565 return
574 return
566 b2caps = bundle2.bundle2caps(pushop.remote)
575 b2caps = bundle2.bundle2caps(pushop.remote)
567 if 'pushkey' not in b2caps:
576 if 'pushkey' not in b2caps:
568 return
577 return
569 pushop.stepsdone.add('bookmarks')
578 pushop.stepsdone.add('bookmarks')
570 part2book = []
579 part2book = []
571 enc = pushkey.encode
580 enc = pushkey.encode
572
581
573 def handlefailure(pushop, exc):
582 def handlefailure(pushop, exc):
574 targetid = int(exc.partid)
583 targetid = int(exc.partid)
575 for partid, book, action in part2book:
584 for partid, book, action in part2book:
576 if partid == targetid:
585 if partid == targetid:
577 raise error.Abort(bookmsgmap[action][1].rstrip() % book)
586 raise error.Abort(bookmsgmap[action][1].rstrip() % book)
578 # we should not be called for part we did not generated
587 # we should not be called for part we did not generated
579 assert False
588 assert False
580
589
581 for book, old, new in pushop.outbookmarks:
590 for book, old, new in pushop.outbookmarks:
582 part = bundler.newpart('pushkey')
591 part = bundler.newpart('pushkey')
583 part.addparam('namespace', enc('bookmarks'))
592 part.addparam('namespace', enc('bookmarks'))
584 part.addparam('key', enc(book))
593 part.addparam('key', enc(book))
585 part.addparam('old', enc(old))
594 part.addparam('old', enc(old))
586 part.addparam('new', enc(new))
595 part.addparam('new', enc(new))
587 action = 'update'
596 action = 'update'
588 if not old:
597 if not old:
589 action = 'export'
598 action = 'export'
590 elif not new:
599 elif not new:
591 action = 'delete'
600 action = 'delete'
592 part2book.append((part.id, book, action))
601 part2book.append((part.id, book, action))
593 pushop.pkfailcb[part.id] = handlefailure
602 pushop.pkfailcb[part.id] = handlefailure
594
603
595 def handlereply(op):
604 def handlereply(op):
596 ui = pushop.ui
605 ui = pushop.ui
597 for partid, book, action in part2book:
606 for partid, book, action in part2book:
598 partrep = op.records.getreplies(partid)
607 partrep = op.records.getreplies(partid)
599 results = partrep['pushkey']
608 results = partrep['pushkey']
600 assert len(results) <= 1
609 assert len(results) <= 1
601 if not results:
610 if not results:
602 pushop.ui.warn(_('server ignored bookmark %s update\n') % book)
611 pushop.ui.warn(_('server ignored bookmark %s update\n') % book)
603 else:
612 else:
604 ret = int(results[0]['return'])
613 ret = int(results[0]['return'])
605 if ret:
614 if ret:
606 ui.status(bookmsgmap[action][0] % book)
615 ui.status(bookmsgmap[action][0] % book)
607 else:
616 else:
608 ui.warn(bookmsgmap[action][1] % book)
617 ui.warn(bookmsgmap[action][1] % book)
609 if pushop.bkresult is not None:
618 if pushop.bkresult is not None:
610 pushop.bkresult = 1
619 pushop.bkresult = 1
611 return handlereply
620 return handlereply
612
621
613
622
614 def _pushbundle2(pushop):
623 def _pushbundle2(pushop):
615 """push data to the remote using bundle2
624 """push data to the remote using bundle2
616
625
617 The only currently supported type of data is changegroup but this will
626 The only currently supported type of data is changegroup but this will
618 evolve in the future."""
627 evolve in the future."""
619 bundler = bundle2.bundle20(pushop.ui, bundle2.bundle2caps(pushop.remote))
628 bundler = bundle2.bundle20(pushop.ui, bundle2.bundle2caps(pushop.remote))
620 pushback = (pushop.trmanager
629 pushback = (pushop.trmanager
621 and pushop.ui.configbool('experimental', 'bundle2.pushback'))
630 and pushop.ui.configbool('experimental', 'bundle2.pushback'))
622
631
623 # create reply capability
632 # create reply capability
624 capsblob = bundle2.encodecaps(bundle2.getrepocaps(pushop.repo,
633 capsblob = bundle2.encodecaps(bundle2.getrepocaps(pushop.repo,
625 allowpushback=pushback))
634 allowpushback=pushback))
626 bundler.newpart('replycaps', data=capsblob)
635 bundler.newpart('replycaps', data=capsblob)
627 replyhandlers = []
636 replyhandlers = []
628 for partgenname in b2partsgenorder:
637 for partgenname in b2partsgenorder:
629 partgen = b2partsgenmapping[partgenname]
638 partgen = b2partsgenmapping[partgenname]
630 ret = partgen(pushop, bundler)
639 ret = partgen(pushop, bundler)
631 if callable(ret):
640 if callable(ret):
632 replyhandlers.append(ret)
641 replyhandlers.append(ret)
633 # do not push if nothing to push
642 # do not push if nothing to push
634 if bundler.nbparts <= 1:
643 if bundler.nbparts <= 1:
635 return
644 return
636 stream = util.chunkbuffer(bundler.getchunks())
645 stream = util.chunkbuffer(bundler.getchunks())
637 try:
646 try:
638 try:
647 try:
639 reply = pushop.remote.unbundle(stream, ['force'], 'push')
648 reply = pushop.remote.unbundle(stream, ['force'], 'push')
640 except error.BundleValueError, exc:
649 except error.BundleValueError, exc:
641 raise util.Abort('missing support for %s' % exc)
650 raise util.Abort('missing support for %s' % exc)
642 try:
651 try:
643 trgetter = None
652 trgetter = None
644 if pushback:
653 if pushback:
645 trgetter = pushop.trmanager.transaction
654 trgetter = pushop.trmanager.transaction
646 op = bundle2.processbundle(pushop.repo, reply, trgetter)
655 op = bundle2.processbundle(pushop.repo, reply, trgetter)
647 except error.BundleValueError, exc:
656 except error.BundleValueError, exc:
648 raise util.Abort('missing support for %s' % exc)
657 raise util.Abort('missing support for %s' % exc)
649 except error.PushkeyFailed, exc:
658 except error.PushkeyFailed, exc:
650 partid = int(exc.partid)
659 partid = int(exc.partid)
651 if partid not in pushop.pkfailcb:
660 if partid not in pushop.pkfailcb:
652 raise
661 raise
653 pushop.pkfailcb[partid](pushop, exc)
662 pushop.pkfailcb[partid](pushop, exc)
654 for rephand in replyhandlers:
663 for rephand in replyhandlers:
655 rephand(op)
664 rephand(op)
656
665
657 def _pushchangeset(pushop):
666 def _pushchangeset(pushop):
658 """Make the actual push of changeset bundle to remote repo"""
667 """Make the actual push of changeset bundle to remote repo"""
659 if 'changesets' in pushop.stepsdone:
668 if 'changesets' in pushop.stepsdone:
660 return
669 return
661 pushop.stepsdone.add('changesets')
670 pushop.stepsdone.add('changesets')
662 if not _pushcheckoutgoing(pushop):
671 if not _pushcheckoutgoing(pushop):
663 return
672 return
664 pushop.repo.prepushoutgoinghooks(pushop.repo,
673 pushop.repo.prepushoutgoinghooks(pushop.repo,
665 pushop.remote,
674 pushop.remote,
666 pushop.outgoing)
675 pushop.outgoing)
667 outgoing = pushop.outgoing
676 outgoing = pushop.outgoing
668 unbundle = pushop.remote.capable('unbundle')
677 unbundle = pushop.remote.capable('unbundle')
669 # TODO: get bundlecaps from remote
678 # TODO: get bundlecaps from remote
670 bundlecaps = None
679 bundlecaps = None
671 # create a changegroup from local
680 # create a changegroup from local
672 if pushop.revs is None and not (outgoing.excluded
681 if pushop.revs is None and not (outgoing.excluded
673 or pushop.repo.changelog.filteredrevs):
682 or pushop.repo.changelog.filteredrevs):
674 # push everything,
683 # push everything,
675 # use the fast path, no race possible on push
684 # use the fast path, no race possible on push
676 bundler = changegroup.cg1packer(pushop.repo, bundlecaps)
685 bundler = changegroup.cg1packer(pushop.repo, bundlecaps)
677 cg = changegroup.getsubset(pushop.repo,
686 cg = changegroup.getsubset(pushop.repo,
678 outgoing,
687 outgoing,
679 bundler,
688 bundler,
680 'push',
689 'push',
681 fastpath=True)
690 fastpath=True)
682 else:
691 else:
683 cg = changegroup.getlocalchangegroup(pushop.repo, 'push', outgoing,
692 cg = changegroup.getlocalchangegroup(pushop.repo, 'push', outgoing,
684 bundlecaps)
693 bundlecaps)
685
694
686 # apply changegroup to remote
695 # apply changegroup to remote
687 if unbundle:
696 if unbundle:
688 # local repo finds heads on server, finds out what
697 # local repo finds heads on server, finds out what
689 # revs it must push. once revs transferred, if server
698 # revs it must push. once revs transferred, if server
690 # finds it has different heads (someone else won
699 # finds it has different heads (someone else won
691 # commit/push race), server aborts.
700 # commit/push race), server aborts.
692 if pushop.force:
701 if pushop.force:
693 remoteheads = ['force']
702 remoteheads = ['force']
694 else:
703 else:
695 remoteheads = pushop.remoteheads
704 remoteheads = pushop.remoteheads
696 # ssh: return remote's addchangegroup()
705 # ssh: return remote's addchangegroup()
697 # http: return remote's addchangegroup() or 0 for error
706 # http: return remote's addchangegroup() or 0 for error
698 pushop.cgresult = pushop.remote.unbundle(cg, remoteheads,
707 pushop.cgresult = pushop.remote.unbundle(cg, remoteheads,
699 pushop.repo.url())
708 pushop.repo.url())
700 else:
709 else:
701 # we return an integer indicating remote head count
710 # we return an integer indicating remote head count
702 # change
711 # change
703 pushop.cgresult = pushop.remote.addchangegroup(cg, 'push',
712 pushop.cgresult = pushop.remote.addchangegroup(cg, 'push',
704 pushop.repo.url())
713 pushop.repo.url())
705
714
706 def _pushsyncphase(pushop):
715 def _pushsyncphase(pushop):
707 """synchronise phase information locally and remotely"""
716 """synchronise phase information locally and remotely"""
708 cheads = pushop.commonheads
717 cheads = pushop.commonheads
709 # even when we don't push, exchanging phase data is useful
718 # even when we don't push, exchanging phase data is useful
710 remotephases = pushop.remote.listkeys('phases')
719 remotephases = pushop.remote.listkeys('phases')
711 if (pushop.ui.configbool('ui', '_usedassubrepo', False)
720 if (pushop.ui.configbool('ui', '_usedassubrepo', False)
712 and remotephases # server supports phases
721 and remotephases # server supports phases
713 and pushop.cgresult is None # nothing was pushed
722 and pushop.cgresult is None # nothing was pushed
714 and remotephases.get('publishing', False)):
723 and remotephases.get('publishing', False)):
715 # When:
724 # When:
716 # - this is a subrepo push
725 # - this is a subrepo push
717 # - and remote support phase
726 # - and remote support phase
718 # - and no changeset was pushed
727 # - and no changeset was pushed
719 # - and remote is publishing
728 # - and remote is publishing
720 # We may be in issue 3871 case!
729 # We may be in issue 3871 case!
721 # We drop the possible phase synchronisation done by
730 # We drop the possible phase synchronisation done by
722 # courtesy to publish changesets possibly locally draft
731 # courtesy to publish changesets possibly locally draft
723 # on the remote.
732 # on the remote.
724 remotephases = {'publishing': 'True'}
733 remotephases = {'publishing': 'True'}
725 if not remotephases: # old server or public only reply from non-publishing
734 if not remotephases: # old server or public only reply from non-publishing
726 _localphasemove(pushop, cheads)
735 _localphasemove(pushop, cheads)
727 # don't push any phase data as there is nothing to push
736 # don't push any phase data as there is nothing to push
728 else:
737 else:
729 ana = phases.analyzeremotephases(pushop.repo, cheads,
738 ana = phases.analyzeremotephases(pushop.repo, cheads,
730 remotephases)
739 remotephases)
731 pheads, droots = ana
740 pheads, droots = ana
732 ### Apply remote phase on local
741 ### Apply remote phase on local
733 if remotephases.get('publishing', False):
742 if remotephases.get('publishing', False):
734 _localphasemove(pushop, cheads)
743 _localphasemove(pushop, cheads)
735 else: # publish = False
744 else: # publish = False
736 _localphasemove(pushop, pheads)
745 _localphasemove(pushop, pheads)
737 _localphasemove(pushop, cheads, phases.draft)
746 _localphasemove(pushop, cheads, phases.draft)
738 ### Apply local phase on remote
747 ### Apply local phase on remote
739
748
740 if pushop.cgresult:
749 if pushop.cgresult:
741 if 'phases' in pushop.stepsdone:
750 if 'phases' in pushop.stepsdone:
742 # phases already pushed though bundle2
751 # phases already pushed though bundle2
743 return
752 return
744 outdated = pushop.outdatedphases
753 outdated = pushop.outdatedphases
745 else:
754 else:
746 outdated = pushop.fallbackoutdatedphases
755 outdated = pushop.fallbackoutdatedphases
747
756
748 pushop.stepsdone.add('phases')
757 pushop.stepsdone.add('phases')
749
758
750 # filter heads already turned public by the push
759 # filter heads already turned public by the push
751 outdated = [c for c in outdated if c.node() not in pheads]
760 outdated = [c for c in outdated if c.node() not in pheads]
752 # fallback to independent pushkey command
761 # fallback to independent pushkey command
753 for newremotehead in outdated:
762 for newremotehead in outdated:
754 r = pushop.remote.pushkey('phases',
763 r = pushop.remote.pushkey('phases',
755 newremotehead.hex(),
764 newremotehead.hex(),
756 str(phases.draft),
765 str(phases.draft),
757 str(phases.public))
766 str(phases.public))
758 if not r:
767 if not r:
759 pushop.ui.warn(_('updating %s to public failed!\n')
768 pushop.ui.warn(_('updating %s to public failed!\n')
760 % newremotehead)
769 % newremotehead)
761
770
762 def _localphasemove(pushop, nodes, phase=phases.public):
771 def _localphasemove(pushop, nodes, phase=phases.public):
763 """move <nodes> to <phase> in the local source repo"""
772 """move <nodes> to <phase> in the local source repo"""
764 if pushop.trmanager:
773 if pushop.trmanager:
765 phases.advanceboundary(pushop.repo,
774 phases.advanceboundary(pushop.repo,
766 pushop.trmanager.transaction(),
775 pushop.trmanager.transaction(),
767 phase,
776 phase,
768 nodes)
777 nodes)
769 else:
778 else:
770 # repo is not locked, do not change any phases!
779 # repo is not locked, do not change any phases!
771 # Informs the user that phases should have been moved when
780 # Informs the user that phases should have been moved when
772 # applicable.
781 # applicable.
773 actualmoves = [n for n in nodes if phase < pushop.repo[n].phase()]
782 actualmoves = [n for n in nodes if phase < pushop.repo[n].phase()]
774 phasestr = phases.phasenames[phase]
783 phasestr = phases.phasenames[phase]
775 if actualmoves:
784 if actualmoves:
776 pushop.ui.status(_('cannot lock source repo, skipping '
785 pushop.ui.status(_('cannot lock source repo, skipping '
777 'local %s phase update\n') % phasestr)
786 'local %s phase update\n') % phasestr)
778
787
779 def _pushobsolete(pushop):
788 def _pushobsolete(pushop):
780 """utility function to push obsolete markers to a remote"""
789 """utility function to push obsolete markers to a remote"""
781 if 'obsmarkers' in pushop.stepsdone:
790 if 'obsmarkers' in pushop.stepsdone:
782 return
791 return
783 pushop.ui.debug('try to push obsolete markers to remote\n')
792 pushop.ui.debug('try to push obsolete markers to remote\n')
784 repo = pushop.repo
793 repo = pushop.repo
785 remote = pushop.remote
794 remote = pushop.remote
786 pushop.stepsdone.add('obsmarkers')
795 pushop.stepsdone.add('obsmarkers')
787 if pushop.outobsmarkers:
796 if pushop.outobsmarkers:
788 rslts = []
797 rslts = []
789 remotedata = obsolete._pushkeyescape(sorted(pushop.outobsmarkers))
798 remotedata = obsolete._pushkeyescape(sorted(pushop.outobsmarkers))
790 for key in sorted(remotedata, reverse=True):
799 for key in sorted(remotedata, reverse=True):
791 # reverse sort to ensure we end with dump0
800 # reverse sort to ensure we end with dump0
792 data = remotedata[key]
801 data = remotedata[key]
793 rslts.append(remote.pushkey('obsolete', key, '', data))
802 rslts.append(remote.pushkey('obsolete', key, '', data))
794 if [r for r in rslts if not r]:
803 if [r for r in rslts if not r]:
795 msg = _('failed to push some obsolete markers!\n')
804 msg = _('failed to push some obsolete markers!\n')
796 repo.ui.warn(msg)
805 repo.ui.warn(msg)
797
806
798 def _pushbookmark(pushop):
807 def _pushbookmark(pushop):
799 """Update bookmark position on remote"""
808 """Update bookmark position on remote"""
800 if pushop.cgresult == 0 or 'bookmarks' in pushop.stepsdone:
809 if pushop.cgresult == 0 or 'bookmarks' in pushop.stepsdone:
801 return
810 return
802 pushop.stepsdone.add('bookmarks')
811 pushop.stepsdone.add('bookmarks')
803 ui = pushop.ui
812 ui = pushop.ui
804 remote = pushop.remote
813 remote = pushop.remote
805
814
806 for b, old, new in pushop.outbookmarks:
815 for b, old, new in pushop.outbookmarks:
807 action = 'update'
816 action = 'update'
808 if not old:
817 if not old:
809 action = 'export'
818 action = 'export'
810 elif not new:
819 elif not new:
811 action = 'delete'
820 action = 'delete'
812 if remote.pushkey('bookmarks', b, old, new):
821 if remote.pushkey('bookmarks', b, old, new):
813 ui.status(bookmsgmap[action][0] % b)
822 ui.status(bookmsgmap[action][0] % b)
814 else:
823 else:
815 ui.warn(bookmsgmap[action][1] % b)
824 ui.warn(bookmsgmap[action][1] % b)
816 # discovery can have set the value form invalid entry
825 # discovery can have set the value form invalid entry
817 if pushop.bkresult is not None:
826 if pushop.bkresult is not None:
818 pushop.bkresult = 1
827 pushop.bkresult = 1
819
828
820 class pulloperation(object):
829 class pulloperation(object):
821 """A object that represent a single pull operation
830 """A object that represent a single pull operation
822
831
823 It purpose is to carry pull related state and very common operation.
832 It purpose is to carry pull related state and very common operation.
824
833
825 A new should be created at the beginning of each pull and discarded
834 A new should be created at the beginning of each pull and discarded
826 afterward.
835 afterward.
827 """
836 """
828
837
829 def __init__(self, repo, remote, heads=None, force=False, bookmarks=(),
838 def __init__(self, repo, remote, heads=None, force=False, bookmarks=(),
830 remotebookmarks=None):
839 remotebookmarks=None):
831 # repo we pull into
840 # repo we pull into
832 self.repo = repo
841 self.repo = repo
833 # repo we pull from
842 # repo we pull from
834 self.remote = remote
843 self.remote = remote
835 # revision we try to pull (None is "all")
844 # revision we try to pull (None is "all")
836 self.heads = heads
845 self.heads = heads
837 # bookmark pulled explicitly
846 # bookmark pulled explicitly
838 self.explicitbookmarks = bookmarks
847 self.explicitbookmarks = bookmarks
839 # do we force pull?
848 # do we force pull?
840 self.force = force
849 self.force = force
841 # transaction manager
850 # transaction manager
842 self.trmanager = None
851 self.trmanager = None
843 # set of common changeset between local and remote before pull
852 # set of common changeset between local and remote before pull
844 self.common = None
853 self.common = None
845 # set of pulled head
854 # set of pulled head
846 self.rheads = None
855 self.rheads = None
847 # list of missing changeset to fetch remotely
856 # list of missing changeset to fetch remotely
848 self.fetch = None
857 self.fetch = None
849 # remote bookmarks data
858 # remote bookmarks data
850 self.remotebookmarks = remotebookmarks
859 self.remotebookmarks = remotebookmarks
851 # result of changegroup pulling (used as return code by pull)
860 # result of changegroup pulling (used as return code by pull)
852 self.cgresult = None
861 self.cgresult = None
853 # list of step already done
862 # list of step already done
854 self.stepsdone = set()
863 self.stepsdone = set()
855
864
856 @util.propertycache
865 @util.propertycache
857 def pulledsubset(self):
866 def pulledsubset(self):
858 """heads of the set of changeset target by the pull"""
867 """heads of the set of changeset target by the pull"""
859 # compute target subset
868 # compute target subset
860 if self.heads is None:
869 if self.heads is None:
861 # We pulled every thing possible
870 # We pulled every thing possible
862 # sync on everything common
871 # sync on everything common
863 c = set(self.common)
872 c = set(self.common)
864 ret = list(self.common)
873 ret = list(self.common)
865 for n in self.rheads:
874 for n in self.rheads:
866 if n not in c:
875 if n not in c:
867 ret.append(n)
876 ret.append(n)
868 return ret
877 return ret
869 else:
878 else:
870 # We pulled a specific subset
879 # We pulled a specific subset
871 # sync on this subset
880 # sync on this subset
872 return self.heads
881 return self.heads
873
882
874 def gettransaction(self):
883 def gettransaction(self):
875 # deprecated; talk to trmanager directly
884 # deprecated; talk to trmanager directly
876 return self.trmanager.transaction()
885 return self.trmanager.transaction()
877
886
878 class transactionmanager(object):
887 class transactionmanager(object):
879 """An object to manage the life cycle of a transaction
888 """An object to manage the life cycle of a transaction
880
889
881 It creates the transaction on demand and calls the appropriate hooks when
890 It creates the transaction on demand and calls the appropriate hooks when
882 closing the transaction."""
891 closing the transaction."""
883 def __init__(self, repo, source, url):
892 def __init__(self, repo, source, url):
884 self.repo = repo
893 self.repo = repo
885 self.source = source
894 self.source = source
886 self.url = url
895 self.url = url
887 self._tr = None
896 self._tr = None
888
897
889 def transaction(self):
898 def transaction(self):
890 """Return an open transaction object, constructing if necessary"""
899 """Return an open transaction object, constructing if necessary"""
891 if not self._tr:
900 if not self._tr:
892 trname = '%s\n%s' % (self.source, util.hidepassword(self.url))
901 trname = '%s\n%s' % (self.source, util.hidepassword(self.url))
893 self._tr = self.repo.transaction(trname)
902 self._tr = self.repo.transaction(trname)
894 self._tr.hookargs['source'] = self.source
903 self._tr.hookargs['source'] = self.source
895 self._tr.hookargs['url'] = self.url
904 self._tr.hookargs['url'] = self.url
896 return self._tr
905 return self._tr
897
906
898 def close(self):
907 def close(self):
899 """close transaction if created"""
908 """close transaction if created"""
900 if self._tr is not None:
909 if self._tr is not None:
901 self._tr.close()
910 self._tr.close()
902
911
903 def release(self):
912 def release(self):
904 """release transaction if created"""
913 """release transaction if created"""
905 if self._tr is not None:
914 if self._tr is not None:
906 self._tr.release()
915 self._tr.release()
907
916
908 def pull(repo, remote, heads=None, force=False, bookmarks=(), opargs=None):
917 def pull(repo, remote, heads=None, force=False, bookmarks=(), opargs=None):
909 if opargs is None:
918 if opargs is None:
910 opargs = {}
919 opargs = {}
911 pullop = pulloperation(repo, remote, heads, force, bookmarks=bookmarks,
920 pullop = pulloperation(repo, remote, heads, force, bookmarks=bookmarks,
912 **opargs)
921 **opargs)
913 if pullop.remote.local():
922 if pullop.remote.local():
914 missing = set(pullop.remote.requirements) - pullop.repo.supported
923 missing = set(pullop.remote.requirements) - pullop.repo.supported
915 if missing:
924 if missing:
916 msg = _("required features are not"
925 msg = _("required features are not"
917 " supported in the destination:"
926 " supported in the destination:"
918 " %s") % (', '.join(sorted(missing)))
927 " %s") % (', '.join(sorted(missing)))
919 raise util.Abort(msg)
928 raise util.Abort(msg)
920
929
921 lock = pullop.repo.lock()
930 lock = pullop.repo.lock()
922 try:
931 try:
923 pullop.trmanager = transactionmanager(repo, 'pull', remote.url())
932 pullop.trmanager = transactionmanager(repo, 'pull', remote.url())
924 _pulldiscovery(pullop)
933 _pulldiscovery(pullop)
925 if _canusebundle2(pullop):
934 if _canusebundle2(pullop):
926 _pullbundle2(pullop)
935 _pullbundle2(pullop)
927 _pullchangeset(pullop)
936 _pullchangeset(pullop)
928 _pullphase(pullop)
937 _pullphase(pullop)
929 _pullbookmarks(pullop)
938 _pullbookmarks(pullop)
930 _pullobsolete(pullop)
939 _pullobsolete(pullop)
931 pullop.trmanager.close()
940 pullop.trmanager.close()
932 finally:
941 finally:
933 pullop.trmanager.release()
942 pullop.trmanager.release()
934 lock.release()
943 lock.release()
935
944
936 return pullop
945 return pullop
937
946
938 # list of steps to perform discovery before pull
947 # list of steps to perform discovery before pull
939 pulldiscoveryorder = []
948 pulldiscoveryorder = []
940
949
941 # Mapping between step name and function
950 # Mapping between step name and function
942 #
951 #
943 # This exists to help extensions wrap steps if necessary
952 # This exists to help extensions wrap steps if necessary
944 pulldiscoverymapping = {}
953 pulldiscoverymapping = {}
945
954
946 def pulldiscovery(stepname):
955 def pulldiscovery(stepname):
947 """decorator for function performing discovery before pull
956 """decorator for function performing discovery before pull
948
957
949 The function is added to the step -> function mapping and appended to the
958 The function is added to the step -> function mapping and appended to the
950 list of steps. Beware that decorated function will be added in order (this
959 list of steps. Beware that decorated function will be added in order (this
951 may matter).
960 may matter).
952
961
953 You can only use this decorator for a new step, if you want to wrap a step
962 You can only use this decorator for a new step, if you want to wrap a step
954 from an extension, change the pulldiscovery dictionary directly."""
963 from an extension, change the pulldiscovery dictionary directly."""
955 def dec(func):
964 def dec(func):
956 assert stepname not in pulldiscoverymapping
965 assert stepname not in pulldiscoverymapping
957 pulldiscoverymapping[stepname] = func
966 pulldiscoverymapping[stepname] = func
958 pulldiscoveryorder.append(stepname)
967 pulldiscoveryorder.append(stepname)
959 return func
968 return func
960 return dec
969 return dec
961
970
962 def _pulldiscovery(pullop):
971 def _pulldiscovery(pullop):
963 """Run all discovery steps"""
972 """Run all discovery steps"""
964 for stepname in pulldiscoveryorder:
973 for stepname in pulldiscoveryorder:
965 step = pulldiscoverymapping[stepname]
974 step = pulldiscoverymapping[stepname]
966 step(pullop)
975 step(pullop)
967
976
968 @pulldiscovery('b1:bookmarks')
977 @pulldiscovery('b1:bookmarks')
969 def _pullbookmarkbundle1(pullop):
978 def _pullbookmarkbundle1(pullop):
970 """fetch bookmark data in bundle1 case
979 """fetch bookmark data in bundle1 case
971
980
972 If not using bundle2, we have to fetch bookmarks before changeset
981 If not using bundle2, we have to fetch bookmarks before changeset
973 discovery to reduce the chance and impact of race conditions."""
982 discovery to reduce the chance and impact of race conditions."""
974 if pullop.remotebookmarks is not None:
983 if pullop.remotebookmarks is not None:
975 return
984 return
976 if (_canusebundle2(pullop)
985 if (_canusebundle2(pullop)
977 and 'listkeys' in bundle2.bundle2caps(pullop.remote)):
986 and 'listkeys' in bundle2.bundle2caps(pullop.remote)):
978 # all known bundle2 servers now support listkeys, but lets be nice with
987 # all known bundle2 servers now support listkeys, but lets be nice with
979 # new implementation.
988 # new implementation.
980 return
989 return
981 pullop.remotebookmarks = pullop.remote.listkeys('bookmarks')
990 pullop.remotebookmarks = pullop.remote.listkeys('bookmarks')
982
991
983
992
984 @pulldiscovery('changegroup')
993 @pulldiscovery('changegroup')
985 def _pulldiscoverychangegroup(pullop):
994 def _pulldiscoverychangegroup(pullop):
986 """discovery phase for the pull
995 """discovery phase for the pull
987
996
988 Current handle changeset discovery only, will change handle all discovery
997 Current handle changeset discovery only, will change handle all discovery
989 at some point."""
998 at some point."""
990 tmp = discovery.findcommonincoming(pullop.repo,
999 tmp = discovery.findcommonincoming(pullop.repo,
991 pullop.remote,
1000 pullop.remote,
992 heads=pullop.heads,
1001 heads=pullop.heads,
993 force=pullop.force)
1002 force=pullop.force)
994 common, fetch, rheads = tmp
1003 common, fetch, rheads = tmp
995 nm = pullop.repo.unfiltered().changelog.nodemap
1004 nm = pullop.repo.unfiltered().changelog.nodemap
996 if fetch and rheads:
1005 if fetch and rheads:
997 # If a remote heads in filtered locally, lets drop it from the unknown
1006 # If a remote heads in filtered locally, lets drop it from the unknown
998 # remote heads and put in back in common.
1007 # remote heads and put in back in common.
999 #
1008 #
1000 # This is a hackish solution to catch most of "common but locally
1009 # This is a hackish solution to catch most of "common but locally
1001 # hidden situation". We do not performs discovery on unfiltered
1010 # hidden situation". We do not performs discovery on unfiltered
1002 # repository because it end up doing a pathological amount of round
1011 # repository because it end up doing a pathological amount of round
1003 # trip for w huge amount of changeset we do not care about.
1012 # trip for w huge amount of changeset we do not care about.
1004 #
1013 #
1005 # If a set of such "common but filtered" changeset exist on the server
1014 # If a set of such "common but filtered" changeset exist on the server
1006 # but are not including a remote heads, we'll not be able to detect it,
1015 # but are not including a remote heads, we'll not be able to detect it,
1007 scommon = set(common)
1016 scommon = set(common)
1008 filteredrheads = []
1017 filteredrheads = []
1009 for n in rheads:
1018 for n in rheads:
1010 if n in nm:
1019 if n in nm:
1011 if n not in scommon:
1020 if n not in scommon:
1012 common.append(n)
1021 common.append(n)
1013 else:
1022 else:
1014 filteredrheads.append(n)
1023 filteredrheads.append(n)
1015 if not filteredrheads:
1024 if not filteredrheads:
1016 fetch = []
1025 fetch = []
1017 rheads = filteredrheads
1026 rheads = filteredrheads
1018 pullop.common = common
1027 pullop.common = common
1019 pullop.fetch = fetch
1028 pullop.fetch = fetch
1020 pullop.rheads = rheads
1029 pullop.rheads = rheads
1021
1030
1022 def _pullbundle2(pullop):
1031 def _pullbundle2(pullop):
1023 """pull data using bundle2
1032 """pull data using bundle2
1024
1033
1025 For now, the only supported data are changegroup."""
1034 For now, the only supported data are changegroup."""
1026 remotecaps = bundle2.bundle2caps(pullop.remote)
1035 remotecaps = bundle2.bundle2caps(pullop.remote)
1027 kwargs = {'bundlecaps': caps20to10(pullop.repo)}
1036 kwargs = {'bundlecaps': caps20to10(pullop.repo)}
1028 # pulling changegroup
1037 # pulling changegroup
1029 pullop.stepsdone.add('changegroup')
1038 pullop.stepsdone.add('changegroup')
1030
1039
1031 kwargs['common'] = pullop.common
1040 kwargs['common'] = pullop.common
1032 kwargs['heads'] = pullop.heads or pullop.rheads
1041 kwargs['heads'] = pullop.heads or pullop.rheads
1033 kwargs['cg'] = pullop.fetch
1042 kwargs['cg'] = pullop.fetch
1034 if 'listkeys' in remotecaps:
1043 if 'listkeys' in remotecaps:
1035 kwargs['listkeys'] = ['phase']
1044 kwargs['listkeys'] = ['phase']
1036 if pullop.remotebookmarks is None:
1045 if pullop.remotebookmarks is None:
1037 # make sure to always includes bookmark data when migrating
1046 # make sure to always includes bookmark data when migrating
1038 # `hg incoming --bundle` to using this function.
1047 # `hg incoming --bundle` to using this function.
1039 kwargs['listkeys'].append('bookmarks')
1048 kwargs['listkeys'].append('bookmarks')
1040 if not pullop.fetch:
1049 if not pullop.fetch:
1041 pullop.repo.ui.status(_("no changes found\n"))
1050 pullop.repo.ui.status(_("no changes found\n"))
1042 pullop.cgresult = 0
1051 pullop.cgresult = 0
1043 else:
1052 else:
1044 if pullop.heads is None and list(pullop.common) == [nullid]:
1053 if pullop.heads is None and list(pullop.common) == [nullid]:
1045 pullop.repo.ui.status(_("requesting all changes\n"))
1054 pullop.repo.ui.status(_("requesting all changes\n"))
1046 if obsolete.isenabled(pullop.repo, obsolete.exchangeopt):
1055 if obsolete.isenabled(pullop.repo, obsolete.exchangeopt):
1047 remoteversions = bundle2.obsmarkersversion(remotecaps)
1056 remoteversions = bundle2.obsmarkersversion(remotecaps)
1048 if obsolete.commonversion(remoteversions) is not None:
1057 if obsolete.commonversion(remoteversions) is not None:
1049 kwargs['obsmarkers'] = True
1058 kwargs['obsmarkers'] = True
1050 pullop.stepsdone.add('obsmarkers')
1059 pullop.stepsdone.add('obsmarkers')
1051 _pullbundle2extraprepare(pullop, kwargs)
1060 _pullbundle2extraprepare(pullop, kwargs)
1052 bundle = pullop.remote.getbundle('pull', **kwargs)
1061 bundle = pullop.remote.getbundle('pull', **kwargs)
1053 try:
1062 try:
1054 op = bundle2.processbundle(pullop.repo, bundle, pullop.gettransaction)
1063 op = bundle2.processbundle(pullop.repo, bundle, pullop.gettransaction)
1055 except error.BundleValueError, exc:
1064 except error.BundleValueError, exc:
1056 raise util.Abort('missing support for %s' % exc)
1065 raise util.Abort('missing support for %s' % exc)
1057
1066
1058 if pullop.fetch:
1067 if pullop.fetch:
1059 results = [cg['return'] for cg in op.records['changegroup']]
1068 results = [cg['return'] for cg in op.records['changegroup']]
1060 pullop.cgresult = changegroup.combineresults(results)
1069 pullop.cgresult = changegroup.combineresults(results)
1061
1070
1062 # processing phases change
1071 # processing phases change
1063 for namespace, value in op.records['listkeys']:
1072 for namespace, value in op.records['listkeys']:
1064 if namespace == 'phases':
1073 if namespace == 'phases':
1065 _pullapplyphases(pullop, value)
1074 _pullapplyphases(pullop, value)
1066
1075
1067 # processing bookmark update
1076 # processing bookmark update
1068 for namespace, value in op.records['listkeys']:
1077 for namespace, value in op.records['listkeys']:
1069 if namespace == 'bookmarks':
1078 if namespace == 'bookmarks':
1070 pullop.remotebookmarks = value
1079 pullop.remotebookmarks = value
1071
1080
1072 # bookmark data were either already there or pulled in the bundle
1081 # bookmark data were either already there or pulled in the bundle
1073 if pullop.remotebookmarks is not None:
1082 if pullop.remotebookmarks is not None:
1074 _pullbookmarks(pullop)
1083 _pullbookmarks(pullop)
1075
1084
1076 def _pullbundle2extraprepare(pullop, kwargs):
1085 def _pullbundle2extraprepare(pullop, kwargs):
1077 """hook function so that extensions can extend the getbundle call"""
1086 """hook function so that extensions can extend the getbundle call"""
1078 pass
1087 pass
1079
1088
1080 def _pullchangeset(pullop):
1089 def _pullchangeset(pullop):
1081 """pull changeset from unbundle into the local repo"""
1090 """pull changeset from unbundle into the local repo"""
1082 # We delay the open of the transaction as late as possible so we
1091 # We delay the open of the transaction as late as possible so we
1083 # don't open transaction for nothing or you break future useful
1092 # don't open transaction for nothing or you break future useful
1084 # rollback call
1093 # rollback call
1085 if 'changegroup' in pullop.stepsdone:
1094 if 'changegroup' in pullop.stepsdone:
1086 return
1095 return
1087 pullop.stepsdone.add('changegroup')
1096 pullop.stepsdone.add('changegroup')
1088 if not pullop.fetch:
1097 if not pullop.fetch:
1089 pullop.repo.ui.status(_("no changes found\n"))
1098 pullop.repo.ui.status(_("no changes found\n"))
1090 pullop.cgresult = 0
1099 pullop.cgresult = 0
1091 return
1100 return
1092 pullop.gettransaction()
1101 pullop.gettransaction()
1093 if pullop.heads is None and list(pullop.common) == [nullid]:
1102 if pullop.heads is None and list(pullop.common) == [nullid]:
1094 pullop.repo.ui.status(_("requesting all changes\n"))
1103 pullop.repo.ui.status(_("requesting all changes\n"))
1095 elif pullop.heads is None and pullop.remote.capable('changegroupsubset'):
1104 elif pullop.heads is None and pullop.remote.capable('changegroupsubset'):
1096 # issue1320, avoid a race if remote changed after discovery
1105 # issue1320, avoid a race if remote changed after discovery
1097 pullop.heads = pullop.rheads
1106 pullop.heads = pullop.rheads
1098
1107
1099 if pullop.remote.capable('getbundle'):
1108 if pullop.remote.capable('getbundle'):
1100 # TODO: get bundlecaps from remote
1109 # TODO: get bundlecaps from remote
1101 cg = pullop.remote.getbundle('pull', common=pullop.common,
1110 cg = pullop.remote.getbundle('pull', common=pullop.common,
1102 heads=pullop.heads or pullop.rheads)
1111 heads=pullop.heads or pullop.rheads)
1103 elif pullop.heads is None:
1112 elif pullop.heads is None:
1104 cg = pullop.remote.changegroup(pullop.fetch, 'pull')
1113 cg = pullop.remote.changegroup(pullop.fetch, 'pull')
1105 elif not pullop.remote.capable('changegroupsubset'):
1114 elif not pullop.remote.capable('changegroupsubset'):
1106 raise util.Abort(_("partial pull cannot be done because "
1115 raise util.Abort(_("partial pull cannot be done because "
1107 "other repository doesn't support "
1116 "other repository doesn't support "
1108 "changegroupsubset."))
1117 "changegroupsubset."))
1109 else:
1118 else:
1110 cg = pullop.remote.changegroupsubset(pullop.fetch, pullop.heads, 'pull')
1119 cg = pullop.remote.changegroupsubset(pullop.fetch, pullop.heads, 'pull')
1111 pullop.cgresult = changegroup.addchangegroup(pullop.repo, cg, 'pull',
1120 pullop.cgresult = changegroup.addchangegroup(pullop.repo, cg, 'pull',
1112 pullop.remote.url())
1121 pullop.remote.url())
1113
1122
1114 def _pullphase(pullop):
1123 def _pullphase(pullop):
1115 # Get remote phases data from remote
1124 # Get remote phases data from remote
1116 if 'phases' in pullop.stepsdone:
1125 if 'phases' in pullop.stepsdone:
1117 return
1126 return
1118 remotephases = pullop.remote.listkeys('phases')
1127 remotephases = pullop.remote.listkeys('phases')
1119 _pullapplyphases(pullop, remotephases)
1128 _pullapplyphases(pullop, remotephases)
1120
1129
1121 def _pullapplyphases(pullop, remotephases):
1130 def _pullapplyphases(pullop, remotephases):
1122 """apply phase movement from observed remote state"""
1131 """apply phase movement from observed remote state"""
1123 if 'phases' in pullop.stepsdone:
1132 if 'phases' in pullop.stepsdone:
1124 return
1133 return
1125 pullop.stepsdone.add('phases')
1134 pullop.stepsdone.add('phases')
1126 publishing = bool(remotephases.get('publishing', False))
1135 publishing = bool(remotephases.get('publishing', False))
1127 if remotephases and not publishing:
1136 if remotephases and not publishing:
1128 # remote is new and unpublishing
1137 # remote is new and unpublishing
1129 pheads, _dr = phases.analyzeremotephases(pullop.repo,
1138 pheads, _dr = phases.analyzeremotephases(pullop.repo,
1130 pullop.pulledsubset,
1139 pullop.pulledsubset,
1131 remotephases)
1140 remotephases)
1132 dheads = pullop.pulledsubset
1141 dheads = pullop.pulledsubset
1133 else:
1142 else:
1134 # Remote is old or publishing all common changesets
1143 # Remote is old or publishing all common changesets
1135 # should be seen as public
1144 # should be seen as public
1136 pheads = pullop.pulledsubset
1145 pheads = pullop.pulledsubset
1137 dheads = []
1146 dheads = []
1138 unfi = pullop.repo.unfiltered()
1147 unfi = pullop.repo.unfiltered()
1139 phase = unfi._phasecache.phase
1148 phase = unfi._phasecache.phase
1140 rev = unfi.changelog.nodemap.get
1149 rev = unfi.changelog.nodemap.get
1141 public = phases.public
1150 public = phases.public
1142 draft = phases.draft
1151 draft = phases.draft
1143
1152
1144 # exclude changesets already public locally and update the others
1153 # exclude changesets already public locally and update the others
1145 pheads = [pn for pn in pheads if phase(unfi, rev(pn)) > public]
1154 pheads = [pn for pn in pheads if phase(unfi, rev(pn)) > public]
1146 if pheads:
1155 if pheads:
1147 tr = pullop.gettransaction()
1156 tr = pullop.gettransaction()
1148 phases.advanceboundary(pullop.repo, tr, public, pheads)
1157 phases.advanceboundary(pullop.repo, tr, public, pheads)
1149
1158
1150 # exclude changesets already draft locally and update the others
1159 # exclude changesets already draft locally and update the others
1151 dheads = [pn for pn in dheads if phase(unfi, rev(pn)) > draft]
1160 dheads = [pn for pn in dheads if phase(unfi, rev(pn)) > draft]
1152 if dheads:
1161 if dheads:
1153 tr = pullop.gettransaction()
1162 tr = pullop.gettransaction()
1154 phases.advanceboundary(pullop.repo, tr, draft, dheads)
1163 phases.advanceboundary(pullop.repo, tr, draft, dheads)
1155
1164
1156 def _pullbookmarks(pullop):
1165 def _pullbookmarks(pullop):
1157 """process the remote bookmark information to update the local one"""
1166 """process the remote bookmark information to update the local one"""
1158 if 'bookmarks' in pullop.stepsdone:
1167 if 'bookmarks' in pullop.stepsdone:
1159 return
1168 return
1160 pullop.stepsdone.add('bookmarks')
1169 pullop.stepsdone.add('bookmarks')
1161 repo = pullop.repo
1170 repo = pullop.repo
1162 remotebookmarks = pullop.remotebookmarks
1171 remotebookmarks = pullop.remotebookmarks
1163 bookmod.updatefromremote(repo.ui, repo, remotebookmarks,
1172 bookmod.updatefromremote(repo.ui, repo, remotebookmarks,
1164 pullop.remote.url(),
1173 pullop.remote.url(),
1165 pullop.gettransaction,
1174 pullop.gettransaction,
1166 explicit=pullop.explicitbookmarks)
1175 explicit=pullop.explicitbookmarks)
1167
1176
1168 def _pullobsolete(pullop):
1177 def _pullobsolete(pullop):
1169 """utility function to pull obsolete markers from a remote
1178 """utility function to pull obsolete markers from a remote
1170
1179
1171 The `gettransaction` is function that return the pull transaction, creating
1180 The `gettransaction` is function that return the pull transaction, creating
1172 one if necessary. We return the transaction to inform the calling code that
1181 one if necessary. We return the transaction to inform the calling code that
1173 a new transaction have been created (when applicable).
1182 a new transaction have been created (when applicable).
1174
1183
1175 Exists mostly to allow overriding for experimentation purpose"""
1184 Exists mostly to allow overriding for experimentation purpose"""
1176 if 'obsmarkers' in pullop.stepsdone:
1185 if 'obsmarkers' in pullop.stepsdone:
1177 return
1186 return
1178 pullop.stepsdone.add('obsmarkers')
1187 pullop.stepsdone.add('obsmarkers')
1179 tr = None
1188 tr = None
1180 if obsolete.isenabled(pullop.repo, obsolete.exchangeopt):
1189 if obsolete.isenabled(pullop.repo, obsolete.exchangeopt):
1181 pullop.repo.ui.debug('fetching remote obsolete markers\n')
1190 pullop.repo.ui.debug('fetching remote obsolete markers\n')
1182 remoteobs = pullop.remote.listkeys('obsolete')
1191 remoteobs = pullop.remote.listkeys('obsolete')
1183 if 'dump0' in remoteobs:
1192 if 'dump0' in remoteobs:
1184 tr = pullop.gettransaction()
1193 tr = pullop.gettransaction()
1185 for key in sorted(remoteobs, reverse=True):
1194 for key in sorted(remoteobs, reverse=True):
1186 if key.startswith('dump'):
1195 if key.startswith('dump'):
1187 data = base85.b85decode(remoteobs[key])
1196 data = base85.b85decode(remoteobs[key])
1188 pullop.repo.obsstore.mergemarkers(tr, data)
1197 pullop.repo.obsstore.mergemarkers(tr, data)
1189 pullop.repo.invalidatevolatilesets()
1198 pullop.repo.invalidatevolatilesets()
1190 return tr
1199 return tr
1191
1200
1192 def caps20to10(repo):
1201 def caps20to10(repo):
1193 """return a set with appropriate options to use bundle20 during getbundle"""
1202 """return a set with appropriate options to use bundle20 during getbundle"""
1194 caps = set(['HG20'])
1203 caps = set(['HG20'])
1195 capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo))
1204 capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo))
1196 caps.add('bundle2=' + urllib.quote(capsblob))
1205 caps.add('bundle2=' + urllib.quote(capsblob))
1197 return caps
1206 return caps
1198
1207
1199 # List of names of steps to perform for a bundle2 for getbundle, order matters.
1208 # List of names of steps to perform for a bundle2 for getbundle, order matters.
1200 getbundle2partsorder = []
1209 getbundle2partsorder = []
1201
1210
1202 # Mapping between step name and function
1211 # Mapping between step name and function
1203 #
1212 #
1204 # This exists to help extensions wrap steps if necessary
1213 # This exists to help extensions wrap steps if necessary
1205 getbundle2partsmapping = {}
1214 getbundle2partsmapping = {}
1206
1215
1207 def getbundle2partsgenerator(stepname, idx=None):
1216 def getbundle2partsgenerator(stepname, idx=None):
1208 """decorator for function generating bundle2 part for getbundle
1217 """decorator for function generating bundle2 part for getbundle
1209
1218
1210 The function is added to the step -> function mapping and appended to the
1219 The function is added to the step -> function mapping and appended to the
1211 list of steps. Beware that decorated functions will be added in order
1220 list of steps. Beware that decorated functions will be added in order
1212 (this may matter).
1221 (this may matter).
1213
1222
1214 You can only use this decorator for new steps, if you want to wrap a step
1223 You can only use this decorator for new steps, if you want to wrap a step
1215 from an extension, attack the getbundle2partsmapping dictionary directly."""
1224 from an extension, attack the getbundle2partsmapping dictionary directly."""
1216 def dec(func):
1225 def dec(func):
1217 assert stepname not in getbundle2partsmapping
1226 assert stepname not in getbundle2partsmapping
1218 getbundle2partsmapping[stepname] = func
1227 getbundle2partsmapping[stepname] = func
1219 if idx is None:
1228 if idx is None:
1220 getbundle2partsorder.append(stepname)
1229 getbundle2partsorder.append(stepname)
1221 else:
1230 else:
1222 getbundle2partsorder.insert(idx, stepname)
1231 getbundle2partsorder.insert(idx, stepname)
1223 return func
1232 return func
1224 return dec
1233 return dec
1225
1234
1226 def getbundle(repo, source, heads=None, common=None, bundlecaps=None,
1235 def getbundle(repo, source, heads=None, common=None, bundlecaps=None,
1227 **kwargs):
1236 **kwargs):
1228 """return a full bundle (with potentially multiple kind of parts)
1237 """return a full bundle (with potentially multiple kind of parts)
1229
1238
1230 Could be a bundle HG10 or a bundle HG20 depending on bundlecaps
1239 Could be a bundle HG10 or a bundle HG20 depending on bundlecaps
1231 passed. For now, the bundle can contain only changegroup, but this will
1240 passed. For now, the bundle can contain only changegroup, but this will
1232 changes when more part type will be available for bundle2.
1241 changes when more part type will be available for bundle2.
1233
1242
1234 This is different from changegroup.getchangegroup that only returns an HG10
1243 This is different from changegroup.getchangegroup that only returns an HG10
1235 changegroup bundle. They may eventually get reunited in the future when we
1244 changegroup bundle. They may eventually get reunited in the future when we
1236 have a clearer idea of the API we what to query different data.
1245 have a clearer idea of the API we what to query different data.
1237
1246
1238 The implementation is at a very early stage and will get massive rework
1247 The implementation is at a very early stage and will get massive rework
1239 when the API of bundle is refined.
1248 when the API of bundle is refined.
1240 """
1249 """
1241 # bundle10 case
1250 # bundle10 case
1242 usebundle2 = False
1251 usebundle2 = False
1243 if bundlecaps is not None:
1252 if bundlecaps is not None:
1244 usebundle2 = any((cap.startswith('HG2') for cap in bundlecaps))
1253 usebundle2 = any((cap.startswith('HG2') for cap in bundlecaps))
1245 if not usebundle2:
1254 if not usebundle2:
1246 if bundlecaps and not kwargs.get('cg', True):
1255 if bundlecaps and not kwargs.get('cg', True):
1247 raise ValueError(_('request for bundle10 must include changegroup'))
1256 raise ValueError(_('request for bundle10 must include changegroup'))
1248
1257
1249 if kwargs:
1258 if kwargs:
1250 raise ValueError(_('unsupported getbundle arguments: %s')
1259 raise ValueError(_('unsupported getbundle arguments: %s')
1251 % ', '.join(sorted(kwargs.keys())))
1260 % ', '.join(sorted(kwargs.keys())))
1252 return changegroup.getchangegroup(repo, source, heads=heads,
1261 return changegroup.getchangegroup(repo, source, heads=heads,
1253 common=common, bundlecaps=bundlecaps)
1262 common=common, bundlecaps=bundlecaps)
1254
1263
1255 # bundle20 case
1264 # bundle20 case
1256 b2caps = {}
1265 b2caps = {}
1257 for bcaps in bundlecaps:
1266 for bcaps in bundlecaps:
1258 if bcaps.startswith('bundle2='):
1267 if bcaps.startswith('bundle2='):
1259 blob = urllib.unquote(bcaps[len('bundle2='):])
1268 blob = urllib.unquote(bcaps[len('bundle2='):])
1260 b2caps.update(bundle2.decodecaps(blob))
1269 b2caps.update(bundle2.decodecaps(blob))
1261 bundler = bundle2.bundle20(repo.ui, b2caps)
1270 bundler = bundle2.bundle20(repo.ui, b2caps)
1262
1271
1263 kwargs['heads'] = heads
1272 kwargs['heads'] = heads
1264 kwargs['common'] = common
1273 kwargs['common'] = common
1265
1274
1266 for name in getbundle2partsorder:
1275 for name in getbundle2partsorder:
1267 func = getbundle2partsmapping[name]
1276 func = getbundle2partsmapping[name]
1268 func(bundler, repo, source, bundlecaps=bundlecaps, b2caps=b2caps,
1277 func(bundler, repo, source, bundlecaps=bundlecaps, b2caps=b2caps,
1269 **kwargs)
1278 **kwargs)
1270
1279
1271 return util.chunkbuffer(bundler.getchunks())
1280 return util.chunkbuffer(bundler.getchunks())
1272
1281
1273 @getbundle2partsgenerator('changegroup')
1282 @getbundle2partsgenerator('changegroup')
1274 def _getbundlechangegrouppart(bundler, repo, source, bundlecaps=None,
1283 def _getbundlechangegrouppart(bundler, repo, source, bundlecaps=None,
1275 b2caps=None, heads=None, common=None, **kwargs):
1284 b2caps=None, heads=None, common=None, **kwargs):
1276 """add a changegroup part to the requested bundle"""
1285 """add a changegroup part to the requested bundle"""
1277 cg = None
1286 cg = None
1278 if kwargs.get('cg', True):
1287 if kwargs.get('cg', True):
1279 # build changegroup bundle here.
1288 # build changegroup bundle here.
1280 version = None
1289 version = None
1281 cgversions = b2caps.get('changegroup')
1290 cgversions = b2caps.get('changegroup')
1282 if not cgversions: # 3.1 and 3.2 ship with an empty value
1291 if not cgversions: # 3.1 and 3.2 ship with an empty value
1283 cg = changegroup.getchangegroupraw(repo, source, heads=heads,
1292 cg = changegroup.getchangegroupraw(repo, source, heads=heads,
1284 common=common,
1293 common=common,
1285 bundlecaps=bundlecaps)
1294 bundlecaps=bundlecaps)
1286 else:
1295 else:
1287 cgversions = [v for v in cgversions if v in changegroup.packermap]
1296 cgversions = [v for v in cgversions if v in changegroup.packermap]
1288 if not cgversions:
1297 if not cgversions:
1289 raise ValueError(_('no common changegroup version'))
1298 raise ValueError(_('no common changegroup version'))
1290 version = max(cgversions)
1299 version = max(cgversions)
1291 cg = changegroup.getchangegroupraw(repo, source, heads=heads,
1300 cg = changegroup.getchangegroupraw(repo, source, heads=heads,
1292 common=common,
1301 common=common,
1293 bundlecaps=bundlecaps,
1302 bundlecaps=bundlecaps,
1294 version=version)
1303 version=version)
1295
1304
1296 if cg:
1305 if cg:
1297 part = bundler.newpart('changegroup', data=cg)
1306 part = bundler.newpart('changegroup', data=cg)
1298 if version is not None:
1307 if version is not None:
1299 part.addparam('version', version)
1308 part.addparam('version', version)
1300
1309
1301 @getbundle2partsgenerator('listkeys')
1310 @getbundle2partsgenerator('listkeys')
1302 def _getbundlelistkeysparts(bundler, repo, source, bundlecaps=None,
1311 def _getbundlelistkeysparts(bundler, repo, source, bundlecaps=None,
1303 b2caps=None, **kwargs):
1312 b2caps=None, **kwargs):
1304 """add parts containing listkeys namespaces to the requested bundle"""
1313 """add parts containing listkeys namespaces to the requested bundle"""
1305 listkeys = kwargs.get('listkeys', ())
1314 listkeys = kwargs.get('listkeys', ())
1306 for namespace in listkeys:
1315 for namespace in listkeys:
1307 part = bundler.newpart('listkeys')
1316 part = bundler.newpart('listkeys')
1308 part.addparam('namespace', namespace)
1317 part.addparam('namespace', namespace)
1309 keys = repo.listkeys(namespace).items()
1318 keys = repo.listkeys(namespace).items()
1310 part.data = pushkey.encodekeys(keys)
1319 part.data = pushkey.encodekeys(keys)
1311
1320
1312 @getbundle2partsgenerator('obsmarkers')
1321 @getbundle2partsgenerator('obsmarkers')
1313 def _getbundleobsmarkerpart(bundler, repo, source, bundlecaps=None,
1322 def _getbundleobsmarkerpart(bundler, repo, source, bundlecaps=None,
1314 b2caps=None, heads=None, **kwargs):
1323 b2caps=None, heads=None, **kwargs):
1315 """add an obsolescence markers part to the requested bundle"""
1324 """add an obsolescence markers part to the requested bundle"""
1316 if kwargs.get('obsmarkers', False):
1325 if kwargs.get('obsmarkers', False):
1317 if heads is None:
1326 if heads is None:
1318 heads = repo.heads()
1327 heads = repo.heads()
1319 subset = [c.node() for c in repo.set('::%ln', heads)]
1328 subset = [c.node() for c in repo.set('::%ln', heads)]
1320 markers = repo.obsstore.relevantmarkers(subset)
1329 markers = repo.obsstore.relevantmarkers(subset)
1321 markers = sorted(markers)
1330 markers = sorted(markers)
1322 buildobsmarkerspart(bundler, markers)
1331 buildobsmarkerspart(bundler, markers)
1323
1332
1324 @getbundle2partsgenerator('hgtagsfnodes')
1333 @getbundle2partsgenerator('hgtagsfnodes')
1325 def _getbundletagsfnodes(bundler, repo, source, bundlecaps=None,
1334 def _getbundletagsfnodes(bundler, repo, source, bundlecaps=None,
1326 b2caps=None, heads=None, common=None,
1335 b2caps=None, heads=None, common=None,
1327 **kwargs):
1336 **kwargs):
1328 """Transfer the .hgtags filenodes mapping.
1337 """Transfer the .hgtags filenodes mapping.
1329
1338
1330 Only values for heads in this bundle will be transferred.
1339 Only values for heads in this bundle will be transferred.
1331
1340
1332 The part data consists of pairs of 20 byte changeset node and .hgtags
1341 The part data consists of pairs of 20 byte changeset node and .hgtags
1333 filenodes raw values.
1342 filenodes raw values.
1334 """
1343 """
1335 # Don't send unless:
1344 # Don't send unless:
1336 # - changeset are being exchanged,
1345 # - changeset are being exchanged,
1337 # - the client supports it.
1346 # - the client supports it.
1338 if not (kwargs.get('cg', True) and 'hgtagsfnodes' in b2caps):
1347 if not (kwargs.get('cg', True) and 'hgtagsfnodes' in b2caps):
1339 return
1348 return
1340
1349
1341 outgoing = changegroup.computeoutgoing(repo, heads, common)
1350 outgoing = changegroup.computeoutgoing(repo, heads, common)
1342
1351
1343 if not outgoing.missingheads:
1352 if not outgoing.missingheads:
1344 return
1353 return
1345
1354
1346 cache = tags.hgtagsfnodescache(repo.unfiltered())
1355 cache = tags.hgtagsfnodescache(repo.unfiltered())
1347 chunks = []
1356 chunks = []
1348
1357
1349 # .hgtags fnodes are only relevant for head changesets. While we could
1358 # .hgtags fnodes are only relevant for head changesets. While we could
1350 # transfer values for all known nodes, there will likely be little to
1359 # transfer values for all known nodes, there will likely be little to
1351 # no benefit.
1360 # no benefit.
1352 #
1361 #
1353 # We don't bother using a generator to produce output data because
1362 # We don't bother using a generator to produce output data because
1354 # a) we only have 40 bytes per head and even esoteric numbers of heads
1363 # a) we only have 40 bytes per head and even esoteric numbers of heads
1355 # consume little memory (1M heads is 40MB) b) we don't want to send the
1364 # consume little memory (1M heads is 40MB) b) we don't want to send the
1356 # part if we don't have entries and knowing if we have entries requires
1365 # part if we don't have entries and knowing if we have entries requires
1357 # cache lookups.
1366 # cache lookups.
1358 for node in outgoing.missingheads:
1367 for node in outgoing.missingheads:
1359 # Don't compute missing, as this may slow down serving.
1368 # Don't compute missing, as this may slow down serving.
1360 fnode = cache.getfnode(node, computemissing=False)
1369 fnode = cache.getfnode(node, computemissing=False)
1361 if fnode is not None:
1370 if fnode is not None:
1362 chunks.extend([node, fnode])
1371 chunks.extend([node, fnode])
1363
1372
1364 if chunks:
1373 if chunks:
1365 bundler.newpart('hgtagsfnodes', data=''.join(chunks))
1374 bundler.newpart('hgtagsfnodes', data=''.join(chunks))
1366
1375
1367 def check_heads(repo, their_heads, context):
1376 def check_heads(repo, their_heads, context):
1368 """check if the heads of a repo have been modified
1377 """check if the heads of a repo have been modified
1369
1378
1370 Used by peer for unbundling.
1379 Used by peer for unbundling.
1371 """
1380 """
1372 heads = repo.heads()
1381 heads = repo.heads()
1373 heads_hash = util.sha1(''.join(sorted(heads))).digest()
1382 heads_hash = util.sha1(''.join(sorted(heads))).digest()
1374 if not (their_heads == ['force'] or their_heads == heads or
1383 if not (their_heads == ['force'] or their_heads == heads or
1375 their_heads == ['hashed', heads_hash]):
1384 their_heads == ['hashed', heads_hash]):
1376 # someone else committed/pushed/unbundled while we
1385 # someone else committed/pushed/unbundled while we
1377 # were transferring data
1386 # were transferring data
1378 raise error.PushRaced('repository changed while %s - '
1387 raise error.PushRaced('repository changed while %s - '
1379 'please try again' % context)
1388 'please try again' % context)
1380
1389
1381 def unbundle(repo, cg, heads, source, url):
1390 def unbundle(repo, cg, heads, source, url):
1382 """Apply a bundle to a repo.
1391 """Apply a bundle to a repo.
1383
1392
1384 this function makes sure the repo is locked during the application and have
1393 this function makes sure the repo is locked during the application and have
1385 mechanism to check that no push race occurred between the creation of the
1394 mechanism to check that no push race occurred between the creation of the
1386 bundle and its application.
1395 bundle and its application.
1387
1396
1388 If the push was raced as PushRaced exception is raised."""
1397 If the push was raced as PushRaced exception is raised."""
1389 r = 0
1398 r = 0
1390 # need a transaction when processing a bundle2 stream
1399 # need a transaction when processing a bundle2 stream
1391 wlock = lock = tr = None
1400 wlock = lock = tr = None
1392 recordout = None
1401 recordout = None
1393 # quick fix for output mismatch with bundle2 in 3.4
1402 # quick fix for output mismatch with bundle2 in 3.4
1394 captureoutput = repo.ui.configbool('experimental', 'bundle2-output-capture',
1403 captureoutput = repo.ui.configbool('experimental', 'bundle2-output-capture',
1395 False)
1404 False)
1396 if url.startswith('remote:http:') or url.startswith('remote:https:'):
1405 if url.startswith('remote:http:') or url.startswith('remote:https:'):
1397 captureoutput = True
1406 captureoutput = True
1398 try:
1407 try:
1399 check_heads(repo, heads, 'uploading changes')
1408 check_heads(repo, heads, 'uploading changes')
1400 # push can proceed
1409 # push can proceed
1401 if util.safehasattr(cg, 'params'):
1410 if util.safehasattr(cg, 'params'):
1402 r = None
1411 r = None
1403 try:
1412 try:
1404 wlock = repo.wlock()
1413 wlock = repo.wlock()
1405 lock = repo.lock()
1414 lock = repo.lock()
1406 tr = repo.transaction(source)
1415 tr = repo.transaction(source)
1407 tr.hookargs['source'] = source
1416 tr.hookargs['source'] = source
1408 tr.hookargs['url'] = url
1417 tr.hookargs['url'] = url
1409 tr.hookargs['bundle2'] = '1'
1418 tr.hookargs['bundle2'] = '1'
1410 op = bundle2.bundleoperation(repo, lambda: tr,
1419 op = bundle2.bundleoperation(repo, lambda: tr,
1411 captureoutput=captureoutput)
1420 captureoutput=captureoutput)
1412 try:
1421 try:
1413 r = bundle2.processbundle(repo, cg, op=op)
1422 r = bundle2.processbundle(repo, cg, op=op)
1414 finally:
1423 finally:
1415 r = op.reply
1424 r = op.reply
1416 if captureoutput and r is not None:
1425 if captureoutput and r is not None:
1417 repo.ui.pushbuffer(error=True, subproc=True)
1426 repo.ui.pushbuffer(error=True, subproc=True)
1418 def recordout(output):
1427 def recordout(output):
1419 r.newpart('output', data=output, mandatory=False)
1428 r.newpart('output', data=output, mandatory=False)
1420 tr.close()
1429 tr.close()
1421 except BaseException, exc:
1430 except BaseException, exc:
1422 exc.duringunbundle2 = True
1431 exc.duringunbundle2 = True
1423 if captureoutput and r is not None:
1432 if captureoutput and r is not None:
1424 parts = exc._bundle2salvagedoutput = r.salvageoutput()
1433 parts = exc._bundle2salvagedoutput = r.salvageoutput()
1425 def recordout(output):
1434 def recordout(output):
1426 part = bundle2.bundlepart('output', data=output,
1435 part = bundle2.bundlepart('output', data=output,
1427 mandatory=False)
1436 mandatory=False)
1428 parts.append(part)
1437 parts.append(part)
1429 raise
1438 raise
1430 else:
1439 else:
1431 lock = repo.lock()
1440 lock = repo.lock()
1432 r = changegroup.addchangegroup(repo, cg, source, url)
1441 r = changegroup.addchangegroup(repo, cg, source, url)
1433 finally:
1442 finally:
1434 lockmod.release(tr, lock, wlock)
1443 lockmod.release(tr, lock, wlock)
1435 if recordout is not None:
1444 if recordout is not None:
1436 recordout(repo.ui.popbuffer())
1445 recordout(repo.ui.popbuffer())
1437 return r
1446 return r
1438
1447
1439 # This is it's own function so extensions can override it.
1448 # This is it's own function so extensions can override it.
1440 def _walkstreamfiles(repo):
1449 def _walkstreamfiles(repo):
1441 return repo.store.walk()
1450 return repo.store.walk()
1442
1451
1443 def generatestreamclone(repo):
1452 def generatestreamclone(repo):
1444 """Emit content for a streaming clone.
1453 """Emit content for a streaming clone.
1445
1454
1446 This is a generator of raw chunks that constitute a streaming clone.
1455 This is a generator of raw chunks that constitute a streaming clone.
1447
1456
1448 The stream begins with a line of 2 space-delimited integers containing the
1457 The stream begins with a line of 2 space-delimited integers containing the
1449 number of entries and total bytes size.
1458 number of entries and total bytes size.
1450
1459
1451 Next, are N entries for each file being transferred. Each file entry starts
1460 Next, are N entries for each file being transferred. Each file entry starts
1452 as a line with the file name and integer size delimited by a null byte.
1461 as a line with the file name and integer size delimited by a null byte.
1453 The raw file data follows. Following the raw file data is the next file
1462 The raw file data follows. Following the raw file data is the next file
1454 entry, or EOF.
1463 entry, or EOF.
1455
1464
1456 When used on the wire protocol, an additional line indicating protocol
1465 When used on the wire protocol, an additional line indicating protocol
1457 success will be prepended to the stream. This function is not responsible
1466 success will be prepended to the stream. This function is not responsible
1458 for adding it.
1467 for adding it.
1459
1468
1460 This function will obtain a repository lock to ensure a consistent view of
1469 This function will obtain a repository lock to ensure a consistent view of
1461 the store is captured. It therefore may raise LockError.
1470 the store is captured. It therefore may raise LockError.
1462 """
1471 """
1463 entries = []
1472 entries = []
1464 total_bytes = 0
1473 total_bytes = 0
1465 # Get consistent snapshot of repo, lock during scan.
1474 # Get consistent snapshot of repo, lock during scan.
1466 lock = repo.lock()
1475 lock = repo.lock()
1467 try:
1476 try:
1468 repo.ui.debug('scanning\n')
1477 repo.ui.debug('scanning\n')
1469 for name, ename, size in _walkstreamfiles(repo):
1478 for name, ename, size in _walkstreamfiles(repo):
1470 if size:
1479 if size:
1471 entries.append((name, size))
1480 entries.append((name, size))
1472 total_bytes += size
1481 total_bytes += size
1473 finally:
1482 finally:
1474 lock.release()
1483 lock.release()
1475
1484
1476 repo.ui.debug('%d files, %d bytes to transfer\n' %
1485 repo.ui.debug('%d files, %d bytes to transfer\n' %
1477 (len(entries), total_bytes))
1486 (len(entries), total_bytes))
1478 yield '%d %d\n' % (len(entries), total_bytes)
1487 yield '%d %d\n' % (len(entries), total_bytes)
1479
1488
1480 sopener = repo.svfs
1489 sopener = repo.svfs
1481 oldaudit = sopener.mustaudit
1490 oldaudit = sopener.mustaudit
1482 debugflag = repo.ui.debugflag
1491 debugflag = repo.ui.debugflag
1483 sopener.mustaudit = False
1492 sopener.mustaudit = False
1484
1493
1485 try:
1494 try:
1486 for name, size in entries:
1495 for name, size in entries:
1487 if debugflag:
1496 if debugflag:
1488 repo.ui.debug('sending %s (%d bytes)\n' % (name, size))
1497 repo.ui.debug('sending %s (%d bytes)\n' % (name, size))
1489 # partially encode name over the wire for backwards compat
1498 # partially encode name over the wire for backwards compat
1490 yield '%s\0%d\n' % (store.encodedir(name), size)
1499 yield '%s\0%d\n' % (store.encodedir(name), size)
1491 if size <= 65536:
1500 if size <= 65536:
1492 fp = sopener(name)
1501 fp = sopener(name)
1493 try:
1502 try:
1494 data = fp.read(size)
1503 data = fp.read(size)
1495 finally:
1504 finally:
1496 fp.close()
1505 fp.close()
1497 yield data
1506 yield data
1498 else:
1507 else:
1499 for chunk in util.filechunkiter(sopener(name), limit=size):
1508 for chunk in util.filechunkiter(sopener(name), limit=size):
1500 yield chunk
1509 yield chunk
1501 finally:
1510 finally:
1502 sopener.mustaudit = oldaudit
1511 sopener.mustaudit = oldaudit
1503
1512
1504 def consumestreamclone(repo, fp):
1513 def consumestreamclone(repo, fp):
1505 """Apply the contents from a streaming clone file.
1514 """Apply the contents from a streaming clone file.
1506
1515
1507 This takes the output from "streamout" and applies it to the specified
1516 This takes the output from "streamout" and applies it to the specified
1508 repository.
1517 repository.
1509
1518
1510 Like "streamout," the status line added by the wire protocol is not handled
1519 Like "streamout," the status line added by the wire protocol is not handled
1511 by this function.
1520 by this function.
1512 """
1521 """
1513 lock = repo.lock()
1522 lock = repo.lock()
1514 try:
1523 try:
1515 repo.ui.status(_('streaming all changes\n'))
1524 repo.ui.status(_('streaming all changes\n'))
1516 l = fp.readline()
1525 l = fp.readline()
1517 try:
1526 try:
1518 total_files, total_bytes = map(int, l.split(' ', 1))
1527 total_files, total_bytes = map(int, l.split(' ', 1))
1519 except (ValueError, TypeError):
1528 except (ValueError, TypeError):
1520 raise error.ResponseError(
1529 raise error.ResponseError(
1521 _('unexpected response from remote server:'), l)
1530 _('unexpected response from remote server:'), l)
1522 repo.ui.status(_('%d files to transfer, %s of data\n') %
1531 repo.ui.status(_('%d files to transfer, %s of data\n') %
1523 (total_files, util.bytecount(total_bytes)))
1532 (total_files, util.bytecount(total_bytes)))
1524 handled_bytes = 0
1533 handled_bytes = 0
1525 repo.ui.progress(_('clone'), 0, total=total_bytes)
1534 repo.ui.progress(_('clone'), 0, total=total_bytes)
1526 start = time.time()
1535 start = time.time()
1527
1536
1528 tr = repo.transaction(_('clone'))
1537 tr = repo.transaction(_('clone'))
1529 try:
1538 try:
1530 for i in xrange(total_files):
1539 for i in xrange(total_files):
1531 # XXX doesn't support '\n' or '\r' in filenames
1540 # XXX doesn't support '\n' or '\r' in filenames
1532 l = fp.readline()
1541 l = fp.readline()
1533 try:
1542 try:
1534 name, size = l.split('\0', 1)
1543 name, size = l.split('\0', 1)
1535 size = int(size)
1544 size = int(size)
1536 except (ValueError, TypeError):
1545 except (ValueError, TypeError):
1537 raise error.ResponseError(
1546 raise error.ResponseError(
1538 _('unexpected response from remote server:'), l)
1547 _('unexpected response from remote server:'), l)
1539 if repo.ui.debugflag:
1548 if repo.ui.debugflag:
1540 repo.ui.debug('adding %s (%s)\n' %
1549 repo.ui.debug('adding %s (%s)\n' %
1541 (name, util.bytecount(size)))
1550 (name, util.bytecount(size)))
1542 # for backwards compat, name was partially encoded
1551 # for backwards compat, name was partially encoded
1543 ofp = repo.svfs(store.decodedir(name), 'w')
1552 ofp = repo.svfs(store.decodedir(name), 'w')
1544 for chunk in util.filechunkiter(fp, limit=size):
1553 for chunk in util.filechunkiter(fp, limit=size):
1545 handled_bytes += len(chunk)
1554 handled_bytes += len(chunk)
1546 repo.ui.progress(_('clone'), handled_bytes,
1555 repo.ui.progress(_('clone'), handled_bytes,
1547 total=total_bytes)
1556 total=total_bytes)
1548 ofp.write(chunk)
1557 ofp.write(chunk)
1549 ofp.close()
1558 ofp.close()
1550 tr.close()
1559 tr.close()
1551 finally:
1560 finally:
1552 tr.release()
1561 tr.release()
1553
1562
1554 # Writing straight to files circumvented the inmemory caches
1563 # Writing straight to files circumvented the inmemory caches
1555 repo.invalidate()
1564 repo.invalidate()
1556
1565
1557 elapsed = time.time() - start
1566 elapsed = time.time() - start
1558 if elapsed <= 0:
1567 if elapsed <= 0:
1559 elapsed = 0.001
1568 elapsed = 0.001
1560 repo.ui.progress(_('clone'), None)
1569 repo.ui.progress(_('clone'), None)
1561 repo.ui.status(_('transferred %s in %.1f seconds (%s/sec)\n') %
1570 repo.ui.status(_('transferred %s in %.1f seconds (%s/sec)\n') %
1562 (util.bytecount(total_bytes), elapsed,
1571 (util.bytecount(total_bytes), elapsed,
1563 util.bytecount(total_bytes / elapsed)))
1572 util.bytecount(total_bytes / elapsed)))
1564 finally:
1573 finally:
1565 lock.release()
1574 lock.release()
@@ -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" 155 bytes payload
102 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
108 bundle2-input-part: total payload size 155
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" (advisory) (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" 155 bytes payload
166 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
172 bundle2-input-part: total payload size 155
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" (advisory) (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" 155 bytes payload
233 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
239 bundle2-input-part: total payload size 155
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" (advisory) (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" 155 bytes payload
310 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
316 bundle2-input-part: total payload size 155
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" 155 bytes payload
375 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
381 bundle2-input-part: total payload size 155
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" 155 bytes payload
445 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
451 bundle2-input-part: total payload size 155
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" 155 bytes payload
512 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
518 bundle2-input-part: total payload size 155
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" 155 bytes payload
584 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
590 bundle2-input-part: total payload size 155
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" 155 bytes payload
653 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
659 bundle2-input-part: total payload size 155
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" 155 bytes payload
724 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
730 bundle2-input-part: total payload size 155
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" (advisory) (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" 155 bytes payload
808 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
814 bundle2-input-part: total payload size 155
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" 155 bytes payload
886 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
892 bundle2-input-part: total payload size 155
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" 155 bytes payload
959 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
965 bundle2-input-part: total payload size 155
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" 155 bytes payload
1043 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
1049 bundle2-input-part: total payload size 155
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" (advisory) (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" 155 bytes payload
1130 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
1136 bundle2-input-part: total payload size 155
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" (advisory) (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" 155 bytes payload
1213 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
1219 bundle2-input-part: total payload size 155
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" 155 bytes payload
1289 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
1295 bundle2-input-part: total payload size 155
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" (advisory) (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" 155 bytes payload
1373 bundle2-output-part: "replycaps" 155 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" (advisory) (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 155
1379 bundle2-input-part: total payload size 155
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" 155 bytes payload
1488 bundle2-output-part: "replycaps" 155 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" (advisory) (params: 4 mandatory) empty payload
1491 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1492 bundle2-output-part: "pushkey" (advisory) (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 155
1495 bundle2-input-part: total payload size 155
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" (advisory) (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" (advisory) (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" 155 bytes payload
1577 bundle2-output-part: "replycaps" 155 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" (advisory) (params: 4 mandatory) empty payload
1580 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1581 bundle2-output-part: "pushkey" (advisory) (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 155
1584 bundle2-input-part: total payload size 155
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" 155 bytes payload
1651 bundle2-output-part: "replycaps" 155 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" (advisory) (params: 4 mandatory) empty payload
1654 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1655 bundle2-output-part: "pushkey" (advisory) (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 155
1658 bundle2-input-part: total payload size 155
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" 155 bytes payload
1721 bundle2-output-part: "replycaps" 155 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" (advisory) (params: 4 mandatory) empty payload
1724 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1725 bundle2-output-part: "pushkey" (advisory) (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 155
1728 bundle2-input-part: total payload size 155
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" 155 bytes payload
1785 bundle2-output-part: "replycaps" 155 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" (advisory) (params: 4 mandatory) empty payload
1788 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1789 bundle2-output-part: "pushkey" (advisory) (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 155
1792 bundle2-input-part: total payload size 155
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" (advisory) (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" (advisory) (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" 155 bytes payload
1879 bundle2-output-part: "replycaps" 155 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" (advisory) (params: 4 mandatory) empty payload
1882 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1883 bundle2-output-part: "pushkey" (advisory) (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 155
1886 bundle2-input-part: total payload size 155
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" (advisory) (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" (advisory) (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" 155 bytes payload
1972 bundle2-output-part: "replycaps" 155 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" (advisory) (params: 4 mandatory) empty payload
1975 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1976 bundle2-output-part: "pushkey" (advisory) (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 155
1979 bundle2-input-part: total payload size 155
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" 155 bytes payload
2041 bundle2-output-part: "replycaps" 155 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" (advisory) (params: 4 mandatory) empty payload
2044 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2045 bundle2-output-part: "pushkey" (advisory) (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 155
2048 bundle2-input-part: total payload size 155
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" (advisory) (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" (advisory) (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" 155 bytes payload
2128 bundle2-output-part: "replycaps" 155 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" (advisory) (params: 4 mandatory) empty payload
2131 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2132 bundle2-output-part: "pushkey" (advisory) (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 155
2135 bundle2-input-part: total payload size 155
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,165 +1,171 b''
1 #require killdaemons
1 #require killdaemons
2
2
3 $ hg init test
3 $ hg init test
4 $ cd test
4 $ cd test
5 $ echo a > a
5 $ echo a > a
6 $ hg ci -Ama
6 $ hg ci -Ama
7 adding a
7 adding a
8 $ cd ..
8 $ cd ..
9 $ hg clone test test2
9 $ hg clone test test2
10 updating to branch default
10 updating to branch default
11 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
11 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
12 $ cd test2
12 $ cd test2
13 $ echo a >> a
13 $ echo a >> a
14 $ hg ci -mb
14 $ hg ci -mb
15 $ req() {
15 $ req() {
16 > hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
16 > hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
17 > cat hg.pid >> $DAEMON_PIDS
17 > cat hg.pid >> $DAEMON_PIDS
18 > hg --cwd ../test2 push http://localhost:$HGPORT/
18 > hg --cwd ../test2 push http://localhost:$HGPORT/
19 > exitstatus=$?
19 > exitstatus=$?
20 > killdaemons.py
20 > killdaemons.py
21 > echo % serve errors
21 > echo % serve errors
22 > cat errors.log
22 > cat errors.log
23 > return $exitstatus
23 > return $exitstatus
24 > }
24 > }
25 $ cd ../test
25 $ cd ../test
26
26
27 expect ssl error
27 expect ssl error
28
28
29 $ req
29 $ req
30 pushing to http://localhost:$HGPORT/
30 pushing to http://localhost:$HGPORT/
31 searching for changes
31 searching for changes
32 abort: HTTP Error 403: ssl required
32 abort: HTTP Error 403: ssl required
33 % serve errors
33 % serve errors
34 [255]
34 [255]
35
35
36 expect authorization error
36 expect authorization error
37
37
38 $ echo '[web]' > .hg/hgrc
38 $ echo '[web]' > .hg/hgrc
39 $ echo 'push_ssl = false' >> .hg/hgrc
39 $ echo 'push_ssl = false' >> .hg/hgrc
40 $ req
40 $ req
41 pushing to http://localhost:$HGPORT/
41 pushing to http://localhost:$HGPORT/
42 searching for changes
42 searching for changes
43 abort: authorization failed
43 abort: authorization failed
44 % serve errors
44 % serve errors
45 [255]
45 [255]
46
46
47 expect authorization error: must have authorized user
47 expect authorization error: must have authorized user
48
48
49 $ echo 'allow_push = unperson' >> .hg/hgrc
49 $ echo 'allow_push = unperson' >> .hg/hgrc
50 $ req
50 $ req
51 pushing to http://localhost:$HGPORT/
51 pushing to http://localhost:$HGPORT/
52 searching for changes
52 searching for changes
53 abort: authorization failed
53 abort: authorization failed
54 % serve errors
54 % serve errors
55 [255]
55 [255]
56
56
57 expect success
57 expect success
58
58
59 $ echo 'allow_push = *' >> .hg/hgrc
59 $ echo 'allow_push = *' >> .hg/hgrc
60 $ echo '[hooks]' >> .hg/hgrc
60 $ echo '[hooks]' >> .hg/hgrc
61 $ echo "changegroup = printenv.py changegroup 0" >> .hg/hgrc
61 $ echo "changegroup = printenv.py changegroup 0" >> .hg/hgrc
62 $ echo "pushkey = printenv.py pushkey 0" >> .hg/hgrc
62 $ echo "pushkey = printenv.py pushkey 0" >> .hg/hgrc
63 $ req
63 $ req
64 pushing to http://localhost:$HGPORT/
64 pushing to http://localhost:$HGPORT/
65 searching for changes
65 searching for changes
66 remote: adding changesets
66 remote: adding changesets
67 remote: adding manifests
67 remote: adding manifests
68 remote: adding file changes
68 remote: adding file changes
69 remote: added 1 changesets with 1 changes to 1 files
69 remote: added 1 changesets with 1 changes to 1 files
70 remote: pushkey hook: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1
70 remote: pushkey hook: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1
71 remote: changegroup hook: HG_BUNDLE2=1 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:http:127.0.0.1: (glob)
71 remote: changegroup hook: HG_BUNDLE2=1 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:http:127.0.0.1: (glob)
72 % serve errors
72 % serve errors
73 $ hg rollback
73 $ hg rollback
74 repository tip rolled back to revision 0 (undo serve)
74 repository tip rolled back to revision 0 (undo serve)
75
75
76 expect success, server lacks the httpheader capability
76 expect success, server lacks the httpheader capability
77
77
78 $ CAP=httpheader
78 $ CAP=httpheader
79 $ . "$TESTDIR/notcapable"
79 $ . "$TESTDIR/notcapable"
80 $ req
80 $ req
81 pushing to http://localhost:$HGPORT/
81 pushing to http://localhost:$HGPORT/
82 searching for changes
82 searching for changes
83 remote: adding changesets
83 remote: adding changesets
84 remote: adding manifests
84 remote: adding manifests
85 remote: adding file changes
85 remote: adding file changes
86 remote: added 1 changesets with 1 changes to 1 files
86 remote: added 1 changesets with 1 changes to 1 files
87 remote: pushkey hook: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1
87 remote: pushkey hook: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1
88 remote: changegroup hook: HG_BUNDLE2=1 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:http:127.0.0.1: (glob)
88 remote: changegroup hook: HG_BUNDLE2=1 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:http:127.0.0.1: (glob)
89 % serve errors
89 % serve errors
90 $ hg rollback
90 $ hg rollback
91 repository tip rolled back to revision 0 (undo serve)
91 repository tip rolled back to revision 0 (undo serve)
92
92
93 expect success, server lacks the unbundlehash capability
93 expect success, server lacks the unbundlehash capability
94
94
95 $ CAP=unbundlehash
95 $ CAP=unbundlehash
96 $ . "$TESTDIR/notcapable"
96 $ . "$TESTDIR/notcapable"
97 $ req
97 $ req
98 pushing to http://localhost:$HGPORT/
98 pushing to http://localhost:$HGPORT/
99 searching for changes
99 searching for changes
100 remote: adding changesets
100 remote: adding changesets
101 remote: adding manifests
101 remote: adding manifests
102 remote: adding file changes
102 remote: adding file changes
103 remote: added 1 changesets with 1 changes to 1 files
103 remote: added 1 changesets with 1 changes to 1 files
104 remote: pushkey hook: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1
104 remote: pushkey hook: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1
105 remote: changegroup hook: HG_BUNDLE2=1 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:http:127.0.0.1: (glob)
105 remote: changegroup hook: HG_BUNDLE2=1 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:http:127.0.0.1: (glob)
106 % serve errors
106 % serve errors
107 $ hg rollback
107 $ hg rollback
108 repository tip rolled back to revision 0 (undo serve)
108 repository tip rolled back to revision 0 (undo serve)
109
109
110 expect push success, phase change failure
110 expect push success, phase change failure
111
111
112 $ cat > .hg/hgrc <<EOF
112 $ cat > .hg/hgrc <<EOF
113 > [web]
113 > [web]
114 > push_ssl = false
114 > push_ssl = false
115 > allow_push = *
115 > allow_push = *
116 > [hooks]
116 > [hooks]
117 > prepushkey = printenv.py prepushkey 1
117 > prepushkey = printenv.py prepushkey 1
118 > EOF
118 > EOF
119 $ req
119 $ req
120 pushing to http://localhost:$HGPORT/
120 pushing to http://localhost:$HGPORT/
121 searching for changes
121 searching for changes
122 remote: adding changesets
122 remote: adding changesets
123 remote: adding manifests
123 remote: adding manifests
124 remote: adding file changes
124 remote: adding file changes
125 remote: added 1 changesets with 1 changes to 1 files
125 remote: added 1 changesets with 1 changes to 1 files
126 remote: prepushkey hook: HG_BUNDLE2=1 HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:http:127.0.0.1: (glob)
126 remote: prepushkey hook: HG_BUNDLE2=1 HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:http:127.0.0.1: (glob)
127 remote: pushkey-abort: prepushkey hook exited with status 1
127 remote: pushkey-abort: prepushkey hook exited with status 1
128 updating ba677d0156c1 to public failed!
128 remote: transaction abort!
129 remote: rollback completed
130 abort: updating ba677d0156c1 to public failed
129 % serve errors
131 % serve errors
132 [255]
130
133
131 expect phase change success
134 expect phase change success
132
135
133 $ echo "prepushkey = printenv.py prepushkey 0" >> .hg/hgrc
136 $ echo "prepushkey = printenv.py prepushkey 0" >> .hg/hgrc
134 $ req
137 $ req
135 pushing to http://localhost:$HGPORT/
138 pushing to http://localhost:$HGPORT/
136 searching for changes
139 searching for changes
137 no changes found
140 remote: adding changesets
141 remote: adding manifests
142 remote: adding file changes
143 remote: added 1 changesets with 1 changes to 1 files
144 remote: prepushkey hook: HG_BUNDLE2=1 HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:* HG_URL=remote:http:127.0.0.1: (glob)
138 % serve errors
145 % serve errors
139 [1]
140 $ hg rollback
146 $ hg rollback
141 repository tip rolled back to revision 0 (undo serve)
147 repository tip rolled back to revision 0 (undo serve)
142
148
143 expect authorization error: all users denied
149 expect authorization error: all users denied
144
150
145 $ echo '[web]' > .hg/hgrc
151 $ echo '[web]' > .hg/hgrc
146 $ echo 'push_ssl = false' >> .hg/hgrc
152 $ echo 'push_ssl = false' >> .hg/hgrc
147 $ echo 'deny_push = *' >> .hg/hgrc
153 $ echo 'deny_push = *' >> .hg/hgrc
148 $ req
154 $ req
149 pushing to http://localhost:$HGPORT/
155 pushing to http://localhost:$HGPORT/
150 searching for changes
156 searching for changes
151 abort: authorization failed
157 abort: authorization failed
152 % serve errors
158 % serve errors
153 [255]
159 [255]
154
160
155 expect authorization error: some users denied, users must be authenticated
161 expect authorization error: some users denied, users must be authenticated
156
162
157 $ echo 'deny_push = unperson' >> .hg/hgrc
163 $ echo 'deny_push = unperson' >> .hg/hgrc
158 $ req
164 $ req
159 pushing to http://localhost:$HGPORT/
165 pushing to http://localhost:$HGPORT/
160 searching for changes
166 searching for changes
161 abort: authorization failed
167 abort: authorization failed
162 % serve errors
168 % serve errors
163 [255]
169 [255]
164
170
165 $ cd ..
171 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now