##// END OF EJS Templates
update: accept --merge to allow merging across topo branches (issue5125)
Martin von Zweigbergk -
r31166:fad5e299 default
parent child Browse files
Show More
@@ -5278,12 +5278,13 b' def unbundle(ui, repo, fname1, *fnames, '
5278 @command('^update|up|checkout|co',
5278 @command('^update|up|checkout|co',
5279 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5279 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5280 ('c', 'check', None, _('require clean working directory')),
5280 ('c', 'check', None, _('require clean working directory')),
5281 ('m', 'merge', None, _('merge uncommitted changes')),
5281 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5282 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5282 ('r', 'rev', '', _('revision'), _('REV'))
5283 ('r', 'rev', '', _('revision'), _('REV'))
5283 ] + mergetoolopts,
5284 ] + mergetoolopts,
5284 _('[-C|-c] [-d DATE] [[-r] REV]'))
5285 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5285 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5286 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5286 tool=None):
5287 merge=None, tool=None):
5287 """update working directory (or switch revisions)
5288 """update working directory (or switch revisions)
5288
5289
5289 Update the repository's working directory to the specified
5290 Update the repository's working directory to the specified
@@ -5302,8 +5303,8 b' def update(ui, repo, node=None, rev=None'
5302
5303
5303 .. container:: verbose
5304 .. container:: verbose
5304
5305
5305 The -C/--clean and -c/--check options control what happens if the
5306 The -C/--clean, -c/--check, and -m/--merge options control what
5306 working directory contains uncommitted changes.
5307 happens if the working directory contains uncommitted changes.
5307 At most of one of them can be specified.
5308 At most of one of them can be specified.
5308
5309
5309 1. If no option is specified, and if
5310 1. If no option is specified, and if
@@ -5315,10 +5316,14 b' def update(ui, repo, node=None, rev=None'
5315 branch), the update is aborted and the uncommitted changes
5316 branch), the update is aborted and the uncommitted changes
5316 are preserved.
5317 are preserved.
5317
5318
5318 2. With the -c/--check option, the update is aborted and the
5319 2. With the -m/--merge option, the update is allowed even if the
5320 requested changeset is not an ancestor or descendant of
5321 the working directory's parent.
5322
5323 3. With the -c/--check option, the update is aborted and the
5319 uncommitted changes are preserved.
5324 uncommitted changes are preserved.
5320
5325
5321 3. With the -C/--clean option, uncommitted changes are discarded and
5326 4. With the -C/--clean option, uncommitted changes are discarded and
5322 the working directory is updated to the requested changeset.
5327 the working directory is updated to the requested changeset.
5323
5328
5324 To cancel an uncommitted merge (and lose your changes), use
5329 To cancel an uncommitted merge (and lose your changes), use
@@ -5343,8 +5348,15 b' def update(ui, repo, node=None, rev=None'
5343 if date and rev is not None:
5348 if date and rev is not None:
5344 raise error.Abort(_("you can't specify a revision and a date"))
5349 raise error.Abort(_("you can't specify a revision and a date"))
5345
5350
5346 if check and clean:
5351 if len([x for x in (clean, check, merge) if x]) > 1:
5347 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
5352 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5353 "or -m/merge"))
5354
5355 updatecheck = None
5356 if check:
5357 updatecheck = 'abort'
5358 elif merge:
5359 updatecheck = 'none'
5348
5360
5349 with repo.wlock():
5361 with repo.wlock():
5350 cmdutil.clearunfinished(repo)
5362 cmdutil.clearunfinished(repo)
@@ -5358,7 +5370,8 b' def update(ui, repo, node=None, rev=None'
5358
5370
5359 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5371 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5360
5372
5361 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
5373 return hg.updatetotally(ui, repo, rev, brev, clean=clean,
5374 updatecheck=updatecheck)
5362
5375
5363 @command('verify', [])
5376 @command('verify', [])
5364 def verify(ui, repo):
5377 def verify(ui, repo):
@@ -691,18 +691,19 b' def _showstats(repo, stats, quietempty=F'
691 repo.ui.status(_("%d files updated, %d files merged, "
691 repo.ui.status(_("%d files updated, %d files merged, "
692 "%d files removed, %d files unresolved\n") % stats)
692 "%d files removed, %d files unresolved\n") % stats)
693
693
694 def updaterepo(repo, node, overwrite):
694 def updaterepo(repo, node, overwrite, updatecheck=None):
695 """Update the working directory to node.
695 """Update the working directory to node.
696
696
697 When overwrite is set, changes are clobbered, merged else
697 When overwrite is set, changes are clobbered, merged else
698
698
699 returns stats (see pydoc mercurial.merge.applyupdates)"""
699 returns stats (see pydoc mercurial.merge.applyupdates)"""
700 return mergemod.update(repo, node, False, overwrite,
700 return mergemod.update(repo, node, False, overwrite,
701 labels=['working copy', 'destination'])
701 labels=['working copy', 'destination'],
702 updatecheck=updatecheck)
702
703
703 def update(repo, node, quietempty=False):
704 def update(repo, node, quietempty=False, updatecheck=None):
704 """update the working directory to node, merging linear changes"""
705 """update the working directory to node"""
705 stats = updaterepo(repo, node, False)
706 stats = updaterepo(repo, node, False, updatecheck=updatecheck)
706 _showstats(repo, stats, quietempty)
707 _showstats(repo, stats, quietempty)
707 if stats[3]:
708 if stats[3]:
708 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
709 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
@@ -722,7 +723,7 b' def clean(repo, node, show_stats=True, q'
722 # naming conflict in updatetotally()
723 # naming conflict in updatetotally()
723 _clean = clean
724 _clean = clean
724
725
725 def updatetotally(ui, repo, checkout, brev, clean=False, check=False):
726 def updatetotally(ui, repo, checkout, brev, clean=False, updatecheck=None):
726 """Update the working directory with extra care for non-file components
727 """Update the working directory with extra care for non-file components
727
728
728 This takes care of non-file components below:
729 This takes care of non-file components below:
@@ -734,10 +735,19 b' def updatetotally(ui, repo, checkout, br'
734 :checkout: to which revision the working directory is updated
735 :checkout: to which revision the working directory is updated
735 :brev: a name, which might be a bookmark to be activated after updating
736 :brev: a name, which might be a bookmark to be activated after updating
736 :clean: whether changes in the working directory can be discarded
737 :clean: whether changes in the working directory can be discarded
737 :check: whether changes in the working directory should be checked
738 :updatecheck: how to deal with a dirty working directory
739
740 Valid values for updatecheck are (None => linear):
741
742 * abort: abort if the working directory is dirty
743 * none: don't check (merge working directory changes into destination)
744 * linear: check that update is linear before merging working directory
745 changes into destination
738
746
739 This returns whether conflict is detected at updating or not.
747 This returns whether conflict is detected at updating or not.
740 """
748 """
749 if updatecheck is None:
750 updatecheck = 'linear'
741 with repo.wlock():
751 with repo.wlock():
742 movemarkfrom = None
752 movemarkfrom = None
743 warndest = False
753 warndest = False
@@ -749,9 +759,10 b' def updatetotally(ui, repo, checkout, br'
749 if clean:
759 if clean:
750 ret = _clean(repo, checkout)
760 ret = _clean(repo, checkout)
751 else:
761 else:
752 if check:
762 if updatecheck == 'abort':
753 cmdutil.bailifchanged(repo, merge=False)
763 cmdutil.bailifchanged(repo, merge=False)
754 ret = _update(repo, checkout)
764 updatecheck = 'none'
765 ret = _update(repo, checkout, updatecheck=updatecheck)
755
766
756 if not ret and movemarkfrom:
767 if not ret and movemarkfrom:
757 if movemarkfrom == repo['.'].node():
768 if movemarkfrom == repo['.'].node():
@@ -1444,7 +1444,8 b' def recordupdates(repo, actions, branchm'
1444 repo.dirstate.normal(f)
1444 repo.dirstate.normal(f)
1445
1445
1446 def update(repo, node, branchmerge, force, ancestor=None,
1446 def update(repo, node, branchmerge, force, ancestor=None,
1447 mergeancestor=False, labels=None, matcher=None, mergeforce=False):
1447 mergeancestor=False, labels=None, matcher=None, mergeforce=False,
1448 updatecheck=None):
1448 """
1449 """
1449 Perform a merge between the working directory and the given node
1450 Perform a merge between the working directory and the given node
1450
1451
@@ -1468,14 +1469,17 b' def update(repo, node, branchmerge, forc'
1468
1469
1469 This logic is tested by test-update-branches.t.
1470 This logic is tested by test-update-branches.t.
1470
1471
1471 -c -C dirty rev linear | result
1472 -c -C -m dirty rev linear | result
1472 y y * * * | (1)
1473 y y * * * * | (1)
1473 * * * n n | x
1474 y * y * * * | (1)
1474 * * n * * | ok
1475 * y y * * * | (1)
1475 n n y * y | merge
1476 * * * * n n | x
1476 n n y y n | (2)
1477 * * * n * * | ok
1477 n y y * * | discard
1478 n n n y * y | merge
1478 y n y * * | (3)
1479 n n n y y n | (2)
1480 n n y y * * | merge
1481 n y n y * * | discard
1482 y n n y * * | (3)
1479
1483
1480 x = can't happen
1484 x = can't happen
1481 * = don't-care
1485 * = don't-care
@@ -1486,9 +1490,16 b' def update(repo, node, branchmerge, forc'
1486 Return the same tuple as applyupdates().
1490 Return the same tuple as applyupdates().
1487 """
1491 """
1488
1492
1489 # This functon used to find the default destination if node was None, but
1493 # This function used to find the default destination if node was None, but
1490 # that's now in destutil.py.
1494 # that's now in destutil.py.
1491 assert node is not None
1495 assert node is not None
1496 if not branchmerge and not force:
1497 # TODO: remove the default once all callers that pass branchmerge=False
1498 # and force=False pass a value for updatecheck. We may want to allow
1499 # updatecheck='abort' to better suppport some of these callers.
1500 if updatecheck is None:
1501 updatecheck = 'linear'
1502 assert updatecheck in ('none', 'linear')
1492 # If we're doing a partial update, we need to skip updating
1503 # If we're doing a partial update, we need to skip updating
1493 # the dirstate, so make a note of any partial-ness to the
1504 # the dirstate, so make a note of any partial-ness to the
1494 # update here.
1505 # update here.
@@ -1545,7 +1556,8 b' def update(repo, node, branchmerge, forc'
1545 repo.hook('update', parent1=xp2, parent2='', error=0)
1556 repo.hook('update', parent1=xp2, parent2='', error=0)
1546 return 0, 0, 0, 0
1557 return 0, 0, 0, 0
1547
1558
1548 if pas not in ([p1], [p2]): # nonlinear
1559 if (updatecheck == 'linear' and
1560 pas not in ([p1], [p2])): # nonlinear
1549 dirty = wc.dirty(missing=True)
1561 dirty = wc.dirty(missing=True)
1550 if dirty:
1562 if dirty:
1551 # Branching is a bit strange to ensure we do the minimal
1563 # Branching is a bit strange to ensure we do the minimal
@@ -228,7 +228,7 b' Show all commands + options'
228 serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
228 serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
229 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos, template
229 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos, template
230 summary: remote
230 summary: remote
231 update: clean, check, date, rev, tool
231 update: clean, check, merge, date, rev, tool
232 addremove: similarity, subrepos, include, exclude, dry-run
232 addremove: similarity, subrepos, include, exclude, dry-run
233 archive: no-decode, prefix, rev, type, subrepos, include, exclude
233 archive: no-decode, prefix, rev, type, subrepos, include, exclude
234 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
234 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
@@ -160,6 +160,16 b' Cases are run as shown in that table, ro'
160 parent=1
160 parent=1
161 M foo
161 M foo
162
162
163 $ revtest '-m dirty linear' dirty 1 2 -m
164 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
165 parent=2
166 M foo
167
168 $ revtest '-m dirty cross' dirty 3 4 -m
169 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
170 parent=4
171 M foo
172
163 $ revtest '-c dirtysub linear' dirtysub 1 2 -c
173 $ revtest '-c dirtysub linear' dirtysub 1 2 -c
164 abort: uncommitted changes in subrepository 'sub'
174 abort: uncommitted changes in subrepository 'sub'
165 parent=1
175 parent=1
@@ -171,7 +181,17 b' Cases are run as shown in that table, ro'
171 parent=2
181 parent=2
172
182
173 $ revtest '-cC dirty linear' dirty 1 2 -cC
183 $ revtest '-cC dirty linear' dirty 1 2 -cC
174 abort: cannot specify both -c/--check and -C/--clean
184 abort: can only specify one of -C/--clean, -c/--check, or -m/merge
185 parent=1
186 M foo
187
188 $ revtest '-mc dirty linear' dirty 1 2 -mc
189 abort: can only specify one of -C/--clean, -c/--check, or -m/merge
190 parent=1
191 M foo
192
193 $ revtest '-mC dirty linear' dirty 1 2 -mC
194 abort: can only specify one of -C/--clean, -c/--check, or -m/merge
175 parent=1
195 parent=1
176 M foo
196 M foo
177
197
General Comments 0
You need to be logged in to leave comments. Login now