You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2014/01/09 10:31:15 UTC

svn commit: r1556765 [2/12] - in /subversion/branches/fsfs-ucsnorm: ./ contrib/server-side/fsfsfixer/fixer/ subversion/bindings/javahl/native/ subversion/bindings/javahl/native/jniwrapper/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ su...

Modified: subversion/branches/fsfs-ucsnorm/subversion/include/svn_ra.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/include/svn_ra.h?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/include/svn_ra.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/include/svn_ra.h Thu Jan  9 09:31:10 2014
@@ -792,6 +792,32 @@ svn_ra_open(svn_ra_session_t **session_p
             apr_hash_t *config,
             apr_pool_t *pool);
 
+/**
+ * Open a new ra session @a *new_session to the same repository as an existing
+ * ra session @a old_session, copying the callbacks, auth baton, etc. from the
+ * old session. This essentially limits the lifetime of the new, duplicated
+ * session to the lifetime of the old session. If the new session should
+ * outlive the new session, creating a new session using svn_ra_open4() is
+ * recommended.
+ *
+ * If @a session_url is not NULL, parent the new session at session_url. Note
+ * that @a session_url MUST BE in the same repository as @a old_session or an
+ * error will be returned. When @a session_url NULL the same session root
+ * will be used.
+ *
+ * Allocate @a new_session in @a result_pool. Perform temporary allocations
+ * in @a scratch_pool.
+ *
+ * @since New in 1.9.
+ */
+svn_error_t *
+svn_ra_dup_session(svn_ra_session_t **new_session,
+                   svn_ra_session_t *old_session,
+                   const char *session_url,
+                   apr_pool_t *result_pool,
+                   apr_pool_t *scratch_pool);
+
+
 /** Change the root URL of an open @a ra_session to point to a new path in the
  * same repository.  @a url is the new root URL.  Use @a pool for
  * temporary allocations.

Modified: subversion/branches/fsfs-ucsnorm/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/include/svn_repos.h?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/include/svn_repos.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/include/svn_repos.h Thu Jan  9 09:31:10 2014
@@ -287,14 +287,6 @@ typedef enum svn_repos_notify_warning_t
   svn_repos_notify_warning_invalid_fspath,
 
   /**
-   * Found a denormalized name. Reported when the name of a directoy
-   * entry is not normalized to Unicode Normalization Form C.
-   *
-   * @since New in 1.9.
-   */
-  svn_repos_notify_warning_denormalized_name,
-
-  /**
    * Detected a name collision. Reported when the names of two or more
    * entries in the same directory differ only in character
    * representation (normalization), but are otherwise identical.
@@ -304,15 +296,6 @@ typedef enum svn_repos_notify_warning_t
   svn_repos_notify_warning_name_collision,
 
   /**
-   * Found a denormalized mergeinfo entry. Reported when the path in
-   * an entry in the svn:mergeinfo property is not normalized to
-   * Unicode Normalization Form C.
-   *
-   * @since New in 1.9.
-   */
-  svn_repos_notify_warning_denormalized_mergeinfo,
-
-  /**
    * Detected a mergeinfo path collision. Reported when the paths in
    * two or more entries in the same svn:mergeinfo property differ
    * only in character representation (normalization), but are
@@ -2694,11 +2677,10 @@ svn_repos_info_format(int *repos_format,
  * not notified. Finally, return an error if there were any failures during
  * verification, or SVN_NO_ERROR if there were no failures.
  *
- * If @a check_normalization is @c TRUE, verify that all path names in
- * the repository and in @c svn:mergeinfo entries are normaized to
- * Unicode Normalization Form C, and report any name collisions within
- * the same directory or svn:mergeinfo property where the names differ
- * only in character representation, but are otherwise identical.
+ * If @a check_normalization is @c TRUE, report any name collisions
+ * within the same directory or svn:mergeinfo property where the names
+ * differ only in character representation, but are otherwise
+ * identical.
  *
  * @since New in 1.9.
  */

Modified: subversion/branches/fsfs-ucsnorm/subversion/include/svn_sorts.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/include/svn_sorts.h?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/include/svn_sorts.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/include/svn_sorts.h Thu Jan  9 09:31:10 2014
@@ -52,16 +52,7 @@ extern "C" {
 /** This structure is used to hold a key/value from a hash table.
  * @note Private. For use by Subversion's own code only. See issue #1644.
  */
-typedef struct svn_sort__item_t {
-  /** pointer to the key */
-  const void *key;
-
-  /** size of the key */
-  apr_ssize_t klen;
-
-  /** pointer to the value */
-  void *value;
-} svn_sort__item_t;
+typedef struct svn_sort__item_t svn_sort__item_t;
 
 
 /** Compare two @c svn_sort__item_t's, returning an integer greater than,
@@ -149,145 +140,6 @@ int
 svn_sort_compare_ranges(const void *a,
                         const void *b);
 
-/** Sort @a ht according to its keys, return an @c apr_array_header_t
- * containing @c svn_sort__item_t structures holding those keys and values
- * (i.e. for each @c svn_sort__item_t @a item in the returned array,
- * @a item->key and @a item->size are the hash key, and @a item->value points to
- * the hash value).
- *
- * Storage is shared with the original hash, not copied.
- *
- * @a comparison_func should take two @c svn_sort__item_t's and return an
- * integer greater than, equal to, or less than 0, according as the first item
- * is greater than, equal to, or less than the second.
- *
- * @note Private. For use by Subversion's own code only. See issue #1644.
- *
- * @note This function and the @c svn_sort__item_t should go over to APR.
- */
-apr_array_header_t *
-svn_sort__hash(apr_hash_t *ht,
-               int (*comparison_func)(const svn_sort__item_t *,
-                                      const svn_sort__item_t *),
-               apr_pool_t *pool);
-
-/* Return the lowest index at which the element @a *key should be inserted into
- * the array @a array, according to the ordering defined by @a compare_func.
- * The array must already be sorted in the ordering defined by @a compare_func.
- * @a compare_func is defined as for the C stdlib function bsearch(); the
- * @a key will always passed to it as the second parameter.
- *
- * @note Private. For use by Subversion's own code only.
- */
-int
-svn_sort__bsearch_lower_bound(const void *key,
-                              const apr_array_header_t *array,
-                              int (*compare_func)(const void *, const void *));
-
-/* Insert a shallow copy of @a *new_element into the array @a array at the index
- * @a insert_index, growing the array and shuffling existing elements along to
- * make room.
- *
- * @note Private. For use by Subversion's own code only.
- */
-void
-svn_sort__array_insert(const void *new_element,
-                       apr_array_header_t *array,
-                       int insert_index);
-
-
-/* Remove @a elements_to_delete elements starting at @a delete_index from the
- * array @a arr. If @a delete_index is not a valid element of @a arr,
- * @a elements_to_delete is not greater than zero, or
- * @a delete_index + @a elements_to_delete is greater than @a arr->nelts,
- * then do nothing.
- *
- * @note Private. For use by Subversion's own code only.
- */
-void
-svn_sort__array_delete(apr_array_header_t *arr,
-                       int delete_index,
-                       int elements_to_delete);
-
-/* Reverse the order of elements in @a array, in place.
- *
- * @note Private. For use by Subversion's own code only.
- */
-void
-svn_sort__array_reverse(apr_array_header_t *array,
-                        apr_pool_t *scratch_pool);
-
-/** Priority queues.
- *
- * @defgroup svn_priority_queue__t Priority Queues
- * @{
- */
-
-/**
- * We implement priority queues on top of existing ELEMENTS arrays.  They
- * provide us with memory management and very basic element type information.
- *
- * The extraction order is being defined by a comparison function similar
- * to the ones used with qsort.  The first element in the queue is always
- * on with COMPARISON_FUNC(first,element) <= 0, for all elements in the
- * queue.
- */
-
-/**
- * Opaque data type for priority queues.
- */
-typedef struct svn_priority_queue__t svn_priority_queue__t;
-
-/**
- * Return a priority queue containing all provided @a elements and prioritize
- * them according to @a compare_func.
- *
- * @note The priority queue will use the existing @a elements array for data
- * storage.  So, you must not manipulate that array while using the queue.
- * Also, the lifetime of the queue is bound to that of the array.
- */
-svn_priority_queue__t *
-svn_priority_queue__create(apr_array_header_t *elements,
-                           int (*compare_func)(const void *, const void *));
-
-/**
- * Returns the number of elements in the @a queue.
- */
-apr_size_t
-svn_priority_queue__size(svn_priority_queue__t *queue);
-
-/**
- * Returns a reference to the first element in the @a queue.  The queue
- * contents remains unchanged.  If the @a queue is empty, #NULL will be
- * returned.
- */
-void *
-svn_priority_queue__peek(svn_priority_queue__t *queue);
-
-/**
- * Notify the @a queue after modifying the first item as returned by
- * #svn_priority_queue__peek.
- */
-void
-svn_priority_queue__update(svn_priority_queue__t *queue);
-
-/**
- * Remove the first element from the @a queue.  This is a no-op for empty
- * queues.
- */
-void
-svn_priority_queue__pop(svn_priority_queue__t *queue);
-
-/**
- * Append the new @a element to the @a queue.  @a element must neither be
- * #NULL nor the first element as returned by #svn_priority_queue__peek.
- */
-void
-svn_priority_queue__push(svn_priority_queue__t *queue, const void *element);
-
-/** @} */
-
-
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/fsfs-ucsnorm/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/include/svn_wc.h?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/include/svn_wc.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/include/svn_wc.h Thu Jan  9 09:31:10 2014
@@ -1264,7 +1264,11 @@ typedef enum svn_wc_notify_action_t
   /** The operation failed because the operation (E.g. commit) is only valid
    * if the operation includes this path.
    * @since New in 1.9. */
-  svn_wc_notify_failed_requires_target
+  svn_wc_notify_failed_requires_target,
+
+  /** Running info on an external module.
+   * @since New in 1.9. */
+  svn_wc_notify_info_external
 
 } svn_wc_notify_action_t;
 
