Patchwork merge: add option to return successful exit code on a 'no-op merge'

login
register
mail settings
Submitter Bernhard Urban
Date Nov. 4, 2014, 4:08 p.m.
Message ID <5c6b2329f67f18a6f2bf.1415117302@delljku>
Download mbox | patch
Permalink /patch/6565/
State Rejected
Headers show

Comments

Bernhard Urban - Nov. 4, 2014, 4:08 p.m.
# HG changeset patch
# User Bernhard Urban <lewurm@gmail.com>
# Date 1415116918 -3600
#      Tue Nov 04 17:01:58 2014 +0100
# Node ID 5c6b2329f67f18a6f2bf9fff2ef86f04337b25ff
# Parent  30e0dcd7c5ffd99fb9c2474e9d73ca01a7d292fa
merge: add option to return successful exit code on a 'no-op merge'
Pierre-Yves David - Nov. 4, 2014, 6:16 p.m.
On 11/04/2014 04:08 PM, Bernhard Urban wrote:
> # HG changeset patch
> # User Bernhard Urban <lewurm@gmail.com>
> # Date 1415116918 -3600
> #      Tue Nov 04 17:01:58 2014 +0100
> # Node ID 5c6b2329f67f18a6f2bf9fff2ef86f04337b25ff
> # Parent  30e0dcd7c5ffd99fb9c2474e9d73ca01a7d292fa
> merge: add option to return successful exit code on a 'no-op merge'

Can you tell us more about your usecase here ?
Bernhard Urban - Nov. 4, 2014, 9:13 p.m.
On Tue, Nov 4, 2014 at 7:16 PM, Pierre-Yves David <
pierre-yves.david@ens-lyon.org> wrote:

>
>
> On 11/04/2014 04:08 PM, Bernhard Urban wrote:
>
>> # HG changeset patch
>> # User Bernhard Urban <lewurm@gmail.com>
>> # Date 1415116918 -3600
>> #      Tue Nov 04 17:01:58 2014 +0100
>> # Node ID 5c6b2329f67f18a6f2bf9fff2ef86f04337b25ff
>> # Parent  30e0dcd7c5ffd99fb9c2474e9d73ca01a7d292fa
>> merge: add option to return successful exit code on a 'no-op merge'
>>
>
> Can you tell us more about your usecase here ?
>
>
Our concrete situation is that we've a downstream repo (repoB) that we want
to automatically merge on pushes to its upstream repo (repoA) and run some
tests.

So we do something like `hg clone repoB && hg pull repoA && hg merge &&
make tests'.  The intended behaviour is that if the merge fails, the whole
build should be marked as failed (and thus, needs human interaction).
However, it can happen that for some reasons repoB is already merged with
repoA and then `hg merge' breaks the chain because it returns something !=0
since there's nothing to merge.

