Patchwork [3,of,3,STABLE?] resolve: don't abort when file is missing

login
register
mail settings
Submitter Siddharth Agarwal
Date Nov. 11, 2015, 1:20 a.m.
Message ID <28e772623b1332468126.1447204829@dev666.prn1.facebook.com>
Download mbox | patch
Permalink /patch/11359/
State Accepted
Headers show

Comments

Siddharth Agarwal - Nov. 11, 2015, 1:20 a.m.
# HG changeset patch
# User Siddharth Agarwal <sid0@fb.com>
# Date 1447204619 28800
#      Tue Nov 10 17:16:59 2015 -0800
# Node ID 28e772623b133246812619909196efe50857309d
# Parent  0829cdf6d0d3da14077f4de0d73c8bddf6190f06
resolve: don't abort when file is missing

A file being missing is a completely valid situation in which the user may want
to re-resolve merge conflicts. Mercurial already maintains backups of local
data, so this turns out to be easy to handle.
Siddharth Agarwal - Nov. 11, 2015, 1:24 a.m.
On 11/10/15 17:20, Siddharth Agarwal wrote:
> # HG changeset patch
> # User Siddharth Agarwal <sid0@fb.com>
> # Date 1447204619 28800
> #      Tue Nov 10 17:16:59 2015 -0800
> # Node ID 28e772623b133246812619909196efe50857309d
> # Parent  0829cdf6d0d3da14077f4de0d73c8bddf6190f06
> resolve: don't abort when file is missing

These patches are currently written against default (actually 
clowncopter's @) but should arguably (maybe?) land in stable. However, 
the code here has changed enough that I'll have to prepare completely 
different patches for stable.

>
> A file being missing is a completely valid situation in which the user may want
> to re-resolve merge conflicts. Mercurial already maintains backups of local
> data, so this turns out to be easy to handle.
>
> diff --git a/mercurial/commands.py b/mercurial/commands.py
> --- a/mercurial/commands.py
> +++ b/mercurial/commands.py
> @@ -5655,7 +5655,11 @@ def resolve(ui, repo, *pats, **opts):
>               else:
>                   # backup pre-resolve (merge uses .orig for its own purposes)
>                   a = repo.wjoin(f)
> -                util.copyfile(a, a + ".resolve")
> +                try:
> +                    util.copyfile(a, a + ".resolve")
> +                except (IOError, OSError) as inst:
> +                    if inst.errno != errno.ENOENT:
> +                        raise
>   
>                   try:
>                       # preresolve file
> @@ -5673,7 +5677,11 @@ def resolve(ui, repo, *pats, **opts):
>                   # replace filemerge's .orig file with our resolve file
>                   # for files in tocomplete, ms.resolve will not overwrite
>                   # .orig -- only preresolve does
> -                util.rename(a + ".resolve", a + ".orig")
> +                try:
> +                    util.rename(a + ".resolve", a + ".orig")
> +                except OSError as inst:
> +                    if inst.errno != errno.ENOENT:
> +                        raise
>   
>           for f in tocomplete:
>               try:
> diff --git a/tests/test-merge-tools.t b/tests/test-merge-tools.t
> --- a/tests/test-merge-tools.t
> +++ b/tests/test-merge-tools.t
> @@ -579,6 +579,33 @@ prompt with EOF
>     ? f.orig
>     # hg resolve --list
>     U f
> +  $ rm f
> +  $ hg resolve --all --config ui.merge=internal:prompt --config ui.interactive=true
> +   no tool found to merge f
> +  keep (l)ocal or take (o)ther?
> +  [1]
> +  $ aftermerge
> +  # cat f
> +  revision 1
> +  space
> +  # hg stat
> +  M f
> +  # hg resolve --list
> +  U f
> +  $ hg resolve --all --config ui.merge=internal:prompt
> +   no tool found to merge f
> +  keep (l)ocal or take (o)ther? l
> +  (no more unresolved files)
> +  $ aftermerge
> +  # cat f
> +  revision 1
> +  space
> +  # hg stat
> +  M f
> +  ? f.orig
> +  # hg resolve --list
> +  R f
> +
>   ui.merge specifies internal:dump:
>   
>     $ beforemerge
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> https://selenic.com/mailman/listinfo/mercurial-devel
Martin von Zweigbergk - Nov. 11, 2015, 6:22 p.m.
On Tue, Nov 10, 2015 at 5:21 PM Siddharth Agarwal <sid0@fb.com> wrote:

> # HG changeset patch
> # User Siddharth Agarwal <sid0@fb.com>
> # Date 1447204619 28800
> #      Tue Nov 10 17:16:59 2015 -0800
> # Node ID 28e772623b133246812619909196efe50857309d
> # Parent  0829cdf6d0d3da14077f4de0d73c8bddf6190f06
> resolve: don't abort when file is missing
>
> A file being missing is a completely valid situation in which the user may
> want
> to re-resolve merge conflicts. Mercurial already maintains backups of local
> data, so this turns out to be easy to handle.
>
> diff --git a/mercurial/commands.py b/mercurial/commands.py
> --- a/mercurial/commands.py
> +++ b/mercurial/commands.py
> @@ -5655,7 +5655,11 @@ def resolve(ui, repo, *pats, **opts):
>              else:
>                  # backup pre-resolve (merge uses .orig for its own
> purposes)
>                  a = repo.wjoin(f)
> -                util.copyfile(a, a + ".resolve")
> +                try:
> +                    util.copyfile(a, a + ".resolve")
> +                except (IOError, OSError) as inst:
> +                    if inst.errno != errno.ENOENT:
> +                        raise
>
>                  try:
>                      # preresolve file
> @@ -5673,7 +5677,11 @@ def resolve(ui, repo, *pats, **opts):
>                  # replace filemerge's .orig file with our resolve file
>                  # for files in tocomplete, ms.resolve will not overwrite
>                  # .orig -- only preresolve does
> -                util.rename(a + ".resolve", a + ".orig")
> +                try:
> +                    util.rename(a + ".resolve", a + ".orig")
> +                except OSError as inst:
> +                    if inst.errno != errno.ENOENT:
> +                        raise
>