@@ -7353,11 +7357,14 @@ svn_wc_cleanup4(svn_wc_context_t *wc_ctx
                 svn_boolean_t vacuum_pristines,
                 svn_cancel_func_t cancel_func,
                 void *cancel_baton,
+                svn_wc_notify_func2_t notify_func,
+                void *notify_baton,
                 apr_pool_t *scratch_pool);
 
 /**
  * Similar to svn_wc_cleanup4() but will always break locks, fix recorded
- * timestamps, clear the dav cache and vacuum pristines.
+ * timestamps, clear the dav cache and vacuum pristines. This function also
+ * doesn't support notifications.
  *
  * @since New in 1.7.
  * @deprecated Provided for backward compatibility with the 1.8 API.

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/cleanup.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/cleanup.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/cleanup.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/cleanup.c Thu Jan  9 09:31:10 2014
@@ -82,6 +82,7 @@ do_cleanup(const char *local_abspath,
                           clear_dav_cache,
                           vacuum_pristines,
                           ctx->cancel_func, ctx->cancel_baton,
+                          ctx->notify_func2, ctx->notify_baton2,
                           scratch_pool));
 
   if (fix_timestamps)

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/client.h?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/client.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/client.h Thu Jan  9 09:31:10 2014
@@ -93,12 +93,17 @@ svn_client__get_revision_number(svn_revn
 /* Set *ORIGINAL_REPOS_RELPATH and *ORIGINAL_REVISION to the original location
    that served as the source of the copy from which PATH_OR_URL at REVISION was
    created, or NULL and SVN_INVALID_REVNUM (respectively) if PATH_OR_URL at
-   REVISION was not the result of a copy operation. */
+   REVISION was not the result of a copy operation.
+
+   If RA_SESSION is not NULL it is an existing session to the repository that
+   might be reparented temporarily to obtain the information.
+   */
 svn_error_t *
 svn_client__get_copy_source(const char **original_repos_relpath,
                             svn_revnum_t *original_revision,
                             const char *path_or_url,
                             const svn_opt_revision_t *revision,
+                            svn_ra_session_t *ra_session,
                             svn_client_ctx_t *ctx,
                             apr_pool_t *result_pool,
                             apr_pool_t *scratch_pool);
@@ -938,18 +943,6 @@ svn_client__condense_commit_items(const 
                                   apr_array_header_t *commit_items,
                                   apr_pool_t *pool);
 
-
-/* Like svn_ra_stat() on the ra session root, but with a compatibility
-   hack for pre-1.2 svnserve that don't support this api. */
-svn_error_t *
-svn_client__ra_stat_compatible(svn_ra_session_t *ra_session,
-                               svn_revnum_t rev,
-                               svn_dirent_t **dirent_p,
-                               apr_uint32_t dirent_fields,
-                               svn_client_ctx_t *ctx,
-                               apr_pool_t *result_pool);
-
-
 /* Commit the items in the COMMIT_ITEMS array using EDITOR/EDIT_BATON
    to describe the committed local mods.  Prior to this call,
    COMMIT_ITEMS should have been run through (and BASE_URL generated

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/cmdline.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/cmdline.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/cmdline.c Thu Jan  9 09:31:10 2014
@@ -87,7 +87,7 @@ check_root_url_of_target(const char **ro
       if ((err->apr_err == SVN_ERR_ENTRY_NOT_FOUND)
           || (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
           || (err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY)
-          || (err->apr_err == SVN_ERR_RA_LOCAL_REPOS_OPEN_FAILED)
+          || (err->apr_err == SVN_ERR_RA_CANNOT_CREATE_SESSION)
           || (err->apr_err == SVN_ERR_CLIENT_BAD_REVISION))
         {
           svn_error_clear(err);

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/commit_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/commit_util.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/commit_util.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/commit_util.c Thu Jan  9 09:31:10 2014
@@ -62,10 +62,12 @@ fixup_commit_error(const char *local_abs
                    apr_pool_t *scratch_pool)
 {
   if (err->apr_err == SVN_ERR_FS_NOT_FOUND
+      || err->apr_err == SVN_ERR_FS_CONFLICT
       || err->apr_err == SVN_ERR_FS_ALREADY_EXISTS
       || err->apr_err == SVN_ERR_FS_TXN_OUT_OF_DATE
       || err->apr_err == SVN_ERR_RA_DAV_PATH_NOT_FOUND
       || err->apr_err == SVN_ERR_RA_DAV_ALREADY_EXISTS
+      || err->apr_err == SVN_ERR_RA_DAV_PRECONDITION_FAILED
       || svn_error_find_cause(err, SVN_ERR_RA_OUT_OF_DATE))
     {
       if (ctx->notify_func2)
@@ -102,6 +104,7 @@ fixup_commit_error(const char *local_abs
     }
   else if (svn_error_find_cause(err, SVN_ERR_FS_NO_LOCK_TOKEN)
            || err->apr_err == SVN_ERR_FS_LOCK_OWNER_MISMATCH
+           || err->apr_err == SVN_ERR_FS_BAD_LOCK_TOKEN
            || err->apr_err == SVN_ERR_RA_NOT_LOCKED)
     {
       if (ctx->notify_func2)
@@ -768,9 +771,11 @@ harvest_status_callback(void *status_bat
            && !(state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE))
     {
       svn_revnum_t dir_rev = SVN_INVALID_REVNUM;
+      const char *dir_repos_relpath = NULL;
 
-      if (!copy_mode_root && !status->switched && !is_added)
-        SVN_ERR(svn_wc__node_get_base(NULL, &dir_rev, NULL, NULL, NULL, NULL,
+      if (!copy_mode_root && !is_added)
+        SVN_ERR(svn_wc__node_get_base(NULL, &dir_rev, &dir_repos_relpath, NULL,
+                                      NULL, NULL,
                                       wc_ctx, svn_dirent_dirname(local_abspath,
                                                                  scratch_pool),
                                       FALSE /* ignore_enoent */,
@@ -794,6 +799,25 @@ harvest_status_callback(void *status_bat
               cf_rev = status->revision;
               cf_relpath = status->repos_relpath;
             }
+
+          if (!copy_mode_root && !is_added && baton->check_url_func
+              && dir_repos_relpath)
+            {
+              svn_node_kind_t me_kind;
+              /* Maybe we need to issue an delete (mixed rev/switched) */
+
+              SVN_ERR(baton->check_url_func(
+                            baton->check_url_baton, &me_kind,
+                            svn_path_url_add_component2(repos_root_url,
+                                        svn_relpath_join(dir_repos_relpath,
+                                            svn_dirent_basename(local_abspath,
+                                                                NULL),
+                                            scratch_pool),
+                                        scratch_pool),
+                                        dir_rev, scratch_pool));
+              if (me_kind != svn_node_none)
+                state_flags |= SVN_CLIENT_COMMIT_ITEM_DELETE;
+            }
         }
     }
 
@@ -1470,6 +1494,7 @@ struct file_mod_t
 {
   const svn_client_commit_item3_t *item;
   void *file_baton;
+  apr_pool_t *file_pool;
 };
 
 
