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

svn commit: r1415773 [2/6] - in /subversion/branches/tree-read-api: ./ build/ac-macros/ build/generator/ notes/ subversion/bindings/cxxhl/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_delta/ subversion/lib...

Modified: subversion/branches/tree-read-api/subversion/libsvn_client/export.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_client/export.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_client/export.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_client/export.c Fri Nov 30 18:12:52 2012
@@ -907,6 +907,47 @@ fetch_base_func(const char **filename,
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+get_editor(const svn_delta_editor_t **export_editor,
+           void **edit_baton,
+           struct edit_baton *eb,
+           svn_client_ctx_t *ctx,
+           apr_pool_t *result_pool,
+           apr_pool_t *scratch_pool)
+{
+  svn_delta_editor_t *editor = svn_delta_default_editor(result_pool);
+  svn_delta_shim_callbacks_t *shim_callbacks =
+                            svn_delta_shim_callbacks_default(result_pool);
+  
+  editor->set_target_revision = set_target_revision;
+  editor->open_root = open_root;
+  editor->add_directory = add_directory;
+  editor->add_file = add_file;
+  editor->apply_textdelta = apply_textdelta;
+  editor->close_file = close_file;
+  editor->change_file_prop = change_file_prop;
+  editor->change_dir_prop = change_dir_prop;
+
+  SVN_ERR(svn_delta_get_cancellation_editor(ctx->cancel_func,
+                                            ctx->cancel_baton,
+                                            editor,
+                                            eb,
+                                            export_editor,
+                                            edit_baton,
+                                            result_pool));
+
+  shim_callbacks->fetch_kind_func = fetch_kind_func;
+  shim_callbacks->fetch_props_func = fetch_props_func;
+  shim_callbacks->fetch_base_func = fetch_base_func;
+  shim_callbacks->fetch_baton = eb;
+
+  SVN_ERR(svn_editor__insert_shims(export_editor, edit_baton,
+                                   *export_editor, *edit_baton,
+                                   NULL, NULL, shim_callbacks,
+                                   result_pool, scratch_pool));
+
+   return SVN_NO_ERROR;
+}
 
 
 /*** Public Interfaces ***/
@@ -1044,37 +1085,10 @@ svn_client_export5(svn_revnum_t *result_
           const svn_delta_editor_t *export_editor;
           const svn_ra_reporter3_t *reporter;
           void *report_baton;
-          svn_delta_editor_t *editor = svn_delta_default_editor(pool);
           svn_boolean_t use_sleep = FALSE;
-          svn_delta_shim_callbacks_t *shim_callbacks =
-                                    svn_delta_shim_callbacks_default(pool);
 
-          editor->set_target_revision = set_target_revision;
-          editor->open_root = open_root;
-          editor->add_directory = add_directory;
-          editor->add_file = add_file;
-          editor->apply_textdelta = apply_textdelta;
-          editor->close_file = close_file;
-          editor->change_file_prop = change_file_prop;
-          editor->change_dir_prop = change_dir_prop;
-
-          SVN_ERR(svn_delta_get_cancellation_editor(ctx->cancel_func,
-                                                    ctx->cancel_baton,
-                                                    editor,
-                                                    eb,
-                                                    &export_editor,
-                                                    &edit_baton,
-                                                    pool));
-
-          shim_callbacks->fetch_kind_func = fetch_kind_func;
-          shim_callbacks->fetch_props_func = fetch_props_func;
-          shim_callbacks->fetch_base_func = fetch_base_func;
-          shim_callbacks->fetch_baton = eb;
-
-          SVN_ERR(svn_editor__insert_shims(&export_editor, &edit_baton,
-                                           export_editor, edit_baton,
-                                           NULL, NULL, shim_callbacks,
-                                           pool, pool));
+          SVN_ERR(get_editor(&export_editor, &edit_baton, eb, ctx,
+                             pool, pool));
 
           /* Manufacture a basic 'report' to the update reporter. */
           SVN_ERR(svn_ra_do_update2(ra_session,

Modified: subversion/branches/tree-read-api/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_client/externals.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_client/externals.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_client/externals.c Fri Nov 30 18:12:52 2012
@@ -1180,3 +1180,105 @@ svn_client__do_external_status(svn_clien
   return SVN_NO_ERROR;
 }
 
+/* Walk through all the external items and list them. */
+static svn_error_t *
+list_external_items(apr_array_header_t *external_items,
+                    const char *externals_parent_url,
+                    svn_depth_t depth,
+                    apr_uint32_t dirent_fields,
+                    svn_boolean_t fetch_locks,
+                    svn_client_list_func2_t list_func,
+                    void *baton,
+                    svn_client_ctx_t *ctx,
+                    apr_pool_t *scratch_pool)
+{
+  const char *externals_parent_repos_root_url;
+  apr_pool_t *iterpool;
+  int i;
+
+  SVN_ERR(svn_client_get_repos_root(&externals_parent_repos_root_url, 
+                                    NULL /* uuid */,
+                                    externals_parent_url, ctx, 
+                                    scratch_pool, scratch_pool));
+
+  iterpool = svn_pool_create(scratch_pool);
+
+  for (i = 0; i < external_items->nelts; i++)
+    {
+      const char *resolved_url;
+
+      svn_wc_external_item2_t *item = 
+          APR_ARRAY_IDX(external_items, i, svn_wc_external_item2_t *);
+
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(svn_wc__resolve_relative_external_url(
+                  &resolved_url, 
+                  item,
+                  externals_parent_repos_root_url,
+                  externals_parent_url,
+                  iterpool, iterpool));
+
+      /* List the external */
+      SVN_ERR(wrap_external_error(ctx, item->target_dir,
+                                  svn_client__list_internal(
+                                                resolved_url,
+                                                &item->peg_revision,
+                                                &item->revision,
+                                                depth, dirent_fields, 
+                                                fetch_locks,
+                                                TRUE,
+                                                externals_parent_url,
+                                                item->target_dir,
+                                                list_func, baton, ctx,
+                                                iterpool),
+                                  iterpool));
+    
+    }
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+      
+    
+svn_error_t * 
+svn_client__list_externals(apr_hash_t *externals, 
+                           svn_depth_t depth,
+                           apr_uint32_t dirent_fields,
+                           svn_boolean_t fetch_locks,
+                           svn_client_list_func2_t list_func,
+                           void *baton,
+                           svn_client_ctx_t *ctx,
+                           apr_pool_t *scratch_pool)
+{
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  apr_hash_index_t *hi;
+
+  for (hi = apr_hash_first(scratch_pool, externals);
+       hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *externals_parent_url = svn__apr_hash_index_key(hi);
+      svn_string_t *externals_desc = svn__apr_hash_index_val(hi);
+      apr_array_header_t *external_items;
+
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(svn_wc_parse_externals_description3(&external_items, 
+                                                  externals_parent_url,
+                                                  externals_desc->data, 
+                                                  FALSE, iterpool));
+
+      if (! external_items->nelts)
+        continue;
+
+      SVN_ERR(list_external_items(external_items, externals_parent_url, depth,
+                                  dirent_fields, fetch_locks, list_func,
+                                  baton, ctx, iterpool));
+
+    }
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+

Modified: subversion/branches/tree-read-api/subversion/libsvn_client/iprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_client/iprops.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_client/iprops.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_client/iprops.c Fri Nov 30 18:12:52 2012
@@ -40,31 +40,30 @@
 
 /*** Code. ***/
 
-/* Determine if ABSPATH needs an inherited property cache (i.e. it is a WC
-   root that is not also the repository root or it is switched).  If it does,
-   then set *NEEDS_CACHE to true, set it to false otherwise. */
+/* Determine if LOCAL_ABSPATH needs an inherited property cache.  If it does,
+   then set *NEEDS_CACHE to TRUE, set it to FALSE otherwise. */
 static svn_error_t *
 need_to_cache_iprops(svn_boolean_t *needs_cache,
-                     const char *abspath,
+                     const char *local_abspath,
                      svn_client_ctx_t *ctx,
                      apr_pool_t *scratch_pool)
 {
   svn_boolean_t is_wc_root;
+  svn_boolean_t is_switched;
   svn_error_t *err;
 
-  /* Our starting assumption. */
-  *needs_cache = FALSE;
-
-  err = svn_wc_is_wc_root2(&is_wc_root, ctx->wc_ctx, abspath,
+  err = svn_wc_check_root(&is_wc_root, &is_switched, NULL,
+                          ctx->wc_ctx, local_abspath,
                            scratch_pool);
 
-  /* ABSPATH can't need a cache if it doesn't exist. */
+  /* LOCAL_ABSPATH doesn't need a cache if it doesn't exist. */
   if (err)
     {
-      if (err->apr_err == SVN_ERR_ENTRY_NOT_FOUND)
+      if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
         {
           svn_error_clear(err);
           is_wc_root = FALSE;
+          is_switched = FALSE;
         }
       else
         {
@@ -72,19 +71,7 @@ need_to_cache_iprops(svn_boolean_t *need
         }
     }
 
-  if (is_wc_root)
-    {
-      const char *child_repos_relpath;
-
-      /* We want to cache the inherited properties for WC roots, unless that
-         root points to the root of the repository, then there in nowhere to
-         inherit properties from. */
-      SVN_ERR(svn_wc__node_get_repos_relpath(&child_repos_relpath,
-                                             ctx->wc_ctx, abspath,
-                                             scratch_pool, scratch_pool));
-      if (child_repos_relpath[0] != '\0')
-        *needs_cache = TRUE;
-    }
+  *needs_cache = (is_wc_root || is_switched);
 
   return SVN_NO_ERROR;
 }
@@ -129,7 +116,10 @@ svn_client__get_inheritable_props(apr_ha
             {
               const char *target_abspath = apr_pstrdup(scratch_pool,
                                                        local_abspath);
-              apr_hash_set(iprop_paths, target_abspath, 
+
+              /* As value we set TARGET_ABSPATH, but any string besides ""
+                 would do */
+              apr_hash_set(iprop_paths, target_abspath,
                            APR_HASH_KEY_STRING, target_abspath);
             }
         }
@@ -139,10 +129,18 @@ svn_client__get_inheritable_props(apr_ha
            hi = apr_hash_next(hi))
         {
           const char *child_abspath = svn__apr_hash_index_key(hi);
+          const char *child_repos_relpath = svn__apr_hash_index_val(hi);
           const char *url;
           apr_array_header_t *inherited_props;
 
           svn_pool_clear(iterpool);
+
+          if (*child_repos_relpath == '\0')
+            {
+              /* A repository root doesn't have inherited properties */
+              continue;
+            }
+
           SVN_ERR(svn_wc__node_get_url(&url, ctx->wc_ctx, child_abspath,
                                        iterpool, iterpool));
           if (ra_session)
@@ -166,7 +164,7 @@ svn_client__get_inheritable_props(apr_ha
 
           SVN_ERR(svn_ra_get_inherited_props(ra_session, &inherited_props,
                                              "", revision, result_pool,
-                                             scratch_pool));
+                                             iterpool));
           apr_hash_set(*wcroot_iprops,
                        apr_pstrdup(result_pool, child_abspath),
                        APR_HASH_KEY_STRING,

Modified: subversion/branches/tree-read-api/subversion/libsvn_client/list.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_client/list.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_client/list.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_client/list.c Fri Nov 30 18:12:52 2012
@@ -47,7 +47,15 @@
 
    LOCKS, if non-NULL, is a hash mapping const char * paths to svn_lock_t
    objects and FS_PATH is the absolute filesystem path of the RA session.
-   Use POOL for temporary allocations.
+   Use SCRATCH_POOL for temporary allocations.
+
+   If the caller passes EXTERNALS as non-NULL, populate the EXTERNALS 
+   hash table whose keys are URLs of the directory which has externals
+   definitions, and whose values are the externals description text. 
+   Allocate the hash's keys and values in RESULT_POOL.
+
+   EXTERNAL_PARENT_URL and EXTERNAL_TARGET are set when external items
+   are listed, otherwise both are set to NULL by the caller.
 */
 static svn_error_t *
 get_dir_contents(apr_uint32_t dirent_fields,
@@ -58,23 +66,31 @@ get_dir_contents(apr_uint32_t dirent_fie
                  const char *fs_path,
                  svn_depth_t depth,
                  svn_client_ctx_t *ctx,
-                 svn_client_list_func_t list_func,
+                 apr_hash_t *externals,
+                 const char *external_parent_url,
+                 const char *external_target,
+                 svn_client_list_func2_t list_func,
                  void *baton,
-                 apr_pool_t *pool)
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
 {
   apr_hash_t *tmpdirents;
-  apr_pool_t *iterpool = svn_pool_create(pool);
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   apr_array_header_t *array;
   svn_error_t *err;
+  apr_hash_t *prop_hash = NULL;
+  const svn_string_t *prop_val = NULL;
   int i;
 
   if (depth == svn_depth_empty)
     return SVN_NO_ERROR;
-
-  /* Get the directory's entries, but not its props.  Ignore any
-     not-authorized errors.  */
-  err = svn_ra_get_dir2(ra_session, &tmpdirents, NULL, NULL,
-                        dir, rev, dirent_fields, pool);
+  
+  /* Get the directory's entries. If externals hash is non-NULL, get its
+     properties also. Ignore any not-authorized errors.  */
+  err = svn_ra_get_dir2(ra_session, &tmpdirents, NULL, 
+                        externals ? &prop_hash : NULL,
+                        dir, rev, dirent_fields, scratch_pool);
+      
   if (err && ((err->apr_err == SVN_ERR_RA_NOT_AUTHORIZED) ||
               (err->apr_err == SVN_ERR_RA_DAV_FORBIDDEN)))
     {
@@ -82,12 +98,29 @@ get_dir_contents(apr_uint32_t dirent_fie
       return SVN_NO_ERROR;
     }
   SVN_ERR(err);
+ 
+ /* Filter out svn:externals from all properties hash. */ 
+  if (prop_hash) 
+    prop_val = apr_hash_get(prop_hash, SVN_PROP_EXTERNALS, 
+                            APR_HASH_KEY_STRING);
+  if (prop_val)
+    {
+      const char *url;
+
+      SVN_ERR(svn_ra_get_session_url(ra_session, &url, scratch_pool));
+      
+      apr_hash_set(externals, svn_path_url_add_component2(url, dir, 
+                                                          result_pool),
+                   APR_HASH_KEY_STRING, svn_string_dup(prop_val, 
+                                                       result_pool));
+    }
 
   if (ctx->cancel_func)
     SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
 
   /* Sort the hash, so we can call the callback in a "deterministic" order. */
-  array = svn_sort__hash(tmpdirents, svn_sort_compare_items_lexically, pool);
+  array = svn_sort__hash(tmpdirents, svn_sort_compare_items_lexically, 
+                         scratch_pool);
   for (i = 0; i < array->nelts; ++i)
     {
       svn_sort__item_t *item = &APR_ARRAY_IDX(array, i, svn_sort__item_t);
@@ -110,12 +143,17 @@ get_dir_contents(apr_uint32_t dirent_fie
       if (the_ent->kind == svn_node_file
           || depth == svn_depth_immediates
           || depth == svn_depth_infinity)
-        SVN_ERR(list_func(baton, path, the_ent, lock, fs_path, iterpool));
-
+        SVN_ERR(list_func(baton, path, the_ent, lock, fs_path,
+                          external_parent_url, external_target, iterpool));
+      
+      /* If externals is non-NULL, populate the externals hash table 
+         recursively for all directory entries. */
       if (depth == svn_depth_infinity && the_ent->kind == svn_node_dir)
         SVN_ERR(get_dir_contents(dirent_fields, path, rev,
-                                 ra_session, locks, fs_path, depth, ctx,
-                                 list_func, baton, iterpool));
+                                 ra_session, locks, fs_path, depth, ctx, 
+                                 externals, external_parent_url,
+                                 external_target, list_func, baton,
+                                 result_pool, iterpool));
     }
 
   svn_pool_destroy(iterpool);
@@ -236,16 +274,19 @@ svn_client__ra_stat_compatible(svn_ra_se
 }
 
 svn_error_t *
-svn_client_list2(const char *path_or_url,
-                 const svn_opt_revision_t *peg_revision,
-                 const svn_opt_revision_t *revision,
-                 svn_depth_t depth,
-                 apr_uint32_t dirent_fields,
-                 svn_boolean_t fetch_locks,
-                 svn_client_list_func_t list_func,
-                 void *baton,
-                 svn_client_ctx_t *ctx,
-                 apr_pool_t *pool)
+svn_client__list_internal(const char *path_or_url,
+                          const svn_opt_revision_t *peg_revision,
+                          const svn_opt_revision_t *revision,
+                          svn_depth_t depth,
+                          apr_uint32_t dirent_fields,
+                          svn_boolean_t fetch_locks,
+                          svn_boolean_t include_externals,
+                          const char *external_parent_url,
+                          const char *external_target,
+                          svn_client_list_func2_t list_func,
+                          void *baton,
+                          svn_client_ctx_t *ctx,
+                          apr_pool_t *pool)
 {
   svn_ra_session_t *ra_session;
   svn_client__pathrev_t *loc;
@@ -253,6 +294,12 @@ svn_client_list2(const char *path_or_url
   const char *fs_path;
   svn_error_t *err;
   apr_hash_t *locks;
+  apr_hash_t *externals;
+
+  if (include_externals)
+    externals = apr_hash_make(pool);
+  else
+    externals = NULL;
 
   /* We use the kind field to determine if we should recurse, so we
      always need it. */
@@ -295,14 +342,52 @@ svn_client_list2(const char *path_or_url
   SVN_ERR(list_func(baton, "", dirent, locks
                     ? (apr_hash_get(locks, fs_path,
                                     APR_HASH_KEY_STRING))
-                    : NULL, fs_path, pool));
+                    : NULL, fs_path, external_parent_url, 
+                    external_target, pool));
 
   if (dirent->kind == svn_node_dir
       && (depth == svn_depth_files
           || depth == svn_depth_immediates
           || depth == svn_depth_infinity))
     SVN_ERR(get_dir_contents(dirent_fields, "", loc->rev, ra_session, locks,
-                             fs_path, depth, ctx, list_func, baton, pool));
-
+                             fs_path, depth, ctx, externals, 
+                             external_parent_url, external_target, list_func,
+                             baton, pool, pool));
+  
+  /* We handle externals after listing entries under path_or_url, so that
+     handling external items (and any errors therefrom) doesn't delay
+     the primary operation. */
+  if (include_externals && apr_hash_count(externals))
+    {
+      /* The 'externals' hash populated by get_dir_contents() is processed 
+         here. */
+      SVN_ERR(svn_client__list_externals(externals, depth, dirent_fields, 
+                                         fetch_locks, list_func, baton,
+                                         ctx, pool));
+    } 
+  
   return SVN_NO_ERROR;
 }
+
+svn_error_t *
+svn_client_list3(const char *path_or_url,
+                 const svn_opt_revision_t *peg_revision,
+                 const svn_opt_revision_t *revision,
+                 svn_depth_t depth,
+                 apr_uint32_t dirent_fields,
+                 svn_boolean_t fetch_locks,
+                 svn_boolean_t include_externals,
+                 svn_client_list_func2_t list_func,
+                 void *baton,
+                 svn_client_ctx_t *ctx,
+                 apr_pool_t *pool)
+{
+
+  return svn_error_trace(svn_client__list_internal(path_or_url, peg_revision,
+                                                   revision, 
+                                                   depth, dirent_fields, 
+                                                   fetch_locks, 
+                                                   include_externals, 
+                                                   NULL, NULL, list_func,
+                                                   baton, ctx, pool));
+}

Modified: subversion/branches/tree-read-api/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_client/merge.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_client/merge.c Fri Nov 30 18:12:52 2012
@@ -260,9 +260,6 @@ typedef struct merge_cmd_baton_t {
                                          SOURCES_ANCESTRAL is FALSE. */
   svn_boolean_t reintegrate_merge;    /* Whether this is a --reintegrate
                                          merge or not. */
-  const char *added_path;             /* Set to the dir path whenever the
-                                         dir is added as a child of a
-                                         versioned dir (dry-run only) */
   const merge_target_t *target;       /* Description of merge target node */
 
   /* The left and right URLs and revs.  The value of this field changes to
@@ -289,9 +286,11 @@ typedef struct merge_cmd_baton_t {
      dry_run mode. */
   apr_hash_t *dry_run_deletions;
 
-  /* The list of paths for entries we've added, used only when in
-     dry_run mode. */
+  /* The list of paths for entries we've added and the most
+     recently added directory.  The latter may be NULL.
+     Both are used only when in dry_run mode. */
   apr_hash_t *dry_run_added;
+  const char *dry_run_last_added_dir;
 
   /* The list of any paths which remained in conflict after a
      resolution attempt was made.  We track this in-memory, rather
@@ -306,9 +305,10 @@ typedef struct merge_cmd_baton_t {
      meet the criteria or DRY_RUN is true. */
   apr_hash_t *paths_with_new_mergeinfo;
 
-  /* A list of absolute paths which had explicit mergeinfo prior to the merge
-     but had this mergeinfo deleted by the merge.  This is populated by
-     merge_change_props() and is allocated in POOL so it is subject to the
+  /* A list of absolute paths whose mergeinfo doesn't need updating after
+     the merge. This can be caused by the removal of mergeinfo by the merge
+     or by deleting the node itself.  This is populated by merge_change_props()
+     and the delete callbacks and is allocated in POOL so it is subject to the
      lifetime limitations of POOL.  Is NULL if no paths are found which
      meet the criteria or DRY_RUN is true. */
   apr_hash_t *paths_with_deleted_mergeinfo;
@@ -490,6 +490,48 @@ dry_run_added_p(const merge_cmd_baton_t 
                        APR_HASH_KEY_STRING) != NULL);
 }
 
+/* Return true iff we're in dry-run mode and a parent of
+   LOCAL_RELPATH/LOCAL_ABSPATH would have been added by now if we
+   weren't in dry-run mode.  Used to avoid spurious notifications
+   (e.g. conflicts) from a merge attempt into an existing target which
+   would have been deleted if we weren't in dry_run mode (issue
+   #2584).  Assumes that WCPATH is still versioned (e.g. has an
+   associated entry). */
+static svn_boolean_t
+dry_run_added_parent_p(const merge_cmd_baton_t *merge_b,
+                       const char *local_relpath,
+                       const char *local_abspath,
+                       apr_pool_t *scratch_pool)
+{
+  const char *abspath = local_abspath;
+  int i;
+
+  if (!merge_b->dry_run)
+    return FALSE;
+
+  /* See if LOCAL_ABSPATH is a child of the most recently added
+     directory.  This is an optimization over searching through
+     dry_run_added that plays to the strengths of the editor's drive
+     ordering constraints.  In fact, we need the fallback approach
+     below only because of ra_serf's insufficiencies in this area.  */
+  if (merge_b->dry_run_last_added_dir
+      && svn_dirent_is_child(merge_b->dry_run_last_added_dir,
+                             local_abspath, NULL))
+    return TRUE;
+
+  /* The fallback:  see if any of LOCAL_ABSPATH's parents have been
+     added in this merge so far. */
+  for (i = 0; i < (svn_path_component_count(local_relpath) - 1); i++)
+    {
+      abspath = svn_dirent_dirname(abspath, scratch_pool);
+      if (apr_hash_get(merge_b->dry_run_added, abspath,
+                       APR_HASH_KEY_STRING))
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
 /* Return whether any WC path was put in conflict by the merge
    operation corresponding to MERGE_B. */
 static APR_INLINE svn_boolean_t
@@ -1857,8 +1899,9 @@ merge_file_added(svn_wc_notify_state_t *
 
     if (obstr_state != svn_wc_notify_state_inapplicable)
       {
-        if (merge_b->dry_run && merge_b->added_path
-            && svn_dirent_is_child(merge_b->added_path, mine_abspath, NULL))
+        if (merge_b->dry_run 
+            && dry_run_added_parent_p(merge_b, mine_relpath,
+                                      mine_abspath, scratch_pool))
           {
             if (content_state)
               *content_state = svn_wc_notify_state_changed;
@@ -2191,6 +2234,15 @@ merge_file_deleted(svn_wc_notify_state_t
                                           merge_b->ctx, scratch_pool));
             if (state)
               *state = svn_wc_notify_state_changed;
+
+            /* Record that we might have deleted mergeinfo */
+            if (!merge_b->paths_with_deleted_mergeinfo)
+              merge_b->paths_with_deleted_mergeinfo =
+                                                apr_hash_make(merge_b->pool);
+
+            apr_hash_set(merge_b->paths_with_deleted_mergeinfo,
+                         apr_pstrdup(merge_b->pool, mine_abspath),
+                         APR_HASH_KEY_STRING, mine_abspath);
           }
         else
           {
@@ -2255,6 +2307,24 @@ merge_file_deleted(svn_wc_notify_state_t
   return SVN_NO_ERROR;
 }
 
+/* Upate dry run list of added directories.
+
+   If the merge is a dry run, then set MERGE_B->DRY_RUN_LAST_ADDED_DIR to a
+   copy of ADDED_DIR_ABSPATH, allocated in MERGE_B->POOL. Add the same copy
+   to MERGE_B->DRY_RUN_ADDED. Do nothing if the merge is not a dry run. */
+static void
+cache_last_added_dir(merge_cmd_baton_t *merge_b,
+                     const char *added_dir_abspath)
+{
+  if (merge_b->dry_run)
+    {
+      merge_b->dry_run_last_added_dir = apr_pstrdup(merge_b->pool,
+                                                   added_dir_abspath);
+      apr_hash_set(merge_b->dry_run_added, merge_b->dry_run_last_added_dir,
+                  APR_HASH_KEY_STRING, merge_b->dry_run_last_added_dir);
+    }
+}
+
 /* An svn_wc_diff_callbacks4_t function. */
 static svn_error_t *
 merge_dir_added(svn_wc_notify_state_t *state,
@@ -2337,13 +2407,16 @@ merge_dir_added(svn_wc_notify_state_t *s
 
     if (obstr_state != svn_wc_notify_state_inapplicable)
       {
-        if (state && merge_b->dry_run && merge_b->added_path
-            && svn_dirent_is_child(merge_b->added_path, local_abspath, NULL))
+        if (state && merge_b->dry_run
+            && dry_run_added_parent_p(merge_b, local_relpath,
+                                      local_abspath, scratch_pool))
           {
             *state = svn_wc_notify_state_changed;
           }
         else if (state)
-          *state = obstr_state;
+          {
+            *state = obstr_state;
+          }
         return SVN_NO_ERROR;
       }
 
@@ -2358,9 +2431,7 @@ merge_dir_added(svn_wc_notify_state_t *s
       /* Unversioned or schedule-delete */
       if (merge_b->dry_run)
         {
-          merge_b->added_path = apr_pstrdup(merge_b->pool, local_abspath);
-          apr_hash_set(merge_b->dry_run_added, merge_b->added_path,
-                       APR_HASH_KEY_STRING, merge_b->added_path);
+          cache_last_added_dir(merge_b, local_abspath);
         }
       else
         {
@@ -2385,15 +2456,19 @@ merge_dir_added(svn_wc_notify_state_t *s
           /* The dir is not known to Subversion, or is schedule-delete.
            * We will make it schedule-add. */
           if (!merge_b->dry_run)
-            SVN_ERR(svn_wc_add4(merge_b->ctx->wc_ctx, local_abspath,
-                                svn_depth_infinity,
-                                copyfrom_url, copyfrom_rev,
-                                merge_b->ctx->cancel_func,
-                                merge_b->ctx->cancel_baton,
-                                NULL, NULL, /* no notification func! */
-                                scratch_pool));
+            {
+              SVN_ERR(svn_wc_add4(merge_b->ctx->wc_ctx, local_abspath,
+                                  svn_depth_infinity,
+                                  copyfrom_url, copyfrom_rev,
+                                  merge_b->ctx->cancel_func,
+                                  merge_b->ctx->cancel_baton,
+                                  NULL, NULL, /* no notification func! */
+                                  scratch_pool));
+            }
           else
-            merge_b->added_path = apr_pstrdup(merge_b->pool, local_abspath);
+            {
+              cache_last_added_dir(merge_b, local_abspath);
+            }
           if (state)
             *state = svn_wc_notify_state_changed;
         }
@@ -2432,7 +2507,7 @@ merge_dir_added(svn_wc_notify_state_t *s
       break;
     case svn_node_file:
       if (merge_b->dry_run)
-        merge_b->added_path = NULL;
+        merge_b->dry_run_last_added_dir = NULL;
 
       if (is_versioned && dry_run_deleted_p(merge_b, local_abspath))
         {
@@ -2456,7 +2531,7 @@ merge_dir_added(svn_wc_notify_state_t *s
       break;
     default:
       if (merge_b->dry_run)
-        merge_b->added_path = NULL;
+        merge_b->dry_run_last_added_dir = NULL;
       if (state)
         *state = svn_wc_notify_state_unknown;
       break;
@@ -2560,6 +2635,15 @@ merge_dir_deleted(svn_wc_notify_state_t 
                 if (state)
                   *state = svn_wc_notify_state_changed;
               }
+
+            /* Record that we might have deleted mergeinfo */
+            if (!merge_b->paths_with_deleted_mergeinfo)
+              merge_b->paths_with_deleted_mergeinfo =
+                                                apr_hash_make(merge_b->pool);
+
+            apr_hash_set(merge_b->paths_with_deleted_mergeinfo,
+                         apr_pstrdup(merge_b->pool, local_abspath),
+                         APR_HASH_KEY_STRING, local_abspath);
           }
         else
           {
@@ -6626,7 +6710,6 @@ normalize_merge_sources_internal(apr_arr
                   new_segment->path = original_repos_relpath;
                   new_segment->range_start = original_revision;
                   new_segment->range_end = original_revision;
-                  segment->range_start = original_revision + 1;
                   svn_sort__array_insert(&new_segment, segments, 0);
                 }
             }
@@ -9163,12 +9246,12 @@ do_merge(apr_hash_t **modified_subtrees,
          be reset for each merge source iteration. */
       merge_cmd_baton.merge_source = *source;
       merge_cmd_baton.implicit_src_gap = NULL;
-      merge_cmd_baton.added_path = NULL;
       merge_cmd_baton.add_necessitated_merge = FALSE;
       merge_cmd_baton.dry_run_deletions =
         dry_run ? apr_hash_make(iterpool) : NULL;
       merge_cmd_baton.dry_run_added =
         dry_run ? apr_hash_make(iterpool) : NULL;
+      merge_cmd_baton.dry_run_last_added_dir = NULL;
       merge_cmd_baton.conflicted_paths = NULL;
       merge_cmd_baton.paths_with_new_mergeinfo = NULL;
       merge_cmd_baton.paths_with_deleted_mergeinfo = NULL;

Modified: subversion/branches/tree-read-api/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_client/mergeinfo.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_client/mergeinfo.c Fri Nov 30 18:12:52 2012
@@ -264,6 +264,7 @@ svn_client__get_wc_mergeinfo(svn_mergein
           !svn_dirent_is_root(local_abspath, strlen(local_abspath)))
         {
           svn_boolean_t is_wc_root;
+          svn_boolean_t is_switched;
           svn_revnum_t parent_base_rev;
           svn_revnum_t parent_changed_rev;
 
@@ -273,9 +274,9 @@ svn_client__get_wc_mergeinfo(svn_mergein
 
           /* If we've reached the root of the working copy don't look any
              higher. */
-          SVN_ERR(svn_wc_is_wc_root2(&is_wc_root, ctx->wc_ctx,
-                                     local_abspath, iterpool));
-          if (is_wc_root)
+          SVN_ERR(svn_wc_check_root(&is_wc_root, &is_switched, NULL,
+                                    ctx->wc_ctx, local_abspath, iterpool));
+          if (is_wc_root || is_switched)
             break;
 
           /* No explicit mergeinfo on this path.  Look higher up the
@@ -910,18 +911,15 @@ elide_mergeinfo(svn_mergeinfo_t parent_m
 
 
 svn_error_t *
-svn_client__elide_mergeinfo(const char *target_wcpath,
-                            const char *wc_elision_limit_path,
+svn_client__elide_mergeinfo(const char *target_abspath,
+                            const char *wc_elision_limit_abspath,
                             svn_client_ctx_t *ctx,
                             apr_pool_t *pool)
 {
-  const char *target_abspath;
-  const char *limit_abspath = NULL;
+  const char *limit_abspath = wc_elision_limit_abspath;
 
-  SVN_ERR(svn_dirent_get_absolute(&target_abspath, target_wcpath, pool));
-  if (wc_elision_limit_path)
-    SVN_ERR(svn_dirent_get_absolute(&limit_abspath, wc_elision_limit_path,
-                                    pool));
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(target_abspath));
+  SVN_ERR_ASSERT(!wc_elision_limit_abspath || svn_dirent_is_absolute(wc_elision_limit_abspath));
 
   /* Check for first easy out: We are already at the limit path. */
   if (!limit_abspath
@@ -984,12 +982,12 @@ svn_client__elide_mergeinfo(const char *
       /* If TARGET_WCPATH inherited no mergeinfo from the WC and we are
          not limiting our search to the working copy then check if it
          inherits any from the repos. */
-      if (!mergeinfo && !wc_elision_limit_path)
+      if (!mergeinfo && !wc_elision_limit_abspath)
         {
           err = svn_client__get_wc_or_repos_mergeinfo(
             &mergeinfo, NULL, NULL, TRUE,
             svn_mergeinfo_nearest_ancestor,
-            NULL, target_wcpath, ctx, pool);
+            NULL, target_abspath, ctx, pool);
           if (err)
             {
               if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)
@@ -1008,7 +1006,7 @@ svn_client__elide_mergeinfo(const char *
 
       /* If there is nowhere to elide TARGET_WCPATH's mergeinfo to and
          the elision is limited, then we are done.*/
-      if (!mergeinfo && wc_elision_limit_path)
+      if (!mergeinfo && wc_elision_limit_abspath)
         return SVN_NO_ERROR;
 
       SVN_ERR(elide_mergeinfo(mergeinfo, target_mergeinfo, target_abspath,

Modified: subversion/branches/tree-read-api/subversion/libsvn_client/mergeinfo.h
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_client/mergeinfo.h?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_client/mergeinfo.h (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_client/mergeinfo.h Fri Nov 30 18:12:52 2012
@@ -345,42 +345,42 @@ svn_client__record_wc_mergeinfo_catalog(
                                         svn_client_ctx_t *ctx,
                                         apr_pool_t *scratch_pool);
 
-/* Elide any svn:mergeinfo set on TARGET_WCPATH to its nearest working
+/* Elide any svn:mergeinfo set on TARGET_ABSPATH to its nearest working
    copy (or possibly repository) ancestor with equivalent mergeinfo.
 
-   If WC_ELISION_LIMIT_PATH is NULL check up to the root of the
+   If WC_ELISION_LIMIT_ABSPATH is NULL check up to the root of the
    working copy or the nearest switched parent for an elision
    destination, if none is found check the repository, otherwise check
-   as far as WC_ELISION_LIMIT_PATH within the working copy.
-   TARGET_WCPATH and WC_ELISION_LIMIT_PATH, if it exists, must both be
+   as far as WC_ELISION_LIMIT_ABSPATH within the working copy.
+   TARGET_WCPATH and WC_ELISION_LIMIT_ABSPATH, if it exists, must both be
    absolute or relative to the working directory.
 
    Elision occurs if:
 
-     A) TARGET_WCPATH has empty mergeinfo and no parent path with
+     A) TARGET_ABSPATH has empty mergeinfo and no parent path with
         explicit mergeinfo can be found in either the WC or the
         repository (WC_ELISION_LIMIT_PATH must be NULL for this to
         occur).
 
-     B) TARGET_WCPATH has empty mergeinfo and its nearest parent also
+     B) TARGET_ABSPATH has empty mergeinfo and its nearest parent also
         has empty mergeinfo.
 
-     C) TARGET_WCPATH has the same mergeinfo as its nearest parent
+     C) TARGET_ABSPATH has the same mergeinfo as its nearest parent
         when that parent's mergeinfo is adjusted for the path
         difference between the two, e.g.:
 
-           TARGET_WCPATH                = A_COPY/D/H
-           TARGET_WCPATH's mergeinfo    = '/A/D/H:3'
-           TARGET_WCPATH nearest parent = A_COPY
-           Parent's mergeinfo           = '/A:3'
-           Path differece               = 'D/H'
-           Parent's adjusted mergeinfo  = '/A/D/H:3'
+           TARGET_ABSPATH                = A_COPY/D/H
+           TARGET_ABSPATH's mergeinfo    = '/A/D/H:3'
+           TARGET_ABSPATH nearest parent = A_COPY
+           Parent's mergeinfo            = '/A:3'
+           Path difference               = 'D/H'
+           Parent's adjusted mergeinfo   = '/A/D/H:3'
 
    If Elision occurs remove the svn:mergeinfo property from
-   TARGET_WCPATH. */
+   TARGET_ABSPATH. */
 svn_error_t *
-svn_client__elide_mergeinfo(const char *target_wcpath,
-                            const char *wc_elision_limit_path,
+svn_client__elide_mergeinfo(const char *target_abspath,
+                            const char *wc_elision_limit_abspath,
                             svn_client_ctx_t *ctx,
                             apr_pool_t *pool);
 

Modified: subversion/branches/tree-read-api/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_client/prop_commands.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_client/prop_commands.c Fri Nov 30 18:12:52 2012
@@ -48,29 +48,6 @@
 
 /*** Code. ***/
 
-/* Check whether NAME is a revision property name.
- *
- * Return TRUE if it is.
- * Return FALSE if it is not.
- */
-static svn_boolean_t
-is_revision_prop_name(const char *name)
-{
-  apr_size_t i;
-  static const char *revision_props[] =
-    {
-      SVN_PROP_REVISION_ALL_PROPS
-    };
-
-  for (i = 0; i < sizeof(revision_props) / sizeof(revision_props[0]); i++)
-    {
-      if (strcmp(name, revision_props[i]) == 0)
-        return TRUE;
-    }
-  return FALSE;
-}
-
-
 /* Return an SVN_ERR_CLIENT_PROPERTY_NAME error if NAME is a wcprop,
    else return SVN_NO_ERROR. */
 static svn_error_t *
@@ -285,7 +262,7 @@ static svn_error_t *
 check_prop_name(const char *propname,
                 const svn_string_t *propval)
 {
-  if (is_revision_prop_name(propname))
+  if (svn_prop_is_known_svn_rev_prop(propname))
     return svn_error_createf(SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
                              _("Revision property '%s' not allowed "
                                "in this context"), propname);

Modified: subversion/branches/tree-read-api/subversion/libsvn_delta/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_delta/compat.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_delta/compat.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_delta/compat.c Fri Nov 30 18:12:52 2012
@@ -163,7 +163,7 @@ enum restructure_action_t
   RESTRUCTURE_NONE = 0,
   RESTRUCTURE_ADD,         /* add the node, maybe replacing. maybe copy  */
   RESTRUCTURE_ADD_ABSENT,  /* add an absent node, possibly replacing  */
-  RESTRUCTURE_DELETE,      /* delete this node  */
+  RESTRUCTURE_DELETE       /* delete this node  */
 };
 
 /* Records everything about how this node is to be changed.  */

Modified: subversion/branches/tree-read-api/subversion/libsvn_diff/diff.h
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_diff/diff.h?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_diff/diff.h (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_diff/diff.h Fri Nov 30 18:12:52 2012
@@ -184,5 +184,34 @@ svn_diff__normalize_buffer(char **tgt,
                            const char *buf,
                            const svn_diff_file_options_t *opts);
 
+/* Set *OUT_STR to a newline followed by a "\ No newline at end of file" line.
+ *
+ * The text will be encoded into HEADER_ENCODING.
+ */
+svn_error_t *
+svn_diff__unified_append_no_newline_msg(svn_stringbuf_t *stringbuf,
+                                        const char *header_encoding,
+                                        apr_pool_t *scratch_pool);
+
+/* Write a unidiff hunk header to OUTPUT_STREAM.
+ *
+ * The header will use HUNK_DELIMITER (which should usually be "@@") before
+ * and after the line-number ranges which are formed from OLD_START,
+ * OLD_LENGTH, NEW_START and NEW_LENGTH.  If HUNK_EXTRA_CONTEXT is not NULL,
+ * it will be written after the final delimiter, with an intervening space.
+ *
+ * The text will be encoded into HEADER_ENCODING.
+ */
+svn_error_t *
+svn_diff__unified_write_hunk_header(svn_stream_t *output_stream,
+                                    const char *header_encoding,
+                                    const char *hunk_delimiter,
+                                    apr_off_t old_start,
+                                    apr_off_t old_length,
+                                    apr_off_t new_start,
+                                    apr_off_t new_length,
+                                    const char *hunk_extra_context,
+                                    apr_pool_t *scratch_pool);
+
 
 #endif /* DIFF_H */

Modified: subversion/branches/tree-read-api/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_diff/diff_file.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_diff/diff_file.c Fri Nov 30 18:12:52 2012
@@ -48,6 +48,7 @@
 #include "private/svn_eol_private.h"
 #include "private/svn_dep_compat.h"
 #include "private/svn_adler32.h"
+#include "private/svn_diff_private.h"
 
 /* A token, i.e. a line read from a file. */
 typedef struct svn_diff__file_token_t
@@ -1491,14 +1492,8 @@ output_unified_line(svn_diff__file_outpu
       if (bytes_processed && (type != svn_diff__file_output_unified_skip)
           && ! had_cr)
         {
-          const char *out_str;
-          SVN_ERR(svn_utf_cstring_from_utf8_ex2
-                  (&out_str,
-                   apr_psprintf(baton->pool,
-                                APR_EOL_STR "\\ %s" APR_EOL_STR,
-                                _("No newline at end of file")),
-                   baton->header_encoding, baton->pool));
-          svn_stringbuf_appendcstr(baton->hunk, out_str);
+          SVN_ERR(svn_diff__unified_append_no_newline_msg(
+                    baton->hunk, baton->header_encoding, baton->pool));
         }
 
       baton->length[idx] = 0;
@@ -1538,41 +1533,13 @@ output_unified_flush_hunk(svn_diff__file
         baton->hunk_start[i]++;
     }
 
-  /* Output the hunk header.  If the hunk length is 1, the file is a one line
-     file.  In this case, surpress the number of lines in the hunk (it is
-     1 implicitly)
-   */
-  SVN_ERR(svn_stream_printf_from_utf8(baton->output_stream,
-                                      baton->header_encoding,
-                                      baton->pool,
-                                      "@@ -%" APR_OFF_T_FMT,
-                                      baton->hunk_start[0]));
-  if (baton->hunk_length[0] != 1)
-    {
-      SVN_ERR(svn_stream_printf_from_utf8(baton->output_stream,
-                                          baton->header_encoding,
-                                          baton->pool, ",%" APR_OFF_T_FMT,
-                                          baton->hunk_length[0]));
-    }
-
-  SVN_ERR(svn_stream_printf_from_utf8(baton->output_stream,
-                                      baton->header_encoding,
-                                      baton->pool, " +%" APR_OFF_T_FMT,
-                                      baton->hunk_start[1]));
-  if (baton->hunk_length[1] != 1)
-    {
-      SVN_ERR(svn_stream_printf_from_utf8(baton->output_stream,
-                                          baton->header_encoding,
-                                          baton->pool, ",%" APR_OFF_T_FMT,
-                                          baton->hunk_length[1]));
-    }
-
-  SVN_ERR(svn_stream_printf_from_utf8(baton->output_stream,
-                                      baton->header_encoding,
-                                      baton->pool, " @@%s%s" APR_EOL_STR,
-                                      baton->hunk_extra_context[0]
-                                      ? " " : "",
-                                      baton->hunk_extra_context));
+  /* Write the hunk header */
+  SVN_ERR(svn_diff__unified_write_hunk_header(
+            baton->output_stream, baton->header_encoding, "@@",
+            baton->hunk_start[0], baton->hunk_length[0],
+            baton->hunk_start[1], baton->hunk_length[1],
+            baton->hunk_extra_context,
+            baton->pool));
 
   /* Output the hunk content */
   hunk_len = baton->hunk->len;
@@ -1733,10 +1700,9 @@ svn_diff_file_output_unified3(svn_stream
                               svn_boolean_t show_c_function,
                               apr_pool_t *pool)
 {
-  svn_diff__file_output_baton_t baton;
-
   if (svn_diff_contains_diffs(diff))
     {
+      svn_diff__file_output_baton_t baton;
       const char **c;
       int i;
 
@@ -1822,10 +1788,9 @@ svn_diff_file_output_unified3(svn_stream
                   (&modified_header, modified_path, pool));
         }
 
-      SVN_ERR(svn_stream_printf_from_utf8(output_stream, header_encoding, pool,
-                                          "--- %s" APR_EOL_STR
-                                          "+++ %s" APR_EOL_STR,
-                                          original_header, modified_header));
+      SVN_ERR(svn_diff__unidiff_write_header(
+                output_stream, header_encoding,
+                original_header, modified_header, pool));
 
       SVN_ERR(svn_diff_output(diff, &baton,
                               &svn_diff__file_output_unified_vtable));
@@ -2238,7 +2203,6 @@ svn_diff_file_output_merge2(svn_stream_t
 {
   svn_diff3__file_output_baton_t baton;
   apr_file_t *file[3];
-  apr_off_t size;
   int idx;
 #if APR_HAS_MMAP
   apr_mmap_t *mm[3] = { 0 };
@@ -2282,6 +2246,8 @@ svn_diff_file_output_merge2(svn_stream_t
 
   for (idx = 0; idx < 3; idx++)
     {
+      apr_off_t size;
+
       SVN_ERR(map_or_read_file(&file[idx],
                                MMAP_T_ARG(mm[idx])
                                &baton.buffer[idx], &size,

Modified: subversion/branches/tree-read-api/subversion/libsvn_diff/diff_memory.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_diff/diff_memory.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_diff/diff_memory.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_diff/diff_memory.c Fri Nov 30 18:12:52 2012
@@ -35,6 +35,7 @@
 #include "diff.h"
 #include "svn_private_config.h"
 #include "private/svn_adler32.h"
+#include "private/svn_diff_private.h"
 
 typedef struct source_tokens_t
 {
@@ -363,6 +364,9 @@ typedef struct unified_output_baton_t
   /* The delimiters of the hunk header, '@@' for text hunks and '##' for
    * property hunks. */
   const char *hunk_delimiter;
+  /* The string to print after a line that does not end with a newline.
+   * It must start with a '\'.  Typically "\ No newline at end of file". */
+  const char *no_newline_string;
 
   /* Pool for allocation of temporary memory in the callbacks
      Should be cleared on entry of each iteration of a callback */
@@ -418,13 +422,10 @@ output_unified_token_range(output_baton_
   if (past_last == source->tokens->nelts && source->ends_without_eol)
     {
       const char *out_str;
-      SVN_ERR(svn_utf_cstring_from_utf8_ex2
-              (&out_str,
-               /* The string below is intentionally not marked for translation:
-                  it's vital to correct operation of the diff(1)/patch(1)
-                  program pair. */
-               APR_EOL_STR "\\ No newline at end of file" APR_EOL_STR,
-               btn->header_encoding, btn->pool));
+
+      SVN_ERR(svn_utf_cstring_from_utf8_ex2(
+                &out_str, btn->no_newline_string,
+                btn->header_encoding, btn->pool));
       svn_stringbuf_appendcstr(btn->hunk, out_str);
     }
 
@@ -459,45 +460,19 @@ output_unified_flush_hunk(output_baton_t
   if (hunk_delimiter == NULL)
     hunk_delimiter = "@@";
 
-  /* Write the hunk header */
+  /* Convert our 0-based line numbers into unidiff 1-based numbers */
   if (baton->hunk_length[0] > 0)
-    /* Convert our 0-based line numbers into unidiff 1-based numbers */
     baton->hunk_start[0]++;
-  SVN_ERR(svn_stream_printf_from_utf8(
-            baton->output_stream, baton->header_encoding,
-            baton->pool,
-            /* Hunk length 1 is implied, don't show the
-               length field if we have a hunk that long */
-            (baton->hunk_length[0] == 1)
-            ? ("%s -%" APR_OFF_T_FMT)
-            : ("%s -%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT),
-            hunk_delimiter,
-            baton->hunk_start[0], baton->hunk_length[0]));
-
   if (baton->hunk_length[1] > 0)
-    /* Convert our 0-based line numbers into unidiff 1-based numbers */
     baton->hunk_start[1]++;
 
-
-  /* Hunk length 1 is implied, don't show the
-     length field if we have a hunk that long */
-  if (baton->hunk_length[1] == 1)
-    {
-      SVN_ERR(svn_stream_printf_from_utf8(
-                baton->output_stream, baton->header_encoding,
-                baton->pool,
-                " +%" APR_OFF_T_FMT " %s" APR_EOL_STR,
-                baton->hunk_start[1], hunk_delimiter));
-    }
-  else
-    {
-      SVN_ERR(svn_stream_printf_from_utf8(
-                baton->output_stream, baton->header_encoding,
-                baton->pool,
-                " +%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT " %s" APR_EOL_STR,
-                baton->hunk_start[1], baton->hunk_length[1],
-                hunk_delimiter));
-    }
+  /* Write the hunk header */
+  SVN_ERR(svn_diff__unified_write_hunk_header(
+            baton->output_stream, baton->header_encoding, hunk_delimiter,
+            baton->hunk_start[0], baton->hunk_length[0],
+            baton->hunk_start[1], baton->hunk_length[1],
+            NULL /* hunk_extra_context */,
+            baton->pool));
 
   hunk_len = baton->hunk->len;
   SVN_ERR(svn_stream_write(baton->output_stream,
@@ -586,6 +561,10 @@ svn_diff_mem_string_output_unified2(svn_
       baton.header_encoding = header_encoding;
       baton.hunk = svn_stringbuf_create_empty(pool);
       baton.hunk_delimiter = hunk_delimiter;
+      baton.no_newline_string
+        = (hunk_delimiter == NULL || strcmp(hunk_delimiter, "##") != 0)
+          ? APR_EOL_STR SVN_DIFF__NO_NEWLINE_AT_END_OF_FILE APR_EOL_STR
+          : APR_EOL_STR SVN_DIFF__NO_NEWLINE_AT_END_OF_PROPERTY APR_EOL_STR;
 
       SVN_ERR(svn_utf_cstring_from_utf8_ex2
               (&(baton.prefix_str[unified_output_context]), " ",
@@ -602,12 +581,9 @@ svn_diff_mem_string_output_unified2(svn_
 
       if (with_diff_header)
         {
-          SVN_ERR(svn_stream_printf_from_utf8(output_stream,
-                                              header_encoding, pool,
-                                              "--- %s" APR_EOL_STR
-                                              "+++ %s" APR_EOL_STR,
-                                              original_header,
-                                              modified_header));
+          SVN_ERR(svn_diff__unidiff_write_header(
+                    output_stream, header_encoding,
+                    original_header, modified_header, pool));
         }
 
       SVN_ERR(svn_diff_output(diff, &baton,

Modified: subversion/branches/tree-read-api/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_diff/parse-diff.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_diff/parse-diff.c Fri Nov 30 18:12:52 2012
@@ -555,15 +555,11 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
       pos = 0;
       SVN_ERR(svn_io_file_seek(apr_file, APR_CUR, &pos, iterpool));
 
-      /* Lines starting with a backslash are comments, such as
-       * "\ No newline at end of file". */
+      /* Lines starting with a backslash indicate a missing EOL:
+       * "\ No newline at end of file" or "end of property". */
       if (line->data[0] == '\\')
         {
-          if (in_hunk &&
-              ((!*is_property &&
-                strcmp(line->data, "\\ No newline at end of file") == 0) ||
-               (*is_property &&
-                strcmp(line->data, "\\ No newline at end of property") == 0)))
+          if (in_hunk)
             {
               char eolbuf[2];
               apr_size_t len;

Modified: subversion/branches/tree-read-api/subversion/libsvn_diff/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_diff/util.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_diff/util.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_diff/util.c Fri Nov 30 18:12:52 2012
@@ -25,14 +25,23 @@
 #include <apr.h>
 #include <apr_general.h>
 
+#include "svn_pools.h"
+#include "svn_dirent_uri.h"
+#include "svn_props.h"
+#include "svn_mergeinfo.h"
 #include "svn_error.h"
 #include "svn_diff.h"
 #include "svn_types.h"
 #include "svn_ctype.h"
+#include "svn_utf.h"
 #include "svn_version.h"
 
+#include "private/svn_diff_private.h"
 #include "diff.h"
 
+#include "svn_private_config.h"
+
+
 svn_boolean_t
 svn_diff_contains_conflicts(svn_diff_t *diff)
 {
@@ -332,6 +341,247 @@ svn_diff__normalize_buffer(char **tgt,
 #undef COPY_INCLUDED_SECTION
 }
 
+svn_error_t *
+svn_diff__unified_append_no_newline_msg(svn_stringbuf_t *stringbuf,
+                                        const char *header_encoding,
+                                        apr_pool_t *scratch_pool)
+{
+  const char *out_str;
+
+  SVN_ERR(svn_utf_cstring_from_utf8_ex2(
+            &out_str,
+            APR_EOL_STR
+            SVN_DIFF__NO_NEWLINE_AT_END_OF_FILE APR_EOL_STR,
+            header_encoding, scratch_pool));
+  svn_stringbuf_appendcstr(stringbuf, out_str);
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_diff__unified_write_hunk_header(svn_stream_t *output_stream,
+                                    const char *header_encoding,
+                                    const char *hunk_delimiter,
+                                    apr_off_t old_start,
+                                    apr_off_t old_length,
+                                    apr_off_t new_start,
+                                    apr_off_t new_length,
+                                    const char *hunk_extra_context,
+                                    apr_pool_t *scratch_pool)
+{
+  SVN_ERR(svn_stream_printf_from_utf8(output_stream, header_encoding,
+                                      scratch_pool,
+                                      "%s -%" APR_OFF_T_FMT,
+                                      hunk_delimiter, old_start));
+  /* If the hunk length is 1, suppress the number of lines in the hunk
+   * (it is 1 implicitly) */
+  if (old_length != 1)
+    {
+      SVN_ERR(svn_stream_printf_from_utf8(output_stream, header_encoding,
+                                          scratch_pool,
+                                          ",%" APR_OFF_T_FMT, old_length));
+    }
+
+  SVN_ERR(svn_stream_printf_from_utf8(output_stream, header_encoding,
+                                      scratch_pool,
+                                      " +%" APR_OFF_T_FMT, new_start));
+  if (new_length != 1)
+    {
+      SVN_ERR(svn_stream_printf_from_utf8(output_stream, header_encoding,
+                                          scratch_pool,
+                                          ",%" APR_OFF_T_FMT, new_length));
+    }
+
+  if (hunk_extra_context == NULL)
+      hunk_extra_context = "";
+  SVN_ERR(svn_stream_printf_from_utf8(output_stream, header_encoding,
+                                      scratch_pool,
+                                      " %s%s%s" APR_EOL_STR,
+                                      hunk_delimiter,
+                                      hunk_extra_context[0] ? " " : "",
+                                      hunk_extra_context));
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_diff__unidiff_write_header(svn_stream_t *output_stream,
+                               const char *header_encoding,
+                               const char *old_header,
+                               const char *new_header,
+                               apr_pool_t *scratch_pool)
+{
+  SVN_ERR(svn_stream_printf_from_utf8(output_stream, header_encoding,
+                                      scratch_pool,
+                                      "--- %s" APR_EOL_STR
+                                      "+++ %s" APR_EOL_STR,
+                                      old_header,
+                                      new_header));
+  return SVN_NO_ERROR;
+}
+
+/* A helper function for display_prop_diffs.  Output the differences between
+   the mergeinfo stored in ORIG_MERGEINFO_VAL and NEW_MERGEINFO_VAL in a
+   human-readable form to OUTSTREAM, using ENCODING.  Use POOL for temporary
+   allocations. */
+static svn_error_t *
+display_mergeinfo_diff(const char *old_mergeinfo_val,
+                       const char *new_mergeinfo_val,
+                       const char *encoding,
+                       svn_stream_t *outstream,
+                       apr_pool_t *pool)
+{
+  apr_hash_t *old_mergeinfo_hash, *new_mergeinfo_hash, *added, *deleted;
+  apr_pool_t *iterpool = svn_pool_create(pool);
+  apr_hash_index_t *hi;
+
+  if (old_mergeinfo_val)
+    SVN_ERR(svn_mergeinfo_parse(&old_mergeinfo_hash, old_mergeinfo_val, pool));
+  else
+    old_mergeinfo_hash = NULL;
+
+  if (new_mergeinfo_val)
+    SVN_ERR(svn_mergeinfo_parse(&new_mergeinfo_hash, new_mergeinfo_val, pool));
+  else
+    new_mergeinfo_hash = NULL;
+
+  SVN_ERR(svn_mergeinfo_diff2(&deleted, &added, old_mergeinfo_hash,
+                              new_mergeinfo_hash,
+                              TRUE, pool, pool));
+
+  for (hi = apr_hash_first(pool, deleted);
+       hi; hi = apr_hash_next(hi))
+    {
+      const char *from_path = svn__apr_hash_index_key(hi);
+      svn_rangelist_t *merge_revarray = svn__apr_hash_index_val(hi);
+      svn_string_t *merge_revstr;
+
+      svn_pool_clear(iterpool);
+      SVN_ERR(svn_rangelist_to_string(&merge_revstr, merge_revarray,
+                                      iterpool));
+
+      SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, iterpool,
+                                          _("   Reverse-merged %s:r%s%s"),
+                                          from_path, merge_revstr->data,
+                                          APR_EOL_STR));
+    }
+
+  for (hi = apr_hash_first(pool, added);
+       hi; hi = apr_hash_next(hi))
+    {
+      const char *from_path = svn__apr_hash_index_key(hi);
+      svn_rangelist_t *merge_revarray = svn__apr_hash_index_val(hi);
+      svn_string_t *merge_revstr;
+
+      svn_pool_clear(iterpool);
+      SVN_ERR(svn_rangelist_to_string(&merge_revstr, merge_revarray,
+                                      iterpool));
+
+      SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, iterpool,
+                                          _("   Merged %s:r%s%s"),
+                                          from_path, merge_revstr->data,
+                                          APR_EOL_STR));
+    }
+
+  svn_pool_destroy(iterpool);
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_diff__display_prop_diffs(svn_stream_t *outstream,
+                             const char *encoding,
+                             const apr_array_header_t *propchanges,
+                             apr_hash_t *original_props,
+                             svn_boolean_t pretty_print_mergeinfo,
+                             apr_pool_t *pool)
+{
+  apr_pool_t *iterpool = svn_pool_create(pool);
+  int i;
+
+  for (i = 0; i < propchanges->nelts; i++)
+    {
+      const char *action;
+      const svn_string_t *original_value;
+      const svn_prop_t *propchange
+        = &APR_ARRAY_IDX(propchanges, i, svn_prop_t);
+
+      if (original_props)
+        original_value = apr_hash_get(original_props,
+                                      propchange->name, APR_HASH_KEY_STRING);
+      else
+        original_value = NULL;
+
+      /* If the property doesn't exist on either side, or if it exists
+         with the same value, skip it.  This can happen if the client is
+         hitting an old mod_dav_svn server that doesn't understand the
+         "send-all" REPORT style. */
+      if ((! (original_value || propchange->value))
+          || (original_value && propchange->value
+              && svn_string_compare(original_value, propchange->value)))
+        continue;
+
+      svn_pool_clear(iterpool);
+
+      if (! original_value)
+        action = "Added";
+      else if (! propchange->value)
+        action = "Deleted";
+      else
+        action = "Modified";
+      SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, iterpool,
+                                          "%s: %s%s", action,
+                                          propchange->name, APR_EOL_STR));
+
+      if (pretty_print_mergeinfo
+          && strcmp(propchange->name, SVN_PROP_MERGEINFO) == 0)
+        {
+          const char *orig = original_value ? original_value->data : NULL;
+          const char *val = propchange->value ? propchange->value->data : NULL;
+          svn_error_t *err = display_mergeinfo_diff(orig, val, encoding,
+                                                    outstream, iterpool);
+
+          /* Issue #3896: If we can't pretty-print mergeinfo differences
+             because invalid mergeinfo is present, then don't let the diff
+             fail, just print the diff as any other property. */
+          if (err && err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)
+            {
+              svn_error_clear(err);
+            }
+          else
+            {
+              SVN_ERR(err);
+              continue;
+            }
+        }
+
+      {
+        svn_diff_t *diff;
+        svn_diff_file_options_t options = { 0 };
+        const svn_string_t *orig
+          = original_value ? original_value
+                           : svn_string_create_empty(iterpool);
+        const svn_string_t *val
+          = propchange->value ? propchange->value
+                              : svn_string_create_empty(iterpool);
+
+        SVN_ERR(svn_diff_mem_string_diff(&diff, orig, val, &options,
+                                         iterpool));
+
+        /* UNIX patch will try to apply a diff even if the diff header
+         * is missing. It tries to be helpful by asking the user for a
+         * target filename when it can't determine the target filename
+         * from the diff header. But there usually are no files which
+         * UNIX patch could apply the property diff to, so we use "##"
+         * instead of "@@" as the default hunk delimiter for property diffs.
+         * We also supress the diff header. */
+        SVN_ERR(svn_diff_mem_string_output_unified2(
+                  outstream, diff, FALSE /* no header */, "##", NULL, NULL,
+                  encoding, orig, val, iterpool));
+      }
+    }
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
 
 /* Return the library version number. */
 const svn_version_t *

Modified: subversion/branches/tree-read-api/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_fs_fs/fs_fs.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_fs_fs/fs_fs.c Fri Nov 30 18:12:52 2012
@@ -2238,8 +2238,10 @@ get_cached_node_revision_body(node_revis
     }
   else
     {
-      pair_cache_key_t key = { svn_fs_fs__id_rev(id),
-                               svn_fs_fs__id_offset(id) };
+      pair_cache_key_t key;
+
+      key.revision = svn_fs_fs__id_rev(id);
+      key.second = svn_fs_fs__id_offset(id);
       SVN_ERR(svn_cache__get((void **) noderev_p,
                             is_cached,
                             ffd->node_revision_cache,
@@ -2265,8 +2267,10 @@ set_cached_node_revision_body(node_revis
 
   if (ffd->node_revision_cache && !svn_fs_fs__id_txn_id(id))
     {
-      pair_cache_key_t key = { svn_fs_fs__id_rev(id),
-                               svn_fs_fs__id_offset(id) };
+      pair_cache_key_t key;
+
+      key.revision = svn_fs_fs__id_rev(id);
+      key.second = svn_fs_fs__id_offset(id);
       return svn_cache__set(ffd->node_revision_cache,
                             &key,
                             noderev_p,
@@ -3529,9 +3533,11 @@ parse_revprop(apr_hash_t **properties,
   SVN_ERR(svn_hash_read2(*properties, stream, SVN_HASH_TERMINATOR, pool));
   if (has_revprop_cache(fs, pool))
     {
-      pair_cache_key_t key = {revision, generation};
       fs_fs_data_t *ffd = fs->fsap_data;
+      pair_cache_key_t key;
 
+      key.revision = revision;
+      key.second = generation;
       SVN_ERR(svn_cache__set(ffd->revprop_cache, &key, *properties,
                              scratch_pool));
     }
@@ -3831,10 +3837,11 @@ get_revision_proplist(apr_hash_t **propl
   if (has_revprop_cache(fs, pool))
     {
       svn_boolean_t is_cached;
-      pair_cache_key_t key = { rev, 0};
+      pair_cache_key_t key;
 
       SVN_ERR(read_revprop_generation(&generation, fs, pool));
 
+      key.revision = rev;
       key.second = generation;
       SVN_ERR(svn_cache__get((void **) proplist_p, &is_cached,
                              ffd->revprop_cache, &key, pool));
@@ -5183,10 +5190,12 @@ read_representation(svn_stream_t **conte
   else
     {
       fs_fs_data_t *ffd = fs->fsap_data;
-      pair_cache_key_t fulltext_cache_key = {rep->revision, rep->offset};
+      pair_cache_key_t fulltext_cache_key;
       svn_filesize_t len = rep->expanded_size ? rep->expanded_size : rep->size;
       struct rep_read_baton *rb;
 
+      fulltext_cache_key.revision = rep->revision;
+      fulltext_cache_key.second = rep->offset;
       if (ffd->fulltext_cache && SVN_IS_VALID_REVNUM(rep->revision)
           && fulltext_size_is_cachable(ffd, len))
         {
@@ -5355,14 +5364,18 @@ svn_fs_fs__try_process_file_contents(svn
   if (rep)
     {
       fs_fs_data_t *ffd = fs->fsap_data;
-      pair_cache_key_t fulltext_cache_key = {rep->revision, rep->offset};
+      pair_cache_key_t fulltext_cache_key;
 
+      fulltext_cache_key.revision = rep->revision;
+      fulltext_cache_key.second = rep->offset;
       if (ffd->fulltext_cache && SVN_IS_VALID_REVNUM(rep->revision)
           && fulltext_size_is_cachable(ffd, rep->expanded_size))
         {
-          cache_access_wrapper_baton_t wrapper_baton = {processor, baton};
+          cache_access_wrapper_baton_t wrapper_baton;
           void *dummy = NULL;
 
+          wrapper_baton.func = processor;
+          wrapper_baton.baton = baton;
           return svn_cache__get_partial(&dummy, success,
                                         ffd->fulltext_cache,
                                         &fulltext_cache_key,
@@ -5658,8 +5671,10 @@ svn_fs_fs__get_proplist(apr_hash_t **pro
     {
       fs_fs_data_t *ffd = fs->fsap_data;
       representation_t *rep = noderev->prop_rep;
-      
-      pair_cache_key_t key = { rep->revision, rep->offset };
+      pair_cache_key_t key;
+
+      key.revision = rep->revision;
+      key.second = rep->offset;
       if (ffd->properties_cache && SVN_IS_VALID_REVNUM(rep->revision))
         {
           svn_boolean_t is_cached;

Modified: subversion/branches/tree-read-api/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_fs_fs/temp_serializer.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_fs_fs/temp_serializer.c Fri Nov 30 18:12:52 2012
@@ -88,27 +88,6 @@ svn_fs_fs__combine_number_and_string(apr
   return key;
 }
 
-const char*
-svn_fs_fs__combine_two_numbers(apr_int64_t a,
-                               apr_int64_t b,
-                               apr_pool_t *pool)
-{
-  /* encode numbers as 2x 10x7 bits + 1 space + 1 terminating \0*/
-  char *key_buffer = apr_palloc(pool, 22);
-  const char *key = key_buffer;
-
-  /* combine the numbers. Since the separator is disjoint from any part
-   * of the encoded numbers, there is no other combination that can yield
-   * the same result */
-  key_buffer = encode_number(a, key_buffer);
-  *++key_buffer = ' ';
-  key_buffer = encode_number(b, ++key_buffer);
-  *++key_buffer = '\0';
-
-  /* return the start of the key */
-  return key;
-}
-
 /* Utility function to serialize string S in the given serialization CONTEXT.
  */
 static void

Modified: subversion/branches/tree-read-api/subversion/libsvn_fs_fs/temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_fs_fs/temp_serializer.h?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_fs_fs/temp_serializer.h (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_fs_fs/temp_serializer.h Fri Nov 30 18:12:52 2012
@@ -36,16 +36,6 @@ svn_fs_fs__combine_number_and_string(apr
                                      apr_pool_t *pool);
 
 /**
- * Combine the numbers @a a and @a b in a space efficient way such that no
- * other combination of numbers can produce the same result.
- * Allocate temporaries as well as the result from @a pool.
- */
-const char*
-svn_fs_fs__combine_two_numbers(apr_int64_t a,
-                               apr_int64_t b,
-                               apr_pool_t *pool);
-
-/**
  * Serialize a @a noderev_p within the serialization @a context.
  */
 void

Modified: subversion/branches/tree-read-api/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_fs_fs/tree.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_fs_fs/tree.c Fri Nov 30 18:12:52 2012
@@ -3243,7 +3243,7 @@ prev_location(const char **prev_path,
   */
   SVN_ERR(fs_copied_from(&copy_src_rev, &copy_src_path,
                          copy_root, copy_path, pool));
-  remainder_path = svn_relpath_skip_ancestor(copy_path, path);
+  remainder_path = svn_fspath__skip_ancestor(copy_path, path);
   *prev_path = svn_fspath__join(copy_src_path, remainder_path, pool);
   *prev_rev = copy_src_rev;
   return SVN_NO_ERROR;

Modified: subversion/branches/tree-read-api/subversion/libsvn_ra_serf/inherited_props.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_ra_serf/inherited_props.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_ra_serf/inherited_props.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_ra_serf/inherited_props.c Fri Nov 30 18:12:52 2012
@@ -277,8 +277,7 @@ svn_ra_serf__get_inherited_props(svn_ra_
                                  apr_pool_t *result_pool,
                                  apr_pool_t *scratch_pool)
 {
-  svn_error_t *err, *err2;
-
+  svn_error_t *err;
   iprops_context_t *iprops_ctx;
   svn_ra_serf__session_t *session = ra_session->priv;
   svn_ra_serf__handler_t *handler;
@@ -293,6 +292,8 @@ svn_ra_serf__get_inherited_props(svn_ra_
                                       revision,
                                       result_pool, scratch_pool));
 
+  SVN_ERR_ASSERT(session->repos_root_str);
+
   iprops_ctx = apr_pcalloc(scratch_pool, sizeof(*iprops_ctx));
   iprops_ctx->done = FALSE;
   iprops_ctx->repos_root_url = session->repos_root_str;
@@ -329,20 +330,12 @@ svn_ra_serf__get_inherited_props(svn_ra_
   handler->response_handler = svn_ra_serf__handle_xml_parser;
   handler->response_baton = parser_ctx;
 
-  svn_ra_serf__request_create(handler);
-
-  err = svn_ra_serf__context_run_wait(&iprops_ctx->done, session,
-                                      scratch_pool);
-
-  err2 = svn_ra_serf__error_on_status(handler->sline.code, handler->path,
-                                      handler->location);
-  if (err2)
-    {
-      svn_error_clear(err);
-      return err2;
-    }
-
-  SVN_ERR(err);
+  err = svn_ra_serf__context_run_one(handler, scratch_pool);
+  SVN_ERR(svn_error_compose_create(
+                    svn_ra_serf__error_on_status(handler->sline.code,
+                                                 handler->path,
+                                                 handler->location),
+                    err));
 
   if (iprops_ctx->done)
     *iprops = iprops_ctx->iprops;

Modified: subversion/branches/tree-read-api/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_ra_serf/ra_serf.h?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_ra_serf/ra_serf.h Fri Nov 30 18:12:52 2012
@@ -189,7 +189,7 @@ struct svn_ra_serf__session_t {
   const char *uuid;
 
   /* Connection timeout value */
-  apr_short_interval_time_t timeout;
+  apr_interval_time_t timeout;
 
   /* HTTPv1 flags */
   svn_tristate_t supports_deadprop_count;

Modified: subversion/branches/tree-read-api/subversion/libsvn_ra_serf/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_ra_serf/replay.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_ra_serf/replay.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_ra_serf/replay.c Fri Nov 30 18:12:52 2012
@@ -732,7 +732,7 @@ svn_ra_serf__replay_range(svn_ra_session
   svn_revnum_t rev = start_revision;
   const char *report_target;
   int active_reports = 0;
-  apr_short_interval_time_t waittime_left = session->timeout;
+  apr_interval_time_t waittime_left = session->timeout;
 
   SVN_ERR(svn_ra_serf__report_resource(&report_target, session, NULL, pool));
 
@@ -873,14 +873,17 @@ svn_ra_serf__replay_range(svn_ra_session
           err = SVN_NO_ERROR;
           status = 0;
 
-          if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
+          if (session->timeout)
             {
-              waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
-            }
-          else
-            {
-              return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
-                                      _("Connection timed out"));
+              if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
+                {
+                  waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
+                }
+              else
+                {
+                  return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
+                                          _("Connection timed out"));
+                }
             }
         }
       else

Modified: subversion/branches/tree-read-api/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_ra_serf/serf.c?rev=1415773&r1=1415772&r2=1415773&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_ra_serf/serf.c Fri Nov 30 18:12:52 2012
@@ -131,7 +131,11 @@ load_http_auth_types(apr_pool_t *pool, s
 
   return SVN_NO_ERROR;
 }
-#define DEFAULT_HTTP_TIMEOUT 3600
+
+/* Default HTTP timeout (in seconds); overridden by the 'http-timeout'
+   runtime configuration variable. */
+#define DEFAULT_HTTP_TIMEOUT 600
+
 static svn_error_t *
 load_config(svn_ra_serf__session_t *session,
             apr_hash_t *config_hash,
@@ -253,6 +257,7 @@ load_config(svn_ra_serf__session_t *sess
     }
 
   /* Parse the connection timeout value, if any. */
+  session->timeout = apr_time_from_sec(DEFAULT_HTTP_TIMEOUT);
   if (timeout_str)
     {
       char *endstr;
@@ -267,13 +272,7 @@ load_config(svn_ra_serf__session_t *sess
                                 _("Invalid config: negative timeout value"));
       session->timeout = apr_time_from_sec(timeout);
     }
-  else
-    session->timeout = apr_time_from_sec(DEFAULT_HTTP_TIMEOUT);
-
-  if (session->timeout < 0) /* Always true for DEFAULT_HTTP_TIMEOUT */
-    session->timeout = apr_time_from_sec(600); /* 10 min */
-
-  SVN_ERR_ASSERT(session->timeout > 0);
+  SVN_ERR_ASSERT(session->timeout >= 0);
 
   /* Convert the proxy port value, if any. */
   if (port_str)