Add option to automatically invoke the interactive merger
authorCatalin Marinas <catalin.marinas@gmail.com>
Wed, 10 Jan 2007 19:38:26 +0000 (19:38 +0000)
committerCatalin Marinas <catalin.marinas@gmail.com>
Wed, 10 Jan 2007 19:38:26 +0000 (19:38 +0000)
The 'autoimerge' option was added (defaulting to 'no') to
automatically invoke the interactive merging tool when a conflict
occurs.

Signed-off-by: Catalin Marinas <catalin.marinas@gmail.com>
examples/gitconfig
stgit/commands/resolved.py
stgit/config.py
stgit/gitmergeonefile.py

index 0c0555a..5e7b240 100644 (file)
@@ -50,6 +50,9 @@
        #imerger = emacs --eval '(ediff-merge-files-with-ancestor \
        #       "%(branch1)s" "%(branch2)s" "%(ancestor)s" nil "%(output)s")'
 
+       # Automatically invoke the interactive merger in case of conflicts
+       #autoimerge = no
+
        # Leave the original files in the working tree in case of a
        # merge conflict
        #keeporig = yes
index ae85f2b..1130641 100644 (file)
@@ -23,6 +23,7 @@ from stgit.commands.common import *
 from stgit.utils import *
 from stgit import stack, git, basedir
 from stgit.config import config, file_extensions
+from stgit.gitmergeonefile import interactive_merge
 
 
 help = 'mark a file conflict as solved'
@@ -42,40 +43,6 @@ options = [make_option('-a', '--all',
                        help = 'run the interactive merging tool',
                        action = 'store_true')]
 
-def interactive_merge(filename):
-    """Run the interactive merger on the given file
-    """
-    try:
-        imerger = config.get('stgit', 'imerger')
-    except Exception, err:
-        raise CmdException, 'Configuration error: %s' % err
-
-    extensions = file_extensions()
-
-    ancestor = filename + extensions['ancestor']
-    current = filename + extensions['current']
-    patched = filename + extensions['patched']
-
-    # check whether we have all the files for a three-way merge
-    for fn in [filename, ancestor, current, patched]:
-        if not os.path.isfile(fn):
-            raise CmdException, \
-                  'Cannot run the interactive merger: "%s" missing' % fn
-
-    mtime = os.path.getmtime(filename)
-
-    err = os.system(imerger % {'branch1': current,
-                               'ancestor': ancestor,
-                               'branch2': patched,
-                               'output': filename})
-
-    if err != 0:
-        raise CmdException, 'The interactive merger failed: %d' % err
-    if not os.path.isfile(filename):
-        raise CmdException, 'The "%s" file is missing' % filename
-    if mtime == os.path.getmtime(filename):
-        raise CmdException, 'The "%s" file was not modified' % filename
-
 def func(parser, options, args):
     """Mark the conflict as resolved
     """
index 2174f09..f5fbdab 100644 (file)
@@ -69,6 +69,7 @@ def config_setup():
     config.set('stgit', 'merger',
                'diff3 -L current -L ancestor -L patched -m -E ' \
                '"%(branch1)s" "%(ancestor)s" "%(branch2)s" > "%(output)s"')
+    config.set('stgit', 'autoimerge', 'no')
     config.set('stgit', 'keeporig', 'yes')
     config.set('stgit', 'keepoptimized', 'no')
     config.set('stgit', 'extensions', '.ancestor .current .patched')
index a8dc2a8..200448b 100644 (file)
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
 import sys, os
 from stgit import basedir
-from stgit.config import file_extensions, ConfigOption
+from stgit.config import config, file_extensions, ConfigOption
 from stgit.utils import append_string
 
 
@@ -98,6 +98,42 @@ def __conflict(path):
     append_string(os.path.join(basedir.get(), 'conflicts'), path)
 
 
+def interactive_merge(filename):
+    """Run the interactive merger on the given file. Note that the
+    index should not have any conflicts.
+    """
+    try:
+        imerger = config.get('stgit', 'imerger')
+    except Exception, err:
+        raise GitMergeException, 'Configuration error: %s' % err
+
+    extensions = file_extensions()
+
+    ancestor = filename + extensions['ancestor']
+    current = filename + extensions['current']
+    patched = filename + extensions['patched']
+
+    # check whether we have all the files for a three-way merge
+    for fn in [filename, ancestor, current, patched]:
+        if not os.path.isfile(fn):
+            raise GitMergeException, \
+                  'Cannot run the interactive merger: "%s" missing' % fn
+
+    mtime = os.path.getmtime(filename)
+
+    err = os.system(imerger % {'branch1': current,
+                               'ancestor': ancestor,
+                               'branch2': patched,
+                               'output': filename})
+
+    if err != 0:
+        raise GitMergeException, 'The interactive merge failed: %d' % err
+    if not os.path.isfile(filename):
+        raise GitMergeException, 'The "%s" file is missing' % filename
+    if mtime == os.path.getmtime(filename):
+        raise GitMergeException, 'The "%s" file was not modified' % filename
+
+
 #
 # Main algorithm
 #
@@ -148,10 +184,30 @@ def merge(orig_hash, file1_hash, file2_hash,
                     # reset the cache to the first branch
                     os.system('git-update-index --cacheinfo %s %s %s'
                               % (file1_mode, file1_hash, path))
-                    if str(keeporig) != 'yes':
+
+                    if config.get('stgit', 'autoimerge') == 'yes':
+                        print >> sys.stderr, \
+                              'Trying the interactive merge'
+                        try:
+                            interactive_merge(path)
+                        except GitMergeException, ex:
+                            # interactive merge failed
+                            print >> sys.stderr, str(ex)
+                            if str(keeporig) != 'yes':
+                                __remove_files(orig_hash, file1_hash,
+                                               file2_hash)
+                            __conflict(path)
+                            return 1
+                        # successful interactive merge
                         __remove_files(orig_hash, file1_hash, file2_hash)
-                    __conflict(path)
-                    return 1
+                        return 0
+                    else:
+                        # no interactive merge, just mark it as conflict
+                        if str(keeporig) != 'yes':
+                            __remove_files(orig_hash, file1_hash, file2_hash)
+                        __conflict(path)
+                        return 1
+
         # file deleted in both or deleted in one and unchanged in the other
         elif not (file1_hash or file2_hash) \
                or file1_hash == orig_hash or file2_hash == orig_hash: