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 2015/01/20 18:52:21 UTC

svn commit: r1653314 [18/20] - in /subversion/branches/move-tracking-2: ./ notes/ subversion/ subversion/bindings/swig/ subversion/bindings/swig/include/ subversion/bindings/swig/perl/native/ subversion/bindings/swig/perl/native/t/ subversion/bindings/...

Modified: subversion/branches/move-tracking-2/subversion/svn/conflict-callbacks.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svn/conflict-callbacks.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svn/conflict-callbacks.c (original)
+++ subversion/branches/move-tracking-2/subversion/svn/conflict-callbacks.c Tue Jan 20 17:52:18 2015
@@ -695,6 +695,10 @@ handle_text_conflict(svn_wc_conflict_res
                                 b->path_prefix, desc->local_abspath,
                                 scratch_pool)));
 
+  /* ### TODO This whole feature availability check is grossly outdated.
+     DIFF_ALLOWED needs either to be redefined or to go away.
+   */
+
   /* Diffing can happen between base and merged, to show conflict
      markers to the user (this is the typical 3-way merge
      scenario), or if no base is available, we can show a diff
@@ -714,9 +718,15 @@ handle_text_conflict(svn_wc_conflict_res
       *next_option++ = "p";
       if (diff_allowed)
         {
-          *next_option++ = "df";
+          /* We need one more path for this feature. */
+          if (desc->my_abspath)
+            *next_option++ = "df";
+
           *next_option++ = "e";
-          *next_option++ = "m";
+
+          /* We need one more path for this feature. */
+          if (desc->my_abspath)
+            *next_option++ = "m";
 
           if (knows_something)
             *next_option++ = "r";