@@ -1535,6 +1560,9 @@ do_item_commit(void **dir_baton,
   else
     file_pool = pool;
 
+  /* Subpools are cheap, but memory isn't */
+  file_pool = svn_pool_create(file_pool); 
+
   /* Call the cancellation function. */
   if (ctx->cancel_func)
     SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
@@ -1618,6 +1646,7 @@ do_item_commit(void **dir_baton,
       else
         notify = NULL;
 
+
       if (notify)
         {
           notify->kind = item->kind;
@@ -1783,6 +1812,7 @@ do_item_commit(void **dir_baton,
       /* Add this file mod to the FILE_MODS hash. */
       mod->item = item;
       mod->file_baton = file_baton;
+      mod->file_pool = file_pool;
       svn_hash_sets(file_mods, item->session_relpath, mod);
     }
   else if (file_baton)
@@ -1790,7 +1820,7 @@ do_item_commit(void **dir_baton,
       /* Close any outstanding file batons that didn't get caught by
          the "has local mods" conditional above. */
       err = editor->close_file(file_baton, NULL, file_pool);
-
+      svn_pool_destroy(file_pool);
       if (err)
         goto fixup_error;
     }
@@ -1905,6 +1935,8 @@ svn_client__do_commit(const char *base_u
 
       if (sha1_checksums)
         svn_hash_sets(*sha1_checksums, item->path, new_text_base_sha1_checksum);
+
+      svn_pool_destroy(mod->file_pool);
     }
 
   svn_pool_destroy(iterpool);

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/copy.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/copy.c Thu Jan  9 09:31:10 2014
@@ -315,6 +315,8 @@ do_wc_to_wc_moves(svn_boolean_t *timesta
     {
       const char *src_parent_abspath;
       svn_boolean_t lock_src, lock_dst;
+      const char *src_wcroot_abspath;
+      const char *dst_wcroot_abspath;
 
       svn_client__copy_pair_t *pair = APR_ARRAY_IDX(copy_pairs, i,
                                                     svn_client__copy_pair_t *);
@@ -327,6 +329,13 @@ do_wc_to_wc_moves(svn_boolean_t *timesta
       src_parent_abspath = svn_dirent_dirname(pair->src_abspath_or_url,
                                               iterpool);
 
+      SVN_ERR(svn_wc__get_wcroot(&src_wcroot_abspath,
+                                 ctx->wc_ctx, src_parent_abspath,
+                                 iterpool, iterpool));
+      SVN_ERR(svn_wc__get_wcroot(&dst_wcroot_abspath,
+                                 ctx->wc_ctx, pair->dst_parent_abspath,
+                                 iterpool, iterpool));
+
       /* We now need to lock the right combination of batons.
          Four cases:
            1) src_parent == dst_parent
@@ -335,15 +344,18 @@ do_wc_to_wc_moves(svn_boolean_t *timesta
            4) src_parent and dst_parent are disjoint
          We can handle 1) as either 2) or 3) */
       if (strcmp(src_parent_abspath, pair->dst_parent_abspath) == 0
-          || svn_dirent_is_child(src_parent_abspath, pair->dst_parent_abspath,
-                                 iterpool))
+          || (svn_dirent_is_child(src_parent_abspath, pair->dst_parent_abspath,
+                                  NULL)
+              && !svn_dirent_is_child(src_parent_abspath, dst_wcroot_abspath,
+                                      NULL)))
         {
           lock_src = TRUE;
           lock_dst = FALSE;
         }
       else if (svn_dirent_is_child(pair->dst_parent_abspath,
-                                   src_parent_abspath,
-                                   iterpool))
+                                   src_parent_abspath, NULL)
+               && !svn_dirent_is_child(pair->dst_parent_abspath,
+                                       src_wcroot_abspath, NULL))
         {
           lock_src = FALSE;
           lock_dst = TRUE;
@@ -1230,7 +1242,9 @@ wc_to_repos_copy(const apr_array_header_
   const char *top_src_abspath;
   svn_ra_session_t *ra_session;
   const svn_delta_editor_t *editor;
+#ifdef ENABLE_EV2_SHIMS
   apr_hash_t *relpath_map = NULL;
+#endif
   void *edit_baton;
   svn_client__committables_t *committables;
   apr_array_header_t *commit_items;
@@ -1480,22 +1494,17 @@ wc_to_repos_copy(const apr_array_header_
     }
 #endif
 
-  /* Close the initial session, to reopen a new session with commit handling */
-  svn_pool_clear(session_pool);
-
-  /* Open a new RA session to DST_URL. */
-  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, top_dst_url,
-                                               NULL, commit_items,
-                                               FALSE, FALSE, ctx,
-                                               session_pool, session_pool));
+  SVN_ERR(svn_ra_reparent(ra_session, top_dst_url, session_pool));
 
   SVN_ERR(svn_client__ensure_revprop_table(&commit_revprops, revprop_table,
                                            message, ctx, session_pool));
 
   /* Fetch RA commit editor. */
+#ifdef ENABLE_EV2_SHIMS
   SVN_ERR(svn_ra__register_editor_shim_callbacks(ra_session,
                         svn_client__get_shim_callbacks(ctx->wc_ctx, relpath_map,
                                                        session_pool)));
+#endif
   SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
                                     commit_revprops,
                                     commit_callback,

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/deprecated.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/deprecated.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/deprecated.c Thu Jan  9 09:31:10 2014
@@ -2524,6 +2524,32 @@ svn_client_checkout(svn_revnum_t *result
 
 /*** From info.c ***/
 
+svn_error_t *
+svn_client_info3(const char *abspath_or_url,
+                 const svn_opt_revision_t *peg_revision,
+                 const svn_opt_revision_t *revision,
+                 svn_depth_t depth,
+                 svn_boolean_t fetch_excluded,
+                 svn_boolean_t fetch_actual_only,
+                 const apr_array_header_t *changelists,
+                 svn_client_info_receiver2_t receiver,
+                 void *receiver_baton,
+                 svn_client_ctx_t *ctx,
+                 apr_pool_t *pool)
+{
+  return svn_error_trace(
+            svn_client_info4(abspath_or_url,
+                             peg_revision,
+                             revision,
+                             depth,
+                             fetch_excluded,
+                             fetch_actual_only,
+                             FALSE /* include_externals */,
+                             changelists,
+                             receiver, receiver_baton,
+                             ctx, pool));
+}
+
 svn_info_t *
 svn_info_dup(const svn_info_t *info, apr_pool_t *pool)
 {

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/diff.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/diff.c Thu Jan  9 09:31:10 2014
@@ -1773,8 +1773,8 @@ diff_repos_repos(const svn_wc_diff_callb
   /* 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.  */
-  SVN_ERR(svn_client_open_ra_session2(&extra_ra_session, anchor1, wri_abspath,
-                                      ctx, pool, pool));
+  SVN_ERR(svn_ra_dup_session(&extra_ra_session, ra_session, anchor1,
+                             pool, pool));
 
   SVN_ERR(svn_client__get_diff_editor2(
                 &diff_editor, &diff_edit_baton,
@@ -2329,8 +2329,8 @@ diff_summarize_repos_repos(svn_client_di
 
   /* Now, we open an extra RA session to the correct anchor
      location for URL1.  This is used to get deleted path information.  */
-  SVN_ERR(svn_client_open_ra_session2(&extra_ra_session, anchor1, NULL,
-                                      ctx, pool, pool));
+  SVN_ERR(svn_ra_dup_session(&extra_ra_session, ra_session, anchor1,
+                             pool, pool));
 
   SVN_ERR(svn_client__get_diff_editor2(&diff_editor, &diff_edit_baton,
                                        extra_ra_session,

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/diff_local.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/diff_local.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/diff_local.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/diff_local.c Thu Jan  9 09:31:10 2014
@@ -47,6 +47,7 @@
 #include "svn_subst.h"
 #include "client.h"
 
+#include "private/svn_sorts_private.h"
 #include "private/svn_wc_private.h"
 
 

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/import.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/import.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/import.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/import.c Thu Jan  9 09:31:10 2014
@@ -48,8 +48,9 @@
 #include "svn_props.h"
 
 #include "client.h"
-#include "private/svn_subr_private.h"
 #include "private/svn_ra_private.h"
+#include "private/svn_sorts_private.h"
+#include "private/svn_subr_private.h"
 #include "private/svn_magic.h"
 
 /* Import context baton.
@@ -278,7 +279,7 @@ import_file(const svn_delta_editor_t *ed
   text_checksum =
     svn_checksum_to_cstring(svn_checksum__from_digest_md5(digest, pool), pool);
 
-  return editor->close_file(file_baton, text_checksum, pool);
+  return svn_error_trace(editor->close_file(file_baton, text_checksum, pool));
 }
 
 
@@ -772,9 +773,9 @@ import(const char *local_abspath,
     }
 
   if (import_ctx->repos_changed)
-    return editor->close_edit(edit_baton, pool);
+    return svn_error_trace(editor->close_edit(edit_baton, pool));
   else
-    return editor->abort_edit(edit_baton, pool);
+    return svn_error_trace(editor->abort_edit(edit_baton, pool));
 }
 
 

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/info.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/info.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/info.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/info.c Thu Jan  9 09:31:10 2014
@@ -26,13 +26,15 @@
 #include "svn_private_config.h"
 #include "client.h"
 #include "svn_client.h"
-#include "svn_pools.h"
 #include "svn_dirent_uri.h"
-#include "svn_path.h"
 #include "svn_hash.h"
+#include "svn_pools.h"
+#include "svn_sorts.h"
+
 #include "svn_wc.h"
 
 #include "private/svn_fspath.h"
+#include "private/svn_sorts_private.h"
 #include "private/svn_wc_private.h"
 
 
@@ -57,6 +59,78 @@ svn_client_info2_dup(const svn_client_in
   return new_info;
 }
 
+/* Handle externals for svn_client_info4() */
+
+static svn_error_t *
+do_external_info(apr_hash_t *external_map,
+                 svn_depth_t depth,
+                 svn_boolean_t fetch_excluded,
+                 svn_boolean_t fetch_actual_only,
+                 const apr_array_header_t *changelists,
+                 svn_client_info_receiver2_t receiver,
+                 void *receiver_baton,
+                 svn_client_ctx_t *ctx,
+                 apr_pool_t *scratch_pool)
+{
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  apr_array_header_t *externals;
+  int i;
+
+  externals = svn_sort__hash(external_map, svn_sort_compare_items_lexically,
+                             scratch_pool);
+
+  /* Loop over the hash of new values (we don't care about the old
+     ones).  This is a mapping of versioned directories to property
+     values. */
+  for (i = 0; i < externals->nelts; i++)
+    {
+      svn_node_kind_t external_kind;
+      svn_sort__item_t item = APR_ARRAY_IDX(externals, i, svn_sort__item_t);
+      const char *local_abspath = item.key;
+      const char *defining_abspath = item.value;
+      svn_opt_revision_t opt_rev;
+      svn_node_kind_t kind;
+
+      svn_pool_clear(iterpool);
+
+      /* Obtain information on the expected external. */
+      SVN_ERR(svn_wc__read_external_info(&external_kind, NULL, NULL, NULL,
+                                         &opt_rev.value.number,
+                                         ctx->wc_ctx, defining_abspath,
+                                         local_abspath, FALSE,
+                                         iterpool, iterpool));
+
+      if (external_kind != svn_node_dir)
+        continue;
+
+      SVN_ERR(svn_io_check_path(local_abspath, &kind, iterpool));
+      if (kind != svn_node_dir)
+        continue;
+
+      /* Tell the client we're starting an external info. */
+      if (ctx->notify_func2)
+        ctx->notify_func2(
+               ctx->notify_baton2,
+               svn_wc_create_notify(local_abspath,
+                                    svn_wc_notify_info_external,
+                                    iterpool), iterpool);
+
+      SVN_ERR(svn_client_info4(local_abspath,
+                               NULL /* peg_revision */,
+                               NULL /* revision */,
+                               depth,
+                               fetch_excluded,
+                               fetch_actual_only,
+                               TRUE /* include_externals */,
+                               changelists,
+                               receiver, receiver_baton,
+                               ctx, iterpool));
+    }
+
+  svn_pool_destroy(iterpool);
+  return SVN_NO_ERROR;
+}
+
 /* Set *INFO to a new info struct built from DIRENT
    and (possibly NULL) svn_lock_t LOCK, all allocated in POOL.
    Pointer fields are copied by reference, not dup'd. */
@@ -247,12 +321,13 @@ wc_info_receiver(void *baton,
 }
 
 svn_error_t *
-svn_client_info3(const char *abspath_or_url,
+svn_client_info4(const char *abspath_or_url,
                  const svn_opt_revision_t *peg_revision,
                  const svn_opt_revision_t *revision,
                  svn_depth_t depth,
                  svn_boolean_t fetch_excluded,
                  svn_boolean_t fetch_actual_only,
+                 svn_boolean_t include_externals,
                  const apr_array_header_t *changelists,
                  svn_client_info_receiver2_t receiver,
                  void *receiver_baton,
@@ -281,11 +356,26 @@ svn_client_info3(const char *abspath_or_
 
       b.client_receiver_func = receiver;
       b.client_receiver_baton = receiver_baton;
-      return svn_error_trace(
-        svn_wc__get_info(ctx->wc_ctx, abspath_or_url, depth,
-                        fetch_excluded, fetch_actual_only, changelists,
-                         wc_info_receiver, &b,
-                         ctx->cancel_func, ctx->cancel_baton, pool));
+      SVN_ERR(svn_wc__get_info(ctx->wc_ctx, abspath_or_url, depth,
+                               fetch_excluded, fetch_actual_only, changelists,
+                               wc_info_receiver, &b,
+                               ctx->cancel_func, ctx->cancel_baton, pool));
+
+      if (include_externals && SVN_DEPTH_IS_RECURSIVE(depth))
+        {
+          apr_hash_t *external_map;
+
+          SVN_ERR(svn_wc__externals_defined_below(&external_map,
+                                                  ctx->wc_ctx, abspath_or_url,
+                                                  pool, pool));
+
+          SVN_ERR(do_external_info(external_map,
+                                   depth, fetch_excluded, fetch_actual_only,
+                                   changelists,
+                                   receiver, receiver_baton, ctx, pool));
+        }
+
+      return SVN_NO_ERROR;
     }
 
   /* Go repository digging instead. */
@@ -300,8 +390,7 @@ svn_client_info3(const char *abspath_or_
   svn_uri_split(NULL, &base_name, pathrev->url, pool);
 
   /* Get the dirent for the URL itself. */
-  SVN_ERR(svn_client__ra_stat_compatible(ra_session, pathrev->rev, &the_ent,
-                                         DIRENT_FIELDS, ctx, pool));
+  SVN_ERR(svn_ra_stat(ra_session, "", pathrev->rev, &the_ent, pool));
 
   if (! the_ent)
     return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/list.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/list.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/list.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/list.c Thu Jan  9 09:31:10 2014
@@ -35,6 +35,7 @@
 
 #include "private/svn_fspath.h"
 #include "private/svn_ra_private.h"
+#include "private/svn_sorts_private.h"
 #include "private/svn_wc_private.h"
 
 /* Prototypes for referencing before declaration */
@@ -191,114 +192,6 @@ get_dir_contents(apr_uint32_t dirent_fie
   return SVN_NO_ERROR;
 }
 
-/* Like svn_ra_stat() but with a compatibility hack for pre-1.2 svnserve. */
-/* ### Maybe we should move this behavior into the svn_ra_stat wrapper? */
-svn_error_t *
-svn_client__ra_stat_compatible(svn_ra_session_t *ra_session,
-                               svn_revnum_t rev,
-                               svn_dirent_t **dirent_p,
-                               apr_uint32_t dirent_fields,
-                               svn_client_ctx_t *ctx,
-                               apr_pool_t *pool)
-{
-  svn_error_t *err;
-
-  err = svn_ra_stat(ra_session, "", rev, dirent_p, pool);
-
-  /* svnserve before 1.2 doesn't support the above, so fall back on
-     a less efficient method. */
-  if (err && err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED)
-    {
-      const char *repos_root_url;
-      const char *session_url;
-      svn_node_kind_t kind;
-      svn_dirent_t *dirent;
-
-      svn_error_clear(err);
-
-      SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_url, pool));
-      SVN_ERR(svn_ra_get_session_url(ra_session, &session_url, pool));
-
-      SVN_ERR(svn_ra_check_path(ra_session, "", rev, &kind, pool));
-
-      if (kind != svn_node_none)
-        {
-          if (strcmp(session_url, repos_root_url) != 0)
-            {
-              svn_ra_session_t *parent_session;
-              apr_hash_t *parent_ents;
-              const char *parent_url, *base_name;
-              apr_pool_t *subpool = svn_pool_create(pool);
-
-              /* Open another session to the path's parent.  This server
-                 doesn't support svn_ra_reparent anyway, so don't try it. */
-              svn_uri_split(&parent_url, &base_name, session_url, subpool);
-
-              SVN_ERR(svn_client_open_ra_session2(&parent_session, parent_url,
-                                                  NULL, ctx,
-                                                  subpool, subpool));
-
-              /* Get all parent's entries, no props. */
-              SVN_ERR(svn_ra_get_dir2(parent_session, &parent_ents, NULL,
-                                      NULL, "", rev, dirent_fields, subpool));
-
-              /* Get the relevant entry. */
-              dirent = svn_hash_gets(parent_ents, base_name);
-
-              if (dirent)
-                *dirent_p = svn_dirent_dup(dirent, pool);
-              else
-                *dirent_p = NULL;
-
-              svn_pool_destroy(subpool); /* Close RA session */
-            }
-          else
-            {
-              /* We can't get the directory entry for the repository root,
-                 but we can still get the information we want.
-                 The created-rev of the repository root must, by definition,
-                 be rev. */
-              dirent = apr_palloc(pool, sizeof(*dirent));
-              dirent->kind = kind;
-              dirent->size = SVN_INVALID_FILESIZE;
-              if (dirent_fields & SVN_DIRENT_HAS_PROPS)
-                {
-                  apr_hash_t *props;
-                  SVN_ERR(svn_ra_get_dir2(ra_session, NULL, NULL, &props,
-                                          "", rev, 0 /* no dirent fields */,
-                                          pool));
-                  dirent->has_props = (apr_hash_count(props) != 0);
-                }
-              dirent->created_rev = rev;
-              if (dirent_fields & (SVN_DIRENT_TIME | SVN_DIRENT_LAST_AUTHOR))
-                {
-                  apr_hash_t *props;
-                  svn_string_t *val;
-
-                  SVN_ERR(svn_ra_rev_proplist(ra_session, rev, &props,
-                                              pool));
-                  val = svn_hash_gets(props, SVN_PROP_REVISION_DATE);
-                  if (val)
-                    SVN_ERR(svn_time_from_cstring(&dirent->time, val->data,
-                                                  pool));
-                  else
-                    dirent->time = 0;
-
-                  val = svn_hash_gets(props, SVN_PROP_REVISION_AUTHOR);
-                  dirent->last_author = val ? val->data : NULL;
-                }
-
-              *dirent_p = dirent;
-            }
-        }
-      else
-        *dirent_p = NULL;
-    }
-  else
-    SVN_ERR(err);
-
-  return SVN_NO_ERROR;
-}
 
 /* List the file/directory entries for PATH_OR_URL at REVISION.
    The actual node revision selected is determined by the path as
@@ -373,8 +266,7 @@ list_internal(const char *path_or_url,
 
   fs_path = svn_client__pathrev_fspath(loc, pool);
 
-  SVN_ERR(svn_client__ra_stat_compatible(ra_session, loc->rev, &dirent,
-                                         dirent_fields, ctx, pool));
+  SVN_ERR(svn_ra_stat(ra_session, "", loc->rev, &dirent, pool));
   if (! dirent)
     return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
                              _("URL '%s' non-existent in revision %ld"),

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/log.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/log.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/log.c Thu Jan  9 09:31:10 2014
@@ -96,6 +96,7 @@ svn_client__get_copy_source(const char *
                             svn_revnum_t *original_revision,
                             const char *path_or_url,
                             const svn_opt_revision_t *revision,
+                            svn_ra_session_t *ra_session,
                             svn_client_ctx_t *ctx,
                             apr_pool_t *result_pool,
                             apr_pool_t *scratch_pool)
@@ -103,18 +104,50 @@ svn_client__get_copy_source(const char *
   svn_error_t *err;
   copyfrom_info_t copyfrom_info = { 0 };
   apr_pool_t *sesspool = svn_pool_create(scratch_pool);
-  svn_ra_session_t *ra_session;
   svn_client__pathrev_t *at_loc;
+  const char *old_session_url = NULL;
 
   copyfrom_info.is_first = TRUE;
   copyfrom_info.path = NULL;
   copyfrom_info.rev = SVN_INVALID_REVNUM;
   copyfrom_info.pool = result_pool;
 
-  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &at_loc,
-                                            path_or_url, NULL,
-                                            revision, revision,
-                                            ctx, sesspool));
+  if (!ra_session)
+    {
+      SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &at_loc,
+                                                path_or_url, NULL,
+                                                revision, revision,
+                                                ctx, sesspool));
+    }
+  else
+    {
+      const char *url;
+      if (svn_path_is_url(path_or_url))
+        url = path_or_url;
+      else
+        {
+          SVN_ERR(svn_client_url_from_path2(&url, path_or_url, ctx, sesspool,
+                                            sesspool));
+
+          if (! url)
+            return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
+                                     _("'%s' has no URL"), path_or_url);
+        }
+
+      SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ra_session,
+                                                url, sesspool));
+
+      err = svn_client__resolve_rev_and_url(&at_loc, ra_session, path_or_url,
+                                            revision, revision, ctx,
+                                            sesspool);
+
+      /* On error reparent back (and return), otherwise reparent to new
+         location */
+      SVN_ERR(svn_error_compose_create(
+                err,
+                svn_ra_reparent(ra_session, err ? old_session_url
+                                                : at_loc->url, sesspool)));
+    }
 
   /* Find the copy source.  Walk the location segments to find the revision
      at which this node was created (copied or added). */
@@ -124,6 +157,11 @@ svn_client__get_copy_source(const char *
                                      copyfrom_info_receiver, &copyfrom_info,
                                      scratch_pool);
 
+  if (old_session_url)
+    err = svn_error_compose_create(
+                    err,
+                    svn_ra_reparent(ra_session, old_session_url, sesspool));
+
   svn_pool_destroy(sesspool);
 
   if (err)
@@ -864,17 +902,19 @@ svn_client_log6(const apr_array_header_t
                                             actual_loc->url, pool));
 
   /* Save us an RA layer round trip if we are on the repository root and
-     know the result in advance.  All the revision data has already been
-     validated.
+     know the result in advance, or if we don't need multiple ranges.
+     All the revision data has already been validated.
    */
-  if (strcmp(actual_loc->url, actual_loc->repos_root_url) == 0)
+  if (strcmp(actual_loc->url, actual_loc->repos_root_url) == 0
+      || opt_rev_ranges->nelts <= 1)
     {
       svn_location_segment_t *segment = apr_pcalloc(pool, sizeof(*segment));
       log_segments = apr_array_make(pool, 1, sizeof(segment));
 
       segment->range_start = oldest_rev;
       segment->range_end = actual_loc->rev;
-      segment->path = "";
+      segment->path = svn_uri_skip_ancestor(actual_loc->repos_root_url,
+                                            actual_loc->url, pool);
       APR_ARRAY_PUSH(log_segments, svn_location_segment_t *) = segment;
     }
   else

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/merge.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/merge.c Thu Jan  9 09:31:10 2014
@@ -56,13 +56,12 @@
 #include "client.h"
 #include "mergeinfo.h"
 
-#include "private/svn_opt_private.h"
-#include "private/svn_wc_private.h"
-#include "private/svn_mergeinfo_private.h"
 #include "private/svn_fspath.h"
-#include "private/svn_ra_private.h"
+#include "private/svn_mergeinfo_private.h"
 #include "private/svn_client_private.h"
+#include "private/svn_sorts_private.h"
 #include "private/svn_subr_private.h"
+#include "private/svn_wc_private.h"
 
 
 /*-----------------------------------------------------------------------*/
@@ -3753,110 +3752,95 @@ adjust_deleted_subtree_ranges(svn_client
                                             younger_rev, older_rev, ctx,
                                             scratch_pool);
 
-  /* If PRIMARY_URL@peg_rev doesn't exist then
-      svn_client__repos_location_segments() typically returns an
-      SVN_ERR_FS_NOT_FOUND error, but if it doesn't exist for a
-      forward merge over ra_neon then we get SVN_ERR_RA_DAV_REQUEST_FAILED.
-      http://subversion.tigris.org/issues/show_bug.cgi?id=3137 fixed some of
-      the cases where different RA layers returned different error codes to
-      signal the "path not found"...but it looks like there is more to do.
-
-      ### Do we still need to special case for ra_neon (since it no longer
-          exists)? */
   if (err)
     {
-      if (err->apr_err == SVN_ERR_FS_NOT_FOUND
-          || err->apr_err == SVN_ERR_RA_DAV_REQUEST_FAILED)
-        {
-          /* PRIMARY_URL@peg_rev doesn't exist.  Check if PRIMARY_URL@older_rev
-             exists, if neither exist then the editor can simply ignore this
-             subtree. */
-          const char *rel_source_path;  /* PRIMARY_URL relative to RA_SESSION */
-          svn_node_kind_t kind;
-
-          svn_error_clear(err);
-          err = NULL;
-
-          SVN_ERR(svn_ra_get_path_relative_to_session(
-                    ra_session, &rel_source_path, primary_url, scratch_pool));
+      const char *rel_source_path;  /* PRIMARY_URL relative to RA_SESSION */
+      svn_node_kind_t kind;
 
-          SVN_ERR(svn_ra_check_path(ra_session, rel_source_path,
-                                    older_rev, &kind, scratch_pool));
-          if (kind == svn_node_none)
-            {
-              /* Neither PRIMARY_URL@peg_rev nor PRIMARY_URL@older_rev exist,
-                 so there is nothing to merge.  Set CHILD->REMAINING_RANGES
-                 identical to PARENT's. */
-              child->remaining_ranges =
-                svn_rangelist_dup(parent->remaining_ranges, scratch_pool);
-            }
-          else
-            {
-              svn_rangelist_t *deleted_rangelist;
-              svn_revnum_t rev_primary_url_deleted;
+      if (err->apr_err != SVN_ERR_FS_NOT_FOUND)
+        return svn_error_trace(err);
 
-              /* PRIMARY_URL@older_rev exists, so it was deleted at some
-                 revision prior to peg_rev, find that revision. */
-              SVN_ERR(svn_ra_get_deleted_rev(ra_session, rel_source_path,
-                                             older_rev, younger_rev,
-                                             &rev_primary_url_deleted,
-                                             scratch_pool));
+      svn_error_clear(err);
 
-              /* PRIMARY_URL@older_rev exists and PRIMARY_URL@peg_rev doesn't,
-                 so svn_ra_get_deleted_rev() should always find the revision
-                 PRIMARY_URL@older_rev was deleted. */
-              SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(rev_primary_url_deleted));
-
-              /* If this is a reverse merge reorder CHILD->REMAINING_RANGES and
-                 PARENT->REMAINING_RANGES so both will work with the
-                 svn_rangelist_* APIs below. */
-              if (is_rollback)
-                {
-                  /* svn_rangelist_reverse operates in place so it's safe
-                     to use our scratch_pool. */
-                  SVN_ERR(svn_rangelist_reverse(child->remaining_ranges,
-                                                scratch_pool));
-                  SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges,
-                                                scratch_pool));
-                }
+      /* PRIMARY_URL@peg_rev doesn't exist.  Check if PRIMARY_URL@older_rev
+         exists, if neither exist then the editor can simply ignore this
+         subtree. */
 
-              /* Find the intersection of CHILD->REMAINING_RANGES with the
-                 range over which PRIMARY_URL@older_rev exists (ending at
-                 the youngest revision at which it still exists). */
-              SVN_ERR(rangelist_intersect_range(&child->remaining_ranges,
-                                                child->remaining_ranges,
-                                                older_rev,
-                                                rev_primary_url_deleted - 1,
-                                                FALSE,
-                                                scratch_pool, scratch_pool));
-
-              /* Merge into CHILD->REMAINING_RANGES the intersection of
-                 PARENT->REMAINING_RANGES with the range beginning when
-                 PRIMARY_URL@older_rev was deleted until younger_rev. */
-              SVN_ERR(rangelist_intersect_range(&deleted_rangelist,
-                                                parent->remaining_ranges,
-                                                rev_primary_url_deleted - 1,
-                                                peg_rev,
-                                                FALSE,
-                                                scratch_pool, scratch_pool));
-              SVN_ERR(svn_rangelist_merge2(child->remaining_ranges,
-                                           deleted_rangelist, scratch_pool,
-                                           scratch_pool));
+      SVN_ERR(svn_ra_get_path_relative_to_session(
+                ra_session, &rel_source_path, primary_url, scratch_pool));
 
-              /* Return CHILD->REMAINING_RANGES and PARENT->REMAINING_RANGES
-                 to reverse order if necessary. */
-              if (is_rollback)
-                {
-                  SVN_ERR(svn_rangelist_reverse(child->remaining_ranges,
-                                                scratch_pool));
-                  SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges,
-                                                scratch_pool));
-                }
-            }
+      SVN_ERR(svn_ra_check_path(ra_session, rel_source_path,
+                                older_rev, &kind, scratch_pool));
+      if (kind == svn_node_none)
+        {
+          /* Neither PRIMARY_URL@peg_rev nor PRIMARY_URL@older_rev exist,
+             so there is nothing to merge.  Set CHILD->REMAINING_RANGES
+             identical to PARENT's. */
+          child->remaining_ranges =
+            svn_rangelist_dup(parent->remaining_ranges, scratch_pool);
         }
       else
         {
-          return svn_error_trace(err);
+          svn_rangelist_t *deleted_rangelist;
+          svn_revnum_t rev_primary_url_deleted;
+
+          /* PRIMARY_URL@older_rev exists, so it was deleted at some
+             revision prior to peg_rev, find that revision. */
+          SVN_ERR(svn_ra_get_deleted_rev(ra_session, rel_source_path,
+                                         older_rev, younger_rev,
+                                         &rev_primary_url_deleted,
+                                         scratch_pool));
+
+          /* PRIMARY_URL@older_rev exists and PRIMARY_URL@peg_rev doesn't,
+             so svn_ra_get_deleted_rev() should always find the revision
+             PRIMARY_URL@older_rev was deleted. */
+          SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(rev_primary_url_deleted));
+
+          /* If this is a reverse merge reorder CHILD->REMAINING_RANGES and
+             PARENT->REMAINING_RANGES so both will work with the
+             svn_rangelist_* APIs below. */
+          if (is_rollback)
+            {
+              /* svn_rangelist_reverse operates in place so it's safe
+                 to use our scratch_pool. */
+              SVN_ERR(svn_rangelist_reverse(child->remaining_ranges,
+                                            scratch_pool));
+              SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges,
+                                            scratch_pool));
+            }
+
+          /* Find the intersection of CHILD->REMAINING_RANGES with the
+             range over which PRIMARY_URL@older_rev exists (ending at
+             the youngest revision at which it still exists). */
+          SVN_ERR(rangelist_intersect_range(&child->remaining_ranges,
+                                            child->remaining_ranges,
+                                            older_rev,
+                                            rev_primary_url_deleted - 1,
+                                            FALSE,
+                                            scratch_pool, scratch_pool));
+
+          /* Merge into CHILD->REMAINING_RANGES the intersection of
+             PARENT->REMAINING_RANGES with the range beginning when
+             PRIMARY_URL@older_rev was deleted until younger_rev. */
+          SVN_ERR(rangelist_intersect_range(&deleted_rangelist,
+                                            parent->remaining_ranges,
+                                            rev_primary_url_deleted - 1,
+                                            peg_rev,
+                                            FALSE,
+                                            scratch_pool, scratch_pool));
+          SVN_ERR(svn_rangelist_merge2(child->remaining_ranges,
+                                       deleted_rangelist, scratch_pool,
+                                       scratch_pool));
+
+          /* Return CHILD->REMAINING_RANGES and PARENT->REMAINING_RANGES
+             to reverse order if necessary. */
+          if (is_rollback)
+            {
+              SVN_ERR(svn_rangelist_reverse(child->remaining_ranges,
+                                            scratch_pool));
+              SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges,
+                                            scratch_pool));
+            }
         }
     }
   else /* PRIMARY_URL@peg_rev exists. */
@@ -5843,7 +5827,7 @@ slice_remaining_ranges(apr_array_header_
               split_range2->start = end_rev;
               APR_ARRAY_IDX(child->remaining_ranges, 0,
                             svn_merge_range_t *) = split_range1;
-              svn_sort__array_insert(&split_range2, child->remaining_ranges, 1);
+              svn_sort__array_insert(child->remaining_ranges, &split_range2, 1);
             }
         }
     }
@@ -5978,11 +5962,11 @@ insert_child_to_merge(apr_array_header_t
 
   /* Find where to insert the new element */
   insert_index =
-    svn_sort__bsearch_lower_bound(&insert_element, children_with_mergeinfo,
+    svn_sort__bsearch_lower_bound(children_with_mergeinfo, &insert_element,
                                   compare_merge_path_t_as_paths);
 
   new_element = svn_client__merge_path_dup(insert_element, pool);
-  svn_sort__array_insert(&new_element, children_with_mergeinfo, insert_index);
+  svn_sort__array_insert(children_with_mergeinfo, &new_element, insert_index);
 }
 
 /* Helper for get_mergeinfo_paths().
@@ -7066,7 +7050,8 @@ normalize_merge_sources_internal(apr_arr
               SVN_ERR(svn_client__get_copy_source(&original_repos_relpath,
                                                   &original_revision,
                                                   segment_url,
-                                                  &range_start_rev, ctx,
+                                                  &range_start_rev,
+                                                  ra_session, ctx,
                                                   result_pool, scratch_pool));
               /* Got copyfrom data?  Fix up the first segment to cover
                  back to COPYFROM_REV + 1, and then prepend a new
@@ -7079,7 +7064,7 @@ normalize_merge_sources_internal(apr_arr
                   new_segment->path = original_repos_relpath;
                   new_segment->range_start = original_revision;
                   new_segment->range_end = original_revision;
-                  svn_sort__array_insert(&new_segment, segments, 0);
+                  svn_sort__array_insert(segments, &new_segment, 0);
                 }
             }
         }

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/mergeinfo.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/mergeinfo.c Thu Jan  9 09:31:10 2014
@@ -39,12 +39,13 @@
 #include "svn_client.h"
 #include "svn_hash.h"
 
+#include "private/svn_client_private.h"
 #include "private/svn_opt_private.h"
 #include "private/svn_mergeinfo_private.h"
-#include "private/svn_wc_private.h"
 #include "private/svn_ra_private.h"
+#include "private/svn_sorts_private.h"
+#include "private/svn_wc_private.h"
 #include "private/svn_fspath.h"
-#include "private/svn_client_private.h"
 #include "client.h"
 #include "mergeinfo.h"
 
@@ -2231,6 +2232,8 @@ svn_client_suggest_merge_sources(apr_arr
   svn_mergeinfo_catalog_t mergeinfo_cat;
   svn_mergeinfo_t mergeinfo;
   apr_hash_index_t *hi;
+  apr_pool_t *session_pool = svn_pool_create(pool);
+  svn_ra_session_t *ra_session;
 
   list = apr_array_make(pool, 1, sizeof(const char *));
 
@@ -2249,26 +2252,32 @@ svn_client_suggest_merge_sources(apr_arr
         1. The copyfrom source.
         2. All remaining merge sources (unordered).
   */
+  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, NULL, path_or_url,
+                                            NULL, peg_revision, peg_revision,
+                                            ctx, session_pool));
 
-  /* ### TODO: Share ra_session batons to improve efficiency? */
   SVN_ERR(get_mergeinfo(&mergeinfo_cat, &repos_root, path_or_url,
-                        peg_revision, FALSE, FALSE, ctx, NULL, pool, pool));
+                        peg_revision, FALSE, FALSE,
+                        ctx, ra_session, session_pool, session_pool));
 
   if (mergeinfo_cat && apr_hash_count(mergeinfo_cat))
     {
       /* We asked only for the PATH_OR_URL's mergeinfo, not any of its
          descendants.  So if there is anything in the catalog it is the
          mergeinfo for PATH_OR_URL. */
-      mergeinfo = svn__apr_hash_index_val(apr_hash_first(pool, mergeinfo_cat));
+      mergeinfo = svn__apr_hash_index_val(apr_hash_first(session_pool,
+                                                         mergeinfo_cat));
     }
   else
     {
       mergeinfo = NULL;
     }
 
+  /* ### Should we only add the last source or all copy sources back to
+         the origin? */
   SVN_ERR(svn_client__get_copy_source(&copyfrom_path, &copyfrom_rev,
-                                      path_or_url, peg_revision, ctx,
-                                      pool, pool));
+                                      path_or_url, peg_revision, ra_session,
+                                      ctx, session_pool, session_pool));
   if (copyfrom_path)
     {
       APR_ARRAY_PUSH(list, const char *) =
@@ -2277,7 +2286,9 @@ svn_client_suggest_merge_sources(apr_arr
 
   if (mergeinfo)
     {
-      for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi))
+      for (hi = apr_hash_first(session_pool, mergeinfo);
+           hi;
+           hi = apr_hash_next(hi))
         {
           const char *rel_path = svn__apr_hash_index_key(hi);
 
@@ -2287,6 +2298,8 @@ svn_client_suggest_merge_sources(apr_arr
         }
     }
 
+  svn_pool_destroy(session_pool);
+
   *suggestions = list;
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/prop_commands.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/prop_commands.c Thu Jan  9 09:31:10 2014
@@ -1197,6 +1197,7 @@ struct recursive_proplist_receiver_baton
   svn_wc_context_t *wc_ctx;  /* Working copy context. */
   svn_proplist_receiver2_t wrapped_receiver;  /* Proplist receiver to call. */
   void *wrapped_receiver_baton;    /* Baton for the proplist receiver. */
+  apr_array_header_t *iprops;
 
   /* Anchor, anchor_abspath pair for converting to relative paths */
   const char *anchor;
@@ -1212,6 +1213,27 @@ recursive_proplist_receiver(void *baton,
 {
   struct recursive_proplist_receiver_baton *b = baton;
   const char *path;
+  apr_array_header_t *iprops = NULL;
+
+  if (b->iprops
+      && ! strcmp(local_abspath, b->anchor_abspath))
+    {
+      /* Report iprops with the properties for the anchor */
+      iprops = b->iprops;
+      b->iprops = NULL;
+    }
+  else if (b->iprops)
+    {
+      /* No report for the root?
+         Report iprops anyway */
+
+      SVN_ERR(b->wrapped_receiver(b->wrapped_receiver_baton,
+                                  b->anchor ? b->anchor : local_abspath,
+                                  NULL /* prop_hash */,
+                                  b->iprops,
+                                  scratch_pool));
+      b->iprops = NULL;
+    }
 
   /* Attempt to convert absolute paths to relative paths for
    * presentation purposes, if needed. */
@@ -1226,7 +1248,7 @@ recursive_proplist_receiver(void *baton,
     path = local_abspath;
 
   return svn_error_trace(b->wrapped_receiver(b->wrapped_receiver_baton,
-                                             path, props, NULL,
+                                             path, props, iprops,
                                              scratch_pool));
 }
 
@@ -1366,6 +1388,7 @@ get_local_props(const char *path_or_url,
   svn_node_kind_t kind;
   apr_hash_t *changelist_hash = NULL;
   const char *local_abspath;
+  apr_array_header_t *iprops = NULL;
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path_or_url,
                                   scratch_pool));
@@ -1388,7 +1411,6 @@ get_local_props(const char *path_or_url,
 
   if (get_target_inherited_props)
     {
-      apr_array_header_t *iprops;
       const char *repos_root_url;
 
       SVN_ERR(svn_wc__get_iprops(&iprops, ctx->wc_ctx, local_abspath,
@@ -1398,8 +1420,6 @@ get_local_props(const char *path_or_url,
       SVN_ERR(svn_client__iprop_relpaths_to_urls(iprops, repos_root_url,
                                                  scratch_pool,
                                                  scratch_pool));
-      SVN_ERR(call_receiver(path_or_url, NULL, iprops, receiver,
-                            receiver_baton, scratch_pool));
     }
 
   if (changelists && changelists->nelts)
@@ -1414,16 +1434,16 @@ get_local_props(const char *path_or_url,
       rb.wc_ctx = ctx->wc_ctx;
       rb.wrapped_receiver = receiver;
       rb.wrapped_receiver_baton = receiver_baton;
+      rb.iprops = iprops;
+      rb.anchor_abspath = local_abspath;
 
       if (strcmp(path_or_url, local_abspath) != 0)
         {
           rb.anchor = path_or_url;
-          rb.anchor_abspath = local_abspath;
         }
       else
         {
           rb.anchor = NULL;
-          rb.anchor_abspath = NULL;
         }
 
       SVN_ERR(svn_wc__prop_list_recursive(ctx->wc_ctx, local_abspath, NULL,
@@ -1431,6 +1451,13 @@ get_local_props(const char *path_or_url,
                                           recursive_proplist_receiver, &rb,
                                           ctx->cancel_func, ctx->cancel_baton,
                                           scratch_pool));
+
+      if (rb.iprops)
+        {
+          /* We didn't report for the root. Report iprops anyway */
+          SVN_ERR(call_receiver(path_or_url, NULL /* props */, rb.iprops,
+                                receiver, receiver_baton, scratch_pool));
+        }
     }
   else if (svn_wc__changelist_match(ctx->wc_ctx, local_abspath,
                                     changelist_hash, scratch_pool))
@@ -1460,7 +1487,7 @@ get_local_props(const char *path_or_url,
               }
           }
 
-      SVN_ERR(call_receiver(path_or_url, props, NULL,
+      SVN_ERR(call_receiver(path_or_url, props, iprops,
                             receiver, receiver_baton, scratch_pool));
 
     }

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/status.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/status.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/status.c Thu Jan  9 09:31:10 2014
@@ -31,6 +31,7 @@
 
 #include "svn_private_config.h"
 #include "svn_pools.h"
+#include "svn_sorts.h"
 #include "client.h"
 
 #include "svn_path.h"
@@ -40,8 +41,9 @@
 #include "svn_error.h"
 #include "svn_hash.h"
 
-#include "private/svn_wc_private.h"
 #include "private/svn_client_private.h"
+#include "private/svn_sorts_private.h"
+#include "private/svn_wc_private.h"
 
 
 /*** Getting update information ***/
@@ -247,25 +249,29 @@ do_external_status(svn_client_ctx_t *ctx
                    svn_boolean_t get_all,
                    svn_boolean_t update,
                    svn_boolean_t no_ignore,
+                   const apr_array_header_t *changelists,
                    const char *anchor_abspath,
                    const char *anchor_relpath,
                    svn_client_status_func_t status_func,
                    void *status_baton,
                    apr_pool_t *scratch_pool)
 {
-  apr_hash_index_t *hi;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  apr_array_header_t *externals;
+  int i;
+
+  externals = svn_sort__hash(external_map, svn_sort_compare_items_lexically,
+                             scratch_pool);
 
   /* Loop over the hash of new values (we don't care about the old
      ones).  This is a mapping of versioned directories to property
      values. */
-  for (hi = apr_hash_first(scratch_pool, external_map);
-       hi;
-       hi = apr_hash_next(hi))
+  for (i = 0; i < externals->nelts; i++)
     {
       svn_node_kind_t external_kind;
-      const char *local_abspath = svn__apr_hash_index_key(hi);
-      const char *defining_abspath = svn__apr_hash_index_val(hi);
+      svn_sort__item_t item = APR_ARRAY_IDX(externals, i, svn_sort__item_t);
+      const char *local_abspath = item.key;
+      const char *defining_abspath = item.value;
       svn_node_kind_t kind;
       svn_opt_revision_t opt_rev;
       const char *status_path;
@@ -310,8 +316,10 @@ do_external_status(svn_client_ctx_t *ctx
 
       /* And then do the status. */
       SVN_ERR(svn_client_status5(NULL, ctx, status_path, &opt_rev, depth,
-                                 get_all, update, no_ignore, FALSE, FALSE,
-                                 NULL, status_func, status_baton,
+                                 get_all, update, no_ignore,
+                                 FALSE /* ignore_exernals */,
+                                 FALSE /* depth_as_sticky */,
+                                 changelists, status_func, status_baton,
                                  iterpool));
     }
 
@@ -590,14 +598,7 @@ svn_client_status5(svn_revnum_t *result_
       SVN_ERR(err);
     }
 
-  /* If there are svn:externals set, we don't want those to show up as
-     unversioned or unrecognized, so patch up the hash.  If caller wants
-     all the statuses, we will change unversioned status items that
-     are interesting to an svn:externals property to
-     svn_wc_status_unversioned, otherwise we'll just remove the status
-     item altogether.
-
-     We only descend into an external if depth is svn_depth_infinity or
+  /* We only descend into an external if depth is svn_depth_infinity or
      svn_depth_unknown.  However, there are conceivable behaviors that
      would involve descending under other circumstances; thus, we pass
      depth anyway, so the code will DTRT if we change the conditional
@@ -613,7 +614,7 @@ svn_client_status5(svn_revnum_t *result_
 
       SVN_ERR(do_external_status(ctx, external_map,
                                  depth, get_all,
-                                 update, no_ignore,
+                                 update, no_ignore, changelists,
                                  sb.anchor_abspath, sb.anchor_relpath,
                                  status_func, status_baton, pool));
     }

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/util.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/util.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_client/util.c Thu Jan  9 09:31:10 2014
@@ -165,6 +165,13 @@ svn_client_commit_item3_dup(const svn_cl
     new_item->outgoing_prop_changes =
       svn_prop_array_dup(new_item->outgoing_prop_changes, pool);
 
+  if (new_item->session_relpath)
+    new_item->session_relpath = apr_pstrdup(pool, new_item->session_relpath);
+
+  if (new_item->moved_from_abspath)
+    new_item->moved_from_abspath = apr_pstrdup(pool,
+                                               new_item->moved_from_abspath);
+
   return new_item;
 }
 

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_delta/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_delta/compat.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_delta/compat.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_delta/compat.c Thu Jan  9 09:31:10 2014
@@ -34,6 +34,7 @@
 #include "svn_pools.h"
 
 #include "private/svn_delta_private.h"
+#include "private/svn_sorts_private.h"
 #include "svn_private_config.h"
 
 

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_delta/svndiff.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_delta/svndiff.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_delta/svndiff.c Thu Jan  9 09:31:10 2014
@@ -872,6 +872,23 @@ svn_txdelta_read_svndiff_window(svn_txde
 
 
 svn_error_t *
+svn_txdelta__read_svndiff_window_sizes(svn_txdelta_window_t **window,
+                                       svn_stream_t *stream,
+                                       int svndiff_version,
+                                       apr_pool_t *pool)
+{
+  apr_size_t inslen, newlen;
+
+  *window = apr_pcalloc(pool, sizeof(**window));
+  SVN_ERR(read_window_header(stream, &(*window)->sview_offset,
+                             &(*window)->sview_len, &(*window)->tview_len,
+                             &inslen, &newlen));
+
+  return svn_error_trace(svn_stream_skip(stream, inslen + newlen));
+}
+
+
+svn_error_t *
 svn_txdelta_skip_svndiff_window(apr_file_t *file,
                                 int svndiff_version,
                                 apr_pool_t *pool)

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/editor.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/editor.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/editor.c Thu Jan  9 09:31:10 2014
@@ -240,23 +240,18 @@ can_modify(svn_fs_root_t *txn_root,
          of those new revisions.
          In either case, the node may not have changed in those new
          revisions; use the node's ID to determine this case.  */
-      const svn_fs_id_t *txn_noderev_id;
       svn_fs_root_t *rev_root;
-      const svn_fs_id_t *new_noderev_id;
-
-      /* The ID of the node that we would be modifying in the txn  */
-      SVN_ERR(svn_fs_node_id(&txn_noderev_id, txn_root, fspath,
-                             scratch_pool));
+      svn_fs_node_relation_t relation;
 
       /* Get the ID from the future/new revision.  */
       SVN_ERR(svn_fs_revision_root(&rev_root, svn_fs_root_fs(txn_root),
                                    revision, scratch_pool));
-      SVN_ERR(svn_fs_node_id(&new_noderev_id, rev_root, fspath,
-                             scratch_pool));
+      SVN_ERR(svn_fs_node_relation(&relation, txn_root, fspath, rev_root,
+                                   fspath, scratch_pool));
       svn_fs_close_root(rev_root);
 
       /* Has the target node changed in the future?  */
-      if (svn_fs_compare_ids(txn_noderev_id, new_noderev_id) != 0)
+      if (relation != svn_fs_node_same)
         {
           /* Restarting the commit will base the txn on the future/new
              revision, allowing the modification at REVISION.  */
@@ -789,10 +784,9 @@ svn_fs__editor_commit(svn_revnum_t *revi
      it placed into RESULT_POOL.  */
 
   if (!err)
-    err = svn_fs_commit_txn2(&inner_conflict_path,
+    err = svn_fs_commit_txn(&inner_conflict_path,
                              revision,
                              eb->txn,
-                             TRUE,
                              scratch_pool);
   if (SVN_IS_VALID_REVNUM(*revision))
     {

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/fs-loader.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/fs-loader.c Thu Jan  9 09:31:10 2014
@@ -818,9 +818,8 @@ svn_fs_begin_txn(svn_fs_txn_t **txn_p, s
 
 
 svn_error_t *
-svn_fs_commit_txn2(const char **conflict_p, svn_revnum_t *new_rev,
-                   svn_fs_txn_t *txn, svn_boolean_t set_timestamp,
-                   apr_pool_t *pool)
+svn_fs_commit_txn(const char **conflict_p, svn_revnum_t *new_rev,
+                   svn_fs_txn_t *txn, apr_pool_t *pool)
 {
   svn_error_t *err;
 
@@ -828,7 +827,7 @@ svn_fs_commit_txn2(const char **conflict
   if (conflict_p)
     *conflict_p = NULL;
 
-  err = txn->vtable->commit(conflict_p, new_rev, txn, set_timestamp, pool);
+  err = txn->vtable->commit(conflict_p, new_rev, txn, pool);
 
 #ifdef SVN_DEBUG
   /* Check postconditions. */
@@ -862,13 +861,6 @@ svn_fs_commit_txn2(const char **conflict
 }
 
 svn_error_t *
-svn_fs_commit_txn(const char **conflict_p, svn_revnum_t *new_rev,
-                  svn_fs_txn_t *txn, apr_pool_t *pool)
-{
-  return svn_fs_commit_txn2(conflict_p, new_rev, txn, TRUE, pool);
-}
-
-svn_error_t *
 svn_fs_abort_txn(svn_fs_txn_t *txn, apr_pool_t *pool)
 {
   return svn_error_trace(txn->vtable->abort(txn, pool));
@@ -924,6 +916,10 @@ svn_error_t *
 svn_fs_change_txn_prop(svn_fs_txn_t *txn, const char *name,
                        const svn_string_t *value, apr_pool_t *pool)
 {
+  /* Silently drop attempts to modify the internal property. */
+  if (!strcmp(name, SVN_FS__PROP_TXN_CLIENT_DATE))
+    return SVN_NO_ERROR;
+
   return svn_error_trace(txn->vtable->change_prop(txn, name, value, pool));
 }
 
@@ -931,6 +927,29 @@ svn_error_t *
 svn_fs_change_txn_props(svn_fs_txn_t *txn, const apr_array_header_t *props,
                         apr_pool_t *pool)
 {
+  int i;
+
+  /* Silently drop attempts to modify the internal property. */
+  for (i = 0; i < props->nelts; ++i)
+    {
+      svn_prop_t *prop = &APR_ARRAY_IDX(props, i, svn_prop_t);
+
+      if (!strcmp(prop->name, SVN_FS__PROP_TXN_CLIENT_DATE))
+        {
+          apr_array_header_t *reduced_props
+            = apr_array_make(pool, props->nelts - 1, sizeof(svn_prop_t));
+
+          for (i = 0; i < props->nelts; ++i)
+            {
+              prop = &APR_ARRAY_IDX(props, i, svn_prop_t);
+              if (strcmp(prop->name, SVN_FS__PROP_TXN_CLIENT_DATE))
+                APR_ARRAY_PUSH(reduced_props, svn_prop_t) = *prop;
+            }
+          props = reduced_props;
+          break;
+        }
+    }
+
   return svn_error_trace(txn->vtable->change_props(txn, props, pool));
 }
 
@@ -1081,6 +1100,24 @@ svn_fs_node_id(const svn_fs_id_t **id_p,
 }
 
 svn_error_t *
+svn_fs_node_relation(svn_fs_node_relation_t *relation,
+                     svn_fs_root_t *root_a, const char *path_a,
+                     svn_fs_root_t *root_b, const char *path_b,
+                     apr_pool_t *pool)
+{
+  /* Different repository types? */
+  if (root_a->vtable != root_b->vtable)
+    {
+      *relation = svn_fs_node_unrelated;
+      return SVN_NO_ERROR;
+    }
+
+  return svn_error_trace(root_a->vtable->node_relation(relation, root_a,
+                                                       path_a, root_b,
+                                                       path_b, pool));
+}
+
+svn_error_t *
 svn_fs_node_created_rev(svn_revnum_t *revision, svn_fs_root_t *root,
                         const char *path, apr_pool_t *pool)
 {

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/fs-loader.h?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/fs-loader.h Thu Jan  9 09:31:10 2014
@@ -27,6 +27,7 @@
 
 #include "svn_types.h"
 #include "svn_fs.h"
+#include "svn_props.h"
 #include "private/svn_mutex.h"
 
 #ifdef __cplusplus
@@ -260,8 +261,7 @@ typedef struct fs_vtable_t
 typedef struct txn_vtable_t
 {
   svn_error_t *(*commit)(const char **conflict_p, svn_revnum_t *new_rev,
-                         svn_fs_txn_t *txn, svn_boolean_t set_timestamp,
-                         apr_pool_t *pool);
+                         svn_fs_txn_t *txn, apr_pool_t *pool);
   svn_error_t *(*abort)(svn_fs_txn_t *txn, apr_pool_t *pool);
   svn_error_t *(*get_prop)(svn_string_t **value_p, svn_fs_txn_t *txn,
                            const char *propname, apr_pool_t *pool);
@@ -299,6 +299,10 @@ typedef struct root_vtable_t
                                apr_pool_t *pool);
   svn_error_t *(*node_id)(const svn_fs_id_t **id_p, svn_fs_root_t *root,
                           const char *path, apr_pool_t *pool);
+  svn_error_t *(*node_relation)(svn_fs_node_relation_t *relation,
+                                svn_fs_root_t *root_a, const char *path_a,
+                                svn_fs_root_t *root_b, const char *path_b,
+                                apr_pool_t *pool);
   svn_error_t *(*node_created_rev)(svn_revnum_t *revision,
                                    svn_fs_root_t *root, const char *path,
                                    apr_pool_t *pool);
@@ -432,6 +436,8 @@ typedef struct id_vtable_t
    in the 'flags' argument to svn_fs_lock().  */
 #define SVN_FS__PROP_TXN_CHECK_LOCKS           SVN_PROP_PREFIX "check-locks"
 #define SVN_FS__PROP_TXN_CHECK_OOD             SVN_PROP_PREFIX "check-ood"
+/* Set to "0" at the start of the txn, to "1" when svn:date changes. */
+#define SVN_FS__PROP_TXN_CLIENT_DATE           SVN_PROP_PREFIX "client-date"
 
 struct svn_fs_t
 {

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/dag.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/dag.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/dag.c Thu Jan  9 09:31:10 2014
@@ -1575,13 +1575,13 @@ svn_error_t *
 svn_fs_base__dag_commit_txn(svn_revnum_t *new_rev,
                             svn_fs_txn_t *txn,
                             trail_t *trail,
-                            svn_boolean_t set_timestamp,
                             apr_pool_t *pool)
 {
   revision_t revision;
   apr_hash_t *txnprops;
   svn_fs_t *fs = txn->fs;
   const char *txn_id = txn->id;
+  const svn_string_t *client_date;
 
   /* Remove any temporary transaction properties initially created by
      begin_txn().  */
@@ -1600,11 +1600,16 @@ svn_fs_base__dag_commit_txn(svn_revnum_t
     SVN_ERR(svn_fs_base__set_txn_prop
             (fs, txn_id, SVN_FS__PROP_TXN_CHECK_LOCKS, NULL, trail, pool));
 
+  client_date = svn_hash_gets(txnprops, SVN_FS__PROP_TXN_CLIENT_DATE);
+  if (client_date)
+    SVN_ERR(svn_fs_base__set_txn_prop
+            (fs, txn_id, SVN_FS__PROP_TXN_CLIENT_DATE, NULL, trail, pool));
+
   /* Promote the unfinished transaction to a committed one. */
   SVN_ERR(svn_fs_base__txn_make_committed(fs, txn_id, *new_rev,
                                           trail, pool));
 
-  if (set_timestamp)
+  if (!client_date || strcmp(client_date->data, "1"))
     {
       /* Set a date on the commit if requested.  We wait until now to fetch the
          date, so it's definitely newer than any previous revision's date. */

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/dag.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/dag.h?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/dag.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/dag.h Thu Jan  9 09:31:10 2014
@@ -273,16 +273,12 @@ svn_error_t *svn_fs_base__dag_clone_root
    latest revision in TXN->FS.  If the caller doesn't take care of this,
    you may lose people's work!
 
-   Update commit time to ensure that svn:date revprops remain ordered if
-   SET_TIMESTAMP is non-zero.
-
    Do any necessary temporary allocation in a subpool of POOL.
    Consume temporary space at most proportional to the maximum depth
    of SVN_TXN's tree of mutable nodes.  */
 svn_error_t *svn_fs_base__dag_commit_txn(svn_revnum_t *new_rev,
                                          svn_fs_txn_t *txn,
                                          trail_t *trail,
-                                         svn_boolean_t set_timestamp,
                                          apr_pool_t *pool);
 
 

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/revs-txns.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/revs-txns.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/revs-txns.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/revs-txns.c Thu Jan  9 09:31:10 2014
@@ -574,6 +574,10 @@ svn_fs_base__set_txn_prop(svn_fs_t *fs,
     txn->proplist = apr_hash_make(pool);
 
   /* Set the property. */
+  if (svn_hash_gets(txn->proplist, SVN_FS__PROP_TXN_CLIENT_DATE)
+      && !strcmp(name, SVN_PROP_REVISION_DATE))
+    svn_hash_sets(txn->proplist, SVN_FS__PROP_TXN_CLIENT_DATE,
+                  svn_string_create("1", pool));
   svn_hash_sets(txn->proplist, name, value);
 
   /* Now overwrite the transaction. */
@@ -707,6 +711,17 @@ txn_body_begin_txn(void *baton, trail_t 
       SVN_ERR(txn_body_change_txn_prop(&cpargs, trail));
     }
 
+  if (args->flags & SVN_FS_TXN_CLIENT_DATE)
+    {
+      struct change_txn_prop_args cpargs;
+      cpargs.fs = trail->fs;
+      cpargs.id = txn_id;
+      cpargs.name = SVN_FS__PROP_TXN_CLIENT_DATE;
+      cpargs.value = svn_string_create("0", trail->pool);
+
+      SVN_ERR(txn_body_change_txn_prop(&cpargs, trail));
+    }
+
   *args->txn_p = make_txn(trail->fs, txn_id, args->base_rev, trail->pool);
   return SVN_NO_ERROR;
 }