Skip to content

Commit 7334f53

Browse files
authored
Merge pull request #98 from mhagger/empty-autocommits
Support autocommitting merges with no changes
2 parents 56dcbfb + 6d44fc4 commit 7334f53

File tree

1 file changed

+103
-38
lines changed

1 file changed

+103
-38
lines changed

git-imerge

Lines changed: 103 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
362394
def 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+
25842667
def 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

Comments
 (0)