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 2012/12/04 16:35:57 UTC

svn commit: r1416996 [4/13] - in /subversion/branches/wc-collate-path: ./ build/ build/ac-macros/ build/generator/ contrib/client-side/svnmerge/ contrib/server-side/svncutter/ notes/ subversion/bindings/cxxhl/ subversion/bindings/javahl/native/ subvers...

Modified: subversion/branches/wc-collate-path/subversion/libsvn_client/info.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_client/info.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_client/info.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_client/info.c Tue Dec  4 15:35:13 2012
@@ -248,75 +248,6 @@ wc_info_receiver(void *baton,
                                  abspath_or_url, &client_info, scratch_pool);
 }
 
-/* Like svn_ra_stat() but with a compatibility hack for pre-1.2 svnserve. */
-static svn_error_t *
-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)
-{
-  const char *repos_root_URL, *url;
-  svn_error_t *err;
-  svn_dirent_t *the_ent;
-
-  SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_URL, pool));
-  SVN_ERR(svn_ra_get_session_url(ra_session, &url, pool));
-
-  err = svn_ra_stat(ra_session, "", rev, &the_ent, pool);
-
-  /* svn_ra_stat() will work against old versions of mod_dav_svn, but
-     not old versions of svnserve.  In the case of a pre-1.2 svnserve,
-     catch the specific error it throws:*/
-  if (err && err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED)
-    {
-      /* Fall back to pre-1.2 strategy for fetching dirent's URL. */
-      svn_node_kind_t url_kind;
-      svn_ra_session_t *parent_ra_session;
-      apr_hash_t *parent_ents;
-      const char *parent_url, *base_name;
-
-      if (strcmp(url, repos_root_URL) == 0)
-        {
-          /* In this universe, there's simply no way to fetch
-             information about the repository's root directory! */
-          return err;
-        }
-
-      svn_error_clear(err);
-
-      SVN_ERR(svn_ra_check_path(ra_session, "", rev, &url_kind, pool));
-      if (url_kind == svn_node_none)
-        return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
-                                 _("URL '%s' non-existent in revision %ld"),
-                                 url, rev);
-
-      /* Open a new RA session to the item's parent. */
-      svn_uri_split(&parent_url, &base_name, url, pool);
-      SVN_ERR(svn_client__open_ra_session_internal(&parent_ra_session, NULL,
-                                                   parent_url, NULL,
-                                                   NULL, FALSE, TRUE,
-                                                   ctx, pool));
-
-      /* Get all parent's entries, and find the item's dirent in the hash. */
-      SVN_ERR(svn_ra_get_dir2(parent_ra_session, &parent_ents, NULL, NULL,
-                              "", rev, dirent_fields, pool));
-      the_ent = apr_hash_get(parent_ents, base_name, APR_HASH_KEY_STRING);
-      if (the_ent == NULL)
-        return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
-                                 _("URL '%s' non-existent in revision %ld"),
-                                 url, rev);
-    }
-  else if (err)
-    {
-      return svn_error_trace(err);
-    }
-
-  *dirent_p = the_ent;
-  return SVN_NO_ERROR;
-}
-
 svn_error_t *
 svn_client_info3(const char *abspath_or_url,
                  const svn_opt_revision_t *peg_revision,
@@ -371,28 +302,8 @@ svn_client_info3(const char *abspath_or_
   svn_uri_split(NULL, &base_name, pathrev->url, pool);
 
   /* Get the dirent for the URL itself. */
-  err = ra_stat_compatible(ra_session, pathrev->rev, &the_ent, DIRENT_FIELDS,
-                           ctx, pool);
-  if (err && err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED)
-    {
-      svn_error_clear(err);
-
-      /* If we're recursing, degrade gracefully: rather than
-         throw an error, return no information about the
-         repos root. */
-      if (depth > svn_depth_empty)
-        goto pre_1_2_recurse;
-
-      /* Otherwise, we really are stuck.  Better tell the user
-         what's going on. */
-      return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
-                               _("Server does not support retrieving "
-                                 "information about the repository root"));
-    }
-  else if (err)
-    {
-      return svn_error_trace(err);
-    }
+  SVN_ERR(svn_client__ra_stat_compatible(ra_session, pathrev->rev, &the_ent,
+                                         DIRENT_FIELDS, ctx, pool));
 
   if (! the_ent)
     return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
@@ -436,7 +347,6 @@ svn_client_info3(const char *abspath_or_
     {
       apr_hash_t *locks;
 
-pre_1_2_recurse:
       if (peg_revision->kind == svn_opt_revision_head)
         {
           err = svn_ra_get_locks2(ra_session, &locks, "", depth,

Modified: subversion/branches/wc-collate-path/subversion/libsvn_client/iprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_client/iprops.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_client/iprops.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_client/iprops.c Tue Dec  4 15:35:13 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/wc-collate-path/subversion/libsvn_client/list.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_client/list.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_client/list.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_client/list.c Tue Dec  4 15:35:13 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);
@@ -123,57 +161,67 @@ get_dir_contents(apr_uint32_t dirent_fie
 }
 
 /* Like svn_ra_stat() but with a compatibility hack for pre-1.2 svnserve. */
-static svn_error_t *
-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)
+/* ### 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)
 {
-  const char *repos_root, *url;
   svn_error_t *err;
-  svn_dirent_t *dirent;
 
-  SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root, pool));
-  SVN_ERR(svn_ra_get_session_url(ra_session, &url, pool));
-
-  err = svn_ra_stat(ra_session, "", rev, &dirent, pool);
+  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(url, repos_root) != 0)
+          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, url, pool);
+              svn_uri_split(&parent_url, &base_name, session_url, subpool);
 
               SVN_ERR(svn_client__open_ra_session_internal(&parent_session,
                                                            NULL, parent_url,
                                                            NULL, NULL, FALSE,
-                                                           TRUE, ctx, pool));
+                                                           TRUE, ctx, subpool));
 
               /* Get all parent's entries, no props. */
               SVN_ERR(svn_ra_get_dir2(parent_session, &parent_ents, NULL,
-                                      NULL, "", rev, dirent_fields, pool));
+                                      NULL, "", rev, dirent_fields, subpool));
 
               /* Get the relevant entry. */
               dirent = apr_hash_get(parent_ents, base_name,
                                     APR_HASH_KEY_STRING);
+
+              if (dirent)
+                *dirent_p = svn_dirent_dup(dirent, pool);
+              else
+                *dirent_p = NULL;
+
+              svn_pool_destroy(subpool); /* Close RA session */
             }
           else
             {
@@ -183,7 +231,7 @@ ra_stat_compatible(svn_ra_session_t *ra_
                  be rev. */
               dirent = apr_palloc(pool, sizeof(*dirent));
               dirent->kind = kind;
-              dirent->size = 0;
+              dirent->size = SVN_INVALID_FILESIZE;
               if (dirent_fields & SVN_DIRENT_HAS_PROPS)
                 {
                   apr_hash_t *props;
@@ -212,29 +260,33 @@ ra_stat_compatible(svn_ra_session_t *ra_
                                      APR_HASH_KEY_STRING);
                   dirent->last_author = val ? val->data : NULL;
                 }
+
+              *dirent_p = dirent;
             }
         }
       else
