##// END OF EJS Templates
push: only say we are trying to push obsmarkers when we actually try...
Pierre-Yves David -
r25559:521c1a31 default
parent child Browse files
Show More
@@ -1,1572 +1,1572
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
527
528 def handlefailure(pushop, exc):
528 def handlefailure(pushop, exc):
529 targetid = int(exc.partid)
529 targetid = int(exc.partid)
530 for partid, node in part2node:
530 for partid, node in part2node:
531 if partid == targetid:
531 if partid == targetid:
532 raise error.Abort(_('updating %s to public failed') % node)
532 raise error.Abort(_('updating %s to public failed') % node)
533
533
534 enc = pushkey.encode
534 enc = pushkey.encode
535 for newremotehead in pushop.outdatedphases:
535 for newremotehead in pushop.outdatedphases:
536 part = bundler.newpart('pushkey')
536 part = bundler.newpart('pushkey')
537 part.addparam('namespace', enc('phases'))
537 part.addparam('namespace', enc('phases'))
538 part.addparam('key', enc(newremotehead.hex()))
538 part.addparam('key', enc(newremotehead.hex()))
539 part.addparam('old', enc(str(phases.draft)))
539 part.addparam('old', enc(str(phases.draft)))
540 part.addparam('new', enc(str(phases.public)))
540 part.addparam('new', enc(str(phases.public)))
541 part2node.append((part.id, newremotehead))
541 part2node.append((part.id, newremotehead))
542 pushop.pkfailcb[part.id] = handlefailure
542 pushop.pkfailcb[part.id] = handlefailure
543
543
544 def handlereply(op):
544 def handlereply(op):
545 for partid, node in part2node:
545 for partid, node in part2node:
546 partrep = op.records.getreplies(partid)
546 partrep = op.records.getreplies(partid)
547 results = partrep['pushkey']
547 results = partrep['pushkey']
548 assert len(results) <= 1
548 assert len(results) <= 1
549 msg = None
549 msg = None
550 if not results:
550 if not results:
551 msg = _('server ignored update of %s to public!\n') % node
551 msg = _('server ignored update of %s to public!\n') % node
552 elif not int(results[0]['return']):
552 elif not int(results[0]['return']):
553 msg = _('updating %s to public failed!\n') % node
553 msg = _('updating %s to public failed!\n') % node
554 if msg is not None:
554 if msg is not None:
555 pushop.ui.warn(msg)
555 pushop.ui.warn(msg)
556 return handlereply
556 return handlereply
557
557
558 @b2partsgenerator('obsmarkers')
558 @b2partsgenerator('obsmarkers')
559 def _pushb2obsmarkers(pushop, bundler):
559 def _pushb2obsmarkers(pushop, bundler):
560 if 'obsmarkers' in pushop.stepsdone:
560 if 'obsmarkers' in pushop.stepsdone:
561 return
561 return
562 remoteversions = bundle2.obsmarkersversion(bundler.capabilities)
562 remoteversions = bundle2.obsmarkersversion(bundler.capabilities)
563 if obsolete.commonversion(remoteversions) is None:
563 if obsolete.commonversion(remoteversions) is None:
564 return
564 return
565 pushop.stepsdone.add('obsmarkers')
565 pushop.stepsdone.add('obsmarkers')
566 if pushop.outobsmarkers:
566 if pushop.outobsmarkers:
567 markers = sorted(pushop.outobsmarkers)
567 markers = sorted(pushop.outobsmarkers)
568 buildobsmarkerspart(bundler, markers)
568 buildobsmarkerspart(bundler, markers)
569
569
570 @b2partsgenerator('bookmarks')
570 @b2partsgenerator('bookmarks')
571 def _pushb2bookmarks(pushop, bundler):
571 def _pushb2bookmarks(pushop, bundler):
572 """handle phase push through bundle2"""
572 """handle phase push through bundle2"""
573 if 'bookmarks' in pushop.stepsdone:
573 if 'bookmarks' in pushop.stepsdone:
574 return
574 return
575 b2caps = bundle2.bundle2caps(pushop.remote)
575 b2caps = bundle2.bundle2caps(pushop.remote)
576 if 'pushkey' not in b2caps:
576 if 'pushkey' not in b2caps:
577 return
577 return
578 pushop.stepsdone.add('bookmarks')
578 pushop.stepsdone.add('bookmarks')
579 part2book = []
579 part2book = []
580 enc = pushkey.encode
580 enc = pushkey.encode
581
581
582 def handlefailure(pushop, exc):
582 def handlefailure(pushop, exc):
583 targetid = int(exc.partid)
583 targetid = int(exc.partid)
584 for partid, book, action in part2book:
584 for partid, book, action in part2book:
585 if partid == targetid:
585 if partid == targetid:
586 raise error.Abort(bookmsgmap[action][1].rstrip() % book)
586 raise error.Abort(bookmsgmap[action][1].rstrip() % book)
587 # we should not be called for part we did not generated
587 # we should not be called for part we did not generated
588 assert False
588 assert False
589
589
590 for book, old, new in pushop.outbookmarks:
590 for book, old, new in pushop.outbookmarks:
591 part = bundler.newpart('pushkey')
591 part = bundler.newpart('pushkey')
592 part.addparam('namespace', enc('bookmarks'))
592 part.addparam('namespace', enc('bookmarks'))
593 part.addparam('key', enc(book))
593 part.addparam('key', enc(book))
594 part.addparam('old', enc(old))
594 part.addparam('old', enc(old))
595 part.addparam('new', enc(new))
595 part.addparam('new', enc(new))
596 action = 'update'
596 action = 'update'
597 if not old:
597 if not old:
598 action = 'export'
598 action = 'export'
599 elif not new:
599 elif not new:
600 action = 'delete'
600 action = 'delete'
601 part2book.append((part.id, book, action))
601 part2book.append((part.id, book, action))
602 pushop.pkfailcb[part.id] = handlefailure
602 pushop.pkfailcb[part.id] = handlefailure
603
603
604 def handlereply(op):
604 def handlereply(op):
605 ui = pushop.ui
605 ui = pushop.ui
606 for partid, book, action in part2book:
606 for partid, book, action in part2book:
607 partrep = op.records.getreplies(partid)
607 partrep = op.records.getreplies(partid)
608 results = partrep['pushkey']
608 results = partrep['pushkey']
609 assert len(results) <= 1
609 assert len(results) <= 1
610 if not results:
610 if not results:
611 pushop.ui.warn(_('server ignored bookmark %s update\n') % book)
611 pushop.ui.warn(_('server ignored bookmark %s update\n') % book)
612 else:
612 else:
613 ret = int(results[0]['return'])
613 ret = int(results[0]['return'])
614 if ret:
614 if ret:
615 ui.status(bookmsgmap[action][0] % book)
615 ui.status(bookmsgmap[action][0] % book)
616 else:
616 else:
617 ui.warn(bookmsgmap[action][1] % book)
617 ui.warn(bookmsgmap[action][1] % book)
618 if pushop.bkresult is not None:
618 if pushop.bkresult is not None:
619 pushop.bkresult = 1
619 pushop.bkresult = 1
620 return handlereply
620 return handlereply
621
621
622
622
623 def _pushbundle2(pushop):
623 def _pushbundle2(pushop):
624 """push data to the remote using bundle2
624 """push data to the remote using bundle2
625
625
626 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
627 evolve in the future."""
627 evolve in the future."""
628 bundler = bundle2.bundle20(pushop.ui, bundle2.bundle2caps(pushop.remote))
628 bundler = bundle2.bundle20(pushop.ui, bundle2.bundle2caps(pushop.remote))
629 pushback = (pushop.trmanager
629 pushback = (pushop.trmanager
630 and pushop.ui.configbool('experimental', 'bundle2.pushback'))
630 and pushop.ui.configbool('experimental', 'bundle2.pushback'))
631
631
632 # create reply capability
632 # create reply capability
633 capsblob = bundle2.encodecaps(bundle2.getrepocaps(pushop.repo,
633 capsblob = bundle2.encodecaps(bundle2.getrepocaps(pushop.repo,
634 allowpushback=pushback))
634 allowpushback=pushback))
635 bundler.newpart('replycaps', data=capsblob)
635 bundler.newpart('replycaps', data=capsblob)
636 replyhandlers = []
636 replyhandlers = []
637 for partgenname in b2partsgenorder:
637 for partgenname in b2partsgenorder:
638 partgen = b2partsgenmapping[partgenname]
638 partgen = b2partsgenmapping[partgenname]
639 ret = partgen(pushop, bundler)
639 ret = partgen(pushop, bundler)
640 if callable(ret):
640 if callable(ret):
641 replyhandlers.append(ret)
641 replyhandlers.append(ret)
642 # do not push if nothing to push
642 # do not push if nothing to push
643 if bundler.nbparts <= 1:
643 if bundler.nbparts <= 1:
644 return
644 return
645 stream = util.chunkbuffer(bundler.getchunks())
645 stream = util.chunkbuffer(bundler.getchunks())
646 try:
646 try:
647 try:
647 try:
648 reply = pushop.remote.unbundle(stream, ['force'], 'push')
648 reply = pushop.remote.unbundle(stream, ['force'], 'push')
649 except error.BundleValueError, exc:
649 except error.BundleValueError, exc:
650 raise util.Abort('missing support for %s' % exc)
650 raise util.Abort('missing support for %s' % exc)
651 try:
651 try:
652 trgetter = None
652 trgetter = None
653 if pushback:
653 if pushback:
654 trgetter = pushop.trmanager.transaction
654 trgetter = pushop.trmanager.transaction
655 op = bundle2.processbundle(pushop.repo, reply, trgetter)
655 op = bundle2.processbundle(pushop.repo, reply, trgetter)
656 except error.BundleValueError, exc:
656 except error.BundleValueError, exc:
657 raise util.Abort('missing support for %s' % exc)
657 raise util.Abort('missing support for %s' % exc)
658 except error.PushkeyFailed, exc:
658 except error.PushkeyFailed, exc:
659 partid = int(exc.partid)
659 partid = int(exc.partid)
660 if partid not in pushop.pkfailcb:
660 if partid not in pushop.pkfailcb:
661 raise
661 raise
662 pushop.pkfailcb[partid](pushop, exc)
662 pushop.pkfailcb[partid](pushop, exc)
663 for rephand in replyhandlers:
663 for rephand in replyhandlers:
664 rephand(op)
664 rephand(op)
665
665
666 def _pushchangeset(pushop):
666 def _pushchangeset(pushop):
667 """Make the actual push of changeset bundle to remote repo"""
667 """Make the actual push of changeset bundle to remote repo"""
668 if 'changesets' in pushop.stepsdone:
668 if 'changesets' in pushop.stepsdone:
669 return
669 return
670 pushop.stepsdone.add('changesets')
670 pushop.stepsdone.add('changesets')
671 if not _pushcheckoutgoing(pushop):
671 if not _pushcheckoutgoing(pushop):
672 return
672 return
673 pushop.repo.prepushoutgoinghooks(pushop.repo,
673 pushop.repo.prepushoutgoinghooks(pushop.repo,
674 pushop.remote,
674 pushop.remote,
675 pushop.outgoing)
675 pushop.outgoing)
676 outgoing = pushop.outgoing
676 outgoing = pushop.outgoing
677 unbundle = pushop.remote.capable('unbundle')
677 unbundle = pushop.remote.capable('unbundle')
678 # TODO: get bundlecaps from remote
678 # TODO: get bundlecaps from remote
679 bundlecaps = None
679 bundlecaps = None
680 # create a changegroup from local
680 # create a changegroup from local
681 if pushop.revs is None and not (outgoing.excluded
681 if pushop.revs is None and not (outgoing.excluded
682 or pushop.repo.changelog.filteredrevs):
682 or pushop.repo.changelog.filteredrevs):
683 # push everything,
683 # push everything,
684 # use the fast path, no race possible on push
684 # use the fast path, no race possible on push
685 bundler = changegroup.cg1packer(pushop.repo, bundlecaps)
685 bundler = changegroup.cg1packer(pushop.repo, bundlecaps)
686 cg = changegroup.getsubset(pushop.repo,
686 cg = changegroup.getsubset(pushop.repo,
687 outgoing,
687 outgoing,
688 bundler,
688 bundler,
689 'push',
689 'push',
690 fastpath=True)
690 fastpath=True)
691 else:
691 else:
692 cg = changegroup.getlocalchangegroup(pushop.repo, 'push', outgoing,
692 cg = changegroup.getlocalchangegroup(pushop.repo, 'push', outgoing,
693 bundlecaps)
693 bundlecaps)
694
694
695 # apply changegroup to remote
695 # apply changegroup to remote
696 if unbundle:
696 if unbundle:
697 # local repo finds heads on server, finds out what
697 # local repo finds heads on server, finds out what
698 # revs it must push. once revs transferred, if server
698 # revs it must push. once revs transferred, if server
699 # finds it has different heads (someone else won
699 # finds it has different heads (someone else won
700 # commit/push race), server aborts.
700 # commit/push race), server aborts.
701 if pushop.force:
701 if pushop.force:
702 remoteheads = ['force']
702 remoteheads = ['force']
703 else:
703 else:
704 remoteheads = pushop.remoteheads
704 remoteheads = pushop.remoteheads
705 # ssh: return remote's addchangegroup()
705 # ssh: return remote's addchangegroup()
706 # http: return remote's addchangegroup() or 0 for error
706 # http: return remote's addchangegroup() or 0 for error
707 pushop.cgresult = pushop.remote.unbundle(cg, remoteheads,
707 pushop.cgresult = pushop.remote.unbundle(cg, remoteheads,
708 pushop.repo.url())
708 pushop.repo.url())
709 else:
709 else:
710 # we return an integer indicating remote head count
710 # we return an integer indicating remote head count
711 # change
711 # change
712 pushop.cgresult = pushop.remote.addchangegroup(cg, 'push',
712 pushop.cgresult = pushop.remote.addchangegroup(cg, 'push',
713 pushop.repo.url())
713 pushop.repo.url())
714
714
715 def _pushsyncphase(pushop):
715 def _pushsyncphase(pushop):
716 """synchronise phase information locally and remotely"""
716 """synchronise phase information locally and remotely"""
717 cheads = pushop.commonheads
717 cheads = pushop.commonheads
718 # even when we don't push, exchanging phase data is useful
718 # even when we don't push, exchanging phase data is useful
719 remotephases = pushop.remote.listkeys('phases')
719 remotephases = pushop.remote.listkeys('phases')
720 if (pushop.ui.configbool('ui', '_usedassubrepo', False)
720 if (pushop.ui.configbool('ui', '_usedassubrepo', False)
721 and remotephases # server supports phases
721 and remotephases # server supports phases
722 and pushop.cgresult is None # nothing was pushed
722 and pushop.cgresult is None # nothing was pushed
723 and remotephases.get('publishing', False)):
723 and remotephases.get('publishing', False)):
724 # When:
724 # When:
725 # - this is a subrepo push
725 # - this is a subrepo push
726 # - and remote support phase
726 # - and remote support phase
727 # - and no changeset was pushed
727 # - and no changeset was pushed
728 # - and remote is publishing
728 # - and remote is publishing
729 # We may be in issue 3871 case!
729 # We may be in issue 3871 case!
730 # We drop the possible phase synchronisation done by
730 # We drop the possible phase synchronisation done by
731 # courtesy to publish changesets possibly locally draft
731 # courtesy to publish changesets possibly locally draft
732 # on the remote.
732 # on the remote.
733 remotephases = {'publishing': 'True'}
733 remotephases = {'publishing': 'True'}
734 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
735 _localphasemove(pushop, cheads)
735 _localphasemove(pushop, cheads)
736 # 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
737 else:
737 else:
738 ana = phases.analyzeremotephases(pushop.repo, cheads,
738 ana = phases.analyzeremotephases(pushop.repo, cheads,
739 remotephases)
739 remotephases)
740 pheads, droots = ana
740 pheads, droots = ana
741 ### Apply remote phase on local
741 ### Apply remote phase on local
742 if remotephases.get('publishing', False):
742 if remotephases.get('publishing', False):
743 _localphasemove(pushop, cheads)
743 _localphasemove(pushop, cheads)
744 else: # publish = False
744 else: # publish = False
745 _localphasemove(pushop, pheads)
745 _localphasemove(pushop, pheads)
746 _localphasemove(pushop, cheads, phases.draft)
746 _localphasemove(pushop, cheads, phases.draft)
747 ### Apply local phase on remote
747 ### Apply local phase on remote
748
748
749 if pushop.cgresult:
749 if pushop.cgresult:
750 if 'phases' in pushop.stepsdone:
750 if 'phases' in pushop.stepsdone:
751 # phases already pushed though bundle2
751 # phases already pushed though bundle2
752 return
752 return
753 outdated = pushop.outdatedphases
753 outdated = pushop.outdatedphases
754 else:
754 else:
755 outdated = pushop.fallbackoutdatedphases
755 outdated = pushop.fallbackoutdatedphases
756
756
757 pushop.stepsdone.add('phases')
757 pushop.stepsdone.add('phases')
758
758
759 # filter heads already turned public by the push
759 # filter heads already turned public by the push
760 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]
761 # fallback to independent pushkey command
761 # fallback to independent pushkey command
762 for newremotehead in outdated:
762 for newremotehead in outdated:
763 r = pushop.remote.pushkey('phases',
763 r = pushop.remote.pushkey('phases',
764 newremotehead.hex(),
764 newremotehead.hex(),
765 str(phases.draft),
765 str(phases.draft),
766 str(phases.public))
766 str(phases.public))
767 if not r:
767 if not r:
768 pushop.ui.warn(_('updating %s to public failed!\n')
768 pushop.ui.warn(_('updating %s to public failed!\n')
769 % newremotehead)
769 % newremotehead)
770
770
771 def _localphasemove(pushop, nodes, phase=phases.public):
771 def _localphasemove(pushop, nodes, phase=phases.public):
772 """move <nodes> to <phase> in the local source repo"""
772 """move <nodes> to <phase> in the local source repo"""
773 if pushop.trmanager:
773 if pushop.trmanager:
774 phases.advanceboundary(pushop.repo,
774 phases.advanceboundary(pushop.repo,
775 pushop.trmanager.transaction(),
775 pushop.trmanager.transaction(),
776 phase,
776 phase,
777 nodes)
777 nodes)
778 else:
778 else:
779 # repo is not locked, do not change any phases!
779 # repo is not locked, do not change any phases!
780 # Informs the user that phases should have been moved when
780 # Informs the user that phases should have been moved when
781 # applicable.
781 # applicable.
782 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()]
783 phasestr = phases.phasenames[phase]
783 phasestr = phases.phasenames[phase]
784 if actualmoves:
784 if actualmoves:
785 pushop.ui.status(_('cannot lock source repo, skipping '
785 pushop.ui.status(_('cannot lock source repo, skipping '
786 'local %s phase update\n') % phasestr)
786 'local %s phase update\n') % phasestr)
787
787
788 def _pushobsolete(pushop):
788 def _pushobsolete(pushop):
789 """utility function to push obsolete markers to a remote"""
789 """utility function to push obsolete markers to a remote"""
790 if 'obsmarkers' in pushop.stepsdone:
790 if 'obsmarkers' in pushop.stepsdone:
791 return
791 return
792 pushop.ui.debug('try to push obsolete markers to remote\n')
793 repo = pushop.repo
792 repo = pushop.repo
794 remote = pushop.remote
793 remote = pushop.remote
795 pushop.stepsdone.add('obsmarkers')
794 pushop.stepsdone.add('obsmarkers')
796 if pushop.outobsmarkers:
795 if pushop.outobsmarkers:
796 pushop.ui.debug('try to push obsolete markers to remote\n')
797 rslts = []
797 rslts = []
798 remotedata = obsolete._pushkeyescape(sorted(pushop.outobsmarkers))
798 remotedata = obsolete._pushkeyescape(sorted(pushop.outobsmarkers))
799 for key in sorted(remotedata, reverse=True):
799 for key in sorted(remotedata, reverse=True):
800 # reverse sort to ensure we end with dump0
800 # reverse sort to ensure we end with dump0
801 data = remotedata[key]
801 data = remotedata[key]
802 rslts.append(remote.pushkey('obsolete', key, '', data))
802 rslts.append(remote.pushkey('obsolete', key, '', data))
803 if [r for r in rslts if not r]:
803 if [r for r in rslts if not r]:
804 msg = _('failed to push some obsolete markers!\n')
804 msg = _('failed to push some obsolete markers!\n')
805 repo.ui.warn(msg)
805 repo.ui.warn(msg)
806
806
807 def _pushbookmark(pushop):
807 def _pushbookmark(pushop):
808 """Update bookmark position on remote"""
808 """Update bookmark position on remote"""
809 if pushop.cgresult == 0 or 'bookmarks' in pushop.stepsdone:
809 if pushop.cgresult == 0 or 'bookmarks' in pushop.stepsdone:
810 return
810 return
811 pushop.stepsdone.add('bookmarks')
811 pushop.stepsdone.add('bookmarks')
812 ui = pushop.ui
812 ui = pushop.ui
813 remote = pushop.remote
813 remote = pushop.remote
814
814
815 for b, old, new in pushop.outbookmarks:
815 for b, old, new in pushop.outbookmarks:
816 action = 'update'
816 action = 'update'
817 if not old:
817 if not old:
818 action = 'export'
818 action = 'export'
819 elif not new:
819 elif not new:
820 action = 'delete'
820 action = 'delete'
821 if remote.pushkey('bookmarks', b, old, new):
821 if remote.pushkey('bookmarks', b, old, new):
822 ui.status(bookmsgmap[action][0] % b)
822 ui.status(bookmsgmap[action][0] % b)
823 else:
823 else:
824 ui.warn(bookmsgmap[action][1] % b)
824 ui.warn(bookmsgmap[action][1] % b)
825 # discovery can have set the value form invalid entry
825 # discovery can have set the value form invalid entry
826 if pushop.bkresult is not None:
826 if pushop.bkresult is not None:
827 pushop.bkresult = 1
827 pushop.bkresult = 1
828
828
829 class pulloperation(object):
829 class pulloperation(object):
830 """A object that represent a single pull operation
830 """A object that represent a single pull operation
831
831
832 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.
833
833
834 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
835 afterward.
835 afterward.
836 """
836 """
837
837
838 def __init__(self, repo, remote, heads=None, force=False, bookmarks=(),
838 def __init__(self, repo, remote, heads=None, force=False, bookmarks=(),
839 remotebookmarks=None):
839 remotebookmarks=None):
840 # repo we pull into
840 # repo we pull into
841 self.repo = repo
841 self.repo = repo
842 # repo we pull from
842 # repo we pull from
843 self.remote = remote
843 self.remote = remote
844 # revision we try to pull (None is "all")
844 # revision we try to pull (None is "all")
845 self.heads = heads
845 self.heads = heads
846 # bookmark pulled explicitly
846 # bookmark pulled explicitly
847 self.explicitbookmarks = bookmarks
847 self.explicitbookmarks = bookmarks
848 # do we force pull?
848 # do we force pull?
849 self.force = force
849 self.force = force
850 # transaction manager
850 # transaction manager
851 self.trmanager = None
851 self.trmanager = None
852 # set of common changeset between local and remote before pull
852 # set of common changeset between local and remote before pull
853 self.common = None
853 self.common = None
854 # set of pulled head
854 # set of pulled head
855 self.rheads = None
855 self.rheads = None
856 # list of missing changeset to fetch remotely
856 # list of missing changeset to fetch remotely
857 self.fetch = None
857 self.fetch = None
858 # remote bookmarks data
858 # remote bookmarks data
859 self.remotebookmarks = remotebookmarks
859 self.remotebookmarks = remotebookmarks
860 # result of changegroup pulling (used as return code by pull)
860 # result of changegroup pulling (used as return code by pull)
861 self.cgresult = None
861 self.cgresult = None
862 # list of step already done
862 # list of step already done
863 self.stepsdone = set()
863 self.stepsdone = set()
864
864
865 @util.propertycache
865 @util.propertycache
866 def pulledsubset(self):
866 def pulledsubset(self):
867 """heads of the set of changeset target by the pull"""
867 """heads of the set of changeset target by the pull"""
868 # compute target subset
868 # compute target subset
869 if self.heads is None:
869 if self.heads is None:
870 # We pulled every thing possible
870 # We pulled every thing possible
871 # sync on everything common
871 # sync on everything common
872 c = set(self.common)
872 c = set(self.common)
873 ret = list(self.common)
873 ret = list(self.common)
874 for n in self.rheads:
874 for n in self.rheads:
875 if n not in c:
875 if n not in c:
876 ret.append(n)
876 ret.append(n)
877 return ret
877 return ret
878 else:
878 else:
879 # We pulled a specific subset
879 # We pulled a specific subset
880 # sync on this subset
880 # sync on this subset
881 return self.heads
881 return self.heads
882
882
883 def gettransaction(self):
883 def gettransaction(self):
884 # deprecated; talk to trmanager directly
884 # deprecated; talk to trmanager directly
885 return self.trmanager.transaction()
885 return self.trmanager.transaction()
886
886
887 class transactionmanager(object):
887 class transactionmanager(object):
888 """An object to manage the life cycle of a transaction
888 """An object to manage the life cycle of a transaction
889
889
890 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
891 closing the transaction."""
891 closing the transaction."""
892 def __init__(self, repo, source, url):
892 def __init__(self, repo, source, url):
893 self.repo = repo
893 self.repo = repo
894 self.source = source
894 self.source = source
895 self.url = url
895 self.url = url
896 self._tr = None
896 self._tr = None
897
897
898 def transaction(self):
898 def transaction(self):
899 """Return an open transaction object, constructing if necessary"""
899 """Return an open transaction object, constructing if necessary"""
900 if not self._tr:
900 if not self._tr:
901 trname = '%s\n%s' % (self.source, util.hidepassword(self.url))
901 trname = '%s\n%s' % (self.source, util.hidepassword(self.url))
902 self._tr = self.repo.transaction(trname)
902 self._tr = self.repo.transaction(trname)
903 self._tr.hookargs['source'] = self.source
903 self._tr.hookargs['source'] = self.source
904 self._tr.hookargs['url'] = self.url
904 self._tr.hookargs['url'] = self.url
905 return self._tr
905 return self._tr
906
906
907 def close(self):
907 def close(self):
908 """close transaction if created"""
908 """close transaction if created"""
909 if self._tr is not None:
909 if self._tr is not None:
910 self._tr.close()
910 self._tr.close()
911
911
912 def release(self):
912 def release(self):
913 """release transaction if created"""
913 """release transaction if created"""
914 if self._tr is not None:
914 if self._tr is not None:
915 self._tr.release()
915 self._tr.release()
916
916
917 def pull(repo, remote, heads=None, force=False, bookmarks=(), opargs=None):
917 def pull(repo, remote, heads=None, force=False, bookmarks=(), opargs=None):
918 if opargs is None:
918 if opargs is None:
919 opargs = {}
919 opargs = {}
920 pullop = pulloperation(repo, remote, heads, force, bookmarks=bookmarks,
920 pullop = pulloperation(repo, remote, heads, force, bookmarks=bookmarks,
921 **opargs)
921 **opargs)
922 if pullop.remote.local():
922 if pullop.remote.local():
923 missing = set(pullop.remote.requirements) - pullop.repo.supported
923 missing = set(pullop.remote.requirements) - pullop.repo.supported
924 if missing:
924 if missing:
925 msg = _("required features are not"
925 msg = _("required features are not"
926 " supported in the destination:"
926 " supported in the destination:"
927 " %s") % (', '.join(sorted(missing)))
927 " %s") % (', '.join(sorted(missing)))
928 raise util.Abort(msg)
928 raise util.Abort(msg)
929
929
930 lock = pullop.repo.lock()
930 lock = pullop.repo.lock()
931 try:
931 try:
932 pullop.trmanager = transactionmanager(repo, 'pull', remote.url())
932 pullop.trmanager = transactionmanager(repo, 'pull', remote.url())
933 _pulldiscovery(pullop)
933 _pulldiscovery(pullop)
934 if _canusebundle2(pullop):
934 if _canusebundle2(pullop):
935 _pullbundle2(pullop)
935 _pullbundle2(pullop)
936 _pullchangeset(pullop)
936 _pullchangeset(pullop)
937 _pullphase(pullop)
937 _pullphase(pullop)
938 _pullbookmarks(pullop)
938 _pullbookmarks(pullop)
939 _pullobsolete(pullop)
939 _pullobsolete(pullop)
940 pullop.trmanager.close()
940 pullop.trmanager.close()
941 finally:
941 finally:
942 pullop.trmanager.release()
942 pullop.trmanager.release()
943 lock.release()
943 lock.release()
944
944
945 return pullop
945 return pullop
946
946
947 # list of steps to perform discovery before pull
947 # list of steps to perform discovery before pull
948 pulldiscoveryorder = []
948 pulldiscoveryorder = []
949
949
950 # Mapping between step name and function
950 # Mapping between step name and function
951 #
951 #
952 # This exists to help extensions wrap steps if necessary
952 # This exists to help extensions wrap steps if necessary
953 pulldiscoverymapping = {}
953 pulldiscoverymapping = {}
954
954
955 def pulldiscovery(stepname):
955 def pulldiscovery(stepname):
956 """decorator for function performing discovery before pull
956 """decorator for function performing discovery before pull
957
957
958 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
959 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
960 may matter).
960 may matter).
961
961
962 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
963 from an extension, change the pulldiscovery dictionary directly."""
963 from an extension, change the pulldiscovery dictionary directly."""
964 def dec(func):
964 def dec(func):
965 assert stepname not in pulldiscoverymapping
965 assert stepname not in pulldiscoverymapping
966 pulldiscoverymapping[stepname] = func
966 pulldiscoverymapping[stepname] = func
967 pulldiscoveryorder.append(stepname)
967 pulldiscoveryorder.append(stepname)
968 return func
968 return func
969 return dec
969 return dec
970
970
971 def _pulldiscovery(pullop):
971 def _pulldiscovery(pullop):
972 """Run all discovery steps"""
972 """Run all discovery steps"""
973 for stepname in pulldiscoveryorder:
973 for stepname in pulldiscoveryorder:
974 step = pulldiscoverymapping[stepname]
974 step = pulldiscoverymapping[stepname]
975 step(pullop)
975 step(pullop)
976
976
977 @pulldiscovery('b1:bookmarks')
977 @pulldiscovery('b1:bookmarks')
978 def _pullbookmarkbundle1(pullop):
978 def _pullbookmarkbundle1(pullop):
979 """fetch bookmark data in bundle1 case
979 """fetch bookmark data in bundle1 case
980
980
981 If not using bundle2, we have to fetch bookmarks before changeset
981 If not using bundle2, we have to fetch bookmarks before changeset
982 discovery to reduce the chance and impact of race conditions."""
982 discovery to reduce the chance and impact of race conditions."""
983 if pullop.remotebookmarks is not None:
983 if pullop.remotebookmarks is not None:
984 return
984 return
985 if (_canusebundle2(pullop)
985 if (_canusebundle2(pullop)
986 and 'listkeys' in bundle2.bundle2caps(pullop.remote)):
986 and 'listkeys' in bundle2.bundle2caps(pullop.remote)):
987 # 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
988 # new implementation.
988 # new implementation.
989 return
989 return
990 pullop.remotebookmarks = pullop.remote.listkeys('bookmarks')
990 pullop.remotebookmarks = pullop.remote.listkeys('bookmarks')
991
991
992
992
993 @pulldiscovery('changegroup')
993 @pulldiscovery('changegroup')
994 def _pulldiscoverychangegroup(pullop):
994 def _pulldiscoverychangegroup(pullop):
995 """discovery phase for the pull
995 """discovery phase for the pull
996
996
997 Current handle changeset discovery only, will change handle all discovery
997 Current handle changeset discovery only, will change handle all discovery
998 at some point."""
998 at some point."""
999 tmp = discovery.findcommonincoming(pullop.repo,
999 tmp = discovery.findcommonincoming(pullop.repo,
1000 pullop.remote,
1000 pullop.remote,
1001 heads=pullop.heads,
1001 heads=pullop.heads,
1002 force=pullop.force)
1002 force=pullop.force)
1003 common, fetch, rheads = tmp
1003 common, fetch, rheads = tmp
1004 nm = pullop.repo.unfiltered().changelog.nodemap
1004 nm = pullop.repo.unfiltered().changelog.nodemap
1005 if fetch and rheads:
1005 if fetch and rheads:
1006 # 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
1007 # remote heads and put in back in common.
1007 # remote heads and put in back in common.
1008 #
1008 #
1009 # 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
1010 # hidden situation". We do not performs discovery on unfiltered
1010 # hidden situation". We do not performs discovery on unfiltered
1011 # repository because it end up doing a pathological amount of round
1011 # repository because it end up doing a pathological amount of round
1012 # 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.
1013 #
1013 #
1014 # 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
1015 # 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,
1016 scommon = set(common)
1016 scommon = set(common)
1017 filteredrheads = []
1017 filteredrheads = []
1018 for n in rheads:
1018 for n in rheads:
1019 if n in nm:
1019 if n in nm:
1020 if n not in scommon:
1020 if n not in scommon:
1021 common.append(n)
1021 common.append(n)
1022 else:
1022 else:
1023 filteredrheads.append(n)
1023 filteredrheads.append(n)
1024 if not filteredrheads:
1024 if not filteredrheads:
1025 fetch = []
1025 fetch = []
1026 rheads = filteredrheads
1026 rheads = filteredrheads
1027 pullop.common = common
1027 pullop.common = common
1028 pullop.fetch = fetch
1028 pullop.fetch = fetch
1029 pullop.rheads = rheads
1029 pullop.rheads = rheads
1030
1030
1031 def _pullbundle2(pullop):
1031 def _pullbundle2(pullop):
1032 """pull data using bundle2
1032 """pull data using bundle2
1033
1033
1034 For now, the only supported data are changegroup."""
1034 For now, the only supported data are changegroup."""
1035 remotecaps = bundle2.bundle2caps(pullop.remote)
1035 remotecaps = bundle2.bundle2caps(pullop.remote)
1036 kwargs = {'bundlecaps': caps20to10(pullop.repo)}
1036 kwargs = {'bundlecaps': caps20to10(pullop.repo)}
1037 # pulling changegroup
1037 # pulling changegroup
1038 pullop.stepsdone.add('changegroup')
1038 pullop.stepsdone.add('changegroup')
1039
1039
1040 kwargs['common'] = pullop.common
1040 kwargs['common'] = pullop.common
1041 kwargs['heads'] = pullop.heads or pullop.rheads
1041 kwargs['heads'] = pullop.heads or pullop.rheads
1042 kwargs['cg'] = pullop.fetch
1042 kwargs['cg'] = pullop.fetch
1043 if 'listkeys' in remotecaps:
1043 if 'listkeys' in remotecaps:
1044 kwargs['listkeys'] = ['phase']
1044 kwargs['listkeys'] = ['phase']
1045 if pullop.remotebookmarks is None:
1045 if pullop.remotebookmarks is None:
1046 # make sure to always includes bookmark data when migrating
1046 # make sure to always includes bookmark data when migrating
1047 # `hg incoming --bundle` to using this function.
1047 # `hg incoming --bundle` to using this function.
1048 kwargs['listkeys'].append('bookmarks')
1048 kwargs['listkeys'].append('bookmarks')
1049 if not pullop.fetch:
1049 if not pullop.fetch:
1050 pullop.repo.ui.status(_("no changes found\n"))
1050 pullop.repo.ui.status(_("no changes found\n"))
1051 pullop.cgresult = 0
1051 pullop.cgresult = 0
1052 else:
1052 else:
1053 if pullop.heads is None and list(pullop.common) == [nullid]:
1053 if pullop.heads is None and list(pullop.common) == [nullid]:
1054 pullop.repo.ui.status(_("requesting all changes\n"))
1054 pullop.repo.ui.status(_("requesting all changes\n"))
1055 if obsolete.isenabled(pullop.repo, obsolete.exchangeopt):
1055 if obsolete.isenabled(pullop.repo, obsolete.exchangeopt):
1056 remoteversions = bundle2.obsmarkersversion(remotecaps)
1056 remoteversions = bundle2.obsmarkersversion(remotecaps)
1057 if obsolete.commonversion(remoteversions) is not None:
1057 if obsolete.commonversion(remoteversions) is not None:
1058 kwargs['obsmarkers'] = True
1058 kwargs['obsmarkers'] = True
1059 pullop.stepsdone.add('obsmarkers')
1059 pullop.stepsdone.add('obsmarkers')
1060 _pullbundle2extraprepare(pullop, kwargs)
1060 _pullbundle2extraprepare(pullop, kwargs)
1061 bundle = pullop.remote.getbundle('pull', **kwargs)
1061 bundle = pullop.remote.getbundle('pull', **kwargs)
1062 try:
1062 try:
1063 op = bundle2.processbundle(pullop.repo, bundle, pullop.gettransaction)
1063 op = bundle2.processbundle(pullop.repo, bundle, pullop.gettransaction)
1064 except error.BundleValueError, exc:
1064 except error.BundleValueError, exc:
1065 raise util.Abort('missing support for %s' % exc)
1065 raise util.Abort('missing support for %s' % exc)
1066
1066
1067 if pullop.fetch:
1067 if pullop.fetch:
1068 results = [cg['return'] for cg in op.records['changegroup']]
1068 results = [cg['return'] for cg in op.records['changegroup']]
1069 pullop.cgresult = changegroup.combineresults(results)
1069 pullop.cgresult = changegroup.combineresults(results)
1070
1070
1071 # processing phases change
1071 # processing phases change
1072 for namespace, value in op.records['listkeys']:
1072 for namespace, value in op.records['listkeys']:
1073 if namespace == 'phases':
1073 if namespace == 'phases':
1074 _pullapplyphases(pullop, value)
1074 _pullapplyphases(pullop, value)
1075
1075
1076 # processing bookmark update
1076 # processing bookmark update
1077 for namespace, value in op.records['listkeys']:
1077 for namespace, value in op.records['listkeys']:
1078 if namespace == 'bookmarks':
1078 if namespace == 'bookmarks':
1079 pullop.remotebookmarks = value
1079 pullop.remotebookmarks = value
1080
1080
1081 # bookmark data were either already there or pulled in the bundle
1081 # bookmark data were either already there or pulled in the bundle
1082 if pullop.remotebookmarks is not None:
1082 if pullop.remotebookmarks is not None:
1083 _pullbookmarks(pullop)
1083 _pullbookmarks(pullop)
1084
1084
1085 def _pullbundle2extraprepare(pullop, kwargs):
1085 def _pullbundle2extraprepare(pullop, kwargs):
1086 """hook function so that extensions can extend the getbundle call"""
1086 """hook function so that extensions can extend the getbundle call"""
1087 pass
1087 pass
1088
1088
1089 def _pullchangeset(pullop):
1089 def _pullchangeset(pullop):
1090 """pull changeset from unbundle into the local repo"""
1090 """pull changeset from unbundle into the local repo"""
1091 # 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
1092 # don't open transaction for nothing or you break future useful
1092 # don't open transaction for nothing or you break future useful
1093 # rollback call
1093 # rollback call
1094 if 'changegroup' in pullop.stepsdone:
1094 if 'changegroup' in pullop.stepsdone:
1095 return
1095 return
1096 pullop.stepsdone.add('changegroup')
1096 pullop.stepsdone.add('changegroup')
1097 if not pullop.fetch:
1097 if not pullop.fetch:
1098 pullop.repo.ui.status(_("no changes found\n"))
1098 pullop.repo.ui.status(_("no changes found\n"))
1099 pullop.cgresult = 0
1099 pullop.cgresult = 0
1100 return
1100 return
1101 pullop.gettransaction()
1101 pullop.gettransaction()
1102 if pullop.heads is None and list(pullop.common) == [nullid]:
1102 if pullop.heads is None and list(pullop.common) == [nullid]:
1103 pullop.repo.ui.status(_("requesting all changes\n"))
1103 pullop.repo.ui.status(_("requesting all changes\n"))
1104 elif pullop.heads is None and pullop.remote.capable('changegroupsubset'):
1104 elif pullop.heads is None and pullop.remote.capable('changegroupsubset'):
1105 # issue1320, avoid a race if remote changed after discovery
1105 # issue1320, avoid a race if remote changed after discovery
1106 pullop.heads = pullop.rheads
1106 pullop.heads = pullop.rheads
1107
1107
1108 if pullop.remote.capable('getbundle'):
1108 if pullop.remote.capable('getbundle'):
1109 # TODO: get bundlecaps from remote
1109 # TODO: get bundlecaps from remote
1110 cg = pullop.remote.getbundle('pull', common=pullop.common,
1110 cg = pullop.remote.getbundle('pull', common=pullop.common,
1111 heads=pullop.heads or pullop.rheads)
1111 heads=pullop.heads or pullop.rheads)
1112 elif pullop.heads is None:
1112 elif pullop.heads is None:
1113 cg = pullop.remote.changegroup(pullop.fetch, 'pull')
1113 cg = pullop.remote.changegroup(pullop.fetch, 'pull')
1114 elif not pullop.remote.capable('changegroupsubset'):
1114 elif not pullop.remote.capable('changegroupsubset'):
1115 raise util.Abort(_("partial pull cannot be done because "
1115 raise util.Abort(_("partial pull cannot be done because "
1116 "other repository doesn't support "
1116 "other repository doesn't support "
1117 "changegroupsubset."))
1117 "changegroupsubset."))
1118 else:
1118 else:
1119 cg = pullop.remote.changegroupsubset(pullop.fetch, pullop.heads, 'pull')
1119 cg = pullop.remote.changegroupsubset(pullop.fetch, pullop.heads, 'pull')
1120 pullop.cgresult = changegroup.addchangegroup(pullop.repo, cg, 'pull',
1120 pullop.cgresult = changegroup.addchangegroup(pullop.repo, cg, 'pull',
1121 pullop.remote.url())
1121 pullop.remote.url())
1122
1122
1123 def _pullphase(pullop):
1123 def _pullphase(pullop):
1124 # Get remote phases data from remote
1124 # Get remote phases data from remote
1125 if 'phases' in pullop.stepsdone:
1125 if 'phases' in pullop.stepsdone:
1126 return
1126 return
1127 remotephases = pullop.remote.listkeys('phases')
1127 remotephases = pullop.remote.listkeys('phases')
1128 _pullapplyphases(pullop, remotephases)
1128 _pullapplyphases(pullop, remotephases)
1129
1129
1130 def _pullapplyphases(pullop, remotephases):
1130 def _pullapplyphases(pullop, remotephases):
1131 """apply phase movement from observed remote state"""
1131 """apply phase movement from observed remote state"""
1132 if 'phases' in pullop.stepsdone:
1132 if 'phases' in pullop.stepsdone:
1133 return
1133 return
1134 pullop.stepsdone.add('phases')
1134 pullop.stepsdone.add('phases')
1135 publishing = bool(remotephases.get('publishing', False))
1135 publishing = bool(remotephases.get('publishing', False))
1136 if remotephases and not publishing:
1136 if remotephases and not publishing:
1137 # remote is new and unpublishing
1137 # remote is new and unpublishing
1138 pheads, _dr = phases.analyzeremotephases(pullop.repo,
1138 pheads, _dr = phases.analyzeremotephases(pullop.repo,
1139 pullop.pulledsubset,
1139 pullop.pulledsubset,
1140 remotephases)
1140 remotephases)
1141 dheads = pullop.pulledsubset
1141 dheads = pullop.pulledsubset
1142 else:
1142 else:
1143 # Remote is old or publishing all common changesets
1143 # Remote is old or publishing all common changesets
1144 # should be seen as public
1144 # should be seen as public
1145 pheads = pullop.pulledsubset
1145 pheads = pullop.pulledsubset
1146 dheads = []
1146 dheads = []
1147 unfi = pullop.repo.unfiltered()
1147 unfi = pullop.repo.unfiltered()
1148 phase = unfi._phasecache.phase
1148 phase = unfi._phasecache.phase
1149 rev = unfi.changelog.nodemap.get
1149 rev = unfi.changelog.nodemap.get
1150 public = phases.public
1150 public = phases.public
1151 draft = phases.draft
1151 draft = phases.draft
1152
1152
1153 # exclude changesets already public locally and update the others
1153 # exclude changesets already public locally and update the others
1154 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]
1155 if pheads:
1155 if pheads:
1156 tr = pullop.gettransaction()
1156 tr = pullop.gettransaction()
1157 phases.advanceboundary(pullop.repo, tr, public, pheads)
1157 phases.advanceboundary(pullop.repo, tr, public, pheads)
1158
1158
1159 # exclude changesets already draft locally and update the others
1159 # exclude changesets already draft locally and update the others
1160 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]
1161 if dheads:
1161 if dheads:
1162 tr = pullop.gettransaction()
1162 tr = pullop.gettransaction()
1163 phases.advanceboundary(pullop.repo, tr, draft, dheads)
1163 phases.advanceboundary(pullop.repo, tr, draft, dheads)
1164
1164
1165 def _pullbookmarks(pullop):
1165 def _pullbookmarks(pullop):
1166 """process the remote bookmark information to update the local one"""
1166 """process the remote bookmark information to update the local one"""
1167 if 'bookmarks' in pullop.stepsdone:
1167 if 'bookmarks' in pullop.stepsdone:
1168 return
1168 return
1169 pullop.stepsdone.add('bookmarks')
1169 pullop.stepsdone.add('bookmarks')
1170 repo = pullop.repo
1170 repo = pullop.repo
1171 remotebookmarks = pullop.remotebookmarks
1171 remotebookmarks = pullop.remotebookmarks
1172 bookmod.updatefromremote(repo.ui, repo, remotebookmarks,
1172 bookmod.updatefromremote(repo.ui, repo, remotebookmarks,
1173 pullop.remote.url(),
1173 pullop.remote.url(),
1174 pullop.gettransaction,
1174 pullop.gettransaction,
1175 explicit=pullop.explicitbookmarks)
1175 explicit=pullop.explicitbookmarks)
1176
1176
1177 def _pullobsolete(pullop):
1177 def _pullobsolete(pullop):
1178 """utility function to pull obsolete markers from a remote
1178 """utility function to pull obsolete markers from a remote
1179
1179
1180 The `gettransaction` is function that return the pull transaction, creating
1180 The `gettransaction` is function that return the pull transaction, creating
1181 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
1182 a new transaction have been created (when applicable).
1182 a new transaction have been created (when applicable).
1183
1183
1184 Exists mostly to allow overriding for experimentation purpose"""
1184 Exists mostly to allow overriding for experimentation purpose"""
1185 if 'obsmarkers' in pullop.stepsdone:
1185 if 'obsmarkers' in pullop.stepsdone:
1186 return
1186 return
1187 pullop.stepsdone.add('obsmarkers')
1187 pullop.stepsdone.add('obsmarkers')
1188 tr = None
1188 tr = None
1189 if obsolete.isenabled(pullop.repo, obsolete.exchangeopt):
1189 if obsolete.isenabled(pullop.repo, obsolete.exchangeopt):
1190 pullop.repo.ui.debug('fetching remote obsolete markers\n')
1190 pullop.repo.ui.debug('fetching remote obsolete markers\n')
1191 remoteobs = pullop.remote.listkeys('obsolete')
1191 remoteobs = pullop.remote.listkeys('obsolete')
1192 if 'dump0' in remoteobs:
1192 if 'dump0' in remoteobs:
1193 tr = pullop.gettransaction()
1193 tr = pullop.gettransaction()
1194 for key in sorted(remoteobs, reverse=True):
1194 for key in sorted(remoteobs, reverse=True):
1195 if key.startswith('dump'):
1195 if key.startswith('dump'):
1196 data = base85.b85decode(remoteobs[key])
1196 data = base85.b85decode(remoteobs[key])
1197 pullop.repo.obsstore.mergemarkers(tr, data)
1197 pullop.repo.obsstore.mergemarkers(tr, data)
1198 pullop.repo.invalidatevolatilesets()
1198 pullop.repo.invalidatevolatilesets()
1199 return tr
1199 return tr
1200
1200
1201 def caps20to10(repo):
1201 def caps20to10(repo):
1202 """return a set with appropriate options to use bundle20 during getbundle"""
1202 """return a set with appropriate options to use bundle20 during getbundle"""
1203 caps = set(['HG20'])
1203 caps = set(['HG20'])
1204 capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo))
1204 capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo))
1205 caps.add('bundle2=' + urllib.quote(capsblob))
1205 caps.add('bundle2=' + urllib.quote(capsblob))
1206 return caps
1206 return caps
1207
1207
1208 # 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.
1209 getbundle2partsorder = []
1209 getbundle2partsorder = []
1210
1210
1211 # Mapping between step name and function
1211 # Mapping between step name and function
1212 #
1212 #
1213 # This exists to help extensions wrap steps if necessary
1213 # This exists to help extensions wrap steps if necessary
1214 getbundle2partsmapping = {}
1214 getbundle2partsmapping = {}
1215
1215
1216 def getbundle2partsgenerator(stepname, idx=None):
1216 def getbundle2partsgenerator(stepname, idx=None):
1217 """decorator for function generating bundle2 part for getbundle
1217 """decorator for function generating bundle2 part for getbundle
1218
1218
1219 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
1220 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
1221 (this may matter).
1221 (this may matter).
1222
1222
1223 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
1224 from an extension, attack the getbundle2partsmapping dictionary directly."""
1224 from an extension, attack the getbundle2partsmapping dictionary directly."""
1225 def dec(func):
1225 def dec(func):
1226 assert stepname not in getbundle2partsmapping
1226 assert stepname not in getbundle2partsmapping
1227 getbundle2partsmapping[stepname] = func
1227 getbundle2partsmapping[stepname] = func
1228 if idx is None:
1228 if idx is None:
1229 getbundle2partsorder.append(stepname)
1229 getbundle2partsorder.append(stepname)
1230 else:
1230 else:
1231 getbundle2partsorder.insert(idx, stepname)
1231 getbundle2partsorder.insert(idx, stepname)
1232 return func
1232 return func
1233 return dec
1233 return dec
1234
1234
1235 def getbundle(repo, source, heads=None, common=None, bundlecaps=None,
1235 def getbundle(repo, source, heads=None, common=None, bundlecaps=None,
1236 **kwargs):
1236 **kwargs):
1237 """return a full bundle (with potentially multiple kind of parts)
1237 """return a full bundle (with potentially multiple kind of parts)
1238
1238
1239 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
1240 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
1241 changes when more part type will be available for bundle2.
1241 changes when more part type will be available for bundle2.
1242
1242
1243 This is different from changegroup.getchangegroup that only returns an HG10
1243 This is different from changegroup.getchangegroup that only returns an HG10
1244 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
1245 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.
1246
1246
1247 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
1248 when the API of bundle is refined.
1248 when the API of bundle is refined.
1249 """
1249 """
1250 # bundle10 case
1250 # bundle10 case
1251 usebundle2 = False
1251 usebundle2 = False
1252 if bundlecaps is not None:
1252 if bundlecaps is not None:
1253 usebundle2 = any((cap.startswith('HG2') for cap in bundlecaps))
1253 usebundle2 = any((cap.startswith('HG2') for cap in bundlecaps))
1254 if not usebundle2:
1254 if not usebundle2:
1255 if bundlecaps and not kwargs.get('cg', True):
1255 if bundlecaps and not kwargs.get('cg', True):
1256 raise ValueError(_('request for bundle10 must include changegroup'))
1256 raise ValueError(_('request for bundle10 must include changegroup'))
1257
1257
1258 if kwargs:
1258 if kwargs:
1259 raise ValueError(_('unsupported getbundle arguments: %s')
1259 raise ValueError(_('unsupported getbundle arguments: %s')
1260 % ', '.join(sorted(kwargs.keys())))
1260 % ', '.join(sorted(kwargs.keys())))
1261 return changegroup.getchangegroup(repo, source, heads=heads,
1261 return changegroup.getchangegroup(repo, source, heads=heads,
1262 common=common, bundlecaps=bundlecaps)
1262 common=common, bundlecaps=bundlecaps)
1263
1263
1264 # bundle20 case
1264 # bundle20 case
1265 b2caps = {}
1265 b2caps = {}
1266 for bcaps in bundlecaps:
1266 for bcaps in bundlecaps:
1267 if bcaps.startswith('bundle2='):
1267 if bcaps.startswith('bundle2='):
1268 blob = urllib.unquote(bcaps[len('bundle2='):])
1268 blob = urllib.unquote(bcaps[len('bundle2='):])
1269 b2caps.update(bundle2.decodecaps(blob))
1269 b2caps.update(bundle2.decodecaps(blob))
1270 bundler = bundle2.bundle20(repo.ui, b2caps)
1270 bundler = bundle2.bundle20(repo.ui, b2caps)
1271
1271
1272 kwargs['heads'] = heads
1272 kwargs['heads'] = heads
1273 kwargs['common'] = common
1273 kwargs['common'] = common
1274
1274
1275 for name in getbundle2partsorder:
1275 for name in getbundle2partsorder:
1276 func = getbundle2partsmapping[name]
1276 func = getbundle2partsmapping[name]
1277 func(bundler, repo, source, bundlecaps=bundlecaps, b2caps=b2caps,
1277 func(bundler, repo, source, bundlecaps=bundlecaps, b2caps=b2caps,
1278 **kwargs)
1278 **kwargs)
1279
1279
1280 return util.chunkbuffer(bundler.getchunks())
1280 return util.chunkbuffer(bundler.getchunks())
1281
1281
1282 @getbundle2partsgenerator('changegroup')
1282 @getbundle2partsgenerator('changegroup')
1283 def _getbundlechangegrouppart(bundler, repo, source, bundlecaps=None,
1283 def _getbundlechangegrouppart(bundler, repo, source, bundlecaps=None,
1284 b2caps=None, heads=None, common=None, **kwargs):
1284 b2caps=None, heads=None, common=None, **kwargs):
1285 """add a changegroup part to the requested bundle"""
1285 """add a changegroup part to the requested bundle"""
1286 cg = None
1286 cg = None
1287 if kwargs.get('cg', True):
1287 if kwargs.get('cg', True):
1288 # build changegroup bundle here.
1288 # build changegroup bundle here.
1289 version = None
1289 version = None
1290 cgversions = b2caps.get('changegroup')
1290 cgversions = b2caps.get('changegroup')
1291 getcgkwargs = {}
1291 getcgkwargs = {}
1292 if cgversions: # 3.1 and 3.2 ship with an empty value
1292 if cgversions: # 3.1 and 3.2 ship with an empty value
1293 cgversions = [v for v in cgversions if v in changegroup.packermap]
1293 cgversions = [v for v in cgversions if v in changegroup.packermap]
1294 if not cgversions:
1294 if not cgversions:
1295 raise ValueError(_('no common changegroup version'))
1295 raise ValueError(_('no common changegroup version'))
1296 version = getcgkwargs['version'] = max(cgversions)
1296 version = getcgkwargs['version'] = max(cgversions)
1297 outgoing = changegroup.computeoutgoing(repo, heads, common)
1297 outgoing = changegroup.computeoutgoing(repo, heads, common)
1298 cg = changegroup.getlocalchangegroupraw(repo, source, outgoing,
1298 cg = changegroup.getlocalchangegroupraw(repo, source, outgoing,
1299 bundlecaps=bundlecaps,
1299 bundlecaps=bundlecaps,
1300 **getcgkwargs)
1300 **getcgkwargs)
1301
1301
1302 if cg:
1302 if cg:
1303 part = bundler.newpart('changegroup', data=cg)
1303 part = bundler.newpart('changegroup', data=cg)
1304 if version is not None:
1304 if version is not None:
1305 part.addparam('version', version)
1305 part.addparam('version', version)
1306 part.addparam('nbchanges', str(len(outgoing.missing)), mandatory=False)
1306 part.addparam('nbchanges', str(len(outgoing.missing)), mandatory=False)
1307
1307
1308 @getbundle2partsgenerator('listkeys')
1308 @getbundle2partsgenerator('listkeys')
1309 def _getbundlelistkeysparts(bundler, repo, source, bundlecaps=None,
1309 def _getbundlelistkeysparts(bundler, repo, source, bundlecaps=None,
1310 b2caps=None, **kwargs):
1310 b2caps=None, **kwargs):
1311 """add parts containing listkeys namespaces to the requested bundle"""
1311 """add parts containing listkeys namespaces to the requested bundle"""
1312 listkeys = kwargs.get('listkeys', ())
1312 listkeys = kwargs.get('listkeys', ())
1313 for namespace in listkeys:
1313 for namespace in listkeys:
1314 part = bundler.newpart('listkeys')
1314 part = bundler.newpart('listkeys')
1315 part.addparam('namespace', namespace)
1315 part.addparam('namespace', namespace)
1316 keys = repo.listkeys(namespace).items()
1316 keys = repo.listkeys(namespace).items()
1317 part.data = pushkey.encodekeys(keys)
1317 part.data = pushkey.encodekeys(keys)
1318
1318
1319 @getbundle2partsgenerator('obsmarkers')
1319 @getbundle2partsgenerator('obsmarkers')
1320 def _getbundleobsmarkerpart(bundler, repo, source, bundlecaps=None,
1320 def _getbundleobsmarkerpart(bundler, repo, source, bundlecaps=None,
1321 b2caps=None, heads=None, **kwargs):
1321 b2caps=None, heads=None, **kwargs):
1322 """add an obsolescence markers part to the requested bundle"""
1322 """add an obsolescence markers part to the requested bundle"""
1323 if kwargs.get('obsmarkers', False):
1323 if kwargs.get('obsmarkers', False):
1324 if heads is None:
1324 if heads is None:
1325 heads = repo.heads()
1325 heads = repo.heads()
1326 subset = [c.node() for c in repo.set('::%ln', heads)]
1326 subset = [c.node() for c in repo.set('::%ln', heads)]
1327 markers = repo.obsstore.relevantmarkers(subset)
1327 markers = repo.obsstore.relevantmarkers(subset)
1328 markers = sorted(markers)
1328 markers = sorted(markers)
1329 buildobsmarkerspart(bundler, markers)
1329 buildobsmarkerspart(bundler, markers)
1330
1330
1331 @getbundle2partsgenerator('hgtagsfnodes')
1331 @getbundle2partsgenerator('hgtagsfnodes')
1332 def _getbundletagsfnodes(bundler, repo, source, bundlecaps=None,
1332 def _getbundletagsfnodes(bundler, repo, source, bundlecaps=None,
1333 b2caps=None, heads=None, common=None,
1333 b2caps=None, heads=None, common=None,
1334 **kwargs):
1334 **kwargs):
1335 """Transfer the .hgtags filenodes mapping.
1335 """Transfer the .hgtags filenodes mapping.
1336
1336
1337 Only values for heads in this bundle will be transferred.
1337 Only values for heads in this bundle will be transferred.
1338
1338
1339 The part data consists of pairs of 20 byte changeset node and .hgtags
1339 The part data consists of pairs of 20 byte changeset node and .hgtags
1340 filenodes raw values.
1340 filenodes raw values.
1341 """
1341 """
1342 # Don't send unless:
1342 # Don't send unless:
1343 # - changeset are being exchanged,
1343 # - changeset are being exchanged,
1344 # - the client supports it.
1344 # - the client supports it.
1345 if not (kwargs.get('cg', True) and 'hgtagsfnodes' in b2caps):
1345 if not (kwargs.get('cg', True) and 'hgtagsfnodes' in b2caps):
1346 return
1346 return
1347
1347
1348 outgoing = changegroup.computeoutgoing(repo, heads, common)
1348 outgoing = changegroup.computeoutgoing(repo, heads, common)
1349
1349
1350 if not outgoing.missingheads:
1350 if not outgoing.missingheads:
1351 return
1351 return
1352
1352
1353 cache = tags.hgtagsfnodescache(repo.unfiltered())
1353 cache = tags.hgtagsfnodescache(repo.unfiltered())
1354 chunks = []
1354 chunks = []
1355
1355
1356 # .hgtags fnodes are only relevant for head changesets. While we could
1356 # .hgtags fnodes are only relevant for head changesets. While we could
1357 # transfer values for all known nodes, there will likely be little to
1357 # transfer values for all known nodes, there will likely be little to
1358 # no benefit.
1358 # no benefit.
1359 #
1359 #
1360 # We don't bother using a generator to produce output data because
1360 # We don't bother using a generator to produce output data because
1361 # a) we only have 40 bytes per head and even esoteric numbers of heads
1361 # a) we only have 40 bytes per head and even esoteric numbers of heads
1362 # consume little memory (1M heads is 40MB) b) we don't want to send the
1362 # consume little memory (1M heads is 40MB) b) we don't want to send the
1363 # part if we don't have entries and knowing if we have entries requires
1363 # part if we don't have entries and knowing if we have entries requires
1364 # cache lookups.
1364 # cache lookups.
1365 for node in outgoing.missingheads:
1365 for node in outgoing.missingheads:
1366 # Don't compute missing, as this may slow down serving.
1366 # Don't compute missing, as this may slow down serving.
1367 fnode = cache.getfnode(node, computemissing=False)
1367 fnode = cache.getfnode(node, computemissing=False)
1368 if fnode is not None:
1368 if fnode is not None:
1369 chunks.extend([node, fnode])
1369 chunks.extend([node, fnode])
1370
1370
1371 if chunks:
1371 if chunks:
1372 bundler.newpart('hgtagsfnodes', data=''.join(chunks))
1372 bundler.newpart('hgtagsfnodes', data=''.join(chunks))
1373
1373
1374 def check_heads(repo, their_heads, context):
1374 def check_heads(repo, their_heads, context):
1375 """check if the heads of a repo have been modified
1375 """check if the heads of a repo have been modified
1376
1376
1377 Used by peer for unbundling.
1377 Used by peer for unbundling.
1378 """
1378 """
1379 heads = repo.heads()
1379 heads = repo.heads()
1380 heads_hash = util.sha1(''.join(sorted(heads))).digest()
1380 heads_hash = util.sha1(''.join(sorted(heads))).digest()
1381 if not (their_heads == ['force'] or their_heads == heads or
1381 if not (their_heads == ['force'] or their_heads == heads or
1382 their_heads == ['hashed', heads_hash]):
1382 their_heads == ['hashed', heads_hash]):
1383 # someone else committed/pushed/unbundled while we
1383 # someone else committed/pushed/unbundled while we
1384 # were transferring data
1384 # were transferring data
1385 raise error.PushRaced('repository changed while %s - '
1385 raise error.PushRaced('repository changed while %s - '
1386 'please try again' % context)
1386 'please try again' % context)
1387
1387
1388 def unbundle(repo, cg, heads, source, url):
1388 def unbundle(repo, cg, heads, source, url):
1389 """Apply a bundle to a repo.
1389 """Apply a bundle to a repo.
1390
1390
1391 this function makes sure the repo is locked during the application and have
1391 this function makes sure the repo is locked during the application and have
1392 mechanism to check that no push race occurred between the creation of the
1392 mechanism to check that no push race occurred between the creation of the
1393 bundle and its application.
1393 bundle and its application.
1394
1394
1395 If the push was raced as PushRaced exception is raised."""
1395 If the push was raced as PushRaced exception is raised."""
1396 r = 0
1396 r = 0
1397 # need a transaction when processing a bundle2 stream
1397 # need a transaction when processing a bundle2 stream
1398 wlock = lock = tr = None
1398 wlock = lock = tr = None
1399 recordout = None
1399 recordout = None
1400 # quick fix for output mismatch with bundle2 in 3.4
1400 # quick fix for output mismatch with bundle2 in 3.4
1401 captureoutput = repo.ui.configbool('experimental', 'bundle2-output-capture',
1401 captureoutput = repo.ui.configbool('experimental', 'bundle2-output-capture',
1402 False)
1402 False)
1403 if url.startswith('remote:http:') or url.startswith('remote:https:'):
1403 if url.startswith('remote:http:') or url.startswith('remote:https:'):
1404 captureoutput = True
1404 captureoutput = True
1405 try:
1405 try:
1406 check_heads(repo, heads, 'uploading changes')
1406 check_heads(repo, heads, 'uploading changes')
1407 # push can proceed
1407 # push can proceed
1408 if util.safehasattr(cg, 'params'):
1408 if util.safehasattr(cg, 'params'):
1409 r = None
1409 r = None
1410 try:
1410 try:
1411 wlock = repo.wlock()
1411 wlock = repo.wlock()
1412 lock = repo.lock()
1412 lock = repo.lock()
1413 tr = repo.transaction(source)
1413 tr = repo.transaction(source)
1414 tr.hookargs['source'] = source
1414 tr.hookargs['source'] = source
1415 tr.hookargs['url'] = url
1415 tr.hookargs['url'] = url
1416 tr.hookargs['bundle2'] = '1'
1416 tr.hookargs['bundle2'] = '1'
1417 op = bundle2.bundleoperation(repo, lambda: tr,
1417 op = bundle2.bundleoperation(repo, lambda: tr,
1418 captureoutput=captureoutput)
1418 captureoutput=captureoutput)
1419 try:
1419 try:
1420 r = bundle2.processbundle(repo, cg, op=op)
1420 r = bundle2.processbundle(repo, cg, op=op)
1421 finally:
1421 finally:
1422 r = op.reply
1422 r = op.reply
1423 if captureoutput and r is not None:
1423 if captureoutput and r is not None:
1424 repo.ui.pushbuffer(error=True, subproc=True)
1424 repo.ui.pushbuffer(error=True, subproc=True)
1425 def recordout(output):
1425 def recordout(output):
1426 r.newpart('output', data=output, mandatory=False)
1426 r.newpart('output', data=output, mandatory=False)
1427 tr.close()
1427 tr.close()
1428 except BaseException, exc:
1428 except BaseException, exc:
1429 exc.duringunbundle2 = True
1429 exc.duringunbundle2 = True
1430 if captureoutput and r is not None:
1430 if captureoutput and r is not None:
1431 parts = exc._bundle2salvagedoutput = r.salvageoutput()
1431 parts = exc._bundle2salvagedoutput = r.salvageoutput()
1432 def recordout(output):
1432 def recordout(output):
1433 part = bundle2.bundlepart('output', data=output,
1433 part = bundle2.bundlepart('output', data=output,
1434 mandatory=False)
1434 mandatory=False)
1435 parts.append(part)
1435 parts.append(part)
1436 raise
1436 raise
1437 else:
1437 else:
1438 lock = repo.lock()
1438 lock = repo.lock()
1439 r = changegroup.addchangegroup(repo, cg, source, url)
1439 r = changegroup.addchangegroup(repo, cg, source, url)
1440 finally:
1440 finally:
1441 lockmod.release(tr, lock, wlock)
1441 lockmod.release(tr, lock, wlock)
1442 if recordout is not None:
1442 if recordout is not None:
1443 recordout(repo.ui.popbuffer())
1443 recordout(repo.ui.popbuffer())
1444 return r
1444 return r
1445
1445
1446 # This is it's own function so extensions can override it.
1446 # This is it's own function so extensions can override it.
1447 def _walkstreamfiles(repo):
1447 def _walkstreamfiles(repo):
1448 return repo.store.walk()
1448 return repo.store.walk()
1449
1449
1450 def generatestreamclone(repo):
1450 def generatestreamclone(repo):
1451 """Emit content for a streaming clone.
1451 """Emit content for a streaming clone.
1452
1452
1453 This is a generator of raw chunks that constitute a streaming clone.
1453 This is a generator of raw chunks that constitute a streaming clone.
1454
1454
1455 The stream begins with a line of 2 space-delimited integers containing the
1455 The stream begins with a line of 2 space-delimited integers containing the
1456 number of entries and total bytes size.
1456 number of entries and total bytes size.
1457
1457
1458 Next, are N entries for each file being transferred. Each file entry starts
1458 Next, are N entries for each file being transferred. Each file entry starts
1459 as a line with the file name and integer size delimited by a null byte.
1459 as a line with the file name and integer size delimited by a null byte.
1460 The raw file data follows. Following the raw file data is the next file
1460 The raw file data follows. Following the raw file data is the next file
1461 entry, or EOF.
1461 entry, or EOF.
1462
1462
1463 When used on the wire protocol, an additional line indicating protocol
1463 When used on the wire protocol, an additional line indicating protocol
1464 success will be prepended to the stream. This function is not responsible
1464 success will be prepended to the stream. This function is not responsible
1465 for adding it.
1465 for adding it.
1466
1466
1467 This function will obtain a repository lock to ensure a consistent view of
1467 This function will obtain a repository lock to ensure a consistent view of
1468 the store is captured. It therefore may raise LockError.
1468 the store is captured. It therefore may raise LockError.
1469 """
1469 """
1470 entries = []
1470 entries = []
1471 total_bytes = 0
1471 total_bytes = 0
1472 # Get consistent snapshot of repo, lock during scan.
1472 # Get consistent snapshot of repo, lock during scan.
1473 lock = repo.lock()
1473 lock = repo.lock()
1474 try:
1474 try:
1475 repo.ui.debug('scanning\n')
1475 repo.ui.debug('scanning\n')
1476 for name, ename, size in _walkstreamfiles(repo):
1476 for name, ename, size in _walkstreamfiles(repo):
1477 if size:
1477 if size:
1478 entries.append((name, size))
1478 entries.append((name, size))
1479 total_bytes += size
1479 total_bytes += size
1480 finally:
1480 finally:
1481 lock.release()
1481 lock.release()
1482
1482
1483 repo.ui.debug('%d files, %d bytes to transfer\n' %
1483 repo.ui.debug('%d files, %d bytes to transfer\n' %
1484 (len(entries), total_bytes))
1484 (len(entries), total_bytes))
1485 yield '%d %d\n' % (len(entries), total_bytes)
1485 yield '%d %d\n' % (len(entries), total_bytes)
1486
1486
1487 sopener = repo.svfs
1487 sopener = repo.svfs
1488 oldaudit = sopener.mustaudit
1488 oldaudit = sopener.mustaudit
1489 debugflag = repo.ui.debugflag
1489 debugflag = repo.ui.debugflag
1490 sopener.mustaudit = False
1490 sopener.mustaudit = False
1491
1491
1492 try:
1492 try:
1493 for name, size in entries:
1493 for name, size in entries:
1494 if debugflag:
1494 if debugflag:
1495 repo.ui.debug('sending %s (%d bytes)\n' % (name, size))
1495 repo.ui.debug('sending %s (%d bytes)\n' % (name, size))
1496 # partially encode name over the wire for backwards compat
1496 # partially encode name over the wire for backwards compat
1497 yield '%s\0%d\n' % (store.encodedir(name), size)
1497 yield '%s\0%d\n' % (store.encodedir(name), size)
1498 if size <= 65536:
1498 if size <= 65536:
1499 fp = sopener(name)
1499 fp = sopener(name)
1500 try:
1500 try:
1501 data = fp.read(size)
1501 data = fp.read(size)
1502 finally:
1502 finally:
1503 fp.close()
1503 fp.close()
1504 yield data
1504 yield data
1505 else:
1505 else:
1506 for chunk in util.filechunkiter(sopener(name), limit=size):
1506 for chunk in util.filechunkiter(sopener(name), limit=size):
1507 yield chunk
1507 yield chunk
1508 finally:
1508 finally:
1509 sopener.mustaudit = oldaudit
1509 sopener.mustaudit = oldaudit
1510
1510
1511 def consumestreamclone(repo, fp):
1511 def consumestreamclone(repo, fp):
1512 """Apply the contents from a streaming clone file.
1512 """Apply the contents from a streaming clone file.
1513
1513
1514 This takes the output from "streamout" and applies it to the specified
1514 This takes the output from "streamout" and applies it to the specified
1515 repository.
1515 repository.
1516
1516
1517 Like "streamout," the status line added by the wire protocol is not handled
1517 Like "streamout," the status line added by the wire protocol is not handled
1518 by this function.
1518 by this function.
1519 """
1519 """
1520 lock = repo.lock()
1520 lock = repo.lock()
1521 try:
1521 try:
1522 repo.ui.status(_('streaming all changes\n'))
1522 repo.ui.status(_('streaming all changes\n'))
1523 l = fp.readline()
1523 l = fp.readline()
1524 try:
1524 try:
1525 total_files, total_bytes = map(int, l.split(' ', 1))
1525 total_files, total_bytes = map(int, l.split(' ', 1))
1526 except (ValueError, TypeError):
1526 except (ValueError, TypeError):
1527 raise error.ResponseError(
1527 raise error.ResponseError(
1528 _('unexpected response from remote server:'), l)
1528 _('unexpected response from remote server:'), l)
1529 repo.ui.status(_('%d files to transfer, %s of data\n') %
1529 repo.ui.status(_('%d files to transfer, %s of data\n') %
1530 (total_files, util.bytecount(total_bytes)))
1530 (total_files, util.bytecount(total_bytes)))
1531 handled_bytes = 0
1531 handled_bytes = 0
1532 repo.ui.progress(_('clone'), 0, total=total_bytes)
1532 repo.ui.progress(_('clone'), 0, total=total_bytes)
1533 start = time.time()
1533 start = time.time()
1534
1534
1535 tr = repo.transaction(_('clone'))
1535 tr = repo.transaction(_('clone'))
1536 try:
1536 try:
1537 for i in xrange(total_files):
1537 for i in xrange(total_files):
1538 # XXX doesn't support '\n' or '\r' in filenames
1538 # XXX doesn't support '\n' or '\r' in filenames
1539 l = fp.readline()
1539 l = fp.readline()
1540 try:
1540 try:
1541 name, size = l.split('\0', 1)
1541 name, size = l.split('\0', 1)
1542 size = int(size)
1542 size = int(size)
1543 except (ValueError, TypeError):
1543 except (ValueError, TypeError):
1544 raise error.ResponseError(
1544 raise error.ResponseError(
1545 _('unexpected response from remote server:'), l)
1545 _('unexpected response from remote server:'), l)
1546 if repo.ui.debugflag:
1546 if repo.ui.debugflag:
1547 repo.ui.debug('adding %s (%s)\n' %
1547 repo.ui.debug('adding %s (%s)\n' %
1548 (name, util.bytecount(size)))
1548 (name, util.bytecount(size)))
1549 # for backwards compat, name was partially encoded
1549 # for backwards compat, name was partially encoded
1550 ofp = repo.svfs(store.decodedir(name), 'w')
1550 ofp = repo.svfs(store.decodedir(name), 'w')
1551 for chunk in util.filechunkiter(fp, limit=size):
1551 for chunk in util.filechunkiter(fp, limit=size):
1552 handled_bytes += len(chunk)
1552 handled_bytes += len(chunk)
1553 repo.ui.progress(_('clone'), handled_bytes,
1553 repo.ui.progress(_('clone'), handled_bytes,
1554 total=total_bytes)
1554 total=total_bytes)
1555 ofp.write(chunk)
1555 ofp.write(chunk)
1556 ofp.close()
1556 ofp.close()
1557 tr.close()
1557 tr.close()
1558 finally:
1558 finally:
1559 tr.release()
1559 tr.release()
1560
1560
1561 # Writing straight to files circumvented the inmemory caches
1561 # Writing straight to files circumvented the inmemory caches
1562 repo.invalidate()
1562 repo.invalidate()
1563
1563
1564 elapsed = time.time() - start
1564 elapsed = time.time() - start
1565 if elapsed <= 0:
1565 if elapsed <= 0:
1566 elapsed = 0.001
1566 elapsed = 0.001
1567 repo.ui.progress(_('clone'), None)
1567 repo.ui.progress(_('clone'), None)
1568 repo.ui.status(_('transferred %s in %.1f seconds (%s/sec)\n') %
1568 repo.ui.status(_('transferred %s in %.1f seconds (%s/sec)\n') %
1569 (util.bytecount(total_bytes), elapsed,
1569 (util.bytecount(total_bytes), elapsed,
1570 util.bytecount(total_bytes / elapsed)))
1570 util.bytecount(total_bytes / elapsed)))
1571 finally:
1571 finally:
1572 lock.release()
1572 lock.release()
@@ -1,2166 +1,2155
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" (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" (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
136 repository tip rolled back to revision 0 (undo push)
135 repository tip rolled back to revision 0 (undo push)
137 0:6675d58eff77
136 0:6675d58eff77
138
137
139
138
140 $ echo '[hooks]' >> $config
139 $ echo '[hooks]' >> $config
141 $ echo 'pretxnchangegroup.acl = python:hgext.acl.hook' >> $config
140 $ echo 'pretxnchangegroup.acl = python:hgext.acl.hook' >> $config
142
141
143 Extension disabled for lack of acl.sources
142 Extension disabled for lack of acl.sources
144
143
145 $ do_push fred
144 $ do_push fred
146 Pushing as user fred
145 Pushing as user fred
147 hgrc = """
146 hgrc = """
148 [hooks]
147 [hooks]
149 pretxnchangegroup.acl = python:hgext.acl.hook
148 pretxnchangegroup.acl = python:hgext.acl.hook
150 """
149 """
151 pushing to ../b
150 pushing to ../b
152 query 1; heads
151 query 1; heads
153 searching for changes
152 searching for changes
154 all remote heads known locally
153 all remote heads known locally
155 listing keys for "phases"
154 listing keys for "phases"
156 checking for updated bookmarks
155 checking for updated bookmarks
157 listing keys for "bookmarks"
156 listing keys for "bookmarks"
158 invalid branchheads cache (served): tip differs
157 invalid branchheads cache (served): tip differs
159 listing keys for "bookmarks"
158 listing keys for "bookmarks"
160 3 changesets found
159 3 changesets found
161 list of changesets:
160 list of changesets:
162 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
161 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
163 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
162 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
164 911600dab2ae7a9baff75958b84fe606851ce955
163 911600dab2ae7a9baff75958b84fe606851ce955
165 bundle2-output-bundle: "HG20", 4 parts total
164 bundle2-output-bundle: "HG20", 4 parts total
166 bundle2-output-part: "replycaps" 155 bytes payload
165 bundle2-output-part: "replycaps" 155 bytes payload
167 bundle2-output-part: "check:heads" streamed payload
166 bundle2-output-part: "check:heads" streamed payload
168 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
167 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
169 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
168 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
170 bundle2-input-bundle: with-transaction
169 bundle2-input-bundle: with-transaction
171 bundle2-input-part: "replycaps" supported
170 bundle2-input-part: "replycaps" supported
172 bundle2-input-part: total payload size 155
171 bundle2-input-part: total payload size 155
173 bundle2-input-part: "check:heads" supported
172 bundle2-input-part: "check:heads" supported
174 bundle2-input-part: total payload size 20
173 bundle2-input-part: total payload size 20
175 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
174 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
176 adding changesets
175 adding changesets
177 add changeset ef1ea85a6374
176 add changeset ef1ea85a6374
178 add changeset f9cafe1212c8
177 add changeset f9cafe1212c8
179 add changeset 911600dab2ae
178 add changeset 911600dab2ae
180 adding manifests
179 adding manifests
181 adding file changes
180 adding file changes
182 adding foo/Bar/file.txt revisions
181 adding foo/Bar/file.txt revisions
183 adding foo/file.txt revisions
182 adding foo/file.txt revisions
184 adding quux/file.py revisions
183 adding quux/file.py revisions
185 added 3 changesets with 3 changes to 3 files
184 added 3 changesets with 3 changes to 3 files
186 calling hook pretxnchangegroup.acl: hgext.acl.hook
185 calling hook pretxnchangegroup.acl: hgext.acl.hook
187 acl: changes have source "push" - skipping
186 acl: changes have source "push" - skipping
188 bundle2-input-part: total payload size 1606
187 bundle2-input-part: total payload size 1606
189 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
188 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
190 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
189 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
191 bundle2-input-bundle: 3 parts total
190 bundle2-input-bundle: 3 parts total
192 updating the branch cache
191 updating the branch cache
193 bundle2-output-bundle: "HG20", 2 parts total
192 bundle2-output-bundle: "HG20", 2 parts total
194 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
193 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
195 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
194 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
196 bundle2-input-bundle: with-transaction
195 bundle2-input-bundle: with-transaction
197 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
196 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
198 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
197 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
199 bundle2-input-bundle: 1 parts total
198 bundle2-input-bundle: 1 parts total
200 listing keys for "phases"
199 listing keys for "phases"
201 try to push obsolete markers to remote
202 repository tip rolled back to revision 0 (undo push)
200 repository tip rolled back to revision 0 (undo push)
203 0:6675d58eff77
201 0:6675d58eff77
204
202
205
203
206 No [acl.allow]/[acl.deny]
204 No [acl.allow]/[acl.deny]
207
205
208 $ echo '[acl]' >> $config
206 $ echo '[acl]' >> $config
209 $ echo 'sources = push' >> $config
207 $ echo 'sources = push' >> $config
210 $ do_push fred
208 $ do_push fred
211 Pushing as user fred
209 Pushing as user fred
212 hgrc = """
210 hgrc = """
213 [hooks]
211 [hooks]
214 pretxnchangegroup.acl = python:hgext.acl.hook
212 pretxnchangegroup.acl = python:hgext.acl.hook
215 [acl]
213 [acl]
216 sources = push
214 sources = push
217 """
215 """
218 pushing to ../b
216 pushing to ../b
219 query 1; heads
217 query 1; heads
220 searching for changes
218 searching for changes
221 all remote heads known locally
219 all remote heads known locally
222 listing keys for "phases"
220 listing keys for "phases"
223 checking for updated bookmarks
221 checking for updated bookmarks
224 listing keys for "bookmarks"
222 listing keys for "bookmarks"
225 invalid branchheads cache (served): tip differs
223 invalid branchheads cache (served): tip differs
226 listing keys for "bookmarks"
224 listing keys for "bookmarks"
227 3 changesets found
225 3 changesets found
228 list of changesets:
226 list of changesets:
229 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
227 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
230 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
228 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
231 911600dab2ae7a9baff75958b84fe606851ce955
229 911600dab2ae7a9baff75958b84fe606851ce955
232 bundle2-output-bundle: "HG20", 4 parts total
230 bundle2-output-bundle: "HG20", 4 parts total
233 bundle2-output-part: "replycaps" 155 bytes payload
231 bundle2-output-part: "replycaps" 155 bytes payload
234 bundle2-output-part: "check:heads" streamed payload
232 bundle2-output-part: "check:heads" streamed payload
235 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
233 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
236 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
234 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
237 bundle2-input-bundle: with-transaction
235 bundle2-input-bundle: with-transaction
238 bundle2-input-part: "replycaps" supported
236 bundle2-input-part: "replycaps" supported
239 bundle2-input-part: total payload size 155
237 bundle2-input-part: total payload size 155
240 bundle2-input-part: "check:heads" supported
238 bundle2-input-part: "check:heads" supported
241 bundle2-input-part: total payload size 20
239 bundle2-input-part: total payload size 20
242 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
240 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
243 adding changesets
241 adding changesets
244 add changeset ef1ea85a6374
242 add changeset ef1ea85a6374
245 add changeset f9cafe1212c8
243 add changeset f9cafe1212c8
246 add changeset 911600dab2ae
244 add changeset 911600dab2ae
247 adding manifests
245 adding manifests
248 adding file changes
246 adding file changes
249 adding foo/Bar/file.txt revisions
247 adding foo/Bar/file.txt revisions
250 adding foo/file.txt revisions
248 adding foo/file.txt revisions
251 adding quux/file.py revisions
249 adding quux/file.py revisions
252 added 3 changesets with 3 changes to 3 files
250 added 3 changesets with 3 changes to 3 files
253 calling hook pretxnchangegroup.acl: hgext.acl.hook
251 calling hook pretxnchangegroup.acl: hgext.acl.hook
254 acl: checking access for user "fred"
252 acl: checking access for user "fred"
255 acl: acl.allow.branches not enabled
253 acl: acl.allow.branches not enabled
256 acl: acl.deny.branches not enabled
254 acl: acl.deny.branches not enabled
257 acl: acl.allow not enabled
255 acl: acl.allow not enabled
258 acl: acl.deny not enabled
256 acl: acl.deny not enabled
259 acl: branch access granted: "ef1ea85a6374" on branch "default"
257 acl: branch access granted: "ef1ea85a6374" on branch "default"
260 acl: path access granted: "ef1ea85a6374"
258 acl: path access granted: "ef1ea85a6374"
261 acl: branch access granted: "f9cafe1212c8" on branch "default"
259 acl: branch access granted: "f9cafe1212c8" on branch "default"
262 acl: path access granted: "f9cafe1212c8"
260 acl: path access granted: "f9cafe1212c8"
263 acl: branch access granted: "911600dab2ae" on branch "default"
261 acl: branch access granted: "911600dab2ae" on branch "default"
264 acl: path access granted: "911600dab2ae"
262 acl: path access granted: "911600dab2ae"
265 bundle2-input-part: total payload size 1606
263 bundle2-input-part: total payload size 1606
266 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
264 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
267 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
265 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
268 bundle2-input-bundle: 3 parts total
266 bundle2-input-bundle: 3 parts total
269 updating the branch cache
267 updating the branch cache
270 bundle2-output-bundle: "HG20", 2 parts total
268 bundle2-output-bundle: "HG20", 2 parts total
271 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
269 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
272 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
270 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
273 bundle2-input-bundle: with-transaction
271 bundle2-input-bundle: with-transaction
274 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
272 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
275 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
273 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
276 bundle2-input-bundle: 1 parts total
274 bundle2-input-bundle: 1 parts total
277 listing keys for "phases"
275 listing keys for "phases"
278 try to push obsolete markers to remote
279 repository tip rolled back to revision 0 (undo push)
276 repository tip rolled back to revision 0 (undo push)
280 0:6675d58eff77
277 0:6675d58eff77
281
278
282
279
283 Empty [acl.allow]
280 Empty [acl.allow]
284
281
285 $ echo '[acl.allow]' >> $config
282 $ echo '[acl.allow]' >> $config
286 $ do_push fred
283 $ do_push fred
287 Pushing as user fred
284 Pushing as user fred
288 hgrc = """
285 hgrc = """
289 [hooks]
286 [hooks]
290 pretxnchangegroup.acl = python:hgext.acl.hook
287 pretxnchangegroup.acl = python:hgext.acl.hook
291 [acl]
288 [acl]
292 sources = push
289 sources = push
293 [acl.allow]
290 [acl.allow]
294 """
291 """
295 pushing to ../b
292 pushing to ../b
296 query 1; heads
293 query 1; heads
297 searching for changes
294 searching for changes
298 all remote heads known locally
295 all remote heads known locally
299 listing keys for "phases"
296 listing keys for "phases"
300 checking for updated bookmarks
297 checking for updated bookmarks
301 listing keys for "bookmarks"
298 listing keys for "bookmarks"
302 invalid branchheads cache (served): tip differs
299 invalid branchheads cache (served): tip differs
303 listing keys for "bookmarks"
300 listing keys for "bookmarks"
304 3 changesets found
301 3 changesets found
305 list of changesets:
302 list of changesets:
306 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
303 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
307 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
304 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
308 911600dab2ae7a9baff75958b84fe606851ce955
305 911600dab2ae7a9baff75958b84fe606851ce955
309 bundle2-output-bundle: "HG20", 4 parts total
306 bundle2-output-bundle: "HG20", 4 parts total
310 bundle2-output-part: "replycaps" 155 bytes payload
307 bundle2-output-part: "replycaps" 155 bytes payload
311 bundle2-output-part: "check:heads" streamed payload
308 bundle2-output-part: "check:heads" streamed payload
312 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
309 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
313 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
310 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
314 bundle2-input-bundle: with-transaction
311 bundle2-input-bundle: with-transaction
315 bundle2-input-part: "replycaps" supported
312 bundle2-input-part: "replycaps" supported
316 bundle2-input-part: total payload size 155
313 bundle2-input-part: total payload size 155
317 bundle2-input-part: "check:heads" supported
314 bundle2-input-part: "check:heads" supported
318 bundle2-input-part: total payload size 20
315 bundle2-input-part: total payload size 20
319 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
316 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
320 adding changesets
317 adding changesets
321 add changeset ef1ea85a6374
318 add changeset ef1ea85a6374
322 add changeset f9cafe1212c8
319 add changeset f9cafe1212c8
323 add changeset 911600dab2ae
320 add changeset 911600dab2ae
324 adding manifests
321 adding manifests
325 adding file changes
322 adding file changes
326 adding foo/Bar/file.txt revisions
323 adding foo/Bar/file.txt revisions
327 adding foo/file.txt revisions
324 adding foo/file.txt revisions
328 adding quux/file.py revisions
325 adding quux/file.py revisions
329 added 3 changesets with 3 changes to 3 files
326 added 3 changesets with 3 changes to 3 files
330 calling hook pretxnchangegroup.acl: hgext.acl.hook
327 calling hook pretxnchangegroup.acl: hgext.acl.hook
331 acl: checking access for user "fred"
328 acl: checking access for user "fred"
332 acl: acl.allow.branches not enabled
329 acl: acl.allow.branches not enabled
333 acl: acl.deny.branches not enabled
330 acl: acl.deny.branches not enabled
334 acl: acl.allow enabled, 0 entries for user fred
331 acl: acl.allow enabled, 0 entries for user fred
335 acl: acl.deny not enabled
332 acl: acl.deny not enabled
336 acl: branch access granted: "ef1ea85a6374" on branch "default"
333 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")
334 error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
338 bundle2-input-part: total payload size 1606
335 bundle2-input-part: total payload size 1606
339 bundle2-input-bundle: 3 parts total
336 bundle2-input-bundle: 3 parts total
340 transaction abort!
337 transaction abort!
341 rollback completed
338 rollback completed
342 abort: acl: user "fred" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
339 abort: acl: user "fred" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
343 no rollback information available
340 no rollback information available
344 0:6675d58eff77
341 0:6675d58eff77
345
342
346
343
347 fred is allowed inside foo/
344 fred is allowed inside foo/
348
345
349 $ echo 'foo/** = fred' >> $config
346 $ echo 'foo/** = fred' >> $config
350 $ do_push fred
347 $ do_push fred
351 Pushing as user fred
348 Pushing as user fred
352 hgrc = """
349 hgrc = """
353 [hooks]
350 [hooks]
354 pretxnchangegroup.acl = python:hgext.acl.hook
351 pretxnchangegroup.acl = python:hgext.acl.hook
355 [acl]
352 [acl]
356 sources = push
353 sources = push
357 [acl.allow]
354 [acl.allow]
358 foo/** = fred
355 foo/** = fred
359 """
356 """
360 pushing to ../b
357 pushing to ../b
361 query 1; heads
358 query 1; heads
362 searching for changes
359 searching for changes
363 all remote heads known locally
360 all remote heads known locally
364 listing keys for "phases"
361 listing keys for "phases"
365 checking for updated bookmarks
362 checking for updated bookmarks
366 listing keys for "bookmarks"
363 listing keys for "bookmarks"
367 invalid branchheads cache (served): tip differs
364 invalid branchheads cache (served): tip differs
368 listing keys for "bookmarks"
365 listing keys for "bookmarks"
369 3 changesets found
366 3 changesets found
370 list of changesets:
367 list of changesets:
371 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
368 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
372 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
369 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
373 911600dab2ae7a9baff75958b84fe606851ce955
370 911600dab2ae7a9baff75958b84fe606851ce955
374 bundle2-output-bundle: "HG20", 4 parts total
371 bundle2-output-bundle: "HG20", 4 parts total
375 bundle2-output-part: "replycaps" 155 bytes payload
372 bundle2-output-part: "replycaps" 155 bytes payload
376 bundle2-output-part: "check:heads" streamed payload
373 bundle2-output-part: "check:heads" streamed payload
377 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
374 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
378 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
375 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
379 bundle2-input-bundle: with-transaction
376 bundle2-input-bundle: with-transaction
380 bundle2-input-part: "replycaps" supported
377 bundle2-input-part: "replycaps" supported
381 bundle2-input-part: total payload size 155
378 bundle2-input-part: total payload size 155
382 bundle2-input-part: "check:heads" supported
379 bundle2-input-part: "check:heads" supported
383 bundle2-input-part: total payload size 20
380 bundle2-input-part: total payload size 20
384 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
381 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
385 adding changesets
382 adding changesets
386 add changeset ef1ea85a6374
383 add changeset ef1ea85a6374
387 add changeset f9cafe1212c8
384 add changeset f9cafe1212c8
388 add changeset 911600dab2ae
385 add changeset 911600dab2ae
389 adding manifests
386 adding manifests
390 adding file changes
387 adding file changes
391 adding foo/Bar/file.txt revisions
388 adding foo/Bar/file.txt revisions
392 adding foo/file.txt revisions
389 adding foo/file.txt revisions
393 adding quux/file.py revisions
390 adding quux/file.py revisions
394 added 3 changesets with 3 changes to 3 files
391 added 3 changesets with 3 changes to 3 files
395 calling hook pretxnchangegroup.acl: hgext.acl.hook
392 calling hook pretxnchangegroup.acl: hgext.acl.hook
396 acl: checking access for user "fred"
393 acl: checking access for user "fred"
397 acl: acl.allow.branches not enabled
394 acl: acl.allow.branches not enabled
398 acl: acl.deny.branches not enabled
395 acl: acl.deny.branches not enabled
399 acl: acl.allow enabled, 1 entries for user fred
396 acl: acl.allow enabled, 1 entries for user fred
400 acl: acl.deny not enabled
397 acl: acl.deny not enabled
401 acl: branch access granted: "ef1ea85a6374" on branch "default"
398 acl: branch access granted: "ef1ea85a6374" on branch "default"
402 acl: path access granted: "ef1ea85a6374"
399 acl: path access granted: "ef1ea85a6374"
403 acl: branch access granted: "f9cafe1212c8" on branch "default"
400 acl: branch access granted: "f9cafe1212c8" on branch "default"
404 acl: path access granted: "f9cafe1212c8"
401 acl: path access granted: "f9cafe1212c8"
405 acl: branch access granted: "911600dab2ae" on branch "default"
402 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")
403 error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
407 bundle2-input-part: total payload size 1606
404 bundle2-input-part: total payload size 1606
408 bundle2-input-bundle: 3 parts total
405 bundle2-input-bundle: 3 parts total
409 transaction abort!
406 transaction abort!
410 rollback completed
407 rollback completed
411 abort: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
408 abort: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
412 no rollback information available
409 no rollback information available
413 0:6675d58eff77
410 0:6675d58eff77
414
411
415
412
416 Empty [acl.deny]
413 Empty [acl.deny]
417
414
418 $ echo '[acl.deny]' >> $config
415 $ echo '[acl.deny]' >> $config
419 $ do_push barney
416 $ do_push barney
420 Pushing as user barney
417 Pushing as user barney
421 hgrc = """
418 hgrc = """
422 [hooks]
419 [hooks]
423 pretxnchangegroup.acl = python:hgext.acl.hook
420 pretxnchangegroup.acl = python:hgext.acl.hook
424 [acl]
421 [acl]
425 sources = push
422 sources = push
426 [acl.allow]
423 [acl.allow]
427 foo/** = fred
424 foo/** = fred
428 [acl.deny]
425 [acl.deny]
429 """
426 """
430 pushing to ../b
427 pushing to ../b
431 query 1; heads
428 query 1; heads
432 searching for changes
429 searching for changes
433 all remote heads known locally
430 all remote heads known locally
434 listing keys for "phases"
431 listing keys for "phases"
435 checking for updated bookmarks
432 checking for updated bookmarks
436 listing keys for "bookmarks"
433 listing keys for "bookmarks"
437 invalid branchheads cache (served): tip differs
434 invalid branchheads cache (served): tip differs
438 listing keys for "bookmarks"
435 listing keys for "bookmarks"
439 3 changesets found
436 3 changesets found
440 list of changesets:
437 list of changesets:
441 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
438 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
442 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
439 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
443 911600dab2ae7a9baff75958b84fe606851ce955
440 911600dab2ae7a9baff75958b84fe606851ce955
444 bundle2-output-bundle: "HG20", 4 parts total
441 bundle2-output-bundle: "HG20", 4 parts total
445 bundle2-output-part: "replycaps" 155 bytes payload
442 bundle2-output-part: "replycaps" 155 bytes payload
446 bundle2-output-part: "check:heads" streamed payload
443 bundle2-output-part: "check:heads" streamed payload
447 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
444 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
448 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
445 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
449 bundle2-input-bundle: with-transaction
446 bundle2-input-bundle: with-transaction
450 bundle2-input-part: "replycaps" supported
447 bundle2-input-part: "replycaps" supported
451 bundle2-input-part: total payload size 155
448 bundle2-input-part: total payload size 155
452 bundle2-input-part: "check:heads" supported
449 bundle2-input-part: "check:heads" supported
453 bundle2-input-part: total payload size 20
450 bundle2-input-part: total payload size 20
454 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
451 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
455 adding changesets
452 adding changesets
456 add changeset ef1ea85a6374
453 add changeset ef1ea85a6374
457 add changeset f9cafe1212c8
454 add changeset f9cafe1212c8
458 add changeset 911600dab2ae
455 add changeset 911600dab2ae
459 adding manifests
456 adding manifests
460 adding file changes
457 adding file changes
461 adding foo/Bar/file.txt revisions
458 adding foo/Bar/file.txt revisions
462 adding foo/file.txt revisions
459 adding foo/file.txt revisions
463 adding quux/file.py revisions
460 adding quux/file.py revisions
464 added 3 changesets with 3 changes to 3 files
461 added 3 changesets with 3 changes to 3 files
465 calling hook pretxnchangegroup.acl: hgext.acl.hook
462 calling hook pretxnchangegroup.acl: hgext.acl.hook
466 acl: checking access for user "barney"
463 acl: checking access for user "barney"
467 acl: acl.allow.branches not enabled
464 acl: acl.allow.branches not enabled
468 acl: acl.deny.branches not enabled
465 acl: acl.deny.branches not enabled
469 acl: acl.allow enabled, 0 entries for user barney
466 acl: acl.allow enabled, 0 entries for user barney
470 acl: acl.deny enabled, 0 entries for user barney
467 acl: acl.deny enabled, 0 entries for user barney
471 acl: branch access granted: "ef1ea85a6374" on branch "default"
468 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")
469 error: pretxnchangegroup.acl hook failed: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
473 bundle2-input-part: total payload size 1606
470 bundle2-input-part: total payload size 1606
474 bundle2-input-bundle: 3 parts total
471 bundle2-input-bundle: 3 parts total
475 transaction abort!
472 transaction abort!
476 rollback completed
473 rollback completed
477 abort: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
474 abort: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
478 no rollback information available
475 no rollback information available
479 0:6675d58eff77
476 0:6675d58eff77
480
477
481
478
482 fred is allowed inside foo/, but not foo/bar/ (case matters)
479 fred is allowed inside foo/, but not foo/bar/ (case matters)
483
480
484 $ echo 'foo/bar/** = fred' >> $config
481 $ echo 'foo/bar/** = fred' >> $config
485 $ do_push fred
482 $ do_push fred
486 Pushing as user fred
483 Pushing as user fred
487 hgrc = """
484 hgrc = """
488 [hooks]
485 [hooks]
489 pretxnchangegroup.acl = python:hgext.acl.hook
486 pretxnchangegroup.acl = python:hgext.acl.hook
490 [acl]
487 [acl]
491 sources = push
488 sources = push
492 [acl.allow]
489 [acl.allow]
493 foo/** = fred
490 foo/** = fred
494 [acl.deny]
491 [acl.deny]
495 foo/bar/** = fred
492 foo/bar/** = fred
496 """
493 """
497 pushing to ../b
494 pushing to ../b
498 query 1; heads
495 query 1; heads
499 searching for changes
496 searching for changes
500 all remote heads known locally
497 all remote heads known locally
501 listing keys for "phases"
498 listing keys for "phases"
502 checking for updated bookmarks
499 checking for updated bookmarks
503 listing keys for "bookmarks"
500 listing keys for "bookmarks"
504 invalid branchheads cache (served): tip differs
501 invalid branchheads cache (served): tip differs
505 listing keys for "bookmarks"
502 listing keys for "bookmarks"
506 3 changesets found
503 3 changesets found
507 list of changesets:
504 list of changesets:
508 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
505 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
509 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
506 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
510 911600dab2ae7a9baff75958b84fe606851ce955
507 911600dab2ae7a9baff75958b84fe606851ce955
511 bundle2-output-bundle: "HG20", 4 parts total
508 bundle2-output-bundle: "HG20", 4 parts total
512 bundle2-output-part: "replycaps" 155 bytes payload
509 bundle2-output-part: "replycaps" 155 bytes payload
513 bundle2-output-part: "check:heads" streamed payload
510 bundle2-output-part: "check:heads" streamed payload
514 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
511 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
515 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
512 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
516 bundle2-input-bundle: with-transaction
513 bundle2-input-bundle: with-transaction
517 bundle2-input-part: "replycaps" supported
514 bundle2-input-part: "replycaps" supported
518 bundle2-input-part: total payload size 155
515 bundle2-input-part: total payload size 155
519 bundle2-input-part: "check:heads" supported
516 bundle2-input-part: "check:heads" supported
520 bundle2-input-part: total payload size 20
517 bundle2-input-part: total payload size 20
521 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
518 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
522 adding changesets
519 adding changesets
523 add changeset ef1ea85a6374
520 add changeset ef1ea85a6374
524 add changeset f9cafe1212c8
521 add changeset f9cafe1212c8
525 add changeset 911600dab2ae
522 add changeset 911600dab2ae
526 adding manifests
523 adding manifests
527 adding file changes
524 adding file changes
528 adding foo/Bar/file.txt revisions
525 adding foo/Bar/file.txt revisions
529 adding foo/file.txt revisions
526 adding foo/file.txt revisions
530 adding quux/file.py revisions
527 adding quux/file.py revisions
531 added 3 changesets with 3 changes to 3 files
528 added 3 changesets with 3 changes to 3 files
532 calling hook pretxnchangegroup.acl: hgext.acl.hook
529 calling hook pretxnchangegroup.acl: hgext.acl.hook
533 acl: checking access for user "fred"
530 acl: checking access for user "fred"
534 acl: acl.allow.branches not enabled
531 acl: acl.allow.branches not enabled
535 acl: acl.deny.branches not enabled
532 acl: acl.deny.branches not enabled
536 acl: acl.allow enabled, 1 entries for user fred
533 acl: acl.allow enabled, 1 entries for user fred
537 acl: acl.deny enabled, 1 entries for user fred
534 acl: acl.deny enabled, 1 entries for user fred
538 acl: branch access granted: "ef1ea85a6374" on branch "default"
535 acl: branch access granted: "ef1ea85a6374" on branch "default"
539 acl: path access granted: "ef1ea85a6374"
536 acl: path access granted: "ef1ea85a6374"
540 acl: branch access granted: "f9cafe1212c8" on branch "default"
537 acl: branch access granted: "f9cafe1212c8" on branch "default"
541 acl: path access granted: "f9cafe1212c8"
538 acl: path access granted: "f9cafe1212c8"
542 acl: branch access granted: "911600dab2ae" on branch "default"
539 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")
540 error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
544 bundle2-input-part: total payload size 1606
541 bundle2-input-part: total payload size 1606
545 bundle2-input-bundle: 3 parts total
542 bundle2-input-bundle: 3 parts total
546 transaction abort!
543 transaction abort!
547 rollback completed
544 rollback completed
548 abort: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
545 abort: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
549 no rollback information available
546 no rollback information available
550 0:6675d58eff77
547 0:6675d58eff77
551
548
552
549
553 fred is allowed inside foo/, but not foo/Bar/
550 fred is allowed inside foo/, but not foo/Bar/
554
551
555 $ echo 'foo/Bar/** = fred' >> $config
552 $ echo 'foo/Bar/** = fred' >> $config
556 $ do_push fred
553 $ do_push fred
557 Pushing as user fred
554 Pushing as user fred
558 hgrc = """
555 hgrc = """
559 [hooks]
556 [hooks]
560 pretxnchangegroup.acl = python:hgext.acl.hook
557 pretxnchangegroup.acl = python:hgext.acl.hook
561 [acl]
558 [acl]
562 sources = push
559 sources = push
563 [acl.allow]
560 [acl.allow]
564 foo/** = fred
561 foo/** = fred
565 [acl.deny]
562 [acl.deny]
566 foo/bar/** = fred
563 foo/bar/** = fred
567 foo/Bar/** = fred
564 foo/Bar/** = fred
568 """
565 """
569 pushing to ../b
566 pushing to ../b
570 query 1; heads
567 query 1; heads
571 searching for changes
568 searching for changes
572 all remote heads known locally
569 all remote heads known locally
573 listing keys for "phases"
570 listing keys for "phases"
574 checking for updated bookmarks
571 checking for updated bookmarks
575 listing keys for "bookmarks"
572 listing keys for "bookmarks"
576 invalid branchheads cache (served): tip differs
573 invalid branchheads cache (served): tip differs
577 listing keys for "bookmarks"
574 listing keys for "bookmarks"
578 3 changesets found
575 3 changesets found
579 list of changesets:
576 list of changesets:
580 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
577 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
581 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
578 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
582 911600dab2ae7a9baff75958b84fe606851ce955
579 911600dab2ae7a9baff75958b84fe606851ce955
583 bundle2-output-bundle: "HG20", 4 parts total
580 bundle2-output-bundle: "HG20", 4 parts total
584 bundle2-output-part: "replycaps" 155 bytes payload
581 bundle2-output-part: "replycaps" 155 bytes payload
585 bundle2-output-part: "check:heads" streamed payload
582 bundle2-output-part: "check:heads" streamed payload
586 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
583 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
587 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
584 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
588 bundle2-input-bundle: with-transaction
585 bundle2-input-bundle: with-transaction
589 bundle2-input-part: "replycaps" supported
586 bundle2-input-part: "replycaps" supported
590 bundle2-input-part: total payload size 155
587 bundle2-input-part: total payload size 155
591 bundle2-input-part: "check:heads" supported
588 bundle2-input-part: "check:heads" supported
592 bundle2-input-part: total payload size 20
589 bundle2-input-part: total payload size 20
593 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
590 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
594 adding changesets
591 adding changesets
595 add changeset ef1ea85a6374
592 add changeset ef1ea85a6374
596 add changeset f9cafe1212c8
593 add changeset f9cafe1212c8
597 add changeset 911600dab2ae
594 add changeset 911600dab2ae
598 adding manifests
595 adding manifests
599 adding file changes
596 adding file changes
600 adding foo/Bar/file.txt revisions
597 adding foo/Bar/file.txt revisions
601 adding foo/file.txt revisions
598 adding foo/file.txt revisions
602 adding quux/file.py revisions
599 adding quux/file.py revisions
603 added 3 changesets with 3 changes to 3 files
600 added 3 changesets with 3 changes to 3 files
604 calling hook pretxnchangegroup.acl: hgext.acl.hook
601 calling hook pretxnchangegroup.acl: hgext.acl.hook
605 acl: checking access for user "fred"
602 acl: checking access for user "fred"
606 acl: acl.allow.branches not enabled
603 acl: acl.allow.branches not enabled
607 acl: acl.deny.branches not enabled
604 acl: acl.deny.branches not enabled
608 acl: acl.allow enabled, 1 entries for user fred
605 acl: acl.allow enabled, 1 entries for user fred
609 acl: acl.deny enabled, 2 entries for user fred
606 acl: acl.deny enabled, 2 entries for user fred
610 acl: branch access granted: "ef1ea85a6374" on branch "default"
607 acl: branch access granted: "ef1ea85a6374" on branch "default"
611 acl: path access granted: "ef1ea85a6374"
608 acl: path access granted: "ef1ea85a6374"
612 acl: branch access granted: "f9cafe1212c8" on branch "default"
609 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")
610 error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
614 bundle2-input-part: total payload size 1606
611 bundle2-input-part: total payload size 1606
615 bundle2-input-bundle: 3 parts total
612 bundle2-input-bundle: 3 parts total
616 transaction abort!
613 transaction abort!
617 rollback completed
614 rollback completed
618 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
615 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
619 no rollback information available
616 no rollback information available
620 0:6675d58eff77
617 0:6675d58eff77
621
618
622
619
623 $ echo 'barney is not mentioned => not allowed anywhere'
620 $ echo 'barney is not mentioned => not allowed anywhere'
624 barney is not mentioned => not allowed anywhere
621 barney is not mentioned => not allowed anywhere
625 $ do_push barney
622 $ do_push barney
626 Pushing as user barney
623 Pushing as user barney
627 hgrc = """
624 hgrc = """
628 [hooks]
625 [hooks]
629 pretxnchangegroup.acl = python:hgext.acl.hook
626 pretxnchangegroup.acl = python:hgext.acl.hook
630 [acl]
627 [acl]
631 sources = push
628 sources = push
632 [acl.allow]
629 [acl.allow]
633 foo/** = fred
630 foo/** = fred
634 [acl.deny]
631 [acl.deny]
635 foo/bar/** = fred
632 foo/bar/** = fred
636 foo/Bar/** = fred
633 foo/Bar/** = fred
637 """
634 """
638 pushing to ../b
635 pushing to ../b
639 query 1; heads
636 query 1; heads
640 searching for changes
637 searching for changes
641 all remote heads known locally
638 all remote heads known locally
642 listing keys for "phases"
639 listing keys for "phases"
643 checking for updated bookmarks
640 checking for updated bookmarks
644 listing keys for "bookmarks"
641 listing keys for "bookmarks"
645 invalid branchheads cache (served): tip differs
642 invalid branchheads cache (served): tip differs
646 listing keys for "bookmarks"
643 listing keys for "bookmarks"
647 3 changesets found
644 3 changesets found
648 list of changesets:
645 list of changesets:
649 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
646 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
650 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
647 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
651 911600dab2ae7a9baff75958b84fe606851ce955
648 911600dab2ae7a9baff75958b84fe606851ce955
652 bundle2-output-bundle: "HG20", 4 parts total
649 bundle2-output-bundle: "HG20", 4 parts total
653 bundle2-output-part: "replycaps" 155 bytes payload
650 bundle2-output-part: "replycaps" 155 bytes payload
654 bundle2-output-part: "check:heads" streamed payload
651 bundle2-output-part: "check:heads" streamed payload
655 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
652 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
656 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
653 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
657 bundle2-input-bundle: with-transaction
654 bundle2-input-bundle: with-transaction
658 bundle2-input-part: "replycaps" supported
655 bundle2-input-part: "replycaps" supported
659 bundle2-input-part: total payload size 155
656 bundle2-input-part: total payload size 155
660 bundle2-input-part: "check:heads" supported
657 bundle2-input-part: "check:heads" supported
661 bundle2-input-part: total payload size 20
658 bundle2-input-part: total payload size 20
662 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
659 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
663 adding changesets
660 adding changesets
664 add changeset ef1ea85a6374
661 add changeset ef1ea85a6374
665 add changeset f9cafe1212c8
662 add changeset f9cafe1212c8
666 add changeset 911600dab2ae
663 add changeset 911600dab2ae
667 adding manifests
664 adding manifests
668 adding file changes
665 adding file changes
669 adding foo/Bar/file.txt revisions
666 adding foo/Bar/file.txt revisions
670 adding foo/file.txt revisions
667 adding foo/file.txt revisions
671 adding quux/file.py revisions
668 adding quux/file.py revisions
672 added 3 changesets with 3 changes to 3 files
669 added 3 changesets with 3 changes to 3 files
673 calling hook pretxnchangegroup.acl: hgext.acl.hook
670 calling hook pretxnchangegroup.acl: hgext.acl.hook
674 acl: checking access for user "barney"
671 acl: checking access for user "barney"
675 acl: acl.allow.branches not enabled
672 acl: acl.allow.branches not enabled
676 acl: acl.deny.branches not enabled
673 acl: acl.deny.branches not enabled
677 acl: acl.allow enabled, 0 entries for user barney
674 acl: acl.allow enabled, 0 entries for user barney
678 acl: acl.deny enabled, 0 entries for user barney
675 acl: acl.deny enabled, 0 entries for user barney
679 acl: branch access granted: "ef1ea85a6374" on branch "default"
676 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")
677 error: pretxnchangegroup.acl hook failed: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
681 bundle2-input-part: total payload size 1606
678 bundle2-input-part: total payload size 1606
682 bundle2-input-bundle: 3 parts total
679 bundle2-input-bundle: 3 parts total
683 transaction abort!
680 transaction abort!
684 rollback completed
681 rollback completed
685 abort: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
682 abort: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
686 no rollback information available
683 no rollback information available
687 0:6675d58eff77
684 0:6675d58eff77
688
685
689
686
690 barney is allowed everywhere
687 barney is allowed everywhere
691
688
692 $ echo '[acl.allow]' >> $config
689 $ echo '[acl.allow]' >> $config
693 $ echo '** = barney' >> $config
690 $ echo '** = barney' >> $config
694 $ do_push barney
691 $ do_push barney
695 Pushing as user barney
692 Pushing as user barney
696 hgrc = """
693 hgrc = """
697 [hooks]
694 [hooks]
698 pretxnchangegroup.acl = python:hgext.acl.hook
695 pretxnchangegroup.acl = python:hgext.acl.hook
699 [acl]
696 [acl]
700 sources = push
697 sources = push
701 [acl.allow]
698 [acl.allow]
702 foo/** = fred
699 foo/** = fred
703 [acl.deny]
700 [acl.deny]
704 foo/bar/** = fred
701 foo/bar/** = fred
705 foo/Bar/** = fred
702 foo/Bar/** = fred
706 [acl.allow]
703 [acl.allow]
707 ** = barney
704 ** = barney
708 """
705 """
709 pushing to ../b
706 pushing to ../b
710 query 1; heads
707 query 1; heads
711 searching for changes
708 searching for changes
712 all remote heads known locally
709 all remote heads known locally
713 listing keys for "phases"
710 listing keys for "phases"
714 checking for updated bookmarks
711 checking for updated bookmarks
715 listing keys for "bookmarks"
712 listing keys for "bookmarks"
716 invalid branchheads cache (served): tip differs
713 invalid branchheads cache (served): tip differs
717 listing keys for "bookmarks"
714 listing keys for "bookmarks"
718 3 changesets found
715 3 changesets found
719 list of changesets:
716 list of changesets:
720 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
717 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
721 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
718 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
722 911600dab2ae7a9baff75958b84fe606851ce955
719 911600dab2ae7a9baff75958b84fe606851ce955
723 bundle2-output-bundle: "HG20", 4 parts total
720 bundle2-output-bundle: "HG20", 4 parts total
724 bundle2-output-part: "replycaps" 155 bytes payload
721 bundle2-output-part: "replycaps" 155 bytes payload
725 bundle2-output-part: "check:heads" streamed payload
722 bundle2-output-part: "check:heads" streamed payload
726 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
723 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
727 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
724 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
728 bundle2-input-bundle: with-transaction
725 bundle2-input-bundle: with-transaction
729 bundle2-input-part: "replycaps" supported
726 bundle2-input-part: "replycaps" supported
730 bundle2-input-part: total payload size 155
727 bundle2-input-part: total payload size 155
731 bundle2-input-part: "check:heads" supported
728 bundle2-input-part: "check:heads" supported
732 bundle2-input-part: total payload size 20
729 bundle2-input-part: total payload size 20
733 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
730 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
734 adding changesets
731 adding changesets
735 add changeset ef1ea85a6374
732 add changeset ef1ea85a6374
736 add changeset f9cafe1212c8
733 add changeset f9cafe1212c8
737 add changeset 911600dab2ae
734 add changeset 911600dab2ae
738 adding manifests
735 adding manifests
739 adding file changes
736 adding file changes
740 adding foo/Bar/file.txt revisions
737 adding foo/Bar/file.txt revisions
741 adding foo/file.txt revisions
738 adding foo/file.txt revisions
742 adding quux/file.py revisions
739 adding quux/file.py revisions
743 added 3 changesets with 3 changes to 3 files
740 added 3 changesets with 3 changes to 3 files
744 calling hook pretxnchangegroup.acl: hgext.acl.hook
741 calling hook pretxnchangegroup.acl: hgext.acl.hook
745 acl: checking access for user "barney"
742 acl: checking access for user "barney"
746 acl: acl.allow.branches not enabled
743 acl: acl.allow.branches not enabled
747 acl: acl.deny.branches not enabled
744 acl: acl.deny.branches not enabled
748 acl: acl.allow enabled, 1 entries for user barney
745 acl: acl.allow enabled, 1 entries for user barney
749 acl: acl.deny enabled, 0 entries for user barney
746 acl: acl.deny enabled, 0 entries for user barney
750 acl: branch access granted: "ef1ea85a6374" on branch "default"
747 acl: branch access granted: "ef1ea85a6374" on branch "default"
751 acl: path access granted: "ef1ea85a6374"
748 acl: path access granted: "ef1ea85a6374"
752 acl: branch access granted: "f9cafe1212c8" on branch "default"
749 acl: branch access granted: "f9cafe1212c8" on branch "default"
753 acl: path access granted: "f9cafe1212c8"
750 acl: path access granted: "f9cafe1212c8"
754 acl: branch access granted: "911600dab2ae" on branch "default"
751 acl: branch access granted: "911600dab2ae" on branch "default"
755 acl: path access granted: "911600dab2ae"
752 acl: path access granted: "911600dab2ae"
756 bundle2-input-part: total payload size 1606
753 bundle2-input-part: total payload size 1606
757 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
754 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
758 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
755 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
759 bundle2-input-bundle: 3 parts total
756 bundle2-input-bundle: 3 parts total
760 updating the branch cache
757 updating the branch cache
761 bundle2-output-bundle: "HG20", 2 parts total
758 bundle2-output-bundle: "HG20", 2 parts total
762 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
759 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
763 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
760 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
764 bundle2-input-bundle: with-transaction
761 bundle2-input-bundle: with-transaction
765 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
762 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
766 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
763 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
767 bundle2-input-bundle: 1 parts total
764 bundle2-input-bundle: 1 parts total
768 listing keys for "phases"
765 listing keys for "phases"
769 try to push obsolete markers to remote
770 repository tip rolled back to revision 0 (undo push)
766 repository tip rolled back to revision 0 (undo push)
771 0:6675d58eff77
767 0:6675d58eff77
772
768
773
769
774 wilma can change files with a .txt extension
770 wilma can change files with a .txt extension
775
771
776 $ echo '**/*.txt = wilma' >> $config
772 $ echo '**/*.txt = wilma' >> $config
777 $ do_push wilma
773 $ do_push wilma
778 Pushing as user wilma
774 Pushing as user wilma
779 hgrc = """
775 hgrc = """
780 [hooks]
776 [hooks]
781 pretxnchangegroup.acl = python:hgext.acl.hook
777 pretxnchangegroup.acl = python:hgext.acl.hook
782 [acl]
778 [acl]
783 sources = push
779 sources = push
784 [acl.allow]
780 [acl.allow]
785 foo/** = fred
781 foo/** = fred
786 [acl.deny]
782 [acl.deny]
787 foo/bar/** = fred
783 foo/bar/** = fred
788 foo/Bar/** = fred
784 foo/Bar/** = fred
789 [acl.allow]
785 [acl.allow]
790 ** = barney
786 ** = barney
791 **/*.txt = wilma
787 **/*.txt = wilma
792 """
788 """
793 pushing to ../b
789 pushing to ../b
794 query 1; heads
790 query 1; heads
795 searching for changes
791 searching for changes
796 all remote heads known locally
792 all remote heads known locally
797 listing keys for "phases"
793 listing keys for "phases"
798 checking for updated bookmarks
794 checking for updated bookmarks
799 listing keys for "bookmarks"
795 listing keys for "bookmarks"
800 invalid branchheads cache (served): tip differs
796 invalid branchheads cache (served): tip differs
801 listing keys for "bookmarks"
797 listing keys for "bookmarks"
802 3 changesets found
798 3 changesets found
803 list of changesets:
799 list of changesets:
804 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
800 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
805 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
801 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
806 911600dab2ae7a9baff75958b84fe606851ce955
802 911600dab2ae7a9baff75958b84fe606851ce955
807 bundle2-output-bundle: "HG20", 4 parts total
803 bundle2-output-bundle: "HG20", 4 parts total
808 bundle2-output-part: "replycaps" 155 bytes payload
804 bundle2-output-part: "replycaps" 155 bytes payload
809 bundle2-output-part: "check:heads" streamed payload
805 bundle2-output-part: "check:heads" streamed payload
810 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
806 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
811 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
807 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
812 bundle2-input-bundle: with-transaction
808 bundle2-input-bundle: with-transaction
813 bundle2-input-part: "replycaps" supported
809 bundle2-input-part: "replycaps" supported
814 bundle2-input-part: total payload size 155
810 bundle2-input-part: total payload size 155
815 bundle2-input-part: "check:heads" supported
811 bundle2-input-part: "check:heads" supported
816 bundle2-input-part: total payload size 20
812 bundle2-input-part: total payload size 20
817 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
813 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
818 adding changesets
814 adding changesets
819 add changeset ef1ea85a6374
815 add changeset ef1ea85a6374
820 add changeset f9cafe1212c8
816 add changeset f9cafe1212c8
821 add changeset 911600dab2ae
817 add changeset 911600dab2ae
822 adding manifests
818 adding manifests
823 adding file changes
819 adding file changes
824 adding foo/Bar/file.txt revisions
820 adding foo/Bar/file.txt revisions
825 adding foo/file.txt revisions
821 adding foo/file.txt revisions
826 adding quux/file.py revisions
822 adding quux/file.py revisions
827 added 3 changesets with 3 changes to 3 files
823 added 3 changesets with 3 changes to 3 files
828 calling hook pretxnchangegroup.acl: hgext.acl.hook
824 calling hook pretxnchangegroup.acl: hgext.acl.hook
829 acl: checking access for user "wilma"
825 acl: checking access for user "wilma"
830 acl: acl.allow.branches not enabled
826 acl: acl.allow.branches not enabled
831 acl: acl.deny.branches not enabled
827 acl: acl.deny.branches not enabled
832 acl: acl.allow enabled, 1 entries for user wilma
828 acl: acl.allow enabled, 1 entries for user wilma
833 acl: acl.deny enabled, 0 entries for user wilma
829 acl: acl.deny enabled, 0 entries for user wilma
834 acl: branch access granted: "ef1ea85a6374" on branch "default"
830 acl: branch access granted: "ef1ea85a6374" on branch "default"
835 acl: path access granted: "ef1ea85a6374"
831 acl: path access granted: "ef1ea85a6374"
836 acl: branch access granted: "f9cafe1212c8" on branch "default"
832 acl: branch access granted: "f9cafe1212c8" on branch "default"
837 acl: path access granted: "f9cafe1212c8"
833 acl: path access granted: "f9cafe1212c8"
838 acl: branch access granted: "911600dab2ae" on branch "default"
834 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")
835 error: pretxnchangegroup.acl hook failed: acl: user "wilma" not allowed on "quux/file.py" (changeset "911600dab2ae")
840 bundle2-input-part: total payload size 1606
836 bundle2-input-part: total payload size 1606
841 bundle2-input-bundle: 3 parts total
837 bundle2-input-bundle: 3 parts total
842 transaction abort!
838 transaction abort!
843 rollback completed
839 rollback completed
844 abort: acl: user "wilma" not allowed on "quux/file.py" (changeset "911600dab2ae")
840 abort: acl: user "wilma" not allowed on "quux/file.py" (changeset "911600dab2ae")
845 no rollback information available
841 no rollback information available
846 0:6675d58eff77
842 0:6675d58eff77
847
843
848
844
849 file specified by acl.config does not exist
845 file specified by acl.config does not exist
850
846
851 $ echo '[acl]' >> $config
847 $ echo '[acl]' >> $config
852 $ echo 'config = ../acl.config' >> $config
848 $ echo 'config = ../acl.config' >> $config
853 $ do_push barney
849 $ do_push barney
854 Pushing as user barney
850 Pushing as user barney
855 hgrc = """
851 hgrc = """
856 [hooks]
852 [hooks]
857 pretxnchangegroup.acl = python:hgext.acl.hook
853 pretxnchangegroup.acl = python:hgext.acl.hook
858 [acl]
854 [acl]
859 sources = push
855 sources = push
860 [acl.allow]
856 [acl.allow]
861 foo/** = fred
857 foo/** = fred
862 [acl.deny]
858 [acl.deny]
863 foo/bar/** = fred
859 foo/bar/** = fred
864 foo/Bar/** = fred
860 foo/Bar/** = fred
865 [acl.allow]
861 [acl.allow]
866 ** = barney
862 ** = barney
867 **/*.txt = wilma
863 **/*.txt = wilma
868 [acl]
864 [acl]
869 config = ../acl.config
865 config = ../acl.config
870 """
866 """
871 pushing to ../b
867 pushing to ../b
872 query 1; heads
868 query 1; heads
873 searching for changes
869 searching for changes
874 all remote heads known locally
870 all remote heads known locally
875 listing keys for "phases"
871 listing keys for "phases"
876 checking for updated bookmarks
872 checking for updated bookmarks
877 listing keys for "bookmarks"
873 listing keys for "bookmarks"
878 invalid branchheads cache (served): tip differs
874 invalid branchheads cache (served): tip differs
879 listing keys for "bookmarks"
875 listing keys for "bookmarks"
880 3 changesets found
876 3 changesets found
881 list of changesets:
877 list of changesets:
882 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
878 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
883 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
879 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
884 911600dab2ae7a9baff75958b84fe606851ce955
880 911600dab2ae7a9baff75958b84fe606851ce955
885 bundle2-output-bundle: "HG20", 4 parts total
881 bundle2-output-bundle: "HG20", 4 parts total
886 bundle2-output-part: "replycaps" 155 bytes payload
882 bundle2-output-part: "replycaps" 155 bytes payload
887 bundle2-output-part: "check:heads" streamed payload
883 bundle2-output-part: "check:heads" streamed payload
888 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
884 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
889 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
885 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
890 bundle2-input-bundle: with-transaction
886 bundle2-input-bundle: with-transaction
891 bundle2-input-part: "replycaps" supported
887 bundle2-input-part: "replycaps" supported
892 bundle2-input-part: total payload size 155
888 bundle2-input-part: total payload size 155
893 bundle2-input-part: "check:heads" supported
889 bundle2-input-part: "check:heads" supported
894 bundle2-input-part: total payload size 20
890 bundle2-input-part: total payload size 20
895 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
891 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
896 adding changesets
892 adding changesets
897 add changeset ef1ea85a6374
893 add changeset ef1ea85a6374
898 add changeset f9cafe1212c8
894 add changeset f9cafe1212c8
899 add changeset 911600dab2ae
895 add changeset 911600dab2ae
900 adding manifests
896 adding manifests
901 adding file changes
897 adding file changes
902 adding foo/Bar/file.txt revisions
898 adding foo/Bar/file.txt revisions
903 adding foo/file.txt revisions
899 adding foo/file.txt revisions
904 adding quux/file.py revisions
900 adding quux/file.py revisions
905 added 3 changesets with 3 changes to 3 files
901 added 3 changesets with 3 changes to 3 files
906 calling hook pretxnchangegroup.acl: hgext.acl.hook
902 calling hook pretxnchangegroup.acl: hgext.acl.hook
907 acl: checking access for user "barney"
903 acl: checking access for user "barney"
908 error: pretxnchangegroup.acl hook raised an exception: [Errno 2] No such file or directory: '../acl.config'
904 error: pretxnchangegroup.acl hook raised an exception: [Errno 2] No such file or directory: '../acl.config'
909 bundle2-input-part: total payload size 1606
905 bundle2-input-part: total payload size 1606
910 bundle2-input-bundle: 3 parts total
906 bundle2-input-bundle: 3 parts total
911 transaction abort!
907 transaction abort!
912 rollback completed
908 rollback completed
913 abort: No such file or directory: ../acl.config
909 abort: No such file or directory: ../acl.config
914 no rollback information available
910 no rollback information available
915 0:6675d58eff77
911 0:6675d58eff77
916
912
917
913
918 betty is allowed inside foo/ by a acl.config file
914 betty is allowed inside foo/ by a acl.config file
919
915
920 $ echo '[acl.allow]' >> acl.config
916 $ echo '[acl.allow]' >> acl.config
921 $ echo 'foo/** = betty' >> acl.config
917 $ echo 'foo/** = betty' >> acl.config
922 $ do_push betty
918 $ do_push betty
923 Pushing as user betty
919 Pushing as user betty
924 hgrc = """
920 hgrc = """
925 [hooks]
921 [hooks]
926 pretxnchangegroup.acl = python:hgext.acl.hook
922 pretxnchangegroup.acl = python:hgext.acl.hook
927 [acl]
923 [acl]
928 sources = push
924 sources = push
929 [acl.allow]
925 [acl.allow]
930 foo/** = fred
926 foo/** = fred
931 [acl.deny]
927 [acl.deny]
932 foo/bar/** = fred
928 foo/bar/** = fred
933 foo/Bar/** = fred
929 foo/Bar/** = fred
934 [acl.allow]
930 [acl.allow]
935 ** = barney
931 ** = barney
936 **/*.txt = wilma
932 **/*.txt = wilma
937 [acl]
933 [acl]
938 config = ../acl.config
934 config = ../acl.config
939 """
935 """
940 acl.config = """
936 acl.config = """
941 [acl.allow]
937 [acl.allow]
942 foo/** = betty
938 foo/** = betty
943 """
939 """
944 pushing to ../b
940 pushing to ../b
945 query 1; heads
941 query 1; heads
946 searching for changes
942 searching for changes
947 all remote heads known locally
943 all remote heads known locally
948 listing keys for "phases"
944 listing keys for "phases"
949 checking for updated bookmarks
945 checking for updated bookmarks
950 listing keys for "bookmarks"
946 listing keys for "bookmarks"
951 invalid branchheads cache (served): tip differs
947 invalid branchheads cache (served): tip differs
952 listing keys for "bookmarks"
948 listing keys for "bookmarks"
953 3 changesets found
949 3 changesets found
954 list of changesets:
950 list of changesets:
955 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
951 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
956 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
952 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
957 911600dab2ae7a9baff75958b84fe606851ce955
953 911600dab2ae7a9baff75958b84fe606851ce955
958 bundle2-output-bundle: "HG20", 4 parts total
954 bundle2-output-bundle: "HG20", 4 parts total
959 bundle2-output-part: "replycaps" 155 bytes payload
955 bundle2-output-part: "replycaps" 155 bytes payload
960 bundle2-output-part: "check:heads" streamed payload
956 bundle2-output-part: "check:heads" streamed payload
961 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
957 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
962 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
958 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
963 bundle2-input-bundle: with-transaction
959 bundle2-input-bundle: with-transaction
964 bundle2-input-part: "replycaps" supported
960 bundle2-input-part: "replycaps" supported
965 bundle2-input-part: total payload size 155
961 bundle2-input-part: total payload size 155
966 bundle2-input-part: "check:heads" supported
962 bundle2-input-part: "check:heads" supported
967 bundle2-input-part: total payload size 20
963 bundle2-input-part: total payload size 20
968 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
964 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
969 adding changesets
965 adding changesets
970 add changeset ef1ea85a6374
966 add changeset ef1ea85a6374
971 add changeset f9cafe1212c8
967 add changeset f9cafe1212c8
972 add changeset 911600dab2ae
968 add changeset 911600dab2ae
973 adding manifests
969 adding manifests
974 adding file changes
970 adding file changes
975 adding foo/Bar/file.txt revisions
971 adding foo/Bar/file.txt revisions
976 adding foo/file.txt revisions
972 adding foo/file.txt revisions
977 adding quux/file.py revisions
973 adding quux/file.py revisions
978 added 3 changesets with 3 changes to 3 files
974 added 3 changesets with 3 changes to 3 files
979 calling hook pretxnchangegroup.acl: hgext.acl.hook
975 calling hook pretxnchangegroup.acl: hgext.acl.hook
980 acl: checking access for user "betty"
976 acl: checking access for user "betty"
981 acl: acl.allow.branches not enabled
977 acl: acl.allow.branches not enabled
982 acl: acl.deny.branches not enabled
978 acl: acl.deny.branches not enabled
983 acl: acl.allow enabled, 1 entries for user betty
979 acl: acl.allow enabled, 1 entries for user betty
984 acl: acl.deny enabled, 0 entries for user betty
980 acl: acl.deny enabled, 0 entries for user betty
985 acl: branch access granted: "ef1ea85a6374" on branch "default"
981 acl: branch access granted: "ef1ea85a6374" on branch "default"
986 acl: path access granted: "ef1ea85a6374"
982 acl: path access granted: "ef1ea85a6374"
987 acl: branch access granted: "f9cafe1212c8" on branch "default"
983 acl: branch access granted: "f9cafe1212c8" on branch "default"
988 acl: path access granted: "f9cafe1212c8"
984 acl: path access granted: "f9cafe1212c8"
989 acl: branch access granted: "911600dab2ae" on branch "default"
985 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")
986 error: pretxnchangegroup.acl hook failed: acl: user "betty" not allowed on "quux/file.py" (changeset "911600dab2ae")
991 bundle2-input-part: total payload size 1606
987 bundle2-input-part: total payload size 1606
992 bundle2-input-bundle: 3 parts total
988 bundle2-input-bundle: 3 parts total
993 transaction abort!
989 transaction abort!
994 rollback completed
990 rollback completed
995 abort: acl: user "betty" not allowed on "quux/file.py" (changeset "911600dab2ae")
991 abort: acl: user "betty" not allowed on "quux/file.py" (changeset "911600dab2ae")
996 no rollback information available
992 no rollback information available
997 0:6675d58eff77
993 0:6675d58eff77
998
994
999
995
1000 acl.config can set only [acl.allow]/[acl.deny]
996 acl.config can set only [acl.allow]/[acl.deny]
1001
997
1002 $ echo '[hooks]' >> acl.config
998 $ echo '[hooks]' >> acl.config
1003 $ echo 'changegroup.acl = false' >> acl.config
999 $ echo 'changegroup.acl = false' >> acl.config
1004 $ do_push barney
1000 $ do_push barney
1005 Pushing as user barney
1001 Pushing as user barney
1006 hgrc = """
1002 hgrc = """
1007 [hooks]
1003 [hooks]
1008 pretxnchangegroup.acl = python:hgext.acl.hook
1004 pretxnchangegroup.acl = python:hgext.acl.hook
1009 [acl]
1005 [acl]
1010 sources = push
1006 sources = push
1011 [acl.allow]
1007 [acl.allow]
1012 foo/** = fred
1008 foo/** = fred
1013 [acl.deny]
1009 [acl.deny]
1014 foo/bar/** = fred
1010 foo/bar/** = fred
1015 foo/Bar/** = fred
1011 foo/Bar/** = fred
1016 [acl.allow]
1012 [acl.allow]
1017 ** = barney
1013 ** = barney
1018 **/*.txt = wilma
1014 **/*.txt = wilma
1019 [acl]
1015 [acl]
1020 config = ../acl.config
1016 config = ../acl.config
1021 """
1017 """
1022 acl.config = """
1018 acl.config = """
1023 [acl.allow]
1019 [acl.allow]
1024 foo/** = betty
1020 foo/** = betty
1025 [hooks]
1021 [hooks]
1026 changegroup.acl = false
1022 changegroup.acl = false
1027 """
1023 """
1028 pushing to ../b
1024 pushing to ../b
1029 query 1; heads
1025 query 1; heads
1030 searching for changes
1026 searching for changes
1031 all remote heads known locally
1027 all remote heads known locally
1032 listing keys for "phases"
1028 listing keys for "phases"
1033 checking for updated bookmarks
1029 checking for updated bookmarks
1034 listing keys for "bookmarks"
1030 listing keys for "bookmarks"
1035 invalid branchheads cache (served): tip differs
1031 invalid branchheads cache (served): tip differs
1036 listing keys for "bookmarks"
1032 listing keys for "bookmarks"
1037 3 changesets found
1033 3 changesets found
1038 list of changesets:
1034 list of changesets:
1039 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1035 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1040 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1036 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1041 911600dab2ae7a9baff75958b84fe606851ce955
1037 911600dab2ae7a9baff75958b84fe606851ce955
1042 bundle2-output-bundle: "HG20", 4 parts total
1038 bundle2-output-bundle: "HG20", 4 parts total
1043 bundle2-output-part: "replycaps" 155 bytes payload
1039 bundle2-output-part: "replycaps" 155 bytes payload
1044 bundle2-output-part: "check:heads" streamed payload
1040 bundle2-output-part: "check:heads" streamed payload
1045 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1041 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1046 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1042 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1047 bundle2-input-bundle: with-transaction
1043 bundle2-input-bundle: with-transaction
1048 bundle2-input-part: "replycaps" supported
1044 bundle2-input-part: "replycaps" supported
1049 bundle2-input-part: total payload size 155
1045 bundle2-input-part: total payload size 155
1050 bundle2-input-part: "check:heads" supported
1046 bundle2-input-part: "check:heads" supported
1051 bundle2-input-part: total payload size 20
1047 bundle2-input-part: total payload size 20
1052 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1048 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1053 adding changesets
1049 adding changesets
1054 add changeset ef1ea85a6374
1050 add changeset ef1ea85a6374
1055 add changeset f9cafe1212c8
1051 add changeset f9cafe1212c8
1056 add changeset 911600dab2ae
1052 add changeset 911600dab2ae
1057 adding manifests
1053 adding manifests
1058 adding file changes
1054 adding file changes
1059 adding foo/Bar/file.txt revisions
1055 adding foo/Bar/file.txt revisions
1060 adding foo/file.txt revisions
1056 adding foo/file.txt revisions
1061 adding quux/file.py revisions
1057 adding quux/file.py revisions
1062 added 3 changesets with 3 changes to 3 files
1058 added 3 changesets with 3 changes to 3 files
1063 calling hook pretxnchangegroup.acl: hgext.acl.hook
1059 calling hook pretxnchangegroup.acl: hgext.acl.hook
1064 acl: checking access for user "barney"
1060 acl: checking access for user "barney"
1065 acl: acl.allow.branches not enabled
1061 acl: acl.allow.branches not enabled
1066 acl: acl.deny.branches not enabled
1062 acl: acl.deny.branches not enabled
1067 acl: acl.allow enabled, 1 entries for user barney
1063 acl: acl.allow enabled, 1 entries for user barney
1068 acl: acl.deny enabled, 0 entries for user barney
1064 acl: acl.deny enabled, 0 entries for user barney
1069 acl: branch access granted: "ef1ea85a6374" on branch "default"
1065 acl: branch access granted: "ef1ea85a6374" on branch "default"
1070 acl: path access granted: "ef1ea85a6374"
1066 acl: path access granted: "ef1ea85a6374"
1071 acl: branch access granted: "f9cafe1212c8" on branch "default"
1067 acl: branch access granted: "f9cafe1212c8" on branch "default"
1072 acl: path access granted: "f9cafe1212c8"
1068 acl: path access granted: "f9cafe1212c8"
1073 acl: branch access granted: "911600dab2ae" on branch "default"
1069 acl: branch access granted: "911600dab2ae" on branch "default"
1074 acl: path access granted: "911600dab2ae"
1070 acl: path access granted: "911600dab2ae"
1075 bundle2-input-part: total payload size 1606
1071 bundle2-input-part: total payload size 1606
1076 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1072 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1077 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1073 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1078 bundle2-input-bundle: 3 parts total
1074 bundle2-input-bundle: 3 parts total
1079 updating the branch cache
1075 updating the branch cache
1080 bundle2-output-bundle: "HG20", 2 parts total
1076 bundle2-output-bundle: "HG20", 2 parts total
1081 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1077 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1082 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1078 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1083 bundle2-input-bundle: with-transaction
1079 bundle2-input-bundle: with-transaction
1084 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1080 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1085 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1081 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1086 bundle2-input-bundle: 1 parts total
1082 bundle2-input-bundle: 1 parts total
1087 listing keys for "phases"
1083 listing keys for "phases"
1088 try to push obsolete markers to remote
1089 repository tip rolled back to revision 0 (undo push)
1084 repository tip rolled back to revision 0 (undo push)
1090 0:6675d58eff77
1085 0:6675d58eff77
1091
1086
1092
1087
1093 asterisk
1088 asterisk
1094
1089
1095 $ init_config
1090 $ init_config
1096
1091
1097 asterisk test
1092 asterisk test
1098
1093
1099 $ echo '[acl.allow]' >> $config
1094 $ echo '[acl.allow]' >> $config
1100 $ echo "** = fred" >> $config
1095 $ echo "** = fred" >> $config
1101
1096
1102 fred is always allowed
1097 fred is always allowed
1103
1098
1104 $ do_push fred
1099 $ do_push fred
1105 Pushing as user fred
1100 Pushing as user fred
1106 hgrc = """
1101 hgrc = """
1107 [hooks]
1102 [hooks]
1108 pretxnchangegroup.acl = python:hgext.acl.hook
1103 pretxnchangegroup.acl = python:hgext.acl.hook
1109 [acl]
1104 [acl]
1110 sources = push
1105 sources = push
1111 [extensions]
1106 [extensions]
1112 [acl.allow]
1107 [acl.allow]
1113 ** = fred
1108 ** = fred
1114 """
1109 """
1115 pushing to ../b
1110 pushing to ../b
1116 query 1; heads
1111 query 1; heads
1117 searching for changes
1112 searching for changes
1118 all remote heads known locally
1113 all remote heads known locally
1119 listing keys for "phases"
1114 listing keys for "phases"
1120 checking for updated bookmarks
1115 checking for updated bookmarks
1121 listing keys for "bookmarks"
1116 listing keys for "bookmarks"
1122 invalid branchheads cache (served): tip differs
1117 invalid branchheads cache (served): tip differs
1123 listing keys for "bookmarks"
1118 listing keys for "bookmarks"
1124 3 changesets found
1119 3 changesets found
1125 list of changesets:
1120 list of changesets:
1126 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1121 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1127 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1122 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1128 911600dab2ae7a9baff75958b84fe606851ce955
1123 911600dab2ae7a9baff75958b84fe606851ce955
1129 bundle2-output-bundle: "HG20", 4 parts total
1124 bundle2-output-bundle: "HG20", 4 parts total
1130 bundle2-output-part: "replycaps" 155 bytes payload
1125 bundle2-output-part: "replycaps" 155 bytes payload
1131 bundle2-output-part: "check:heads" streamed payload
1126 bundle2-output-part: "check:heads" streamed payload
1132 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1127 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1133 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1128 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1134 bundle2-input-bundle: with-transaction
1129 bundle2-input-bundle: with-transaction
1135 bundle2-input-part: "replycaps" supported
1130 bundle2-input-part: "replycaps" supported
1136 bundle2-input-part: total payload size 155
1131 bundle2-input-part: total payload size 155
1137 bundle2-input-part: "check:heads" supported
1132 bundle2-input-part: "check:heads" supported
1138 bundle2-input-part: total payload size 20
1133 bundle2-input-part: total payload size 20
1139 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1134 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1140 adding changesets
1135 adding changesets
1141 add changeset ef1ea85a6374
1136 add changeset ef1ea85a6374
1142 add changeset f9cafe1212c8
1137 add changeset f9cafe1212c8
1143 add changeset 911600dab2ae
1138 add changeset 911600dab2ae
1144 adding manifests
1139 adding manifests
1145 adding file changes
1140 adding file changes
1146 adding foo/Bar/file.txt revisions
1141 adding foo/Bar/file.txt revisions
1147 adding foo/file.txt revisions
1142 adding foo/file.txt revisions
1148 adding quux/file.py revisions
1143 adding quux/file.py revisions
1149 added 3 changesets with 3 changes to 3 files
1144 added 3 changesets with 3 changes to 3 files
1150 calling hook pretxnchangegroup.acl: hgext.acl.hook
1145 calling hook pretxnchangegroup.acl: hgext.acl.hook
1151 acl: checking access for user "fred"
1146 acl: checking access for user "fred"
1152 acl: acl.allow.branches not enabled
1147 acl: acl.allow.branches not enabled
1153 acl: acl.deny.branches not enabled
1148 acl: acl.deny.branches not enabled
1154 acl: acl.allow enabled, 1 entries for user fred
1149 acl: acl.allow enabled, 1 entries for user fred
1155 acl: acl.deny not enabled
1150 acl: acl.deny not enabled
1156 acl: branch access granted: "ef1ea85a6374" on branch "default"
1151 acl: branch access granted: "ef1ea85a6374" on branch "default"
1157 acl: path access granted: "ef1ea85a6374"
1152 acl: path access granted: "ef1ea85a6374"
1158 acl: branch access granted: "f9cafe1212c8" on branch "default"
1153 acl: branch access granted: "f9cafe1212c8" on branch "default"
1159 acl: path access granted: "f9cafe1212c8"
1154 acl: path access granted: "f9cafe1212c8"
1160 acl: branch access granted: "911600dab2ae" on branch "default"
1155 acl: branch access granted: "911600dab2ae" on branch "default"
1161 acl: path access granted: "911600dab2ae"
1156 acl: path access granted: "911600dab2ae"
1162 bundle2-input-part: total payload size 1606
1157 bundle2-input-part: total payload size 1606
1163 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1158 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1164 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1159 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1165 bundle2-input-bundle: 3 parts total
1160 bundle2-input-bundle: 3 parts total
1166 updating the branch cache
1161 updating the branch cache
1167 bundle2-output-bundle: "HG20", 2 parts total
1162 bundle2-output-bundle: "HG20", 2 parts total
1168 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1163 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1169 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1164 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1170 bundle2-input-bundle: with-transaction
1165 bundle2-input-bundle: with-transaction
1171 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1166 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1172 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1167 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1173 bundle2-input-bundle: 1 parts total
1168 bundle2-input-bundle: 1 parts total
1174 listing keys for "phases"
1169 listing keys for "phases"
1175 try to push obsolete markers to remote
1176 repository tip rolled back to revision 0 (undo push)
1170 repository tip rolled back to revision 0 (undo push)
1177 0:6675d58eff77
1171 0:6675d58eff77
1178
1172
1179
1173
1180 $ echo '[acl.deny]' >> $config
1174 $ echo '[acl.deny]' >> $config
1181 $ echo "foo/Bar/** = *" >> $config
1175 $ echo "foo/Bar/** = *" >> $config
1182
1176
1183 no one is allowed inside foo/Bar/
1177 no one is allowed inside foo/Bar/
1184
1178
1185 $ do_push fred
1179 $ do_push fred
1186 Pushing as user fred
1180 Pushing as user fred
1187 hgrc = """
1181 hgrc = """
1188 [hooks]
1182 [hooks]
1189 pretxnchangegroup.acl = python:hgext.acl.hook
1183 pretxnchangegroup.acl = python:hgext.acl.hook
1190 [acl]
1184 [acl]
1191 sources = push
1185 sources = push
1192 [extensions]
1186 [extensions]
1193 [acl.allow]
1187 [acl.allow]
1194 ** = fred
1188 ** = fred
1195 [acl.deny]
1189 [acl.deny]
1196 foo/Bar/** = *
1190 foo/Bar/** = *
1197 """
1191 """
1198 pushing to ../b
1192 pushing to ../b
1199 query 1; heads
1193 query 1; heads
1200 searching for changes
1194 searching for changes
1201 all remote heads known locally
1195 all remote heads known locally
1202 listing keys for "phases"
1196 listing keys for "phases"
1203 checking for updated bookmarks
1197 checking for updated bookmarks
1204 listing keys for "bookmarks"
1198 listing keys for "bookmarks"
1205 invalid branchheads cache (served): tip differs
1199 invalid branchheads cache (served): tip differs
1206 listing keys for "bookmarks"
1200 listing keys for "bookmarks"
1207 3 changesets found
1201 3 changesets found
1208 list of changesets:
1202 list of changesets:
1209 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1203 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1210 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1204 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1211 911600dab2ae7a9baff75958b84fe606851ce955
1205 911600dab2ae7a9baff75958b84fe606851ce955
1212 bundle2-output-bundle: "HG20", 4 parts total
1206 bundle2-output-bundle: "HG20", 4 parts total
1213 bundle2-output-part: "replycaps" 155 bytes payload
1207 bundle2-output-part: "replycaps" 155 bytes payload
1214 bundle2-output-part: "check:heads" streamed payload
1208 bundle2-output-part: "check:heads" streamed payload
1215 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1209 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1216 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1210 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1217 bundle2-input-bundle: with-transaction
1211 bundle2-input-bundle: with-transaction
1218 bundle2-input-part: "replycaps" supported
1212 bundle2-input-part: "replycaps" supported
1219 bundle2-input-part: total payload size 155
1213 bundle2-input-part: total payload size 155
1220 bundle2-input-part: "check:heads" supported
1214 bundle2-input-part: "check:heads" supported
1221 bundle2-input-part: total payload size 20
1215 bundle2-input-part: total payload size 20
1222 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1216 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1223 adding changesets
1217 adding changesets
1224 add changeset ef1ea85a6374
1218 add changeset ef1ea85a6374
1225 add changeset f9cafe1212c8
1219 add changeset f9cafe1212c8
1226 add changeset 911600dab2ae
1220 add changeset 911600dab2ae
1227 adding manifests
1221 adding manifests
1228 adding file changes
1222 adding file changes
1229 adding foo/Bar/file.txt revisions
1223 adding foo/Bar/file.txt revisions
1230 adding foo/file.txt revisions
1224 adding foo/file.txt revisions
1231 adding quux/file.py revisions
1225 adding quux/file.py revisions
1232 added 3 changesets with 3 changes to 3 files
1226 added 3 changesets with 3 changes to 3 files
1233 calling hook pretxnchangegroup.acl: hgext.acl.hook
1227 calling hook pretxnchangegroup.acl: hgext.acl.hook
1234 acl: checking access for user "fred"
1228 acl: checking access for user "fred"
1235 acl: acl.allow.branches not enabled
1229 acl: acl.allow.branches not enabled
1236 acl: acl.deny.branches not enabled
1230 acl: acl.deny.branches not enabled
1237 acl: acl.allow enabled, 1 entries for user fred
1231 acl: acl.allow enabled, 1 entries for user fred
1238 acl: acl.deny enabled, 1 entries for user fred
1232 acl: acl.deny enabled, 1 entries for user fred
1239 acl: branch access granted: "ef1ea85a6374" on branch "default"
1233 acl: branch access granted: "ef1ea85a6374" on branch "default"
1240 acl: path access granted: "ef1ea85a6374"
1234 acl: path access granted: "ef1ea85a6374"
1241 acl: branch access granted: "f9cafe1212c8" on branch "default"
1235 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")
1236 error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1243 bundle2-input-part: total payload size 1606
1237 bundle2-input-part: total payload size 1606
1244 bundle2-input-bundle: 3 parts total
1238 bundle2-input-bundle: 3 parts total
1245 transaction abort!
1239 transaction abort!
1246 rollback completed
1240 rollback completed
1247 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1241 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1248 no rollback information available
1242 no rollback information available
1249 0:6675d58eff77
1243 0:6675d58eff77
1250
1244
1251
1245
1252 Groups
1246 Groups
1253
1247
1254 $ init_config
1248 $ init_config
1255
1249
1256 OS-level groups
1250 OS-level groups
1257
1251
1258 $ echo '[acl.allow]' >> $config
1252 $ echo '[acl.allow]' >> $config
1259 $ echo "** = @group1" >> $config
1253 $ echo "** = @group1" >> $config
1260
1254
1261 @group1 is always allowed
1255 @group1 is always allowed
1262
1256
1263 $ do_push fred
1257 $ do_push fred
1264 Pushing as user fred
1258 Pushing as user fred
1265 hgrc = """
1259 hgrc = """
1266 [hooks]
1260 [hooks]
1267 pretxnchangegroup.acl = python:hgext.acl.hook
1261 pretxnchangegroup.acl = python:hgext.acl.hook
1268 [acl]
1262 [acl]
1269 sources = push
1263 sources = push
1270 [extensions]
1264 [extensions]
1271 [acl.allow]
1265 [acl.allow]
1272 ** = @group1
1266 ** = @group1
1273 """
1267 """
1274 pushing to ../b
1268 pushing to ../b
1275 query 1; heads
1269 query 1; heads
1276 searching for changes
1270 searching for changes
1277 all remote heads known locally
1271 all remote heads known locally
1278 listing keys for "phases"
1272 listing keys for "phases"
1279 checking for updated bookmarks
1273 checking for updated bookmarks
1280 listing keys for "bookmarks"
1274 listing keys for "bookmarks"
1281 invalid branchheads cache (served): tip differs
1275 invalid branchheads cache (served): tip differs
1282 listing keys for "bookmarks"
1276 listing keys for "bookmarks"
1283 3 changesets found
1277 3 changesets found
1284 list of changesets:
1278 list of changesets:
1285 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1279 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1286 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1280 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1287 911600dab2ae7a9baff75958b84fe606851ce955
1281 911600dab2ae7a9baff75958b84fe606851ce955
1288 bundle2-output-bundle: "HG20", 4 parts total
1282 bundle2-output-bundle: "HG20", 4 parts total
1289 bundle2-output-part: "replycaps" 155 bytes payload
1283 bundle2-output-part: "replycaps" 155 bytes payload
1290 bundle2-output-part: "check:heads" streamed payload
1284 bundle2-output-part: "check:heads" streamed payload
1291 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1285 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1292 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1286 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1293 bundle2-input-bundle: with-transaction
1287 bundle2-input-bundle: with-transaction
1294 bundle2-input-part: "replycaps" supported
1288 bundle2-input-part: "replycaps" supported
1295 bundle2-input-part: total payload size 155
1289 bundle2-input-part: total payload size 155
1296 bundle2-input-part: "check:heads" supported
1290 bundle2-input-part: "check:heads" supported
1297 bundle2-input-part: total payload size 20
1291 bundle2-input-part: total payload size 20
1298 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1292 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1299 adding changesets
1293 adding changesets
1300 add changeset ef1ea85a6374
1294 add changeset ef1ea85a6374
1301 add changeset f9cafe1212c8
1295 add changeset f9cafe1212c8
1302 add changeset 911600dab2ae
1296 add changeset 911600dab2ae
1303 adding manifests
1297 adding manifests
1304 adding file changes
1298 adding file changes
1305 adding foo/Bar/file.txt revisions
1299 adding foo/Bar/file.txt revisions
1306 adding foo/file.txt revisions
1300 adding foo/file.txt revisions
1307 adding quux/file.py revisions
1301 adding quux/file.py revisions
1308 added 3 changesets with 3 changes to 3 files
1302 added 3 changesets with 3 changes to 3 files
1309 calling hook pretxnchangegroup.acl: hgext.acl.hook
1303 calling hook pretxnchangegroup.acl: hgext.acl.hook
1310 acl: checking access for user "fred"
1304 acl: checking access for user "fred"
1311 acl: acl.allow.branches not enabled
1305 acl: acl.allow.branches not enabled
1312 acl: acl.deny.branches not enabled
1306 acl: acl.deny.branches not enabled
1313 acl: "group1" not defined in [acl.groups]
1307 acl: "group1" not defined in [acl.groups]
1314 acl: acl.allow enabled, 1 entries for user fred
1308 acl: acl.allow enabled, 1 entries for user fred
1315 acl: acl.deny not enabled
1309 acl: acl.deny not enabled
1316 acl: branch access granted: "ef1ea85a6374" on branch "default"
1310 acl: branch access granted: "ef1ea85a6374" on branch "default"
1317 acl: path access granted: "ef1ea85a6374"
1311 acl: path access granted: "ef1ea85a6374"
1318 acl: branch access granted: "f9cafe1212c8" on branch "default"
1312 acl: branch access granted: "f9cafe1212c8" on branch "default"
1319 acl: path access granted: "f9cafe1212c8"
1313 acl: path access granted: "f9cafe1212c8"
1320 acl: branch access granted: "911600dab2ae" on branch "default"
1314 acl: branch access granted: "911600dab2ae" on branch "default"
1321 acl: path access granted: "911600dab2ae"
1315 acl: path access granted: "911600dab2ae"
1322 bundle2-input-part: total payload size 1606
1316 bundle2-input-part: total payload size 1606
1323 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1317 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1324 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1318 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1325 bundle2-input-bundle: 3 parts total
1319 bundle2-input-bundle: 3 parts total
1326 updating the branch cache
1320 updating the branch cache
1327 bundle2-output-bundle: "HG20", 2 parts total
1321 bundle2-output-bundle: "HG20", 2 parts total
1328 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1322 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1329 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1323 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1330 bundle2-input-bundle: with-transaction
1324 bundle2-input-bundle: with-transaction
1331 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1325 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1332 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1326 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1333 bundle2-input-bundle: 1 parts total
1327 bundle2-input-bundle: 1 parts total
1334 listing keys for "phases"
1328 listing keys for "phases"
1335 try to push obsolete markers to remote
1336 repository tip rolled back to revision 0 (undo push)
1329 repository tip rolled back to revision 0 (undo push)
1337 0:6675d58eff77
1330 0:6675d58eff77
1338
1331
1339
1332
1340 $ echo '[acl.deny]' >> $config
1333 $ echo '[acl.deny]' >> $config
1341 $ echo "foo/Bar/** = @group1" >> $config
1334 $ echo "foo/Bar/** = @group1" >> $config
1342
1335
1343 @group is allowed inside anything but foo/Bar/
1336 @group is allowed inside anything but foo/Bar/
1344
1337
1345 $ do_push fred
1338 $ do_push fred
1346 Pushing as user fred
1339 Pushing as user fred
1347 hgrc = """
1340 hgrc = """
1348 [hooks]
1341 [hooks]
1349 pretxnchangegroup.acl = python:hgext.acl.hook
1342 pretxnchangegroup.acl = python:hgext.acl.hook
1350 [acl]
1343 [acl]
1351 sources = push
1344 sources = push
1352 [extensions]
1345 [extensions]
1353 [acl.allow]
1346 [acl.allow]
1354 ** = @group1
1347 ** = @group1
1355 [acl.deny]
1348 [acl.deny]
1356 foo/Bar/** = @group1
1349 foo/Bar/** = @group1
1357 """
1350 """
1358 pushing to ../b
1351 pushing to ../b
1359 query 1; heads
1352 query 1; heads
1360 searching for changes
1353 searching for changes
1361 all remote heads known locally
1354 all remote heads known locally
1362 listing keys for "phases"
1355 listing keys for "phases"
1363 checking for updated bookmarks
1356 checking for updated bookmarks
1364 listing keys for "bookmarks"
1357 listing keys for "bookmarks"
1365 invalid branchheads cache (served): tip differs
1358 invalid branchheads cache (served): tip differs
1366 listing keys for "bookmarks"
1359 listing keys for "bookmarks"
1367 3 changesets found
1360 3 changesets found
1368 list of changesets:
1361 list of changesets:
1369 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1362 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1370 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1363 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1371 911600dab2ae7a9baff75958b84fe606851ce955
1364 911600dab2ae7a9baff75958b84fe606851ce955
1372 bundle2-output-bundle: "HG20", 4 parts total
1365 bundle2-output-bundle: "HG20", 4 parts total
1373 bundle2-output-part: "replycaps" 155 bytes payload
1366 bundle2-output-part: "replycaps" 155 bytes payload
1374 bundle2-output-part: "check:heads" streamed payload
1367 bundle2-output-part: "check:heads" streamed payload
1375 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1368 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1376 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1369 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1377 bundle2-input-bundle: with-transaction
1370 bundle2-input-bundle: with-transaction
1378 bundle2-input-part: "replycaps" supported
1371 bundle2-input-part: "replycaps" supported
1379 bundle2-input-part: total payload size 155
1372 bundle2-input-part: total payload size 155
1380 bundle2-input-part: "check:heads" supported
1373 bundle2-input-part: "check:heads" supported
1381 bundle2-input-part: total payload size 20
1374 bundle2-input-part: total payload size 20
1382 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1375 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1383 adding changesets
1376 adding changesets
1384 add changeset ef1ea85a6374
1377 add changeset ef1ea85a6374
1385 add changeset f9cafe1212c8
1378 add changeset f9cafe1212c8
1386 add changeset 911600dab2ae
1379 add changeset 911600dab2ae
1387 adding manifests
1380 adding manifests
1388 adding file changes
1381 adding file changes
1389 adding foo/Bar/file.txt revisions
1382 adding foo/Bar/file.txt revisions
1390 adding foo/file.txt revisions
1383 adding foo/file.txt revisions
1391 adding quux/file.py revisions
1384 adding quux/file.py revisions
1392 added 3 changesets with 3 changes to 3 files
1385 added 3 changesets with 3 changes to 3 files
1393 calling hook pretxnchangegroup.acl: hgext.acl.hook
1386 calling hook pretxnchangegroup.acl: hgext.acl.hook
1394 acl: checking access for user "fred"
1387 acl: checking access for user "fred"
1395 acl: acl.allow.branches not enabled
1388 acl: acl.allow.branches not enabled
1396 acl: acl.deny.branches not enabled
1389 acl: acl.deny.branches not enabled
1397 acl: "group1" not defined in [acl.groups]
1390 acl: "group1" not defined in [acl.groups]
1398 acl: acl.allow enabled, 1 entries for user fred
1391 acl: acl.allow enabled, 1 entries for user fred
1399 acl: "group1" not defined in [acl.groups]
1392 acl: "group1" not defined in [acl.groups]
1400 acl: acl.deny enabled, 1 entries for user fred
1393 acl: acl.deny enabled, 1 entries for user fred
1401 acl: branch access granted: "ef1ea85a6374" on branch "default"
1394 acl: branch access granted: "ef1ea85a6374" on branch "default"
1402 acl: path access granted: "ef1ea85a6374"
1395 acl: path access granted: "ef1ea85a6374"
1403 acl: branch access granted: "f9cafe1212c8" on branch "default"
1396 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")
1397 error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1405 bundle2-input-part: total payload size 1606
1398 bundle2-input-part: total payload size 1606
1406 bundle2-input-bundle: 3 parts total
1399 bundle2-input-bundle: 3 parts total
1407 transaction abort!
1400 transaction abort!
1408 rollback completed
1401 rollback completed
1409 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1402 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1410 no rollback information available
1403 no rollback information available
1411 0:6675d58eff77
1404 0:6675d58eff77
1412
1405
1413
1406
1414 Invalid group
1407 Invalid group
1415
1408
1416 Disable the fakegroups trick to get real failures
1409 Disable the fakegroups trick to get real failures
1417
1410
1418 $ grep -v fakegroups $config > config.tmp
1411 $ grep -v fakegroups $config > config.tmp
1419 $ mv config.tmp $config
1412 $ mv config.tmp $config
1420 $ echo '[acl.allow]' >> $config
1413 $ echo '[acl.allow]' >> $config
1421 $ echo "** = @unlikelytoexist" >> $config
1414 $ echo "** = @unlikelytoexist" >> $config
1422 $ do_push fred 2>&1 | grep unlikelytoexist
1415 $ do_push fred 2>&1 | grep unlikelytoexist
1423 ** = @unlikelytoexist
1416 ** = @unlikelytoexist
1424 acl: "unlikelytoexist" not defined in [acl.groups]
1417 acl: "unlikelytoexist" not defined in [acl.groups]
1425 error: pretxnchangegroup.acl hook failed: group 'unlikelytoexist' is undefined
1418 error: pretxnchangegroup.acl hook failed: group 'unlikelytoexist' is undefined
1426 abort: group 'unlikelytoexist' is undefined
1419 abort: group 'unlikelytoexist' is undefined
1427
1420
1428
1421
1429 Branch acl tests setup
1422 Branch acl tests setup
1430
1423
1431 $ init_config
1424 $ init_config
1432 $ cd b
1425 $ cd b
1433 $ hg up
1426 $ hg up
1434 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1427 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1435 $ hg branch foobar
1428 $ hg branch foobar
1436 marked working directory as branch foobar
1429 marked working directory as branch foobar
1437 (branches are permanent and global, did you want a bookmark?)
1430 (branches are permanent and global, did you want a bookmark?)
1438 $ hg commit -m 'create foobar'
1431 $ hg commit -m 'create foobar'
1439 $ echo 'foo contents' > abc.txt
1432 $ echo 'foo contents' > abc.txt
1440 $ hg add abc.txt
1433 $ hg add abc.txt
1441 $ hg commit -m 'foobar contents'
1434 $ hg commit -m 'foobar contents'
1442 $ cd ..
1435 $ cd ..
1443 $ hg --cwd a pull ../b
1436 $ hg --cwd a pull ../b
1444 pulling from ../b
1437 pulling from ../b
1445 searching for changes
1438 searching for changes
1446 adding changesets
1439 adding changesets
1447 adding manifests
1440 adding manifests
1448 adding file changes
1441 adding file changes
1449 added 2 changesets with 1 changes to 1 files (+1 heads)
1442 added 2 changesets with 1 changes to 1 files (+1 heads)
1450 (run 'hg heads' to see heads)
1443 (run 'hg heads' to see heads)
1451
1444
1452 Create additional changeset on foobar branch
1445 Create additional changeset on foobar branch
1453
1446
1454 $ cd a
1447 $ cd a
1455 $ hg up -C foobar
1448 $ hg up -C foobar
1456 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1449 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1457 $ echo 'foo contents2' > abc.txt
1450 $ echo 'foo contents2' > abc.txt
1458 $ hg commit -m 'foobar contents2'
1451 $ hg commit -m 'foobar contents2'
1459 $ cd ..
1452 $ cd ..
1460
1453
1461
1454
1462 No branch acls specified
1455 No branch acls specified
1463
1456
1464 $ do_push astro
1457 $ do_push astro
1465 Pushing as user astro
1458 Pushing as user astro
1466 hgrc = """
1459 hgrc = """
1467 [hooks]
1460 [hooks]
1468 pretxnchangegroup.acl = python:hgext.acl.hook
1461 pretxnchangegroup.acl = python:hgext.acl.hook
1469 [acl]
1462 [acl]
1470 sources = push
1463 sources = push
1471 [extensions]
1464 [extensions]
1472 """
1465 """
1473 pushing to ../b
1466 pushing to ../b
1474 query 1; heads
1467 query 1; heads
1475 searching for changes
1468 searching for changes
1476 all remote heads known locally
1469 all remote heads known locally
1477 listing keys for "phases"
1470 listing keys for "phases"
1478 checking for updated bookmarks
1471 checking for updated bookmarks
1479 listing keys for "bookmarks"
1472 listing keys for "bookmarks"
1480 listing keys for "bookmarks"
1473 listing keys for "bookmarks"
1481 4 changesets found
1474 4 changesets found
1482 list of changesets:
1475 list of changesets:
1483 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1476 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1484 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1477 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1485 911600dab2ae7a9baff75958b84fe606851ce955
1478 911600dab2ae7a9baff75958b84fe606851ce955
1486 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1479 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1487 bundle2-output-bundle: "HG20", 5 parts total
1480 bundle2-output-bundle: "HG20", 5 parts total
1488 bundle2-output-part: "replycaps" 155 bytes payload
1481 bundle2-output-part: "replycaps" 155 bytes payload
1489 bundle2-output-part: "check:heads" streamed payload
1482 bundle2-output-part: "check:heads" streamed payload
1490 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1483 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1491 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1484 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1492 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1485 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1493 bundle2-input-bundle: with-transaction
1486 bundle2-input-bundle: with-transaction
1494 bundle2-input-part: "replycaps" supported
1487 bundle2-input-part: "replycaps" supported
1495 bundle2-input-part: total payload size 155
1488 bundle2-input-part: total payload size 155
1496 bundle2-input-part: "check:heads" supported
1489 bundle2-input-part: "check:heads" supported
1497 bundle2-input-part: total payload size 20
1490 bundle2-input-part: total payload size 20
1498 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1491 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1499 adding changesets
1492 adding changesets
1500 add changeset ef1ea85a6374
1493 add changeset ef1ea85a6374
1501 add changeset f9cafe1212c8
1494 add changeset f9cafe1212c8
1502 add changeset 911600dab2ae
1495 add changeset 911600dab2ae
1503 add changeset e8fc755d4d82
1496 add changeset e8fc755d4d82
1504 adding manifests
1497 adding manifests
1505 adding file changes
1498 adding file changes
1506 adding abc.txt revisions
1499 adding abc.txt revisions
1507 adding foo/Bar/file.txt revisions
1500 adding foo/Bar/file.txt revisions
1508 adding foo/file.txt revisions
1501 adding foo/file.txt revisions
1509 adding quux/file.py revisions
1502 adding quux/file.py revisions
1510 added 4 changesets with 4 changes to 4 files (+1 heads)
1503 added 4 changesets with 4 changes to 4 files (+1 heads)
1511 calling hook pretxnchangegroup.acl: hgext.acl.hook
1504 calling hook pretxnchangegroup.acl: hgext.acl.hook
1512 acl: checking access for user "astro"
1505 acl: checking access for user "astro"
1513 acl: acl.allow.branches not enabled
1506 acl: acl.allow.branches not enabled
1514 acl: acl.deny.branches not enabled
1507 acl: acl.deny.branches not enabled
1515 acl: acl.allow not enabled
1508 acl: acl.allow not enabled
1516 acl: acl.deny not enabled
1509 acl: acl.deny not enabled
1517 acl: branch access granted: "ef1ea85a6374" on branch "default"
1510 acl: branch access granted: "ef1ea85a6374" on branch "default"
1518 acl: path access granted: "ef1ea85a6374"
1511 acl: path access granted: "ef1ea85a6374"
1519 acl: branch access granted: "f9cafe1212c8" on branch "default"
1512 acl: branch access granted: "f9cafe1212c8" on branch "default"
1520 acl: path access granted: "f9cafe1212c8"
1513 acl: path access granted: "f9cafe1212c8"
1521 acl: branch access granted: "911600dab2ae" on branch "default"
1514 acl: branch access granted: "911600dab2ae" on branch "default"
1522 acl: path access granted: "911600dab2ae"
1515 acl: path access granted: "911600dab2ae"
1523 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
1516 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
1524 acl: path access granted: "e8fc755d4d82"
1517 acl: path access granted: "e8fc755d4d82"
1525 bundle2-input-part: total payload size 2101
1518 bundle2-input-part: total payload size 2101
1526 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1519 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1527 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1520 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1528 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1521 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1529 pushing key for "phases:e8fc755d4d8217ee5b0c2bb41558c40d43b92c01"
1522 pushing key for "phases:e8fc755d4d8217ee5b0c2bb41558c40d43b92c01"
1530 bundle2-input-bundle: 4 parts total
1523 bundle2-input-bundle: 4 parts total
1531 updating the branch cache
1524 updating the branch cache
1532 bundle2-output-bundle: "HG20", 3 parts total
1525 bundle2-output-bundle: "HG20", 3 parts total
1533 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1526 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1534 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1527 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1535 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1528 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1536 bundle2-input-bundle: with-transaction
1529 bundle2-input-bundle: with-transaction
1537 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1530 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1538 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1531 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1539 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1532 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1540 bundle2-input-bundle: 2 parts total
1533 bundle2-input-bundle: 2 parts total
1541 listing keys for "phases"
1534 listing keys for "phases"
1542 try to push obsolete markers to remote
1543 repository tip rolled back to revision 2 (undo push)
1535 repository tip rolled back to revision 2 (undo push)
1544 2:fb35475503ef
1536 2:fb35475503ef
1545
1537
1546
1538
1547 Branch acl deny test
1539 Branch acl deny test
1548
1540
1549 $ echo "[acl.deny.branches]" >> $config
1541 $ echo "[acl.deny.branches]" >> $config
1550 $ echo "foobar = *" >> $config
1542 $ echo "foobar = *" >> $config
1551 $ do_push astro
1543 $ do_push astro
1552 Pushing as user astro
1544 Pushing as user astro
1553 hgrc = """
1545 hgrc = """
1554 [hooks]
1546 [hooks]
1555 pretxnchangegroup.acl = python:hgext.acl.hook
1547 pretxnchangegroup.acl = python:hgext.acl.hook
1556 [acl]
1548 [acl]
1557 sources = push
1549 sources = push
1558 [extensions]
1550 [extensions]
1559 [acl.deny.branches]
1551 [acl.deny.branches]
1560 foobar = *
1552 foobar = *
1561 """
1553 """
1562 pushing to ../b
1554 pushing to ../b
1563 query 1; heads
1555 query 1; heads
1564 searching for changes
1556 searching for changes
1565 all remote heads known locally
1557 all remote heads known locally
1566 listing keys for "phases"
1558 listing keys for "phases"
1567 checking for updated bookmarks
1559 checking for updated bookmarks
1568 listing keys for "bookmarks"
1560 listing keys for "bookmarks"
1569 listing keys for "bookmarks"
1561 listing keys for "bookmarks"
1570 4 changesets found
1562 4 changesets found
1571 list of changesets:
1563 list of changesets:
1572 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1564 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1573 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1565 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1574 911600dab2ae7a9baff75958b84fe606851ce955
1566 911600dab2ae7a9baff75958b84fe606851ce955
1575 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1567 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1576 bundle2-output-bundle: "HG20", 5 parts total
1568 bundle2-output-bundle: "HG20", 5 parts total
1577 bundle2-output-part: "replycaps" 155 bytes payload
1569 bundle2-output-part: "replycaps" 155 bytes payload
1578 bundle2-output-part: "check:heads" streamed payload
1570 bundle2-output-part: "check:heads" streamed payload
1579 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1571 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1580 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1572 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1581 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1573 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1582 bundle2-input-bundle: with-transaction
1574 bundle2-input-bundle: with-transaction
1583 bundle2-input-part: "replycaps" supported
1575 bundle2-input-part: "replycaps" supported
1584 bundle2-input-part: total payload size 155
1576 bundle2-input-part: total payload size 155
1585 bundle2-input-part: "check:heads" supported
1577 bundle2-input-part: "check:heads" supported
1586 bundle2-input-part: total payload size 20
1578 bundle2-input-part: total payload size 20
1587 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1579 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1588 adding changesets
1580 adding changesets
1589 add changeset ef1ea85a6374
1581 add changeset ef1ea85a6374
1590 add changeset f9cafe1212c8
1582 add changeset f9cafe1212c8
1591 add changeset 911600dab2ae
1583 add changeset 911600dab2ae
1592 add changeset e8fc755d4d82
1584 add changeset e8fc755d4d82
1593 adding manifests
1585 adding manifests
1594 adding file changes
1586 adding file changes
1595 adding abc.txt revisions
1587 adding abc.txt revisions
1596 adding foo/Bar/file.txt revisions
1588 adding foo/Bar/file.txt revisions
1597 adding foo/file.txt revisions
1589 adding foo/file.txt revisions
1598 adding quux/file.py revisions
1590 adding quux/file.py revisions
1599 added 4 changesets with 4 changes to 4 files (+1 heads)
1591 added 4 changesets with 4 changes to 4 files (+1 heads)
1600 calling hook pretxnchangegroup.acl: hgext.acl.hook
1592 calling hook pretxnchangegroup.acl: hgext.acl.hook
1601 acl: checking access for user "astro"
1593 acl: checking access for user "astro"
1602 acl: acl.allow.branches not enabled
1594 acl: acl.allow.branches not enabled
1603 acl: acl.deny.branches enabled, 1 entries for user astro
1595 acl: acl.deny.branches enabled, 1 entries for user astro
1604 acl: acl.allow not enabled
1596 acl: acl.allow not enabled
1605 acl: acl.deny not enabled
1597 acl: acl.deny not enabled
1606 acl: branch access granted: "ef1ea85a6374" on branch "default"
1598 acl: branch access granted: "ef1ea85a6374" on branch "default"
1607 acl: path access granted: "ef1ea85a6374"
1599 acl: path access granted: "ef1ea85a6374"
1608 acl: branch access granted: "f9cafe1212c8" on branch "default"
1600 acl: branch access granted: "f9cafe1212c8" on branch "default"
1609 acl: path access granted: "f9cafe1212c8"
1601 acl: path access granted: "f9cafe1212c8"
1610 acl: branch access granted: "911600dab2ae" on branch "default"
1602 acl: branch access granted: "911600dab2ae" on branch "default"
1611 acl: path access granted: "911600dab2ae"
1603 acl: path access granted: "911600dab2ae"
1612 error: pretxnchangegroup.acl hook failed: acl: user "astro" denied on branch "foobar" (changeset "e8fc755d4d82")
1604 error: pretxnchangegroup.acl hook failed: acl: user "astro" denied on branch "foobar" (changeset "e8fc755d4d82")
1613 bundle2-input-part: total payload size 2101
1605 bundle2-input-part: total payload size 2101
1614 bundle2-input-bundle: 4 parts total
1606 bundle2-input-bundle: 4 parts total
1615 transaction abort!
1607 transaction abort!
1616 rollback completed
1608 rollback completed
1617 abort: acl: user "astro" denied on branch "foobar" (changeset "e8fc755d4d82")
1609 abort: acl: user "astro" denied on branch "foobar" (changeset "e8fc755d4d82")
1618 no rollback information available
1610 no rollback information available
1619 2:fb35475503ef
1611 2:fb35475503ef
1620
1612
1621
1613
1622 Branch acl empty allow test
1614 Branch acl empty allow test
1623
1615
1624 $ init_config
1616 $ init_config
1625 $ echo "[acl.allow.branches]" >> $config
1617 $ echo "[acl.allow.branches]" >> $config
1626 $ do_push astro
1618 $ do_push astro
1627 Pushing as user astro
1619 Pushing as user astro
1628 hgrc = """
1620 hgrc = """
1629 [hooks]
1621 [hooks]
1630 pretxnchangegroup.acl = python:hgext.acl.hook
1622 pretxnchangegroup.acl = python:hgext.acl.hook
1631 [acl]
1623 [acl]
1632 sources = push
1624 sources = push
1633 [extensions]
1625 [extensions]
1634 [acl.allow.branches]
1626 [acl.allow.branches]
1635 """
1627 """
1636 pushing to ../b
1628 pushing to ../b
1637 query 1; heads
1629 query 1; heads
1638 searching for changes
1630 searching for changes
1639 all remote heads known locally
1631 all remote heads known locally
1640 listing keys for "phases"
1632 listing keys for "phases"
1641 checking for updated bookmarks
1633 checking for updated bookmarks
1642 listing keys for "bookmarks"
1634 listing keys for "bookmarks"
1643 listing keys for "bookmarks"
1635 listing keys for "bookmarks"
1644 4 changesets found
1636 4 changesets found
1645 list of changesets:
1637 list of changesets:
1646 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1638 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1647 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1639 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1648 911600dab2ae7a9baff75958b84fe606851ce955
1640 911600dab2ae7a9baff75958b84fe606851ce955
1649 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1641 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1650 bundle2-output-bundle: "HG20", 5 parts total
1642 bundle2-output-bundle: "HG20", 5 parts total
1651 bundle2-output-part: "replycaps" 155 bytes payload
1643 bundle2-output-part: "replycaps" 155 bytes payload
1652 bundle2-output-part: "check:heads" streamed payload
1644 bundle2-output-part: "check:heads" streamed payload
1653 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1645 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1654 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1646 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1655 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1647 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1656 bundle2-input-bundle: with-transaction
1648 bundle2-input-bundle: with-transaction
1657 bundle2-input-part: "replycaps" supported
1649 bundle2-input-part: "replycaps" supported
1658 bundle2-input-part: total payload size 155
1650 bundle2-input-part: total payload size 155
1659 bundle2-input-part: "check:heads" supported
1651 bundle2-input-part: "check:heads" supported
1660 bundle2-input-part: total payload size 20
1652 bundle2-input-part: total payload size 20
1661 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1653 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1662 adding changesets
1654 adding changesets
1663 add changeset ef1ea85a6374
1655 add changeset ef1ea85a6374
1664 add changeset f9cafe1212c8
1656 add changeset f9cafe1212c8
1665 add changeset 911600dab2ae
1657 add changeset 911600dab2ae
1666 add changeset e8fc755d4d82
1658 add changeset e8fc755d4d82
1667 adding manifests
1659 adding manifests
1668 adding file changes
1660 adding file changes
1669 adding abc.txt revisions
1661 adding abc.txt revisions
1670 adding foo/Bar/file.txt revisions
1662 adding foo/Bar/file.txt revisions
1671 adding foo/file.txt revisions
1663 adding foo/file.txt revisions
1672 adding quux/file.py revisions
1664 adding quux/file.py revisions
1673 added 4 changesets with 4 changes to 4 files (+1 heads)
1665 added 4 changesets with 4 changes to 4 files (+1 heads)
1674 calling hook pretxnchangegroup.acl: hgext.acl.hook
1666 calling hook pretxnchangegroup.acl: hgext.acl.hook
1675 acl: checking access for user "astro"
1667 acl: checking access for user "astro"
1676 acl: acl.allow.branches enabled, 0 entries for user astro
1668 acl: acl.allow.branches enabled, 0 entries for user astro
1677 acl: acl.deny.branches not enabled
1669 acl: acl.deny.branches not enabled
1678 acl: acl.allow not enabled
1670 acl: acl.allow not enabled
1679 acl: acl.deny not enabled
1671 acl: acl.deny not enabled
1680 error: pretxnchangegroup.acl hook failed: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1672 error: pretxnchangegroup.acl hook failed: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1681 bundle2-input-part: total payload size 2101
1673 bundle2-input-part: total payload size 2101
1682 bundle2-input-bundle: 4 parts total
1674 bundle2-input-bundle: 4 parts total
1683 transaction abort!
1675 transaction abort!
1684 rollback completed
1676 rollback completed
1685 abort: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1677 abort: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1686 no rollback information available
1678 no rollback information available
1687 2:fb35475503ef
1679 2:fb35475503ef
1688
1680
1689
1681
1690 Branch acl allow other
1682 Branch acl allow other
1691
1683
1692 $ init_config
1684 $ init_config
1693 $ echo "[acl.allow.branches]" >> $config
1685 $ echo "[acl.allow.branches]" >> $config
1694 $ echo "* = george" >> $config
1686 $ echo "* = george" >> $config
1695 $ do_push astro
1687 $ do_push astro
1696 Pushing as user astro
1688 Pushing as user astro
1697 hgrc = """
1689 hgrc = """
1698 [hooks]
1690 [hooks]
1699 pretxnchangegroup.acl = python:hgext.acl.hook
1691 pretxnchangegroup.acl = python:hgext.acl.hook
1700 [acl]
1692 [acl]
1701 sources = push
1693 sources = push
1702 [extensions]
1694 [extensions]
1703 [acl.allow.branches]
1695 [acl.allow.branches]
1704 * = george
1696 * = george
1705 """
1697 """
1706 pushing to ../b
1698 pushing to ../b
1707 query 1; heads
1699 query 1; heads
1708 searching for changes
1700 searching for changes
1709 all remote heads known locally
1701 all remote heads known locally
1710 listing keys for "phases"
1702 listing keys for "phases"
1711 checking for updated bookmarks
1703 checking for updated bookmarks
1712 listing keys for "bookmarks"
1704 listing keys for "bookmarks"
1713 listing keys for "bookmarks"
1705 listing keys for "bookmarks"
1714 4 changesets found
1706 4 changesets found
1715 list of changesets:
1707 list of changesets:
1716 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1708 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1717 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1709 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1718 911600dab2ae7a9baff75958b84fe606851ce955
1710 911600dab2ae7a9baff75958b84fe606851ce955
1719 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1711 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1720 bundle2-output-bundle: "HG20", 5 parts total
1712 bundle2-output-bundle: "HG20", 5 parts total
1721 bundle2-output-part: "replycaps" 155 bytes payload
1713 bundle2-output-part: "replycaps" 155 bytes payload
1722 bundle2-output-part: "check:heads" streamed payload
1714 bundle2-output-part: "check:heads" streamed payload
1723 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1715 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1724 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1716 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1725 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1717 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1726 bundle2-input-bundle: with-transaction
1718 bundle2-input-bundle: with-transaction
1727 bundle2-input-part: "replycaps" supported
1719 bundle2-input-part: "replycaps" supported
1728 bundle2-input-part: total payload size 155
1720 bundle2-input-part: total payload size 155
1729 bundle2-input-part: "check:heads" supported
1721 bundle2-input-part: "check:heads" supported
1730 bundle2-input-part: total payload size 20
1722 bundle2-input-part: total payload size 20
1731 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1723 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1732 adding changesets
1724 adding changesets
1733 add changeset ef1ea85a6374
1725 add changeset ef1ea85a6374
1734 add changeset f9cafe1212c8
1726 add changeset f9cafe1212c8
1735 add changeset 911600dab2ae
1727 add changeset 911600dab2ae
1736 add changeset e8fc755d4d82
1728 add changeset e8fc755d4d82
1737 adding manifests
1729 adding manifests
1738 adding file changes
1730 adding file changes
1739 adding abc.txt revisions
1731 adding abc.txt revisions
1740 adding foo/Bar/file.txt revisions
1732 adding foo/Bar/file.txt revisions
1741 adding foo/file.txt revisions
1733 adding foo/file.txt revisions
1742 adding quux/file.py revisions
1734 adding quux/file.py revisions
1743 added 4 changesets with 4 changes to 4 files (+1 heads)
1735 added 4 changesets with 4 changes to 4 files (+1 heads)
1744 calling hook pretxnchangegroup.acl: hgext.acl.hook
1736 calling hook pretxnchangegroup.acl: hgext.acl.hook
1745 acl: checking access for user "astro"
1737 acl: checking access for user "astro"
1746 acl: acl.allow.branches enabled, 0 entries for user astro
1738 acl: acl.allow.branches enabled, 0 entries for user astro
1747 acl: acl.deny.branches not enabled
1739 acl: acl.deny.branches not enabled
1748 acl: acl.allow not enabled
1740 acl: acl.allow not enabled
1749 acl: acl.deny not enabled
1741 acl: acl.deny not enabled
1750 error: pretxnchangegroup.acl hook failed: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1742 error: pretxnchangegroup.acl hook failed: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1751 bundle2-input-part: total payload size 2101
1743 bundle2-input-part: total payload size 2101
1752 bundle2-input-bundle: 4 parts total
1744 bundle2-input-bundle: 4 parts total
1753 transaction abort!
1745 transaction abort!
1754 rollback completed
1746 rollback completed
1755 abort: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1747 abort: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1756 no rollback information available
1748 no rollback information available
1757 2:fb35475503ef
1749 2:fb35475503ef
1758
1750
1759 $ do_push george
1751 $ do_push george
1760 Pushing as user george
1752 Pushing as user george
1761 hgrc = """
1753 hgrc = """
1762 [hooks]
1754 [hooks]
1763 pretxnchangegroup.acl = python:hgext.acl.hook
1755 pretxnchangegroup.acl = python:hgext.acl.hook
1764 [acl]
1756 [acl]
1765 sources = push
1757 sources = push
1766 [extensions]
1758 [extensions]
1767 [acl.allow.branches]
1759 [acl.allow.branches]
1768 * = george
1760 * = george
1769 """
1761 """
1770 pushing to ../b
1762 pushing to ../b
1771 query 1; heads
1763 query 1; heads
1772 searching for changes
1764 searching for changes
1773 all remote heads known locally
1765 all remote heads known locally
1774 listing keys for "phases"
1766 listing keys for "phases"
1775 checking for updated bookmarks
1767 checking for updated bookmarks
1776 listing keys for "bookmarks"
1768 listing keys for "bookmarks"
1777 listing keys for "bookmarks"
1769 listing keys for "bookmarks"
1778 4 changesets found
1770 4 changesets found
1779 list of changesets:
1771 list of changesets:
1780 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1772 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1781 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1773 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1782 911600dab2ae7a9baff75958b84fe606851ce955
1774 911600dab2ae7a9baff75958b84fe606851ce955
1783 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1775 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1784 bundle2-output-bundle: "HG20", 5 parts total
1776 bundle2-output-bundle: "HG20", 5 parts total
1785 bundle2-output-part: "replycaps" 155 bytes payload
1777 bundle2-output-part: "replycaps" 155 bytes payload
1786 bundle2-output-part: "check:heads" streamed payload
1778 bundle2-output-part: "check:heads" streamed payload
1787 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1779 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1788 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1780 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1789 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1781 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1790 bundle2-input-bundle: with-transaction
1782 bundle2-input-bundle: with-transaction
1791 bundle2-input-part: "replycaps" supported
1783 bundle2-input-part: "replycaps" supported
1792 bundle2-input-part: total payload size 155
1784 bundle2-input-part: total payload size 155
1793 bundle2-input-part: "check:heads" supported
1785 bundle2-input-part: "check:heads" supported
1794 bundle2-input-part: total payload size 20
1786 bundle2-input-part: total payload size 20
1795 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1787 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1796 adding changesets
1788 adding changesets
1797 add changeset ef1ea85a6374
1789 add changeset ef1ea85a6374
1798 add changeset f9cafe1212c8
1790 add changeset f9cafe1212c8
1799 add changeset 911600dab2ae
1791 add changeset 911600dab2ae
1800 add changeset e8fc755d4d82
1792 add changeset e8fc755d4d82
1801 adding manifests
1793 adding manifests
1802 adding file changes
1794 adding file changes
1803 adding abc.txt revisions
1795 adding abc.txt revisions
1804 adding foo/Bar/file.txt revisions
1796 adding foo/Bar/file.txt revisions
1805 adding foo/file.txt revisions
1797 adding foo/file.txt revisions
1806 adding quux/file.py revisions
1798 adding quux/file.py revisions
1807 added 4 changesets with 4 changes to 4 files (+1 heads)
1799 added 4 changesets with 4 changes to 4 files (+1 heads)
1808 calling hook pretxnchangegroup.acl: hgext.acl.hook
1800 calling hook pretxnchangegroup.acl: hgext.acl.hook
1809 acl: checking access for user "george"
1801 acl: checking access for user "george"
1810 acl: acl.allow.branches enabled, 1 entries for user george
1802 acl: acl.allow.branches enabled, 1 entries for user george
1811 acl: acl.deny.branches not enabled
1803 acl: acl.deny.branches not enabled
1812 acl: acl.allow not enabled
1804 acl: acl.allow not enabled
1813 acl: acl.deny not enabled
1805 acl: acl.deny not enabled
1814 acl: branch access granted: "ef1ea85a6374" on branch "default"
1806 acl: branch access granted: "ef1ea85a6374" on branch "default"
1815 acl: path access granted: "ef1ea85a6374"
1807 acl: path access granted: "ef1ea85a6374"
1816 acl: branch access granted: "f9cafe1212c8" on branch "default"
1808 acl: branch access granted: "f9cafe1212c8" on branch "default"
1817 acl: path access granted: "f9cafe1212c8"
1809 acl: path access granted: "f9cafe1212c8"
1818 acl: branch access granted: "911600dab2ae" on branch "default"
1810 acl: branch access granted: "911600dab2ae" on branch "default"
1819 acl: path access granted: "911600dab2ae"
1811 acl: path access granted: "911600dab2ae"
1820 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
1812 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
1821 acl: path access granted: "e8fc755d4d82"
1813 acl: path access granted: "e8fc755d4d82"
1822 bundle2-input-part: total payload size 2101
1814 bundle2-input-part: total payload size 2101
1823 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1815 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1824 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1816 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1825 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1817 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1826 pushing key for "phases:e8fc755d4d8217ee5b0c2bb41558c40d43b92c01"
1818 pushing key for "phases:e8fc755d4d8217ee5b0c2bb41558c40d43b92c01"
1827 bundle2-input-bundle: 4 parts total
1819 bundle2-input-bundle: 4 parts total
1828 updating the branch cache
1820 updating the branch cache
1829 bundle2-output-bundle: "HG20", 3 parts total
1821 bundle2-output-bundle: "HG20", 3 parts total
1830 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1822 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1831 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1823 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1832 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1824 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1833 bundle2-input-bundle: with-transaction
1825 bundle2-input-bundle: with-transaction
1834 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1826 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1835 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1827 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1836 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1828 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1837 bundle2-input-bundle: 2 parts total
1829 bundle2-input-bundle: 2 parts total
1838 listing keys for "phases"
1830 listing keys for "phases"
1839 try to push obsolete markers to remote
1840 repository tip rolled back to revision 2 (undo push)
1831 repository tip rolled back to revision 2 (undo push)
1841 2:fb35475503ef
1832 2:fb35475503ef
1842
1833
1843
1834
1844 Branch acl conflicting allow
1835 Branch acl conflicting allow
1845 asterisk ends up applying to all branches and allowing george to
1836 asterisk ends up applying to all branches and allowing george to
1846 push foobar into the remote
1837 push foobar into the remote
1847
1838
1848 $ init_config
1839 $ init_config
1849 $ echo "[acl.allow.branches]" >> $config
1840 $ echo "[acl.allow.branches]" >> $config
1850 $ echo "foobar = astro" >> $config
1841 $ echo "foobar = astro" >> $config
1851 $ echo "* = george" >> $config
1842 $ echo "* = george" >> $config
1852 $ do_push george
1843 $ do_push george
1853 Pushing as user george
1844 Pushing as user george
1854 hgrc = """
1845 hgrc = """
1855 [hooks]
1846 [hooks]
1856 pretxnchangegroup.acl = python:hgext.acl.hook
1847 pretxnchangegroup.acl = python:hgext.acl.hook
1857 [acl]
1848 [acl]
1858 sources = push
1849 sources = push
1859 [extensions]
1850 [extensions]
1860 [acl.allow.branches]
1851 [acl.allow.branches]
1861 foobar = astro
1852 foobar = astro
1862 * = george
1853 * = george
1863 """
1854 """
1864 pushing to ../b
1855 pushing to ../b
1865 query 1; heads
1856 query 1; heads
1866 searching for changes
1857 searching for changes
1867 all remote heads known locally
1858 all remote heads known locally
1868 listing keys for "phases"
1859 listing keys for "phases"
1869 checking for updated bookmarks
1860 checking for updated bookmarks
1870 listing keys for "bookmarks"
1861 listing keys for "bookmarks"
1871 listing keys for "bookmarks"
1862 listing keys for "bookmarks"
1872 4 changesets found
1863 4 changesets found
1873 list of changesets:
1864 list of changesets:
1874 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1865 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1875 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1866 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1876 911600dab2ae7a9baff75958b84fe606851ce955
1867 911600dab2ae7a9baff75958b84fe606851ce955
1877 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1868 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1878 bundle2-output-bundle: "HG20", 5 parts total
1869 bundle2-output-bundle: "HG20", 5 parts total
1879 bundle2-output-part: "replycaps" 155 bytes payload
1870 bundle2-output-part: "replycaps" 155 bytes payload
1880 bundle2-output-part: "check:heads" streamed payload
1871 bundle2-output-part: "check:heads" streamed payload
1881 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1872 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1882 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1873 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1883 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1874 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1884 bundle2-input-bundle: with-transaction
1875 bundle2-input-bundle: with-transaction
1885 bundle2-input-part: "replycaps" supported
1876 bundle2-input-part: "replycaps" supported
1886 bundle2-input-part: total payload size 155
1877 bundle2-input-part: total payload size 155
1887 bundle2-input-part: "check:heads" supported
1878 bundle2-input-part: "check:heads" supported
1888 bundle2-input-part: total payload size 20
1879 bundle2-input-part: total payload size 20
1889 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1880 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1890 adding changesets
1881 adding changesets
1891 add changeset ef1ea85a6374
1882 add changeset ef1ea85a6374
1892 add changeset f9cafe1212c8
1883 add changeset f9cafe1212c8
1893 add changeset 911600dab2ae
1884 add changeset 911600dab2ae
1894 add changeset e8fc755d4d82
1885 add changeset e8fc755d4d82
1895 adding manifests
1886 adding manifests
1896 adding file changes
1887 adding file changes
1897 adding abc.txt revisions
1888 adding abc.txt revisions
1898 adding foo/Bar/file.txt revisions
1889 adding foo/Bar/file.txt revisions
1899 adding foo/file.txt revisions
1890 adding foo/file.txt revisions
1900 adding quux/file.py revisions
1891 adding quux/file.py revisions
1901 added 4 changesets with 4 changes to 4 files (+1 heads)
1892 added 4 changesets with 4 changes to 4 files (+1 heads)
1902 calling hook pretxnchangegroup.acl: hgext.acl.hook
1893 calling hook pretxnchangegroup.acl: hgext.acl.hook
1903 acl: checking access for user "george"
1894 acl: checking access for user "george"
1904 acl: acl.allow.branches enabled, 1 entries for user george
1895 acl: acl.allow.branches enabled, 1 entries for user george
1905 acl: acl.deny.branches not enabled
1896 acl: acl.deny.branches not enabled
1906 acl: acl.allow not enabled
1897 acl: acl.allow not enabled
1907 acl: acl.deny not enabled
1898 acl: acl.deny not enabled
1908 acl: branch access granted: "ef1ea85a6374" on branch "default"
1899 acl: branch access granted: "ef1ea85a6374" on branch "default"
1909 acl: path access granted: "ef1ea85a6374"
1900 acl: path access granted: "ef1ea85a6374"
1910 acl: branch access granted: "f9cafe1212c8" on branch "default"
1901 acl: branch access granted: "f9cafe1212c8" on branch "default"
1911 acl: path access granted: "f9cafe1212c8"
1902 acl: path access granted: "f9cafe1212c8"
1912 acl: branch access granted: "911600dab2ae" on branch "default"
1903 acl: branch access granted: "911600dab2ae" on branch "default"
1913 acl: path access granted: "911600dab2ae"
1904 acl: path access granted: "911600dab2ae"
1914 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
1905 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
1915 acl: path access granted: "e8fc755d4d82"
1906 acl: path access granted: "e8fc755d4d82"
1916 bundle2-input-part: total payload size 2101
1907 bundle2-input-part: total payload size 2101
1917 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1908 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1918 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1909 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
1919 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1910 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
1920 pushing key for "phases:e8fc755d4d8217ee5b0c2bb41558c40d43b92c01"
1911 pushing key for "phases:e8fc755d4d8217ee5b0c2bb41558c40d43b92c01"
1921 bundle2-input-bundle: 4 parts total
1912 bundle2-input-bundle: 4 parts total
1922 updating the branch cache
1913 updating the branch cache
1923 bundle2-output-bundle: "HG20", 3 parts total
1914 bundle2-output-bundle: "HG20", 3 parts total
1924 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1915 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1925 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1916 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1926 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1917 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
1927 bundle2-input-bundle: with-transaction
1918 bundle2-input-bundle: with-transaction
1928 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1919 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1929 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1920 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1930 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1921 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
1931 bundle2-input-bundle: 2 parts total
1922 bundle2-input-bundle: 2 parts total
1932 listing keys for "phases"
1923 listing keys for "phases"
1933 try to push obsolete markers to remote
1934 repository tip rolled back to revision 2 (undo push)
1924 repository tip rolled back to revision 2 (undo push)
1935 2:fb35475503ef
1925 2:fb35475503ef
1936
1926
1937 Branch acl conflicting deny
1927 Branch acl conflicting deny
1938
1928
1939 $ init_config
1929 $ init_config
1940 $ echo "[acl.deny.branches]" >> $config
1930 $ echo "[acl.deny.branches]" >> $config
1941 $ echo "foobar = astro" >> $config
1931 $ echo "foobar = astro" >> $config
1942 $ echo "default = astro" >> $config
1932 $ echo "default = astro" >> $config
1943 $ echo "* = george" >> $config
1933 $ echo "* = george" >> $config
1944 $ do_push george
1934 $ do_push george
1945 Pushing as user george
1935 Pushing as user george
1946 hgrc = """
1936 hgrc = """
1947 [hooks]
1937 [hooks]
1948 pretxnchangegroup.acl = python:hgext.acl.hook
1938 pretxnchangegroup.acl = python:hgext.acl.hook
1949 [acl]
1939 [acl]
1950 sources = push
1940 sources = push
1951 [extensions]
1941 [extensions]
1952 [acl.deny.branches]
1942 [acl.deny.branches]
1953 foobar = astro
1943 foobar = astro
1954 default = astro
1944 default = astro
1955 * = george
1945 * = george
1956 """
1946 """
1957 pushing to ../b
1947 pushing to ../b
1958 query 1; heads
1948 query 1; heads
1959 searching for changes
1949 searching for changes
1960 all remote heads known locally
1950 all remote heads known locally
1961 listing keys for "phases"
1951 listing keys for "phases"
1962 checking for updated bookmarks
1952 checking for updated bookmarks
1963 listing keys for "bookmarks"
1953 listing keys for "bookmarks"
1964 listing keys for "bookmarks"
1954 listing keys for "bookmarks"
1965 4 changesets found
1955 4 changesets found
1966 list of changesets:
1956 list of changesets:
1967 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1957 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1968 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1958 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1969 911600dab2ae7a9baff75958b84fe606851ce955
1959 911600dab2ae7a9baff75958b84fe606851ce955
1970 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1960 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1971 bundle2-output-bundle: "HG20", 5 parts total
1961 bundle2-output-bundle: "HG20", 5 parts total
1972 bundle2-output-part: "replycaps" 155 bytes payload
1962 bundle2-output-part: "replycaps" 155 bytes payload
1973 bundle2-output-part: "check:heads" streamed payload
1963 bundle2-output-part: "check:heads" streamed payload
1974 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1964 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1975 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1965 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1976 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1966 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
1977 bundle2-input-bundle: with-transaction
1967 bundle2-input-bundle: with-transaction
1978 bundle2-input-part: "replycaps" supported
1968 bundle2-input-part: "replycaps" supported
1979 bundle2-input-part: total payload size 155
1969 bundle2-input-part: total payload size 155
1980 bundle2-input-part: "check:heads" supported
1970 bundle2-input-part: "check:heads" supported
1981 bundle2-input-part: total payload size 20
1971 bundle2-input-part: total payload size 20
1982 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1972 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1983 adding changesets
1973 adding changesets
1984 add changeset ef1ea85a6374
1974 add changeset ef1ea85a6374
1985 add changeset f9cafe1212c8
1975 add changeset f9cafe1212c8
1986 add changeset 911600dab2ae
1976 add changeset 911600dab2ae
1987 add changeset e8fc755d4d82
1977 add changeset e8fc755d4d82
1988 adding manifests
1978 adding manifests
1989 adding file changes
1979 adding file changes
1990 adding abc.txt revisions
1980 adding abc.txt revisions
1991 adding foo/Bar/file.txt revisions
1981 adding foo/Bar/file.txt revisions
1992 adding foo/file.txt revisions
1982 adding foo/file.txt revisions
1993 adding quux/file.py revisions
1983 adding quux/file.py revisions
1994 added 4 changesets with 4 changes to 4 files (+1 heads)
1984 added 4 changesets with 4 changes to 4 files (+1 heads)
1995 calling hook pretxnchangegroup.acl: hgext.acl.hook
1985 calling hook pretxnchangegroup.acl: hgext.acl.hook
1996 acl: checking access for user "george"
1986 acl: checking access for user "george"
1997 acl: acl.allow.branches not enabled
1987 acl: acl.allow.branches not enabled
1998 acl: acl.deny.branches enabled, 1 entries for user george
1988 acl: acl.deny.branches enabled, 1 entries for user george
1999 acl: acl.allow not enabled
1989 acl: acl.allow not enabled
2000 acl: acl.deny not enabled
1990 acl: acl.deny not enabled
2001 error: pretxnchangegroup.acl hook failed: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
1991 error: pretxnchangegroup.acl hook failed: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2002 bundle2-input-part: total payload size 2101
1992 bundle2-input-part: total payload size 2101
2003 bundle2-input-bundle: 4 parts total
1993 bundle2-input-bundle: 4 parts total
2004 transaction abort!
1994 transaction abort!
2005 rollback completed
1995 rollback completed
2006 abort: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
1996 abort: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2007 no rollback information available
1997 no rollback information available
2008 2:fb35475503ef
1998 2:fb35475503ef
2009
1999
2010 User 'astro' must not be denied
2000 User 'astro' must not be denied
2011
2001
2012 $ init_config
2002 $ init_config
2013 $ echo "[acl.deny.branches]" >> $config
2003 $ echo "[acl.deny.branches]" >> $config
2014 $ echo "default = !astro" >> $config
2004 $ echo "default = !astro" >> $config
2015 $ do_push astro
2005 $ do_push astro
2016 Pushing as user astro
2006 Pushing as user astro
2017 hgrc = """
2007 hgrc = """
2018 [hooks]
2008 [hooks]
2019 pretxnchangegroup.acl = python:hgext.acl.hook
2009 pretxnchangegroup.acl = python:hgext.acl.hook
2020 [acl]
2010 [acl]
2021 sources = push
2011 sources = push
2022 [extensions]
2012 [extensions]
2023 [acl.deny.branches]
2013 [acl.deny.branches]
2024 default = !astro
2014 default = !astro
2025 """
2015 """
2026 pushing to ../b
2016 pushing to ../b
2027 query 1; heads
2017 query 1; heads
2028 searching for changes
2018 searching for changes
2029 all remote heads known locally
2019 all remote heads known locally
2030 listing keys for "phases"
2020 listing keys for "phases"
2031 checking for updated bookmarks
2021 checking for updated bookmarks
2032 listing keys for "bookmarks"
2022 listing keys for "bookmarks"
2033 listing keys for "bookmarks"
2023 listing keys for "bookmarks"
2034 4 changesets found
2024 4 changesets found
2035 list of changesets:
2025 list of changesets:
2036 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
2026 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
2037 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
2027 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
2038 911600dab2ae7a9baff75958b84fe606851ce955
2028 911600dab2ae7a9baff75958b84fe606851ce955
2039 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
2029 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
2040 bundle2-output-bundle: "HG20", 5 parts total
2030 bundle2-output-bundle: "HG20", 5 parts total
2041 bundle2-output-part: "replycaps" 155 bytes payload
2031 bundle2-output-part: "replycaps" 155 bytes payload
2042 bundle2-output-part: "check:heads" streamed payload
2032 bundle2-output-part: "check:heads" streamed payload
2043 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
2033 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
2044 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2034 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2045 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2035 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2046 bundle2-input-bundle: with-transaction
2036 bundle2-input-bundle: with-transaction
2047 bundle2-input-part: "replycaps" supported
2037 bundle2-input-part: "replycaps" supported
2048 bundle2-input-part: total payload size 155
2038 bundle2-input-part: total payload size 155
2049 bundle2-input-part: "check:heads" supported
2039 bundle2-input-part: "check:heads" supported
2050 bundle2-input-part: total payload size 20
2040 bundle2-input-part: total payload size 20
2051 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
2041 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
2052 adding changesets
2042 adding changesets
2053 add changeset ef1ea85a6374
2043 add changeset ef1ea85a6374
2054 add changeset f9cafe1212c8
2044 add changeset f9cafe1212c8
2055 add changeset 911600dab2ae
2045 add changeset 911600dab2ae
2056 add changeset e8fc755d4d82
2046 add changeset e8fc755d4d82
2057 adding manifests
2047 adding manifests
2058 adding file changes
2048 adding file changes
2059 adding abc.txt revisions
2049 adding abc.txt revisions
2060 adding foo/Bar/file.txt revisions
2050 adding foo/Bar/file.txt revisions
2061 adding foo/file.txt revisions
2051 adding foo/file.txt revisions
2062 adding quux/file.py revisions
2052 adding quux/file.py revisions
2063 added 4 changesets with 4 changes to 4 files (+1 heads)
2053 added 4 changesets with 4 changes to 4 files (+1 heads)
2064 calling hook pretxnchangegroup.acl: hgext.acl.hook
2054 calling hook pretxnchangegroup.acl: hgext.acl.hook
2065 acl: checking access for user "astro"
2055 acl: checking access for user "astro"
2066 acl: acl.allow.branches not enabled
2056 acl: acl.allow.branches not enabled
2067 acl: acl.deny.branches enabled, 0 entries for user astro
2057 acl: acl.deny.branches enabled, 0 entries for user astro
2068 acl: acl.allow not enabled
2058 acl: acl.allow not enabled
2069 acl: acl.deny not enabled
2059 acl: acl.deny not enabled
2070 acl: branch access granted: "ef1ea85a6374" on branch "default"
2060 acl: branch access granted: "ef1ea85a6374" on branch "default"
2071 acl: path access granted: "ef1ea85a6374"
2061 acl: path access granted: "ef1ea85a6374"
2072 acl: branch access granted: "f9cafe1212c8" on branch "default"
2062 acl: branch access granted: "f9cafe1212c8" on branch "default"
2073 acl: path access granted: "f9cafe1212c8"
2063 acl: path access granted: "f9cafe1212c8"
2074 acl: branch access granted: "911600dab2ae" on branch "default"
2064 acl: branch access granted: "911600dab2ae" on branch "default"
2075 acl: path access granted: "911600dab2ae"
2065 acl: path access granted: "911600dab2ae"
2076 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
2066 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
2077 acl: path access granted: "e8fc755d4d82"
2067 acl: path access granted: "e8fc755d4d82"
2078 bundle2-input-part: total payload size 2101
2068 bundle2-input-part: total payload size 2101
2079 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
2069 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
2080 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
2070 pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
2081 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
2071 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
2082 pushing key for "phases:e8fc755d4d8217ee5b0c2bb41558c40d43b92c01"
2072 pushing key for "phases:e8fc755d4d8217ee5b0c2bb41558c40d43b92c01"
2083 bundle2-input-bundle: 4 parts total
2073 bundle2-input-bundle: 4 parts total
2084 updating the branch cache
2074 updating the branch cache
2085 bundle2-output-bundle: "HG20", 3 parts total
2075 bundle2-output-bundle: "HG20", 3 parts total
2086 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
2076 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
2087 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
2077 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
2088 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
2078 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
2089 bundle2-input-bundle: with-transaction
2079 bundle2-input-bundle: with-transaction
2090 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
2080 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
2091 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
2081 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
2092 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
2082 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
2093 bundle2-input-bundle: 2 parts total
2083 bundle2-input-bundle: 2 parts total
2094 listing keys for "phases"
2084 listing keys for "phases"
2095 try to push obsolete markers to remote
2096 repository tip rolled back to revision 2 (undo push)
2085 repository tip rolled back to revision 2 (undo push)
2097 2:fb35475503ef
2086 2:fb35475503ef
2098
2087
2099
2088
2100 Non-astro users must be denied
2089 Non-astro users must be denied
2101
2090
2102 $ do_push george
2091 $ do_push george
2103 Pushing as user george
2092 Pushing as user george
2104 hgrc = """
2093 hgrc = """
2105 [hooks]
2094 [hooks]
2106 pretxnchangegroup.acl = python:hgext.acl.hook
2095 pretxnchangegroup.acl = python:hgext.acl.hook
2107 [acl]
2096 [acl]
2108 sources = push
2097 sources = push
2109 [extensions]
2098 [extensions]
2110 [acl.deny.branches]
2099 [acl.deny.branches]
2111 default = !astro
2100 default = !astro
2112 """
2101 """
2113 pushing to ../b
2102 pushing to ../b
2114 query 1; heads
2103 query 1; heads
2115 searching for changes
2104 searching for changes
2116 all remote heads known locally
2105 all remote heads known locally
2117 listing keys for "phases"
2106 listing keys for "phases"
2118 checking for updated bookmarks
2107 checking for updated bookmarks
2119 listing keys for "bookmarks"
2108 listing keys for "bookmarks"
2120 listing keys for "bookmarks"
2109 listing keys for "bookmarks"
2121 4 changesets found
2110 4 changesets found
2122 list of changesets:
2111 list of changesets:
2123 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
2112 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
2124 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
2113 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
2125 911600dab2ae7a9baff75958b84fe606851ce955
2114 911600dab2ae7a9baff75958b84fe606851ce955
2126 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
2115 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
2127 bundle2-output-bundle: "HG20", 5 parts total
2116 bundle2-output-bundle: "HG20", 5 parts total
2128 bundle2-output-part: "replycaps" 155 bytes payload
2117 bundle2-output-part: "replycaps" 155 bytes payload
2129 bundle2-output-part: "check:heads" streamed payload
2118 bundle2-output-part: "check:heads" streamed payload
2130 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
2119 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
2131 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2120 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2132 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2121 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
2133 bundle2-input-bundle: with-transaction
2122 bundle2-input-bundle: with-transaction
2134 bundle2-input-part: "replycaps" supported
2123 bundle2-input-part: "replycaps" supported
2135 bundle2-input-part: total payload size 155
2124 bundle2-input-part: total payload size 155
2136 bundle2-input-part: "check:heads" supported
2125 bundle2-input-part: "check:heads" supported
2137 bundle2-input-part: total payload size 20
2126 bundle2-input-part: total payload size 20
2138 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
2127 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
2139 adding changesets
2128 adding changesets
2140 add changeset ef1ea85a6374
2129 add changeset ef1ea85a6374
2141 add changeset f9cafe1212c8
2130 add changeset f9cafe1212c8
2142 add changeset 911600dab2ae
2131 add changeset 911600dab2ae
2143 add changeset e8fc755d4d82
2132 add changeset e8fc755d4d82
2144 adding manifests
2133 adding manifests
2145 adding file changes
2134 adding file changes
2146 adding abc.txt revisions
2135 adding abc.txt revisions
2147 adding foo/Bar/file.txt revisions
2136 adding foo/Bar/file.txt revisions
2148 adding foo/file.txt revisions
2137 adding foo/file.txt revisions
2149 adding quux/file.py revisions
2138 adding quux/file.py revisions
2150 added 4 changesets with 4 changes to 4 files (+1 heads)
2139 added 4 changesets with 4 changes to 4 files (+1 heads)
2151 calling hook pretxnchangegroup.acl: hgext.acl.hook
2140 calling hook pretxnchangegroup.acl: hgext.acl.hook
2152 acl: checking access for user "george"
2141 acl: checking access for user "george"
2153 acl: acl.allow.branches not enabled
2142 acl: acl.allow.branches not enabled
2154 acl: acl.deny.branches enabled, 1 entries for user george
2143 acl: acl.deny.branches enabled, 1 entries for user george
2155 acl: acl.allow not enabled
2144 acl: acl.allow not enabled
2156 acl: acl.deny not enabled
2145 acl: acl.deny not enabled
2157 error: pretxnchangegroup.acl hook failed: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2146 error: pretxnchangegroup.acl hook failed: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2158 bundle2-input-part: total payload size 2101
2147 bundle2-input-part: total payload size 2101
2159 bundle2-input-bundle: 4 parts total
2148 bundle2-input-bundle: 4 parts total
2160 transaction abort!
2149 transaction abort!
2161 rollback completed
2150 rollback completed
2162 abort: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2151 abort: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2163 no rollback information available
2152 no rollback information available
2164 2:fb35475503ef
2153 2:fb35475503ef
2165
2154
2166
2155
General Comments 0
You need to be logged in to leave comments. Login now