* [StGit PATCH 0/6] Use git conflict handling on push @ 2007-08-20 8:11 David Kågedal 2007-08-20 8:11 ` [StGit PATCH 1/6] Split git.merge into two functions David Kågedal ` (2 more replies) 0 siblings, 3 replies; 19+ messages in thread From: David Kågedal @ 2007-08-20 8:11 UTC (permalink / raw) To: catalin.marinas, git; +Cc: David Kågedal This series of patches updates "stg push" to leave conflicts in the index, in the normal git fashion. This means that conflict handling and resolution are handled by git and not stg, which should make it possible to simplify stg quite a bit. For instance, the 'conflicts' file should go away. Unfortunately, this patch series isn't complete, since it doesn't remove all uses of the stg merge code. The remaining client of that code is the "sync" command, which I have never used, and haven't studied very much. But if that command is changed somehow, then most of the code in gitmergeonefile.py will go simply away. And the 'conflicts' file will not be used. See also previous discussions: https://gna.org/task/?5140 http://thread.gmane.org/gmane.comp.version-control.git/48271 -- David KÃ¥gedal ^ permalink raw reply [flat|nested] 19+ messages in thread
* [StGit PATCH 1/6] Split git.merge into two functions 2007-08-20 8:11 [StGit PATCH 0/6] Use git conflict handling on push David Kågedal @ 2007-08-20 8:11 ` David Kågedal 2007-08-20 8:11 ` [StGit PATCH 2/6] Don't try to merge files that merge-recursive already merged David Kågedal 2007-08-20 8:55 ` [StGit PATCH 1/6] Split git.merge into two functions David Kågedal 2007-08-22 9:17 ` [StGit PATCH 0/6] Use git conflict handling on push Karl Hasselström 2007-08-23 14:54 ` Catalin Marinas 2 siblings, 2 replies; 19+ messages in thread From: David Kågedal @ 2007-08-20 8:11 UTC (permalink / raw) To: catalin.marinas, git; +Cc: David Kågedal From: David KÃ¥gedal <davidk@lysator.liu.se> This only prepares for later simplifications. Signed-off-by: David KÃ¥gedal <davidk@lysator.liu.se> --- stgit/commands/pick.py | 2 +- stgit/git.py | 86 ++++++++++++++++++++++++++++++++++++++---------- stgit/stack.py | 2 +- 3 files changed, 70 insertions(+), 20 deletions(-) diff --git a/stgit/commands/pick.py b/stgit/commands/pick.py index 27fdf9c..9913e63 100644 --- a/stgit/commands/pick.py +++ b/stgit/commands/pick.py @@ -98,7 +98,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 72bf889..9d8da5d 100644 --- a/stgit/git.py +++ b/stgit/git.py @@ -667,33 +667,83 @@ 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: - # use _output() to mask the verbose prints of the tool - _output(['git-merge-recursive', base, '--', head1, head2]) - except GitException, 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) - if __run('git-read-tree -u -m --aggressive', - [base, head1, head2]) != 0: - 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: + # use _output() to mask the verbose prints of the tool + _output(['git-merge-recursive', base, '--', head1, head2]) + except GitException, ex: + err_output = str(ex) + pass + + # check the index for unmerged entries + files = {} + + for line in _output(['git-ls-files', '--unmerged', '--stage', '-z']).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) + if __run('git-read-tree -u -m --aggressive', + [base, head1, head2]) != 0: + 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 _output(['git-ls-files', '--unmerged', '--stage', '-z']).split('\0'): if not line: diff --git a/stgit/stack.py b/stgit/stack.py index dbd7ea4..8b77943 100644 --- a/stgit/stack.py +++ b/stgit/stack.py @@ -1061,7 +1061,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' -- 1.5.3.rc3.119.g1812 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* [StGit PATCH 2/6] Don't try to merge files that merge-recursive already merged 2007-08-20 8:11 ` [StGit PATCH 1/6] Split git.merge into two functions David Kågedal @ 2007-08-20 8:11 ` David Kågedal 2007-08-20 8:12 ` [StGit PATCH 3/6] Don't touch state after conflict in push David Kågedal 2007-08-22 9:21 ` [StGit PATCH 2/6] Don't try to merge files that merge-recursive already merged Karl Hasselström 2007-08-20 8:55 ` [StGit PATCH 1/6] Split git.merge into two functions David Kågedal 1 sibling, 2 replies; 19+ messages in thread From: David Kågedal @ 2007-08-20 8:11 UTC (permalink / raw) To: catalin.marinas, git; +Cc: David Kågedal From: David KÃ¥gedal <davidk@lysator.liu.se> This avoid duplicating work, but also changes the resulting index state so that the conflicts are left in the index in the three stages. Signed-off-by: David KÃ¥gedal <davidk@lysator.liu.se> --- stgit/git.py | 20 +------------------- 1 files changed, 1 insertions(+), 19 deletions(-) diff --git a/stgit/git.py b/stgit/git.py index 9d8da5d..5e1548c 100644 --- a/stgit/git.py +++ b/stgit/git.py @@ -707,25 +707,7 @@ def merge_recursive(base, head1, head2): # 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: + if files: raise GitException, 'GIT index merging failed (possible conflicts)' def merge(base, head1, head2): -- 1.5.3.rc3.119.g1812 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* [StGit PATCH 3/6] Don't touch state after conflict in push 2007-08-20 8:11 ` [StGit PATCH 2/6] Don't try to merge files that merge-recursive already merged David Kågedal @ 2007-08-20 8:12 ` David Kågedal 2007-08-20 8:12 ` [StGit PATCH 4/6] Added a test case to check what happens when push finds a conflict David Kågedal 2007-08-22 9:21 ` [StGit PATCH 2/6] Don't try to merge files that merge-recursive already merged Karl Hasselström 1 sibling, 1 reply; 19+ messages in thread From: David Kågedal @ 2007-08-20 8:12 UTC (permalink / raw) To: catalin.marinas, git; +Cc: David Kågedal From: David KÃ¥gedal <davidk@lysator.liu.se> This leaves the index and working tree in the state that merge-recursive left it, with unmerged files in different stages, and the non-conflicting changes in the index. Signed-off-by: David KÃ¥gedal <davidk@lysator.liu.se> --- stgit/stack.py | 17 ++++++++++++----- 1 files changed, 12 insertions(+), 5 deletions(-) diff --git a/stgit/stack.py b/stgit/stack.py index 8b77943..0e43f75 100644 --- a/stgit/stack.py +++ b/stgit/stack.py @@ -728,6 +728,7 @@ class Series(PatchSet): config.unset(self.format_version_key()) def refresh_patch(self, files = None, message = None, edit = False, + empty = False, show_patch = False, cache_update = True, author_name = None, author_email = None, @@ -777,9 +778,16 @@ class Series(PatchSet): bottom = patch.get_bottom() + if empty: + tree_id = git.get_commit(bottom).get_tree() + else: + tree_id = None + commit_id = git.commit(files = files, message = descr, parents = [bottom], cache_update = cache_update, + tree_id = tree_id, + set_head = True, allowempty = True, author_name = author_name, author_email = author_email, @@ -1083,11 +1091,10 @@ class Series(PatchSet): log = 'push' self.refresh_patch(cache_update = False, log = log) else: - # we store the correctly merged files only for - # tracking the conflict history. Note that the - # git.merge() operations should always leave the index - # in a valid state (i.e. only stage 0 files) - self.refresh_patch(cache_update = False, log = 'push(c)') + # we make the patch empty, with the merged state in + # the working tree. + self.refresh_patch(cache_update = False, empty = True, + log = 'push(c)') raise StackException, str(ex) return modified -- 1.5.3.rc3.119.g1812 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* [StGit PATCH 4/6] Added a test case to check what happens when push finds a conflict 2007-08-20 8:12 ` [StGit PATCH 3/6] Don't touch state after conflict in push David Kågedal @ 2007-08-20 8:12 ` David Kågedal 2007-08-20 8:12 ` [StGit PATCH 5/6] Simplify merge_recursive David Kågedal 0 siblings, 1 reply; 19+ messages in thread From: David Kågedal @ 2007-08-20 8:12 UTC (permalink / raw) To: catalin.marinas, git; +Cc: David Kågedal From: David KÃ¥gedal <davidk@lysator.liu.se> Signed-off-by: David KÃ¥gedal <davidk@lysator.liu.se> --- t/t1203-push-conflict.sh | 64 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 64 insertions(+), 0 deletions(-) diff --git a/t/t1203-push-conflict.sh b/t/t1203-push-conflict.sh new file mode 100755 index 0000000..57fb477 --- /dev/null +++ b/t/t1203-push-conflict.sh @@ -0,0 +1,64 @@ +#!/bin/sh +# +# Copyright (c) 2006 David KÃ¥gedal +# + +test_description='Exercise push conflicts. + +Test that the index has no modifications after a push with conflicts. +' + +. ./test-lib.sh + +test_expect_success \ + 'Initialize the StGIT repository' \ + 'stg init +' + +test_expect_success \ + 'Create the first patch' \ + ' + stg new foo -m foo && + echo foo > test && + echo fie > test2 && + stg add test test2 && + stg refresh && + stg pop + ' + +test_expect_success \ + 'Create the second patch' \ + ' + stg new bar -m bar && + echo bar > test && + stg add test && + stg refresh + ' + +test_expect_failure \ + 'Push the first patch with conflict' \ + ' + stg push foo + ' + +test_expect_failure \ + 'Show the, now empty, first patch' \ + ' + stg show foo | grep -q -e "^diff " + ' + +test_expect_success \ + 'Check that the index has the non-conflict updates' \ + ' + git diff --cached --stat | grep -q -e "^ test2 | *1 " + ' + +test_expect_success \ + 'Resolve the conflict' \ + ' + echo resolved > test && + git add test && + stg refresh + ' + +test_done -- 1.5.3.rc3.119.g1812 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* [StGit PATCH 5/6] Simplify merge_recursive 2007-08-20 8:12 ` [StGit PATCH 4/6] Added a test case to check what happens when push finds a conflict David Kågedal @ 2007-08-20 8:12 ` David Kågedal 2007-08-20 8:12 ` [StGit PATCH 6/6] Use the output from merge-recursive to list conflicts David Kågedal 0 siblings, 1 reply; 19+ messages in thread From: David Kågedal @ 2007-08-20 8:12 UTC (permalink / raw) To: catalin.marinas, git; +Cc: David Kågedal From: David KÃ¥gedal <davidk@lysator.liu.se> Listing the unmerged files is unnecessary, since the information isn't really used anyway. Just note if the merge failed or succeeded. Signed-off-by: David KÃ¥gedal <davidk@lysator.liu.se> --- stgit/git.py | 33 ++------------------------------- 1 files changed, 2 insertions(+), 31 deletions(-) diff --git a/stgit/git.py b/stgit/git.py index 5e1548c..63798bd 100644 --- a/stgit/git.py +++ b/stgit/git.py @@ -675,39 +675,10 @@ def merge_recursive(base, head1, head2): """ refresh_index() - err_output = None - # this operation tracks renames but it is slower (used in - # general when pushing or picking patches) + # use _output() to mask the verbose prints of the tool try: - # use _output() to mask the verbose prints of the tool _output(['git-merge-recursive', base, '--', head1, head2]) - except GitException, ex: - err_output = str(ex) - pass - - # check the index for unmerged entries - files = {} - - for line in _output(['git-ls-files', '--unmerged', '--stage', '-z']).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 - - if files: + except GitException: raise GitException, 'GIT index merging failed (possible conflicts)' def merge(base, head1, head2): -- 1.5.3.rc3.119.g1812 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* [StGit PATCH 6/6] Use the output from merge-recursive to list conflicts 2007-08-20 8:12 ` [StGit PATCH 5/6] Simplify merge_recursive David Kågedal @ 2007-08-20 8:12 ` David Kågedal 0 siblings, 0 replies; 19+ messages in thread From: David Kågedal @ 2007-08-20 8:12 UTC (permalink / raw) To: catalin.marinas, git; +Cc: David Kågedal From: David KÃ¥gedal <davidk@lysator.liu.se> merge-recursive already has useful information about what the conflicts were, so we reuse that when pushing. Signed-off-by: David KÃ¥gedal <davidk@lysator.liu.se> --- stgit/git.py | 27 +++++++++++++++++++++------ stgit/stack.py | 2 ++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/stgit/git.py b/stgit/git.py index 63798bd..59423ab 100644 --- a/stgit/git.py +++ b/stgit/git.py @@ -30,7 +30,14 @@ from sets import Set class GitException(Exception): pass - +class GitConflictException(GitException): + def __init__(self, conflicts): + GitException.__init__(self) + self.conflicts = conflicts + def __str__(self): + return "%d conflicts" % len(self.conflicts) + def list(self): + out.info(*self.conflicts) # # Classes @@ -675,11 +682,19 @@ def merge_recursive(base, head1, head2): """ refresh_index() - # use _output() to mask the verbose prints of the tool - try: - _output(['git-merge-recursive', base, '--', head1, head2]) - except GitException: - raise GitException, 'GIT index merging failed (possible conflicts)' + # Duplicate _output(), since we need the exit status + p=popen2.Popen3(['git-merge-recursive', base, '--', head1, head2], True) + output = p.fromchild.readlines() + st = p.wait() >> 8 + if st == 0: + # No problems + return + elif st == 1: + # There were conflicts + conflicts = [l.strip() for l in output if l.startswith('CONFLICT')] + raise GitConflictException(conflicts) + else: + raise GitException, 'git-merge-recursive failed (%s)' % (p.childerr.read().strip()) def merge(base, head1, head2): """Perform a 3-way merge between base, head1 and head2 into the diff --git a/stgit/stack.py b/stgit/stack.py index 0e43f75..3b06ca5 100644 --- a/stgit/stack.py +++ b/stgit/stack.py @@ -1070,6 +1070,8 @@ class Series(PatchSet): # merge can fail but the patch needs to be pushed try: git.merge_recursive(bottom, head, top) + except git.GitConflictException, ex: + ex.list() except git.GitException, ex: out.error('The merge failed during "push".', 'Use "refresh" after fixing the conflicts or' -- 1.5.3.rc3.119.g1812 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [StGit PATCH 2/6] Don't try to merge files that merge-recursive already merged 2007-08-20 8:11 ` [StGit PATCH 2/6] Don't try to merge files that merge-recursive already merged David Kågedal 2007-08-20 8:12 ` [StGit PATCH 3/6] Don't touch state after conflict in push David Kågedal @ 2007-08-22 9:21 ` Karl Hasselström 2007-08-22 9:37 ` David Kågedal 1 sibling, 1 reply; 19+ messages in thread From: Karl Hasselström @ 2007-08-22 9:21 UTC (permalink / raw) To: David Kågedal; +Cc: catalin.marinas, git On 2007-08-20 10:11:59 +0200, David Kågedal wrote: > This avoid duplicating work, but also changes the resulting index > state so that the conflicts are left in the index in the three > stages. After this patch, t1400-patch-history fails: * ok 1: Initialize the StGIT repository * ok 2: Create the first patch * ok 3: Create the second patch * ok 4: Check the "new" and "refresh" logs * ok 5: Check the log annotation * ok 6: Check the "push" log * ok 7: Check the "push(f)" log * ok 8: Check the "push(m)" log * FAIL 9: Check the "push(c)" log echo bar > test && stg refresh && stg pop && echo foo > test && stg refresh && ! stg push && stg log --full | grep -q -e "^push(c) " * ok 10: Check the push "undo" log * ok 11: Check the refresh "undo" log * failed 1 among 11 test(s) I'll see if I can figure out what's wrong. -- Karl Hasselström, kha@treskal.com www.treskal.com/kalle ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [StGit PATCH 2/6] Don't try to merge files that merge-recursive already merged 2007-08-22 9:21 ` [StGit PATCH 2/6] Don't try to merge files that merge-recursive already merged Karl Hasselström @ 2007-08-22 9:37 ` David Kågedal 2007-08-22 9:44 ` Karl Hasselström 0 siblings, 1 reply; 19+ messages in thread From: David Kågedal @ 2007-08-22 9:37 UTC (permalink / raw) To: Karl Hasselström; +Cc: git, catalin marinas Karl Hasselström <kha@treskal.com> writes: > On 2007-08-20 10:11:59 +0200, David Kågedal wrote: > >> This avoid duplicating work, but also changes the resulting index >> state so that the conflicts are left in the index in the three >> stages. > > After this patch, t1400-patch-history fails: I think that the push(c) commits will never happen with my patches, so the test case needs an update. > * ok 1: Initialize the StGIT repository > * ok 2: Create the first patch > * ok 3: Create the second patch > * ok 4: Check the "new" and "refresh" logs > * ok 5: Check the log annotation > * ok 6: Check the "push" log > * ok 7: Check the "push(f)" log > * ok 8: Check the "push(m)" log > * FAIL 9: Check the "push(c)" log > > echo bar > test && stg refresh && > stg pop && > echo foo > test && stg refresh && > ! stg push && > stg log --full | grep -q -e "^push(c) " > > * ok 10: Check the push "undo" log > * ok 11: Check the refresh "undo" log > * failed 1 among 11 test(s) > > I'll see if I can figure out what's wrong. -- David Kågedal ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [StGit PATCH 2/6] Don't try to merge files that merge-recursive already merged 2007-08-22 9:37 ` David Kågedal @ 2007-08-22 9:44 ` Karl Hasselström 2007-08-22 9:59 ` Karl Hasselström 0 siblings, 1 reply; 19+ messages in thread From: Karl Hasselström @ 2007-08-22 9:44 UTC (permalink / raw) To: David Kågedal; +Cc: git, catalin marinas On 2007-08-22 11:37:03 +0200, David Kågedal wrote: > Karl Hasselström <kha@treskal.com> writes: > > > On 2007-08-20 10:11:59 +0200, David Kågedal wrote: > > > > > This avoid duplicating work, but also changes the resulting > > > index state so that the conflicts are left in the index in the > > > three stages. > > > > After this patch, t1400-patch-history fails: > > I think that the push(c) commits will never happen with my patches, > so the test case needs an update. Actually, the failure vanishes once the next patch in the series is applied. I thought this was a good thing, but if they're never supposed to happen, maybe the test is still broken, just not in a way that's detected? -- Karl Hasselström, kha@treskal.com www.treskal.com/kalle ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [StGit PATCH 2/6] Don't try to merge files that merge-recursive already merged 2007-08-22 9:44 ` Karl Hasselström @ 2007-08-22 9:59 ` Karl Hasselström 2007-08-22 10:29 ` [StGIT PATCH] Leave working dir and index alone after failed (conflicting) push Karl Hasselström 0 siblings, 1 reply; 19+ messages in thread From: Karl Hasselström @ 2007-08-22 9:59 UTC (permalink / raw) To: David Kågedal; +Cc: git, catalin marinas On 2007-08-22 11:44:13 +0200, Karl Hasselström wrote: > On 2007-08-22 11:37:03 +0200, David Kågedal wrote: > > > I think that the push(c) commits will never happen with my > > patches, so the test case needs an update. > > Actually, the failure vanishes once the next patch in the series is > applied. I thought this was a good thing, but if they're never > supposed to happen, maybe the test is still broken, just not in a > way that's detected? No, after path 2 we don't get a push(c) entry, and the test fails, but after patch 3 we get it again and the test succeeds. Looking at the code (the string "push(c)" occurs exactly once, so it's easy to find), it seems the log stuff continues to work as expected after patch 3: it writes a "push(c)" entry when the patch becomes empty due to conflicts, and its entire contents are dumped in the wd (or the index+wd with your patches). So it is just patch 2 that needs fixing -- and I suspect the fix might be to merge it with patch 3. -- Karl Hasselström, kha@treskal.com www.treskal.com/kalle ^ permalink raw reply [flat|nested] 19+ messages in thread
* [StGIT PATCH] Leave working dir and index alone after failed (conflicting) push 2007-08-22 9:59 ` Karl Hasselström @ 2007-08-22 10:29 ` Karl Hasselström 0 siblings, 0 replies; 19+ messages in thread From: Karl Hasselström @ 2007-08-22 10:29 UTC (permalink / raw) To: Catalin Marinas, David Kågedal; +Cc: git From: David Kågedal <davidk@lysator.liu.se> This leaves the index and working tree in the state that merge-recursive left it, with unmerged files in different stages, and the non-conflicting changes in the index. Signed-off-by: David Kågedal <davidk@lysator.liu.se> Signed-off-by: Karl Hasselström <kha@treskal.com> --- This is David's patch 2 and 3 clumped together, so that there is no intermediate stage where the test suite fails. stgit/git.py | 20 +------------------- stgit/stack.py | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/stgit/git.py b/stgit/git.py index 170c5d1..676314a 100644 --- a/stgit/git.py +++ b/stgit/git.py @@ -723,25 +723,7 @@ def merge_recursive(base, head1, head2): # 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: + if files: raise GitException, 'GIT index merging failed (possible conflicts)' def merge(base, head1, head2): diff --git a/stgit/stack.py b/stgit/stack.py index 95f20f1..123efac 100644 --- a/stgit/stack.py +++ b/stgit/stack.py @@ -732,6 +732,7 @@ class Series(PatchSet): config.unset(self.format_version_key()) def refresh_patch(self, files = None, message = None, edit = False, + empty = False, show_patch = False, cache_update = True, author_name = None, author_email = None, @@ -781,9 +782,16 @@ class Series(PatchSet): bottom = patch.get_bottom() + if empty: + tree_id = git.get_commit(bottom).get_tree() + else: + tree_id = None + commit_id = git.commit(files = files, message = descr, parents = [bottom], cache_update = cache_update, + tree_id = tree_id, + set_head = True, allowempty = True, author_name = author_name, author_email = author_email, @@ -1086,11 +1094,11 @@ class Series(PatchSet): log = 'push' self.refresh_patch(cache_update = False, log = log) else: - # we store the correctly merged files only for - # tracking the conflict history. Note that the - # git.merge() operations should always leave the index - # in a valid state (i.e. only stage 0 files) - self.refresh_patch(cache_update = False, log = 'push(c)') + # We make the patch empty, with the merged state in + # the working tree and index just like after a failed + # git merge. + self.refresh_patch(cache_update = False, empty = True, + log = 'push(c)') raise StackException, str(ex) return modified ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [StGit PATCH 1/6] Split git.merge into two functions 2007-08-20 8:11 ` [StGit PATCH 1/6] Split git.merge into two functions David Kågedal 2007-08-20 8:11 ` [StGit PATCH 2/6] Don't try to merge files that merge-recursive already merged David Kågedal @ 2007-08-20 8:55 ` David Kågedal 2007-08-20 23:52 ` Junio C Hamano 1 sibling, 1 reply; 19+ messages in thread From: David Kågedal @ 2007-08-20 8:55 UTC (permalink / raw) To: git David Kågedal <davidk@lysator.liu.se> writes: > From: David KÃ¥gedal <davidk@lysator.liu.se> It seems that git-send-email didn't like me for some reason. Double UTF-8 encoding is not very pretty. I also got a number of these when running it: W: unable to extract a valid address from: David KÃ¥gedal <davidk@lysator.liu.se> W: unable to extract a valid address from: David KÃ¥gedal <davidk@lysator.liu.se> (the above was written in my latin1 xterm, so it wasn't double-encoded there) Is there a way to make send-email not add a "From:" header to the body of the message? The header already had the correct "From:" line. -- David Kågedal ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [StGit PATCH 1/6] Split git.merge into two functions 2007-08-20 8:55 ` [StGit PATCH 1/6] Split git.merge into two functions David Kågedal @ 2007-08-20 23:52 ` Junio C Hamano 2007-08-21 19:35 ` Uwe Kleine-König 0 siblings, 1 reply; 19+ messages in thread From: Junio C Hamano @ 2007-08-20 23:52 UTC (permalink / raw) To: David Kågedal; +Cc: git, ukleinek David Kågedal <davidk@lysator.liu.se> writes: > David Kågedal <davidk@lysator.liu.se> writes: > > It seems that git-send-email didn't like me for some reason. Double > UTF-8 encoding is not very pretty. I believe Uwe (CC'ed) had a few patches to deal with this area. Do they help? ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [StGit PATCH 1/6] Split git.merge into two functions 2007-08-20 23:52 ` Junio C Hamano @ 2007-08-21 19:35 ` Uwe Kleine-König 2007-08-22 10:04 ` Junio C Hamano 0 siblings, 1 reply; 19+ messages in thread From: Uwe Kleine-König @ 2007-08-21 19:35 UTC (permalink / raw) To: Junio C Hamano; +Cc: David Kågedal, git Hello David, Junio C Hamano wrote: > David Kågedal <davidk@lysator.liu.se> writes: > > > David Kågedal <davidk@lysator.liu.se> writes: > > > > It seems that git-send-email didn't like me for some reason. Double > > UTF-8 encoding is not very pretty. > > I believe Uwe (CC'ed) had a few patches to deal with this area. > Do they help? My patches are already in next, the relevant being probably v1.5.3-rc4-38-g94638f8. David, can you retry with a more recent version that includes that patch? And IIRC send-email expects the patch being encoded in UTF-8, but I'm not sure. If you could send me the patches you sent as a tar-ball or something similar, I can look into it. Best regards Uwe -- Uwe Kleine-König $ dc << EOF [d1-d1<a]sa99d1<a1[rdn555760928P*pz1<a]salax EOF ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [StGit PATCH 1/6] Split git.merge into two functions 2007-08-21 19:35 ` Uwe Kleine-König @ 2007-08-22 10:04 ` Junio C Hamano 0 siblings, 0 replies; 19+ messages in thread From: Junio C Hamano @ 2007-08-22 10:04 UTC (permalink / raw) To: Uwe Kleine-König; +Cc: David Kågedal, git Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de> writes: > Hello David, > > Junio C Hamano wrote: >> David Kågedal <davidk@lysator.liu.se> writes: >> >> > David Kågedal <davidk@lysator.liu.se> writes: >> > >> > It seems that git-send-email didn't like me for some reason. Double >> > UTF-8 encoding is not very pretty. >> >> I believe Uwe (CC'ed) had a few patches to deal with this area. >> Do they help? > > My patches are already in next, the relevant being probably > v1.5.3-rc4-38-g94638f8. It is in 'master' and in -rc5/-rc6. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [StGit PATCH 0/6] Use git conflict handling on push 2007-08-20 8:11 [StGit PATCH 0/6] Use git conflict handling on push David Kågedal 2007-08-20 8:11 ` [StGit PATCH 1/6] Split git.merge into two functions David Kågedal @ 2007-08-22 9:17 ` Karl Hasselström 2007-08-23 14:54 ` Catalin Marinas 2 siblings, 0 replies; 19+ messages in thread From: Karl Hasselström @ 2007-08-22 9:17 UTC (permalink / raw) To: David Kågedal; +Cc: catalin.marinas, git On 2007-08-20 10:11:57 +0200, David Kågedal wrote: > This series of patches updates "stg push" to leave conflicts in the > index, in the normal git fashion. Great initiative! This will make stg conceptually simpler to anyone who already knows git (which ought to be a large fraction of the user base), _and_ get rid of a lot of complicated code. -- Karl Hasselström, kha@treskal.com www.treskal.com/kalle ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [StGit PATCH 0/6] Use git conflict handling on push 2007-08-20 8:11 [StGit PATCH 0/6] Use git conflict handling on push David Kågedal 2007-08-20 8:11 ` [StGit PATCH 1/6] Split git.merge into two functions David Kågedal 2007-08-22 9:17 ` [StGit PATCH 0/6] Use git conflict handling on push Karl Hasselström @ 2007-08-23 14:54 ` Catalin Marinas 2 siblings, 0 replies; 19+ messages in thread From: Catalin Marinas @ 2007-08-23 14:54 UTC (permalink / raw) To: David Kågedal; +Cc: git On 20/08/07, David Kågedal <davidk@lysator.liu.se> wrote: > This series of patches updates "stg push" to leave conflicts in the > index, in the normal git fashion. Thanks for this series. I'll give it a try (importing it from the kha branch as it is easier) and check other issues it might break. > This means that conflict handling and resolution are handled by git > and not stg, which should make it possible to simplify stg quite a > bit. For instance, the 'conflicts' file should go away. Yes, indeed. > Unfortunately, this patch series isn't complete, since it doesn't > remove all uses of the stg merge code. The remaining client of that > code is the "sync" command, which I have never used, and haven't > studied very much. But if that command is changed somehow, then most > of the code in gitmergeonefile.py will go simply away. I still like to keep the interactive merging from that file. > https://gna.org/task/?5140 BTW, would you like to be added as a project member at gna.org/projects/stgit? Regards. -- Catalin ^ permalink raw reply [flat|nested] 19+ messages in thread
* [StGIT PATCH 0/6] David's conflict series using my subprocess stuff @ 2007-08-26 20:42 Karl Hasselström 2007-08-26 20:42 ` [StGIT PATCH 1/6] Split git.merge into two functions Karl Hasselström 0 siblings, 1 reply; 19+ messages in thread From: Karl Hasselström @ 2007-08-26 20:42 UTC (permalink / raw) To: Catalin Marinas, David Kågedal; +Cc: git This is David's conflict series, rebased on top of my subprocess calling series. There was one place where it used to have to call popen2.Popen3 directly, since none of our existing ten subprocess functions could do that particular job. But the new subprocess machinery can. (This was the original motivation for that refactoring, by the way.) -- Karl Hasselström, kha@treskal.com www.treskal.com/kalle ^ permalink raw reply [flat|nested] 19+ messages in thread
* [StGIT PATCH 1/6] Split git.merge into two functions 2007-08-26 20:42 [StGIT PATCH 0/6] David's conflict series using my subprocess stuff Karl Hasselström @ 2007-08-26 20:42 ` Karl Hasselström 0 siblings, 0 replies; 19+ messages in thread From: Karl Hasselström @ 2007-08-26 20:42 UTC (permalink / raw) To: Catalin Marinas, David Kågedal; +Cc: git From: David Kågedal <davidk@lysator.liu.se> This only prepares for later simplifications. Signed-off-by: David Kågedal <davidk@lysator.liu.se> Signed-off-by: Karl Hasselström <kha@treskal.com> --- 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' ^ permalink raw reply related [flat|nested] 19+ messages in thread
end of thread, other threads:[~2007-08-26 20:42 UTC | newest] Thread overview: 19+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-08-20 8:11 [StGit PATCH 0/6] Use git conflict handling on push David Kågedal 2007-08-20 8:11 ` [StGit PATCH 1/6] Split git.merge into two functions David Kågedal 2007-08-20 8:11 ` [StGit PATCH 2/6] Don't try to merge files that merge-recursive already merged David Kågedal 2007-08-20 8:12 ` [StGit PATCH 3/6] Don't touch state after conflict in push David Kågedal 2007-08-20 8:12 ` [StGit PATCH 4/6] Added a test case to check what happens when push finds a conflict David Kågedal 2007-08-20 8:12 ` [StGit PATCH 5/6] Simplify merge_recursive David Kågedal 2007-08-20 8:12 ` [StGit PATCH 6/6] Use the output from merge-recursive to list conflicts David Kågedal 2007-08-22 9:21 ` [StGit PATCH 2/6] Don't try to merge files that merge-recursive already merged Karl Hasselström 2007-08-22 9:37 ` David Kågedal 2007-08-22 9:44 ` Karl Hasselström 2007-08-22 9:59 ` Karl Hasselström 2007-08-22 10:29 ` [StGIT PATCH] Leave working dir and index alone after failed (conflicting) push Karl Hasselström 2007-08-20 8:55 ` [StGit PATCH 1/6] Split git.merge into two functions David Kågedal 2007-08-20 23:52 ` Junio C Hamano 2007-08-21 19:35 ` Uwe Kleine-König 2007-08-22 10:04 ` Junio C Hamano 2007-08-22 9:17 ` [StGit PATCH 0/6] Use git conflict handling on push Karl Hasselström 2007-08-23 14:54 ` Catalin Marinas -- strict thread matches above, loose matches on Subject: below -- 2007-08-26 20:42 [StGIT PATCH 0/6] David's conflict series using my subprocess stuff Karl Hasselström 2007-08-26 20:42 ` [StGIT PATCH 1/6] Split git.merge into two functions Karl Hasselström
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).