You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2012/11/11 21:24:21 UTC

svn commit: r1408109 [2/2] - in /subversion/branches/tree-read-api: ./ subversion/bindings/javahl/native/ subversion/bindings/swig/perl/native/ subversion/bindings/swig/ruby/svn/ subversion/bindings/swig/ruby/test/ subversion/bindings/swig/ruby/test/te...

Modified: subversion/branches/tree-read-api/subversion/libsvn_wc/wc_db_wcroot.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_wc/wc_db_wcroot.c?rev=1408109&r1=1408108&r2=1408109&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_wc/wc_db_wcroot.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_wc/wc_db_wcroot.c Sun Nov 11 20:24:17 2012
@@ -419,7 +419,7 @@ svn_wc__db_wcroot_parse_local_abspath(sv
   svn_wc__db_wcroot_t *probe_wcroot;
   svn_wc__db_wcroot_t *found_wcroot = NULL;
   const char *scan_abspath;
-  svn_sqlite__db_t *sdb;
+  svn_sqlite__db_t *sdb = NULL;
   svn_boolean_t moved_upwards = FALSE;
   svn_boolean_t always_check = FALSE;
   int wc_format = 0;
@@ -763,7 +763,8 @@ try_symlink_as_dir:
                                        scratch_pool));
               /* This handle was opened in this function but is not going
                  to be used further so close it. */
-              SVN_ERR(svn_sqlite__close(sdb));
+              if (sdb)
+                SVN_ERR(svn_sqlite__close(sdb));
               goto try_symlink_as_dir;
             }
         }

Modified: subversion/branches/tree-read-api/subversion/svn/mergeinfo-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/svn/mergeinfo-cmd.c?rev=1408109&r1=1408108&r2=1408109&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/svn/mergeinfo-cmd.c (original)
+++ subversion/branches/tree-read-api/subversion/svn/mergeinfo-cmd.c Sun Nov 11 20:24:17 2012
@@ -37,7 +37,6 @@
 #include "cl.h"
 
 #include "svn_private_config.h"
-#include "private/svn_client_private.h"
 
 
 /*** Code. ***/
@@ -60,10 +59,15 @@ print_log_rev(void *baton,
  * of merging between two branches, given the merge description
  * indicated by YCA, BASE, RIGHT, TARGET, REINTEGRATE_LIKE. */
 static svn_error_t *
-mergeinfo_diagram(svn_client__pathrev_t *yca,
-                  svn_client__pathrev_t *base,
-                  svn_client__pathrev_t *right,
-                  svn_client__pathrev_t *target,
+mergeinfo_diagram(const char *yca_url,
+                  const char *base_url,
+                  const char *right_url,
+                  const char *target_url,
+                  svn_revnum_t yca_rev,
+                  svn_revnum_t base_rev,
+                  svn_revnum_t right_rev,
+                  svn_revnum_t target_rev,
+                  const char *repos_root_url,
                   svn_boolean_t target_is_wc,
                   svn_boolean_t reintegrate_like,
                   apr_pool_t *pool)
@@ -82,16 +86,16 @@ mergeinfo_diagram(svn_client__pathrev_t 
 
   /* The YCA (that is, the branching point).  And an ellipsis, because we
    * don't show information about earlier merges */
-  g[0][0] = apr_psprintf(pool, "  %-8ld  ", yca->rev);
+  g[0][0] = apr_psprintf(pool, "  %-8ld  ", yca_rev);
   g[1][0] =     "  |         ";
-  if (strcmp(yca->url, right->url) == 0)
+  if (strcmp(yca_url, right_url) == 0)
     {
       g[2][0] = "-------| |--";
       g[3][0] = "   \\        ";
       g[4][0] = "    \\       ";
       g[5][0] = "     --| |--";
     }
-  else if (strcmp(yca->url, target->url) == 0)
+  else if (strcmp(yca_url, target_url) == 0)
     {
       g[2][0] = "     --| |--";
       g[3][0] = "    /       ";
@@ -107,18 +111,18 @@ mergeinfo_diagram(svn_client__pathrev_t 
     }
 
   /* The last full merge */
-  if ((base->rev > yca->rev) && reintegrate_like)
+  if ((base_rev > yca_rev) && reintegrate_like)
     {
       g[2][2] = "---------";
       g[3][2] = "  /      ";
       g[4][2] = " /       ";
       g[5][2] = "---------";
       g[6][2] = "|        ";
-      g[7][2] = apr_psprintf(pool, "%-8ld ", base->rev);
+      g[7][2] = apr_psprintf(pool, "%-8ld ", base_rev);
     }
-  else if (base->rev > yca->rev)
+  else if (base_rev > yca_rev)
     {
-      g[0][2] = apr_psprintf(pool, "%-8ld ", base->rev);
+      g[0][2] = apr_psprintf(pool, "%-8ld ", base_rev);
       g[1][2] = "|        ";
       g[2][2] = "---------";
       g[3][2] = " \\       ";
@@ -135,7 +139,7 @@ mergeinfo_diagram(svn_client__pathrev_t 
 
   /* The tips of the branches */
     {
-      g[0][3] = apr_psprintf(pool, "%-8ld", right->rev);
+      g[0][3] = apr_psprintf(pool, "%-8ld", right_rev);
       g[1][3] = "|       ";
       g[2][3] = "-       ";
       g[3][3] = "        ";
@@ -143,7 +147,7 @@ mergeinfo_diagram(svn_client__pathrev_t 
       g[5][3] = "-       ";
       g[6][3] = "|       ";
       g[7][3] = target_is_wc ? "WC      "
-                             : apr_psprintf(pool, "%-8ld", target->rev);
+                             : apr_psprintf(pool, "%-8ld", target_rev);
     }
 
   /* Find the width of each column, so we know how to print blank cells */
@@ -183,10 +187,10 @@ mergeinfo_diagram(svn_client__pathrev_t 
         }
       if (row == 2)
         SVN_ERR(svn_cmdline_printf(pool, "  %s",
-                svn_client__pathrev_relpath(right, pool)));
+                svn_uri_skip_ancestor(repos_root_url, right_url, pool)));
       if (row == 5)
         SVN_ERR(svn_cmdline_printf(pool, "  %s",
-                svn_client__pathrev_relpath(target, pool)));
+                svn_uri_skip_ancestor(repos_root_url, target_url, pool)));
       SVN_ERR(svn_cmdline_fputs("\n", stdout, pool));
     }
 
@@ -206,7 +210,9 @@ mergeinfo_summary(
                   apr_pool_t *pool)
 {
   svn_client_automatic_merge_t *the_merge;
-  svn_client__pathrev_t *yca, *base, *right, *target;
+  const char *yca_url, *base_url, *right_url, *target_url;
+  svn_revnum_t yca_rev, base_rev, right_rev, target_rev;
+  const char *repos_root_url;
   svn_boolean_t target_is_wc, reintegrate_like;
 
   target_is_wc = (! svn_path_is_url(target_path_or_url))
@@ -226,12 +232,18 @@ mergeinfo_summary(
               target_path_or_url, target_revision,
               ctx, pool, pool));
 
-  SVN_ERR(svn_client__automatic_merge_get_locations(
-            &yca, &base, &right, &target, the_merge, pool));
+  SVN_ERR(svn_client_automatic_merge_get_locations(
+            &yca_url, &yca_rev,
+            &base_url, &base_rev,
+            &right_url, &right_rev,
+            &target_url, &target_rev,
+            &repos_root_url,
+            the_merge, pool));
   reintegrate_like = svn_client_automatic_merge_is_reintegrate_like(the_merge);
 
-  SVN_ERR(mergeinfo_diagram(yca, base, right, target,
-                            target_is_wc, reintegrate_like,
+  SVN_ERR(mergeinfo_diagram(yca_url, base_url, right_url, target_url,
+                            yca_rev, base_rev, right_rev, target_rev,
+                            repos_root_url, target_is_wc, reintegrate_like,
                             pool));
 
   return SVN_NO_ERROR;

Modified: subversion/branches/tree-read-api/subversion/svnadmin/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/svnadmin/main.c?rev=1408109&r1=1408108&r2=1408109&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/svnadmin/main.c (original)
+++ subversion/branches/tree-read-api/subversion/svnadmin/main.c Sun Nov 11 20:24:17 2012
@@ -43,6 +43,7 @@
 #include "svn_xml.h"
 
 #include "private/svn_opt_private.h"
+#include "private/svn_subr_private.h"
 
 #include "svn_private_config.h"
 
@@ -193,7 +194,7 @@ enum svnadmin__cmdline_options_t
     svnadmin__pre_1_4_compatible,
     svnadmin__pre_1_5_compatible,
     svnadmin__pre_1_6_compatible,
-    svnadmin__pre_1_8_compatible
+    svnadmin__compatible_version
   };
 
 /* Option codes and descriptions.
@@ -271,26 +272,23 @@ static const apr_getopt_option_t options
         "                             use by another process")},
 
     {"pre-1.4-compatible",     svnadmin__pre_1_4_compatible, 0,
-     N_("use format compatible with Subversion versions\n"
-        "                             earlier than 1.4")},
+     N_("deprecated; see --compatible-version")},
 
     {"pre-1.5-compatible",     svnadmin__pre_1_5_compatible, 0,
-     N_("use format compatible with Subversion versions\n"
-        "                             earlier than 1.5")},
+     N_("deprecated; see --compatible-version")},
 
     {"pre-1.6-compatible",     svnadmin__pre_1_6_compatible, 0,
-     N_("use format compatible with Subversion versions\n"
-        "                             earlier than 1.6")},
-
-    {"pre-1.8-compatible",     svnadmin__pre_1_8_compatible, 0,
-     N_("use format compatible with Subversion versions\n"
-        "                             earlier than 1.8")},
+     N_("deprecated; see --compatible-version")},
 
     {"memory-cache-size",     'M', 1,
      N_("size of the extra in-memory cache in MB used to\n"
         "                             minimize redundant operations. Default: 16.\n"
         "                             [used for FSFS repositories only]")},
 
+    {"compatible-version",     svnadmin__compatible_version, 1,
+     N_("use repository format compatible with Subversion\n"
+        "                             version ARG (\"1.5.5\", \"1.7\", etc.)")},
+
     {NULL}
   };
 
@@ -310,9 +308,9 @@ static const svn_opt_subcommand_desc2_t 
    ("usage: svnadmin create REPOS_PATH\n\n"
     "Create a new, empty repository at REPOS_PATH.\n"),
    {svnadmin__bdb_txn_nosync, svnadmin__bdb_log_keep,
-    svnadmin__config_dir, svnadmin__fs_type, svnadmin__pre_1_4_compatible,
-    svnadmin__pre_1_5_compatible, svnadmin__pre_1_6_compatible,
-    svnadmin__pre_1_8_compatible
+    svnadmin__config_dir, svnadmin__fs_type, svnadmin__compatible_version,
+    svnadmin__pre_1_4_compatible, svnadmin__pre_1_5_compatible,
+    svnadmin__pre_1_6_compatible
     } },
 
   {"deltify", subcommand_deltify, {0}, N_
@@ -487,7 +485,7 @@ struct svnadmin_opt_state
   svn_boolean_t pre_1_4_compatible;                 /* --pre-1.4-compatible */
   svn_boolean_t pre_1_5_compatible;                 /* --pre-1.5-compatible */
   svn_boolean_t pre_1_6_compatible;                 /* --pre-1.6-compatible */
-  svn_boolean_t pre_1_8_compatible;                 /* --pre-1.8-compatible */
+  svn_version_t *compatible_version;                /* --compatible-version */
   svn_opt_revision_t start_revision, end_revision;  /* -r X[:Y] */
   svn_boolean_t help;                               /* --help or -? */
   svn_boolean_t version;                            /* --version */
@@ -638,25 +636,35 @@ subcommand_create(apr_getopt_t *os, void
                  APR_HASH_KEY_STRING,
                  opt_state->fs_type);
 
+  /* Prior to 1.8, we had explicit options to specify compatibility
+     with a handful of prior Subversion releases. */
   if (opt_state->pre_1_4_compatible)
     apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_4_COMPATIBLE,
-                 APR_HASH_KEY_STRING,
-                 "1");
-
+                 APR_HASH_KEY_STRING, "1");
   if (opt_state->pre_1_5_compatible)
     apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_5_COMPATIBLE,
-                 APR_HASH_KEY_STRING,
-                 "1");
-
+                 APR_HASH_KEY_STRING, "1");
   if (opt_state->pre_1_6_compatible)
     apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_6_COMPATIBLE,