Is this hunk needed for the fix? IIUC, it's about renaming from the backed
up .resolve file, which seems like a much less likely case. Separate patch
and description (and maybe test)?


>
>          for f in tocomplete:
>              try:
> diff --git a/tests/test-merge-tools.t b/tests/test-merge-tools.t
> --- a/tests/test-merge-tools.t
> +++ b/tests/test-merge-tools.t
> @@ -579,6 +579,33 @@ prompt with EOF
>    ? f.orig
>    # hg resolve --list
>    U f
> +  $ rm f
> +  $ hg resolve --all --config ui.merge=internal:prompt --config
> ui.interactive=true
> +   no tool found to merge f
> +  keep (l)ocal or take (o)ther?
> +  [1]
> +  $ aftermerge
> +  # cat f
> +  revision 1
> +  space
> +  # hg stat
> +  M f
> +  # hg resolve --list
> +  U f
> +  $ hg resolve --all --config ui.merge=internal:prompt
> +   no tool found to merge f
> +  keep (l)ocal or take (o)ther? l
> +  (no more unresolved files)
> +  $ aftermerge
> +  # cat f
> +  revision 1
> +  space
> +  # hg stat
> +  M f
> +  ? f.orig
> +  # hg resolve --list
> +  R f
> +
>  ui.merge specifies internal:dump:
>
>    $ beforemerge
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> https://selenic.com/mailman/listinfo/mercurial-devel
>
Martin von Zweigbergk - Nov. 11, 2015, 6:24 p.m.
On Tue, Nov 10, 2015 at 5:24 PM Siddharth Agarwal <sid@less-broken.com>
wrote:

> On 11/10/15 17:20, Siddharth Agarwal wrote:
> > # HG changeset patch
> > # User Siddharth Agarwal <sid0@fb.com>
> > # Date 1447204619 28800
> > #      Tue Nov 10 17:16:59 2015 -0800
> > # Node ID 28e772623b133246812619909196efe50857309d
> > # Parent  0829cdf6d0d3da14077f4de0d73c8bddf6190f06
> > resolve: don't abort when file is missing
>
> These patches are currently written against default (actually
> clowncopter's @) but should arguably (maybe?) land in stable. However,
> the code here has changed enough that I'll have to prepare completely
> different patches for stable.
>

These are probably very old bugs, so I'd say it's not worth spending time
backporting them.


>
> >
> > A file being missing is a completely valid situation in which the user
> may want
> > to re-resolve merge conflicts. Mercurial already maintains backups of
> local
> > data, so this turns out to be easy to handle.
> >
> > diff --git a/mercurial/commands.py b/mercurial/commands.py
> > --- a/mercurial/commands.py
> > +++ b/mercurial/commands.py
> > @@ -5655,7 +5655,11 @@ def resolve(ui, repo, *pats, **opts):
> >               else:
> >                   # backup pre-resolve (merge uses .orig for its own
> purposes)
> >                   a = repo.wjoin(f)
> > -                util.copyfile(a, a + ".resolve")
> > +                try:
> > +                    util.copyfile(a, a + ".resolve")
> > +                except (IOError, OSError) as inst:
> > +                    if inst.errno != errno.ENOENT:
> > +                        raise
> >
> >                   try:
> >                       # preresolve file
> > @@ -5673,7 +5677,11 @@ def resolve(ui, repo, *pats, **opts):
> >                   # replace filemerge's .orig file with our resolve file
> >                   # for files in tocomplete, ms.resolve will not
> overwrite
> >                   # .orig -- only preresolve does
> > -                util.rename(a + ".resolve", a + ".orig")
> > +                try:
> > +                    util.rename(a + ".resolve", a + ".orig")
> > +                except OSError as inst:
> > +                    if inst.errno != errno.ENOENT:
> > +                        raise
> >
> >           for f in tocomplete:
> >               try:
> > diff --git a/tests/test-merge-tools.t b/tests/test-merge-tools.t
> > --- a/tests/test-merge-tools.t
> > +++ b/tests/test-merge-tools.t
> > @@ -579,6 +579,33 @@ prompt with EOF
> >     ? f.orig
> >     # hg resolve --list
> >     U f
> > +  $ rm f
> > +  $ hg resolve --all --config ui.merge=internal:prompt --config
> ui.interactive=true
> > +   no tool found to merge f
> > +  keep (l)ocal or take (o)ther?
> > +  [1]
> > +  $ aftermerge
> > +  # cat f
> > +  revision 1
> > +  space
> > +  # hg stat
> > +  M f
> > +  # hg resolve --list
> > +  U f
> > +  $ hg resolve --all --config ui.merge=internal:prompt
> > +   no tool found to merge f
> > +  keep (l)ocal or take (o)ther? l
> > +  (no more unresolved files)
> > +  $ aftermerge
> > +  # cat f
> > +  revision 1
> > +  space
> > +  # hg stat
> > +  M f
> > +  ? f.orig
> > +  # hg resolve --list
> > +  R f
> > +
> >   ui.merge specifies internal:dump:
> >
> >     $ beforemerge
> > _______________________________________________
> > Mercurial-devel mailing list
> > Mercurial-devel@selenic.com
> > https://selenic.com/mailman/listinfo/mercurial-devel
>
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> https://selenic.com/mailman/listinfo/mercurial-devel
>
Siddharth Agarwal - Nov. 11, 2015, 6:25 p.m.
On Wednesday, November 11, 2015, Martin von Zweigbergk <
martinvonz@google.com> wrote:

>
>
> On Tue, Nov 10, 2015 at 5:21 PM Siddharth Agarwal <sid0@fb.com
> <javascript:_e(%7B%7D,'cvml','sid0@fb.com');>> wrote:
>
>> # HG changeset patch
>> # User Siddharth Agarwal <sid0@fb.com
>> <javascript:_e(%7B%7D,'cvml','sid0@fb.com');>>
>> # Date 1447204619 28800
>> #      Tue Nov 10 17:16:59 2015 -0800
>> # Node ID 28e772623b133246812619909196efe50857309d
>> # Parent  0829cdf6d0d3da14077f4de0d73c8bddf6190f06
>> resolve: don't abort when file is missing
>>
>> A file being missing is a completely valid situation in which the user
>> may want
>> to re-resolve merge conflicts. Mercurial already maintains backups of
>> local
>> data, so this turns out to be easy to handle.
>>
>> diff --git a/mercurial/commands.py b/mercurial/commands.py
>> --- a/mercurial/commands.py
>> +++ b/mercurial/commands.py
>> @@ -5655,7 +5655,11 @@ def resolve(ui, repo, *pats, **opts):
>>              else:
>>                  # backup pre-resolve (merge uses .orig for its own
>> purposes)
>>                  a = repo.wjoin(f)
>> -                util.copyfile(a, a + ".resolve")
>> +                try:
>> +                    util.copyfile(a, a + ".resolve")
>> +                except (IOError, OSError) as inst:
>> +                    if inst.errno != errno.ENOENT:
>> +                        raise
>>
>>                  try:
>>                      # preresolve file
>> @@ -5673,7 +5677,11 @@ def resolve(ui, repo, *pats, **opts):
>>                  # replace filemerge's .orig file with our resolve file
>>                  # for files in tocomplete, ms.resolve will not overwrite
>>                  # .orig -- only preresolve does
>> -                util.rename(a + ".resolve", a + ".orig")
>> +                try:
>> +                    util.rename(a + ".resolve", a + ".orig")
>> +                except OSError as inst:
>> +                    if inst.errno != errno.ENOENT:
>> +                        raise
>>
>
> Is this hunk needed for the fix? IIUC, it's about renaming from the backed
> up .resolve file, which seems like a much less likely case. Separate patch
> and description (and maybe test)?
>

It's part of the same fix. We copy the file to .resolve, but if it's
missing then we don't write out the .resolve file at all. On the way back
we try to copy it back, but if it was missing in the first place then we
still need to ignore that error.




>
>>
>>          for f in tocomplete:
>>              try:
>> diff --git a/tests/test-merge-tools.t b/tests/test-merge-tools.t
>> --- a/tests/test-merge-tools.t
>> +++ b/tests/test-merge-tools.t
>> @@ -579,6 +579,33 @@ prompt with EOF
>>    ? f.orig
>>    # hg resolve --list
>>    U f
>> +  $ rm f
>> +  $ hg resolve --all --config ui.merge=internal:prompt --config
>> ui.interactive=true
>> +   no tool found to merge f
>> +  keep (l)ocal or take (o)ther?
>> +  [1]
>> +  $ aftermerge
>> +  # cat f
>> +  revision 1
>> +  space
>> +  # hg stat
>> +  M f
>> +  # hg resolve --list
>> +  U f
>> +  $ hg resolve --all --config ui.merge=internal:prompt
>> +   no tool found to merge f
>> +  keep (l)ocal or take (o)ther? l
>> +  (no more unresolved files)
>> +  $ aftermerge
>> +  # cat f
>> +  revision 1
>> +  space
>> +  # hg stat
>> +  M f
>> +  ? f.orig
>> +  # hg resolve --list
>> +  R f
>> +
>>  ui.merge specifies internal:dump:
>>
>>    $ beforemerge
>> _______________________________________________
>> Mercurial-devel mailing list
>> Mercurial-devel@selenic.com
>> <javascript:_e(%7B%7D,'cvml','Mercurial-devel@selenic.com');>
>> https://selenic.com/mailman/listinfo/mercurial-devel
>>
>
Martin von Zweigbergk - Nov. 11, 2015, 6:34 p.m.
On Wed, Nov 11, 2015 at 10:25 AM Siddharth Agarwal <sid@less-broken.com>
wrote:

