You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/09/28 19:35:26 UTC

svn commit: r1002283 [8/10] - in /subversion/branches/javahl-ra: ./ build/ notes/ notes/http-and-webdav/ notes/wc-ng/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversion/bindings/javahl/src/org/tig...

Modified: subversion/branches/javahl-ra/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/cl.h?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/cl.h (original)
+++ subversion/branches/javahl-ra/subversion/svn/cl.h Tue Sep 28 17:35:22 2010
@@ -229,6 +229,7 @@ typedef struct svn_cl__opt_state_t
   svn_boolean_t show_diff;        /* produce diff output */
   svn_boolean_t internal_diff;    /* override diff_cmd in config file */
   svn_boolean_t use_git_diff_format; /* Use git's extended diff format */
+  svn_boolean_t old_patch_target_names; /* Use target names from old side */
 } svn_cl__opt_state_t;
 
 

Modified: subversion/branches/javahl-ra/subversion/svn/commit-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/commit-cmd.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/commit-cmd.c (original)
+++ subversion/branches/javahl-ra/subversion/svn/commit-cmd.c Tue Sep 28 17:35:22 2010
@@ -97,6 +97,21 @@ svn_cl__commit(apr_getopt_t *os,
   if (opt_state->depth == svn_depth_unknown)
     opt_state->depth = svn_depth_infinity;
 
+  /* Copies are done server-side, and cheaply, which means they're
+   * effectively always done with infinite depth.
+   * This is a potential cause of confusion for users trying to commit
+   * copied subtrees in part by restricting the commit's depth.
+   * See issue #3699. */
+  if (opt_state->depth < svn_depth_infinity)
+    SVN_ERR(svn_cmdline_printf(pool,
+                               _("svn: warning: The depth of this commit "
+                                 "is '%s', but copied directories will "
+                                 "regardless be committed with depth '%s'. "
+                                 "You must remove unwanted children of those "
+                                 "directories in a separate commit.\n"),
+                               svn_depth_to_word(opt_state->depth),
+                               svn_depth_to_word(svn_depth_infinity)));
+    
   cfg = apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
                      APR_HASH_KEY_STRING);
   if (cfg)

Modified: subversion/branches/javahl-ra/subversion/svn/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/main.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/main.c (original)
+++ subversion/branches/javahl-ra/subversion/svn/main.c Tue Sep 28 17:35:22 2010
@@ -122,6 +122,7 @@ typedef enum {
   opt_show_diff,
   opt_internal_diff,
   opt_use_git_diff_format,
+  opt_old_patch_target_names,
 } svn_cl__longopt_t;
 
 /* Option codes and descriptions for the command line client.
@@ -357,6 +358,10 @@ const apr_getopt_option_t svn_cl__option
   {"reverse-diff", opt_reverse_diff, 0,
                     N_("apply the unidiff in reverse\n"
                        "                             "
+                       "This option also reverses patch target names; the\n"
+                       "                             "
+                       "--old-patch-target-names option will prevent this.\n"
+                       "                             "
                        "[alias: --rd]")},
   {"ignore-whitespace", opt_ignore_whitespace, 0,
                        N_("ignore whitespace during pattern matching\n"
@@ -373,6 +378,19 @@ const apr_getopt_option_t svn_cl__option
   {"git", opt_use_git_diff_format, 0,
                        N_("use git's extended diff format\n")},
                   
+  {"old-patch-target-names", opt_old_patch_target_names, 0,
+                       N_("use target names from the old side of a patch.\n"
+                       "                             "
+                       "If a diff header contains\n"
+                       "                             "
+                       "  --- foo.c\n"
+                       "                             "
+                       "  +++ foo.c.new\n"
+                       "                             "
+                       "this option will cause the name \"foo.c\" to be used\n"
+                       "                             "
+                       "[alias: --optn]")},
+
   /* Long-opt Aliases
    *
    * These have NULL desriptions, but an option code that matches some
@@ -403,6 +421,7 @@ const apr_getopt_option_t svn_cl__option
   {"idiff",         opt_internal_diff, 0, NULL},
   {"nul",           opt_no_unlock, 0, NULL},
   {"keep-lock",     opt_no_unlock, 0, NULL},
+  {"optn",          opt_old_patch_target_names, 0, NULL},
 
   {0,               0, 0, 0},
 };
@@ -852,7 +871,7 @@ const svn_opt_subcommand_desc2_t svn_cl_
      "  do not agree with.\n"
      ),
     {'q', opt_dry_run, opt_strip_count, opt_reverse_diff,
-     opt_ignore_whitespace} },
+     opt_ignore_whitespace, opt_old_patch_target_names} },
 
   { "propdel", svn_cl__propdel, {"pdel", "pd"}, N_
     ("Remove a property from files, dirs, or revisions.\n"
@@ -1788,6 +1807,9 @@ main(int argc, const char *argv[])
       case opt_use_git_diff_format:
         opt_state.use_git_diff_format = TRUE;
         break;
+      case opt_old_patch_target_names:
+        opt_state.old_patch_target_names = TRUE;
+        break;
       default:
         /* Hmmm. Perhaps this would be a good place to squirrel away
            opts that commands like svn diff might need. Hmmm indeed. */
@@ -2065,12 +2087,24 @@ main(int argc, const char *argv[])
         }
     }
 
-  if (opt_state.relocate && (opt_state.depth != svn_depth_unknown))
+  /* Relocation is infinite-depth only. */
+  if (opt_state.relocate)
     {
-      err = svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
-                             _("--relocate and --depth are mutually "
-                               "exclusive"));
-      return svn_cmdline_handle_exit_error(err, pool, "svn: ");
+      if (opt_state.depth != svn_depth_unknown)
+        {
+          err = svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
+                                 _("--relocate and --depth are mutually "
+                                   "exclusive"));
+          return svn_cmdline_handle_exit_error(err, pool, "svn: ");
+        }
+      if (! descend)
+        {
+          err = svn_error_create(
+                    SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
+                    _("--relocate and --non-recursive (-N) are mutually "
+                      "exclusive"));
+          return svn_cmdline_handle_exit_error(err, pool, "svn: ");
+        }
     }
 
   /* Only a few commands can accept a revision range; the rest can take at
@@ -2274,9 +2308,6 @@ main(int argc, const char *argv[])
                                            pool)))
     svn_handle_error2(err, stderr, TRUE, "svn: ");
 
-  /* svn can safely create instance of QApplication class. */
-  svn_auth_set_parameter(ab, "svn:auth:qapplication-safe", "1");
-
   ctx->auth_baton = ab;
 
   /* Set up conflict resolution callback. */

Modified: subversion/branches/javahl-ra/subversion/svn/move-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/move-cmd.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/move-cmd.c (original)
+++ subversion/branches/javahl-ra/subversion/svn/move-cmd.c Tue Sep 28 17:35:22 2010
@@ -84,7 +84,7 @@ svn_cl__move(apr_getopt_t *os,
 
   SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, pool));
 
