Show changes to 6 files +20 −191
examples/gitconfig, stgit/commands/resolved.py, stgit/config.py, stgit/git.py, stgit/gitmergeonefile.py, t/t0002-status.sh
diff --git a/examples/gitconfig b/examples/gitconfig
index 2fc5f52..f6e3a79 100644
--- a/examples/gitconfig
+++ b/examples/gitconfig
@@ -64,27 +64,10 @@
# To support local parent branches:
#pull-policy = rebase
- # Interactive two/three-way merge tool. It is executed by the
- # 'resolved --interactive' command
- #i3merge = xxdiff --title1 current --title2 ancestor --title3 patched \
- # --show-merged-pane -m -E -O -X -M \"%(output)s\" \
- # \"%(branch1)s\" \"%(ancestor)s\" \"%(branch2)s\"
- #i2merge = xxdiff --title1 current --title2 patched \
- # --show-merged-pane -m -E -O -X -M \"%(output)s\" \
- # \"%(branch1)s\" \"%(branch2)s\"
- #i3merge = emacs --eval '(ediff-merge-files-with-ancestor \
- # \"%(branch1)s\" \"%(branch2)s\" \"%(ancestor)s\" nil \
- # \"%(output)s\")'
- #i2merge = emacs --eval '(ediff-merge-files \
- # \"%(branch1)s\" \"%(branch2)s\" nil \"%(output)s\")'
-
- # Automatically invoke the interactive merger in case of conflicts
+ # Automatically invoke the interactive merger (git mergetool) in case
+ # of conflicts
#autoimerge = no
- # Leave the original files in the working tree in case of a
- # merge conflict
- #keeporig = yes
-
# Optimize (repack) the object store after every pull
#keepoptimized = yes
diff --git a/stgit/commands/resolved.py b/stgit/commands/resolved.py
index 2ce7ec3..eba778d 100644
--- a/stgit/commands/resolved.py
+++ b/stgit/commands/resolved.py
@@ -22,7 +22,6 @@ from stgit.commands.common import *
from stgit.utils import *
from stgit import argparse, stack, git, basedir
from stgit.config import config, file_extensions
-from stgit.gitmergeonefile import interactive_merge
help = 'Mark a file conflict as solved'
kind = 'wc'
@@ -78,8 +77,6 @@ def func(parser, options, args):
# resolved
if options.interactive:
- for filename in files:
- interactive_merge(filename)
- git.resolved([filename])
+ git.mergetool(files)
else:
git.resolved(files, options.reset)
diff --git a/stgit/config.py b/stgit/config.py
index 05ef624..efce097 100644
--- a/stgit/config.py
+++ b/stgit/config.py
@@ -35,7 +35,6 @@ class GitConfig:
'stgit.fetchcmd': 'git fetch',
'stgit.pull-policy': 'pull',
'stgit.autoimerge': 'no',
- 'stgit.keeporig': 'yes',
'stgit.keepoptimized': 'no',
'stgit.extensions': '.ancestor .current .patched',
'stgit.shortnr': '5'
diff --git a/stgit/git.py b/stgit/git.py
index 4d01fc2..cbdefe8 100644
--- a/stgit/git.py
+++ b/stgit/git.py
@@ -18,7 +18,7 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
-import sys, os, re, gitmergeonefile
+import sys, os, re
from shutil import copyfile
from stgit.exception import *
@@ -632,19 +632,23 @@ def merge_recursive(base, head1, head2):
output = p.output_lines()
if p.exitcode:
# There were conflicts
- conflicts = [l.strip() for l in output if l.startswith('CONFLICT')]
+ if config.get('stgit.autoimerge') == 'yes':
+ mergetool()
+ else:
+ conflicts = [l for l in output if l.startswith('CONFLICT')]
+ out.info(*conflicts)
+ raise GitException, "%d conflict(s)" % len(conflicts)
+
+def mergetool(files = ()):
+ """Invoke 'git mergetool' to resolve any outstanding conflicts. If 'not
+ files', all the files in an unmerged state will be processed."""
+ GRun('mergetool', *list(files)).returns([0, 1]).run()
+ # check for unmerged entries (prepend 'CONFLICT ' for consistency with
+ # merge_recursive())
+ conflicts = ['CONFLICT ' + f for f in get_conflicts()]
+ if conflicts:
out.info(*conflicts)
-
- # try the interactive merge or stage checkout (if enabled)
- for filename in get_conflicts():
- if (gitmergeonefile.merge(filename)):
- # interactive merge succeeded
- resolved([filename])
-
- # any conflicts left unsolved?
- cn = len(get_conflicts())
- if cn:
- raise GitException, "%d conflict(s)" % cn
+ raise GitException, "%d conflict(s)" % len(conflicts)
def diff(files = None, rev1 = 'HEAD', rev2 = None, diff_flags = [],
binary = True):
@@ -754,7 +758,6 @@ def resolved(filenames, reset = None):
'--stdin', '-z').input_nulterm(filenames).no_output()
GRun('update-index', '--add', '--').xargs(filenames)
for filename in filenames:
- gitmergeonefile.clean_up(filename)
# update the access and modificatied times
os.utime(filename, None)
diff --git a/stgit/gitmergeonefile.py b/stgit/gitmergeonefile.py
deleted file mode 100644
index 1fe226e..0000000
--- a/stgit/gitmergeonefile.py
+++ /dev/null
@@ -1,150 +0,0 @@
-"""Performs a 3-way merge for GIT files
-"""
-
-__copyright__ = """
-Copyright (C) 2006, Catalin Marinas <catalin.marinas@gmail.com>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License version 2 as
-published by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-"""
-
-import sys, os
-from stgit.exception import *
-from stgit import basedir
-from stgit.config import config, file_extensions, ConfigOption
-from stgit.utils import append_string
-from stgit.out import *
-from stgit.run import *
-
-class GitMergeException(StgException):
- pass
-
-
-#
-# Options
-#
-autoimerge = ConfigOption('stgit', 'autoimerge')
-keeporig = ConfigOption('stgit', 'keeporig')
-
-#
-# Utility functions
-#
-def __str2none(x):
- if x == '':
- return None
- else:
- return x
-
-class MRun(Run):
- exc = GitMergeException # use a custom exception class on errors
-
-def __checkout_stages(filename):
- """Check-out the merge stages in the index for the give file
- """
- extensions = file_extensions()
- line = MRun('git', 'checkout-index', '--stage=all', '--', filename
- ).output_one_line()
- stages, path = line.split('\t')
- stages = dict(zip(['ancestor', 'current', 'patched'],
- stages.split(' ')))
-
- for stage, fn in stages.iteritems():
- if stages[stage] == '.':
- stages[stage] = None
- else:
- newname = filename + extensions[stage]
- if os.path.exists(newname):
- # remove the stage if it is already checked out
- os.remove(newname)
- os.rename(stages[stage], newname)
- stages[stage] = newname
-
- return stages
-
-def __remove_stages(filename):
- """Remove the merge stages from the working directory
- """
- extensions = file_extensions()
- for ext in extensions.itervalues():
- fn = filename + ext
- if os.path.isfile(fn):
- os.remove(fn)
-
-def interactive_merge(filename):
- """Run the interactive merger on the given file. Stages will be
- removed according to stgit.keeporig. If successful and stages
- kept, they will be removed via git.resolved().
- """
- stages = __checkout_stages(filename)
-
- try:
- # Check whether we have all the files for the merge.
- if not (stages['current'] and stages['patched']):
- raise GitMergeException('Cannot run the interactive merge')
-
- if stages['ancestor']:
- three_way = True
- files_dict = {'branch1': stages['current'],
- 'ancestor': stages['ancestor'],
- 'branch2': stages['patched'],
- 'output': filename}
- imerger = config.get('stgit.i3merge')
- else:
- three_way = False
- files_dict = {'branch1': stages['current'],
- 'branch2': stages['patched'],
- 'output': filename}
- imerger = config.get('stgit.i2merge')
-
- if not imerger:
- raise GitMergeException, 'No interactive merge command configured'
-
- mtime = os.path.getmtime(filename)
-
- out.start('Trying the interactive %s merge'
- % (three_way and 'three-way' or 'two-way'))
- err = os.system(imerger % files_dict)
- out.done()
- if err != 0:
- raise GitMergeException, 'The interactive merge failed'
- 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
- finally:
- # keep the merge stages?
- if str(keeporig) != 'yes':
- __remove_stages(filename)
-
-def clean_up(filename):
- """Remove merge conflict stages if they were generated.
- """
- if str(keeporig) == 'yes':
- __remove_stages(filename)
-
-def merge(filename):
- """Merge one file if interactive is allowed or check out the stages
- if keeporig is set.
- """
- if str(autoimerge) == 'yes':
- try:
- interactive_merge(filename)
- except GitMergeException, ex:
- out.error(str(ex))
- return False
- return True
-
- if str(keeporig) == 'yes':
- __checkout_stages(filename)
-
- return False
diff --git a/t/t0002-status.sh b/t/t0002-status.sh
index ac92aa8..d95a83b 100755
--- a/t/t0002-status.sh
+++ b/t/t0002-status.sh
@@ -107,9 +107,6 @@ test_expect_success 'Make a conflicting patch' '
'
cat > expected.txt <<EOF
-? foo/bar.ancestor
-? foo/bar.current
-? foo/bar.patched
A fie
C foo/bar
EOF