You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by sv...@apache.org on 2013/11/06 05:02:38 UTC

svn commit: r1539234 - in /subversion/branches/1.7.x: ./ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_fs_fs/ subversion/libsvn_subr/ subversion/svn/ subversion/svnserve/ subversion/tests/cmdline/ subversion/tests/cmdline/svnt...

Author: svn-role
Date: Wed Nov  6 04:02:38 2013
New Revision: 1539234

URL: http://svn.apache.org/r1539234
Log:
Merge the 1.7.x-issue4153 branch:

 * r1306275, and other revisions
   New diff support code for added/deleted files and directories.
   Fixes issue #4153, "svn log --diff" on moved file gives "not found",
   and other problems such as issue #4421, "diff --summarize of a child of
   a newly added child causes crash" (over HTTP only).
   Justification:
     The current code (introduced in 1.7.x in the r1207351 backport commit)
     produces inconsistent paths in diff output (see
     http://svn.haxx.se/dev/archive-2012-03/0385.shtml), and it also breaks
     with the paradigm that the target of an editor drive may never have more
     than one path component (which according to cmpilato is an API violation).
   Notes:
     Please read the branch and related trunk log messages for detailed notes
     about these changes.
     breser: Not so fond of the temp file use but 1.8.x is out with a much
     better implementation anyway.
   Branch:
     ^/subversion/branches/1.7.x-issue4153
   Votes:
     +1: breser, julianfoad, stsp

Added:
    subversion/branches/1.7.x/subversion/libsvn_client/diff_summarize.c
      - copied unchanged from r1539233, subversion/branches/1.7.x-issue4153/subversion/libsvn_client/diff_summarize.c
Modified:
    subversion/branches/1.7.x/   (props changed)
    subversion/branches/1.7.x/CHANGES   (props changed)
    subversion/branches/1.7.x/STATUS
    subversion/branches/1.7.x/subversion/include/private/svn_adler32.h   (props changed)
    subversion/branches/1.7.x/subversion/include/private/svn_string_private.h   (props changed)
    subversion/branches/1.7.x/subversion/include/private/svn_temp_serializer.h   (props changed)
    subversion/branches/1.7.x/subversion/libsvn_client/client.h
    subversion/branches/1.7.x/subversion/libsvn_client/diff.c
    subversion/branches/1.7.x/subversion/libsvn_fs_fs/temp_serializer.c   (props changed)
    subversion/branches/1.7.x/subversion/libsvn_fs_fs/temp_serializer.h   (props changed)
    subversion/branches/1.7.x/subversion/libsvn_subr/adler32.c   (props changed)
    subversion/branches/1.7.x/subversion/libsvn_subr/hash.c   (props changed)
    subversion/branches/1.7.x/subversion/libsvn_subr/svn_base64.c   (props changed)
    subversion/branches/1.7.x/subversion/libsvn_subr/svn_cache_config.c   (props changed)
    subversion/branches/1.7.x/subversion/libsvn_subr/svn_temp_serializer.c   (props changed)
    subversion/branches/1.7.x/subversion/svn/main.c   (props changed)
    subversion/branches/1.7.x/subversion/svnserve/main.c   (props changed)
    subversion/branches/1.7.x/subversion/tests/cmdline/basic_tests.py   (props changed)
    subversion/branches/1.7.x/subversion/tests/cmdline/diff_tests.py
    subversion/branches/1.7.x/subversion/tests/cmdline/log_tests.py
    subversion/branches/1.7.x/subversion/tests/cmdline/svntest/   (props changed)
    subversion/branches/1.7.x/tools/client-side/svnmucc/svnmucc.c   (props changed)

Propchange: subversion/branches/1.7.x/
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-issue4153:r1309894-1539233
  Merged /subversion/trunk:r1164116,1230798,1306275,1309865,1338291,1338297,1338314,1338688,1338708,1338713,1338739,1338748,1339159,1341544,1341560,1535551,1535591

Propchange: subversion/branches/1.7.x/CHANGES
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-issue4153/CHANGES:r1309894-1539233

Modified: subversion/branches/1.7.x/STATUS
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/STATUS?rev=1539234&r1=1539233&r2=1539234&view=diff
==============================================================================
--- subversion/branches/1.7.x/STATUS (original)
+++ subversion/branches/1.7.x/STATUS Wed Nov  6 04:02:38 2013
@@ -121,24 +121,3 @@ Veto-blocked changes:
 
 Approved changes:
 =================
-
- * r1306275, and other revisions
-   New diff support code for added/deleted files and directories.
-   Fixes issue #4153, "svn log --diff" on moved file gives "not found",
-   and other problems such as issue #4421, "diff --summarize of a child of
-   a newly added child causes crash" (over HTTP only).
-   Justification:
-     The current code (introduced in 1.7.x in the r1207351 backport commit)
-     produces inconsistent paths in diff output (see
-     http://svn.haxx.se/dev/archive-2012-03/0385.shtml), and it also breaks
-     with the paradigm that the target of an editor drive may never have more
-     than one path component (which according to cmpilato is an API violation).
-   Notes:
-     Please read the branch and related trunk log messages for detailed notes
-     about these changes.
-     breser: Not so fond of the temp file use but 1.8.x is out with a much
-     better implementation anyway.
-   Branch:
-     ^/subversion/branches/1.7.x-issue4153
-   Votes:
-     +1: breser, julianfoad, stsp

Propchange: subversion/branches/1.7.x/subversion/include/private/svn_adler32.h
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-issue4153/subversion/include/private/svn_adler32.h:r1309894-1539233

Propchange: subversion/branches/1.7.x/subversion/include/private/svn_string_private.h
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-issue4153/subversion/include/private/svn_string_private.h:r1309894-1539233

Propchange: subversion/branches/1.7.x/subversion/include/private/svn_temp_serializer.h
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-issue4153/subversion/include/private/svn_temp_serializer.h:r1309894-1539233

Modified: subversion/branches/1.7.x/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/libsvn_client/client.h?rev=1539234&r1=1539233&r2=1539234&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/libsvn_client/client.h (original)
+++ subversion/branches/1.7.x/subversion/libsvn_client/client.h Wed Nov  6 04:02:38 2013
@@ -609,6 +609,24 @@ svn_client__get_diff_summarize_editor(co
                                       void **edit_baton,
                                       apr_pool_t *pool);
 
+/* Set *CALLBACKS and *CALLBACK_BATON to a set of diff callbacks that will
+   report a diff summary, i.e. only providing information about the changed
+   items without the text deltas.
+
+   TARGET is the target path, relative to the anchor, of the diff.
+
+   SUMMARIZE_FUNC is called with SUMMARIZE_BATON as parameter by the
+   created callbacks for each changed item.
+*/
+svn_error_t *
+svn_client__get_diff_summarize_callbacks(
+                        svn_wc_diff_callbacks4_t **callbacks,
+                        void **callback_baton,
+                        const char *target,
+                        svn_client_diff_summarize_func_t summarize_func,
+                        void *summarize_baton,
+                        apr_pool_t *pool);
+
 /* ---------------------------------------------------------------- */
 
 /*** Copy Stuff ***/

Modified: subversion/branches/1.7.x/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/libsvn_client/diff.c?rev=1539234&r1=1539233&r2=1539234&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/1.7.x/subversion/libsvn_client/diff.c Wed Nov  6 04:02:38 2013
@@ -1494,11 +1494,55 @@ check_diff_target_exists(const char *url
   return SVN_NO_ERROR;
 }
 
+/* Resolve PATH_OR_URL@PEG_REVISION to a possibly different *RESOLVED_URL
+ * which the corresponding object has in REVISION. If the object has no
+ * location in REVISION, set *RESOLVED_URL to NULL. */
+static svn_error_t *
+resolve_pegged_diff_target_url(const char **resolved_url,
+                               svn_ra_session_t *ra_session,
+                               const char *path_or_url,
+                               const svn_opt_revision_t *peg_revision,
+                               const svn_opt_revision_t *revision,
+                               svn_client_ctx_t *ctx,
+                               apr_pool_t *scratch_pool)
+{
+  svn_opt_revision_t *start_rev_ignore, *end_rev_ignore;
+  const char *end_url_ignore;
+  static const svn_opt_revision_t unspecified_rev =
+    { svn_opt_revision_unspecified, { 0 } };
+  svn_error_t *err;
+
+  /* Check if the PATH_OR_URL exists at REVISION. */
+  err = svn_client__repos_locations(resolved_url, &start_rev_ignore,
+                                    &end_url_ignore, &end_rev_ignore,
+                                    ra_session,
+                                    path_or_url,
+                                    peg_revision,
+                                    revision,
+                                    &unspecified_rev,
+                                    ctx, scratch_pool);
+  if (err)
+    {
+      if (err->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES ||
+          err->apr_err == SVN_ERR_FS_NOT_FOUND)
+        {
+          svn_error_clear(err);
+          *resolved_url = NULL;
+        }
+      else
+        return svn_error_trace(err);
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /** Prepare a repos repos diff between PATH1 and PATH2@PEG_REVISION,
  * in the revision range REVISION1:REVISION2.
  * Return URLs and peg revisions in *URL1, *REV1 and in *URL2, *REV2.
  * Return suitable anchors in *ANCHOR1 and *ANCHOR2, and targets in
  * *TARGET1 and *TARGET2, based on *URL1 and *URL2.
+ * Indicate the corresponding node kinds in *KIND1 and *KIND2, and verify
+ * that at least one of the diff targets exists.
  * Set *BASE_PATH corresponding to the URL opened in the new *RA_SESSION
  * which is pointing at *ANCHOR1.
  * Use client context CTX. Do all allocations in POOL. */
@@ -1512,6 +1556,8 @@ diff_prepare_repos_repos(const char **ur
                          const char **anchor2,
                          const char **target1,
                          const char **target2,
+                         svn_node_kind_t *kind1,
+                         svn_node_kind_t *kind2,
                          svn_ra_session_t **ra_session,
                          svn_client_ctx_t *ctx,
                          const char *path1,
@@ -1521,7 +1567,6 @@ diff_prepare_repos_repos(const char **ur
                          const svn_opt_revision_t *peg_revision,
                          apr_pool_t *pool)
 {
-  svn_node_kind_t kind1, kind2;
   const char *path2_abspath;
   const char *path1_abspath;
 
@@ -1560,53 +1605,56 @@ diff_prepare_repos_repos(const char **ur
      actual URLs will be. */
   if (peg_revision->kind != svn_opt_revision_unspecified)
     {
-      svn_opt_revision_t *start_ignore, *end_ignore;
-      svn_error_t *err;
+      const char *resolved_url1;
+      const char *resolved_url2;
 
-      err = svn_client__repos_locations(url1, &start_ignore,
-                                        url2, &end_ignore,
-                                        *ra_session,
-                                        path2,
-                                        peg_revision,
-                                        revision1,
-                                        revision2,
-                                        ctx, pool);
-      if (err)
+      SVN_ERR(resolve_pegged_diff_target_url(&resolved_url2, *ra_session,
+                                             path2, peg_revision,
+                                             revision2, ctx, pool));
+
+      SVN_ERR(svn_ra_reparent(*ra_session, *url1, pool));
+      SVN_ERR(resolve_pegged_diff_target_url(&resolved_url1, *ra_session,
+                                             path1, peg_revision,
+                                             revision1, ctx, pool));
+
+      /* Either or both URLs might have changed as a result of resolving
+       * the PATH_OR_URL@PEG_REVISION's history. If only one of the URLs
+       * could be resolved, use the same URL for URL1 and URL2, so we can
+       * show diff that 'adds' the object (see issue #4153). */
+      if (resolved_url2)
         {
-          if (err->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES)
-            {
-              /* Don't give up just yet. A missing path might translate
-               * into an addition in the diff. Below, we verify that each
-               * URL exists on at least one side of the diff. */
-              svn_error_clear(err);
-            }
-          else
-            return svn_error_trace(err);
+          *url2 = resolved_url2;
+          if (!resolved_url1)
+            *url1 = resolved_url2;
         }
-      else
+      if (resolved_url1)
         {
-          /* Reparent the session, since *URL2 might have changed as a result
-             the above call. */
-          SVN_ERR(svn_ra_reparent(*ra_session, *url2, pool));
+          *url1 = resolved_url1;
+          if (!resolved_url2)
+            *url2 = resolved_url1;
         }
+
+      /* Reparent the session, since *URL2 might have changed as a result
+         the above call. */
+      SVN_ERR(svn_ra_reparent(*ra_session, *url2, pool));
     }
 
   /* Resolve revision and get path kind for the second target. */
   SVN_ERR(svn_client__get_revision_number(rev2, NULL, ctx->wc_ctx,
            (path2 == *url2) ? NULL : path2_abspath,
            *ra_session, revision2, pool));
-  SVN_ERR(svn_ra_check_path(*ra_session, "", *rev2, &kind2, pool));
+  SVN_ERR(svn_ra_check_path(*ra_session, "", *rev2, kind2, pool));
 
   /* Do the same for the first target. */
   SVN_ERR(svn_ra_reparent(*ra_session, *url1, pool));
   SVN_ERR(svn_client__get_revision_number(rev1, NULL, ctx->wc_ctx,
            (strcmp(path1, *url1) == 0) ? NULL : path1_abspath,
            *ra_session, revision1, pool));
-  SVN_ERR(svn_ra_check_path(*ra_session, "", *rev1, &kind1, pool));
+  SVN_ERR(svn_ra_check_path(*ra_session, "", *rev1, kind1, pool));
 
   /* Either both URLs must exist at their respective revisions,
    * or one of them may be missing from one side of the diff. */
-  if (kind1 == svn_node_none && kind2 == svn_node_none)
+  if (*kind1 == svn_node_none && *kind2 == svn_node_none)
     {
       if (strcmp(*url1, *url2) == 0)
         return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
@@ -1620,9 +1668,9 @@ diff_prepare_repos_repos(const char **ur
                                    "'%ld'"),
                                  *url1, *url2, *rev1, *rev2);
     }
-  else if (kind1 == svn_node_none)
+  else if (*kind1 == svn_node_none)
     SVN_ERR(check_diff_target_exists(*url1, *rev2, *rev1, *ra_session, pool));
-  else if (kind2 == svn_node_none)
+  else if (*kind2 == svn_node_none)
     SVN_ERR(check_diff_target_exists(*url2, *rev1, *rev2, *ra_session, pool));
 
   /* Choose useful anchors and targets for our two URLs. */
@@ -1630,57 +1678,9 @@ diff_prepare_repos_repos(const char **ur
   *anchor2 = *url2;
   *target1 = "";
   *target2 = "";
-  if ((kind1 == svn_node_none) || (kind2 == svn_node_none))
-    {
-      svn_node_kind_t kind;
-      const char *repos_root;
-      const char *new_anchor;
-      svn_revnum_t rev;
-
-      /* The diff target does not exist on one side of the diff.
-       * This can happen if the target was added or deleted within the
-       * revision range being diffed.
-       * However, we don't know how deep within a added/deleted subtree the
-       * diff target is. Find a common parent that exists on both sides of
-       * the diff and use it as anchor for the diff operation.
-       *
-       * ### This can fail due to authz restrictions (like in issue #3242).
-       * ### But it is the only option we have right now to try to get
-       * ### a usable diff in this situation. */
-
-      SVN_ERR(svn_ra_get_repos_root2(*ra_session, &repos_root, pool));
-
-      /* Since we already know that one of the URLs does exist,
-       * look for an existing parent of the URL which doesn't exist. */
-      new_anchor = (kind1 == svn_node_none ? *anchor1 : *anchor2);
-      rev = (kind1 == svn_node_none ? *rev1 : *rev2);
-      do
-        {
-          if (strcmp(new_anchor, repos_root) != 0)
-            {
-              new_anchor = svn_path_uri_decode(svn_uri_dirname(new_anchor,
-                                                               pool),
-                                               pool);
-              if (*base_path)
-                *base_path = svn_dirent_dirname(*base_path, pool);
-            }
 
-          SVN_ERR(svn_ra_reparent(*ra_session, new_anchor, pool));
-          SVN_ERR(svn_ra_check_path(*ra_session, "", rev, &kind, pool));
-
-        }
-      while (kind != svn_node_dir);
-      *anchor1 = *anchor2 = new_anchor;
-      /* Diff targets must be relative to the new anchor. */
-      *target1 = svn_uri_skip_ancestor(new_anchor, *url1, pool);
-      *target2 = svn_uri_skip_ancestor(new_anchor, *url2, pool);
-      SVN_ERR_ASSERT(*target1 && *target2);
-      if (kind1 == svn_node_none)
-        kind1 = svn_node_dir;
-      else
-        kind2 = svn_node_dir;
-    }
-  else if ((kind1 == svn_node_file) || (kind2 == svn_node_file))
+  /* If one of the targets is a file, use the parent directory as anchor. */
+  if (*kind1 == svn_node_file || *kind2 == svn_node_file)
     {
       svn_uri_split(anchor1, target1, *url1, pool);
       svn_uri_split(anchor2, target2, *url2, pool);
@@ -1811,6 +1811,299 @@ diff_wc_wc(const char *path1,
   return SVN_NO_ERROR;
 }
 
+/* Create an array of regular properties in PROP_HASH, filtering entry-props
+ * and wc-props. Allocate the returned array in RESULT_POOL.
+ * Use SCRATCH_POOL for temporary allocations. */
+static apr_array_header_t *
+make_regular_props_array(apr_hash_t *prop_hash,
+                         apr_pool_t *result_pool,
+                         apr_pool_t *scratch_pool)
+{
+  apr_array_header_t *regular_props;
+  apr_hash_index_t *hi;
+
+  regular_props = apr_array_make(result_pool, 0, sizeof(svn_prop_t));
+  for (hi = apr_hash_first(scratch_pool, prop_hash); hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *name = svn__apr_hash_index_key(hi);
+      svn_string_t *value = svn__apr_hash_index_val(hi);
+      svn_prop_kind_t prop_kind = svn_property_kind(NULL, name);
+
+      if (prop_kind == svn_prop_regular_kind)
+        {
+          svn_prop_t *prop = apr_palloc(scratch_pool, sizeof(svn_prop_t));
+
+          prop->name = name;
+          prop->value = value;
+          APR_ARRAY_PUSH(regular_props, svn_prop_t) = *prop;
+        }
+    }
+
+  return regular_props;
+}
+
+/* Create a hash of regular properties from PROP_HASH, filtering entry-props
+ * and wc-props. Allocate the returned hash in RESULT_POOL.
+ * Use SCRATCH_POOL for temporary allocations. */
+static apr_hash_t *
+make_regular_props_hash(apr_hash_t *prop_hash,
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool)
+{
+  apr_hash_t *regular_props;
+  apr_hash_index_t *hi;
+
+  regular_props = apr_hash_make(result_pool);
+  for (hi = apr_hash_first(scratch_pool, prop_hash); hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *name = svn__apr_hash_index_key(hi);
+      svn_string_t *value = svn__apr_hash_index_val(hi);
+      svn_prop_kind_t prop_kind = svn_property_kind(NULL, name);
+
+      if (prop_kind == svn_prop_regular_kind)
+        apr_hash_set(regular_props, name, APR_HASH_KEY_STRING, value);
+    }
+
+  return regular_props;
+}
+
+/* Handle an added or deleted diff target file for a repos<->repos diff.
+ *
+ * Using the provided diff CALLBACKS and the CALLBACK_BATON, show the file
+ * TARGET@PEG_REVISION as added or deleted, depending on SHOW_DELETION.
+ * TARGET is a path relative to RA_SESSION's URL.
+ * REV1 and REV2 are the revisions being compared.
+ * Use SCRATCH_POOL for temporary allocations. */
+static svn_error_t *
+diff_repos_repos_added_or_deleted_file(const char *target,
+                                       svn_revnum_t peg_revision,
+                                       svn_revnum_t rev1,
+                                       svn_revnum_t rev2,
+                                       svn_boolean_t show_deletion,
+                                      const char *empty_file,
+                                       const svn_wc_diff_callbacks4_t
+                                         *callbacks,
+                                       struct diff_cmd_baton *callback_baton,
+                                       svn_ra_session_t *ra_session,
+                                       apr_pool_t *scratch_pool)
+{
+  const char *file_abspath;
+  svn_stream_t *content;
+  apr_hash_t *prop_hash;
+
+  SVN_ERR(svn_stream_open_unique(&content, &file_abspath, NULL,
+                                 svn_io_file_del_on_pool_cleanup,
+                                 scratch_pool, scratch_pool));
+  SVN_ERR(svn_ra_get_file(ra_session, target, peg_revision, content, NULL,
+                          &prop_hash, scratch_pool));
+  SVN_ERR(svn_stream_close(content));
+
+  if (show_deletion)
+    {
+      SVN_ERR(callbacks->file_deleted(NULL, NULL,
+                                      target, file_abspath, empty_file,
+                                      apr_hash_get(prop_hash,
+                                                   SVN_PROP_MIME_TYPE,
+                                                   APR_HASH_KEY_STRING),
+                                      NULL,
+                                      make_regular_props_hash(
+                                        prop_hash, scratch_pool, scratch_pool),
+                                      callback_baton, scratch_pool));
+    }
+  else
+    {
+      SVN_ERR(callbacks->file_added(NULL, NULL, NULL,
+                                    target, empty_file, file_abspath,
+                                    rev1, rev2, NULL,
+                                    apr_hash_get(prop_hash, SVN_PROP_MIME_TYPE,
+                                                 APR_HASH_KEY_STRING),
+                                    NULL, SVN_INVALID_REVNUM,
+                                    make_regular_props_array(prop_hash,
+                                                             scratch_pool,
+                                                             scratch_pool),
+                                    NULL, callback_baton, scratch_pool));
+    }
+    
+  return SVN_NO_ERROR;
+}
+
+/* Handle an added or deleted diff target directory for a repos<->repos diff.
+ *
+ * Using the provided diff CALLBACKS and the CALLBACK_BATON, show the
+ * directory TARGET@PEG_REVISION, and all of its children, as added or deleted,
+ * depending on SHOW_DELETION. TARGET is a path relative to RA_SESSION's URL.
+ * REV1 and REV2 are the revisions being compared.
+ * Use SCRATCH_POOL for temporary allocations. */
+static svn_error_t *
+diff_repos_repos_added_or_deleted_dir(const char *target,
+                                      svn_revnum_t revision,
+                                      svn_revnum_t rev1,
+                                      svn_revnum_t rev2,
+                                      svn_boolean_t show_deletion,
+                                      const char *empty_file,
+                                      const svn_wc_diff_callbacks4_t
+                                        *callbacks,
+                                      struct diff_cmd_baton *callback_baton,
+                                      svn_ra_session_t *ra_session,
+                                      apr_pool_t *scratch_pool)
+{
+  apr_hash_t *dirents;
+  apr_hash_t *props;
+  apr_pool_t *iterpool;
+  apr_hash_index_t *hi;
+
+  SVN_ERR(svn_ra_get_dir2(ra_session, &dirents, NULL, &props,
+                          target, revision, SVN_DIRENT_KIND,
+                          scratch_pool));
+
+  if (show_deletion)
+    SVN_ERR(callbacks->dir_deleted(NULL, NULL, target, callback_baton,
+                                   scratch_pool));
+  else
+    SVN_ERR(callbacks->dir_added(NULL, NULL, NULL, NULL,
+                                 target, revision,
+                                 NULL, SVN_INVALID_REVNUM,
+                                 callback_baton, scratch_pool));
+  if (props)
+    {
+      if (show_deletion)
+        SVN_ERR(callbacks->dir_props_changed(NULL, NULL, target, FALSE,
+                                             apr_array_make(scratch_pool, 0,
+                                                            sizeof(svn_prop_t)),
+                                             make_regular_props_hash(
+                                               props, scratch_pool,
+                                               scratch_pool),
+                                             callback_baton, scratch_pool));
+      else
+        SVN_ERR(callbacks->dir_props_changed(NULL, NULL, target, TRUE,
+                                             make_regular_props_array(
+                                               props, scratch_pool,
+                                               scratch_pool),
+                                             NULL,
+                                             callback_baton, scratch_pool));
+    }
+
+  iterpool = svn_pool_create(scratch_pool);
+  for (hi = apr_hash_first(scratch_pool, dirents); hi; hi = apr_hash_next(hi))
+    {
+      const char *name = svn__apr_hash_index_key(hi);
+      svn_dirent_t *dirent = svn__apr_hash_index_val(hi);
+      const char *child_target;
+
+      svn_pool_clear(iterpool);
+
+      child_target = svn_relpath_join(target, name, iterpool);
+
+      if (dirent->kind == svn_node_dir)
+        SVN_ERR(diff_repos_repos_added_or_deleted_dir(child_target,
+                                                      revision, rev1, rev2,
+                                                      show_deletion,
+                                                      empty_file,
+                                                      callbacks,
+                                                      callback_baton,
+                                                      ra_session,
+                                                      iterpool));
+      else if (dirent->kind == svn_node_file)
+        SVN_ERR(diff_repos_repos_added_or_deleted_file(child_target,
+                                                       revision, rev1, rev2,
+                                                       show_deletion,
+                                                       empty_file,
+                                                       callbacks,
+                                                       callback_baton,
+                                                       ra_session,
+                                                       iterpool));
+    }
+  svn_pool_destroy(iterpool);
+
+  if (!show_deletion)
+    SVN_ERR(callbacks->dir_closed(NULL, NULL, NULL, target, TRUE,
+                                  callback_baton, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+
+/* Handle an added or deleted diff target for a repos<->repos diff.
+ *
+ * Using the provided diff CALLBACKS and the CALLBACK_BATON, show
+ * TARGET@PEG_REVISION, and all of its children, if any, as added or deleted.
+ * TARGET is a path relative to RA_SESSION's URL.
+ * REV1 and REV2 are the revisions being compared.
+ * Use SCRATCH_POOL for temporary allocations. */
+static svn_error_t *
+diff_repos_repos_added_or_deleted_target(const char *target1,
+                                         const char *target2,
+                                         svn_revnum_t rev1,
+                                         svn_revnum_t rev2,
+                                         svn_node_kind_t kind1,
+                                         svn_node_kind_t kind2,
+                                         const svn_wc_diff_callbacks4_t
+                                           *callbacks,
+                                         struct diff_cmd_baton *callback_baton,
+                                         svn_ra_session_t *ra_session,
+                                         apr_pool_t *scratch_pool)
+{
+  const char *existing_target;
+  svn_revnum_t existing_rev;
+  svn_node_kind_t existing_kind;
+  svn_boolean_t show_deletion;
+  const char *empty_file;
+
+  SVN_ERR_ASSERT(kind1 == svn_node_none || kind2 == svn_node_none);
+
+  /* Are we showing an addition or deletion? */
+  show_deletion = (kind2 == svn_node_none);
+
+  /* Which target is being added/deleted? Is it a file or a directory? */
+  if (show_deletion)
+    {
+      existing_target = target1;
+      existing_rev = rev1;
+      existing_kind = kind1;
+    }
+  else
+    {
+      existing_target = target2;
+      existing_rev = rev2;
+      existing_kind = kind2;
+    }
+
+  /* All file content will be diffed against the empty file. */
+  SVN_ERR(svn_io_open_unique_file3(NULL, &empty_file, NULL,
+                                   svn_io_file_del_on_pool_cleanup,
+                                   scratch_pool, scratch_pool));
+
+  if (existing_kind == svn_node_file)
+    {
+      /* Get file content and show a diff against the empty file. */
+      SVN_ERR(diff_repos_repos_added_or_deleted_file(existing_target,
+                                                     existing_rev,
+                                                     rev1, rev2,
+                                                     show_deletion,
+                                                     empty_file,
+                                                     callbacks,
+                                                     callback_baton,
+                                                     ra_session,
+                                                     scratch_pool));
+    }
+  else
+    {
+      /* Walk the added/deleted tree and show a diff for each child. */
+      SVN_ERR(diff_repos_repos_added_or_deleted_dir(existing_target,
+                                                    existing_rev,
+                                                    rev1, rev2,
+                                                    show_deletion,
+                                                    empty_file,
+                                                    callbacks,
+                                                    callback_baton,
+                                                    ra_session,
+                                                    scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
 
 /* Perform a diff between two repository paths.
 
@@ -1847,6 +2140,8 @@ diff_repos_repos(const svn_wc_diff_callb
   const char *base_path;
   svn_revnum_t rev1;
   svn_revnum_t rev2;
+  svn_node_kind_t kind1;
+  svn_node_kind_t kind2;
   const char *anchor1;
   const char *anchor2;
   const char *target1;
@@ -1856,7 +2151,8 @@ diff_repos_repos(const svn_wc_diff_callb
   /* Prepare info for the repos repos diff. */
   SVN_ERR(diff_prepare_repos_repos(&url1, &url2, &base_path, &rev1, &rev2,
                                    &anchor1, &anchor2, &target1, &target2,
-                                   &ra_session, ctx, path1, path2,
+                                   &kind1, &kind2, &ra_session,
+                                   ctx, path1, path2,
                                    revision1, revision2, peg_revision,
                                    pool));
 
@@ -1871,6 +2167,21 @@ diff_repos_repos(const svn_wc_diff_callb
   callback_baton->ra_session = ra_session;
   callback_baton->anchor = base_path;
 
+  if (kind1 == svn_node_none || kind2 == svn_node_none)
+    {
+      /* One side of the diff does not exist.
+       * Walk the tree that does exist, showing a series of additions
+       * or deletions. */
+      SVN_ERR(diff_repos_repos_added_or_deleted_target(target1, target2,
+                                                       rev1, rev2,
+                                                       kind1, kind2,
+                                                       callbacks,
+                                                       callback_baton,
+                                                       ra_session,
+                                                       pool));
+      return SVN_NO_ERROR;
+    }
+
   /* Now, we open an extra RA session to the correct anchor
      location for URL1.  This is used during the editor calls to fetch file
      contents.  */
@@ -1904,6 +2215,195 @@ diff_repos_repos(const svn_wc_diff_callb
 }
 
 
+/* Using CALLBACKS, show a REPOS->WC diff for a file TARGET, which in the
+ * working copy is at FILE2_ABSPATH. KIND1 is the node kind of the repository
+ * target (either svn_node_file or svn_node_none). REV is the revision the
+ * working file is diffed against. RA_SESSION points at the URL of the file
+ * in the repository and is used to get the file's repository-version content,
+ * if necessary. If DIFF_WITH_BASE is set, diff against the BASE version of
+ * the local file instead of WORKING.
+ * The other parameters are as in diff_repos_wc(). */
+static svn_error_t *
+diff_repos_wc_file_target(const char *target,
+                          const char *file2_abspath,
+                          svn_node_kind_t kind1,
+                          svn_revnum_t rev,
+                          svn_boolean_t reverse,
+                          svn_boolean_t show_copies_as_adds,
+                          svn_boolean_t diff_with_base,
+                          const svn_wc_diff_callbacks4_t *callbacks,
+                          void *callback_baton,
+                          svn_ra_session_t *ra_session,
+                          svn_client_ctx_t *ctx,
+                          apr_pool_t *scratch_pool)
+{
+  const char *file1_abspath;
+  svn_stream_t *file1_content;
+  svn_stream_t *file2_content;
+  apr_hash_t *file1_props = NULL;
+  apr_hash_t *file2_props;
+  svn_boolean_t is_copy = FALSE;
+
+  /* Get content and props of file 1 (the remote file). */
+  SVN_ERR(svn_stream_open_unique(&file1_content, &file1_abspath, NULL,
+                                 svn_io_file_del_on_pool_cleanup,
+                                 scratch_pool, scratch_pool));
+  if (kind1 == svn_node_file)
+    {
+      if (show_copies_as_adds)
+        SVN_ERR(svn_wc__node_get_origin(&is_copy, 
+                                        NULL, NULL, NULL, NULL, NULL,
+                                        ctx->wc_ctx, file2_abspath,
+                                        FALSE, scratch_pool, scratch_pool));
+      /* If showing copies as adds, diff against the empty file. */
+      if (!(show_copies_as_adds && is_copy))
+        SVN_ERR(svn_ra_get_file(ra_session, "", rev, file1_content,
+                                NULL, &file1_props, scratch_pool));
+    }
+
+  SVN_ERR(svn_stream_close(file1_content));
+
+  /* Get content and props of file 2 (the local file). */
+  if (diff_with_base)
+    {
+      svn_stream_t *pristine_content;
+
+      SVN_ERR(svn_wc_get_pristine_props(&file2_props, ctx->wc_ctx,
+                                        file2_abspath, scratch_pool,
+                                        scratch_pool));
+
+      /* ### We need a filename, but this API returns an opaque stream.
+       * ### This requires us to copy to a temporary file. Maybe libsvn_wc
+       * ### should also provide an API that returns a path to a file that
+       * ### contains pristine content, possibly temporary? */
+      SVN_ERR(svn_wc_get_pristine_contents2(&pristine_content,
+                                            ctx->wc_ctx,
+                                            file2_abspath,
+                                            scratch_pool, scratch_pool));
+
+      SVN_ERR(svn_stream_open_unique(&file2_content, &file2_abspath, NULL,
+                                     svn_io_file_del_on_pool_cleanup,
+                                     scratch_pool, scratch_pool));
+      SVN_ERR(svn_stream_copy3(pristine_content, file2_content,
+                               ctx->cancel_func, ctx->cancel_baton,
+                               scratch_pool));
+    }
+  else
+    {
+      apr_hash_t *keywords = NULL;
+      svn_string_t *keywords_prop;
+      svn_subst_eol_style_t eol_style;
+      const char *eol_str;
+
+      SVN_ERR(svn_wc_prop_list2(&file2_props, ctx->wc_ctx, file2_abspath,
+                                scratch_pool, scratch_pool));
+
+      /* We might have to create a normalised version of the working file. */
+      svn_subst_eol_style_from_value(&eol_style, &eol_str,
+                                     apr_hash_get(file2_props,
+                                                  SVN_PROP_EOL_STYLE,
+                                                  APR_HASH_KEY_STRING));
+      keywords_prop = apr_hash_get(file2_props, SVN_PROP_KEYWORDS,
+                                   APR_HASH_KEY_STRING);
+      if (keywords_prop)
+        SVN_ERR(svn_subst_build_keywords2(&keywords, keywords_prop->data,
+                                          NULL, NULL, 0, NULL,
+                                          scratch_pool));
+      if (svn_subst_translation_required(eol_style, SVN_SUBST_NATIVE_EOL_STR,
+                                         keywords, FALSE, TRUE))
+        {
+          svn_stream_t *working_content;
+          svn_stream_t *normalized_content;
+
+          SVN_ERR(svn_stream_open_readonly(&working_content, file2_abspath,
+                                           scratch_pool, scratch_pool));
+
+          /* Create a temporary file and copy normalised data into it. */
+          SVN_ERR(svn_stream_open_unique(&file2_content, &file2_abspath, NULL,
+                                         svn_io_file_del_on_pool_cleanup,
+                                         scratch_pool, scratch_pool));
+          normalized_content = svn_subst_stream_translated(
+                                 file2_content, SVN_SUBST_NATIVE_EOL_STR,
+                                 TRUE, keywords, FALSE, scratch_pool);
+          SVN_ERR(svn_stream_copy3(working_content, normalized_content,
+                                   ctx->cancel_func, ctx->cancel_baton,
+                                   scratch_pool));
+        }
+    }
+
+  if (kind1 == svn_node_file && !(show_copies_as_adds && is_copy))
+    {
+      SVN_ERR(callbacks->file_opened(NULL, NULL, target,
+                                     reverse ? SVN_INVALID_REVNUM : rev,
+                                     callback_baton, scratch_pool));
+
+      if (reverse)
+        SVN_ERR(callbacks->file_changed(NULL, NULL, NULL, target,
+                                        file2_abspath, file1_abspath,
+                                        SVN_INVALID_REVNUM, rev,
+                                        apr_hash_get(file2_props,
+                                                     SVN_PROP_MIME_TYPE,
+                                                     APR_HASH_KEY_STRING),
+                                        apr_hash_get(file1_props,
+                                                     SVN_PROP_MIME_TYPE,
+                                                     APR_HASH_KEY_STRING),
+                                        make_regular_props_array(
+                                          file1_props, scratch_pool,
+                                          scratch_pool),
+                                        file2_props,
+                                        callback_baton, scratch_pool));
+      else
+        SVN_ERR(callbacks->file_changed(NULL, NULL, NULL, target,
+                                        file1_abspath, file2_abspath,
+                                        rev, SVN_INVALID_REVNUM,
+                                        apr_hash_get(file1_props,
+                                                     SVN_PROP_MIME_TYPE,
+                                                     APR_HASH_KEY_STRING),
+                                        apr_hash_get(file2_props,
+                                                     SVN_PROP_MIME_TYPE,
+                                                     APR_HASH_KEY_STRING),
+                                        make_regular_props_array(
+                                          file2_props, scratch_pool,
+                                          scratch_pool),
+                                        file1_props,
+                                        callback_baton, scratch_pool));
+    }
+  else
+    {
+      if (reverse)
+        {
+          SVN_ERR(callbacks->file_deleted(NULL, NULL,
+                                          target, file2_abspath, file1_abspath,
+                                          apr_hash_get(file2_props,
+                                                       SVN_PROP_MIME_TYPE,
+                                                       APR_HASH_KEY_STRING),
+                                          NULL,
+                                          make_regular_props_hash(
+                                            file2_props, scratch_pool,
+                                            scratch_pool),
+                                          callback_baton, scratch_pool));
+        }
+      else
+        {
+          SVN_ERR(callbacks->file_added(NULL, NULL, NULL, target,
+                                        file1_abspath, file2_abspath,
+                                        rev, SVN_INVALID_REVNUM,
+                                        NULL,
+                                        apr_hash_get(file2_props,
+                                                     SVN_PROP_MIME_TYPE,
+                                                     APR_HASH_KEY_STRING),
+                                        NULL, SVN_INVALID_REVNUM,
+                                        make_regular_props_array(
+                                          file2_props, scratch_pool,
+                                          scratch_pool),
+                                        NULL,
+                                        callback_baton, scratch_pool));
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /* Perform a diff between a repository path and a working-copy path.
 
    PATH1 may be either a URL or a working copy path.  PATH2 is a
@@ -1944,6 +2444,8 @@ diff_repos_wc(const char *path1,
   const char *abspath1;
   const char *abspath2;
   const char *anchor_abspath;
+  svn_node_kind_t kind1;
+  svn_node_kind_t kind2;
 
   SVN_ERR_ASSERT(! svn_path_is_url(path2));
 
@@ -2000,22 +2502,53 @@ diff_repos_wc(const char *path1,
         }
     }
 
-  /* Establish RA session to path2's anchor */
-  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, anchor_url,
-                                               NULL, NULL, FALSE, TRUE,
-                                               ctx, pool));
-  callback_baton->ra_session = ra_session;
   if (use_git_diff_format)
     {
       SVN_ERR(svn_wc__get_wc_root(&callback_baton->wc_root_abspath,
                                   ctx->wc_ctx, anchor_abspath,
                                   pool, pool));
     }
+
+  /* Open an RA session to URL1 to figure out its node kind. */
+  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, url1,
+                                               NULL, NULL, FALSE, TRUE,
+                                               ctx, pool));
+  /* Resolve the revision to use for URL1. */
+  SVN_ERR(svn_client__get_revision_number(&rev, NULL, ctx->wc_ctx,
+                                          (strcmp(path1, url1) == 0)
+                                                    ? NULL : abspath1,
+                                          ra_session, revision1, pool));
+  SVN_ERR(svn_ra_check_path(ra_session, "", rev, &kind1, pool));
+
+  /* Figure out the node kind of the local target. */
+  SVN_ERR(svn_io_check_resolved_path(abspath2, &kind2, pool));
+
+  callback_baton->ra_session = ra_session;
   callback_baton->anchor = anchor;
 
+  if (!reverse)
+    callback_baton->revnum1 = rev;
+  else
+    callback_baton->revnum2 = rev;
+
+  /* If both diff targets can be diffed as files, fetch the file from the
+   * repository and generate a diff against the local version of the file. */
+  if ((kind1 == svn_node_file || kind1 == svn_node_none)
+       && kind2 == svn_node_file)
+    {
+      SVN_ERR(diff_repos_wc_file_target(target, abspath2, kind1, rev,
+                                        reverse, show_copies_as_adds,
+                                        rev2_is_base,
+                                        callbacks, callback_baton,
+                                        ra_session, ctx, pool));
+
+      return SVN_NO_ERROR;
+    }
+
+  /* Else, use the diff editor to generate the diff. */
+  SVN_ERR(svn_ra_reparent(ra_session, anchor_url, pool));
   SVN_ERR(svn_ra_has_capability(ra_session, &server_supports_depth,
                                 SVN_RA_CAPABILITY_DEPTH, pool));
-
   SVN_ERR(svn_wc_get_diff_editor6(&diff_editor, &diff_edit_baton,
                                   ctx->wc_ctx,
                                   anchor_abspath,
@@ -2032,22 +2565,12 @@ diff_repos_wc(const char *path1,
                                   ctx->cancel_func, ctx->cancel_baton,
                                   pool, pool));
 
-  /* Tell the RA layer we want a delta to change our txn to URL1 */
-  SVN_ERR(svn_client__get_revision_number(&rev, NULL, ctx->wc_ctx,
-                                          (strcmp(path1, url1) == 0)
-                                                    ? NULL : abspath1,
-                                          ra_session, revision1, pool));
-
-  if (!reverse)
-    callback_baton->revnum1 = rev;
-  else
-    callback_baton->revnum2 = rev;
-
   if (depth != svn_depth_infinity)
     diff_depth = depth;
   else
     diff_depth = svn_depth_unknown;
 
+  /* Tell the RA layer we want a delta to change our txn to URL1 */ 
   SVN_ERR(svn_ra_do_diff3(ra_session,
                           &reporter, &reporter_baton,
                           rev,
@@ -2136,6 +2659,7 @@ do_diff(const svn_wc_diff_callbacks4_t *
   return SVN_NO_ERROR;
 }
 
+
 /* Perform a diff summary between two repository paths. */
 static svn_error_t *
 diff_summarize_repos_repos(svn_client_diff_summarize_func_t summarize_func,
@@ -2163,6 +2687,8 @@ diff_summarize_repos_repos(svn_client_di
   const char *base_path;
   svn_revnum_t rev1;
   svn_revnum_t rev2;
+  svn_node_kind_t kind1;
+  svn_node_kind_t kind2;
   const char *anchor1;
   const char *anchor2;
   const char *target1;
@@ -2172,10 +2698,32 @@ diff_summarize_repos_repos(svn_client_di
   /* Prepare info for the repos repos diff. */
   SVN_ERR(diff_prepare_repos_repos(&url1, &url2, &base_path, &rev1, &rev2,
                                    &anchor1, &anchor2, &target1, &target2,
-                                   &ra_session, ctx,
-                                   path1, path2, revision1, revision2,
+                                   &kind1, &kind2, &ra_session,
+                                   ctx, path1, path2,
+                                   revision1, revision2,
                                    peg_revision, pool));
 
+  if (kind1 == svn_node_none || kind2 == svn_node_none)
+    {
+      svn_wc_diff_callbacks4_t *callbacks;
+      void *callback_baton;
+
+      /* One side of the diff does not exist.
+       * Walk the tree that does exist, showing a series of additions
+       * or deletions. */
+      SVN_ERR(svn_client__get_diff_summarize_callbacks(
+                &callbacks, &callback_baton, target1,
+                summarize_func, summarize_baton, pool));
+      SVN_ERR(diff_repos_repos_added_or_deleted_target(target1, target2,
+                                                       rev1, rev2,
+                                                       kind1, kind2,
+                                                       callbacks,
+                                                       callback_baton,
+                                                       ra_session,
+                                                       pool));
+      return SVN_NO_ERROR;
+    }
+
   /* Now, we open an extra RA session to the correct anchor
      location for URL1.  This is used to get the kind of deleted paths.  */
   SVN_ERR(svn_client__open_ra_session_internal(&extra_ra_session, NULL,

Propchange: subversion/branches/1.7.x/subversion/libsvn_fs_fs/temp_serializer.c
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-issue4153/subversion/libsvn_fs_fs/temp_serializer.c:r1309894-1539233

Propchange: subversion/branches/1.7.x/subversion/libsvn_fs_fs/temp_serializer.h
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-issue4153/subversion/libsvn_fs_fs/temp_serializer.h:r1309894-1539233

Propchange: subversion/branches/1.7.x/subversion/libsvn_subr/adler32.c
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-issue4153/subversion/libsvn_subr/adler32.c:r1309894-1539233

Propchange: subversion/branches/1.7.x/subversion/libsvn_subr/hash.c
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-issue4153/subversion/libsvn_subr/hash.c:r1309894-1539233

Propchange: subversion/branches/1.7.x/subversion/libsvn_subr/svn_base64.c
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-issue4153/subversion/libsvn_subr/svn_base64.c:r1309894-1539233

Propchange: subversion/branches/1.7.x/subversion/libsvn_subr/svn_cache_config.c
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-r1507044/subversion/libsvn_subr/svn_cache_config.c:r1507300-1511568
  Merged /subversion/branches/1.7.x-r1407131/subversion/libsvn_subr/svn_cache_config.c:r1407164-1419607
  Merged /subversion/branches/1.7.x-r1401915/subversion/libsvn_subr/svn_cache_config.c:r1401934-1407349
  Merged /subversion/branches/1.7.x-issue4263/subversion/libsvn_subr/svn_cache_config.c:r1423588-1434547
  Merged /subversion/branches/1.7.x-gssapi-solaris10/subversion/libsvn_subr/svn_cache_config.c:r1453164-1515067
  Merged /subversion/branches/1.7.x-issue4408/subversion/libsvn_subr/svn_cache_config.c:r1512143-1514943
  Merged /subversion/branches/1.7.x-issue4257/subversion/libsvn_subr/svn_cache_config.c:r1454456-1461404
  Merged /subversion/branches/1.7.x-r1482759/subversion/libsvn_subr/svn_cache_config.c:r1483584-1485046
  Merged /subversion/branches/1.7.x-r1481010/subversion/libsvn_subr/svn_cache_config.c:r1481034-1482194
  Merged /subversion/branches/1.7.x-r1352031/subversion/libsvn_subr/svn_cache_config.c:r1431725-1435017
  Merged /subversion/trunk/subversion/libsvn_subr/svn_cache_config.c:r1164116,1230798,1237779,1295418,1306275,1309865,1338291,1338297,1338314,1338688,1338708,1338713,1338739,1338748,1339159,1341544,1341560,1345740,1352031,1390653,1394519,1398100,1399174,1401915,1402417,1402421,1403258,1403583,1403588,1403691,1403964,1403982,1405922,1407131,1407812,1408650,1409146,1409939,1410106,1410203,1419670-1419681,1421011,1421103,1421380,1421541,1422053,1422100,1423585,1423837,1423840,1423848,1424977,1425368,1426138,1426264,1426752,1426830,1427197,1427210,1427278,1429201,1434128,1434405,1434414,1434418,1434435,1434476,1434750,1435361,1438602,1438683,1441810,1443763,1443929,1445753,1451678,1452617,1452780,1452967,1453780,1454088,1454217,1455352,1458341,1459599,1461278,1461562,1461580,1461701,1461743,1462293,1462300,1462302,1462321,1462334,1465975,1476359,1477730,1481010,1481627,1482282,1483781,1485350,1490684,1503528,1507044,1512432,1512471-1512472,1513463,1513472,1514763,1515119,1515237,1515992,
 1515997,1516023-1516024,1516051-1516052,1516565
  Merged /subversion/branches/1.7.x-r1427278/subversion/libsvn_subr/svn_cache_config.c:r1433724-1485338
  Merged /subversion/branches/1.7.x-r1475724/subversion/libsvn_subr/svn_cache_config.c:r1475743-1482192
  Merged /subversion/branches/1.7.x-issue4270/subversion/libsvn_subr/svn_cache_config.c:r1433737-1485341
  Merged /subversion/branches/1.7.x-r1399174/subversion/libsvn_subr/svn_cache_config.c:r1399176-1403964
  Merged /subversion/branches/1.7.x-neon-properr/subversion/libsvn_subr/svn_cache_config.c:r1440619-1461944
  Merged /subversion/branches/1.7.x-r1461743/subversion/libsvn_subr/svn_cache_config.c:r1461745-1482189
  Merged /subversion/branches/1.7.x-issue4306/subversion/libsvn_subr/svn_cache_config.c:r1438872-1514941
  Merged /subversion/branches/1.7.x-issue4332/subversion/libsvn_subr/svn_cache_config.c:r1453478-1460963
  Merged /subversion/branches/1.7.x-issue4340/subversion/libsvn_subr/svn_cache_config.c:r1461589-1485180
  Merged /subversion/branches/1.7.x-issue4153/subversion/libsvn_subr/svn_cache_config.c:r1309894-1539233
  Merged /subversion/branches/1.7.x-r1426752/subversion/libsvn_subr/svn_cache_config.c:r1426753-1485335

Propchange: subversion/branches/1.7.x/subversion/libsvn_subr/svn_temp_serializer.c
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-issue4153/subversion/libsvn_subr/svn_temp_serializer.c:r1309894-1539233

Propchange: subversion/branches/1.7.x/subversion/svn/main.c
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-r1426752/subversion/svn/main.c:r1426753-1485335
  Merged /subversion/trunk/subversion/svn/main.c:r1164116,1230798,1306275,1309865,1338291,1338297,1338314,1338688,1338708,1338713,1338739,1338748,1339159,1341544,1341560,1405922,1421541,1423837,1423840,1423848,1424977,1426752,1426830,1427197,1427210,1427278,1434128,1434405,1434414,1434418,1434435,1434476,1434750,1438602,1438683,1441810,1445753,1451678,1452617,1452780,1461562,1461580,1461701,1461743,1465975,1476359,1477730,1481010,1481627,1482282,1483781,1485350,1490684,1503528,1507044,1512432,1512471-1512472,1513463,1513472,1514763,1515119,1515237,1515992,1515997,1516023-1516024,1516051-1516052,1516565
  Merged /subversion/branches/1.7.x-issue4306/subversion/svn/main.c:r1438872-1514941
  Merged /subversion/branches/1.7.x-r1461743/subversion/svn/main.c:r1461745-1482189
  Merged /subversion/branches/1.7.x-r1481010/subversion/svn/main.c:r1481034-1482194
  Merged /subversion/branches/1.7.x-issue4340/subversion/svn/main.c:r1461589-1485180
  Merged /subversion/branches/1.7.x-r1427278/subversion/svn/main.c:r1433724-1485338
  Merged /subversion/branches/1.7.x-r1507044/subversion/svn/main.c:r1507300-1511568
  Merged /subversion/branches/1.7.x-issue4270/subversion/svn/main.c:r1433737-1485341
  Merged /subversion/branches/1.7.x-r1482759/subversion/svn/main.c:r1483584-1485046
  Merged /subversion/branches/1.7.x-issue4408/subversion/svn/main.c:r1512143-1514943
  Merged /subversion/branches/1.7.x-issue4153/subversion/svn/main.c:r1309894-1539233
  Merged /subversion/branches/1.7.x-gssapi-solaris10/subversion/svn/main.c:r1453164-1515067

Propchange: subversion/branches/1.7.x/subversion/svnserve/main.c
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-issue4340/subversion/svnserve/main.c:r1461589-1485180
  Merged /subversion/branches/1.7.x-r1399174/subversion/svnserve/main.c:r1399176-1403964
  Merged /subversion/branches/1.7.x-issue4270/subversion/svnserve/main.c:r1433737-1485341
  Merged /subversion/branches/1.7.x-issue4408/subversion/svnserve/main.c:r1512143-1514943
  Merged /subversion/branches/1.7.x-r1426752/subversion/svnserve/main.c:r1426753-1485335
  Merged /subversion/branches/1.7.x-issue4263/subversion/svnserve/main.c:r1423588-1434547
  Merged /subversion/branches/1.7.x-neon-properr/subversion/svnserve/main.c:r1440619-1461944
  Merged /subversion/branches/1.7.x-issue4257/subversion/svnserve/main.c:r1454456-1461404
  Merged /subversion/branches/1.7.x-r1427278/subversion/svnserve/main.c:r1433724-1485338
  Merged /subversion/trunk/subversion/svnserve/main.c:r1164116,1230798,1237779,1295418,1306275,1309865,1338291,1338297,1338314,1338688,1338708,1338713,1338739,1338748,1339159,1341544,1341560,1345740,1352031,1390653,1394519,1398100,1399174,1401915,1402417,1402421,1403258,1403583,1403588,1403691,1403964,1403982,1405922,1407131,1407812,1408650,1409146,1409939,1410106,1410203,1419670-1419681,1421011,1421103,1421380,1421541,1422053,1422100,1423585,1423837,1423840,1423848,1424977,1425368,1426138,1426264,1426752,1426830,1427197,1427210,1427278,1429201,1434128,1434405,1434414,1434418,1434435,1434476,1434750,1435361,1438602,1438683,1441810,1443763,1443929,1445753,1451678,1452617,1452780,1452967,1453780,1454088,1454217,1455352,1458341,1459599,1461278,1461562,1461580,1461701,1461743,1462293,1462300,1462302,1462321,1462334,1465975,1476359,1477730,1481010,1481627,1482282,1483781,1485350,1490684,1503528,1507044,1512432,1512471-1512472,1513463,1513472,1514763,1515119,1515237,1515992,1515997,1516023
 -1516024,1516051-1516052,1516565
  Merged /subversion/branches/1.7.x-r1352031/subversion/svnserve/main.c:r1431725-1435017
  Merged /subversion/branches/1.7.x-r1401915/subversion/svnserve/main.c:r1401934-1407349
  Merged /subversion/branches/1.7.x-issue4306/subversion/svnserve/main.c:r1438872-1514941
  Merged /subversion/branches/1.7.x-r1475724/subversion/svnserve/main.c:r1475743-1482192
  Merged /subversion/branches/1.7.x-gssapi-solaris10/subversion/svnserve/main.c:r1453164-1515067
  Merged /subversion/branches/1.7.x-r1507044/subversion/svnserve/main.c:r1507300-1511568
  Merged /subversion/branches/1.7.x-r1461743/subversion/svnserve/main.c:r1461745-1482189
  Merged /subversion/branches/1.7.x-issue4153/subversion/svnserve/main.c:r1309894-1539233
  Merged /subversion/branches/1.7.x-issue4332/subversion/svnserve/main.c:r1453478-1460963
  Merged /subversion/branches/1.7.x-r1407131/subversion/svnserve/main.c:r1407164-1419607

Propchange: subversion/branches/1.7.x/subversion/tests/cmdline/basic_tests.py
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-issue4153/subversion/tests/cmdline/basic_tests.py:r1309894-1539233

Modified: subversion/branches/1.7.x/subversion/tests/cmdline/diff_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/tests/cmdline/diff_tests.py?rev=1539234&r1=1539233&r2=1539234&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/tests/cmdline/diff_tests.py (original)
+++ subversion/branches/1.7.x/subversion/tests/cmdline/diff_tests.py Wed Nov  6 04:02:38 2013
@@ -1580,7 +1580,6 @@ def check_for_omitted_prefix_in_path_com
     raise svntest.Failure
 
 #----------------------------------------------------------------------
-@XFail()
 def diff_renamed_file(sbox):
   "diff a file that has been renamed"
 
@@ -2574,6 +2573,52 @@ def basic_diff_summarize(sbox):
   wc_dir = sbox.wc_dir
   p = sbox.ospath
 
+  # Diff summarize of a newly added file
+  expected_diff = svntest.wc.State(wc_dir, {
+    'iota': Item(status='A '),
+    })
+  svntest.actions.run_and_verify_diff_summarize(expected_diff,
+                                                p('iota'), '-c1')
+
+  # Reverse summarize diff of a newly added file
+  expected_diff = svntest.wc.State(wc_dir, {
+    'iota': Item(status='D '),
+    })
+  svntest.actions.run_and_verify_diff_summarize(expected_diff,
+                                                p('iota'), '-c-1')
+
+  # Diff summarize of a newly added directory
+  expected_diff = svntest.wc.State(wc_dir, {
+    'A/D':          Item(status='A '),
+    'A/D/gamma':    Item(status='A '),
+    'A/D/H':        Item(status='A '),
+    'A/D/H/chi':    Item(status='A '),
+    'A/D/H/psi':    Item(status='A '),
+    'A/D/H/omega':  Item(status='A '),
+    'A/D/G':        Item(status='A '),
+    'A/D/G/pi':     Item(status='A '),
+    'A/D/G/rho':    Item(status='A '),
+    'A/D/G/tau':    Item(status='A '),
+    })
+  svntest.actions.run_and_verify_diff_summarize(expected_diff,
+                                                p('A/D'), '-c1')
+
+  # Reverse summarize diff of a newly added directory
+  expected_diff = svntest.wc.State(wc_dir, {
+    'A/D':          Item(status='D '),
+    'A/D/gamma':    Item(status='D '),
+    'A/D/H':        Item(status='D '),
+    'A/D/H/chi':    Item(status='D '),
+    'A/D/H/psi':    Item(status='D '),
+    'A/D/H/omega':  Item(status='D '),
+    'A/D/G':        Item(status='D '),
+    'A/D/G/pi':     Item(status='D '),
+    'A/D/G/rho':    Item(status='D '),
+    'A/D/G/tau':    Item(status='D '),
+    })
+  svntest.actions.run_and_verify_diff_summarize(expected_diff,
+                                                p('A/D'), '-c-1')
+
   # Add props to some items that will be deleted, and commit.
   sbox.simple_propset('prop', 'val',
                       'A/C',
@@ -2677,29 +2722,19 @@ def basic_diff_summarize(sbox):
   svntest.actions.run_and_verify_diff_summarize(expected_reverse_diff,
                                                 wc_dir, '-c-3')
 
-  # Get the differences between a newly added file 
+  # Get the differences between a deep newly added dir Issue(4421)
   expected_diff = svntest.wc.State(wc_dir, {
-    'newfile': Item(status='A '),
+    'Q/R'         : Item(status='A '),
+    'Q/R/newfile' : Item(status='A '),
     })
   expected_reverse_diff = svntest.wc.State(wc_dir, {
-    'newfile': Item(status='D '),
+    'Q/R'         : Item(status='D '),
+    'Q/R/newfile' : Item(status='D '),
     })
   svntest.actions.run_and_verify_diff_summarize(expected_diff,
-                                                p('newfile'), '-c3')
+                                                p('Q/R'), '-c3')
   svntest.actions.run_and_verify_diff_summarize(expected_reverse_diff,
-                                                p('newfile'), '-c-3')
-
-  # Get the differences between a newly added dir 
-  expected_diff = svntest.wc.State(wc_dir, {
-    'P': Item(status='A '),
-    })
-  expected_reverse_diff = svntest.wc.State(wc_dir, {
-    'P': Item(status='D '),
-    })
-  svntest.actions.run_and_verify_diff_summarize(expected_diff,
-                                                p('P'), '-c3')
-  svntest.actions.run_and_verify_diff_summarize(expected_reverse_diff,
-                                                p('P'), '-c-3')
+                                                p('Q/R'), '-c-3')
 
 #----------------------------------------------------------------------
 def diff_weird_author(sbox):
@@ -3803,6 +3838,35 @@ def no_spurious_conflict(sbox):
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
 
+def diff_deleted_url(sbox):
+  "diff -cN of URL deleted in rN"
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  # remove A/D/H in r2
+  sbox.simple_rm("A/D/H")
+  sbox.simple_commit()
+
+  # A diff of r2 with target A/D/H should show the removed children
+  expected_output = make_diff_header("chi", "revision 1", "revision 2") + [
+                      "@@ -1 +0,0 @@\n",
+                      "-This is the file 'chi'.\n",
+                    ] + make_diff_header("omega", "revision 1",
+                                         "revision 2") + [
+                      "@@ -1 +0,0 @@\n",
+                      "-This is the file 'omega'.\n",
+                    ] + make_diff_header("psi", "revision 1",
+                                         "revision 2") + [
+                      "@@ -1 +0,0 @@\n",
+                      "-This is the file 'psi'.\n",
+                    ]
+
+  # Files in diff may be in any order.
+  expected_output = svntest.verify.UnorderedOutput(expected_output)
+  svntest.actions.run_and_verify_svn(None, expected_output, [],
+                                     'diff', '-c2',
+                                     sbox.repo_url + '/A/D/H')
+
 ########################################################################
 #Run the tests
 
@@ -3869,6 +3933,7 @@ test_list = [ None,
               diff_git_with_props_on_dir,
               diff_abs_localpath_from_wc_folder,
               no_spurious_conflict,
+              diff_deleted_url,
               diff_git_format_wc_wc_dir_mv,
               ]
 

Modified: subversion/branches/1.7.x/subversion/tests/cmdline/log_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/tests/cmdline/log_tests.py?rev=1539234&r1=1539233&r2=1539234&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/tests/cmdline/log_tests.py (original)
+++ subversion/branches/1.7.x/subversion/tests/cmdline/log_tests.py Wed Nov  6 04:02:38 2013
@@ -697,6 +697,42 @@ def check_log_chain(chain, revlist, path
                             missing_revs, chain)
 
 
+def parse_diff(output):
+  """Return a set containing the various diff bits, broken up by file."""
+
+  diff_set = []
+  current_diff = []
+  for line in output:
+    if line.startswith('Index: ') and current_diff:
+      diff_set.append(current_diff)
+      current_diff = []
+    current_diff.append(line)
+  diff_set.append(current_diff)
+
+  return diff_set
+
+
+def setify(diff_list):
+  """Take a list of lists and make it a set of tuples."""
+  s = set()
+  for diff in diff_list:
+    s.add(tuple(diff))
+  return s
+
+
+def compare_diff_output(expected_diffs, output):
+  """Compare the diffs in EXPECTED_DIFFS (which is a Python set) with the
+  text in OUTPUT, remembering that there is no canonical ordering for diffs."""
+
+  diffs = parse_diff(output)
+  diffs = setify(diffs)
+  expected_diffs = setify(expected_diffs)
+
+  if diffs.issubset(expected_diffs) and diffs.issuperset(expected_diffs):
+    return
+
+  raise svntest.Failure("Diffs not equal")
+
 
 ######################################################################
 # Tests
@@ -2081,26 +2117,97 @@ def log_diff(sbox):
                                                               '-r10:8', 'A2')
   os.chdir(was_cwd)
 
-  r9diff = make_no_diff_deleted_header('A2/B/E/alpha', 8, 9) \
-           + make_diff_header('A2/B/E/beta', 'revision 8', 'revision 9') \
-           + [ "@@ -1 +1,2 @@\n",
-               " This is the file 'beta'.\n",
-               "+9\n",
-               "\ No newline at end of file\n",
-             ]
-  r8diff = make_diff_header('A2/D/G/rho', 'revision 0', 'revision 8') \
-           + [ "@@ -0,0 +1 @@\n",
-               "+88\n",
-               "\ No newline at end of file\n",
-             ]
+  r9diff = [ make_no_diff_deleted_header('A2/B/E/alpha', 8, 9),
+              make_diff_header('A2/B/E/beta', 'revision 8', 'revision 9')
+               + [ "@@ -1 +1,2 @@\n",
+                   " This is the file 'beta'.\n",
+                   "+9\n",
+                   "\ No newline at end of file\n",
+                 ]
+           ]
+  r8diff = [ make_diff_header('A2/D/G/rho', 'revision 0', 'revision 8')
+              + [ "@@ -0,0 +1 @@\n",
+                  "+88\n",
+                  "\ No newline at end of file\n",
+                ]
+           ]
   log_chain = parse_log_output(output, with_diffs=True)
   if len(log_chain) != 3:
     raise SVNLogParseError("%d logs found, 3 expected" % len(log_chain))
-  svntest.verify.compare_and_display_lines(None, "diff for r9",
-                                           r9diff, log_chain[1]['diff_lines'])
-  svntest.verify.compare_and_display_lines(None, "diff for r8",
-                                           r8diff, log_chain[2]['diff_lines'])
+  compare_diff_output(r9diff, log_chain[1]['diff_lines'])
+  compare_diff_output(r8diff, log_chain[2]['diff_lines'])
+
+
+@Issue(4153)
+def log_diff_moved(sbox):
+  "log --diff on moved file"
 
+  sbox.build()
+
+  sbox.simple_move('A/mu', 'A/mu2')
+  svntest.main.file_append(sbox.ospath('A/mu2'), "now mu2\n")
+  sbox.simple_commit()
+  sbox.simple_move('A/mu2', 'A/mu3')
+  svntest.main.file_append(sbox.ospath('A/mu3'), "now mu3\n")
+  sbox.simple_commit()
+  
+  mu_at_1 = sbox.repo_url + '/A/mu@1'
+  mu3_at_3 = sbox.repo_url + '/A/mu3@3'
+
+  r1diff = [make_diff_header('mu', 'revision 0', 'revision 1')
+            + ["@@ -0,0 +1 @@\n",
+               "+This is the file 'mu'.\n"]]
+
+  # The mu2@2 and mu3@3 diffs show diffs relative to the copy source
+  r2diff = [make_diff_header('mu',
+                             '.../mu)\t(revision 1',
+                             '.../mu2)\t(revision 2')
+            + ["@@ -1 +1,2 @@\n",
+               " This is the file 'mu'.\n",
+               "+now mu2\n"]]
+
+  r3diff = [make_diff_header('mu2',
+                             '.../mu2)\t(revision 2',
+                             '.../mu3)\t(revision 3')
+            + ["@@ -1,2 +1,3 @@\n",
+               " This is the file 'mu'.\n",
+               " now mu2\n",
+               "+now mu3\n"]]
+
+  exit_code, output, err = svntest.actions.run_and_verify_svn(None, None, [],
+                                                              'log', '--diff',
+                                                              mu_at_1)
+  log_chain = parse_log_output(output, with_diffs=True)
+  if len(log_chain) != 1:
+    raise SVNLogParseError("%d logs found, 1 expected" % len(log_chain))
+  compare_diff_output(r1diff, log_chain[0]['diff_lines'])
+
+  exit_code, output, err = svntest.actions.run_and_verify_svn(None, None, [],
+                                                              'log', '--diff',
+                                                              '-r3', mu3_at_3)
+  log_chain = parse_log_output(output, with_diffs=True)
+  if len(log_chain) != 1:
+    raise SVNLogParseError("%d logs found, 1 expected" % len(log_chain))
+  compare_diff_output(r3diff, log_chain[0]['diff_lines'])
+
+  exit_code, output, err = svntest.actions.run_and_verify_svn(None, None, [],
+                                                              'log', '--diff',
+                                                              '-r3:2', mu3_at_3)
+  log_chain = parse_log_output(output, with_diffs=True)
+  if len(log_chain) != 2:
+    raise SVNLogParseError("%d logs found, 2 expected" % len(log_chain))
+  compare_diff_output(r3diff, log_chain[0]['diff_lines'])
+  compare_diff_output(r2diff, log_chain[1]['diff_lines'])
+
+  exit_code, output, err = svntest.actions.run_and_verify_svn(None, None, [],
+                                                              'log', '--diff',
+                                                              mu3_at_3)
+  log_chain = parse_log_output(output, with_diffs=True)
+  if len(log_chain) != 3:
+    raise SVNLogParseError("%d logs found, 3 expected" % len(log_chain))
+  compare_diff_output(r3diff, log_chain[0]['diff_lines'])
+  compare_diff_output(r2diff, log_chain[1]['diff_lines'])
+  compare_diff_output(r1diff, log_chain[2]['diff_lines'])
 
 ########################################################################
 # Run the tests
@@ -2142,6 +2249,7 @@ test_list = [ None,
               log_with_unrelated_peg_and_operative_revs,
               log_on_nonexistent_path_and_valid_rev,
               log_diff,
+              log_diff_moved,
              ]
 
 if __name__ == '__main__':

Propchange: subversion/branches/1.7.x/subversion/tests/cmdline/svntest/
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-r1352031/subversion/tests/cmdline/svntest:r1431725-1435017
  Merged /subversion/branches/1.7.x-gssapi-solaris10/subversion/tests/cmdline/svntest:r1453164-1515067
  Merged /subversion/branches/1.7.x-r1427278/subversion/tests/cmdline/svntest:r1433724-1485338
  Merged /subversion/branches/1.7.x-r1475724/subversion/tests/cmdline/svntest:r1475743-1482192
  Merged /subversion/branches/1.7.x-issue4263/subversion/tests/cmdline/svntest:r1423588-1434547
  Merged /subversion/branches/1.7.x-r1481010/subversion/tests/cmdline/svntest:r1481034-1482194
  Merged /subversion/branches/1.7.x-issue4340/subversion/tests/cmdline/svntest:r1461589-1485180
  Merged /subversion/branches/1.7.x-issue4257/subversion/tests/cmdline/svntest:r1454456-1461404
  Merged /subversion/branches/1.7.x-neon-properr/subversion/tests/cmdline/svntest:r1440619-1461944
  Merged /subversion/branches/1.7.x-issue4332/subversion/tests/cmdline/svntest:r1453478-1460963
  Merged /subversion/branches/1.7.x-issue4270/subversion/tests/cmdline/svntest:r1433737-1485341
  Merged /subversion/branches/1.7.x-r1461743/subversion/tests/cmdline/svntest:r1461745-1482189
  Merged /subversion/trunk/subversion/tests/cmdline/svntest:r1164116,1230798,1306275,1309865,1338291,1338297,1338314,1338688,1338708,1338713,1338739,1338748,1339159,1341544,1341560,1352031,1405922,1409939,1419670-1419681,1421011,1421103,1421380,1421541,1422053,1422100,1423585,1423837,1423840,1423848,1424977,1425368,1426138,1426264,1426752,1426830,1427197,1427210,1427278,1429201,1434128,1434405,1434414,1434418,1434435,1434476,1434750,1435361,1438602,1438683,1441810,1443763,1443929,1445753,1451678,1452617,1452780,1452967,1453780,1454088,1454217,1455352,1458341,1459599,1461278,1461562,1461580,1461701,1461743,1462293,1462300,1462302,1462321,1462334,1465975,1476359,1477730,1481010,1481627,1482282,1483781,1485350,1490684,1503528,1507044,1512432,1512471-1512472,1513463,1513472,1514763,1515119,1515237,1515992,1515997,1516023-1516024,1516051-1516052,1516565
  Merged /subversion/branches/1.7.x-r1426752/subversion/tests/cmdline/svntest:r1426753-1485335
  Merged /subversion/branches/1.7.x-issue4408/subversion/tests/cmdline/svntest:r1512143-1514943
  Merged /subversion/branches/1.7.x-r1507044/subversion/tests/cmdline/svntest:r1507300-1511568
  Merged /subversion/branches/1.7.x-issue4153/subversion/tests/cmdline/svntest:r1309894-1539233
  Merged /subversion/branches/1.7.x-r1482759/subversion/tests/cmdline/svntest:r1483584-1485046
  Merged /subversion/branches/1.7.x-issue4306/subversion/tests/cmdline/svntest:r1438872-1514941

Propchange: subversion/branches/1.7.x/tools/client-side/svnmucc/svnmucc.c
------------------------------------------------------------------------------
  Merged /subversion/branches/1.7.x-gssapi-solaris10/tools/client-side/svnmucc/svnmucc.c:r1453164-1515067
  Merged /subversion/branches/1.7.x-r1427278/tools/client-side/svnmucc/svnmucc.c:r1433724-1485338
  Merged /subversion/branches/1.7.x-issue4408/tools/client-side/svnmucc/svnmucc.c:r1512143-1514943
  Merged /subversion/branches/1.7.x-issue4270/tools/client-side/svnmucc/svnmucc.c:r1433737-1485341
  Merged /subversion/branches/1.7.x-issue4153/tools/client-side/svnmucc/svnmucc.c:r1309894-1539233
  Merged /subversion/branches/1.7.x-r1407131/tools/client-side/svnmucc/svnmucc.c:r1407164-1419607
  Merged /subversion/branches/1.7.x-issue4332/tools/client-side/svnmucc/svnmucc.c:r1453478-1460963
  Merged /subversion/branches/1.7.x-issue4306/tools/client-side/svnmucc/svnmucc.c:r1438872-1514941
  Merged /subversion/branches/1.7.x-issue4340/tools/client-side/svnmucc/svnmucc.c:r1461589-1485180
  Merged /subversion/branches/1.7.x-r1426752/tools/client-side/svnmucc/svnmucc.c:r1426753-1485335
  Merged /subversion/branches/1.7.x-issue4257/tools/client-side/svnmucc/svnmucc.c:r1454456-1461404
  Merged /subversion/branches/1.7.x-r1352031/tools/client-side/svnmucc/svnmucc.c:r1431725-1435017
  Merged /subversion/branches/1.7.x-neon-properr/tools/client-side/svnmucc/svnmucc.c:r1440619-1461944
  Merged /subversion/branches/1.7.x-r1481010/tools/client-side/svnmucc/svnmucc.c:r1481034-1482194
  Merged /subversion/branches/1.7.x-r1475724/tools/client-side/svnmucc/svnmucc.c:r1475743-1482192
  Merged /subversion/branches/1.7.x-r1507044/tools/client-side/svnmucc/svnmucc.c:r1507300-1511568
  Merged /subversion/branches/1.7.x-r1482759/tools/client-side/svnmucc/svnmucc.c:r1483584-1485046
  Merged /subversion/trunk/tools/client-side/svnmucc/svnmucc.c:r1164116,1230798,1295418,1306275,1309865,1338291,1338297,1338314,1338688,1338708,1338713,1338739,1338748,1339159,1341544,1341560,1352031,1403588,1403691,1405922,1407131,1407812,1408650,1409146,1409939,1419670-1419681,1421011,1421103,1421380,1421541,1422053,1422100,1423585,1423837,1423840,1423848,1424977,1425368,1426138,1426264,1426752,1426830,1427197,1427210,1427278,1429201,1434128,1434405,1434414,1434418,1434435,1434476,1434750,1435361,1438602,1438683,1441810,1443763,1443929,1445753,1451678,1452617,1452780,1452967,1453780,1454088,1454217,1455352,1458341,1459599,1461278,1461562,1461580,1461701,1461743,1462293,1462300,1462302,1462321,1462334,1465975,1476359,1477730,1481010,1481627,1482282,1483781,1485350,1490684,1503528,1507044,1512432,1512471-1512472,1513463,1513472,1514763,1515119,1515237,1515992,1515997,1516023-1516024,1516051-1516052,1516565
  Merged /subversion/branches/1.7.x-r1461743/tools/client-side/svnmucc/svnmucc.c:r1461745-1482189
  Merged /subversion/branches/1.7.x-issue4263/tools/client-side/svnmucc/svnmucc.c:r1423588-1434547