-        dirent = NULL;
+        *dirent_p = NULL;
     }
-  else if (err)
-    return svn_error_trace(err);
+  else
+    SVN_ERR(err);
 
-  *dirent_p = dirent;
   return SVN_NO_ERROR;
 }
 
 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;
@@ -242,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. */
@@ -255,8 +313,8 @@ svn_client_list2(const char *path_or_url
 
   fs_path = svn_client__pathrev_fspath(loc, pool);
 
-  SVN_ERR(ra_stat_compatible(ra_session, loc->rev, &dirent, dirent_fields,
-                             ctx, pool));
+  SVN_ERR(svn_client__ra_stat_compatible(ra_session, loc->rev, &dirent,
+                                         dirent_fields, ctx, pool));
   if (! dirent)
     return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
                              _("URL '%s' non-existent in revision %ld"),
@@ -284,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/wc-collate-path/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_client/merge.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_client/merge.c Tue Dec  4 15:35:13 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;
@@ -11788,21 +11871,37 @@ svn_client_automatic_merge_is_reintegrat
 }
 
 svn_error_t *
-svn_client__automatic_merge_get_locations(
-                                svn_client__pathrev_t **yca,
-                                svn_client__pathrev_t **base,
-                                svn_client__pathrev_t **right,
-                                svn_client__pathrev_t **target,
+svn_client_automatic_merge_get_locations(
+                                const char **yca_url,
+                                svn_revnum_t *yca_rev,
+                                const char **base_url,
+                                svn_revnum_t *base_rev,
+                                const char **right_url,
+                                svn_revnum_t *right_rev,
+                                const char **target_url,
+                                svn_revnum_t *target_rev,
+                                const char **repos_root_url,
                                 const svn_client_automatic_merge_t *merge,
                                 apr_pool_t *result_pool)
 {
-  if (yca)
-    *yca = svn_client__pathrev_dup(merge->yca, result_pool);
-  if (base)
-    *base = svn_client__pathrev_dup(merge->base, result_pool);
-  if (right)
-    *right = svn_client__pathrev_dup(merge->right, result_pool);
-  if (target)
-    *target = svn_client__pathrev_dup(merge->target, result_pool);
+  if (yca_url)
+    *yca_url = apr_pstrdup(result_pool, merge->yca->url);
+  if (yca_rev)
+    *yca_rev = merge->yca->rev;
+  if (base_url)
+    *base_url = apr_pstrdup(result_pool, merge->base->url);
+  if (base_rev)
+    *base_rev = merge->base->rev;
+  if (right_url)
+    *right_url = apr_pstrdup(result_pool, merge->right->url);
+  if (right_rev)
+    *right_rev = merge->right->rev;
+  if (target_url)
+    *target_url = apr_pstrdup(result_pool, merge->target->url);
+  if (target_rev)
+    *target_rev = merge->target->rev;
+  if (repos_root_url)
+    *repos_root_url = apr_pstrdup(result_pool, merge->yca->repos_root_url);
+
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/wc-collate-path/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_client/mergeinfo.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_client/mergeinfo.c Tue Dec  4 15:35:13 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/wc-collate-path/subversion/libsvn_client/mergeinfo.h
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_client/mergeinfo.h?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_client/mergeinfo.h (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_client/mergeinfo.h Tue Dec  4 15:35:13 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/wc-collate-path/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_client/prop_commands.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_client/prop_commands.c Tue Dec  4 15:35:13 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);
@@ -915,12 +892,12 @@ svn_client_propget5(apr_hash_t **props,
       if (inherited_props && local_iprops)
         SVN_ERR(svn_wc__get_iprops(inherited_props, ctx->wc_ctx,
                                    target, propname,
-                                   scratch_pool, scratch_pool));
+                                   result_pool, scratch_pool));
 
       SVN_ERR(get_prop_from_wc(props, propname, target,
                                pristine, kind,
-                               depth, changelists, ctx, scratch_pool,
-                               result_pool));
+                               depth, changelists, ctx, result_pool,
+                               scratch_pool));
     }
 
   if ((inherited_props && !local_iprops)

Modified: subversion/branches/wc-collate-path/subversion/libsvn_client/ra.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_client/ra.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_client/ra.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_client/ra.c Tue Dec  4 15:35:13 2012
@@ -1033,9 +1033,9 @@ svn_client__ra_provide_base(svn_stream_t
     {
       /* The pristine contents refer to the BASE, or to the pristine of
          a copy/move to this location. Fetch the correct revision.  */
-      SVN_ERR(svn_wc__node_get_commit_base(revision, NULL, NULL, NULL,
-                                           reb->wc_ctx, local_abspath,
-                                           scratch_pool, scratch_pool));
+      SVN_ERR(svn_wc__node_get_origin(NULL, revision, NULL, NULL, NULL, NULL,
+                                      reb->wc_ctx, local_abspath, FALSE,
+                                      scratch_pool, scratch_pool));
     }
 
   return SVN_NO_ERROR;
@@ -1078,9 +1078,9 @@ svn_client__ra_provide_props(apr_hash_t 
     {
       /* The pristine props refer to the BASE, or to the pristine props of
          a copy/move to this location. Fetch the correct revision.  */
-      SVN_ERR(svn_wc__node_get_commit_base(revision, NULL, NULL, NULL,
-                                           reb->wc_ctx, local_abspath,
-                                           scratch_pool, scratch_pool));
+      SVN_ERR(svn_wc__node_get_origin(NULL, revision, NULL, NULL, NULL, NULL,
+                                      reb->wc_ctx, local_abspath, FALSE,
+                                      scratch_pool, scratch_pool));
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/wc-collate-path/subversion/libsvn_client/revisions.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_client/revisions.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_client/revisions.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_client/revisions.c Tue Dec  4 15:35:13 2012
@@ -91,9 +91,9 @@ svn_client__get_revision_number(svn_revn
         if (svn_path_is_url(local_abspath))
           goto invalid_rev_arg;
 
-        err = svn_wc__node_get_commit_base(revnum, NULL, NULL, NULL,
-                                           wc_ctx, local_abspath,
-                                           scratch_pool, scratch_pool);
+        err = svn_wc__node_get_origin(NULL, revnum, NULL, NULL, NULL, NULL,
+                                      wc_ctx, local_abspath, TRUE,
+                                      scratch_pool, scratch_pool);
 
         /* Return the same error as older code did (before and at r935091).
            At least svn_client_proplist4 promises SVN_ERR_ENTRY_NOT_FOUND. */

Modified: subversion/branches/wc-collate-path/subversion/libsvn_delta/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_delta/compat.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_delta/compat.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_delta/compat.c Tue Dec  4 15:35:13 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.  */
@@ -911,7 +911,7 @@ ev2_abort_edit(void *edit_baton,
 }
 
 /* Return a svn_delta_editor_t * in DEDITOR, with an accompanying baton in
- * DEDITOR_BATON, which will be driven by EDITOR.  These will both be
+ * DEDITOR_BATON, which will drive EDITOR.  These will both be
  * allocated in RESULT_POOL, which may become large and long-lived;
  * SCRATCH_POOL is used for temporary allocations.
  *
@@ -1832,7 +1832,7 @@ do_unlock(void *baton,
   return SVN_NO_ERROR;
 }
 
-/* Return an svn_editor_t * in EDITOR_P which will be driven by
+/* Return an svn_editor_t * in EDITOR_P which will drive
  * DEDITOR/DEDIT_BATON.  EDITOR_P is allocated in RESULT_POOL, which may
  * become large and long-lived; SCRATCH_POOL is used for temporary
  * allocations.

Modified: subversion/branches/wc-collate-path/subversion/libsvn_delta/debug_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_delta/debug_editor.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_delta/debug_editor.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_delta/debug_editor.c Tue Dec  4 15:35:13 2012
@@ -52,6 +52,8 @@ write_indent(struct edit_baton *eb, apr_
 {
   int i;
 
+  /* This is DBG_FLAG from ../libsvn_subr/debug.c */
+  SVN_ERR(svn_stream_puts(eb->out, "DBG:"));
   for (i = 0; i < eb->indent_level; ++i)
     SVN_ERR(svn_stream_puts(eb->out, " "));
 

Modified: subversion/branches/wc-collate-path/subversion/libsvn_delta/svndiff.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_delta/svndiff.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_delta/svndiff.c Tue Dec  4 15:35:13 2012
@@ -181,6 +181,7 @@ zlib_encode(const char *data,
           return SVN_NO_ERROR;
         }
       out->len = endlen + intlen;
+      out->data[out->len] = 0;
     }
   return SVN_NO_ERROR;
 }
@@ -228,10 +229,11 @@ send_simple_insertion_window(svn_txdelta
       ip_len = encode_int(ibuf + 1, window->tview_len) - ibuf;
     }
 
-  /* encode the window header.  */
-  header_current[0] = 0;  /* source offset == 0 */
-  header_current[1] = 0;  /* source length == 0 */
-  header_current = encode_int(header_current + 2, window->tview_len);
+  /* encode the window header.  Please note that the source window may
+   * have content despite not being used for deltification. */
+  header_current = encode_int(header_current, window->sview_offset);
+  header_current = encode_int(header_current, window->sview_len);
+  header_current = encode_int(header_current, window->tview_len);
   header_current[0] = (unsigned char)ip_len;  /* 1 instruction */
   header_current = encode_int(&header_current[1], len);
 
@@ -569,6 +571,7 @@ zlib_decode(const unsigned char *in, apr
                                 NULL,
                                 _("Size of uncompressed data "
                                   "does not match stored original length"));
+      out->data[zlen] = 0;
       out->len = zlen;
     }
   return SVN_NO_ERROR;

Modified: subversion/branches/wc-collate-path/subversion/libsvn_delta/text_delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_delta/text_delta.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_delta/text_delta.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_delta/text_delta.c Tue Dec  4 15:35:13 2012
@@ -709,6 +709,7 @@ svn_txdelta_apply_instructions(svn_txdel
         {
         case svn_txdelta_source:
           /* Copy from source area.  */
+          assert(sbuf);
           assert(op->offset + op->length <= window->sview_len);
           fast_memcpy(tbuf + tpos, sbuf + op->offset, buf_len);
           break;

Modified: subversion/branches/wc-collate-path/subversion/libsvn_diff/diff.h
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_diff/diff.h?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_diff/diff.h (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_diff/diff.h Tue Dec  4 15:35:13 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/wc-collate-path/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_diff/diff_file.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_diff/diff_file.c Tue Dec  4 15:35:13 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/wc-collate-path/subversion/libsvn_diff/diff_memory.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_diff/diff_memory.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_diff/diff_memory.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_diff/diff_memory.c Tue Dec  4 15:35:13 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/wc-collate-path/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_diff/parse-diff.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_diff/parse-diff.c Tue Dec  4 15:35:13 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/wc-collate-path/subversion/libsvn_diff/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_diff/util.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_diff/util.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_diff/util.c Tue Dec  4 15:35:13 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/wc-collate-path/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/fs.h?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/fs.h Tue Dec  4 15:35:13 2012
@@ -180,6 +180,7 @@ typedef struct fs_fs_shared_txn_data_t
    per file.  On Windows apr implements the locking as per file handle
    locks, so we don't have to add our own mutex for just in-process
    synchronization. */
+/* Compare ../libsvn_subr/named_atomic.c:USE_THREAD_MUTEX */
 #if APR_HAS_THREADS && !defined(WIN32)
 #define SVN_FS_FS__USE_LOCK_MUTEX 1
 #else