Patchwork [2,of,2] filemerge: add non-interactive :merge-local and :merge-other

login
register
mail settings
Submitter Jordi Gutiérrez Hermoso
Date Sept. 10, 2015, 1:46 p.m.
Message ID <2e027e77612762dda893.1441892783@Iris>
Download mbox | patch
Permalink /patch/10460/
State Accepted
Headers show

Comments

Jordi Gutiérrez Hermoso - Sept. 10, 2015, 1:46 p.m.
# HG changeset patch
# User Jordi Gutiérrez Hermoso <jordigh@octave.org>
# Date 1441892471 14400
#      Thu Sep 10 09:41:11 2015 -0400
# Node ID 2e027e77612762dda8935d8ae98dec89e9967ed4
# Parent  b39d3a8d66dfb964ceffda0fecdb9f7fd47449ef
filemerge: add non-interactive :merge-local and :merge-other

There are two non-interactive internal merge tools, :other and :local,
but they don't really merge, they just pick all changes from the local
or other version of the file. In some situations, it is known that we
want a merge and also know that all merge conflicts should be resolved
in one direction. Although external merge tools can do this, sometimes
it can be convenient to do so from within hg, without invoking a merge
tool. These new :merge-local and :merge-other tools can do just that.
Augie Fackler - Sept. 10, 2015, 1:59 p.m.
On Thu, Sep 10, 2015 at 09:46:23AM -0400, Jordi Gutiérrez Hermoso wrote:
> # HG changeset patch
> # User Jordi Gutiérrez Hermoso <jordigh@octave.org>
> # Date 1441892471 14400
> #      Thu Sep 10 09:41:11 2015 -0400
> # Node ID 2e027e77612762dda8935d8ae98dec89e9967ed4
> # Parent  b39d3a8d66dfb964ceffda0fecdb9f7fd47449ef
> filemerge: add non-interactive :merge-local and :merge-other

I have wanted this more times than I can express. Queued with delight.

>
> There are two non-interactive internal merge tools, :other and :local,
> but they don't really merge, they just pick all changes from the local
> or other version of the file. In some situations, it is known that we
> want a merge and also know that all merge conflicts should be resolved
> in one direction. Although external merge tools can do this, sometimes
> it can be convenient to do so from within hg, without invoking a merge
> tool. These new :merge-local and :merge-other tools can do just that.
>
> diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
> --- a/mercurial/filemerge.py
> +++ b/mercurial/filemerge.py
> @@ -286,6 +286,38 @@ def _imerge3(repo, mynode, orig, fcd, fc
>          labels.append('base')
>      return _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels)
>
> +def _imergeauto(repo, mynode, orig, fcd, fco, fca, toolconf, files,
> +                labels=None, localorother=None):
> +    """
> +    Generic driver for _imergelocal and _imergeother
> +    """
> +    assert localorother is not None
> +    tool, toolpath, binary, symlink = toolconf
> +    if symlink:
> +        repo.ui.warn(_('warning: :merge-%s cannot merge symlinks '
> +                       'for %s\n') % (localorother, fcd.path()))
> +        return False, 1
> +    a, b, c, back = files
> +    r = simplemerge.simplemerge(repo.ui, a, b, c, label=labels,
> +                                localorother=localorother)
> +    return True, r
> +
> +@internaltool('merge-local', True)
> +def _imergelocal(*args, **kwargs):
> +    """
> +    Like :merge, but resolve all conflicts non-interactively in favor
> +    of the local changes."""
> +    success, status = _imergeauto(localorother='local', *args, **kwargs)
> +    return success, status
> +
> +@internaltool('merge-other', True)
> +def _imergeother(*args, **kwargs):
> +    """
> +    Like :merge, but resolve all conflicts non-interactively in favor
> +    of the other changes."""
> +    success, status = _imergeauto(localorother='other', *args, **kwargs)
> +    return success, status
> +
>  @internaltool('tagmerge', True,
>                _("automatic tag merging of %s failed! "
>                  "(use 'hg resolve --tool :merge' or another merge "
> diff --git a/tests/test-conflict.t b/tests/test-conflict.t
> --- a/tests/test-conflict.t
> +++ b/tests/test-conflict.t
> @@ -232,3 +232,65 @@ internal:merge3
>    5
>    >>>>>>> other
>    Hop we are done.
> +
> +Add some unconflicting changes on each head, to make sure we really
> +are merging, unlike :local and :other
> +
> +  $ hg up -C
> +  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ printf "\n\nEnd of file\n" >> a
> +  $ hg ci -m "Add some stuff at the end"
> +  $ hg up -r 1
> +  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
> +  $ printf "Start of file\n\n\n" > tmp
> +  $ cat a >> tmp
> +  $ mv tmp a
> +  $ hg ci -m "Add some stuff at the beginning"
> +
> +Now test :merge-other and :merge-local
> +
> +  $ hg merge
> +  merging a
> +  warning: conflicts during merge.
> +  merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
> +  1 files updated, 0 files merged, 0 files removed, 1 files unresolved
> +  use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
> +  [1]
> +  $ hg resolve --tool :merge-other a
> +  merging a
> +  (no more unresolved files)
> +  $ cat a
> +  Start of file
> +
> +
> +  Small Mathematical Series.
> +  1
> +  2
> +  3
> +  6
> +  8
> +  Hop we are done.
> +
> +
> +  End of file
> +
> +  $ hg up -C
> +  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
> +  $ hg merge --tool :merge-local
> +  merging a
> +  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  (branch merge, don't forget to commit)
> +  $ cat a
> +  Start of file
> +
> +
> +  Small Mathematical Series.
> +  1
> +  2
> +  3
> +  4
> +  5
> +  Hop we are done.
> +
> +
> +  End of file
> diff --git a/tests/test-help.t b/tests/test-help.t
> --- a/tests/test-help.t
> +++ b/tests/test-help.t
> @@ -1220,6 +1220,14 @@ Test dynamic list of merge tools only sh
>          partially merged file. Markers will have two sections, one for each side
>          of merge.
>
> +      ":merge-local"
> +        Like :merge, but resolve all conflicts non-interactively in favor of the
> +        local changes.
> +
> +      ":merge-other"
> +        Like :merge, but resolve all conflicts non-interactively in favor of the
> +        other changes.
> +
>        ":merge3"
>          Uses the internal non-interactive simple merge algorithm for merging
>          files. It will fail if there are any conflicts and leave markers in the
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> https://selenic.com/mailman/listinfo/mercurial-devel

Patch

diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
--- a/mercurial/filemerge.py
+++ b/mercurial/filemerge.py
@@ -286,6 +286,38 @@  def _imerge3(repo, mynode, orig, fcd, fc
         labels.append('base')
     return _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels)
 
+def _imergeauto(repo, mynode, orig, fcd, fco, fca, toolconf, files,
+                labels=None, localorother=None):
+    """
+    Generic driver for _imergelocal and _imergeother
+    """
+    assert localorother is not None
+    tool, toolpath, binary, symlink = toolconf
+    if symlink:
+        repo.ui.warn(_('warning: :merge-%s cannot merge symlinks '
+                       'for %s\n') % (localorother, fcd.path()))
+        return False, 1
+    a, b, c, back = files
+    r = simplemerge.simplemerge(repo.ui, a, b, c, label=labels,
+                                localorother=localorother)
+    return True, r
+
+@internaltool('merge-local', True)
+def _imergelocal(*args, **kwargs):
+    """
+    Like :merge, but resolve all conflicts non-interactively in favor
+    of the local changes."""
+    success, status = _imergeauto(localorother='local', *args, **kwargs)
+    return success, status
+
+@internaltool('merge-other', True)
+def _imergeother(*args, **kwargs):
+    """
+    Like :merge, but resolve all conflicts non-interactively in favor
+    of the other changes."""
+    success, status = _imergeauto(localorother='other', *args, **kwargs)
+    return success, status
+
 @internaltool('tagmerge', True,
               _("automatic tag merging of %s failed! "
                 "(use 'hg resolve --tool :merge' or another merge "
diff --git a/tests/test-conflict.t b/tests/test-conflict.t
--- a/tests/test-conflict.t
+++ b/tests/test-conflict.t
@@ -232,3 +232,65 @@  internal:merge3
   5
   >>>>>>> other
   Hop we are done.
+
+Add some unconflicting changes on each head, to make sure we really
+are merging, unlike :local and :other
+
+  $ hg up -C
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ printf "\n\nEnd of file\n" >> a
+  $ hg ci -m "Add some stuff at the end"
+  $ hg up -r 1
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ printf "Start of file\n\n\n" > tmp
+  $ cat a >> tmp
+  $ mv tmp a
+  $ hg ci -m "Add some stuff at the beginning"
+
+Now test :merge-other and :merge-local
+
+  $ hg merge
+  merging a
+  warning: conflicts during merge.
+  merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
+  1 files updated, 0 files merged, 0 files removed, 1 files unresolved
+  use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
+  [1]
+  $ hg resolve --tool :merge-other a
+  merging a
+  (no more unresolved files)
+  $ cat a
+  Start of file
+  
+  
+  Small Mathematical Series.
+  1
+  2
+  3
+  6
+  8
+  Hop we are done.
+  
+  
+  End of file
+
+  $ hg up -C
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg merge --tool :merge-local
+  merging a
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ cat a
+  Start of file
+  
+  
+  Small Mathematical Series.
+  1
+  2
+  3
+  4
+  5
+  Hop we are done.
+  
+  
+  End of file
diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -1220,6 +1220,14 @@  Test dynamic list of merge tools only sh
         partially merged file. Markers will have two sections, one for each side
         of merge.
   
+      ":merge-local"
+        Like :merge, but resolve all conflicts non-interactively in favor of the
+        local changes.
+  
+      ":merge-other"
+        Like :merge, but resolve all conflicts non-interactively in favor of the
+        other changes.
+  
       ":merge3"
         Uses the internal non-interactive simple merge algorithm for merging
         files. It will fail if there are any conflicts and leave markers in the