You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ar...@apache.org on 2012/07/30 08:39:38 UTC

svn commit: r1367002 [18/21] - in /subversion/branches/svn-bisect: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/client-side/emacs/ contrib/server-side/mod_dontdothat/ notes/ notes/api-errata/1.7/ notes/http-and-webdav/...

Modified: subversion/branches/svn-bisect/subversion/svnrdump/svnrdump.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/svnrdump/svnrdump.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/svnrdump/svnrdump.c (original)
+++ subversion/branches/svn-bisect/subversion/svnrdump/svnrdump.c Mon Jul 30 06:39:28 2012
@@ -151,11 +151,11 @@ static const apr_getopt_option_t svnrdum
 
 /* Baton for the RA replay session. */
 struct replay_baton {
-  /* The editor producing diffs. */
-  const svn_delta_editor_t *editor;
+  /* A backdoor ra session for fetching information. */
+  svn_ra_session_t *extra_ra_session;
 
-  /* Baton for the editor. */
-  void *edit_baton;
+  /* The output stream */
+  svn_stream_t *stdout_stream;
 
   /* Whether to be quiet. */
   svn_boolean_t quiet;
@@ -220,10 +220,9 @@ replay_revstart(svn_revnum_t revision,
   SVN_ERR(svn_stream_printf(stdout_stream, pool, "\n"));
   SVN_ERR(svn_stream_close(stdout_stream));
 
-  /* Extract editor and editor_baton from the replay_baton and
-     set them so that the editor callbacks can use them. */
-  *editor = rb->editor;
-  *edit_baton = rb->edit_baton;
+  SVN_ERR(svn_rdump__get_dump_editor(editor, edit_baton, revision,
+                                     rb->stdout_stream, rb->extra_ra_session,
+                                     check_cancel, NULL, pool));
 
   return SVN_NO_ERROR;
 }
@@ -240,6 +239,9 @@ replay_revend(svn_revnum_t revision,
 {
   /* No resources left to free. */
   struct replay_baton *rb = replay_baton;
+
+  SVN_ERR(editor->close_edit(edit_baton, pool));
+
   if (! rb->quiet)
     SVN_ERR(svn_cmdline_fprintf(stderr, pool, "* Dumped revision %lu.\n",
                                 revision));
@@ -343,6 +345,7 @@ dump_revision_header(svn_ra_session_t *s
  */
 static svn_error_t *
 replay_revisions(svn_ra_session_t *session,
+                 svn_ra_session_t *extra_ra_session,
                  const char *url,
                  svn_revnum_t start_revision,
                  svn_revnum_t end_revision,
@@ -350,20 +353,15 @@ replay_revisions(svn_ra_session_t *sessi
                  svn_boolean_t incremental,
                  apr_pool_t *pool)
 {
-  const svn_delta_editor_t *dump_editor;
   struct replay_baton *replay_baton;
-  void *dump_baton;
   const char *uuid;
   svn_stream_t *stdout_stream;
 
   SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));
 
-  SVN_ERR(svn_rdump__get_dump_editor(&dump_editor, &dump_baton, stdout_stream,
-                                     check_cancel, NULL, pool));
-
   replay_baton = apr_pcalloc(pool, sizeof(*replay_baton));
-  replay_baton->editor = dump_editor;
-  replay_baton->edit_baton = dump_baton;
+  replay_baton->stdout_stream = stdout_stream;
+  replay_baton->extra_ra_session = extra_ra_session;
   replay_baton->quiet = quiet;
 
   /* Write the magic header and UUID */
@@ -401,6 +399,8 @@ replay_revisions(svn_ra_session_t *sessi
     {
       const svn_ra_reporter3_t *reporter;
       void *report_baton;
+      const svn_delta_editor_t *dump_editor;
+      void *dump_baton;
 
       /* First, we need to dump the start_revision in full.  We'll
          start with a revision record header. */
@@ -413,6 +413,10 @@ replay_revisions(svn_ra_session_t *sessi
          to the update reporter, telling it that we have nothing to
          start with.  The delta between nothing and everything-at-REV
          is, effectively, a full dump of REV. */
+      SVN_ERR(svn_rdump__get_dump_editor(&dump_editor, &dump_baton,
+                                         start_revision,
+                                         stdout_stream, extra_ra_session,
+                                         check_cancel, NULL, pool));
       SVN_ERR(svn_ra_do_update2(session, &reporter, &report_baton,
                                 start_revision, "", svn_depth_infinity,
                                 FALSE, dump_editor, dump_baton, pool));
@@ -531,7 +535,17 @@ dump_cmd(apr_getopt_t *os,
          apr_pool_t *pool)
 {
   opt_baton_t *opt_baton = baton;
-  return replay_revisions(opt_baton->session, opt_baton->url,
+  svn_ra_session_t *extra_ra_session;
+  const char *repos_root;
+
+  SVN_ERR(svn_client_open_ra_session(&extra_ra_session,
+                                     opt_baton->url,
+                                     opt_baton->ctx, pool));
+  SVN_ERR(svn_ra_get_repos_root2(extra_ra_session, &repos_root, pool));
+  SVN_ERR(svn_ra_reparent(extra_ra_session, repos_root, pool));
+
+  return replay_revisions(opt_baton->session, extra_ra_session,
+                          opt_baton->url,
                           opt_baton->start_revision.value.number,
                           opt_baton->end_revision.value.number,
                           opt_baton->quiet, opt_baton->incremental, pool);

Modified: subversion/branches/svn-bisect/subversion/svnrdump/svnrdump.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/svnrdump/svnrdump.h?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/svnrdump/svnrdump.h (original)
+++ subversion/branches/svn-bisect/subversion/svnrdump/svnrdump.h Mon Jul 30 06:39:28 2012
@@ -46,7 +46,9 @@ extern "C" {
 svn_error_t *
 svn_rdump__get_dump_editor(const svn_delta_editor_t **editor,
                            void **edit_baton,
+                           svn_revnum_t revision,
                            svn_stream_t *stream,
+                           svn_ra_session_t *ra_session,
                            svn_cancel_func_t cancel_func,
                            void *cancel_baton,
                            apr_pool_t *pool);

Modified: subversion/branches/svn-bisect/subversion/svnserve/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/svnserve/main.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/svnserve/main.c (original)
+++ subversion/branches/svn-bisect/subversion/svnserve/main.c Mon Jul 30 06:39:28 2012
@@ -428,7 +428,9 @@ int main(int argc, const char *argv[])
   const char *host = NULL;
   int family = APR_INET;
   apr_int32_t sockaddr_info_flags = 0;
+#if APR_HAVE_IPV6
   svn_boolean_t prefer_v6 = FALSE;
+#endif
   svn_boolean_t quiet = FALSE;
   svn_boolean_t is_version = FALSE;
   int mode_opt_count = 0;
@@ -486,7 +488,10 @@ int main(int argc, const char *argv[])
       switch (opt)
         {
         case '6':
+#if APR_HAVE_IPV6
           prefer_v6 = TRUE;
+#endif
+          /* ### Maybe error here if we don't have IPV6 support? */
           break;
 
         case 'h':

Modified: subversion/branches/svn-bisect/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/svnserve/serve.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/svnserve/serve.c (original)
+++ subversion/branches/svn-bisect/subversion/svnserve/serve.c Mon Jul 30 06:39:28 2012
@@ -243,6 +243,7 @@ svn_error_t *load_configs(svn_config_t *
   *pwdb = NULL;
   if (pwdb_path)
     {
+      pwdb_path = svn_dirent_canonicalize(pwdb_path, pool);
       pwdb_path = svn_dirent_join(base, pwdb_path, pool);
 
       err = svn_config_read2(pwdb, pwdb_path, TRUE, FALSE, pool);
@@ -290,6 +291,7 @@ svn_error_t *load_configs(svn_config_t *
     {
       const char *case_force_val;
 
+      authzdb_path = svn_dirent_canonicalize(authzdb_path, pool);
       authzdb_path = svn_dirent_join(base, authzdb_path, pool);
       err = svn_repos_authz_read(authzdb, authzdb_path, TRUE, pool);
       if (err)
@@ -1979,7 +1981,7 @@ static svn_error_t *log_cmd(svn_ra_svn_c
   server_baton_t *b = baton;
   svn_revnum_t start_rev, end_rev;
   const char *full_path;
-  svn_boolean_t changed_paths, strict_node, include_merged_revisions;
+  svn_boolean_t send_changed_paths, strict_node, include_merged_revisions;
   apr_array_header_t *paths, *full_paths, *revprop_items, *revprops;
   char *revprop_word;
   svn_ra_svn_item_t *elt;
@@ -1988,7 +1990,7 @@ static svn_error_t *log_cmd(svn_ra_svn_c
   log_baton_t lb;
 
   SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "l(?r)(?r)bb?n?Bwl", &paths,
-                                 &start_rev, &end_rev, &changed_paths,
+                                 &start_rev, &end_rev, &send_changed_paths,
                                  &strict_node, &limit,
                                  &include_merged_revs_param,
                                  &revprop_word, &revprop_items));
@@ -2045,7 +2047,7 @@ static svn_error_t *log_cmd(svn_ra_svn_c
 
   SVN_ERR(log_command(b, conn, pool, "%s",
                       svn_log__log(full_paths, start_rev, end_rev,
-                                   limit, changed_paths, strict_node,
+                                   limit, send_changed_paths, strict_node,
                                    include_merged_revisions, revprops,
                                    pool)));
 
@@ -2054,7 +2056,7 @@ static svn_error_t *log_cmd(svn_ra_svn_c
   lb.conn = conn;
   lb.stack_depth = 0;
   err = svn_repos_get_logs4(b->repos, full_paths, start_rev, end_rev,
-                            (int) limit, changed_paths, strict_node,
+                            (int) limit, send_changed_paths, strict_node,
                             include_merged_revisions, revprops,
                             authz_check_access_cb_func(b), b, log_receiver,
                             &lb, pool);
@@ -2947,6 +2949,24 @@ repos_path_valid(const char *path)
   return TRUE;
 }
 
+/* Callback which receives hook environment variables from the hook
+ * environment configuration section,
+ * An implementation of svn_config_enumerator2_t. */
+static svn_boolean_t
+hooks_env_conf_cb(const char *name,
+                  const char *value,
+                  void *baton,
+                  apr_pool_t *pool)
+{
+  apr_hash_t *hooks_env = baton;
+  apr_pool_t *hash_pool = apr_hash_pool_get(hooks_env);
+
+  apr_hash_set(hooks_env, apr_pstrdup(hash_pool, name),
+               APR_HASH_KEY_STRING, apr_pstrdup(hash_pool, value));
+
+  return TRUE;
+}
+
 /* Look for the repository given by URL, using ROOT as the virtual
  * repository root.  If we find one, fill in the repos, fs, cfg,
  * repos_url, and fs_path fields of B.  Set B->repos's client
@@ -3037,6 +3057,17 @@ static svn_error_t *find_repos(const cha
                                  "No access allowed to this repository",
                                  b, conn, pool);
 
+  /* If a hook environment has been configured, set it up. */
+  if (svn_config_has_section(b->cfg, SVN_CONFIG_SECTION_HOOKS_ENV))
+    {
+      apr_hash_t *hooks_env = apr_hash_make(pool);
+
+      svn_config_enumerate2(b->cfg, SVN_CONFIG_SECTION_HOOKS_ENV,
+                            hooks_env_conf_cb, hooks_env, pool);
+
+      svn_repos_hooks_setenv(b->repos, hooks_env);
+    }
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/svn-bisect/subversion/svnsync/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/svnsync/main.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/svnsync/main.c (original)
+++ subversion/branches/svn-bisect/subversion/svnsync/main.c Mon Jul 30 06:39:28 2012
@@ -1051,8 +1051,6 @@ replay_rev_started(svn_revnum_t revision
   apr_hash_t *filtered;
   int filtered_count;
   int normalized_count;
-  svn_delta_shim_callbacks_t *shim_callbacks =
-                                    svn_delta_shim_callbacks_default(pool);
 
   /* We set this property so that if we error out for some reason
      we can later determine where we were in the process of
@@ -1120,9 +1118,6 @@ replay_rev_started(svn_revnum_t revision
   *editor = cancel_editor;
   *edit_baton = cancel_baton;
 
-  SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton,
-                                   shim_callbacks, pool, pool));
-
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/svn-bisect/subversion/svnsync/sync.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/svnsync/sync.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/svnsync/sync.c (original)
+++ subversion/branches/svn-bisect/subversion/svnsync/sync.c Mon Jul 30 06:39:28 2012
@@ -33,9 +33,6 @@
 #include "svn_subst.h"
 #include "svn_string.h"
 
-#include "private/svn_opt_private.h"
-#include "private/svn_cmdline_private.h"
-
 #include "sync.h"
 
 #include "svn_private_config.h"

Modified: subversion/branches/svn-bisect/subversion/tests/README
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/README?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/README (original)
+++ subversion/branches/svn-bisect/subversion/tests/README Mon Jul 30 06:39:28 2012
@@ -130,6 +130,47 @@ This same rule applies to Subversion dev
 bug, write a test for it. **
 
 
+When to file a related issue
+----------------------------
+
+By definition, if you write a new test which is set to XFail, then it
+assumed that the test is for a known bug.  In these cases it is
+recommended that you associate an issue in the issue tracker with the
+XFailing test.  This ensures that the issue tracker is the authoritative
+list of known bugs -- see http://subversion.tigris.org/issue-tracker.html.
+You may need to create a new issue if one doesn't already exist.
+
+For C tests simply add a comment noting any associated issue:
+
+    /* This is for issue #3234. */
+    static svn_error_t *
+    test_copy_crash(const svn_test_opts_t *opts,
+                    apr_pool_t *pool)
+    {
+      apr_array_header_t *sources;
+      svn_opt_revision_t rev;
+      .
+      .
+
+For Python tests use the @Issue() decorator (a summary comment of the
+issue never hurts either):
+
+    #---------------------------------------------------------------------
+    # Test for issue #3657 'dav update report handler in skelta mode can
+    # cause spurious conflicts'.
+    @Issue(3657)
+    @XFail()
+    def dav_skelta_mode_causes_spurious_conflicts(sbox):
+      "dav skelta mode can cause spurious conflicts"
+      .
+      .
+
+Of course it isn't *always* necessary to create an associated issue.
+If a the fix for an new XFailing test is imminent, you are probably
+better off simply fixing the bug and moving on.  Use common sense, but
+when in doubt associate a new issue.
+
+
 What not to test
 ----------------
 

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/README
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/README?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/README (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/README Mon Jul 30 06:39:28 2012
@@ -12,7 +12,7 @@ command-line client.  It has no access t
 looks inside the .svn/ directory; it only performs actions that a
 human user would do.
 
-These tests require Python 2.4 or later.
+These tests require Python 2.5 or later.
 
   [ For more general information on Subversion's testing system,
     please read the README in subversion/tests/. ]

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/basic_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/basic_tests.py?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/basic_tests.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/basic_tests.py Mon Jul 30 06:39:28 2012
@@ -991,7 +991,7 @@ def verify_file_deleted(message, path):
   if message is not None:
     print(message)
   ###TODO We should raise a less generic error here. which?
-  raise Failure
+  raise svntest.Failure
 
 def verify_dir_deleted(path):
   if not os.path.isdir(path):
@@ -999,6 +999,7 @@ def verify_dir_deleted(path):
 
   return 1
 
+@Issue(687,4074)
 def basic_delete(sbox):
   "basic delete command"
 
@@ -1190,6 +1191,12 @@ def basic_delete(sbox):
                                      'rm', '-m', 'delete iota URL',
                                      iota_URL)
 
+  # Issue 4074, deleting a root url SEGV.
+  expected_error = 'svn: E170000: .*not within a repository'
+  svntest.actions.run_and_verify_svn(None, [], expected_error,
+                                     'rm', sbox.repo_url,
+                                     '--message', 'delete root')
+
 #----------------------------------------------------------------------
 
 def basic_checkout_deleted(sbox):
@@ -2879,6 +2886,66 @@ def quiet_commits(sbox):
                                         expected_disk,
                                         expected_status)
 
+# Regression test for issue #4023: on Windows, 'svn rm' incorrectly deletes
+# on-disk file if it is case-clashing with intended (non-on-disk) target.
+@Issue(4023)
+@XFail(svntest.main.is_fs_case_insensitive)
+def rm_missing_with_case_clashing_ondisk_item(sbox):
+  """rm missing item with case-clashing ondisk item"""
+
+  sbox.build(read_only = True)
+  wc_dir = sbox.wc_dir
+
+  iota_path = os.path.join(wc_dir, 'iota')
+  IOTA_path = os.path.join(wc_dir, 'IOTA')
+  
+  # Out-of-svn move, to make iota missing, while IOTA appears as unversioned.
+  os.rename(iota_path, IOTA_path)
+  
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'iota'              : Item(status='! ', wc_rev='1'),
+    'IOTA'              : Item(status='? '),
+    })
+  svntest.actions.run_and_verify_unquiet_status(wc_dir, expected_status)
+    
+  # 'svn rm' iota, should leave IOTA alone.
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'rm', iota_path)
+
+  # Test status: the unversioned IOTA should still be there.
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+    'iota'              : Item(status='D ', wc_rev='1'),
+    'IOTA'              : Item(status='? '),
+    })
+  svntest.actions.run_and_verify_unquiet_status(wc_dir, expected_status)
+
+
+def delete_conflicts_one_of_many(sbox):
+  """delete multiple targets one conflict"""
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  svntest.main.file_append(sbox.ospath('A/D/G/rho'), 'new rho')
+  sbox.simple_commit()
+  svntest.main.file_append(sbox.ospath('A/D/G/rho'), 'conflict rho')
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'update', '-r1', '--accept', 'postpone',
+                                     wc_dir)
+                           
+  if not os.path.exists(sbox.ospath('A/D/G/rho.mine')):
+    raise svntest.Failure("conflict file rho.mine missing")
+
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'rm', '--force',
+                                     sbox.ospath('A/D/G/rho'),
+                                     sbox.ospath('A/D/G/tau'))
+
+  verify_file_deleted("failed to remove conflict file",
+                      sbox.ospath('A/D/G/rho.mine'))
+
 ########################################################################
 # Run the tests
 
@@ -2943,6 +3010,8 @@ test_list = [ None,
               ls_multiple_and_non_existent_targets,
               add_multiple_targets,
               quiet_commits,
+              rm_missing_with_case_clashing_ondisk_item,
+              delete_conflicts_one_of_many,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/commit_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/commit_tests.py?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/commit_tests.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/commit_tests.py Mon Jul 30 06:39:28 2012
@@ -1136,19 +1136,26 @@ def commit_in_dir_scheduled_for_addition
 
   A_path = os.path.join(wc_dir, 'A')
   Z_path = os.path.join(wc_dir, 'Z')
+  Z_abspath = os.path.abspath(Z_path)
   mu_path = os.path.join(wc_dir, 'Z', 'mu')
 
   svntest.main.run_svn(None, 'move', A_path, Z_path)
+  
+  # Make sure mu is a committable
+  svntest.main.file_write(mu_path, "xxxx")
 
   # Commit a copied thing inside an added-with-history directory,
   # expecting a specific error to occur!
   svntest.actions.run_and_verify_commit(wc_dir,
                                         None,
                                         None,
-                                        "not under version control",
+                                        "svn: E200009: '" +
+                                        re.escape(Z_abspath) +
+                                        "' is not known to exist in the",
                                         mu_path)
 
   Q_path = os.path.join(wc_dir, 'Q')
+  Q_abspath = os.path.abspath(Q_path)
   bloo_path = os.path.join(Q_path, 'bloo')
 
   os.mkdir(Q_path)
@@ -1160,9 +1167,24 @@ def commit_in_dir_scheduled_for_addition
   svntest.actions.run_and_verify_commit(wc_dir,
                                         None,
                                         None,
-                                        "not under version control",
+                                        "svn: E200009: '" +
+                                        re.escape(Q_abspath) +
+                                        "' is not known to exist in the",
                                         bloo_path)
 
+  R_path = sbox.ospath('Z/B/R')
+  sbox.simple_mkdir('Z/B/R')
+
+  # Commit a d added thing inside an added directory,
+  # expecting a specific error to occur!
+  svntest.actions.run_and_verify_commit(wc_dir,
+                                        None,
+                                        None,
+                                        "svn: E200009: '" +
+                                        re.escape(Z_abspath) +
+                                        "' is not known to exist in the.*",
+                                        R_path)                                        
+
 #----------------------------------------------------------------------
 
 # Does this make sense now that deleted files are always removed from the wc?
@@ -2832,32 +2854,27 @@ def commit_incomplete(sbox):
 #   From: Fergus Slorach <su...@gmail.com>
 #   Subject: svn commit --targets behaviour change in 1.7?
 @Issue(4059)
-@XFail()
 def commit_add_subadd(sbox):
   "committing add with explicit subadd targets"
 
   sbox.build()
   wc_dir = sbox.wc_dir
 
-  A_path = os.path.join(wc_dir, 'A')
-  A2_path = os.path.join(wc_dir, 'A2')
-
   targets_file = sbox.ospath('targets') # ### better tempdir?
   targets_file = os.path.abspath(targets_file)
 
   # prepare targets file
-  targets = "A2/D A2/D/H A2/D/H/chi A2/D/H/omega A2/D/H/psi".split()
+  targets = "A/D A/D/H A/D/H/chi A/D/H/omega A/D/H/psi".split()
   open(targets_file, 'w').write("\n".join(targets))
 
-  # r2: add some stuff, with specific invocation
-  import shutil
-  shutil.copytree(A_path, A2_path)
-
-  # hack to copy A to A2, without creating .svn dirs when running against 1.6
-  svntest.main.run_svn(None, 'cp', A_path, A2_path)
-  svntest.main.run_svn(None, 'revert', '-R', A2_path)
+  # r2: rm A/D
+  sbox.simple_rm('A/D')
+  sbox.simple_commit(message='rm')
 
+  # r3: revert r2, with specific invocation
   os.chdir(wc_dir)
+  svntest.main.run_svn(None, 'up')
+  svntest.main.run_svn(None, 'merge', '-c', '-2', './')
   svntest.main.run_svn(None, 'commit', '--targets', targets_file, '-mm')
 
 

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/copy_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/copy_tests.py?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/copy_tests.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/copy_tests.py Mon Jul 30 06:39:28 2012
@@ -4654,9 +4654,15 @@ def changed_dir_data_should_match_checko
 
   os.chdir(was_cwd)
   os.chdir(wc_dir)
-  svntest.actions.run_and_verify_svn(None, verify_out, [], 'status', '-v')
+  rv, verify_out2, err = main.run_svn (None, 'status', '-v')
   os.chdir(was_cwd)
 
+  # The order of the status output is not absolutely defined, but
+  # otherwise should match
+  svntest.verify.verify_outputs(None,
+                                sorted(verify_out2), None,
+                                sorted(verify_out), None)
+
 def move_added_nodes(sbox):
   """move added nodes"""
 
@@ -5553,10 +5559,17 @@ def wc_wc_copy_incomplete(sbox):
   sbox.build()
   wc_dir = sbox.wc_dir
 
+  # We don't know what order the copy will do children of A/B so
+  # remove files so that only subdirs remain then all children can be
+  # marked incomplete.
+  sbox.simple_rm('A/B/lambda')
+  sbox.simple_commit()
+  sbox.simple_update()
+
   # We don't know whether copy will do E or F first, so make both
   # incomplete
-  svntest.actions.set_incomplete(sbox.ospath('A/B/E'), 1)
-  svntest.actions.set_incomplete(sbox.ospath('A/B/F'), 1)
+  svntest.actions.set_incomplete(sbox.ospath('A/B/E'), 2)
+  svntest.actions.set_incomplete(sbox.ospath('A/B/F'), 2)
 
   # Copy fails with no changes to wc
   svntest.actions.run_and_verify_svn(None, None,
@@ -5564,7 +5577,8 @@ def wc_wc_copy_incomplete(sbox):
                                      'copy',
                                      sbox.ospath('A/B/E'),
                                      sbox.ospath('A/B/E2'))
-  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
+  expected_status.remove('A/B/lambda')
   expected_status.tweak('A/B/E', 'A/B/F', status='! ')
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
@@ -5579,7 +5593,6 @@ def wc_wc_copy_incomplete(sbox):
       'A/B2'        : Item(status='A ', copied='+', wc_rev='-'),
       'A/B2/E'      : Item(status='! ', wc_rev='-'),
       'A/B2/F'      : Item(status='! ', wc_rev='-'),
-      'A/B2/lambda' : Item(status='  ', copied='+', wc_rev='-'),
       })
   ### Can't get this to work as copied status of E and F in 1.6
   ### entries tree doesn't match 1.7 status tree
@@ -5589,10 +5602,10 @@ def wc_wc_copy_incomplete(sbox):
   expected_output = svntest.wc.State(wc_dir, {
       'A/B2': Item(verb='Adding'),
       })
-  expected_status.tweak('A/B2', 'A/B2/lambda',
-                        status='  ', copied=None, wc_rev=2)
+  expected_status.tweak('A/B2',
+                        status='  ', copied=None, wc_rev=3)
   expected_status.tweak('A/B2/E', 'A/B2/F',
-                        status='! ', copied=None, wc_rev=2)
+                        status='! ', copied=None, wc_rev=3)
   ### E and F are status '!' but the test code ignores them?
   expected_status.remove('A/B2/E', 'A/B2/F')
   svntest.actions.run_and_verify_commit(wc_dir,
@@ -5600,8 +5613,8 @@ def wc_wc_copy_incomplete(sbox):
                                         expected_status,
                                         None, wc_dir)
   expected_status.add({
-      'A/B2/E'       : Item(status='! ', wc_rev=2),
-      'A/B2/F'       : Item(status='! ', wc_rev=2),
+      'A/B2/E'       : Item(status='! ', wc_rev=3),
+      'A/B2/F'       : Item(status='! ', wc_rev=3),
       })
 
   # Update makes things complete
@@ -5611,16 +5624,57 @@ def wc_wc_copy_incomplete(sbox):
       'A/B2/E/beta'  : Item(status='A '),
       'A/B2/F'       : Item(status='A '),
       })
-  expected_status.tweak(wc_rev=2, status='  ')
+  expected_status.tweak(wc_rev=3, status='  ')
   expected_status.add({
-      'A/B2/E/alpha' : Item(status='  ', wc_rev=2),
-      'A/B2/E/beta'  : Item(status='  ', wc_rev=2),
+      'A/B2/E/alpha' : Item(status='  ', wc_rev=3),
+      'A/B2/E/beta'  : Item(status='  ', wc_rev=3),
       })
   svntest.actions.run_and_verify_update(wc_dir,
                                         expected_output,
                                         None,
                                         expected_status)
 
+def three_nested_moves(sbox):
+  "three nested moves"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  svntest.actions.run_and_verify_svn(None, None, [], 'mv',
+                                     sbox.ospath('A/B'),
+                                     sbox.ospath('A/B2'))
+  svntest.actions.run_and_verify_svn(None, None, [], 'mv',
+                                     sbox.ospath('A/B2/E'),
+                                     sbox.ospath('A/B2/E2'))
+  svntest.actions.run_and_verify_svn(None, None, [], 'mv',
+                                     sbox.ospath('A/B2/E2/alpha'),
+                                     sbox.ospath('A/B2/E2/alpha2'))
+
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.add({
+      'A/B2'           : Item(status='  ', wc_rev=2),
+      'A/B2/E2'        : Item(status='  ', wc_rev=2),
+      'A/B2/E2/alpha2' : Item(status='  ', wc_rev=2),
+      'A/B2/E2/beta'   : Item(status='  ', wc_rev=2),
+      'A/B2/F'         : Item(status='  ', wc_rev=2),
+      'A/B2/lambda'    : Item(status='  ', wc_rev=2),
+      })
+  expected_status.remove('A/B', 'A/B/E', 'A/B/E/alpha', 'A/B/E/beta',
+                         'A/B/F', 'A/B/lambda')
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/B'            : Item(verb='Deleting'),
+    'A/B2'           : Item(verb='Adding'),
+    'A/B2/E'         : Item(verb='Deleting'),
+    'A/B2/E2'        : Item(verb='Adding'),
+    'A/B2/E2/alpha'  : Item(verb='Deleting'),
+    'A/B2/E2/alpha2' : Item(verb='Adding'),
+    })
+
+  svntest.actions.run_and_verify_commit(wc_dir,
+                                        expected_output,
+                                        expected_status,
+                                        None, wc_dir)
+
 ########################################################################
 # Run the tests
 
@@ -5734,6 +5788,7 @@ test_list = [ None,
               commit_copied_half_of_move,
               commit_deleted_half_of_move,
               wc_wc_copy_incomplete,
+              three_nested_moves,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/davautocheck.sh
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/davautocheck.sh?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/davautocheck.sh (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/davautocheck.sh Mon Jul 30 06:39:28 2012
@@ -292,9 +292,22 @@ $LOAD_MOD_AUTHZ_USER
 $LOAD_MOD_AUTHZ_HOST
 LoadModule          authz_svn_module "$MOD_AUTHZ_SVN"
 
+__EOF__
+
+if "$HTTPD" -v | grep '/2\.[012]' >/dev/null; then
+  cat >> "$HTTPD_CFG" <<__EOF__
 LockFile            lock
 User                $(id -un)
 Group               $(id -gn)
+__EOF__
+else
+  cat >> "$HTTPD_CFG" <<__EOF__
+# TODO: maybe uncomment this for prefork,worker MPMs only?
+# Mutex file:lock mpm-accept
+__EOF__
+fi
+
+cat >> "$HTTPD_CFG" <<__EOF__
 Listen              $HTTPD_PORT
 ServerName          localhost
 PidFile             "$HTTPD_PID"

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/depth_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/depth_tests.py?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/depth_tests.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/depth_tests.py Mon Jul 30 06:39:28 2012
@@ -1076,7 +1076,8 @@ def diff_in_depthy_wc(sbox):
     "___________________________________________________________________\n",
     "Deleted: foo\n",
     "## -1 +0,0 ##\n",
-    "-foo-val\n"]
+    "-foo-val\n",
+    "\\ No newline at end of property\n"]
 
   os.chdir(wc_empty)
 

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/diff_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/diff_tests.py?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/diff_tests.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/diff_tests.py Mon Jul 30 06:39:28 2012
@@ -57,6 +57,16 @@ def make_diff_header(path, old_tag, new_
     "+++ " + path_as_shown + "\t(" + new_tag + ")\n",
     ]
 
+def make_no_diff_deleted_header(path, old_tag, new_tag):
+  """Generate the expected diff header for a deleted file PATH when in
+  'no-diff-deleted' mode. (In that mode, no further details appear after the
+  header.) Return the header as an array of newline-terminated strings."""
+  path_as_shown = path.replace('\\', '/')
+  return [
+    "Index: " + path_as_shown + " (deleted)\n",
+    "===================================================================\n",
+    ]
+
 def make_git_diff_header(target_path, repos_relpath,
                          old_tag, new_tag, add=False, src_label=None,
                          dst_label=None, delete=False, text_changes=True,
@@ -146,15 +156,20 @@ def make_diff_prop_header(path):
     "___________________________________________________________________\n"
   ]
 
+def make_diff_prop_val(plus_minus, pval):
+  "Return diff for prop value PVAL, with leading PLUS_MINUS (+ or -)."
+  if len(pval) > 0 and pval[-1] != '\n':
+    return [plus_minus + pval + "\n","\\ No newline at end of property\n"]
+  return [plus_minus + pval]
+  
 def make_diff_prop_deleted(pname, pval):
   """Return a property diff for deletion of property PNAME, old value PVAL.
      PVAL is a single string with no embedded newlines.  Return the result
      as a list of newline-terminated strings."""
   return [
     "Deleted: " + pname + "\n",
-    "## -1 +0,0 ##\n",
-    "-" + pval + "\n"
-  ]
+    "## -1 +0,0 ##\n"
+  ] + make_diff_prop_val("-", pval)
 
 def make_diff_prop_added(pname, pval):
   """Return a property diff for addition of property PNAME, new value PVAL.
@@ -163,8 +178,7 @@ def make_diff_prop_added(pname, pval):
   return [
     "Added: " + pname + "\n",
     "## -0,0 +1 ##\n",
-    "+" + pval + "\n"
-  ]
+  ] + make_diff_prop_val("+", pval)
 
 def make_diff_prop_modified(pname, pval1, pval2):
   """Return a property diff for modification of property PNAME, old value
@@ -173,9 +187,7 @@ def make_diff_prop_modified(pname, pval1
   return [
     "Modified: " + pname + "\n",
     "## -1 +1 ##\n",
-    "-" + pval1 + "\n",
-    "+" + pval2 + "\n"
-  ]
+  ] + make_diff_prop_val("-", pval1) + make_diff_prop_val("+", pval2)
 
 ######################################################################
 # Diff output checker
@@ -1157,8 +1169,10 @@ def diff_base_to_repos(sbox):
     if not re_infoline.match(line):
       list2.append(line)
 
-  if list1 != list2:
-    raise svntest.Failure
+  # Two files in diff may be in any order.
+  list1 = svntest.verify.UnorderedOutput(list1)
+
+  svntest.verify.compare_and_display_lines('', '', list1, list2)
 
 
 #----------------------------------------------------------------------
@@ -1218,6 +1232,7 @@ def diff_deleted_in_head(sbox):
 
 
 #----------------------------------------------------------------------
+@Issue(2873)
 def diff_targets(sbox):
   "select diff targets"
 
@@ -2853,18 +2868,18 @@ def diff_with_depth(sbox):
   A_header = make_diff_header('A', "revision 1", "working copy")
   B_header = make_diff_header(B_path, "revision 1", "working copy")
 
-  expected_empty = svntest.verify.UnorderedOutput(dot_header + diff[:6])
-  expected_files = svntest.verify.UnorderedOutput(dot_header + diff[:6]
-                                                  + iota_header + diff[7:12])
-  expected_immediates = svntest.verify.UnorderedOutput(dot_header + diff[:6]
+  expected_empty = svntest.verify.UnorderedOutput(dot_header + diff[:7])
+  expected_files = svntest.verify.UnorderedOutput(dot_header + diff[:7]
+                                                  + iota_header + diff[8:14])
+  expected_immediates = svntest.verify.UnorderedOutput(dot_header + diff[:7]
                                                        + iota_header
-                                                       + diff[7:12]
-                                                       +  A_header + diff[8:18])
-  expected_infinity = svntest.verify.UnorderedOutput(dot_header + diff[:6]
+                                                       + diff[8:14]
+                                                       + A_header + diff[15:21])
+  expected_infinity = svntest.verify.UnorderedOutput(dot_header + diff[:7]
                                                        + iota_header
-                                                       + diff[7:12]
-                                                       +  A_header + diff[8:18]
-                                                       + B_header + diff[12:])
+                                                       + diff[8:14]
+                                                       + A_header + diff[15:21]
+                                                       + B_header + diff[22:])
 
   os.chdir(sbox.wc_dir)
 
@@ -2900,18 +2915,18 @@ def diff_with_depth(sbox):
   A_header = make_diff_header('A', "revision 1", "revision 2")
   B_header = make_diff_header(B_path, "revision 1", "revision 2")
 
-  expected_empty = svntest.verify.UnorderedOutput(dot_header + diff[:6])
-  expected_files = svntest.verify.UnorderedOutput(dot_header + diff[:6]
-                                                  + iota_header + diff[7:12])
-  expected_immediates = svntest.verify.UnorderedOutput(dot_header + diff[:6]
+  expected_empty = svntest.verify.UnorderedOutput(dot_header + diff[:7])
+  expected_files = svntest.verify.UnorderedOutput(dot_header + diff[:7]
+                                                  + iota_header + diff[8:14])
+  expected_immediates = svntest.verify.UnorderedOutput(dot_header + diff[:7]
                                                        + iota_header
-                                                       + diff[7:12]
-                                                       +  A_header + diff[8:18])
+                                                       + diff[8:14]
+                                                       + A_header + diff[15:21])
   expected_infinity = svntest.verify.UnorderedOutput(dot_header + diff[:6]
                                                        + iota_header
-                                                       + diff[7:12]
-                                                       +  A_header + diff[8:18]
-                                                       + B_header + diff[12:])
+                                                       + diff[8:14]
+                                                       + A_header + diff[15:21]
+                                                       + B_header + diff[22:])
 
   # Test repos-repos diff.
   svntest.actions.run_and_verify_svn(None, expected_empty, [],
@@ -2944,10 +2959,10 @@ def diff_with_depth(sbox):
     make_diff_prop_header(".") + \
     make_diff_prop_modified("foo1", "bar1", "baz1")
 
-  expected_empty = svntest.verify.UnorderedOutput(diff_wc_repos[43:])
-  expected_files = svntest.verify.UnorderedOutput(diff_wc_repos[29:])
-  expected_immediates = svntest.verify.UnorderedOutput(diff_wc_repos[11:22]
-                                                       +diff_wc_repos[29:])
+  expected_empty = svntest.verify.UnorderedOutput(diff_wc_repos[49:])
+  expected_files = svntest.verify.UnorderedOutput(diff_wc_repos[33:])
+  expected_immediates = svntest.verify.UnorderedOutput(diff_wc_repos[13:26]
+                                                       +diff_wc_repos[33:])
   expected_infinity = svntest.verify.UnorderedOutput(diff_wc_repos[:])
 
   svntest.actions.run_and_verify_svn(None, None, [],
@@ -3575,6 +3590,9 @@ def diff_git_empty_files(sbox):
   ] + make_git_diff_header(iota_path, "iota", "revision 2", "working copy",
                            delete=True, text_changes=False)
 
+  # Two files in diff may be in any order.
+  expected_output = svntest.verify.UnorderedOutput(expected_output)
+
   svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
                                      '--git', wc_dir)
 
@@ -3615,6 +3633,9 @@ def diff_git_with_props(sbox):
                     make_diff_prop_header("iota") + \
                     make_diff_prop_added("svn:keywords", "Id")
 
+  # Files in diff may be in any order.
+  expected_output = svntest.verify.UnorderedOutput(expected_output)
+
   svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
                                      '--git', wc_dir)
 

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/externals_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/externals_tests.py?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/externals_tests.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/externals_tests.py Mon Jul 30 06:39:28 2012
@@ -225,7 +225,7 @@ def change_external_expect_error(path, n
   but expect to get an error message that matches EXPECTED_ERR."""
 
   svntest.actions.set_prop('svn:externals', new_val, path,
-                           expected_err=expected_err)
+                           expected_re_string=expected_err)
 
 
 def probe_paths_exist(paths):
@@ -706,6 +706,13 @@ def disallow_dot_or_dotdot_directory_ref
   if not external_urls: external_urls = list(external_url_for.values())
   externals_value_8 = external_urls.pop() + " /foo \n"
   if not external_urls: external_urls = list(external_url_for.values())
+  if svntest.main.is_os_windows():
+    externals_value_9 = external_urls.pop() + " D:/foo\n"
+    if not external_urls: external_urls = list(external_url_for.values())
+    externals_value_10 = external_urls.pop() + " D:\\foo\n"
+    if not external_urls: external_urls = list(external_url_for.values())
+    externals_value_11 = external_urls.pop() + " D:foo\n"
+    if not external_urls: external_urls = list(external_url_for.values())
 
   set_externals_for_path_expect_error(B_path, externals_value_1)
   set_externals_for_path_expect_error(G_path, externals_value_2)
@@ -715,6 +722,10 @@ def disallow_dot_or_dotdot_directory_ref
   set_externals_for_path_expect_error(B_path, externals_value_6)
   set_externals_for_path_expect_error(G_path, externals_value_7)
   set_externals_for_path_expect_error(H_path, externals_value_8)
+  if svntest.main.is_os_windows():
+    set_externals_for_path_expect_error(B_path, externals_value_9)
+    set_externals_for_path_expect_error(B_path, externals_value_10)
+    set_externals_for_path_expect_error(B_path, externals_value_11)
 
 
 #----------------------------------------------------------------------
@@ -1877,7 +1888,7 @@ def exclude_externals(sbox):
                                         None, None, None, None, False,
                                         '--set-depth', 'infinity', wc_dir)
 
-def file_externals_different_repos(sbox):
+def file_externals_different_url(sbox):
   "update file externals via different url"
 
   sbox.build()
@@ -1896,30 +1907,40 @@ def file_externals_different_repos(sbox)
                       r2_url + '/iota  r2-e-2\n' +
                       '^/iota  rr-e-1\n', '')
 
+  # All file externals appear in the working copy, with normalised URLs.
   expected_output = svntest.wc.State(wc_dir, {
     'r1-e-1'            : Item(status='A '),
     'r1-e-2'            : Item(status='A '),
+    'r2-e-1'            : Item(status='A '),
+    'r2-e-2'            : Item(status='A '),
     'rr-e-1'            : Item(status='A '),
   })
 
-  # The externals from r2 should fail, but currently pass.
-  # This creates a wc.db inconsistency
   svntest.actions.run_and_verify_update(wc_dir,
-                                        expected_output, None, None,
-                                        'svn: warning: W200007: Unsupported.*')
+                                        expected_output, None, None, None)
+
+  # Verify that all file external URLs are descendants of r1_url
+  for e in ['r1-e-1', 'r1-e-2', 'r2-e-1', 'r2-e-2', 'rr-e-1']:
+    actions.run_and_verify_info([{'Repository Root' : r1_url}],
+                                os.path.join(sbox.wc_dir, e))
+    
 
   svntest.actions.run_and_verify_svn(None, None, [],
                                      'relocate', r1_url, r2_url, wc_dir)
 
 
+  # URLs of existing file externals are silently rewritten
   expected_output = svntest.wc.State(wc_dir, {
-    'r2-e-1'            : Item(status='A '),
-    'r2-e-2'            : Item(status='A '),
   })
 
   svntest.actions.run_and_verify_update(wc_dir,
-                                        expected_output, None, None,
-                                        'svn: warning: W200007: Unsupported.*')
+                                        expected_output, None, None, None)
+
+  # Verify that all file external URLs are descendants of r2_url
+  for e in ['r1-e-1', 'r1-e-2', 'r2-e-1', 'r2-e-2', 'rr-e-1']:
+    actions.run_and_verify_info([{'Repository Root' : r2_url}],
+                                os.path.join(sbox.wc_dir, e))
+
 
 def file_external_in_unversioned(sbox):
   "file external in unversioned dir"
@@ -2640,6 +2661,197 @@ def include_immediate_dir_externals(sbox
     None, '--include-externals', '--depth=immediates', X)
 
 
+@Issue(4085)
+@XFail()
+def shadowing(sbox):
+  "external shadows an existing dir"
+
+  sbox.build(read_only=True)
+  wc_dir = sbox.wc_dir
+
+  # Setup external: /A/B/F as 'C' child of /A
+  externals_prop = "^/A/B/F C\n"
+
+  raised = False
+  try:
+    change_external(sbox.ospath('A'), externals_prop, commit=False)
+  except:
+    raised = True
+  if not raised:
+    raise svntest.Failure("Creating conflicting child 'C' of 'A' didn't error")
+
+# Test for issue #4093 'remapping a file external can segfault due to
+# "deleted" props'.
+@Issue(4093)
+def remap_file_external_with_prop_del(sbox):
+  "file external remap segfaults due to deleted props"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  A_path  = os.path.join(wc_dir, "A")
+  mu_path = os.path.join(wc_dir, "A", "mu")
+
+  # Add a property to A/mu
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'ps', 'propname', 'propval', mu_path)
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'commit', '-m', 'New property on a file',
+                                     wc_dir)
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+
+  # Add a new file external A/external pointing to ^/A/mu
+  externals_prop = "^/A/mu external\n"
+  change_external(A_path, externals_prop)
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+
+  # Change A/external to point to ^/iota
+  externals_prop = "^/iota external\n"
+  change_external(A_path, externals_prop)
+
+  # Now update to bring the new external down.
+  # This previously segfaulted as described in
+  # http://subversion.tigris.org/issues/show_bug.cgi?id=4093#desc1
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+
+
+# Test for issue #4053 'svn:externals with explicit rev checks out HEAD'
+@Issue(4053)
+def dir_external_with_dash_r_only(sbox):
+  "whether '-r1 ^/A B' updates properly"
+  # svntest.factory.make(sbox,"""
+  #   echo 'newer alpha' > A/B/E/alpha
+  #   svn ci
+  #   svn ps svn:externals ' -r1 ^/A/B/E E_ext' .
+  #   svn up
+  #   # ^ move the 'status.tweak(wc_rev=2)' above the 'add()' call
+  #   svn info E_ext
+  #   # ^ change the 'svn info' call to
+  #   #  expected_info = { 'Revision': '1' }
+  #   #  actions.run_and_verify_info([expected_info], E_ext)
+  #   """)
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  url = sbox.repo_url
+
+  A_B_E_alpha = os.path.join(wc_dir, 'A', 'B', 'E', 'alpha')
+  E_ext = os.path.join(wc_dir, 'E_ext')
+
+  # echo 'newer alpha' > A/B/E/alpha
+  main.file_write(A_B_E_alpha, 'newer alpha\n')
+
+  # svn ci
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/B/E/alpha'       : Item(verb='Sending'),
+  })
+
+  expected_status = actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/B/E/alpha', wc_rev='2')
+
+  actions.run_and_verify_commit(wc_dir, expected_output, expected_status,
+    None, wc_dir)
+
+  # svn ps svn:externals ' -r1 ^/A/B/E E_ext' .
+  expected_stdout = ["property 'svn:externals' set on '" + wc_dir + "'\n"]
+
+  actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0, 'ps',
+    'svn:externals', ' -r1 ^/A/B/E E_ext', wc_dir)
+
+  # svn up
+  expected_output = svntest.wc.State(wc_dir, {
+    'E_ext/beta'        : Item(status='A '),
+    'E_ext/alpha'       : Item(status='A '),
+  })
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+    'E_ext'             : Item(),
+    'E_ext/alpha'       : Item(contents="This is the file 'alpha'.\n"),
+    'E_ext/beta'        : Item(contents="This is the file 'beta'.\n"),
+  })
+  expected_disk.tweak('A/B/E/alpha', contents='newer alpha\n')
+
+  expected_status.tweak(wc_rev='2')
+  expected_status.tweak('', status=' M')
+  expected_status.add({
+    'E_ext'             : Item(status='X '),
+  })
+
+  actions.run_and_verify_update(wc_dir, expected_output, expected_disk,
+    expected_status, None, None, None, None, None, False, wc_dir)
+
+  # svn info E_ext/alpha
+  expected_info = { 'Revision': '1' }
+  actions.run_and_verify_info([expected_info], E_ext)
+
+# Test for issue #4123 'URL-to-WC copy of externals fails on Windows'
+@Issue(4123)
+def url_to_wc_copy_of_externals(sbox):
+  "url-to-wc copy of externals"
+
+  sbox.build()
+
+  wc_dir = sbox.wc_dir
+  repo_url = sbox.repo_url
+
+  # Create an external A/C/external pointing to ^/A/D/G.
+  svntest.actions.run_and_verify_svn(None, None, [], 'ps',
+                                     'svn:externals', '^/A/D/G external',
+                                     os.path.join(wc_dir, 'A', 'C'))
+  svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
+                                     'create an external', wc_dir)
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+
+  # Copy ^/A/C to External-WC-to-URL-Copy.
+  #
+  # Previously this failed with:
+  #   >svn copy ^^/A/C External-WC-to-URL-Copy
+  #    U   External-WC-to-URL-Copy
+  #   
+  #   Fetching external item into 'External-WC-to-URL-Copy\external':
+  #   A    External-WC-to-URL-Copy\external\pi
+  #   A    External-WC-to-URL-Copy\external\rho
+  #   A    External-WC-to-URL-Copy\external\tau
+  #   Checked out external at revision 2.
+  #
+  #   Checked out revision 2.
+  #   ..\..\..\subversion\libsvn_client\copy.c:2249: (apr_err=720005)
+  #   ..\..\..\subversion\libsvn_client\copy.c:1857: (apr_err=720005)
+  #   ..\..\..\subversion\libsvn_client\copy.c:1857: (apr_err=720005)
+  #   ..\..\..\subversion\libsvn_client\copy.c:1737: (apr_err=720005)
+  #   ..\..\..\subversion\libsvn_client\copy.c:1737: (apr_err=720005)
+  #   ..\..\..\subversion\libsvn_client\copy.c:1537: (apr_err=720005)
+  #   ..\..\..\subversion\libsvn_subr\io.c:3416: (apr_err=720005)
+  #   svn: E720005: Can't move 'C:\SVN\src-trunk-3\Debug\subversion\tests\
+  #   cmdline\svn-test-work\working_copies\externals_tests-41\.svn\tmp\
+  #   svn-F9E2C0EC' to 'C:\SVN\src-trunk-3\Debug\subversion\tests\cmdline\
+  #   svn-test-work\working_copies\externals_tests-41\External-WC-to-URL-Copy':
+  #   Access is denied.
+  external_root_path = os.path.join(wc_dir, "External-WC-to-URL-Copy")
+  external_ex_path = os.path.join(wc_dir, "External-WC-to-URL-Copy",
+                                  "external")
+  external_pi_path = os.path.join(wc_dir, "External-WC-to-URL-Copy",
+                                  "external", "pi")
+  external_rho_path = os.path.join(wc_dir, "External-WC-to-URL-Copy",
+                                   "external", "rho")
+  external_tau_path = os.path.join(wc_dir, "External-WC-to-URL-Copy",
+                                   "external", "tau")
+  expected_stdout = verify.UnorderedOutput([
+    "\n",
+    " U   " + external_root_path + "\n",
+    "Fetching external item into '" + external_ex_path + "':\n",
+    "A    " + external_pi_path + "\n",
+    "A    " + external_rho_path + "\n",
+    "A    " + external_tau_path + "\n",
+    "Checked out external at revision 2.\n",
+    "Checked out revision 2.\n",
+    "A         " + external_root_path + "\n"
+  ])
+  exit_code, stdout, stderr = svntest.actions.run_and_verify_svn2(
+    "OUTPUT", expected_stdout, [], 0, 'copy', repo_url + '/A/C',
+    os.path.join(wc_dir, 'External-WC-to-URL-Copy'))
+
 ########################################################################
 # Run the tests
 
