You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2012/03/06 18:50:31 UTC

svn commit: r1297604 [3/12] - in /subversion/branches/reintegrate-keep-alive: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ notes/ notes/api-errata/1.7/ subversion/bindings/javahl/native/ subversion/bindings/javahl...

Modified: subversion/branches/reintegrate-keep-alive/subversion/include/svn_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/include/svn_fs.h?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/include/svn_fs.h (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/include/svn_fs.h Tue Mar  6 17:50:23 2012
@@ -250,6 +250,10 @@ svn_fs_upgrade(const char *path,
  * to the Subversion filesystem located in the directory @a path.
  * Use @a pool for necessary allocations.
  *
+ * @a start and @a end may be #SVN_INVALID_REVNUM, in which case
+ * svn_repos_verify_fs2()'s semantics apply.  When @c r0 is being
+ * verified, global invariants may be verified as well.
+ *
  * @note You probably don't want to use this directly.  Take a look at
  * svn_repos_verify_fs2() instead, which does non-backend-specific
  * verifications as well.
@@ -260,7 +264,9 @@ svn_error_t *
 svn_fs_verify(const char *path,
               svn_cancel_func_t cancel_func,
               void *cancel_baton,
-              apr_pool_t *pool);
+              svn_revnum_t start,
+              svn_revnum_t end,
+              apr_pool_t *scratch_pool);
 
 /**
  * Return, in @a *fs_type, a string identifying the back-end type of

Modified: subversion/branches/reintegrate-keep-alive/subversion/include/svn_io.h
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/include/svn_io.h?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/include/svn_io.h (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/include/svn_io.h Tue Mar  6 17:50:23 2012
@@ -1531,10 +1531,35 @@ svn_io_dir_walk(const char *dirname,
  * Otherwise, the invoked program runs with an empty environment and @a cmd
  * must be an absolute path.
  *
+ * If @a inherit is FALSE and @a env is not NULL, the invoked program
+ * inherits the environment defined by @a env, instead of an empty
+ * environment or the caller's environment.
+ *
  * @note On some platforms, failure to execute @a cmd in the child process
  * will result in error output being written to @a errfile, if non-NULL, and
  * a non-zero exit status being returned to the parent process.
  *
+ * @since New in 1.8.
+ */
+svn_error_t *svn_io_start_cmd3(apr_proc_t *cmd_proc,
+                               const char *path,
+                               const char *cmd,
+                               const char *const *args,
+                               const char *const *env,
+                               svn_boolean_t inherit,
+                               svn_boolean_t infile_pipe,
+                               apr_file_t *infile,
+                               svn_boolean_t outfile_pipe,
+                               apr_file_t *outfile,
+                               svn_boolean_t errfile_pipe,
+                               apr_file_t *errfile,
+                               apr_pool_t *pool);
+
+
+/**
+ * Similar to svn_io_start_cmd3() but with @a env always set to NULL.
+ *
+ * @deprecated Provided for backward compatibility with the 1.7 API
  * @since New in 1.7.
  */
 svn_error_t *svn_io_start_cmd2(apr_proc_t *cmd_proc,

Modified: subversion/branches/reintegrate-keep-alive/subversion/include/svn_ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/include/svn_ra_svn.h?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/include/svn_ra_svn.h (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/include/svn_ra_svn.h Tue Mar  6 17:50:23 2012
@@ -157,6 +157,15 @@ typedef struct svn_ra_svn_item_t
 
 typedef svn_error_t *(*svn_ra_svn_edit_callback)(void *baton);
 
+/**
+ * Set the shim callbacks to be used by @a conn to @a shim_callbacks.
+ *
+ * @note This is a private API, external consumers should not use it.
+ */
+svn_error_t *
+svn_ra_svn__set_shim_callbacks(svn_ra_svn_conn_t *conn,
+                               svn_delta_shim_callbacks_t *shim_callbacks);
+
 /** Initialize a connection structure for the given socket or
  * input/output files.
  *

Modified: subversion/branches/reintegrate-keep-alive/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/include/svn_repos.h?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/include/svn_repos.h (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/include/svn_repos.h Tue Mar  6 17:50:23 2012
@@ -532,7 +532,7 @@ svn_repos_hotcopy2(const char *src_path,
                    void *cancel_baton,
                    apr_pool_t *pool);
 
-/** 
+/**
  * Like svn_repos_hotcopy2(), but without the @a incremental parameter
  * and without cancellation support.
  *
@@ -764,6 +764,17 @@ const char *
 svn_repos_post_unlock_hook(svn_repos_t *repos,
                            apr_pool_t *pool);
 
+/** Set the environment that @a repos's hooks will inherit to @a hooks_env,
+ * a hash table where keys and values represent names and values of environment
+ * variables. @a hooks_env must live at least as long as @a repos.
+ *
+ * If this function is not called, hooks will run in an empty environment.
+ *
+ * @since New in 1.8. */
+void
+svn_repos_hooks_setenv(svn_repos_t *repos,
+                       apr_hash_t *hooks_env);
+
 /** @} */
 
 /* ---------------------------------------------------------------*/
@@ -3016,6 +3027,10 @@ svn_repos_authz_read(svn_authz_t **authz
  * For compatibility with 1.6, and earlier, @a repos_name can be NULL
  * in which case it is equivalent to a @a repos_name of "".
  *
+ * @note Presently, @a repos_name must byte-for-byte match the repos_name
+ * specified in the authz file; it is treated as an opaque string, and not
+ * as a dirent.
+ *
  * @since New in 1.3.
  */
 svn_error_t *

Modified: subversion/branches/reintegrate-keep-alive/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/include/svn_wc.h?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/include/svn_wc.h (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/include/svn_wc.h Tue Mar  6 17:50:23 2012
@@ -3059,7 +3059,7 @@ svn_wc_entry_dup(const svn_wc_entry_t *e
  */
 typedef struct svn_wc_info_t
 {
-  /** The schedule of this item 
+  /** The schedule of this item
    * ### Do we still need schedule? */
   svn_wc_schedule_t schedule;
 
@@ -3657,7 +3657,7 @@ typedef struct svn_wc_status3_t
    * This will be NULL for moved-here nodes that are just part of a subtree
    * that was moved along (and are not themselves a root of a different move
    * operation).
-   * 
+   *
    * @since New in 1.8. */
   const char *moved_from_abspath;
 
@@ -4049,6 +4049,10 @@ svn_wc_walk_status(svn_wc_context_t *wc_
                    apr_pool_t *scratch_pool);
 
 /**
+ * DEPRECATED -- please use APIs from svn_client.h
+ *
+ * ---
+ *
  * Set @a *editor and @a *edit_baton to an editor that generates
  * #svn_wc_status3_t structures and sends them through @a status_func /
  * @a status_baton.  @a anchor_abspath is a working copy directory
@@ -4110,7 +4114,9 @@ svn_wc_walk_status(svn_wc_context_t *wc_
  * in a subpool of @a result_pool.
  *
  * @since New in 1.7.
+ * @deprecated Provided for backward compatibility with the 1.7 API.
  */
+SVN_DEPRECATED
 svn_error_t *
 svn_wc_get_status_editor5(const svn_delta_editor_t **editor,
                           void **edit_baton,
@@ -5487,6 +5493,10 @@ typedef svn_error_t *(*svn_wc_dirents_fu
 
 
 /**
+ * DEPRECATED -- please use APIs from svn_client.h
+ *
+ * ---
+ *
  * Set @a *editor and @a *edit_baton to an editor and baton for updating a
  * working copy.
  *
@@ -5560,7 +5570,9 @@ typedef svn_error_t *(*svn_wc_dirents_fu
  * before returning the editor to allow using the primary ra session for this.
  *
  * @since New in 1.7.
+ * @deprecated Provided for backward compatibility with the 1.7 API.
  */
+SVN_DEPRECATED
 svn_error_t *
 svn_wc_get_update_editor4(const svn_delta_editor_t **editor,
                           void **edit_baton,
@@ -5691,6 +5703,10 @@ svn_wc_get_update_editor(svn_revnum_t *t
                          apr_pool_t *pool);
 
 /**
+ * DEPRECATED -- please use APIs from svn_client.h
+ *
+ * ---
+ *
  * A variant of svn_wc_get_update_editor4().
  *
  * Set @a *editor and @a *edit_baton to an editor and baton for "switching"
@@ -5701,7 +5717,9 @@ svn_wc_get_update_editor(svn_revnum_t *t
  * All other parameters behave as for svn_wc_get_update_editor4().
  *
  * @since New in 1.7.
+ * @deprecated Provided for backward compatibility with the 1.7 API.
  */
+SVN_DEPRECATED
 svn_error_t *
 svn_wc_get_switch_editor4(const svn_delta_editor_t **editor,
                           void **edit_baton,
@@ -6138,6 +6156,10 @@ svn_wc_canonicalize_svn_prop(const svn_s
  */
 
 /**
+ * DEPRECATED -- please use APIs from svn_client.h
+ *
+ * ---
+ *
  * Return an @a editor/@a edit_baton for diffing a working copy against the
  * repository. The editor is allocated in @a result_pool; temporary
  * calculations are performed in @a scratch_pool.
@@ -6191,7 +6213,9 @@ svn_wc_canonicalize_svn_prop(const svn_s
  * editor.
  *
  * @since New in 1.7.
+ * @deprecated Provided for backward compatibility with the 1.7 API.
  */
+SVN_DEPRECATED
 svn_error_t *
 svn_wc_get_diff_editor6(const svn_delta_editor_t **editor,
                         void **edit_baton,

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_auth_gnome_keyring/gnome_keyring.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_auth_gnome_keyring/gnome_keyring.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_auth_gnome_keyring/gnome_keyring.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_auth_gnome_keyring/gnome_keyring.c Tue Mar  6 17:50:23 2012
@@ -230,10 +230,60 @@ unlock_gnome_keyring(const char *keyring
   return TRUE;
 }
 
-/* Implementation of password_get_t that retrieves the password
+
+/* There is a race here: this ensures keyring is unlocked just now,
+   but will it still be unlocked when we use it? */
+static svn_error_t *
+ensure_gnome_keyring_is_unlocked(svn_boolean_t non_interactive,
+                                 apr_hash_t *parameters,
+                                 apr_pool_t *scratch_pool)
+{
+  const char *default_keyring = get_default_keyring_name(scratch_pool);
+
+  if (! non_interactive)
+    {
+      svn_auth_gnome_keyring_unlock_prompt_func_t unlock_prompt_func =
+        apr_hash_get(parameters,
+                     SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC,
+                     APR_HASH_KEY_STRING);
+      void *unlock_prompt_baton =
+        apr_hash_get(parameters,
+                     SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_BATON,
+                     APR_HASH_KEY_STRING);
+
+      char *keyring_password;
+
+      if (unlock_prompt_func && check_keyring_is_locked(default_keyring))
+        {
+          SVN_ERR((*unlock_prompt_func)(&keyring_password,
+                                        default_keyring,
+                                        unlock_prompt_baton,
+                                        scratch_pool));
+
+          /* If keyring is locked give up and try the next provider. */
+          if (! unlock_gnome_keyring(default_keyring, keyring_password,
+                                     scratch_pool))
+            return SVN_NO_ERROR;
+        }
+    }
+  else
+    {
+      if (check_keyring_is_locked(default_keyring))
+        {
+          return svn_error_create(SVN_ERR_AUTHN_CREDS_UNAVAILABLE, NULL,
+                                  _("GNOME Keyring is locked and "
+                                    "we are non-interactive"));
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* Implementation of svn_auth__password_get_t that retrieves the password
    from GNOME Keyring. */
-static svn_boolean_t
-password_get_gnome_keyring(const char **password,
+static svn_error_t *
+password_get_gnome_keyring(svn_boolean_t *done,
+                           const char **password,
                            apr_hash_t *creds,
                            const char *realmstring,
                            const char *username,
@@ -244,13 +294,10 @@ password_get_gnome_keyring(const char **
   char *default_keyring = NULL;
   GnomeKeyringResult result;
   GList *items;
-  svn_boolean_t ret = FALSE;
 
-  if (! dbus_bus_get(DBUS_BUS_SESSION, NULL))
-    return FALSE;
+  *done = FALSE;
 
-  if (! gnome_keyring_is_available())
-    return FALSE;
+  SVN_ERR(ensure_gnome_keyring_is_unlocked(non_interactive, parameters, pool));
 
   default_keyring = get_default_keyring_name(pool);
 
@@ -278,7 +325,7 @@ password_get_gnome_keyring(const char **
               if (len > 0)
                 {
                   *password = apr_pstrmemdup(pool, item->password, len);
-                  ret = TRUE;
+                  *done = TRUE;
                 }
             }
           gnome_keyring_network_password_list_free(items);
@@ -294,13 +341,14 @@ password_get_gnome_keyring(const char **
 
   free(default_keyring);
 
-  return ret;
+  return SVN_NO_ERROR;
 }
 
-/* Implementation of password_set_t that stores the password in
+/* Implementation of svn_auth__password_set_t that stores the password in
    GNOME Keyring. */
-static svn_boolean_t
-password_set_gnome_keyring(apr_hash_t *creds,
+static svn_error_t *
+password_set_gnome_keyring(svn_boolean_t *done,
+                           apr_hash_t *creds,
                            const char *realmstring,
                            const char *username,
                            const char *password,
@@ -312,11 +360,9 @@ password_set_gnome_keyring(apr_hash_t *c
   GnomeKeyringResult result;
   guint32 item_id;
 
-  if (! dbus_bus_get(DBUS_BUS_SESSION, NULL))
-    return FALSE;
+  *done = FALSE;
 
-  if (! gnome_keyring_is_available())
-    return FALSE;
+  SVN_ERR(ensure_gnome_keyring_is_unlocked(non_interactive, parameters, pool));
 
   default_keyring = get_default_keyring_name(pool);
 
@@ -344,7 +390,8 @@ password_set_gnome_keyring(apr_hash_t *c
 
   free(default_keyring);
 
-  return result == GNOME_KEYRING_RESULT_OK;
+  *done = (result == GNOME_KEYRING_RESULT_OK);
+  return SVN_NO_ERROR;
 }
 
 /* Get cached encrypted credentials from the simple provider's cache. */
@@ -356,43 +403,6 @@ simple_gnome_keyring_first_creds(void **
                                  const char *realmstring,
                                  apr_pool_t *pool)
 {
-  svn_boolean_t non_interactive = apr_hash_get(parameters,
-                                               SVN_AUTH_PARAM_NON_INTERACTIVE,
-                                               APR_HASH_KEY_STRING) != NULL;
-  const char *default_keyring = get_default_keyring_name(pool);
-  if (! non_interactive)
-    {
-      svn_auth_gnome_keyring_unlock_prompt_func_t unlock_prompt_func =
-        apr_hash_get(parameters,
-                     SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC,
-                     APR_HASH_KEY_STRING);
-      void *unlock_prompt_baton =
-        apr_hash_get(parameters, SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_BATON,
-                     APR_HASH_KEY_STRING);
-
-      char *keyring_password;
-
-      if (unlock_prompt_func && check_keyring_is_locked(default_keyring))
-        {
-          SVN_ERR((*unlock_prompt_func)(&keyring_password,
-                                        default_keyring,
-                                        unlock_prompt_baton,
-                                        pool));
-
-          /* If keyring is locked give up and try the next provider. */
-          if (! unlock_gnome_keyring(default_keyring, keyring_password, pool))
-            return SVN_NO_ERROR;
-        }
-    }
-  else
-    {
-      if (check_keyring_is_locked(default_keyring))
-        {
-          return svn_error_create(SVN_ERR_AUTHN_CREDS_UNAVAILABLE, NULL,
-                                  _("GNOME Keyring is locked and "
-                                    "we are non-interactive"));
-        }
-    }
   return svn_auth__simple_first_creds_helper
            (credentials,
             iter_baton, provider_baton,
@@ -411,43 +421,6 @@ simple_gnome_keyring_save_creds(svn_bool
                                 const char *realmstring,
                                 apr_pool_t *pool)
 {
-  svn_boolean_t non_interactive = apr_hash_get(parameters,
-                                               SVN_AUTH_PARAM_NON_INTERACTIVE,
-                                               APR_HASH_KEY_STRING) != NULL;
-  const char *default_keyring = get_default_keyring_name(pool);
-  if (! non_interactive)
-    {
-      svn_auth_gnome_keyring_unlock_prompt_func_t unlock_prompt_func =
-        apr_hash_get(parameters,
-                     SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC,
-                     APR_HASH_KEY_STRING);
-      void *unlock_prompt_baton =
-        apr_hash_get(parameters, SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_BATON,
-                     APR_HASH_KEY_STRING);
-
-      char *keyring_password;
-
-      if (unlock_prompt_func && check_keyring_is_locked(default_keyring))
-        {
-          SVN_ERR((*unlock_prompt_func)(&keyring_password,
-                                        default_keyring,
-                                        unlock_prompt_baton,
-                                        pool));
-
-          /* If keyring is locked give up and try the next provider. */
-          if (! unlock_gnome_keyring(default_keyring, keyring_password, pool))
-            return SVN_NO_ERROR;
-        }
-    }
-  else
-    {
-      if (check_keyring_is_locked(default_keyring))
-        {
-          return svn_error_create(SVN_ERR_AUTHN_CREDS_NOT_SAVED, NULL,
-                                  _("GNOME Keyring is locked and "
-                                    "we are non-interactive"));
-        }
-    }
   return svn_auth__simple_save_creds_helper
            (saved, credentials,
             provider_baton, parameters,
@@ -518,43 +491,6 @@ ssl_client_cert_pw_gnome_keyring_first_c
                                              const char *realmstring,
                                              apr_pool_t *pool)
 {
-  svn_boolean_t non_interactive = apr_hash_get(parameters,
-                                               SVN_AUTH_PARAM_NON_INTERACTIVE,
-                                               APR_HASH_KEY_STRING) != NULL;
-  const char *default_keyring = get_default_keyring_name(pool);
-  if (! non_interactive)
-    {
-      svn_auth_gnome_keyring_unlock_prompt_func_t unlock_prompt_func =
-        apr_hash_get(parameters,
-                     SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC,
-                     APR_HASH_KEY_STRING);
-      void *unlock_prompt_baton =
-        apr_hash_get(parameters, SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_BATON,
-                     APR_HASH_KEY_STRING);
-
-      char *keyring_password;
-
-      if (unlock_prompt_func && check_keyring_is_locked(default_keyring))
-        {
-          SVN_ERR((*unlock_prompt_func)(&keyring_password,
-                                        default_keyring,
-                                        unlock_prompt_baton,
-                                        pool));
-
-          /* If keyring is locked give up and try the next provider. */
-          if (! unlock_gnome_keyring(default_keyring, keyring_password, pool))
-            return SVN_NO_ERROR;
-        }
-    }
-  else
-    {
-      if (check_keyring_is_locked(default_keyring))
-        {
-          return svn_error_create(SVN_ERR_AUTHN_CREDS_UNAVAILABLE, NULL,
-                                  _("GNOME Keyring is locked and "
-                                    "we are non-interactive"));
-        }
-    }
   return svn_auth__ssl_client_cert_pw_file_first_creds_helper
            (credentials,
             iter_baton, provider_baton,
@@ -574,43 +510,6 @@ ssl_client_cert_pw_gnome_keyring_save_cr
                                             const char *realmstring,
                                             apr_pool_t *pool)
 {
-  svn_boolean_t non_interactive = apr_hash_get(parameters,
-                                               SVN_AUTH_PARAM_NON_INTERACTIVE,
-                                               APR_HASH_KEY_STRING) != NULL;
-  const char *default_keyring = get_default_keyring_name(pool);
-  if (! non_interactive)
-    {
-      svn_auth_gnome_keyring_unlock_prompt_func_t unlock_prompt_func =
-        apr_hash_get(parameters,
-                     SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC,
-                     APR_HASH_KEY_STRING);
-      void *unlock_prompt_baton =
-        apr_hash_get(parameters, SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_BATON,
-                     APR_HASH_KEY_STRING);
-
-      char *keyring_password;
-
-      if (unlock_prompt_func && check_keyring_is_locked(default_keyring))
-        {
-          SVN_ERR((*unlock_prompt_func)(&keyring_password,
-                                        default_keyring,
-                                        unlock_prompt_baton,
-                                        pool));
-
-          /* If keyring is locked give up and try the next provider. */
-          if (! unlock_gnome_keyring(default_keyring, keyring_password, pool))
-            return SVN_NO_ERROR;
-         }
-    }
-  else
-    {
-      if (check_keyring_is_locked(default_keyring))
-        {
-          return svn_error_create(SVN_ERR_AUTHN_CREDS_NOT_SAVED, NULL,
-                                  _("GNOME Keyring is locked and "
-                                    "we are non-interactive"));
-        }
-    }
   return svn_auth__ssl_client_cert_pw_file_save_creds_helper
            (saved, credentials,
             provider_baton, parameters,

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_auth_kwallet/kwallet.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_auth_kwallet/kwallet.cpp?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_auth_kwallet/kwallet.cpp (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_auth_kwallet/kwallet.cpp Tue Mar  6 17:50:23 2012
@@ -181,8 +181,9 @@ kwallet_terminate(void *data)
 
 /* Implementation of svn_auth__password_get_t that retrieves
    the password from KWallet. */
-static svn_boolean_t
-kwallet_password_get(const char **password,
+static svn_error_t *
+kwallet_password_get(svn_boolean_t *done,
+                     const char **password,
                      apr_hash_t *creds,
                      const char *realmstring,
                      const char *username,
@@ -190,14 +191,22 @@ kwallet_password_get(const char **passwo
                      svn_boolean_t non_interactive,
                      apr_pool_t *pool)
 {
-  if (non_interactive)
+  QString wallet_name = get_wallet_name(parameters);
+
+  *done = FALSE;
+
+  if (! dbus_bus_get(DBUS_BUS_SESSION, NULL))
     {
-      return FALSE;
+      return SVN_NO_ERROR;
     }
 
-  if (! dbus_bus_get(DBUS_BUS_SESSION, NULL))
+  if (non_interactive)
     {
-      return FALSE;
+      if (!KWallet::Wallet::isOpen(wallet_name))
+        return SVN_NO_ERROR;
+
+      /* There is a race here: the wallet was open just now, but will
+         it still be open when we come to use it below? */
     }
 
   QCoreApplication *app;
@@ -216,8 +225,6 @@ kwallet_password_get(const char **passwo
                      ki18n("Version control system"),
                      KCmdLineArgs::CmdLineArgKDE);
   KComponentData component_data(KCmdLineArgs::aboutData());
-  svn_boolean_t ret = FALSE;
-  QString wallet_name = get_wallet_name(parameters);
   QString folder = QString::fromUtf8("Subversion");
   QString key =
     QString::fromUtf8(username) + "@" + QString::fromUtf8(realmstring);
@@ -238,7 +245,7 @@ kwallet_password_get(const char **passwo
                   *password = apr_pstrmemdup(pool,
                                              q_password.toUtf8().data(),
                                              q_password.size());
-                  ret = TRUE;
+                  *done = TRUE;
                 }
             }
         }
@@ -246,13 +253,14 @@ kwallet_password_get(const char **passwo
 
   apr_pool_cleanup_register(pool, parameters, kwallet_terminate, NULL);
 
-  return ret;
+  return SVN_NO_ERROR;
 }
 
 /* Implementation of svn_auth__password_set_t that stores
    the password in KWallet. */
-static svn_boolean_t
-kwallet_password_set(apr_hash_t *creds,
+static svn_error_t *
+kwallet_password_set(svn_boolean_t *done,
+                     apr_hash_t *creds,
                      const char *realmstring,
                      const char *username,
                      const char *password,
@@ -260,14 +268,22 @@ kwallet_password_set(apr_hash_t *creds,
                      svn_boolean_t non_interactive,
                      apr_pool_t *pool)
 {
-  if (non_interactive)
+  QString wallet_name = get_wallet_name(parameters);
+
+  *done = FALSE;
+
+  if (! dbus_bus_get(DBUS_BUS_SESSION, NULL))
     {
-      return FALSE;
+      return SVN_NO_ERROR;
     }
 
-  if (! dbus_bus_get(DBUS_BUS_SESSION, NULL))
+  if (non_interactive)
     {
-      return FALSE;
+      if (!KWallet::Wallet::isOpen(wallet_name))
+        return SVN_NO_ERROR;
+
+      /* There is a race here: the wallet was open just now, but will
+         it still be open when we come to use it below? */
     }
 
   QCoreApplication *app;
@@ -286,9 +302,7 @@ kwallet_password_set(apr_hash_t *creds,
                      ki18n("Version control system"),
                      KCmdLineArgs::CmdLineArgKDE);
   KComponentData component_data(KCmdLineArgs::aboutData());
-  svn_boolean_t ret = FALSE;
   QString q_password = QString::fromUtf8(password);
-  QString wallet_name = get_wallet_name(parameters);
   QString folder = QString::fromUtf8("Subversion");
   KWallet::Wallet *wallet = get_wallet(wallet_name, parameters);
   if (wallet)
@@ -307,14 +321,14 @@ kwallet_password_set(apr_hash_t *creds,
             + QString::fromUtf8(realmstring);
           if (wallet->writePassword(key, q_password) == 0)
             {
-              ret = TRUE;
+              *done = TRUE;
             }
         }
     }
 
   apr_pool_cleanup_register(pool, parameters, kwallet_terminate, NULL);
 
-  return ret;
+  return SVN_NO_ERROR;
 }
 
 /* Get cached encrypted credentials from the simple provider's cache. */

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/add.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/add.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/add.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/add.c Tue Mar  6 17:50:23 2012
@@ -47,6 +47,7 @@
 
 #include "private/svn_client_private.h"
 #include "private/svn_wc_private.h"
+#include "private/svn_ra_private.h"
 #include "private/svn_magic.h"
 
 #include "svn_private_config.h"
@@ -896,6 +897,9 @@ mkdir_urls(const apr_array_header_t *url
                                                  ctx, pool));
 
   /* Fetch RA commit editor */
+  SVN_ERR(svn_ra__register_editor_shim_callbacks(ra_session,
+                        svn_client__get_shim_callbacks(ctx->wc_ctx,
+                                                       NULL, pool)));
   SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
                                     commit_revprops,
                                     commit_callback,

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/checkout.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/checkout.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/checkout.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/checkout.c Tue Mar  6 17:50:23 2012
@@ -73,7 +73,6 @@ svn_client__checkout_internal(svn_revnum
                               const char *local_abspath,
                               const svn_opt_revision_t *peg_revision,
                               const svn_opt_revision_t *revision,
-                              const svn_client__ra_session_from_path_results *ra_cache,
                               svn_depth_t depth,
                               svn_boolean_t ignore_externals,
                               svn_boolean_t allow_unver_obstructions,
@@ -88,6 +87,10 @@ svn_client__checkout_internal(svn_revnum
   const char *session_url;
   svn_node_kind_t kind;
   const char *uuid, *repos_root;
+  apr_pool_t *session_pool = svn_pool_create(pool);
+  svn_ra_session_t *ra_session;
+  svn_revnum_t tmp_revnum;
+  const char *tmp_session_url;
 
   /* Sanity check.  Without these, the checkout is meaningless. */
   SVN_ERR_ASSERT(local_abspath != NULL);
@@ -100,60 +103,19 @@ svn_client__checkout_internal(svn_revnum
       && (revision->kind != svn_opt_revision_head))
     return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL, NULL);
 
-  {
-    svn_boolean_t have_repos_root_url;
-    svn_boolean_t have_repos_uuid;
-    svn_boolean_t have_session_url;
-    svn_boolean_t have_revnum;
-    svn_boolean_t have_kind;
-
-    if ((have_repos_root_url = (ra_cache && ra_cache->repos_root_url)))
-      repos_root = ra_cache->repos_root_url;
-
-    if ((have_repos_uuid = (ra_cache && ra_cache->repos_uuid)))
-      uuid = ra_cache->repos_uuid;
-
-    if ((have_session_url = (ra_cache && ra_cache->ra_session_url)))
-      session_url = ra_cache->ra_session_url;
-
-    if ((have_revnum = (ra_cache && SVN_IS_VALID_REVNUM(ra_cache->ra_revnum))))
-      revnum = ra_cache->ra_revnum;
-
-    if ((have_kind = (ra_cache && ra_cache->kind != svn_node_unknown)))
-      kind = ra_cache->kind;
-
-    if (! have_repos_root_url || ! have_repos_uuid || ! have_session_url ||
-        ! have_revnum || ! have_kind)
-      {
-        apr_pool_t *session_pool = svn_pool_create(pool);
-        svn_ra_session_t *ra_session;
-        svn_revnum_t tmp_revnum;
-        const char *tmp_session_url;
-
-        /* Get the RA connection. */
-        SVN_ERR(svn_client__ra_session_from_path(&ra_session, &tmp_revnum,
-                                                 &tmp_session_url, url, NULL,
-                                                 peg_revision, revision, ctx,
-                                                 session_pool));
-
-        if (! have_repos_root_url)
-          SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root, pool));
-
-        if (! have_repos_uuid)
-          SVN_ERR(svn_ra_get_uuid2(ra_session, &uuid, pool));
-
-        if (! have_session_url)
-          session_url = apr_pstrdup(pool, tmp_session_url);
-
-        if (! have_revnum)
-          revnum = tmp_revnum;
-
-        if (! have_kind)
-          SVN_ERR(svn_ra_check_path(ra_session, "", revnum, &kind, pool));
-
-        svn_pool_destroy(session_pool);
-      }
-  }
+  /* Get the RA connection. */
+  SVN_ERR(svn_client__ra_session_from_path(&ra_session, &tmp_revnum,
+                                           &tmp_session_url, url, NULL,
+                                           peg_revision, revision, ctx,
+                                           session_pool));
+
+  SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root, pool));
+  SVN_ERR(svn_ra_get_uuid2(ra_session, &uuid, pool));
+  session_url = apr_pstrdup(pool, tmp_session_url);
+  revnum = tmp_revnum;
+  SVN_ERR(svn_ra_check_path(ra_session, "", revnum, &kind, pool));
+
+  svn_pool_destroy(session_pool);
 
   if (kind == svn_node_none)
     return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
@@ -253,7 +215,7 @@ svn_client_checkout3(svn_revnum_t *resul
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
 
   return svn_client__checkout_internal(result_rev, URL, local_abspath,
-                                       peg_revision, revision, NULL, depth,
+                                       peg_revision, revision, depth,
                                        ignore_externals,
                                        allow_unver_obstructions, NULL,
                                        ctx, pool);

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/client.h?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/client.h (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/client.h Tue Mar  6 17:50:23 2012
@@ -499,36 +499,6 @@ svn_client__update_internal(svn_revnum_t
                             svn_client_ctx_t *ctx,
                             apr_pool_t *pool);
 
-/* Structure holding the results of svn_client__ra_session_from_path()
-   plus the repository root URL and UUID and the node kind for the
-   input URL, REVISION and PEG_REVISION .  See
-   svn_client__ra_session_from_path() for the meaning of these fields.
-   This structure is used by svn_client__checkout_internal() to save
-   one or more round-trips if the client already gathered some of this
-   information.  Not all the fields need to be filled in.  */
-typedef struct svn_client__ra_session_from_path_results
-{
-  /* The repository root URL.  A NULL value means the root URL is
-     unknown.*/
-  const char *repos_root_url;
-
-  /* The repository UUID.  A NULL value means the UUID is unknown.  */
-  const char *repos_uuid;
-
-  /* The actual final resulting URL for the input URL.  This may be
-     different because of copy history.  A NULL value means the
-     resulting URL is unknown.  */
-  const char *ra_session_url;
-
-  /* The actual final resulting revision for the input URL.  An
-     invalid revnum as determined by SVN_IS_VALID_REVNUM() means the
-     revnum is unknown.  */
-  svn_revnum_t ra_revnum;
-
-  /* An optional node kind for the URL.  svn_node_unknown if unknown */
-  svn_node_kind_t kind;
-} svn_client__ra_session_from_path_results;
-
 /* Checkout into LOCAL_ABSPATH a working copy of URL at REVISION, and (if not
    NULL) set RESULT_REV to the checked out revision.
 
@@ -565,7 +535,6 @@ svn_client__checkout_internal(svn_revnum
                               const char *local_abspath,
                               const svn_opt_revision_t *peg_revision,
                               const svn_opt_revision_t *revision,
-                              const svn_client__ra_session_from_path_results *ra_cache,
                               svn_depth_t depth,
                               svn_boolean_t ignore_externals,
                               svn_boolean_t allow_unver_obstructions,
@@ -1104,6 +1073,11 @@ svn_client__get_normalized_stream(svn_st
                                   apr_pool_t *result_pool,
                                   apr_pool_t *scratch_pool);
 
+/* Return a set of callbacks to use with the Ev2 shims. */
+svn_delta_shim_callbacks_t *
+svn_client__get_shim_callbacks(svn_wc_context_t *wc_ctx,
+                               const char *anchor_abspath,
+                               apr_pool_t *result_pool);
 
 /* Return true if KIND is a revision kind that is dependent on the working
  * copy. Otherwise, return false. */

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/commit.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/commit.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/commit.c Tue Mar  6 17:50:23 2012
@@ -49,6 +49,7 @@
 
 #include "client.h"
 #include "private/svn_wc_private.h"
+#include "private/svn_ra_private.h"
 #include "private/svn_magic.h"
 
 #include "svn_private_config.h"
@@ -645,6 +646,7 @@ get_ra_editor(svn_ra_session_t **ra_sess
               apr_pool_t *pool)
 {
   apr_hash_t *commit_revprops;
+  const char *anchor_abspath;
 
   /* Open an RA session to URL. */
   SVN_ERR(svn_client__open_ra_session_internal(ra_session, NULL, base_url,
@@ -669,7 +671,28 @@ get_ra_editor(svn_ra_session_t **ra_sess
   SVN_ERR(svn_client__ensure_revprop_table(&commit_revprops, revprop_table,
                                            log_msg, ctx, pool));
 
+#ifdef ENABLE_EDITOR_SHIMS
+  /* We need this for the shims. */
+  if (base_dir_abspath)
+    {
+      const char *relpath;
+      const char *wcroot_abspath;
+
+      SVN_ERR(svn_wc__get_wc_root(&wcroot_abspath, ctx->wc_ctx,
+                                  base_dir_abspath, pool, pool));
+
+      SVN_ERR(svn_ra_get_path_relative_to_root(*ra_session, &relpath, base_url,
+                                               pool));
+      anchor_abspath = svn_dirent_join(wcroot_abspath, relpath, pool);
+    }
+  else
+#endif
+    anchor_abspath = NULL;
+
   /* Fetch RA commit editor. */
+  SVN_ERR(svn_ra__register_editor_shim_callbacks(*ra_session,
+                        svn_client__get_shim_callbacks(ctx->wc_ctx,
+                                                       anchor_abspath, pool)));
   SVN_ERR(svn_ra_get_commit_editor3(*ra_session, editor, edit_baton,
                                     commit_revprops, commit_callback,
                                     commit_baton, lock_tokens, keep_locks,
@@ -1256,7 +1279,7 @@ append_externals_as_explicit_targets(apr
 
               rel_target = svn_dirent_skip_ancestor(base_abspath,
                                                     xinfo->local_abspath);
-              
+
               SVN_ERR_ASSERT(rel_target != NULL && *rel_target != '\0');
 
               APR_ARRAY_PUSH(rel_targets, const char *) =
@@ -1492,7 +1515,7 @@ svn_client_commit6(const apr_array_heade
               svn_boolean_t found_delete_half =
                 (apr_hash_get(committables->by_path, delete_op_root_abspath,
                                APR_HASH_KEY_STRING) != NULL);
-              
+
               if (!found_delete_half)
                 {
                   const char *delete_half_parent_abspath;

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/commit_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/commit_util.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/commit_util.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/commit_util.c Tue Mar  6 17:50:23 2012
@@ -417,8 +417,8 @@ bail_on_tree_conflicted_ancestor(svn_wc_
    externals that aren't explicit commit targets.)
 
    DANGLERS is a hash table mapping const char* absolute paths of a parent
-   that must be committed to a const char * absolute path of a child that
-   needs them.
+   to a const char * absolute path of a child. See the comment about
+   danglers at the top of svn_client__harvest_committables().
 
    If CANCEL_FUNC is non-null, call it with CANCEL_BATON to see
    if the user has cancelled the operation.
@@ -834,14 +834,12 @@ harvest_committables(svn_wc_context_t *w
 
       if (parent_added)
         {
-          /* The op-root of the parent must be part of the commit */
           const char *copy_root_abspath;
           svn_boolean_t parent_is_copy;
 
-          /* Copies are always committed recursively as long as the
-           * copy root is in the commit target list.
-           * So for nodes copied along with a parent, the copy root path
-           * is the dangling parent. See issue #4059. */
+          /* The parent is added, so either it is a copy, or a locally added
+           * directory. In either case, we require the op-root of the parent
+           * to be part of the commit. See issue #4059. */
           SVN_ERR(svn_wc__node_get_origin(&parent_is_copy, NULL, NULL, NULL,
                                           NULL, &copy_root_abspath,
                                           wc_ctx, parent_abspath,
@@ -850,9 +848,6 @@ harvest_committables(svn_wc_context_t *w
           if (parent_is_copy)
             parent_abspath = copy_root_abspath;
 
-          /* Copy the parent and target into pool; iterpool
-             lasts only for this loop iteration, and we check
-             danglers after the loop is over. */
           if (!apr_hash_get(danglers, parent_abspath, APR_HASH_KEY_STRING))
             {
               apr_hash_set(danglers,

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/copy.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/copy.c Tue Mar  6 17:50:23 2012
@@ -44,6 +44,7 @@
 
 #include "svn_private_config.h"
 #include "private/svn_wc_private.h"
+#include "private/svn_ra_private.h"
 #include "private/svn_mergeinfo_private.h"
 
 
@@ -1089,6 +1090,9 @@ repos_to_repos_copy(const apr_array_head
                                            message, ctx, pool));
 
   /* Fetch RA commit editor. */
+  SVN_ERR(svn_ra__register_editor_shim_callbacks(ra_session,
+                        svn_client__get_shim_callbacks(ctx->wc_ctx,
+                                                       NULL, pool)));
   SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
                                     commit_revprops,
                                     commit_callback,
@@ -1401,6 +1405,9 @@ wc_to_repos_copy(const apr_array_header_
                                                FALSE, FALSE, ctx, pool));
 
   /* Fetch RA commit editor. */
+  SVN_ERR(svn_ra__register_editor_shim_callbacks(ra_session,
+                        svn_client__get_shim_callbacks(ctx->wc_ctx,
+                                                       NULL, pool)));
   SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
                                     commit_revprops,
                                     commit_callback,
@@ -1503,7 +1510,7 @@ repos_to_wc_copy_single(svn_client__copy
                                             pair->src_original,
                                             tmp_abspath,
                                             &pair->src_peg_revision,
-                                            &pair->src_op_revision, NULL,
+                                            &pair->src_op_revision,
                                             svn_depth_infinity,
                                             ignore_externals, FALSE,
                                             &sleep_needed, ctx, pool);

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/delete.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/delete.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/delete.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/delete.c Tue Mar  6 17:50:23 2012
@@ -39,6 +39,7 @@
 
 #include "private/svn_client_private.h"
 #include "private/svn_wc_private.h"
+#include "private/svn_ra_private.h"
 
 #include "svn_private_config.h"
 
@@ -187,6 +188,9 @@ single_repos_delete(svn_ra_session_t *ra
                                            log_msg, ctx, pool));
 
   /* Fetch RA commit editor */
+  SVN_ERR(svn_ra__register_editor_shim_callbacks(ra_session,
+                        svn_client__get_shim_callbacks(ctx->wc_ctx,
+                                                       NULL, pool)));
   SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
                                     commit_revprops,
                                     commit_callback,

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/deprecated.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/deprecated.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/deprecated.c Tue Mar  6 17:50:23 2012
@@ -864,7 +864,7 @@ svn_client_diff5(const apr_array_header_
   return svn_client_diff6(diff_options, path1, revision1, path2,
                           revision2, relative_to_dir, depth,
                           ignore_ancestry, no_diff_deleted,
-                          show_copies_as_adds, ignore_content_type,
+                          show_copies_as_adds, ignore_content_type, FALSE,
                           use_git_diff_format, header_encoding,
                           outstream, errstream, changelists, ctx, pool);
 }
@@ -992,6 +992,7 @@ svn_client_diff_peg5(const apr_array_hea
                               no_diff_deleted,
                               show_copies_as_adds,
                               ignore_content_type,
+                              FALSE,
                               use_git_diff_format,
                               header_encoding,
                               outstream,

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/diff.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/diff.c Tue Mar  6 17:50:23 2012
@@ -678,9 +678,9 @@ display_prop_diffs(const apr_array_heade
 
         /* The last character in a property is often not a newline.
            An eol character is appended to prevent the diff API to add a
-           ' \ No newline at end of file' line. We add 
+           ' \ No newline at end of file' line. We add
            ' \ No newline at end of property' manually if needed. */
-        tmp = original_value ? original_value 
+        tmp = original_value ? original_value
                              : svn_string_create_empty(iterpool);
         orig = maybe_append_eol(tmp, NULL, iterpool);
 
@@ -777,6 +777,9 @@ struct diff_cmd_baton {
      relative to for output generation (see issue #2723). */
   const char *relative_to_dir;
 
+  /* Whether property differences are ignored. */
+  svn_boolean_t ignore_prop_diff;
+
   /* Whether we're producing a git-style diff. */
   svn_boolean_t use_git_diff_format;
 
@@ -817,6 +820,10 @@ diff_props_changed(svn_wc_notify_state_t
   apr_array_header_t *props;
   svn_boolean_t show_diff_header;
 
+  /* If property differences are ignored, there's nothing to do. */
+  if (diff_cmd_baton->ignore_prop_diff)
+    return SVN_NO_ERROR;
+
   SVN_ERR(svn_categorize_props(propchanges, NULL, NULL, &props,
                                scratch_pool));
 
@@ -1329,7 +1336,7 @@ static const svn_wc_diff_callbacks4_t di
   diff_dir_opened,
   diff_dir_added,
   diff_dir_props_changed,
-  diff_dir_closed    
+  diff_dir_closed
 };
 
 /*-----------------------------------------------------------------*/
@@ -2003,7 +2010,7 @@ diff_repos_wc(const char *path_or_url1,
   SVN_ERR(svn_ra_has_capability(ra_session, &server_supports_depth,
                                 SVN_RA_CAPABILITY_DEPTH, pool));
 
-  SVN_ERR(svn_wc_get_diff_editor6(&diff_editor, &diff_edit_baton,
+  SVN_ERR(svn_wc__get_diff_editor(&diff_editor, &diff_edit_baton,
                                   ctx->wc_ctx,
                                   anchor_abspath,
                                   target,
@@ -2413,6 +2420,7 @@ svn_client_diff6(const apr_array_header_
                  svn_boolean_t no_diff_deleted,
                  svn_boolean_t show_copies_as_adds,
                  svn_boolean_t ignore_content_type,
+                 svn_boolean_t ignore_prop_diff,
                  svn_boolean_t use_git_diff_format,
                  const char *header_encoding,
                  svn_stream_t *outstream,
@@ -2442,6 +2450,7 @@ svn_client_diff6(const apr_array_header_
 
   diff_cmd_baton.force_empty = FALSE;
   diff_cmd_baton.force_binary = ignore_content_type;
+  diff_cmd_baton.ignore_prop_diff = ignore_prop_diff;
   diff_cmd_baton.relative_to_dir = relative_to_dir;
   diff_cmd_baton.use_git_diff_format = use_git_diff_format;
   diff_cmd_baton.no_diff_deleted = no_diff_deleted;
@@ -2470,6 +2479,7 @@ svn_client_diff_peg6(const apr_array_hea
                      svn_boolean_t no_diff_deleted,
                      svn_boolean_t show_copies_as_adds,
                      svn_boolean_t ignore_content_type,
+                     svn_boolean_t ignore_prop_diff,
                      svn_boolean_t use_git_diff_format,
                      const char *header_encoding,
                      svn_stream_t *outstream,
@@ -2495,6 +2505,7 @@ svn_client_diff_peg6(const apr_array_hea
 
   diff_cmd_baton.force_empty = FALSE;
   diff_cmd_baton.force_binary = ignore_content_type;
+  diff_cmd_baton.ignore_prop_diff = ignore_prop_diff;
   diff_cmd_baton.relative_to_dir = relative_to_dir;
   diff_cmd_baton.use_git_diff_format = use_git_diff_format;
   diff_cmd_baton.no_diff_deleted = no_diff_deleted;

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/externals.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/externals.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/externals.c Tue Mar  6 17:50:23 2012
@@ -277,7 +277,7 @@ switch_dir_external(const char *local_ab
 
   /* ... Hello, new hotness. */
   SVN_ERR(svn_client__checkout_internal(NULL, url, local_abspath, peg_revision,
-                                        revision, NULL, svn_depth_infinity,
+                                        revision, svn_depth_infinity,
                                         FALSE, FALSE, timestamp_sleep,
                                         ctx, pool));
 
@@ -299,6 +299,9 @@ switch_dir_external(const char *local_ab
                                       external_peg_rev,
                                       external_rev,
                                       pool));
+    /* Issue #4123: We don't need to keep the newly checked out external's
+       DB open. */
+    SVN_ERR(svn_wc__close_db(local_abspath, ctx->wc_ctx, pool));
   }
 
   return SVN_NO_ERROR;
@@ -604,11 +607,12 @@ handle_external_item_change(const struct
                             apr_pool_t *scratch_pool)
 {
   svn_ra_session_t *ra_session;
-  svn_client__ra_session_from_path_results ra_cache = { 0 };
+  svn_revnum_t ra_revnum;
+  const char *ra_session_url;
+  const char *repos_root_url;
+  const char *repos_uuid;
   const char *new_url;
-  svn_node_kind_t kind;
-
-  ra_cache.kind = svn_node_unknown;
+  svn_node_kind_t ext_kind;
 
   SVN_ERR_ASSERT(eb->repos_root_url && parent_dir_url);
   SVN_ERR_ASSERT(new_item != NULL);
@@ -628,34 +632,28 @@ handle_external_item_change(const struct
   /* Determine if the external is a file or directory. */
   /* Get the RA connection. */
   SVN_ERR(svn_client__ra_session_from_path(&ra_session,
-                                           &ra_cache.ra_revnum,
-                                           &ra_cache.ra_session_url,
+                                           &ra_revnum,
+                                           &ra_session_url,
                                            new_url, NULL,
                                            &(new_item->peg_revision),
                                            &(new_item->revision), eb->ctx,
                                            scratch_pool));
 
-  SVN_ERR(svn_ra_get_uuid2(ra_session, &ra_cache.repos_uuid,
-                           scratch_pool));
-  SVN_ERR(svn_ra_get_repos_root2(ra_session, &ra_cache.repos_root_url,
-                                 scratch_pool));
-  SVN_ERR(svn_ra_check_path(ra_session, "", ra_cache.ra_revnum, &kind,
+  SVN_ERR(svn_ra_get_uuid2(ra_session, &repos_uuid, scratch_pool));
+  SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_url, scratch_pool));
+  SVN_ERR(svn_ra_check_path(ra_session, "", ra_revnum, &ext_kind,
                             scratch_pool));
 
-  if (svn_node_none == kind)
+  if (svn_node_none == ext_kind)
     return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
                              _("URL '%s' at revision %ld doesn't exist"),
-                             ra_cache.ra_session_url,
-                             ra_cache.ra_revnum);
+                             ra_session_url, ra_revnum);
 
-  if (svn_node_dir != kind && svn_node_file != kind)
+  if (svn_node_dir != ext_kind && svn_node_file != ext_kind)
     return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
                              _("URL '%s' at revision %ld is not a file "
                                "or a directory"),
-                             ra_cache.ra_session_url,
-                             ra_cache.ra_revnum);
-
-  ra_cache.kind = kind;
+                             ra_session_url, ra_revnum);
 
 
   /* Not protecting against recursive externals.  Detecting them in
@@ -682,7 +680,7 @@ handle_external_item_change(const struct
                                           scratch_pool));
     }
 
-  switch (ra_cache.kind)
+  switch (ext_kind)
     {
       case svn_node_dir:
         SVN_ERR(switch_dir_external(local_abspath, new_url,
@@ -693,20 +691,60 @@ handle_external_item_change(const struct
                                     scratch_pool));
         break;
       case svn_node_file:
-        if (strcmp(eb->repos_root_url, ra_cache.repos_root_url))
-          return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
-                    _("Unsupported external: "
-                      "url of file external '%s' is not in repository '%s'"),
-                    new_url, eb->repos_root_url);
+        if (strcmp(eb->repos_root_url, repos_root_url))
+          {
+            const char *local_repos_root_url;
+            const char *local_repos_uuid;
+            const char *ext_repos_relpath;
+
+            /*
+             * The working copy library currently requires that all files
+             * in the working copy have the same repository root URL.
+             * The URL from the file external's definition differs from the
+             * one used by the working copy. As a workaround, replace the
+             * root URL portion of the file external's URL, after making
+             * sure both URLs point to the same repository. See issue #4087.
+             */
+
+            SVN_ERR(svn_wc__node_get_repos_info(&local_repos_root_url,
+                                                &local_repos_uuid,
+                                                eb->ctx->wc_ctx,
+                                                parent_dir_abspath,
+                                                scratch_pool, scratch_pool));
+            ext_repos_relpath = svn_uri_skip_ancestor(repos_root_url,
+                                                      new_url, scratch_pool);
+            if (local_repos_uuid == NULL || local_repos_root_url == NULL ||
+                ext_repos_relpath == NULL ||
+                strcmp(local_repos_uuid, repos_uuid) != 0)
+              return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                        _("Unsupported external: URL of file external '%s' "
+                          "is not in repository '%s'"),
+                        new_url, eb->repos_root_url);
+
+            new_url = svn_path_url_add_component2(local_repos_root_url,
+                                                  ext_repos_relpath,
+                                                  scratch_pool);
+            SVN_ERR(svn_client__ra_session_from_path(&ra_session,
+                                                     &ra_revnum,
+                                                     &ra_session_url,
+                                                     new_url,
+                                                     NULL,
+                                                     &(new_item->peg_revision),
+                                                     &(new_item->revision),
+                                                     eb->ctx, scratch_pool));
+            SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_url,
+                                           scratch_pool));
+          }
+
         SVN_ERR(switch_file_external(local_abspath,
                                      new_url,
                                      &new_item->peg_revision,
                                      &new_item->revision,
                                      parent_dir_abspath,
                                      ra_session,
-                                     ra_cache.ra_session_url,
-                                     ra_cache.ra_revnum,
-                                     ra_cache.repos_root_url,
+                                     ra_session_url,
+                                     ra_revnum,
+                                     repos_root_url,
                                      eb->timestamp_sleep, eb->ctx,
                                      scratch_pool));
         break;
@@ -743,10 +781,6 @@ wrap_external_error(const struct externa
   return err;
 }
 
-/* This implements the 'svn_hash_diff_func_t' interface.
-   BATON is of type 'struct handle_externals_desc_change_baton *'.
-   KEY is a 'const char *'.
-*/
 static svn_error_t *
 handle_externals_change(const struct external_change_baton_t *eb,
                         const char *local_abspath,

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/merge.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/merge.c Tue Mar  6 17:50:23 2012
@@ -48,6 +48,7 @@
 #include "svn_props.h"
 #include "svn_time.h"
 #include "svn_sorts.h"
+#include "svn_subst.h"
 #include "svn_ra.h"
 #include "client.h"
 #include "mergeinfo.h"
@@ -1393,7 +1394,7 @@ check_moved_away(svn_boolean_t *moved_aw
 {
   const char *moved_to_abspath;
   svn_error_t *err;
-  
+
   *moved_away = FALSE;
 
   err = svn_wc__node_was_moved_away(&moved_to_abspath, NULL,
@@ -1423,7 +1424,7 @@ check_moved_here(svn_boolean_t *moved_he
 {
   const char *moved_from_abspath;
   svn_error_t *err;
-  
+
   *moved_here = FALSE;
 
   err = svn_wc__node_was_moved_here(&moved_from_abspath, NULL,
@@ -1995,10 +1996,14 @@ files_same_p(svn_boolean_t *same,
       svn_opt_revision_t working_rev = { svn_opt_revision_working, { 0 } };
 
       /* Compare the file content, translating 'mine' to 'normal' form. */
-      SVN_ERR(svn_client__get_normalized_stream(&mine_stream, wc_ctx,
-                                                mine_abspath, &working_rev,
-                                                FALSE, TRUE, NULL, NULL,
-                                                scratch_pool, scratch_pool));
+      if (svn_prop_get_value(working_props, SVN_PROP_SPECIAL) != NULL)
+        SVN_ERR(svn_subst_read_specialfile(&mine_stream, mine_abspath,
+                                           scratch_pool, scratch_pool));
+      else
+        SVN_ERR(svn_client__get_normalized_stream(&mine_stream, wc_ctx,
+                                                  mine_abspath, &working_rev,
+                                                  FALSE, TRUE, NULL, NULL,
+                                                  scratch_pool, scratch_pool));
 
       SVN_ERR(svn_stream_open_readonly(&older_stream, older_abspath,
                                        scratch_pool, scratch_pool));
@@ -7540,7 +7545,7 @@ flag_subtrees_needing_mergeinfo(svn_bool
                      operational depth is empty or files, then the mere
                      existence of operative immediate children means we
                      must record non-inheritable mergeinfo.
-                     
+
                      ### What about svn_depth_immediates?  In that case
                      ### the merge target needs only normal inheritable
                      ### mergeinfo and the target's immediate children will

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/mergeinfo.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/mergeinfo.c Tue Mar  6 17:50:23 2012
@@ -1147,7 +1147,7 @@ svn_client__elide_mergeinfo_catalog(svn_
           const char *top;
           const char *path_suffix;
           svn_boolean_t elides = FALSE;
-          
+
           svn_pool_clear(iterpool);
 
           /* Pop off any paths which are not ancestors of PATH. */

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/prop_commands.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/prop_commands.c Tue Mar  6 17:50:23 2012
@@ -41,6 +41,7 @@
 
 #include "svn_private_config.h"
 #include "private/svn_wc_private.h"
+#include "private/svn_ra_private.h"
 #include "private/svn_client_private.h"
 
 
@@ -242,6 +243,9 @@ propset_on_url(const char *propname,
                                            message, ctx, pool));
 
   /* Fetch RA commit editor. */
+  SVN_ERR(svn_ra__register_editor_shim_callbacks(ra_session,
+                        svn_client__get_shim_callbacks(ctx->wc_ctx,
+                                                       NULL, pool)));
   SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
                                     commit_revprops,
                                     commit_callback,

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/repos_diff.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/repos_diff.c Tue Mar  6 17:50:23 2012
@@ -1317,7 +1317,10 @@ fetch_kind_func(svn_kind_t *kind,
   struct edit_baton *eb = baton;
   svn_node_kind_t node_kind;
 
-  SVN_ERR(svn_ra_check_path(eb->ra_session, path, eb->revision, &node_kind,
+  if (!SVN_IS_VALID_REVNUM(base_revision))
+    base_revision = eb->revision;
+
+  SVN_ERR(svn_ra_check_path(eb->ra_session, path, base_revision, &node_kind,
                             scratch_pool));
 
   *kind = svn__kind_from_node_kind(node_kind, FALSE);
@@ -1335,12 +1338,15 @@ fetch_props_func(apr_hash_t **props,
   struct edit_baton *eb = baton;
   svn_node_kind_t node_kind;
 
-  SVN_ERR(svn_ra_check_path(eb->ra_session, path, eb->revision, &node_kind,
+  if (!SVN_IS_VALID_REVNUM(base_revision))
+    base_revision = eb->revision;
+
+  SVN_ERR(svn_ra_check_path(eb->ra_session, path, base_revision, &node_kind,
                             scratch_pool));
 
   if (node_kind == svn_node_file)
     {
-      SVN_ERR(svn_ra_get_file(eb->ra_session, path, eb->revision,
+      SVN_ERR(svn_ra_get_file(eb->ra_session, path, base_revision,
                               NULL, NULL, props, result_pool));
     }
   else if (node_kind == svn_node_dir)
@@ -1348,7 +1354,7 @@ fetch_props_func(apr_hash_t **props,
       apr_array_header_t *tmp_props;
 
       SVN_ERR(svn_ra_get_dir2(eb->ra_session, NULL, NULL, props, path,
-                              eb->revision, 0 /* Dirent fields */,
+                              base_revision, 0 /* Dirent fields */,
                               result_pool));
       tmp_props = svn_prop_hash_to_array(*props, result_pool);
       SVN_ERR(svn_categorize_props(tmp_props, NULL, NULL, &tmp_props,
@@ -1375,11 +1381,14 @@ fetch_base_func(const char **filename,
   svn_stream_t *fstream;
   svn_error_t *err;
 
+  if (!SVN_IS_VALID_REVNUM(base_revision))
+    base_revision = eb->revision;
+
   SVN_ERR(svn_stream_open_unique(&fstream, filename, NULL,
                                  svn_io_file_del_on_pool_cleanup,
                                  result_pool, scratch_pool));
 
-  err = svn_ra_get_file(eb->ra_session, path, eb->revision,
+  err = svn_ra_get_file(eb->ra_session, path, base_revision,
                         fstream, NULL, NULL, scratch_pool);
   if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)
     {
@@ -1391,7 +1400,7 @@ fetch_base_func(const char **filename,
     }
   else if (err)
     return svn_error_trace(err);
-  
+
   SVN_ERR(svn_stream_close(fstream));
 
   return SVN_NO_ERROR;

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/status.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/status.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/status.c Tue Mar  6 17:50:23 2012
@@ -374,7 +374,7 @@ svn_client_status5(svn_revnum_t *result_
       SVN_ERR(svn_ra_has_capability(ra_session, &server_supports_depth,
                                     SVN_RA_CAPABILITY_DEPTH, pool));
 
-      SVN_ERR(svn_wc_get_status_editor5(&editor, &edit_baton, &set_locks_baton,
+      SVN_ERR(svn_wc__get_status_editor(&editor, &edit_baton, &set_locks_baton,
                                     &edit_revision, ctx->wc_ctx,
                                     dir_abspath, target_basename,
                                     depth, get_all,

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/switch.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/switch.c Tue Mar  6 17:50:23 2012
@@ -228,7 +228,7 @@ switch_internal(svn_revnum_t *result_rev
   SVN_ERR(svn_ra_get_session_url(ra_session, &dfb.anchor_url, pool));
   dfb.target_revision = revnum;
 
-  SVN_ERR(svn_wc_get_switch_editor4(&switch_editor, &switch_edit_baton,
+  SVN_ERR(svn_wc__get_switch_editor(&switch_editor, &switch_edit_baton,
                                     &revnum, ctx->wc_ctx, anchor_abspath,
                                     target, switch_rev_url, use_commit_times,
                                     depth,

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/update.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/update.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/update.c Tue Mar  6 17:50:23 2012
@@ -370,7 +370,7 @@ update_internal(svn_revnum_t *result_rev
 
   /* Fetch the update editor.  If REVISION is invalid, that's okay;
      the RA driver will call editor->set_target_revision later on. */
-  SVN_ERR(svn_wc_get_update_editor4(&update_editor, &update_edit_baton,
+  SVN_ERR(svn_wc__get_update_editor(&update_editor, &update_edit_baton,
                                     &revnum, ctx->wc_ctx, anchor_abspath,
                                     target, use_commit_times, depth,
                                     depth_is_sticky, allow_unver_obstructions,

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/util.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/util.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_client/util.c Tue Mar  6 17:50:23 2012
@@ -240,3 +240,163 @@ svn_client__assert_homogeneous_target_ty
 
   return SVN_NO_ERROR;
 }
+
+struct shim_callbacks_baton
+{
+  svn_wc_context_t *wc_ctx;
+  const char *anchor_abspath;
+};
+
+static svn_error_t *
+rationalize_shim_path(const char **local_abspath,
+                      struct shim_callbacks_baton *scb,
+                      const char *path,
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool)
+{
+  if (svn_path_is_url(path))
+    {
+      /* This is a copyfrom URL */
+      const char *wcroot_abspath;
+      const char *wcroot_url;
+      const char *relpath;
+
+      SVN_ERR(svn_wc__get_wc_root(&wcroot_abspath, scb->wc_ctx,
+                                  scb->anchor_abspath,
+                                  scratch_pool, scratch_pool));
+      SVN_ERR(svn_wc__node_get_url(&wcroot_url, scb->wc_ctx, wcroot_abspath,
+                                   scratch_pool, scratch_pool));
+      relpath = svn_uri_skip_ancestor(wcroot_url, path, scratch_pool);
+      *local_abspath = svn_dirent_join(wcroot_abspath, relpath, result_pool);
+    }
+  else
+    *local_abspath = svn_dirent_join(scb->anchor_abspath, path, result_pool);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_props_func(apr_hash_t **props,
+                 void *baton,
+                 const char *path,
+                 svn_revnum_t base_revision,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
+{
+  struct shim_callbacks_baton *scb = baton;
+  const char *local_abspath;
+
+  /* Early out: if we didn't get an anchor_abspath, it means we don't have a
+     working copy, and hence no method of fetching the requisite information. */
+  if (!scb->anchor_abspath)
+    {
+      *props = apr_hash_make(result_pool);
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(rationalize_shim_path(&local_abspath, scb, path, scratch_pool,
+                                scratch_pool));
+
+  SVN_ERR(svn_wc_get_pristine_props(props, scb->wc_ctx, local_abspath,
+                                    result_pool, scratch_pool));
+
+  if (!*props)
+    *props = apr_hash_make(result_pool);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_kind_func(svn_kind_t *kind,
+                void *baton,
+                const char *path,
+                svn_revnum_t base_revision,
+                apr_pool_t *scratch_pool)
+{
+  struct shim_callbacks_baton *scb = baton;
+  svn_node_kind_t node_kind;
+  const char *local_abspath;
+
+  /* Early out: if we didn't get an anchor_abspath, it means we don't have a
+     working copy, and hence no method of fetching the requisite information. */
+  if (!scb->anchor_abspath)
+    {
+      *kind = svn_kind_unknown;
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(rationalize_shim_path(&local_abspath, scb, path, scratch_pool,
+                                scratch_pool));
+
+  SVN_ERR(svn_wc_read_kind(&node_kind, scb->wc_ctx, local_abspath, FALSE,
+                           scratch_pool));
+  *kind = svn__kind_from_node_kind(node_kind, FALSE);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_base_func(const char **filename,
+                void *baton,
+                const char *path,
+                svn_revnum_t base_revision,
+                apr_pool_t *result_pool,
+                apr_pool_t *scratch_pool)
+{
+  struct shim_callbacks_baton *scb = baton;
+  const char *local_abspath;
+  svn_stream_t *pristine_stream;
+  svn_stream_t *temp_stream;
+  svn_error_t *err;
+
+  /* Early out: if we didn't get an anchor_abspath, it means we don't have a
+     working copy, and hence no method of fetching the requisite information. */
+  if (!scb->anchor_abspath)
+    {
+      *filename = NULL;
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(rationalize_shim_path(&local_abspath, scb, path, scratch_pool,
+                                scratch_pool));
+
+  err = svn_wc_get_pristine_contents2(&pristine_stream, scb->wc_ctx,
+                                      local_abspath, scratch_pool,
+                                      scratch_pool);
+  if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+    {
+      svn_error_clear(err);
+      *filename = NULL;
+      return SVN_NO_ERROR;
+    }
+  else if (err)
+    return svn_error_trace(err);
+
+  SVN_ERR(svn_stream_open_unique(&temp_stream, filename, NULL,
+                                 svn_io_file_del_on_pool_cleanup,
+                                 result_pool, scratch_pool));
+  SVN_ERR(svn_stream_copy3(pristine_stream, temp_stream, NULL, NULL,
+                           scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+svn_delta_shim_callbacks_t *
+svn_client__get_shim_callbacks(svn_wc_context_t *wc_ctx,
+                               const char *anchor_abspath,
+                               apr_pool_t *result_pool)
+{
+  svn_delta_shim_callbacks_t *callbacks =
+                            svn_delta_shim_callbacks_default(result_pool);
+  struct shim_callbacks_baton *scb = apr_pcalloc(result_pool, sizeof(*scb));
+
+  scb->wc_ctx = wc_ctx;
+  scb->anchor_abspath = apr_pstrdup(result_pool, anchor_abspath);
+
+  callbacks->fetch_props_func = fetch_props_func;
+  callbacks->fetch_kind_func = fetch_kind_func;
+  callbacks->fetch_base_func = fetch_base_func;
+  callbacks->fetch_baton = scb;
+
+  return callbacks;
+}