subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s...@apache.org
Subject svn commit: r1841731 - in /subversion/trunk/subversion: libsvn_client/conflicts.c tests/cmdline/tree_conflict_tests.py
Date Sun, 23 Sep 2018 09:40:44 GMT
Author: stsp
Date: Sun Sep 23 09:40:44 2018
New Revision: 1841731

URL: http://svn.apache.org/viewvc?rev=1841731&view=rev
Log:
Fix an endless loop in the interactive conflict resolver.

The problem was that the library returned SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
and this error code makes 'svn' retry resolution under the assumption that a
resolution option could not be executed successfully for some reason.

In this case the error was due to a buggy consistency check which ensures
that the client has already fetched details from the repository.
This check should only trigger during SVN client development, never during
regular usage. And, in fact, 'svn' had already fetched the details, but the
consistency check inside the library didn't look at all the relevant data.

Fix the consistency check in the library and add a regression test.

* subversion/libsvn_client/conflicts.c
  (svn_client_conflict_option_get_moved_to_repos_relpath_candidates2): Fix
   the check which ensures that details have already been fetched from
   the repository. Details for a 'local missing' conflict may contain
   no information about moves but still contain information about working
   copy siblings. Working copy siblings are not a valid result from this
   function, so return a NULL repository path array in this case.

* subversion/tests/cmdline/tree_conflict_tests.py
  (local_missing_dir_endless_loop): New test. This test will trigger an
   endless loop if the above bug is not yet fixed. I believe this is the
   first Python test which uses the interactive resolver, so it may also
   serve as an example of how the resolver can be used from Python tests.
  (test_list): Add test.

Modified:
    subversion/trunk/subversion/libsvn_client/conflicts.c
    subversion/trunk/subversion/tests/cmdline/tree_conflict_tests.py

Modified: subversion/trunk/subversion/libsvn_client/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/conflicts.c?rev=1841731&r1=1841730&r2=1841731&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/conflicts.c (original)
+++ subversion/trunk/subversion/libsvn_client/conflicts.c Sun Sep 23 09:40:44 2018
@@ -10565,7 +10565,8 @@ svn_client_conflict_option_get_moved_to_
       struct conflict_tree_local_missing_details *details;
 
       details = conflict->tree_conflict_local_details;
-      if (details == NULL || details->wc_move_targets == NULL)
+      if (details == NULL ||
+          (details->wc_move_targets == NULL && details->wc_siblings == NULL))
         return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
                                  _("Getting a list of possible move targets "
                                    "requires details for tree conflict at '%s' "
@@ -10573,9 +10574,12 @@ svn_client_conflict_option_get_moved_to_
                                 svn_dirent_local_style(victim_abspath,
                                                        scratch_pool));
 
-      SVN_ERR(get_repos_relpath_candidates(possible_moved_to_repos_relpaths,
-                                           details->wc_move_targets,
-                                           result_pool, scratch_pool));
+      if (details->wc_move_targets)
+        SVN_ERR(get_repos_relpath_candidates(possible_moved_to_repos_relpaths,
+                                             details->wc_move_targets,
+                                             result_pool, scratch_pool));
+      else
+        *possible_moved_to_repos_relpaths = NULL;
     }
   else
     {

Modified: subversion/trunk/subversion/tests/cmdline/tree_conflict_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/tree_conflict_tests.py?rev=1841731&r1=1841730&r2=1841731&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/tree_conflict_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/tree_conflict_tests.py Sun Sep 23 09:40:44 2018
@@ -1506,6 +1506,47 @@ def update_delete_mixed_rev(sbox):
   }
   run_and_verify_info([expected_info], sbox.repo_url + '/A/B/E/alpha2')
 
+# NB: This test will run forever if the bug it is testing for is present!
+def local_missing_dir_endless_loop(sbox):
+  "endless loop when resolving local-missing dir"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  sbox.simple_copy('A', 'A1')
+  sbox.simple_commit()
+  sbox.simple_update()
+  sbox.simple_move('A/B', 'A/B2')
+  sbox.simple_commit()
+  sbox.simple_update()
+  main.file_append(sbox.ospath("A/B2/lambda"), "This is more content.\n")
+  sbox.simple_commit()
+  sbox.simple_update()
+
+  # Create a config which enables the interactive conflict resolver
+  config_contents = '''\
+[auth]
+password-stores =
+
+[miscellany]
+interactive-conflicts = true
+'''
+  config_dir = sbox.create_config_dir(config_contents)
+
+  # Bug: 'svn' keeps retrying interactive conflict resolution while the library
+  # keeps signalling 'SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE' -> endless loop
+  main.run_svn("Tree conflict on '%s'" % sbox.ospath("A1/B2"),
+      'merge', '-c4', '^/A', sbox.ospath('A1'),
+      '--config-dir', config_dir, '--force-interactive')
+
+  # If everything works as expected the resolver will recommended a
+  # resolution option and 'svn' will resolve the conflict automatically.
+  # Verify that 'A1/B/lambda' contains the merged content:
+  contents = open(sbox.ospath('A1/B/lambda'), 'rb').readlines()
+  svntest.verify.compare_and_display_lines(
+    "A1/B/lambda has unexpectected contents", sbox.ospath("A1/B/lambda"),
+    [ "This is the file 'lambda'.\n", "This is more content.\n"], contents)
+
+
 #######################################################################
 # Run the tests
 
@@ -1537,6 +1578,7 @@ test_list = [ None,
               actual_only_node_behaviour,
               update_dir_with_not_present,
               update_delete_mixed_rev,
+              local_missing_dir_endless_loop,
              ]
 
 if __name__ == '__main__':



Mime
View raw message