>
>
> On Wednesday, November 11, 2015, Martin von Zweigbergk <
> martinvonz@google.com> wrote:
>
>>
>>
>> On Tue, Nov 10, 2015 at 5:21 PM Siddharth Agarwal <sid0@fb.com> wrote:
>>
>>> # HG changeset patch
>>> # User Siddharth Agarwal <sid0@fb.com>
>>> # Date 1447204619 28800
>>> #      Tue Nov 10 17:16:59 2015 -0800
>>> # Node ID 28e772623b133246812619909196efe50857309d
>>> # Parent  0829cdf6d0d3da14077f4de0d73c8bddf6190f06
>>> resolve: don't abort when file is missing
>>>
>>> A file being missing is a completely valid situation in which the user
>>> may want
>>> to re-resolve merge conflicts. Mercurial already maintains backups of
>>> local
>>> data, so this turns out to be easy to handle.
>>>
>>> diff --git a/mercurial/commands.py b/mercurial/commands.py
>>> --- a/mercurial/commands.py
>>> +++ b/mercurial/commands.py
>>> @@ -5655,7 +5655,11 @@ def resolve(ui, repo, *pats, **opts):
>>>              else:
>>>                  # backup pre-resolve (merge uses .orig for its own
>>> purposes)
>>>                  a = repo.wjoin(f)
>>> -                util.copyfile(a, a + ".resolve")
>>> +                try:
>>> +                    util.copyfile(a, a + ".resolve")
>>> +                except (IOError, OSError) as inst:
>>> +                    if inst.errno != errno.ENOENT:
>>> +                        raise
>>>
>>>                  try:
>>>                      # preresolve file
>>> @@ -5673,7 +5677,11 @@ def resolve(ui, repo, *pats, **opts):
>>>                  # replace filemerge's .orig file with our resolve file
>>>                  # for files in tocomplete, ms.resolve will not overwrite
>>>                  # .orig -- only preresolve does
>>> -                util.rename(a + ".resolve", a + ".orig")
>>> +                try:
>>> +                    util.rename(a + ".resolve", a + ".orig")
>>> +                except OSError as inst:
>>> +                    if inst.errno != errno.ENOENT:
>>> +                        raise
>>>
>>
>> Is this hunk needed for the fix? IIUC, it's about renaming from the
>> backed up .resolve file, which seems like a much less likely case. Separate
>> patch and description (and maybe test)?
>>
>
> It's part of the same fix. We copy the file to .resolve, but if it's
> missing then we don't write out the .resolve file at all. On the way back
> we try to copy it back, but if it was missing in the first place then we
> still need to ignore that error.
>

Oh, of course, I don't know what I was thinking. Do you want me to push
these to the clowncopter or should we decide whether to backport them to
the stable branch first? I'm guessing it's fine to apply them to the
default branch and then we can cherry-pick (or write new patches) for the
stable branch later if we want to.


>
>
>
>
>>
>>>
>>>          for f in tocomplete:
>>>              try:
>>> diff --git a/tests/test-merge-tools.t b/tests/test-merge-tools.t
>>> --- a/tests/test-merge-tools.t
>>> +++ b/tests/test-merge-tools.t
>>> @@ -579,6 +579,33 @@ prompt with EOF
>>>    ? f.orig
>>>    # hg resolve --list
>>>    U f
>>> +  $ rm f
>>> +  $ hg resolve --all --config ui.merge=internal:prompt --config
>>> ui.interactive=true
>>> +   no tool found to merge f
>>> +  keep (l)ocal or take (o)ther?
>>> +  [1]
>>> +  $ aftermerge
>>> +  # cat f
>>> +  revision 1
>>> +  space
>>> +  # hg stat
>>> +  M f
>>> +  # hg resolve --list
>>> +  U f
>>> +  $ hg resolve --all --config ui.merge=internal:prompt
>>> +   no tool found to merge f
>>> +  keep (l)ocal or take (o)ther? l
>>> +  (no more unresolved files)
>>> +  $ aftermerge
>>> +  # cat f
>>> +  revision 1
>>> +  space
>>> +  # hg stat
>>> +  M f
>>> +  ? f.orig
>>> +  # hg resolve --list
>>> +  R f
>>> +
>>>  ui.merge specifies internal:dump:
>>>
>>>    $ beforemerge
>>> _______________________________________________
>>> Mercurial-devel mailing list
>>> Mercurial-devel@selenic.com
>>> https://selenic.com/mailman/listinfo/mercurial-devel
>>>
>>
Martin von Zweigbergk - Nov. 11, 2015, 7:20 p.m.
On Wed, Nov 11, 2015 at 10:34 AM Martin von Zweigbergk <
martinvonz@google.com> wrote:

> On Wed, Nov 11, 2015 at 10:25 AM Siddharth Agarwal <sid@less-broken.com>
> wrote:
>
>>
>>
>> On Wednesday, November 11, 2015, Martin von Zweigbergk <
>> martinvonz@google.com> wrote:
>>
>>>
>>>
>>> On Tue, Nov 10, 2015 at 5:21 PM Siddharth Agarwal <sid0@fb.com> wrote:
>>>
>>>> # HG changeset patch
>>>> # User Siddharth Agarwal <sid0@fb.com>
>>>> # Date 1447204619 28800
>>>> #      Tue Nov 10 17:16:59 2015 -0800
>>>> # Node ID 28e772623b133246812619909196efe50857309d
>>>> # Parent  0829cdf6d0d3da14077f4de0d73c8bddf6190f06
>>>> resolve: don't abort when file is missing
>>>>
>>>> A file being missing is a completely valid situation in which the user
>>>> may want
>>>> to re-resolve merge conflicts. Mercurial already maintains backups of
>>>> local
>>>> data, so this turns out to be easy to handle.
>>>>
>>>> diff --git a/mercurial/commands.py b/mercurial/commands.py
>>>> --- a/mercurial/commands.py
>>>> +++ b/mercurial/commands.py
>>>> @@ -5655,7 +5655,11 @@ def resolve(ui, repo, *pats, **opts):
>>>>              else:
>>>>                  # backup pre-resolve (merge uses .orig for its own
>>>> purposes)
>>>>                  a = repo.wjoin(f)
>>>> -                util.copyfile(a, a + ".resolve")
>>>> +                try:
>>>> +                    util.copyfile(a, a + ".resolve")
>>>> +                except (IOError, OSError) as inst:
>>>> +                    if inst.errno != errno.ENOENT:
>>>> +                        raise
>>>>
>>>>                  try:
>>>>                      # preresolve file
>>>> @@ -5673,7 +5677,11 @@ def resolve(ui, repo, *pats, **opts):
>>>>                  # replace filemerge's .orig file with our resolve file
>>>>                  # for files in tocomplete, ms.resolve will not
>>>> overwrite
>>>>                  # .orig -- only preresolve does
>>>> -                util.rename(a + ".resolve", a + ".orig")
>>>> +                try:
>>>> +                    util.rename(a + ".resolve", a + ".orig")
>>>> +                except OSError as inst:
>>>> +                    if inst.errno != errno.ENOENT:
>>>> +                        raise
>>>>
>>>
>>> Is this hunk needed for the fix? IIUC, it's about renaming from the
>>> backed up .resolve file, which seems like a much less likely case. Separate
>>> patch and description (and maybe test)?
>>>
>>
>> It's part of the same fix. We copy the file to .resolve, but if it's
>> missing then we don't write out the .resolve file at all. On the way
>> back we try to copy it back, but if it was missing in the first place then
>> we still need to ignore that error.
>>
>
> Oh, of course, I don't know what I was thinking. Do you want me to push
> these to the clowncopter or should we decide whether to backport them to
> the stable branch first? I'm guessing it's fine to apply them to the
> default branch and then we can cherry-pick (or write new patches) for the
> stable branch later if we want to.
>

OK, pushing this to the clowncopter, thanks.


>
>
>>
>>
>>
>>
>>>
>>>>
>>>>          for f in tocomplete:
>>>>              try:
>>>> diff --git a/tests/test-merge-tools.t b/tests/test-merge-tools.t
>>>> --- a/tests/test-merge-tools.t
>>>> +++ b/tests/test-merge-tools.t
>>>> @@ -579,6 +579,33 @@ prompt with EOF
>>>>    ? f.orig
>>>>    # hg resolve --list
>>>>    U f
>>>> +  $ rm f
>>>> +  $ hg resolve --all --config ui.merge=internal:prompt --config
>>>> ui.interactive=true
>>>> +   no tool found to merge f
>>>> +  keep (l)ocal or take (o)ther?
>>>> +  [1]
>>>> +  $ aftermerge
>>>> +  # cat f
>>>> +  revision 1
>>>> +  space
>>>> +  # hg stat
>>>> +  M f
>>>> +  # hg resolve --list
>>>> +  U f
>>>> +  $ hg resolve --all --config ui.merge=internal:prompt
>>>> +   no tool found to merge f
>>>> +  keep (l)ocal or take (o)ther? l
>>>> +  (no more unresolved files)
>>>> +  $ aftermerge
>>>> +  # cat f
>>>> +  revision 1
>>>> +  space
>>>> +  # hg stat
>>>> +  M f
>>>> +  ? f.orig
>>>> +  # hg resolve --list
>>>> +  R f
>>>> +
>>>>  ui.merge specifies internal:dump:
>>>>
>>>>    $ beforemerge
>>>> _______________________________________________
>>>> Mercurial-devel mailing list
>>>> Mercurial-devel@selenic.com
>>>> https://selenic.com/mailman/listinfo/mercurial-devel
>>>>
>>>

Patch

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -5655,7 +5655,11 @@  def resolve(ui, repo, *pats, **opts):
             else:
                 # backup pre-resolve (merge uses .orig for its own purposes)
                 a = repo.wjoin(f)
-                util.copyfile(a, a + ".resolve")
+                try:
+                    util.copyfile(a, a + ".resolve")
+                except (IOError, OSError) as inst:
+                    if inst.errno != errno.ENOENT:
+                        raise
 
                 try:
                     # preresolve file
@@ -5673,7 +5677,11 @@  def resolve(ui, repo, *pats, **opts):
                 # replace filemerge's .orig file with our resolve file
                 # for files in tocomplete, ms.resolve will not overwrite
                 # .orig -- only preresolve does
-                util.rename(a + ".resolve", a + ".orig")
+                try:
+                    util.rename(a + ".resolve", a + ".orig")
+                except OSError as inst:
+                    if inst.errno != errno.ENOENT:
+                        raise
 
         for f in tocomplete:
             try:
diff --git a/tests/test-merge-tools.t b/tests/test-merge-tools.t
--- a/tests/test-merge-tools.t
+++ b/tests/test-merge-tools.t
@@ -579,6 +579,33 @@  prompt with EOF
   ? f.orig
   # hg resolve --list
   U f
+  $ rm f
+  $ hg resolve --all --config ui.merge=internal:prompt --config ui.interactive=true
+   no tool found to merge f
+  keep (l)ocal or take (o)ther? 
+  [1]
+  $ aftermerge
+  # cat f
+  revision 1
+  space
+  # hg stat
+  M f
+  # hg resolve --list
+  U f
+  $ hg resolve --all --config ui.merge=internal:prompt
+   no tool found to merge f
+  keep (l)ocal or take (o)ther? l
+  (no more unresolved files)
+  $ aftermerge
+  # cat f
+  revision 1
+  space
+  # hg stat
+  M f
+  ? f.orig
+  # hg resolve --list
+  R f
+
 ui.merge specifies internal:dump:
 
   $ beforemerge