-                 APR_HASH_KEY_STRING,
-                 "1");
+                 APR_HASH_KEY_STRING, "1");
 
-  if (opt_state->pre_1_8_compatible)
-    apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_8_COMPATIBLE,
-                 APR_HASH_KEY_STRING,
-                 "1");
+  /* In 1.8, we figured out that we didn't have to keep extending this
+     madness indefinitely. */
+  if (opt_state->compatible_version)
+    {
+      if (! svn_version__at_least(opt_state->compatible_version, 1, 4, 0))
+        apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_4_COMPATIBLE,
+                     APR_HASH_KEY_STRING, "1");
+      if (! svn_version__at_least(opt_state->compatible_version, 1, 5, 0))
+        apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_5_COMPATIBLE,
+                     APR_HASH_KEY_STRING, "1");
+      if (! svn_version__at_least(opt_state->compatible_version, 1, 6, 0))
+        apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_6_COMPATIBLE,
+                     APR_HASH_KEY_STRING, "1");
+      if (! svn_version__at_least(opt_state->compatible_version, 1, 8, 0))
+        apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_8_COMPATIBLE,
+                     APR_HASH_KEY_STRING, "1");
+    }
 
   SVN_ERR(svn_repos_create(&repos, opt_state->repository_path,
                            NULL, NULL, NULL, fs_config, pool));
@@ -1987,8 +1995,42 @@ sub_main(int argc, const char *argv[], a
       case svnadmin__pre_1_6_compatible:
         opt_state.pre_1_6_compatible = TRUE;
         break;
-      case svnadmin__pre_1_8_compatible:
-        opt_state.pre_1_8_compatible = TRUE;
+      case svnadmin__compatible_version:
+        {
+          svn_version_t latest = { SVN_VER_MAJOR, SVN_VER_MINOR,
+                                   SVN_VER_PATCH, NULL };
+          svn_version_t *compatible_version;
+
+          /* Parse the version string which carries our target
+             compatibility. */
+          SVN_INT_ERR(svn_version__parse_version_string(&compatible_version,
+                                                        opt_arg, pool));
+
+          /* We can't create repository with a version older than 1.0.0.  */
+          if (! svn_version__at_least(compatible_version, 1, 0, 0))
+            {
+              err = svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                                      _("Cannot create pre-1.0-compatible "
+                                        "repositories"));
+              return EXIT_ERROR(err);
+            }
+
+          /* We can't create repository with a version newer than what
+             the running version of Subversion supports. */
+          if (! svn_version__at_least(&latest,
+                                      compatible_version->major,
+                                      compatible_version->minor,
+                                      compatible_version->patch))
+            {
+              err = svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                                      _("Cannot guaranteed compatibility "
+                                        "beyond the current running version "
+                                        "(" SVN_VER_NUM ")"));
+              return EXIT_ERROR(err);
+            }
+
+          opt_state.compatible_version = compatible_version;
+        }
         break;
       case svnadmin__fs_type:
         SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_state.fs_type, opt_arg, pool));

Modified: subversion/branches/tree-read-api/subversion/svnlook/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/svnlook/main.c?rev=1408109&r1=1408108&r2=1408109&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/svnlook/main.c (original)
+++ subversion/branches/tree-read-api/subversion/svnlook/main.c Sun Nov 11 20:24:17 2012
@@ -93,7 +93,9 @@ enum
     svnlook__revprop_opt,
     svnlook__full_paths,
     svnlook__copy_info,
-    svnlook__xml_opt
+    svnlook__xml_opt,
+    svnlook__ignore_properties,
+    svnlook__properties_only
   };
 
 /*
@@ -125,6 +127,12 @@ static const apr_getopt_option_t options
   {"no-diff-deleted",   svnlook__no_diff_deleted, 0,
    N_("do not print differences for deleted files")},
 
+  {"ignore-properties",   svnlook__ignore_properties, 0,
+   N_("ignore properties during the operation")},
+
+  {"properties-only",   svnlook__properties_only, 0,
+   N_("show only properties during the operation")},
+
   {"non-recursive",     'N', 0,
    N_("operate on single directory only")},
 
@@ -218,7 +226,8 @@ static const svn_opt_subcommand_desc2_t 
    N_("usage: svnlook diff REPOS_PATH\n\n"
       "Print GNU-style diffs of changed files and properties.\n"),
    {'r', 't', svnlook__no_diff_deleted, svnlook__no_diff_added,
-    svnlook__diff_copy_from, 'x'} },
+    svnlook__diff_copy_from, 'x', svnlook__ignore_properties,
+    svnlook__properties_only} },
 
   {"dirs-changed", subcommand_dirschanged, {0},
    N_("usage: svnlook dirs-changed REPOS_PATH\n\n"
@@ -320,6 +329,8 @@ struct svnlook_opt_state
   svn_boolean_t xml;              /* --xml */
   const char *extensions;         /* diff extension args (UTF-8!) */
   svn_boolean_t quiet;            /* --quiet */
+  svn_boolean_t ignore_properties;  /* --ignore_properties */
+  svn_boolean_t properties_only;    /* --properties-only */
 };
 
 
@@ -339,6 +350,8 @@ typedef struct svnlook_ctxt_t
   svn_fs_txn_t *txn;
   const char *txn_name /* UTF-8! */;
   const apr_array_header_t *diff_options;
+  svn_boolean_t ignore_properties;
+  svn_boolean_t properties_only;
 
 } svnlook_ctxt_t;
 
