##// END OF EJS Templates
bookmarks: abort 'push -B .' when no active bookmark
liscju -
r29354:af849596 default
parent child Browse files
Show More
@@ -1,606 +1,610 b''
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 8 from __future__ import absolute_import
9 9
10 10 import errno
11 11 import os
12 12
13 13 from .i18n import _
14 14 from .node import (
15 15 bin,
16 16 hex,
17 17 )
18 18 from . import (
19 19 encoding,
20 error,
20 21 lock as lockmod,
21 22 obsolete,
22 23 util,
23 24 )
24 25
25 26 def _getbkfile(repo):
26 27 """Hook so that extensions that mess with the store can hook bm storage.
27 28
28 29 For core, this just handles wether we should see pending
29 30 bookmarks or the committed ones. Other extensions (like share)
30 31 may need to tweak this behavior further.
31 32 """
32 33 bkfile = None
33 34 if 'HG_PENDING' in os.environ:
34 35 try:
35 36 bkfile = repo.vfs('bookmarks.pending')
36 37 except IOError as inst:
37 38 if inst.errno != errno.ENOENT:
38 39 raise
39 40 if bkfile is None:
40 41 bkfile = repo.vfs('bookmarks')
41 42 return bkfile
42 43
43 44
44 45 class bmstore(dict):
45 46 """Storage for bookmarks.
46 47
47 48 This object should do all bookmark-related reads and writes, so
48 49 that it's fairly simple to replace the storage underlying
49 50 bookmarks without having to clone the logic surrounding
50 51 bookmarks. This type also should manage the active bookmark, if
51 52 any.
52 53
53 54 This particular bmstore implementation stores bookmarks as
54 55 {hash}\s{name}\n (the same format as localtags) in
55 56 .hg/bookmarks. The mapping is stored as {name: nodeid}.
56 57 """
57 58
58 59 def __init__(self, repo):
59 60 dict.__init__(self)
60 61 self._repo = repo
61 62 try:
62 63 bkfile = _getbkfile(repo)
63 64 for line in bkfile:
64 65 line = line.strip()
65 66 if not line:
66 67 continue
67 68 if ' ' not in line:
68 69 repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n')
69 70 % line)
70 71 continue
71 72 sha, refspec = line.split(' ', 1)
72 73 refspec = encoding.tolocal(refspec)
73 74 try:
74 75 self[refspec] = repo.changelog.lookup(sha)
75 76 except LookupError:
76 77 pass
77 78 except IOError as inst:
78 79 if inst.errno != errno.ENOENT:
79 80 raise
80 81 self._clean = True
81 82 self._active = _readactive(repo, self)
82 83 self._aclean = True
83 84
84 85 @property
85 86 def active(self):
86 87 return self._active
87 88
88 89 @active.setter
89 90 def active(self, mark):
90 91 if mark is not None and mark not in self:
91 92 raise AssertionError('bookmark %s does not exist!' % mark)
92 93
93 94 self._active = mark
94 95 self._aclean = False
95 96
96 97 def __setitem__(self, *args, **kwargs):
97 98 self._clean = False
98 99 return dict.__setitem__(self, *args, **kwargs)
99 100
100 101 def __delitem__(self, key):
101 102 self._clean = False
102 103 return dict.__delitem__(self, key)
103 104
104 105 def recordchange(self, tr):
105 106 """record that bookmarks have been changed in a transaction
106 107
107 108 The transaction is then responsible for updating the file content."""
108 109 tr.addfilegenerator('bookmarks', ('bookmarks',), self._write,
109 110 location='plain')
110 111 tr.hookargs['bookmark_moved'] = '1'
111 112
112 113 def _writerepo(self, repo):
113 114 """Factored out for extensibility"""
114 115 rbm = repo._bookmarks
115 116 if rbm.active not in self:
116 117 rbm.active = None
117 118 rbm._writeactive()
118 119
119 120 with repo.wlock():
120 121 file_ = repo.vfs('bookmarks', 'w', atomictemp=True,
121 122 checkambig=True)
122 123 try:
123 124 self._write(file_)
124 125 except: # re-raises
125 126 file_.discard()
126 127 raise
127 128 finally:
128 129 file_.close()
129 130
130 131 def _writeactive(self):
131 132 if self._aclean:
132 133 return
133 134 with self._repo.wlock():
134 135 if self._active is not None:
135 136 f = self._repo.vfs('bookmarks.current', 'w', atomictemp=True,
136 137 checkambig=True)
137 138 try:
138 139 f.write(encoding.fromlocal(self._active))
139 140 finally:
140 141 f.close()
141 142 else:
142 143 try:
143 144 self._repo.vfs.unlink('bookmarks.current')
144 145 except OSError as inst:
145 146 if inst.errno != errno.ENOENT:
146 147 raise
147 148 self._aclean = True
148 149
149 150 def _write(self, fp):
150 151 for name, node in self.iteritems():
151 152 fp.write("%s %s\n" % (hex(node), encoding.fromlocal(name)))
152 153 self._clean = True
153 154 self._repo.invalidatevolatilesets()
154 155
155 156 def expandname(self, bname):
156 157 if bname == '.':
157 return self.active
158 if self.active:
159 return self.active
160 else:
161 raise error.Abort(_("no active bookmark"))
158 162 return bname
159 163
160 164 def _readactive(repo, marks):
161 165 """
162 166 Get the active bookmark. We can have an active bookmark that updates
163 167 itself as we commit. This function returns the name of that bookmark.
164 168 It is stored in .hg/bookmarks.current
165 169 """
166 170 mark = None
167 171 try:
168 172 file = repo.vfs('bookmarks.current')
169 173 except IOError as inst:
170 174 if inst.errno != errno.ENOENT:
171 175 raise
172 176 return None
173 177 try:
174 178 # No readline() in osutil.posixfile, reading everything is
175 179 # cheap.
176 180 # Note that it's possible for readlines() here to raise
177 181 # IOError, since we might be reading the active mark over
178 182 # static-http which only tries to load the file when we try
179 183 # to read from it.
180 184 mark = encoding.tolocal((file.readlines() or [''])[0])
181 185 if mark == '' or mark not in marks:
182 186 mark = None
183 187 except IOError as inst:
184 188 if inst.errno != errno.ENOENT:
185 189 raise
186 190 return None
187 191 finally:
188 192 file.close()
189 193 return mark
190 194
191 195 def activate(repo, mark):
192 196 """
193 197 Set the given bookmark to be 'active', meaning that this bookmark will
194 198 follow new commits that are made.
195 199 The name is recorded in .hg/bookmarks.current
196 200 """
197 201 repo._bookmarks.active = mark
198 202 repo._bookmarks._writeactive()
199 203
200 204 def deactivate(repo):
201 205 """
202 206 Unset the active bookmark in this repository.
203 207 """
204 208 repo._bookmarks.active = None
205 209 repo._bookmarks._writeactive()
206 210
207 211 def isactivewdirparent(repo):
208 212 """
209 213 Tell whether the 'active' bookmark (the one that follows new commits)
210 214 points to one of the parents of the current working directory (wdir).
211 215
212 216 While this is normally the case, it can on occasion be false; for example,
213 217 immediately after a pull, the active bookmark can be moved to point
214 218 to a place different than the wdir. This is solved by running `hg update`.
215 219 """
216 220 mark = repo._activebookmark
217 221 marks = repo._bookmarks
218 222 parents = [p.node() for p in repo[None].parents()]
219 223 return (mark in marks and marks[mark] in parents)
220 224
221 225 def deletedivergent(repo, deletefrom, bm):
222 226 '''Delete divergent versions of bm on nodes in deletefrom.
223 227
224 228 Return True if at least one bookmark was deleted, False otherwise.'''
225 229 deleted = False
226 230 marks = repo._bookmarks
227 231 divergent = [b for b in marks if b.split('@', 1)[0] == bm.split('@', 1)[0]]
228 232 for mark in divergent:
229 233 if mark == '@' or '@' not in mark:
230 234 # can't be divergent by definition
231 235 continue
232 236 if mark and marks[mark] in deletefrom:
233 237 if mark != bm:
234 238 del marks[mark]
235 239 deleted = True
236 240 return deleted
237 241
238 242 def calculateupdate(ui, repo, checkout):
239 243 '''Return a tuple (targetrev, movemarkfrom) indicating the rev to
240 244 check out and where to move the active bookmark from, if needed.'''
241 245 movemarkfrom = None
242 246 if checkout is None:
243 247 activemark = repo._activebookmark
244 248 if isactivewdirparent(repo):
245 249 movemarkfrom = repo['.'].node()
246 250 elif activemark:
247 251 ui.status(_("updating to active bookmark %s\n") % activemark)
248 252 checkout = activemark
249 253 return (checkout, movemarkfrom)
250 254
251 255 def update(repo, parents, node):
252 256 deletefrom = parents
253 257 marks = repo._bookmarks
254 258 update = False
255 259 active = marks.active
256 260 if not active:
257 261 return False
258 262
259 263 if marks[active] in parents:
260 264 new = repo[node]
261 265 divs = [repo[b] for b in marks
262 266 if b.split('@', 1)[0] == active.split('@', 1)[0]]
263 267 anc = repo.changelog.ancestors([new.rev()])
264 268 deletefrom = [b.node() for b in divs if b.rev() in anc or b == new]
265 269 if validdest(repo, repo[marks[active]], new):
266 270 marks[active] = new.node()
267 271 update = True
268 272
269 273 if deletedivergent(repo, deletefrom, active):
270 274 update = True
271 275
272 276 if update:
273 277 lock = tr = None
274 278 try:
275 279 lock = repo.lock()
276 280 tr = repo.transaction('bookmark')
277 281 marks.recordchange(tr)
278 282 tr.close()
279 283 finally:
280 284 lockmod.release(tr, lock)
281 285 return update
282 286
283 287 def listbookmarks(repo):
284 288 # We may try to list bookmarks on a repo type that does not
285 289 # support it (e.g., statichttprepository).
286 290 marks = getattr(repo, '_bookmarks', {})
287 291
288 292 d = {}
289 293 hasnode = repo.changelog.hasnode
290 294 for k, v in marks.iteritems():
291 295 # don't expose local divergent bookmarks
292 296 if hasnode(v) and ('@' not in k or k.endswith('@')):
293 297 d[k] = hex(v)
294 298 return d
295 299
296 300 def pushbookmark(repo, key, old, new):
297 301 w = l = tr = None
298 302 try:
299 303 w = repo.wlock()
300 304 l = repo.lock()
301 305 tr = repo.transaction('bookmarks')
302 306 marks = repo._bookmarks
303 307 existing = hex(marks.get(key, ''))
304 308 if existing != old and existing != new:
305 309 return False
306 310 if new == '':
307 311 del marks[key]
308 312 else:
309 313 if new not in repo:
310 314 return False
311 315 marks[key] = repo[new].node()
312 316 marks.recordchange(tr)
313 317 tr.close()
314 318 return True
315 319 finally:
316 320 lockmod.release(tr, l, w)
317 321
318 322 def compare(repo, srcmarks, dstmarks,
319 323 srchex=None, dsthex=None, targets=None):
320 324 '''Compare bookmarks between srcmarks and dstmarks
321 325
322 326 This returns tuple "(addsrc, adddst, advsrc, advdst, diverge,
323 327 differ, invalid)", each are list of bookmarks below:
324 328
325 329 :addsrc: added on src side (removed on dst side, perhaps)
326 330 :adddst: added on dst side (removed on src side, perhaps)
327 331 :advsrc: advanced on src side
328 332 :advdst: advanced on dst side
329 333 :diverge: diverge
330 334 :differ: changed, but changeset referred on src is unknown on dst
331 335 :invalid: unknown on both side
332 336 :same: same on both side
333 337
334 338 Each elements of lists in result tuple is tuple "(bookmark name,
335 339 changeset ID on source side, changeset ID on destination
336 340 side)". Each changeset IDs are 40 hexadecimal digit string or
337 341 None.
338 342
339 343 Changeset IDs of tuples in "addsrc", "adddst", "differ" or
340 344 "invalid" list may be unknown for repo.
341 345
342 346 This function expects that "srcmarks" and "dstmarks" return
343 347 changeset ID in 40 hexadecimal digit string for specified
344 348 bookmark. If not so (e.g. bmstore "repo._bookmarks" returning
345 349 binary value), "srchex" or "dsthex" should be specified to convert
346 350 into such form.
347 351
348 352 If "targets" is specified, only bookmarks listed in it are
349 353 examined.
350 354 '''
351 355 if not srchex:
352 356 srchex = lambda x: x
353 357 if not dsthex:
354 358 dsthex = lambda x: x
355 359
356 360 if targets:
357 361 bset = set(targets)
358 362 else:
359 363 srcmarkset = set(srcmarks)
360 364 dstmarkset = set(dstmarks)
361 365 bset = srcmarkset | dstmarkset
362 366
363 367 results = ([], [], [], [], [], [], [], [])
364 368 addsrc = results[0].append
365 369 adddst = results[1].append
366 370 advsrc = results[2].append
367 371 advdst = results[3].append
368 372 diverge = results[4].append
369 373 differ = results[5].append
370 374 invalid = results[6].append
371 375 same = results[7].append
372 376
373 377 for b in sorted(bset):
374 378 if b not in srcmarks:
375 379 if b in dstmarks:
376 380 adddst((b, None, dsthex(dstmarks[b])))
377 381 else:
378 382 invalid((b, None, None))
379 383 elif b not in dstmarks:
380 384 addsrc((b, srchex(srcmarks[b]), None))
381 385 else:
382 386 scid = srchex(srcmarks[b])
383 387 dcid = dsthex(dstmarks[b])
384 388 if scid == dcid:
385 389 same((b, scid, dcid))
386 390 elif scid in repo and dcid in repo:
387 391 sctx = repo[scid]
388 392 dctx = repo[dcid]
389 393 if sctx.rev() < dctx.rev():
390 394 if validdest(repo, sctx, dctx):
391 395 advdst((b, scid, dcid))
392 396 else:
393 397 diverge((b, scid, dcid))
394 398 else:
395 399 if validdest(repo, dctx, sctx):
396 400 advsrc((b, scid, dcid))
397 401 else:
398 402 diverge((b, scid, dcid))
399 403 else:
400 404 # it is too expensive to examine in detail, in this case
401 405 differ((b, scid, dcid))
402 406
403 407 return results
404 408
405 409 def _diverge(ui, b, path, localmarks, remotenode):
406 410 '''Return appropriate diverged bookmark for specified ``path``
407 411
408 412 This returns None, if it is failed to assign any divergent
409 413 bookmark name.
410 414
411 415 This reuses already existing one with "@number" suffix, if it
412 416 refers ``remotenode``.
413 417 '''
414 418 if b == '@':
415 419 b = ''
416 420 # try to use an @pathalias suffix
417 421 # if an @pathalias already exists, we overwrite (update) it
418 422 if path.startswith("file:"):
419 423 path = util.url(path).path
420 424 for p, u in ui.configitems("paths"):
421 425 if u.startswith("file:"):
422 426 u = util.url(u).path
423 427 if path == u:
424 428 return '%s@%s' % (b, p)
425 429
426 430 # assign a unique "@number" suffix newly
427 431 for x in range(1, 100):
428 432 n = '%s@%d' % (b, x)
429 433 if n not in localmarks or localmarks[n] == remotenode:
430 434 return n
431 435
432 436 return None
433 437
434 438 def updatefromremote(ui, repo, remotemarks, path, trfunc, explicit=()):
435 439 ui.debug("checking for updated bookmarks\n")
436 440 localmarks = repo._bookmarks
437 441 (addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same
438 442 ) = compare(repo, remotemarks, localmarks, dsthex=hex)
439 443
440 444 status = ui.status
441 445 warn = ui.warn
442 446 if ui.configbool('ui', 'quietbookmarkmove', False):
443 447 status = warn = ui.debug
444 448
445 449 explicit = set(explicit)
446 450 changed = []
447 451 for b, scid, dcid in addsrc:
448 452 if scid in repo: # add remote bookmarks for changes we already have
449 453 changed.append((b, bin(scid), status,
450 454 _("adding remote bookmark %s\n") % (b)))
451 455 elif b in explicit:
452 456 explicit.remove(b)
453 457 ui.warn(_("remote bookmark %s points to locally missing %s\n")
454 458 % (b, scid[:12]))
455 459
456 460 for b, scid, dcid in advsrc:
457 461 changed.append((b, bin(scid), status,
458 462 _("updating bookmark %s\n") % (b)))
459 463 # remove normal movement from explicit set
460 464 explicit.difference_update(d[0] for d in changed)
461 465
462 466 for b, scid, dcid in diverge:
463 467 if b in explicit:
464 468 explicit.discard(b)
465 469 changed.append((b, bin(scid), status,
466 470 _("importing bookmark %s\n") % (b)))
467 471 else:
468 472 snode = bin(scid)
469 473 db = _diverge(ui, b, path, localmarks, snode)
470 474 if db:
471 475 changed.append((db, snode, warn,
472 476 _("divergent bookmark %s stored as %s\n") %
473 477 (b, db)))
474 478 else:
475 479 warn(_("warning: failed to assign numbered name "
476 480 "to divergent bookmark %s\n") % (b))
477 481 for b, scid, dcid in adddst + advdst:
478 482 if b in explicit:
479 483 explicit.discard(b)
480 484 changed.append((b, bin(scid), status,
481 485 _("importing bookmark %s\n") % (b)))
482 486 for b, scid, dcid in differ:
483 487 if b in explicit:
484 488 explicit.remove(b)
485 489 ui.warn(_("remote bookmark %s points to locally missing %s\n")
486 490 % (b, scid[:12]))
487 491
488 492 if changed:
489 493 tr = trfunc()
490 494 for b, node, writer, msg in sorted(changed):
491 495 localmarks[b] = node
492 496 writer(msg)
493 497 localmarks.recordchange(tr)
494 498
495 499 def incoming(ui, repo, other):
496 500 '''Show bookmarks incoming from other to repo
497 501 '''
498 502 ui.status(_("searching for changed bookmarks\n"))
499 503
500 504 r = compare(repo, other.listkeys('bookmarks'), repo._bookmarks,
501 505 dsthex=hex)
502 506 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
503 507
504 508 incomings = []
505 509 if ui.debugflag:
506 510 getid = lambda id: id
507 511 else:
508 512 getid = lambda id: id[:12]
509 513 if ui.verbose:
510 514 def add(b, id, st):
511 515 incomings.append(" %-25s %s %s\n" % (b, getid(id), st))
512 516 else:
513 517 def add(b, id, st):
514 518 incomings.append(" %-25s %s\n" % (b, getid(id)))
515 519 for b, scid, dcid in addsrc:
516 520 # i18n: "added" refers to a bookmark
517 521 add(b, scid, _('added'))
518 522 for b, scid, dcid in advsrc:
519 523 # i18n: "advanced" refers to a bookmark
520 524 add(b, scid, _('advanced'))
521 525 for b, scid, dcid in diverge:
522 526 # i18n: "diverged" refers to a bookmark
523 527 add(b, scid, _('diverged'))
524 528 for b, scid, dcid in differ:
525 529 # i18n: "changed" refers to a bookmark
526 530 add(b, scid, _('changed'))
527 531
528 532 if not incomings:
529 533 ui.status(_("no changed bookmarks found\n"))
530 534 return 1
531 535
532 536 for s in sorted(incomings):
533 537 ui.write(s)
534 538
535 539 return 0
536 540
537 541 def outgoing(ui, repo, other):
538 542 '''Show bookmarks outgoing from repo to other
539 543 '''
540 544 ui.status(_("searching for changed bookmarks\n"))
541 545
542 546 r = compare(repo, repo._bookmarks, other.listkeys('bookmarks'),
543 547 srchex=hex)
544 548 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
545 549
546 550 outgoings = []
547 551 if ui.debugflag:
548 552 getid = lambda id: id
549 553 else:
550 554 getid = lambda id: id[:12]
551 555 if ui.verbose:
552 556 def add(b, id, st):
553 557 outgoings.append(" %-25s %s %s\n" % (b, getid(id), st))
554 558 else:
555 559 def add(b, id, st):
556 560 outgoings.append(" %-25s %s\n" % (b, getid(id)))
557 561 for b, scid, dcid in addsrc:
558 562 # i18n: "added refers to a bookmark
559 563 add(b, scid, _('added'))
560 564 for b, scid, dcid in adddst:
561 565 # i18n: "deleted" refers to a bookmark
562 566 add(b, ' ' * 40, _('deleted'))
563 567 for b, scid, dcid in advsrc:
564 568 # i18n: "advanced" refers to a bookmark
565 569 add(b, scid, _('advanced'))
566 570 for b, scid, dcid in diverge:
567 571 # i18n: "diverged" refers to a bookmark
568 572 add(b, scid, _('diverged'))
569 573 for b, scid, dcid in differ:
570 574 # i18n: "changed" refers to a bookmark
571 575 add(b, scid, _('changed'))
572 576
573 577 if not outgoings:
574 578 ui.status(_("no changed bookmarks found\n"))
575 579 return 1
576 580
577 581 for s in sorted(outgoings):
578 582 ui.write(s)
579 583
580 584 return 0
581 585
582 586 def summary(repo, other):
583 587 '''Compare bookmarks between repo and other for "hg summary" output
584 588
585 589 This returns "(# of incoming, # of outgoing)" tuple.
586 590 '''
587 591 r = compare(repo, other.listkeys('bookmarks'), repo._bookmarks,
588 592 dsthex=hex)
589 593 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
590 594 return (len(addsrc), len(adddst))
591 595
592 596 def validdest(repo, old, new):
593 597 """Is the new bookmark destination a valid update from the old one"""
594 598 repo = repo.unfiltered()
595 599 if old == new:
596 600 # Old == new -> nothing to update.
597 601 return False
598 602 elif not old:
599 603 # old is nullrev, anything is valid.
600 604 # (new != nullrev has been excluded by the previous check)
601 605 return True
602 606 elif repo.obsstore:
603 607 return new.node() in obsolete.foreground(repo, [old.node()])
604 608 else:
605 609 # still an independent clause as it is lazier (and therefore faster)
606 610 return old.descendant(new)
@@ -1,850 +1,863 b''
1 1 #require serve
2 2
3 3 $ cat << EOF >> $HGRCPATH
4 4 > [ui]
5 5 > logtemplate={rev}:{node|short} {desc|firstline}
6 6 > [phases]
7 7 > publish=False
8 8 > [experimental]
9 9 > evolution=createmarkers,exchange
10 10 > # drop me once bundle2 is the default,
11 11 > # added to get test change early.
12 12 > bundle2-exp = True
13 13 > EOF
14 14
15 15 initialize
16 16
17 17 $ hg init a
18 18 $ cd a
19 19 $ echo 'test' > test
20 20 $ hg commit -Am'test'
21 21 adding test
22 22
23 23 set bookmarks
24 24
25 25 $ hg bookmark X
26 26 $ hg bookmark Y
27 27 $ hg bookmark Z
28 28
29 29 import bookmark by name
30 30
31 31 $ hg init ../b
32 32 $ cd ../b
33 33 $ hg book Y
34 34 $ hg book
35 35 * Y -1:000000000000
36 36 $ hg pull ../a
37 37 pulling from ../a
38 38 requesting all changes
39 39 adding changesets
40 40 adding manifests
41 41 adding file changes
42 42 added 1 changesets with 1 changes to 1 files
43 43 adding remote bookmark X
44 44 updating bookmark Y
45 45 adding remote bookmark Z
46 46 (run 'hg update' to get a working copy)
47 47 $ hg bookmarks
48 48 X 0:4e3505fd9583
49 49 * Y 0:4e3505fd9583
50 50 Z 0:4e3505fd9583
51 51 $ hg debugpushkey ../a namespaces
52 52 bookmarks
53 53 namespaces
54 54 obsolete
55 55 phases
56 56 $ hg debugpushkey ../a bookmarks
57 57 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
58 58 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
59 59 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
60 60
61 61 delete the bookmark to re-pull it
62 62
63 63 $ hg book -d X
64 64 $ hg pull -B X ../a
65 65 pulling from ../a
66 66 no changes found
67 67 adding remote bookmark X
68 68
69 69 finally no-op pull
70 70
71 71 $ hg pull -B X ../a
72 72 pulling from ../a
73 73 no changes found
74 74 $ hg bookmark
75 75 X 0:4e3505fd9583
76 76 * Y 0:4e3505fd9583
77 77 Z 0:4e3505fd9583
78 78
79 79 export bookmark by name
80 80
81 81 $ hg bookmark W
82 82 $ hg bookmark foo
83 83 $ hg bookmark foobar
84 84 $ hg push -B W ../a
85 85 pushing to ../a
86 86 searching for changes
87 87 no changes found
88 88 exporting bookmark W
89 89 [1]
90 90 $ hg -R ../a bookmarks
91 91 W -1:000000000000
92 92 X 0:4e3505fd9583
93 93 Y 0:4e3505fd9583
94 94 * Z 0:4e3505fd9583
95 95
96 96 delete a remote bookmark
97 97
98 98 $ hg book -d W
99 99 $ hg push -B W ../a
100 100 pushing to ../a
101 101 searching for changes
102 102 no changes found
103 103 deleting remote bookmark W
104 104 [1]
105 105
106 106 export the active bookmark
107 107
108 108 $ hg bookmark V
109 109 $ hg push -B . ../a
110 110 pushing to ../a
111 111 searching for changes
112 112 no changes found
113 113 exporting bookmark V
114 114 [1]
115 115
116 exporting the active bookmark with 'push -B .'
117 demand that one of the bookmarks is activated
118
119 $ hg update -r default
120 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
121 (leaving bookmark V)
122 $ hg push -B . ../a
123 abort: no active bookmark
124 [255]
125 $ hg update -r V
126 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
127 (activating bookmark V)
128
116 129 delete the bookmark
117 130
118 131 $ hg book -d V
119 132 $ hg push -B V ../a
120 133 pushing to ../a
121 134 searching for changes
122 135 no changes found
123 136 deleting remote bookmark V
124 137 [1]
125 138 $ hg up foobar
126 139 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
127 140 (activating bookmark foobar)
128 141
129 142 push/pull name that doesn't exist
130 143
131 144 $ hg push -B badname ../a
132 145 pushing to ../a
133 146 searching for changes
134 147 bookmark badname does not exist on the local or remote repository!
135 148 no changes found
136 149 [2]
137 150 $ hg pull -B anotherbadname ../a
138 151 pulling from ../a
139 152 abort: remote bookmark anotherbadname not found!
140 153 [255]
141 154
142 155 divergent bookmarks
143 156
144 157 $ cd ../a
145 158 $ echo c1 > f1
146 159 $ hg ci -Am1
147 160 adding f1
148 161 $ hg book -f @
149 162 $ hg book -f X
150 163 $ hg book
151 164 @ 1:0d2164f0ce0d
152 165 * X 1:0d2164f0ce0d
153 166 Y 0:4e3505fd9583
154 167 Z 1:0d2164f0ce0d
155 168
156 169 $ cd ../b
157 170 $ hg up
158 171 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
159 172 updating bookmark foobar
160 173 $ echo c2 > f2
161 174 $ hg ci -Am2
162 175 adding f2
163 176 $ hg book -if @
164 177 $ hg book -if X
165 178 $ hg book
166 179 @ 1:9b140be10808
167 180 X 1:9b140be10808
168 181 Y 0:4e3505fd9583
169 182 Z 0:4e3505fd9583
170 183 foo -1:000000000000
171 184 * foobar 1:9b140be10808
172 185
173 186 $ hg pull --config paths.foo=../a foo
174 187 pulling from $TESTTMP/a (glob)
175 188 searching for changes
176 189 adding changesets
177 190 adding manifests
178 191 adding file changes
179 192 added 1 changesets with 1 changes to 1 files (+1 heads)
180 193 divergent bookmark @ stored as @foo
181 194 divergent bookmark X stored as X@foo
182 195 updating bookmark Z
183 196 (run 'hg heads' to see heads, 'hg merge' to merge)
184 197 $ hg book
185 198 @ 1:9b140be10808
186 199 @foo 2:0d2164f0ce0d
187 200 X 1:9b140be10808
188 201 X@foo 2:0d2164f0ce0d
189 202 Y 0:4e3505fd9583
190 203 Z 2:0d2164f0ce0d
191 204 foo -1:000000000000
192 205 * foobar 1:9b140be10808
193 206
194 207 (test that too many divergence of bookmark)
195 208
196 209 $ python $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -r 000000000000 "X@${i}"; done
197 210 $ hg pull ../a
198 211 pulling from ../a
199 212 searching for changes
200 213 no changes found
201 214 warning: failed to assign numbered name to divergent bookmark X
202 215 divergent bookmark @ stored as @1
203 216 $ hg bookmarks | grep '^ X' | grep -v ':000000000000'
204 217 X 1:9b140be10808
205 218 X@foo 2:0d2164f0ce0d
206 219
207 220 (test that remotely diverged bookmarks are reused if they aren't changed)
208 221
209 222 $ hg bookmarks | grep '^ @'
210 223 @ 1:9b140be10808
211 224 @1 2:0d2164f0ce0d
212 225 @foo 2:0d2164f0ce0d
213 226 $ hg pull ../a
214 227 pulling from ../a
215 228 searching for changes
216 229 no changes found
217 230 warning: failed to assign numbered name to divergent bookmark X
218 231 divergent bookmark @ stored as @1
219 232 $ hg bookmarks | grep '^ @'
220 233 @ 1:9b140be10808
221 234 @1 2:0d2164f0ce0d
222 235 @foo 2:0d2164f0ce0d
223 236
224 237 $ python $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -d "X@${i}"; done
225 238 $ hg bookmarks -d "@1"
226 239
227 240 $ hg push -f ../a
228 241 pushing to ../a
229 242 searching for changes
230 243 adding changesets
231 244 adding manifests
232 245 adding file changes
233 246 added 1 changesets with 1 changes to 1 files (+1 heads)
234 247 $ hg -R ../a book
235 248 @ 1:0d2164f0ce0d
236 249 * X 1:0d2164f0ce0d
237 250 Y 0:4e3505fd9583
238 251 Z 1:0d2164f0ce0d
239 252
240 253 explicit pull should overwrite the local version (issue4439)
241 254
242 255 $ hg pull --config paths.foo=../a foo -B X
243 256 pulling from $TESTTMP/a (glob)
244 257 no changes found
245 258 divergent bookmark @ stored as @foo
246 259 importing bookmark X
247 260
248 261 reinstall state for further testing:
249 262
250 263 $ hg book -fr 9b140be10808 X
251 264
252 265 revsets should not ignore divergent bookmarks
253 266
254 267 $ hg bookmark -fr 1 Z
255 268 $ hg log -r 'bookmark()' --template '{rev}:{node|short} {bookmarks}\n'
256 269 0:4e3505fd9583 Y
257 270 1:9b140be10808 @ X Z foobar
258 271 2:0d2164f0ce0d @foo X@foo
259 272 $ hg log -r 'bookmark("X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
260 273 2:0d2164f0ce0d @foo X@foo
261 274 $ hg log -r 'bookmark("re:X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
262 275 2:0d2164f0ce0d @foo X@foo
263 276
264 277 update a remote bookmark from a non-head to a head
265 278
266 279 $ hg up -q Y
267 280 $ echo c3 > f2
268 281 $ hg ci -Am3
269 282 adding f2
270 283 created new head
271 284 $ hg push ../a
272 285 pushing to ../a
273 286 searching for changes
274 287 adding changesets
275 288 adding manifests
276 289 adding file changes
277 290 added 1 changesets with 1 changes to 1 files (+1 heads)
278 291 updating bookmark Y
279 292 $ hg -R ../a book
280 293 @ 1:0d2164f0ce0d
281 294 * X 1:0d2164f0ce0d
282 295 Y 3:f6fc62dde3c0
283 296 Z 1:0d2164f0ce0d
284 297
285 298 update a bookmark in the middle of a client pulling changes
286 299
287 300 $ cd ..
288 301 $ hg clone -q a pull-race
289 302
290 303 We want to use http because it is stateless and therefore more susceptible to
291 304 race conditions
292 305
293 306 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
294 307 $ cat pull-race.pid >> $DAEMON_PIDS
295 308
296 309 $ hg clone -q http://localhost:$HGPORT/ pull-race2
297 310 $ cd pull-race
298 311 $ hg up -q Y
299 312 $ echo c4 > f2
300 313 $ hg ci -Am4
301 314 $ echo c5 > f3
302 315 $ cat <<EOF > .hg/hgrc
303 316 > [hooks]
304 317 > outgoing.makecommit = hg ci -Am5; echo committed in pull-race
305 318 > EOF
306 319
307 320 (new config needs a server restart)
308 321
309 322 $ cd ..
310 323 $ killdaemons.py
311 324 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
312 325 $ cat pull-race.pid >> $DAEMON_PIDS
313 326 $ cd pull-race2
314 327 $ hg -R $TESTTMP/pull-race book
315 328 @ 1:0d2164f0ce0d
316 329 X 1:0d2164f0ce0d
317 330 * Y 4:b0a5eff05604
318 331 Z 1:0d2164f0ce0d
319 332 $ hg pull
320 333 pulling from http://localhost:$HGPORT/
321 334 searching for changes
322 335 adding changesets
323 336 adding manifests
324 337 adding file changes
325 338 added 1 changesets with 1 changes to 1 files
326 339 updating bookmark Y
327 340 (run 'hg update' to get a working copy)
328 341 $ hg book
329 342 * @ 1:0d2164f0ce0d
330 343 X 1:0d2164f0ce0d
331 344 Y 4:b0a5eff05604
332 345 Z 1:0d2164f0ce0d
333 346
334 347 Update a bookmark right after the initial lookup -B (issue4689)
335 348
336 349 $ echo c6 > ../pull-race/f3 # to be committed during the race
337 350 $ cat <<EOF > ../pull-race/.hg/hgrc
338 351 > [hooks]
339 352 > # If anything to commit, commit it right after the first key listing used
340 353 > # during lookup. This makes the commit appear before the actual getbundle
341 354 > # call.
342 355 > listkeys.makecommit= ((hg st | grep -q M) && (hg commit -m race; echo commited in pull-race)) || exit 0
343 356 > EOF
344 357
345 358 (new config need server restart)
346 359
347 360 $ killdaemons.py
348 361 $ hg serve -R ../pull-race -p $HGPORT -d --pid-file=../pull-race.pid -E main-error.log
349 362 $ cat ../pull-race.pid >> $DAEMON_PIDS
350 363
351 364 $ hg -R $TESTTMP/pull-race book
352 365 @ 1:0d2164f0ce0d
353 366 X 1:0d2164f0ce0d
354 367 * Y 5:35d1ef0a8d1b
355 368 Z 1:0d2164f0ce0d
356 369 $ hg pull -B Y
357 370 pulling from http://localhost:$HGPORT/
358 371 searching for changes
359 372 adding changesets
360 373 adding manifests
361 374 adding file changes
362 375 added 1 changesets with 1 changes to 1 files
363 376 updating bookmark Y
364 377 (run 'hg update' to get a working copy)
365 378 $ hg book
366 379 * @ 1:0d2164f0ce0d
367 380 X 1:0d2164f0ce0d
368 381 Y 5:35d1ef0a8d1b
369 382 Z 1:0d2164f0ce0d
370 383
371 384 (done with this section of the test)
372 385
373 386 $ killdaemons.py
374 387 $ cd ../b
375 388
376 389 diverging a remote bookmark fails
377 390
378 391 $ hg up -q 4e3505fd9583
379 392 $ echo c4 > f2
380 393 $ hg ci -Am4
381 394 adding f2
382 395 created new head
383 396 $ echo c5 > f2
384 397 $ hg ci -Am5
385 398 $ hg log -G
386 399 @ 5:c922c0139ca0 5
387 400 |
388 401 o 4:4efff6d98829 4
389 402 |
390 403 | o 3:f6fc62dde3c0 3
391 404 |/
392 405 | o 2:0d2164f0ce0d 1
393 406 |/
394 407 | o 1:9b140be10808 2
395 408 |/
396 409 o 0:4e3505fd9583 test
397 410
398 411
399 412 $ hg book -f Y
400 413
401 414 $ cat <<EOF > ../a/.hg/hgrc
402 415 > [web]
403 416 > push_ssl = false
404 417 > allow_push = *
405 418 > EOF
406 419
407 420 $ hg serve -R ../a -p $HGPORT2 -d --pid-file=../hg2.pid
408 421 $ cat ../hg2.pid >> $DAEMON_PIDS
409 422
410 423 $ hg push http://localhost:$HGPORT2/
411 424 pushing to http://localhost:$HGPORT2/
412 425 searching for changes
413 426 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
414 427 (merge or see "hg help push" for details about pushing new heads)
415 428 [255]
416 429 $ hg -R ../a book
417 430 @ 1:0d2164f0ce0d
418 431 * X 1:0d2164f0ce0d
419 432 Y 3:f6fc62dde3c0
420 433 Z 1:0d2164f0ce0d
421 434
422 435
423 436 Unrelated marker does not alter the decision
424 437
425 438 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
426 439 $ hg push http://localhost:$HGPORT2/
427 440 pushing to http://localhost:$HGPORT2/
428 441 searching for changes
429 442 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
430 443 (merge or see "hg help push" for details about pushing new heads)
431 444 [255]
432 445 $ hg -R ../a book
433 446 @ 1:0d2164f0ce0d
434 447 * X 1:0d2164f0ce0d
435 448 Y 3:f6fc62dde3c0
436 449 Z 1:0d2164f0ce0d
437 450
438 451 Update to a successor works
439 452
440 453 $ hg id --debug -r 3
441 454 f6fc62dde3c0771e29704af56ba4d8af77abcc2f
442 455 $ hg id --debug -r 4
443 456 4efff6d98829d9c824c621afd6e3f01865f5439f
444 457 $ hg id --debug -r 5
445 458 c922c0139ca03858f655e4a2af4dd02796a63969 tip Y
446 459 $ hg debugobsolete f6fc62dde3c0771e29704af56ba4d8af77abcc2f cccccccccccccccccccccccccccccccccccccccc
447 460 $ hg debugobsolete cccccccccccccccccccccccccccccccccccccccc 4efff6d98829d9c824c621afd6e3f01865f5439f
448 461 $ hg push http://localhost:$HGPORT2/
449 462 pushing to http://localhost:$HGPORT2/
450 463 searching for changes
451 464 remote: adding changesets
452 465 remote: adding manifests
453 466 remote: adding file changes
454 467 remote: added 2 changesets with 2 changes to 1 files (+1 heads)
455 468 remote: 2 new obsolescence markers
456 469 updating bookmark Y
457 470 $ hg -R ../a book
458 471 @ 1:0d2164f0ce0d
459 472 * X 1:0d2164f0ce0d
460 473 Y 5:c922c0139ca0
461 474 Z 1:0d2164f0ce0d
462 475
463 476 hgweb
464 477
465 478 $ cat <<EOF > .hg/hgrc
466 479 > [web]
467 480 > push_ssl = false
468 481 > allow_push = *
469 482 > EOF
470 483
471 484 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
472 485 $ cat ../hg.pid >> $DAEMON_PIDS
473 486 $ cd ../a
474 487
475 488 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
476 489 bookmarks
477 490 namespaces
478 491 obsolete
479 492 phases
480 493 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
481 494 @ 9b140be1080824d768c5a4691a564088eede71f9
482 495 X 9b140be1080824d768c5a4691a564088eede71f9
483 496 Y c922c0139ca03858f655e4a2af4dd02796a63969
484 497 Z 9b140be1080824d768c5a4691a564088eede71f9
485 498 foo 0000000000000000000000000000000000000000
486 499 foobar 9b140be1080824d768c5a4691a564088eede71f9
487 500 $ hg out -B http://localhost:$HGPORT/
488 501 comparing with http://localhost:$HGPORT/
489 502 searching for changed bookmarks
490 503 @ 0d2164f0ce0d
491 504 X 0d2164f0ce0d
492 505 Z 0d2164f0ce0d
493 506 foo
494 507 foobar
495 508 $ hg push -B Z http://localhost:$HGPORT/
496 509 pushing to http://localhost:$HGPORT/
497 510 searching for changes
498 511 no changes found
499 512 updating bookmark Z
500 513 [1]
501 514 $ hg book -d Z
502 515 $ hg in -B http://localhost:$HGPORT/
503 516 comparing with http://localhost:$HGPORT/
504 517 searching for changed bookmarks
505 518 @ 9b140be10808
506 519 X 9b140be10808
507 520 Z 0d2164f0ce0d
508 521 foo 000000000000
509 522 foobar 9b140be10808
510 523 $ hg pull -B Z http://localhost:$HGPORT/
511 524 pulling from http://localhost:$HGPORT/
512 525 no changes found
513 526 divergent bookmark @ stored as @1
514 527 divergent bookmark X stored as X@1
515 528 adding remote bookmark Z
516 529 adding remote bookmark foo
517 530 adding remote bookmark foobar
518 531 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
519 532 requesting all changes
520 533 adding changesets
521 534 adding manifests
522 535 adding file changes
523 536 added 5 changesets with 5 changes to 3 files (+2 heads)
524 537 2 new obsolescence markers
525 538 updating to bookmark @
526 539 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
527 540 $ hg -R cloned-bookmarks bookmarks
528 541 * @ 1:9b140be10808
529 542 X 1:9b140be10808
530 543 Y 4:c922c0139ca0
531 544 Z 2:0d2164f0ce0d
532 545 foo -1:000000000000
533 546 foobar 1:9b140be10808
534 547
535 548 $ cd ..
536 549
537 550 Test to show result of bookmarks comparision
538 551
539 552 $ mkdir bmcomparison
540 553 $ cd bmcomparison
541 554
542 555 $ hg init source
543 556 $ hg -R source debugbuilddag '+2*2*3*4'
544 557 $ hg -R source log -G --template '{rev}:{node|short}'
545 558 o 4:e7bd5218ca15
546 559 |
547 560 | o 3:6100d3090acf
548 561 |/
549 562 | o 2:fa942426a6fd
550 563 |/
551 564 | o 1:66f7d451a68b
552 565 |/
553 566 o 0:1ea73414a91b
554 567
555 568 $ hg -R source bookmarks -r 0 SAME
556 569 $ hg -R source bookmarks -r 0 ADV_ON_REPO1
557 570 $ hg -R source bookmarks -r 0 ADV_ON_REPO2
558 571 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO1
559 572 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO2
560 573 $ hg -R source bookmarks -r 1 DIVERGED
561 574
562 575 $ hg clone -U source repo1
563 576
564 577 (test that incoming/outgoing exit with 1, if there is no bookmark to
565 578 be exchanged)
566 579
567 580 $ hg -R repo1 incoming -B
568 581 comparing with $TESTTMP/bmcomparison/source
569 582 searching for changed bookmarks
570 583 no changed bookmarks found
571 584 [1]
572 585 $ hg -R repo1 outgoing -B
573 586 comparing with $TESTTMP/bmcomparison/source
574 587 searching for changed bookmarks
575 588 no changed bookmarks found
576 589 [1]
577 590
578 591 $ hg -R repo1 bookmarks -f -r 1 ADD_ON_REPO1
579 592 $ hg -R repo1 bookmarks -f -r 2 ADV_ON_REPO1
580 593 $ hg -R repo1 bookmarks -f -r 3 DIFF_ADV_ON_REPO1
581 594 $ hg -R repo1 bookmarks -f -r 3 DIFF_DIVERGED
582 595 $ hg -R repo1 -q --config extensions.mq= strip 4
583 596 $ hg -R repo1 log -G --template '{node|short} ({bookmarks})'
584 597 o 6100d3090acf (DIFF_ADV_ON_REPO1 DIFF_DIVERGED)
585 598 |
586 599 | o fa942426a6fd (ADV_ON_REPO1)
587 600 |/
588 601 | o 66f7d451a68b (ADD_ON_REPO1 DIVERGED)
589 602 |/
590 603 o 1ea73414a91b (ADV_ON_REPO2 DIFF_ADV_ON_REPO2 SAME)
591 604
592 605
593 606 $ hg clone -U source repo2
594 607 $ hg -R repo2 bookmarks -f -r 1 ADD_ON_REPO2
595 608 $ hg -R repo2 bookmarks -f -r 1 ADV_ON_REPO2
596 609 $ hg -R repo2 bookmarks -f -r 2 DIVERGED
597 610 $ hg -R repo2 bookmarks -f -r 4 DIFF_ADV_ON_REPO2
598 611 $ hg -R repo2 bookmarks -f -r 4 DIFF_DIVERGED
599 612 $ hg -R repo2 -q --config extensions.mq= strip 3
600 613 $ hg -R repo2 log -G --template '{node|short} ({bookmarks})'
601 614 o e7bd5218ca15 (DIFF_ADV_ON_REPO2 DIFF_DIVERGED)
602 615 |
603 616 | o fa942426a6fd (DIVERGED)
604 617 |/
605 618 | o 66f7d451a68b (ADD_ON_REPO2 ADV_ON_REPO2)
606 619 |/
607 620 o 1ea73414a91b (ADV_ON_REPO1 DIFF_ADV_ON_REPO1 SAME)
608 621
609 622
610 623 (test that difference of bookmarks between repositories are fully shown)
611 624
612 625 $ hg -R repo1 incoming -B repo2 -v
613 626 comparing with repo2
614 627 searching for changed bookmarks
615 628 ADD_ON_REPO2 66f7d451a68b added
616 629 ADV_ON_REPO2 66f7d451a68b advanced
617 630 DIFF_ADV_ON_REPO2 e7bd5218ca15 changed
618 631 DIFF_DIVERGED e7bd5218ca15 changed
619 632 DIVERGED fa942426a6fd diverged
620 633 $ hg -R repo1 outgoing -B repo2 -v
621 634 comparing with repo2
622 635 searching for changed bookmarks
623 636 ADD_ON_REPO1 66f7d451a68b added
624 637 ADD_ON_REPO2 deleted
625 638 ADV_ON_REPO1 fa942426a6fd advanced
626 639 DIFF_ADV_ON_REPO1 6100d3090acf advanced
627 640 DIFF_ADV_ON_REPO2 1ea73414a91b changed
628 641 DIFF_DIVERGED 6100d3090acf changed
629 642 DIVERGED 66f7d451a68b diverged
630 643
631 644 $ hg -R repo2 incoming -B repo1 -v
632 645 comparing with repo1
633 646 searching for changed bookmarks
634 647 ADD_ON_REPO1 66f7d451a68b added
635 648 ADV_ON_REPO1 fa942426a6fd advanced
636 649 DIFF_ADV_ON_REPO1 6100d3090acf changed
637 650 DIFF_DIVERGED 6100d3090acf changed
638 651 DIVERGED 66f7d451a68b diverged
639 652 $ hg -R repo2 outgoing -B repo1 -v
640 653 comparing with repo1
641 654 searching for changed bookmarks
642 655 ADD_ON_REPO1 deleted
643 656 ADD_ON_REPO2 66f7d451a68b added
644 657 ADV_ON_REPO2 66f7d451a68b advanced
645 658 DIFF_ADV_ON_REPO1 1ea73414a91b changed
646 659 DIFF_ADV_ON_REPO2 e7bd5218ca15 advanced
647 660 DIFF_DIVERGED e7bd5218ca15 changed
648 661 DIVERGED fa942426a6fd diverged
649 662
650 663 $ cd ..
651 664
652 665 Pushing a bookmark should only push the changes required by that
653 666 bookmark, not all outgoing changes:
654 667 $ hg clone http://localhost:$HGPORT/ addmarks
655 668 requesting all changes
656 669 adding changesets
657 670 adding manifests
658 671 adding file changes
659 672 added 5 changesets with 5 changes to 3 files (+2 heads)
660 673 2 new obsolescence markers
661 674 updating to bookmark @
662 675 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
663 676 $ cd addmarks
664 677 $ echo foo > foo
665 678 $ hg add foo
666 679 $ hg commit -m 'add foo'
667 680 $ echo bar > bar
668 681 $ hg add bar
669 682 $ hg commit -m 'add bar'
670 683 $ hg co "tip^"
671 684 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
672 685 (leaving bookmark @)
673 686 $ hg book add-foo
674 687 $ hg book -r tip add-bar
675 688 Note: this push *must* push only a single changeset, as that's the point
676 689 of this test.
677 690 $ hg push -B add-foo --traceback
678 691 pushing to http://localhost:$HGPORT/
679 692 searching for changes
680 693 remote: adding changesets
681 694 remote: adding manifests
682 695 remote: adding file changes
683 696 remote: added 1 changesets with 1 changes to 1 files
684 697 exporting bookmark add-foo
685 698
686 699 pushing a new bookmark on a new head does not require -f if -B is specified
687 700
688 701 $ hg up -q X
689 702 $ hg book W
690 703 $ echo c5 > f2
691 704 $ hg ci -Am5
692 705 created new head
693 706 $ hg push -B .
694 707 pushing to http://localhost:$HGPORT/
695 708 searching for changes
696 709 remote: adding changesets
697 710 remote: adding manifests
698 711 remote: adding file changes
699 712 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
700 713 exporting bookmark W
701 714 $ hg -R ../b id -r W
702 715 cc978a373a53 tip W
703 716
704 717 pushing an existing but divergent bookmark with -B still requires -f
705 718
706 719 $ hg clone -q . ../r
707 720 $ hg up -q X
708 721 $ echo 1 > f2
709 722 $ hg ci -qAml
710 723
711 724 $ cd ../r
712 725 $ hg up -q X
713 726 $ echo 2 > f2
714 727 $ hg ci -qAmr
715 728 $ hg push -B X
716 729 pushing to $TESTTMP/addmarks (glob)
717 730 searching for changes
718 731 remote has heads on branch 'default' that are not known locally: a2a606d9ff1b
719 732 abort: push creates new remote head 54694f811df9 with bookmark 'X'!
720 733 (pull and merge or see "hg help push" for details about pushing new heads)
721 734 [255]
722 735 $ cd ../addmarks
723 736
724 737 Check summary output for incoming/outgoing bookmarks
725 738
726 739 $ hg bookmarks -d X
727 740 $ hg bookmarks -d Y
728 741 $ hg summary --remote | grep '^remote:'
729 742 remote: *, 2 incoming bookmarks, 1 outgoing bookmarks (glob)
730 743
731 744 $ cd ..
732 745
733 746 pushing an unchanged bookmark should result in no changes
734 747
735 748 $ hg init unchanged-a
736 749 $ hg init unchanged-b
737 750 $ cd unchanged-a
738 751 $ echo initial > foo
739 752 $ hg commit -A -m initial
740 753 adding foo
741 754 $ hg bookmark @
742 755 $ hg push -B @ ../unchanged-b
743 756 pushing to ../unchanged-b
744 757 searching for changes
745 758 adding changesets
746 759 adding manifests
747 760 adding file changes
748 761 added 1 changesets with 1 changes to 1 files
749 762 exporting bookmark @
750 763
751 764 $ hg push -B @ ../unchanged-b
752 765 pushing to ../unchanged-b
753 766 searching for changes
754 767 no changes found
755 768 [1]
756 769
757 770
758 771 Check hook preventing push (issue4455)
759 772 ======================================
760 773
761 774 $ hg bookmarks
762 775 * @ 0:55482a6fb4b1
763 776 $ hg log -G
764 777 @ 0:55482a6fb4b1 initial
765 778
766 779 $ hg init ../issue4455-dest
767 780 $ hg push ../issue4455-dest # changesets only
768 781 pushing to ../issue4455-dest
769 782 searching for changes
770 783 adding changesets
771 784 adding manifests
772 785 adding file changes
773 786 added 1 changesets with 1 changes to 1 files
774 787 $ cat >> .hg/hgrc << EOF
775 788 > [paths]
776 789 > local=../issue4455-dest/
777 790 > ssh=ssh://user@dummy/issue4455-dest
778 791 > http=http://localhost:$HGPORT/
779 792 > [ui]
780 793 > ssh=python "$TESTDIR/dummyssh"
781 794 > EOF
782 795 $ cat >> ../issue4455-dest/.hg/hgrc << EOF
783 796 > [hooks]
784 797 > prepushkey=false
785 798 > [web]
786 799 > push_ssl = false
787 800 > allow_push = *
788 801 > EOF
789 802 $ killdaemons.py
790 803 $ hg serve -R ../issue4455-dest -p $HGPORT -d --pid-file=../issue4455.pid -E ../issue4455-error.log
791 804 $ cat ../issue4455.pid >> $DAEMON_PIDS
792 805
793 806 Local push
794 807 ----------
795 808
796 809 $ hg push -B @ local
797 810 pushing to $TESTTMP/issue4455-dest (glob)
798 811 searching for changes
799 812 no changes found
800 813 pushkey-abort: prepushkey hook exited with status 1
801 814 abort: exporting bookmark @ failed!
802 815 [255]
803 816 $ hg -R ../issue4455-dest/ bookmarks
804 817 no bookmarks set
805 818
806 819 Using ssh
807 820 ---------
808 821
809 822 $ hg push -B @ ssh --config experimental.bundle2-exp=True
810 823 pushing to ssh://user@dummy/issue4455-dest
811 824 searching for changes
812 825 no changes found
813 826 remote: pushkey-abort: prepushkey hook exited with status 1
814 827 abort: exporting bookmark @ failed!
815 828 [255]
816 829 $ hg -R ../issue4455-dest/ bookmarks
817 830 no bookmarks set
818 831
819 832 $ hg push -B @ ssh --config experimental.bundle2-exp=False
820 833 pushing to ssh://user@dummy/issue4455-dest
821 834 searching for changes
822 835 no changes found
823 836 remote: pushkey-abort: prepushkey hook exited with status 1
824 837 exporting bookmark @ failed!
825 838 [1]
826 839 $ hg -R ../issue4455-dest/ bookmarks
827 840 no bookmarks set
828 841
829 842 Using http
830 843 ----------
831 844
832 845 $ hg push -B @ http --config experimental.bundle2-exp=True
833 846 pushing to http://localhost:$HGPORT/
834 847 searching for changes
835 848 no changes found
836 849 remote: pushkey-abort: prepushkey hook exited with status 1
837 850 abort: exporting bookmark @ failed!
838 851 [255]
839 852 $ hg -R ../issue4455-dest/ bookmarks
840 853 no bookmarks set
841 854
842 855 $ hg push -B @ http --config experimental.bundle2-exp=False
843 856 pushing to http://localhost:$HGPORT/
844 857 searching for changes
845 858 no changes found
846 859 remote: pushkey-abort: prepushkey hook exited with status 1
847 860 exporting bookmark @ failed!
848 861 [1]
849 862 $ hg -R ../issue4455-dest/ bookmarks
850 863 no bookmarks set
General Comments 0
You need to be logged in to leave comments. Login now