# 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
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 *
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):
'--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)
+++ /dev/null
-"""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