Index: subversion/tests/cmdline/basic_tests.py =================================================================== --- subversion/tests/cmdline/basic_tests.py (revision 25134) +++ subversion/tests/cmdline/basic_tests.py (working copy) @@ -1935,8 +1935,164 @@ expected_output, expected_disk, expected_status) + +#---------------------------------------------------------------------- +def automatic_conflict_resolution(sbox): + "automatic conflict resolution" + sbox.build() + wc_dir = sbox.wc_dir + + # Make a backup copy of the working copy + wc_backup = sbox.add_wc_path('backup') + svntest.actions.duplicate_dir(wc_dir, wc_backup) + + # Make a couple of local mods to files which will be committed + mu_path = os.path.join(wc_dir, 'A', 'mu') + lambda_path = os.path.join(wc_dir, 'A', 'B', 'lambda') + rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho') + svntest.main.file_append(mu_path, 'Original appended text for mu\n') + svntest.main.file_append(lambda_path, 'Original appended text for lambda\n') + svntest.main.file_append(rho_path, 'Original appended text for rho\n') + + # Make a couple of local mods to files which will be conflicted + mu_path_backup = os.path.join(wc_backup, 'A', 'mu') + lambda_path_backup = os.path.join(wc_backup, 'A', 'B', 'lambda') + rho_path_backup = os.path.join(wc_backup, 'A', 'D', 'G', 'rho') + svntest.main.file_append(mu_path_backup, + 'Conflicting appended text for mu\n') + svntest.main.file_append(lambda_path_backup, + 'Conflicting appended text for lambda\n') + svntest.main.file_append(rho_path_backup, + 'Conflicting appended text for rho\n') + + # Created expected output tree for 'svn ci' + expected_output = wc.State(wc_dir, { + 'A/mu' : Item(verb='Sending'), + 'A/B/lambda' : Item(verb='Sending'), + 'A/D/G/rho' : Item(verb='Sending'), + }) + + # Create expected status tree; all local revisions should be at 1, + # but lambda, mu and rho should be at revision 2. + expected_status = svntest.actions.get_virginal_state(wc_dir, 1) + expected_status.tweak('A/mu', 'A/B/lambda', 'A/D/G/rho', wc_rev=2) + + # Commit. + svntest.actions.run_and_verify_commit(wc_dir, expected_output, + expected_status, None, + None, None, None, None, wc_dir) + + # Create expected output tree for an update of the wc_backup. + expected_output = wc.State(wc_backup, { + 'A/mu' : Item(status='C '), + 'A/B/lambda' : Item(status='C '), + 'A/D/G/rho' : Item(status='C '), + }) + + # Create expected disk tree for the update. + expected_disk = svntest.main.greek_state.copy() + expected_disk.tweak('A/mu', contents="""This is the file 'mu'. +<<<<<<< .mine +Conflicting appended text for mu +======= +Original appended text for mu +>>>>>>> .r2 +""") + expected_disk.tweak('A/B/lambda', contents="""This is the file 'lambda'. +<<<<<<< .mine +Conflicting appended text for lambda +======= +Original appended text for lambda +>>>>>>> .r2 +""") + expected_disk.tweak('A/D/G/rho', contents="""This is the file 'rho'. +<<<<<<< .mine +Conflicting appended text for rho +======= +Original appended text for rho +>>>>>>> .r2 +""") + + # Create expected status tree for the update. + expected_status = svntest.actions.get_virginal_state(wc_backup, '2') + expected_status.tweak('A/mu', 'A/B/lambda', 'A/D/G/rho', status='C ') + + # "Extra" files that we expect to result from the conflicts. + # These are expressed as list of regexps. What a cool system! :-) + extra_files = ['mu.*\.r1', 'mu.*\.r2', 'mu.*\.mine', + 'lambda.*\.r1', 'lambda.*\.r2', 'lambda.*\.mine', + 'rho.*\.r1', 'rho.*\.r2', 'rho.*\.mine',] + + # Do the update and check the results in three ways. + # All "extra" files are passed to detect_conflict_files(). + svntest.actions.run_and_verify_update(wc_backup, + expected_output, + expected_disk, + expected_status, + None, + svntest.tree.detect_conflict_files, + extra_files) + + # verify that the extra_files list is now empty. + if len(extra_files) != 0: + # Because we want to be a well-behaved test, we silently raise if + # the test fails. However, these two print statements would + # probably reveal the cause for the failure, if they were + # uncommented: + # + # print "Not all extra reject files have been accounted for:" + # print extra_files + ### we should raise a less generic error here. which? + raise svntest.Failure + + # So now lambda, mu and rho are all in a "conflicted" state. Run 'svn + # resolved' with the respective "--accept[mine|orig|repo]" flag. + + # Run 'svn resolved --accept=orig. Using lambda for the test. + svntest.actions.run_and_verify_svn("Resolved command", None, [], + 'resolved', + '--accept=orig', + lambda_path_backup) + + # Run 'svn resolved --accept=mine. Using mu for the test. + svntest.actions.run_and_verify_svn("Resolved command", None, [], + 'resolved', + '--accept=mine', + mu_path_backup) + + # Run 'svn resolved --accept=repo. Using rho for the test. + svntest.actions.run_and_verify_svn("Resolved command", None, [], + 'resolved', + '--accept=repo', + rho_path_backup) + + # Set the expected disk contents for the test + expected_disk = svntest.main.greek_state.copy() + + expected_disk.tweak('A/B/lambda', contents="This is the file 'lambda'.\n") + expected_disk.tweak('A/mu', contents="This is the file 'mu'.\n" + "Conflicting appended text for mu\n") + expected_disk.tweak('A/D/G/rho', contents="This is the file 'rho'.\n" + "Original appended text for rho\n") + + # Set the expected status for the test + expected_status = svntest.actions.get_virginal_state(wc_backup, '2') + + expected_status.tweak('A/mu', status='M ') + expected_status.tweak('A/B/lambda', status='M ') + expected_status.tweak('A/D/G/rho', status=' ') + + # Do the update and check the results in three ways. + svntest.actions.run_and_verify_update(wc_backup, + expected_output, + expected_disk, + expected_status) + +#---------------------------------------------------------------------- + + ######################################################################## # Run the tests @@ -1979,6 +2135,7 @@ delete_keep_local, windows_paths_in_repos, basic_rm_urls_one_repo, + automatic_conflict_resolution ] if __name__ == '__main__': Index: subversion/svn/cl.h =================================================================== --- subversion/svn/cl.h (revision 25134) +++ subversion/svn/cl.h (working copy) @@ -159,6 +159,7 @@ apr_hash_t *revprop_table; /* table with revision properties to set */ svn_boolean_t parents; /* create intermediate directories */ svn_boolean_t merge_sensitive; /* use/display extra merge information */ + const char *accept; /* automatically resolve conflict with original, wc or repository file */ } svn_cl__opt_state_t; Index: subversion/svn/main.c =================================================================== --- subversion/svn/main.c (revision 25134) +++ subversion/svn/main.c (working copy) @@ -207,7 +207,11 @@ {"merge-sensitive", 'g', 0, N_("use/display additional information from merge " "history")}, - {0, 0, 0, 0} + {"accept", 'a', 1, + N_("specify automatic conflict resolution source\n" + " " + "('orig', 'mine', or 'repo')")}, + {0, 0, 0, 0}, }; @@ -695,7 +699,7 @@ " remove conflict markers; it merely removes the conflict-related\n" " artifact files and allows PATH to be committed again.\n"), {svn_cl__targets_opt, 'R', svn_cl__depth_opt, 'q', - svn_cl__config_dir_opt} }, + svn_cl__config_dir_opt, 'a'} }, { "revert", svn_cl__revert, {0}, N_ ("Restore pristine working copy file (undo most local edits).\n"