@@ -2678,11 +2890,15 @@ test_list = [ None,
               incoming_file_on_file_external,
               incoming_file_external_on_file,
               exclude_externals,
-              file_externals_different_repos,
+              file_externals_different_url,
               file_external_in_unversioned,
               copy_file_externals,
               include_externals,
               include_immediate_dir_externals,
+              shadowing,
+              remap_file_external_with_prop_del,
+              dir_external_with_dash_r_only,
+              url_to_wc_copy_of_externals,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout Mon Jul 30 06:39:28 2012
@@ -38,6 +38,10 @@ usage: 1. log [PATH][@REV]
     svn log http://www.example.com/repo/project foo.c bar.c
     svn log http://www.example.com/repo/project@50 foo.c bar.c
 
+    This command shows the log entry for the revision the branch
+    ^/branches/foo was created in:
+      svn log --stop-on-copy --limit 1 -r0:HEAD ^/branches/foo
+
 Valid options:
   -r [--revision] ARG      : ARG (some commands also take ARG1:ARG2 range)
                              A revision argument can be one of:
@@ -157,9 +161,10 @@ Valid options:
   --ignore-ancestry        : ignore ancestry when calculating merges
   --force                  : force operation to run
   --accept ARG             : specify automatic conflict resolution action
-                             ('postpone', 'base', 'mine-conflict',
+                             ('postpone', 'working', 'base', 'mine-conflict',
                              'theirs-conflict', 'mine-full', 'theirs-full',
                              'edit', 'launch')
+                             (shorthand: 'p', 'mc', 'tc', 'mf', 'tf', 'e', 'l')
 
 Global options:
   --username ARG           : specify a username ARG

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/input_validation_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/input_validation_tests.py?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/input_validation_tests.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/input_validation_tests.py Mon Jul 30 06:39:28 2012
@@ -151,18 +151,23 @@ def invalid_log_targets(sbox):
 def invalid_merge_args(sbox):
   "invalid arguments for 'merge'"
   sbox.build(read_only=True)
-  run_and_verify_svn_in_wc(sbox, "svn: E195002: A working copy merge source needs "
-                           "an explicit revision", 'merge', 'iota', '^/')
-  for (src, target) in [('iota@HEAD', '^/'), ('iota@BASE', 'file://')]:
-    run_and_verify_svn_in_wc(sbox, "svn: E205000: Merge sources must both be either "
-                             "paths or URLs", 'merge', src, target)
-  run_and_verify_svn_in_wc(sbox, "svn: E155010: Path '.*' does not exist",
-                           'merge', 'iota@BASE', 'iota@HEAD', 'nonexistent')
+  for args in [('iota', 'A/mu@HEAD'),
+               ('iota@BASE', 'A/mu@HEAD')]:
+    run_and_verify_svn_in_wc(sbox, "svn: E195002: .* working copy .* revision",
+                             'merge', *args)
+  for args in [(sbox.repo_url, 'A@1', 'A'),
+               ('^/A', 'A@HEAD', 'A'),
+               ('A@HEAD', '^/A', 'A'),
+               ('A@HEAD', '^/A')]:
+    run_and_verify_svn_in_wc(sbox, "svn: E205000: Merge sources must both "
+                             "be either paths or URLs", 'merge', *args)
+  run_and_verify_svn_in_wc(sbox, "svn: E155010: .* was not found",
+                           'merge', '^/@0', '^/@1', 'nonexistent')
   run_and_verify_svn_in_wc(sbox, "svn: E205000: Too many arguments given",
                           'merge', '-c42', '^/A/B', '^/A/C', 'iota')
   run_and_verify_svn_in_wc(sbox, "svn: E205000: Cannot specify a revision range with" +
                            " two URLs", 'merge', '-c42', '^/mu', '^/')
-  run_and_verify_svn_in_wc(sbox, "svn: E155010: Path '.*' does not exist",
+  run_and_verify_svn_in_wc(sbox, "svn: E155010: .* was not found",
                            'merge', '-c42', '^/mu', 'nonexistent')
 
 def invalid_wcpath_upgrade(sbox):

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/lock_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/lock_tests.py?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/lock_tests.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/lock_tests.py Mon Jul 30 06:39:28 2012
@@ -1172,6 +1172,8 @@ def repos_lock_with_info(sbox):
 
 
 #----------------------------------------------------------------------
+@Issue(4126)
+@Skip(svntest.main.is_ra_type_dav_serf) # Issue 4126 unpredictable result
 def unlock_already_unlocked_files(sbox):
   "(un)lock set of files, one already (un)locked"
 

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/log_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/log_tests.py?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/log_tests.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/log_tests.py Mon Jul 30 06:39:28 2012
@@ -34,6 +34,7 @@ from svntest import wc
 from svntest.main import server_has_mergeinfo
 from svntest.main import SVN_PROP_MERGEINFO
 from merge_tests import set_up_branch
+from diff_tests import make_diff_header, make_no_diff_deleted_header
 
 # (abbreviation)
 Skip = svntest.testcase.Skip_deco
@@ -178,7 +179,8 @@ def guarantee_repos_and_wc(sbox):
   to test the code"""
   svntest.main.file_write(msg_file, msg)
   svntest.main.file_append(iota_path, "8")
-  svntest.main.file_append(rho_path, "8")
+  svntest.main.file_append(rho_path, "88") # More than one char so libmagic
+                                           # treats it as text.
   svntest.main.run_svn(None, 'add', rho_path)
   svntest.main.run_svn(None,
                        'ci', '-F', msg_file)
@@ -216,7 +218,7 @@ def guarantee_repos_and_wc(sbox):
 
 def merge_history_repos(sbox):
   """Make a repos with varied and interesting merge history, similar
-  to the repos found at: log_tests_data/merge_history_dump.png"""
+  to the repos found at: log_tests_data/merge_history_repo.png"""
 
   upsilon_path = os.path.join('A', 'upsilon')
   omicron_path = os.path.join('blocked', 'omicron')
@@ -279,7 +281,6 @@ def merge_history_repos(sbox):
   # From branch_a to trunk: add 'upsilon' and modify 'iota' and 'mu'.
   #
   # Mergeinfo changes on /trunk:
-  #    Merged /trunk:r2
   #    Merged /branches/a:r3-5
   os.chdir('trunk')
   svntest.main.run_svn(None, 'merge', os.path.join('..', branch_a) + '@HEAD')
@@ -361,8 +362,6 @@ def merge_history_repos(sbox):
   # More merging - r14
   #
   # Mergeinfo changes on /trunk:
-  #    Reverse-merged /trunk:r2
-  #    Merged /trunk:r3-9
   #    Merged /branches/a:r6,8-11
   #    Merged /branches/b:r10-13
   os.chdir('trunk')
@@ -395,8 +394,7 @@ def merge_history_repos(sbox):
   # Merge branches/c to trunk, which produces a conflict - r17
   #
   # Mergeinfo changes on /trunk:
-  #    Merged /trunk:r2
-  #    Merged /branches/c:r3-16
+  #    Merged /branches/c:r5-16
   os.chdir('trunk')
   svntest.main.run_svn(None, 'merge', '--allow-mixed-revisions',
                        os.path.join('..', branch_c) + '@HEAD')
@@ -424,7 +422,7 @@ class SVNLogParseError(Exception):
   pass
 
 
-def parse_log_output(log_lines):
+def parse_log_output(log_lines, with_diffs=False):
   """Return a log chain derived from LOG_LINES.
   A log chain is a list of hashes; each hash represents one log
   message, in the order it appears in LOG_LINES (the first log
@@ -438,6 +436,7 @@ def parse_log_output(log_lines):
      'date'     ===>  string
      'msg'      ===>  string  (the log message itself)
      'lines'    ===>  number  (so that it may be checked against rev)
+
   If LOG_LINES contains changed-path information, then the hash
   also contains
 
@@ -451,7 +450,11 @@ def parse_log_output(log_lines):
 
      'reverse_merges'   ===> list of reverse-merging revisions that resulted
   in this log being part of the list of messages.
-     """
+
+  If LOG_LINES contains diffs and WITH_DIFFS=True, then the hash also contains
+
+     'diff_lines'  ===> list of strings  (diffs)
+  """
 
   # Here's some log output to look at while writing this function:
 
@@ -566,6 +569,20 @@ def parse_log_output(log_lines):
       for line in log_lines[0:lines]:
         msg += line
       del log_lines[0:lines]
+
+      # Maybe accumulate a diff.
+      # If there is a diff, there is a blank line before and after it.
+      if with_diffs and len(log_lines) >= 2 and log_lines[0] == '\n':
+        log_lines.pop(0)
+        diff_lines = []
+        while len(log_lines) and log_lines[0] != msg_separator:
+          diff_lines.append(log_lines.pop(0))
+        if diff_lines[-1] == '\n':
+          diff_lines.pop()
+        else:
+          raise SVNLogParseError("no blank line after diff in log")
+        this_item['diff_lines'] = diff_lines
+
     elif this_line == msg_separator:
       if this_item:
         this_item['msg'] = msg
@@ -676,6 +693,42 @@ def check_log_chain(chain, revlist, path
                             missing_revs, chain)
 
 
+def parse_diff(output):
+  """Return a set containing the various diff bits, broken up by file."""
+
+  diff_set = []
+  current_diff = []
+  for line in output:
+    if line.startswith('Index: ') and current_diff:
+      diff_set.append(current_diff)
+      current_diff = []
+    current_diff.append(line)
+  diff_set.append(current_diff)
+
+  return diff_set
+
+
+def setify(diff_list):
+  """Take a list of lists and make it a set of tuples."""
+  s = set()
+  for diff in diff_list:
+    s.add(tuple(diff))
+  return s
+
+
+def compare_diff_output(expected_diffs, output):
+  """Compare the diffs in EXPECTED_DIFFS (which is a Python set) with the
+  text in OUTPUT, remembering that there is no canonical ordering for diffs."""
+
+  diffs = parse_diff(output)
+  diffs = setify(diffs)
+  expected_diffs = setify(expected_diffs)
+
+  if diffs.issubset(expected_diffs) and diffs.issuperset(expected_diffs):
+    return
+
+  raise svntest.Failure("Diffs not equal")
+
 
 ######################################################################
 # Tests
@@ -2093,6 +2146,78 @@ def merge_sensitive_log_copied_path_inhe
   log_chain = parse_log_output(out)
   check_merge_results(log_chain, expected_merges)
 
+#----------------------------------------------------------------------
+def log_diff(sbox):
+  "'svn log --diff'"
+
+  guarantee_repos_and_wc(sbox)
+
+  was_cwd = os.getcwd()
+  os.chdir(sbox.wc_dir)
+
+  exit_code, output, err = svntest.actions.run_and_verify_svn(None, None, [],
+                                                              'log', '--diff')
+  os.chdir(was_cwd)
+
+  for line in output:
+    if line.startswith('Index:'):
+      break
+  else:
+    raise SVNLogParseError("no diffs found in log output")
+
+  # After a copy, a log of the copy destination used to fail because the
+  # diff tried to use the head-revision URL with the old revision numbers
+  # without using the correct peg revision.
+
+  sbox.simple_copy('A', 'A2')
+  sbox.simple_commit()
+
+  os.chdir(sbox.wc_dir)
+  exit_code, output, err = svntest.actions.run_and_verify_svn(None, None, [],
+                                                              'log', '--diff',
+                                                              '-r10:8', 'A2')
+  os.chdir(was_cwd)
+
+  r9diff = [ make_no_diff_deleted_header('A2/B/E/alpha', 8, 9),
+              make_diff_header('A2/B/E/beta', 'revision 8', 'revision 9')
+               + [ "@@ -1 +1,2 @@\n",
+                   " This is the file 'beta'.\n",
+                   "+9\n",
+                   "\ No newline at end of file\n",
+                 ]
+           ]
+  r8diff = [ make_diff_header('A2/D/G/rho', 'revision 0', 'revision 8')
+              + [ "@@ -0,0 +1 @@\n",
+                  "+88\n",
+                  "\ No newline at end of file\n",
+                ]
+           ]
+  log_chain = parse_log_output(output, with_diffs=True)
+  if len(log_chain) != 3:
+    raise SVNLogParseError("%d logs found, 3 expected" % len(log_chain))
+  compare_diff_output(r9diff, log_chain[1]['diff_lines'])
+  compare_diff_output(r8diff, log_chain[2]['diff_lines'])
+
+def log_xml_old(sbox):
+  "log --xml shows kind for old style repository"
+
+  sbox.build(minor_version=5)
+
+  sbox.simple_copy('A/B', 'A/B2')
+  sbox.simple_rm('A/B/lambda', 'A/B/E', 'A/B2/lambda', 'A/B2/E')
+  sbox.simple_commit()
+
+  os.chdir(sbox.wc_dir)
+  paths=[{'/A/B/E'       : [{'kind':'dir',  'action':'D'}],
+          '/A/B/lambda'  : [{'kind':'file', 'action':'D'}],
+          '/A/B2'        : [{'kind':'dir',  'action':'A'}],
+          '/A/B2/E'      : [{'kind':'dir',  'action':'D'}],
+          '/A/B2/lambda' : [{'kind':'file', 'action':'D'}]}]
+  svntest.actions.run_and_verify_log_xml(args=['-r', '2', '-v'],
+                                         expected_paths=paths)
+
+
+
 ########################################################################
 # Run the tests
 
@@ -2133,6 +2258,8 @@ test_list = [ None,
               log_with_unrelated_peg_and_operative_revs,
               log_on_nonexistent_path_and_valid_rev,
               merge_sensitive_log_copied_path_inherited_mergeinfo,
+              log_diff,
+              log_xml_old,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/log_tests_data/merge_history_repo.png
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/log_tests_data/merge_history_repo.png?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
Binary files - no diff available.

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/merge_authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/merge_authz_tests.py?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/merge_authz_tests.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/merge_authz_tests.py Mon Jul 30 06:39:28 2012
@@ -73,7 +73,10 @@ from svntest.actions import inject_confl
 #         This is *not* a full test of issue #2829, see also merge_tests.py,
 #         search for "2829".  This tests the problem where a merge adds a path
 #         with a missing sibling and so needs its own explicit mergeinfo.
-@Issues(2893,2997,2829)
+#
+# #4056 - Don't record non-inheritable mergeinfo if missing subtrees are not
+#         touched by the full-depth diff
+@Issues(2893,2997,2829,4056)
 @SkipUnless(svntest.main.server_has_mergeinfo)
 @Skip(svntest.main.is_ra_type_file)
 def mergeinfo_and_skipped_paths(sbox):
@@ -393,10 +396,54 @@ def mergeinfo_and_skipped_paths(sbox):
 
   # Merge -r7:9 to the restricted WC's A_COPY_2/D/H.
   #
+  # r9 adds a path, 'A_COPY_2/D/H/zeta', which has a missing sibling 'psi',
+  # but since 'psi' is untouched by the merge it isn't skipped, and since it
+  # isn't skipped, its parent 'A_COPY_2/D/H' won't get non-inheritable
+  # mergeinfo set on it to describe the merge, so none of the parent's
+  # children will get explicit mergeinfo -- see issue #4056.
+  expected_output = wc.State(A_COPY_2_H_path, {
+    'omega' : Item(status='U '),
+    'zeta'  : Item(status='A '),
+    })
+  expected_mergeinfo_output = wc.State(A_COPY_2_H_path, {
+    ''      : Item(status=' U'),
+    'omega' : Item(status=' U'),
+    })
+  expected_elision_output = wc.State(A_COPY_2_H_path, {
+    'omega' : Item(status=' U'),
+    })
+  expected_status = wc.State(A_COPY_2_H_path, {
+    ''      : Item(status=' M', wc_rev=8),
+    'chi'   : Item(status='  ', wc_rev=8),
+    'omega' : Item(status='M ', wc_rev=8),
+    'zeta'  : Item(status='A ', copied='+', wc_rev='-'),
+    })
+  expected_disk = wc.State('', {
+    ''      : Item(props={SVN_PROP_MERGEINFO : '/A/D/H:8-9'}),
+    'omega' : Item("New content"),
+    'chi'   : Item("This is the file 'chi'.\n"),
+    'zeta'  : Item("This is the file 'zeta'.\n"),
+    })
+  expected_skip = wc.State(A_COPY_2_H_path, {})
+  svntest.actions.run_and_verify_merge(A_COPY_2_H_path, '7', '9',
+                                       sbox.repo_url + '/A/D/H', None,
+                                       expected_output,
+                                       expected_mergeinfo_output,
+                                       expected_elision_output,
+                                       expected_disk,
+                                       expected_status,
+                                       expected_skip,
+                                       None, None, None, None,
+                                       None, 1, 0)
+
+  # Merge -r4:9 to the restricted WC's A_COPY_2/D/H.
+  #
   # r9 adds a path, 'A_COPY_2/D/H/zeta', which has a parent with
-  # non-inheritable mergeinfo (due to the fact 'A_COPY_2/D/H/psi' is missing).
-  # 'A_COPY_2/D/H/zeta' must therefore get its own explicit mergeinfo from
-  # this merge.
+  # non-inheritable mergeinfo (due to the fact 'A_COPY_2/D/H/psi' is missing
+  # and skipped). 'A_COPY_2/D/H/zeta' must therefore get its own explicit
+  # mergeinfo from this merge.
+  svntest.actions.run_and_verify_svn(None, None, [], 'revert', '--recursive',
+                                     wc_restricted)  
   expected_output = wc.State(A_COPY_2_H_path, {
     'omega' : Item(status='U '),
     'zeta'  : Item(status='A '),
@@ -415,15 +462,17 @@ def mergeinfo_and_skipped_paths(sbox):
     'zeta'  : Item(status='A ', copied='+', wc_rev='-'),
     })
   expected_disk = wc.State('', {
-    ''      : Item(props={SVN_PROP_MERGEINFO : '/A/D/H:8-9*'}),
+    ''      : Item(props={SVN_PROP_MERGEINFO : '/A/D/H:5-9*'}),
     'omega' : Item("New content",
-                   props={SVN_PROP_MERGEINFO : '/A/D/H/omega:8-9'}),
+                   props={SVN_PROP_MERGEINFO : '/A/D/H/omega:5-9'}),
     'chi'   : Item("This is the file 'chi'.\n"),
     'zeta'  : Item("This is the file 'zeta'.\n",
                    props={SVN_PROP_MERGEINFO : '/A/D/H/zeta:9'}),
     })
-  expected_skip = wc.State(A_COPY_2_H_path, {})
-  svntest.actions.run_and_verify_merge(A_COPY_2_H_path, '7', '9',
+  expected_skip = wc.State(A_COPY_2_H_path, {
+    'psi' : Item(),
+    })
+  svntest.actions.run_and_verify_merge(A_COPY_2_H_path, '4', '9',
                                        sbox.repo_url + '/A/D/H', None,
                                        expected_output,
                                        expected_mergeinfo_output,

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/merge_reintegrate_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/merge_reintegrate_tests.py?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/merge_reintegrate_tests.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/merge_reintegrate_tests.py Mon Jul 30 06:39:28 2012
@@ -2435,7 +2435,7 @@ def reintegrate_replaced_source(sbox):
   # Using cherrypick merges, simulate a series of sync merges from A to
   # A_COPY with a replace of A_COPY along the way.
   #
-  # r6 - Merge r3 from A to A_COPY
+  # r7 - Merge r3 from A to A_COPY
   svntest.main.run_svn(None, 'up', wc_dir)
   svntest.main.run_svn(None, 'merge', sbox.repo_url + '/A', A_COPY_path,
                        '-c3')
@@ -2542,6 +2542,46 @@ def reintegrate_replaced_source(sbox):
                                        [], None, None, None, None, True, True,
                                        '--reintegrate', A_path)
   
+#----------------------------------------------------------------------
+@SkipUnless(svntest.main.is_posix_os)
+@Issue(4052)
+def reintegrate_symlink_deletion(sbox):
+  "reintegrate symlink deletion"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  ## path vars
+  A_path = sbox.ospath('A')
+  A_omicron_path = sbox.ospath('A/omicron')
+  mu_path = sbox.ospath('A/mu')
+  A_COPY_path = sbox.ospath('A_COPY')
+  A_COPY_omicron_path = sbox.ospath('A_COPY/omicron')
+  A_url = sbox.repo_url + "/A"
+  A_COPY_url = sbox.repo_url + "/A_COPY"
+
+  ## add symlink
+  os.symlink(mu_path, A_omicron_path)
+  sbox.simple_add('A/omicron')
+  sbox.simple_commit(message='add symlink')
+
+  ## branch
+  sbox.simple_repo_copy('A', 'A_COPY')
+  sbox.simple_update()
+
+  ## branch rm
+  sbox.simple_rm('A_COPY/omicron')
+  sbox.simple_commit(message='remove symlink on branch')
+
+  ## Note: running update at this point avoids the bug.
+
+  ## reintegrate
+  # ### TODO: verify something here
+  svntest.main.run_svn(None, 'merge', '--reintegrate',
+                       A_COPY_url, A_path)
+
+
+
 ########################################################################
 # Run the tests
 
@@ -2565,6 +2605,7 @@ test_list = [ None,
               reintegrate_creates_bogus_mergeinfo,
               no_source_subtree_mergeinfo,
               reintegrate_replaced_source,
+              reintegrate_symlink_deletion,
              ]
 
 if __name__ == '__main__':