##// END OF EJS Templates
bookmark: read pending data when appropriate...
Pierre-Yves David -
r23360:e06daad6 default
parent child Browse files
Show More
@@ -1,442 +1,452
1 1 # Mercurial bookmark support code
2 2 #
3 3 # Copyright 2008 David Soria Parra <dsp@php.net>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 import os
8 9 from mercurial.i18n import _
9 10 from mercurial.node import hex, bin
10 11 from mercurial import encoding, error, util, obsolete, lock as lockmod
11 12 import errno
12 13
13 14 class bmstore(dict):
14 15 """Storage for bookmarks.
15 16
16 17 This object should do all bookmark reads and writes, so that it's
17 18 fairly simple to replace the storage underlying bookmarks without
18 19 having to clone the logic surrounding bookmarks.
19 20
20 21 This particular bmstore implementation stores bookmarks as
21 22 {hash}\s{name}\n (the same format as localtags) in
22 23 .hg/bookmarks. The mapping is stored as {name: nodeid}.
23 24
24 25 This class does NOT handle the "current" bookmark state at this
25 26 time.
26 27 """
27 28
28 29 def __init__(self, repo):
29 30 dict.__init__(self)
30 31 self._repo = repo
31 32 try:
32 for line in repo.vfs('bookmarks'):
33 bkfile = None
34 if 'HG_PENDING' in os.environ:
35 try:
36 bkfile = repo.vfs('bookmarks.pending')
37 except IOError, inst:
38 if inst.errno != errno.ENOENT:
39 raise
40 if bkfile is None:
41 bkfile = repo.vfs('bookmarks')
42 for line in bkfile:
33 43 line = line.strip()
34 44 if not line:
35 45 continue
36 46 if ' ' not in line:
37 47 repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n')
38 48 % line)
39 49 continue
40 50 sha, refspec = line.split(' ', 1)
41 51 refspec = encoding.tolocal(refspec)
42 52 try:
43 53 self[refspec] = repo.changelog.lookup(sha)
44 54 except LookupError:
45 55 pass
46 56 except IOError, inst:
47 57 if inst.errno != errno.ENOENT:
48 58 raise
49 59
50 60 def recordchange(self, tr):
51 61 """record that bookmarks have been changed in a transaction
52 62
53 63 The transaction is then responsible for updating the file content."""
54 64 tr.addfilegenerator('bookmarks', ('bookmarks',), self._write,
55 65 location='plain')
56 66 tr.hookargs['bookmark_moved'] = '1'
57 67
58 68 def write(self):
59 69 '''Write bookmarks
60 70
61 71 Write the given bookmark => hash dictionary to the .hg/bookmarks file
62 72 in a format equal to those of localtags.
63 73
64 74 We also store a backup of the previous state in undo.bookmarks that
65 75 can be copied back on rollback.
66 76 '''
67 77 repo = self._repo
68 78 if repo._bookmarkcurrent not in self:
69 79 unsetcurrent(repo)
70 80
71 81 wlock = repo.wlock()
72 82 try:
73 83
74 84 file = repo.vfs('bookmarks', 'w', atomictemp=True)
75 85 self._write(file)
76 86 file.close()
77 87
78 88 # touch 00changelog.i so hgweb reloads bookmarks (no lock needed)
79 89 try:
80 90 repo.svfs.utime('00changelog.i', None)
81 91 except OSError:
82 92 pass
83 93
84 94 finally:
85 95 wlock.release()
86 96
87 97 def _write(self, fp):
88 98 for name, node in self.iteritems():
89 99 fp.write("%s %s\n" % (hex(node), encoding.fromlocal(name)))
90 100
91 101 def readcurrent(repo):
92 102 '''Get the current bookmark
93 103
94 104 If we use gittish branches we have a current bookmark that
95 105 we are on. This function returns the name of the bookmark. It
96 106 is stored in .hg/bookmarks.current
97 107 '''
98 108 mark = None
99 109 try:
100 110 file = repo.opener('bookmarks.current')
101 111 except IOError, inst:
102 112 if inst.errno != errno.ENOENT:
103 113 raise
104 114 return None
105 115 try:
106 116 # No readline() in osutil.posixfile, reading everything is cheap
107 117 mark = encoding.tolocal((file.readlines() or [''])[0])
108 118 if mark == '' or mark not in repo._bookmarks:
109 119 mark = None
110 120 finally:
111 121 file.close()
112 122 return mark
113 123
114 124 def setcurrent(repo, mark):
115 125 '''Set the name of the bookmark that we are currently on
116 126
117 127 Set the name of the bookmark that we are on (hg update <bookmark>).
118 128 The name is recorded in .hg/bookmarks.current
119 129 '''
120 130 if mark not in repo._bookmarks:
121 131 raise AssertionError('bookmark %s does not exist!' % mark)
122 132
123 133 current = repo._bookmarkcurrent
124 134 if current == mark:
125 135 return
126 136
127 137 wlock = repo.wlock()
128 138 try:
129 139 file = repo.opener('bookmarks.current', 'w', atomictemp=True)
130 140 file.write(encoding.fromlocal(mark))
131 141 file.close()
132 142 finally:
133 143 wlock.release()
134 144 repo._bookmarkcurrent = mark
135 145
136 146 def unsetcurrent(repo):
137 147 wlock = repo.wlock()
138 148 try:
139 149 try:
140 150 repo.vfs.unlink('bookmarks.current')
141 151 repo._bookmarkcurrent = None
142 152 except OSError, inst:
143 153 if inst.errno != errno.ENOENT:
144 154 raise
145 155 finally:
146 156 wlock.release()
147 157
148 158 def iscurrent(repo, mark=None, parents=None):
149 159 '''Tell whether the current bookmark is also active
150 160
151 161 I.e., the bookmark listed in .hg/bookmarks.current also points to a
152 162 parent of the working directory.
153 163 '''
154 164 if not mark:
155 165 mark = repo._bookmarkcurrent
156 166 if not parents:
157 167 parents = [p.node() for p in repo[None].parents()]
158 168 marks = repo._bookmarks
159 169 return (mark in marks and marks[mark] in parents)
160 170
161 171 def updatecurrentbookmark(repo, oldnode, curbranch):
162 172 try:
163 173 return update(repo, oldnode, repo.branchtip(curbranch))
164 174 except error.RepoLookupError:
165 175 if curbranch == "default": # no default branch!
166 176 return update(repo, oldnode, repo.lookup("tip"))
167 177 else:
168 178 raise util.Abort(_("branch %s not found") % curbranch)
169 179
170 180 def deletedivergent(repo, deletefrom, bm):
171 181 '''Delete divergent versions of bm on nodes in deletefrom.
172 182
173 183 Return True if at least one bookmark was deleted, False otherwise.'''
174 184 deleted = False
175 185 marks = repo._bookmarks
176 186 divergent = [b for b in marks if b.split('@', 1)[0] == bm.split('@', 1)[0]]
177 187 for mark in divergent:
178 188 if mark == '@' or '@' not in mark:
179 189 # can't be divergent by definition
180 190 continue
181 191 if mark and marks[mark] in deletefrom:
182 192 if mark != bm:
183 193 del marks[mark]
184 194 deleted = True
185 195 return deleted
186 196
187 197 def calculateupdate(ui, repo, checkout):
188 198 '''Return a tuple (targetrev, movemarkfrom) indicating the rev to
189 199 check out and where to move the active bookmark from, if needed.'''
190 200 movemarkfrom = None
191 201 if checkout is None:
192 202 curmark = repo._bookmarkcurrent
193 203 if iscurrent(repo):
194 204 movemarkfrom = repo['.'].node()
195 205 elif curmark:
196 206 ui.status(_("updating to active bookmark %s\n") % curmark)
197 207 checkout = curmark
198 208 return (checkout, movemarkfrom)
199 209
200 210 def update(repo, parents, node):
201 211 deletefrom = parents
202 212 marks = repo._bookmarks
203 213 update = False
204 214 cur = repo._bookmarkcurrent
205 215 if not cur:
206 216 return False
207 217
208 218 if marks[cur] in parents:
209 219 new = repo[node]
210 220 divs = [repo[b] for b in marks
211 221 if b.split('@', 1)[0] == cur.split('@', 1)[0]]
212 222 anc = repo.changelog.ancestors([new.rev()])
213 223 deletefrom = [b.node() for b in divs if b.rev() in anc or b == new]
214 224 if validdest(repo, repo[marks[cur]], new):
215 225 marks[cur] = new.node()
216 226 update = True
217 227
218 228 if deletedivergent(repo, deletefrom, cur):
219 229 update = True
220 230
221 231 if update:
222 232 marks.write()
223 233 return update
224 234
225 235 def listbookmarks(repo):
226 236 # We may try to list bookmarks on a repo type that does not
227 237 # support it (e.g., statichttprepository).
228 238 marks = getattr(repo, '_bookmarks', {})
229 239
230 240 d = {}
231 241 hasnode = repo.changelog.hasnode
232 242 for k, v in marks.iteritems():
233 243 # don't expose local divergent bookmarks
234 244 if hasnode(v) and ('@' not in k or k.endswith('@')):
235 245 d[k] = hex(v)
236 246 return d
237 247
238 248 def pushbookmark(repo, key, old, new):
239 249 w = l = tr = None
240 250 try:
241 251 w = repo.wlock()
242 252 l = repo.lock()
243 253 tr = repo.transaction('bookmarks')
244 254 marks = repo._bookmarks
245 255 existing = hex(marks.get(key, ''))
246 256 if existing != old and existing != new:
247 257 return False
248 258 if new == '':
249 259 del marks[key]
250 260 else:
251 261 if new not in repo:
252 262 return False
253 263 marks[key] = repo[new].node()
254 264 marks.recordchange(tr)
255 265 tr.close()
256 266 return True
257 267 finally:
258 268 lockmod.release(tr, l, w)
259 269
260 270 def compare(repo, srcmarks, dstmarks,
261 271 srchex=None, dsthex=None, targets=None):
262 272 '''Compare bookmarks between srcmarks and dstmarks
263 273
264 274 This returns tuple "(addsrc, adddst, advsrc, advdst, diverge,
265 275 differ, invalid)", each are list of bookmarks below:
266 276
267 277 :addsrc: added on src side (removed on dst side, perhaps)
268 278 :adddst: added on dst side (removed on src side, perhaps)
269 279 :advsrc: advanced on src side
270 280 :advdst: advanced on dst side
271 281 :diverge: diverge
272 282 :differ: changed, but changeset referred on src is unknown on dst
273 283 :invalid: unknown on both side
274 284 :same: same on both side
275 285
276 286 Each elements of lists in result tuple is tuple "(bookmark name,
277 287 changeset ID on source side, changeset ID on destination
278 288 side)". Each changeset IDs are 40 hexadecimal digit string or
279 289 None.
280 290
281 291 Changeset IDs of tuples in "addsrc", "adddst", "differ" or
282 292 "invalid" list may be unknown for repo.
283 293
284 294 This function expects that "srcmarks" and "dstmarks" return
285 295 changeset ID in 40 hexadecimal digit string for specified
286 296 bookmark. If not so (e.g. bmstore "repo._bookmarks" returning
287 297 binary value), "srchex" or "dsthex" should be specified to convert
288 298 into such form.
289 299
290 300 If "targets" is specified, only bookmarks listed in it are
291 301 examined.
292 302 '''
293 303 if not srchex:
294 304 srchex = lambda x: x
295 305 if not dsthex:
296 306 dsthex = lambda x: x
297 307
298 308 if targets:
299 309 bset = set(targets)
300 310 else:
301 311 srcmarkset = set(srcmarks)
302 312 dstmarkset = set(dstmarks)
303 313 bset = srcmarkset | dstmarkset
304 314
305 315 results = ([], [], [], [], [], [], [], [])
306 316 addsrc = results[0].append
307 317 adddst = results[1].append
308 318 advsrc = results[2].append
309 319 advdst = results[3].append
310 320 diverge = results[4].append
311 321 differ = results[5].append
312 322 invalid = results[6].append
313 323 same = results[7].append
314 324
315 325 for b in sorted(bset):
316 326 if b not in srcmarks:
317 327 if b in dstmarks:
318 328 adddst((b, None, dsthex(dstmarks[b])))
319 329 else:
320 330 invalid((b, None, None))
321 331 elif b not in dstmarks:
322 332 addsrc((b, srchex(srcmarks[b]), None))
323 333 else:
324 334 scid = srchex(srcmarks[b])
325 335 dcid = dsthex(dstmarks[b])
326 336 if scid == dcid:
327 337 same((b, scid, dcid))
328 338 elif scid in repo and dcid in repo:
329 339 sctx = repo[scid]
330 340 dctx = repo[dcid]
331 341 if sctx.rev() < dctx.rev():
332 342 if validdest(repo, sctx, dctx):
333 343 advdst((b, scid, dcid))
334 344 else:
335 345 diverge((b, scid, dcid))
336 346 else:
337 347 if validdest(repo, dctx, sctx):
338 348 advsrc((b, scid, dcid))
339 349 else:
340 350 diverge((b, scid, dcid))
341 351 else:
342 352 # it is too expensive to examine in detail, in this case
343 353 differ((b, scid, dcid))
344 354
345 355 return results
346 356
347 357 def _diverge(ui, b, path, localmarks):
348 358 if b == '@':
349 359 b = ''
350 360 # find a unique @ suffix
351 361 for x in range(1, 100):
352 362 n = '%s@%d' % (b, x)
353 363 if n not in localmarks:
354 364 break
355 365 # try to use an @pathalias suffix
356 366 # if an @pathalias already exists, we overwrite (update) it
357 367 if path.startswith("file:"):
358 368 path = util.url(path).path
359 369 for p, u in ui.configitems("paths"):
360 370 if u.startswith("file:"):
361 371 u = util.url(u).path
362 372 if path == u:
363 373 n = '%s@%s' % (b, p)
364 374 return n
365 375
366 376 def updatefromremote(ui, repo, remotemarks, path, trfunc, explicit=()):
367 377 ui.debug("checking for updated bookmarks\n")
368 378 localmarks = repo._bookmarks
369 379 (addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same
370 380 ) = compare(repo, remotemarks, localmarks, dsthex=hex)
371 381
372 382 status = ui.status
373 383 warn = ui.warn
374 384 if ui.configbool('ui', 'quietbookmarkmove', False):
375 385 status = warn = ui.debug
376 386
377 387 explicit = set(explicit)
378 388 changed = []
379 389 for b, scid, dcid in addsrc:
380 390 if scid in repo: # add remote bookmarks for changes we already have
381 391 changed.append((b, bin(scid), status,
382 392 _("adding remote bookmark %s\n") % (b)))
383 393 for b, scid, dcid in advsrc:
384 394 changed.append((b, bin(scid), status,
385 395 _("updating bookmark %s\n") % (b)))
386 396 # remove normal movement from explicit set
387 397 explicit.difference_update(d[0] for d in changed)
388 398
389 399 for b, scid, dcid in diverge:
390 400 if b in explicit:
391 401 explicit.discard(b)
392 402 changed.append((b, bin(scid), status,
393 403 _("importing bookmark %s\n") % (b)))
394 404 else:
395 405 db = _diverge(ui, b, path, localmarks)
396 406 changed.append((db, bin(scid), warn,
397 407 _("divergent bookmark %s stored as %s\n")
398 408 % (b, db)))
399 409 for b, scid, dcid in adddst + advdst:
400 410 if b in explicit:
401 411 explicit.discard(b)
402 412 changed.append((b, bin(scid), status,
403 413 _("importing bookmark %s\n") % (b)))
404 414
405 415 if changed:
406 416 tr = trfunc()
407 417 for b, node, writer, msg in sorted(changed):
408 418 localmarks[b] = node
409 419 writer(msg)
410 420 localmarks.recordchange(tr)
411 421
412 422 def diff(ui, dst, src):
413 423 ui.status(_("searching for changed bookmarks\n"))
414 424
415 425 smarks = src.listkeys('bookmarks')
416 426 dmarks = dst.listkeys('bookmarks')
417 427
418 428 diff = sorted(set(smarks) - set(dmarks))
419 429 for k in diff:
420 430 mark = ui.debugflag and smarks[k] or smarks[k][:12]
421 431 ui.write(" %-25s %s\n" % (k, mark))
422 432
423 433 if len(diff) <= 0:
424 434 ui.status(_("no changed bookmarks found\n"))
425 435 return 1
426 436 return 0
427 437
428 438 def validdest(repo, old, new):
429 439 """Is the new bookmark destination a valid update from the old one"""
430 440 repo = repo.unfiltered()
431 441 if old == new:
432 442 # Old == new -> nothing to update.
433 443 return False
434 444 elif not old:
435 445 # old is nullrev, anything is valid.
436 446 # (new != nullrev has been excluded by the previous check)
437 447 return True
438 448 elif repo.obsstore:
439 449 return new.node() in obsolete.foreground(repo, [old.node()])
440 450 else:
441 451 # still an independent clause as it is lazyer (and therefore faster)
442 452 return old.descendant(new)
@@ -1,519 +1,519
1 1 Test exchange of common information using bundle2
2 2
3 3
4 4 $ getmainid() {
5 5 > hg -R main log --template '{node}\n' --rev "$1"
6 6 > }
7 7
8 8 enable obsolescence
9 9
10 10 $ cat >> $HGRCPATH << EOF
11 11 > [experimental]
12 12 > evolution=createmarkers,exchange
13 13 > bundle2-exp=True
14 14 > [ui]
15 15 > ssh=python "$TESTDIR/dummyssh"
16 16 > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
17 17 > [web]
18 18 > push_ssl = false
19 19 > allow_push = *
20 20 > [phases]
21 21 > publish=False
22 22 > [hooks]
23 23 > changegroup = sh -c "HG_LOCAL= python \"$TESTDIR/printenv.py\" changegroup"
24 24 > b2x-pretransactionclose.tip = printf 'pre-close-tip:'; hg log -r tip -T '{node|short} {phase} {bookmarks}\n'
25 25 > b2x-transactionclose.tip = printf 'postclose-tip:'; hg log -r tip -T '{node|short} {phase} {bookmarks}\n'
26 26 > b2x-transactionclose.env = sh -c "HG_LOCAL= python \"$TESTDIR/printenv.py\" b2x-transactionclose"
27 27 > EOF
28 28
29 29 The extension requires a repo (currently unused)
30 30
31 31 $ hg init main
32 32 $ cd main
33 33 $ touch a
34 34 $ hg add a
35 35 $ hg commit -m 'a'
36 36
37 37 $ hg unbundle $TESTDIR/bundles/rebase.hg
38 38 adding changesets
39 39 adding manifests
40 40 adding file changes
41 41 added 8 changesets with 7 changes to 7 files (+3 heads)
42 42 changegroup hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_SOURCE=unbundle HG_URL=bundle:*/rebase.hg (glob)
43 43 (run 'hg heads' to see heads, 'hg merge' to merge)
44 44
45 45 $ cd ..
46 46
47 47 Real world exchange
48 48 =====================
49 49
50 50 Add more obsolescence information
51 51
52 52 $ hg -R main debugobsolete -d '0 0' 1111111111111111111111111111111111111111 `getmainid 9520eea781bc`
53 53 $ hg -R main debugobsolete -d '0 0' 2222222222222222222222222222222222222222 `getmainid 24b6387c8c8c`
54 54
55 55 clone --pull
56 56
57 57 $ hg -R main phase --public cd010b8cd998
58 58 $ hg clone main other --pull --rev 9520eea781bc
59 59 adding changesets
60 60 adding manifests
61 61 adding file changes
62 62 added 2 changesets with 2 changes to 2 files
63 63 1 new obsolescence markers
64 64 pre-close-tip:9520eea781bc public
65 65 postclose-tip:9520eea781bc draft
66 66 b2x-transactionclose hook: HG_NEW_OBSMARKERS=1 HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
67 67 changegroup hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
68 68 updating to branch default
69 69 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
70 70 $ hg -R other log -G
71 71 @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
72 72 |
73 73 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
74 74
75 75 $ hg -R other debugobsolete
76 76 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
77 77
78 78 pull
79 79
80 80 $ hg -R main phase --public 9520eea781bc
81 81 $ hg -R other pull -r 24b6387c8c8c
82 82 pulling from $TESTTMP/main (glob)
83 83 searching for changes
84 84 adding changesets
85 85 adding manifests
86 86 adding file changes
87 87 added 1 changesets with 1 changes to 1 files (+1 heads)
88 88 1 new obsolescence markers
89 89 pre-close-tip:24b6387c8c8c public
90 90 postclose-tip:24b6387c8c8c draft
91 91 b2x-transactionclose hook: HG_NEW_OBSMARKERS=1 HG_NODE=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
92 92 changegroup hook: HG_NODE=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
93 93 (run 'hg heads' to see heads, 'hg merge' to merge)
94 94 $ hg -R other log -G
95 95 o 2:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F
96 96 |
97 97 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
98 98 |/
99 99 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
100 100
101 101 $ hg -R other debugobsolete
102 102 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
103 103 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
104 104
105 105 pull empty (with phase movement)
106 106
107 107 $ hg -R main phase --public 24b6387c8c8c
108 108 $ hg -R other pull -r 24b6387c8c8c
109 109 pulling from $TESTTMP/main (glob)
110 110 no changes found
111 111 pre-close-tip:000000000000 public
112 112 postclose-tip:24b6387c8c8c public
113 113 b2x-transactionclose hook: HG_NEW_OBSMARKERS=0 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
114 114 $ hg -R other log -G
115 115 o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
116 116 |
117 117 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
118 118 |/
119 119 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
120 120
121 121 $ hg -R other debugobsolete
122 122 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
123 123 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
124 124
125 125 pull empty
126 126
127 127 $ hg -R other pull -r 24b6387c8c8c
128 128 pulling from $TESTTMP/main (glob)
129 129 no changes found
130 130 pre-close-tip:24b6387c8c8c public
131 131 postclose-tip:24b6387c8c8c public
132 132 b2x-transactionclose hook: HG_NEW_OBSMARKERS=0 HG_SOURCE=pull HG_URL=file:$TESTTMP/main
133 133 $ hg -R other log -G
134 134 o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
135 135 |
136 136 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
137 137 |/
138 138 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
139 139
140 140 $ hg -R other debugobsolete
141 141 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
142 142 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
143 143
144 144 add extra data to test their exchange during push
145 145
146 146 $ hg -R main bookmark --rev eea13746799a book_eea1
147 147 $ hg -R main debugobsolete -d '0 0' 3333333333333333333333333333333333333333 `getmainid eea13746799a`
148 148 $ hg -R main bookmark --rev 02de42196ebe book_02de
149 149 $ hg -R main debugobsolete -d '0 0' 4444444444444444444444444444444444444444 `getmainid 02de42196ebe`
150 150 $ hg -R main bookmark --rev 42ccdea3bb16 book_42cc
151 151 $ hg -R main debugobsolete -d '0 0' 5555555555555555555555555555555555555555 `getmainid 42ccdea3bb16`
152 152 $ hg -R main bookmark --rev 5fddd98957c8 book_5fdd
153 153 $ hg -R main debugobsolete -d '0 0' 6666666666666666666666666666666666666666 `getmainid 5fddd98957c8`
154 154 $ hg -R main bookmark --rev 32af7686d403 book_32af
155 155 $ hg -R main debugobsolete -d '0 0' 7777777777777777777777777777777777777777 `getmainid 32af7686d403`
156 156
157 157 $ hg -R other bookmark --rev cd010b8cd998 book_eea1
158 158 $ hg -R other bookmark --rev cd010b8cd998 book_02de
159 159 $ hg -R other bookmark --rev cd010b8cd998 book_42cc
160 160 $ hg -R other bookmark --rev cd010b8cd998 book_5fdd
161 161 $ hg -R other bookmark --rev cd010b8cd998 book_32af
162 162
163 163 $ hg -R main phase --public eea13746799a
164 164
165 165 push
166 166 $ hg -R main push other --rev eea13746799a --bookmark book_eea1
167 167 pushing to other
168 168 searching for changes
169 pre-close-tip:eea13746799a draft
169 pre-close-tip:eea13746799a draft book_eea1
170 170 postclose-tip:eea13746799a public book_eea1
171 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 172 changegroup hook: HG_BUNDLE2-EXP=1 HG_NODE=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_SOURCE=push HG_URL=push
173 173 remote: adding changesets
174 174 remote: adding manifests
175 175 remote: adding file changes
176 176 remote: added 1 changesets with 0 changes to 0 files (-1 heads)
177 177 remote: 1 new obsolescence markers
178 178 updating bookmark book_eea1
179 179 $ hg -R other log -G
180 180 o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
181 181 |\
182 182 | o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
183 183 | |
184 184 @ | 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
185 185 |/
186 186 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de book_32af book_42cc book_5fdd A
187 187
188 188 $ hg -R other debugobsolete
189 189 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
190 190 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
191 191 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
192 192
193 193 pull over ssh
194 194
195 195 $ hg -R other pull ssh://user@dummy/main -r 02de42196ebe --bookmark book_02de
196 196 pulling from ssh://user@dummy/main
197 197 searching for changes
198 198 adding changesets
199 199 adding manifests
200 200 adding file changes
201 201 added 1 changesets with 1 changes to 1 files (+1 heads)
202 202 1 new obsolescence markers
203 203 updating bookmark book_02de
204 pre-close-tip:02de42196ebe public
204 pre-close-tip:02de42196ebe public book_02de
205 205 postclose-tip:02de42196ebe draft book_02de
206 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 207 changegroup hook: HG_NODE=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_SOURCE=pull HG_URL=ssh://user@dummy/main
208 208 (run 'hg heads' to see heads, 'hg merge' to merge)
209 209 $ hg -R other debugobsolete
210 210 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
211 211 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
212 212 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
213 213 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
214 214
215 215 pull over http
216 216
217 217 $ hg -R main serve -p $HGPORT -d --pid-file=main.pid -E main-error.log
218 218 $ cat main.pid >> $DAEMON_PIDS
219 219
220 220 $ hg -R other pull http://localhost:$HGPORT/ -r 42ccdea3bb16 --bookmark book_42cc
221 221 pulling from http://localhost:$HGPORT/
222 222 searching for changes
223 223 adding changesets
224 224 adding manifests
225 225 adding file changes
226 226 added 1 changesets with 1 changes to 1 files (+1 heads)
227 227 1 new obsolescence markers
228 228 updating bookmark book_42cc
229 pre-close-tip:42ccdea3bb16 public
229 pre-close-tip:42ccdea3bb16 public book_42cc
230 230 postclose-tip:42ccdea3bb16 draft book_42cc
231 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 232 changegroup hook: HG_NODE=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_SOURCE=pull HG_URL=http://localhost:$HGPORT/
233 233 (run 'hg heads .' to see heads, 'hg merge' to merge)
234 234 $ cat main-error.log
235 235 $ hg -R other debugobsolete
236 236 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
237 237 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
238 238 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
239 239 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
240 240 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
241 241
242 242 push over ssh
243 243
244 244 $ hg -R main push ssh://user@dummy/other -r 5fddd98957c8 --bookmark book_5fdd
245 245 pushing to ssh://user@dummy/other
246 246 searching for changes
247 247 remote: adding changesets
248 248 remote: adding manifests
249 249 remote: adding file changes
250 250 remote: added 1 changesets with 1 changes to 1 files
251 251 remote: 1 new obsolescence markers
252 252 updating bookmark book_5fdd
253 remote: pre-close-tip:5fddd98957c8 draft
253 remote: pre-close-tip:5fddd98957c8 draft book_5fdd
254 254 remote: postclose-tip:5fddd98957c8 draft book_5fdd
255 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 256 remote: changegroup hook: HG_BUNDLE2-EXP=1 HG_NODE=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_SOURCE=serve HG_URL=remote:ssh:127.0.0.1
257 257 $ hg -R other log -G
258 258 o 6:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C
259 259 |
260 260 o 5:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B
261 261 |
262 262 | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H
263 263 | |
264 264 | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
265 265 | |/|
266 266 | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
267 267 |/ /
268 268 | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
269 269 |/
270 270 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af A
271 271
272 272 $ hg -R other debugobsolete
273 273 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
274 274 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
275 275 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
276 276 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
277 277 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
278 278 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
279 279
280 280 push over http
281 281
282 282 $ hg -R other serve -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
283 283 $ cat other.pid >> $DAEMON_PIDS
284 284
285 285 $ hg -R main phase --public 32af7686d403
286 286 $ hg -R main push http://localhost:$HGPORT2/ -r 32af7686d403 --bookmark book_32af
287 287 pushing to http://localhost:$HGPORT2/
288 288 searching for changes
289 289 remote: adding changesets
290 290 remote: adding manifests
291 291 remote: adding file changes
292 292 remote: added 1 changesets with 1 changes to 1 files
293 293 remote: 1 new obsolescence markers
294 294 updating bookmark book_32af
295 295 $ cat other-error.log
296 296
297 297 Check final content.
298 298
299 299 $ hg -R other log -G
300 300 o 7:32af7686d403 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af D
301 301 |
302 302 o 6:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C
303 303 |
304 304 o 5:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B
305 305 |
306 306 | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H
307 307 | |
308 308 | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
309 309 | |/|
310 310 | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
311 311 |/ /
312 312 | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
313 313 |/
314 314 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
315 315
316 316 $ hg -R other debugobsolete
317 317 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
318 318 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
319 319 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
320 320 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
321 321 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
322 322 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
323 323 7777777777777777777777777777777777777777 32af7686d403cf45b5d95f2d70cebea587ac806a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
324 324
325 325 (check that no 'pending' files remain)
326 326
327 327 $ ls -1 other/.hg/bookmarks*
328 328 other/.hg/bookmarks
329 329 $ ls -1 other/.hg/store/phaseroots*
330 330 other/.hg/store/phaseroots
331 331 $ ls -1 other/.hg/store/00changelog.i*
332 332 other/.hg/store/00changelog.i
333 333
334 334 Error Handling
335 335 ==============
336 336
337 337 Check that errors are properly returned to the client during push.
338 338
339 339 Setting up
340 340
341 341 $ cat > failpush.py << EOF
342 342 > """A small extension that makes push fails when using bundle2
343 343 >
344 344 > used to test error handling in bundle2
345 345 > """
346 346 >
347 347 > from mercurial import util
348 348 > from mercurial import bundle2
349 349 > from mercurial import exchange
350 350 > from mercurial import extensions
351 351 >
352 352 > def _pushbundle2failpart(pushop, bundler):
353 353 > reason = pushop.ui.config('failpush', 'reason', None)
354 354 > part = None
355 355 > if reason == 'abort':
356 356 > bundler.newpart('test:abort')
357 357 > if reason == 'unknown':
358 358 > bundler.newpart('TEST:UNKNOWN')
359 359 > if reason == 'race':
360 360 > # 20 Bytes of crap
361 361 > bundler.newpart('b2x:check:heads', data='01234567890123456789')
362 362 >
363 363 > @bundle2.parthandler("test:abort")
364 364 > def handleabort(op, part):
365 365 > raise util.Abort('Abandon ship!', hint="don't panic")
366 366 >
367 367 > def uisetup(ui):
368 368 > exchange.b2partsgenmapping['failpart'] = _pushbundle2failpart
369 369 > exchange.b2partsgenorder.insert(0, 'failpart')
370 370 >
371 371 > EOF
372 372
373 373 $ cd main
374 374 $ hg up tip
375 375 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
376 376 $ echo 'I' > I
377 377 $ hg add I
378 378 $ hg ci -m 'I'
379 379 $ hg id
380 380 e7ec4e813ba6 tip
381 381 $ cd ..
382 382
383 383 $ cat << EOF >> $HGRCPATH
384 384 > [extensions]
385 385 > failpush=$TESTTMP/failpush.py
386 386 > EOF
387 387
388 388 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
389 389 $ hg -R other serve -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
390 390 $ cat other.pid >> $DAEMON_PIDS
391 391
392 392 Doing the actual push: Abort error
393 393
394 394 $ cat << EOF >> $HGRCPATH
395 395 > [failpush]
396 396 > reason = abort
397 397 > EOF
398 398
399 399 $ hg -R main push other -r e7ec4e813ba6
400 400 pushing to other
401 401 searching for changes
402 402 abort: Abandon ship!
403 403 (don't panic)
404 404 [255]
405 405
406 406 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
407 407 pushing to ssh://user@dummy/other
408 408 searching for changes
409 409 abort: Abandon ship!
410 410 (don't panic)
411 411 [255]
412 412
413 413 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
414 414 pushing to http://localhost:$HGPORT2/
415 415 searching for changes
416 416 abort: Abandon ship!
417 417 (don't panic)
418 418 [255]
419 419
420 420
421 421 Doing the actual push: unknown mandatory parts
422 422
423 423 $ cat << EOF >> $HGRCPATH
424 424 > [failpush]
425 425 > reason = unknown
426 426 > EOF
427 427
428 428 $ hg -R main push other -r e7ec4e813ba6
429 429 pushing to other
430 430 searching for changes
431 431 abort: missing support for test:unknown
432 432 [255]
433 433
434 434 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
435 435 pushing to ssh://user@dummy/other
436 436 searching for changes
437 437 abort: missing support for test:unknown
438 438 [255]
439 439
440 440 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
441 441 pushing to http://localhost:$HGPORT2/
442 442 searching for changes
443 443 abort: missing support for test:unknown
444 444 [255]
445 445
446 446 Doing the actual push: race
447 447
448 448 $ cat << EOF >> $HGRCPATH
449 449 > [failpush]
450 450 > reason = race
451 451 > EOF
452 452
453 453 $ hg -R main push other -r e7ec4e813ba6
454 454 pushing to other
455 455 searching for changes
456 456 abort: push failed:
457 457 'repository changed while pushing - please try again'
458 458 [255]
459 459
460 460 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
461 461 pushing to ssh://user@dummy/other
462 462 searching for changes
463 463 abort: push failed:
464 464 'repository changed while pushing - please try again'
465 465 [255]
466 466
467 467 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
468 468 pushing to http://localhost:$HGPORT2/
469 469 searching for changes
470 470 abort: push failed:
471 471 'repository changed while pushing - please try again'
472 472 [255]
473 473
474 474 Doing the actual push: hook abort
475 475
476 476 $ cat << EOF >> $HGRCPATH
477 477 > [failpush]
478 478 > reason =
479 479 > [hooks]
480 480 > b2x-pretransactionclose.failpush = false
481 481 > EOF
482 482
483 483 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
484 484 $ hg -R other serve -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
485 485 $ cat other.pid >> $DAEMON_PIDS
486 486
487 487 $ hg -R main push other -r e7ec4e813ba6
488 488 pushing to other
489 489 searching for changes
490 490 pre-close-tip:e7ec4e813ba6 draft
491 491 transaction abort!
492 492 rollback completed
493 493 abort: b2x-pretransactionclose.failpush hook exited with status 1
494 494 [255]
495 495
496 496 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
497 497 pushing to ssh://user@dummy/other
498 498 searching for changes
499 499 abort: b2x-pretransactionclose.failpush hook exited with status 1
500 500 remote: pre-close-tip:e7ec4e813ba6 draft
501 501 remote: transaction abort!
502 502 remote: rollback completed
503 503 [255]
504 504
505 505 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
506 506 pushing to http://localhost:$HGPORT2/
507 507 searching for changes
508 508 abort: b2x-pretransactionclose.failpush hook exited with status 1
509 509 [255]
510 510
511 511 (check that no 'pending' files remain)
512 512
513 513 $ ls -1 other/.hg/bookmarks*
514 514 other/.hg/bookmarks
515 515 $ ls -1 other/.hg/store/phaseroots*
516 516 other/.hg/store/phaseroots
517 517 $ ls -1 other/.hg/store/00changelog.i*
518 518 other/.hg/store/00changelog.i
519 519
General Comments 0
You need to be logged in to leave comments. Login now