@@ -781,7 +791,8 @@ handle_text_conflict(svn_wc_conflict_res
         }
       else if (strcmp(opt->code, "df") == 0)
         {
-          if (! diff_allowed)
+          /* Re-check preconditions. */
+          if (! diff_allowed || desc->my_abspath)
             {
               SVN_ERR(svn_cmdline_fprintf(stderr, iterpool,
                              _("Invalid option; there's no "
@@ -805,6 +816,15 @@ handle_text_conflict(svn_wc_conflict_res
         {
           svn_error_t *err;
 
+          /* Re-check preconditions. */
+          if (! desc->my_abspath)
+            {
+              SVN_ERR(svn_cmdline_fprintf(stderr, iterpool,
+                             _("Invalid option; there's no "
+                                "base path to merge.\n\n")));
+              continue;
+            }
+
           err = svn_cl__merge_file_externally(desc->base_abspath,
                                               desc->their_abspath,
                                               desc->my_abspath,

Modified: subversion/branches/move-tracking-2/subversion/svnadmin/svnadmin.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnadmin/svnadmin.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnadmin/svnadmin.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnadmin/svnadmin.c Tue Jan 20 17:52:18 2015
@@ -1271,7 +1271,7 @@ subcommand_freeze(apr_getopt_t *os, void
     }
 
   b.command = APR_ARRAY_IDX(args, 0, const char *);
-  b.args = apr_palloc(pool, sizeof(char *) * args->nelts + 1);
+  b.args = apr_palloc(pool, sizeof(char *) * (args->nelts + 1));
   for (i = 0; i < args->nelts; ++i)
     b.args[i] = APR_ARRAY_IDX(args, i, const char *);
   b.args[args->nelts] = NULL;

Modified: subversion/branches/move-tracking-2/subversion/svndumpfilter/svndumpfilter.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svndumpfilter/svndumpfilter.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svndumpfilter/svndumpfilter.c (original)
+++ subversion/branches/move-tracking-2/subversion/svndumpfilter/svndumpfilter.c Tue Jan 20 17:52:18 2015
@@ -43,6 +43,7 @@
 #include "svn_mergeinfo.h"
 #include "svn_version.h"
 
+#include "private/svn_repos_private.h"
 #include "private/svn_mergeinfo_private.h"
 #include "private/svn_cmdline_private.h"
 #include "private/svn_sorts_private.h"
@@ -240,7 +241,6 @@ struct revision_baton_t
 
   /* Does this revision have node or prop changes? */
   svn_boolean_t has_nodes;
-  svn_boolean_t has_props;
 
   /* Did we drop any nodes? */
   svn_boolean_t had_dropped_nodes;
@@ -253,7 +253,7 @@ struct revision_baton_t
   svn_revnum_t rev_actual;
 
   /* Pointers to dumpfile data. */
-  svn_stringbuf_t *header;
+  apr_hash_t *original_headers;
   apr_hash_t *props;
 };
 
@@ -310,6 +310,24 @@ magic_header_record(int version, void *p
 }
 
 
+/* Return a deep copy of a (char * -> char *) hash. */
+static apr_hash_t *
+headers_dup(apr_hash_t *headers,
+            apr_pool_t *pool)
+{
+  apr_hash_t *new_hash = apr_hash_make(pool);
+  apr_hash_index_t *hi;
+
+  for (hi = apr_hash_first(pool, headers); hi; hi = apr_hash_next(hi))
+    {
+      const char *key = apr_hash_this_key(hi);
+      const char *val = apr_hash_this_val(hi);
+
+      svn_hash_sets(new_hash, apr_pstrdup(pool, key), apr_pstrdup(pool, val));
+    }
+  return new_hash;
+}
+
 /* New revision: set up revision_baton, decide if we skip it. */
 static svn_error_t *
 new_revision_record(void **revision_baton,
@@ -318,21 +336,16 @@ new_revision_record(void **revision_bato
                     apr_pool_t *pool)
 {
   struct revision_baton_t *rb;
-  apr_hash_index_t *hi;
   const char *rev_orig;
-  svn_stream_t *header_stream;
 
   *revision_baton = apr_palloc(pool, sizeof(struct revision_baton_t));
   rb = *revision_baton;
   rb->pb = parse_baton;
   rb->has_nodes = FALSE;
-  rb->has_props = FALSE;
   rb->had_dropped_nodes = FALSE;
   rb->writing_begun = FALSE;
-  rb->header = svn_stringbuf_create_empty(pool);
   rb->props = apr_hash_make(pool);
-
-  header_stream = svn_stream_from_stringbuf(rb->header, pool);
+  rb->original_headers = headers_dup(headers, pool);
 
   rev_orig = svn_hash_gets(headers, SVN_REPOS_DUMPFILE_REVISION_NUMBER);
   rb->rev_orig = SVN_STR_TO_REV(rev_orig);
@@ -342,28 +355,6 @@ new_revision_record(void **revision_bato
   else
     rb->rev_actual = rb->rev_orig;
 
-  SVN_ERR(svn_stream_printf(header_stream, pool,
-                            SVN_REPOS_DUMPFILE_REVISION_NUMBER ": %ld\n",
-                            rb->rev_actual));
-
-  for (hi = apr_hash_first(pool, headers); hi; hi = apr_hash_next(hi))
-    {
-      const char *key = apr_hash_this_key(hi);
-      const char *val = apr_hash_this_val(hi);
-
-      if ((!strcmp(key, SVN_REPOS_DUMPFILE_CONTENT_LENGTH))
-          || (!strcmp(key, SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH))
-          || (!strcmp(key, SVN_REPOS_DUMPFILE_REVISION_NUMBER)))
-        continue;
-
-      /* passthru: put header into header stringbuf. */
-
-      SVN_ERR(svn_stream_printf(header_stream, pool, "%s: %s\n",
-                                key, val));
-    }
-
-  SVN_ERR(svn_stream_close(header_stream));
-
   return SVN_NO_ERROR;
 }
 
@@ -375,12 +366,8 @@ new_revision_record(void **revision_bato
 static svn_error_t *
 output_revision(struct revision_baton_t *rb)
 {
-  int bytes_used;
-  char buf[SVN_KEYLINE_MAXLEN];
-  apr_hash_index_t *hi;
   svn_boolean_t write_out_rev = FALSE;
   apr_pool_t *hash_pool = apr_hash_pool_get(rb->props);
-  svn_stringbuf_t *props = svn_stringbuf_create_empty(hash_pool);
   apr_pool_t *subpool = svn_pool_create(hash_pool);
 
   rb->writing_begun = TRUE;
@@ -398,7 +385,6 @@ output_revision(struct revision_baton_t
       && (! rb->pb->drop_all_empty_revs))
     {
       apr_hash_t *old_props = rb->props;
-      rb->has_props = TRUE;
       rb->props = apr_hash_make(hash_pool);
       svn_hash_sets(rb->props, SVN_PROP_REVISION_DATE,
                     svn_hash_gets(old_props, SVN_PROP_REVISION_DATE));
@@ -407,39 +393,6 @@ output_revision(struct revision_baton_t
                                         "padding."), hash_pool));
     }
 
-  /* Now, "rasterize" the props to a string, and append the property
-     information to the header string.  */
-  if (rb->has_props)
-    {
-      for (hi = apr_hash_first(subpool, rb->props);
-           hi;
-           hi = apr_hash_next(hi))
-        {
-          const char *pname = apr_hash_this_key(hi);
-          const svn_string_t *pval = apr_hash_this_val(hi);
-
-          write_prop_to_stringbuf(props, pname, pval);
-        }
-      svn_stringbuf_appendcstr(props, "PROPS-END\n");
-      svn_stringbuf_appendcstr(rb->header,
-                               SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH);
-      bytes_used = apr_snprintf(buf, sizeof(buf), ": %" APR_SIZE_T_FMT,
-                                props->len);
-      svn_stringbuf_appendbytes(rb->header, buf, bytes_used);
-      svn_stringbuf_appendbyte(rb->header, '\n');
-    }
-
-  svn_stringbuf_appendcstr(rb->header, SVN_REPOS_DUMPFILE_CONTENT_LENGTH);
-  bytes_used = apr_snprintf(buf, sizeof(buf), ": %" APR_SIZE_T_FMT, props->len);
-  svn_stringbuf_appendbytes(rb->header, buf, bytes_used);
-  svn_stringbuf_appendbyte(rb->header, '\n');
-
-  /* put an end to headers */
-  svn_stringbuf_appendbyte(rb->header, '\n');
-
-  /* put an end to revision */
-  svn_stringbuf_appendbyte(props, '\n');
-
   /* write out the revision */
   /* Revision is written out in the following cases:
      1. If the revision has nodes or
@@ -459,10 +412,12 @@ output_revision(struct revision_baton_t
   if (write_out_rev)
     {
       /* This revision is a keeper. */
-      SVN_ERR(svn_stream_write(rb->pb->out_stream,
-                               rb->header->data, &(rb->header->len)));
-      SVN_ERR(svn_stream_write(rb->pb->out_stream,
-                               props->data, &(props->len)));
+      SVN_ERR(svn_repos__dump_revision_record(rb->pb->out_stream,
+                                              rb->rev_actual,
+                                              rb->original_headers,
+                                              rb->props,
+                                              FALSE /*props_section_always*/,
+                                              subpool));
 
       /* Stash the oldest original rev not dropped. */
       if (rb->rev_orig > 0
@@ -791,10 +746,16 @@ adjust_mergeinfo(svn_string_t **final_va
      start of all history.  E.g. if we dump -r100:400 then dumpfilter the
      result with --skip-missing-merge-sources, any mergeinfo with revision
      100 implies a change of -r99:100, but r99 is part of the history we
-     want filtered.  This is analogous to how r1 is always meaningless as
-     a merge source revision.
+     want filtered.
 
      If the oldest rev is r0 then there is nothing to filter. */
+
+  /* ### This seems to cater only for use cases where the revisions being
+         processed are not following on from revisions that will already
+         exist in the destination repository. If the revisions being
+         processed do follow on, then we might want to keep the mergeinfo
+         that refers to those older revisions. */
+
   if (rb->pb->skip_missing_merge_sources && rb->pb->oldest_original_rev > 0)
     SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
       &mergeinfo, mergeinfo,
@@ -852,7 +813,7 @@ adjust_mergeinfo(svn_string_t **final_va
       svn_hash_sets(final_mergeinfo, merge_source, rangelist);
     }
 
-  SVN_ERR(svn_mergeinfo_sort(final_mergeinfo, subpool));
+  SVN_ERR(svn_mergeinfo__canonicalize_ranges(final_mergeinfo, subpool));
   SVN_ERR(svn_mergeinfo_to_string(final_val, final_mergeinfo, pool));
   svn_pool_destroy(subpool);
 
@@ -868,7 +829,6 @@ set_revision_property(void *revision_bat
   struct revision_baton_t *rb = revision_baton;
   apr_pool_t *hash_pool = apr_hash_pool_get(rb->props);
 
-  rb->has_props = TRUE;
   svn_hash_sets(rb->props,
                 apr_pstrdup(hash_pool, name),
                 svn_string_dup(value, hash_pool));
@@ -887,6 +847,9 @@ set_node_property(void *node_baton,
   if (nb->do_skip)
     return SVN_NO_ERROR;
 
+  /* Try to detect if a delta-mode property occurs unexpectedly. HAS_PROPS
+     can be false here only if the parser didn't call remove_node_props(),
+     so this may indicate a bug rather than bad data. */
   if (! (nb->has_props || nb->has_prop_delta))
     return svn_error_createf(SVN_ERR_STREAM_MALFORMED_DATA, NULL,
                              _("Delta property block detected, but deltas "
@@ -932,14 +895,17 @@ delete_node_property(void *node_baton, c
 }
 
 
+/* The parser calls this method if the node record has a non-delta
+ * property content section, before any calls to set_node_property().
+ * If the node record uses property deltas, this is not called.
+ */
 static svn_error_t *
 remove_node_props(void *node_baton)
 {
   struct node_baton_t *nb = node_baton;
 
   /* In this case, not actually indicating that the node *has* props,
-     rather that we know about all the props that it has, since it now
-     has none. */
+     rather that it has a property content section. */
   nb->has_props = TRUE;
 
   return SVN_NO_ERROR;

Modified: subversion/branches/move-tracking-2/subversion/svnfsfs/stats-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnfsfs/stats-cmd.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnfsfs/stats-cmd.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnfsfs/stats-cmd.c Tue Jan 20 17:52:18 2015
@@ -31,6 +31,35 @@
 #include "svn_private_config.h"
 #include "svnfsfs.h"
 
+/* Return the string, allocated in RESULT_POOL, describing the value 2**I.
+ */
+static const char *
+print_two_power(int i,
+                apr_pool_t *result_pool)
+{
+  /* These are the SI prefixes for base-1000, the binary ones with base-1024
+     are too clumsy and require appending B for "byte" to be intelligible,
+     e.g. "MiB".
+
+     Therefore, we ignore the official standard and revert to the traditional
+     contextual use were the base-1000 prefixes are understood as base-1024
+     when it came to data sizes.
+   */
+  const char *si_prefixes = " kMGTPEZY";
+
+  int number = (1 << (i % 10));
+  int thousands = i / 10;
+
+  char si_prefix = ((thousands >= 0) && (thousands < strlen(si_prefixes)))
+                 ? si_prefixes[thousands]
+                 : '?';
+
+  if (si_prefix == ' ')
+    return apr_psprintf(result_pool, "%d", number);
+
+  return apr_psprintf(result_pool, "%d%c", number, si_prefix);
+}
+
 /* Print statistics for the given group of representations to console.
  * Use POOL for allocations.
  */
@@ -88,8 +117,8 @@ print_histogram(svn_fs_fs__histogram_t *
 
   /* display histogram lines */
   for (i = last; i >= first; --i)
-    printf(_("  [2^%2d, 2^%2d)   %15s (%2d%%) bytes in %12s (%2d%%) items\n"),
-           i-1, i,
+    printf(_("  %4s .. < %-4s %19s (%2d%%) bytes in %12s (%2d%%) items\n"),
+           print_two_power(i-1, pool), print_two_power(i, pool),
            svn__ui64toa_sep(histogram->lines[i].sum, ',', pool),
            (int)(histogram->lines[i].sum * 100 / histogram->total.sum),
            svn__ui64toa_sep(histogram->lines[i].count, ',', pool),

Modified: subversion/branches/move-tracking-2/subversion/svnrdump/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnrdump/dump_editor.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnrdump/dump_editor.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnrdump/dump_editor.c Tue Jan 20 17:52:18 2015
@@ -58,9 +58,6 @@ struct dir_baton
   /* is this directory a new addition to this revision? */
   svn_boolean_t added;
 
-  /* has this directory been written to the output stream? */
-  svn_boolean_t written_out;
-
   /* the path to this directory */
   const char *repos_relpath; /* a relpath */
 
@@ -179,38 +176,30 @@ make_dir_baton(const char *path,
   struct dump_edit_baton *eb = edit_baton;
   struct dir_baton *new_db = apr_pcalloc(pool, sizeof(*new_db));
   const char *repos_relpath;
-  apr_pool_t *dir_pool;
 
   /* Construct the full path of this node. */
   if (pb)
-    {
-      dir_pool = svn_pool_create(pb->pool);
-      repos_relpath = svn_relpath_canonicalize(path, dir_pool);
-    }
+    repos_relpath = svn_relpath_canonicalize(path, pool);
   else
-    {
-      dir_pool = svn_pool_create(eb->pool);
-      repos_relpath = "";
-    }
+    repos_relpath = "";
 
   /* Strip leading slash from copyfrom_path so that the path is
      canonical and svn_relpath_join can be used */
   if (copyfrom_path)
-    copyfrom_path = svn_relpath_canonicalize(copyfrom_path, dir_pool);
+    copyfrom_path = svn_relpath_canonicalize(copyfrom_path, pool);
 
   new_db->eb = eb;
   new_db->parent_dir_baton = pb;
-  new_db->pool = dir_pool;
+  new_db->pool = pool;
   new_db->repos_relpath = repos_relpath;
   new_db->copyfrom_path = copyfrom_path
-                            ? svn_relpath_canonicalize(copyfrom_path, dir_pool)
+                            ? svn_relpath_canonicalize(copyfrom_path, pool)
                             : NULL;
   new_db->copyfrom_rev = copyfrom_rev;
   new_db->added = added;
-  new_db->written_out = FALSE;
-  new_db->props = apr_hash_make(dir_pool);
-  new_db->deleted_props = apr_hash_make(dir_pool);
-  new_db->deleted_entries = apr_hash_make(dir_pool);
+  new_db->props = apr_hash_make(pool);
+  new_db->deleted_props = apr_hash_make(pool);
+  new_db->deleted_entries = apr_hash_make(pool);
 
   return new_db;
 }
@@ -224,15 +213,14 @@ make_file_baton(const char *path,
                 struct dir_baton *pb,
                 apr_pool_t *pool)
 {
-  apr_pool_t *file_pool = svn_pool_create(pb->pool);
-  struct file_baton *new_fb = apr_pcalloc(file_pool, sizeof(*new_fb));
+  struct file_baton *new_fb = apr_pcalloc(pool, sizeof(*new_fb));
 
   new_fb->eb = pb->eb;
   new_fb->parent_dir_baton = pb;
-  new_fb->pool = file_pool;
-  new_fb->repos_relpath = svn_relpath_canonicalize(path, file_pool);
-  new_fb->props = apr_hash_make(file_pool);
-  new_fb->deleted_props = apr_hash_make(file_pool);
+  new_fb->pool = pool;
+  new_fb->repos_relpath = svn_relpath_canonicalize(path, pool);
+  new_fb->props = apr_hash_make(pool);
+  new_fb->deleted_props = apr_hash_make(pool);
   new_fb->is_copy = FALSE;
   new_fb->copyfrom_path = NULL;
   new_fb->copyfrom_rev = SVN_INVALID_REVNUM;
@@ -277,64 +265,6 @@ get_props_content(svn_stringbuf_t **head
   return SVN_NO_ERROR;
 }
 
-/* Extract and dump properties stored in PROPS and property deletions
- * stored in DELETED_PROPS. If TRIGGER_VAR is not NULL, it is set to
- * FALSE.
- *
- * If PROPSTRING is non-NULL, set *PROPSTRING to a string containing
- * the content block of the property changes; otherwise, dump that to
- * the stream, too.
- */
-static svn_error_t *
-do_dump_props(svn_stringbuf_t **propstring,
-              svn_stream_t *stream,
-              apr_hash_t *props,
-              apr_hash_t *deleted_props,
-              svn_boolean_t *trigger_var,
-              apr_pool_t *result_pool,
-              apr_pool_t *scratch_pool)
-{
-  svn_stringbuf_t *header;
-  svn_stringbuf_t *content;
-  apr_size_t len;
-
-  if (trigger_var && !*trigger_var)
-    return SVN_NO_ERROR;
-
-  SVN_ERR(get_props_content(&header, &content, props, deleted_props,
-                            result_pool, scratch_pool));
-  len = header->len;
-  SVN_ERR(svn_stream_write(stream, header->data, &len));
-
-  if (propstring)
-    {
-      *propstring = content;
-    }
-  else
-    {
-      /* Content-length: 14 */
-      SVN_ERR(svn_stream_printf(stream, scratch_pool,
-                                SVN_REPOS_DUMPFILE_CONTENT_LENGTH
-                                ": %" APR_SIZE_T_FMT "\n\n",
-                                content->len));
-
-      len = content->len;
-      SVN_ERR(svn_stream_write(stream, content->data, &len));
-
-      /* No text is going to be dumped. Write a couple of newlines and
-         wait for the next node/ revision. */
-      SVN_ERR(svn_stream_puts(stream, "\n\n"));
-
-      /* Cleanup so that data is never dumped twice. */
-      apr_hash_clear(props);
-      apr_hash_clear(deleted_props);
-      if (trigger_var)
-        *trigger_var = FALSE;
-    }
-
-  return SVN_NO_ERROR;
-}
-
 static svn_error_t *
 do_dump_newlines(struct dump_edit_baton *eb,
                  svn_boolean_t *trigger_var,
@@ -351,8 +281,7 @@ do_dump_newlines(struct dump_edit_baton
 /*
  * Write out a node record for PATH of type KIND under EB->FS_ROOT.
  * ACTION describes what is happening to the node (see enum
- * svn_node_action). Write record to writable EB->STREAM, using
- * EB->BUFFER to write in chunks.
+ * svn_node_action). Write record to writable EB->STREAM.
  *
  * If the node was itself copied, IS_COPY is TRUE and the
  * path/revision of the copy source are in COPYFROM_PATH/COPYFROM_REV.
@@ -411,10 +340,15 @@ dump_node(struct dump_edit_baton *eb,
     case svn_node_action_replace:
       if (is_copy)
         {
-          /* Delete the original, and then re-add the replacement as a
-             copy using recursive calls into this function. */
-          SVN_ERR(dump_node(eb, repos_relpath, db, fb, svn_node_action_delete,
-                            FALSE, NULL, SVN_INVALID_REVNUM, pool));
+          /* More complex case: is_copy is true, and copyfrom_path/
+             copyfrom_rev are present: delete the original, and then re-add
+             it */
+
+          SVN_ERR(svn_stream_puts(eb->stream,
+                                  SVN_REPOS_DUMPFILE_NODE_ACTION
+                                  ": delete\n\n"));
+
+          /* Recurse: Print an additional add-with-history record. */
           SVN_ERR(dump_node(eb, repos_relpath, db, fb, svn_node_action_add,
                             is_copy, copyfrom_path, copyfrom_rev, pool));
         }
@@ -547,31 +481,77 @@ static svn_error_t *
 dump_pending(struct dump_edit_baton *eb,
              apr_pool_t *scratch_pool)
 {
+  svn_boolean_t dump_props = FALSE;
+  apr_hash_t *props, *deleted_props;
+
   if (! eb->pending_baton)
     return SVN_NO_ERROR;
 
+  /* Some pending properties to dump? */
   if (eb->pending_kind == svn_node_dir)
     {
       struct dir_baton *db = eb->pending_baton;
 
-      /* Some pending properties to dump? */
-      SVN_ERR(do_dump_props(NULL, eb->stream, db->props, db->deleted_props,
-                            &(db->dump_props), db->pool, scratch_pool));
+      if (db->dump_props)
+        {
+          dump_props = TRUE;
+          props = db->props;
+          deleted_props = db->deleted_props;
 
-      /* Some pending newlines to dump? */
-      SVN_ERR(do_dump_newlines(eb, &(db->dump_newlines), scratch_pool));
+          db->dump_props = FALSE;
+        }
     }
   else if (eb->pending_kind == svn_node_file)
     {
       struct file_baton *fb = eb->pending_baton;
 
-      /* Some pending properties to dump? */
-      SVN_ERR(do_dump_props(NULL, eb->stream, fb->props, fb->deleted_props,
-                            &(fb->dump_props), fb->pool, scratch_pool));
+      if (fb->dump_props)
+        {
+          dump_props = TRUE;
+          props = fb->props;
+          deleted_props = fb->deleted_props;
+          fb->dump_props = FALSE;
+        }
     }
   else
     abort();
 
+  if (dump_props)
+    {
+      svn_stringbuf_t *header, *content;
+      apr_size_t len;
+
+      SVN_ERR(get_props_content(&header, &content, props, deleted_props,
+                                scratch_pool, scratch_pool));
+      len = header->len;
+      SVN_ERR(svn_stream_write(eb->stream, header->data, &len));
+
+      /* Content-length: 14 */
+      SVN_ERR(svn_stream_printf(eb->stream, scratch_pool,
+                                SVN_REPOS_DUMPFILE_CONTENT_LENGTH
+                                ": %" APR_SIZE_T_FMT "\n\n",
+                                content->len));
+
+      len = content->len;
+      SVN_ERR(svn_stream_write(eb->stream, content->data, &len));
+
+      /* No text is going to be dumped. Write a couple of newlines and
+         wait for the next node/ revision. */
+      SVN_ERR(svn_stream_puts(eb->stream, "\n\n"));
+
+      /* Cleanup so that data is never dumped twice. */
+      apr_hash_clear(props);
+      apr_hash_clear(deleted_props);
+    }
+
+  if (eb->pending_kind == svn_node_dir)
+    {
+      struct dir_baton *db = eb->pending_baton;
+
+      /* Some pending newlines to dump? */
+      SVN_ERR(do_dump_newlines(eb, &(db->dump_newlines), scratch_pool));
+    }
+
   /* Anything that was pending is pending no longer. */
   eb->pending_baton = NULL;
   eb->pending_kind = svn_node_none;
@@ -636,7 +616,6 @@ open_root(void *edit_baton,
 
               /* Remember that we've started but not yet finished
                  handling this directory. */
-              new_db->written_out = TRUE;
               eb->pending_baton = new_db;
               eb->pending_kind = svn_node_dir;
             }
@@ -715,7 +694,6 @@ add_directory(const char *path,
 
   /* Remember that we've started, but not yet finished handling this
      directory. */
-  new_db->written_out = TRUE;
   pb->eb->pending_baton = new_db;
   pb->eb->pending_kind = svn_node_dir;
 
@@ -801,7 +779,7 @@ close_directory(void *dir_baton,
     }
 
   /* ### should be unnecessary */
-  svn_pool_destroy(db->pool);
+  apr_hash_clear(db->deleted_entries);
 
   return SVN_NO_ERROR;
 }
@@ -988,8 +966,16 @@ close_file(void *file_baton,
   /* Some pending properties to dump?  We'll dump just the headers for
      now, then dump the actual propchange content only after dumping
      the text headers too (if present). */
-  SVN_ERR(do_dump_props(&propstring, eb->stream, fb->props, fb->deleted_props,
-                        &(fb->dump_props), pool, pool));
+  if (fb->dump_props)
+    {
+      svn_stringbuf_t *header;
+      apr_size_t len;
+
+      SVN_ERR(get_props_content(&header, &propstring, fb->props, fb->deleted_props,
+                                pool, pool));
+      len = header->len;
+      SVN_ERR(svn_stream_write(eb->stream, header->data, &len));
+    }
 
   /* Dump the text headers */
   if (fb->dump_text)
@@ -1074,8 +1060,6 @@ close_file(void *file_baton,
      dump` */
   SVN_ERR(svn_stream_puts(eb->stream, "\n\n"));
 
-  svn_pool_clear(fb->pool);
-
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/move-tracking-2/subversion/svnrdump/load_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnrdump/load_editor.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnrdump/load_editor.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnrdump/load_editor.c Tue Jan 20 17:52:18 2015
@@ -66,9 +66,6 @@ struct parse_baton
   /* To bleep, or not to bleep?  (What kind of question is that?) */
   svn_boolean_t quiet;
 
-  /* UUID found in the dumpstream, if any; NULL otherwise. */
-  const char *uuid;
-
   /* Root URL of the target repository. */
   const char *root_url;
 
@@ -99,13 +96,12 @@ struct parse_baton
 
 /**
  * Use to wrap the dir_context_t in commit.c so we can keep track of
- * depth, relpath and parent for open_directory and close_directory.
+ * relpath and parent for open_directory and close_directory.
  */
 struct directory_baton
 {
   void *baton;
   const char *relpath;
-  int depth;
   struct directory_baton *parent;
 };
 
@@ -175,169 +171,6 @@ get_revision_mapping(apr_hash_t *rev_map
 }
 
 
-/* Prepend the mergeinfo source paths in MERGEINFO_ORIG with
-   PARENT_DIR, and return it in *MERGEINFO_VAL. */
-/* ### FIXME:  Consider somehow sharing code with
-   ### libsvn_repos/load-fs-vtable.c:prefix_mergeinfo_paths() */
-static svn_error_t *
-prefix_mergeinfo_paths(svn_string_t **mergeinfo_val,
-                       const svn_string_t *mergeinfo_orig,
-                       const char *parent_dir,
-                       apr_pool_t *pool)
-{
-  apr_hash_t *prefixed_mergeinfo, *mergeinfo;
-  apr_hash_index_t *hi;
-  void *rangelist;
-
-  SVN_ERR(svn_mergeinfo_parse(&mergeinfo, mergeinfo_orig->data, pool));
-  prefixed_mergeinfo = apr_hash_make(pool);
-  for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi))
-    {
-      const void *key;
-      const char *path, *merge_source;
-
-      apr_hash_this(hi, &key, NULL, &rangelist);
-      merge_source = svn_relpath_canonicalize(key, pool);
-
-      /* The svn:mergeinfo property syntax demands a repos abspath */
-      path = svn_fspath__canonicalize(svn_relpath_join(parent_dir,
-                                                       merge_source, pool),
-                                      pool);
-      svn_hash_sets(prefixed_mergeinfo, path, rangelist);
-    }
-  return svn_mergeinfo_to_string(mergeinfo_val, prefixed_mergeinfo, pool);
-}
-
-
-/* Examine the mergeinfo in INITIAL_VAL, renumber revisions in rangelists
-   as appropriate, and return the (possibly new) mergeinfo in *FINAL_VAL
-   (allocated from POOL). */
-/* ### FIXME:  Consider somehow sharing code with
-   ### libsvn_repos/load-fs-vtable.c:renumber_mergeinfo_revs() */
-static svn_error_t *
-renumber_mergeinfo_revs(svn_string_t **final_val,
-                        const svn_string_t *initial_val,
-                        struct revision_baton *rb,
-                        apr_pool_t *pool)
-{
-  apr_pool_t *subpool = svn_pool_create(pool);
-  svn_mergeinfo_t mergeinfo, predates_stream_mergeinfo;
-  svn_mergeinfo_t final_mergeinfo = apr_hash_make(subpool);
-  apr_hash_index_t *hi;
-
-  SVN_ERR(svn_mergeinfo_parse(&mergeinfo, initial_val->data, subpool));
-
-  /* Issue #3020
-     http://subversion.tigris.org/issues/show_bug.cgi?id=3020#desc16
-     Remove mergeinfo older than the oldest revision in the dump stream
-     and adjust its revisions by the difference between the head rev of
-     the target repository and the current dump stream rev. */
-  if (rb->pb->oldest_dumpstream_rev > 1)
-    {
-      SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
-                  &predates_stream_mergeinfo, mergeinfo,
-                  rb->pb->oldest_dumpstream_rev - 1, 0,
-                  TRUE, subpool, subpool));
-      SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
-                  &mergeinfo, mergeinfo,
-                  rb->pb->oldest_dumpstream_rev - 1, 0,
-                  FALSE, subpool, subpool));
-      SVN_ERR(svn_mergeinfo__adjust_mergeinfo_rangelists(
-                  &predates_stream_mergeinfo,
-                  predates_stream_mergeinfo,
-                  -rb->rev_offset, subpool, subpool));
-    }
-  else
-    {
-      predates_stream_mergeinfo = NULL;
-    }
-
-  for (hi = apr_hash_first(subpool, mergeinfo); hi; hi = apr_hash_next(hi))
-    {
-      svn_rangelist_t *rangelist;
-      struct parse_baton *pb = rb->pb;
-      int i;
-      const void *path;
-      apr_ssize_t pathlen;
-      void *val;
-
-      apr_hash_this(hi, &path, &pathlen, &val);
-      rangelist = val;
-
-      /* Possibly renumber revisions in merge source's rangelist. */
-      for (i = 0; i < rangelist->nelts; i++)
-        {
-          svn_revnum_t rev_from_map;
-          svn_merge_range_t *range = APR_ARRAY_IDX(rangelist, i,
-                                                   svn_merge_range_t *);
-          rev_from_map = get_revision_mapping(pb->rev_map, range->start);
-          if (SVN_IS_VALID_REVNUM(rev_from_map))
-            {
-              range->start = rev_from_map;
-            }
-          else if (range->start == pb->oldest_dumpstream_rev - 1)
-            {
-              /* Since the start revision of svn_merge_range_t are not
-                 inclusive there is one possible valid start revision that
-                 won't be found in the PB->REV_MAP mapping of load stream
-                 revsions to loaded revisions: The revision immediately
-                 preceding the oldest revision from the load stream.
-                 This is a valid revision for mergeinfo, but not a valid
-                 copy from revision (which PB->REV_MAP also maps for) so it
-                 will never be in the mapping.
-
-                 If that is what we have here, then find the mapping for the
-                 oldest rev from the load stream and subtract 1 to get the
-                 renumbered, non-inclusive, start revision. */
-              rev_from_map = get_revision_mapping(pb->rev_map,
-                                                  pb->oldest_dumpstream_rev);
-              if (SVN_IS_VALID_REVNUM(rev_from_map))
-                range->start = rev_from_map - 1;
-            }
-          else
-            {
-              /* If we can't remap the start revision then don't even bother
-                 trying to remap the end revision.  It's possible we might
-                 actually succeed at the latter, which can result in invalid
-                 mergeinfo with a start rev > end rev.  If that gets into the
-                 repository then a world of bustage breaks loose anytime that
-                 bogus mergeinfo is parsed.  See
-                 http://subversion.tigris.org/issues/show_bug.cgi?id=3020#desc16.
-                 */
-              continue;
-            }
-
-          rev_from_map = get_revision_mapping(pb->rev_map, range->end);
-          if (SVN_IS_VALID_REVNUM(rev_from_map))
-            range->end = rev_from_map;
-        }
-      apr_hash_set(final_mergeinfo, path, pathlen, rangelist);
-    }
-
-  if (predates_stream_mergeinfo)
-    {
-      SVN_ERR(svn_mergeinfo_merge2(final_mergeinfo, predates_stream_mergeinfo,
-                                   subpool, subpool));
-    }
-
-  SVN_ERR(svn_mergeinfo_sort(final_mergeinfo, subpool));
-
-  /* Mergeinfo revision sources for r0 and r1 are invalid; you can't merge r0
-     or r1.  However, svndumpfilter can be abused to produce r1 merge source
-     revs.  So if we encounter any, then strip them out, no need to put them
-     into the load target. */
-  SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(&final_mergeinfo,
-                                                    final_mergeinfo,
-                                                    1, 0, FALSE,
-                                                    subpool, subpool));
-
-  SVN_ERR(svn_mergeinfo_to_string(final_val, final_mergeinfo, pool));
-  svn_pool_destroy(subpool);
-
-  return SVN_NO_ERROR;
-}
-
-
 static svn_error_t *
 commit_callback(const svn_commit_info_t *commit_info,
                 void *baton,
@@ -599,9 +432,6 @@ uuid_record(const char *uuid,
             void *parse_baton,
             apr_pool_t *pool)
 {
-  struct parse_baton *pb;
-  pb = parse_baton;
-  pb->uuid = apr_pstrdup(pool, uuid);
   return SVN_NO_ERROR;
 }
 
@@ -661,7 +491,6 @@ new_node_record(void **node_baton,
       /* child_db corresponds to the root directory baton here */
       child_db = apr_pcalloc(rb->pool, sizeof(*child_db));
       child_db->baton = child_baton;
-      child_db->depth = 0;
       child_db->relpath = "";
       child_db->parent = NULL;
       rb->db = child_db;
@@ -745,7 +574,6 @@ new_node_record(void **node_baton,
           LDR_DBG(("Opened dir %p\n", child_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 = relpath_compose;
           child_db->parent = rb->db;
           rb->db = child_db;
@@ -813,7 +641,6 @@ new_node_record(void **node_baton,
                    nb->path, rb->db->baton, child_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 = apr_pstrdup(rb->pool, nb->path);
           child_db->parent = rb->db;
           rb->db = child_db;
@@ -836,7 +663,6 @@ new_node_record(void **node_baton,
                                                 rb->pool, &child_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 = apr_pstrdup(rb->pool, nb->path);
           child_db->parent = rb->db;
           rb->db = child_db;
@@ -893,51 +719,30 @@ set_node_property(void *baton,
                   const svn_string_t *value)
 {
   struct node_baton *nb = baton;
+  struct revision_baton *rb = nb->rb;
+  struct parse_baton *pb = rb->pb;
   const struct svn_delta_editor_t *commit_editor = nb->rb->pb->commit_editor;
   apr_pool_t *pool = nb->rb->pool;
 
   if (value && strcmp(name, SVN_PROP_MERGEINFO) == 0)
     {
-      svn_string_t *renumbered_mergeinfo;
-      svn_string_t prop_val;
+      svn_string_t *new_value;
+      svn_error_t *err;
 
-      /* Tolerate mergeinfo with "\r\n" line endings because some
-         dumpstream sources might contain as much.  If so normalize
-         the line endings to '\n' and make a notification to
-         PARSE_BATON->FEEDBACK_STREAM that we have made this
-         correction. */
-      if (strstr(value->data, "\r"))
+      err = svn_repos__adjust_mergeinfo_property(&new_value, value,
+                                                 pb->parent_dir,
+                                                 pb->rev_map,
+                                                 pb->oldest_dumpstream_rev,
+                                                 rb->rev_offset,
+                                                 NULL, NULL, /*notify*/
+                                                 pool, pool);
+      if (err)
         {
-          const char *prop_eol_normalized;
-
-          SVN_ERR(svn_subst_translate_cstring2(value->data,
-                                               &prop_eol_normalized,
-                                               "\n",  /* translate to LF */
-                                               FALSE, /* no repair */
-                                               NULL,  /* no keywords */
-                                               FALSE, /* no expansion */
-                                               pool));
-          prop_val.data = prop_eol_normalized;
-          prop_val.len = strlen(prop_eol_normalized);
-          value = &prop_val;
-
-          /* ### TODO: notify? */
+          return svn_error_quick_wrap(err,
+                                      _("Invalid svn:mergeinfo value"));
         }
 
-      /* Renumber mergeinfo as appropriate. */
-      SVN_ERR(renumber_mergeinfo_revs(&renumbered_mergeinfo, value,
-                                      nb->rb, pool));
-      value = renumbered_mergeinfo;
-
-      if (nb->rb->pb->parent_dir)
-        {
-          /* Prefix the merge source paths with PB->parent_dir. */
-          /* ASSUMPTION: All source paths are included in the dump stream. */
-          svn_string_t *mergeinfo_val;
-          SVN_ERR(prefix_mergeinfo_paths(&mergeinfo_val, value,
-                                         nb->rb->pb->parent_dir, pool));
-          value = mergeinfo_val;
-        }
+      value = new_value;
     }
 
   SVN_ERR(svn_rdump__normalize_prop(name, &value, pool));

Modified: subversion/branches/move-tracking-2/subversion/svnrdump/svnrdump.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnrdump/svnrdump.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnrdump/svnrdump.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnrdump/svnrdump.c Tue Jan 20 17:52:18 2015
@@ -39,6 +39,7 @@
 
 #include "svnrdump.h"
 
+#include "private/svn_repos_private.h"
 #include "private/svn_cmdline_private.h"
 #include "private/svn_ra_private.h"
 
@@ -229,38 +230,13 @@ replay_revstart(svn_revnum_t revision,
 {
   struct replay_baton *rb = replay_baton;
   apr_hash_t *normal_props;
-  svn_stringbuf_t *propstring;
-  svn_stream_t *stdout_stream;
-  svn_stream_t *revprop_stream;
-
-  SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));
 
-  /* Revision-number: 19 */
-  SVN_ERR(svn_stream_printf(stdout_stream, pool,
-                            SVN_REPOS_DUMPFILE_REVISION_NUMBER
-                            ": %ld\n", revision));
+  /* Normalize and dump the revprops */
   SVN_ERR(svn_rdump__normalize_props(&normal_props, rev_props, pool));
-  propstring = svn_stringbuf_create_ensure(0, pool);
-  revprop_stream = svn_stream_from_stringbuf(propstring, pool);
-  SVN_ERR(svn_hash_write2(normal_props, revprop_stream, "PROPS-END", pool));
-  SVN_ERR(svn_stream_close(revprop_stream));
-
-  /* Prop-content-length: 13 */
-  SVN_ERR(svn_stream_printf(stdout_stream, pool,
-                            SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
-                            ": %" APR_SIZE_T_FMT "\n", propstring->len));
-
-  /* Content-length: 29 */
-  SVN_ERR(svn_stream_printf(stdout_stream, pool,
-                            SVN_REPOS_DUMPFILE_CONTENT_LENGTH
-                            ": %" APR_SIZE_T_FMT "\n\n", propstring->len));
-
-  /* Property data. */
-  SVN_ERR(svn_stream_write(stdout_stream, propstring->data,
-                           &(propstring->len)));
-
-  SVN_ERR(svn_stream_puts(stdout_stream, "\n"));
-  SVN_ERR(svn_stream_close(stdout_stream));
+  SVN_ERR(svn_repos__dump_revision_record(rb->stdout_stream, revision, NULL,
+                                          normal_props,
+                                          TRUE /*props_section_always*/,
+                                          pool));
 
   SVN_ERR(svn_rdump__get_dump_editor(editor, edit_baton, revision,
                                      rb->stdout_stream, rb->extra_ra_session,
@@ -303,38 +279,13 @@ replay_revstart_v2(svn_revnum_t revision
 {
   struct replay_baton *rb = replay_baton;
   apr_hash_t *normal_props;
-  svn_stringbuf_t *propstring;
-  svn_stream_t *stdout_stream;
-  svn_stream_t *revprop_stream;
 
-  SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));
-
-  /* Revision-number: 19 */
-  SVN_ERR(svn_stream_printf(stdout_stream, pool,
-                            SVN_REPOS_DUMPFILE_REVISION_NUMBER
-                            ": %ld\n", revision));
+  /* Normalize and dump the revprops */
   SVN_ERR(svn_rdump__normalize_props(&normal_props, rev_props, pool));
-  propstring = svn_stringbuf_create_ensure(0, pool);
-  revprop_stream = svn_stream_from_stringbuf(propstring, pool);
-  SVN_ERR(svn_hash_write2(normal_props, revprop_stream, "PROPS-END", pool));
-  SVN_ERR(svn_stream_close(revprop_stream));
-
-  /* Prop-content-length: 13 */
-  SVN_ERR(svn_stream_printf(stdout_stream, pool,
-                            SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
-                            ": %" APR_SIZE_T_FMT "\n", propstring->len));
-
-  /* Content-length: 29 */
-  SVN_ERR(svn_stream_printf(stdout_stream, pool,
-                            SVN_REPOS_DUMPFILE_CONTENT_LENGTH
-                            ": %" APR_SIZE_T_FMT "\n\n", propstring->len));
-
-  /* Property data. */
-  SVN_ERR(svn_stream_write(stdout_stream, propstring->data,
-                           &(propstring->len)));
-
-  SVN_ERR(svn_stream_puts(stdout_stream, "\n"));
-  SVN_ERR(svn_stream_close(stdout_stream));
+  SVN_ERR(svn_repos__dump_revision_record(rb->stdout_stream, revision,
+                                          normal_props,
+                                          TRUE /*props_section_always*/,
+                                          pool));
 
   SVN_ERR(svn_rdump__get_dump_editor_v2(editor, revision,
                                         rb->stdout_stream,
@@ -471,35 +422,12 @@ dump_revision_header(svn_ra_session_t *s
                      apr_pool_t *pool)
 {
   apr_hash_t *prophash;
-  svn_stringbuf_t *propstring;
-  svn_stream_t *propstream;
 
-  SVN_ERR(svn_stream_printf(stdout_stream, pool,
-                            SVN_REPOS_DUMPFILE_REVISION_NUMBER
-                            ": %ld\n", revision));
-
-  prophash = apr_hash_make(pool);
-  propstring = svn_stringbuf_create_empty(pool);
   SVN_ERR(svn_ra_rev_proplist(session, revision, &prophash, pool));
-
-  propstream = svn_stream_from_stringbuf(propstring, pool);
-  SVN_ERR(svn_hash_write2(prophash, propstream, "PROPS-END", pool));
-  SVN_ERR(svn_stream_close(propstream));
-
-  /* Property-content-length: 14; Content-length: 14 */
-  SVN_ERR(svn_stream_printf(stdout_stream, pool,
-                            SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
-                            ": %" APR_SIZE_T_FMT "\n",
-                            propstring->len));
-  SVN_ERR(svn_stream_printf(stdout_stream, pool,
-                            SVN_REPOS_DUMPFILE_CONTENT_LENGTH
-                            ": %" APR_SIZE_T_FMT "\n\n",
-                            propstring->len));
-  /* The properties */
-  SVN_ERR(svn_stream_write(stdout_stream, propstring->data,
-                           &(propstring->len)));
-  SVN_ERR(svn_stream_puts(stdout_stream, "\n"));
-
+  SVN_ERR(svn_repos__dump_revision_record(stdout_stream, revision, NULL,
+                                          prophash,
+                                          TRUE /*props_section_always*/,
+                                          pool));
   return SVN_NO_ERROR;
 }
 
@@ -1176,7 +1104,7 @@ sub_main(int *exit_code, int argc, const
 
   if (strcmp(subcommand->name, "load") == 0)
     {
-      /* 
+      /*
        * By default (no --*-interactive options given), the 'load' subcommand
        * is interactive unless username and password were provided on the
        * command line. This allows prompting for auth creds to work without

Modified: subversion/branches/move-tracking-2/subversion/svnserve/logger.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnserve/logger.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnserve/logger.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnserve/logger.c Tue Jan 20 17:52:18 2015
@@ -134,7 +134,10 @@ logger__log_error(logger_t *logger,
           if (len > sizeof(errstr) - sizeof(APR_EOL_STR)) {
             len = sizeof(errstr) - sizeof(APR_EOL_STR);
           }
+
           memcpy(errstr + len, APR_EOL_STR, sizeof(APR_EOL_STR));
+          len += sizeof(APR_EOL_STR) -1;  /* add NL, ex terminating NUL */
+
           svn_error_clear(svn_stream_write(logger->stream, errstr, &len));
 
           continuation = "-";

Modified: subversion/branches/move-tracking-2/subversion/svnserve/svnserve.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnserve/svnserve.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnserve/svnserve.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnserve/svnserve.c Tue Jan 20 17:52:18 2015
@@ -271,6 +271,8 @@ static const apr_getopt_option_t svnserv
         "                             "
         "Default is 16.\n"
         "                             "
+        "0 switches to dynamically sized caches.\n"
+        "                             "
         "[used for FSFS and FSX repositories only]")},
     {"cache-txdeltas", SVNSERVE_OPT_CACHE_TXDELTAS, 1,
      N_("enable or disable caching of deltas between older\n"

Modified: subversion/branches/move-tracking-2/subversion/svnsync/svnsync.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnsync/svnsync.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnsync/svnsync.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnsync/svnsync.c Tue Jan 20 17:52:18 2015
@@ -764,8 +764,10 @@ open_target_session(svn_ra_session_t **t
 /*** `svnsync init' ***/
 
 /* Initialize the repository associated with RA session TO_SESSION,
- * using information found in BATON, while the repository is
- * locked.  Implements `with_locked_func_t' interface.
+ * using information found in BATON.
+ *
+ * Implements `with_locked_func_t' interface.  The caller has
+ * acquired a lock on the repository if locking is needed.
  */
 static svn_error_t *
 do_initialize(svn_ra_session_t *to_session,
@@ -1403,8 +1405,10 @@ replay_rev_finished(svn_revnum_t revisio
 }
 
 /* Synchronize the repository associated with RA session TO_SESSION,
- * using information found in BATON, while the repository is
- * locked.  Implements `with_locked_func_t' interface.
+ * using information found in BATON.
+ *
+ * Implements `with_locked_func_t' interface.  The caller has
+ * acquired a lock on the repository if locking is needed.
  */
 static svn_error_t *
 do_synchronize(svn_ra_session_t *to_session,
@@ -1597,8 +1601,10 @@ synchronize_cmd(apr_getopt_t *os, void *
 /*** `svnsync copy-revprops' ***/
 
 /* Copy revision properties to the repository associated with RA
- * session TO_SESSION, using information found in BATON, while the
- * repository is locked.  Implements `with_locked_func_t' interface.
+ * session TO_SESSION, using information found in BATON.
+ *
+ * Implements `with_locked_func_t' interface.  The caller has
+ * acquired a lock on the repository if locking is needed.
  */
 static svn_error_t *
 do_copy_revprops(svn_ra_session_t *to_session,

Modified: subversion/branches/move-tracking-2/subversion/svnsync/sync.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnsync/sync.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnsync/sync.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnsync/sync.c Tue Jan 20 17:52:18 2015
@@ -34,6 +34,8 @@
 #include "svn_subst.h"
 #include "svn_string.h"
 
+#include "private/svn_string_private.h"
+
 #include "sync.h"
 
 #include "svn_private_config.h"
@@ -83,6 +85,90 @@ normalize_string(const svn_string_t **st
   return SVN_NO_ERROR;
 }
 
+/* Remove r0 references from the mergeinfo string *STR.
+ *
+ * r0 was never a valid mergeinfo reference and cannot be committed with
+ * recent servers, but can be committed through a server older than 1.6.18
+ * for HTTP or older than 1.6.17 for the other protocols. See issue #4476
+ * "Mergeinfo containing r0 makes svnsync and dump and load fail".
+ *
+ * Set *WAS_CHANGED to TRUE if *STR was changed, otherwise to FALSE.
+ */
+static svn_error_t *
+remove_r0_mergeinfo(const svn_string_t **str,
+                    svn_boolean_t *was_changed,
+                    apr_pool_t *result_pool,
+                    apr_pool_t *scratch_pool)
+{
+  svn_stringbuf_t *new_str = svn_stringbuf_create_empty(result_pool);
+  apr_array_header_t *lines;
+  int i;
+
+  SVN_ERR_ASSERT(*str && (*str)->data);
+
+  *was_changed = FALSE;
+
+  /* for each line */
+  lines = svn_cstring_split((*str)->data, "\n", FALSE, scratch_pool);
+
+  for (i = 0; i < lines->nelts; i++)
+    {
+      char *line = APR_ARRAY_IDX(lines, i, char *);
+      char *colon;
+
+      /* split at the last colon */
+      colon = strrchr(line, ':');
+
+      if (! colon)
+        return svn_error_createf(SVN_ERR_MERGEINFO_PARSE_ERROR, NULL,
+                                 _("Missing colon in svn:mergeinfo "
+                                   "property"));
+
+      /* remove r0 */
+      if (colon[1] == '0')
+        {
+          char *rangelist;
+
+          rangelist = colon + 1;
+
+          if (strncmp(rangelist, "0*,", 3) == 0)
+            {
+              rangelist += 3;
+            }
+          else if (strcmp(rangelist, "0*") == 0
+                   || strncmp(rangelist, "0,", 2) == 0
+                   || strncmp(rangelist, "0-1*", 4) == 0
+                   || strncmp(rangelist, "0-1,", 4) == 0
+                   || strcmp(rangelist, "0-1") == 0)
+            {
+              rangelist += 2;
+            }
+          else if (strcmp(rangelist, "0") == 0)
+            {
+              rangelist += 1;
+            }
+          else if (strncmp(rangelist, "0-", 2) == 0)
+            {
+              rangelist[0] = '1';
+            }
+
+          /* reassemble */
+          if (new_str->len)
+            svn_stringbuf_appendbyte(new_str, '\n');
+          svn_stringbuf_appendbytes(new_str, line, colon + 1 - line);
+          svn_stringbuf_appendcstr(new_str, rangelist);
+        }
+    }
+
+  if (strcmp((*str)->data, new_str->data) != 0)
+    {
+      *was_changed = TRUE;
+    }
+
+  *str = svn_stringbuf__morph_into_string(new_str);
+  return SVN_NO_ERROR;
+}
+
 
 /* Normalize the encoding and line ending style of the values of properties
  * in REV_PROPS that "need translation" (according to
@@ -153,6 +239,7 @@ typedef struct edit_baton_t {
   svn_boolean_t got_textdeltas;
   svn_revnum_t base_revision;
   svn_boolean_t quiet;
+  svn_boolean_t mergeinfo_tweaked;  /* Did we tweak svn:mergeinfo? */
   svn_boolean_t strip_mergeinfo;    /* Are we stripping svn:mergeinfo? */
   svn_boolean_t migrate_svnmerge;   /* Are we converting svnmerge.py data? */
   svn_boolean_t mergeinfo_stripped; /* Did we strip svn:mergeinfo? */
@@ -414,8 +501,19 @@ change_file_prop(void *file_baton,
   if (svn_prop_needs_translation(name))
     {
       svn_boolean_t was_normalized;
+      svn_boolean_t mergeinfo_tweaked = FALSE;
+
+      /* Normalize encoding to UTF-8, and EOL style to LF. */
       SVN_ERR(normalize_string(&value, &was_normalized,
                                eb->source_prop_encoding, pool, pool));
+      /* Correct malformed mergeinfo. */
+      if (strcmp(name, SVN_PROP_MERGEINFO) == 0)
+        {
+          SVN_ERR(remove_r0_mergeinfo(&value, &mergeinfo_tweaked,
+                                      pool, pool));
+          if (mergeinfo_tweaked)
+            eb->mergeinfo_tweaked = TRUE;
+        }
       if (was_normalized)
         (*(eb->normalized_node_props_counter))++;
     }
@@ -513,8 +611,19 @@ change_dir_prop(void *dir_baton,
   if (svn_prop_needs_translation(name))
     {
       svn_boolean_t was_normalized;
+      svn_boolean_t mergeinfo_tweaked = FALSE;
+
+      /* Normalize encoding to UTF-8, and EOL style to LF. */
       SVN_ERR(normalize_string(&value, &was_normalized, eb->source_prop_encoding,
                                pool, pool));
+      /* Maybe adjust svn:mergeinfo. */
+      if (strcmp(name, SVN_PROP_MERGEINFO) == 0)
+        {
+          SVN_ERR(remove_r0_mergeinfo(&value, &mergeinfo_tweaked,
+                                      pool, pool));
+          if (mergeinfo_tweaked)
+            eb->mergeinfo_tweaked = TRUE;
+        }
       if (was_normalized)
         (*(eb->normalized_node_props_counter))++;
     }
@@ -548,6 +657,10 @@ close_edit(void *edit_baton,
     {
       if (eb->got_textdeltas)
         SVN_ERR(svn_cmdline_printf(pool, "\n"));
+      if (eb->mergeinfo_tweaked)
+        SVN_ERR(svn_cmdline_printf(pool,
+                                   "NOTE: Adjusted Subversion mergeinfo in "
+                                   "this revision.\n"));
       if (eb->mergeinfo_stripped)
         SVN_ERR(svn_cmdline_printf(pool,
                                    "NOTE: Dropped Subversion mergeinfo "

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/basic_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/basic_tests.py?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/basic_tests.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/basic_tests.py Tue Jan 20 17:52:18 2015
@@ -3146,6 +3146,31 @@ def basic_youngest(sbox):
                                            'youngest', path)
 
 
+# With 'svn mkdir --parents' the target directory may already exist on disk.
+# In that case it was wrongly performing a recursive 'add' on its contents.
+def mkdir_parents_target_exists_on_disk(sbox):
+  "mkdir parents target exists on disk"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  Y_path = sbox.ospath('Y')
+  Y_Z_path = sbox.ospath('Y/Z')
+
+  os.mkdir(Y_path)
+  os.mkdir(Y_Z_path)
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'mkdir', '--parents', Y_path)
+
+  # Y should be added, and Z should not. There was a regression in which Z
+  # was also added.
+  expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+  expected_status.add({
+    'Y'      : Item(status='A ', wc_rev=0),
+    })
+  svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+
 ########################################################################
 # Run the tests
 
@@ -3215,6 +3240,7 @@ test_list = [ None,
               delete_conflicts_one_of_many,
               peg_rev_on_non_existent_wc_path,
               basic_youngest,
+              mkdir_parents_target_exists_on_disk,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/copy_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/copy_tests.py?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/copy_tests.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/copy_tests.py Tue Jan 20 17:52:18 2015
@@ -560,7 +560,7 @@ def no_copy_overwrites(sbox):
   # Repeat the last command.  It should *fail* because A/D/H/G already exists.
   svntest.actions.run_and_verify_svn(
     "Whoa, I was able to overwrite a directory!",
-    None, svntest.verify.AnyOutput,
+    None, ".*'/A/D/H/G'.*",
     'cp', dirURL1, dirURL2,
     '-m', 'fooogle')
 

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/externals_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/externals_tests.py?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/externals_tests.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/externals_tests.py Tue Jan 20 17:52:18 2015
@@ -3480,6 +3480,73 @@ def switch_relative_externals(sbox):
                                      'up', wc)
 
 
+def copy_file_external_to_repo(sbox):
+  "explicitly copy file external to repo"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  change_external(sbox.ospath('A'), '^/A/mu ext')
+  sbox.simple_update()
+
+  svntest.actions.run_and_verify_svn(None, None, [], 'cp',
+                                     '--message', 'external copy',
+                                     sbox.ospath('A/ext'),
+                                     sbox.repo_url + '/ext_copy')
+
+  expected_output = svntest.wc.State(wc_dir, {
+      'ext_copy' : Item(status='A '),
+  })
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.add({
+      'A/ext'    : Item('This is the file \'mu\'.\n'),
+      'ext_copy' : Item('This is the file \'mu\'.\n'),
+      })
+  svntest.actions.run_and_verify_update(wc_dir,
+                                        expected_output, expected_disk, None)
+
+@Issue(4550)
+def replace_tree_with_foreign_external(sbox):
+  "replace tree with foreign external"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  repo_dir = sbox.repo_dir
+
+  other_repo_dir, other_repo_url = sbox.add_repo_path('other')
+  svntest.main.copy_repos(repo_dir, other_repo_dir, 1)
+
+  sbox.simple_propset('svn:externals', other_repo_url + '/A/B X', 'A')
+  sbox.simple_commit()
+  sbox.simple_propdel('svn:externals', 'A')
+  sbox.simple_mkdir('A/X')
+  sbox.simple_mkdir('A/X/E')
+  sbox.simple_commit()
+  sbox.simple_update()
+
+  expected_output = svntest.wc.State(wc_dir, {
+      'A/X'         : Item(status='D '),
+      'A'           : Item(status=' U'),
+      'A/X/lambda'  : Item(status='A '),
+      'A/X/E'       : Item(status='A '),
+      'A/X/E/alpha' : Item(status='A '),
+      'A/X/E/beta'  : Item(status='A '),
+      'A/X/F'       : Item(status='A '),
+      })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
+  expected_status.add({
+    'A/X'         : Item(status='  ', wc_rev=1, prev_status='X '),
+    'A/X/E'       : Item(status='  ', wc_rev=1, prev_status='  '),
+    'A/X/E/alpha' : Item(status='  ', wc_rev=1),
+    'A/X/E/beta'  : Item(status='  ', wc_rev=1),
+    'A/X/F'       : Item(status='  ', wc_rev=1),
+    'A/X/lambda'  : Item(status='  ', wc_rev=1),
+    })
+  svntest.actions.run_and_verify_update(wc_dir,
+                                        expected_output, None, expected_status,
+                                        None, None, None, None, None, 1,
+                                        '-r', '2', wc_dir)
+
 ########################################################################
 # Run the tests
 
@@ -3538,6 +3605,8 @@ test_list = [ None,
               update_external_peg_rev,
               update_deletes_file_external,
               switch_relative_externals,
+              copy_file_external_to_repo,
+              replace_tree_with_foreign_external,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/lock_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/lock_tests.py?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/lock_tests.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/lock_tests.py Tue Jan 20 17:52:18 2015
@@ -2355,6 +2355,26 @@ def lock_commit_bump(sbox):
   svntest.actions.run_and_verify_info(expected_infos, 
                                       sbox.ospath('iota'))
 
+def copy_dir_with_locked_file(sbox):
+  "copy a directory containing a locked file"
+
+  sbox.build()
+  AA_url = sbox.repo_url + '/AA'
+  AA2_url = sbox.repo_url + '/AA2'
+  A_url = sbox.repo_url + '/A'
+  mu_url = A_url + '/mu'
+
+  svntest.main.run_svn(None, 'lock', '-m', 'locked', mu_url)
+
+  svntest.actions.run_and_verify_svn(None, None, [],
+                                     'cp', A_url, AA_url,
+                                     '-m', '')
+
+  expected_err = "svn: E160037: .*no matching lock-token available"
+  svntest.actions.run_and_verify_svn(None, None, expected_err,
+                                     'mv', A_url, AA2_url,
+                                     '-m', '')
+
 
 ########################################################################
 # Run the tests
@@ -2420,6 +2440,7 @@ test_list = [ None,
               dav_lock_refresh,
               delete_locked_file_with_percent,
               lock_commit_bump,
+              copy_dir_with_locked_file,
             ]
 
 if __name__ == '__main__':