##// END OF EJS Templates
phases: read pending data when appropriate...
Pierre-Yves David -
r23361:936b0ff3 default
parent child Browse files
Show More
@@ -1,436 +1,445 b''
1 """ Mercurial phases support code
1 """ Mercurial phases support code
2
2
3 ---
3 ---
4
4
5 Copyright 2011 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
5 Copyright 2011 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
6 Logilab SA <contact@logilab.fr>
6 Logilab SA <contact@logilab.fr>
7 Augie Fackler <durin42@gmail.com>
7 Augie Fackler <durin42@gmail.com>
8
8
9 This software may be used and distributed according to the terms
9 This software may be used and distributed according to the terms
10 of the GNU General Public License version 2 or any later version.
10 of the GNU General Public License version 2 or any later version.
11
11
12 ---
12 ---
13
13
14 This module implements most phase logic in mercurial.
14 This module implements most phase logic in mercurial.
15
15
16
16
17 Basic Concept
17 Basic Concept
18 =============
18 =============
19
19
20 A 'changeset phase' is an indicator that tells us how a changeset is
20 A 'changeset phase' is an indicator that tells us how a changeset is
21 manipulated and communicated. The details of each phase is described
21 manipulated and communicated. The details of each phase is described
22 below, here we describe the properties they have in common.
22 below, here we describe the properties they have in common.
23
23
24 Like bookmarks, phases are not stored in history and thus are not
24 Like bookmarks, phases are not stored in history and thus are not
25 permanent and leave no audit trail.
25 permanent and leave no audit trail.
26
26
27 First, no changeset can be in two phases at once. Phases are ordered,
27 First, no changeset can be in two phases at once. Phases are ordered,
28 so they can be considered from lowest to highest. The default, lowest
28 so they can be considered from lowest to highest. The default, lowest
29 phase is 'public' - this is the normal phase of existing changesets. A
29 phase is 'public' - this is the normal phase of existing changesets. A
30 child changeset can not be in a lower phase than its parents.
30 child changeset can not be in a lower phase than its parents.
31
31
32 These phases share a hierarchy of traits:
32 These phases share a hierarchy of traits:
33
33
34 immutable shared
34 immutable shared
35 public: X X
35 public: X X
36 draft: X
36 draft: X
37 secret:
37 secret:
38
38
39 Local commits are draft by default.
39 Local commits are draft by default.
40
40
41 Phase Movement and Exchange
41 Phase Movement and Exchange
42 ===========================
42 ===========================
43
43
44 Phase data is exchanged by pushkey on pull and push. Some servers have
44 Phase data is exchanged by pushkey on pull and push. Some servers have
45 a publish option set, we call such a server a "publishing server".
45 a publish option set, we call such a server a "publishing server".
46 Pushing a draft changeset to a publishing server changes the phase to
46 Pushing a draft changeset to a publishing server changes the phase to
47 public.
47 public.
48
48
49 A small list of fact/rules define the exchange of phase:
49 A small list of fact/rules define the exchange of phase:
50
50
51 * old client never changes server states
51 * old client never changes server states
52 * pull never changes server states
52 * pull never changes server states
53 * publish and old server changesets are seen as public by client
53 * publish and old server changesets are seen as public by client
54 * any secret changeset seen in another repository is lowered to at
54 * any secret changeset seen in another repository is lowered to at
55 least draft
55 least draft
56
56
57 Here is the final table summing up the 49 possible use cases of phase
57 Here is the final table summing up the 49 possible use cases of phase
58 exchange:
58 exchange:
59
59
60 server
60 server
61 old publish non-publish
61 old publish non-publish
62 N X N D P N D P
62 N X N D P N D P
63 old client
63 old client
64 pull
64 pull
65 N - X/X - X/D X/P - X/D X/P
65 N - X/X - X/D X/P - X/D X/P
66 X - X/X - X/D X/P - X/D X/P
66 X - X/X - X/D X/P - X/D X/P
67 push
67 push
68 X X/X X/X X/P X/P X/P X/D X/D X/P
68 X X/X X/X X/P X/P X/P X/D X/D X/P
69 new client
69 new client
70 pull
70 pull
71 N - P/X - P/D P/P - D/D P/P
71 N - P/X - P/D P/P - D/D P/P
72 D - P/X - P/D P/P - D/D P/P
72 D - P/X - P/D P/P - D/D P/P
73 P - P/X - P/D P/P - P/D P/P
73 P - P/X - P/D P/P - P/D P/P
74 push
74 push
75 D P/X P/X P/P P/P P/P D/D D/D P/P
75 D P/X P/X P/P P/P P/P D/D D/D P/P
76 P P/X P/X P/P P/P P/P P/P P/P P/P
76 P P/X P/X P/P P/P P/P P/P P/P P/P
77
77
78 Legend:
78 Legend:
79
79
80 A/B = final state on client / state on server
80 A/B = final state on client / state on server
81
81
82 * N = new/not present,
82 * N = new/not present,
83 * P = public,
83 * P = public,
84 * D = draft,
84 * D = draft,
85 * X = not tracked (i.e., the old client or server has no internal
85 * X = not tracked (i.e., the old client or server has no internal
86 way of recording the phase.)
86 way of recording the phase.)
87
87
88 passive = only pushes
88 passive = only pushes
89
89
90
90
91 A cell here can be read like this:
91 A cell here can be read like this:
92
92
93 "When a new client pushes a draft changeset (D) to a publishing
93 "When a new client pushes a draft changeset (D) to a publishing
94 server where it's not present (N), it's marked public on both
94 server where it's not present (N), it's marked public on both
95 sides (P/P)."
95 sides (P/P)."
96
96
97 Note: old client behave as a publishing server with draft only content
97 Note: old client behave as a publishing server with draft only content
98 - other people see it as public
98 - other people see it as public
99 - content is pushed as draft
99 - content is pushed as draft
100
100
101 """
101 """
102
102
103 import os
103 import errno
104 import errno
104 from node import nullid, nullrev, bin, hex, short
105 from node import nullid, nullrev, bin, hex, short
105 from i18n import _
106 from i18n import _
106 import util, error
107 import util, error
107
108
108 allphases = public, draft, secret = range(3)
109 allphases = public, draft, secret = range(3)
109 trackedphases = allphases[1:]
110 trackedphases = allphases[1:]
110 phasenames = ['public', 'draft', 'secret']
111 phasenames = ['public', 'draft', 'secret']
111
112
112 def _readroots(repo, phasedefaults=None):
113 def _readroots(repo, phasedefaults=None):
113 """Read phase roots from disk
114 """Read phase roots from disk
114
115
115 phasedefaults is a list of fn(repo, roots) callable, which are
116 phasedefaults is a list of fn(repo, roots) callable, which are
116 executed if the phase roots file does not exist. When phases are
117 executed if the phase roots file does not exist. When phases are
117 being initialized on an existing repository, this could be used to
118 being initialized on an existing repository, this could be used to
118 set selected changesets phase to something else than public.
119 set selected changesets phase to something else than public.
119
120
120 Return (roots, dirty) where dirty is true if roots differ from
121 Return (roots, dirty) where dirty is true if roots differ from
121 what is being stored.
122 what is being stored.
122 """
123 """
123 repo = repo.unfiltered()
124 repo = repo.unfiltered()
124 dirty = False
125 dirty = False
125 roots = [set() for i in allphases]
126 roots = [set() for i in allphases]
126 try:
127 try:
127 f = repo.sopener('phaseroots')
128 f = None
129 if 'HG_PENDING' in os.environ:
130 try:
131 f = repo.svfs('phaseroots.pending')
132 except IOError, inst:
133 if inst.errno != errno.ENOENT:
134 raise
135 if f is None:
136 f = repo.sopener('phaseroots')
128 try:
137 try:
129 for line in f:
138 for line in f:
130 phase, nh = line.split()
139 phase, nh = line.split()
131 roots[int(phase)].add(bin(nh))
140 roots[int(phase)].add(bin(nh))
132 finally:
141 finally:
133 f.close()
142 f.close()
134 except IOError, inst:
143 except IOError, inst:
135 if inst.errno != errno.ENOENT:
144 if inst.errno != errno.ENOENT:
136 raise
145 raise
137 if phasedefaults:
146 if phasedefaults:
138 for f in phasedefaults:
147 for f in phasedefaults:
139 roots = f(repo, roots)
148 roots = f(repo, roots)
140 dirty = True
149 dirty = True
141 return roots, dirty
150 return roots, dirty
142
151
143 class phasecache(object):
152 class phasecache(object):
144 def __init__(self, repo, phasedefaults, _load=True):
153 def __init__(self, repo, phasedefaults, _load=True):
145 if _load:
154 if _load:
146 # Cheap trick to allow shallow-copy without copy module
155 # Cheap trick to allow shallow-copy without copy module
147 self.phaseroots, self.dirty = _readroots(repo, phasedefaults)
156 self.phaseroots, self.dirty = _readroots(repo, phasedefaults)
148 self._phaserevs = None
157 self._phaserevs = None
149 self.filterunknown(repo)
158 self.filterunknown(repo)
150 self.opener = repo.sopener
159 self.opener = repo.sopener
151
160
152 def copy(self):
161 def copy(self):
153 # Shallow copy meant to ensure isolation in
162 # Shallow copy meant to ensure isolation in
154 # advance/retractboundary(), nothing more.
163 # advance/retractboundary(), nothing more.
155 ph = phasecache(None, None, _load=False)
164 ph = phasecache(None, None, _load=False)
156 ph.phaseroots = self.phaseroots[:]
165 ph.phaseroots = self.phaseroots[:]
157 ph.dirty = self.dirty
166 ph.dirty = self.dirty
158 ph.opener = self.opener
167 ph.opener = self.opener
159 ph._phaserevs = self._phaserevs
168 ph._phaserevs = self._phaserevs
160 return ph
169 return ph
161
170
162 def replace(self, phcache):
171 def replace(self, phcache):
163 for a in 'phaseroots dirty opener _phaserevs'.split():
172 for a in 'phaseroots dirty opener _phaserevs'.split():
164 setattr(self, a, getattr(phcache, a))
173 setattr(self, a, getattr(phcache, a))
165
174
166 def getphaserevs(self, repo):
175 def getphaserevs(self, repo):
167 if self._phaserevs is None:
176 if self._phaserevs is None:
168 repo = repo.unfiltered()
177 repo = repo.unfiltered()
169 revs = [public] * len(repo.changelog)
178 revs = [public] * len(repo.changelog)
170 self._phaserevs = revs
179 self._phaserevs = revs
171 self._populatephaseroots(repo)
180 self._populatephaseroots(repo)
172 for phase in trackedphases:
181 for phase in trackedphases:
173 roots = map(repo.changelog.rev, self.phaseroots[phase])
182 roots = map(repo.changelog.rev, self.phaseroots[phase])
174 if roots:
183 if roots:
175 for rev in roots:
184 for rev in roots:
176 revs[rev] = phase
185 revs[rev] = phase
177 for rev in repo.changelog.descendants(roots):
186 for rev in repo.changelog.descendants(roots):
178 revs[rev] = phase
187 revs[rev] = phase
179 return self._phaserevs
188 return self._phaserevs
180
189
181 def invalidate(self):
190 def invalidate(self):
182 self._phaserevs = None
191 self._phaserevs = None
183
192
184 def _populatephaseroots(self, repo):
193 def _populatephaseroots(self, repo):
185 """Fills the _phaserevs cache with phases for the roots.
194 """Fills the _phaserevs cache with phases for the roots.
186 """
195 """
187 cl = repo.changelog
196 cl = repo.changelog
188 phaserevs = self._phaserevs
197 phaserevs = self._phaserevs
189 for phase in trackedphases:
198 for phase in trackedphases:
190 roots = map(cl.rev, self.phaseroots[phase])
199 roots = map(cl.rev, self.phaseroots[phase])
191 for root in roots:
200 for root in roots:
192 phaserevs[root] = phase
201 phaserevs[root] = phase
193
202
194 def phase(self, repo, rev):
203 def phase(self, repo, rev):
195 # We need a repo argument here to be able to build _phaserevs
204 # We need a repo argument here to be able to build _phaserevs
196 # if necessary. The repository instance is not stored in
205 # if necessary. The repository instance is not stored in
197 # phasecache to avoid reference cycles. The changelog instance
206 # phasecache to avoid reference cycles. The changelog instance
198 # is not stored because it is a filecache() property and can
207 # is not stored because it is a filecache() property and can
199 # be replaced without us being notified.
208 # be replaced without us being notified.
200 if rev == nullrev:
209 if rev == nullrev:
201 return public
210 return public
202 if rev < nullrev:
211 if rev < nullrev:
203 raise ValueError(_('cannot lookup negative revision'))
212 raise ValueError(_('cannot lookup negative revision'))
204 if self._phaserevs is None or rev >= len(self._phaserevs):
213 if self._phaserevs is None or rev >= len(self._phaserevs):
205 self.invalidate()
214 self.invalidate()
206 self._phaserevs = self.getphaserevs(repo)
215 self._phaserevs = self.getphaserevs(repo)
207 return self._phaserevs[rev]
216 return self._phaserevs[rev]
208
217
209 def write(self):
218 def write(self):
210 if not self.dirty:
219 if not self.dirty:
211 return
220 return
212 f = self.opener('phaseroots', 'w', atomictemp=True)
221 f = self.opener('phaseroots', 'w', atomictemp=True)
213 try:
222 try:
214 self._write(f)
223 self._write(f)
215 finally:
224 finally:
216 f.close()
225 f.close()
217
226
218 def _write(self, fp):
227 def _write(self, fp):
219 for phase, roots in enumerate(self.phaseroots):
228 for phase, roots in enumerate(self.phaseroots):
220 for h in roots:
229 for h in roots:
221 fp.write('%i %s\n' % (phase, hex(h)))
230 fp.write('%i %s\n' % (phase, hex(h)))
222 self.dirty = False
231 self.dirty = False
223
232
224 def _updateroots(self, phase, newroots, tr):
233 def _updateroots(self, phase, newroots, tr):
225 self.phaseroots[phase] = newroots
234 self.phaseroots[phase] = newroots
226 self.invalidate()
235 self.invalidate()
227 self.dirty = True
236 self.dirty = True
228
237
229 tr.addfilegenerator('phase', ('phaseroots',), self._write)
238 tr.addfilegenerator('phase', ('phaseroots',), self._write)
230 tr.hookargs['phases_moved'] = '1'
239 tr.hookargs['phases_moved'] = '1'
231
240
232 def advanceboundary(self, repo, tr, targetphase, nodes):
241 def advanceboundary(self, repo, tr, targetphase, nodes):
233 # Be careful to preserve shallow-copied values: do not update
242 # Be careful to preserve shallow-copied values: do not update
234 # phaseroots values, replace them.
243 # phaseroots values, replace them.
235
244
236 repo = repo.unfiltered()
245 repo = repo.unfiltered()
237 delroots = [] # set of root deleted by this path
246 delroots = [] # set of root deleted by this path
238 for phase in xrange(targetphase + 1, len(allphases)):
247 for phase in xrange(targetphase + 1, len(allphases)):
239 # filter nodes that are not in a compatible phase already
248 # filter nodes that are not in a compatible phase already
240 nodes = [n for n in nodes
249 nodes = [n for n in nodes
241 if self.phase(repo, repo[n].rev()) >= phase]
250 if self.phase(repo, repo[n].rev()) >= phase]
242 if not nodes:
251 if not nodes:
243 break # no roots to move anymore
252 break # no roots to move anymore
244 olds = self.phaseroots[phase]
253 olds = self.phaseroots[phase]
245 roots = set(ctx.node() for ctx in repo.set(
254 roots = set(ctx.node() for ctx in repo.set(
246 'roots((%ln::) - (%ln::%ln))', olds, olds, nodes))
255 'roots((%ln::) - (%ln::%ln))', olds, olds, nodes))
247 if olds != roots:
256 if olds != roots:
248 self._updateroots(phase, roots, tr)
257 self._updateroots(phase, roots, tr)
249 # some roots may need to be declared for lower phases
258 # some roots may need to be declared for lower phases
250 delroots.extend(olds - roots)
259 delroots.extend(olds - roots)
251 # declare deleted root in the target phase
260 # declare deleted root in the target phase
252 if targetphase != 0:
261 if targetphase != 0:
253 self.retractboundary(repo, tr, targetphase, delroots)
262 self.retractboundary(repo, tr, targetphase, delroots)
254 repo.invalidatevolatilesets()
263 repo.invalidatevolatilesets()
255
264
256 def retractboundary(self, repo, tr, targetphase, nodes):
265 def retractboundary(self, repo, tr, targetphase, nodes):
257 # Be careful to preserve shallow-copied values: do not update
266 # Be careful to preserve shallow-copied values: do not update
258 # phaseroots values, replace them.
267 # phaseroots values, replace them.
259
268
260 repo = repo.unfiltered()
269 repo = repo.unfiltered()
261 currentroots = self.phaseroots[targetphase]
270 currentroots = self.phaseroots[targetphase]
262 newroots = [n for n in nodes
271 newroots = [n for n in nodes
263 if self.phase(repo, repo[n].rev()) < targetphase]
272 if self.phase(repo, repo[n].rev()) < targetphase]
264 if newroots:
273 if newroots:
265 if nullid in newroots:
274 if nullid in newroots:
266 raise util.Abort(_('cannot change null revision phase'))
275 raise util.Abort(_('cannot change null revision phase'))
267 currentroots = currentroots.copy()
276 currentroots = currentroots.copy()
268 currentroots.update(newroots)
277 currentroots.update(newroots)
269 ctxs = repo.set('roots(%ln::)', currentroots)
278 ctxs = repo.set('roots(%ln::)', currentroots)
270 currentroots.intersection_update(ctx.node() for ctx in ctxs)
279 currentroots.intersection_update(ctx.node() for ctx in ctxs)
271 self._updateroots(targetphase, currentroots, tr)
280 self._updateroots(targetphase, currentroots, tr)
272 repo.invalidatevolatilesets()
281 repo.invalidatevolatilesets()
273
282
274 def filterunknown(self, repo):
283 def filterunknown(self, repo):
275 """remove unknown nodes from the phase boundary
284 """remove unknown nodes from the phase boundary
276
285
277 Nothing is lost as unknown nodes only hold data for their descendants.
286 Nothing is lost as unknown nodes only hold data for their descendants.
278 """
287 """
279 filtered = False
288 filtered = False
280 nodemap = repo.changelog.nodemap # to filter unknown nodes
289 nodemap = repo.changelog.nodemap # to filter unknown nodes
281 for phase, nodes in enumerate(self.phaseroots):
290 for phase, nodes in enumerate(self.phaseroots):
282 missing = sorted(node for node in nodes if node not in nodemap)
291 missing = sorted(node for node in nodes if node not in nodemap)
283 if missing:
292 if missing:
284 for mnode in missing:
293 for mnode in missing:
285 repo.ui.debug(
294 repo.ui.debug(
286 'removing unknown node %s from %i-phase boundary\n'
295 'removing unknown node %s from %i-phase boundary\n'
287 % (short(mnode), phase))
296 % (short(mnode), phase))
288 nodes.symmetric_difference_update(missing)
297 nodes.symmetric_difference_update(missing)
289 filtered = True
298 filtered = True
290 if filtered:
299 if filtered:
291 self.dirty = True
300 self.dirty = True
292 # filterunknown is called by repo.destroyed, we may have no changes in
301 # filterunknown is called by repo.destroyed, we may have no changes in
293 # root but phaserevs contents is certainly invalid (or at least we
302 # root but phaserevs contents is certainly invalid (or at least we
294 # have not proper way to check that). related to issue 3858.
303 # have not proper way to check that). related to issue 3858.
295 #
304 #
296 # The other caller is __init__ that have no _phaserevs initialized
305 # The other caller is __init__ that have no _phaserevs initialized
297 # anyway. If this change we should consider adding a dedicated
306 # anyway. If this change we should consider adding a dedicated
298 # "destroyed" function to phasecache or a proper cache key mechanism
307 # "destroyed" function to phasecache or a proper cache key mechanism
299 # (see branchmap one)
308 # (see branchmap one)
300 self.invalidate()
309 self.invalidate()
301
310
302 def advanceboundary(repo, tr, targetphase, nodes):
311 def advanceboundary(repo, tr, targetphase, nodes):
303 """Add nodes to a phase changing other nodes phases if necessary.
312 """Add nodes to a phase changing other nodes phases if necessary.
304
313
305 This function move boundary *forward* this means that all nodes
314 This function move boundary *forward* this means that all nodes
306 are set in the target phase or kept in a *lower* phase.
315 are set in the target phase or kept in a *lower* phase.
307
316
308 Simplify boundary to contains phase roots only."""
317 Simplify boundary to contains phase roots only."""
309 phcache = repo._phasecache.copy()
318 phcache = repo._phasecache.copy()
310 phcache.advanceboundary(repo, tr, targetphase, nodes)
319 phcache.advanceboundary(repo, tr, targetphase, nodes)
311 repo._phasecache.replace(phcache)
320 repo._phasecache.replace(phcache)
312
321
313 def retractboundary(repo, tr, targetphase, nodes):
322 def retractboundary(repo, tr, targetphase, nodes):
314 """Set nodes back to a phase changing other nodes phases if
323 """Set nodes back to a phase changing other nodes phases if
315 necessary.
324 necessary.
316
325
317 This function move boundary *backward* this means that all nodes
326 This function move boundary *backward* this means that all nodes
318 are set in the target phase or kept in a *higher* phase.
327 are set in the target phase or kept in a *higher* phase.
319
328
320 Simplify boundary to contains phase roots only."""
329 Simplify boundary to contains phase roots only."""
321 phcache = repo._phasecache.copy()
330 phcache = repo._phasecache.copy()
322 phcache.retractboundary(repo, tr, targetphase, nodes)
331 phcache.retractboundary(repo, tr, targetphase, nodes)
323 repo._phasecache.replace(phcache)
332 repo._phasecache.replace(phcache)
324
333
325 def listphases(repo):
334 def listphases(repo):
326 """List phases root for serialization over pushkey"""
335 """List phases root for serialization over pushkey"""
327 keys = {}
336 keys = {}
328 value = '%i' % draft
337 value = '%i' % draft
329 for root in repo._phasecache.phaseroots[draft]:
338 for root in repo._phasecache.phaseroots[draft]:
330 keys[hex(root)] = value
339 keys[hex(root)] = value
331
340
332 if repo.ui.configbool('phases', 'publish', True):
341 if repo.ui.configbool('phases', 'publish', True):
333 # Add an extra data to let remote know we are a publishing
342 # Add an extra data to let remote know we are a publishing
334 # repo. Publishing repo can't just pretend they are old repo.
343 # repo. Publishing repo can't just pretend they are old repo.
335 # When pushing to a publishing repo, the client still need to
344 # When pushing to a publishing repo, the client still need to
336 # push phase boundary
345 # push phase boundary
337 #
346 #
338 # Push do not only push changeset. It also push phase data.
347 # Push do not only push changeset. It also push phase data.
339 # New phase data may apply to common changeset which won't be
348 # New phase data may apply to common changeset which won't be
340 # push (as they are common). Here is a very simple example:
349 # push (as they are common). Here is a very simple example:
341 #
350 #
342 # 1) repo A push changeset X as draft to repo B
351 # 1) repo A push changeset X as draft to repo B
343 # 2) repo B make changeset X public
352 # 2) repo B make changeset X public
344 # 3) repo B push to repo A. X is not pushed but the data that
353 # 3) repo B push to repo A. X is not pushed but the data that
345 # X as now public should
354 # X as now public should
346 #
355 #
347 # The server can't handle it on it's own as it has no idea of
356 # The server can't handle it on it's own as it has no idea of
348 # client phase data.
357 # client phase data.
349 keys['publishing'] = 'True'
358 keys['publishing'] = 'True'
350 return keys
359 return keys
351
360
352 def pushphase(repo, nhex, oldphasestr, newphasestr):
361 def pushphase(repo, nhex, oldphasestr, newphasestr):
353 """List phases root for serialization over pushkey"""
362 """List phases root for serialization over pushkey"""
354 repo = repo.unfiltered()
363 repo = repo.unfiltered()
355 tr = None
364 tr = None
356 lock = repo.lock()
365 lock = repo.lock()
357 try:
366 try:
358 currentphase = repo[nhex].phase()
367 currentphase = repo[nhex].phase()
359 newphase = abs(int(newphasestr)) # let's avoid negative index surprise
368 newphase = abs(int(newphasestr)) # let's avoid negative index surprise
360 oldphase = abs(int(oldphasestr)) # let's avoid negative index surprise
369 oldphase = abs(int(oldphasestr)) # let's avoid negative index surprise
361 if currentphase == oldphase and newphase < oldphase:
370 if currentphase == oldphase and newphase < oldphase:
362 tr = repo.transaction('pushkey-phase')
371 tr = repo.transaction('pushkey-phase')
363 advanceboundary(repo, tr, newphase, [bin(nhex)])
372 advanceboundary(repo, tr, newphase, [bin(nhex)])
364 tr.close()
373 tr.close()
365 return 1
374 return 1
366 elif currentphase == newphase:
375 elif currentphase == newphase:
367 # raced, but got correct result
376 # raced, but got correct result
368 return 1
377 return 1
369 else:
378 else:
370 return 0
379 return 0
371 finally:
380 finally:
372 if tr:
381 if tr:
373 tr.release()
382 tr.release()
374 lock.release()
383 lock.release()
375
384
376 def analyzeremotephases(repo, subset, roots):
385 def analyzeremotephases(repo, subset, roots):
377 """Compute phases heads and root in a subset of node from root dict
386 """Compute phases heads and root in a subset of node from root dict
378
387
379 * subset is heads of the subset
388 * subset is heads of the subset
380 * roots is {<nodeid> => phase} mapping. key and value are string.
389 * roots is {<nodeid> => phase} mapping. key and value are string.
381
390
382 Accept unknown element input
391 Accept unknown element input
383 """
392 """
384 repo = repo.unfiltered()
393 repo = repo.unfiltered()
385 # build list from dictionary
394 # build list from dictionary
386 draftroots = []
395 draftroots = []
387 nodemap = repo.changelog.nodemap # to filter unknown nodes
396 nodemap = repo.changelog.nodemap # to filter unknown nodes
388 for nhex, phase in roots.iteritems():
397 for nhex, phase in roots.iteritems():
389 if nhex == 'publishing': # ignore data related to publish option
398 if nhex == 'publishing': # ignore data related to publish option
390 continue
399 continue
391 node = bin(nhex)
400 node = bin(nhex)
392 phase = int(phase)
401 phase = int(phase)
393 if phase == 0:
402 if phase == 0:
394 if node != nullid:
403 if node != nullid:
395 repo.ui.warn(_('ignoring inconsistent public root'
404 repo.ui.warn(_('ignoring inconsistent public root'
396 ' from remote: %s\n') % nhex)
405 ' from remote: %s\n') % nhex)
397 elif phase == 1:
406 elif phase == 1:
398 if node in nodemap:
407 if node in nodemap:
399 draftroots.append(node)
408 draftroots.append(node)
400 else:
409 else:
401 repo.ui.warn(_('ignoring unexpected root from remote: %i %s\n')
410 repo.ui.warn(_('ignoring unexpected root from remote: %i %s\n')
402 % (phase, nhex))
411 % (phase, nhex))
403 # compute heads
412 # compute heads
404 publicheads = newheads(repo, subset, draftroots)
413 publicheads = newheads(repo, subset, draftroots)
405 return publicheads, draftroots
414 return publicheads, draftroots
406
415
407 def newheads(repo, heads, roots):
416 def newheads(repo, heads, roots):
408 """compute new head of a subset minus another
417 """compute new head of a subset minus another
409
418
410 * `heads`: define the first subset
419 * `heads`: define the first subset
411 * `roots`: define the second we subtract from the first"""
420 * `roots`: define the second we subtract from the first"""
412 repo = repo.unfiltered()
421 repo = repo.unfiltered()
413 revset = repo.set('heads((%ln + parents(%ln)) - (%ln::%ln))',
422 revset = repo.set('heads((%ln + parents(%ln)) - (%ln::%ln))',
414 heads, roots, roots, heads)
423 heads, roots, roots, heads)
415 return [c.node() for c in revset]
424 return [c.node() for c in revset]
416
425
417
426
418 def newcommitphase(ui):
427 def newcommitphase(ui):
419 """helper to get the target phase of new commit
428 """helper to get the target phase of new commit
420
429
421 Handle all possible values for the phases.new-commit options.
430 Handle all possible values for the phases.new-commit options.
422
431
423 """
432 """
424 v = ui.config('phases', 'new-commit', draft)
433 v = ui.config('phases', 'new-commit', draft)
425 try:
434 try:
426 return phasenames.index(v)
435 return phasenames.index(v)
427 except ValueError:
436 except ValueError:
428 try:
437 try:
429 return int(v)
438 return int(v)
430 except ValueError:
439 except ValueError:
431 msg = _("phases.new-commit: not a valid phase name ('%s')")
440 msg = _("phases.new-commit: not a valid phase name ('%s')")
432 raise error.ConfigError(msg % v)
441 raise error.ConfigError(msg % v)
433
442
434 def hassecret(repo):
443 def hassecret(repo):
435 """utility function that check if a repo have any secret changeset."""
444 """utility function that check if a repo have any secret changeset."""
436 return bool(repo._phasecache.phaseroots[2])
445 return bool(repo._phasecache.phaseroots[2])
@@ -1,519 +1,519 b''
1 Test exchange of common information using bundle2
1 Test exchange of common information using bundle2
2
2
3
3
4 $ getmainid() {
4 $ getmainid() {
5 > hg -R main log --template '{node}\n' --rev "$1"
5 > hg -R main log --template '{node}\n' --rev "$1"
6 > }
6 > }
7
7
8 enable obsolescence
8 enable obsolescence
9
9
10 $ cat >> $HGRCPATH << EOF
10 $ cat >> $HGRCPATH << EOF
11 > [experimental]
11 > [experimental]
12 > evolution=createmarkers,exchange
12 > evolution=createmarkers,exchange
13 > bundle2-exp=True
13 > bundle2-exp=True
14 > [ui]
14 > [ui]
15 > ssh=python "$TESTDIR/dummyssh"
15 > ssh=python "$TESTDIR/dummyssh"
16 > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
16 > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
17 > [web]
17 > [web]
18 > push_ssl = false
18 > push_ssl = false
19 > allow_push = *
19 > allow_push = *
20 > [phases]
20 > [phases]
21 > publish=False
21 > publish=False
22 > [hooks]
22 > [hooks]
23 > changegroup = sh -c "HG_LOCAL= python \"$TESTDIR/printenv.py\" changegroup"
23 > changegroup = sh -c "HG_LOCAL= python \"$TESTDIR/printenv.py\" changegroup"
24 > b2x-pretransactionclose.tip = printf 'pre-close-tip:'; hg log -r tip -T '{node|short} {phase} {bookmarks}\n'
24 > b2x-pretransactionclose.tip = printf 'pre-close-tip:'; hg log -r tip -T '{node|short} {phase} {bookmarks}\n'
25 > b2x-transactionclose.tip = printf 'postclose-tip:'; hg log -r tip -T '{node|short} {phase} {bookmarks}\n'
25 > b2x-transactionclose.tip = printf 'postclose-tip:'; hg log -r tip -T '{node|short} {phase} {bookmarks}\n'
26 > b2x-transactionclose.env = sh -c "HG_LOCAL= python \"$TESTDIR/printenv.py\" b2x-transactionclose"
26 > b2x-transactionclose.env = sh -c "HG_LOCAL= python \"$TESTDIR/printenv.py\" b2x-transactionclose"
27 > EOF
27 > EOF
28
28
29 The extension requires a repo (currently unused)
29 The extension requires a repo (currently unused)
30
30
31 $ hg init main
31 $ hg init main
32 $ cd main
32 $ cd main
33 $ touch a
33 $ touch a
34 $ hg add a
34 $ hg add a
35 $ hg commit -m 'a'
35 $ hg commit -m 'a'
36
36
37 $ hg unbundle $TESTDIR/bundles/rebase.hg
37 $ hg unbundle $TESTDIR/bundles/rebase.hg
38 adding changesets
38 adding changesets
39 adding manifests
39 adding manifests
40 adding file changes
40 adding file changes
41 added 8 changesets with 7 changes to 7 files (+3 heads)
41 added 8 changesets with 7 changes to 7 files (+3 heads)
42 changegroup hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_SOURCE=unbundle HG_URL=bundle:*/rebase.hg (glob)
42 changegroup hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_SOURCE=unbundle HG_URL=bundle:*/rebase.hg (glob)
43 (run 'hg heads' to see heads, 'hg merge' to merge)
43 (run 'hg heads' to see heads, 'hg merge' to merge)
44
44
45 $ cd ..
45 $ cd ..
46
46
47 Real world exchange
47 Real world exchange
48 =====================
48 =====================
49
49
50 Add more obsolescence information
50 Add more obsolescence information
51
51
52 $ hg -R main debugobsolete -d '0 0' 1111111111111111111111111111111111111111 `getmainid 9520eea781bc`
52 $ hg -R main debugobsolete -d '0 0' 1111111111111111111111111111111111111111 `getmainid 9520eea781bc`
53 $ hg -R main debugobsolete -d '0 0' 2222222222222222222222222222222222222222 `getmainid 24b6387c8c8c`
53 $ hg -R main debugobsolete -d '0 0' 2222222222222222222222222222222222222222 `getmainid 24b6387c8c8c`
54
54
55 clone --pull
55 clone --pull
56
56
57 $ hg -R main phase --public cd010b8cd998
57 $ hg -R main phase --public cd010b8cd998
58 $ hg clone main other --pull --rev 9520eea781bc
58 $ hg clone main other --pull --rev 9520eea781bc
59 adding changesets
59 adding changesets
60 adding manifests
60 adding manifests
61 adding file changes
61 adding file changes
62 added 2 changesets with 2 changes to 2 files
62 added 2 changesets with 2 changes to 2 files
63 1 new obsolescence markers
63 1 new obsolescence markers
64 pre-close-tip:9520eea781bc public
64 pre-close-tip:9520eea781bc draft
65 postclose-tip:9520eea781bc draft
65 postclose-tip:9520eea781bc draft
66 b2x-transactionclose hook: HG_NEW_OBSMARKERS=1 HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
66 b2x-transactionclose hook: HG_NEW_OBSMARKERS=1 HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
67 changegroup hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
67 changegroup hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
68 updating to branch default
68 updating to branch default
69 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
69 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
70 $ hg -R other log -G
70 $ hg -R other log -G
71 @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
71 @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
72 |
72 |
73 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
73 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
74
74
75 $ hg -R other debugobsolete
75 $ hg -R other debugobsolete
76 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
76 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
77
77
78 pull
78 pull
79
79
80 $ hg -R main phase --public 9520eea781bc
80 $ hg -R main phase --public 9520eea781bc
81 $ hg -R other pull -r 24b6387c8c8c
81 $ hg -R other pull -r 24b6387c8c8c
82 pulling from $TESTTMP/main (glob)
82 pulling from $TESTTMP/main (glob)
83 searching for changes
83 searching for changes
84 adding changesets
84 adding changesets
85 adding manifests
85 adding manifests
86 adding file changes
86 adding file changes
87 added 1 changesets with 1 changes to 1 files (+1 heads)
87 added 1 changesets with 1 changes to 1 files (+1 heads)
88 1 new obsolescence markers
88 1 new obsolescence markers
89 pre-close-tip:24b6387c8c8c public
89 pre-close-tip:24b6387c8c8c draft
90 postclose-tip:24b6387c8c8c draft
90 postclose-tip:24b6387c8c8c draft
91 b2x-transactionclose hook: HG_NEW_OBSMARKERS=1 HG_NODE=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
91 b2x-transactionclose hook: HG_NEW_OBSMARKERS=1 HG_NODE=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
92 changegroup hook: HG_NODE=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
92 changegroup hook: HG_NODE=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
93 (run 'hg heads' to see heads, 'hg merge' to merge)
93 (run 'hg heads' to see heads, 'hg merge' to merge)
94 $ hg -R other log -G
94 $ hg -R other log -G
95 o 2:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F
95 o 2:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F
96 |
96 |
97 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
97 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
98 |/
98 |/
99 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
99 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
100
100
101 $ hg -R other debugobsolete
101 $ hg -R other debugobsolete
102 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
102 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
103 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
103 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
104
104
105 pull empty (with phase movement)
105 pull empty (with phase movement)
106
106
107 $ hg -R main phase --public 24b6387c8c8c
107 $ hg -R main phase --public 24b6387c8c8c
108 $ hg -R other pull -r 24b6387c8c8c
108 $ hg -R other pull -r 24b6387c8c8c
109 pulling from $TESTTMP/main (glob)
109 pulling from $TESTTMP/main (glob)
110 no changes found
110 no changes found
111 pre-close-tip:000000000000 public
111 pre-close-tip:000000000000 public
112 postclose-tip:24b6387c8c8c public
112 postclose-tip:24b6387c8c8c public
113 b2x-transactionclose hook: HG_NEW_OBSMARKERS=0 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
113 b2x-transactionclose hook: HG_NEW_OBSMARKERS=0 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
114 $ hg -R other log -G
114 $ hg -R other log -G
115 o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
115 o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
116 |
116 |
117 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
117 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
118 |/
118 |/
119 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
119 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
120
120
121 $ hg -R other debugobsolete
121 $ hg -R other debugobsolete
122 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
122 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
123 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
123 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
124
124
125 pull empty
125 pull empty
126
126
127 $ hg -R other pull -r 24b6387c8c8c
127 $ hg -R other pull -r 24b6387c8c8c
128 pulling from $TESTTMP/main (glob)
128 pulling from $TESTTMP/main (glob)
129 no changes found
129 no changes found
130 pre-close-tip:24b6387c8c8c public
130 pre-close-tip:24b6387c8c8c public
131 postclose-tip:24b6387c8c8c public
131 postclose-tip:24b6387c8c8c public
132 b2x-transactionclose hook: HG_NEW_OBSMARKERS=0 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
132 b2x-transactionclose hook: HG_NEW_OBSMARKERS=0 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
133 $ hg -R other log -G
133 $ hg -R other log -G
134 o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
134 o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
135 |
135 |
136 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
136 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
137 |/
137 |/
138 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
138 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
139
139
140 $ hg -R other debugobsolete
140 $ hg -R other debugobsolete
141 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
141 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
142 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
142 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
143
143
144 add extra data to test their exchange during push
144 add extra data to test their exchange during push
145
145
146 $ hg -R main bookmark --rev eea13746799a book_eea1
146 $ hg -R main bookmark --rev eea13746799a book_eea1
147 $ hg -R main debugobsolete -d '0 0' 3333333333333333333333333333333333333333 `getmainid eea13746799a`
147 $ hg -R main debugobsolete -d '0 0' 3333333333333333333333333333333333333333 `getmainid eea13746799a`
148 $ hg -R main bookmark --rev 02de42196ebe book_02de
148 $ hg -R main bookmark --rev 02de42196ebe book_02de
149 $ hg -R main debugobsolete -d '0 0' 4444444444444444444444444444444444444444 `getmainid 02de42196ebe`
149 $ hg -R main debugobsolete -d '0 0' 4444444444444444444444444444444444444444 `getmainid 02de42196ebe`
150 $ hg -R main bookmark --rev 42ccdea3bb16 book_42cc
150 $ hg -R main bookmark --rev 42ccdea3bb16 book_42cc
151 $ hg -R main debugobsolete -d '0 0' 5555555555555555555555555555555555555555 `getmainid 42ccdea3bb16`
151 $ hg -R main debugobsolete -d '0 0' 5555555555555555555555555555555555555555 `getmainid 42ccdea3bb16`
152 $ hg -R main bookmark --rev 5fddd98957c8 book_5fdd
152 $ hg -R main bookmark --rev 5fddd98957c8 book_5fdd
153 $ hg -R main debugobsolete -d '0 0' 6666666666666666666666666666666666666666 `getmainid 5fddd98957c8`
153 $ hg -R main debugobsolete -d '0 0' 6666666666666666666666666666666666666666 `getmainid 5fddd98957c8`
154 $ hg -R main bookmark --rev 32af7686d403 book_32af
154 $ hg -R main bookmark --rev 32af7686d403 book_32af
155 $ hg -R main debugobsolete -d '0 0' 7777777777777777777777777777777777777777 `getmainid 32af7686d403`
155 $ hg -R main debugobsolete -d '0 0' 7777777777777777777777777777777777777777 `getmainid 32af7686d403`
156
156
157 $ hg -R other bookmark --rev cd010b8cd998 book_eea1
157 $ hg -R other bookmark --rev cd010b8cd998 book_eea1
158 $ hg -R other bookmark --rev cd010b8cd998 book_02de
158 $ hg -R other bookmark --rev cd010b8cd998 book_02de
159 $ hg -R other bookmark --rev cd010b8cd998 book_42cc
159 $ hg -R other bookmark --rev cd010b8cd998 book_42cc
160 $ hg -R other bookmark --rev cd010b8cd998 book_5fdd
160 $ hg -R other bookmark --rev cd010b8cd998 book_5fdd
161 $ hg -R other bookmark --rev cd010b8cd998 book_32af
161 $ hg -R other bookmark --rev cd010b8cd998 book_32af
162
162
163 $ hg -R main phase --public eea13746799a
163 $ hg -R main phase --public eea13746799a
164
164
165 push
165 push
166 $ hg -R main push other --rev eea13746799a --bookmark book_eea1
166 $ hg -R main push other --rev eea13746799a --bookmark book_eea1
167 pushing to other
167 pushing to other
168 searching for changes
168 searching for changes
169 pre-close-tip:eea13746799a draft book_eea1
169 pre-close-tip:eea13746799a public book_eea1
170 postclose-tip:eea13746799a public book_eea1
170 postclose-tip:eea13746799a public book_eea1
171 b2x-transactionclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2-EXP=1 HG_NEW_OBSMARKERS=1 HG_NODE=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_PHASES_MOVED=1 HG_SOURCE=push HG_URL=push
171 b2x-transactionclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2-EXP=1 HG_NEW_OBSMARKERS=1 HG_NODE=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_PHASES_MOVED=1 HG_SOURCE=push HG_URL=push
172 changegroup hook: HG_BUNDLE2-EXP=1 HG_NODE=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_SOURCE=push HG_URL=push
172 changegroup hook: HG_BUNDLE2-EXP=1 HG_NODE=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_SOURCE=push HG_URL=push
173 remote: adding changesets
173 remote: adding changesets
174 remote: adding manifests
174 remote: adding manifests
175 remote: adding file changes
175 remote: adding file changes
176 remote: added 1 changesets with 0 changes to 0 files (-1 heads)
176 remote: added 1 changesets with 0 changes to 0 files (-1 heads)
177 remote: 1 new obsolescence markers
177 remote: 1 new obsolescence markers
178 updating bookmark book_eea1
178 updating bookmark book_eea1
179 $ hg -R other log -G
179 $ hg -R other log -G
180 o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
180 o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
181 |\
181 |\
182 | o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
182 | o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
183 | |
183 | |
184 @ | 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
184 @ | 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
185 |/
185 |/
186 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de book_32af book_42cc book_5fdd A
186 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de book_32af book_42cc book_5fdd A
187
187
188 $ hg -R other debugobsolete
188 $ hg -R other debugobsolete
189 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
189 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
190 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
190 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
191 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
191 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
192
192
193 pull over ssh
193 pull over ssh
194
194
195 $ hg -R other pull ssh://user@dummy/main -r 02de42196ebe --bookmark book_02de
195 $ hg -R other pull ssh://user@dummy/main -r 02de42196ebe --bookmark book_02de
196 pulling from ssh://user@dummy/main
196 pulling from ssh://user@dummy/main
197 searching for changes
197 searching for changes
198 adding changesets
198 adding changesets
199 adding manifests
199 adding manifests
200 adding file changes
200 adding file changes
201 added 1 changesets with 1 changes to 1 files (+1 heads)
201 added 1 changesets with 1 changes to 1 files (+1 heads)
202 1 new obsolescence markers
202 1 new obsolescence markers
203 updating bookmark book_02de
203 updating bookmark book_02de
204 pre-close-tip:02de42196ebe public book_02de
204 pre-close-tip:02de42196ebe draft book_02de
205 postclose-tip:02de42196ebe draft book_02de
205 postclose-tip:02de42196ebe draft book_02de
206 b2x-transactionclose hook: HG_BOOKMARK_MOVED=1 HG_NEW_OBSMARKERS=1 HG_NODE=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=ssh://user@dummy/main
206 b2x-transactionclose hook: HG_BOOKMARK_MOVED=1 HG_NEW_OBSMARKERS=1 HG_NODE=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=ssh://user@dummy/main
207 changegroup hook: HG_NODE=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_SOURCE=pull HG_URL=ssh://user@dummy/main
207 changegroup hook: HG_NODE=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_SOURCE=pull HG_URL=ssh://user@dummy/main
208 (run 'hg heads' to see heads, 'hg merge' to merge)
208 (run 'hg heads' to see heads, 'hg merge' to merge)
209 $ hg -R other debugobsolete
209 $ hg -R other debugobsolete
210 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
210 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
211 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
211 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
212 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
212 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
213 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
213 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
214
214
215 pull over http
215 pull over http
216
216
217 $ hg -R main serve -p $HGPORT -d --pid-file=main.pid -E main-error.log
217 $ hg -R main serve -p $HGPORT -d --pid-file=main.pid -E main-error.log
218 $ cat main.pid >> $DAEMON_PIDS
218 $ cat main.pid >> $DAEMON_PIDS
219
219
220 $ hg -R other pull http://localhost:$HGPORT/ -r 42ccdea3bb16 --bookmark book_42cc
220 $ hg -R other pull http://localhost:$HGPORT/ -r 42ccdea3bb16 --bookmark book_42cc
221 pulling from http://localhost:$HGPORT/
221 pulling from http://localhost:$HGPORT/
222 searching for changes
222 searching for changes
223 adding changesets
223 adding changesets
224 adding manifests
224 adding manifests
225 adding file changes
225 adding file changes
226 added 1 changesets with 1 changes to 1 files (+1 heads)
226 added 1 changesets with 1 changes to 1 files (+1 heads)
227 1 new obsolescence markers
227 1 new obsolescence markers
228 updating bookmark book_42cc
228 updating bookmark book_42cc
229 pre-close-tip:42ccdea3bb16 public book_42cc
229 pre-close-tip:42ccdea3bb16 draft book_42cc
230 postclose-tip:42ccdea3bb16 draft book_42cc
230 postclose-tip:42ccdea3bb16 draft book_42cc
231 b2x-transactionclose hook: HG_BOOKMARK_MOVED=1 HG_NEW_OBSMARKERS=1 HG_NODE=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=http://localhost:$HGPORT/
231 b2x-transactionclose hook: HG_BOOKMARK_MOVED=1 HG_NEW_OBSMARKERS=1 HG_NODE=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=http://localhost:$HGPORT/
232 changegroup hook: HG_NODE=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_SOURCE=pull HG_URL=http://localhost:$HGPORT/
232 changegroup hook: HG_NODE=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_SOURCE=pull HG_URL=http://localhost:$HGPORT/
233 (run 'hg heads .' to see heads, 'hg merge' to merge)
233 (run 'hg heads .' to see heads, 'hg merge' to merge)
234 $ cat main-error.log
234 $ cat main-error.log
235 $ hg -R other debugobsolete
235 $ hg -R other debugobsolete
236 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
236 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
237 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
237 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
238 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
238 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
239 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
239 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
240 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
240 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
241
241
242 push over ssh
242 push over ssh
243
243
244 $ hg -R main push ssh://user@dummy/other -r 5fddd98957c8 --bookmark book_5fdd
244 $ hg -R main push ssh://user@dummy/other -r 5fddd98957c8 --bookmark book_5fdd
245 pushing to ssh://user@dummy/other
245 pushing to ssh://user@dummy/other
246 searching for changes
246 searching for changes
247 remote: adding changesets
247 remote: adding changesets
248 remote: adding manifests
248 remote: adding manifests
249 remote: adding file changes
249 remote: adding file changes
250 remote: added 1 changesets with 1 changes to 1 files
250 remote: added 1 changesets with 1 changes to 1 files
251 remote: 1 new obsolescence markers
251 remote: 1 new obsolescence markers
252 updating bookmark book_5fdd
252 updating bookmark book_5fdd
253 remote: pre-close-tip:5fddd98957c8 draft book_5fdd
253 remote: pre-close-tip:5fddd98957c8 draft book_5fdd
254 remote: postclose-tip:5fddd98957c8 draft book_5fdd
254 remote: postclose-tip:5fddd98957c8 draft book_5fdd
255 remote: b2x-transactionclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2-EXP=1 HG_NEW_OBSMARKERS=1 HG_NODE=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
255 remote: b2x-transactionclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2-EXP=1 HG_NEW_OBSMARKERS=1 HG_NODE=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
256 remote: changegroup hook: HG_BUNDLE2-EXP=1 HG_NODE=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
256 remote: changegroup hook: HG_BUNDLE2-EXP=1 HG_NODE=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
257 $ hg -R other log -G
257 $ hg -R other log -G
258 o 6:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C
258 o 6:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C
259 |
259 |
260 o 5:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B
260 o 5:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B
261 |
261 |
262 | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H
262 | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H
263 | |
263 | |
264 | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
264 | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
265 | |/|
265 | |/|
266 | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
266 | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
267 |/ /
267 |/ /
268 | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
268 | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
269 |/
269 |/
270 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af A
270 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af A
271
271
272 $ hg -R other debugobsolete
272 $ hg -R other debugobsolete
273 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
273 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
274 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
274 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
275 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
275 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
276 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
276 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
277 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
277 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
278 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
278 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
279
279
280 push over http
280 push over http
281
281
282 $ hg -R other serve -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
282 $ hg -R other serve -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
283 $ cat other.pid >> $DAEMON_PIDS
283 $ cat other.pid >> $DAEMON_PIDS
284
284
285 $ hg -R main phase --public 32af7686d403
285 $ hg -R main phase --public 32af7686d403
286 $ hg -R main push http://localhost:$HGPORT2/ -r 32af7686d403 --bookmark book_32af
286 $ hg -R main push http://localhost:$HGPORT2/ -r 32af7686d403 --bookmark book_32af
287 pushing to http://localhost:$HGPORT2/
287 pushing to http://localhost:$HGPORT2/
288 searching for changes
288 searching for changes
289 remote: adding changesets
289 remote: adding changesets
290 remote: adding manifests
290 remote: adding manifests
291 remote: adding file changes
291 remote: adding file changes
292 remote: added 1 changesets with 1 changes to 1 files
292 remote: added 1 changesets with 1 changes to 1 files
293 remote: 1 new obsolescence markers
293 remote: 1 new obsolescence markers
294 updating bookmark book_32af
294 updating bookmark book_32af
295 $ cat other-error.log
295 $ cat other-error.log
296
296
297 Check final content.
297 Check final content.
298
298
299 $ hg -R other log -G
299 $ hg -R other log -G
300 o 7:32af7686d403 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af D
300 o 7:32af7686d403 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af D
301 |
301 |
302 o 6:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C
302 o 6:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C
303 |
303 |
304 o 5:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B
304 o 5:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B
305 |
305 |
306 | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H
306 | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H
307 | |
307 | |
308 | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
308 | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
309 | |/|
309 | |/|
310 | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
310 | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
311 |/ /
311 |/ /
312 | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
312 | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
313 |/
313 |/
314 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
314 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
315
315
316 $ hg -R other debugobsolete
316 $ hg -R other debugobsolete
317 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
317 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
318 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
318 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
319 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
319 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
320 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
320 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
321 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
321 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
322 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
322 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
323 7777777777777777777777777777777777777777 32af7686d403cf45b5d95f2d70cebea587ac806a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
323 7777777777777777777777777777777777777777 32af7686d403cf45b5d95f2d70cebea587ac806a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
324
324
325 (check that no 'pending' files remain)
325 (check that no 'pending' files remain)
326
326
327 $ ls -1 other/.hg/bookmarks*
327 $ ls -1 other/.hg/bookmarks*
328 other/.hg/bookmarks
328 other/.hg/bookmarks
329 $ ls -1 other/.hg/store/phaseroots*
329 $ ls -1 other/.hg/store/phaseroots*
330 other/.hg/store/phaseroots
330 other/.hg/store/phaseroots
331 $ ls -1 other/.hg/store/00changelog.i*
331 $ ls -1 other/.hg/store/00changelog.i*
332 other/.hg/store/00changelog.i
332 other/.hg/store/00changelog.i
333
333
334 Error Handling
334 Error Handling
335 ==============
335 ==============
336
336
337 Check that errors are properly returned to the client during push.
337 Check that errors are properly returned to the client during push.
338
338
339 Setting up
339 Setting up
340
340
341 $ cat > failpush.py << EOF
341 $ cat > failpush.py << EOF
342 > """A small extension that makes push fails when using bundle2
342 > """A small extension that makes push fails when using bundle2
343 >
343 >
344 > used to test error handling in bundle2
344 > used to test error handling in bundle2
345 > """
345 > """
346 >
346 >
347 > from mercurial import util
347 > from mercurial import util
348 > from mercurial import bundle2
348 > from mercurial import bundle2
349 > from mercurial import exchange
349 > from mercurial import exchange
350 > from mercurial import extensions
350 > from mercurial import extensions
351 >
351 >
352 > def _pushbundle2failpart(pushop, bundler):
352 > def _pushbundle2failpart(pushop, bundler):
353 > reason = pushop.ui.config('failpush', 'reason', None)
353 > reason = pushop.ui.config('failpush', 'reason', None)
354 > part = None
354 > part = None
355 > if reason == 'abort':
355 > if reason == 'abort':
356 > bundler.newpart('test:abort')
356 > bundler.newpart('test:abort')
357 > if reason == 'unknown':
357 > if reason == 'unknown':
358 > bundler.newpart('TEST:UNKNOWN')
358 > bundler.newpart('TEST:UNKNOWN')
359 > if reason == 'race':
359 > if reason == 'race':
360 > # 20 Bytes of crap
360 > # 20 Bytes of crap
361 > bundler.newpart('b2x:check:heads', data='01234567890123456789')
361 > bundler.newpart('b2x:check:heads', data='01234567890123456789')
362 >
362 >
363 > @bundle2.parthandler("test:abort")
363 > @bundle2.parthandler("test:abort")
364 > def handleabort(op, part):
364 > def handleabort(op, part):
365 > raise util.Abort('Abandon ship!', hint="don't panic")
365 > raise util.Abort('Abandon ship!', hint="don't panic")
366 >
366 >
367 > def uisetup(ui):
367 > def uisetup(ui):
368 > exchange.b2partsgenmapping['failpart'] = _pushbundle2failpart
368 > exchange.b2partsgenmapping['failpart'] = _pushbundle2failpart
369 > exchange.b2partsgenorder.insert(0, 'failpart')
369 > exchange.b2partsgenorder.insert(0, 'failpart')
370 >
370 >
371 > EOF
371 > EOF
372
372
373 $ cd main
373 $ cd main
374 $ hg up tip
374 $ hg up tip
375 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
375 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
376 $ echo 'I' > I
376 $ echo 'I' > I
377 $ hg add I
377 $ hg add I
378 $ hg ci -m 'I'
378 $ hg ci -m 'I'
379 $ hg id
379 $ hg id
380 e7ec4e813ba6 tip
380 e7ec4e813ba6 tip
381 $ cd ..
381 $ cd ..
382
382
383 $ cat << EOF >> $HGRCPATH
383 $ cat << EOF >> $HGRCPATH
384 > [extensions]
384 > [extensions]
385 > failpush=$TESTTMP/failpush.py
385 > failpush=$TESTTMP/failpush.py
386 > EOF
386 > EOF
387
387
388 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
388 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
389 $ hg -R other serve -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
389 $ hg -R other serve -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
390 $ cat other.pid >> $DAEMON_PIDS
390 $ cat other.pid >> $DAEMON_PIDS
391
391
392 Doing the actual push: Abort error
392 Doing the actual push: Abort error
393
393
394 $ cat << EOF >> $HGRCPATH
394 $ cat << EOF >> $HGRCPATH
395 > [failpush]
395 > [failpush]
396 > reason = abort
396 > reason = abort
397 > EOF
397 > EOF
398
398
399 $ hg -R main push other -r e7ec4e813ba6
399 $ hg -R main push other -r e7ec4e813ba6
400 pushing to other
400 pushing to other
401 searching for changes
401 searching for changes
402 abort: Abandon ship!
402 abort: Abandon ship!
403 (don't panic)
403 (don't panic)
404 [255]
404 [255]
405
405
406 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
406 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
407 pushing to ssh://user@dummy/other
407 pushing to ssh://user@dummy/other
408 searching for changes
408 searching for changes
409 abort: Abandon ship!
409 abort: Abandon ship!
410 (don't panic)
410 (don't panic)
411 [255]
411 [255]
412
412
413 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
413 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
414 pushing to http://localhost:$HGPORT2/
414 pushing to http://localhost:$HGPORT2/
415 searching for changes
415 searching for changes
416 abort: Abandon ship!
416 abort: Abandon ship!
417 (don't panic)
417 (don't panic)
418 [255]
418 [255]
419
419
420
420
421 Doing the actual push: unknown mandatory parts
421 Doing the actual push: unknown mandatory parts
422
422
423 $ cat << EOF >> $HGRCPATH
423 $ cat << EOF >> $HGRCPATH
424 > [failpush]
424 > [failpush]
425 > reason = unknown
425 > reason = unknown
426 > EOF
426 > EOF
427
427
428 $ hg -R main push other -r e7ec4e813ba6
428 $ hg -R main push other -r e7ec4e813ba6
429 pushing to other
429 pushing to other
430 searching for changes
430 searching for changes
431 abort: missing support for test:unknown
431 abort: missing support for test:unknown
432 [255]
432 [255]
433
433
434 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
434 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
435 pushing to ssh://user@dummy/other
435 pushing to ssh://user@dummy/other
436 searching for changes
436 searching for changes
437 abort: missing support for test:unknown
437 abort: missing support for test:unknown
438 [255]
438 [255]
439
439
440 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
440 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
441 pushing to http://localhost:$HGPORT2/
441 pushing to http://localhost:$HGPORT2/
442 searching for changes
442 searching for changes
443 abort: missing support for test:unknown
443 abort: missing support for test:unknown
444 [255]
444 [255]
445
445
446 Doing the actual push: race
446 Doing the actual push: race
447
447
448 $ cat << EOF >> $HGRCPATH
448 $ cat << EOF >> $HGRCPATH
449 > [failpush]
449 > [failpush]
450 > reason = race
450 > reason = race
451 > EOF
451 > EOF
452
452
453 $ hg -R main push other -r e7ec4e813ba6
453 $ hg -R main push other -r e7ec4e813ba6
454 pushing to other
454 pushing to other
455 searching for changes
455 searching for changes
456 abort: push failed:
456 abort: push failed:
457 'repository changed while pushing - please try again'
457 'repository changed while pushing - please try again'
458 [255]
458 [255]
459
459
460 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
460 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
461 pushing to ssh://user@dummy/other
461 pushing to ssh://user@dummy/other
462 searching for changes
462 searching for changes
463 abort: push failed:
463 abort: push failed:
464 'repository changed while pushing - please try again'
464 'repository changed while pushing - please try again'
465 [255]
465 [255]
466
466
467 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
467 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
468 pushing to http://localhost:$HGPORT2/
468 pushing to http://localhost:$HGPORT2/
469 searching for changes
469 searching for changes
470 abort: push failed:
470 abort: push failed:
471 'repository changed while pushing - please try again'
471 'repository changed while pushing - please try again'
472 [255]
472 [255]
473
473
474 Doing the actual push: hook abort
474 Doing the actual push: hook abort
475
475
476 $ cat << EOF >> $HGRCPATH
476 $ cat << EOF >> $HGRCPATH
477 > [failpush]
477 > [failpush]
478 > reason =
478 > reason =
479 > [hooks]
479 > [hooks]
480 > b2x-pretransactionclose.failpush = false
480 > b2x-pretransactionclose.failpush = false
481 > EOF
481 > EOF
482
482
483 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
483 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
484 $ hg -R other serve -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
484 $ hg -R other serve -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
485 $ cat other.pid >> $DAEMON_PIDS
485 $ cat other.pid >> $DAEMON_PIDS
486
486
487 $ hg -R main push other -r e7ec4e813ba6
487 $ hg -R main push other -r e7ec4e813ba6
488 pushing to other
488 pushing to other
489 searching for changes
489 searching for changes
490 pre-close-tip:e7ec4e813ba6 draft
490 pre-close-tip:e7ec4e813ba6 draft
491 transaction abort!
491 transaction abort!
492 rollback completed
492 rollback completed
493 abort: b2x-pretransactionclose.failpush hook exited with status 1
493 abort: b2x-pretransactionclose.failpush hook exited with status 1
494 [255]
494 [255]
495
495
496 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
496 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
497 pushing to ssh://user@dummy/other
497 pushing to ssh://user@dummy/other
498 searching for changes
498 searching for changes
499 abort: b2x-pretransactionclose.failpush hook exited with status 1
499 abort: b2x-pretransactionclose.failpush hook exited with status 1
500 remote: pre-close-tip:e7ec4e813ba6 draft
500 remote: pre-close-tip:e7ec4e813ba6 draft
501 remote: transaction abort!
501 remote: transaction abort!
502 remote: rollback completed
502 remote: rollback completed
503 [255]
503 [255]
504
504
505 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
505 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
506 pushing to http://localhost:$HGPORT2/
506 pushing to http://localhost:$HGPORT2/
507 searching for changes
507 searching for changes
508 abort: b2x-pretransactionclose.failpush hook exited with status 1
508 abort: b2x-pretransactionclose.failpush hook exited with status 1
509 [255]
509 [255]
510
510
511 (check that no 'pending' files remain)
511 (check that no 'pending' files remain)
512
512
513 $ ls -1 other/.hg/bookmarks*
513 $ ls -1 other/.hg/bookmarks*
514 other/.hg/bookmarks
514 other/.hg/bookmarks
515 $ ls -1 other/.hg/store/phaseroots*
515 $ ls -1 other/.hg/store/phaseroots*
516 other/.hg/store/phaseroots
516 other/.hg/store/phaseroots
517 $ ls -1 other/.hg/store/00changelog.i*
517 $ ls -1 other/.hg/store/00changelog.i*
518 other/.hg/store/00changelog.i
518 other/.hg/store/00changelog.i
519
519
General Comments 0
You need to be logged in to leave comments. Login now