Granted, we can do something like 'hg clone repoB && hg pull repoA && (test
`hg log -r 'head()' --template '{node}\n' | wc -l` -le 1 || hg merge) &&
make tests', but I think it's somehow unintentional that `hg merge' bails
out on such a "no-op" merge.  I would even go that far and make the
suggested -a option as default, but I can see how this could break existing
software.


What do you think?


Thanks,
Bernhard
Matt Mackall - Nov. 4, 2014, 10:09 p.m.
On Tue, 2014-11-04 at 22:13 +0100, Bernhard Urban wrote:
> On Tue, Nov 4, 2014 at 7:16 PM, Pierre-Yves David <
> pierre-yves.david@ens-lyon.org> wrote:
> 
> >
> >
> > On 11/04/2014 04:08 PM, Bernhard Urban wrote:
> >
> >> # HG changeset patch
> >> # User Bernhard Urban <lewurm@gmail.com>
> >> # Date 1415116918 -3600
> >> #      Tue Nov 04 17:01:58 2014 +0100
> >> # Node ID 5c6b2329f67f18a6f2bf9fff2ef86f04337b25ff
> >> # Parent  30e0dcd7c5ffd99fb9c2474e9d73ca01a7d292fa
> >> merge: add option to return successful exit code on a 'no-op merge'
> >>
> >
> > Can you tell us more about your usecase here ?
> >
> >
> Our concrete situation is that we've a downstream repo (repoB) that we want
> to automatically merge on pushes to its upstream repo (repoA) and run some
> tests.
> 
> So we do something like `hg clone repoB && hg pull repoA && hg merge &&
> make tests'.  The intended behaviour is that if the merge fails, the whole
> build should be marked as failed (and thus, needs human interaction).
> However, it can happen that for some reasons repoB is already merged with
> repoA and then `hg merge' breaks the chain because it returns something !=0
> since there's nothing to merge.

We're pretty reluctant to add new flags with very narrow uses. The fact
that we've gotten nearly 10 years without this being proposed suggests
it might be a pretty obscure need.

I think for your case, it might be better to have:

a) a compact query to find the merge target
b) a command that has no output but returns true for a non-empty revset

This is sort of what you want:

hg id -qr 'head() and not .' # not silent
Bernhard Urban - Nov. 5, 2014, 1:11 p.m.
On Tue, Nov 4, 2014 at 11:09 PM, Matt Mackall <mpm@selenic.com> wrote:

> On Tue, 2014-11-04 at 22:13 +0100, Bernhard Urban wrote:
> > On Tue, Nov 4, 2014 at 7:16 PM, Pierre-Yves David <
> > pierre-yves.david@ens-lyon.org> wrote:
> >
> > >
> > >
> > > On 11/04/2014 04:08 PM, Bernhard Urban wrote:
> > >
> > >> # HG changeset patch
> > >> # User Bernhard Urban <lewurm@gmail.com>
> > >> # Date 1415116918 -3600
> > >> #      Tue Nov 04 17:01:58 2014 +0100
> > >> # Node ID 5c6b2329f67f18a6f2bf9fff2ef86f04337b25ff
> > >> # Parent  30e0dcd7c5ffd99fb9c2474e9d73ca01a7d292fa
> > >> merge: add option to return successful exit code on a 'no-op merge'
> > >>
> > >
> > > Can you tell us more about your usecase here ?
> > >
> > >
> > Our concrete situation is that we've a downstream repo (repoB) that we
> want
> > to automatically merge on pushes to its upstream repo (repoA) and run
> some
> > tests.
> >
> > So we do something like `hg clone repoB && hg pull repoA && hg merge &&
> > make tests'.  The intended behaviour is that if the merge fails, the
> whole
> > build should be marked as failed (and thus, needs human interaction).
> > However, it can happen that for some reasons repoB is already merged with
> > repoA and then `hg merge' breaks the chain because it returns something
> !=0
> > since there's nothing to merge.
>
> We're pretty reluctant to add new flags with very narrow uses. The fact
> that we've gotten nearly 10 years without this being proposed suggests
> it might be a pretty obscure need.
>

ok I understand.  Thanks for your comments and suggestions anyway! :)

-Bernhard

Patch

diff -r 30e0dcd7c5ff -r 5c6b2329f67f mercurial/commands.py
--- a/mercurial/commands.py	Thu Oct 16 23:15:35 2014 -0700
+++ b/mercurial/commands.py	Tue Nov 04 17:01:58 2014 +0100
@@ -4530,10 +4530,12 @@ 
     [('f', 'force', None,
       _('force a merge including outstanding changes (DEPRECATED)')),
     ('r', 'rev', '', _('revision to merge'), _('REV')),
+    ('a', 'acceptnothing', None,
+     _('if the merge has no effect, the exit code is still 0')),
     ('P', 'preview', None,
      _('review revisions to merge (no merge is performed)'))
      ] + mergetoolopts,
-    _('[-P] [-f] [[-r] REV]'))
+    _('[-P] [-a] [-f] [[-r] REV]'))
 def merge(ui, repo, node=None, **opts):
     """merge working directory with another revision
 
@@ -4613,6 +4615,8 @@ 
             msg, hint = _('nothing to merge'), None
             if parent != repo.lookup(branch):
                 hint = _("use 'hg update' instead")
+            elif opts.get('acceptnothing'):
+                return 0
             raise util.Abort(msg, hint=hint)
 
         if parent not in bheads:
diff -r 30e0dcd7c5ff -r 5c6b2329f67f tests/test-merge-default.t
--- a/tests/test-merge-default.t	Thu Oct 16 23:15:35 2014 -0700
+++ b/tests/test-merge-default.t	Tue Nov 04 17:01:58 2014 +0100
@@ -69,6 +69,10 @@ 
   abort: nothing to merge
   [255]
 
+Should succeed because --acceptnothing is provided:
+
+  $ hg merge -a
+
   $ hg up 0
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved