Patchwork [11,of,11,V5] update: allow setting default update check to "noconflict"

login
register
mail settings
Submitter via Mercurial-devel
Date Feb. 28, 2017, 12:31 a.m.
Message ID <c88aa4bc36ee81b0837d.1488241888@martinvonz.mtv.corp.google.com>
Download mbox | patch
Permalink /patch/18829/
State Accepted
Headers show

Comments

via Mercurial-devel - Feb. 28, 2017, 12:31 a.m.
# HG changeset patch
# User Martin von Zweigbergk <martinvonz@google.com>
# Date 1486973155 28800
#      Mon Feb 13 00:05:55 2017 -0800
# Node ID c88aa4bc36ee81b0837d2949501d6b4fcf825c38
# Parent  ae37f4578e3af6fd4cb7c29c9ab06ad0efd726da
update: allow setting default update check to "noconflict"

The new value allows update (linear or not) as long as they don't
result in file merges.

I'm hoping that this value can some day become the default.
Ryan McElroy - March 1, 2017, 7:54 p.m.
I'm a very big +1 on this direction -- this is a huge usability improvment.

Facebook currently adds a "--nocheck" flag and turns on "check" by 
default in our "tweakdefaults" extension, but this direction is strictly 
better than that and we will definitely switch over to this "noconflict" 
functionality once it gets into core. I even volunteer to do the work to 
remove the "nocheck" stuff from tweakdefaults and all that.

Thanks a ton for working on this Martin!



On 2/27/17 4:31 PM, Martin von Zweigbergk via Mercurial-devel wrote:
> # HG changeset patch
> # User Martin von Zweigbergk <martinvonz@google.com>
> # Date 1486973155 28800
> #      Mon Feb 13 00:05:55 2017 -0800
> # Node ID c88aa4bc36ee81b0837d2949501d6b4fcf825c38
> # Parent  ae37f4578e3af6fd4cb7c29c9ab06ad0efd726da
> update: allow setting default update check to "noconflict"
>
> The new value allows update (linear or not) as long as they don't
> result in file merges.
>
> I'm hoping that this value can some day become the default.
>
> diff -r ae37f4578e3a -r c88aa4bc36ee mercurial/hg.py
> --- a/mercurial/hg.py	Mon Feb 13 16:03:05 2017 -0800
> +++ b/mercurial/hg.py	Mon Feb 13 00:05:55 2017 -0800
> @@ -733,12 +733,13 @@
>        * none: don't check (merge working directory changes into destination)
>        * linear: check that update is linear before merging working directory
>                  changes into destination
> +     * noconflict: check that the update does not result in file merges
>   
>       This returns whether conflict is detected at updating or not.
>       """
>       if updatecheck is None:
>           updatecheck = ui.config('experimental', 'updatecheck')
> -        if updatecheck not in ('abort', 'none', 'linear'):
> +        if updatecheck not in ('abort', 'none', 'linear', 'noconflict'):
>               # If not configured, or invalid value configured
>               updatecheck = 'linear'
>       with repo.wlock():
> diff -r ae37f4578e3a -r c88aa4bc36ee mercurial/merge.py
> --- a/mercurial/merge.py	Mon Feb 13 16:03:05 2017 -0800
> +++ b/mercurial/merge.py	Mon Feb 13 00:05:55 2017 -0800
> @@ -1465,21 +1465,27 @@
>       The table below shows all the behaviors of the update command
>       given the -c and -C or no options, whether the working directory
>       is dirty, whether a revision is specified, and the relationship of
> -    the parent rev to the target rev (linear or not). Match from top first.
> +    the parent rev to the target rev (linear or not). Match from top first. The
> +    -n option doesn't exist on the command line, but represents the
> +    experimental.updatecheck=noconflict option.
>   
>       This logic is tested by test-update-branches.t.
>   
> -    -c  -C  -m  dirty  rev  linear  |  result
> -     y   y   *    *     *     *     |    (1)
> -     y   *   y    *     *     *     |    (1)
> -     *   y   y    *     *     *     |    (1)
> -     *   *   *    *     n     n     |     x
> -     *   *   *    n     *     *     |    ok
> -     n   n   n    y     *     y     |   merge
> -     n   n   n    y     y     n     |    (2)
> -     n   n   y    y     *     *     |   merge
> -     n   y   n    y     *     *     |  discard
> -     y   n   n    y     *     *     |    (3)
> +    -c  -C  -n  -m  dirty  rev  linear  |  result
> +     y   y   *   *    *     *     *     |    (1)
> +     y   *   y   *    *     *     *     |    (1)
> +     y   *   *   y    *     *     *     |    (1)
> +     *   y   y   *    *     *     *     |    (1)
> +     *   y   *   y    *     *     *     |    (1)
> +     *   *   y   y    *     *     *     |    (1)
> +     *   *   *   *    *     n     n     |     x
> +     *   *   *   *    n     *     *     |    ok
> +     n   n   n   n    y     *     y     |   merge
> +     n   n   n   n    y     y     n     |    (2)
> +     n   n   n   y    y     *     *     |   merge
> +     n   n   y   n    y     *     *     |  merge if no conflict
> +     n   y   n   n    y     *     *     |  discard
> +     y   n   n   n    y     *     *     |    (3)
>   
>       x = can't happen
>       * = don't-care
> @@ -1499,7 +1505,7 @@
>           # updatecheck='abort' to better suppport some of these callers.
>           if updatecheck is None:
>               updatecheck = 'linear'
> -        assert updatecheck in ('none', 'linear')
> +        assert updatecheck in ('none', 'linear', 'noconflict')
>       # 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.
> @@ -1593,6 +1599,13 @@
>               repo, wc, p2, pas, branchmerge, force, mergeancestor,
>               followcopies, matcher=matcher, mergeforce=mergeforce)
>   
> +        if updatecheck == 'noconflict':
> +            for f, (m, args, msg) in actionbyfile.iteritems():
> +                if m not in ('g', 'k', 'r'):
> +                    msg = _("uncommitted changes")

I'd make this message more specific/correct -- something like 
"conflicting changes", or perhaps more pedantically, "working copy 
changes conflict with update changes". I bring this up because 
"uncommitted changes" is true but doesn't really explain why we're aborting.

> +                    hint = _("commit or update --merge to allow merge")
> +                    raise error.Abort(msg, hint=hint)
> +
>           # Prompt and create actions. Most of this is in the resolve phase
>           # already, but we can't handle .hgsubstate in filemerge or
>           # subrepo.submerge yet so we have to keep prompting for it.
> diff -r ae37f4578e3a -r c88aa4bc36ee tests/test-update-branches.t
> --- a/tests/test-update-branches.t	Mon Feb 13 16:03:05 2017 -0800
> +++ b/tests/test-update-branches.t	Mon Feb 13 00:05:55 2017 -0800
> @@ -255,6 +255,65 @@
>     >>>>>>> destination:  d047485b3896 b1 - test: 4
>     $ rm a.orig
>   
> +  $ echo 'updatecheck = noconflict' >> .hg/hgrc
> +
> +  $ revtest 'none dirty cross'  dirty 3 4
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  parent=4
> +  M foo
> +
> +  $ revtest 'none dirty linear' dirty 1 2
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  parent=2
> +  M foo
> +
> +  $ revtest 'none dirty linear' dirty 1 2 -c
> +  abort: uncommitted changes
> +  parent=1
> +  M foo
> +
> +  $ revtest 'none dirty linear' dirty 1 2 -C
> +  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  parent=2
> +
> +Locally added file is allowed
> +  $ hg up -qC 3
> +  $ echo a > bar
> +  $ hg add bar
> +  $ hg up -q 4
> +  $ hg st
> +  A bar
> +  $ hg forget bar
> +  $ rm bar
> +
> +Locally removed file is allowed
> +  $ hg up -qC 3
> +  $ hg rm a
> +  $ hg up -q 4
> +  abort: uncommitted changes
> +  (commit or update --merge to allow merge)
> +  [255]
> +
> +File conflict is not allowed
> +  $ hg up -qC 3
> +  $ echo dirty >> a
> +  $ hg up -q 4
> +  abort: uncommitted changes
> +  (commit or update --merge to allow merge)
> +  [255]
> +  $ hg up -m 4
> +  merging a
> +  warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
> +  0 files updated, 0 files merged, 0 files removed, 1 files unresolved
> +  use 'hg resolve' to retry unresolved file merges
> +  [1]
> +  $ rm a.orig
> +
> +Change/delete conflict is not allowed
> +  $ hg up -qC 3
> +  $ hg rm foo
> +  $ hg up -q 4
> +
>   Uses default value of "linear" when value is misspelled
>     $ echo 'updatecheck = linyar' >> .hg/hgrc
>   
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://urldefense.proofpoint.com/v2/url?u=https-3A__www.mercurial-2Dscm.org_mailman_listinfo_mercurial-2Ddevel&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=Jw8rundaE7TbmqBYd1txIQ&m=2u9dCw6A0fe99XyZphoSmE3eMMmzpJiKHmWN2Jw59OY&s=w8OK4IdcRn8DN3K02gpGh2Bhm-eW0Up6dtnK75FifPY&e=
via Mercurial-devel - March 1, 2017, 8:41 p.m.
On Wed, Mar 1, 2017 at 11:54 AM, Ryan McElroy <rm@fb.com> wrote:
> I'm a very big +1 on this direction -- this is a huge usability improvment.
>
> Facebook currently adds a "--nocheck" flag and turns on "check" by default
> in our "tweakdefaults" extension, but this direction is strictly better than
> that and we will definitely switch over to this "noconflict" functionality
> once it gets into core. I even volunteer to do the work to remove the
> "nocheck" stuff from tweakdefaults and all that.
>
> Thanks a ton for working on this Martin!

Great to hear it will be sufficient to replace that part of tweakdefaults.

>
>
>
>
> On 2/27/17 4:31 PM, Martin von Zweigbergk via Mercurial-devel wrote:
>>
>> # HG changeset patch
>> # User Martin von Zweigbergk <martinvonz@google.com>
>> # Date 1486973155 28800
>> #      Mon Feb 13 00:05:55 2017 -0800
>> # Node ID c88aa4bc36ee81b0837d2949501d6b4fcf825c38
>> # Parent  ae37f4578e3af6fd4cb7c29c9ab06ad0efd726da
>> update: allow setting default update check to "noconflict"
>>
>> The new value allows update (linear or not) as long as they don't
>> result in file merges.
>>
>> I'm hoping that this value can some day become the default.
>>
>> diff -r ae37f4578e3a -r c88aa4bc36ee mercurial/hg.py
>> --- a/mercurial/hg.py   Mon Feb 13 16:03:05 2017 -0800
>> +++ b/mercurial/hg.py   Mon Feb 13 00:05:55 2017 -0800
>> @@ -733,12 +733,13 @@
>>        * none: don't check (merge working directory changes into
>> destination)
>>        * linear: check that update is linear before merging working
>> directory
>>                  changes into destination
>> +     * noconflict: check that the update does not result in file merges
>>         This returns whether conflict is detected at updating or not.
>>       """
>>       if updatecheck is None:
>>           updatecheck = ui.config('experimental', 'updatecheck')
>> -        if updatecheck not in ('abort', 'none', 'linear'):
>> +        if updatecheck not in ('abort', 'none', 'linear', 'noconflict'):
>>               # If not configured, or invalid value configured
>>               updatecheck = 'linear'
>>       with repo.wlock():
>> diff -r ae37f4578e3a -r c88aa4bc36ee mercurial/merge.py
>> --- a/mercurial/merge.py        Mon Feb 13 16:03:05 2017 -0800
>> +++ b/mercurial/merge.py        Mon Feb 13 00:05:55 2017 -0800
>> @@ -1465,21 +1465,27 @@
>>       The table below shows all the behaviors of the update command
>>       given the -c and -C or no options, whether the working directory
>>       is dirty, whether a revision is specified, and the relationship of
>> -    the parent rev to the target rev (linear or not). Match from top
>> first.
>> +    the parent rev to the target rev (linear or not). Match from top
>> first. The
>> +    -n option doesn't exist on the command line, but represents the
>> +    experimental.updatecheck=noconflict option.
>>         This logic is tested by test-update-branches.t.
>>   -    -c  -C  -m  dirty  rev  linear  |  result
>> -     y   y   *    *     *     *     |    (1)
>> -     y   *   y    *     *     *     |    (1)
>> -     *   y   y    *     *     *     |    (1)
>> -     *   *   *    *     n     n     |     x
>> -     *   *   *    n     *     *     |    ok
>> -     n   n   n    y     *     y     |   merge
>> -     n   n   n    y     y     n     |    (2)
>> -     n   n   y    y     *     *     |   merge
>> -     n   y   n    y     *     *     |  discard
>> -     y   n   n    y     *     *     |    (3)
>> +    -c  -C  -n  -m  dirty  rev  linear  |  result
>> +     y   y   *   *    *     *     *     |    (1)
>> +     y   *   y   *    *     *     *     |    (1)
>> +     y   *   *   y    *     *     *     |    (1)
>> +     *   y   y   *    *     *     *     |    (1)
>> +     *   y   *   y    *     *     *     |    (1)
>> +     *   *   y   y    *     *     *     |    (1)
>> +     *   *   *   *    *     n     n     |     x
>> +     *   *   *   *    n     *     *     |    ok
>> +     n   n   n   n    y     *     y     |   merge
>> +     n   n   n   n    y     y     n     |    (2)
>> +     n   n   n   y    y     *     *     |   merge
>> +     n   n   y   n    y     *     *     |  merge if no conflict
>> +     n   y   n   n    y     *     *     |  discard
>> +     y   n   n   n    y     *     *     |    (3)
>>         x = can't happen
>>       * = don't-care
>> @@ -1499,7 +1505,7 @@
>>           # updatecheck='abort' to better suppport some of these callers.
>>           if updatecheck is None:
>>               updatecheck = 'linear'
>> -        assert updatecheck in ('none', 'linear')
>> +        assert updatecheck in ('none', 'linear', 'noconflict')
>>       # 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.
>> @@ -1593,6 +1599,13 @@
>>               repo, wc, p2, pas, branchmerge, force, mergeancestor,
>>               followcopies, matcher=matcher, mergeforce=mergeforce)
>>   +        if updatecheck == 'noconflict':
>> +            for f, (m, args, msg) in actionbyfile.iteritems():
>> +                if m not in ('g', 'k', 'r'):
>> +                    msg = _("uncommitted changes")
>
>
> I'd make this message more specific/correct -- something like "conflicting
> changes", or perhaps more pedantically, "working copy changes conflict with
> update changes". I bring this up because "uncommitted changes" is true but
> doesn't really explain why we're aborting.

Oh, good point. Looks like I just copied and pasted that without thinking.

To the person queuing this, do you want to queue the first 10 and I
can just send an update of this patch, to avoid spamming the list with
a V6 of all 11 patches?

>
>> +                    hint = _("commit or update --merge to allow merge")
>> +                    raise error.Abort(msg, hint=hint)
>> +
>>           # Prompt and create actions. Most of this is in the resolve
>> phase
>>           # already, but we can't handle .hgsubstate in filemerge or
>>           # subrepo.submerge yet so we have to keep prompting for it.
>> diff -r ae37f4578e3a -r c88aa4bc36ee tests/test-update-branches.t
>> --- a/tests/test-update-branches.t      Mon Feb 13 16:03:05 2017 -0800
>> +++ b/tests/test-update-branches.t      Mon Feb 13 00:05:55 2017 -0800
>> @@ -255,6 +255,65 @@
>>     >>>>>>> destination:  d047485b3896 b1 - test: 4
>>     $ rm a.orig
>>   +  $ echo 'updatecheck = noconflict' >> .hg/hgrc
>> +
>> +  $ revtest 'none dirty cross'  dirty 3 4
>> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
>> +  parent=4
>> +  M foo
>> +
>> +  $ revtest 'none dirty linear' dirty 1 2
>> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
>> +  parent=2
>> +  M foo
>> +
>> +  $ revtest 'none dirty linear' dirty 1 2 -c
>> +  abort: uncommitted changes
>> +  parent=1
>> +  M foo
>> +
>> +  $ revtest 'none dirty linear' dirty 1 2 -C
>> +  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
>> +  parent=2
>> +
>> +Locally added file is allowed
>> +  $ hg up -qC 3
>> +  $ echo a > bar
>> +  $ hg add bar
>> +  $ hg up -q 4
>> +  $ hg st
>> +  A bar
>> +  $ hg forget bar
>> +  $ rm bar
>> +
>> +Locally removed file is allowed
>> +  $ hg up -qC 3
>> +  $ hg rm a
>> +  $ hg up -q 4
>> +  abort: uncommitted changes
>> +  (commit or update --merge to allow merge)
>> +  [255]
>> +
>> +File conflict is not allowed
>> +  $ hg up -qC 3
>> +  $ echo dirty >> a
>> +  $ hg up -q 4
>> +  abort: uncommitted changes
>> +  (commit or update --merge to allow merge)
>> +  [255]
>> +  $ hg up -m 4
>> +  merging a
>> +  warning: conflicts while merging a! (edit, then use 'hg resolve
>> --mark')
>> +  0 files updated, 0 files merged, 0 files removed, 1 files unresolved
>> +  use 'hg resolve' to retry unresolved file merges
>> +  [1]
>> +  $ rm a.orig
>> +
>> +Change/delete conflict is not allowed
>> +  $ hg up -qC 3
>> +  $ hg rm foo
>> +  $ hg up -q 4
>> +
>>   Uses default value of "linear" when value is misspelled
>>     $ echo 'updatecheck = linyar' >> .hg/hgrc
>>   _______________________________________________
>> Mercurial-devel mailing list
>> Mercurial-devel@mercurial-scm.org
>>
>> https://urldefense.proofpoint.com/v2/url?u=https-3A__www.mercurial-2Dscm.org_mailman_listinfo_mercurial-2Ddevel&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=Jw8rundaE7TbmqBYd1txIQ&m=2u9dCw6A0fe99XyZphoSmE3eMMmzpJiKHmWN2Jw59OY&s=w8OK4IdcRn8DN3K02gpGh2Bhm-eW0Up6dtnK75FifPY&e=
>
>
Ryan McElroy - March 2, 2017, 1:59 a.m.
I've reviwed the rest of the series and it looks good to me.


On 3/1/17 12:41 PM, Martin von Zweigbergk wrote:
> On Wed, Mar 1, 2017 at 11:54 AM, Ryan McElroy <rm@fb.com> wrote:
>> I'm a very big +1 on this direction -- this is a huge usability improvment.
>>
>> Facebook currently adds a "--nocheck" flag and turns on "check" by default
>> in our "tweakdefaults" extension, but this direction is strictly better than
>> that and we will definitely switch over to this "noconflict" functionality
>> once it gets into core. I even volunteer to do the work to remove the
>> "nocheck" stuff from tweakdefaults and all that.
>>
>> Thanks a ton for working on this Martin!
> Great to hear it will be sufficient to replace that part of tweakdefaults.
>
>>
>>
>>
>> On 2/27/17 4:31 PM, Martin von Zweigbergk via Mercurial-devel wrote:
>>> # HG changeset patch
>>> # User Martin von Zweigbergk <martinvonz@google.com>
>>> # Date 1486973155 28800
>>> #      Mon Feb 13 00:05:55 2017 -0800
>>> # Node ID c88aa4bc36ee81b0837d2949501d6b4fcf825c38
>>> # Parent  ae37f4578e3af6fd4cb7c29c9ab06ad0efd726da
>>> update: allow setting default update check to "noconflict"
>>>
>>> The new value allows update (linear or not) as long as they don't
>>> result in file merges.
>>>
>>> I'm hoping that this value can some day become the default.
>>>
>>> diff -r ae37f4578e3a -r c88aa4bc36ee mercurial/hg.py
>>> --- a/mercurial/hg.py   Mon Feb 13 16:03:05 2017 -0800
>>> +++ b/mercurial/hg.py   Mon Feb 13 00:05:55 2017 -0800
>>> @@ -733,12 +733,13 @@
>>>         * none: don't check (merge working directory changes into
>>> destination)
>>>         * linear: check that update is linear before merging working
>>> directory
>>>                   changes into destination
>>> +     * noconflict: check that the update does not result in file merges
>>>          This returns whether conflict is detected at updating or not.
>>>        """
>>>        if updatecheck is None:
>>>            updatecheck = ui.config('experimental', 'updatecheck')
>>> -        if updatecheck not in ('abort', 'none', 'linear'):
>>> +        if updatecheck not in ('abort', 'none', 'linear', 'noconflict'):
>>>                # If not configured, or invalid value configured
>>>                updatecheck = 'linear'
>>>        with repo.wlock():
>>> diff -r ae37f4578e3a -r c88aa4bc36ee mercurial/merge.py
>>> --- a/mercurial/merge.py        Mon Feb 13 16:03:05 2017 -0800
>>> +++ b/mercurial/merge.py        Mon Feb 13 00:05:55 2017 -0800
>>> @@ -1465,21 +1465,27 @@
>>>        The table below shows all the behaviors of the update command
>>>        given the -c and -C or no options, whether the working directory
>>>        is dirty, whether a revision is specified, and the relationship of
>>> -    the parent rev to the target rev (linear or not). Match from top
>>> first.
>>> +    the parent rev to the target rev (linear or not). Match from top
>>> first. The
>>> +    -n option doesn't exist on the command line, but represents the
>>> +    experimental.updatecheck=noconflict option.
>>>          This logic is tested by test-update-branches.t.
>>>    -    -c  -C  -m  dirty  rev  linear  |  result
>>> -     y   y   *    *     *     *     |    (1)
>>> -     y   *   y    *     *     *     |    (1)
>>> -     *   y   y    *     *     *     |    (1)
>>> -     *   *   *    *     n     n     |     x
>>> -     *   *   *    n     *     *     |    ok
>>> -     n   n   n    y     *     y     |   merge
>>> -     n   n   n    y     y     n     |    (2)
>>> -     n   n   y    y     *     *     |   merge
>>> -     n   y   n    y     *     *     |  discard
>>> -     y   n   n    y     *     *     |    (3)
>>> +    -c  -C  -n  -m  dirty  rev  linear  |  result
>>> +     y   y   *   *    *     *     *     |    (1)
>>> +     y   *   y   *    *     *     *     |    (1)
>>> +     y   *   *   y    *     *     *     |    (1)
>>> +     *   y   y   *    *     *     *     |    (1)
>>> +     *   y   *   y    *     *     *     |    (1)
>>> +     *   *   y   y    *     *     *     |    (1)
>>> +     *   *   *   *    *     n     n     |     x
>>> +     *   *   *   *    n     *     *     |    ok
>>> +     n   n   n   n    y     *     y     |   merge
>>> +     n   n   n   n    y     y     n     |    (2)
>>> +     n   n   n   y    y     *     *     |   merge
>>> +     n   n   y   n    y     *     *     |  merge if no conflict
>>> +     n   y   n   n    y     *     *     |  discard
>>> +     y   n   n   n    y     *     *     |    (3)
>>>          x = can't happen
>>>        * = don't-care
>>> @@ -1499,7 +1505,7 @@
>>>            # updatecheck='abort' to better suppport some of these callers.
>>>            if updatecheck is None:
>>>                updatecheck = 'linear'
>>> -        assert updatecheck in ('none', 'linear')
>>> +        assert updatecheck in ('none', 'linear', 'noconflict')
>>>        # 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.
>>> @@ -1593,6 +1599,13 @@
>>>                repo, wc, p2, pas, branchmerge, force, mergeancestor,
>>>                followcopies, matcher=matcher, mergeforce=mergeforce)
>>>    +        if updatecheck == 'noconflict':
>>> +            for f, (m, args, msg) in actionbyfile.iteritems():
>>> +                if m not in ('g', 'k', 'r'):
>>> +                    msg = _("uncommitted changes")
>>
>> I'd make this message more specific/correct -- something like "conflicting
>> changes", or perhaps more pedantically, "working copy changes conflict with
>> update changes". I bring this up because "uncommitted changes" is true but
>> doesn't really explain why we're aborting.
> Oh, good point. Looks like I just copied and pasted that without thinking.
>
> To the person queuing this, do you want to queue the first 10 and I
> can just send an update of this patch, to avoid spamming the list with
> a V6 of all 11 patches?
>
>>> +                    hint = _("commit or update --merge to allow merge")
>>> +                    raise error.Abort(msg, hint=hint)
>>> +
>>>            # Prompt and create actions. Most of this is in the resolve
>>> phase
>>>            # already, but we can't handle .hgsubstate in filemerge or
>>>            # subrepo.submerge yet so we have to keep prompting for it.
>>> diff -r ae37f4578e3a -r c88aa4bc36ee tests/test-update-branches.t
>>> --- a/tests/test-update-branches.t      Mon Feb 13 16:03:05 2017 -0800
>>> +++ b/tests/test-update-branches.t      Mon Feb 13 00:05:55 2017 -0800
>>> @@ -255,6 +255,65 @@
>>>      >>>>>>> destination:  d047485b3896 b1 - test: 4
>>>      $ rm a.orig
>>>    +  $ echo 'updatecheck = noconflict' >> .hg/hgrc
>>> +
>>> +  $ revtest 'none dirty cross'  dirty 3 4
>>> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
>>> +  parent=4
>>> +  M foo
>>> +
>>> +  $ revtest 'none dirty linear' dirty 1 2
>>> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
>>> +  parent=2
>>> +  M foo
>>> +
>>> +  $ revtest 'none dirty linear' dirty 1 2 -c
>>> +  abort: uncommitted changes
>>> +  parent=1
>>> +  M foo
>>> +
>>> +  $ revtest 'none dirty linear' dirty 1 2 -C
>>> +  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
>>> +  parent=2
>>> +
>>> +Locally added file is allowed
>>> +  $ hg up -qC 3
>>> +  $ echo a > bar
>>> +  $ hg add bar
>>> +  $ hg up -q 4
>>> +  $ hg st
>>> +  A bar
>>> +  $ hg forget bar
>>> +  $ rm bar
>>> +
>>> +Locally removed file is allowed
>>> +  $ hg up -qC 3
>>> +  $ hg rm a
>>> +  $ hg up -q 4
>>> +  abort: uncommitted changes
>>> +  (commit or update --merge to allow merge)
>>> +  [255]
>>> +
>>> +File conflict is not allowed
>>> +  $ hg up -qC 3
>>> +  $ echo dirty >> a
>>> +  $ hg up -q 4
>>> +  abort: uncommitted changes
>>> +  (commit or update --merge to allow merge)
>>> +  [255]
>>> +  $ hg up -m 4
>>> +  merging a
>>> +  warning: conflicts while merging a! (edit, then use 'hg resolve
>>> --mark')
>>> +  0 files updated, 0 files merged, 0 files removed, 1 files unresolved
>>> +  use 'hg resolve' to retry unresolved file merges
>>> +  [1]
>>> +  $ rm a.orig
>>> +
>>> +Change/delete conflict is not allowed
>>> +  $ hg up -qC 3
>>> +  $ hg rm foo
>>> +  $ hg up -q 4
>>> +
>>>    Uses default value of "linear" when value is misspelled
>>>      $ echo 'updatecheck = linyar' >> .hg/hgrc
>>>    _______________________________________________
>>> Mercurial-devel mailing list
>>> Mercurial-devel@mercurial-scm.org
>>>
>>> https://urldefense.proofpoint.com/v2/url?u=https-3A__www.mercurial-2Dscm.org_mailman_listinfo_mercurial-2Ddevel&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=Jw8rundaE7TbmqBYd1txIQ&m=2u9dCw6A0fe99XyZphoSmE3eMMmzpJiKHmWN2Jw59OY&s=w8OK4IdcRn8DN3K02gpGh2Bhm-eW0Up6dtnK75FifPY&e=
>>
Yuya Nishihara - March 6, 2017, 3 p.m.
On Mon, 27 Feb 2017 16:31:28 -0800, Martin von Zweigbergk via Mercurial-devel wrote:
> # HG changeset patch
> # User Martin von Zweigbergk <martinvonz@google.com>
> # Date 1486973155 28800
> #      Mon Feb 13 00:05:55 2017 -0800
> # Node ID c88aa4bc36ee81b0837d2949501d6b4fcf825c38
> # Parent  ae37f4578e3af6fd4cb7c29c9ab06ad0efd726da
> update: allow setting default update check to "noconflict"

> @@ -1593,6 +1599,13 @@
>              repo, wc, p2, pas, branchmerge, force, mergeancestor,
>              followcopies, matcher=matcher, mergeforce=mergeforce)
>  
> +        if updatecheck == 'noconflict':
> +            for f, (m, args, msg) in actionbyfile.iteritems():
> +                if m not in ('g', 'k', 'r'):
> +                    msg = _("uncommitted changes")
> +                    hint = _("commit or update --merge to allow merge")
> +                    raise error.Abort(msg, hint=hint)

Also queued this, thanks. I'm not perfectly sure if this ('g', 'k', 'r') list
is exhaustive, but it would go safer side in case it lacks something.
via Mercurial-devel - March 6, 2017, 5:10 p.m.
On Mon, Mar 6, 2017 at 7:00 AM, Yuya Nishihara <yuya@tcha.org> wrote:
> On Mon, 27 Feb 2017 16:31:28 -0800, Martin von Zweigbergk via Mercurial-devel wrote:
>> # HG changeset patch
>> # User Martin von Zweigbergk <martinvonz@google.com>
>> # Date 1486973155 28800
>> #      Mon Feb 13 00:05:55 2017 -0800
>> # Node ID c88aa4bc36ee81b0837d2949501d6b4fcf825c38
>> # Parent  ae37f4578e3af6fd4cb7c29c9ab06ad0efd726da
>> update: allow setting default update check to "noconflict"
>
>> @@ -1593,6 +1599,13 @@
>>              repo, wc, p2, pas, branchmerge, force, mergeancestor,
>>              followcopies, matcher=matcher, mergeforce=mergeforce)
>>
>> +        if updatecheck == 'noconflict':
>> +            for f, (m, args, msg) in actionbyfile.iteritems():
>> +                if m not in ('g', 'k', 'r'):
>> +                    msg = _("uncommitted changes")
>> +                    hint = _("commit or update --merge to allow merge")
>> +                    raise error.Abort(msg, hint=hint)
>
> Also queued this, thanks.

Thanks.

I'm not sure if you saw Ryan's comment.  I'll address that as a follow-up patch.

> I'm not perfectly sure if this ('g', 'k', 'r') list
> is exhaustive, but it would go safer side in case it lacks something.

Exactly :-)
via Mercurial-devel - March 6, 2017, 5:10 p.m.
+mercurial-devel (sorry, missed that again)

On Mon, Mar 6, 2017 at 9:10 AM, Martin von Zweigbergk
<martinvonz@google.com> wrote:
> On Mon, Mar 6, 2017 at 7:00 AM, Yuya Nishihara <yuya@tcha.org> wrote:
>> On Mon, 27 Feb 2017 16:31:28 -0800, Martin von Zweigbergk via Mercurial-devel wrote:
>>> # HG changeset patch
>>> # User Martin von Zweigbergk <martinvonz@google.com>
>>> # Date 1486973155 28800
>>> #      Mon Feb 13 00:05:55 2017 -0800
>>> # Node ID c88aa4bc36ee81b0837d2949501d6b4fcf825c38
>>> # Parent  ae37f4578e3af6fd4cb7c29c9ab06ad0efd726da
>>> update: allow setting default update check to "noconflict"
>>
>>> @@ -1593,6 +1599,13 @@
>>>              repo, wc, p2, pas, branchmerge, force, mergeancestor,
>>>              followcopies, matcher=matcher, mergeforce=mergeforce)
>>>
>>> +        if updatecheck == 'noconflict':
>>> +            for f, (m, args, msg) in actionbyfile.iteritems():
>>> +                if m not in ('g', 'k', 'r'):
>>> +                    msg = _("uncommitted changes")
>>> +                    hint = _("commit or update --merge to allow merge")
>>> +                    raise error.Abort(msg, hint=hint)
>>
>> Also queued this, thanks.
>
> Thanks.
>
> I'm not sure if you saw Ryan's comment.  I'll address that as a follow-up patch.
>
>> I'm not perfectly sure if this ('g', 'k', 'r') list
>> is exhaustive, but it would go safer side in case it lacks something.
>
> Exactly :-)
Augie Fackler - March 7, 2017, 4:33 p.m.
On Wed, Mar 01, 2017 at 11:54:21AM -0800, Ryan McElroy wrote:
> I'm a very big +1 on this direction -- this is a huge usability improvment.
>
> Facebook currently adds a "--nocheck" flag and turns on "check" by default
> in our "tweakdefaults" extension, but this direction is strictly better than
> that and we will definitely switch over to this "noconflict" functionality
> once it gets into core. I even volunteer to do the work to remove the
> "nocheck" stuff from tweakdefaults and all that.

I feel obligated to point out that 4.1 added a --no-check flag to core
(but 4.2 will let you drop this entirely, hopefully, so probably don't
make your users change muscle memory now.)

>
> Thanks a ton for working on this Martin!
>
>
>
> On 2/27/17 4:31 PM, Martin von Zweigbergk via Mercurial-devel wrote:
> > # HG changeset patch
> > # User Martin von Zweigbergk <martinvonz@google.com>
> > # Date 1486973155 28800
> > #      Mon Feb 13 00:05:55 2017 -0800
> > # Node ID c88aa4bc36ee81b0837d2949501d6b4fcf825c38
> > # Parent  ae37f4578e3af6fd4cb7c29c9ab06ad0efd726da
> > update: allow setting default update check to "noconflict"
> >
> > The new value allows update (linear or not) as long as they don't
> > result in file merges.
> >
> > I'm hoping that this value can some day become the default.
> >
> > diff -r ae37f4578e3a -r c88aa4bc36ee mercurial/hg.py
> > --- a/mercurial/hg.py	Mon Feb 13 16:03:05 2017 -0800
> > +++ b/mercurial/hg.py	Mon Feb 13 00:05:55 2017 -0800
> > @@ -733,12 +733,13 @@
> >        * none: don't check (merge working directory changes into destination)
> >        * linear: check that update is linear before merging working directory
> >                  changes into destination
> > +     * noconflict: check that the update does not result in file merges
> >       This returns whether conflict is detected at updating or not.
> >       """
> >       if updatecheck is None:
> >           updatecheck = ui.config('experimental', 'updatecheck')
> > -        if updatecheck not in ('abort', 'none', 'linear'):
> > +        if updatecheck not in ('abort', 'none', 'linear', 'noconflict'):
> >               # If not configured, or invalid value configured
> >               updatecheck = 'linear'
> >       with repo.wlock():
> > diff -r ae37f4578e3a -r c88aa4bc36ee mercurial/merge.py
> > --- a/mercurial/merge.py	Mon Feb 13 16:03:05 2017 -0800
> > +++ b/mercurial/merge.py	Mon Feb 13 00:05:55 2017 -0800
> > @@ -1465,21 +1465,27 @@
> >       The table below shows all the behaviors of the update command
> >       given the -c and -C or no options, whether the working directory
> >       is dirty, whether a revision is specified, and the relationship of
> > -    the parent rev to the target rev (linear or not). Match from top first.
> > +    the parent rev to the target rev (linear or not). Match from top first. The
> > +    -n option doesn't exist on the command line, but represents the
> > +    experimental.updatecheck=noconflict option.
> >       This logic is tested by test-update-branches.t.
> > -    -c  -C  -m  dirty  rev  linear  |  result
> > -     y   y   *    *     *     *     |    (1)
> > -     y   *   y    *     *     *     |    (1)
> > -     *   y   y    *     *     *     |    (1)
> > -     *   *   *    *     n     n     |     x
> > -     *   *   *    n     *     *     |    ok
> > -     n   n   n    y     *     y     |   merge
> > -     n   n   n    y     y     n     |    (2)
> > -     n   n   y    y     *     *     |   merge
> > -     n   y   n    y     *     *     |  discard
> > -     y   n   n    y     *     *     |    (3)
> > +    -c  -C  -n  -m  dirty  rev  linear  |  result
> > +     y   y   *   *    *     *     *     |    (1)
> > +     y   *   y   *    *     *     *     |    (1)
> > +     y   *   *   y    *     *     *     |    (1)
> > +     *   y   y   *    *     *     *     |    (1)
> > +     *   y   *   y    *     *     *     |    (1)
> > +     *   *   y   y    *     *     *     |    (1)
> > +     *   *   *   *    *     n     n     |     x
> > +     *   *   *   *    n     *     *     |    ok
> > +     n   n   n   n    y     *     y     |   merge
> > +     n   n   n   n    y     y     n     |    (2)
> > +     n   n   n   y    y     *     *     |   merge
> > +     n   n   y   n    y     *     *     |  merge if no conflict
> > +     n   y   n   n    y     *     *     |  discard
> > +     y   n   n   n    y     *     *     |    (3)
> >       x = can't happen
> >       * = don't-care
> > @@ -1499,7 +1505,7 @@
> >           # updatecheck='abort' to better suppport some of these callers.
> >           if updatecheck is None:
> >               updatecheck = 'linear'
> > -        assert updatecheck in ('none', 'linear')
> > +        assert updatecheck in ('none', 'linear', 'noconflict')
> >       # 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.
> > @@ -1593,6 +1599,13 @@
> >               repo, wc, p2, pas, branchmerge, force, mergeancestor,
> >               followcopies, matcher=matcher, mergeforce=mergeforce)
> > +        if updatecheck == 'noconflict':
> > +            for f, (m, args, msg) in actionbyfile.iteritems():
> > +                if m not in ('g', 'k', 'r'):
> > +                    msg = _("uncommitted changes")
>
> I'd make this message more specific/correct -- something like "conflicting
> changes", or perhaps more pedantically, "working copy changes conflict with
> update changes". I bring this up because "uncommitted changes" is true but
> doesn't really explain why we're aborting.
>
> > +                    hint = _("commit or update --merge to allow merge")
> > +                    raise error.Abort(msg, hint=hint)
> > +
> >           # Prompt and create actions. Most of this is in the resolve phase
> >           # already, but we can't handle .hgsubstate in filemerge or
> >           # subrepo.submerge yet so we have to keep prompting for it.
> > diff -r ae37f4578e3a -r c88aa4bc36ee tests/test-update-branches.t
> > --- a/tests/test-update-branches.t	Mon Feb 13 16:03:05 2017 -0800
> > +++ b/tests/test-update-branches.t	Mon Feb 13 00:05:55 2017 -0800
> > @@ -255,6 +255,65 @@
> >     >>>>>>> destination:  d047485b3896 b1 - test: 4
> >     $ rm a.orig
> > +  $ echo 'updatecheck = noconflict' >> .hg/hgrc
> > +
> > +  $ revtest 'none dirty cross'  dirty 3 4
> > +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> > +  parent=4
> > +  M foo
> > +
> > +  $ revtest 'none dirty linear' dirty 1 2
> > +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> > +  parent=2
> > +  M foo
> > +
> > +  $ revtest 'none dirty linear' dirty 1 2 -c
> > +  abort: uncommitted changes
> > +  parent=1
> > +  M foo
> > +
> > +  $ revtest 'none dirty linear' dirty 1 2 -C
> > +  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
> > +  parent=2
> > +
> > +Locally added file is allowed
> > +  $ hg up -qC 3
> > +  $ echo a > bar
> > +  $ hg add bar
> > +  $ hg up -q 4
> > +  $ hg st
> > +  A bar
> > +  $ hg forget bar
> > +  $ rm bar
> > +
> > +Locally removed file is allowed
> > +  $ hg up -qC 3
> > +  $ hg rm a
> > +  $ hg up -q 4
> > +  abort: uncommitted changes
> > +  (commit or update --merge to allow merge)
> > +  [255]
> > +
> > +File conflict is not allowed
> > +  $ hg up -qC 3
> > +  $ echo dirty >> a
> > +  $ hg up -q 4
> > +  abort: uncommitted changes
> > +  (commit or update --merge to allow merge)
> > +  [255]
> > +  $ hg up -m 4
> > +  merging a
> > +  warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
> > +  0 files updated, 0 files merged, 0 files removed, 1 files unresolved
> > +  use 'hg resolve' to retry unresolved file merges
> > +  [1]
> > +  $ rm a.orig
> > +
> > +Change/delete conflict is not allowed
> > +  $ hg up -qC 3
> > +  $ hg rm foo
> > +  $ hg up -q 4
> > +
> >   Uses default value of "linear" when value is misspelled
> >     $ echo 'updatecheck = linyar' >> .hg/hgrc
> > _______________________________________________
> > Mercurial-devel mailing list
> > Mercurial-devel@mercurial-scm.org
> > https://urldefense.proofpoint.com/v2/url?u=https-3A__www.mercurial-2Dscm.org_mailman_listinfo_mercurial-2Ddevel&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=Jw8rundaE7TbmqBYd1txIQ&m=2u9dCw6A0fe99XyZphoSmE3eMMmzpJiKHmWN2Jw59OY&s=w8OK4IdcRn8DN3K02gpGh2Bhm-eW0Up6dtnK75FifPY&e=
>
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

Patch

diff -r ae37f4578e3a -r c88aa4bc36ee mercurial/hg.py
--- a/mercurial/hg.py	Mon Feb 13 16:03:05 2017 -0800
+++ b/mercurial/hg.py	Mon Feb 13 00:05:55 2017 -0800
@@ -733,12 +733,13 @@ 
      * none: don't check (merge working directory changes into destination)
      * linear: check that update is linear before merging working directory
                changes into destination
+     * noconflict: check that the update does not result in file merges
 
     This returns whether conflict is detected at updating or not.
     """
     if updatecheck is None:
         updatecheck = ui.config('experimental', 'updatecheck')
-        if updatecheck not in ('abort', 'none', 'linear'):
+        if updatecheck not in ('abort', 'none', 'linear', 'noconflict'):
             # If not configured, or invalid value configured
             updatecheck = 'linear'
     with repo.wlock():
diff -r ae37f4578e3a -r c88aa4bc36ee mercurial/merge.py
--- a/mercurial/merge.py	Mon Feb 13 16:03:05 2017 -0800
+++ b/mercurial/merge.py	Mon Feb 13 00:05:55 2017 -0800
@@ -1465,21 +1465,27 @@ 
     The table below shows all the behaviors of the update command
     given the -c and -C or no options, whether the working directory
     is dirty, whether a revision is specified, and the relationship of
-    the parent rev to the target rev (linear or not). Match from top first.
+    the parent rev to the target rev (linear or not). Match from top first. The
+    -n option doesn't exist on the command line, but represents the
+    experimental.updatecheck=noconflict option.
 
     This logic is tested by test-update-branches.t.
 
-    -c  -C  -m  dirty  rev  linear  |  result
-     y   y   *    *     *     *     |    (1)
-     y   *   y    *     *     *     |    (1)
-     *   y   y    *     *     *     |    (1)
-     *   *   *    *     n     n     |     x
-     *   *   *    n     *     *     |    ok
-     n   n   n    y     *     y     |   merge
-     n   n   n    y     y     n     |    (2)
-     n   n   y    y     *     *     |   merge
-     n   y   n    y     *     *     |  discard
-     y   n   n    y     *     *     |    (3)
+    -c  -C  -n  -m  dirty  rev  linear  |  result
+     y   y   *   *    *     *     *     |    (1)
+     y   *   y   *    *     *     *     |    (1)
+     y   *   *   y    *     *     *     |    (1)
+     *   y   y   *    *     *     *     |    (1)
+     *   y   *   y    *     *     *     |    (1)
+     *   *   y   y    *     *     *     |    (1)
+     *   *   *   *    *     n     n     |     x
+     *   *   *   *    n     *     *     |    ok
+     n   n   n   n    y     *     y     |   merge
+     n   n   n   n    y     y     n     |    (2)
+     n   n   n   y    y     *     *     |   merge
+     n   n   y   n    y     *     *     |  merge if no conflict
+     n   y   n   n    y     *     *     |  discard
+     y   n   n   n    y     *     *     |    (3)
 
     x = can't happen
     * = don't-care
@@ -1499,7 +1505,7 @@ 
         # updatecheck='abort' to better suppport some of these callers.
         if updatecheck is None:
             updatecheck = 'linear'
-        assert updatecheck in ('none', 'linear')
+        assert updatecheck in ('none', 'linear', 'noconflict')
     # 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.
@@ -1593,6 +1599,13 @@ 
             repo, wc, p2, pas, branchmerge, force, mergeancestor,
             followcopies, matcher=matcher, mergeforce=mergeforce)
 
+        if updatecheck == 'noconflict':
+            for f, (m, args, msg) in actionbyfile.iteritems():
+                if m not in ('g', 'k', 'r'):
+                    msg = _("uncommitted changes")
+                    hint = _("commit or update --merge to allow merge")
+                    raise error.Abort(msg, hint=hint)
+
         # Prompt and create actions. Most of this is in the resolve phase
         # already, but we can't handle .hgsubstate in filemerge or
         # subrepo.submerge yet so we have to keep prompting for it.
diff -r ae37f4578e3a -r c88aa4bc36ee tests/test-update-branches.t
--- a/tests/test-update-branches.t	Mon Feb 13 16:03:05 2017 -0800
+++ b/tests/test-update-branches.t	Mon Feb 13 00:05:55 2017 -0800
@@ -255,6 +255,65 @@ 
   >>>>>>> destination:  d047485b3896 b1 - test: 4
   $ rm a.orig
 
+  $ echo 'updatecheck = noconflict' >> .hg/hgrc
+
+  $ revtest 'none dirty cross'  dirty 3 4
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  parent=4
+  M foo
+
+  $ revtest 'none dirty linear' dirty 1 2
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  parent=2
+  M foo
+
+  $ revtest 'none dirty linear' dirty 1 2 -c
+  abort: uncommitted changes
+  parent=1
+  M foo
+
+  $ revtest 'none dirty linear' dirty 1 2 -C
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  parent=2
+
+Locally added file is allowed
+  $ hg up -qC 3
+  $ echo a > bar
+  $ hg add bar
+  $ hg up -q 4
+  $ hg st
+  A bar
+  $ hg forget bar
+  $ rm bar
+
+Locally removed file is allowed
+  $ hg up -qC 3
+  $ hg rm a
+  $ hg up -q 4
+  abort: uncommitted changes
+  (commit or update --merge to allow merge)
+  [255]
+
+File conflict is not allowed
+  $ hg up -qC 3
+  $ echo dirty >> a
+  $ hg up -q 4
+  abort: uncommitted changes
+  (commit or update --merge to allow merge)
+  [255]
+  $ hg up -m 4
+  merging a
+  warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
+  0 files updated, 0 files merged, 0 files removed, 1 files unresolved
+  use 'hg resolve' to retry unresolved file merges
+  [1]
+  $ rm a.orig
+
+Change/delete conflict is not allowed
+  $ hg up -qC 3
+  $ hg rm foo
+  $ hg up -q 4
+
 Uses default value of "linear" when value is misspelled
   $ echo 'updatecheck = linyar' >> .hg/hgrc