@@ -1031,7 +1044,7 @@ print_diff_tree(svn_fs_root_t *root,
         }
     }
 
-  if (do_diff)
+  if (do_diff && (! c->properties_only))
     {
       svn_stringbuf_appendcstr(header, equal_string);
       svn_stringbuf_appendcstr(header, "\n");
@@ -1122,7 +1135,7 @@ print_diff_tree(svn_fs_root_t *root,
     SVN_ERR(svn_io_remove_file2(new_path, FALSE, pool));
 
   /*** Now handle property diffs ***/
-  if ((node->prop_mod) && (node->action != 'D'))
+  if ((node->prop_mod) && (node->action != 'D') && (! c->ignore_properties))
     {
       apr_hash_t *local_proptable;
       apr_hash_t *base_proptable;
@@ -1913,6 +1926,8 @@ get_ctxt_baton(svnlook_ctxt_t **baton_p,
   baton->diff_options = svn_cstring_split(opt_state->extensions
                                           ? opt_state->extensions : "",
                                           " \t\n\r", TRUE, pool);
+  baton->ignore_properties = opt_state->ignore_properties;
+  baton->properties_only = opt_state->properties_only;
 
   if (baton->txn_name)
     SVN_ERR(svn_fs_open_txn(&(baton->txn), baton->fs,
@@ -2414,6 +2429,14 @@ main(int argc, const char *argv[])
           opt_state.extensions = opt_arg;
           break;
 
+        case svnlook__ignore_properties:
+          opt_state.ignore_properties = TRUE;
+          break;
+
+        case svnlook__properties_only:
+          opt_state.properties_only = TRUE;
+          break;
+
         default:
           SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
           svn_pool_destroy(pool);

Modified: subversion/branches/tree-read-api/subversion/svnmucc/svnmucc.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/svnmucc/svnmucc.c?rev=1408109&r1=1408108&r2=1408109&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/svnmucc/svnmucc.c (original)
+++ subversion/branches/tree-read-api/subversion/svnmucc/svnmucc.c Sun Nov 11 20:24:17 2012
@@ -1300,7 +1300,7 @@ main(int argc, const char **argv)
           else
             anchor = svn_uri_get_longest_ancestor(anchor, url, pool);
 
-          if ((++i == action_args->nelts) && (j >= num_url_args))
+          if ((++i == action_args->nelts) && (j + 1 < num_url_args))
             insufficient(pool);
         }
       APR_ARRAY_PUSH(actions, struct action *) = action;

Modified: subversion/branches/tree-read-api/subversion/tests/cmdline/copy_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/cmdline/copy_tests.py?rev=1408109&r1=1408108&r2=1408109&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/cmdline/copy_tests.py (original)
+++ subversion/branches/tree-read-api/subversion/tests/cmdline/copy_tests.py Sun Nov 11 20:24:17 2012
@@ -4361,7 +4361,7 @@ def nonrecursive_commit_of_copy(sbox):
 def copy_added_dir_with_copy(sbox):
   """copy of new dir with copied file keeps history"""
 
-  sbox.build()
+  sbox.build(read_only=True)
   wc_dir = sbox.wc_dir
 
   new_dir = sbox.ospath('NewDir');
@@ -4670,7 +4670,7 @@ def changed_dir_data_should_match_checko
 def move_added_nodes(sbox):
   """move added nodes"""
 
-  sbox.build()
+  sbox.build(read_only=True)
 
   svntest.actions.run_and_verify_svn(None, None, [], 'mkdir',
                                      sbox.ospath('X'),
@@ -4784,7 +4784,7 @@ def mixed_rev_copy_del(sbox):
 def copy_delete_undo(sbox, use_revert):
   "copy, delete child, undo"
 
-  sbox.build()
+  sbox.build(read_only=True)
   wc_dir = sbox.wc_dir
 
   # Copy directory with children
@@ -4839,7 +4839,7 @@ def copy_delete_revert(sbox):
 def delete_replace_delete(sbox):
   "delete a directory scheduled for replacement"
 
-  sbox.build()
+  sbox.build(read_only=True)
   wc_dir = sbox.wc_dir
 
   # Delete directory with children

Modified: subversion/branches/tree-read-api/subversion/tests/cmdline/merge_automatic_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/cmdline/merge_automatic_tests.py?rev=1408109&r1=1408108&r2=1408109&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/cmdline/merge_automatic_tests.py (original)
+++ subversion/branches/tree-read-api/subversion/tests/cmdline/merge_automatic_tests.py Sun Nov 11 20:24:17 2012
@@ -83,6 +83,8 @@ from merge_tests import set_up_branch
 #     B (--o--x--o-----?--x
 #
 #   Merge with cherry-picks
+#   (This set of six cases represents all of the topologically distinct
+#   scenarios involving one cherry-pick between two automatic merges.)
 #
 #     Cherry1, fwd
 #     A (--o-----o-[o]----o---
@@ -701,6 +703,7 @@ def cherry1_fwd(sbox):
 
 @SkipUnless(server_has_mergeinfo)
 @XFail()
+@Issue(4255)
 def cherry2_fwd(sbox):
   """cherry2_fwd"""
 
@@ -721,6 +724,7 @@ def cherry2_fwd(sbox):
 
 @SkipUnless(server_has_mergeinfo)
 @XFail()
+@Issue(4255)
 def cherry3_fwd(sbox):
   """cherry3_fwd"""
 
@@ -728,7 +732,7 @@ def cherry3_fwd(sbox):
   #     (          \     /     \
   #     (           \   /       \
   #   B (---o--o-[o]-x-/---------x
-  #               \__/
+  #                \__/
   #     2  34  5  6  7    8  9   0
 
   make_branches(sbox)

Modified: subversion/branches/tree-read-api/subversion/tests/cmdline/special_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/cmdline/special_tests.py?rev=1408109&r1=1408108&r2=1408109&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/cmdline/special_tests.py (original)
+++ subversion/branches/tree-read-api/subversion/tests/cmdline/special_tests.py Sun Nov 11 20:24:17 2012
@@ -25,7 +25,7 @@
 ######################################################################
 
 # General modules
-import sys, os, re
+import sys, os, re, copy
 
 # Our testing module
 import svntest
@@ -49,7 +49,6 @@ Item = svntest.wc.StateItem
 
 
 #----------------------------------------------------------------------
-@SkipUnless(svntest.main.is_posix_os)
 def general_symlink(sbox):
   "general symlink handling"
 
@@ -57,11 +56,11 @@ def general_symlink(sbox):
   wc_dir = sbox.wc_dir
 
   # First try to just commit a symlink
-  newfile_path = os.path.join(wc_dir, 'newfile')
-  linktarget_path = os.path.join(wc_dir, 'linktarget')
-  svntest.main.file_append(linktarget_path, 'this is just a link target')
-  os.symlink('linktarget', newfile_path)
-  svntest.main.run_svn(None, 'add', newfile_path, linktarget_path)
+  newfile_path = sbox.ospath('newfile')
+
+  sbox.simple_append('linktarget', 'this is just a link target')
+  sbox.simple_add('linktarget')
+  sbox.simple_add_symlink('linktarget', 'newfile')
 
   expected_output = svntest.wc.State(wc_dir, {
     'newfile' : Item(verb='Adding'),
@@ -104,14 +103,18 @@ def general_symlink(sbox):
                                      'up', '-r', '2', wc_dir)
 
   # Is the symlink back?
-  new_target = os.readlink(newfile_path)
-  if new_target != 'linktarget':
-    raise svntest.Failure
+  if svntest.main.is_posix_os():
+    new_target = os.readlink(newfile_path)
+    if new_target != 'linktarget':
+      raise svntest.Failure
 
   ## Now change the target of the symlink, verify that it is shown as
   ## modified and that a commit succeeds.
   os.remove(newfile_path)
-  os.symlink('A', newfile_path)
+  if svntest.main.is_posix_os():
+    os.symlink('A', newfile_path)
+  else:
+    sbox.simple_append('newfile', 'link A', truncate = True)
 
   was_cwd = os.getcwd()
   os.chdir(wc_dir)
@@ -223,7 +226,6 @@ def import_export_symlink(sbox):
 #----------------------------------------------------------------------
 # Regression test for issue 1986
 @Issue(1986)
-@SkipUnless(svntest.main.is_posix_os)
 def copy_tree_with_symlink(sbox):
   "'svn cp dir1 dir2' which contains a symlink"
 
@@ -231,11 +233,10 @@ def copy_tree_with_symlink(sbox):
   wc_dir = sbox.wc_dir
 
   # Create a versioned symlink within directory 'A/D/H'.
-  newfile_path = os.path.join(wc_dir, 'A', 'D', 'H', 'newfile')
-  linktarget_path = os.path.join(wc_dir, 'A', 'D', 'H', 'linktarget')
-  svntest.main.file_append(linktarget_path, 'this is just a link target')
-  os.symlink('linktarget', newfile_path)
-  svntest.main.run_svn(None, 'add', newfile_path, linktarget_path)
+  newfile_path = sbox.ospath('A/D/H/newfile')
+  sbox.simple_append('A/D/H/linktarget', 'this is just a link target')
+  sbox.simple_add('A/D/H/linktarget')
+  sbox.simple_add_symlink('linktarget', 'A/D/H/newfile')
 
   expected_output = svntest.wc.State(wc_dir, {
     'A/D/H/newfile' : Item(verb='Adding'),
@@ -323,7 +324,7 @@ def replace_symlink_with_file(sbox):
     raise svntest.Failure
 
 
-@SkipUnless(svntest.main.is_posix_os)
+#----------------------------------------------------------------------
 def remove_symlink(sbox):
   "remove a symlink"
 
@@ -334,8 +335,8 @@ def remove_symlink(sbox):
   newfile_path = os.path.join(wc_dir, 'newfile')
   linktarget_path = os.path.join(wc_dir, 'linktarget')
   svntest.main.file_append(linktarget_path, 'this is just a link target')
-  os.symlink('linktarget', newfile_path)
-  svntest.main.run_svn(None, 'add', newfile_path, linktarget_path)
+  sbox.simple_add_symlink('linktarget', 'newfile')
+  sbox.simple_add('linktarget')
 
   expected_output = svntest.wc.State(wc_dir, {
     'newfile' : Item(verb='Adding'),
@@ -367,7 +368,7 @@ def remove_symlink(sbox):
   svntest.actions.run_and_verify_commit(wc_dir, expected_output,
                                         expected_status, None, wc_dir)
 
-@SkipUnless(svntest.main.is_posix_os)
+#----------------------------------------------------------------------
 @SkipUnless(server_has_mergeinfo)
 @Issue(2530)
 def merge_symlink_into_file(sbox):
@@ -378,8 +379,8 @@ def merge_symlink_into_file(sbox):
   d_url = sbox.repo_url + '/A/D'
   dprime_url = sbox.repo_url + '/A/Dprime'
 
-  gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma')
-  gamma_prime_path = os.path.join(wc_dir, 'A', 'Dprime', 'gamma')
+  gamma_path = sbox.ospath('A/D/gamma')
+  gamma_prime_path = sbox.ospath('A/Dprime/gamma')
 
   # create a copy of the D directory to play with
   svntest.main.run_svn(None,
@@ -400,8 +401,7 @@ def merge_symlink_into_file(sbox):
   # Commit a symlink in its place
   linktarget_path = os.path.join(wc_dir, 'linktarget')
   svntest.main.file_append(linktarget_path, 'this is just a link target')
-  os.symlink('linktarget', gamma_prime_path)
-  svntest.main.run_svn(None, 'add', gamma_prime_path)
+  sbox.simple_add_symlink('linktarget', 'A/Dprime/gamma')
 
   expected_output = svntest.wc.State(wc_dir, {
     'A/Dprime/gamma' : Item(verb='Adding'),
@@ -435,7 +435,7 @@ def merge_symlink_into_file(sbox):
 
 
 
-@SkipUnless(svntest.main.is_posix_os)
+#----------------------------------------------------------------------
 def merge_file_into_symlink(sbox):
   "merge file into symlink"
 
@@ -466,8 +466,7 @@ def merge_file_into_symlink(sbox):
   # Commit a symlink in its place
   linktarget_path = os.path.join(wc_dir, 'linktarget')
   svntest.main.file_append(linktarget_path, 'this is just a link target')
-  os.symlink('linktarget', gamma_prime_path)
-  svntest.main.run_svn(None, 'add', gamma_prime_path)
+  sbox.simple_add_symlink('linktarget', 'A/Dprime/gamma')
 
   expected_output = svntest.wc.State(wc_dir, {
     'A/Dprime/gamma' : Item(verb='Adding'),
@@ -520,22 +519,19 @@ def checkout_repo_with_symlinks(sbox):
                                           expected_output,
                                           expected_wc)
 
+#----------------------------------------------------------------------
 # Issue 2716: 'svn diff' against a symlink to a directory within the wc
 @Issue(2716)
-@SkipUnless(svntest.main.is_posix_os)
 def diff_symlink_to_dir(sbox):
   "diff a symlink to a directory"
 
   sbox.build(read_only = True)
-  os.chdir(sbox.wc_dir)
 
-  # Create a symlink to A/D/.
+  # Create a symlink to A/D as link.
   d_path = os.path.join('A', 'D')
-  link_path = 'link'
-  os.symlink(d_path, link_path)
+  sbox.simple_add_symlink('A/D', 'link')
 
-  # Add the symlink.
-  svntest.main.run_svn(None, 'add', link_path)
+  os.chdir(sbox.wc_dir)
 
   # Now diff the wc itself and check the results.
   expected_output = [
@@ -544,7 +540,7 @@ def diff_symlink_to_dir(sbox):
     "--- link\t(revision 0)\n",
     "+++ link\t(working copy)\n",
     "@@ -0,0 +1 @@\n",
-    "+link " + d_path + "\n",
+    "+link A/D\n",
     "\ No newline at end of file\n",
     "\n",
     "Property changes on: link\n",
@@ -557,9 +553,9 @@ def diff_symlink_to_dir(sbox):
   svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
                                      '.')
   # We should get the same output if we the diff the symlink itself.
-  svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
-                                     link_path)
+  svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff', 'link')
 
+#----------------------------------------------------------------------
 # Issue 2692 (part of): Check that the client can check out a repository
 # that contains an unknown special file type.
 @Issue(2692)
@@ -710,9 +706,8 @@ def unrelated_changed_special_status(sbo
                                      '--changelist', 'chi cl',
                                      '-m', 'psi changed special status')
 
-
+#----------------------------------------------------------------------
 @Issue(3972)
-@SkipUnless(svntest.main.is_posix_os)
 def symlink_destination_change(sbox):
   "revert a symlink destination change"
 
@@ -721,8 +716,7 @@ def symlink_destination_change(sbox):
 
   # Create a new symlink and commit it.
   newfile_path = os.path.join(wc_dir, 'newfile')
-  os.symlink('linktarget', newfile_path)
-  svntest.main.run_svn(None, 'add', newfile_path)
+  sbox.simple_add_symlink('linktarget', 'newfile')
 
   expected_output = svntest.wc.State(wc_dir, {
     'newfile' : Item(verb='Adding'),
@@ -738,7 +732,10 @@ def symlink_destination_change(sbox):
 
   # Modify the symlink to point somewhere else
   os.remove(newfile_path)
-  os.symlink('linktarget2', newfile_path)
+  if svntest.main.is_posix_os():
+    os.symlink('linktarget2', newfile_path)
+  else:
+    sbox.simple_append('newfile', 'link linktarget2', truncate = True)
 
   expected_status.tweak('newfile', status='M ')
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
@@ -758,7 +755,6 @@ def symlink_destination_change(sbox):
 # This used to lose the special status in the target working copy
 # (disk and metadata).
 @Issue(3884)
-@SkipUnless(svntest.main.is_posix_os)
 def merge_foreign_symlink(sbox):
   "merge symlink-add from foreign repos"
 
@@ -777,8 +773,7 @@ def merge_foreign_symlink(sbox):
   zeta2_path = sbox2.ospath('A/zeta')
 
   # sbox2 r2: create zeta2 in sbox2
-  os.symlink('target', zeta2_path)
-  sbox2.simple_add('A/zeta')
+  sbox2.simple_add_symlink('target', 'A/zeta')
   sbox2.simple_commit('A/zeta')
 
 
@@ -859,8 +854,8 @@ def symlink_to_wc_svnversion(sbox):
                                             symlink_path, sbox.repo_url,
                                             [ "1\n" ], [])
 
+#----------------------------------------------------------------------
 # Regression in 1.7.0: Update fails to change a symlink
-@SkipUnless(svntest.main.is_posix_os)
 def update_symlink(sbox):
   "update a symlink"
 
@@ -873,13 +868,15 @@ def update_symlink(sbox):
   symlink_path = sbox.ospath('symlink')
 
   # create a symlink to /A/mu
-  os.symlink("A/mu", symlink_path)
-  sbox.simple_add('symlink')
+  sbox.simple_add_symlink("A/mu", 'symlink')
   sbox.simple_commit()
 
   # change the symlink to /iota
   os.remove(symlink_path)
-  os.symlink("iota", symlink_path)
+  if svntest.main.is_posix_os():
+    os.symlink("iota", symlink_path)
+  else:
+    file_write(symlink_path, 'link iota')
   sbox.simple_commit()
 
   # update back to r2
@@ -896,6 +893,10 @@ def update_symlink(sbox):
   expected_status.add({
     'symlink'           : Item(status='  ', wc_rev='3'),
   })
+
+  if not svntest.main.is_posix_os():
+    expected_disk = None
+
   svntest.actions.run_and_verify_update(wc_dir,
                                         expected_output,
                                         expected_disk,
@@ -903,9 +904,8 @@ def update_symlink(sbox):
                                         None, None, None,
                                         None, None, 1)
 
-@XFail()
+#----------------------------------------------------------------------
 @Issue(4091)
-@SkipUnless(svntest.main.is_posix_os)
 def replace_symlinks(sbox):
   "replace symlinks"
   sbox.build()
@@ -922,10 +922,8 @@ def replace_symlinks(sbox):
   sbox.simple_mkdir('A/D/Y')
   sbox.simple_mkdir('Ax')
 
-  os.symlink('../Y', wc('A/D/H/Z'))
-  os.symlink('../Y', wc('A/D/Hx/Z'))
-  sbox.simple_add('A/D/H/Z',
-                  'A/D/Hx/Z')
+  sbox.simple_add_symlink('../Y', 'A/D/H/Z')
+  sbox.simple_add_symlink('../Y', 'A/D/Hx/Z')
 
   for p in ['Ax/mu',
             'A/D/Gx/pi',
@@ -946,6 +944,8 @@ def replace_symlinks(sbox):
       file_write(wc(p), '#!/bin/sh\necho "hello, svn!"\n')
       os.chmod(wc(p), 0775)
       sbox.simple_add(p)
+      if not svntest.main.is_posix_os():
+        sbox.simple_propset('svn:executable', 'X', p)
   sbox.simple_commit() # r2
   sbox.simple_update()
   expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 2)
@@ -971,19 +971,17 @@ def replace_symlinks(sbox):
     'A/mu.sh'       : Item(status='  ', wc_rev=2),
     'iota.sh'       : Item(status='  ', wc_rev=2),
     })
-  expected_status_r2 = expected_status
+  expected_status_r2 = copy.deepcopy(expected_status)
   svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status_r2)
 
   # Failing git-svn test: 'new symlink is added to a file that was
   # also just made executable', i.e., in the same revision.
-  sbox.simple_propset("svn:executable", "*", 'A/B/E/alpha')
-  os.symlink('alpha', wc('A/B/E/sym-alpha'))
-  sbox.simple_add('A/B/E/sym-alpha')
+  sbox.simple_propset("svn:executable", "X", 'A/B/E/alpha')
+  sbox.simple_add_symlink('alpha', 'A/B/E/sym-alpha')
 
   # Add a symlink to a file made non-executable in the same revision.
   sbox.simple_propdel("svn:executable", 'A/B/E/beta.sh')
-  os.symlink('beta.sh', wc('A/B/E/sym-beta.sh'))
-  sbox.simple_add('A/B/E/sym-beta.sh')
+  sbox.simple_add_symlink('beta.sh', 'A/B/E/sym-beta.sh')
 
   # Replace a normal {file, exec, dir} with a symlink to the same kind
   # via Subversion replacement.
@@ -991,13 +989,9 @@ def replace_symlinks(sbox):
                  'A/D/G/rho.sh',
                  #'A/D/G/Z', # Ooops, not compatible with --bin=svn1.6.
                  )
-  os.symlink(wc('../gamma'), wc('A/D/G/pi'))
-  os.symlink(wc('../gamma.sh'), wc('A/D/G/rho.sh'))
-  #os.symlink(wc('../Y'), wc('A/D/G/Z'))
-  sbox.simple_add('A/D/G/pi',
-                  'A/D/G/rho.sh',
-                  #'A/D/G/Z',
-                  )
+  sbox.simple_add_symlink('../gamma', 'A/D/G/pi')
+  sbox.simple_add_symlink('../gamma.sh', 'A/D/G/rho.sh')
+  #sbox.simple_add_symlink('../Y', 'A/D/G/Z')
 
   # Replace a symlink to {file, exec, dir} with a normal item of the
   # same kind via Subversion replacement.
@@ -1005,30 +999,34 @@ def replace_symlinks(sbox):
                  'A/D/H/psi.sh',
                  #'A/D/H/Z',
                  )
-  os.symlink(wc('../gamma'), wc('A/D/H/chi'))
-  os.symlink(wc('../gamma.sh'), wc('A/D/H/psi.sh'))
-  #os.symlink(wc('../Y'), wc('A/D/H/Z'))
-  sbox.simple_add('A/D/H/chi',
-                  'A/D/H/psi.sh',
-                  #'A/D/H/Z',
-                  )
+  sbox.simple_add_symlink('../gamma', 'A/D/H/chi')
+  sbox.simple_add_symlink('../gamma.sh', 'A/D/H/psi.sh')
+  #sbox.simple_add_symlink('../Y', 'A/D/H/Z')
 
   # Replace a normal {file, exec} with a symlink to {exec, file} via
   # Subversion replacement.
   sbox.simple_rm('A/mu',
                  'A/mu.sh')
-  os.symlink('../iota2', wc('A/mu'))
-  os.symlink('../iota', wc('A/mu.sh'))
-  sbox.simple_add('A/mu',
-                  'A/mu.sh')
+  sbox.simple_add_symlink('../iota2', 'A/mu')
+  sbox.simple_add_symlink('../iota', 'A/mu.sh')
 
   # Ditto, without the Subversion replacement.  Failing git-svn test
   # 'executable file becomes a symlink to bar/zzz (file)'.
-  os.remove(wc('Ax/mu'))
-  os.remove(wc('Ax/mu.sh'))
-  os.symlink('../iota2', wc('Ax/mu'))
-  os.symlink('../iota', wc('Ax/mu.sh'))
-  sbox.simple_propset('svn:special', '*',
+  if svntest.main.is_posix_os():
+    os.remove(wc('Ax/mu'))
+    os.remove(wc('Ax/mu.sh'))
+    os.symlink('../iota2', wc('Ax/mu'))
+    os.symlink('../iota', wc('Ax/mu.sh'))
+  else:
+    # At least modify the file a bit
+
+    # ### Somehow this breaks the test when using multiline data?
+    # ### Is that intended behavior?
+
+    file_write(sbox.ospath('Ax/mu'), 'Link to iota2')
+    file_write(sbox.ospath('Ax/mu.sh'), 'Link to iota')
+
+  sbox.simple_propset('svn:special', 'X',
                       'Ax/mu',
                       'Ax/mu.sh')
   sbox.simple_propdel('svn:executable', 'Ax/mu.sh')
@@ -1100,20 +1098,121 @@ def externals_as_symlink_targets(sbox):
 
   sbox.simple_commit()
 
+#----------------------------------------------------------------------
 @XFail()
 @Issue(4119)
-@SkipUnless(svntest.main.is_posix_os)
 def cat_added_symlink(sbox):
   "cat added symlink"
 
   sbox.build(read_only = True)
 
   kappa_path = sbox.ospath('kappa')
-  os.symlink('iota', kappa_path)
-  sbox.simple_add('kappa')
+  sbox.simple_add_symlink('iota', 'kappa')
   svntest.actions.run_and_verify_svn(None, "link iota", [],
                                      "cat", kappa_path)
 
+#----------------------------------------------------------------------
+def incoming_symlink_changes(sbox):
+  "verify incoming symlink change behavior"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  sbox.simple_add_symlink('iota', 's-replace')
+  sbox.simple_add_symlink('iota', 's-in-place')
+  sbox.simple_add_symlink('iota', 's-type')
+  sbox.simple_append('s-reverse', 'link iota')
+  sbox.simple_add('s-reverse')
+  # Sleep here so that the subsequent s-in-place change is detected.
+  svntest.actions.do_sleep_for_timestamps()
+  sbox.simple_commit() # r2
+  svntest.actions.no_sleep_for_timestamps()
+
+  # Replace s-replace
+  sbox.simple_rm('s-replace')
+  sbox.simple_add_symlink('A/mu', 's-replace')
+
+  # Change target of s-in-place
+  if svntest.main.is_posix_os():
+    os.remove(sbox.ospath('s-in-place'))
+    os.symlink('A/mu', sbox.ospath('s-in-place'))
+  else:
+    sbox.simple_append('s-in-place', 'link A/mu', truncate = True)
+  sbox.simple_commit() # r3
+
+  # r4
+  svntest.main.run_svnmucc('propdel', 'svn:special',
+                           sbox.repo_url + '/s-type',
+                           '-m', 'Turn s-type into a file')
+
+  # r5
+  svntest.main.run_svnmucc('propset', 'svn:special', 'X',
+                           sbox.repo_url + '/s-reverse',
+                           '-m', 'Turn s-reverse into a symlink')
+
+  # Currently we expect to see 'U'pdates, but we would like to see
+  # replacements
+  expected_output = svntest.wc.State(wc_dir, {
+    's-reverse'         : Item(status=' U'),
+    's-type'            : Item(status=' U'),
+  })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 5)
+  expected_status.add({
+    's-type'            : Item(status='  ', wc_rev='5'),
+    's-replace'         : Item(status='  ', wc_rev='5'),
+    's-reverse'         : Item(status='  ', wc_rev='5'),
+    's-in-place'        : Item(status='  ', wc_rev='5'),
+  })
+
+  # Update to HEAD/r5 to fetch the r4 and r5 symlink changes
+  svntest.actions.run_and_verify_update(wc_dir,
+                                        expected_output,
+                                        None,
+                                        expected_status,
+                                        None, None, None, None, None,
+                                        check_props=True)
+
+  # Update back to r2, to prepare some local changes
+  expected_output = svntest.wc.State(wc_dir, {
+    # s-replace is D + A
+    's-replace'         : Item(status='A '),
+    's-in-place'        : Item(status='U '),
+    's-reverse'         : Item(status=' U'),
+    's-type'            : Item(status=' U'),
+  })
+  expected_status.tweak(wc_rev=2)
+
+  svntest.actions.run_and_verify_update(wc_dir,
+                                        expected_output,
+                                        None,
+                                        expected_status,
+                                        None, None, None, None, None,
+                                        True,
+                                        wc_dir, '-r', '2')
+
+  # Ok, now add a property on all of them to make future symlinkness changes
+  # a tree conflict
+  # ### We should also try this with a 'textual change'
+  sbox.simple_propset('x', 'y', 's-replace', 's-in-place', 's-reverse', 's-type')
+
+  expected_output = svntest.wc.State(wc_dir, {
+    's-replace'         : Item(status='  ', treeconflict='A'),
+    's-in-place'        : Item(status='U '),
+    's-reverse'         : Item(status='  ', treeconflict='C'),
+    's-type'            : Item(status='  ', treeconflict='C'),
+  })
+  expected_status.tweak(wc_rev=5)
+  expected_status.tweak('s-replace', 's-reverse', 's-type', status='RM',
+                        copied='+', treeconflict='C', wc_rev='-')
+  expected_status.tweak('s-in-place', status=' M')
+
+  svntest.actions.run_and_verify_update(wc_dir,
+                                        expected_output,
+                                        None,
+                                        expected_status,
+                                        None, None, None, None, None,
+                                        True)
+
 ########################################################################
 # Run the tests
 
@@ -1144,6 +1243,7 @@ test_list = [ None,
               replace_symlinks,
               externals_as_symlink_targets,
               cat_added_symlink,
+              incoming_symlink_changes,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/tree-read-api/subversion/tests/cmdline/svntest/main.py
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/cmdline/svntest/main.py?rev=1408109&r1=1408108&r2=1408109&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/cmdline/svntest/main.py (original)
+++ subversion/branches/tree-read-api/subversion/tests/cmdline/svntest/main.py Sun Nov 11 20:24:17 2012
@@ -829,12 +829,7 @@ def create_repos(path, minor_version = N
   opts = ("--bdb-txn-nosync",)
   if not minor_version or minor_version > options.server_minor_version:
     minor_version = options.server_minor_version
-  if minor_version < 4:
-    opts += ("--pre-1.4-compatible",)
-  elif minor_version < 5:
-    opts += ("--pre-1.5-compatible",)
-  elif minor_version < 6:
-    opts += ("--pre-1.6-compatible",)
+  opts += ("--compatible-version=1.%d" % (minor_version),)
   if options.fs_type is not None:
     opts += ("--fs-type=" + options.fs_type,)
   exit_code, stdout, stderr = run_command(svnadmin_binary, 1, 0, "create",

Modified: subversion/branches/tree-read-api/subversion/tests/cmdline/svntest/sandbox.py
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/cmdline/svntest/sandbox.py?rev=1408109&r1=1408108&r2=1408109&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/cmdline/svntest/sandbox.py (original)
+++ subversion/branches/tree-read-api/subversion/tests/cmdline/svntest/sandbox.py Sun Nov 11 20:24:17 2012
@@ -307,6 +307,17 @@ class Sandbox:
         raise Exception("Unexpected line '" + line + "' in proplist output" + str(out))
     return props
 
+  def simple_add_symlink(self, dest, target):
+    """Create a symlink TARGET pointing to DEST and add it to subversion"""
+    if svntest.main.is_posix_os():
+      os.symlink(dest, self.ospath(target))
+    else:
+      svntest.main.file_write(self.ospath(target), "link %s" % dest)
+    self.simple_add(target)
+    if not svntest.main.is_posix_os():
+      # '*' is evaluated on Windows
+      self.simple_propset('svn:special', 'X', target)
+
   def simple_copy(self, source, dest):
     """Copy SOURCE to DEST in the WC.
        SOURCE and DEST are relpaths relative to the WC."""

Modified: subversion/branches/tree-read-api/subversion/tests/libsvn_wc/op-depth-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/tests/libsvn_wc/op-depth-test.c?rev=1408109&r1=1408108&r2=1408109&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/branches/tree-read-api/subversion/tests/libsvn_wc/op-depth-test.c Sun Nov 11 20:24:17 2012
@@ -1628,7 +1628,7 @@ temp_op_make_copy(svn_test__sandbox_t *b
 
   SVN_ERR(insert_dirs(b, before));
 
-  SVN_ERR(svn_wc__db_temp_op_make_copy(b->wc_ctx->db, dir_abspath, b->pool));
+  SVN_ERR(svn_wc__db_op_make_copy(b->wc_ctx->db, dir_abspath, NULL, NULL, b->pool));
 
   SVN_ERR(check_db_rows(b, "", after));
 

Modified: subversion/branches/tree-read-api/tools/server-side/fsfs-reorg.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/tools/server-side/fsfs-reorg.c?rev=1408109&r1=1408108&r2=1408109&view=diff
==============================================================================
--- subversion/branches/tree-read-api/tools/server-side/fsfs-reorg.c (original)
+++ subversion/branches/tree-read-api/tools/server-side/fsfs-reorg.c Sun Nov 11 20:24:17 2012
@@ -47,165 +47,376 @@
 
 #define ERROR_TAG "diff: "
 
+/* forward declarations */
 typedef struct noderev_t noderev_t;
 typedef struct revision_info_t revision_info_t;
 
+/* A FSFS rev file is sequence of fragments and unused space (the latter
+ * only being inserted by this tool and not during ordinary SVN operation).
+ * 
+ * This type defines the type of any fragment.
+ *
+ * Please note that the classification as "property", "dir" or "file"
+ * fragments is only to be used while determining the future placement
+ * of a representation.  If the rep is shared, the same rep may be used
+ * as *any* of the 3 kinds.
+ */
 enum fragment_kind_t
 {
+  /* the 2 number line containing changes and root node offsets */
   header_fragment,
+
+  /* list of all changes in a revision */
   changes_fragment,
-  noderep_fragment,
+
+  /* (the textual representation of) a noderev */
+  noderev_fragment,
+
+  /* a property rep (including PLAIN / DELTA header) */
   property_fragment,
+
+  /* a directory rep (including PLAIN / DELTA header) */
   dir_fragment,
+
+  /* a file rep (including PLAIN / DELTA header) */
   file_fragment
 };
 
+/* A fragment.  This is used to represent the final ordering, i.e. there
+ * will be an array containing elements of this type that basically put
+ * a fragment at some location in the target file.
+ */
 typedef struct fragment_t
 {
+  /* position in the target file */
   apr_size_t position;
-  void *data;
+
+  /* kind of fragment */
   enum fragment_kind_t kind;
+
+  /* pointer to the  fragment struct; type depends on KIND */
+  void *data;
 } fragment_t;
 
+/* Location info for a single revision.
+ */
 typedef struct revision_location_t
 {
+  /* pack file offset (manifest value), 0 for non-packed files */
   apr_size_t offset;
+  
+  /* offset of the changes list relative to OFFSET */
   apr_size_t changes;
+
+  /* length of the changes list on bytes */
   apr_size_t changes_len;
+
+  /* first offset behind the revision data in the pack file (file length
+   * for non-packed revs) */
   apr_size_t end;  
 } revision_location_t;
 
+/* Absolute position and size of some item.
+ */
 typedef struct location_t
 {
+  /* absolute offset in the file */
   apr_size_t offset;
+
+  /* item length in bytes */
   apr_size_t size;
 } location_t;
 
+/* A parsed directory entry. Note that instances of this struct may be
+ * shared between different DIRECTORY_T containers.
+ */
 typedef struct direntry_t
 {
+  /* (local) entry / path name */
   const char *name;
+
+  /* strlen (name) */
   apr_size_t name_len;
+
+  /* node rev providing ID and representation(s) */
   noderev_t *node;
 } direntry_t;
 
+/* Representation of a parsed directory content.
+ */
 typedef struct directory_t
 {
+  /* array of pointers to DIRENTRY_T */
   apr_array_header_t *entries;
+
+  /* MD5 of the textual representation. Will be set lazily as a side-effect
+   * of determining the length of this dir's textual representation. */
   unsigned char target_md5[16];
+
+  /* (expanded) length of the textual representation.
+   * Determined lazily during the write process. */
   apr_size_t size;
 } directory_t;
 
+/* A representation fragment.
+ */
 typedef struct representation_t
 {
+  /* location in the source file */
   location_t original;
+
+  /* location in the reordered target file */
   location_t target;
+
+  /* length of the PLAIN / DELTA line in the source file in bytes */
   apr_size_t header_size;
+
+  /* deltification base, or NULL if there is none */
   struct representation_t *delta_base;
+
+  /* revision that contains this representation
+   * (may be referenced by other revisions, though) */
   revision_info_t *revision;
+
+  /* representation content parsed as a directory. This will be NULL, if
+   * *no* directory noderev uses this representation. */
   directory_t *dir;
+
+  /* the source content has a PLAIN header, so we may simply copy the
+   * source content into the target */
   svn_boolean_t is_plain;
+
+  /* coloring flag used in the reordering algorithm to keep track of
+   * representations that still need to be placed. */
   svn_boolean_t covered;
 } representation_t;
 
+/* A node rev.
+ */
 struct noderev_t
 {
+  /* location within the source file */
   location_t original;
+
+  /* location within the reorganized target file. */
   location_t target;
+
+  /* predecessor node, or NULL if there is none */
   noderev_t *predecessor;
+
+  /* content representation; may be NULL if there is none */
   representation_t *text;
+
+  /* properties representation; may be NULL if there is none */
   representation_t *props;
+
+  /* revision that this noderev belongs to */
   revision_info_t *revision;
+
+  /* coloring flag used in the reordering algorithm to keep track of
+   * representations that still need to be placed. */
   svn_boolean_t covered;
 };
 
+/* Represents a single revision.
+ * There will be only one instance per revision. */
 struct revision_info_t
 {
+  /* number of this revision */
   svn_revnum_t revision;
+
+  /* position in the source file */
   revision_location_t original;
+
+  /* position in the reorganized target file */
   revision_location_t target;
+
+  /* noderev of the root directory */
   noderev_t *root_noderev;
+
+  /* all noderevs_t of this revision (in no particular order),
+   * i.e. those that point back to this struct */
   apr_array_header_t *node_revs;
+  
+  /* all representation_t of this revision (in no particular order),
+   * i.e. those that point back to this struct */
   apr_array_header_t *representations;
 };
 
+/* Represents a packed revision file.
+ */
 typedef struct revision_pack_t
 {
+  /* first revision in the pack file */
   svn_revnum_t base;
+
+  /* revision_info_t* of all revisions in the pack file; in revision order. */
   apr_array_header_t *info;
+
+  /* list of fragments to place in the target pack file; in target order. */
   apr_array_header_t *fragments;
+
+  /* source pack file length */
   apr_size_t filesize;
+
+  /* temporary value. Equal to the number of bytes in the target pack file
+   * already allocated to fragments. */
   apr_size_t target_offset;
 } revision_pack_t;
 
+/* Cache for revision source content.  All content is stored in DATA and
+ * the HASH maps revision number to an svn_string_t instance whose data
+ * member points into DATA.
+ * 
+ * Once TOTAL_SIZE exceeds LIMIT, all content will be discarded.  Similarly,
+ * the hash gets cleared every 10000 insertions to keep the HASH_POOL
+ * memory usage in check.
+ */
 typedef struct content_cache_t
 {
-  apr_pool_t *pool;
+  /* pool used for HASH */
   apr_pool_t *hash_pool;
 
+  /* svn_revnum_t -> svn_string_t.
+   * The strings become (potentially) invalid when adding new cache entries. */
   apr_hash_t *hash;
 
+  /* data buffer. the first TOTAL_SIZE bytes are actually being used. */
   char *data;
+
+  /* DATA capacity */
   apr_size_t limit;
 
+  /* number of bytes used in DATA */
   apr_size_t total_size;
+
+  /* number of insertions since the last hash cleanup */
   apr_size_t insert_count;
 } content_cache_t;
 
+/* A cached directory. In contrast to directory_t, this stored the data as
+ * the plain hash that the normal FSFS will use to serialize & diff dirs.
+ */
 typedef struct dir_cache_entry_t
 {
+  /* revision containing the representation */
   svn_revnum_t revision;
+
+  /* offset of the representation within that revision */
   apr_size_t offset;
-  
+
+  /* key-value representation of the directory entries */
   apr_hash_t *hash;
 } dir_cache_entry_t;
 
+/* Directory cache. (revision, offset) will be mapped directly into the
+ * ENTRIES array of ENTRY_COUNT buckets (many entries will be NULL).
+ * Two alternating pools will be used to allocate dir content.
+ * 
+ * If the INSERT_COUNT exceeds a given limit, the pools get exchanged and
+ * the older of the two will be cleared. This is to keep dir objects valid
+ * for at least one insertion.
+ */
 typedef struct dir_cache_t
 {
+  /* fixed-size array of ENTRY_COUNT elements */
   dir_cache_entry_t *entries;
 
+  /* currently used for entry allocations */
   apr_pool_t *pool1;
+  
+  /* previously used for entry allocations */
   apr_pool_t *pool2;
+
+  /* size of ENTRIES in elements */
   apr_size_t entry_count;
+
+  /* number of directory elements added. I.e. usually >> #cached dirs */
   apr_size_t insert_count;
 } dir_cache_t;
 
+/* A cached, undeltified txdelta window.
+ */
 typedef struct window_cache_entry_t
 {
+  /* revision containing the window */
   svn_revnum_t revision;
+
+  /* offset of the deltified window within that revision */
   apr_size_t offset;
 
+  /* window content */
   svn_stringbuf_t *window;
 } window_cache_entry_t;
 
+/* Cache for undeltified txdelta windows. (revision, offset) will be mapped
+ * directly into the ENTRIES array of INSERT_COUNT buckets (most entries
+ * will be NULL).
+ *
+ * The cache will be cleared when USED exceeds CAPACITY.
+ */
 typedef struct window_cache_t
 {
+  /* fixed-size array of ENTRY_COUNT elements */
   window_cache_entry_t *entries;
 
+  /* used to allocate windows */
   apr_pool_t *pool;
+
+  /* size of ENTRIES in elements */
   apr_size_t entry_count;
+
+  /* maximum combined size of all cached windows */
   apr_size_t capacity;
+
+  /* current combined size of all cached windows */
   apr_size_t used;
 } window_cache_t;
 
+/* Root data structure containing all information about a given repository.
+ */
 typedef struct fs_fs_t
 {
+  /* repository to reorg */
   const char *path;
+
+  /* revision to start at (must be 0, ATM) */
   svn_revnum_t start_revision;
+
+  /* FSFS format number */
   int format;
 
+  /* highest revision number in the repo */
   svn_revnum_t max_revision;
+
+  /* first non-packed revision */
   svn_revnum_t min_unpacked_rev;
+
+  /* sharing size*/
   int max_files_per_dir;
 
+  /* all revisions */
   apr_array_header_t *revisions;
+
+  /* all packed files */
   apr_array_header_t *packs;
 
+  /* empty representation.
+   * Used as a dummy base for DELTA reps without base. */
   representation_t *null_base;
+
+  /* revision content cache */
   content_cache_t *cache;
+
+  /* directory hash cache */
   dir_cache_t *dir_cache;
+
+  /* undeltified txdelta window cache */
   window_cache_t *window_cache;
 } fs_fs_t;
 
+/* Return the rev pack folder for revision REV in FS.
+ */
 static const char *
 get_pack_folder(fs_fs_t *fs,
                 svn_revnum_t rev,
@@ -215,6 +426,8 @@ get_pack_folder(fs_fs_t *fs,
                       fs->path, rev / fs->max_files_per_dir);
 }
 
+/* Return the path of the file containing revision REV in FS.
+ */
 static const char *
 rev_or_pack_file_name(fs_fs_t *fs,
                       svn_revnum_t rev,
@@ -226,6 +439,8 @@ rev_or_pack_file_name(fs_fs_t *fs,
                           rev / fs->max_files_per_dir, rev);
 }
 
+/* Open the file containing revision REV in FS and return it in *FILE.
+ */
 static svn_error_t *
 open_rev_or_pack_file(apr_file_t **file,
                       fs_fs_t *fs,
@@ -239,6 +454,9 @@ open_rev_or_pack_file(apr_file_t **file,
                           pool);
 }
 
+/* Read the whole content of the file containing REV in FS and return that
+ * in *CONTENT.
+ */
 static svn_error_t *
 read_rev_or_pack_file(svn_stringbuf_t **content,
                       fs_fs_t *fs,
@@ -250,13 +468,15 @@ read_rev_or_pack_file(svn_stringbuf_t **
                                   pool);
 }
 
+/* Return a new content cache with the given size LIMIT.  Use POOL for
+ * all cache-related allocations.
+ */
 static content_cache_t *
 create_content_cache(apr_pool_t *pool,
                      apr_size_t limit)
 {
   content_cache_t *result = apr_pcalloc(pool, sizeof(*result));
 
-  result->pool = pool;
   result->hash_pool = svn_pool_create(pool);
   result->hash = svn_hash__make(result->hash_pool);
   result->limit = limit;
@@ -267,6 +487,9 @@ create_content_cache(apr_pool_t *pool,
   return result;
 }
 
+/* Return the content of revision REVISION from CACHE. Return NULL upon a
+ * cache miss. This is a cache-internal function.
+ */
 static svn_string_t *
 get_cached_content(content_cache_t *cache,
                    svn_revnum_t revision)
@@ -274,6 +497,9 @@ get_cached_content(content_cache_t *cach
   return apr_hash_get(cache->hash, &revision, sizeof(revision));
 }
 
+/* Take the content in DATA and store it under REVISION in CACHE.
+ * This is a cache-internal function.
+ */
 static void
 set_cached_content(content_cache_t *cache,
                    svn_revnum_t revision,
@@ -281,11 +507,14 @@ set_cached_content(content_cache_t *cach
 {
   svn_string_t *content;
   svn_revnum_t *key;
-  
+
+  /* double insertion? -> broken cache logic */
   assert(get_cached_content(cache, revision) == NULL);
 
+  /* purge the cache upon overflow */
   if (cache->total_size + data->len > cache->limit)
     {
+      /* the hash pool grows slowly over time; clear it once in a while */
       if (cache->insert_count > 10000)
         {
           svn_pool_clear(cache->hash_pool);
@@ -296,8 +525,13 @@ set_cached_content(content_cache_t *cach
         cache->hash = svn_hash__make(cache->hash_pool);
 
       cache->total_size = 0;
+
+      /* buffer overflow / revision too large */
+      if (data->len > cache->limit)
+        SVN_ERR_MALFUNCTION_NO_RETURN();
     }
 
+  /* copy data to cache and update he index (hash) */
   content = apr_palloc(cache->hash_pool, sizeof(*content));
   content->data = cache->data + cache->total_size;
   content->len = data->len;
@@ -312,6 +546,9 @@ set_cached_content(content_cache_t *cach
   ++cache->insert_count;
 }
 
+/* Get the file content of revision REVISION in FS and return it in *DATA.
+ * Use SCRATCH_POOL for temporary allocations.
+ */
 static svn_error_t *
 get_content(svn_string_t **data,
             fs_fs_t *fs,
@@ -322,7 +559,8 @@ get_content(svn_string_t **data,
   revision_info_t *revision_info;
   svn_stringbuf_t *temp;
   apr_off_t temp_offset;
-  
+
+  /* try getting the data from our cache */
   svn_string_t *result = get_cached_content(fs->cache, revision);
   if (result)
     {
@@ -330,6 +568,7 @@ get_content(svn_string_t **data,
       return SVN_NO_ERROR;
     }
 
+  /* not in cache. Is the revision valid at all? */
   if (revision - fs->start_revision > fs->revisions->nelts)
     return svn_error_createf(SVN_ERR_BAD_VERSION_FILE_FORMAT, NULL,
                              _("Unknown revision %ld"), revision);
@@ -337,6 +576,8 @@ get_content(svn_string_t **data,
                                 revision - fs->start_revision,
                                 revision_info_t*);
 
+  /* read the revision content. Assume that the file has *not* been
+   * reorg'ed, yet, i.e. all data is in one place. */
   temp = svn_stringbuf_create_ensure(  revision_info->original.end
                                      - revision_info->original.offset,
                                      scratch_pool);
@@ -350,6 +591,7 @@ get_content(svn_string_t **data,
   revision_info->original.offset = (apr_size_t)temp_offset;
   SVN_ERR(svn_io_file_read(file, temp->data, &temp->len, scratch_pool));
 
+  /* cache the result and return it */
   set_cached_content(fs->cache, revision,
                      svn_stringbuf__morph_into_string(temp));
   *data = get_cached_content(fs->cache, revision);
@@ -357,6 +599,9 @@ get_content(svn_string_t **data,
   return SVN_NO_ERROR;
 }
 
+/* Return a new directory cache with ENTRY_COUNT buckets in its index.
+ * Use POOL for all cache-related allocations.
+ */
 static dir_cache_t *
 create_dir_cache(apr_pool_t *pool,
                  apr_size_t entry_count)
@@ -372,6 +617,9 @@ create_dir_cache(apr_pool_t *pool,
   return result;
 }
 
+/* Return the position within FS' dir cache ENTRIES index for the given
+ * (REVISION, OFFSET) pair. This is a cache-internal function.
+ */
 static apr_size_t
 get_dir_cache_index(fs_fs_t *fs,
                     svn_revnum_t revision,
@@ -380,12 +628,18 @@ get_dir_cache_index(fs_fs_t *fs,
   return (revision + offset * 0xd1f3da69) % fs->dir_cache->entry_count;
 }
 
+/* Return the currently active pool of FS' dir cache. Note that it may be
+ * cleared after *2* insertions.
+ */
 static apr_pool_t *
 get_cached_dir_pool(fs_fs_t *fs)
 {
   return fs->dir_cache->pool1;
 }
 
+/* Return the cached directory content stored in REPRESENTAION within FS.
+ * If that has not been found in cache, return NULL.
+ */
 static apr_hash_t *
 get_cached_dir(fs_fs_t *fs,
                representation_t *representation)
@@ -401,17 +655,21 @@ get_cached_dir(fs_fs_t *fs,
     : NULL;
 }
 
+/* Cache the directory HASH for  REPRESENTAION within FS.
+ */
 static void
 set_cached_dir(fs_fs_t *fs,
                representation_t *representation,
                apr_hash_t *hash)
 {
+  /* select the entry to use */
   svn_revnum_t revision = representation->revision->revision;
   apr_size_t offset = representation->original.offset;
 
   apr_size_t i = get_dir_cache_index(fs, revision, offset);
   dir_cache_entry_t *entry = &fs->dir_cache->entries[i];
 
+  /* clean the cache and rotate pools at regular intervals */
   fs->dir_cache->insert_count += apr_hash_count(hash);
   if (fs->dir_cache->insert_count >= fs->dir_cache->entry_count * 100)
     {
@@ -428,11 +686,16 @@ set_cached_dir(fs_fs_t *fs,
       fs->dir_cache->pool1 = pool;
     }
 
+  /* write data to cache */
   entry->hash = hash;
   entry->offset = offset;
   entry->revision = revision;
 }
 
+/* Return a new txdelta window cache with ENTRY_COUNT buckets in its index
+ * and a the total CAPACITY given in bytes.
+ * Use POOL for all cache-related allocations.
+ */
 static window_cache_t *
 create_window_cache(apr_pool_t *pool,
                     apr_size_t entry_count,
@@ -449,6 +712,9 @@ create_window_cache(apr_pool_t *pool,
   return result;
 }
 
+/* Return the position within FS' window cache ENTRIES index for the given
+ * (REVISION, OFFSET) pair. This is a cache-internal function.
+ */
 static apr_size_t
 get_window_cache_index(fs_fs_t *fs,
                        svn_revnum_t revision,
@@ -457,6 +723,9 @@ get_window_cache_index(fs_fs_t *fs,
   return (revision + offset * 0xd1f3da69) % fs->window_cache->entry_count;
 }
 
+/* Return the cached txdelta window stored in REPRESENTAION within FS.
+ * If that has not been found in cache, return NULL.
+ */
 static svn_stringbuf_t *
 get_cached_window(fs_fs_t *fs,
                   representation_t *representation,
@@ -473,17 +742,21 @@ get_cached_window(fs_fs_t *fs,
     : NULL;
 }
 
+/* Cache the undeltified txdelta WINDOW for REPRESENTAION within FS.
+ */
 static void
 set_cached_window(fs_fs_t *fs,
                   representation_t *representation,
                   svn_stringbuf_t *window)
 {
+  /* select entry */
   svn_revnum_t revision = representation->revision->revision;
   apr_size_t offset = representation->original.offset;
 
   apr_size_t i = get_window_cache_index(fs, revision, offset);
   window_cache_entry_t *entry = &fs->window_cache->entries[i];
 
+  /* if the capacity is exceeded, clear the cache */
   fs->window_cache->used += window->len;
   if (fs->window_cache->used >= fs->window_cache->capacity)
     {
@@ -494,6 +767,7 @@ set_cached_window(fs_fs_t *fs,
       fs->window_cache->used = window->len;
     }
 
+  /* set the entry to a copy of the window data */
   entry->window = svn_stringbuf_dup(window, fs->window_cache->pool);
   entry->offset = offset;
   entry->revision = revision;
@@ -1672,7 +1946,7 @@ add_noderev_recursively(fs_fs_t *fs,
   node->target.offset = *current_pos;
 
   fragment.data = node;
-  fragment.kind = noderep_fragment;
+  fragment.kind = noderev_fragment;
   fragment.position = *current_pos;
   APR_ARRAY_PUSH(fragments, fragment_t) = fragment;
 
@@ -1804,7 +2078,7 @@ get_content_length(apr_size_t *length,
         case dir_fragment:
           *length = content->len + 16;
           break;
-        case noderep_fragment:
+        case noderev_fragment:
           *length = content->len + 3;
           break;
         default:
@@ -1846,7 +2120,7 @@ move_fragment(fragment_t *fragment,
         representation->target.offset = new_position;
         break;
 
-      case noderep_fragment:
+      case noderev_fragment:
         node = fragment->data;
         node->target.offset = new_position;
         break;
@@ -2352,7 +2626,7 @@ get_fragment_content(svn_string_t **cont
 
         return SVN_NO_ERROR;
 
-      case noderep_fragment:
+      case noderev_fragment:
         node = fragment->data;
         SVN_ERR(get_content(&revision_content, fs,
                             node->revision->revision, pool));