Index: subversion/libsvn_wc/adm_ops.c =================================================================== --- subversion/libsvn_wc/adm_ops.c (revision 18840) +++ subversion/libsvn_wc/adm_ops.c (working copy) @@ -1337,7 +1337,7 @@ /* Revert ENTRY for NAME in directory represented by ADM_ACCESS. Sets - *REVERTED if file actually have reverted. + *REVERTED to TRUE if something actually is reverted. Use SVN_WC_ENTRY_THIS_DIR as NAME for reverting ADM_ACCESS directory itself. @@ -1384,6 +1384,7 @@ SVN_ERR(svn_wc__loggy_remove (&log_accum, adm_access, svn_path_is_child(adm_path, rprop, pool), pool)); + *reverted = TRUE; } } @@ -1426,6 +1427,7 @@ { flags |= SVN_WC__ENTRY_MODIFY_COPIED; tmp_entry.copied = FALSE; + *reverted = TRUE; } /* Deal with the contents. */ @@ -1494,6 +1496,8 @@ SVN_ERR(svn_wc__loggy_set_entry_timestamp_from_wc (&log_accum, adm_access, name, SVN_WC__ENTRY_ATTR_TEXT_TIME, pool)); + + *reverted = TRUE; } } @@ -1537,6 +1541,7 @@ { flags |= SVN_WC__ENTRY_MODIFY_SCHEDULE; tmp_entry.schedule = svn_wc_schedule_normal; + *reverted = TRUE; } SVN_ERR(svn_wc__loggy_entry_modify(&log_accum, adm_access, name, @@ -1547,13 +1552,7 @@ { SVN_ERR(svn_wc__write_log(adm_access, 0, log_accum, pool)); SVN_ERR(svn_wc__run_log(adm_access, NULL, pool)); - - *reverted = TRUE; } - else - { - *reverted = FALSE; - } return SVN_NO_ERROR; } Index: subversion/tests/cmdline/revert_tests.py =================================================================== --- subversion/tests/cmdline/revert_tests.py (revision 18840) +++ subversion/tests/cmdline/revert_tests.py (working copy) @@ -523,6 +523,67 @@ actual_disk = svntest.tree.build_tree_from_wc(wc_dir, 1) svntest.tree.compare_trees(actual_disk, expected_disk.old_tree()) + +#---------------------------------------------------------------------- +# Tests for issue #2517. +# +# Manual conflict resolution leads to spurious revert report. + +def revert_after_manual_conflict_resolution__text(sbox): + "revert after manual text-conflict resolution" + + # Make two working copies + sbox.build() + wc_dir_1 = sbox.wc_dir + wc_dir_2 = sbox.add_wc_path('other') + svntest.actions.duplicate_dir(wc_dir_1, wc_dir_2) + + # Cause a (text) conflict + iota_path_1 = os.path.join(wc_dir_1, 'iota') + iota_path_2 = os.path.join(wc_dir_2, 'iota') + svntest.main.file_write(iota_path_1, 'Modified iota text') + svntest.main.file_write(iota_path_2, 'Conflicting iota text') + svntest.main.run_svn(None, 'commit', '-m', 'r2', wc_dir_1) + svntest.main.run_svn(None, 'update', wc_dir_2) + + # Resolve the conflict "manually" + svntest.main.file_write(iota_path_2, 'Modified iota text') + os.remove(iota_path_2 + '.mine') + os.remove(iota_path_2 + '.r1') + os.remove(iota_path_2 + '.r2') + + # Verify no output from status, diff, or revert + svntest.actions.run_and_verify_svn(None, [], [], "status", wc_dir_2) + svntest.actions.run_and_verify_svn(None, [], [], "diff", wc_dir_2) + svntest.actions.run_and_verify_svn(None, [], [], "revert", "-R", wc_dir_2) + +def revert_after_manual_conflict_resolution__prop(sbox): + "revert after manual property-conflict resolution" + + # Make two working copies + sbox.build() + wc_dir_1 = sbox.wc_dir + wc_dir_2 = sbox.add_wc_path('other') + svntest.actions.duplicate_dir(wc_dir_1, wc_dir_2) + + # Cause a (property) conflict + iota_path_1 = os.path.join(wc_dir_1, 'iota') + iota_path_2 = os.path.join(wc_dir_2, 'iota') + svntest.main.run_svn(None, 'propset', 'foo', '1', iota_path_1) + svntest.main.run_svn(None, 'propset', 'foo', '2', iota_path_2) + svntest.main.run_svn(None, 'commit', '-m', 'r2', wc_dir_1) + svntest.main.run_svn(None, 'update', wc_dir_2) + + # Resolve the conflict "manually" + svntest.main.run_svn(None, 'propset', 'foo', '1', iota_path_2) + os.remove(iota_path_2 + '.prej') + + # Verify no output from status, diff, or revert + svntest.actions.run_and_verify_svn(None, [], [], "status", wc_dir_2) + svntest.actions.run_and_verify_svn(None, [], [], "diff", wc_dir_2) + svntest.actions.run_and_verify_svn(None, [], [], "revert", "-R", wc_dir_2) + + ######################################################################## # Run the tests @@ -537,6 +598,8 @@ revert_file_merge_replace_with_history, revert_repos_to_wc_replace_with_props, revert_after_second_replace, + revert_after_manual_conflict_resolution__text, + revert_after_manual_conflict_resolution__prop, ] if __name__ == '__main__': Index: subversion/tests/cmdline/svntest/main.py =================================================================== --- subversion/tests/cmdline/svntest/main.py (revision 18840) +++ subversion/tests/cmdline/svntest/main.py (working copy) @@ -395,6 +395,14 @@ fp.write(new_text) fp.close() +# For making local mods to files +def file_write(path, new_text): + "Replace contents of file at PATH with NEW_TEXT" + + fp = open(path, 'w') # open in (w)rite mode + fp.write(new_text) + fp.close() + # For creating blank new repositories def create_repos(path): """Create a brand-new SVN repository at PATH. If PATH does not yet