-  err = svn_client_move6(targets, dst_path, opt_state->force,
+  err = svn_client_move6(targets, dst_path,
                          TRUE, opt_state->parents, opt_state->revprop_table,
                          svn_cl__print_commit_info, NULL, ctx, pool);
 

Modified: subversion/branches/javahl-ra/subversion/svn/patch-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/patch-cmd.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/patch-cmd.c (original)
+++ subversion/branches/javahl-ra/subversion/svn/patch-cmd.c Tue Sep 28 17:35:22 2010
@@ -74,6 +74,7 @@ svn_cl__patch(apr_getopt_t *os,
 
   SVN_ERR(svn_client_patch(abs_patch_path, abs_target_path,
                            opt_state->dry_run, opt_state->strip_count,
+                           opt_state->old_patch_target_names,
                            opt_state->reverse_diff,
                            opt_state->ignore_whitespace,
                            TRUE, NULL, NULL, ctx, pool, pool));

Modified: subversion/branches/javahl-ra/subversion/svn/switch-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/switch-cmd.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/switch-cmd.c (original)
+++ subversion/branches/javahl-ra/subversion/svn/switch-cmd.c Tue Sep 28 17:35:22 2010
@@ -41,7 +41,6 @@
 
 static svn_error_t *
 rewrite_urls(const apr_array_header_t *targets,
-             svn_boolean_t recurse,
              svn_client_ctx_t *ctx,
              apr_pool_t *pool)
 {
@@ -67,7 +66,7 @@ rewrite_urls(const apr_array_header_t *t
 
   if (targets->nelts == 2)
     {
-      SVN_ERR(svn_client_relocate("", from, to, recurse, ctx, pool));
+      SVN_ERR(svn_client_relocate2("", from, to, ctx, pool));
     }
   else
     {
@@ -75,8 +74,7 @@ rewrite_urls(const apr_array_header_t *t
         {
           const char *target = APR_ARRAY_IDX(targets, i, const char *);
           svn_pool_clear(subpool);
-          SVN_ERR(svn_client_relocate(target, from, to, recurse,
-                                      ctx, subpool));
+          SVN_ERR(svn_client_relocate2(target, from, to, ctx, subpool));
         }
     }
 
@@ -109,9 +107,7 @@ svn_cl__switch(apr_getopt_t *os,
 
   /* handle only-rewrite case specially */
   if (opt_state->relocate)
-    return rewrite_urls(targets,
-                        SVN_DEPTH_IS_RECURSIVE(opt_state->depth),
-                        ctx, scratch_pool);
+    return rewrite_urls(targets, ctx, scratch_pool);
 
   if (targets->nelts < 1)
     return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);

Modified: subversion/branches/javahl-ra/subversion/svn/upgrade-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/upgrade-cmd.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/upgrade-cmd.c (original)
+++ subversion/branches/javahl-ra/subversion/svn/upgrade-cmd.c Tue Sep 28 17:35:22 2010
@@ -31,6 +31,7 @@
 #include "svn_client.h"
 #include "svn_error_codes.h"
 #include "svn_error.h"
+#include "svn_path.h"
 #include "cl.h"
 #include "svn_private_config.h"
 
@@ -59,6 +60,19 @@ svn_cl__upgrade(apr_getopt_t *os,
 
   SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool));
 
+  /* Don't even attempt to modify the working copy if any of the
+   * targets look like URLs. URLs are invalid input. */
+  for (i = 0; i < targets->nelts; i++)
+    {
+      const char *target = APR_ARRAY_IDX(targets, i, const char *);
+
+      if (svn_path_is_url(target))
+        return svn_error_return(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
+                                                  NULL,
+                                                  _("'%s' is not a local path"),
+                                                  target));
+    }
+
   iterpool = svn_pool_create(scratch_pool);
   for (i = 0; i < targets->nelts; i++)
     {

Modified: subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.c (original)
+++ subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.c Tue Sep 28 17:35:22 2010
@@ -27,12 +27,19 @@
 #include "svn_repos.h"
 #include "svn_path.h"
 #include "svn_props.h"
+#include "svn_subst.h"
 #include "svn_dirent_uri.h"
 
 #include "dump_editor.h"
 
 #define ARE_VALID_COPY_ARGS(p,r) ((p) && SVN_IS_VALID_REVNUM(r))
 
+#ifdef SVN_DEBUG
+#define LDR_DBG(x) SVN_DBG(x)
+#else
+#define LDR_DBG(x) while(0)
+#endif
+
 /* The baton used by the dump editor. */
 struct dump_edit_baton {
   /* The output stream we write the dumpfile to */
@@ -60,11 +67,41 @@ struct dump_edit_baton {
   const char *base_checksum;
 
   /* Flags to trigger dumping props and text */
-  svn_boolean_t dump_props;
   svn_boolean_t dump_text;
-  svn_boolean_t dump_props_pending;
+  svn_boolean_t dump_props;
+  svn_boolean_t dump_newlines;
 };
 
+/* Normalize the line ending style of the values of properties in PROPS
+ * that "need translation" (according to svn_prop_needs_translation(),
+ * currently all svn:* props) so that they contain only LF (\n) line endings.
+ */
+svn_error_t *
+normalize_props(apr_hash_t *props,
+                apr_pool_t *pool)
+{
+  apr_hash_index_t *hi;
+  const char *key, *cstring;
+  const svn_string_t *value;
+
+  for (hi = apr_hash_first(pool, props); hi; hi = apr_hash_next(hi))
+    {
+      key = svn__apr_hash_index_key(hi);
+      value = svn__apr_hash_index_val(hi);
+
+      if (svn_prop_needs_translation(key))
+        {
+          SVN_ERR(svn_subst_translate_cstring2(value->data, &cstring,
+                                               "\n", TRUE,
+                                               NULL, FALSE,
+                                               pool));
+          value = svn_string_create(cstring, pool);
+          apr_hash_set(props, key, APR_HASH_KEY_STRING, value);
+        }
+    }
+  return SVN_NO_ERROR;
+}
+
 /* Make a directory baton to represent the directory at path (relative
  * to the edit_baton).
  *
@@ -91,17 +128,15 @@ make_dir_baton(const char *path,
   struct dir_baton *new_db = apr_pcalloc(pool, sizeof(*new_db));
   const char *abspath;
 
-  /* Disallow a path relative to nothing. */
-  SVN_ERR_ASSERT_NO_RETURN(!path || pb);
-
   /* Construct the full path of this node. */
   if (pb)
     abspath = svn_uri_join("/", path, pool);
   else
-    abspath = "/";
+    abspath = apr_pstrdup(pool, "/");
 
-  /* Remove leading slashes from copyfrom paths. */
-  if (copyfrom_path && strcmp(copyfrom_path, "/"))
+  /* Strip leading slash from copyfrom_path so that the path is
+     canonical and svn_relpath_join can be used */
+  if (copyfrom_path)
     copyfrom_path = ((*copyfrom_path == '/') ?
                      copyfrom_path + 1 : copyfrom_path);
 
@@ -113,7 +148,7 @@ make_dir_baton(const char *path,
   new_db->copyfrom_rev = copyfrom_rev;
   new_db->added = added;
   new_db->written_out = FALSE;
-  new_db->deleted_entries = apr_hash_make(pool);
+  new_db->deleted_entries = apr_hash_make(eb->pool);
 
   return new_db;
 }
@@ -133,6 +168,7 @@ dump_props(struct dump_edit_baton *eb,
   if (trigger_var && !*trigger_var)
     return SVN_NO_ERROR;
 
+  SVN_ERR(normalize_props(eb->props, eb->pool));
   svn_stringbuf_setempty(eb->propstring);
   propstream = svn_stream_from_stringbuf(eb->propstring, eb->pool);
   SVN_ERR(svn_hash_write_incremental(eb->props, eb->deleted_props,
@@ -166,8 +202,8 @@ dump_props(struct dump_edit_baton *eb,
       SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
 
       /* Cleanup so that data is never dumped twice. */
-      svn_hash__clear(eb->props, pool);
-      svn_hash__clear(eb->deleted_props, pool);
+      svn_hash__clear(eb->props, eb->pool);
+      svn_hash__clear(eb->deleted_props, eb->pool);
       if (trigger_var)
         *trigger_var = FALSE;
     }
@@ -175,6 +211,19 @@ dump_props(struct dump_edit_baton *eb,
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+dump_newlines(struct dump_edit_baton *eb,
+           svn_boolean_t *trigger_var,
+           apr_pool_t *pool)
+{
+  if (trigger_var && *trigger_var)
+    {
+      SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
+      *trigger_var = FALSE;
+    }
+  return SVN_NO_ERROR;
+}
+
 /*
  * Write out a node record for PATH of type KIND under EB->FS_ROOT.
  * ACTION describes what is happening to the node (see enum
@@ -197,10 +246,10 @@ dump_node(struct dump_edit_baton *eb,
           apr_pool_t *pool)
 {
   /* Remove leading slashes from path and copyfrom_path */
-  if (path && strcmp(path, "/"))
+  if (path)
     path = ((*path == '/') ? path + 1 : path);
   
-  if (copyfrom_path && strcmp(copyfrom_path, "/"))
+  if (copyfrom_path)
     copyfrom_path = ((*copyfrom_path == '/') ?
                      copyfrom_path + 1 : copyfrom_path);
 
@@ -221,6 +270,9 @@ dump_node(struct dump_edit_baton *eb,
   switch (action)
     {
     case svn_node_action_change:
+      /* We are here after a change_file_prop or change_dir_prop. They
+         set up whatever dump_props they needed to- nothing to
+         do here but print node action information */
       SVN_ERR(svn_stream_printf(eb->stream, pool,
                                 SVN_REPOS_DUMPFILE_NODE_ACTION
                                 ": change\n"));
@@ -234,7 +286,9 @@ dump_node(struct dump_edit_baton *eb,
                                     SVN_REPOS_DUMPFILE_NODE_ACTION
                                     ": replace\n"));
 
-          eb->dump_props_pending = TRUE;
+          /* Wait for a change_*_prop to be called before dumping
+             anything */          
+          eb->dump_props = TRUE;
           break;
         }
       /* More complex case: is_copy is true, and copyfrom_path/
@@ -251,7 +305,6 @@ dump_node(struct dump_edit_baton *eb,
 
       /* We can leave this routine quietly now, don't need to dump any
          content; that was already done in the second record. */
-      eb->dump_props = FALSE;
       break;
 
     case svn_node_action_delete:
@@ -259,10 +312,10 @@ dump_node(struct dump_edit_baton *eb,
                                 SVN_REPOS_DUMPFILE_NODE_ACTION
                                 ": delete\n"));
 
-      /* We can leave this routine quietly now, don't need to dump
-         any content. */
+      /* We can leave this routine quietly now. Nothing more to do-
+         print a couple of newlines because we're not dumping props or
+         text. */      
       SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
-      eb->dump_props = FALSE;
       break;
 
     case svn_node_action_add:
@@ -271,15 +324,17 @@ dump_node(struct dump_edit_baton *eb,
 
       if (!is_copy)
         {
-          /* eb->dump_props_pending for files is handled in close_file
+          /* eb->dump_props for files is handled in close_file
              which is called immediately.  However, directories are not
              closed until all the work inside them has been done;
-             eb->dump_props_pending for directories is handled in all the
+             eb->dump_props for directories is handled in all the
              functions that can possibly be called after add_directory:
              add_directory, open_directory, delete_entry, close_directory,
              add_file, open_file. change_dir_prop is a special case. */
 
-          eb->dump_props_pending = TRUE;
+          /* Wait for a change_*_prop to be called before dumping
+             anything */          
+          eb->dump_props = TRUE;
           break;
         }
 
@@ -290,19 +345,18 @@ dump_node(struct dump_edit_baton *eb,
                                 ": %s\n",
                                 copyfrom_rev, copyfrom_path));
 
-      /* Ugly hack: If a directory was copied from a previous revision,
-         nothing else can be done, and close_file won't be called to
-         write two blank lines. Write them here otherwise the `svnadmin
-         load` parser will fail. */
+      /* Ugly hack: If a directory was copied from a previous
+         revision, nothing like close_file will be called to write two
+         blank lines. If change_dir_prop is called, props are dumped
+         (along with the necessary PROPS-END\n\n and we're good. So
+         set a dump_newlines here to print the newlines unless
+         change_dir_prop is called next otherwise the `svnadmin load`
+         parser will fail.  */ 
       if (kind == svn_node_dir)
-        SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
+        eb->dump_newlines = TRUE;
 
       break;
     }
-
-  /* Dump property headers */
-  SVN_ERR(dump_props(eb, &(eb->dump_props), FALSE, pool));
-
   return SVN_NO_ERROR;
 }
 
@@ -315,6 +369,7 @@ open_root(void *edit_baton,
   struct dump_edit_baton *eb = edit_baton;
   /* Allocate a special pool for the edit_baton to avoid pool
      lifetime issues */
+
   eb->pool = svn_pool_create(pool);
   eb->props = apr_hash_make(eb->pool);
   eb->deleted_props = apr_hash_make(eb->pool);
@@ -322,6 +377,8 @@ open_root(void *edit_baton,
 
   *root_baton = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
                                edit_baton, NULL, FALSE, pool);
+  LDR_DBG(("open_root %p\n", *root_baton));
+
   return SVN_NO_ERROR;
 }
 
@@ -332,14 +389,19 @@ delete_entry(const char *path,
              apr_pool_t *pool)
 {
   struct dir_baton *pb = parent_baton;
-  const char *mypath = apr_pstrdup(pool, path);
+
+  LDR_DBG(("delete_entry %s\n", path));
 
   /* Some pending properties to dump? */
-  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
+  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+
+  /* Some pending newlines to dump? */
+  SVN_ERR(dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
 
   /* Add this path to the deleted_entries of the parent directory
      baton. */
-  apr_hash_set(pb->deleted_entries, mypath, APR_HASH_KEY_STRING, pb);
+  apr_hash_set(pb->deleted_entries, apr_pstrdup(pb->eb->pool, path),
+               APR_HASH_KEY_STRING, pb);
 
   return SVN_NO_ERROR;
 }
@@ -358,8 +420,13 @@ add_directory(const char *path,
     = make_dir_baton(path, copyfrom_path, copyfrom_rev, pb->eb, pb, TRUE, pool);
   svn_boolean_t is_copy;
 
+  LDR_DBG(("add_directory %s\n", path));
+
   /* Some pending properties to dump? */
-  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
+  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+
+  /* Some pending newlines to dump? */
+  SVN_ERR(dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
 
   /* This might be a replacement -- is the path already deleted? */
   val = apr_hash_get(pb->deleted_entries, path, APR_HASH_KEY_STRING);
@@ -398,8 +465,13 @@ open_directory(const char *path,
   const char *copyfrom_path = NULL;
   svn_revnum_t copyfrom_rev = SVN_INVALID_REVNUM;
 
+  LDR_DBG(("open_directory %s\n", path));
+
   /* Some pending properties to dump? */
-  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
+  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+
+  /* Some pending newlines to dump? */
+  SVN_ERR(dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
 
   /* If the parent directory has explicit comparison path and rev,
      record the same for this one. */
@@ -423,14 +495,22 @@ close_directory(void *dir_baton,
 {
   struct dir_baton *db = dir_baton;
   struct dump_edit_baton *eb = db->eb;
+  apr_pool_t *iterpool;
   apr_hash_index_t *hi;
-  apr_pool_t *iterpool = svn_pool_create(pool);
+
+  LDR_DBG(("close_directory %p\n", dir_baton));
 
   /* Some pending properties to dump? */
-  SVN_ERR(dump_props(eb, &(eb->dump_props_pending), TRUE, pool));
+  SVN_ERR(dump_props(eb, &(eb->dump_props), TRUE, pool));
 
-  /* Dump the directory entries */
-  for (hi = apr_hash_first(pool, db->deleted_entries); hi;
+  /* Some pending newlines to dump? */
+  SVN_ERR(dump_newlines(eb, &(eb->dump_newlines), pool));
+
+  /* Create a pool just for iterations to allocate a loop variable */
+  iterpool = svn_pool_create(pool);
+
+  /* Dump the deleted directory entries */
+  for (hi = apr_hash_first(iterpool, db->deleted_entries); hi;
        hi = apr_hash_next(hi))
     {
       const void *key;
@@ -438,12 +518,11 @@ close_directory(void *dir_baton,
       apr_hash_this(hi, &key, NULL, NULL);
       path = key;
 
-      svn_pool_clear(iterpool);
-
       SVN_ERR(dump_node(db->eb, path, svn_node_unknown, svn_node_action_delete,
-                        FALSE, NULL, SVN_INVALID_REVNUM, iterpool));
+                        FALSE, NULL, SVN_INVALID_REVNUM, pool));
     }
 
+  svn_hash__clear(db->deleted_entries, pool);
   svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
 }
@@ -460,8 +539,13 @@ add_file(const char *path,
   void *val;
   svn_boolean_t is_copy;
 
+  LDR_DBG(("add_file %s\n", path));
+
   /* Some pending properties to dump? */
-  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
+  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+
+  /* Some pending newlines to dump? */
+  SVN_ERR(dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
 
   /* This might be a replacement -- is the path already deleted? */
   val = apr_hash_get(pb->deleted_entries, path, APR_HASH_KEY_STRING);
@@ -500,8 +584,13 @@ open_file(const char *path,
   const char *copyfrom_path = NULL;
   svn_revnum_t copyfrom_rev = SVN_INVALID_REVNUM;
 
+  LDR_DBG(("open_file %s\n", path));
+
   /* Some pending properties to dump? */
-  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
+  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+
+  /* Some pending newlines to dump? */
+  SVN_ERR(dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
 
   /* If the parent directory has explicit copyfrom path and rev,
      record the same for this one. */
@@ -530,12 +619,14 @@ change_dir_prop(void *parent_baton,
 {
   struct dir_baton *db = parent_baton;
 
+  LDR_DBG(("change_dir_prop %p\n", parent_baton));
+
   if (svn_property_kind(NULL, name) != svn_prop_regular_kind)
     return SVN_NO_ERROR;
 
   if (value)
-    apr_hash_set(db->eb->props, apr_pstrdup(pool, name),
-                 APR_HASH_KEY_STRING, svn_string_dup(value, pool));
+    apr_hash_set(db->eb->props, apr_pstrdup(db->eb->pool, name),
+                 APR_HASH_KEY_STRING, svn_string_dup(value, db->eb->pool));
   else
     apr_hash_set(db->eb->deleted_props, apr_pstrdup(pool, name),
                  APR_HASH_KEY_STRING, "");
@@ -544,17 +635,21 @@ change_dir_prop(void *parent_baton,
     {
       /* If db->written_out is set, it means that the node information
          corresponding to this directory has already been written: don't
-         do anything; dump_props_pending will take care of dumping the
+         do anything; dump_props will take care of dumping the
          props. If it not, dump the node itself before dumping the
          props. */
 
       SVN_ERR(dump_node(db->eb, db->abspath, svn_node_dir,
                         svn_node_action_change, FALSE, db->copyfrom_path,
                         db->copyfrom_rev, pool));
-
-      SVN_ERR(dump_props(db->eb, NULL, TRUE, pool));
       db->written_out = TRUE;
     }
+
+  /* Dump props whether or not the directory has been written
+     out. Then disable printing a couple of extra newlines */
+  SVN_ERR(dump_props(db->eb, NULL, TRUE, pool));
+  db->eb->dump_newlines = FALSE;
+
   return SVN_NO_ERROR;
 }
 
@@ -566,20 +661,22 @@ change_file_prop(void *file_baton,
 {
   struct dump_edit_baton *eb = file_baton;
 
+  LDR_DBG(("change_file_prop %p\n", file_baton));
+
   if (svn_property_kind(NULL, name) != svn_prop_regular_kind)
     return SVN_NO_ERROR;
 
   if (value)
-    apr_hash_set(eb->props, apr_pstrdup(pool, name),
-                 APR_HASH_KEY_STRING, svn_string_dup(value, pool));
+    apr_hash_set(eb->props, apr_pstrdup(eb->pool, name),
+                 APR_HASH_KEY_STRING, svn_string_dup(value, eb->pool));
   else
-    apr_hash_set(eb->deleted_props, apr_pstrdup(pool, name),
+    apr_hash_set(eb->deleted_props, apr_pstrdup(eb->pool, name),
                  APR_HASH_KEY_STRING, "");
 
   /* Dump the property headers and wait; close_file might need
      to write text headers too depending on whether
      apply_textdelta is called */
-  eb->dump_props_pending = TRUE;
+  eb->dump_props = TRUE;
 
   return SVN_NO_ERROR;
 }
@@ -620,6 +717,8 @@ apply_textdelta(void *file_baton, const 
   hb->pool = handler_pool;
   hb->eb = eb;
 
+  LDR_DBG(("apply_textdelta %p\n", file_baton));
+
   /* Use a temporary file to measure the text-content-length */
   SVN_ERR(svn_stream_open_unique(&(hb->delta_filestream), &hb->delta_abspath,
                                  NULL, svn_io_file_del_none, hb->pool,
@@ -650,11 +749,13 @@ close_file(void *file_baton,
   svn_stream_t *delta_filestream;
   apr_finfo_t *info = apr_pcalloc(pool, sizeof(apr_finfo_t));
 
-  /* Some pending properties to dump? */
-  SVN_ERR(dump_props(eb, &(eb->dump_props_pending), FALSE, pool));
+  LDR_DBG(("close_file %p\n", file_baton));
 
-  /* The prop headers have already been dumped in dump_node; now dump
-     the text headers. */
+  /* Some pending properties to dump? Dump just the headers- dump the
+     props only after dumping the text headers too (if present) */
+  SVN_ERR(dump_props(eb, &(eb->dump_props), FALSE, pool));
+
+  /* Dump the text headers */
   if (eb->dump_text)
     {
       /* Text-delta: true */
@@ -686,7 +787,7 @@ close_file(void *file_baton,
 
   /* Content-length: 1549 */
   /* If both text and props are absent, skip this header */
-  if (eb->dump_props || eb->dump_props_pending)
+  if (eb->dump_props)
     SVN_ERR(svn_stream_printf(eb->stream, pool,
                               SVN_REPOS_DUMPFILE_CONTENT_LENGTH
                               ": %ld\n\n",
@@ -697,17 +798,16 @@ close_file(void *file_baton,
                               ": %ld\n\n",
                               (unsigned long)info->size));
 
-  /* Dump the props; the propstring should have already been
-     written in dump_node or above */
-  if (eb->dump_props || eb->dump_props_pending)
+  /* Dump the props now */
+  if (eb->dump_props)
     {
       SVN_ERR(svn_stream_write(eb->stream, eb->propstring->data,
                                &(eb->propstring->len)));
 
       /* Cleanup */
-      eb->dump_props = eb->dump_props_pending = FALSE;
-      svn_hash__clear(eb->props, pool);
-      svn_hash__clear(eb->deleted_props, pool);
+      eb->dump_props = FALSE;
+      svn_hash__clear(eb->props, eb->pool);
+      svn_hash__clear(eb->deleted_props, eb->pool);
     }
 
   /* Dump the text */
@@ -728,6 +828,8 @@ close_file(void *file_baton,
       eb->dump_text = FALSE;
     }
 
+  /* Write a couple of blank lines for matching output with `svnadmin
+     dump` */
   SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
 
   return SVN_NO_ERROR;
@@ -737,6 +839,7 @@ static svn_error_t *
 close_edit(void *edit_baton, apr_pool_t *pool)
 {
   struct dump_edit_baton *eb = edit_baton;
+  LDR_DBG(("close_edit\n"));
   svn_pool_destroy(eb->pool);
 
   return SVN_NO_ERROR;

Modified: subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.h?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.h (original)
+++ subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.h Tue Sep 28 17:35:22 2010
@@ -87,4 +87,12 @@ get_dump_editor(const svn_delta_editor_t
                 svn_stream_t *stream,
                 apr_pool_t *pool);
 
+/**
+ * Normalize the line ending style of the values of properties in @a
+ * rev_props using @a pool for memory allocation.
+ */
+svn_error_t *
+normalize_props(apr_hash_t *props,
+                apr_pool_t *pool);
+
 #endif

Modified: subversion/branches/javahl-ra/subversion/svnrdump/load_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnrdump/load_editor.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnrdump/load_editor.c (original)
+++ subversion/branches/javahl-ra/subversion/svnrdump/load_editor.c Tue Sep 28 17:35:22 2010
@@ -30,9 +30,15 @@
 #include "svn_path.h"
 #include "svn_ra.h"
 #include "svn_io.h"
+#include "svn_private_config.h"
+
+#include <apr_network_io.h>
 
 #include "load_editor.h"
 
+#define SVNRDUMP_PROP_LOCK SVN_PROP_PREFIX "rdump-lock"
+#define LOCK_RETRIES 10
+
 #ifdef SVN_DEBUG
 #define LDR_DBG(x) SVN_DBG(x)
 #else
@@ -50,6 +56,117 @@ commit_callback(const svn_commit_info_t 
   return SVN_NO_ERROR;
 }
 
+/* See subversion/svnsync/main.c for docstring */
+static svn_boolean_t is_atomicity_error(svn_error_t *err)
+{
+  return svn_error_has_cause(err, SVN_ERR_FS_PROP_BASEVALUE_MISMATCH);
+}
+
+/* Acquire a lock (of sorts) on the repository associated with the
+ * given RA SESSION. This lock is just a revprop change attempt in a
+ * time-delay loop. This function is duplicated by svnsync in main.c.
+ *
+ * ### TODO: Make this function more generic and
+ * expose it through a header for use by other Subversion
+ * applications to avoid duplication.
+ */
+static svn_error_t *
+get_lock(const svn_string_t **lock_string_p,
+         svn_ra_session_t *session,
+         apr_pool_t *pool)
+{
+  char hostname_str[APRMAXHOSTLEN + 1] = { 0 };
+  svn_string_t *mylocktoken, *reposlocktoken;
+  apr_status_t apr_err;
+  svn_boolean_t be_atomic;
+  apr_pool_t *subpool;
+  int i;
+
+  SVN_ERR(svn_ra_has_capability(session, &be_atomic,
+                                SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+                                pool));
+  if (! be_atomic)
+    {
+      /* Pre-1.7 server.  Can't lock without a race condition.
+         See issue #3546.
+       */
+      svn_error_t *err;
+
+      err = svn_error_create(
+              SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+              _("Target server does not support atomic revision property "
+                "edits; consider upgrading it to 1.7 or using an external "
+                "locking program"));
+      svn_handle_warning2(stderr, err, "svnrdump: ");
+      svn_error_clear(err);
+    }
+
+  apr_err = apr_gethostname(hostname_str, sizeof(hostname_str), pool);
+  if (apr_err)
+    return svn_error_wrap_apr(apr_err, _("Can't get local hostname"));
+
+  mylocktoken = svn_string_createf(pool, "%s:%s", hostname_str,
+                                   svn_uuid_generate(pool));
+
+  /* If we succeed, this is what the property will be set to. */
+  *lock_string_p = mylocktoken;
+
+  subpool = svn_pool_create(pool);
+
+  for (i = 0; i < LOCK_RETRIES; ++i)
+    {
+      svn_error_t *err;
+
+      svn_pool_clear(subpool);
+
+      SVN_ERR(svn_ra_rev_prop(session, 0, SVNRDUMP_PROP_LOCK, &reposlocktoken,
+                              subpool));
+
+      if (reposlocktoken)
+        {
+          /* Did we get it? If so, we're done, otherwise we sleep. */
+          if (strcmp(reposlocktoken->data, mylocktoken->data) == 0)
+            return SVN_NO_ERROR;
+          else
+            {
+              SVN_ERR(svn_cmdline_printf
+                      (pool, _("Failed to get lock on destination "
+                               "repos, currently held by '%s'\n"),
+                       reposlocktoken->data));
+
+              apr_sleep(apr_time_from_sec(1));
+            }
+        }
+      else if (i < LOCK_RETRIES - 1)
+        {
+          const svn_string_t *unset = NULL;
+
+          /* Except in the very last iteration, try to set the lock. */
+          err = svn_ra_change_rev_prop2(session, 0, SVNRDUMP_PROP_LOCK,
+                                        be_atomic ? &unset : NULL,
+                                        mylocktoken, subpool);
+
+          if (be_atomic && err && is_atomicity_error(err))
+            /* Someone else has the lock.  Let's loop. */
+            svn_error_clear(err);
+          else if (be_atomic && err == SVN_NO_ERROR)
+            /* We have the lock. 
+
+               However, for compatibility with concurrent svnsync's that don't
+               support atomicity, loop anyway to double-check that they haven't
+               overwritten our lock.
+             */
+            continue;
+          else
+            /* Genuine error, or we aren't atomic and need to loop. */
+            SVN_ERR(err);
+        }
+    }
+
+  return svn_error_createf(APR_EINVAL, NULL,
+                           _("Couldn't get lock on destination repos "
+                             "after %d attempts"), i);
+}
 
 static svn_error_t *
 new_revision_record(void **revision_baton,
@@ -116,6 +233,7 @@ new_node_record(void **node_baton,
   void *commit_edit_baton;
   char *ancestor_path;
   apr_array_header_t *residual_open_path;
+  char *relpath_compose;
   const char *nb_dirname;
   apr_size_t residual_close_count;
   int i;
@@ -238,8 +356,11 @@ new_node_record(void **node_baton,
         
       for (i = 0; i < residual_open_path->nelts; i ++)
         {
-          SVN_ERR(commit_editor->open_directory(APR_ARRAY_IDX(residual_open_path,
-                                                              i, const char *),
+          relpath_compose =
+            svn_relpath_join(rb->db->relpath,
+                             APR_ARRAY_IDX(residual_open_path, i, const char *),
+                             rb->pool);
+          SVN_ERR(commit_editor->open_directory(relpath_compose,
                                                 rb->db->baton,
                                                 rb->rev - 1,
                                                 rb->pool, &child_baton));
@@ -247,10 +368,7 @@ new_node_record(void **node_baton,
           child_db = apr_pcalloc(rb->pool, sizeof(*child_db));
           child_db->baton = child_baton;
           child_db->depth = rb->db->depth + 1;
-          child_db->relpath = svn_relpath_join(rb->db->relpath,
-                                               APR_ARRAY_IDX(residual_open_path,
-                                                             i, const char *),
-                                               rb->pool);
+          child_db->relpath = relpath_compose;
           child_db->parent = rb->db;
           rb->db = child_db;
         }
@@ -328,8 +446,8 @@ set_revision_property(void *baton,
   else
     /* Special handling for revision 0; this is safe because the
        commit_editor hasn't been created yet. */
-    SVN_ERR(svn_ra_change_rev_prop(rb->pb->session, rb->rev, name, value,
-                                   rb->pool));
+    SVN_ERR(svn_ra_change_rev_prop2(rb->pb->session, rb->rev,
+                                    name, NULL, value, rb->pool));
 
   /* Remember any datestamp/ author that passes through (see comment
      in close_revision). */
@@ -353,14 +471,21 @@ set_node_property(void *baton,
   commit_editor = nb->rb->pb->commit_editor;
   pool = nb->rb->pool;
 
-  LDR_DBG(("Applying properties on %p\n", nb->file_baton));
-  if (nb->kind == svn_node_file)
-    SVN_ERR(commit_editor->change_file_prop(nb->file_baton, name,
-                                            value, pool));
-  else
-    SVN_ERR(commit_editor->change_dir_prop(nb->rb->db->baton, name,
-                                           value, pool));
-
+  switch (nb->kind)
+    {
+    case svn_node_file:
+      LDR_DBG(("Applying properties on %p\n", nb->file_baton));
+      SVN_ERR(commit_editor->change_file_prop(nb->file_baton, name,
+                                              value, pool));
+      break;
+    case svn_node_dir:
+      LDR_DBG(("Applying properties on %p\n", nb->rb->db->baton));
+      SVN_ERR(commit_editor->change_dir_prop(nb->rb->db->baton, name,
+                                             value, pool));
+      break;
+    default:
+      break;
+    }
   return SVN_NO_ERROR;
 }
 
@@ -486,12 +611,12 @@ close_revision(void *baton)
 
   /* svn_fs_commit_txn rewrites the datestamp/ author property-
      rewrite it by hand after closing the commit_editor. */
-  SVN_ERR(svn_ra_change_rev_prop(rb->pb->session, rb->rev,
-                                 SVN_PROP_REVISION_DATE,
-                                 rb->datestamp, rb->pool));
-  SVN_ERR(svn_ra_change_rev_prop(rb->pb->session, rb->rev,
-                                 SVN_PROP_REVISION_AUTHOR,
-                                 rb->author, rb->pool));
+  SVN_ERR(svn_ra_change_rev_prop2(rb->pb->session, rb->rev,
+                                  SVN_PROP_REVISION_DATE,
+                                  NULL, rb->datestamp, rb->pool));
+  SVN_ERR(svn_ra_change_rev_prop2(rb->pb->session, rb->rev,
+                                  SVN_PROP_REVISION_AUTHOR,
+                                  NULL, rb->author, rb->pool));
 
   svn_pool_destroy(rb->pool);
 
@@ -536,16 +661,25 @@ drive_dumpstream_loader(svn_stream_t *st
                         svn_ra_session_t *session,
                         apr_pool_t *pool)
 {
-  struct parse_baton *pb;
-  pb = parse_baton;
-
-  /* ### TODO: Figure out if we're allowed to set revprops before
-     ### we're too late and mess up the repository. svnsync uses some
-     ### sort of locking mechanism. */
+  struct parse_baton *pb = parse_baton;
+  const svn_string_t *lock_string;
+  svn_boolean_t be_atomic;
+  svn_error_t *err;
+
+  SVN_ERR(svn_ra_has_capability(session, &be_atomic,
+                                SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+                                pool));
 
+  SVN_ERR(get_lock(&lock_string, session, pool));
   SVN_ERR(svn_ra_get_repos_root2(session, &(pb->root_url), pool));
   SVN_ERR(svn_repos_parse_dumpstream2(stream, parser, parse_baton,
                                       NULL, NULL, pool));
+  err = svn_ra_change_rev_prop2(session, 0, SVNRDUMP_PROP_LOCK,
+                                 be_atomic ? &lock_string : NULL, NULL, pool);
+  if (is_atomicity_error(err))
+    return svn_error_quick_wrap(err,
+                                _("\"svnrdump load\"'s lock was stolen; "
+                                  "can't remove it"));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/javahl-ra/subversion/svnrdump/load_editor.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnrdump/load_editor.h?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnrdump/load_editor.h (original)
+++ subversion/branches/javahl-ra/subversion/svnrdump/load_editor.h Tue Sep 28 17:35:22 2010
@@ -89,11 +89,10 @@ struct revision_baton
 };
 
 /**
- * Build up a load editor @a parser for parsing a dumpfile stream from @a stream
- * set to fire the appropriate callbacks in load editor along with a
- * @a parser_baton, using @a pool for all memory allocations. The
- * @a editor/ @a edit_baton are central to the functionality of the
- *  parser.
+ * Build up a dumpstream parser @a parser (and corresponding baton @a
+ * parse_baton) to fire the appropriate callbacks in a commit editor
+ * set to commit to session @a session. Use @a pool for all memory
+ * allocations.
  */
 svn_error_t *
 get_dumpstream_loader(const svn_repos_parse_fns2_t **parser,
@@ -102,8 +101,10 @@ get_dumpstream_loader(const svn_repos_pa
                       apr_pool_t *pool);
 
 /**
- * Drive the load editor @a editor using the data in @a stream using
- * @a pool for all memory allocations.
+ * Drive the dumpstream loader described by @a parser and @a
+ * parse_baton to parse and commit the stream @a stream to the
+ * location described by @a session. Use @a pool for all memory
+ * allocations.
  */
 svn_error_t *
 drive_dumpstream_loader(svn_stream_t *stream,

Modified: subversion/branches/javahl-ra/subversion/svnrdump/svnrdump.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnrdump/svnrdump.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnrdump/svnrdump.c (original)
+++ subversion/branches/javahl-ra/subversion/svnrdump/svnrdump.c Tue Sep 28 17:35:22 2010
@@ -110,7 +110,7 @@ struct replay_baton {
   svn_boolean_t quiet;
 };
 
-typedef struct {
+typedef struct opt_baton_t {
   svn_ra_session_t *session;
   const char *url;
   svn_revnum_t start_revision;
@@ -137,6 +137,7 @@ replay_revstart(svn_revnum_t revision,
   SVN_ERR(svn_stream_printf(stdout_stream, pool,
                             SVN_REPOS_DUMPFILE_REVISION_NUMBER
                             ": %ld\n", revision));
+  SVN_ERR(normalize_props(rev_props, pool));
   propstring = svn_stringbuf_create_ensure(0, pool);
   revprop_stream = svn_stream_from_stringbuf(propstring, pool);
   SVN_ERR(svn_hash_write2(rev_props, revprop_stream, "PROPS-END", pool));

Modified: subversion/branches/javahl-ra/subversion/svnserve/cyrus_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnserve/cyrus_auth.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnserve/cyrus_auth.c (original)
+++ subversion/branches/javahl-ra/subversion/svnserve/cyrus_auth.c Tue Sep 28 17:35:22 2010
@@ -361,7 +361,7 @@ svn_error_t *cyrus_auth_request(svn_ra_s
 
       if ((p = strchr(user, '@')) != NULL)
         /* Drop the realm part. */
-        b->user = apr_pstrndup(b->pool, user, p - (char *)user);
+        b->user = apr_pstrndup(b->pool, user, p - (const char *)user);
       else
         {
           svn_error_t *err;

Modified: subversion/branches/javahl-ra/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnserve/serve.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnserve/serve.c (original)
+++ subversion/branches/javahl-ra/subversion/svnserve/serve.c Tue Sep 28 17:35:22 2010
@@ -994,6 +994,65 @@ static svn_error_t *get_dated_rev(svn_ra
   return SVN_NO_ERROR;
 }
 
+/* Common logic for change_rev_prop() and change_rev_prop2(). */
+static svn_error_t *do_change_rev_prop(svn_ra_svn_conn_t *conn,
+                                       server_baton_t *b,
+                                       svn_revnum_t rev,
+                                       const char *name,
+                                       const svn_string_t *const *old_value_p,
+                                       const svn_string_t *value,
+                                       apr_pool_t *pool)
+{
+  SVN_ERR(must_have_access(conn, pool, b, svn_authz_write, NULL, FALSE));
+  SVN_ERR(log_command(b, conn, pool, "%s",
+                      svn_log__change_rev_prop(rev, name, pool)));
+  SVN_CMD_ERR(svn_repos_fs_change_rev_prop4(b->repos, rev, b->user,
+                                            name, old_value_p, value,
+                                            TRUE, TRUE,
+                                            authz_check_access_cb_func(b), b,
+                                            pool));
+  SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, ""));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *change_rev_prop2(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
+                                     apr_array_header_t *params, void *baton)
+{
+  server_baton_t *b = baton;
+  svn_revnum_t rev;
+  const char *name;
+  svn_string_t *value;
+  const svn_string_t *const *old_value_p;
+  svn_string_t *old_value;
+  svn_boolean_t dont_care;
+
+  SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "rc(?s)(b?s)",
+                                 &rev, &name, &value,
+                                 &dont_care, &old_value));
+
+  /* Argument parsing. */
+  if (dont_care)
+    old_value_p = NULL;
+  else
+    old_value_p = (const svn_string_t *const *)&old_value;
+
+  /* Input validation. */
+  if (dont_care && old_value)
+    {
+      svn_error_t *err;
+      err = svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
+                             "'previous-value' and 'dont-care' cannot both be "
+                             "set in 'change-rev-prop2' request");
+      return log_fail_and_flush(err, b, conn, pool);
+    }
+
+  /* Do it. */
+  SVN_ERR(do_change_rev_prop(conn, b, rev, name, old_value_p, value, pool));
+
+  return SVN_NO_ERROR;
+}
+
 static svn_error_t *change_rev_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
                                     apr_array_header_t *params, void *baton)
 {
@@ -1006,14 +1065,8 @@ static svn_error_t *change_rev_prop(svn_
      optional element pattern "(?s)" isn't used. */
   SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "rc?s", &rev, &name, &value));
 
-  SVN_ERR(must_have_access(conn, pool, b, svn_authz_write, NULL, FALSE));
-  SVN_ERR(log_command(b, conn, pool, "%s",
-                      svn_log__change_rev_prop(rev, name, pool)));
-  SVN_CMD_ERR(svn_repos_fs_change_rev_prop3(b->repos, rev, b->user,
-                                            name, value, TRUE, TRUE,
-                                            authz_check_access_cb_func(b), b,
-                                            pool));
-  SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, ""));
+  SVN_ERR(do_change_rev_prop(conn, b, rev, name, NULL, value, pool));
+
   return SVN_NO_ERROR;
 }
 
@@ -1452,6 +1505,14 @@ static svn_error_t *get_dir(svn_ra_svn_c
           svn_pool_clear(subpool);
 
           file_path = svn_uri_join(full_path, name, subpool);
+
+          if (! lookup_access(subpool, b, conn, svn_authz_read,
+                              file_path, FALSE))
+            {
+              apr_hash_set(entries, name, APR_HASH_KEY_STRING, NULL);
+              continue;
+            }
+
           entry = apr_pcalloc(pool, sizeof(*entry));
 
           if (dirent_fields & SVN_DIRENT_KIND)
@@ -2755,6 +2816,7 @@ static const svn_ra_svn_cmd_entry_t main
   { "get-latest-rev",  get_latest_rev },
   { "get-dated-rev",   get_dated_rev },
   { "change-rev-prop", change_rev_prop },
+  { "change-rev-prop2",change_rev_prop2 },
   { "rev-proplist",    rev_proplist },
   { "rev-prop",        rev_prop },
   { "commit",          commit },
@@ -2978,7 +3040,8 @@ svn_error_t *serve(svn_ra_svn_conn_t *co
 
   /* Send greeting.  We don't support version 1 any more, so we can
    * send an empty mechlist. */
-  SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "nn()(wwwwwww)",
+  /* Server-side capabilities list: */
+  SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "nn()(wwwwwwww)",
                                         (apr_uint64_t) 2, (apr_uint64_t) 2,
                                         SVN_RA_SVN_CAP_EDIT_PIPELINE,
                                         SVN_RA_SVN_CAP_SVNDIFF1,
@@ -2986,6 +3049,7 @@ svn_error_t *serve(svn_ra_svn_conn_t *co
                                         SVN_RA_SVN_CAP_COMMIT_REVPROPS,
                                         SVN_RA_SVN_CAP_DEPTH,
                                         SVN_RA_SVN_CAP_LOG_REVPROPS,
+                                        SVN_RA_SVN_CAP_ATOMIC_REVPROPS,
                                         SVN_RA_SVN_CAP_PARTIAL_REPLAY));
 
   /* Read client response, which we assume to be in version 2 format:

Modified: subversion/branches/javahl-ra/subversion/svnsync/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnsync/main.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnsync/main.c (original)
+++ subversion/branches/javahl-ra/subversion/svnsync/main.c Tue Sep 28 17:35:22 2010
@@ -284,18 +284,77 @@ check_lib_versions(void)
 }
 
 
+/* Does ERR mean "the current value of the revprop isn't equal to
+   the *OLD_VALUE_P you gave me"?
+ */
+static svn_boolean_t is_atomicity_error(svn_error_t *err)
+{
+  return svn_error_has_cause(err, SVN_ERR_FS_PROP_BASEVALUE_MISMATCH);
+}
+
+/* Remove the lock on SESSION iff the lock is owned by MYLOCKTOKEN. */
+static svn_error_t *
+maybe_unlock(svn_ra_session_t *session,
+             const svn_string_t *mylocktoken,
+             apr_pool_t *scratch_pool)
+{
+  svn_string_t *reposlocktoken;
+  svn_boolean_t be_atomic;
+
+  SVN_ERR(svn_ra_has_capability(session, &be_atomic,
+                                SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+                                scratch_pool));
+
+  SVN_ERR(svn_ra_rev_prop(session, 0, SVNSYNC_PROP_LOCK, &reposlocktoken,
+                          scratch_pool));
+  if (reposlocktoken && strcmp(reposlocktoken->data, mylocktoken->data) == 0)
+    SVN_ERR(svn_ra_change_rev_prop2(session, 0, SVNSYNC_PROP_LOCK, 
+                                    be_atomic ? &mylocktoken : NULL, NULL,
+                                    scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
 /* Acquire a lock (of sorts) on the repository associated with the
- * given RA SESSION.
+ * given RA SESSION. This lock is just a revprop change attempt in a
+ * time-delay loop. This function is duplicated by svnrdump in
+ * load_editor.c.
+ *
+ * ### TODO: Make this function more generic and
+ * expose it through a header for use by other Subversion
+ * applications to avoid duplication.
  */
 static svn_error_t *
-get_lock(svn_ra_session_t *session, apr_pool_t *pool)
+get_lock(const svn_string_t **lock_string_p,
+         svn_ra_session_t *session,
+         apr_pool_t *pool)
 {
   char hostname_str[APRMAXHOSTLEN + 1] = { 0 };
   svn_string_t *mylocktoken, *reposlocktoken;
   apr_status_t apr_err;
+  svn_boolean_t be_atomic;
   apr_pool_t *subpool;
   int i;
 
+  SVN_ERR(svn_ra_has_capability(session, &be_atomic,
+                                SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+                                pool));
+  if (! be_atomic)
+    {
+      /* Pre-1.7 server.  Can't lock without a race condition.
+         See issue #3546.
+       */
+      svn_error_t *err;
+
+      err = svn_error_create(
+              SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+              _("Target server does not support atomic revision property "
+                "edits; consider upgrading it to 1.7 or using an external "
+                "locking program"));
+      svn_handle_warning2(stderr, err, "svnsync: ");
+      svn_error_clear(err);
+    }
+
   apr_err = apr_gethostname(hostname_str, sizeof(hostname_str), pool);
   if (apr_err)
     return svn_error_wrap_apr(apr_err, _("Can't get local hostname"));
@@ -303,17 +362,29 @@ get_lock(svn_ra_session_t *session, apr_
   mylocktoken = svn_string_createf(pool, "%s:%s", hostname_str,
                                    svn_uuid_generate(pool));
 
+  /* If we succeed, this is what the property will be set to. */
+  *lock_string_p = mylocktoken;
+
   subpool = svn_pool_create(pool);
 
 #define SVNSYNC_LOCK_RETRIES 10
   for (i = 0; i < SVNSYNC_LOCK_RETRIES; ++i)
     {
+      svn_error_t *err;
+
       svn_pool_clear(subpool);
-      SVN_ERR(check_cancel(NULL));
+
+      /* If we're cancelled, don't leave a stray lock behind. */
+      err = check_cancel(NULL);
+      if (err && err->apr_err == SVN_ERR_CANCELLED)
+      	return svn_error_compose_create(
+      	             maybe_unlock(session, mylocktoken, subpool),
+      	             err);
+      else
+      	SVN_ERR(err);
 
       SVN_ERR(svn_ra_rev_prop(session, 0, SVNSYNC_PROP_LOCK, &reposlocktoken,
                               subpool));
-
       if (reposlocktoken)
         {
           /* Did we get it?   If so, we're done, otherwise we sleep. */
@@ -331,9 +402,27 @@ get_lock(svn_ra_session_t *session, apr_
         }
       else if (i < SVNSYNC_LOCK_RETRIES - 1)
         {
+          const svn_string_t *unset = NULL;
+
           /* Except in the very last iteration, try to set the lock. */
-          SVN_ERR(svn_ra_change_rev_prop(session, 0, SVNSYNC_PROP_LOCK,
-                                         mylocktoken, subpool));
+          err = svn_ra_change_rev_prop2(session, 0, SVNSYNC_PROP_LOCK,
+                                        be_atomic ? &unset : NULL,
+                                        mylocktoken, subpool);
+
+          if (be_atomic && err && is_atomicity_error(err))
+            /* Someone else has the lock.  Let's loop. */
+            svn_error_clear(err);
+          else if (be_atomic && err == SVN_NO_ERROR)
+            /* We have the lock. 
+
+               However, for compatibility with concurrent svnsync's that don't
+               support atomicity, loop anyway to double-check that they haven't
+               overwritten our lock.
+             */
+            continue;
+          else
+            /* Genuine error, or we aren't atomic and need to loop. */
+            SVN_ERR(err);
         }
     }
 
@@ -381,12 +470,24 @@ with_locked(svn_ra_session_t *session,
             apr_pool_t *pool)
 {
   svn_error_t *err, *err2;
+  const svn_string_t *lock_string;
+  svn_boolean_t be_atomic;
+
+  SVN_ERR(svn_ra_has_capability(session, &be_atomic,
+                                SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+                                pool));
 
-  SVN_ERR(get_lock(session, pool));
+  SVN_ERR(get_lock(&lock_string, session, pool));
 
   err = func(session, baton, pool);
 
-  err2 = svn_ra_change_rev_prop(session, 0, SVNSYNC_PROP_LOCK, NULL, pool);
+  err2 = svn_ra_change_rev_prop2(session, 0, SVNSYNC_PROP_LOCK,
+                                 be_atomic ? &lock_string : NULL, NULL, pool);
+  if (is_atomicity_error(err2))
+    err2 = svn_error_quick_wrap(err2,
+                                _("svnsync's lock was stolen; "
+                                  "can't remove it"));
+
 
   return svn_error_compose_create(err, svn_error_return(err2));
 }
@@ -451,8 +552,8 @@ remove_props_not_in_source(svn_ra_sessio
 
       /* Delete property if the name can't be found in SOURCE_PROPS. */
       if (! apr_hash_get(source_props, propname, APR_HASH_KEY_STRING))
-        SVN_ERR(svn_ra_change_rev_prop(session, rev, propname, NULL,
-                                       subpool));
+        SVN_ERR(svn_ra_change_rev_prop2(session, rev, propname, NULL,
+                                        NULL, subpool));
     }
 
   svn_pool_destroy(subpool);
@@ -535,8 +636,8 @@ write_revprops(int *filtered_count,
       if (strncmp(propname, SVNSYNC_PROP_PREFIX,
                   sizeof(SVNSYNC_PROP_PREFIX) - 1) != 0)
         {
-          SVN_ERR(svn_ra_change_rev_prop(session, rev, propname, propval,
-                                         subpool));
+          SVN_ERR(svn_ra_change_rev_prop2(session, rev, propname, NULL,
+                                          propval, subpool));
         }
       else
         {
@@ -670,6 +771,11 @@ make_subcommand_baton(opt_baton_t *opt_b
   return b;
 }
 
+static svn_error_t *
+open_target_session(svn_ra_session_t **to_session_p,
+                    subcommand_baton_t *baton,
+                    apr_pool_t *pool);
+
 
 /*** `svnsync init' ***/
 
@@ -743,17 +849,17 @@ do_initialize(svn_ra_session_t *to_sessi
              "repository"));
     }
 
-  SVN_ERR(svn_ra_change_rev_prop(to_session, 0, SVNSYNC_PROP_FROM_URL,
-                                 svn_string_create(baton->from_url, pool),
-                                 pool));
+  SVN_ERR(svn_ra_change_rev_prop2(to_session, 0, SVNSYNC_PROP_FROM_URL, NULL,
+                                  svn_string_create(baton->from_url, pool),
+                                  pool));
 
   SVN_ERR(svn_ra_get_uuid2(from_session, &uuid, pool));
-  SVN_ERR(svn_ra_change_rev_prop(to_session, 0, SVNSYNC_PROP_FROM_UUID,
-                                 svn_string_create(uuid, pool), pool));
+  SVN_ERR(svn_ra_change_rev_prop2(to_session, 0, SVNSYNC_PROP_FROM_UUID, NULL,
+                                  svn_string_create(uuid, pool), pool));
 
-  SVN_ERR(svn_ra_change_rev_prop(to_session, 0, SVNSYNC_PROP_LAST_MERGED_REV,
-                                 svn_string_createf(pool, "%ld", latest),
-                                 pool));
+  SVN_ERR(svn_ra_change_rev_prop2(to_session, 0, SVNSYNC_PROP_LAST_MERGED_REV,
+                                  NULL, svn_string_createf(pool, "%ld", latest),
+                                  pool));
 
   /* Copy all non-svnsync revprops from the LATEST rev in the source
      repository into the destination, notifying about normalized
@@ -809,9 +915,7 @@ initialize_cmd(apr_getopt_t *os, void *b
                              _("Path '%s' is not a URL"), from_url);
 
   baton = make_subcommand_baton(opt_baton, to_url, from_url, 0, 0, pool);
-  SVN_ERR(svn_ra_open4(&to_session, NULL, baton->to_url, NULL,
-                       &(baton->sync_callbacks), baton, baton->config, pool));
-  SVN_ERR(check_if_session_is_at_repos_root(to_session, baton->to_url, pool));
+  SVN_ERR(open_target_session(&to_session, baton, pool));
   if (opt_baton->disable_locking)
     SVN_ERR(do_initialize(to_session, baton, pool));
   else
@@ -891,6 +995,23 @@ open_source_session(svn_ra_session_t **f
   return SVN_NO_ERROR;
 }
 
+/* Set *TARGET_SESSION_P to an RA session associated with the target
+ * repository of the synchronization.
+ */
+static svn_error_t *
+open_target_session(svn_ra_session_t **target_session_p,
+                    subcommand_baton_t *baton,
+                    apr_pool_t *pool)
+{
+  svn_ra_session_t *target_session;
+  SVN_ERR(svn_ra_open4(&target_session, NULL, baton->to_url, NULL,
+                       &(baton->sync_callbacks), baton, baton->config, pool));
+  SVN_ERR(check_if_session_is_at_repos_root(target_session, baton->to_url, pool));
+
+  *target_session_p = target_session;
+  return SVN_NO_ERROR;
+}
+
 /* Replay baton, used during sychnronization. */
 typedef struct {
   svn_ra_session_t *from_session;
@@ -997,11 +1118,11 @@ replay_rev_started(svn_revnum_t revision
      NOTE: We have to set this before we start the commit editor,
      because ra_svn doesn't let you change rev props during a
      commit. */
-  SVN_ERR(svn_ra_change_rev_prop(rb->to_session, 0,
-                                 SVNSYNC_PROP_CURRENTLY_COPYING,
-                                 svn_string_createf(pool, "%ld",
-                                                    revision),
-                                 pool));
+  SVN_ERR(svn_ra_change_rev_prop2(rb->to_session, 0,
+                                  SVNSYNC_PROP_CURRENTLY_COPYING,
+                                  NULL,
+                                  svn_string_createf(pool, "%ld", revision),
+                                  pool));
 
   /* The actual copy is just a replay hooked up to a commit.  Include
      all the revision properties from the source repositories, except
@@ -1110,19 +1231,20 @@ replay_rev_finished(svn_revnum_t revisio
   svn_pool_clear(subpool);
 
   /* Ok, we're done, bring the last-merged-rev property up to date. */
-  SVN_ERR(svn_ra_change_rev_prop
-          (rb->to_session,
+  SVN_ERR(svn_ra_change_rev_prop2(
+           rb->to_session,
            0,
            SVNSYNC_PROP_LAST_MERGED_REV,
+           NULL,
            svn_string_create(apr_psprintf(pool, "%ld", revision),
                              subpool),
            subpool));
 
   /* And finally drop the currently copying prop, since we're done
      with this revision. */
-  SVN_ERR(svn_ra_change_rev_prop(rb->to_session, 0,
-                                 SVNSYNC_PROP_CURRENTLY_COPYING,
-                                 NULL, subpool));
+  SVN_ERR(svn_ra_change_rev_prop2(rb->to_session, 0,
+                                  SVNSYNC_PROP_CURRENTLY_COPYING,
+                                  NULL, NULL, subpool));
 
   /* Notify the user that we copied revision properties. */
   if (! rb->sb->quiet)
@@ -1215,12 +1337,12 @@ do_synchronize(svn_ra_session_t *to_sess
              end up not being able to tell if there have been bogus
              (i.e. non-svnsync) commits to the dest repository. */
 
-          SVN_ERR(svn_ra_change_rev_prop(to_session, 0,
-                                         SVNSYNC_PROP_LAST_MERGED_REV,
-                                         last_merged_rev, pool));
-          SVN_ERR(svn_ra_change_rev_prop(to_session, 0,
-                                         SVNSYNC_PROP_CURRENTLY_COPYING,
-                                         NULL, pool));
+          SVN_ERR(svn_ra_change_rev_prop2(to_session, 0,
+                                          SVNSYNC_PROP_LAST_MERGED_REV,
+                                          NULL, last_merged_rev, pool));
+          SVN_ERR(svn_ra_change_rev_prop2(to_session, 0,
+                                          SVNSYNC_PROP_CURRENTLY_COPYING,
+                                          NULL, NULL, pool));
         }
       /* If copying > to_latest, then we just fall through to
          attempting to copy the revision again. */
@@ -1309,9 +1431,7 @@ synchronize_cmd(apr_getopt_t *os, void *
     }
 
   baton = make_subcommand_baton(opt_baton, to_url, from_url, 0, 0, pool);
-  SVN_ERR(svn_ra_open4(&to_session, NULL, baton->to_url, NULL,
-                       &(baton->sync_callbacks), baton, baton->config, pool));
-  SVN_ERR(check_if_session_is_at_repos_root(to_session, baton->to_url, pool));
+  SVN_ERR(open_target_session(&to_session, baton, pool));
   if (opt_baton->disable_locking)
     SVN_ERR(do_synchronize(to_session, baton, pool));
   else
@@ -1545,9 +1665,7 @@ copy_revprops_cmd(apr_getopt_t *os, void
       
   baton = make_subcommand_baton(opt_baton, to_url, from_url,
                                 start_rev, end_rev, pool);
-  SVN_ERR(svn_ra_open4(&to_session, NULL, baton->to_url, NULL,
-                       &(baton->sync_callbacks), baton, baton->config, pool));
-  SVN_ERR(check_if_session_is_at_repos_root(to_session, baton->to_url, pool));
+  SVN_ERR(open_target_session(&to_session, baton, pool));
   if (opt_baton->disable_locking)
     SVN_ERR(do_copy_revprops(to_session, baton, pool));
   else
@@ -1589,9 +1707,7 @@ info_cmd(apr_getopt_t *os, void *b, apr_
 
   /* Open an RA session to the mirror repository URL. */
   baton = make_subcommand_baton(opt_baton, to_url, NULL, 0, 0, pool);
-  SVN_ERR(svn_ra_open4(&to_session, NULL, baton->to_url, NULL,
-                       &(baton->sync_callbacks), baton, baton->config, pool));
-  SVN_ERR(check_if_session_is_at_repos_root(to_session, baton->to_url, pool));
+  SVN_ERR(open_target_session(&to_session, baton, pool));
 
   /* Verify that the repos has been initialized for synchronization. */
   SVN_ERR(svn_ra_rev_prop(to_session, 0, SVNSYNC_PROP_FROM_URL,
@@ -2033,15 +2149,7 @@ main(int argc, const char *argv[])
                                         check_cancel, NULL,
                                         pool);
   if (! err)
-    {
-      /* svnsync can safely create instance of QApplication class. */
-      svn_auth_set_parameter(opt_baton.source_auth_baton,
-                             "svn:auth:qapplication-safe", "1");
-      svn_auth_set_parameter(opt_baton.sync_auth_baton,
-                             "svn:auth:qapplication-safe", "1");
-
-      err = (*subcommand->cmd_func)(os, &opt_baton, pool);
-    }
+    err = (*subcommand->cmd_func)(os, &opt_baton, pool);
   if (err)
     {
       /* For argument-related problems, suggest using the 'help'

Propchange: subversion/branches/javahl-ra/subversion/tests/cmdline/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Tue Sep 28 17:35:22 2010
@@ -6,4 +6,5 @@ httpd-*
 *~
 .*~
 entries-dump
+atomic-ra-revprop-change
 .libs

Modified: subversion/branches/javahl-ra/subversion/tests/cmdline/authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/tests/cmdline/authz_tests.py?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/tests/cmdline/authz_tests.py (original)
+++ subversion/branches/javahl-ra/subversion/tests/cmdline/authz_tests.py Tue Sep 28 17:35:22 2010
@@ -1091,9 +1091,8 @@ test_list = [ None,
               Skip(wc_wc_copy, svntest.main.is_ra_type_file),
               Skip(wc_wc_copy_revert,
                    svntest.main.is_ra_type_file),
-              XFail(Skip(authz_recursive_ls,
-                         svntest.main.is_ra_type_file),
-                    svntest.main.is_ra_type_svn),
+              Skip(authz_recursive_ls,
+                   svntest.main.is_ra_type_file),
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/javahl-ra/subversion/tests/cmdline/copy_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/tests/cmdline/copy_tests.py?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/tests/cmdline/copy_tests.py (original)
+++ subversion/branches/javahl-ra/subversion/tests/cmdline/copy_tests.py Tue Sep 28 17:35:22 2010
@@ -3799,106 +3799,6 @@ def allow_unversioned_parent_for_copy_sr
                                      wc2_dir,
                                      copy_to_path)
 
-
-#----------------------------------------------------------------------
-# Issue #2986
-def replaced_local_source_for_incoming_copy(sbox):
-  "update receives copy, but local source is replaced"
-  sbox.build()
-  wc_dir = sbox.wc_dir
-  other_wc_dir = wc_dir + '-other'
-
-  # These paths are for regular content testing.
-  tau_path = os.path.join(wc_dir, 'A', 'D', 'G', 'tau')
-  rho_url = sbox.repo_url + '/A/D/G/rho'
-  pi_url = sbox.repo_url + '/A/D/G/pi'
-  other_G_path = os.path.join(other_wc_dir, 'A', 'D', 'G')
-  other_rho_path = os.path.join(other_G_path, 'rho')
-
-  # These paths are for properties testing.
-  H_path = os.path.join(wc_dir, 'A', 'D', 'H')
-  chi_path = os.path.join(H_path, 'chi')
-  psi_path = os.path.join(H_path, 'psi')
-  omega_path = os.path.join(H_path, 'omega')
-  psi_url = sbox.repo_url + '/A/D/H/psi'
-  chi_url = sbox.repo_url + '/A/D/H/chi'
-  other_H_path = os.path.join(other_wc_dir, 'A', 'D', 'H')
-  other_psi_path = os.path.join(other_H_path, 'psi')
-  other_omega_path = os.path.join(other_H_path, 'omega')
-
-  # Prepare for properties testing.  If the regular content bug
-  # reappears, we still want to be able to test for the property bug
-  # independently.  That means making two files have the same content,
-  # to avoid encountering the checksum error that might reappear in a
-  # regression.  So here we do that, as well as set the marker
-  # property that we'll check for later.  The reason to set the marker
-  # property in this commit, rather than later, is so that we pass the
-  # conditional in update_editor.c:locate_copyfrom() that compares the
-  # revisions.
-  svntest.main.file_write(chi_path, "Same contents for two files.\n")
-  svntest.main.file_write(psi_path, "Same contents for two files.\n")
-  svntest.actions.run_and_verify_svn(None, None, [], 'propset',
-                                     'chi-prop', 'chi-val', chi_path)
-  svntest.actions.run_and_verify_svn(None, None, [], 'ci',
-                                     '-m', 'identicalize contents', wc_dir);
-  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
-
-  # Make the duplicate working copy.
-  svntest.main.safe_rmtree(other_wc_dir)
-  shutil.copytree(wc_dir, other_wc_dir)
-
-  try:
-    ## Test properties. ##
-
-    # Commit a replacement from the first working copy.
-    svntest.actions.run_and_verify_svn(None, None, [], 'rm',
-                                       omega_path);
-    svntest.actions.run_and_verify_svn(None, None, [], 'cp',
-                                       psi_url, omega_path);
-    svntest.actions.run_and_verify_svn(None, None, [], 'ci',
-                                       '-m', 'a propset and a copy', wc_dir);
-
-    # Now schedule a replacement in the second working copy, then update
-    # to receive the replacement from the first working copy, with the
-    # source being the now-scheduled-replace file.
-    svntest.actions.run_and_verify_svn(None, None, [], 'rm',
-                                       other_psi_path);
-    svntest.actions.run_and_verify_svn(None, None, [], 'cp',
-                                       chi_url, other_psi_path);
-    svntest.actions.run_and_verify_svn(None, None, [], 'up',
-                                       other_wc_dir)
-    exit_code, output, errput = svntest.main.run_svn(None, 'proplist',
-                                                     '-v', other_omega_path)
-    if len(errput):
-      raise svntest.Failure("unexpected error output: %s" % errput)
-    if len(output):
-      raise svntest.Failure("unexpected properties found on '%s': %s"
-                            % (other_omega_path, output))
-
-    ## Test regular content. ##
-
-    # Commit a replacement from the first working copy.
-    svntest.actions.run_and_verify_svn(None, None, [], 'rm',
-                                       tau_path);
-    svntest.actions.run_and_verify_svn(None, None, [], 'cp',
-                                       rho_url, tau_path);
-    svntest.actions.run_and_verify_svn(None, None, [], 'ci',
-                                       '-m', 'copy rho to tau', wc_dir);
-
-    # Now schedule a replacement in the second working copy, then update
-    # to receive the replacement from the first working copy, with the
-    # source being the now-scheduled-replace file.
-    svntest.actions.run_and_verify_svn(None, None, [], 'rm',
-                                       other_rho_path);
-    svntest.actions.run_and_verify_svn(None, None, [], 'cp',
-                                       pi_url, other_rho_path);
-    svntest.actions.run_and_verify_svn(None, None, [], 'up',
-                                       other_wc_dir)
-
-  finally:
-    svntest.main.safe_rmtree(other_wc_dir)
-
-
 def unneeded_parents(sbox):
   "svn cp --parents FILE_URL DIR_URL"
 
@@ -4771,60 +4671,6 @@ def move_added_nodes(sbox):
   expected_status.add({'X/Z' : Item(status='A ', wc_rev='0')})
   svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status)
 
-def locate_wrong_origin(sbox):
-  "update editor locates invalid file source"
-
-  sbox.build()
-
-  iota = os.path.join(sbox.wc_dir, 'iota')
-  gamma = os.path.join(sbox.wc_dir, 'A/D/gamma')
-
-  D1 = os.path.join(sbox.wc_dir, 'D1')
-  D2 = os.path.join(sbox.wc_dir, 'D2')
-
-  main.run_svn(None, 'mkdir', D1, D2)
-  main.run_svn(None, 'cp', iota, os.path.join(D1, 'iota'))
-  main.run_svn(None, 'cp', gamma, os.path.join(D2, 'iota'))
-
-  main.run_svn(None, 'ci', sbox.wc_dir, '-m', 'Add 2*iotas in r2')
-  main.run_svn(None, 'rm', D1)
-
-  main.run_svn(None, 'ci', sbox.wc_dir, '-m', 'Why?')
-
-  main.run_svn(None, 'cp', D2, D1)
-  main.run_svn(None, 'ci', sbox.wc_dir, '-m', 'Replace one iota')
-
-  # <= 1.6 needs a new checkout here to reproduce, but not since r961831.
-  # so we just perform an update
-  main.run_svn(None, 'up', sbox.wc_dir)
-
-  main.run_svn(None, 'cp', sbox.repo_url + '/D1/iota@2',
-               sbox.repo_url + '/iobeta', '-m', 'Copy iota')
-
-
-  expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 4)
-  expected_status.add({
-    'D1'                : Item(status='  ', wc_rev='4'),
-    'D1/iota'           : Item(status='  ', wc_rev='4'),
-    'D2'                : Item(status='  ', wc_rev='4'),
-    'D2/iota'           : Item(status='  ', wc_rev='4'),
-  })
-  svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status)
-
-  # The next update receives an add_file('/D1/iota', 2), which it then tries
-  # to locate in the local working copy. It finds a '/D1/iota' in the expected
-  # place, with a last-changed revision of 2 and a local revision of HEAD-1
-  #
-  # locate_copyfrom identifies this file as correct because 
-  #     * last-mod <= 2 and
-  #     * 2 <= REV
-  #
-  # Luckily close_file() receives an expected_checksum which makes us fail, or
-  # we would have a completely broken working copy
-
-  # So this gives a Checksum mismatch error.
-  main.run_svn(None, 'up', sbox.wc_dir)
-
 # This test currently fails, but should work ok once we move to single DB
 def copy_over_deleted_dir(sbox):
   "copy a directory over a deleted directory"
@@ -4910,7 +4756,6 @@ test_list = [ None,
               copy_make_parents_repo_repo,
               URI_encoded_repos_to_wc,
               allow_unversioned_parent_for_copy_src,
-              replaced_local_source_for_incoming_copy,
               unneeded_parents,
               double_parents_with_url,
               copy_into_absent_dir,
@@ -4929,9 +4774,6 @@ test_list = [ None,
               changed_data_should_match_checkout,
               XFail(changed_dir_data_should_match_checkout),
               move_added_nodes,
-              # Serf needs a different testcase for this issue
-              XFail(Skip(locate_wrong_origin,
-                         svntest.main.is_ra_type_dav_serf)),
               copy_over_deleted_dir,
              ]
 

Modified: subversion/branches/javahl-ra/subversion/tests/cmdline/input_validation_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/tests/cmdline/input_validation_tests.py?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/tests/cmdline/input_validation_tests.py (original)
+++ subversion/branches/javahl-ra/subversion/tests/cmdline/input_validation_tests.py Tue Sep 28 17:35:22 2010
@@ -166,6 +166,13 @@ def invalid_merge_args(sbox):
   run_and_verify_svn_in_wc(sbox, "svn: Path '.*' does not exist",
                            'merge', '-c42', '^/mu', 'nonexistent')
 
+def invalid_wcpath_upgrade(sbox):
+  "non-working copy paths for 'upgrade'"
+  sbox.build(read_only=True)
+  for target in _invalid_wc_path_targets:
+    run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'upgrade',
+                             target, target)
+
 
 ########################################################################
 # Run the tests
@@ -184,6 +191,7 @@ test_list = [ None,
               invalid_import_args,
               invalid_log_targets,
               invalid_merge_args,
+              invalid_wcpath_upgrade,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/javahl-ra/subversion/tests/cmdline/merge_reintegrate_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/tests/cmdline/merge_reintegrate_tests.py?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/tests/cmdline/merge_reintegrate_tests.py (original)
+++ subversion/branches/javahl-ra/subversion/tests/cmdline/merge_reintegrate_tests.py Tue Sep 28 17:35:22 2010
@@ -2075,8 +2075,8 @@ def added_subtrees_with_mergeinfo_break_
 #----------------------------------------------------------------------
 # Test for issue #3648 '2-URL merges incorrectly reverse-merge mergeinfo
 # for merge target'.
-def two_URL_merge_removes_valid_mergefino_from_target(sbox):
-  "2-URL merge removes valid mergefino from target"
+def two_URL_merge_removes_valid_mergeinfo_from_target(sbox):
+  "2-URL merge removes valid mergeinfo from target"
 
   sbox.build()
   wc_dir = sbox.wc_dir
@@ -2254,7 +2254,7 @@ test_list = [ None,
                          server_has_mergeinfo),
               reintegrate_with_self_referential_mergeinfo,
               added_subtrees_with_mergeinfo_break_reintegrate,
-              two_URL_merge_removes_valid_mergefino_from_target,
+              two_URL_merge_removes_valid_mergeinfo_from_target,
              ]
 
 if __name__ == '__main__':