Commit 6e68e17e authored by Pierre-Yves David's avatar Pierre-Yves David 🐙
Browse files

topic: add a `exp….topic.linear-merge` option to allow some oedipus

If this option is set to `from-branch`, a user can call `hg merge some-topic`
from a bare branch even if `some-topic` is a direct descendant of the current
working copy parents. This was previously denied if the changesets was on the
same branch, since the result would be an "oedipus merge".

Some user have been requesting this, and this type of merge is one of Gitlab
standard way of merging a "Merge Request". That new option will unlock issue
`heptapod#200` and make this mode available for those who wants it.
parent d77d61c9e5e9
Pipeline #11912 passed with stage
in 4 minutes and 1 second
......@@ -16,6 +16,8 @@ Changelog
topic (0.20.0)
* stack: support foo#stack relation revset (hg-5.4+ only)
* merge: add a experimental.topic.linear-merge option to allow oedipus merges
in some cases.
10.0.3 - in progress
--------------------
......
......@@ -123,6 +123,36 @@ the default in future::
[experimental]
topic.server-gate-topic-changesets = yes
Explicitly merging in the target branch
=======================================
By default, Mercurial will not let your merge a topic into its target branch if
that topic is already based on the head of that branch. In other word,
Mercurial will not let your create a merge that will eventually have two
parents in the same branches, one parent being the ancestors of the other
parent. This behavior can be lifted using the following config::
[experimental]
topic.linear-merge = allow-from-bare-branch
When this option is set to `allow-from-bare-branch`, it is possible to merge a
topic branch from a bare branch (commit an active topic (eg: public one))
regardless of the topology. The result would typically looks like that::
@ summary: resulting merge commit
|\\ branch: my-branch
| |
| o summary: some more change in a topic, the merge "target"
| | branch: my-branch
| | topic: my-topic
| |
| o summary: some change in a topic
|/ branch: my-branch
| topic: my-topic
|
o summary: previous head of the branch, the merge "source"
| branch: my-branch
"""
from __future__ import absolute_import
......@@ -239,6 +269,9 @@ if util.safehasattr(registrar, 'configitem'):
configitem(b'experimental', b'topic.server-gate-topic-changesets',
default=False,
)
configitem(b'experimental', b'topic.linear-merge',
default="reject",
)
def extsetup(ui):
# register config that strictly belong to other code (thg, core, etc)
......@@ -1288,7 +1321,37 @@ def mergeupdatewrap(orig, repo, node, branchmerge, force, *args, **kwargs):
isrebase = False
ist0 = False
try:
ret = orig(repo, node, branchmerge, force, *args, **kwargs)
mergemode = repo.ui.config(b'experimental', b'topic.linear-merge')
cleanup = lambda: None
oldrepo = repo
if mergemode == b'allow-from-bare-branch' and not repo[None].topic():
unfi = repo.unfiltered()
oldrepo = repo
old = unfi.__class__
class overridebranch(old):
def __getitem__(self, rev):
ret = super(overridebranch, self).__getitem__(rev)
if rev == node:
b = ret.branch()
t = ret.topic()
if t:
ret.branch = lambda: b'%s//%s' % (b, t)
return ret
unfi.__class__ = overridebranch
if repo.filtername is not None:
repo = unfi.filtered(repo.filtername)
def cleanup():
unfi.__class__ = old
try:
ret = orig(repo, node, branchmerge, force, *args, **kwargs)
finally:
cleanup()
repo = oldrepo
if not hastopicext(repo):
return ret
# The mergeupdatewrap function makes the destination's topic as the
......
==========================================================
Testing the ability to control merge behavior around topic
==========================================================
Especially, we want to test mode allowing the creation of merge that will
eventually become "oedipus" merge.
$ . "$TESTDIR/testlib/topic_setup.sh"
$ . "$TESTDIR/testlib/common.sh"
Setup a test repository
=======================
$ hg init test-repo
$ cd test-repo
$ mkcommit root
$ mkcommit default-1
$ mkcommit default-2
$ hg up 'desc("default-2")'
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg topic test-topic
marked working directory as topic: test-topic
$ mkcommit topic-1
active topic 'test-topic' grew its first changeset
(see 'hg help topics' for more information)
$ mkcommit topic-2
$ hg up null
0 files updated, 0 files merged, 5 files removed, 0 files unresolved
$ hg log -G
o changeset: 4:c3ec1ef2bf00
| tag: tip
| topic: test-topic
| user: test
| date: Thu Jan 01 00:00:00 1970 +0000
| summary: topic-2
|
o changeset: 3:3300cececc85
| topic: test-topic
| user: test
| date: Thu Jan 01 00:00:00 1970 +0000
| summary: topic-1
|
o changeset: 2:b05d997f9ab0
| user: test
| date: Thu Jan 01 00:00:00 1970 +0000
| summary: default-2
|
o changeset: 1:ccab697ce421
| user: test
| date: Thu Jan 01 00:00:00 1970 +0000
| summary: default-1
|
o changeset: 0:1e4be0697311
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: root
Test that the merge is rejected by default
==========================================
from the topic
$ hg up test-topic
switching to topic test-topic
5 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg merge default
abort: merging with a working directory ancestor has no effect
[255]
from the bare branch
$ hg up default
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
$ hg merge test-topic
abort: nothing to merge
(use 'hg update' or check 'hg heads')
[255]
Test that the merge is rejected if set to reject
================================================
Actually, this also work with any unvalid value, but:
- the default value might change in the future,
- this make sure we read the config right.
Same result when setting the config to be strict
$ cat >> .hg/hgrc << EOF
> [experimental]
> topic.linear-merge = reject
> EOF
from the topic
$ hg up test-topic
switching to topic test-topic
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg merge default
abort: merging with a working directory ancestor has no effect
[255]
from the bare branch
$ hg up default
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
$ hg merge test-topic
abort: nothing to merge
(use 'hg update' or check 'hg heads')
[255]
Test that the merge is accepted if configured to allow them
===========================================================
$ cat >> .hg/hgrc << EOF
> [experimental]
> topic.linear-merge = allow-from-bare-branch
> EOF
from the topic, this is rejected since the resulting merge would be in the topic itself
$ hg up test-topic
switching to topic test-topic
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg merge default
abort: merging with a working directory ancestor has no effect
[255]
from the bare branch this is allowed since the resulting merge will be in the branch
$ hg up default
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
$ hg merge test-topic --traceback
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg ci -m "How dreadful the knowledge of the truth can be when there's no help in truth."
$ hg log -G
@ changeset: 5:42ca2e8cb810
|\ tag: tip
| | parent: 2:b05d997f9ab0
| | parent: 4:c3ec1ef2bf00
| | user: test
| | date: Thu Jan 01 00:00:00 1970 +0000
| | summary: How dreadful the knowledge of the truth can be when there's no help in truth.
| |
| o changeset: 4:c3ec1ef2bf00
| | topic: test-topic
| | user: test
| | date: Thu Jan 01 00:00:00 1970 +0000
| | summary: topic-2
| |
| o changeset: 3:3300cececc85
|/ topic: test-topic
| user: test
| date: Thu Jan 01 00:00:00 1970 +0000
| summary: topic-1
|
o changeset: 2:b05d997f9ab0
| user: test
| date: Thu Jan 01 00:00:00 1970 +0000
| summary: default-2
|
o changeset: 1:ccab697ce421
| user: test
| date: Thu Jan 01 00:00:00 1970 +0000
| summary: default-1
|
o changeset: 0:1e4be0697311
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: root
......@@ -134,6 +134,36 @@
[experimental]
topic.server-gate-topic-changesets = yes
Explicitly merging in the target branch
=======================================
By default, Mercurial will not let your merge a topic into its target branch
if that topic is already based on the head of that branch. In other word,
Mercurial will not let your create a merge that will eventually have two
parents in the same branches, one parent being the ancestors of the other
parent. This behavior can be lifted using the following config:
[experimental]
topic.linear-merge = allow-from-bare-branch
When this option is set to 'allow-from-bare-branch', it is possible to merge a
topic branch from a bare branch (commit an active topic (eg: public one))
regardless of the topology. The result would typically looks like that:
@ summary: resulting merge commit
|\ branch: my-branch
| |
| o summary: some more change in a topic, the merge "target"
| | branch: my-branch
| | topic: my-topic
| |
| o summary: some change in a topic
|/ branch: my-branch
| topic: my-topic
|
o summary: previous head of the branch, the merge "source"
| branch: my-branch
list of commands:
Change organization:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment