From: David Kågedal <davidk@xxxxxxxxxxxxxx> This only prepares for later simplifications. Signed-off-by: David Kågedal <davidk@xxxxxxxxxxxxxx> Signed-off-by: Karl Hasselström <kha@xxxxxxxxxxx> --- stgit/commands/pick.py | 2 + stgit/git.py | 92 +++++++++++++++++++++++++++++++++++++----------- stgit/stack.py | 2 + 3 files changed, 73 insertions(+), 23 deletions(-) diff --git a/stgit/commands/pick.py b/stgit/commands/pick.py index 1c3ef11..871879c 100644 --- a/stgit/commands/pick.py +++ b/stgit/commands/pick.py @@ -99,7 +99,7 @@ def func(parser, options, args): # try a direct git-apply first if not git.apply_diff(bottom, top): - git.merge(bottom, git.get_head(), top, recursive = True) + git.merge_recursive(bottom, git.get_head(), top) out.done() elif options.update: diff --git a/stgit/git.py b/stgit/git.py index 7962cdb..87551ee 100644 --- a/stgit/git.py +++ b/stgit/git.py @@ -634,36 +634,86 @@ def apply_diff(rev1, rev2, check_index = True, files = None): return True -def merge(base, head1, head2, recursive = False): +stages_re = re.compile('^([0-7]+) ([0-9a-f]{40}) ([1-3])\t(.*)$', re.S) + +def merge_recursive(base, head1, head2): """Perform a 3-way merge between base, head1 and head2 into the local tree """ refresh_index() err_output = None - if recursive: - # this operation tracks renames but it is slower (used in - # general when pushing or picking patches) - try: - # discard output to mask the verbose prints of the tool - GRun('git-merge-recursive', base, '--', head1, head2 - ).discard_output() - except GitRunException, ex: - err_output = str(ex) - pass - else: - # the fast case where we don't track renames (used when the - # distance between base and heads is small, i.e. folding or - # synchronising patches) - try: - GRun('git-read-tree', '-u', '-m', '--aggressive', - base, head1, head2).run() - except GitRunException: - raise GitException, 'git-read-tree failed (local changes maybe?)' + # this operation tracks renames but it is slower (used in + # general when pushing or picking patches) + try: + # discard output to mask the verbose prints of the tool + GRun('git-merge-recursive', base, '--', head1, head2).discard_output() + except GitRunException, ex: + err_output = str(ex) + pass + + # check the index for unmerged entries + files = {} + + for line in GRun('git-ls-files', '--unmerged', '--stage', '-z' + ).raw_output().split('\0'): + if not line: + continue + + mode, hash, stage, path = stages_re.findall(line)[0] + + if not path in files: + files[path] = {} + files[path]['1'] = ('', '') + files[path]['2'] = ('', '') + files[path]['3'] = ('', '') + + files[path][stage] = (mode, hash) + + if err_output and not files: + # if no unmerged files, there was probably a different type of + # error and we have to abort the merge + raise GitException, err_output + + # merge the unmerged files + errors = False + for path in files: + # remove additional files that might be generated for some + # newer versions of GIT + for suffix in [base, head1, head2]: + if not suffix: + continue + fname = path + '~' + suffix + if os.path.exists(fname): + os.remove(fname) + + stages = files[path] + if gitmergeonefile.merge(stages['1'][1], stages['2'][1], + stages['3'][1], path, stages['1'][0], + stages['2'][0], stages['3'][0]) != 0: + errors = True + + if errors: + raise GitException, 'GIT index merging failed (possible conflicts)' + +def merge(base, head1, head2): + """Perform a 3-way merge between base, head1 and head2 into the + local tree + """ + refresh_index() + + err_output = None + # the fast case where we don't track renames (used when the + # distance between base and heads is small, i.e. folding or + # synchronising patches) + try: + GRun('git-read-tree', '-u', '-m', '--aggressive', base, head1, head2 + ).run() + except GitRunException: + raise GitException, 'git-read-tree failed (local changes maybe?)' # check the index for unmerged entries files = {} - stages_re = re.compile('^([0-7]+) ([0-9a-f]{40}) ([1-3])\t(.*)$', re.S) for line in GRun('git-ls-files', '--unmerged', '--stage', '-z' ).raw_output().split('\0'): diff --git a/stgit/stack.py b/stgit/stack.py index 12c5091..a82392f 100644 --- a/stgit/stack.py +++ b/stgit/stack.py @@ -1066,7 +1066,7 @@ class Series(PatchSet): # merge can fail but the patch needs to be pushed try: - git.merge(bottom, head, top, recursive = True) + git.merge_recursive(bottom, head, top) except git.GitException, ex: out.error('The merge failed during "push".', 'Use "refresh" after fixing the conflicts or' - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html