diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -1249,15 +1249,35 @@ pass return baseset(datarepr=('', subset, os)) -@predicate('merge()', safe=True) +@predicate('merge([withbranch])', safe=True) def merge(repo, subset, x): - """Changeset is a merge changeset. - """ + """Changeset is a merge changeset + + All merge revisions are returned by default. If a "withbranch" + pattern is provided only merges with (i.e. whose second parent + belongs to) those branches that match the pattern will be returned. + The simplest pattern is the name of a single branch. It is also + possible to specify a regular expression by starting the pattern + with "re:". This can be used to match more than one branch + (e.g. "re:branch1|branch2"). + """ + cl = repo.changelog + # matchfn is a function that returns true when a revision is a merge + matchfn = lambda r: cl.parentrevs(r)[1] != -1 + # i18n: "merge" is a keyword - getargs(x, 0, 0, _("merge takes no arguments")) - cl = repo.changelog - return subset.filter(lambda r: cl.parentrevs(r)[1] != -1, - condrepr='') + args = getargsdict(x, 'merge', 'withbranch') + if 'withbranch' in args: + withbranch = getstring(args['withbranch'], + _('withbranch argument must be a string')) + kind, branchname, branchmatcher = stringutil.stringmatcher(withbranch) + if branchname: + # create the function that will filter the subset + # is a merge and the second parent belongs to a branch that + # matches the withbranch pattern (which can be a literal or a regex) + matchfn = lambda r: (cl.parentrevs(r)[1] != -1 + and branchmatcher(repo[r].p2().branch())) + return subset.filter(matchfn, condrepr='') @predicate('branchpoint()', safe=True) def branchpoint(repo, subset, x): diff --git a/tests/test-help.t b/tests/test-help.t --- a/tests/test-help.t +++ b/tests/test-help.t @@ -1743,8 +1743,15 @@ Test section lookup $ hg help revset.merge - "merge()" - Changeset is a merge changeset. + "merge([withbranch])" + Changeset is a merge changeset + + All merge revisions are returned by default. If a "withbranch" pattern + is provided only merges with (i.e. whose second parent belongs to) those + branches that match the pattern will be returned. The simplest pattern + is the name of a single branch. It is also possible to specify a regular + expression by starting the pattern with "re:". This can be used to match + more than one branch (e.g. "re:branch1|branch2"). $ hg help glossary.dag DAG diff --git a/tests/test-revset.t b/tests/test-revset.t --- a/tests/test-revset.t +++ b/tests/test-revset.t @@ -2954,3 +2954,82 @@ * set: 0 + +test the merge() revset parameters + +create a few merge revisions to test merge() parameters + $ hg up 9 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo a > a + $ hg branch --force ".a.b.c." + marked working directory as branch .a.b.c. + $ hg add a + $ hg commit -m "added a" + created new head + $ hg merge 7 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg commit -m "same branch merge 1" + $ hg up 10 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo a2 > a + $ hg commit -m "changed a to a2" + created new head + $ hg up 11 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg merge 12 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg commit -m "same branch merge 2" + $ echo a3 > a + $ hg commit -m "changed a to a3" + $ hg up 12 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg branch --force "_a_b_c_" + marked working directory as branch _a_b_c_ + $ hg merge 14 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg commit -m "same branch merge 3 (both parents on same branch while merge is on another branch)" + created new head + $ hg up 14 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo a4 > a + $ hg commit -m "changed a to a4" + $ hg up 15 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg merge 16 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg commit -m "different branch merge 1" + $ hg up 16 + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo a5 > a + $ hg branch --force "_a_b_c_" + marked working directory as branch _a_b_c_ + $ hg commit -m "changed a to a5" + created new head + $ hg up 17 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg merge 18 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg commit -m "different branch merge 2" + +show merges with a particular branch + $ log 'merge(.a.b.c.)' + 11 + 13 + 15 + 17 + $ log 'merge(-a-b-c-)' + 6 + +show merges with multiple branches using a regex + $ log 'merge("re:.a.b.c.")' + 6 + 11 + 13 + 15 + 17 + 19