[PATCH 5 of 6] update: learn --merge to allow merging across topological branches (issue5125)
Martin von Zweigbergk
martinvonz at google.com
Tue Feb 14 17:36:15 EST 2017
(+mercurial-devel)
On Tue, Feb 14, 2017 at 10:48 AM, Gábor STEFANIK <Gabor.STEFANIK at nng.com> wrote:
>>
>
>
> --------------------------------------------------------------------------
> This message, including its attachments, is confidential. For more information please read NNG's email policy here:
> http://www.nng.com/emailpolicy/
> By responding to this email you accept the email policy.
>
>
> -----Original Message-----
>> From: Mercurial-devel [mailto:mercurial-devel-bounces at mercurial-scm.org]
>> On Behalf Of Martin von Zweigbergk via Mercurial-devel
>> Sent: Tuesday, February 14, 2017 2:07 AM
>> To: mercurial-devel at mercurial-scm.org
>> Subject: [PATCH 5 of 6] update: learn --merge to allow merging across
>> topological branches (issue5125)
>>
>> # HG changeset patch
>> # User Martin von Zweigbergk <martinvonz at google.com>
>> # Date 1487019517 28800
>> # Mon Feb 13 12:58:37 2017 -0800
>> # Node ID 75e5a492d7f69420a554fe498ae24060c755b09f
>> # Parent 59e2d3da607cc09ebe133ab199fc4f343d74e1e6
>> update: learn --merge to allow merging across topological branches
>> (issue5125)
>>
>> diff -r 59e2d3da607c -r 75e5a492d7f6 mercurial/commands.py
>> --- a/mercurial/commands.py Mon Feb 13 15:04:46 2017 -0800
>> +++ b/mercurial/commands.py Mon Feb 13 12:58:37 2017 -0800
>> @@ -6471,12 +6471,13 @@
>> @command('^update|up|checkout|co',
>> [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
>> ('c', 'check', None, _('require clean working directory')),
>> + ('m', 'merge', None, _('merge local changes')),
>> ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
>> ('r', 'rev', '', _('revision'), _('REV'))
>> ] + mergetoolopts,
>> - _('[-C|-c] [-d DATE] [[-r] REV]'))
>> + _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
>> def update(ui, repo, node=None, rev=None, clean=False, date=None,
>> check=False,
>> - tool=None):
>> + merge=None, tool=None):
>> """update working directory (or switch revisions)
>>
>> Update the repository's working directory to the specified
>> @@ -6498,7 +6499,7 @@
>> The following rules apply when the working directory contains
>> uncommitted changes:
>>
>> - 1. If neither -c/--check nor -C/--clean is specified, and if
>> + 1. If none of -c/--check, -C/--clean, or -m/--merge is specified, and if
>> the requested changeset is an ancestor or descendant of
>> the working directory's parent, the uncommitted changes
>> are merged into the requested changeset and the merged
>> @@ -6507,10 +6508,14 @@
>> branch), the update is aborted and the uncommitted changes
>> are preserved.
>>
>> - 2. With the -c/--check option, the update is aborted and the
>> + 2. With the -m/--merge option, the update is allowed even if the
>> + requested changeset is not an ancestor or descendant of
>> + the working directory's parent.
>> +
>> + 3. With the -c/--check option, the update is aborted and the
>> uncommitted changes are preserved.
>>
>> - 3. With the -C/--clean option, uncommitted changes are discarded and
>> + 4. With the -C/--clean option, uncommitted changes are discarded and
>> the working directory is updated to the requested changeset.
>>
>> To cancel an uncommitted merge (and lose your changes), use
>> @@ -6535,8 +6540,15 @@
>> if date and rev is not None:
>> raise error.Abort(_("you can't specify a revision and a date"))
>>
>> - if check and clean:
>> - raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
>> + if len([x for x in (check, clean , merge) if x]) > 1:
>> + raise error.Abort(_("can only specify one of -c/--check, -C/--clean, "
>> + "and -m/merge"))
>> +
>> + updatecheck = 'linear'
>> + if check:
>> + updatecheck = 'abort'
>> + elif merge:
>> + updatecheck = None
>
> I don't really like the use of None to indicate "always merge".
> I would strongly prefer updatecheck = 'merge', with None instead
> representing a default or "unset" case.
Makes sense. Since the check that's done is not about merging, I'll
call it 'none' instead, if you don't mind.
>
> This makes setting the default via a config option (as in your 6th patch)
> a lot safer and easier - see below.
>
>>
>> with repo.wlock():
>> cmdutil.clearunfinished(repo)
>> @@ -6550,7 +6562,8 @@
>>
>> repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
>>
>> - return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
>> + return hg.updatetotally(ui, repo, rev, brev, clean=clean,
>> + updatecheck=updatecheck)
>>
>> @command('verify', [])
>> def verify(ui, repo):
>> diff -r 59e2d3da607c -r 75e5a492d7f6 mercurial/hg.py
>> --- a/mercurial/hg.py Mon Feb 13 15:04:46 2017 -0800
>> +++ b/mercurial/hg.py Mon Feb 13 12:58:37 2017 -0800
>> @@ -681,18 +681,19 @@
>> repo.ui.status(_("%d files updated, %d files merged, "
>> "%d files removed, %d files unresolved\n") % stats)
>>
>> -def updaterepo(repo, node, overwrite):
>> +def updaterepo(repo, node, overwrite, updatecheck=None):
>> """Update the working directory to node.
>>
>> When overwrite is set, changes are clobbered, merged else
>>
>> returns stats (see pydoc mercurial.merge.applyupdates)"""
>> return mergemod.update(repo, node, False, overwrite,
>> - labels=['working copy', 'destination'])
>> + labels=['working copy', 'destination'],
>> + updatecheck=updatecheck)
>>
>> -def update(repo, node, quietempty=False):
>> - """update the working directory to node, merging linear changes"""
>> - stats = updaterepo(repo, node, False)
>> +def update(repo, node, quietempty=False, updatecheck=None):
>> + """update the working directory to node"""
>> + stats = updaterepo(repo, node, False, updatecheck=updatecheck)
>> _showstats(repo, stats, quietempty)
>> if stats[3]:
>> repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
>> @@ -712,7 +713,8 @@
>> # naming conflict in updatetotally()
>> _clean = clean
>>
>> -def updatetotally(ui, repo, checkout, brev, clean=False, check=False):
>> +def updatetotally(ui, repo, checkout, brev, clean=False,
>> + updatecheck='linear'):
>
> Please make this updatecheck=None, and set it to 'linear' inside merge.update()
> explicitly if None was passed to that function.
Will do.
>
> This way, in patch 6, you can red the config option inside merge.update(), and let
> other callers (primarily extensions) also automatically follow the config option.
I don't think it's a good idea for the low-level merge.update() to
read the config. That function is called e.g. by rebase and graft and
they should not have their behavior changed by this config.
>
>> """Update the working directory with extra care for non-file components
>>
>> This takes care of non-file components below:
>> @@ -724,7 +726,14 @@
>> :checkout: to which revision the working directory is updated
>> :brev: a name, which might be a bookmark to be activated after updating
>> :clean: whether changes in the working directory can be discarded
>> - :check: whether changes in the working directory should be checked
>> + :updatecheck: how to deal with a dirty working directory
>> +
>> + Valid values for updatecheck are:
>> +
>> + * abort: abort if the working directory is dirty
>> + * None: don't check (merge working directory changes into destination)
>> + * linear: check that update is linear before merging working directory
>> + changes into destination
>>
>> This returns whether conflict is detected at updating or not.
>> """
>> @@ -739,9 +748,10 @@
>> if clean:
>> ret = _clean(repo, checkout)
>> else:
>> - if check:
>> + if updatecheck == 'abort':
>> cmdutil.bailifchanged(repo, merge=False)
>> - ret = _update(repo, checkout)
>> + updatecheck = None
>> + ret = _update(repo, checkout, updatecheck=updatecheck)
>>
>> if not ret and movemarkfrom:
>> if movemarkfrom == repo['.'].node():
>> diff -r 59e2d3da607c -r 75e5a492d7f6 mercurial/merge.py
>> --- a/mercurial/merge.py Mon Feb 13 15:04:46 2017 -0800
>> +++ b/mercurial/merge.py Mon Feb 13 12:58:37 2017 -0800
>> @@ -1444,7 +1444,8 @@
>> repo.dirstate.normal(f)
>>
>> def update(repo, node, branchmerge, force, ancestor=None,
>> - mergeancestor=False, labels=None, matcher=None,
>> mergeforce=False):
>> + mergeancestor=False, labels=None, matcher=None,
>> mergeforce=False,
>> + updatecheck='linear'):
>
> Again, default to None here, and explicitly set to 'linear'
> (and later set it based on config) if it's None.
Will do.
>
>> """
>> Perform a merge between the working directory and the given node
>>
>> @@ -1494,6 +1495,7 @@
>> # This functon used to find the default destination if node was None, but
>> # that's now in destutil.py.
>> assert node is not None
>> + assert updatecheck in (None, 'linear')
>> # If we're doing a partial update, we need to skip updating
>> # the dirstate, so make a note of any partial-ness to the
>> # update here.
>> @@ -1550,7 +1552,8 @@
>> repo.hook('update', parent1=xp2, parent2='', error=0)
>> return 0, 0, 0, 0
>>
>> - if pas not in ([p1], [p2]): # nonlinear
>> + if (updatecheck == 'linear' and
>> + pas not in ([p1], [p2])): # nonlinear
>> dirty = wc.dirty(missing=True)
>> if dirty:
>> # Branching is a bit strange to ensure we do the minimal
>> diff -r 59e2d3da607c -r 75e5a492d7f6 tests/test-completion.t
>> --- a/tests/test-completion.t Mon Feb 13 15:04:46 2017 -0800
>> +++ b/tests/test-completion.t Mon Feb 13 12:58:37 2017 -0800
>> @@ -223,7 +223,7 @@
>> serve: accesslog, daemon, daemon-postexec, errorlog, port, address,
>> prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates,
>> style, ipv6, certificate
>> status: all, modified, added, removed, deleted, clean, unknown, ignored,
>> no-status, copies, print0, rev, change, include, exclude, subrepos, template
>> summary: remote
>> - update: clean, check, date, rev, tool
>> + update: clean, check, merge, date, rev, tool
>> addremove: similarity, subrepos, include, exclude, dry-run
>> archive: no-decode, prefix, rev, type, subrepos, include, exclude
>> backout: merge, commit, no-commit, parent, rev, edit, tool, include,
>> exclude, message, logfile, date, user
>> diff -r 59e2d3da607c -r 75e5a492d7f6 tests/test-update-branches.t
>> --- a/tests/test-update-branches.t Mon Feb 13 15:04:46 2017 -0800
>> +++ b/tests/test-update-branches.t Mon Feb 13 12:58:37 2017 -0800
>> @@ -160,6 +160,16 @@
>> parent=1
>> M foo
>>
>> + $ revtest '-m dirty linear' dirty 1 2 -m
>> + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
>> + parent=2
>> + M foo
>> +
>> + $ revtest '-m dirty cross' dirty 3 4 -m
>> + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
>> + parent=4
>> + M foo
>> +
>> $ revtest '-c dirtysub linear' dirtysub 1 2 -c
>> abort: uncommitted changes in subrepository 'sub'
>> parent=1
>> @@ -171,7 +181,17 @@
>> parent=2
>>
>> $ revtest '-cC dirty linear' dirty 1 2 -cC
>> - abort: cannot specify both -c/--check and -C/--clean
>> + abort: can only specify one of -c/--check, -C/--clean, and -m/merge
>> + parent=1
>> + M foo
>> +
>> + $ revtest '-mc dirty linear' dirty 1 2 -mc
>> + abort: can only specify one of -c/--check, -C/--clean, and -m/merge
>> + parent=1
>> + M foo
>> +
>> + $ revtest '-mC dirty linear' dirty 1 2 -mC
>> + abort: can only specify one of -c/--check, -C/--clean, and -m/merge
>> parent=1
>> M foo
>>
>> _______________________________________________
>> Mercurial-devel mailing list
>> Mercurial-devel at mercurial-scm.org
>> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
More information about the Mercurial-devel
mailing list