@@ -288,21 +288,7 @@ class UncleanWorkTreeError(Failure):
288288 pass
289289
290290
291- def require_clean_work_tree (action ):
292- """Verify that the current tree is clean.
293-
294- The code is a Python translation of the git-sh-setup(1) function
295- of the same name."""
296-
297- process = subprocess .Popen (
298- ['git' , 'rev-parse' , '--verify' , 'HEAD' ],
299- stdout = subprocess .PIPE , stderr = subprocess .PIPE ,
300- )
301- err = communicate (process )[1 ]
302- retcode = process .poll ()
303- if retcode :
304- raise UncleanWorkTreeError (err .rstrip ())
305-
291+ def refresh_index ():
306292 process = subprocess .Popen (
307293 ['git' , 'update-index' , '-q' , '--ignore-submodules' , '--refresh' ],
308294 stdout = subprocess .PIPE , stderr = subprocess .PIPE ,
@@ -312,18 +298,52 @@ def require_clean_work_tree(action):
312298 if retcode :
313299 raise UncleanWorkTreeError (err .rstrip () or out .rstrip ())
314300
315- error = []
301+
302+ def unstaged_changes ():
303+ """Return True iff there are unstaged changes in the working copy"""
304+
316305 try :
317306 check_call (['git' , 'diff-files' , '--quiet' , '--ignore-submodules' ])
307+ return False
318308 except CalledProcessError :
319- error .append ('Cannot %s: You have unstaged changes.' % (action ,))
309+ return True
310+
311+
312+ def uncommitted_changes ():
313+ """Return True iff the index contains uncommitted changes."""
320314
321315 try :
322316 check_call ([
323317 'git' , 'diff-index' , '--cached' , '--quiet' ,
324318 '--ignore-submodules' , 'HEAD' , '--' ,
325319 ])
320+ return False
326321 except CalledProcessError :
322+ return True
323+
324+
325+ def require_clean_work_tree (action ):
326+ """Verify that the current tree is clean.
327+
328+ The code is a Python translation of the git-sh-setup(1) function
329+ of the same name."""
330+
331+ process = subprocess .Popen (
332+ ['git' , 'rev-parse' , '--verify' , 'HEAD' ],
333+ stdout = subprocess .PIPE , stderr = subprocess .PIPE ,
334+ )
335+ err = communicate (process )[1 ]
336+ retcode = process .poll ()
337+ if retcode :
338+ raise UncleanWorkTreeError (err .rstrip ())
339+
340+ refresh_index ()
341+
342+ error = []
343+ if unstaged_changes ():
344+ error .append ('Cannot %s: You have unstaged changes.' % (action ,))
345+
346+ if uncommitted_changes ():
327347 if not error :
328348 error .append ('Cannot %s: Your index contains uncommitted changes.' % (action ,))
329349 else :
@@ -359,6 +379,18 @@ def rev_list(*args):
359379 ]
360380
361381
382+ git_dir_cache = None
383+
384+ def git_dir ():
385+ global git_dir_cache
386+
387+ if git_dir_cache is None :
388+ git_dir_cache = check_output (
389+ ['git' , 'rev-parse' , '--git-dir' ]
390+ ).rstrip ('\n ' )
391+ return git_dir_cache
392+
393+
362394def get_type (arg ):
363395 """Return the type of a git object ('commit', 'tree', 'blob', or 'tag')."""
364396
@@ -2581,6 +2613,57 @@ def request_user_merge(merge_state, i1, i2):
25812613 )
25822614
25832615
2616+ def simple_merge_in_progress ():
2617+ # Check if a merge (of a single branch) is in progress:
2618+ try :
2619+ with open (os .path .join (git_dir (), 'MERGE_HEAD' )) as f :
2620+ heads = [line .rstrip () for line in f ]
2621+ except IOError :
2622+ return False
2623+
2624+ return len (heads ) == 1
2625+
2626+
2627+ def commit_user_merge (merge_state , edit_log_msg = None ):
2628+ """If a merge is in progress and ready to be committed, commit it.
2629+
2630+ If a simple merge is in progress and any changes in the working
2631+ tree are staged, commit the merge commit and return True.
2632+ Otherwise, return False.
2633+
2634+ """
2635+
2636+ if not simple_merge_in_progress ():
2637+ return False
2638+
2639+ # Check if all conflicts are resolved and everything in the
2640+ # working tree is staged:
2641+ refresh_index ()
2642+ if unstaged_changes ():
2643+ raise UncleanWorkTreeError (
2644+ 'Cannot proceed: You have unstaged changes.' % (action ,)
2645+ )
2646+
2647+ # A merge is in progress, and either all changes have been staged
2648+ # or no changes are necessary. Create a merge commit.
2649+ cmd = ['git' , 'commit' , '--no-verify' ]
2650+
2651+ if edit_log_msg is None :
2652+ edit_log_msg = get_default_edit ()
2653+
2654+ if edit_log_msg :
2655+ cmd += ['--edit' ]
2656+ else :
2657+ cmd += ['--no-edit' ]
2658+
2659+ try :
2660+ check_call (cmd )
2661+ except CalledProcessError :
2662+ raise Failure ('Could not commit staged changes.' )
2663+
2664+ return True
2665+
2666+
25842667def incorporate_user_merge (merge_state , edit_log_msg = None ):
25852668 """If the user has done a merge for us, incorporate the results.
25862669
@@ -2652,31 +2735,13 @@ def incorporate_user_merge(merge_state, edit_log_msg=None):
26522735 # If we reach this point, then the scratch reference exists and is
26532736 # checked out. Now check whether there is staged content that
26542737 # can be committed:
2655-
2656- merge_frontier = MergeFrontier .map_known_frontier (merge_state )
2657-
2658- try :
2659- check_call (['git' , 'diff-index' , '--cached' , '--quiet' , 'HEAD' , '--' ])
2660- except CalledProcessError :
2661- # There are staged changes; commit them if possible.
2662- cmd = ['git' , 'commit' , '--no-verify' ]
2663-
2664- if edit_log_msg is None :
2665- edit_log_msg = get_default_edit ()
2666-
2667- if edit_log_msg :
2668- cmd += ['--edit' ]
2669- else :
2670- cmd += ['--no-edit' ]
2671-
2672- try :
2673- check_call (cmd )
2674- except CalledProcessError :
2675- raise Failure ('Could not commit staged changes.' )
2738+ if commit_user_merge (merge_state , edit_log_msg = edit_log_msg ):
26762739 commit = get_commit_sha1 ('HEAD' )
26772740
26782741 require_clean_work_tree ('proceed' )
26792742
2743+ merge_frontier = MergeFrontier .map_known_frontier (merge_state )
2744+
26802745 # This might throw ManualMergeUnusableError:
26812746 (i1 , i2 ) = merge_state .incorporate_manual_merge (commit )
26822747
0 commit comments